yllawwally Posted February 3, 2010 Share Posted February 3, 2010 I'm trying to learn 2600 programming. I took the face example from one of the tutorials here. I modified it to have alternate pics of the player every 8 screens. So that I could do a walking animation. However the top line seems to be a copy of the bottom line. I can't see what I'm doing wrong. I was hoping someone could help me find my error. ; move a happy face with the joystick by Kirk Israel ; (with a can't'dodge'em line sweeping across the screen) processor 6502 include vcs.h org $F000 YPosFromBot = $80; VisiblePlayerLine = $81; PICS = $93; PICSNUM = $94; ;generic start up stuff... Start SEI CLD LDX #$FF TXS LDA #0 STA PICSNUM ClearMem STA 0,X DEX BNE ClearMem LDA #$00 ;start with a black background STA COLUBK LDA #$1C ;lets go for bright yellow, the traditional color for happyfaces STA COLUP0 ;Setting some variables... LDA #80 STA YPosFromBot ;Initial Y Position ;; Let's set up the sweeping line. as Missile 1 LDA #2 STA ENAM1 ;enable it LDA #33 STA COLUP1 ;color it LDA #$20 STA NUSIZ1 ;make it quadwidth (not so thin, that) LDA #$F0 ; -1 in the left nibble STA HMM1 ; of HMM1 sets it to moving ;VSYNC time MainLoop LDA #2 STA VSYNC STA WSYNC STA WSYNC STA WSYNC LDA #43 STA TIM64T LDA #0 STA VSYNC ;Main Computations; check down, up, left, right ;general idea is to do a BIT compare to see if ;a certain direction is pressed, and skip the value ;change if so ; ;Not the most effecient code, but gets the job done, ;including diagonal movement ; ; for up and down, we INC or DEC ; the Y Position LDA #010000 ;Down? BIT SWCHA BNE SkipMoveDown INC YPosFromBot SkipMoveDown LDA #100000 ;Up? BIT SWCHA BNE SkipMoveUp DEC YPosFromBot SkipMoveUp ; for left and right, we're gonna ; set the horizontal speed, and then do ; a single HMOVE. We'll use X to hold the ; horizontal speed, then store it in the ; appropriate register ;assum horiz speed will be zero LDX #0 LDA #%01000000 ;Left? BIT SWCHA BNE SkipMoveLeft LDX #$10 ;a 1 in the left nibble means go left ;; moving left, so we need the mirror image LDA #001000 ;a 1 in D3 of REFP0 says make it mirror STA REFP0 SkipMoveLeft LDA #%10000000 ;Right? BIT SWCHA BNE SkipMoveRight LDX #$F0 ;a -1 in the left nibble means go right... ;; moving right, cancel any mirrorimage LDA #000000 STA REFP0 SkipMoveRight STX HMP0 ;set the move for player 0, not the missile like last time... ; see if player and missile collide, and change the background color if so ;just a review...comparisons of numbers always seem a little backwards to me, ;since it's easier to load up the accumulator with the test value, and then ;compare that value to what's in the register we're interested. ;in this case, we want to see if D7 of CXM1P (meaning Player 0 hit ; missile 1) is on. So we put 10000000 into the Accumulator, ;then use BIT to compare it to the value in CXM1P LDA #%10000000 BIT CXM1P BEQ NoCollision ;skip if not hitting... LDA YPosFromBot ;must be a hit! load in the YPos... STA COLUBK ;and store as the bgcolor NoCollision STA CXCLR ;reset the collision detection for next time INC PICSNUM LDA PICSNUM AND #15 ;every 8th screen swap to next image of player CMP #8 BEQ PICSET4 JMP PICSET3 PICSET4 LDA PICS CMP #8 BEQ PICSET LDA #8 JMP PICSET2 PICSET LDA #0 PICSET2 STA PICS PICSET3 WaitForVblankEnd LDA INTIM BNE WaitForVblankEnd LDY #191 STA WSYNC STA HMOVE STA VBLANK ;main scanline loop... PreScanLoop ;set player graphic to all zeros for this line, and then see if ;we need to load it with graphic data LDA #0 STA GRP0 ScanLoop STA WSYNC ; here the idea is that VisiblePlayerLine ; is zero if the line isn't being drawn now, ; otherwise it's however many lines we have to go CheckActivatePlayer CPY YPosFromBot BNE SkipActivatePlayer LDA #8 STA VisiblePlayerLine SkipActivatePlayer ;set player graphic to all zeros for this line, and then see if ;we need to load it with graphic data LDA #0 STA GRP0 ; ;if the VisiblePlayerLine is non zero, ;we're drawing it now! ; LDX VisiblePlayerLine ;check the visible player line... BEQ FinishPlayer ;skip the drawing if its zero... IsPlayerOn TXA ;Transfers the byte in the X Register to the Accumulator ADC PICS ;add value of pics to Accumulator TAX ;Transfers the byte in the Accumulator to the X Register LDA BigHeadGraphic-1,X ;shift to change which pic were showing ; ORA #1 ;creates a shield STA GRP0 ;put that line as player graphic DEC VisiblePlayerLine ;and decrement the line count FinishPlayer DEY BNE ScanLoop LDA #2 STA WSYNC STA VBLANK LDX #24 OverScanWait STA WSYNC DEX BNE OverScanWait JMP MainLoop ; here's the actual graphic! If you squint you can see its ; upsidedown smiling self BigHeadGraphic .byte #010100 .byte #010100 .byte #011000 .byte #011000 .byte #%01111110 .byte #010000 .byte #011000 .byte #011000 .byte #010010 .byte #010100 .byte #011000 .byte #011000 .byte #%01111110 .byte #010000 .byte #011000 .byte #011000 .byte #010100 .byte #010100 .byte #011000 .byte #011000 .byte #%01111110 .byte #010000 .byte #011000 .byte #011000 .byte #010010 .byte #010100 .byte #011000 .byte #011000 .byte #%01111110 .byte #010000 .byte #011000 .byte #011000 org $FFFC .word Start .word Start Quote Link to comment Share on other sites More sharing options...
e1will Posted February 4, 2010 Share Posted February 4, 2010 You're setting the "first" GRP0 line AFTER you turn the screen on, so whatever was in GRP0 from the last pass gets drawn at the top. If you put the "LDA #0" and "STA GRP0" lines BEFORE the STA WSYNC/STA HMOVE/STA VBLANK group, that should clear it out. Hope this helps. --Will Quote Link to comment Share on other sites More sharing options...
yllawwally Posted February 5, 2010 Author Share Posted February 5, 2010 Sorry I mischaracterized the issue. Really the problem was the first line of the player was a copy of the previous last line. However that wasn't what was happening. I used ADC to add a counter for each step. I didn't realize that if the carry flag was set an additional 1 would be added. So I placed a CLC before adc, which has fixed it. Quote Link to comment Share on other sites More sharing options...
yllawwally Posted February 11, 2010 Author Share Posted February 11, 2010 I seem to now have a problem using too many cycles. When the player and enemy are on the same lines, they get twice as tall. It seems that I should have cycles to spare. What am I doing wrong? processor 6502 include vcs.h org $F000 ;Variables ------ YPosFromBot = $80; VisiblePlayerLine = $81; PICS = $82; ROLLING_COUNTER = $83; Graphics_Buffer = $84 YPosFromBotE1 = $85; VisibleEnemyLine = $86; VisibleEnemyLineCurrent = $87; EnemyLineBuffer = $88; VisiblePlayerLineCurrent = $90; ; Constants ------ playerheight ds #8; enemyheight ds #8; ;generic start up stuff... Start SEI CLD LDX #$FF TXS LDA #0 STA ROLLING_COUNTER STA PICS STA EnemyLineBuffer ClearMem STA 0,X DEX BNE ClearMem LDA #$00 ;start with a black background STA COLUBK LDA #$1C ;lets go for bright yellow, the traditional color for happyfaces STA COLUP0 ;Setting some variables... LDA #80 STA YPosFromBot ;Initial Y Position STA YPosFromBotE1 ;; Let's set up the sweeping line. as Missile 1 LDA #2 STA ENAM1 ;enable it LDA #33 STA COLUP1 ;color it LDA #$10 STA NUSIZ1 ;make it quadwidth (not so thin, that) LDA #000000 ; set to not move STA HMM1 ; of HMM1 sets it to moving ;VSYNC time MainLoop LDA #2 STA VSYNC STA WSYNC ; for up and down, we INC or DEC ; the Y Position LDA #010000 ;Down? BIT SWCHA BNE SkipMoveDown INC YPosFromBot INC YPosFromBotE1 INC YPosFromBotE1 SkipMoveDown LDA #100000 ;Up? BIT SWCHA BNE SkipMoveUp DEC YPosFromBot DEC YPosFromBotE1 DEC YPosFromBotE1 SkipMoveUp ; for left and right, we're gonna ; set the horizontal speed, and then do ; a single HMOVE. We'll use X to hold the ; horizontal speed, then store it in the ; appropriate register ;assum horiz speed will be zero LDX #0 LDA #%01000000 ;Left? BIT SWCHA BNE SkipMoveLeft LDX #$10 ;a 1 in the left nibble means go left ;; moving left, so we need the mirror image LDA #001000 ;a 1 in D3 of REFP0 says make it mirror STA REFP0 SkipMoveLeft LDA #%10000000 ;Right? BIT SWCHA BNE SkipMoveRight LDX #$F0 ;a -1 in the left nibble means go right... ;; moving right, cancel any mirrorimage LDA #000000 STA REFP0 SkipMoveRight STX HMP0 ;set the move for player 0, not the missile like last time... ; see if player and missile collide, and change the background color if so ;just a review...comparisons of numbers always seem a little backwards to me, ;since it's easier to load up the accumulator with the test value, and then ;compare that value to what's in the register we're interested. ;in this case, we want to see if D7 of CXM1P (meaning Player 0 hit ; missile 1) is on. So we put 10000000 into the Accumulator, ;then use BIT to compare it to the value in CXM1P LDA #%10000000 BIT CXM1P BEQ NoCollision ;skip if not hitting... LDA YPosFromBot ;must be a hit! load in the YPos... STA COLUBK ;and store as the bgcolor NoCollision STA CXCLR ;reset the collision detection for next time STA WSYNC ;////////////////////////////////////////////// ;setup pic animations ---------------------------------------------- INC ROLLING_COUNTER LDA ROLLING_COUNTER AND #15 ;every 8th screen swap to next image of player CMP #8 BEQ PICSET4 JMP PICSET3 PICSET4 LDA PICS CMP #8 BEQ PICSET LDA #8 JMP PICSET2 PICSET LDA #0 PICSET2 STA PICS PICSET3 LDA ROLLING_COUNTER AND #25 ;how often to move enemy, larger number is slower CMP #8 BEQ PICSET5 LDA #001111 ; +1 in the left nibble JMP PICSET6 PICSET5 LDA #011111 ; 0 in the left nibble PICSET6 STA HMP1 ; of HMP1 sets it to moving the enemy LDA #8 CLC ADC PICS ;add value of pics to Accumulator STA VisibleEnemyLineCurrent LDA #8 CLC ADC PICS ;add value of pics to Accumulator STA VisiblePlayerLineCurrent ;setup pic animations ---------------------------------------------- STA WSYNC ;////////////////////////////////////////////// LDA #43 STA TIM64T LDA #0 STA VSYNC ;------------------------- ;------------------------- WaitForVblankEnd LDA INTIM BNE WaitForVblankEnd LDY #191 STA WSYNC STA HMOVE STA VBLANK ;main scanline loop... PreScanLoop LDA #0 ScanLoop ;start of kernal +++++++++++++++++++++++ STA GRP0 ;put that line as player graphic 0 ;2 cycles AFTERPLAYERDRAW LDA EnemyLineBuffer ;2 cycles STA GRP1 ; put player 1 into grp1 2 cycles AfterEnemyDraw DEY ;count down number of scan lines 1 cycles LDA #8 ;2 cycles CheckActivatePlayer CPY YPosFromBot ;2 cycles BNE SkipActivatePlayer ;2 cycles STA VisiblePlayerLine ;2 cycles SkipActivatePlayer CheckActivateEnemy CPY YPosFromBotE1 ;2 cycles BNE SkipActivateEnemy ;2 cycles STA VisibleEnemyLine ;2 cycles SkipActivateEnemy LDA #0 ;2 cycles STA EnemyLineBuffer ;2 cycles LDA VisibleEnemyLine ;check the visible enemy line... 2 cycles BEQ FinishEnemy ;skip the drawing if its zero... 2 cycles IsEnemyOn LDX VisibleEnemyLineCurrent ;2 cycles LDA EnemyGraphics-1,x ;2 cycles STA EnemyLineBuffer DEC VisibleEnemyLine ;2 cycles DEC VisibleEnemyLineCurrent ;2 cycles FinishEnemy LDA VisiblePlayerLine ;check the visible player line... 2 cycles BEQ FinishPlayer ;skip the drawing if its zero... 2 cycles IsPlayerOn LDX VisiblePlayerLineCurrent ;2 cycles LDA MainPlayerGraphics-1,x ;shift to change which pic were showing 2 cycles ; ORA #1 ;creates a shield DEC VisiblePlayerLineCurrent ;2 cycles DEC VisiblePlayerLine ;2 cycles FinishPlayer CPY #0 ;2 cycles STA WSYNC ;2 cycles BNE ScanLoop ;2 cycles EndScanLoop ;end of kernal +++++++++++++++++ STA WSYNC STA VBLANK LDX #24 OverScanWait STA WSYNC DEX BNE OverScanWait JMP MainLoop MainPlayerGraphics .byte #010100 .byte #010100 .byte #011000 .byte #011000 .byte #%01111110 .byte #010000 .byte #111000 .byte #111000 .byte #010010 .byte #010100 .byte #011000 .byte #011000 .byte #%01111110 .byte #010000 .byte #111000 .byte #111000 EnemyGraphics .byte #%01111000 .byte #%10000100 .byte #001000 .byte #010000 .byte #010000 .byte #010000 .byte #111000 .byte #111000 .byte #%01111000 .byte #%01001000 .byte #010000 .byte #100000 .byte #100000 .byte #100000 .byte #%01110000 .byte #%01110000 org $FFFC .word Start .word Start Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted February 11, 2010 Share Posted February 11, 2010 (edited) You are using too many cycles...and you seem to be confused regarding how many cycles are taken by the various instructions / addressing modes. There are NO instructions that only take a single cycle (DEY above should be 2 cycles). Most of the LDAs and STA's above are 3 cycles (not 2). The DEC's are 5 cycles (again, not 2). Branches are 2 cycles if not taken, but 3 cycles if they are. Worst-case scenario...which is when the program takes the long path (i.e. no branches taken to skip ahead)...is 84 cycles. Edited February 11, 2010 by Nukey Shay Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted February 12, 2010 Share Posted February 12, 2010 Correction...89 cycles worst-case in the scanline loop Quote Link to comment Share on other sites More sharing options...
yllawwally Posted February 12, 2010 Author Share Posted February 12, 2010 Thank you very much. I was using number of bytes as the cycle time. Which is why I was totally confused. Quote Link to comment Share on other sites More sharing options...
yllawwally Posted March 18, 2010 Author Share Posted March 18, 2010 I'm trying to convert this code to use skipdraw. However so far the graphics aren't correct. What am I doing wrong? ; move a happy face with the joystick by Kirk Israel ; (with a can't'dodge'em line sweeping across the screen) processor 6502 include vcs.h org $F000 ;Variables ------ YPosFromBot = $80; VisiblePlayerLine = $81; PICS = $82; ROLLING_COUNTER = $83; Graphics_Buffer = $84 YPosFromBotE1 = $85; VisibleEnemyLine = $86; VisibleEnemyLineCurrent = $87; EnemyLineBuffer = $88; VisiblePlayerLineCurrent = $90; BG_0 = $91; BG_1 = $92; BG_2 = $93; ; Constants ------ playerheight ds #8; ;generic start up stuff... Start SEI CLD LDX #$FF TXS LDA #0 STA ROLLING_COUNTER STA PICS STA EnemyLineBuffer ClearMem STA 0,X DEX BNE ClearMem LDA #$00 ;start with a black background STA COLUBK LDA #$1C ;lets go for bright yellow, the traditional color for happyfaces STA COLUP0 ;Setting some variables... LDA #80 STA YPosFromBot ;Initial Y Position STA YPosFromBotE1 LDA #010001 ; 2 cycles STA BG_0 ; 3 cycles STA BG_1 ; 3 cycles STA BG_2 ; 3 cycles ;; Let's set up the sweeping line. as Missile 1 LDA #2 ; STA ENAM1 ;enable it LDA #33 STA COLUP0 ;color it STA COLUP1 ;color it LDA #$10 ; STA NUSIZ0 ;make it quadwidth (not so thin, that) STA NUSIZ1 ;make it quadwidth (not so thin, that) LDA #000000 ; set to not move STA HMM1 ; of HMM1 sets it to moving ;VSYNC time MainLoop ;+++++++++++++++++++++++++++The start of a new screen LDA #0 STA GRP0 STA GRP1 STA PF0 STA PF1 STA PF2 LDA #2 STA VSYNC STA WSYNC ; for up and down, we INC or DEC ; the Y Position LDA #010000 ;Down? BIT SWCHA BNE SkipMoveDown INC YPosFromBot INC YPosFromBotE1 INC YPosFromBotE1 SkipMoveDown LDA #100000 ;Up? BIT SWCHA BNE SkipMoveUp DEC YPosFromBot DEC YPosFromBotE1 DEC YPosFromBotE1 SkipMoveUp ; for left and right, we're gonna ; set the horizontal speed, and then do ; a single HMOVE. We'll use X to hold the ; horizontal speed, then store it in the ; appropriate register ;assum horiz speed will be zero LDX #0 LDA #%01000000 ;Left? BIT SWCHA BNE SkipMoveLeft LDX #$10 ;a 1 in the left nibble means go left ;; moving left, so we need the mirror image LDA #001000 ;a 1 in D3 of REFP0 says make it mirror STA REFP0 STA REFP1 SkipMoveLeft LDA #%10000000 ;Right? BIT SWCHA BNE SkipMoveRight LDX #$F0 ;a -1 in the left nibble means go right... ;; moving right, cancel any mirrorimage LDA #000000 STA REFP0 STA REFP1 SkipMoveRight STX HMP0 ;set the move for player 0, not the missile like last time... STX HMP1 ;set the move for player 0, not the missile like last time... ; see if player and missile collide, and change the background color if so ;just a review...comparisons of numbers always seem a little backwards to me, ;since it's easier to load up the accumulator with the test value, and then ;compare that value to what's in the register we're interested. ;in this case, we want to see if D7 of CXM1P (meaning Player 0 hit ; missile 1) is on. So we put 10000000 into the Accumulator, ;then use BIT to compare it to the value in CXM1P LDA #%10000000 BIT CXM1P BEQ NoCollision ;skip if not hitting... LDA YPosFromBot ;must be a hit! load in the YPos... STA COLUBK ;and store as the bgcolor NoCollision STA CXCLR ;reset the collision detection for next time STA WSYNC ;////////////////////////////////////////////// ;setup pic animations ---------------------------------------------- INC ROLLING_COUNTER LDA ROLLING_COUNTER AND #15 ;every 8th screen swap to next image of player CMP #8 BEQ PICSET4 JMP PICSET3 PICSET4 LDA PICS CMP #8 BEQ PICSET LDA #8 JMP PICSET2 PICSET LDA #0 PICSET2 STA PICS PICSET3 LDA ROLLING_COUNTER AND #25 ;how often to move enemy, larger number is slower CMP #8 BEQ PICSET5 LDA #001111 ; +1 in the left nibble JMP PICSET6 PICSET5 LDA #011111 ; 0 in the left nibble PICSET6 STA HMP1 ; of HMP1 sets it to moving the enemy LDA #8 CLC ADC PICS ;add value of pics to Accumulator STA VisibleEnemyLineCurrent LDA #8 CLC ADC PICS ;add value of pics to Accumulator STA VisiblePlayerLineCurrent ;setup pic animations ---------------------------------------------- STA WSYNC ;////////////////////////////////////////////// LDA #43 STA TIM64T LDA #0 STA VSYNC ;------------------------- setup backgrounds 20 pixels accross LDA #255 ; 3 cycles STA PF0 ; 3 cycles STA PF1 ; 3 cycles STA PF2 ; 3 cycles ;------------------------- WaitForVblankEnd LDA INTIM BNE WaitForVblankEnd LDY #4 ; was 191 STA WSYNC STA HMOVE STA VBLANK ;main scanline loop... PreScanLoop ScanLoop1 ;start of kernal +++++++++++++++++++++++ for skyline LDA PFCOLOR-1,Y ; 4 cycles STA COLUBK ;and store as the bgcolor ; 3 cycles LDA PFData0-1,Y ; 4 cycles STA PF0 ; 3 cycles LDA PFData1-1,Y ; 4 cycles STA RESM0 ; 3 cycles places left scan line leftmost STA PF1 ; 3 cycles LDA PFData2-1,Y ; 4 cycles STA PF2 ; 3 cycles LDA #0 ;2 cycles =30 STA GRP1 ; put player 1 into grp1 3 cycles STA GRP0 ;put that line as player graphic 0 ;3 cycles =28 DEY ;count down number of scan lines 2 cycles =71 STA WSYNC ;3 cycles =74 BNE ScanLoop1 ;2 cycles =76 EndScanLoop1 ;end of kernal +++++++++++++++++++++++ for skyline LDA #100; STA COLUBK ;and store as the bgcolor LDY #186 ; was 191 was 186 LDA #0 STA PF0 ; 3 cycles STA PF1 ; 3 cycles STA PF2 ; 3 cycles LDA #%11100011 ;The last 3 bits control number and size of players ;the firs 3 bits control missle size STA NUSIZ0 STA NUSIZ1 STA WSYNC ;3 cycles ScanLoop ;start of kernal +++++++++++++++++++++++ for players ;-------------------------- ; SPRITE DRAW tya ; 2 Transfers the byte in the Y Register to the Accumulator. sec ; 2 Sets the carry (C) flag (in the processor Status Register byte). sbc SpriteEnd ; 3 Subtracts a byte in memory from the byte in the Accumulator, and "borrows" if necessary. adc #8 ; 2 Adds byte in memory to the byte in the Accumulator, plus the carry flag if set. bcs .Draw ; 2(3) Branches up to 127 bytes forward or 128 bytes backward from its own address if the carry flag is set. nop ; 2 Wait nop ; 2 Wait sec ; 2 Sets the carry (C) flag bcs .skipDraw ; 3 Branches up to 127 bytes forward or 128 bytes backward from its own address if the carry flag is set. .Draw lda MainPlayerGraphics,y ; 5 Loads the Accumulator with a byte from memory. sta GRP0 ; 3 Stores the byte in the Accumulator into memory. .skipDraw ;-->18 cycles used ;-------------------------- STA GRP0 ;set player graphics 3 cycles STA GRP1 ;set player graphics 3 cycles DEY ;count down number of scan lines 2 cycles = STA WSYNC ;3 cycles = BNE ScanLoop ;2 cycles = EndScanLoop ;end of kernal +++++++++++++++++ for players STA WSYNC STA VBLANK LDX #24 OverScanWait STA WSYNC DEX BNE OverScanWait JMP MainLoop MainPlayerGraphics .byte #010100 .byte #010100 .byte #011000 .byte #011000 .byte #%01111110 .byte #010000 .byte #111000 .byte #111000 SpriteEnd .byte #100010 .byte #100100 .byte #101000 .byte #011000 .byte #%01111110 .byte #010000 .byte #111000 .byte #111000 EnemyGraphics .byte #%01111000 .byte #%10000100 .byte #001000 .byte #010000 .byte #010000 .byte #010000 .byte #111000 .byte #111000 .byte #%01111000 .byte #%01001000 .byte #010000 .byte #100000 .byte #100000 .byte #100000 .byte #%01110000 .byte #%01110000 PFData0 .byte #001111 .byte #011111 .byte #%01111111 .byte #%11111111 PFData1 .byte #000000 .byte #001110 .byte #111111 .byte #%01111111 PFData2 .byte #000000 .byte #011000 .byte #%10111100 .byte #%11111111 PFCOLOR .byte #$5F .byte #$5D .byte #$5B .byte #$59 org $FFFC .word Start .word Start Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.