Re: [stella] Baubles; some progress, some problems...

Subject: Re: [stella] Baubles; some progress, some problems...
From: Jake Patterson <jpatters@xxxxxxxxxxx>
Date: Wed, 14 Nov 2001 14:03:07 -0500 (EST)
On Wed, 14 Nov 2001, Thomas Jentzsch wrote:

> I found two errors:
> 1. you forgot to fill the LevelWeAreOnBuffer variables
> 2. the LevelWeAreOnBuffer variables overlap with the next variables.
> That won't happen any more, if you follow Glenn's suggestions.

That's actually intentional.

These five variables are used while drawing the indicators at the top:

LivesIndicatorBuffer     5 bytes
TimeRemainingBuffer1     5 bytes
TimeRemainingBuffer0     5 bytes
LevelWeAreOnBuffer1      5 bytes
LevelWeAreOnBuffer0      5 bytes

These five variables are used while drawing the game area, and can safely
overlap the above variables:

GamePlayfieldPF0Buffer   5 bytes
GamePlayfieldPF1Buffer   5 bytes
GamePlayfieldPF2Buffer   5 bytes
BufferPointer            1 byte
NextTableRecord          1 byte

I will follow Glenn's suggestions anyway, but I will keep the variables
overlapping in order to preserve RAM.  It may only be 17 bytes,  but that
is 13.3% of the whole available.  If I wasted that percentage of my
Powerbook's RAM in a program, it would be 7.14038e+07 bytes!

I am *attempting* to fill all five of the indicator buffers, in the
section of code right after the GameTopLines loop.  For some reason,
only the LivesIndicatorBuffer is actually getting filled.  It is clear
from the output that the two TimeRemainingBuffers still have the data from
GamePlayfieldPF*Buffers, and the LevelWeAreOnBuffers have the data from
BufferPointer and NextTableRecord.

I know that my approach there is sound, because the LivesIndicatorBuffer
overlaps in RAM with GamePlayfieldPF0Buffer, and both display correctly.
So there is some stupid thing that is wrong with filling the other four
buffers that I can't see.

Ohh wait a minute!  I see the problem now!  After typing in this whole
email message, I see the problem!!!  Lets just call it a copy/paste error,
I was actually not loading up the right buffers, I was repeatedly loading
up the TimeRemainingBuffer1 with the data intended for the subsequent
buffers.  Gosh I feel dumb now.  The bugfixed version is attached.  You
can now see the time meaninglessly tick away in hex.  Zowie!

> Suggestions:
> 1. you are wasting way to many cycles (24!) for coloring the playfield.
> That won't work, when you want to add players too. And your colour
> changes will change the players colors too. You should use COLUPF for
> this. (But I bet, that would still cost to many cycles.)

The color design is intentional.  The idea is that P0 will have the side
colored with P1 colors as its home, and P1 will live in the other side.
So in a two player game, they compete to collect the baubles which may
appear on either side, so they may need to cross over to their non-home
side and have a more dificult time manuvering since the colors match.  I
could develop a scoring scheme very similar to tennis, where having the
bauble on your side is analogous to serving, and collecting a buable on
your opponents side is analogous to scorring a point against your
opponents serve.

> 2. This code is looking very elegant, but unfortunately is to inefficient:
>      LDX BufferPointer               ; [0]  + 3
>      ...
>      LDX NextTableRecord             ; [43] + 3
>      LDA ScrollTablePage,X           ; [46] + 4
>      STA BufferPointer               ; [50] + 3
>      INX                             ; [53] + 2
>      LDA ScrollTablePage,X           ; [55] + 4
>      STA NextTableRecord             ; [59] + 3
>
> As ScrollTablePage is defined now, the NextTableRecord variable is
> simply increased by two every line and BufferPointer is increased by one
> every 14th line.

Every 20th line actually, since I am counting in hex.  Or maybe you are
just stating that in hex :-)

> That way, your table allows you to scroll your data without checking,
> if a new 14 line block starts and if yes, if your block counter has to
> be reset to zero. That's the idea? Right?

Well, it only gets reset to zero if it has just displayed the last line of
the last block.  Then it should display the first line of the first block
next, unless it has already displayed 100 lines, in which case it is done
drawing the play area.

