include vcs2600.h org $1000 ;RAM locations MazePointer = $80 ;offset of maze data for current row RowPointer = $82 ;16-bit pointer to data for current row SpritePointer = $84 ;16-bit pointer to gfx data for current sprite ScreenPointer = $86 ;16-bit pointer to data for current screen CurrentScreen = $88 ;current screen number CurrentRow = $89 ;current row number within block, decrements 4-3-2-1 PlayerX = $8A ;player-X, 0 to 19 PlayerY = $8B ;player-Y, 0 to 13 FramesToMove = $8C Temp1 = $F6 Temp2 = $F7 Temp3 = $F8 Temp4 = $F9 Start SEI ; Disable interrupts, if there are any. CLD ; Clear BCD math bit. LDX #$FF TXS ; Set stack to top of RAM. LDA #0 ;Zero everything except VSYNC. V1 STA 0,X DEX BNE V1 LDA #$00 STA SWACNT ;set data direction registers to input STA SWBCNT lda #12 sta PlayerX sta PlayerY JSR GameInit MainLoop JSR VerticalBlank ;Execute the vertical blank. JSR CheckSwitches ;Check console switches. JSR GameCalc ;Do calculations during Vblank JSR SetupScreen JSR DrawScreen ;Draw the screen JSR OverScan ;Do more calculations during overscan JMP MainLoop ;Continue forever. VerticalBlank ;Beginning of the frame - at the end of overscan. LDA #2 ;VBLANK was set at the beginning of overscan. STA WSYNC STA VSYNC ;Begin vertical sync. STA WSYNC ;First line of VSYNC STA WSYNC ;Second line of VSYNC. LDA #44 ;Set timer to activate during the last line of VBLANK. STA TIM64T LDA #0 STA WSYNC ; Third line of VSYNC. STA VSYNC ; Writing zero to VSYNC ends vertical sync period. RTS CheckSwitches dec FramesToMove bpl M3 lda #0 sta FramesToMove ldx #10 ;for FramesToMove lda SWCHA tay bmi M0 inc PlayerX ;move right stx FramesToMove M0 and #$40 bne M1 dec PlayerX ;move left stx FramesToMove M1 tya and #$20 bne M2 inc PlayerY ;move down stx FramesToMove M2 tya and #$10 bne M3 dec PlayerY ;move up stx FramesToMove M3 RTS GameCalc RTS SetupScreen ;lda CurrentScreen ;get currentscreen address ldy #0 sty ScreenPointer lda #$13 sta ScreenPointer+1 ;for now, screen starts at $1300 lda (ScreenPointer),Y ;get mazetype sta MazePointer ldy #3 lda (ScreenPointer),Y ;low byte of block pointer sta RowPointer iny lda (ScreenPointer),Y ;high byte of block pointer sta RowPointer+1 lda PlayerY sta Temp4 ldx PlayerX sta WSYNC lda HorzTable,X ;+4 4 sta HMCLR ;+3 7 sta HMP0 ;+3 10 and #$0F ;+2 12 tax ;+2 14 P00 dex ;+2 16 bpl P00 ;+2 18 sta RESP0 ;+3 (21 + x*5) sta WSYNC sta HMOVE RTS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DrawScreen LDA INTIM BNE DrawScreen STA WSYNC ;begin scanline 0 STA VBLANK ;here we go! sta COLUPF sta COLUBK sta GRP1 sta COLUP1 ldx #31 ;Skip the top (status-bar) DoStatus dex sta WSYNC ;begin scanlines 1 through 31 bpl DoStatus DoScreen ;this happens during scanline 31 ldy #1 sty CTRLPF lda (ScreenPointer),Y sta COLUPF iny lda (ScreenPointer),Y sta COLUBK jsr DoABlock ;+xx 29 First block ;For first special, Rowpointer must equal ;ScreenPointer+5. lda ScreenPointer ;+3 32 clc ;+2 34 adc #5 ;+2 36 sta RowPointer ;+3 39 lda ScreenPointer+1 ;+3 42 adc #00 ;+2 44 sta RowPointer+1 ;+3 47 jsr DoRow ;first special ldy #8 lda (ScreenPointer),Y sta RowPointer iny lda (ScreenPointer),Y sta RowPointer+1 jsr DoABlock ;second block lda ScreenPointer clc adc #10 sta RowPointer lda ScreenPointer+1 adc #00 sta RowPointer+1 jsr DoRow ;second special ldy #13 lda (ScreenPointer),Y sta RowPointer iny lda (ScreenPointer),Y sta RowPointer+1 jsr DoABlock ;third block RTS ; Here, RowPointer should always be a 16-bit pointer to the start of ; the current row. DoABlock lda #4 sta CurrentRow B00 jsr DoRow dec CurrentRow bne B00 rts DoRow sta WSYNC ;begin line 0 of row ldx MazePointer ;+3 3 lda MazeData,X ;+4 7 ;get PF0 for row sta PF0 ;+3 10 lda MazeData+1,X ;+4 14 ;get PF1 sta PF1 ;+3 17 lda MazeData+2,X ;+4 21 sta PF2 ;+3 24 ldy #0 ;+2 26 sty GRP0 ;+3 29 sty GRP1 ;+3 32 lda (RowPointer),Y ;+5 37 get address of sprite data tax ;+2 39 and #$F0 ;+2 41 top 4 bits sta SpritePointer ;+3 44 txa ;+2 46 and #$0F ;+2 48 bottom 4 bits clc ;+2 50 adc #$1C ;+2 52 base page $1C sta SpritePointer+1 ;+3 55 SpritePointer set. sta HMCLR ;+3 58 iny ;+2 60 (RowPointer,Y) points to horz pos lda (RowPointer),Y ;+5 65 get 0-19 x-position tax ;+2 67 lda HorzTable,X ;+4 71 sta WSYNC ;start sta HMP1 ;+3 3 and #$0F ;+2 5 tax ;+2 7 cpx #5 ;+2 9 If x is 4 or lower, set position, then bpl R01 ;+2 11 write NUSIZ and reflect. If x >=5, sta Temp1 ;+3 14 do the other stuff first. R00 dex ;+2 16 bpl R00 ;when branch not taken: +2 (18 + x*5) sta RESP1 ;(21 + x*5), maximum 41 R01 iny ;+2 46 or 14 lda (RowPointer),Y ;+5 51 19 sta NUSIZ1 ;+3 54 22 sta REFP1 ;+3 57 25 ldy #14 ;+2 59 27 preparing for eachline txa ;+2 61 29 bmi R03 ;+2 63 31 if minus flag, we already resp1 sec ;+2 33 sbc #5 ;+2 35 tax ;+2 37 nop ;+2 39 R02 dex ;+2 41 bpl R02 ;when branch not taken: +2 (43 + x*5) sta RESP1 ;(46 + x*5) ;This begins first of ten graphics lines. ;Still need to add 3 to RowPointer before next row R03 sta WSYNC ;begin first line of pair sta HMOVE ;make sure the fine motion counted DoEachLine lda (SpritePointer),Y sta GRP1 dey lda (SpritePointer),Y sta COLUP1 ldx #0 ;this will be GRP0 for second line. lda Temp4 bne NoPlayer lda PlayerData+1,Y sta GRP0 lda PlayerData,Y sta COLUP0 lda PlayerData-1,Y tax NoPlayer dey lda (SpritePointer),Y dey sta WSYNC ;begin second line of pair stx GRP0 sta GRP1 bmi DoneLines ;if Y went negative, this was the last pair sta WSYNC ;begin first line of next pair jmp DoEachLine ;and continue DoneLines lda RowPointer clc adc #03 ;carry was set sta RowPointer lda MazePointer clc adc #3 sta MazePointer dec Temp4 RTS ;from DoRow OverScan LDA #35 ;Set timer to activate during the last line of overscan. STA TIM64T LDA #2 STA VBLANK ;do other calculations here EndOverscan LDA INTIM BNE EndOverscan STA WSYNC RTS GameInit RTS org $1200 ;========================================================================== ;Maze data. ;PF0first, PF1, PF2 (* 14) MazeData .byte $F0,$FF,$3F .byte $F0,$FF,$0F .byte $F0,$C0,$00 .byte $F0,$C0,$00 .byte $F0,$C0,$00 .byte $F0,$C0,$00 .byte $00,$00,$00 .byte $00,$00,$00 .byte $30,$00,$00 .byte $30,$00,$00 .byte $30,$00,$00 .byte $30,$00,$00 .byte $30,$00,$00 .byte $F0,$FF,$FF org $1300 ;========================================================================== ;Screen data. ;Mazetype, COLUPF, COLUBK, Blk1addr, spec1, blk2addr, spec2, blk3addr, ;Actiondatas ;Mazetype: Offset within page for maze ScreenData .byte 0, Brown+B1, Orange+B4, 0,$F8, $20,5,0, $0C,$F8, $10,16,Copy2C, $0C,$F8, 0,0 org $1800 ;========================================================================== ;Data for blocks. ;Gfxtype, Position (0-19), Action/NUSIZ/Reflect ;Gfxtype: Top 4 bits is offset within page for graphic, bottom 4 ;is number of pages to add to base. BlockData .byte 0,8,Copy2M .byte 0,2,0 .byte 0,17,0 .byte $10,8,Copy2M+Reflect .byte $10,8,Copy3W .byte $10,5,Copy2M .byte $10,3,Copy2W .byte $10,2,Copy2M+Reflect org $1C00 ;========================================================================== ;Gfx data for sprites. ;From bottom, (gfx color gfx) * 5 Grey = %0 Gold = %00010000 Brown = %00100000 Red = %00110000 Pink = %01000000 Purple = %01010000 Violet = %01100000 Blue = %10000000 LBlue = %10010000 Turquoise = %10100000 GBlue = %10110000 Green = %11000000 Yellow = %11010000 Orange = %11100000 LOrange = %11110000 B0 = %0000 B1 = %0010 B2 = %0100 B3 = %0110 B4 = %1000 B5 = %1010 B6 = %1100 B7 = %1110 Copy2C = 1 Copy2M = 2 Copy3C = 3 Copy2W = 4 CopyDW = 5 Copy3W = 6 CopyQW = 7 Reflect = 8 SpriteData .byte %11111011 ;Mountain .byte Brown+B6 .byte %10111111 .byte %11101111 .byte Brown+B5 .byte %11111111 .byte %11111110 .byte Brown+B4 .byte %01111110 .byte %01111100 .byte Brown+B3 .byte %00111100 .byte %00111100 .byte Grey+B6 .byte %00011000 .byte 0 .byte %00011000 ;Tree .byte LOrange+B2 .byte %00011000 .byte %00111100 .byte LOrange+B2 .byte %01111110 .byte %11111111 .byte Green+B5 .byte %11111111 .byte %11111111 .byte Green+B6 .byte %01111111 .byte %01111110 .byte Green+B5 .byte %00111100 .byte 0 .byte %00100100 .byte Blue+B4 .byte %00100100 .byte %10111101 .byte Blue+B5 .byte %10111101 .byte %11111111 .byte Blue+B6 .byte %01111110 .byte %00011000 .byte LBlue+B7 .byte %00111100 .byte %00111100 .byte LBlue+B7 .byte %00011000 org $1F00 ;========================================================================== ;Tables ;Horz positioning - converts 0-19 into FC-X HorzTable .byte $00,$71,$F1,$62,$E2,$53,$D3,$44,$C4,$35 .byte $B5,$26,$A6,$17,$97,$08,$79,$F9,$6A,$DA PlayerData ;From bottom, same format as SpriteData .byte %01111110 .byte Grey+B3 .byte %11000011 .byte %10011001 .byte Grey+B3 .byte %10100101 .byte %10000001 .byte Grey+B5 .byte %10100101 .byte %10000001 .byte Grey+B3 .byte %10000001 .byte %11000011 .byte Grey+B3 .byte %01111110 ;Starting positions for PC org $1FFC .word Start .word Start