EVENT__start = 1 EVENT__postframe = 1 EVENT__preframe = 1 EVENT__kernel = 1 EVENT__scanline = 1 EVENT__joyleft = 1 EVENT__joyright = 1 EVENT__joyup = 1 EVENT__joydown = 1 EVENT__prekernel = 1 EVENT__SetHorizPos = 1 EVENT__AddBCD4 = 1 EVENT__AddBCD2 = 1 EVENT__SubBCD2 = 1 .scope Main .zeropage Sprite_bitmap_b0: .res 1 .res 1 .res 1 .res 1 HasColormap_colormap_b0: .res 1 .res 1 .res 1 .res 1 HasXpos_xpos_b0: .res 1 .res 1 .res 1 .res 1 HasYpos_ypos_b0: .res 1 .res 1 .res 1 .res 1 SpriteSlot_sprite_b0: .res 1 .res 1 .res 1 .res 1 BCDScore6_digits_b0: .res 1 BCDScore6_digits_b8: .res 1 BCDScore6_digits_b16: .res 1 TEMP: Kernel2Sprite__2__tmp: Joystick__3__tmp: SpriteHider__9__tmp: .res 1 SpriteShuffler__8__tmp: .res 1 .res 1 .res 1 .res 1 .res 1 .res 1 .res 1 .res 1 .res 1 .res 1 .res 1 .res 1 Kernel6Digit__10__tmp: .res 1 .res 1 .res 1 .res 1 .res 1 .res 1 .res 1 .res 1 .res 1 .res 1 .res 1 .res 1 .res 1 .res 1 .res 1 .code PFColor_pfcolor_b0: .byte 60 BGColor_bgcolor_b0: .byte 2 .byte 160 KernelSection_lines_b0: .byte 168 Bitmap_bitmapdata_b0: .byte <(Bitmap_bitmapdata_e2_b0+31) .byte <(Bitmap_bitmapdata_e3_b0+31) .byte <(Bitmap_bitmapdata_e4_b0+31) .byte <(Bitmap_bitmapdata_e5_b0+31) .byte <(Bitmap_bitmapdata_e6_b0+31) Bitmap_bitmapdata_b8: .byte >(Bitmap_bitmapdata_e2_b0+31) .byte >(Bitmap_bitmapdata_e3_b0+31) .byte >(Bitmap_bitmapdata_e4_b0+31) .byte >(Bitmap_bitmapdata_e5_b0+31) .byte >(Bitmap_bitmapdata_e6_b0+31) Bitmap_bitmapdata_e2_b0: .byte 85 .byte 119 .byte 126 .byte 124 .byte 120 .byte 112 .byte 96 .byte 64 Bitmap_height_b0: .byte 7 .byte 12 .byte 12 .byte 8 .byte 8 Colormap_colormapdata_b0: .byte <(Colormap_colormapdata_e2_b0+31) .byte <(Colormap_colormapdata_e3_b0+31) .byte <(Colormap_colormapdata_e4_b0+31) .res 1 .res 1 .byte <(Colormap_colormapdata_e7_b0+31) Colormap_colormapdata_b8: .byte >(Colormap_colormapdata_e2_b0+31) .byte >(Colormap_colormapdata_e3_b0+31) .byte >(Colormap_colormapdata_e4_b0+31) .res 1 .res 1 .byte >(Colormap_colormapdata_e7_b0+31) Colormap_colormapdata_e2_b0: .byte 24 .byte 30 .byte 28 .byte 26 .byte 24 .byte 22 .byte 20 .byte 18 Bitmap_bitmapdata_e3_b0: .byte 60 .byte 126 .byte 255 .byte 195 .byte 255 .byte 255 .byte 255 .byte 187 .byte 153 .byte 255 .byte 126 .byte 60 .byte 24 Colormap_colormapdata_e3_b0: .byte 74 .byte 76 .byte 78 .byte 78 .byte 78 .byte 78 .byte 78 .byte 78 .byte 78 .byte 78 .byte 76 .byte 74 .byte 72 Bitmap_bitmapdata_e4_b0: .byte 60 .byte 126 .byte 231 .byte 219 .byte 255 .byte 255 .byte 255 .byte 153 .byte 153 .byte 255 .byte 126 .byte 60 .byte 24 Colormap_colormapdata_e4_b0: .byte 74 .byte 76 .byte 78 .byte 78 .byte 78 .byte 78 .byte 206 .byte 206 .byte 206 .byte 142 .byte 76 .byte 74 .byte 72 Bitmap_bitmapdata_e5_b0: .byte 1 .byte 1 .byte 3 .byte 7 .byte 15 .byte 31 .byte 63 .byte 255 Bitmap_bitmapdata_e6_b0: .byte 24 .byte 62 .byte 255 .byte 255 .byte 255 .byte 255 .byte 62 .byte 24 Colormap_colormapdata_e7_b0: .byte 6 .byte 3 .byte 6 .byte 9 .byte 12 .byte 14 .byte 31 .byte 63 Sprite_plyrflags_b0: .byte 0 .byte 3 .byte 0 .byte 0 Main__INITDATA: .byte 1 .byte 2 .byte 0 .byte 0 .byte 1 .byte 2 .byte 0 .byte 0 .byte 50 .byte 100 .byte 80 .byte 40 .byte 150 .byte 60 .byte 90 .byte 150 .byte 0 .byte 1 .byte 2 .byte 3 .byte 0 .byte 0 .byte 0 __Start: ;;; start action Init__main_init__1 .include "vcs-ca65.h" .macpack longbranch .define PAL 0 __NMI: __Reset: __BRK: CLEAN_START ldy #23 : lda Main__INITDATA-1,y sta Sprite_bitmap_b0-1,y dey bne :- ;;; start action FrameLoop__start__3 FrameLoop__start__4__NextFrame: FRAME_END FRAME_START ;;; start action Kernel2Sprite__preframe__5 ; TODOO: can store KLINES in memory? .define KLINES #168 .define KPAD 32 ; set height to zero in case no sprites lda #0 sta Kernel2Sprite__2__tmp+8 sta Kernel2Sprite__2__tmp+9 ;;; end action Kernel2Sprite__preframe__5 ;;; start action Kernel2Sprite__preframe__8 ldy #0 Kernel2Sprite__preframe__9____each: ldx SpriteSlot_sprite_b0,y ; set player object flags lda Sprite_plyrflags_b0,x sta NUSIZ0,y sta REFP0,y ; calculate screen height - ypos lda KLINES clc adc KPAD sec sbc HasYpos_ypos_b0,x sta Kernel2Sprite__2__tmp+11 ; calculate bitmap pointer stx Kernel2Sprite__2__tmp+12 ; save X (Sprite index) lda Sprite_bitmap_b0,x ; deref bitmap tax lda Bitmap_bitmapdata_b0,x sec sbc Kernel2Sprite__2__tmp+11 sta Kernel2Sprite__2__tmp+0,y ; Y = sprite slot index lda Bitmap_bitmapdata_b8,x sbc #0 sta Kernel2Sprite__2__tmp+2,y ; get bitmap height lda Bitmap_height_b0,x sta Kernel2Sprite__2__tmp+8,y ; calculate colormap pointer ldx Kernel2Sprite__2__tmp+12 ; restore X lda HasColormap_colormap_b0,x ; deref colormap tax lda Colormap_colormapdata_b0,x sec sbc Kernel2Sprite__2__tmp+11 sta Kernel2Sprite__2__tmp+4,y lda Colormap_colormapdata_b8,x sbc #0 sta Kernel2Sprite__2__tmp+6,y ; save ypos ldx Kernel2Sprite__2__tmp+12 ; restore X lda HasYpos_ypos_b0,x sta Kernel2Sprite__2__tmp+10,y iny cpy #2 jne Kernel2Sprite__preframe__9____each Kernel2Sprite__preframe__9____exit: ;;; end action Kernel2Sprite__preframe__8 ;;; start action Kernel2Sprite__preframe__11 ; shuffle pointers into (MSB, LSB) byte order ; L0 L1 H0 H1 -> L0 H0 L1 H1 lda Kernel2Sprite__2__tmp+1 ldy Kernel2Sprite__2__tmp+2 sty Kernel2Sprite__2__tmp+1 sta Kernel2Sprite__2__tmp+2 lda Kernel2Sprite__2__tmp+5 ldy Kernel2Sprite__2__tmp+6 sty Kernel2Sprite__2__tmp+5 sta Kernel2Sprite__2__tmp+6 ;;; end action Kernel2Sprite__preframe__11 ;;; start action Kernel2Sprite__preframe__13 lda #160 sta COLUBK ;;; end action Kernel2Sprite__preframe__13 ;;; start action Kernel2Sprite__preframe__16 ;;; end action Kernel2Sprite__preframe__16 ;;; start action SetXPos__preframe__17 ldy #0 SetXPos__preframe__18____each: ldx SpriteSlot_sprite_b0,y lda HasXpos_xpos_b0,x jsr SetHorizPos__SetHorizPos__20 iny cpy #2 jne SetXPos__preframe__18____each SetXPos__preframe__18____exit: ;;; end action SetXPos__preframe__17 ;;; start action SetXPos__preframe__22 ;;; end action SetXPos__preframe__22 ;;; start action Kernel6Digit__preframe__23 Digit0 = Kernel6Digit__10__tmp+0 Digit1 = Kernel6Digit__10__tmp+2 Digit2 = Kernel6Digit__10__tmp+4 Digit3 = Kernel6Digit__10__tmp+6 Digit4 = Kernel6Digit__10__tmp+8 Digit5 = Kernel6Digit__10__tmp+10 Kernel6Digit__preframe__25__BCD0 = Kernel6Digit__10__tmp+12 Kernel6Digit__preframe__25__BCD1 = Kernel6Digit__10__tmp+13 Kernel6Digit__preframe__25__BCD2 = Kernel6Digit__10__tmp+14 lda BCDScore6_digits_b0 sta Kernel6Digit__preframe__25__BCD0 lda BCDScore6_digits_b8 sta Kernel6Digit__preframe__25__BCD1 lda BCDScore6_digits_b16 sta Kernel6Digit__preframe__25__BCD2 ldx #0 ; leftmost bitmap ldy #2 ; start from most-sigificant BCD value Kernel6Digit__preframe__25__Loop: lda Kernel6Digit__preframe__25__BCD0,y ; get BCD value and #$f0 ; isolate high nibble (* 16) lsr ; shift right 1 bit (* 8) clc adc #FontTable adc #0 sta Digit0+1,x ; store pointer hi byte inx inx ; next bitmap pointer lda Kernel6Digit__preframe__25__BCD0,y ; get BCD value (again) and #$f ; isolate low nibble asl asl asl ; * 8 clc adc #FontTable adc #0 sta Digit0+1,x ; store pointer hi byte inx inx ; next bitmap pointer dey ; next BCD value bpl Kernel6Digit__preframe__25__Loop ; repeat until < 0 ;;; end action Kernel6Digit__preframe__23 ;;; start action SetXPos__prekernel__26 sta WSYNC sta HMOVE SLEEPR 24 sta HMCLR ;;; end action SetXPos__prekernel__26 KERNEL_START ;;; start action Kernel2Sprite__kernel__28 ldy #0 sty VDELP0 iny sty VDELP1 ;;; end action Kernel2Sprite__kernel__28 jsr Kernel2Sprite__kernel__31 ;;; start action Kernel2Sprite__kernel__40 lda #0 sta GRP0 sta GRP1 sta GRP0 sta GRP1 ;;; end action Kernel2Sprite__kernel__40 ;;; start action Kernel6Digit__kernel__42 lda #60 sta COLUP0 sta COLUP1 lda #3 sta NUSIZ0 sta NUSIZ1 ; set horizontal position of player objects sta WSYNC sta HMCLR SLEEPR 24 sta RESP0 sta RESP1 lda #$10 sta HMP1 sta WSYNC sta HMOVE SLEEPR 24 ; wait 24 cycles between write to HMOVE and HMxxx sta HMCLR lda #1 sta VDELP0 sta VDELP1 ;;; end action Kernel6Digit__kernel__42 jsr Kernel6Digit__kernel__45 KERNEL_END ;;; start action FrameLoop__postframe__48 lsr SWCHB ; test Game Reset switch bcs FrameLoop__postframe__49__NoStart FrameLoop__postframe__49__NoStart: ;;; end action FrameLoop__postframe__48 ;;; start action Joystick__postframe__50 ; 2 control inputs share a single byte, 4 bits each lda SWCHA sta Joystick__3__tmp+0 ;;; end action Joystick__postframe__50 ;;; start action Joystick__postframe__52 ldx #0 Joystick__postframe__53____each: asl Joystick__3__tmp+0 .ifdef EVENT__joyright bcs Joystick__postframe__54__SkipMoveRight ;;; start action MoveJoyX__joyright__55 lda HasXpos_xpos_b0,x clc adc #1 cmp #150 bcs MoveJoyX__joyright__57__nomove sta HasXpos_xpos_b0,x MoveJoyX__joyright__57__nomove: ;;; end action MoveJoyX__joyright__55 Joystick__postframe__54__SkipMoveRight: .endif asl Joystick__3__tmp+0 .ifdef EVENT__joyleft bcs Joystick__postframe__54__SkipMoveLeft ;;; start action MoveJoyX__joyleft__58 lda HasXpos_xpos_b0,x sec sbc #1 bcc MoveJoyX__joyleft__60__nomove sta HasXpos_xpos_b0,x MoveJoyX__joyleft__60__nomove: ;;; end action MoveJoyX__joyleft__58 Joystick__postframe__54__SkipMoveLeft: .endif asl Joystick__3__tmp+0 .ifdef EVENT__joydown bcs Joystick__postframe__54__SkipMoveDown ;;; start action MoveJoyY__joydown__61 lda HasYpos_ypos_b0,x clc adc #1 cmp #220 bcs MoveJoyY__joydown__63__nomove sta HasYpos_ypos_b0,x MoveJoyY__joydown__63__nomove: ;;; end action MoveJoyY__joydown__61 Joystick__postframe__54__SkipMoveDown: .endif asl Joystick__3__tmp+0 .ifdef EVENT__joyup bcs Joystick__postframe__54__SkipMoveUp ;;; start action MoveJoyY__joyup__64 lda HasYpos_ypos_b0,x sec sbc #1 bcc MoveJoyY__joyup__66__nomove sta HasYpos_ypos_b0,x MoveJoyY__joyup__66__nomove: ;;; end action MoveJoyY__joyup__64 Joystick__postframe__54__SkipMoveUp: .endif inx cpx #2 jne Joystick__postframe__53____each Joystick__postframe__53____exit: ;;; end action Joystick__postframe__52 ;;; start action SpriteShuffler__postframe__67 ; load two sprite slots at left side of array lda SpriteSlot_sprite_b0 sta SpriteShuffler__8__tmp+0 lda SpriteSlot_sprite_b0+1 sta SpriteShuffler__8__tmp+1 ; move two slots to the left ldx #0 SpriteShuffler__postframe__69__loop: lda SpriteSlot_sprite_b0+2,x sta SpriteSlot_sprite_b0,x inx cpx #4-2 bne SpriteShuffler__postframe__69__loop ; store two sprite slots at right side of array lda SpriteShuffler__8__tmp+0 sta SpriteSlot_sprite_b0+4-2 lda SpriteShuffler__8__tmp+1 sta SpriteSlot_sprite_b0+4-1 ;;; end action SpriteShuffler__postframe__67 ;;; start action SpriteHider__postframe__70 lda #4-1 sta SpriteHider__9__tmp+0 ;;; end action SpriteHider__postframe__70 ;;; start action SpriteHider__postframe__73 ldy #0 SpriteHider__postframe__74____each: ldx SpriteSlot_sprite_b0,y lda HasYpos_ypos_b0,x cmp #192 bcc SpriteHider__postframe__75__skip ; swap this sprite slot with slot at end of array lda SpriteSlot_sprite_b0,y pha ldx SpriteHider__9__tmp+0 ; clobbers X, but no longer used lda SpriteSlot_sprite_b0,x sta SpriteSlot_sprite_b0,y pla sta SpriteSlot_sprite_b0,x dec SpriteHider__9__tmp+0 SpriteHider__postframe__75__skip: iny cpy #2 jne SpriteHider__postframe__74____each SpriteHider__postframe__74____exit: ;;; end action SpriteHider__postframe__73 ;;; start action JoyButton__postframe__76 ldx #0 JoyButton__postframe__77____each: lda INPT4,x ;read button input bmi JoyButton__postframe__78__NotPressed JoyButton__postframe__78__NotPressed: inx cpx #2 jne JoyButton__postframe__77____each JoyButton__postframe__77____exit: ;;; end action JoyButton__postframe__76 ;;; start action Enemies__postframe__79 ldx #0 Enemies__postframe__80____each: inc HasYpos_ypos_b0+2,x ; inc HasYpos_ypos_b0+2,x inx cpx #2 jne Enemies__postframe__80____each Enemies__postframe__80____exit: ;;; end action Enemies__postframe__79 jmp FrameLoop__start__4__NextFrame ; loop to next frame ;;; end action FrameLoop__start__3 ; start main routine .segment "VECTORS" ZeroByte: .byte $00 Return: .byte $60 VecNMI: VecReset: .word __Reset VecBRK: .word __BRK .code ;;; end action Init__main_init__1 .rodata __ALIGNORIGIN: .rodata SetHorizPos__SetHorizPos__20: ; SetHorizPos routine ; A = X coordinate ; Y = player number (0 or 1) sec ; set carry flag sta WSYNC ; start a new line : sbc #15 ; subtract 15 bcs :- ; branch until negative eor #7 ; calculate fine offset asl asl asl asl sta HMP0,y ; set fine offset sta RESP0,y ; fix coarse position sta WSYNC ; won't overrun if X < 150 rts .assert >(SetHorizPos__SetHorizPos__20) = >(*), error, "SetHorizPos__SetHorizPos__20 crosses a page boundary!" .assert (* - SetHorizPos__SetHorizPos__20) <= 22, error, .sprintf("SetHorizPos__SetHorizPos__20 does not fit in 22 bytes, it took %d!", (* - SetHorizPos__SetHorizPos__20)) .rodata Kernel2Sprite__kernel__31: ldy #168 Kernel2Sprite__kernel__33__LVScan: ;;; start action Kernel2Sprite__scanline__34 ; draw player 0 lda Kernel2Sprite__2__tmp+8 ; height dcp Kernel2Sprite__2__tmp+10 ; ypos bcs Kernel2Sprite__scanline__35__DoDraw1 lda #0 .byte $2C Kernel2Sprite__scanline__35__DoDraw1: lda (Kernel2Sprite__2__tmp+0),y ; .if 0 = 0 ; TODO: configurable? sta WSYNC ; .endif sta GRP0 lda (Kernel2Sprite__2__tmp+4),y sta COLUP0 ; draw player 1 lda Kernel2Sprite__2__tmp+9 ; height dcp Kernel2Sprite__2__tmp+11 ; ypos bcs Kernel2Sprite__scanline__35__DoDraw2 lda #0 .byte $2C Kernel2Sprite__scanline__35__DoDraw2: lda (Kernel2Sprite__2__tmp+2),y sta GRP1 lda (Kernel2Sprite__2__tmp+6),y sta COLUP1 ;;; end action Kernel2Sprite__scanline__34 ;;; start action Kernel2Sprite__scanline__36 ;;; end action Kernel2Sprite__scanline__36 dey ; next scanline ;;; start action Kernel2Sprite__scanline__37 ; draw player 0 lda Kernel2Sprite__2__tmp+8 ; height dcp Kernel2Sprite__2__tmp+10 ; ypos bcs Kernel2Sprite__scanline__38__DoDraw1 lda #0 .byte $2C Kernel2Sprite__scanline__38__DoDraw1: lda (Kernel2Sprite__2__tmp+0),y ; .if 1 = 0 ; TODO: configurable? sta WSYNC ; .endif sta GRP0 lda (Kernel2Sprite__2__tmp+4),y sta COLUP0 ; draw player 1 lda Kernel2Sprite__2__tmp+9 ; height dcp Kernel2Sprite__2__tmp+11 ; ypos bcs Kernel2Sprite__scanline__38__DoDraw2 lda #0 .byte $2C Kernel2Sprite__scanline__38__DoDraw2: lda (Kernel2Sprite__2__tmp+2),y sta GRP1 lda (Kernel2Sprite__2__tmp+6),y sta COLUP1 ;;; end action Kernel2Sprite__scanline__37 ;;; start action Kernel2Sprite__scanline__39 ;;; end action Kernel2Sprite__scanline__39 dey ; next scanline bne Kernel2Sprite__kernel__33__LVScan ; repeat until out of lines rts .assert >(Kernel2Sprite__kernel__31) = >(*), error, "Kernel2Sprite__kernel__31 crosses a page boundary!" .if <(* - __ALIGNORIGIN) > 256-72 .align $100 .endif .rodata Kernel6Digit__kernel__45: ; Display the resulting 48x8 bitmap ; using the Digit0-5 pointers. Kernel6Digit__kernel__47__LoopCount = Kernel6Digit__10__tmp+12 Kernel6Digit__kernel__47__Temp = Kernel6Digit__10__tmp+13 lda #2 sta WSYNC sta COLUBK lda #7 sta Kernel6Digit__kernel__47__LoopCount SLEEPR 20 ; TODO? : ldy Kernel6Digit__kernel__47__LoopCount ; counts backwards lda (Digit0),y ; load B0 (1st sprite byte) sta GRP0 ; B0 -> [GRP0] lda (Digit1),y ; load B1 -> A sta GRP1 ; B1 -> [GRP1], B0 -> GRP0 sta WSYNC ; sync to next scanline lda (Digit2),y ; load B2 -> A sta GRP0 ; B2 -> [GRP0], B1 -> GRP1 lda (Digit5),y ; load B5 -> A sta Kernel6Digit__kernel__47__Temp ; B5 -> temp lda (Digit4),y ; load B4 tax ; -> X lda (Digit3),y ; load B3 -> A ldy Kernel6Digit__kernel__47__Temp ; load B5 -> Y sta GRP1 ; B3 -> [GRP1]; B2 -> GRP0 stx GRP0 ; B4 -> [GRP0]; B3 -> GRP1 sty GRP1 ; B5 -> [GRP1]; B4 -> GRP0 sta GRP0 ; ?? -> [GRP0]; B5 -> GRP1 dec Kernel6Digit__kernel__47__LoopCount ; go to next line bpl :- ; repeat until < 0 lda #0 ; clear the sprite registers sta WSYNC sta GRP0 sta GRP1 sta GRP0 sta GRP1 sta COLUBK rts .assert >(Kernel6Digit__kernel__45) = >(*), error, "Kernel6Digit__kernel__45 crosses a page boundary!" .assert (* - Kernel6Digit__kernel__45) <= 72, error, .sprintf("Kernel6Digit__kernel__45 does not fit in 72 bytes, it took %d!", (* - Kernel6Digit__kernel__45)) FontTable: ;;; start action FontTable__FontTable__82 ; Font table for digits 0-9 (8x8 pixels) ;;{w:8,h:8,count:10,brev:1,flip:1};; .byte $00,$3c,$66,$66,$76,$6e,$66,$3c,$00,$7e,$18,$18,$18,$38,$18,$18 .byte $00,$7e,$60,$30,$0c,$06,$66,$3c,$00,$3c,$66,$06,$1c,$06,$66,$3c .byte $00,$06,$06,$7f,$66,$1e,$0e,$06,$00,$3c,$66,$06,$06,$7c,$60,$7e .byte $00,$3c,$66,$66,$7c,$60,$66,$3c,$00,$18,$18,$18,$18,$0c,$66,$7e .byte $00,$3c,$66,$66,$3c,$66,$66,$3c,$00,$3c,$66,$06,$3e,$66,$66,$3c ;;; end action FontTable__FontTable__82 .endscope Main__Start = Main::__Start