notBD 0.12 - some extra graphics

Subject: notBD 0.12 - some extra graphics
From: "Andrew Davie" <atari2600@xxxxxxxxxxxxx>
Date: Wed, 12 Jan 2005 00:20:26 +1100
A few small graphics additons, and the full source code. A bit messy, but interesting to see how it's all done, I hope :) Also included, a screen shot for those unable to view on the real thing.
Cheers
A

Attachment: notBD12JAN2005b.zip
Description: Zip compressed data

Attachment: 01911734.jpg
Description: JPEG image

;------------------------------------------------------------------------------
; not-Boulderdash! Copyright (C)2003-2005 Andrew Davie
; This is a testbed for background animation games.
; Display technology developed late 2004 by Andrew Davie



; The genesis of the large-sprite system contained herein comes from Eckhard Stohlberg's
; fine work on the 'BIGTWO' sprite system (see the [stella] list archives at
; http://www.biglist.com/lists/stella/archives/ ) and in his preliminary fighter code
; kindly loaned to assist in creating this program.

; The sprite system this program uses is somewhat different to Eckhard's - being more
; efficient and capable (in terms of sprite display) but does essentially retain the
; positioning and movement system of the initial system.  Many thanks ES!

; This code is for a 512KB cartridge using the $3F bank-switching scheme.  If running
; with Z26 emulator (v1.57+) use -g11 switch on command-line.

;------------------------------------------------------------------------------
; COLOUR BITMAP COLOUR CYCLING TESTBED
; Code Copyright (C)2003 Andrew Davie -- atari2600@xxxxxxxxxxxxx
; May be freely used for private, educational and research purposes.
; If you wish to profit from it, please ask me for permission first.
; Distributed to the [stella] list 30/March/2003

FIXED_BANK          = 63 * 2048         ;--> 128K ROM for KK/CC2 compatibility
;FIXED_BANK         = 239 * 2048        ;--> 480K ROM for KK/CC2 compatibility
;FIXED_BANK         = 255 * 2048        ;--> 512K ROM tested OK
;FIXED_BANK         = 127 * 2048        ;--> 256K ROM tested OK

NTSC                = 0
PAL                 = 1
SECAM               = 2


#ifconst COLOUR #else

; Preferentially assemble with...
; -DCOLOUR=0 for NTSC ; -DCOLOUR=1 for PAL
; -DCOLOUR=2 for SECAM
; If not present, then will default to the value shown here


COLOUR              = PAL               ; <-- change THIS to NTSC, PAL, or SECAM
#endif

;DOUBLE_BUFFERED = 1 ; 0 disableds double-buffering

RESERVED_FOR_STACK = 6 ; guaranteed not overwritten by variable use

;------------------------------------------------------------------------------

; THE SCREEN BUFFERS...
; We have a double-buffered bitmap screen system.  Each of the screens itself
; is composed of two 'frames' -- as we're displaying using an interlaced display
; system.  Each screen/frame buffer is in its own RAM bank, as it is close to
; 1K in size.  In theory, we fill the non-visible pair of frame buffers (eg:
; Screen0A *and* Screen0B), and then switch the display system to use these
; now-completed buffers -- freeing Screen1A and Screen1B for the next draw.

BYTES_PER_LINE  = 5                         ; PF0 is double-packed!
SCREEN_WIDTH    = 10                        ; board characters per line (DIFFICULT TO CHANGE)

LINES_PER_CHAR  = 18                        ; MULTIPLE OF 3 SO RGB INTERFACES CHARS OK
SCREEN_LINES    = 10                        ; number of scanlines in screen buffer

SCREEN_DEPTH    = SCREEN_LINES * LINES_PER_CHAR
SCREEN_ARRAY_SIZE   = SCREEN_WIDTH * SCREEN_LINES

; Note: we're balancing lines per screen (LINES_PER_CHAR * SCREEN_LINES) against scanlines
;   which should be 192 or preferably less so we can display status line data
;   against 1K (BYTES_PER_LINE * SCREEN_LINES * LINES_PER_CHAR ) RAM limit for buffer
;   against aspect ratio of characters (square is about 24 lines per char).
;   against the cost per character for drawing and ROM (the less lines the better).
;   The best balance seems to be 18 lines/char @ 9 lines/screen.  Also Try 18/10

; 18/9 --> 972 bytes

               processor 6502
               include "vcs.h"
               include "macro.h"

BGCHRONO            = 0
SPRITES             = 0
DEBUG               = 0         ; non-zero for debug stuff

BGCOL = BLACK
PFCOL = 0 ;%011100100


D0                  = 1
D1                  = 2
D2                  = 4
D3                  = 8
D4                  = 16
D5                  = 32
D6                  = 64
D7                  = 128

SET_BANK = $3F ; write address to switch ROM banks

SET_BANK_RAM        = $3E       ; write address to switch RAM banks
                           ; these live at $1000-$13FF (READ) and +$400 (WRITE)

BANKPAGE = $F000 ; base address of bank blocks

BLACK		        = 0
NTSC_RED            = %00110110         ; NTSC colours
NTSC_GREEN          = %11001000
NTSC_BLUE           = %01110110

PAL_RED             = $66 ;64               ; PAL colours  $C8?
PAL_GREEN           = $56 ;54
PAL_BLUE            = $D6 ;D4


#if COLOUR = NTSC RED = NTSC_RED GREEN = NTSC_GREEN BLUE = NTSC_BLUE #endif

#if COLOUR = PAL
RED         = PAL_RED
GREEN       = PAL_GREEN
BLUE        = PAL_BLUE
#endif


;------------------------------------------------------------------------------
; Code automatically compiles to implement the sprites in the size/format
; specified here. Can handle up to 6 rows.





INTERLACED = 1 ; zero for standard Interleaved ChronoColour(TM) ; non-0 generates interlaced image


;DIRECTION = 1 ; 0 = inwards, non-0 = outwards


BIG_ROWS        = 1
BIG_COLS        = 6         ; DO NOT CHANGE

BIG_SPRITES = 1 ; #creatures

;------------------------------------------------------------------------------
; MACRO definitions


           MAC NEWBANK ; bank name
               SEG {1}
               ORG ORIGIN
               RORG $F000
{1}             SET ORIGIN / 2048
ORIGIN          SET ORIGIN + 2048
_CURRENT_BANK   SET {1}
           ENDM

;--------------------------------------------------------------------------


MAC VECTOR ; just a word pointer to code .word {1} ENDM


MAC SETBANK lda #{1} sta ROM_Bank ; store as last-switched bank variable sta SET_BANK ; actually switch ROM bank ENDM


MAC ANIMATION lda #<{1} sta ObjAnimLO,x lda #>{1} sta ObjAnimHI,x lda #1 sta ObjDelay,x

			lda ObjFlag,x
			ora #OBJFLAG_WAIT			; animation in progress
			sta ObjFlag,x

ENDM

   MAC HANDLER
           ldy #{1}*2
           jsr SetHandler
   ENDM

MAC STATE ; does not continue after macro!

           ldy #STATE_{1}*2
           jmp SetState

ENDM

   MAC CALL ;label
           lda #{1}_BANK
           sta SET_BANK
           sta ROM_Bank
           jsr {1}
   ENDM

   MAC DEFINE_SUBROUTINE               ; name of subroutine
BANK_{1}        = _CURRENT_BANK         ; bank in which this subroutine resides
               SUBROUTINE              ; keep everything local
{1}                                     ; entry point
   ENDM



;------------------------------------------------------------------------------

               SEG.U variables
               ORG $80

BDF_Line                ds 1                ; line counter
BDF_LastLine            ds 1

BDS_LastChar            ds 1
BDS_CharPointer         ds 1
BufferedJoystick        ds 1


BoardScrollY ds 1 ; scroll position in board (Y) BoardScrollX ds 1 ; scroll position in board (X) ManY ds 1 ManX ds 1 OldX ds 1 OldY ds 1

ScreenDrawPhase ds 1 ; phase of screen drawing

rnd             ds 2
timer           ds 1
retry           ds 1
BASE_Bank       ds 1
BASE_Flag_Bank  ds 1

ScreenMask      ds 1
NegMask         ds 2
ScreenAddress   ds 2
ScreenAddressWRITE   ds 2

field           ds 1                ; for interlace toggle
BuildMode       ds 1                ; steps through the game/screen build process
clearer         ds 1
tscol           ds 2
tsRow           ds 1
Character       ds 2
Character2       ds 2

;DrawX           ds 2
;DrawY           ds 1
;CenterX         ds 2
;CenterY         ds 1
;FrameBank       ds 1

VisualX         ds 2
VisualY         ds 1

LoopCount       ds 1
SPBASE          ds BIG_ROWS * BIG_COLS * 2

TPlayer ds 1

BGColour        ds 1
BGPlayer        ds 1

Temp            ds 2
Anim            ds 2
RGBVec          ds 2
FrameCount      ds 1

Player          ds 1
FrameAddress    ds 2
Phase           ds 1
Phase2          ds 1
switch          ds 1

RAM_Bank        ds 1            ; last switched RAM bank (not accessible if ROM subsequently switched)
ROM_Bank        ds 1            ; last switched ROM bank (not accessible if RAM subsequently switched)

PCount          ds 1
Audio           ds 2

;----
Flags           ds 1
DrawStackPointer    ds 1        ; points to start entry of drawing stack (-1 = nothing to draw)

               ; -------L
               ; L = locked to opponent

FLAG_LOCK = D0

#if 0
LineR0X                                 ; 6 columns of each of RED, GREEN, BLUE
LineR0          ds 2                    ; 6 columns of RED sub-image
LineR1          ds 2
LineR2          ds 2
LineR3          ds 2
LineR4          ds 2
LineR5          ds 2

LineG0          ds 2                    ; 6 columns of GREEN sub-image
LineG1          ds 2
LineG2          ds 2
LineG3          ds 2
LineG4          ds 2
LineG5          ds 2

LineB0          ds 2                    ; 6 columns of BLUE sub-image
LineB1          ds 2
LineB2          ds 2
LineB3          ds 2
LineB4          ds 2
LineB5          ds 2
#endif


;---- ; Object variables


ObjXPosition ds BIG_SPRITES ObjYPosition ds BIG_SPRITES

ObjFacing ds BIG_SPRITES

               ; F-------
               ; F = facing direction (0 = right, 1 = left)
               ; - = unused

ObjDelay        ds BIG_SPRITES              ; delay count for frame animation
ObjAnimLO       ds BIG_SPRITES              ; animation pointer lo byte
ObjAnimHI       ds BIG_SPRITES              ; animation pointer hi byte
objAnimBank     ds BIG_SPRITES              ; bank containing animation

; Note: Possibly include bank with animation hi byte

ObjStateLO      ds BIG_SPRITES              ; state table lo byte
ObjStateHI      ds BIG_SPRITES              ; state table hi byte

ObjFSMLO        ds BIG_SPRITES              ; FSM system lo byte
ObjFSMHI        ds BIG_SPRITES              ; FSM system hi byte

ObjFlag			ds BIG_SPRITES
ObjFrame        ds BIG_SPRITES
ObjFrameBank    ds BIG_SPRITES
ObjPhase        ds BIG_SPRITES




Colour ds 3 Count ds 1


OBJFLAG_WAIT = D7 ; wait for animation



;------------------------------------------------------------------------------


STACK_SPACE     SET 6                       ; bytes for generic use (including jsr)
OVERLAY_SIZE    SET SCREEN_WIDTH + 10

MAC VALIDATE_OVERLAY

       #if * > $FF - STACK_SPACE
           ERR
       #endif

       #if * - Overlay > OVERLAY_SIZE
           ERR
       #endif
   ENDM



       ; This overlay variable is used for the overlay variables.  That's OK.
       ; However, it is positioned at the END of the variables so, if on the off chance we're overlapping
       ; stack space and variable, it is LIKELY that that won't be a problem, as the temp variables
       ; (especially the latter ones) are only used in rare occasions.

       ; FOR SAFETY, DO NOT USE THIS AREA DIRECTLY (ie: NEVER reference 'Overlay' in the code)
       ; ADD AN OVERLAY FOR EACH ROUTINE'S USE, SO CLASHES CAN BE EASILY CHECKED

Overlay         ds OVERLAY_SIZE       ;--> overlay (share) variables
               VALIDATE_OVERLAY


ds RESERVED_FOR_STACK


ECHO "FREE BYTES IN ZERO PAGE = ", $FF - *
;------------------------------------------------------------------------------
; OVERLAYS!
; These variables are overlays, and should be managed with care
; That is, variables are ALREADY DEFINED, and we're reusing RAM for other purposes


; EACH OF THESE ARE VARIABLES (TEMPORARY) USED BY ONE ROUTINE (AND IT'S SUBROUTINES)
; THAT IS, LOCAL VARIABLES.  USE 'EM FREELY, THEY COST NOTHING

; TOTAL SPACE USED BY ANY OVERLAY GROUP SHOULD BE <= SIZE OF 'Overlay'

;------------------------------------------------------------------------------

               SEG.U OVERLAY_BuildDrawFlags
               org Overlay

BDF_DrawFlagAddress ds 2 ; destination address of draw flag (mirrors ScreenBuffer)
BDF_BoardAddress ds 2 ; source address from Board
BDF_LineBuffer ds SCREEN_WIDTH ; copy of line for efficient builds BDF_BoardBank ds 1 ; holds bank of current line
ECHO "FREE BYTES IN IN OVERLAY_BuildDrawFlags = ", OVERLAY_SIZE - ( * - Overlay )
VALIDATE_OVERLAY


;------------------------------------------------------------------------------

               SEG.U OVERLAY_TimeSlice
               org Overlay

TS_Vector               ds 2                ; vector to correct processing code
   ECHO "FREE BYTES IN IN OVERLAY_TimeSlice = ", OVERLAY_SIZE - ( * - Overlay )
               VALIDATE_OVERLAY

;------------------------------------------------------------------------------

               SEG.U OVERLAY_DrawNewCharacters
               org Overlay

DNC_CharCount           ds 1                ; character draw counter
   ECHO "FREE BYTES IN IN OVERLAY_DrawNewCharacters = ", OVERLAY_SIZE - ( * - Overlay )
               VALIDATE_OVERLAY

;------------------------------------------------------------------------------

               SEG.U OVERLAY_ClearScreen
               org Overlay

CS_Line         ds 1
CS_BoardAddress ds 2
   ECHO "FREE BYTES IN IN OVERLAY_ClearScreen = ", OVERLAY_SIZE - ( * - Overlay )
               VALIDATE_OVERLAY

;------------------------------------------------------------------------------

               SEG.U OVERLAY_BuildDrawStack
               org Overlay
BDS_DrawFlag    ds 2
BDS_ScreenBuffer   ds 2
   ECHO "FREE BYTES IN IN OVERLAY_BuildDrawStack = ", OVERLAY_SIZE - ( * - Overlay )
               VALIDATE_OVERLAY

;------------------------------------------------------------------------------

               SEG.U OVERLAY_SwapDrawBuffer
               org Overlay
SDB_Address         ds 2
   ECHO "FREE BYTES IN IN OVERLAY_SwapDrawBuffer = ", OVERLAY_SIZE - ( * - Overlay )
               VALIDATE_OVERLAY

;------------------------------------------------------------------------------

               SEG.U OVERLAY_ChronoOverlay
               org Overlay
ChronoBank      ds 3
ChronoColour    ds 3
ScreenPtr       ds 2
   ECHO "FREE BYTES IN IN ChronoOverlay = ", OVERLAY_SIZE - ( * - Overlay )
               VALIDATE_OVERLAY


;============================================================================== ; NOW THE VERY INTERESTING '3E' RAM BANKS ; EACH BANK HAS A READ-ADDRESS AND A WRITE-ADDRESS, WITH 2k TOTAL

RAM_3E          = $1000
RAM_SIZE        = $400
RAM_WRITE       = $400                  ; add this to RAM address when doing writes

   MAC NEWRAMBANK ; bank name
       SEG.U {1}
       ORG ORIGIN
       RORG RAM_3E
{1}     SET ORIGIN / RAM_SIZE
ORIGIN  SET ORIGIN + RAM_SIZE
   ENDM

   MAC VALIDATE_RAM_SIZE
       #if * - RAM_3E > RAM_SIZE
           ERR
       #endif
   ENDM

;------------------------------------------------------------------------------

ORIGIN SET 0


; NOTE: BANK NUMBERING OF BANK_BUFFER_0 and BANK_SCREEN_0A MUST BE SUCH THAT AN EOR
; with 1 or 2 will switch between the alternate buffers.
NEWRAMBANK BANK_BUFFER_0
; NOTE: Access to these buffers must NOT overlap pages...
DrawFlag ds SCREEN_ARRAY_SIZE ; marks if ScreenBuffer character has to be drawn
ScreenBuffer ds SCREEN_ARRAY_SIZE ; the char buffer for delta-drawing
ALIGN 256
DrawStack ds SCREEN_ARRAY_SIZE ; marks if ScreenBuffer character has to be drawn
VALIDATE_RAM_SIZE
NEWRAMBANK BANK_BUFFER_1 ; MIRROR of BANK_BUFFER_0
ds SCREEN_ARRAY_SIZE ; marks if ScreenBuffer character has to be drawn
ds SCREEN_ARRAY_SIZE ; the char buffer for delta-drawing
ALIGN 256
ds SCREEN_ARRAY_SIZE ; marks if ScreenBuffer character has to be drawn


SWAP_FLAG = BANK_BUFFER_0 ^ BANK_BUFFER_1
; Note: Ordering of banks, and variable placement in these banks is assumed by ClearScreen NEWRAMBANK BANK_SCREEN_0A
ScreenBitmap ds BYTES_PER_LINE * SCREEN_DEPTH ; the actual bitmap buffer
VALIDATE_RAM_SIZE


               NEWRAMBANK BANK_SCREEN_0B               ; MIRROR of BANK_SCREEN_0A
               ds BYTES_PER_LINE * SCREEN_DEPTH        ; the actual bitmap buffer
               NEWRAMBANK BANK_SCREEN_1A               ; MIRROR of BANK_SCREEN_0A
               ds BYTES_PER_LINE * SCREEN_DEPTH        ; the actual bitmap buffer
               NEWRAMBANK BANK_SCREEN_1B               ; MIRROR of BANK_SCREEN_0A
               ds BYTES_PER_LINE * SCREEN_DEPTH        ; the actual bitmap buffer


SWAP_SCREEN = BANK_SCREEN_0A ^ BANK_SCREEN_1A



; With the above, we essentially end up with 4 identical banks, consisting of two
; pairs of buffers (ie: double-buffered) which each consist of two frames (of interlaced data)
; The buffers are all addressed through the labels 'ScreenBitmap' and 'ScreenBuffer' with
; the correct bank switched in. It's a neat overloaded system.


; Note that when we are drawing, we *ONLY* have to draw the characters that are
; different between our ScreenXXBuffer[][] and the Board[][].  Those which are
; the same (which will be MOST of the screen MOST of the time) will already have
; their correct shape in the ScreenXX[][] bitmap.




; Now the interesting 'BOARD' -- which in reality is a free-form system of M*N ; rows and columns. We need to reserve enough RAM for the board's entirety, but ; don't really care much how it overlaps the 1K bank limit. The code accessing ; the board *MUST* calculate and take account of the correct RAM bank to switch ; when accessing. Ouch!


SIZE_BOARD_X = 64 SIZE_BOARD_Y = 32 SIZE_BOARD = SIZE_BOARD_X * SIZE_BOARD_Y


; NOTE: Assumption is that board lines CANNOT CROSS page boundaries.


NEWRAMBANK BANK_BOARD
Board ds SIZE_BOARD ; Note, we can only access this in ; 1024 byte chunks, switching RAM
; banks as we go. In other words,
; this overlaps multiple banks! ; free space here (but hard to use) ; So we need to calculate where the next free bank is!


ORIGIN          SET ( * + RAM_SIZE - 1 ) / RAM_SIZE
ORIGIN          SET ORIGIN * RAM_SIZE




NEWRAMBANK BANK_OBJSTACK


   ; The objects are a list of X,Y positions into the BOARD.  Each of these is a board
   ; position of something that needs to be processed.  These things include anything
   ; that animates.  Objects which no longer need processing do not re-add themselves
   ; to the object stack.  There are two stacks -- the one being processed, and the
   ; one for the next processing iteration.

ObjStackX       ds 256                      ; X coord of object to process
ObjStackY       ds 256                      ; Y coord of object to process

VALIDATE_RAM_SIZE

NEWRAMBANK BANK_OBJSTACK2
; THIS IS A MIRROR OF BANK_DOLIST -- DO NOT MODIFY OR USE!!
VALIDATE_RAM_SIZE
SWAP_OBJSTACK = BANK_OBJSTACK ^ BANK_OBJSTACK2



NEWRAMBANK BANK_RAM_X ; free space here VALIDATE_RAM_SIZE





; NOTE: THERE ARE *ONLY* 32 1K RAM BANKS SO WE CAN'T EXCEED THIS LIMIT!

#if ORIGIN > 32*1024
   ERR "RAM overflow"
#endif



;==============================================================================
; Include all the graphics into separate 2K segments

ORIGIN SET $00000

           NEWBANK FRAMEBANK09
           include "Graphics\bank09.asm"

           NEWBANK FRAMEBANK02
           include "Graphics\bank02.asm"

NEWBANK FRAMEBANK03
include "Graphics\bank03.asm"
NEWBANK FRAMEBANK11
include "Graphics\bank11.asm"
NEWBANK FRAMEBANK12
include "Graphics\bank12.asm"
NEWBANK FRAMEBANK10
include "Graphics\bank10.asm"


           NEWBANK FRAMEBANK06
           include "Graphics\bank06.asm"

           NEWBANK FRAMEBANK07
           include "Graphics\bank07.asm"

           NEWBANK FRAMEBANK08
           include "Graphics\bank08.asm"

           NEWBANK FRAMEBANK13
           include "Graphics\bank13.asm"

           NEWBANK FRAMEBANK00
           include "Graphics\bank00.asm"

           NEWBANK FRAMEBANK01
           include "Graphics\bank01.asm"

           NEWBANK FRAMEBANK04
           include "Graphics\bank04.asm"

           NEWBANK FRAMEBANK05
           include "Graphics\bank05.asm"

           NEWBANK FRAMEBANK14
           include "Graphics\bank14.asm"

           NEWBANK FRAMEBANK15
           include "Graphics\bank15.asm"

           NEWBANK FRAMEBANK16
           include "Graphics\bank16.asm"

           NEWBANK FRAMEBANK17
           include "Graphics\bank17.asm"

           NEWBANK FRAMEBANK18
           include "Graphics\bank18.asm"

           NEWBANK FRAMEBANK19
           include "Graphics\bank19.asm"
;==============================================================================

;            NEWBANK BLUEBANK
;            include "testblue.asm"

;------------------------------------------------------------------------------
;            NEWBANK REDBANK
;            include "testred.asm"

;------------------------------------------------------------------------------
;            NEWBANK GREENBANK
;            include "testgreen.asm"


NEWBANK MOVIE0 include "Movie\0red.asm"

           NEWBANK MOVIE1
           include "Movie\0blue.asm"

           NEWBANK MOVIE2
           include "Movie\1green.asm"

           NEWBANK MOVIE3
           include "Movie\2red.asm"
           include "Movie\2green.asm"

           NEWBANK MOVIE4
           include "Movie\2blue.asm"
           include "Movie\3red.asm"

           NEWBANK MOVIE5
           include "Movie\3green.asm"
           include "Movie\3blue.asm"

           NEWBANK MOVIE6
           include "Movie\4red.asm"
           include "Movie\4green.asm"

           NEWBANK MOVIE7
           include "Movie\4blue.asm"
           include "Movie\5red.asm"

           NEWBANK MOVIE8
           include "Movie\5green.asm"
           include "Movie\5blue.asm"

           NEWBANK MOVIE0B
           include "Movie\0green.asm"

           NEWBANK MOVIE1B
           include "Movie\1red.asm"

           NEWBANK MOVIE1BLUE
           include "Movie\1blue.asm"


;------------------------------------------------------------------------------ NEWBANK TITLESCREEN

#if 0

DoMovie
rts

lda #$80
sta Audio+1 ; audio pointer
lda #0
sta Audio


           lda #0
           sta PCount

rr

           ldy PCount
           lda PFrame,y
           bpl PCOKC
           lda #0
           sta PCount
           beq rr
PCOKC
           ldy #3
           jsr TitleScreen

inc PCount

           clc
           lda Audio
           adc #0
           sta Audio
           lda Audio+1
           adc #1
           sta Audio+1

;; inc Audio+1

jmp rr

rts
;PFrame gives list of frames to play!


PFrame      .byte 0,1,0,1,0,1,0,1,0,1,0,1,0,1,4,5,4,5,4,5,4,5,4,5,-1
#endif


#if 0


   ; The image file is composed of strips (corresponding to PF0-PF2, repeated)
   ; which are decomposed by a utility from colour-separated RGB components of
   ; an original image. The displayed image is 40 pixels x 192 pixels.

   ; For access to the conversion/decomposition tool which generated these data
   ; please contact me privately.

;------------------------------------------------------------------------------


TitleScreen


sty FrameCount

; Calculate address data for requested screen

           asl
           tay                 ; word index
           lda ChronoScreen,y
           sta ScreenPtr
           lda ChronoScreen+1,y
           sta ScreenPtr+1


ldy #0


lda (ScreenPtr),y
sta ChronoBank
iny
lda (ScreenPtr),y
sta ChronoBank+1


           iny
           lda (ScreenPtr),y
           sta ChronoBank+2



ldx #0

SetupLinePtr
           iny
           lda (ScreenPtr),y
           sta LineR0,x
           inx
           cpx #42
           bne SetupLinePtr



;---------------------------------------------------------------------------

           lda #RED
           sta Colour
           lda #GREEN
           sta Colour+1
           lda #BLUE
           sta Colour+2




           lda #2
           sta Phase

AnotherFrame

           jsr TitleFrame
           jsr TitleFrame

           dec FrameCount
           bne AnotherFrame

rts





TitleFrame


; Start of vertical blank processing



NewFrame2 lda #D6+D1
sta VBLANK


lda #43 sta TIM64T

lda #0
sta HMCLR
lda field
#if INTERLACED
eor #1
sta field
#endif
jsr Interlace
; jsr VBPROCESSING @2000 cycles
VblankLoop2 lda INTIM
bne VblankLoop2 sta WSYNC sta VBLANK


   ;------------------------------------------------------------------------------
   ; START OF DISPLAY


#if COLOUR = NTSC lda #238 ; NTSC #else lda #238 #endif sta TIM64T

lda #%00010100 ; reflect, priority, 2 pixel wide ball
sta CTRLPF
lda #0
sta PF0
sta PF1
sta PF2


   ;--------------------------------------------------------------------------
   ; START OF COLOUR BITMAP DISPLAY KERNEL

           ldx Phase
           lda NextPhase,x
           sta Phase

           lda #0
           sta Count
Nzap

           lda #RED
           sta ChronoColour
           lda #GREEN
           sta ChronoColour+1
           lda #BLUE
           sta ChronoColour+2

jsr ChronoDraw

; Screen has been drawn - now just tidy up

           sty WSYNC
           sty PF0
           sty PF1
           sty PF2

PadScreen2b lda INTIM
bne PadScreen2b
sta WSYNC


           lda #%01000010
           sta VBLANK                      ; end of screen - enter blanking


#if COLOUR = NTSC


lda #84 ;25

#else
           lda #88

#endif

sta TIM64T

Overscan2    lda INTIM
           bne Overscan2

sta WSYNC rts



ChronoScreen


.word BeachFrame0 .word BeachFrame1 .word BeachFrame2 .word BeachFrame3 .word BeachFrame4 .word BeachFrame5


BeachFrame0 .byte MOVIE0, MOVIE0B, MOVIE1 .word testred0_STRIP_0, testred0_STRIP_1, testred0_STRIP_2, testred0_STRIP_3, testred0_STRIP_4, testred0_STRIP_5, AUDIO0RED .word testgreen0_STRIP_0, testgreen0_STRIP_1, testgreen0_STRIP_2, testgreen0_STRIP_3, testgreen0_STRIP_4, testgreen0_STRIP_5, $8000 .word testblue0_STRIP_0, testblue0_STRIP_1, testblue0_STRIP_2, testblue0_STRIP_3, testblue0_STRIP_4, testblue0_STRIP_5, $8000

BeachFrame1
   .byte MOVIE1B, MOVIE2, MOVIE1BLUE
   .word testred1_STRIP_0, testred1_STRIP_1, testred1_STRIP_2, testred1_STRIP_3, testred1_STRIP_4, testred1_STRIP_5, $8000
   .word testgreen1_STRIP_0, testgreen1_STRIP_1, testgreen1_STRIP_2, testgreen1_STRIP_3, testgreen1_STRIP_4, testgreen1_STRIP_5, $8000
   .word testblue1_STRIP_0, testblue1_STRIP_1, testblue1_STRIP_2, testblue1_STRIP_3, testblue1_STRIP_4, testblue1_STRIP_5, $8000

BeachFrame2
   .byte MOVIE3, MOVIE3, MOVIE4
   .word testred2_STRIP_0, testred2_STRIP_1, testred2_STRIP_2, testred2_STRIP_3, testred2_STRIP_4, testred2_STRIP_5, $8000
   .word testgreen2_STRIP_0, testgreen2_STRIP_1, testgreen2_STRIP_2, testgreen2_STRIP_3, testgreen2_STRIP_4, testgreen2_STRIP_5, $8000
   .word testblue2_STRIP_0, testblue2_STRIP_1, testblue2_STRIP_2, testblue2_STRIP_3, testblue2_STRIP_4, testblue2_STRIP_5, $8000

BeachFrame3
   .byte MOVIE4, MOVIE5, MOVIE5
   .word testred3_STRIP_0, testred3_STRIP_1, testred3_STRIP_2, testred3_STRIP_3, testred3_STRIP_4, testred3_STRIP_5, $8000
   .word testgreen3_STRIP_0, testgreen3_STRIP_1, testgreen3_STRIP_2, testgreen3_STRIP_3, testgreen3_STRIP_4, testgreen3_STRIP_5, $8000
   .word testblue3_STRIP_0, testblue3_STRIP_1, testblue3_STRIP_2, testblue3_STRIP_3, testblue3_STRIP_4, testblue3_STRIP_5, $8000

BeachFrame4
   .byte MOVIE6, MOVIE6, MOVIE7
   .word testred4_STRIP_0, testred4_STRIP_1, testred4_STRIP_2, testred4_STRIP_3, testred4_STRIP_4, testred4_STRIP_5, $8000
   .word testgreen4_STRIP_0, testgreen4_STRIP_1, testgreen4_STRIP_2, testgreen4_STRIP_3, testgreen4_STRIP_4, testgreen4_STRIP_5, $8000
   .word testblue4_STRIP_0, testblue4_STRIP_1, testblue4_STRIP_2, testblue4_STRIP_3, testblue4_STRIP_4, testblue4_STRIP_5, $8000

BeachFrame5
   .byte MOVIE7, MOVIE7, MOVIE8
   .word testred5_STRIP_0, testred5_STRIP_1, testred5_STRIP_2, testred5_STRIP_3, testred5_STRIP_4, testred5_STRIP_5, $8000
   .word testgreen5_STRIP_0, testgreen5_STRIP_1, testgreen5_STRIP_2, testgreen5_STRIP_3, testgreen5_STRIP_4, testgreen5_STRIP_5, $8000
   .word testblue5_STRIP_0, testblue5_STRIP_1, testblue5_STRIP_2, testblue5_STRIP_3, testblue5_STRIP_4, testblue5_STRIP_5, $8000

;===============================================================================
#endif

NEWBANK INITBANK

InitX
.XP     SET 80-48


REPEAT BIG_SPRITES .byte .XP .XP SET .XP + 48 REPEND


; There's no particular reason why this code lives in a separate bank ; but it's as good-a-test as any for checking the bankswitching is working


Cart_Init


CLEAN_START

lda #0
sta SWBCNT ; console I/O always set to INPUT
sta SWACNT ; set controller I/O to INPUT




;-------------------------------------------------------------------------------------
lda #0
sta BoardScrollX
sta BoardScrollY ; Setup the screen to the start of the board
sta ScreenDrawPhase ; sequences the sections of gameplay/screen drawing
lda #5
sta ManX
sta ManY
lda #BANK_SCREEN_0A
sta BASE_Bank ; base screen bank for double-buffering
lda #BANK_BUFFER_0
sta BASE_Flag_Bank ; and the corresponding buffer bank
;-------------------------------------------------------------------------------------



jsr BOULDERDASH_SCREENDRAW


#if SPRITES

           sta field
           sta BuildMode                   ; start at the beginning of the build


GameInit


           lda #0
           sta Flags
           sta Player

; Initialise creatures

ldx #BIG_SPRITES-1
PreClear


lda #0
sta ObjFacing,x
sta ObjFlag,x
sta ObjPhase,x ; RGB 0/1/2 kernel display pase
; sta ObjAnimHI,x
lda #120
sta ObjYPosition,x


           lda InitX,x
           sta ObjXPosition,x

SETBANK INITBANK
ldy #STATE_NORMAL*2
jsr SetState ; also calls processFSM


CALL AnimateObject ; process object animation sequence

           dex
           bpl PreClear

;loopx       inx
;            stx COLUBK
;            jmp loopx


;---------------------------------- ; Hardwire init a single creature...

#if BIG_SPRITES > 1

;            lda #D7
;            sta ObjFacing           ;todo currently fucked

           ldx #1
           HANDLER EVENT_INIT2

;            ldx #0
;            HANDLER 0

#endif

; ldx #0
; HANDLER NORMAL_STAND


;----------------------------------


lda #BGCOL sta BGColour jmp NewFrame


#endif


#if 0
   include "Graphics\bank_FRAMETABLE.asm"
;------------------------------------------------------------------------------
; OBJECT Animation
; *MUST* BE IN ONE BANK


MAC SHOW .byte {1},{2} ENDM

   MAC SHOWRGB
   REPEAT {2}
       SHOW FRAME_{1}RED,1
       ;SHOW FRAME_{1}GREEN,1
       SHOW FRAME_{1}BLUE,1
   REPEND
   ENDM

MAC SYNCH
.byte TOKEN_SYNCH
ENDM
MAC SETCOL
.byte TOKEN_COLOUR
.byte {1}
ENDM


MAC LOCK

           .byte TOKEN_LOCK
           .byte {1}*2

ENDM


MAC UNLOCK .byte TOKEN_UNLOCK ENDM

   MAC GOTO
           .byte TOKEN_JUMP
           .word {1}
   ENDM

	MAC DONE
			.byte TOKEN_DONE
	ENDM

   MAC MOVE
           .byte TOKEN_MOVE
           .word {1}
           .byte {2}
   ENDM

	MAC FLIP
			.byte TOKEN_FLIP
	ENDM



NOFRAME equ $FF


noAnim lda #NOFRAME sta ObjFrame,x rts


exitAnim rts



DEFINE_SUBROUTINE AnimateObject


           lda ObjAnimHI,x
           beq noAnim                      ; animation switched off - use a null frame
           lda ObjAnimHI,x

           lda ObjDelay,x
           beq exitAnim                    ; static frame - no animation
           dec ObjDelay,x
           bne exitAnim                    ; not ready to change

ReAnimate   lda ObjAnimHI,x
           sta Anim+1
           lda ObjAnimLO,x
           sta Anim                        ; (Anim) points to frame sequence

ReReAnim    ldy #0
           lda (Anim),y
           bpl NormalFrame

           asl
           tay

           lda AnimVec,y
           sta Temp
           lda AnimVec+1,y
           sta Temp+1
           jmp (Temp)

   ;------------------------------------------------------------------------------
   ; Automatically define tokens and a vector table to token-processing code
   ; This is fairly neat, as the ordering of the entries in the table auto-generates
   ; the appropriate equates to access the table correctly!

TOK         SET 128
           MAC TOKEN
TOKEN_{1}   equ TOK
TOK         SET TOK + 1
           VECTOR Animate{1}
           ENDM

AnimVec     TOKEN JUMP
           TOKEN LOCK
           TOKEN MOVE
           TOKEN UNLOCK
           TOKEN DONE
           TOKEN FLIP
           TOKEN COLOUR
           TOKEN SYNCH


;------------------------------------------------------------------------------


AnimateDONE
			lda ObjFlag,x
			and #(~OBJFLAG_WAIT)&$FF
			sta ObjFlag,x
			
			lda #1
			jmp AnimUp



;------------------------------------------------------------------------------

AnimateFLIP

           lda ObjFacing,x
           eor #D7
           sta ObjFacing,x

			lda #1
			jmp AnimUp


NormalFrame
sta ObjFrame,x


           iny
           lda (Anim),y
           sta ObjDelay,x                  ; should be < 128

           clc
           lda Anim
           adc #2
           sta ObjAnimLO,x
           lda Anim+1
           adc #0
           sta ObjAnimHI,x
           rts

;------------------------------------------------------------------------------

AnimateLOCK

; lock other creature to this

           lda ObjXPosition,x
           pha
           lda ObjYPosition,x
           pha

           lda Flags
           ora #FLAG_LOCK
           sta Flags

           txa
           eor #1
           tax                         ; other player

           ldy #1
           lda (Anim),y
           tay
           jsr SetHandler              ; cause other player to react

           pla
           sta ObjYPosition,x
           pla
           sta ObjXPosition,x

           txa
           eor #1
           tax

lda #2

AnimUp      clc
           adc Anim
           sta Anim
           lda Anim+1
           adc #0
           sta Anim+1

jmp ReReAnim

;------------------------------------------------------------------------------

AnimateUNLOCK

           lda Flags
           and #(~FLAG_LOCK)&$FF
           sta Flags

           lda #1
           jmp AnimUp


;------------------------------------------------------------------------------



AnimateJUMP


; Handle a JUMP

           ldy #1
           lda (Anim),y
           sta ObjAnimLO,x
           iny
           lda (Anim),y
           sta ObjAnimHI,x
           jmp ReAnimate


AnimateCOLOUR ldy #1 lda (Anim),y sta BGPlayer lda #2 jmp AnimUp

;------------------------------------------------------------------------------
AnimateMOVE


ldy #1

           lda (Anim),y
           sta Temp
           iny
           lda (Anim),y
           sta Temp+1

           lda ObjFacing,x
           bpl MoveRight

           sec
           lda #0
           sbc Temp
           sta Temp
           lda #0
           sbc Temp+1
           sta Temp+1

MoveRight

           clc
           lda DrawX
           adc Temp
           sta DrawX
           lda DrawX+1
           adc Temp+1
           sta DrawX+1

           iny
           lda (Anim),y
           clc
           adc DrawY
           sta DrawY

           clc
           lda Anim
           adc #4
           sta Anim
           lda Anim+1
           adc #0
           sta Anim+1

jmp ReReAnim

AnimateSYNCH

#if BIG_SPRITES = 1
           ;lda #0
#else
           ;lda #2
#endif

           ;sta Phase
           lda #1
           jmp AnimUp

;------------------------------------------------------------------------------


; Animations processing code proceeds until it has a frame and duration ; The duration is in TV-frames, and counts down. When 0, the next 'command' in the ; animation sequence is processed. Animations must use the GOTO to halt or repeat ; Animations are tokenised interpreted little programs.

   ; Commands/Macros
   ;   GOTO label              Vector to the label
   ;   LOCK event              Lock opponents together, sending the opponent the event
   ;   MOVE x,y                Adjust position by x,y pixels
   ;   UNLOCK                  Unlock opponents
   ;   DONE                    Indicate animation finished (clears OBJFLAG_WAIT for creature)
   ;   FLIP                    Mirror creature
   ;   SHOW frame,delay        Set th creature rame and delay (also halts animation till delay counts to 0)



ANIMATION_STAND


; SYNCH




ANIMATION_STAND2

       SHOWRGB 1,4
       SHOWRGB 2,4
       SHOWRGB 3,4
       SHOWRGB 4,4
       SHOWRGB 5,4
       SHOWRGB 6,4
       SHOWRGB 7,4
       SHOWRGB 8,4
       SHOWRGB 9,4
       SHOWRGB 10,4
       SHOWRGB 11,4
       SHOWRGB 12,4

;        SHOWRGB CROC,4
       GOTO ANIMATION_STAND2


ANIMATION_RIGHT


       ;SHOWRGB 11,10
       GOTO ANIMATION_STAND2




; OBJECT Animation END ;------------------------------------------------------------------------------


;------------------------------------------------------------------------------ ; STATE Processing ; *MUST* BE IN ONE BANK

MAC FACEOPPONENT

txa
eor #1
tay
lda ObjFacing,y
sta ObjFacing,x
ENDM


	MAC WAIT
	SUBROUTINE
.HERE
			lda #<.HERE
			sta ObjFSMLO,x
			lda #>.HERE
			sta ObjFSMHI,x

; wait for animation to complete

			lda ObjFlag,x
			and #OBJFLAG_WAIT
			bne .CONT
			
		    lda #<{1}
           sta Temp
           lda #>{1}
           sta Temp+1
           jmp (Temp)						; vector to the handler now the wait has completed
.CONT
		; Or, wait is incomplete, so fall through

ENDM



SetState

   ; Set object's state base
   ; x = obj
   ; y = state table (*2)

           lda StateTables,y
           sta ObjStateLO,x
           lda StateTables+1,y
           sta ObjStateHI,x

ldy #EVENT_DEFAULT*2 ; fall through and include DEFAULT init for handler

SetHandler

   ; Change object's processing code
   ; x = obj
   ; y = new handler entry (word access)

           lda ObjStateHI,x
           beq NullHandler                     ; don't handle anything with no entry

           sta Temp+1
           lda ObjStateLO,x
           sta Temp

           iny
           lda (Temp),y
           beq NullHandler                     ; no handler present for given event
           sta ObjFSMHI,x
           dey
           lda (Temp),y
           sta ObjFSMLO,x



ProcessFSM

   ; Vector to the creature's processing code
   ; x = creature

           lda ObjFSMLO,x
           sta Temp
           lda ObjFSMHI,x
           sta Temp+1
           jmp (Temp)

NullHandler rts




;------------------------------------------------------------------------------ ; List of events

EVENT_DEFAULT           = 0                     ; default entry when switching states
EVENT_JOY_NULL          = 1
EVENT_JOY_UP            = 2
EVENT_JOY_DOWN          = 3
EVENT_JOY_LEFT          = 4
EVENT_JOY_RIGHT         = 5
EVENT_ATTACK_THROW      = 6

EVENT_INIT2 = 2


;------------------------------------------------------------------------------ ; Automatically define states and a vector table to state-processing code ; This is fairly neat, as the ordering of the entries in the table auto-generates ; the appropriate equates to access the table correctly!

STATEQ      SET 0
           MAC STATENTRY
STATE_{1}   equ STATEQ
STATEQ      SET STATEQ + 1
           VECTOR State{1}
           ENDM

StateTables STATENTRY NORMAL
           STATENTRY WAIT

   ;------------------------------------------------------------------------------
   ; NORMAL state table
   ; Each State table is a table of pointers to code processing 'EVENTS'

StateNORMAL
           VECTOR NormalInit                ; 0     EVENT_DEFAULT
           VECTOR NormalWait                ; 1     EVENT_JOY_NULL
           VECTOR NormalInitRight ;0 ;GetUp                     ; 4     EVENT_JOY_UP
           VECTOR 0 ;NormalInit;AttackThrow1              ; 5     EVENT_JOY_DOWN
           VECTOR 0;WalkTurnAround            ; 6     EVENT_JOY_LEFT
           VECTOR 0;WalkStart                 ; 7     EVEMT_JOY_RIGHT
           VECTOR 0;React_AttackThrow         ; 8     EVENT_ATTACK_THROW

;------------------------------------------------------------------------------


StateWAIT


; allows moves to complete without joystick interaction ; TODO: should still react to other creature moves

			VECTOR BusyInit                  ; 0     EVENT_DEFAULT
           VECTOR 0                         ; 1     EVENT_JOY_NULL
           VECTOR 0                         ; 4     EVENT_JOY_UP
           VECTOR 0					     ; 5     EVENT_JOY_DOWN
           VECTOR 0						 ; 6     EVENT_JOY_LEFT
           VECTOR 0						 ; 7     EVEMT_JOY_RIGHT
           VECTOR 0                         ; 8     EVENT_ATTACK_THROW

   ;------------------------------------------------------------------------------
   ; BUSY
   ; Waits until the animation clears the wait flag
   ; Then reverts to STATE_NORMAL

BusyInit	WAIT BusyDone
			rts

BusyDone STATE NORMAL


;------------------------------------------------------------------------------ ; NORMAL ; The basic default standing, doing nothing.


NormalInit ANIMATION ANIMATION_STAND HANDLER EVENT_JOY_NULL rts

NormalWait
          ;WAIT NormalInit
           rts


NormalInitRight


           ANIMATION ANIMATION_STAND ;RIGHT
           HANDLER EVENT_JOY_NULL
           rts



; STATE Processing END
;------------------------------------------------------------------------------

#endif
           NEWBANK BANK_TABLESX

CharAddressLO ;[abs char location]

   ; Gives the absolute screen buffer address of the first line of the given character
   ; Where character number is 0-99 (in, for example, a 10x10 grid)
   ; Currently hardwired to 10x10 format.  ACROSS first then DOWN

.LINE SET 0
REPEAT 10
.byte < ( ScreenBitmap + ( 0 * SCREEN_DEPTH ) + ( .LINE * LINES_PER_CHAR ) ) ; 0
.byte < ( ScreenBitmap + ( 1 * SCREEN_DEPTH ) + ( .LINE * LINES_PER_CHAR ) ) ; 1
.byte < ( ScreenBitmap + ( 1 * SCREEN_DEPTH ) + ( .LINE * LINES_PER_CHAR ) ) ; 2
.byte < ( ScreenBitmap + ( 2 * SCREEN_DEPTH ) + ( .LINE * LINES_PER_CHAR ) ) ; 3
.byte < ( ScreenBitmap + ( 2 * SCREEN_DEPTH ) + ( .LINE * LINES_PER_CHAR ) ) ; 4
.byte < ( ScreenBitmap + ( 0 * SCREEN_DEPTH ) + ( .LINE * LINES_PER_CHAR ) ) ; 5
.byte < ( ScreenBitmap + ( 3 * SCREEN_DEPTH ) + ( .LINE * LINES_PER_CHAR ) ) ; 6
.byte < ( ScreenBitmap + ( 3 * SCREEN_DEPTH ) + ( .LINE * LINES_PER_CHAR ) ) ; 7
.byte < ( ScreenBitmap + ( 4 * SCREEN_DEPTH ) + ( .LINE * LINES_PER_CHAR ) ) ; 8
.byte < ( ScreenBitmap + ( 4 * SCREEN_DEPTH ) + ( .LINE * LINES_PER_CHAR ) ) ; 9


.LINE SET .LINE + 1 REPEND
CharAddressHI ;[abs char location]


   ; Gives the absolute screen buffer address of the first line of the given character
   ; Where character number is 0-99 (in, for example, a 10x10 grid)
   ; Currently hardwired to 10x10 format.  ACROSS first then DOWN

.LINE SET 0
REPEAT 10
.byte > ( ScreenBitmap + ( 0 * SCREEN_DEPTH ) + ( .LINE * LINES_PER_CHAR ) ) ; 0
.byte > ( ScreenBitmap + ( 1 * SCREEN_DEPTH ) + ( .LINE * LINES_PER_CHAR ) ) ; 1
.byte > ( ScreenBitmap + ( 1 * SCREEN_DEPTH ) + ( .LINE * LINES_PER_CHAR ) ) ; 2
.byte > ( ScreenBitmap + ( 2 * SCREEN_DEPTH ) + ( .LINE * LINES_PER_CHAR ) ) ; 3
.byte > ( ScreenBitmap + ( 2 * SCREEN_DEPTH ) + ( .LINE * LINES_PER_CHAR ) ) ; 4
.byte > ( ScreenBitmap + ( 0 * SCREEN_DEPTH ) + ( .LINE * LINES_PER_CHAR ) ) ; 5
.byte > ( ScreenBitmap + ( 3 * SCREEN_DEPTH ) + ( .LINE * LINES_PER_CHAR ) ) ; 6
.byte > ( ScreenBitmap + ( 3 * SCREEN_DEPTH ) + ( .LINE * LINES_PER_CHAR ) ) ; 7
.byte > ( ScreenBitmap + ( 4 * SCREEN_DEPTH ) + ( .LINE * LINES_PER_CHAR ) ) ; 8
.byte > ( ScreenBitmap + ( 4 * SCREEN_DEPTH ) + ( .LINE * LINES_PER_CHAR ) ) ; 9


.LINE SET .LINE + 1 REPEND

CharMask ; [abs char location]

; Gives the mask for any char of the screen
; Note, this is hardwired to the screen format of 6 bytes/line
REPEAT 10
.byte $F ; 0
.byte $0F ; 1
.byte $F0 ; 2
.byte $F0 ; 3
.byte $F ; 4
.byte $F0 ; 5
.byte $F ; 6
.byte $F0 ; 7
.byte $F0 ; 8
.byte $F ; 9
REPEND
;------------------------------------------------------------------------------


BoardBank

; Gives the RAM bank of the start of the board row for a given row.

.BOARD_LOCATION SET Board
           REPEAT SIZE_BOARD_Y
               .byte .BOARD_LOCATION / 1024            ; actual bank #
.BOARD_LOCATION SET .BOARD_LOCATION + SIZE_BOARD_X      ; note, we CANNOT cross a page boundary within a row
           REPEND

;------------------------------------------------------------------------------

BoardLineStartLO

; Gives the start address (LO) of each board line
.BOARD_LOCATION SET Board
REPEAT SIZE_BOARD_Y
.byte <.BOARD_LOCATION
.BOARD_LOCATION SET .BOARD_LOCATION + SIZE_BOARD_X
REPEND
;------------------------------------------------------------------------------


BoardLineStartHI

; Gives the start address (HI) of each board line
; Note this caters for the memory wrapping when we go from bank to bank, as
; the board overlays multiple banks!
.BOARD_LOCATION SET Board
REPEAT SIZE_BOARD_Y
.byte >( .BOARD_LOCATION & $13FF ) ; cater for mirroring of memory images
.BOARD_LOCATION SET .BOARD_LOCATION + SIZE_BOARD_X
REPEND
;------------------------------------------------------------------------------


DrawLineStartLO

; Gives the start address of each line in the draw flags buffer
.DRAW_LOCATION SET DrawFlag
REPEAT SCREEN_LINES
.byte <.DRAW_LOCATION
.DRAW_LOCATION SET .DRAW_LOCATION + SCREEN_WIDTH
REPEND
;------------------------------------------------------------------------------


TS_PhaseVectorLO

; Gives LO byte of addresses of subroutines for timeslice processing
;TODO: scrolling code comes first
; drop the builddrawflags (it's now done by object processing)
.byte <BuildDrawFlagsPart1
.byte <BuildDrawFlagsPart2
.byte <BuildDrawStackPart1
.byte <DrawNewCharacters
.byte <SwitchDoubleBuffer
TS_PhaseVectorHI


; Gives HI byte of addresses of subroutines for timeslice processing
.byte >BuildDrawFlagsPart1
.byte >BuildDrawFlagsPart2
.byte >BuildDrawStackPart1
.byte >DrawNewCharacters
.byte >SwitchDoubleBuffer
TS_PhaseBank


; Gives bank of subroutines for timeslice processing
.byte BANK_BuildDrawFlagsPart1
.byte BANK_BuildDrawFlagsPart2
.byte BANK_BuildDrawStackPart1
.byte BANK_DrawNewCharacters
.byte BANK_SwitchDoubleBuffer
;------------------------------------------------------------------------------





NEWBANK BANK_GENERAL_SUBROUTINES




;************************************** FIXED BANK **************************************

ORIGIN          SET FIXED_BANK
               NEWBANK THE_FIXED_BANK
               RORG $f800

DEFINE_SUBROUTINE Random
; Generate a pseudo-random number
; semi-independant numbers


       lda rnd
       eor timer
       lsr
       lsr
       sbc rnd
       lsr
       ror rnd+1
       ror rnd
       ror rnd

       lda rnd
nogo        rts
   ;------------------------------------------------------------------------------

DEFINE_SUBROUTINE SwitchDoubleBuffer

; Flip buffers -- we've completed our draw process!
lda field
;beq WaitForField0 ; so interlacing effect doesn't glitch






; control the scrolling via the joystick
lda ManX
sta OldX
lda ManY
sta OldY
ldy ManY
lda #BANK_TABLESX
sta SET_BANK
clc
lda BoardLineStartLO,y
adc ManX
sta SDB_Address
lda BoardLineStartHI,y
adc #>RAM_WRITE
sta SDB_Address+1
lda BoardBank,y
sta SET_BANK_RAM
lda #0
ldy #0
sta (SDB_Address),y


lda BufferedJoystick ; joystick
asl
bcc right asl
bcc left
asl
bcc down
asl
bcc up
phase0


ldy ManY
lda #BANK_TABLESX
sta SET_BANK
clc
lda BoardLineStartLO,y
adc ManX
sta SDB_Address
lda BoardLineStartHI,y
sta SDB_Address+1
lda BoardBank,y
sta SET_BANK_RAM
ldy #0
lda (SDB_Address),y
cmp #2
beq FailMove
lda #3
bne DoMove
FailMove lda OldX
sta ManX
lda OldY
sta ManY
jmp phase0 DoMove pha
clc
lda SDB_Address+1
adc #>RAM_WRITE
sta SDB_Address+1
pla
sta (SDB_Address),y



jsr TrackPlayer
lda #0
sta ScreenDrawPhase ; restart the whole process lda #$FF
sta BufferedJoystick
WaitForField0 rts


up lda ManY
beq GoPhase0
dec ManY
GoPhase0 jmp phase0



down lda ManY cmp #SIZE_BOARD_Y-1 bcs phase0 inc ManY jmp phase0

right lda ManX
cmp #SIZE_BOARD_X-1
bcs GoPhase0
inc ManX
jmp GoPhase0


left        lda ManX
           beq phase0
           dec ManX
           jmp phase0



past2

#ifconst DOUBLE_BUFFERED
               lda BASE_Bank
               eor #SWAP_SCREEN
               sta BASE_Bank
               lda BASE_Flag_Bank
               eor #SWAP_FLAG
               sta BASE_Flag_Bank
#endif







TrackPlayer


sec
lda ManX
sbc BoardScrollX
; bcc ManLeft
cmp #9
bcc XOK
clc
lda BoardScrollX
adc #5
cmp #SIZE_BOARD_X-10
bcc bbs
lda #SIZE_BOARD_X-10 bbs sta BoardScrollX


jmp CheckManY
XOK cmp #1
bcs CheckManY
sec
lda BoardScrollX
sbc #5
bcs inB
lda #0
inB sta BoardScrollX



CheckManY
sec
lda ManY
sbc BoardScrollY
cmp #9
bcc YOK
clc
lda BoardScrollY
adc #5
cmp #SIZE_BOARD_Y - 10
bcc sss2
lda #SIZE_BOARD_Y-10
sss2 sta BoardScrollY
jmp CheckRet YOK
cmp #1
bcs CheckRet
sec
lda BoardScrollY
sbc #5
bcs inB2
lda #0
inB2 sta BoardScrollY



CheckRet


rts


;------------------------------------------------------------------------------

DEFINE_SUBROUTINE TimeSlice ; MUST BE IN FIXED-BANK
TimeSlice


; Uses the phase variable to vector to the correct processing code for the given timeslice
; Code may be in any bank. Avoid the fixed bank at all costs! Once a section is complete
; it should increment ScreenDrawPhase.
; Switched-in bank(s) are undefined after this function is called!


;        lda #RED
;        sta COLUBK

               lda #BANK_TABLESX
               sta SET_BANK

ldx ScreenDrawPhase ; current phase of drawing
lda TS_PhaseVectorLO,x
sta TS_Vector
lda TS_PhaseVectorHI,x
sta TS_Vector+1
lda TS_PhaseBank,x
sta SET_BANK ; switch bank
jmp (TS_Vector) ; vector to the correct processing code




;------------------------------------------------------------------------------

DEFINE_SUBROUTINE BuildDrawFlagsPart1 ; MUST BE IN FIXED BANK

; Check the screen for all those characters that need to be redrawn
; Just copies the mxn grid from the board to a DrawFlags array. If the entry in
; the drawflags array is different to the ScreenBuffer array entry, then the
; screenbuffer will need redrawing.


inc ScreenDrawPhase ; so we're next in phase 2
lda #SCREEN_LINES-1
sta BDF_Line


DEFINE_SUBROUTINE BuildDrawFlagsPart2 ; MUST BE IN FIXED_BANK
BeginRowCopy lda BDF_Line
sec
sbc #7 ; lines per iteration
bcs inBound
lda #$FF
inBound sta BDF_LastLine


lda #>( DrawFlag + RAM_WRITE )
sta BDF_DrawFlagAddress+1
; 10 * (
CheckRowStart ldx BDF_Line
bmi EndDrawDS
cpx BDF_LastLine
beq EndThisBatch
lda #BANK_TABLESX ; 2
sta SET_BANK ; access address/data tables ; 3
lda DrawLineStartLO,x ; 4
sta BDF_DrawFlagAddress ; 3
clc


txa ; 2
adc BoardScrollY ; the Y offset of screen into board ; 3
tay ; 2
lda BoardLineStartLO,y ; 4
adc BoardScrollX ; the X offset of screen into board ; 3
sta BDF_BoardAddress ; 3
lda BoardLineStartHI,y ; a board line *WILL NOT CROSS* page boundary ; 4
sta BDF_BoardAddress+1 ; 3


lda BoardBank,y
sta BDF_BoardBank
ldx BASE_Flag_Bank
ldy #SCREEN_WIDTH - 1
CopyRow lda BDF_BoardBank
sta SET_BANK_RAM ; 3
lda (BDF_BoardAddress),y
stx SET_BANK_RAM
sta (BDF_DrawFlagAddress),y
dey
bpl CopyRow
dec BDF_Line
jmp CheckRowStart
EndDrawDS inc ScreenDrawPhase
EndThisBatch rts
;------------------------------------------------------------------------------


DEFINE_SUBROUTINE BuildDrawStackPart1 ; MUST BE IN FIXED BANK
; Parse the DrawFlags buffer and create a draw stack
; so that the actual draw doesn't need to scan for characters to draw.
ldy #$FF
ldx #SCREEN_ARRAY_SIZE-1
lda BASE_Flag_Bank
sta SET_BANK_RAM
R0 lda DrawFlag,x
cmp ScreenBuffer,x
beq R1
iny
txa
sta DrawStack+RAM_WRITE,y
R1 dex
bpl R0


sty DrawStackPointer
Switch2 inc ScreenDrawPhase
rts



;------------------------------------------------------------------------------


DEFINE_SUBROUTINE DrawNewCharacters ; MUST BE IN FIXED BANK
; CURRENTLY only draws 1 character/frame.
; *SHOULD* be able to get away with 2/frame
lda #1
sta DNC_CharCount ; Maximum number of chars to draw/iteration




DoAnother ldy DrawStackPointer ; MUST have been set by BuildDrawStack!
bmi Switch2
lda BASE_Flag_Bank
sta SET_BANK_RAM


dec DrawStackPointer ; one less to draw

ldx DrawStack,y ; in actuality a character index
lda DrawFlag,x ; new character to draw
sta ScreenBuffer+RAM_WRITE,x
asl
tay
lda #BANK_TABLESX
sta SET_BANK
clc
lda cvec,y
sta Character
adc #LINES_PER_CHAR
sta Character2
lda cvec+1,y
sta Character+1 ; pointer to the actual character definition
adc #0
sta Character2+1
lda CharAddressLO,x
sta ScreenAddress
sta ScreenAddressWRITE
lda CharAddressHI,x
sta ScreenAddress+1 ; read address for the screen bitmap
clc
adc #>RAM_WRITE
sta ScreenAddressWRITE+1 ; write address for the screen bitmap
lda CharMask,x
sta ScreenMask
eor #$FF
sta NegMask




ldy #LINES_PER_CHAR - 1
clc
lda ScreenAddress
adc #LINES_PER_CHAR - 1
bcs skipthis
tya
pha


ldx BASE_Bank
stx SET_BANK_RAM
TSFill lda (ScreenAddress),y
and ScreenMask
sta Temp
lda (Character),y
and NegMask
ora Temp
sta (ScreenAddressWRITE),y
dey
bpl TSFill


               inx
               stx SET_BANK_RAM

pla
tay
TSFill2 lda (ScreenAddress),y
and ScreenMask
sta Temp
lda (Character2),y
and NegMask
ora Temp
sta (ScreenAddressWRITE),y
dey
bpl TSFill2


past
skipthis complete dec DNC_CharCount
bne DoAnother


ldy DrawStackPointer ; MUST have been set by BuildDrawStack!
bmi ended
rts
ended


; AnotherComing

Switch inc ScreenDrawPhase ; when all characters drawn, we are done
jmp SwitchDoubleBuffer
AnotherComing rts



#if 0 clc lda ScreenAddress adc #LINES_PER_CHAR - 1 bcc complete

           tay
           iny

eor #$FF
adc #LINES_PER_CHAR
pha
clc
adc Character
sta Character
bcc nCX
inc Character+1
nCX pla
clc
adc Character2
sta Character2
bcc nCX2
inc Character2+1
nCX2


           lda #0
           sta ScreenAddress
           sta ScreenAddressWRITE
           inc ScreenAddress+1
           inc ScreenAddressWRITE+1

           jmp normal
#endif





cvec    .word CharacterBlank, CharacterSoil, CharacterRock, CharacterB
       .word CharacterDiamond, CharacterDiamond, CharacterWater, CharacterB


CharacterBlank


; Can probably find a better place where reading will always return 0's
REPEAT 36
.byte 0
REPEND
CharacterWater


.byte 0
.byte 0
.byte 240

.byte 0
.byte 0
.byte 240

.byte 0
.byte 0
.byte 240

.byte 0
.byte 128
.byte 176

.byte 0
.byte 0
.byte 224

.byte 0
.byte 0
.byte 240

.byte 240
.byte 0
.byte 64


.byte 240
.byte 0
.byte 0

.byte 240
.byte 0
.byte 64

.byte 240
.byte 0
.byte 32

.byte 240
.byte 0
.byte 64

.byte 240
.byte 0
.byte 0





CharacterWall ; average

.byte 0
.byte 0
.byte 96

.byte 0
.byte 96
.byte 224

.byte 0
.byte 224
.byte 240

.byte 00
.byte 224
.byte 224

.byte 0
.byte 96
.byte 96

.byte 0
.byte 32
.byte 32

.byte 64
.byte 0
.byte 96

.byte 96
.byte 96
.byte 96
.byte 224
.byte 0
.byte 240

.byte 240
.byte 224
.byte 224

.byte 96
.byte 0
.byte 96

.byte 96
.byte 32
.byte 32




CharacterDiamond


.byte 0
.byte 0
.byte 0
.byte 102
.byte 102
.byte 0
.byte 0
.byte 0
.byte 51
.byte 255
.byte 238
.byte 0
.byte 0
.byte 0
.byte 34
.byte 102
.byte 34
.byte 0


.byte 68 ;b .byte 68 .byte 102 .byte 102 .byte 102 .byte 238 .byte 238 .byte 238 .byte 255 .byte 255 .byte 238 .byte 238 .byte 102 .byte 102 .byte 102 .byte 102 .byte 34 .byte 34



CharacterSoil

   .byte %01000100
   .byte %00000000
   .byte %00000000

   .byte %10101010
   .byte %00000000
   .byte %00000000

   .byte %00110010
   .byte %00000000
   .byte %00000000

   .byte %10111011
   .byte %00000000
   .byte %00000000

   .byte %00100010
   .byte %00000000
   .byte %00000000

   .byte %01000101
   .byte %00000000
   .byte %00000000


.byte %00000000 .byte %00010001 .byte %00000000

   .byte %00000000
   .byte %01000100
   .byte %00000000

   .byte %00000000
   .byte %01000100
   .byte %00000000

   .byte %00000000
   .byte %01010101
   .byte %00000000

   .byte %00000000
   .byte %00011001
   .byte %00000000

   .byte %00000000
   .byte %00100010
   .byte %00000000




CharacterB


REPEAT 6
.byte 0<<4
.byte (15<<4) + 15
.byte 0<<4
REPEND
REPEAT 6
.byte 0<<4
.byte 0<<4
.byte (15<<4) + 15
REPEND
CharacterC


REPEAT 6
.byte 0<<4
.byte 0<<4
.byte (15<<4) + 15
REPEND
REPEAT 6
.byte (15<<4) + 15
.byte 0<<4
.byte 0<<4
REPEND


CharacterRock

   .byte %01100110
   .byte %01100110
   .byte %00000000
   .byte %11111111
   .byte %00010001
   .byte %00000000
   .byte %11111111
   .byte %00110011
   .byte %00000000
   .byte %11111111
   .byte %10011001
   .byte %00000000
   .byte %11111111
   .byte %00100010
   .byte %00000000
   .byte %01100110
   .byte %00000000
   .byte %00000000

.byte %00000000
.byte %01100110
.byte %00110011
.byte %00000000
.byte %11111111
.byte %00110011
.byte %00000000
.byte %11111111
.byte %00010001
.byte %00000000
.byte %11111111
.byte %00000000
.byte %00000000
.byte %11111111
.byte %00100010
.byte %00000000
.byte %01100110
.byte %00000000




;------------------------------------------------------------------------------

   ; The image file is composed of strips (corresponding to PF0-PF2, repeated)
   ; which are decomposed by a utility from colour-separated RGB components of
   ; an original image. The displayed image is 40 pixels x 192 pixels.

;------------------------------------------------------------------------------


BOULDERDASH_SCREENDRAW


           lda #RED
           sta Colour
           lda #GREEN
           sta Colour+1
           lda #BLUE
           sta Colour+2

lda #0
sta field
sta Phase
NewFrameBD



; Start of vertical blank processing
; Very VERY sensitive to extra cycles before the interlacing!



lda #%01000010 ;D6+D1
sta VBLANK





lda #43 sta TIM64T
lda #0
sta HMCLR
lda field
eor #1
sta field
jsr Interlace


inc timer

jsr TimeSlice

           lda BGColour
           sta COLUBK

           clc
           lda BASE_Bank
#ifconst DOUBLE_BUFFERED
           eor #SWAP_SCREEN
#endif
           adc field
           sta SET_BANK_RAM                    ; we DISPLAY the one we're NOT drawing to
           sta RAM_Bank


lda INTIM bne VblankLoopBD inc BGColour

VblankLoopBD  lda INTIM
           bne VblankLoopBD



sta WSYNC sta VBLANK

           lda SWCHA
           ;and BufferedJoystick
           sta BufferedJoystick

   ;------------------------------------------------------------------------------
   ; START OF DISPLAY


#if COLOUR = PAL lda #238 ; NTSC #else lda #236 #endif sta TIM64T

lda #%00010100 ; reflect, priority, 2 pixel wide ball
sta CTRLPF
lda #0
sta PF0
sta PF1
sta PF2


   ;--------------------------------------------------------------------------
   ; START OF COLOUR BITMAP DISPLAY KERNEL


lda #%00100101 sta NUSIZ0



           ldx Phase
           lda aPhase2,x
           sta Phase



           lda #0
           sta Count

NzapBD


ldy #0 ; total number of scanlines to display



; Vector to the correct start - a red, blue or green line


ldx Phase


beq ScanRedBD
dex
beq ScanGreenBD
bne ScanBlueBD
ScanGreenBD sta WSYNC


           lda Colour+1            ; 3
           sta COLUPF              ; 3


ldx ScreenBitmap,y ; 4 stx PF0 ; 3 ldx ScreenBitmap+1*SCREEN_DEPTH,y ; 4 stx PF1 ; 3 ldx ScreenBitmap+2*SCREEN_DEPTH,y ; 4 stx PF2 ; 3

           lda ScreenBitmap,y                  ; 4
           asl
           asl
           asl
           asl
           sta PF0                             ; 3
           lda ScreenBitmap+3*SCREEN_DEPTH,y   ; 4
           sta PF1                             ; 3
           lda ScreenBitmap+4*SCREEN_DEPTH,y   ; 4
           sta PF2                             ; 3

;SLEEP 14

iny ; 2
cpy #SCREEN_DEPTH
bne ScanBlueBD ; 2 (3) --> <76
jmp ScanEndBD



ScanRedBD sta WSYNC


           lda Colour              ; 3
           sta COLUPF              ; 3

; LEFT (HIGH NYBBLE) PF0 LEFT OF SCREEN, REVERSE BIT ORDER. D4-D5-D6-D7
ldx ScreenBitmap,y ; 4
stx PF0 ; 3
ldx ScreenBitmap+1*SCREEN_DEPTH,y ; 4
stx PF1 ; 3
ldx ScreenBitmap+2*SCREEN_DEPTH,y ; 4
stx PF2 ; 3


           lda ScreenBitmap,y                  ; 4
           asl
           asl
           asl
           asl
           sta PF0                             ; 3
           lda ScreenBitmap+3*SCREEN_DEPTH,y   ; 4
           sta PF1                             ; 3
           lda ScreenBitmap+4*SCREEN_DEPTH,y   ; 4
           sta PF2                             ; 3

;SLEEP 14

           iny                     ; 2
           cpy #SCREEN_DEPTH
           bne ScanGreenBD         ; 2(3)
           beq ScanEndBD           ; 2(3)             -->   <76

ScanBlueBD sta WSYNC

           lda Colour+2            ; 3
           sta COLUPF              ; 3


ldx ScreenBitmap,y ; 4 stx PF0 ; 3 ldx ScreenBitmap+1*SCREEN_DEPTH,y ; 4 stx PF1 ; 3 ldx ScreenBitmap+2*SCREEN_DEPTH,y ; 4 stx PF2 ; 3


lda ScreenBitmap,y ; 4 asl asl asl asl

           sta PF0                             ; 3
           lda ScreenBitmap+3*SCREEN_DEPTH,y   ; 4
           sta PF1                             ; 3
           lda ScreenBitmap+4*SCREEN_DEPTH,y   ; 4
           sta PF2                             ; 3

;SLEEP 14

           iny                     ; 2
           cpy #SCREEN_DEPTH
           bne ScanRedBD           ; 2(3)


ScanEndBD


   ; Screen has been drawn - now just tidy up
           lda #0
           sta PF0
           sta PF1
           sta PF2

PadScreen2BD lda INTIM
bne PadScreen2BD
sta WSYNC


           lda #%01000010
           sta VBLANK                      ; end of screen - enter blanking


#if COLOUR = PAL


           lda #60
           sta TIM64T
PALTiming   lda INTIM
           bne PALTiming

#endif

           lda #30
           sta TIM64T

OverscanBD    lda INTIM
           bne OverscanBD

sta WSYNC sta WSYNC sta WSYNC

jmp NewFrameBD


aPhase2 .byte 2,0,0





;************************************** FIXED BANK **************************************


DEFINE_SUBROUTINE ClearScreen

   ; Clears the entire screen bank area (1K x 4)
   ; Must reside in fixed bank
   ; 30 bytes


ldy #BANK_SCREEN_0A lda #0 ldx #0 ClearBank sty SET_BANK_RAM ClearBlock sta ScreenBitmap + RAM_WRITE,x sta ScreenBitmap + RAM_WRITE + $100,x sta ScreenBitmap + RAM_WRITE + $200,x sta ScreenBitmap + RAM_WRITE + $300,x dex bne ClearBlock iny cpy #BANK_SCREEN_1B + 1 bne ClearBank

ldy #1
clearP
tya
clc
adc #BANK_BUFFER_0
sta SET_BANK_RAM


ldx #0
lda #0
CSBuffer sta ScreenBuffer+RAM_WRITE,x
sta DrawFlag+RAM_WRITE,x
dex
bne CSBuffer
dey
bpl clearP



; Now clear the Board
lda #SIZE_BOARD_Y - 1
sta CS_Line
ClearLine ldy CS_Line
; inc BGColour
; lda BGColour
; sta COLUBK
lda #BANK_TABLESX ; 2
sta SET_BANK ; access address/data tables ; 3
clc
lda BoardLineStartLO,y
sta CS_BoardAddress
lda BoardLineStartHI,y
adc #>RAM_WRITE
sta CS_BoardAddress+1


lda BoardBank,y ; 4
sta SET_BANK_RAM ; 3
ldy #SIZE_BOARD_X-1
ClearBoard jsr Random
and #7
tax
lda ShapeX,x
sta (CS_BoardAddress),y
dey
bpl ClearBoard
dec CS_Line
bpl ClearLine




rts

ShapeX .byte 1,4,1,1,5,1,2,6

;************************************** FIXED BANK **************************************

BuildFrame

; set the bank to the correct frame BEFORE calling this

#if 0

;lda (* byte from board *)
;cmp (* byte from screen *)
;beq SameCharacter
;(* store to byte from screen *)
;(* build character from charset to screen buffer *)
;(* count penalty for doing this *) SameCharacter
;(* next board pointer *)
;if end, then flag as completed
#endif


rts
#if 0


lda #<2000
sta BudgetCycles
lda #>2000
sta BudgetCycles


ldx BuildMode
lda BuildVector,x
sta Vector
lda BuldVectorHI,x
sta Vector+1
jmp (Vector)
BuildVectorLO .byte <BuildStart
.byte <BuildEnd
BuildVectorHI .byte >BuildStart
.byte >BuildEnd



BuildStart inc BuildMode ; --> BuildBoardStart rts


BuildBoardStart


               lda #0
               sta BoardY
               sta BoardX              ; start at top left of board

               inc BuildMode           ; --> BuildBoard
               rts

BuildBoard

; Where we animate the board itself.  Each object in the board has its own behaviour and
; this may affect other objects.  We scan through the entire board incrementally until
; we reach the end.  Note that this process happens over several (many!) frames.

jsr CheckBoardPosition


inc BoardX
lda BoardX
cmp #SIZE_BOARD_X
bne NotDone
lda #0
sta BoardX
inc BoardY
lda BoardY
cmp #SIZE_BOARD_Y
beq FinishedBoard
;NotDone BUDGET 100, BuildBoard


FinishedBoard inc BuildMode - --> BuildEnd

NotDone rts


BuildEnd
rts


CheckBoardPosition

; We update whatever needs to happen at Board[BoardY][BoardX]
; Should also manage budget

               ldx BoardY
               ldy BoardX
               jsr GetBoardChar








rts


#endif



;************************************** FIXED BANK **************************************


Interlace


;Common subroutines
;------------------------------------------------------
;$Id: common.s,v 1.2.4.2 2002/08/16 04:14:11 Billy Exp $
;------------------------------------------------------
;start the vertical sync and set the timer for 37 lines of blank
;the status registers need to be set to alternate between frames, zero and non-zero
;something like lda with the framenum
vertical_sync_interlaced		subroutine
	beq	even_sync	




;this is the vertical sync for the first field of an interlaced frame ;or just a normal non-interlaced vertical sync lda #2 sta WSYNC sta VSYNC ; Begin vertical sync.

	sta WSYNC ; First line of VSYNC
	sta WSYNC ; Second line of VSYNC.
	lda	#0
	sta WSYNC ; Third line of VSYNC.
	sta VSYNC ; (0)


jmp done_sync
even_sync
;this is the vertical sync for the second field of an interlaced fram
sta WSYNC
;need 40 cycles until the start of vertical sync

;this style of loop delays 5*Y+1
ldy #7
even_sync_loop1
dey bne even_sync_loop1
;36 cycles
nop ;38


	lda #2		;40
		
	sta VSYNC ; Begin vertical sync.
	sta WSYNC ; First line of VSYNC
	sta WSYNC ; Second line of VSYNC.

	sta WSYNC ; Third line of VSYNC.
	;need 33 cycles until the end of VSYNC

;this style of loop delays 5*Y+1
ldy #6
even_sync_loop2
dey bne even_sync_loop2
;31 cycles
lda #0 ;33
sta VSYNC


done_sync

	lda	#BLACK
	sta	COLUBK              ;; but not duplicated below?!!

rts
;************************************** FIXED BANK **************************************


#if SPRITES

VBProcessing

ldx Player


jsr ProcessFSM ; process creature FSM logic


           lda ObjXPosition,x
           sta DrawX
           lda #1
           sta DrawX+1
           lda ObjYPosition,x
           sta DrawY

SETBANK INITBANK

CALL AnimateObject

;            jsr AnimateObject               ; process object animation sequence
           jsr CalculateDrawPosition       ; setup position(s) for next VB draw


ldy Player


           lda ObjFacing,y
           and #D7
           lsr
           lsr
           lsr
           lsr
           sta REFP0
           sta REFP1                   ;@17

           lda BGColour
           sta COLUBK

_RTS14      nop
           rts                         ; 14-cycle waste

;------------------------------------------------------------------------

NewFrame

; Start of vertical blank processing


lda #43 sta TIM64T


           lda #$00
           sta HMCLR

           lda SWCHB
           lda #D7
           sta switch


jsr VBProcessing ; spend 2000+ cycles


#if DEBUG
           lda INTIM
           bne Whoops
           inc BGColour            ; Overflow
Whoops
#endif



VblankLoop lda INTIM
bne VblankLoop


; End of vertical blank processing
sta WSYNC sta VBLANK


   ;------------------------------------------------------------------------------
   ; START OF DISPLAY

#if COLOUR = NTSC
           lda #221                ; NTSC
#else
           lda #238
#endif
           sta TIM64T


;? lda #%00010100 ; reflect, priority, 2 pixel wide ball sta CTRLPF ;^?

lda #PFCOL
sta COLUPF
lda #0
sta PF0
sta PF1
sta PF2



sta GRP0 sta GRP1

           lda BGPlayer
           sta COLUP0
           sta COLUP1                  ; tentative colour




;-------------------------------------------------------------------------- ; Init the loop counters (16 rows each) for each of the rows

           lda #127
           sta LoopCount

ldy Player
lda ObjFrame,y
bmi SkipDraw
ldx ObjPhase,y
lda NextPhase,x
sta ObjPhase,y
asl
tax
lda PhasePtr,x
sta RGBVec
lda PhasePtr+1,x
sta RGBVec+1


           lda ObjFrameBank,y
           sta SET_BANK

lda #30
sta VisualY
lda #40
sta VisualX
jsr PositionObject
jsr DrawSprite


sta WSYNC
SkipDraw lda #0
sta GRP0
sta GRP1
sta GRP0 ; buffered??
sta GRP1 ; buffered??


           sta VDELP0
           sta VDELP1

           sta REFP0
           sta REFP1

sta WSYNC

PadScreen2 lda INTIM
bne PadScreen2
sta HMCLR
sta WSYNC



#if COLOUR = PAL sta WSYNC lda #42 sta TIM64T PALx lda INTIM bne PALx #endif


CleanFrameHook


sta WSYNC
lda #D6+D1
sta VBLANK ; end of screen - enter blanking


lda #43 sta TIM64T

;*******************************************************************************
;****************** START OF OVERSCAN PROCESSING TIME **************************
;*******************************************************************************

   lda field
#if INTERLACED
   eor #1
   sta field
#endif
   jsr Interlace


;--------------------------------------------------------------------------
; Switch to alternate player(s)
dec Player
bpl PlayerN
lda #BIG_SPRITES-1
sta Player
PlayerN



;-------------------------------------------------------------------------- ; PLAYER INTERACTION


; lda #0 ; sta SWACNT ; all input bits (IMPLICITLY SET @ STARTUP)

; lda SWCHA ; joystick

;            ldx Player
;            bne P1shift

;            lsr
;            lsr
;            lsr
;            lsr

;P1shift and #$f

;            ldy ObjFacing,x
;            bpl FacOK

;            tay
;            and #D3+D2
;            cmp #D3+D2
;            beq FacOK2

;            tya
;            eor #D3+D2                      ; swap left/right if mirrored
;FacOK       tay
;FacOK2

SETBANK INITBANK

;            lda JoystickEvent,y
;           bmi NullJoy                     ; an unhandled joystick direction

;            asl
;            tay

;            ldy #EVENT_JOY_NULL*2
;            jsr SetHandler                  ; handle joystick event

;NullJoy
;                lda     SWCHB
;                and     #$01
;                bne     NoResetSwitch





;*******************************************************************************
;****************** END OF VERTICAL BLANK PROCESSING TIME **********************
;*******************************************************************************


Overscan lda INTIM bne Overscan

sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC sta VBLANK


jmp NewFrame





;--------------------------------------------------------------------------

CalculateDrawPosition

   ; Given the current frame of the player, calculate a draw position such that
   ; the centerpoint is at the creature's (ObjXPosition,ObjYPosition) and that the
   ; left and right edges are then forced to be onscreen.


; Calculate the frame definition start address. Each frame is a 32-byte ; definition block giving the bank containing the frame and a matrix of ; 16-sprite numbers making up the nx6 grid.

   ; FORMAT:
   ;    BYTE       centerpointx, centerpointy
   ;    BYTES...    0, 1, 2, 3, 4, 5   \
   ;                6, 7, 8, 9,10,11    |  n x 6 matrix of 16-sprite #s
   ;                ....                |
   ;               24,25,26,27,28,29   /

SETBANK INITBANK

ldy Player
lda #0
sta FrameAddress+1


           lda ObjFrame,y              ; animation frame (absolute)
           asl
           adc ObjFrame,y              ; Frametable is bank, AddressLO, AddressHI
           tax

           lda FrameTable+1,x
           sta FrameAddress
           lda FrameTable+2,x
           sta FrameAddress+1

           lda FrameTable,x
           ;sta FrameBank
           sta ObjFrameBank,y
           sta SET_BANK

           ldx #0
           lda ObjFacing,y
           bpl nMirror
           ldx #BIG_ROWS*BIG_COLS
nMirror


; Now we have a pointer to the frame definition block (FrameAddress) ; Go through the entire BIG_ROWS*BIG_COLS entries and convert the matrix 16-sprite ; number into an absolute address pointing to the sprite data. This will correspond ; nicely to the vars used for the actual draw.

           ldy #0
           sty CenterX+1
           lda (FrameAddress),y
           lda #17 ;0 ;tmp
           sta CenterX
           iny
           lda (FrameAddress),y
           lda #0 ;tmp
           sta CenterY

stx Temp+1

Mirrorable iny

           inc Temp+1
           ldx Temp+1
           lda BaseMirror-1,x
           tax


tya pha

           lda (FrameAddress),y
           asl
           tay
           lda T128,y
           sta SPBASE,x
           lda T128+1,y
           sta SPBASE+1,x

           pla
           tay


cpy #BIG_ROWS*BIG_COLS+1 bcc Mirrorable


;-------------------------------------------------------------------------- ; Centerpoint Adjustment based on frame

ldy Player

           lda ObjFrame,y
           bmi SkipRepos

           lda ObjFacing,y
           bpl nM

           clc
           lda #0
           sbc CenterX
           sta CenterX
           lda #0
           sbc CenterX+1
           sta CenterX+1

           clc
           lda CenterX
           adc #48
           sta CenterX
           lda CenterX+1
           adc #0
           sta CenterX+1

nM

; Adjust draw position so that centerpoint is where the ObjXPosition is

           sec
           lda DrawX
           sbc CenterX
           sta VisualX
           lda DrawX+1
           sbc CenterX+1
           sta VisualX+1

bne OKleft


; OK, so the object is offscreen (to the left) ; This means that, with the centerpoint adjustment, the left edge of the sprite is offscreen ; So we need to adjust the object position (DrawX,DrawY) such that the sprite will be onscreen ; As a minimum, we know we want the sprite to be at (0,DrawY). So we just adjust the ; object position by the negative of the offsreen offset

           sec
           lda #0
           sbc VisualX                     ; all we really care about - the offset
           sta Temp
           adc DrawX                       ; adjust (what will be) the actual coordinate
           sta DrawX

; and set the visual draw position to left edge

;            lda #1
;            sta VisualX+1
           lda #0
           sta VisualX
           beq Onscreen

OKleft

; Check for right-hand side boundary conditions


sec lda VisualX sbc #160-48 sta Temp lda VisualX+1 sbc #1 bcc Onscreen

           lda Temp
           eor #$FF
           adc #0
           sta Temp

           adc DrawX
           sta DrawX


lda #160-48 sta VisualX ; lda #1 ; sta VisualX+1

Onscreen

           sec
           lda DrawY
           sbc CenterY
           sta VisualY
SkipRepos

;--------------------------------------------------------------------------

           ldx Player
           lda DrawX
           sta ObjXPosition,x
           lda DrawY
           sta ObjYPosition,x


rts



T128 .T128 SET $F000

   REPEAT 22
       .word .T128
.T128        SET .T128 + 128
   REPEND

   ;--------------------------------------------------------------------------
#endif


Reset


jsr ClearScreen

           SETBANK INITBANK
           jmp Cart_Init                   ; init code is in bank 1!




;------------------------------------------------------------------------------


#if 0
VectorToBankedSubroutine

           lda ROM_Bank
           pha

           lda SubroutineBank,y
           sta ROM_Bank
           sta SET_BANK

           lda SubroutineAddrLO,y
           sta temp
           lda SubroutineAddrHI,y
           sta temp+1

jsr ReVector

           pla
           sta ROM_Bank
           sta SET_BANK

rts

ReVector jmp (temp)


SubroutineBANK #endif




;------------------------------------------------------------------------------



;JoystickEvent


; .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,EVENT_JOY_RIGHT,$FF,$FF,$FF,EVENT_JOY_LEFT,$FF,EVENT_JOY_DOWN,EVENT_JOY_UP,EVENT_JOY_NULL


#if 0


   ;--------------------------------------------------------------------------
   ; Object X,Y positioning
   ; Timing is absolutely critical here!

PositionObject

; Waste scanlines to start of object position, giving our vertical movement

           ldx VisualY
           inx
DelayVert   sta WSYNC
           dex
           bne DelayVert

; Now the horizontal magic (which isn't working (1/MAR))

           ldx VisualX
           clc
           lda MoveTable,x
           sta HMP0
           adc #$10
           sta HMP1

           lda #1
           sta VDELP0
           sta VDELP1

           lda #3
           sta NUSIZ0
           sta NUSIZ1

sta WSYNC

           lda #>JNDelayPos
           sta Temp+1
           lda DelayTable,x
           sta Temp
           jmp (Temp)

ALIGN 256

JNDelayPos .byte $c9,$c9,$c9,$c9,$c9,$c9,$c9,$c9,$c9
.byte $c9,$c9,$c9,$c9,$c9,$c9,$c9,$c9,$c9
.byte $c9,$c9,$c9,$c9,$c9,$c9,$c9,$c9,$c9
.byte $c9,$c9,$c9,$c9,$c9,$c9,$c9,$c9,$c9,$c5


blast nop

           sta RESP0
           sta RESP1
           sta WSYNC
           sta HMOVE

           lda #>JNDelayDraw
           sta Temp+1
           lda #<JNDelayDraw
           clc
           adc DelayTable,x
           sta Temp

           ;lda #0
           ;sta PF2

sta WSYNC

SLEEP 20

jmp (Temp)


JNDelayDraw


           .byte   $c9,$c9,$c9,$c9,$c9,$c9,$c9,$c9,$c9
           .byte   $c9,$c9,$c9,$c9,$c9,$c9,$c9,$c9,$c9
           .byte   $c9,$c9,$c9,$c9,$c9,$c9,$c9,$c9,$c9
           .byte   $c9,$c9,$c9,$c9,$c9,$c9,$c9,$c9,$c9,$c9,$c5

rts


ALIGN 256 DelayTable .byte 37, 37 Q SET 36 REPEAT 37 .byte Q, Q, Q Q SET Q-1 REPEND

MoveTable
          .byte   $30, $20
           REPEAT  37
               .byte   $40, $30, $20
           REPEND


;-------------------------------------------------------------------------- ; The beautiful, beautiful, draw loop which draws the entire matrix onscreen ; This caters for an adjustable (at compile-time) number of rows and also ; facilitates double-size pixels.

SUBROUTINE

.S1         SET SPBASE
.S2         SET SPBASE + 2
.S3         SET SPBASE + 4
.S4         SET SPBASE + 6
.S5         SET SPBASE + 8
.S6         SET SPBASE + 10

DrawSprite



jmp (RGBVec)

NextPhase   .byte 2,0,0 ;1,2,0 ;1,2,0                     ; FIXED BANK ALWAYS
PhasePtr    .word .LABR,.LABG,.LABB
           .word .LABPALR,.LABPALG,.LABPALB

ALIGN 256

.LABG       lda #GREEN          ; 2
           sta COLUP0          ; 3
           sta COLUP1          ; 3

ldy LoopCount ; 3

           lda (.S1),y         ; 5
           sta GRP0            ; 3
           lda (.S2),y         ; 5
           sta GRP1            ; 3
           lda (.S3),y         ; 5
           sta GRP0            ; 3

lda (.S6),y ; 5
sta Temp ; 3
lax (.S5),y ; 5
lda (.S4),y ; 5
ldy Temp ; 3
sta GRP1 ; 3
stx GRP0 ; 3
sty GRP1 ; 3
sta GRP0 ; 3
dec LoopCount ; 5
bpl .LABB ; 3
bmi EndDraw


.LABR       lda #RED            ; 2
           sta COLUP0          ; 3
           sta COLUP1          ; 3

ldy LoopCount ; 3

           lda (.S1),y         ; 5
           sta GRP0            ; 3
           lda (.S2),y         ; 5
           sta GRP1            ; 3
           lda (.S3),y         ; 5
           sta GRP0            ; 3

lda (.S6),y ; 5
sta Temp ; 3
lax (.S5),y ; 5
lda (.S4),y ; 5
ldy Temp ; 3
sta GRP1 ; 3
stx GRP0 ; 3
sty GRP1 ; 3
sta GRP0 ; 3
dec LoopCount ; 5
bpl .LABG ; 3


bmi EndDraw

.LABB       lda #BLUE           ; 2
           sta COLUP0          ; 3
           sta COLUP1          ; 3

ldy LoopCount ; 3

           lda (.S1),y         ; 5
           sta GRP0            ; 3
           lda (.S2),y         ; 5
           sta GRP1            ; 3
           lda (.S3),y         ; 5
           sta GRP0            ; 3

lda (.S6),y ; 5
sta Temp ; 3
lax (.S5),y ; 5
lda (.S4),y ; 5
ldy Temp ; 3
sta GRP1 ; 3
stx GRP0 ; 3
sty GRP1 ; 3
sta GRP0 ; 3
dec LoopCount ; 5
bpl .LABR ; 3


EndDraw rts


ALIGN 256


;PALRED         = $64
;PALGREEN       = $54
;PALBLUE        = $D4

PALRED         = PAL_RED ;$C8 ;$D6              ; secam 8
PALGREEN       = PAL_GREEN ;%00110100 ;$42        ; secam 4
PALBLUE        = PAL_BLUE ;%01110100             ; secam 2

.LABPALG    lda #PALGREEN       ; 2
           sta COLUP0          ; 3
           sta COLUP1          ; 3

ldy LoopCount ; 3

           lda (.S1),y         ; 5
           sta GRP0            ; 3
           lda (.S2),y         ; 5
           sta GRP1            ; 3
           lda (.S3),y         ; 5
           sta GRP0            ; 3

lda (.S6),y ; 5
sta Temp ; 3
lax (.S5),y ; 5
lda (.S4),y ; 5
ldy Temp ; 3
sta GRP1 ; 3
stx GRP0 ; 3
sty GRP1 ; 3
sta GRP0 ; 3
dec LoopCount ; 5
bpl .LABPALB ; 3
bmi EndPalDraw


.LABPALR    lda #PALRED         ; 2
           sta COLUP0          ; 3
           sta COLUP1          ; 3

ldy LoopCount ; 3

           lda (.S1),y         ; 5
           sta GRP0            ; 3
           lda (.S2),y         ; 5
           sta GRP1            ; 3
           lda (.S3),y         ; 5
           sta GRP0            ; 3

lda (.S6),y ; 5
sta Temp ; 3
lax (.S5),y ; 5
lda (.S4),y ; 5
ldy Temp ; 3
sta GRP1 ; 3
stx GRP0 ; 3
sty GRP1 ; 3
sta GRP0 ; 3
dec LoopCount ; 5
bpl .LABPALG ; 3


bmi EndPalDraw

.LABPALB    lda #PALBLUE        ; 2
           sta COLUP0          ; 3
           sta COLUP1          ; 3

ldy LoopCount ; 3

           lda (.S1),y         ; 5
           sta GRP0            ; 3
           lda (.S2),y         ; 5
           sta GRP1            ; 3
           lda (.S3),y         ; 5
           sta GRP0            ; 3

lda (.S6),y ; 5
sta Temp ; 3
lax (.S5),y ; 5
lda (.S4),y ; 5
ldy Temp ; 3
sta GRP1 ; 3
stx GRP0 ; 3
sty GRP1 ; 3
sta GRP0 ; 3
dec LoopCount ; 5
bpl .LABPALR ; 3


EndPalDraw rts



BaseMirror

.SP         SET 0
           REPEAT BIG_ROWS*BIG_COLS
           .byte .SP
.SP         SET .SP + 2
           REPEND
.SPBASE     SET 0
           REPEAT BIG_ROWS
.SPOFF      SET 10
           REPEAT BIG_COLS
           .byte .SPBASE + .SPOFF
.SPOFF      SET .SPOFF-2
           REPEND
.SPBASE     SET .SPBASE + 12
           REPEND

#endif

#if 0

;===============================================================================
; Fixed bank portion of Interleaved ChronoColour Draw System


MAC CHRONOLINE ;{line}


;7+

           lda ChronoBank + {1}                ; 3
           sta SET_BANK                        ; 3     = 6

;sta WSYNC ; 3

           lda ChronoColour + {1}              ; 3
           sta COLUPF                          ; 3     = 6

           lda ( LineR0 +  0 + {1} * 14 ),y    ; 5
           sta PF0                             ; 3
           lda ( LineR0 +  2 + {1} * 14 ),y    ; 5
           sta PF1                             ; 3
           lda ( LineR0 +  4 + {1} * 14 ),y    ; 5
           sta PF2                             ; 3     = 24

           lda ( LineR0 +  6 + {1} * 14 ),y    ; 5
           sta PF0                             ; 3
           lda ( LineR0 +  8 + {1} * 14 ),y    ; 5
           sta PF1                             ; 3
           lda ( LineR0 + 10 + {1} * 14 ),y    ; 5
           sta PF2                             ; 3     = 24

;            lda (LineR0 + 12 + {1} * 14 ),y     ; 5
;            sta.w AUDV0                         ; 3     = 8

; lda.w 0

SLEEP 8
; SLEEP 9


ENDM

_rts        rts
sleep61     SLEEP (61-12)
           rts


ALIGN 256


ChronoDraw

           lda ROM_Bank
           pha                     ; save callee's bank

ldy #169 ; total number of scanlines to display

           sta WSYNC
;           jsr _rts
;           jsr _rts
;           jsr _rts
;           jsr _rts

           ldx Phase
           beq ScanRedStart        ; 2(3) --> 3 if taken
           dex                     ; 2
           beq ScanGreenStart      ; 2(3) --> 7 if taken
           bne ScanBlueStart       ; (3) --> 9

ScanRedStart
           ; @3

SLEEP 6

           ; now 9 cycles after WSYNC
           jsr sleep61

ScanRed     CHRONOLINE 0
           dey
           beq ScanEnd
           jmp ScanGreen

ScanGreenStart
           ; @7
           SLEEP 2
           jsr sleep61

ScanGreen   CHRONOLINE 1
           dey
           beq ScanEnd
           jmp ScanBlue

ScanBlueStart
               ; @9
           jsr sleep61


ScanBlue CHRONOLINE 2 dey beq ScanEnd jmp ScanRed


ScanEnd pla sta ROM_Bank sta SET_BANK ; restore previous bank for callee


rts #endif



ECHO "FREE BYTES IN IN FIXED BANK = ", $FFF9 - *


;========================================================================== ; The reset vectors ; these must live in the fixed bank (last 2K of any ROM image in TigerVision)

           SEG InterruptVectors
           ORG FIXED_BANK + $7FA
           RORG $7ffa

           VECTOR Reset           ; NMI        (not used)
           VECTOR Reset           ; RESET
           VECTOR Reset           ; IRQ        (not used)

;==========================================================================


; JUNK... ;------------------------------------------------------------------------------



END
Current Thread