Hi All,
So in my pong game, I'm trying to learn how to transition from one background screen to another. I'm able to load a title screen, and switch from the title screen to my playfield screen without issues. The code I use to do that is here.
But when I use basically the same code to switch from playfield screen to the gameover screen (after a winning score has been achieved) the code doesn't function properly. The screen goes blank and stays blank. Now I expect it to go blank because I turn the screen off to allow time to draw the background,
But the screen doesn't come back on. My NMI handler should turn it back on because it has a "clean up" piece of code that re-enables everything.
Here is the code I use to draw the game over screen. Again basically the same code I use to draw the playfield after I switch from title. Allthough the screen stays blank, if I check FCEUX's Nametable viewer, it shows that screen has indeed drawn
And here is my NMI code
Any thoughts on this would be greatly appreciated here. I'm really banging my head on this. Seeing as how switching screens is pretty important I really want to understand the concept well. Also, I have attached the full code of my PONG game to this post as well if anyone would like to see it to help me determine my problem. There is also a screen shot in there of the nametable viewer in FCEUX showing the GameOver screen.
Thank You So Much
Hundo
So in my pong game, I'm trying to learn how to transition from one background screen to another. I'm able to load a title screen, and switch from the title screen to my playfield screen without issues. The code I use to do that is here.
Code:
LDA #%00000000 ;Turn Screen Off
STA $2001
LoadPlayScreen: ; load playfield screen
LDA $2002 ; read PPU status to reset the high/low latch
LDA #$20
STA $2006 ; write the high byte of $2000 address
LDA #$00
STA $2006 ; write the low byte of $2000 address
LDA #$00
STA pointerLo ; put the low byte of the address of background into pointer
LDA #HIGH(playfield)
STA pointerHi ; put the high byte of the address into pointer
LDX #$00 ; start at pointer + 0
LDY #$00
PlayFieldOutsideLoop:
PlayFieldInsideLoop:
LDA [pointerLo], y ; copy one background byte from address in pointer plus Y
STA $2007 ; this runs 256 * 4 times
INY ; inside loop counter
CPY #$00
BNE PlayFieldInsideLoop ; run the inside loop 256 times before continuing down
INC pointerHi ; low byte went 0 to 256, so high byte needs to be changed now
INX
CPX #$04
BNE PlayFieldOutsideLoop ; run the outside loop 256 times before continuing down
STA $2001
LoadPlayScreen: ; load playfield screen
LDA $2002 ; read PPU status to reset the high/low latch
LDA #$20
STA $2006 ; write the high byte of $2000 address
LDA #$00
STA $2006 ; write the low byte of $2000 address
LDA #$00
STA pointerLo ; put the low byte of the address of background into pointer
LDA #HIGH(playfield)
STA pointerHi ; put the high byte of the address into pointer
LDX #$00 ; start at pointer + 0
LDY #$00
PlayFieldOutsideLoop:
PlayFieldInsideLoop:
LDA [pointerLo], y ; copy one background byte from address in pointer plus Y
STA $2007 ; this runs 256 * 4 times
INY ; inside loop counter
CPY #$00
BNE PlayFieldInsideLoop ; run the inside loop 256 times before continuing down
INC pointerHi ; low byte went 0 to 256, so high byte needs to be changed now
INX
CPX #$04
BNE PlayFieldOutsideLoop ; run the outside loop 256 times before continuing down
But when I use basically the same code to switch from playfield screen to the gameover screen (after a winning score has been achieved) the code doesn't function properly. The screen goes blank and stays blank. Now I expect it to go blank because I turn the screen off to allow time to draw the background,
But the screen doesn't come back on. My NMI handler should turn it back on because it has a "clean up" piece of code that re-enables everything.
Here is the code I use to draw the game over screen. Again basically the same code I use to draw the playfield after I switch from title. Allthough the screen stays blank, if I check FCEUX's Nametable viewer, it shows that screen has indeed drawn
Code:
LDA #%00000000 ;Turn Screen Off
STA $2001
LoadGameOverScreen: ;Load Game Over Screen
LDA $2002 ; read PPU status to reset the high/low latch
LDA #$20
STA $2006 ; write the high byte of $2000 address
LDA #$00
STA $2006 ; write the low byte of $2000 address
LDA #$00
STA pointerLo ; put the low byte of the address of background into pointer
LDA #HIGH(gameover)
STA pointerHi ; put the high byte of the address into pointer
LDX #$00 ; start at pointer + 0
LDY #$00
GameOverOutsideLoop:
GameOverInsideLoop:
LDA [pointerLo], y ; copy one background byte from address in pointer plus Y
STA $2007 ; this runs 256 * 4 times
INY ; inside loop counter
CPY #$00
BNE GameOverInsideLoop ; run the inside loop 256 times before continuing down
INC pointerHi ; low byte went 0 to 256, so high byte needs to be changed now
INX
CPX #$04
BNE GameOverOutsideLoop ; run the outside loop 256 times before continuing down
STA $2001
LoadGameOverScreen: ;Load Game Over Screen
LDA $2002 ; read PPU status to reset the high/low latch
LDA #$20
STA $2006 ; write the high byte of $2000 address
LDA #$00
STA $2006 ; write the low byte of $2000 address
LDA #$00
STA pointerLo ; put the low byte of the address of background into pointer
LDA #HIGH(gameover)
STA pointerHi ; put the high byte of the address into pointer
LDX #$00 ; start at pointer + 0
LDY #$00
GameOverOutsideLoop:
GameOverInsideLoop:
LDA [pointerLo], y ; copy one background byte from address in pointer plus Y
STA $2007 ; this runs 256 * 4 times
INY ; inside loop counter
CPY #$00
BNE GameOverInsideLoop ; run the inside loop 256 times before continuing down
INC pointerHi ; low byte went 0 to 256, so high byte needs to be changed now
INX
CPX #$04
BNE GameOverOutsideLoop ; run the outside loop 256 times before continuing down
And here is my NMI code
Code:
NMI:
PHA ; back up registers (important)
TXA
PHA
TYA
PHA
LDA #$00
STA $2003 ; set the low byte (00) of the RAM address
LDA #$02
STA $4014 ; set the high byte (02) of the RAM address, start the transfer
Score:
LDA gamestate
CMP #STATETITLE
BEQ CleanUp
JSR DrawScore
CleanUp:
LDA #%10010000 ; enable NMI, sprites from Pattern Table 0, background from Pattern Table 1 - ;;PPU clean up section, so rendering the next frame starts properly.
STA $2000
LDA #%00011110 ; enable sprites, enable background, no clipping on left side
STA $2001
LDA #$00 ;;tell the ppu there is no background scrolling
STA $2005
STA $2005 ;;;all graphics updates done by here, run game engine
JSR ReadController1 ;;get the current button data for player 1
JSR ReadController2 ;;get the current button data for player 2
GameEngine:
StateTitle:
LDA gamestate
CMP #STATETITLE
BNE StateGameOver ;;game is displaying title screen
JMP EngineTitle
StateGameOver:
LDA gamestate
CMP #STATEGAMEOVER
BNE StatePlaying ;;game is displaying ending screen
JMP EngineGameOver
StatePlaying:
LDA gamestate
CMP #STATEPLAYING
BNE GameEngineDone
JMP EnginePlaying ;;game is playing
GameEngineDone:
JSR UpdateSprites ;;set ball/paddle sprites from positions
PLA ; restore regs and exit
TAY
PLA
TAX
PLA
RTI
PHA ; back up registers (important)
TXA
PHA
TYA
PHA
LDA #$00
STA $2003 ; set the low byte (00) of the RAM address
LDA #$02
STA $4014 ; set the high byte (02) of the RAM address, start the transfer
Score:
LDA gamestate
CMP #STATETITLE
BEQ CleanUp
JSR DrawScore
CleanUp:
LDA #%10010000 ; enable NMI, sprites from Pattern Table 0, background from Pattern Table 1 - ;;PPU clean up section, so rendering the next frame starts properly.
STA $2000
LDA #%00011110 ; enable sprites, enable background, no clipping on left side
STA $2001
LDA #$00 ;;tell the ppu there is no background scrolling
STA $2005
STA $2005 ;;;all graphics updates done by here, run game engine
JSR ReadController1 ;;get the current button data for player 1
JSR ReadController2 ;;get the current button data for player 2
GameEngine:
StateTitle:
LDA gamestate
CMP #STATETITLE
BNE StateGameOver ;;game is displaying title screen
JMP EngineTitle
StateGameOver:
LDA gamestate
CMP #STATEGAMEOVER
BNE StatePlaying ;;game is displaying ending screen
JMP EngineGameOver
StatePlaying:
LDA gamestate
CMP #STATEPLAYING
BNE GameEngineDone
JMP EnginePlaying ;;game is playing
GameEngineDone:
JSR UpdateSprites ;;set ball/paddle sprites from positions
PLA ; restore regs and exit
TAY
PLA
TAX
PLA
RTI
Any thoughts on this would be greatly appreciated here. I'm really banging my head on this. Seeing as how switching screens is pretty important I really want to understand the concept well. Also, I have attached the full code of my PONG game to this post as well if anyone would like to see it to help me determine my problem. There is also a screen shot in there of the nametable viewer in FCEUX showing the GameOver screen.
Thank You So Much
Hundo