> It's a very good idea, doing this with a table. But it costs to many
> cycles (and a lot of ROM too). If I count correct, you need 22 cylces.
>
> First change: Throw away your table based approach :)
> Second change: Count your indexes down to zero, that makes checking
> faster.
>
> Now you could simply do something like:
>     LDX BufferPointer   ;3
>     ...
>     DEC LineCounter     ;5
>     BNE .ok             ;2³
>     LDA  #14            ;2
>     STA LineCounter     ;3
>     DEC BufferPointer   ;5
>     BNE .ok             ;2³
>     LDA #0              ;2
>     STA BufferPointer   ;3
> .ok:
> ...and it would be even slower (worst case: 27 cycles) than your
> approach. :(
>
> But now you have a lot of options:
>
> Remove BufferPointer and use X instead, that saves a lot (9) of cycles.
> Now we are already faster (18 cycles) than your solution
>     DEC LineCounter     ;5
>     BNE .ok             ;2³
>     LDA  #14            ;2
>     STA LineCounter     ;3
>     DEX                 ;2
>     BNE .ok             ;2³
>     LDX #0              ;2
> .ok:
>
> Then you could repeat the data X (was BufferPointer) is pointing at.
> That will cost you some ROM, but now you never have to check and reset X
> (4 more cycles won -> 14 cycles):
>     DEC LineCounter     ;5
>     BNE .ok             ;2³
>     LDA  #14            ;2
>     STA LineCounter     ;3
>     INX                 ;2   X is counting up again, that makes
>                         ;    initialisation easier
> .ok:

I don't want to do anything that will increase the ROM footprint of the
level data, I have a big list of four letter words that will each be a
level in the game, the smaller they are in ROM the more of them I will be
able to include.  I suppose I could increase their RAM footprint if
necessary by copying them two for one or four for one into the buffers or
something.

> Now it is getting a bit more complicated.
> You could use the Y variable instead of LineCounter and make your
> blocks 2^4 (=16) lines high. Finally you are down to 11 cycles :)
>
>     TYA                 ;2
>     EOR Offset          ;3
>     AND #15             ;2
>     BNE .ok             ;2³
>     INX                 ;2
> .ok:
>
> The contents of the Offset variable depends on PlayfieldY, it should be
> something like (PlayfieldY*2) or -(PlayfieldY*2). You have to test this.
>
> 3. If you need even more cycles, don't change PF0 and make the game
> area a bit smaller.

That is certainly an option, it would actually reduce the ROM footprint of
my level data, allowing me to include 50% more levels, but at the same
time it would restrict which four letter words I could use, since they
would have to fit in the smaller screen space.  For example, "ZERO"
requires 15 playfield pixels, as do "2600" "AAPL" "BOLD" "CARP" "FART"
"FISH" "HASP" "HOPE" "LEET" "LIFE" "PERL" and "POET".  The following would
require 16 playfield pixels, and would be doable: "CLUB" "DUPE" "FORK"
"FOUR" "GAFF" "HACK" "HOUR" "JEFF" "KARL" "KOSH" "PAUL" and "PIKE".
Anything requiring more then 16 playfield pixels would not be doable
without PF0, including such interesting words as: "FIVE" "HTML" "JAKE"
"KIRK" "LUKE" "MOOF" "SLAM" "UNIX" "WKRP" "DAWN" "FUNK" "INTV" and "MARX"

That's only a small sampling of my list.  On each level (n), it will be
necessary to collect 2( (floor(n/4)) +1) baubles in the available time
to procede to the next level.  The baubles appear one at a time somewhere
within the moving playfield, and will move with the playfield.  The player
moves freely within the confines of the blue border, and must avoid
colliding with the moving playfield.  Surrounding the moving playfield is
a safe zone, the time will tick away twice as fast while the player is in
the safe zone.  I havn't decided how to handle that in a two player game
yet.  I had intended to have the left and right safe zones gradually
disappear as the words get wider.  In fact "DAWN" "FUNK" "INTV" and
"MARX" would abut the blue border on the sides, resulting on no side safe
zones.  Unfortunately, I don't think I will be able to switch CTRLPF to
"score mode" and back precisely enough for that.

It will take me some time to grok your suggestions, but I am sure they
will help!

One other question, how much time does it take to read the paddles?  I
have 32 black scanlines (or rather, I will have 32 black scanlines) below
the game area, will that be enough to read two paddles?  I want to offer
a single player mode that uses two paddles for movement, one for x and one
for y.  It will also have a joystick mode of course.  In the joystick
modes, I guess I could use that space for the score(s).

Thanks for the help, I will keep chugging away at this!  I would love to
hear any other comments/suggestions!

