colourgo/colourgo/game.s

1635 lines
33 KiB
ArmAsm

;
; main.s
; colourgo
;
; Created by Jeremy Rand on 2017-07-19.
; Copyright © 2017 Jeremy Rand. All rights reserved.
;
.export _game
.import _vblWait
.include "apple2.inc"
MAXY=191
MAXXBYTE=40
MAXX=280
SPEAKER=$C030
ZPADDR0=<$80
ZPADDR1=<$82
ZPADDR2=<$84
ZPADDR3=<$86
ZPADDR4=<$88
ZPADDR5=<$8a
ZPADDR6=<$8c
ZPADDR7=<$8e
LEVELADDR=<$90
COL_BLACK=0
COL_VIOLET=1
COL_GREEN=2
COL_WHITE=3
CHAR_HEIGHT=10
NUM_CHAR_BITMAPS=3
CHAR_MAX_JUMPS=2
CHAR_XPOS=3
CHAR_STATE_NONE=0
CHAR_STATE_JUMPING=1
CHAR_STATE_FALLING=2
JUMP_SPEED=5
GRAVITY=64
GRID_YPOS=140
GRID_HEIGHT=5
GRID_MAX_SHIFT=7
LEVEL_STRUCT_SIZE=5
LEVEL_STRUCT_START=0
LEVEL_STRUCT_WIDTH=1
LEVEL_STRUCT_TOP=2
LEVEL_STRUCT_BOTTOM=3
LEVEL_STRUCT_COLOUR=4
LINE0 = $2000
LINE1 = LINE0 + 1024
LINE2 = LINE1 + 1024
LINE3 = LINE2 + 1024
LINE4 = LINE3 + 1024
LINE5 = LINE4 + 1024
LINE6 = LINE5 + 1024
LINE7 = LINE6 + 1024
LINE8 = LINE0 + 128
LINE9 = LINE8 + 1024
LINE10 = LINE9 + 1024
LINE11 = LINE10 + 1024
LINE12 = LINE11 + 1024
LINE13 = LINE12 + 1024
LINE14 = LINE13 + 1024
LINE15 = LINE14 + 1024
LINE16 = LINE8 + 128
LINE17 = LINE16 + 1024
LINE18 = LINE17 + 1024
LINE19 = LINE18 + 1024
LINE20 = LINE19 + 1024
LINE21 = LINE20 + 1024
LINE22 = LINE21 + 1024
LINE23 = LINE22 + 1024
LINE24 = LINE16 + 128
LINE25 = LINE24 + 1024
LINE26 = LINE25 + 1024
LINE27 = LINE26 + 1024
LINE28 = LINE27 + 1024
LINE29 = LINE28 + 1024
LINE30 = LINE29 + 1024
LINE31 = LINE30 + 1024
LINE32 = LINE24 + 128
LINE33 = LINE32 + 1024
LINE34 = LINE33 + 1024
LINE35 = LINE34 + 1024
LINE36 = LINE35 + 1024
LINE37 = LINE36 + 1024
LINE38 = LINE37 + 1024
LINE39 = LINE38 + 1024
LINE40 = LINE32 + 128
LINE41 = LINE40 + 1024
LINE42 = LINE41 + 1024
LINE43 = LINE42 + 1024
LINE44 = LINE43 + 1024
LINE45 = LINE44 + 1024
LINE46 = LINE45 + 1024
LINE47 = LINE46 + 1024
LINE48 = LINE40 + 128
LINE49 = LINE48 + 1024
LINE50 = LINE49 + 1024
LINE51 = LINE50 + 1024
LINE52 = LINE51 + 1024
LINE53 = LINE52 + 1024
LINE54 = LINE53 + 1024
LINE55 = LINE54 + 1024
LINE56 = LINE48 + 128
LINE57 = LINE56 + 1024
LINE58 = LINE57 + 1024
LINE59 = LINE58 + 1024
LINE60 = LINE59 + 1024
LINE61 = LINE60 + 1024
LINE62 = LINE61 + 1024
LINE63 = LINE62 + 1024
LINE64 = LINE0 + 40
LINE65 = LINE64 + 1024
LINE66 = LINE65 + 1024
LINE67 = LINE66 + 1024
LINE68 = LINE67 + 1024
LINE69 = LINE68 + 1024
LINE70 = LINE69 + 1024
LINE71 = LINE70 + 1024
LINE72 = LINE64 + 128
LINE73 = LINE72 + 1024
LINE74 = LINE73 + 1024
LINE75 = LINE74 + 1024
LINE76 = LINE75 + 1024
LINE77 = LINE76 + 1024
LINE78 = LINE77 + 1024
LINE79 = LINE78 + 1024
LINE80 = LINE72 + 128
LINE81 = LINE80 + 1024
LINE82 = LINE81 + 1024
LINE83 = LINE82 + 1024
LINE84 = LINE83 + 1024
LINE85 = LINE84 + 1024
LINE86 = LINE85 + 1024
LINE87 = LINE86 + 1024
LINE88 = LINE80 + 128
LINE89 = LINE88 + 1024
LINE90 = LINE89 + 1024
LINE91 = LINE90 + 1024
LINE92 = LINE91 + 1024
LINE93 = LINE92 + 1024
LINE94 = LINE93 + 1024
LINE95 = LINE94 + 1024
LINE96 = LINE88 + 128
LINE97 = LINE96 + 1024
LINE98 = LINE97 + 1024
LINE99 = LINE98 + 1024
LINE100 = LINE99 + 1024
LINE101 = LINE100 + 1024
LINE102 = LINE101 + 1024
LINE103 = LINE102 + 1024
LINE104 = LINE96 + 128
LINE105 = LINE104 + 1024
LINE106 = LINE105 + 1024
LINE107 = LINE106 + 1024
LINE108 = LINE107 + 1024
LINE109 = LINE108 + 1024
LINE110 = LINE109 + 1024
LINE111 = LINE110 + 1024
LINE112 = LINE104 + 128
LINE113 = LINE112 + 1024
LINE114 = LINE113 + 1024
LINE115 = LINE114 + 1024
LINE116 = LINE115 + 1024
LINE117 = LINE116 + 1024
LINE118 = LINE117 + 1024
LINE119 = LINE118 + 1024
LINE120 = LINE112 + 128
LINE121 = LINE120 + 1024
LINE122 = LINE121 + 1024
LINE123 = LINE122 + 1024
LINE124 = LINE123 + 1024
LINE125 = LINE124 + 1024
LINE126 = LINE125 + 1024
LINE127 = LINE126 + 1024
LINE128 = LINE64 + 40
LINE129 = LINE128 + 1024
LINE130 = LINE129 + 1024
LINE131 = LINE130 + 1024
LINE132 = LINE131 + 1024
LINE133 = LINE132 + 1024
LINE134 = LINE133 + 1024
LINE135 = LINE134 + 1024
LINE136 = LINE128 + 128
LINE137 = LINE136 + 1024
LINE138 = LINE137 + 1024
LINE139 = LINE138 + 1024
LINE140 = LINE139 + 1024
LINE141 = LINE140 + 1024
LINE142 = LINE141 + 1024
LINE143 = LINE142 + 1024
LINE144 = LINE136 + 128
LINE145 = LINE144 + 1024
LINE146 = LINE145 + 1024
LINE147 = LINE146 + 1024
LINE148 = LINE147 + 1024
LINE149 = LINE148 + 1024
LINE150 = LINE149 + 1024
LINE151 = LINE150 + 1024
LINE152 = LINE144 + 128
LINE153 = LINE152 + 1024
LINE154 = LINE153 + 1024
LINE155 = LINE154 + 1024
LINE156 = LINE155 + 1024
LINE157 = LINE156 + 1024
LINE158 = LINE157 + 1024
LINE159 = LINE158 + 1024
LINE160 = LINE152 + 128
LINE161 = LINE160 + 1024
LINE162 = LINE161 + 1024
LINE163 = LINE162 + 1024
LINE164 = LINE163 + 1024
LINE165 = LINE164 + 1024
LINE166 = LINE165 + 1024
LINE167 = LINE166 + 1024
LINE168 = LINE160 + 128
LINE169 = LINE168 + 1024
LINE170 = LINE169 + 1024
LINE171 = LINE170 + 1024
LINE172 = LINE171 + 1024
LINE173 = LINE172 + 1024
LINE174 = LINE173 + 1024
LINE175 = LINE174 + 1024
LINE176 = LINE168 + 128
LINE177 = LINE176 + 1024
LINE178 = LINE177 + 1024
LINE179 = LINE178 + 1024
LINE180 = LINE179 + 1024
LINE181 = LINE180 + 1024
LINE182 = LINE181 + 1024
LINE183 = LINE182 + 1024
LINE184 = LINE176 + 128
LINE185 = LINE184 + 1024
LINE186 = LINE185 + 1024
LINE187 = LINE186 + 1024
LINE188 = LINE187 + 1024
LINE189 = LINE188 + 1024
LINE190 = LINE189 + 1024
LINE191 = LINE190 + 1024
.CODE
.proc _game
; Set up hires screen
jsr clearScreen
jsr resetGame
@nextframe:
jsr _vblWait
jsr drawCharacter
jsr drawGrids
;@debugLoop:
; ldx KBD
; bpl @debugLoop
; ldx KBDSTRB
jsr updateGrid
jsr updateCharacter
lda shouldQuit
beq @nextframe
lda TXTSET
rts
.endproc
.proc resetGame
lda #0
sta characterBitmap
sta characterY
sta characterOldY
sta characterNumJumps
sta characterYSpeed
sta characterYSpeedFrac
sta gridXShift
sta gridXPos
lda #COL_VIOLET
sta characterColour
lda #CHAR_HEIGHT
sta characterYBottom
sta characterOldYBottom
lda #CHAR_STATE_FALLING
sta characterState
@setLevelAddr:
ldx level
lda levelsLo,x
sta LEVELADDR
lda levelsHi,x
sta LEVELADDR+1
bne @notAtTheEnd
; If the high byte of the level address is 0, then there are no more levels
; For now, just loop back to level 0. TODO - Something better.
sta level
jmp @setLevelAddr
@notAtTheEnd:
rts
.endproc
.proc playSound
; A is the frequency
; X is the duration
sta freq
@loop:
sta SPEAKER
ldy freq
@innerloop:
dey
bne @innerloop
dex
bne @loop
rts
; Locals
freq: .BYTE $00
.endproc
.proc promptForReset
@loop:
lda KBD
bpl @loop
ldx KBDSTRB
cmp #$9b ; Compare to Escape
beq @quit
cmp #$d1 ; Compare to 'Q'
beq @quit
cmp #$f1 ; Compare to 'q'
beq @quit
jsr resetGame
jmp clearScreen
@quit:
lda #$01
sta shouldQuit
rts
.endproc
.proc gameOver
jsr drawCharacter
jsr drawGrids
lda #0
ldx #36
jsr playSound
lda #250
ldx #34
jsr playSound
lda #230
ldx #32
jsr playSound
lda #220
ldx #30
jsr playSound
lda #230
ldx #32
jsr playSound
lda #250
ldx #34
jsr playSound
lda #0
ldx #36
jsr playSound
jmp promptForReset
.endproc
.proc levelWon
lda #COL_WHITE
sta characterColour
jsr drawCharacter
lda #80
ldx #36
jsr playSound
lda #120
ldx #34
jsr playSound
lda #160
ldx #32
jsr playSound
lda #200
ldx #30
jsr playSound
lda #160
ldx #32
jsr playSound
lda #120
ldx #34
jsr playSound
lda #80
ldx #36
jsr playSound
inc level
jmp promptForReset
.endproc
.proc updateCharacter
; Save the old character position so it can be erased
jsr updateCharacterState
jsr updateCharacterPos
jsr updateCharacterBitmap
jsr updateCharacterColour
rts
.endproc
.proc updateCharacterState
lda BUTN1
bpl @buttonUp
lda #$01
jmp @buttonDown
@buttonUp:
lda #$00
@buttonDown:
cmp lastButtonState
beq @return ; No change in button state so exit
sta lastButtonState
lda characterState
cmp #CHAR_STATE_JUMPING
beq @jumping
lda lastButtonState
beq @return ; If button is not down, exit
ldx characterNumJumps
cpx #CHAR_MAX_JUMPS
beq @return ; If we have reached max jumps, exit
inx
stx characterNumJumps
lda #CHAR_STATE_JUMPING
sta characterState
lda #JUMP_SPEED
sta characterYSpeed
lda #0
sta characterYSpeedFrac
rts
@jumping:
lda lastButtonState
bne @return ; If the button is still pressed, exit
lda #CHAR_STATE_FALLING
sta characterState
lda #0
sta characterYSpeed
sta characterYSpeedFrac
@return:
rts
; Local
lastButtonState: .BYTE $00
.endproc
.proc updateCharacterPos
lda characterY
sta characterOldY
lda characterYBottom
sta characterOldYBottom
lda #0
sta ZPADDR6+1
lda characterState
cmp #CHAR_STATE_NONE
beq @stateNone
cmp #CHAR_STATE_JUMPING
beq @stateJumping
jmp updateCharacterPosFalling
@stateNone:
jmp updateCharacterPosNone
@stateJumping:
jmp updateCharacterPosJumping
.endproc
.proc nextGridAtCharacter
lda ZPADDR6+1
bne @nextGrid
lda LEVELADDR
sta ZPADDR6
lda LEVELADDR+1
sta ZPADDR6+1
lda #$0
sta gridLeft
lda gridXPos
clc
adc #MAXXBYTE
sta screenRight
ldy #LEVEL_STRUCT_WIDTH
lda (ZPADDR6),y
beq @noneFound
@gridLoop:
lda gridLeft
cmp screenRight
bcs @noneFound
; Add the width of the grid to the current gridLeft
ldy #LEVEL_STRUCT_WIDTH
clc
adc (ZPADDR6),y
; If we got a carry, that means the width of the next grid plus
; the grid left overflowed 256. If that happens we are definitely
; not left of gridXPos. We just need to subtract gridXPos to get
; onto screen coords.
bcs @overflow
cmp gridXPos
bcc @nextGrid
beq @nextGrid
@overflow:
sbc gridXPos
ldx gridXShift
beq @skipRightAdjust
cpx #5
bcs @skipRightAdjust
sec
sbc #2
@skipRightAdjust:
cmp #MAXXBYTE
bcc @rightIsNotOffScreen
lda #MAXXBYTE
@rightIsNotOffScreen:
sta gridScreenRight
lda gridLeft
sec
sbc gridXPos
beq @skipLeftAdjust
bpl @leftIsOnScreen
lda #$0
jmp @skipLeftAdjust
@leftIsOnScreen:
ldx gridXShift
beq @skipLeftAdjust
sec
sbc #1
@skipLeftAdjust:
cmp #CHAR_XPOS+1
bcs @noneFound
lda gridScreenRight
cmp #CHAR_XPOS
bcs @foundOne
@nextGrid:
lda ZPADDR6
clc
adc #LEVEL_STRUCT_SIZE
bcc @doNotIncHiByte
inc ZPADDR6+1
@doNotIncHiByte:
sta ZPADDR6
ldy #LEVEL_STRUCT_WIDTH
lda (ZPADDR6),y
beq @noneFound
ldy #LEVEL_STRUCT_START
lda gridLeft
clc
adc (ZPADDR6),y
cmp screenRight
beq @L2
bcs @noneFound
@L2:
sta gridLeft
jmp @gridLoop
@noneFound:
sec
rts
@foundOne:
clc
rts
; Locals
screenRight: .BYTE $00
gridLeft: .BYTE $00
.endproc
.proc updateCharacterPosNone
@loop:
jsr nextGridAtCharacter
bcs @floorGone
ldy #LEVEL_STRUCT_TOP
lda (ZPADDR6),y
cmp characterYBottom
bne @loop
ldy #LEVEL_STRUCT_COLOUR
lda (ZPADDR6),y
cmp characterColour
beq @checkForWin
jmp gameOver
@checkForWin:
ldy #LEVEL_STRUCT_SIZE+LEVEL_STRUCT_WIDTH
lda (ZPADDR6),y
bne @return
jmp levelWon
@floorGone:
lda #CHAR_STATE_FALLING
sta characterState
lda #0
sta characterYSpeed
sta characterYSpeedFrac
@return:
rts
.endproc
.proc updateCharacterPosJumping
; For jumping, we need to calculate the top first and check
; for collisions
lda #$ff
sta didHitHead
lda characterY
sec
sbc characterYSpeed
bcc @hitCeiling
sta characterY
@loop:
jsr nextGridAtCharacter
bcs @didNotHitHead
ldy #LEVEL_STRUCT_TOP
lda (ZPADDR6),y
sta gridTop
ldy #LEVEL_STRUCT_BOTTOM
lda (ZPADDR6),y
sta gridBottom
cmp characterOldY
bcc @wasBelowToStart
jmp @loop
@wasBelowToStart:
cmp characterY
bcc @loop
ldy #0
sty didHitHead
jmp @startFalling
@hitCeiling:
lda #$0
jmp @startFalling
@dropToBottomOfGrid:
lda gridBottom
@startFalling:
sta characterY
lda #0
sta characterYSpeed
sta characterYSpeedFrac
sta characterNumJumps
lda #CHAR_STATE_FALLING
sta characterState
jmp @updateYBottom
@didNotHitHead:
lda characterYSpeedFrac
clc
adc #GRAVITY
sta characterYSpeedFrac
bcc @updateYBottom
dec characterYSpeed
bne @updateYBottom
lda #CHAR_STATE_FALLING
sta characterState
@updateYBottom: ; Need to calculate characterYBottom now from characterY
lda characterY
clc
adc #CHAR_HEIGHT
sta characterYBottom
lda didHitHead
bne @return
; Check that the colour matches
ldy #LEVEL_STRUCT_COLOUR
lda (ZPADDR6),y
cmp characterColour
beq @return
jmp gameOver
@return:
rts
; Locals
gridTop: .BYTE $00
gridBottom: .BYTE $00
didHitHead: .BYTE $ff
.endproc
.proc updateCharacterPosFalling
; For falling, we need to calculate the bottom first and check
; for collisions
lda characterYBottom
clc
adc characterYSpeed
sta characterYBottom
cmp #MAXY
bcc @loop
lda #MAXY
sta characterYBottom
sec
sbc #CHAR_HEIGHT
sta characterY
jsr gameOver
rts
@loop:
jsr nextGridAtCharacter
bcs @didNotLand
ldy #LEVEL_STRUCT_BOTTOM
lda (ZPADDR6),y
sta gridBottom
ldy #LEVEL_STRUCT_TOP
lda (ZPADDR6),y
cmp characterOldYBottom
bcs @wasAboveToStart
lda characterYBottom
sec
sbc #CHAR_HEIGHT
cmp gridBottom
bcc @dropToBottomOfGrid
jmp @loop
@wasAboveToStart:
cmp characterYBottom
beq @L1
bcs @loop
@L1:
sta characterYBottom
lda #0
sta characterYSpeed
sta characterYSpeedFrac
sta characterNumJumps
lda #CHAR_STATE_NONE
sta characterState
jmp @updateY
@dropToBottomOfGrid:
lda gridBottom
clc
adc #CHAR_HEIGHT
sta characterYBottom
@didNotLand:
lda characterYSpeedFrac
clc
adc #GRAVITY
sta characterYSpeedFrac
bcc @updateY
inc characterYSpeed
@updateY: ; Need to calculate characterY now from characterYBottom
lda characterYBottom
sec
sbc #CHAR_HEIGHT
sta characterY
lda characterState
cmp #CHAR_STATE_NONE
bne @return
ldy #LEVEL_STRUCT_COLOUR
lda (ZPADDR6),y
cmp characterColour
beq @return
jmp gameOver
@return:
rts
; Locals
gridBottom: .BYTE $00
.endproc
.proc updateCharacterBitmap
ldx characterBitmap
inx
cpx #NUM_CHAR_BITMAPS
bne @noBitmapWrap
ldx #0
@noBitmapWrap:
stx characterBitmap
rts
.endproc
.proc updateCharacterColour
lda KBD
bpl @return
ldx KBDSTRB
cmp #$9b ; Compare to Escape
beq @quit
cmp #$d1 ; Compare to 'Q'
beq @quit
cmp #$f1 ; Compare to 'q'
beq @quit
lda characterColour
cmp #COL_VIOLET
beq @changeToGreen
lda #COL_VIOLET
sta characterColour
rts
@changeToGreen:
lda #COL_GREEN
sta characterColour
rts
@quit:
lda #$01
sta shouldQuit
@return: ; No key pressed
rts
.endproc
.proc drawCharacter
ldx characterColour
lda colourEvenLookup,x
sta evenVal
lda colourOddLookup,x
sta oddVal
ldx characterBitmap
lda characterBitmapLo,x
sta ZPADDR1
lda characterBitmapHi,x
sta ZPADDR1+1
ldx characterOldY
cpx characterY
beq @doNotEraseOld
@oldEraseLoop:
lda loAddrs,x
sta ZPADDR0
lda page1HiAddrs,x
sta ZPADDR0+1
ldy #CHAR_XPOS
lda #0
sta (ZPADDR0),y
iny
sta (ZPADDR0),y
inx
cpx characterOldYBottom
bne @oldEraseLoop
@doNotEraseOld:
ldy characterY
ldx #0
@drawLoop:
lda loAddrs,y
sta ZPADDR0
lda page1HiAddrs,y
sta ZPADDR0+1
sty yPos
ldy #CHAR_XPOS
lda oddVal
and (ZPADDR1,x)
sta (ZPADDR0),y
inc ZPADDR1
bne @doNotIncHiByte1
inc ZPADDR1+1
@doNotIncHiByte1:
iny
lda evenVal
and (ZPADDR1,x)
sta (ZPADDR0),y
inc ZPADDR1
bne @doNotIncHiByte2
inc ZPADDR1+1
@doNotIncHiByte2:
ldy yPos
iny
cpy characterYBottom
bne @drawLoop
rts
; Locals
evenVal: .BYTE $00
oddVal: .BYTE $00
yPos: .BYTE $00
.endproc
.proc updateGrid
dec gridXShift
beq @moveGridPos
bpl @return
ldx #GRID_MAX_SHIFT-1
stx gridXShift
rts
@moveGridPos:
inc gridXPos
inc gridXPos
@loop:
ldy #LEVEL_STRUCT_WIDTH
lda gridXPos
cmp (LEVELADDR),y
bcc @return
beq @return
; At this point, we know that this grid is not visible
; Check to see if the start of the next grid is left justified
; or off screen.
ldy #LEVEL_STRUCT_SIZE+LEVEL_STRUCT_START
cmp (LEVELADDR),y
bcc @return
; At this point, we know that the gridXPos is at the start of
; the next grid or maybe past the start. Move the LEVELADDR
; pointer forward to this grid and update gridXPos to be
; relative to this grid.
lda LEVELADDR
clc
adc #LEVEL_STRUCT_SIZE
bcc @doNotIncHiByte
inc LEVELADDR+1
@doNotIncHiByte:
sta LEVELADDR
ldy #LEVEL_STRUCT_START
lda gridXPos
sec
sbc (LEVELADDR),y
sta gridXPos
; We should check to see if this new grid is visible and if not,
; adjust the grid position again.
jmp @loop
@return:
rts
.endproc
.proc drawGrids
lda LEVELADDR
sta ZPADDR6
lda LEVELADDR+1
sta ZPADDR6+1
lda #$0
sta gridLeft
lda gridXPos
clc
adc #MAXXBYTE
sta screenRight
ldy #LEVEL_STRUCT_WIDTH
lda (ZPADDR6),y
bne @gridLoop
rts
@gridLoop:
lda gridLeft
cmp screenRight
beq @continue
bcs @return
@continue:
ldy #LEVEL_STRUCT_WIDTH
clc
adc (ZPADDR6),y
; If we got a carry, that means the width of the next grid plus
; the grid left overflowed 256. If that happens we are definitely
; not left of gridXPos. We just need to subtract gridXPos to get
; onto screen coords.
bcs @overflow
cmp gridXPos
bcc @nextGrid
sec
@overflow:
sbc gridXPos
tax
; Now depending on the X shift, we need to stop drawing the
; body of the grid and fill in the right end cap. We need
; to decrement the right boundary N times according to this
; chart:
; Shift 0 - 0 decrements
; Shift 1 - 2 decrements
; Shift 2 - 2 decrements
; Shift 3 - 1 decrement
; Shift 4 - 1 decrement
; Shift 5 - 1 decrement
; Shift 6 - 1 decrement
;
; Another special case, for a situation where the gridRight
; is 0 so the grid and the shift is 0 or 6, that means the
; grid is coming off the screen. We need to do no decrement
; and draw the grid to clear the cap.
lda gridXShift
beq @L1
cpx #$0
beq @gridRightZeroSpecialCase
dex
cmp #$3
bcs @L1
dex
jmp @L1
@gridRightZeroSpecialCase:
cmp #$6
bne @nextGrid
@L1:
cpx #MAXXBYTE
bcc @rightIsNotOffScreen
ldx #MAXXBYTE
@rightIsNotOffScreen:
stx gridScreenRight
lda gridLeft
sec
sbc gridXPos
bmi @leftIsOffScreen
beq @doneLeftAdjust
ldx gridXShift
beq @doneLeftAdjust
cpx #$4
bcs @doneLeftAdjust
sec
sbc #$1
jmp @doneLeftAdjust
@leftIsOffScreen:
lda #$0
@doneLeftAdjust:
sta gridScreenLeft
jsr drawGrid
;@debugLoop:
; lda KBD
; bpl @debugLoop
; lda KBDSTRB
@nextGrid:
lda ZPADDR6
clc
adc #LEVEL_STRUCT_SIZE
bcc @doNotIncHiByte
inc ZPADDR6+1
@doNotIncHiByte:
sta ZPADDR6
ldy #LEVEL_STRUCT_WIDTH
lda (ZPADDR6),y
beq @return
ldy #LEVEL_STRUCT_START
lda gridLeft
clc
adc (ZPADDR6),y
cmp screenRight
beq @L2
bcs @return
@L2:
sta gridLeft
jmp @gridLoop
@return:
rts
; Locals
screenRight: .BYTE $00
gridLeft: .BYTE $00
.endproc
.proc drawGrid
ldy #LEVEL_STRUCT_TOP
lda (ZPADDR6),y
tay
lda loAddrs,y
sta ZPADDR0
lda page1HiAddrs,y
sta ZPADDR0+1
iny
lda loAddrs,y
sta ZPADDR1
lda page1HiAddrs,y
sta ZPADDR1+1
iny
lda loAddrs,y
sta ZPADDR2
lda page1HiAddrs,y
sta ZPADDR2+1
iny
lda loAddrs,y
sta ZPADDR3
lda page1HiAddrs,y
sta ZPADDR3+1
iny
lda loAddrs,y
sta ZPADDR4
lda page1HiAddrs,y
sta ZPADDR4+1
iny
lda loAddrs,y
sta ZPADDR5
lda page1HiAddrs,y
sta ZPADDR5+1
ldx gridXShift
ldy #LEVEL_STRUCT_COLOUR
lda (ZPADDR6),y
tay
lda colourEvenLookup,y
sta evenVal
and evenGrid,x
sta evenGridVal
lda colourOddLookup,y
sta oddVal
and oddGrid,x
sta oddGridVal
ldy #LEVEL_STRUCT_SIZE+LEVEL_STRUCT_WIDTH
lda (ZPADDR6),y
bne @notLastGrid
lda evenVal
sta evenGridVal
lda oddVal
sta oddGridVal
@notLastGrid:
lda evenGridRight,x
and evenVal
sta evenRightCap
lda oddGridRight,x
and oddVal
sta oddRightCap
ldy gridScreenLeft
beq @nextGridComponent
; Draw the left cap
dey
tya
and #$01
bne @leftCapOdd
lda evenGridLeft,x
and evenVal
sta evenLeftCap
lda evenGridLeft,x
eor #$ff
sta evenLeftMask
lda evenLeftCap
and evenGridVal
tax
lda evenLeftMask
and (ZPADDR0),y
ora evenLeftCap
jmp @drawLeftCapComponent
@leftCapOdd:
lda oddGridLeft,x
and oddVal
sta oddLeftCap
lda oddGridLeft,x
eor #$ff
sta oddLeftMask
lda oddLeftCap
and oddGridVal
tax
lda oddLeftMask
and (ZPADDR0),y
ora oddLeftCap
@drawLeftCapComponent:
jsr drawGridComponent
ldy gridScreenLeft
@nextGridComponent:
cpy gridScreenRight
beq @lastGridComponent
tya
and #$01
bne @bodyOdd
lda evenVal
ldx evenGridVal
jmp @drawComponent
@bodyOdd:
lda oddVal
ldx oddGridVal
@drawComponent:
jsr drawGridComponent
iny
jmp @nextGridComponent
@lastGridComponent:
cpy #MAXXBYTE
beq @return
tya
and #$01
bne @rightCapOdd1
lda evenGridVal
and evenRightCap
tax
lda evenRightCap
jmp @nextRightCapComponent
@rightCapOdd1:
lda oddGridVal
and oddRightCap
tax
lda oddRightCap
@nextRightCapComponent:
jsr drawGridComponent
iny
cpy #MAXXBYTE
beq @return
lda #$00
tax
jsr drawGridComponent
@return:
rts
; Locals
evenVal: .BYTE $00
oddVal: .BYTE $00
evenGridVal: .BYTE $00
oddGridVal: .BYTE $00
evenLeftCap: .BYTE $00
oddLeftCap: .BYTE $00
evenLeftMask: .BYTE $00
oddLeftMask: .BYTE $00
evenRightCap: .BYTE $00
oddRightCap: .BYTE $00
.endproc
.proc drawGridComponent
sta (ZPADDR0),y
sta (ZPADDR5),y
txa
sta (ZPADDR1),y
sta (ZPADDR2),y
sta (ZPADDR3),y
sta (ZPADDR4),y
rts
.endproc
.proc clearScreen
ldx #0
ldy #0
@nextLine:
lda loAddrs,x
sta ZPADDR0
lda page1HiAddrs,x
sta ZPADDR0+1
lda #$0
@nextByte:
sta (ZPADDR0),y
iny
cpy #MAXXBYTE
bne @nextByte
inx
cpx #MAXY
bne @nextLine
lda TXTCLR
lda MIXCLR
lda HIRES
lda LOWSCR
rts
.endproc
.DATA
loAddrs:
.LOBYTES LINE0, LINE1, LINE2, LINE3, LINE4, LINE5, LINE6, LINE7
.LOBYTES LINE8, LINE9, LINE10, LINE11, LINE12, LINE13, LINE14, LINE15
.LOBYTES LINE16, LINE17, LINE18, LINE19, LINE20, LINE21, LINE22, LINE23
.LOBYTES LINE24, LINE25, LINE26, LINE27, LINE28, LINE29, LINE30, LINE31
.LOBYTES LINE32, LINE33, LINE34, LINE35, LINE36, LINE37, LINE38, LINE39
.LOBYTES LINE40, LINE41, LINE42, LINE43, LINE44, LINE45, LINE46, LINE47
.LOBYTES LINE48, LINE49, LINE50, LINE51, LINE52, LINE53, LINE54, LINE55
.LOBYTES LINE56, LINE57, LINE58, LINE59, LINE60, LINE61, LINE62, LINE63
.LOBYTES LINE64, LINE65, LINE66, LINE67, LINE68, LINE69, LINE70, LINE71
.LOBYTES LINE72, LINE73, LINE74, LINE75, LINE76, LINE77, LINE78, LINE79
.LOBYTES LINE80, LINE81, LINE82, LINE83, LINE84, LINE85, LINE86, LINE87
.LOBYTES LINE88, LINE89, LINE90, LINE91, LINE92, LINE93, LINE94, LINE95
.LOBYTES LINE96, LINE97, LINE98, LINE99, LINE100, LINE101, LINE102, LINE103
.LOBYTES LINE104, LINE105, LINE106, LINE107, LINE108, LINE109, LINE110, LINE111
.LOBYTES LINE112, LINE113, LINE114, LINE115, LINE116, LINE117, LINE118, LINE119
.LOBYTES LINE120, LINE121, LINE122, LINE123, LINE124, LINE125, LINE126, LINE127
.LOBYTES LINE128, LINE129, LINE130, LINE131, LINE132, LINE133, LINE134, LINE135
.LOBYTES LINE136, LINE137, LINE138, LINE139, LINE140, LINE141, LINE142, LINE143
.LOBYTES LINE144, LINE145, LINE146, LINE147, LINE148, LINE149, LINE150, LINE151
.LOBYTES LINE152, LINE153, LINE154, LINE155, LINE156, LINE157, LINE158, LINE159
.LOBYTES LINE160, LINE161, LINE162, LINE163, LINE164, LINE165, LINE166, LINE167
.LOBYTES LINE168, LINE169, LINE170, LINE171, LINE172, LINE173, LINE174, LINE175
.LOBYTES LINE176, LINE177, LINE178, LINE179, LINE180, LINE181, LINE182, LINE183
.LOBYTES LINE184, LINE185, LINE186, LINE187, LINE188, LINE189, LINE190, LINE191
page1HiAddrs:
.HIBYTES LINE0, LINE1, LINE2, LINE3, LINE4, LINE5, LINE6, LINE7
.HIBYTES LINE8, LINE9, LINE10, LINE11, LINE12, LINE13, LINE14, LINE15
.HIBYTES LINE16, LINE17, LINE18, LINE19, LINE20, LINE21, LINE22, LINE23
.HIBYTES LINE24, LINE25, LINE26, LINE27, LINE28, LINE29, LINE30, LINE31
.HIBYTES LINE32, LINE33, LINE34, LINE35, LINE36, LINE37, LINE38, LINE39
.HIBYTES LINE40, LINE41, LINE42, LINE43, LINE44, LINE45, LINE46, LINE47
.HIBYTES LINE48, LINE49, LINE50, LINE51, LINE52, LINE53, LINE54, LINE55
.HIBYTES LINE56, LINE57, LINE58, LINE59, LINE60, LINE61, LINE62, LINE63
.HIBYTES LINE64, LINE65, LINE66, LINE67, LINE68, LINE69, LINE70, LINE71
.HIBYTES LINE72, LINE73, LINE74, LINE75, LINE76, LINE77, LINE78, LINE79
.HIBYTES LINE80, LINE81, LINE82, LINE83, LINE84, LINE85, LINE86, LINE87
.HIBYTES LINE88, LINE89, LINE90, LINE91, LINE92, LINE93, LINE94, LINE95
.HIBYTES LINE96, LINE97, LINE98, LINE99, LINE100, LINE101, LINE102, LINE103
.HIBYTES LINE104, LINE105, LINE106, LINE107, LINE108, LINE109, LINE110, LINE111
.HIBYTES LINE112, LINE113, LINE114, LINE115, LINE116, LINE117, LINE118, LINE119
.HIBYTES LINE120, LINE121, LINE122, LINE123, LINE124, LINE125, LINE126, LINE127
.HIBYTES LINE128, LINE129, LINE130, LINE131, LINE132, LINE133, LINE134, LINE135
.HIBYTES LINE136, LINE137, LINE138, LINE139, LINE140, LINE141, LINE142, LINE143
.HIBYTES LINE144, LINE145, LINE146, LINE147, LINE148, LINE149, LINE150, LINE151
.HIBYTES LINE152, LINE153, LINE154, LINE155, LINE156, LINE157, LINE158, LINE159
.HIBYTES LINE160, LINE161, LINE162, LINE163, LINE164, LINE165, LINE166, LINE167
.HIBYTES LINE168, LINE169, LINE170, LINE171, LINE172, LINE173, LINE174, LINE175
.HIBYTES LINE176, LINE177, LINE178, LINE179, LINE180, LINE181, LINE182, LINE183
.HIBYTES LINE184, LINE185, LINE186, LINE187, LINE188, LINE189, LINE190, LINE191
page2HiAddrs:
.HIBYTES LINE0+$2000, LINE1+$2000, LINE2+$2000, LINE3+$2000, LINE4+$2000, LINE5+$2000, LINE6+$2000, LINE7+$2000
.HIBYTES LINE8+$2000, LINE9+$2000, LINE10+$2000, LINE11+$2000, LINE12+$2000, LINE13+$2000, LINE14+$2000, LINE15+$2000
.HIBYTES LINE16+$2000, LINE17+$2000, LINE18+$2000, LINE19+$2000, LINE20+$2000, LINE21+$2000, LINE22+$2000, LINE23+$2000
.HIBYTES LINE24+$2000, LINE25+$2000, LINE26+$2000, LINE27+$2000, LINE28+$2000, LINE29+$2000, LINE30+$2000, LINE31+$2000
.HIBYTES LINE32+$2000, LINE33+$2000, LINE34+$2000, LINE35+$2000, LINE36+$2000, LINE37+$2000, LINE38+$2000, LINE39+$2000
.HIBYTES LINE40+$2000, LINE41+$2000, LINE42+$2000, LINE43+$2000, LINE44+$2000, LINE45+$2000, LINE46+$2000, LINE47+$2000
.HIBYTES LINE48+$2000, LINE49+$2000, LINE50+$2000, LINE51+$2000, LINE52+$2000, LINE53+$2000, LINE54+$2000, LINE55+$2000
.HIBYTES LINE56+$2000, LINE57+$2000, LINE58+$2000, LINE59+$2000, LINE60+$2000, LINE61+$2000, LINE62+$2000, LINE63+$2000
.HIBYTES LINE64+$2000, LINE65+$2000, LINE66+$2000, LINE67+$2000, LINE68+$2000, LINE69+$2000, LINE70+$2000, LINE71+$2000
.HIBYTES LINE72+$2000, LINE73+$2000, LINE74+$2000, LINE75+$2000, LINE76+$2000, LINE77+$2000, LINE78+$2000, LINE79+$2000
.HIBYTES LINE80+$2000, LINE81+$2000, LINE82+$2000, LINE83+$2000, LINE84+$2000, LINE85+$2000, LINE86+$2000, LINE87+$2000
.HIBYTES LINE88+$2000, LINE89+$2000, LINE90+$2000, LINE91+$2000, LINE92+$2000, LINE93+$2000, LINE94+$2000, LINE95+$2000
.HIBYTES LINE96+$2000, LINE97+$2000, LINE98+$2000, LINE99+$2000, LINE100+$2000, LINE101+$2000, LINE102+$2000, LINE103+$2000
.HIBYTES LINE104+$2000, LINE105+$2000, LINE106+$2000, LINE107+$2000, LINE108+$2000, LINE109+$2000, LINE110+$2000, LINE111+$2000
.HIBYTES LINE112+$2000, LINE113+$2000, LINE114+$2000, LINE115+$2000, LINE116+$2000, LINE117+$2000, LINE118+$2000, LINE119+$2000
.HIBYTES LINE120+$2000, LINE121+$2000, LINE122+$2000, LINE123+$2000, LINE124+$2000, LINE125+$2000, LINE126+$2000, LINE127+$2000
.HIBYTES LINE128+$2000, LINE129+$2000, LINE130+$2000, LINE131+$2000, LINE132+$2000, LINE133+$2000, LINE134+$2000, LINE135+$2000
.HIBYTES LINE136+$2000, LINE137+$2000, LINE138+$2000, LINE139+$2000, LINE140+$2000, LINE141+$2000, LINE142+$2000, LINE143+$2000
.HIBYTES LINE144+$2000, LINE145+$2000, LINE146+$2000, LINE147+$2000, LINE148+$2000, LINE149+$2000, LINE150+$2000, LINE151+$2000
.HIBYTES LINE152+$2000, LINE153+$2000, LINE154+$2000, LINE155+$2000, LINE156+$2000, LINE157+$2000, LINE158+$2000, LINE159+$2000
.HIBYTES LINE160+$2000, LINE161+$2000, LINE162+$2000, LINE163+$2000, LINE164+$2000, LINE165+$2000, LINE166+$2000, LINE167+$2000
.HIBYTES LINE168+$2000, LINE169+$2000, LINE170+$2000, LINE171+$2000, LINE172+$2000, LINE173+$2000, LINE174+$2000, LINE175+$2000
.HIBYTES LINE176+$2000, LINE177+$2000, LINE178+$2000, LINE179+$2000, LINE180+$2000, LINE181+$2000, LINE182+$2000, LINE183+$2000
.HIBYTES LINE184+$2000, LINE185+$2000, LINE186+$2000, LINE187+$2000, LINE188+$2000, LINE189+$2000, LINE190+$2000, LINE191+$2000
colourEvenLookup:
.BYTE $00, $55, $2a, $ff
colourOddLookup:
.BYTE $00, $2a, $55, $ff
evenGrid:
.BYTE $03, $0c, $30, $40, $00, $00, $00
oddGrid:
.BYTE $00, $00, $00, $01, $06, $18, $60
evenGridLeft:
.BYTE $00, $7c, $70, $40, $00, $00, $00
oddGridLeft:
.BYTE $00, $7f, $7f, $7f, $7e, $78, $60
evenGridRight:
.BYTE $03, $0f, $3f, $00, $00, $00, $00
oddGridRight:
.BYTE $00, $00, $00, $01, $07, $1f, $7f
characterBitmap1:
.BYTE $70, $01
.BYTE $70, $01
.BYTE $30, $00
.BYTE $7c, $01
.BYTE $33, $06
.BYTE $30, $00
.BYTE $30, $00
.BYTE $4f, $01
.BYTE $40, $01
.BYTE $40, $01
characterBitmap2:
.BYTE $70, $01
.BYTE $70, $01
.BYTE $30, $00
.BYTE $3c, $06
.BYTE $73, $01
.BYTE $30, $00
.BYTE $7c, $01
.BYTE $43, $07
.BYTE $43, $07
.BYTE $03, $00
characterBitmap3:
.BYTE $70, $01
.BYTE $70, $01
.BYTE $30, $00
.BYTE $7c, $01
.BYTE $3c, $06
.BYTE $70, $01
.BYTE $7c, $01
.BYTE $3c, $00
.BYTE $3f, $00
.BYTE $0c, $00
characterBitmapLo:
.LOBYTES characterBitmap3, characterBitmap2, characterBitmap1
characterBitmapHi:
.HIBYTES characterBitmap3, characterBitmap2, characterBitmap1
characterColour: .BYTE COL_VIOLET
characterBitmap: .BYTE $00
characterY: .BYTE 0
characterYBottom: .BYTE CHAR_HEIGHT
characterOldY: .BYTE 0
characterOldYBottom: .BYTE CHAR_HEIGHT
characterState: .BYTE CHAR_STATE_FALLING
characterNumJumps: .BYTE $00
characterYSpeed: .BYTE $00
characterYSpeedFrac: .BYTE $00
gridY: .BYTE GRID_YPOS
gridXShift: .BYTE $00
gridXPos: .BYTE $00
gridScreenLeft: .BYTE $00
gridScreenRight: .BYTE $00
shouldQuit: .BYTE $00
level: .BYTE $0
; A level consists of the following for each grid:
; Byte 0 - Offset of the start of this grid from the previous grid's start
; Byte 1 - Grid width
; Byte 2 - Grid top
; Byte 3 - Grid bottom
; Byte 4 - Grid colour
; The end of a level has a grid width of 0
level1:
.BYTE 0, 80, 140, 140+GRID_HEIGHT, COL_VIOLET
.BYTE 90, 80, 140, 140+GRID_HEIGHT, COL_VIOLET
.BYTE 90, 80, 140, 140+GRID_HEIGHT, COL_VIOLET
.BYTE 90, 40, 140, 140+GRID_HEIGHT, COL_VIOLET
.BYTE 40, $00, $00, $00, $00
level2:
.BYTE 0, 80, 140, 140+GRID_HEIGHT, COL_VIOLET
.BYTE 90, 80, 140, 140+GRID_HEIGHT, COL_GREEN
.BYTE 90, 80, 140, 140+GRID_HEIGHT, COL_VIOLET
.BYTE 90, 40, 140, 140+GRID_HEIGHT, COL_GREEN
.BYTE 40, $00, $00, $00, $00
level3:
.BYTE 0, 80, 140, 140+GRID_HEIGHT, COL_VIOLET
.BYTE 80, 10, 140, 140+GRID_HEIGHT, COL_WHITE
.BYTE 10, 80, 140, 140+GRID_HEIGHT, COL_GREEN
.BYTE 80, 10, 140, 140+GRID_HEIGHT, COL_WHITE
.BYTE 10, 80, 140, 140+GRID_HEIGHT, COL_VIOLET
.BYTE 90, 40, 140, 140+GRID_HEIGHT, COL_GREEN
.BYTE 40, $00, $00, $00, $00
level4:
.BYTE 0, 80, 80, 80+GRID_HEIGHT, COL_VIOLET
.BYTE 60, 80, 100, 100+GRID_HEIGHT, COL_GREEN
.BYTE 60, 80, 120, 120+GRID_HEIGHT, COL_VIOLET
.BYTE 60, 40, 140, 140+GRID_HEIGHT, COL_GREEN
.BYTE 40, $00, $00, $00, $00
level5:
.BYTE 0, 80, 140, 140+GRID_HEIGHT, COL_VIOLET
.BYTE 60, 80, 120, 120+GRID_HEIGHT, COL_VIOLET
.BYTE 60, 80, 140, 140+GRID_HEIGHT, COL_VIOLET
.BYTE 60, 40, 120, 120+GRID_HEIGHT, COL_VIOLET
.BYTE 40, $00, $00, $00, $00
level6:
.BYTE 0, 80, 140, 140+GRID_HEIGHT, COL_VIOLET
.BYTE 60, 80, 120, 120+GRID_HEIGHT, COL_VIOLET
.BYTE 10, 70, 160, 160+GRID_HEIGHT, COL_GREEN
.BYTE 50, 80, 140, 140+GRID_HEIGHT, COL_VIOLET
.BYTE 60, 40, 120, 120+GRID_HEIGHT, COL_VIOLET
.BYTE 40, $00, $00, $00, $00
level7:
.BYTE 0, 80, 140, 140+GRID_HEIGHT, COL_VIOLET
.BYTE 100, 20, 120, 120+GRID_HEIGHT, COL_GREEN
.BYTE 40, 20, 100, 100+GRID_HEIGHT, COL_VIOLET
.BYTE 34, 20, 80, 80+GRID_HEIGHT, COL_GREEN
.BYTE 34, 20, 60, 60+GRID_HEIGHT, COL_VIOLET
.BYTE 30, 20, 40, 40+GRID_HEIGHT, COL_GREEN
.BYTE 40, $00, $00, $00, $00
levelsLo:
.LOBYTES level1, level2, level3, level4, level5, level6, level7, 0
levelsHi:
.HIBYTES level1, level2, level3, level4, level5, level6, level7, 0