; 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
Page 1 of 1
sprite display not as expected
|
Posted Wed Feb 3, 2010 3:32 PM
|
|
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.
|
|
|
Posted Wed Feb 3, 2010 9:03 PM
|
|
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 |
|
|
Posted Fri Feb 5, 2010 10:38 AM
|
|
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.
|
|
|
Posted Thu Feb 11, 2010 3:29 PM
|
|
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 |
|
|
Posted Thu Feb 11, 2010 5:29 PM
|
|
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. This post has been edited by Nukey Shay: Thu Feb 11, 2010 5:45 PM |
|
Page 1 of 1

Sign In
Register
Help


MultiQuote