--                                         ,
                                         ,@[
                                       ,@@@[
                                     ,@@@@'@@@@'
`@@@@@@@@@@@@@@@@',@@@'            ,@@@@',@@@'
  `@@@@@@@@@@@@',@@@',aa.       ,aa.   ,@@[  ]@@',@@@' ,aa.'aaaaaaa, aa'
    `@@@@@@@@',@@@|@@@@@@@'  ,@@@@@@'  ]@@[  ]',@@@',@@@@@@@''@@@@',@'
      `@@@@',@@@']@7`,@@',@[]@@@@@',@@[]@@[  ]@@[  ]@7`,@@',@[ '@@@'
        `@a@@@'  ]@,@@',@@@[]@@@' ,@@@[]@@[  ]@@[  ]@,@@',@@@[ ,@@@,
          `@'     `@@@@@@@'  `@@@@@@@' ]@@[  ]@@[   `@@@@@@@',@@@',@@,
                     `~'        `~'    `~~'  `~~'      `~'  '~~' ~~~~~'

.....................................GCE Vectrex - Entertaining New Ideas

Attachment: baublesgame002.bin
Description: baublesgame002.bin

; Baubles game screen
; by Jake Patterson, September 2001
; This has *not* been tested on actual hardware
;
; Somewhat derived from:
; How to Draw A Playfield.
; by Nick Bensema  9:23PM  3/2/97
;
    processor 6502
    include vcs.h

    org $F000
       
Temp                    =   $80
LivesIndicator          =   $81     ; remaining lives.
TimeRemaining1          =   $82     ; high order hex digit of time remaining
TimeRemaining0          =   $83     ; low order hex digit of time remaining
LevelWeAreOn1           =   $84     ; high order hex digit of current level
LevelWeAreOn0           =   $85     ; low order hex digit of current level
LivesIndicatorBuffer    =   $86     ; buffer, five bytes of lives graphic
GamePlayfieldPF0Buffer  =   $86     ; buffer for PF0 byte of the game playfield
TimeRemainingBuffer1    =   $8B     ; buffer, five bytes high order time graphic
GamePlayfieldPF1Buffer  =   $8B     ; buffer for PF1 byte of the game playfield
TimeRemainingBuffer0    =   $90     ; buffer, five bytes low order time graphic
GamePlayfieldPF2Buffer  =   $90     ; buffer for PF2 byte of the game playfield
LevelWeAreOnBuffer1     =   $95     ; buffer, five bytes high order lvl graphic
BufferPointer           =   $95
NextTableRecord         =   $96
LevelWeAreOnBuffer0     =   $9A     ; buffer, five bytes low order lvl graphic
PlayfieldY              =   $9F

darkblue                =   $82
black                   =   $00

Start
    SEI  ; Disable interrupts, if there are any.
    CLD  ; Clear BCD math bit.

    LDX  #$FF
    TXS  ; Set stack to beginning.
	
    LDA #0
B1      STA 0,X
    DEX
    BNE B1
    
    LDA #$03
    STA LivesIndicator
    LDA #$01
    STA TimeRemaining1
    LDA #$0F
    STA TimeRemaining0
    LDA #$00
    STA LevelWeAreOn1
    STA LevelWeAreOn0
    STA PlayfieldY

; *****************************************************************************
MainLoop

; *****************************************************************************

    JSR  VerticalBlank  ;Execute the vertical blank.
    JSR  CheckSwitches  ;Check Console Switches.
    JSR  DrawScreen	    ;Draw the screen
    JSR  OverScan       ;Do more calculations during overscan
    JMP  MainLoop       ;Continue forever.
	
; *****************************************************************************
VerticalBlank

; *****************************************************************************

    LDX  #0
	LDA  #2
    STA  WSYNC  
	STA  WSYNC
	STA  WSYNC
	STA  VSYNC ;Begin vertical sync.
	STA  WSYNC ; First line of VSYNC
	STA  WSYNC ; Second line of VSYNC.

	LDA  #44
	STA  TIM64T

	LDA #0
	STA CXCLR

	STA  WSYNC ; Third line of VSYNC.
	STA  VSYNC ; (0)

	RTS  

; *****************************************************************************
CheckSwitches

; *****************************************************************************
	
	LDA #$0000
	STA PF0
	STA PF1
	STA PF2
	STA COLUPF
	STA COLUBK
	
	RTS

; *****************************************************************************
DrawScreen

; *****************************************************************************

; *************************************** 0th through 47th scanlines (48 total)

	LDY #44
	
GameTopLines

	LDA #black
	STA COLUBK
	STA COLUPF
	STA PF0
	STA PF1
	STA PF2

	STA WSYNC

	DEY				
	BNE GameTopLines                ; finished with 0th thru 44th scanlines now
	
	LDA LivesIndicator              ; [0]  + 3
	AND #3                          ; [3]  + 2
	TAX                             ; [5]  + 2
	LDA LivesIndicatorData0,X       ; [7]  + 4
	STA LivesIndicatorBuffer        ; [11] + 3
	LDA LivesIndicatorData1,X       ; [14] + 4
	STA LivesIndicatorBuffer+1      ; [18] + 3
	LDA LivesIndicatorData2,X       ; [21] + 4
	STA LivesIndicatorBuffer+2      ; [25] + 3
	LDA LivesIndicatorData3,X       ; [28] + 4
	STA LivesIndicatorBuffer+3      ; [32] + 3
	LDA LivesIndicatorData4,X       ; [35] + 4
	STA LivesIndicatorBuffer+4      ; [39] + 3
	
	LDX TimeRemaining1              ; [42] + 2
	LDA DigitsDataPF1Right0,X       ; [44] + 4
	STA TimeRemainingBuffer1        ; [48] + 3
	LDA DigitsDataPF1Right1,X       ; [51] + 4
	STA TimeRemainingBuffer1+1      ; [55] + 3
	LDA DigitsDataPF1Right2,X       ; [58] + 4
	STA TimeRemainingBuffer1+2      ; [62] + 3
	LDA DigitsDataPF1Right3,X       ; [65] + 4
	STA TimeRemainingBuffer1+3      ; [69] + 3
	LDA DigitsDataPF1Right4,X       ; [72] + 4
	STA TimeRemainingBuffer1+4      ; [76] + 3
	
	LDX TimeRemaining0              ;
	LDA DigitsDataPF2Left0,X        ;
	STA TimeRemainingBuffer0        ;
	LDA DigitsDataPF2Left1,X        ;
	STA TimeRemainingBuffer0+1      ;
	LDA DigitsDataPF2Left2,X        ;
	STA TimeRemainingBuffer0+2      ;
	LDA DigitsDataPF2Left3,X        ;
	STA TimeRemainingBuffer0+3      ;
	LDA DigitsDataPF2Left4,X        ;
	STA TimeRemainingBuffer0+4      ; [79] + 37
	
	LDX LevelWeAreOn1               ;
	LDA DigitsDataPF1Right0,X       ;
	STA LevelWeAreOnBuffer1         ;
	LDA DigitsDataPF1Right1,X       ;
	STA LevelWeAreOnBuffer1+1       ;
	LDA DigitsDataPF1Right2,X       ;
	STA LevelWeAreOnBuffer1+2       ;
	LDA DigitsDataPF1Right3,X       ;
	STA LevelWeAreOnBuffer1+3       ;
	LDA DigitsDataPF1Right4,X       ;
	STA LevelWeAreOnBuffer1+4       ; [116]+ 37
	
	LDX LevelWeAreOn0               ;
	LDA DigitsDataPF2Left0,X        ;
	STA LevelWeAreOnBuffer0         ;
	LDA DigitsDataPF2Left1,X        ;
	STA LevelWeAreOnBuffer0+1       ;
	LDA DigitsDataPF2Left2,X        ;
	STA LevelWeAreOnBuffer0+2       ;
	LDA DigitsDataPF2Left3,X        ;
	STA LevelWeAreOnBuffer0+3       ;
	LDA DigitsDataPF2Left4,X        ;
	STA LevelWeAreOnBuffer0+4       ; [153]+ 37	
	
	STA WSYNC                       ; [190] scan lines 45, 46, and 47 now done

; *********** top of screen, indicators, 48th through 75th scanlines (28 total)

    LDX #5

IndicatorLinesSet

    LDA #4                          ; [64] + 2
    STA Temp                        ; [66] + 3
    DEX                             ; [69] + 2
        
IndicatorLines

    STA WSYNC                       ; [71] + 3

    LDA #darkblue                   ; [0]  + 2
    STA COLUPF                      ; [2]  + 3
    LDA LivesIndicatorBuffer,X      ; [5]  + 4
    STA PF0                         ; [9]  + 3
    
    LDA TimeRemainingBuffer1,X      ; [12] + 4
    STA PF1                         ; [16] + 3
    LDA TimeRemainingBuffer0,X      ; [19] + 4
    STA PF2                         ; [23] + 3
    LDA IndicatorColorData,X        ; [26] + 4
    STA COLUPF                      ; [30] + 3

    LDA #0                          ; [33] + 2
    STA PF0                         ; [35] + 3

    LDA LevelWeAreOnBuffer1,X       ; [38] + 4
    STA PF1                         ; [42] + 3
    LDA LevelWeAreOnBuffer0,X       ; [45] + 4
    STA PF2                         ; [49] + 3
    
    DEC Temp                        ; [52] + 5
    BNE IndicatorLines              ; [57] + 2
    
    TXA                             ; [59] + 2
    BNE IndicatorLinesSet           ; [61] + 3
    
    STA WSYNC                       ; scanline 68
    
    LDA #1
    STA CTRLPF                      ; mirror the thing
    LDA #0
    STA PF0
    STA PF1
    STA PF2
    STA WSYNC
    STA WSYNC
    STA WSYNC
    STA WSYNC
    STA WSYNC
    STA WSYNC
    STA WSYNC                       ; scanline 75
    
; ******************* top of blue border, 76th through 83rd scanlines (8 total)

    LDA #darkblue
    STA COLUPF
    LDA #$FF
    STA PF0
    STA PF1
    STA PF2
    STA WSYNC
    STA WSYNC
    STA WSYNC
    STA WSYNC
    STA WSYNC
    STA WSYNC
    STA WSYNC
    STA WSYNC                       ; scanline 83

; ************************ top safe zone, 84th through 91st scanlines (8 total)

    LDA #darkblue
    STA COLUPF
    LDA #%00010000
    STA PF0
    LDA #0
    STA PF1
    STA PF2
    STA WSYNC
    STA WSYNC
    STA WSYNC
    STA WSYNC
    STA WSYNC
    
    LDX #0                          ; [0]  + 2
    LDA LevelZeroData,X             ; [2]  + 3
    STA GamePlayfieldPF0Buffer,X    ; [5]  + 4
    INX                             ; [9]  + 2
    LDA LevelZeroData,X             ; [11] + 3
    STA GamePlayfieldPF0Buffer,X    ; [14] + 4
    INX                             ; [18] + 2
    LDA LevelZeroData,X             ; [20] + 3
    STA GamePlayfieldPF0Buffer,X    ; [23] + 4
    INX                             ; [27] + 2
    LDA LevelZeroData,X             ; [29] + 3
    STA GamePlayfieldPF0Buffer,X    ; [32] + 4
    INX                             ; [36] + 2
    LDA LevelZeroData,X             ; [38] + 3
    STA GamePlayfieldPF0Buffer,X    ; [41] + 4
    INX                             ; [45] + 2
    LDA LevelZeroData,X             ; [47] + 3
    STA GamePlayfieldPF0Buffer,X    ; [50] + 4
    INX                             ; [54] + 2
    LDA LevelZeroData,X             ; [56] + 3
    STA GamePlayfieldPF0Buffer,X    ; [59] + 4
    INX                             ; [63] + 2
    LDA LevelZeroData,X             ; [65] + 3
    STA GamePlayfieldPF0Buffer,X    ; [68] + 4
    
    STA WSYNC
  
    INX                             ; [0]  + 2
    LDA LevelZeroData,X             ; [2]  + 3
    STA GamePlayfieldPF0Buffer,X    ; [5]  + 4
    INX                             ; [9]  + 2
    LDA LevelZeroData,X             ; [11] + 3
    STA GamePlayfieldPF0Buffer,X    ; [14] + 4
    INX                             ; [18] + 2
    LDA LevelZeroData,X             ; [20] + 3
    STA GamePlayfieldPF0Buffer,X    ; [23] + 4
    INX                             ; [27] + 2
    LDA LevelZeroData,X             ; [29] + 3
    STA GamePlayfieldPF0Buffer,X    ; [32] + 4
    INX                             ; [36] + 2
    LDA LevelZeroData,X             ; [38] + 3
    STA GamePlayfieldPF0Buffer,X    ; [41] + 4
    INX                             ; [45] + 2
    LDA LevelZeroData,X             ; [47] + 3
    STA GamePlayfieldPF0Buffer,X    ; [50] + 4
    INX                             ; [54] + 2
    LDA LevelZeroData,X             ; [56] + 3
    STA GamePlayfieldPF0Buffer,X    ; [59] + 4

    STA WSYNC

    LDY #100
    LDA PlayfieldY                  ; value between 0 and 99 decimal
    ASL                             ; multiply by 2
    TAX
    LDA ScrollTable00,X
    STA BufferPointer               ; initial pointer to playfield graphic
    INX
    LDA ScrollTable00,X
    STA NextTableRecord             ; next record in table
;    STA WSYNC                       ; scanline 91    
    
; ******************** main game area, 92nd through 191st scanlines (100 total)

GameAreaLoop

    LDA #1                          ; [67] + 2
    STA CTRLPF                      ; [69] + 3
 
    STA WSYNC                       ; [72]

    LDX BufferPointer               ; [0]  + 3
    
    LDA ColorDataP0,X               ; [3]  + 4
    STA COLUP0                      ; [7]  + 3
    
    LDA GamePlayfieldPF0Buffer,X    ; [10] + 4
    STA PF0                         ; [14] + 3
    
    LDA GamePlayfieldPF1Buffer,X    ; [17] + 4
    STA PF1                         ; [21] + 3
    
    LDA #3                          ; [24] + 2
    STA CTRLPF                      ; [26] + 3
        
    LDA GamePlayfieldPF2Buffer,X    ; [29] + 4
    STA PF2                         ; [33] + 3        

    LDA ColorDataP1,X               ; [36] + 4
    STA COLUP1                      ; [40] + 3
    
    LDX NextTableRecord             ; [43] + 3
    LDA ScrollTablePage,X           ; [46] + 4
    STA BufferPointer               ; [50] + 3
    INX                             ; [53] + 2
    LDA ScrollTablePage,X           ; [55] + 4
    STA NextTableRecord             ; [59] + 3
    
    DEY                             ; [62] + 2
    BNE GameAreaLoop                ; [64] + 3
    
    LDA #1
    STA CTRLPF 

    STA WSYNC
    
    INC PlayfieldY                  ; [0]  + 5
    LDA #100                        ; [5]  + 2
    CMP PlayfieldY                  ; [7]  + 3
    BNE Foo                         ; [10] + 2
    LDA #0                          ; [12] + 2
    STA PlayfieldY                  ; [14] + 3
    DEC TimeRemaining0              ; [17] + 5
    BPL Foo                         ; [22] + 2
    LDA #$0F                        ; [24] + 2
    STA TimeRemaining0              ; [26] + 3
    DEC TimeRemaining1              ; [29] + 5
    BPL Foo                         ; [34] + 2
    LDA #$09                        ; [36] + 2
    STA TimeRemaining1              ; [38] + 3
Foo   
    
; ******************* bottom safe zone, 192nd through 199th scanlines (8 total)

    LDA #darkblue                   ; [41] + 2
    STA COLUPF                      ; [43] + 3
    LDA #%00010000                  ; [46] + 2
    STA PF0                         ; [48] + 3
    LDA #0                          ; [51] + 2
    STA PF1                         ; [53] + 3
    STA PF2                         ; [56] + 3
    STA WSYNC
    STA WSYNC
    STA WSYNC
    STA WSYNC
    STA WSYNC
    STA WSYNC
    STA WSYNC
    STA WSYNC                       ; scanline 199
    
; ************** bottom of blue border, 200th through 207th scanlines (8 total)

    LDA #darkblue
    STA COLUPF
    LDA #$FF
    STA PF0
    STA PF1
    STA PF2
    STA WSYNC
    STA WSYNC
    STA WSYNC
    STA WSYNC
    STA WSYNC
    STA WSYNC
    STA WSYNC
    STA WSYNC                       ; scanline 207th        
    
; *****************************************************************************
		
	LDA #$0000
	STA PF0
	STA PF1
	STA PF2
	STA COLUPF
	STA COLUBK
		
	RTS
	
; *****************************************************************************
OverScan

; *****************************************************************************

	LDX #30
KillLines
	 STA WSYNC
	 DEX
	 BNE KillLines
	RTS

; *****************************************************************************
; Graphics Data

; *****************************************************************************

;;  Ok, what this is is a table to facilitate smooth scrolling of the game
;;  playfield graphic, which consists of a four letter word spelled out with
;;  the playfield graphics, the letters are five "blocks" high, and it is
;;  spread out over 100 scan lines, therefore each block is 20 scan lines.
;;  each record contains two bytes, the first byte points to the appropriate
;;  point in a buffer in zero page RAM, and the second byte is the low order
;;  address of the next entery in the table. 
;;  the table is 201 bytes.

    org $FE00

ScrollTablePage
    .byte >ScrollTablePage
    
ScrollTable00
    .byte 0, <ScrollTable01
ScrollTable01
    .byte 0, <ScrollTable02
ScrollTable02
    .byte 0, <ScrollTable03
ScrollTable03
    .byte 0, <ScrollTable04
ScrollTable04
    .byte 0, <ScrollTable05
ScrollTable05
    .byte 0, <ScrollTable06
ScrollTable06
    .byte 0, <ScrollTable07
ScrollTable07
    .byte 0, <ScrollTable08
ScrollTable08
    .byte 0, <ScrollTable09
ScrollTable09
    .byte 0, <ScrollTable0A
ScrollTable0A
    .byte 0, <ScrollTable0B
ScrollTable0B
    .byte 0, <ScrollTable0C
ScrollTable0C
    .byte 0, <ScrollTable0D
ScrollTable0D
    .byte 0, <ScrollTable0E
ScrollTable0E
    .byte 0, <ScrollTable0F
ScrollTable0F
    .byte 0, <ScrollTable10
ScrollTable10
    .byte 0, <ScrollTable11
ScrollTable11
    .byte 0, <ScrollTable12
ScrollTable12
    .byte 0, <ScrollTable13
ScrollTable13
    .byte 0, <ScrollTable14
ScrollTable14
    .byte 1, <ScrollTable15
ScrollTable15
    .byte 1, <ScrollTable16
ScrollTable16
    .byte 1, <ScrollTable17
ScrollTable17
    .byte 1, <ScrollTable18
ScrollTable18
    .byte 1, <ScrollTable19
ScrollTable19
    .byte 1, <ScrollTable1A
ScrollTable1A
    .byte 1, <ScrollTable1B
ScrollTable1B
    .byte 1, <ScrollTable1C
ScrollTable1C
    .byte 1, <ScrollTable1D
ScrollTable1D
    .byte 1, <ScrollTable1E
ScrollTable1E
    .byte 1, <ScrollTable1F
ScrollTable1F
    .byte 1, <ScrollTable20
ScrollTable20
    .byte 1, <ScrollTable21
ScrollTable21
    .byte 1, <ScrollTable22
ScrollTable22
    .byte 1, <ScrollTable23
ScrollTable23
    .byte 1, <ScrollTable24
ScrollTable24
    .byte 1, <ScrollTable25
ScrollTable25
    .byte 1, <ScrollTable26
ScrollTable26
    .byte 1, <ScrollTable27
ScrollTable27
    .byte 1, <ScrollTable28
ScrollTable28
    .byte 2, <ScrollTable29
ScrollTable29
    .byte 2, <ScrollTable2A
ScrollTable2A
    .byte 2, <ScrollTable2B
ScrollTable2B
    .byte 2, <ScrollTable2C
ScrollTable2C
    .byte 2, <ScrollTable2D
ScrollTable2D
    .byte 2, <ScrollTable2E
ScrollTable2E
    .byte 2, <ScrollTable2F
ScrollTable2F
    .byte 2, <ScrollTable30
ScrollTable30
    .byte 2, <ScrollTable31
ScrollTable31
    .byte 2, <ScrollTable32
ScrollTable32
    .byte 2, <ScrollTable33
ScrollTable33
    .byte 2, <ScrollTable34
ScrollTable34
    .byte 2, <ScrollTable35
ScrollTable35
    .byte 2, <ScrollTable36
ScrollTable36
    .byte 2, <ScrollTable37
ScrollTable37
    .byte 2, <ScrollTable38
ScrollTable38
    .byte 2, <ScrollTable39
ScrollTable39
    .byte 2, <ScrollTable3A
ScrollTable3A
    .byte 2, <ScrollTable3B
ScrollTable3B
    .byte 2, <ScrollTable3C
ScrollTable3C
    .byte 3, <ScrollTable3D
ScrollTable3D
    .byte 3, <ScrollTable3E
ScrollTable3E
    .byte 3, <ScrollTable3F
ScrollTable3F
    .byte 3, <ScrollTable40
ScrollTable40
    .byte 3, <ScrollTable41
ScrollTable41
    .byte 3, <ScrollTable42
ScrollTable42
    .byte 3, <ScrollTable43
ScrollTable43
    .byte 3, <ScrollTable44
ScrollTable44
    .byte 3, <ScrollTable45
ScrollTable45
    .byte 3, <ScrollTable46
ScrollTable46
    .byte 3, <ScrollTable47
ScrollTable47
    .byte 3, <ScrollTable48
ScrollTable48
    .byte 3, <ScrollTable49
ScrollTable49
    .byte 3, <ScrollTable4A
ScrollTable4A
    .byte 3, <ScrollTable4B
ScrollTable4B
    .byte 3, <ScrollTable4C
ScrollTable4C
    .byte 3, <ScrollTable4D
ScrollTable4D
    .byte 3, <ScrollTable4E
ScrollTable4E
    .byte 3, <ScrollTable4F
ScrollTable4F
    .byte 3, <ScrollTable50
ScrollTable50
    .byte 4, <ScrollTable51
ScrollTable51
    .byte 4, <ScrollTable52
ScrollTable52
    .byte 4, <ScrollTable53
ScrollTable53
    .byte 4, <ScrollTable54
ScrollTable54
    .byte 4, <ScrollTable55
ScrollTable55
    .byte 4, <ScrollTable56
ScrollTable56
    .byte 4, <ScrollTable57
ScrollTable57
    .byte 4, <ScrollTable58
ScrollTable58
    .byte 4, <ScrollTable59
ScrollTable59
    .byte 4, <ScrollTable5A
ScrollTable5A
    .byte 4, <ScrollTable5B
ScrollTable5B
    .byte 4, <ScrollTable5C
ScrollTable5C
    .byte 4, <ScrollTable5D
ScrollTable5D
    .byte 4, <ScrollTable5E
ScrollTable5E
    .byte 4, <ScrollTable5F
ScrollTable5F
    .byte 4, <ScrollTable60
ScrollTable60
    .byte 4, <ScrollTable61
ScrollTable61
    .byte 4, <ScrollTable62
ScrollTable62
    .byte 4, <ScrollTable63
ScrollTable63
    .byte 4, <ScrollTable00

; *****************************************************************************
	
	org $FF00       ; 16 x 10 + 25 + 15 + 10 = 210 bytes in this page so far, 
	                ; max is 252
	
DigitsDataPF1Right0
; digits 0 through F for display on the Right screen nyble of PF1, first line

    .byte %00000010, %00000111, %00000111, %00000110, %00000001, %00000110
	.byte %00000010, %00000010, %00000010, %00000010, %00000101, %00000110
	.byte %00000010, %00000110, %00000111, %00000100

DigitsDataPF1Right1
; digits 0 through F for display on the Right screen nyble of PF1, second line

	.byte %00000101, %00000010, %00000100, %00000001, %00000001, %00000001
	.byte %00000101, %00000010, %00000101, %00000001, %00000101, %00000101
	.byte %00000101, %00000101, %00000100, %00000100
	
DigitsDataPF1Right2
; digits 0 through F for display on the Right screen nyble of PF1, third line

	.byte %00000101, %00000010, %00000010, %00000010, %00000111, %00000110
	.byte %00000110, %00000010, %00000010, %00000011, %00000111, %00000110
	.byte %00000100, %00000101, %00000110, %00000110
	
DigitsDataPF1Right3
; digits 0 through F for display on the Right screen nyble of PF1, fourth line

	.byte %00000101, %00000110, %00000001, %00000001, %00000101, %00000100
	.byte %00000100, %00000001, %00000101, %00000101, %00000101, %00000101
	.byte %00000101, %00000101, %00000100, %00000100
	
DigitsDataPF1Right4
; digits 0 through F for display on the Right screen nyble of PF1, fifth line

	.byte %00000010, %00000010, %00000110, %00000110, %00000101, %00000111
	.byte %00000010, %00000111, %00000010, %00000010, %00000010, %00000110
	.byte %00000010, %00000110, %00000111, %00000111

DigitsDataPF2Left0
; digits 0 through F for display on the Left screen nyble of PF2, first line

	.byte %00000100, %00001110, %00001110, %00000110, %00001000, %00000110
	.byte %00000100, %00000100, %00000100, %00000100, %00001010, %00000110
	.byte %00000100, %00000110, %00001110, %00000010
	
DigitsDataPF2Left1
; digits 0 through F for display on the Left screen nyble of PF2, second line

	.byte %00001010, %00000100, %00000010, %00001000, %00001000, %00001000
	.byte %00001010, %00000100, %00001010, %00001000, %00001010, %00001010
	.byte %00001010, %00001010, %00000010, %00000010
	
DigitsDataPF2Left2
; digits 0 through F for display on the Left screen nyble of PF2, third line

	.byte %00001010, %00000100, %00000100, %00000100, %00001110, %00000110
	.byte %00000110, %00000100, %00000100, %00001100, %00001110, %00000110
	.byte %00000010, %00001010, %00000110, %00000110
	
DigitsDataPF2Left3
; digits 0 through F for display on the Left screen nyble of PF2, fourth line

	.byte %00001010, %00000110, %00001000, %00001000, %00001010, %00000010
	.byte %00000010, %00001000, %00001010, %00001010, %00001010, %00001010
	.byte %00001010, %00001010, %00000010, %00000010
	
DigitsDataPF2Left4
; digits 0 through F for display on the Left screen nyble of PF2, fifth line
	
    .byte %00000100, %00000100, %00000110, %00000110, %00001010, %00001110
	.byte %00000100, %00001110, %00000100, %00000100, %00000100, %00000110
	.byte %00000100, %00000110, %00001110, %00001110

LivesIndicatorData0
; tick mark style digits 0 through 3 for display in PF0, fifth line

	.byte %00000000, %00100000, %00100000, %00100000

LivesIndicatorData1
; tick mark style digits 0 through 3 for display in PF0, fourth line

	.byte %00000000, %00000000, %00000000, %00000000
	
LivesIndicatorData2
; tick mark style digits 0 through 3 for display in PF0, third line

	.byte %00000000, %00000000, %00100000, %00100000
	
LivesIndicatorData3
; tick mark style digits 0 through 3 for display in PF0, second line

	.byte %00000000, %00000000, %00000000, %00000000
	
LivesIndicatorData4
; tick mark style digits 0 through 3 for display in PF0, first line

	.byte %00000000, %00000000, %00000000, %00100000
	
IndicatorColorData

    .byte $4A, $48, $46, $44, $42
    
LevelZeroData

    .byte %00010000, %00010000, %00010000, %00010000, %00010000
    .byte %01110111, %00010100, %00100110, %01000100, %01110111
    .byte %01000110, %10101010, %10100110, %10101010, %01001010
    
ColorDataP0

    .byte $18, $16, $14, $12, $10

ColorDataP1

    .byte $58, $56, $54, $42, $50
		
	
; *****************************************************************************

	org $FFFC
	.word Start
	.word Start

	org $FF00
Current Thread