;******************************************************************************* ; ; BattlePong ; ---------- ;******************************************************************************* ; Yet another game attempt ; Jeff Haber ; July 2016 ; ; compile using DASM: ; dasm BP1.asm -f3 -v0 -sBP1.sym -lBP1.lst -oBP1.bin ;=============================================================================== ; Change Log ;=============================================================================== ; Pill1d. Added ball though with shearing on right side. ; Pill1e. Corrected shearing by moving ball to line 2 ; Pill1f. Attempting to add missiles. Failed ; Pill1fb. Had the friggin BNE in the same spot it was before I added the ; missile stuff. Had a totally blank screen until I removed the line ; 1 WSYNC. Works now, but ball shearing is back due to removing the ; WSYNC. ; Pill1g. Created muticolored heads. Caused some kernal issues- warping. ; Commented out pills which fixed most of it except ball shear. ; Pill1h. Minor maintenance changes ; Pill1i. Learned a new player color change scheme from Darrell. Partially ; successful. Glitchy ; Pill1j Continuation. Color issues corrected- though there is massive ; shearing probably because line one of the kernal is very small ; Pill1k Re-introduced pills into band 4 ; Pill1m Introduced player colors to band 4 ; Pill1n Set up band 2 framework ; Pill1o Set up band 5 framework ; Pill1p Set up band 1 framework ; Pill1q Maintenance ; Pill1r Adding score loop. Working, with glitches ; Pill1s Attempting to correct PF ; Pill1sb Score screen working well. ; ; Pill2b Fixing Ball shear ; Pill2d Colored the pills. Reduced pill graphics ; Pill2e Added static screen ; Pill2f Adding Test Pattern ; Pill2i Cleanup ; Pill2j Cleanup continued ; BP1 Changed name to BattlePong ;=============================================================================== ; Initialize DASM ;=============================================================================== PROCESSOR 6502 include vcs.h include macro.h ;=============================================================================== ; Define Constants ;=============================================================================== ARENA_HEIGHT = 90 ; height of gameplay area ?Was 100 PF_COLOR = $1C ; yellow BALL_HEIGHT = 8 ; 8 MISSILE_HEIGHT = 1 ; 1 HAIR_COLOR = $24 HEAD_COLOR = $4C BODY_COLOR = $82 LEG_COLOR = $E4 FOOT_COLOR = $22 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; SCORE LOOP CONSTANTS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SHAPE_DASH = $44 SHAPE_SIDES = $1C ;=============================================================================== ; Define RAM Usage ;=============================================================================== SEG.U VARS ORG $80 ; holds background color BackgroundColor: ds 1 ; stored in $80 ; holds X locations in $81-82 ObjectX: ds 2 ; player0, player1 ; holds Y locations in $83-84 ObjectY: ds 2 ; player0, player1 ; DoDraw storage in $85-86 Player0Draw: ds 1 ; used for drawing player0 Player1Draw: ds 1 ; used for drawing player1 ; DoDraw Graphic Pointers in $87-8a Player0Ptr: ds 2 ; used for drawing player0 Player1Ptr: ds 2 ; used for drawing player1 ; current random number Rand8: ds 1 ; stored in $8b ; DoDraw storage in $8c ;PillDraw: ds 1 ;used for drawing pills PillY: ds 1 ; PillPtr: ds 2 ; PillRAMGfx: ds 12 ; BallDraw: ds 1 ; BallY: ds 1 ; Missile0Draw: ds 1 Missile1Draw: ds 1 Missile0Y: ds 1 Missile1Y: ds 1 FrameCounter: ds 1 PlayerColorPtr: ds 2 ; used for drawing player0 Player1ColorPtr: ds 2 ;=============================================================================== ; Define Start of Cartridge ;=============================================================================== SEG CODE ; 2K ROM starts at $F800, 4K ROM starts at $F000 ORG $F000 ;=============================================================================== ; Subroutines ;=============================================================================== ;------------------------------------------------------------------------------- ; PosObject ;---------- ; subroutine for setting the X position of any TIA object ; when called, set the following registers: ; A - holds the X position of the object ; X - holds which object to position ; 0 = player0 ; 1 = player1 ; 2 = missile0 ; 3 = missile1 ; 4 = ball ; the routine will set the coarse X position of the object, as well as the ; fine-tune register. The fine-tune register will be used to adjust the objects ; final position when an HMOVE is strobed. The HMOVE must be strobed ; immediately after the WSYNC is strobed. ; ; Note: The X position differs based on the object, for player0 and player1 ; 0 is the leftmost pixel while for missile0, missile1 and ball 1 is ; the leftmost pixel: ; players - X range is 0-159 ; missiles - X range is 1-160 ; ball - X range is 1-160 ; ; Note: Setting players to double or quad size will affect the position of ; the players. ;------------------------------------------------------------------------------- PosObject: sec sta WSYNC DivideLoop sbc #15 ; 2 2 - each time thru this loop takes 5 cycles, which is bcs DivideLoop ; 2 4 - the same amount of time it takes to draw 15 pixels eor #7 ; 2 6 - The EOR & ASL statements convert the remainder asl ; 2 8 - of position/15 to the value needed to fine tune asl ; 2 10 - the X position asl ; 2 12 asl ; 2 14 sta.wx HMP0,X ; 5 19 - store fine tuning of X sta RESP0,X ; 4 23 - set coarse X position of object rts ; 6 29 - ReTurn from Subroutine ;------------------------------------------------------------------------------- ; Random ;------------------------------------------------------------------------------- Random: lda Rand8 ; 3 3 lsr ; 2 5 bcc noeor ; 2,3 7,8 eor #$B4 ; 2 9 noeor: sta Rand8 ; 3 12 or 11 from bcc rts ; 6 18 ; also the jsr ; 6 24 ;=============================================================================== ; Initialize Atari ;=============================================================================== InitSystem: CLEAN_START ; set initial player0 position lda #40 sta ObjectX lda #(ARENA_HEIGHT - PLAYER0_HEIGHT)/2 sta ObjectY ; set initial player 1 position lda #120 sta ObjectX+1 lda #(ARENA_HEIGHT - PLAYER1_HEIGHT)/2 sta ObjectY+1 ; set initial pill position lda #15 ;(ARENA_HEIGHT - COIN_HEIGHT)/2 sta PillY ; set initial ball position lda #70 ;#(ARENA_HEIGHT - BALL_HEIGHT)/2 sta BallY ; set initial missile0 position lda #(ARENA_HEIGHT - MISSILE_HEIGHT)/2 sta Missile0Y ; set initial missile1 position lda #(ARENA_HEIGHT - MISSILE_HEIGHT)/2 sta Missile1Y lda #0 ; black sta BackgroundColor lda #PF_COLOR sta COLUPF lda #$84 sta Rand8 ; also use $84 as seed for the LFSR lda #%00000000 sta PillRAMGfx lda #%00000000 sta PillRAMGfx+1 lda #%01010100 sta PillRAMGfx+2 lda #%01010100 sta PillRAMGfx+3 lda #%01010100 sta PillRAMGfx+4 lda #%01010100 sta PillRAMGfx+5 lda #%01010100 sta PillRAMGfx+6 lda #%01010100 sta PillRAMGfx+7 lda #%00010100 sta PillRAMGfx+8 lda #%00010000 sta PillRAMGfx+9 lda #%00010000 sta PillRAMGfx+10 lda #%00010000 sta PillRAMGfx+11 ; Set temporary ball speed lda #%00010000 ; Move left slow sta HMBL ; Set temporary Missile0 speed lda #%11000000 ; sta HMM0 ; Set temporary missile1 speed lda #%01000000 ; sta HMM1 ; Set temporary ball size and reflect lda #%1111001 sta CTRLPF sta VDELBL ;D0 to delay ;sta REFP0 ;D3 to reflect ;sta REFP1 ;D3 to reflect ;=============================================================================== ; Main Program Loop ;=============================================================================== Main: jsr VerticalSync ; Jump to SubRoutine VerticalSync jsr VerticalBlank ; Jump to SubRoutine VerticalBlank jsr Kernel ; Jump to SubRoutine Kernel jsr OverScan ; Jump to SubRoutine OverScan jmp Main ; JuMP to Main ;======================================== ; Sync Signal ;======================================== VerticalSync: lda #2 ; LoaD Accumulator with 2 sta WSYNC ; STore Accumulator to WSYNC, any value halts CPU until start of next scanline sta VSYNC ; Accumulator D1=1, turns on Vertical Sync signal sta VBLANK ; Accumulator D1=1, turns on Vertical Blank signal (image output off) lda #47 sta TIM64T ; set timer for end of Vertical Blank sta WSYNC ; 1st scanline of VSYNC sta WSYNC ; 2nd scanline of VSYNC lda #0 ; LoaD Accumulator with 0 sta GRP0 sta GRP1 sta WSYNC ; 3rd scanline of VSYNC sta VSYNC ; Accumulator D1=0, turns off Vertical Sync signal rts ;======================================== ; Vertical Blank ; -------------- ; game logic runs here. ; ;======================================== VerticalBlank: jsr Random ;Called and not used to advance the register jsr ProcessJoystick jsr PositionObjectsY VBwait: sta WSYNC bit TIMINT bpl VBwait ; wait for the timer to denote end of Vertical Blank rts ;=============================================================================== ; ProcessJoystick ; -------------- ; Read joystick and move player0 ; ; joystick directions are held in the SWCHA register of the RIOT chip. ; Directions are read via the following bit pattern: ; 76543210 ; RLDUrldu - RIGHT LEFT DOWN UP right left down up ; ; UPPERCASE denotes the left joystick directions ; lowercase denotes the right joystick directions ; ; Note: The values are the opposite of what you might expect. If the direction ; is held, the bit value will be 0. ; ; Note: Fire buttons are read via INPT4 (left) and INPT5 (right). ;=============================================================================== ProcessJoystick: lda SWCHA ; fetch state of both joysticks asl ; shift A bits left, R is now in carry bit bcs CheckLeft ; branch if joystick is not held right ldy ObjectX ; get position of player0 iny ; and move it right cpy #160 ; test for edge of screen bne SaveX ; save value as is if we're not at edge ldy #0 ; else wrap to left edge of screen SaveX: sty ObjectX ; save player0's new X position ldy #0 ; turn off reflect of player0, which sty REFP0 ; makes player0 image face right CheckLeft: asl ; shift A bits left, L is now in the carry bit bcs CheckDown ; branch if joystick not held left ldy ObjectX ; get the object's X position dey ; and move it left cpy #255 ; test for edge of screen bne SaveX2 ; save X if we're not at the edge ldy #159 ; else wrap to right edge SaveX2: sty ObjectX ; save player0's new X position ldy #0 ;8 ; turn on reflect of player0, which. ;Disabled for score sty REFP0 ; makes player0 image face left CheckDown: asl ; shift A bits left, D is now in the carry bit bcs CheckUp ; branch if joystick not held down ldy ObjectY ; get the object's Y position dey ; move it down cpy #255 ; test for bottom of screen bne SaveY ; save Y if we're not at the bottom ldy #ARENA_HEIGHT ; else wrap to top SaveY: sty ObjectY ; save Y CheckUp: asl ; shift A bits left, U is now in the carry bit bcs DoneWithJoystick ; branch if joystick not held up ldy ObjectY ; get the object's Y position iny ; move it up cpy #ARENA_HEIGHT ; test for top of screen bne SaveY2 ; save Y if we're not at the top ldy #0 ; else wrap to bottom SaveY2: sty ObjectY ; save Y DoneWithJoystick: rts ;=============================================================================== ; PositionObjects ; -------------- ; Updates TIA for X position of both player objects ; Updates Kernel variables for Y position of both player objects ;=============================================================================== PositionObjectsX: ldx #1 ; position players 0 and 1 POloop: lda ObjectX,x ; get the object's X position jsr PosObject ; set coarse X position and fine-tune amount dex ; DEcrement X bpl POloop ; Branch PLus so we position all objects sta WSYNC ; wait for end of scanline sta HMOVE ; Tell TIA to use fine-tune values to set final X positions rts PositionObjectsY: ; Player0Draw = ARENA_HEIGHT + PLAYER0_HEIGHT - Y_position lda #(ARENA_HEIGHT + PLAYER0_HEIGHT) sec sbc ObjectY sta Player0Draw ; Set Player0Ptr to proper value for drawing player0 lda #<(Player0Gfx + PLAYER0_HEIGHT - 1) sec sbc ObjectY sta Player0Ptr lda #>(Player0Gfx + PLAYER0_HEIGHT - 1) sbc #0 sta Player0Ptr+1 ; Set PlayerColorPtr to proper value for drawing player0 lda #<(PlayerColor + COLOR_HEIGHT - 1) sec sbc ObjectY sta PlayerColorPtr lda #>(PlayerColor + COLOR_HEIGHT - 1) sbc #0 sta PlayerColorPtr+1 ; Player1Draw = ARENA_HEIGHT + PLAYER1_HEIGHT - Y_position lda #(ARENA_HEIGHT + PLAYER1_HEIGHT) sec sbc ObjectY+1 sta Player1Draw ; Set Player1Ptr to proper value for drawing player1 lda #<(Player1Gfx + PLAYER1_HEIGHT - 1) sec sbc ObjectY+1 sta Player1Ptr lda #>(Player1Gfx + PLAYER1_HEIGHT - 1) sbc #0 sta Player1Ptr+1 ; Set Player1ColorPtr to proper value for drawing player1 lda #<(PlayerColor + COLOR_HEIGHT - 1) sec sbc ObjectY+1 sta Player1ColorPtr lda #>(PlayerColor + COLOR_HEIGHT - 1) sbc #0 sta Player1ColorPtr+1 ; Set PillPtr to proper value for drawing pills ;lda #<(CoinGfx + COIN_HEIGHT - 1) lda #<(PillRAMGfx + COIN_HEIGHT - 1) sec sbc PillY sta PillPtr ;lda #>(CoinGfx + COIN_HEIGHT - 1) lda #>(PillRAMGfx + COIN_HEIGHT - 1) sbc #0 sta PillPtr+1 ; BallDraw = ARENA_HEIGHT + BALL_HEIGHT - Y_position lda #(ARENA_HEIGHT + BALL_HEIGHT) sec sbc BallY sta BallDraw ; Missile0Draw = ARENA_HEIGHT + MISSILE_HEIGHT - Y_position lda #(ARENA_HEIGHT + MISSILE_HEIGHT) sec sbc Missile0Y sta Missile0Draw ; Missile1Draw = ARENA_HEIGHT + MISSILE_HEIGHT - Y_position lda #(ARENA_HEIGHT + MISSILE_HEIGHT) sec sbc Missile1Y sta Missile1Draw rts ;======================================== ; Kernel ; -------------- ; generate the display ;======================================== Kernel: lda #0 ldy #ARENA_HEIGHT ; init loop counter sta WSYNC sta VBLANK ; 3 3 - turn on video output ;lda BackgroundColor ; 3 6 ;sta COLUBK ; 3 9 ;111111111111111111111111111111111111111111111111111111111111111111111111111111 ;111111111111111111111111111111111111111111111111111111111111111111111111111111 ;111111111111111111111111111111111111111111111111111111111111111111111111111111 ;111111111111111111111111111111111111111111111111111111111111111111111111111111 ;jsr TestPattern ;jsr StaticDisplay jsr DrawDigit ldy #90 ; compensate for score loop dec BallDraw ; dec Missile0Draw dec Missile1Draw ;222222222222222222222222222222222222222222222222222222222222222222222222222222 ;222222222222222222222222222222222222222222222222222222222222222222222222222222 ;222222222222222222222222222222222222222222222222222222222222222222222222222222 ;222222222222222222222222222222222222222222222222222222222222222222222222222222 ldx #20 ArenaLoop2: ; 23 - worse case time to get here sta WSYNC ; 3 26 ;---------------------------- start of line 1 of the 2LK lda TopBand0,x sta PF0 lda TopBand1,x sta PF1 lda TopBand2,x sta PF2 dex lda #PLAYER0_HEIGHT-1 ; 2 2 - height of the player graphics, dcp Player0Draw ; 5 7 - Decrement Player0Draw and compare with height bcs BDoDrawGrp0 ; 2 9 - (3 10) if Carry is Set then player0 is on current scanline lda #0 ; 2 11 - otherwise use 0 to turn off player0 .byte $2C ; 4 15 - $2C = BIT with absolute addressing, trick that ; causes the lda (Player0Ptr),y to be skipped BDoDrawGrp0: ; 10 - from bcs DoDrawGRP0 lda (Player0Ptr),y ; 5 15 - load the shape for player0 sta GRP0 ; 3 18 TempDec2: ; dec PillDraw ; Can be switched to constant when bands are finalized dec BallDraw ; dec Missile0Draw dec Missile1Draw sta WSYNC ; 3 21 ;---------------------------- start of line 2 of the 2LK lda TopBand0,x sta PF0 lda TopBand1,x sta PF1 lda TopBand2,x sta PF2 dex lda #PLAYER1_HEIGHT-1 ; 2 2 - height of the player 1 graphics, subtract 1 due to starting with 0 dcp Player1Draw ; 5 7 - Decrement Player1Draw and compare with height bcs BDoDrawGrp1 ; 2 9 - (3 10) if Carry is Set, then player1 is on current scanline lda #0 ; 2 11 - otherwise use 0 to turn off player1 .byte $2C ; 4 15 - $2C = BIT with absolute addressing, trick that ; causes the lda (Player1Ptr),y to be skipped BDoDrawGrp1: ; 10 - from bcs DoDrawGrp1 lda (Player1Ptr),y ; 5 15 - load the shape for player1 sta GRP1 ; 3 18 dey ; 2 20 - update loop counter cpy #80 ; was 80 bne ArenaLoop2 ; 2 22 - 3 23 if taken lda #0 ;delete? sta COLUBK ;delete? sta NUSIZ0 sta NUSIZ1 jsr PositionObjectsX ;rts ; 6 28 ;3333333333333333333333333333333333333333333333333333333333333333333333333333333 ;3333333333333333333333333333333333333333333333333333333333333333333333333333333 ;3333333333333333333333333333333333333333333333333333333333333333333333333333333 ;3333333333333333333333333333333333333333333333333333333333333333333333333333333 ArenaLoop3: ; 23 - worse case time to get here sta WSYNC ; 3 26 ;---------------------------- start of line 1 of the 2LK lda #PLAYER0_HEIGHT-1 ; 2 2 - height of the player graphics, dcp Player0Draw ; 5 7 - Decrement Player0Draw and compare with height bcs CDoDrawGrp0 ; 2 9 - (3 10) if Carry is Set then player0 is on current scanline lda #0 ; 2 11 - otherwise use 0 to turn off player0 .byte $2C ; 4 15 - $2C = BIT with absolute addressing, trick that ; causes the lda (Player0Ptr),y to be skipped CDoDrawGrp0: ; 10 - from bcs DoDrawGRP0 lda (Player0Ptr),y ; 5 15 - load the shape for player0 sta GRP0 ; 3 18 lda (PlayerColorPtr),y ; 5 23 sta COLUP0 ; 3 26 Ball: lda #BALL_HEIGHT-1 ; 2 28 dcp BallDraw ; 5 33 ; Definitely need to fix bcs DoDrawBall ; 2 35 lda #0 ; 2 37 .byte $2C ; 4 41 DoDrawBall: ; 36 - from bcs DoDrawBall lda #2 ; 2 38 sta ENABL ; 3 41 ; dec PillDraw sta WSYNC ; 3 ;---------------------------- start of line 2 of the 2LK lda #PLAYER1_HEIGHT-1 ; 2 2 - height of the player 1 graphics, subtract 1 due to starting with 0 dcp Player1Draw ; 5 7 - Decrement Player1Draw and compare with height bcs CDoDrawGrp1 ; 2 9 - (3 10) if Carry is Set, then player1 is on current scanline lda #0 ; 2 11 - otherwise use 0 to turn off player1 .byte $2C ; 4 15 - $2C = BIT with absolute addressing, trick that ; causes the lda (Player1Ptr),y to be skipped CDoDrawGrp1: ; 10 - from bcs DoDrawGrp1 lda (Player1Ptr),y ; 5 15 - load the shape for player1 sta GRP1 ; 3 18 lda (Player1ColorPtr),y ;5 23 sta COLUP1 ; 3 26 Missile0: lda #MISSILE_HEIGHT-1 ; 2 28 dcp Missile0Draw ; 5 33 bcs DoDrawMis0 ; 2 35 lda #0 ; 2 37 .byte $2C ; 4 41 DoDrawMis0: ; 36 - from bcs DoDrawBall lda #2 ; 2 38 sta ENAM0 ; 3 41 Missile1: lda #MISSILE_HEIGHT-1 ; 2 43 dcp Missile1Draw ; 5 48 bcs DoDrawMis1 ; 2 50 lda #0 ; 2 52 .byte $2C ; 4 56 DoDrawMis1: ; 51 - from bcs DoDrawBall lda #2 ; 2 53 sta ENAM1 ; 3 56 dey ; 2 58 - update loop counter cpy #20 ; 2 60 bne ArenaLoop3 ; 2 62 - 3 if taken ;rts ; 6 ;444444444444444444444444444444444444444444444444444444444444444444444444444444 ;444444444444444444444444444444444444444444444444444444444444444444444444444444 ;444444444444444444444444444444444444444444444444444444444444444444444444444444 ;444444444444444444444444444444444444444444444444444444444444444444444444444444 ldx #3 ArenaLoop4: sta WSYNC ; 3 0 ;---------------------------- start of line 1 of the 2LK DoDrawPills: ; lda (PillPtr),y ; 5 5 sta PF2 ; 3 8 lda #PLAYER0_HEIGHT-1 ; 2 10 - height of the player graphics, dcp Player0Draw ; 5 15 - Decrement Player0Draw and compare with height bcs DDoDrawGrp0 ; 2 17 - (3 10) if Carry is Set then player0 is on current scanline lda #0 ; 2 19 - otherwise use 0 to turn off player0 .byte $2C ; 4 23 - $2C = BIT with absolute addressing, trick that ; causes the lda (Player0Ptr),y to be skipped DDoDrawGrp0: ; 18 - from bcs DoDrawGRP0 lda (Player0Ptr),y ; 5 23 - load the shape for player0 sta GRP0 ; 3 26 lda (PlayerColorPtr),y ; 5 31 sta COLUP0 ; 3 34 lda CoinColor,x ; 3 37 sta COLUPF ; 3 40 nop ; 2 42 nop ; 2 44 nop ; 2 46 nop ; 2 48 nop ; 2 42 nop ; 2 44 nop ; 2 46 nop ; 2 48 nop nop nop nop lda #PF_COLOR ; 2 50 sta COLUPF ; 2 52 dex sta WSYNC ; 3 ;---------------------------- start of line 2 of the 2LK lda #PLAYER1_HEIGHT-1 ; 2 2 - height of the player 1 graphics, subtract 1 due to starting with 0 dcp Player1Draw ; 5 7 - Decrement Player1Draw and compare with height bcs DDoDrawGrp1 ; 2 9 - (3 10) if Carry is Set, then player1 is on current scanline lda #0 ; 2 11 - otherwise use 0 to turn off player1 .byte $2C ; 4 15 - $2C = BIT with absolute addressing, trick that ; causes the lda (Player1Ptr),y to be skipped DDoDrawGrp1: ; 10 - from bcs DoDrawGrp1 lda (Player1Ptr),y ; 5 15 - load the shape for player1 sta GRP1 ; 3 18 lda (Player1ColorPtr),y ;5 23 sta COLUP1 ; 3 26 lda CoinColor,x ; 3 29 sta COLUPF ; 3 32 nop ; 2 34 nop ; 2 36 nop ; 2 38 nop ; 2 40 nop ; 2 42 nop ; 2 44 nop ; 2 46 nop ; 2 48 nop ; 2 50 nop ; 2 52 ; nop ; 2 54 ; nop ; 2 56 dex ; 2 63 txa ; 2 65 and #%00000011 ; 2 67 tax ; 2 69 lda #PF_COLOR ; 2 58 sta COLUPF ; 3 61 dey ; 2 71 - update loop counter cpy #10 ; 2 73 bne ArenaLoop4 ; 2 75 - 3 76 if taken ;5555555555555555555555555555555555555555555555555555555555555555555555555555555 ;5555555555555555555555555555555555555555555555555555555555555555555555555555555 ;5555555555555555555555555555555555555555555555555555555555555555555555555555555 ;5555555555555555555555555555555555555555555555555555555555555555555555555555555 ldx #0 ArenaLoop5: ; 23 - worse case time to get here sta WSYNC ; 3 26 ;---------------------------- start of line 1 of the 2LK lda TopBand0,x sta PF0 lda TopBand1,x sta PF1 lda TopBand2,x sta PF2 inx lda #PLAYER0_HEIGHT-1 ; 2 2 - height of the player graphics, dcp Player0Draw ; 5 7 - Decrement Player0Draw and compare with height bcs EDoDrawGrp0 ; 2 9 - (3 10) if Carry is Set then player0 is on current scanline lda #0 ; 2 11 - otherwise use 0 to turn off player0 .byte $2C ; 4 15 - $2C = BIT with absolute addressing, trick that ; causes the lda (Player0Ptr),y to be skipped EDoDrawGrp0: ; 10 - from bcs DoDrawGRP0 lda (Player0Ptr),y ; 5 15 - load the shape for player0 sta GRP0 ; 3 18 sta WSYNC ; 3 21 ;---------------------------- start of line 2 of the 2LK lda TopBand0,x sta PF0 lda TopBand1,x sta PF1 lda TopBand2,x sta PF2 inx lda #PLAYER1_HEIGHT-1 ; 2 2 - height of the player 1 graphics, subtract 1 due to starting with 0 dcp Player1Draw ; 5 7 - Decrement Player1Draw and compare with height bcs EDoDrawGrp1 ; 2 9 - (3 10) if Carry is Set, then player1 is on current scanline lda #0 ; 2 11 - otherwise use 0 to turn off player1 .byte $2C ; 4 15 - $2C = BIT with absolute addressing, trick that ; causes the lda (Player1Ptr),y to be skipped EDoDrawGrp1: ; 10 - from bcs DoDrawGrp1 lda (Player1Ptr),y ; 5 15 - load the shape for player1 sta GRP1 ; 3 18 dey ; 2 20 - update loop counter bne ArenaLoop5 ; 2 22 - 3 23 if taken rts ; 6 28 ;======================================== ; ; Overscan ; ;======================================== OverScan: sta WSYNC ; Wait for SYNC (start of next scanline) lda #2 ; LoaD Accumulator with 2 sta VBLANK ; STore Accumulator to VBLANK, D1=1 turns image output off lda #22 sta TIM64T ; set timer for end of Overscan jsr ProcessCollisions FrameCount: inc FrameCounter OSwait: sta WSYNC bit TIMINT bpl OSwait ; wait for the timer to denote end of Overscan rts ;======================================== ; Process Collisions ; -------------- ; If player0 touchs player 1 then change the background color and reposition the player 1 ;======================================== ProcessCollisions: bit CXPPMM ; check to see if player0 collided with player1 ; (also used to check if missile collided with missile) bpl ExitPC NewX: jsr Random ; get a random value between 0-255 cmp #152 ; compare it with 152 bcs NewX ; get a new random number if >= 152 sta ObjectX+1 ; save player 1's new X location NewY: jsr Random ; get a random value between 0-255 cmp #ARENA_HEIGHT-PLAYER1_HEIGHT bcs NewY ; get a new random number if Y position is offscreen adc #PLAYER1_HEIGHT ; adjust value so player 1 is fully onscreen sta ObjectY+1 ; save Player 1's new Y location ExitPC: sta CXCLR ; clear collision detection latches rts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Score Display ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DrawDigit: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; top dash ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; sta WSYNC lda #$8A sta COLUP0 sta COLUP1 lda #3 ; 3 copies close sta NUSIZ0 sta NUSIZ1 sta WSYNC sta WSYNC ;--------------------------------------- lda #SHAPE_SIDES sta GRP0 asl sta GRP1 nop $EA nop nop nop sta RESP0 sta RESP1 sta RESP0 sta RESP1 nop nop nop nop nop nop sta RESP0 sta RESP1 sta RESP0 sta RESP1 nop $EA nop nop nop nop nop nop ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; upper sides ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ldy #6 .loopUpperDigit: nop nop ;--------------------------------------- lda #SHAPE_DASH sta GRP1 lsr sta GRP0 nop $EA nop nop nop sta RESP0 sta RESP1 sta RESP0 sta RESP1 nop nop nop nop nop nop sta RESP0 sta RESP1 sta RESP0 sta RESP1 nop nop nop nop nop nop dey bne .loopUpperDigit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; middle dash ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; nop $EA nop ;--------------------------------------- lda #SHAPE_SIDES sta GRP0 asl sta GRP1 nop $EA nop nop nop sta RESP0 sta RESP1 sta RESP0 sta RESP1 nop nop nop nop nop nop sta RESP0 sta RESP1 sta RESP0 sta RESP1 nop $EA nop nop nop nop nop nop ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; lower sides ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ldy #6 ;should be 6 .loopLowerDigit: nop nop ;--------------------------------------- lda #SHAPE_DASH sta GRP1 lsr sta GRP0 nop $EA nop nop nop sta RESP0 sta RESP1 sta RESP0 sta RESP1 nop nop nop nop nop nop sta RESP0 sta RESP1 sta RESP0 sta RESP1 nop nop nop nop nop nop dey bne .loopLowerDigit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; bottom dash ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; nop $EA nop ;--------------------------------------- lda #SHAPE_SIDES sta GRP0 asl sta GRP1 nop $EA nop nop nop sta RESP0 sta RESP1 sta RESP0 sta RESP1 nop nop nop nop nop nop sta RESP0 sta RESP1 sta RESP0 sta RESP1 nop $EA nop nop nop nop nop nop sta WSYNC ;--------------------------------------- lda #0 ; clear all sta GRP0 sta GRP1 sta WSYNC sta WSYNC sta WSYNC rts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ;Static Display ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; StaticDisplay: ; 6 from the jsr ldy #10 ; 2 8 lda #$0C ; 2 10 sta COLUPF ; 3 13 ;lda #0 ;sta CTRLPF SD: sta WSYNC ; 3 16 lda Rand8 ; 3 19 sta PF0 ; 3 22 eor #$FF ; 2 24 sta PF1 ; 3 37 eor #$FF ; 3 40 sta PF2 ; 3 43 ;and #%00111000 background color filter ;sta COLUBK jsr Random ; 24 67 ;dec BallDraw ; ;dec Missile0Draw ;dec Missile1Draw sta WSYNC ; 3 70 lda Rand8 ; 3 3 sta PF0 ; 3 6 sta PF1 ; 3 9 sta PF2 ; 3 12 jsr Random ; 24 36 dey ; 2 38 bne SD ; 2,3 40 not taken lda #PF_COLOR ; 2 42 sta COLUPF ; 3 45 lda #0 ; 2 47 sta COLUBK ; 3 50 nop nop nop nop sta PF2 ; 3 sta PF1 ; 3 sta PF0 ; 3 rts ; 6 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ;Test Pattern Display ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; TestPattern: ; 6 from the jsr ldy #19 ; 2 8 lda #PF_COLOR sta COLUPF lda #%11111111 sta PF0 TP: sta WSYNC nop lda #$34 ; 2 10 sta COLUBK ; 3 13 ror ; 2 15 sta COLUBK ; 3 18 ror ; 2 20 sta COLUBK ; 3 23 ror ; 2 25 sta COLUBK ; 3 28 ror ; 2 30 sta COLUBK ; 3 33 ror ; 2 35 sta COLUBK ; 3 38 ror ; 2 40 sta COLUBK ; 3 43 ror ; 2 45 sta COLUBK ; 3 48 ror ; 2 50 sta COLUBK ; 3 53 ror ; 2 55 sta COLUBK ; 3 58 ror ; 2 60 sta COLUBK ; 3 63 ror ; 2 65 sta COLUBK ; 3 68 lda #0 ; 2 70 sta COLUBK ; 3 73 ;sta WSYNC dey ; 2 bne TP ; 2,3 40 not taken rts ; 6 ;======================================== ; Graphics ; ;======================================== align 256 Player0Gfx: .byte %00111100 .byte %00000000 .byte %00111100 .byte %00111100 .byte %00111100 .byte %00111100 .byte %10111101 .byte %10111101 .byte %11111111 .byte %10100101 .byte %10111101 .byte %00011000 .byte %00011000 PLAYER0_HEIGHT = * - Player0Gfx Player1Gfx: .byte %00111100 .byte %00000000 .byte %00111100 .byte %00111100 .byte %00111100 .byte %00111100 .byte %10111101 .byte %10111101 .byte %11111111 .byte %10100101 .byte %10111101 .byte %00011000 .byte %00011000 PLAYER1_HEIGHT = * - Player1Gfx CoinGfx: ; .byte %11111111 ; .byte %00000000 ; .byte %10000001 ; .byte %00000000 ; .byte %10000001 ; .byte %00000000 .byte %10000001 ; Not currently used .byte %00000000 .byte %10000001 .byte %00000000 .byte %10000001 .byte %11111111 COIN_HEIGHT = * - CoinGfx PlayerColor: .byte FOOT_COLOR .byte LEG_COLOR .byte LEG_COLOR .byte LEG_COLOR .byte LEG_COLOR .byte LEG_COLOR .byte BODY_COLOR .byte BODY_COLOR .byte BODY_COLOR .byte BODY_COLOR .byte BODY_COLOR .byte HEAD_COLOR .byte HAIR_COLOR COLOR_HEIGHT = * - PlayerColor CoinColor: .byte $50 .byte $46 .byte $50 .byte $00 ;Bookmark- Rolling Cleanup Edit TopBand0: ;.byte %00000000 ;Not necessary .byte %10000000 ; Last Line .byte %10000000 .byte %10000000 .byte %10000000 .byte %10000000 .byte %10000000 .byte %10000000 .byte %10000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000;added .byte %00000000 .byte %11111111 .byte %01000100 .byte %10101010 .byte %00010001 .byte %11111111 TopBand1: .byte %00000000 .byte %00000000 .byte %11101111 .byte %11111111 .byte %11111111 .byte %11111111 .byte %11111111 .byte %11111111 .byte %11111111 .byte %00111000 .byte %00010000 .byte %00010000 .byte %00000000 .byte %00010000 .byte %00000000 .byte %00010000 .byte %00000000 .byte %00010000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %11111111 .byte %01000100 .byte %10101010 .byte %00010001 .byte %11111111 TopBand2: .byte %00000000 .byte %00000000 .byte %11110111 .byte %11111111 .byte %11111111 .byte %11111111 .byte %11111111 .byte %11111111 .byte %11111111 .byte %00011100 .byte %00001000 .byte %00001000 .byte %00000000 .byte %00001000 .byte %00000000 .byte %00001000 .byte %00000000 .byte %00001000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %11111111 .byte %01000100 .byte %10101010 .byte %00010001 .byte %11111111 ;added extra ;======================================== ; Define End of Cartridge ;======================================== ORG $FFFA ; set address to 6507 Interrupt Vectors .WORD InitSystem ; NMI .WORD InitSystem ; RESET .WORD InitSystem ; IRQ