I'm having a kind of Schrodinger's cat problem with my reset. I have a value that is getting set when the game loads up but doesn't get set when I hit reset. However, if I step through the reset in the Mesen debugger, it gets set and everything works fine.
Any ideas why that would happen?
Thanks
Quote:
reset
In mesen?
Soft reset (reset button) or hard reset (power off and on)?
Do you have "Default power on state for RAM = random" set in Advanced settings?
dougeff wrote:
In mesen?
Yes, in Mesen
dougeff wrote:
Soft reset (reset button) or hard reset (power off and on)?
Soft reset through the menu. Hard reset (reloading the file) seems to work fine.
dougeff wrote:
Do you have "Default power on state for RAM = random" set in Advanced settings?
In Advanced settings I see "Start game from power on instead of resuming the previous gameplay session", but I'm not sure that's the setting your talking about.
Thanks for your help
I found that setting you were talking about in Emulation. My background gets random tiles dumped into it (thought I was clearing the background but I guess not). That doesn't give me the other problem though
No, but that could be a clue that something at startup isn't behaving like you think.
Maybe something isn't getting zeroed, or maybe you aren't waiting enough vblanks before writing to PPU.
Code or .nes file would help.
dougeff wrote:
No, but that could be a clue that something at startup isn't behaving like you think.
Maybe something isn't getting zeroed, or maybe you aren't waiting enough vblanks before writing to PPU.
Code or .nes file would help.
Ok, I'm no longer having an issue with the reset (I don't think). I am having a problem when I try to force a reset when the game is over. I added a
Code:
jmp reset
that gets run when your game is over and you press start. If I step through it in the debugger it works fine. If I don't run the debugger, the game freezes while trying to find the sprite0 collision. It shouldn't hit that part of the code because I have an open screen flag that gets set in the reset code. This seems to happen only if I step through it in the debugger.
I'm attaching the game and the mesen dbg file.
Thanks for your help Doug
I had to rename the .dbg file with a .txt extension for some reason
The procedure that calls the reset is "press_start"
Code:
.proc press_start
lda PRESS_START
and gamepad_press
beq skip_press_start
advance_random_ptr ; advance the random pointer based on the frame
lda start_delay
bne skip_press_start
lda open_screen_active
beq dont_start
lda #0
sta open_screen_active
jsr start_game
lda #30
sta start_delay
jmp start_end
dont_start:
lda game_over_active
beq dont_reset
lda #30
sta start_delay
lda #0
sta PPU_CTRL
set nmi_ready, #1 ; I ADDED THIS RECENTLY TO DISABLE THE NMI (IN CASE THAT WAS THE PROBLEM)
jmp reset ; THIS WORKS IF I START DEBUGGING FROM HERE
dont_reset:
; THE START BUTTON IS PRESSED
; start button action
jmp start_end
skip_press_start:
; if the start is not pressed
start_end:
rts
.endproc
Basically I'm trying to trigger a reset when the game is over and the player hits start. I do this with a jmp. I'm not sure if there's a different way to do this, but a soft reset seems to be working now. Now I'm just having an issue triggering the reset from the game over screen
I'm just guessing here:
before the reset, you set the PPUCTRL to 0, which disable the NMI. If you had some NMI code that had to be done then it may have stopped processed the thing you were waiting for, like a flag that waits for nmi to continue or things like that.
Banshaku wrote:
I'm just guessing here:
before the reset, you set the PPUCTRL to 0, which disable the NMI. If you had some NMI code that had to be done then it may have stopped processed the thing you were waiting for, like a flag that waits for nmi to continue or things like that.
Thanks for getting back to me.
I don't think that's the issue because initially I didn't have that in there and it was happening. I added that because at first I thought the NMI was coming in and clobbering things or possibly doing something in a half baked state. It didn't fix anything so I'll try it again without the PPUCTRL stuff. Maybe some other changes I made would have fixed it if I hadn't added that code in.
Anyway, I'll give it a quick try just in case.
Thanks again
It's is sometime hard to find a issue without looking a the complete code (reset etc) and the only thing that can be done in that case is give opinion on what could be going wrong.
The currently shown code doesn't seems to do anything strange, so calling the "reset", if it is the same one as the one when pressing the reset button, should have restarted it properly. This means there is a good chance that something is going on in the reset code that causes it to freeze. A good guess would be that it is something state related, like a state that occurs when a variable has not been reset properly and cause the game to do something it was not supposed to.
You should review your reset code for such state.
Banshaku wrote:
It's is sometime hard to find a issue without looking a the complete code (reset etc) and the only thing that can be done in that case is give opinion on what could be going wrong.
The currently shown code doesn't seems to do anything strange, so calling the "reset", if it is the same one as the one when pressing the reset button, should have restarted it properly. This means there is a good chance that something is going on in the reset code that causes it to freeze. A good guess would be that it is something state related, like a state that occurs when a variable has not been reset properly and cause the game to do something it was not supposed to.
You should review your reset code for such state.
I'm not sure my code is in a great state for a review right now. The problem seems to be a value in a flag "open_screen_active" that should be getting set at the end of my reset isn't getting set for some reason. However, if I step through the code with the debugger to see why it isn't getting set, it magically gets set and everything works just fine.
I was wondering if doing a jmp reset needs to do something else to make it work. Do I need to do something to clear out the stack? Or does the ldx #$ff and txs near the beginning of my reset work the same if I'm jumping to that code as it would if I hit the reset through the menu system? Since I'm doing the jmp from within a procedure, do I need to worry about it jumping back to the calling procedure when the reset is complete?
I'm mostly looking for some ideas of things to look in to. This has been helpful so far because it's given me some new areas to explore. Unfortunately none of them have been the problem yet.
Is it normal to try and reset the game back to the main menu using a jmp to reset on the game over screen? Or is that a strange thing to do and perhaps I should try a different method of restarting the game?
Thanks for your help
I can't test at the moment since i don't have access to a computer, but if NMI was causing the problem, it's possible that the code was executing with a different timing due to the debugger being opened? A good way to check would be to use the trace logger and compare both executions to see where they differ (ppu cycle and scanline,etc.) and confirm if NMI had something to do with it.
In general though, the debugger should never affect the execution of the game (if it does, that's a bug)
@battagline
Well, jumping from that part of code to reset, if the stack is reset properly should be fine. As for reset is the "right" way, it may be a matter of preference. I personally prefer to use reset when the machine is powered or reset is pressed. That code just prepare the machine initial state, special settings for mapper etc.
Once this is done, I enter my main loop which decide what to do next. In your case the main loop would "jsr" to the start state and once the "playing" look is over, it would return to the main loop, reset some state and wait what to do next.
Everything is suggestive, there is no best way, just what is easier for you to manage.
I had a chance to look at it.
The problem happens when you are holding down the start button while the game is reset. It seems you are checking the start button before something critical is done. (not exactly sure what that 'something' is).
It crashes on a sprite zero hit that never happens.
EDIT - it seems the sprite is in place, but there is no non-transparent tile in place.
EDIT2 - yes. Your title / pre-game code checks for the Start button about 3-4 frames before the Lives / Score and Sprite Zero collision tile are loaded.
On a side note. You might want to make the "lives" lower on the screen. Old CRT TVs will tend to cut off some of those pixels. See the "overscan" entry in the wiki.
Thanks for your help Doug
dougeff wrote:
EDIT2 - yes. Your title / pre-game code checks for the Start button about 3-4 frames before the Lives / Score and Sprite Zero collision tile are loaded.
So the sprite0 check is not supposed to happen on the open screen. I have a flag called open_screen_active that should be set at the end of the reset code to '1'. If the value is 1 it should skip the sprite0 code. If I go into the Mesen menu and tell it to reset from there, everything works fine. The flag is set, and there is no sprite0 check on the open screen (as it should be).
If I use the start button on game over to call the reset, for some reason that flag is not set to 1, but is 0 so the sprite0 code runs.
If I put a debug break point in the start button press and step through it with the debugger, everything works fine and the flag is set as it's supposed to be.
Not that I'm typing this out, I wonder if I'm calling that start button code more than once and therefore calling the reset multiple times in a row. Will need to investigate.
dougeff wrote:
On a side note. You might want to make the "lives" lower on the screen. Old CRT TVs will tend to cut off some of those pixels. See the "overscan" entry in the wiki.
I might do that. This is more of a personal research project and I'm not super concerned about the game running on old CRTs. I'm not sure anyone will actually be playing it on an old CRT, but I'll see what I can do.
Thanks again,
Rick
You're missing the point. The problem is you are doing things out of order. Although it is unlikely that the user will be holding the start button down at exactly the power on moment... if it crashes the game, it needs fixed, especially now that you restart the game by jumping to reset.
Either load the BG tiles as soon as possible, before buttons are ever read, ...or disable button presses until those tiles are loaded.
Or you could make Pressing Start the trigger to load the BG tiles in place, and disable Sprite zero hits until that is done.
The reason it doesn't happen during debugging is because it's difficult to hold down the Start button while you step through the game in a debugger.
And if all else fails, yet another way to avoid a freeze is to make the sprite 0 waiting loop resilient to failure, where you get a momentary graphical glitch instead.
Code:
s0offloop:
bit $2002
bvs s0offloop
; Now wait for either sprite 0 or vblank
lda #$C0
s0onloop:
bit $2002
beq s0onloop
bmi vblank_was_hit_instead
dougeff wrote:
Either load the BG tiles as soon as possible, before buttons are ever read, ...or disable button presses until those tiles are loaded.
Thanks Doug.
I fixed the issue, although not quite how you indicated. Basically I started pulling code out of the reset into a subroutine and called that from the start button press. This way I was able to move things in and out until the system either didn't clear everything I needed it to, or broke. I think part of the problem was that I was clearing all of memory and flags were getting overwritten at the wrong time.
Out of curiosity, how do you disable button presses? Can you do something to $4016 to disable the gamepad?
Thanks
battagline wrote:
Can you do something to $4016 to disable the gamepad?
No, you just ignore any input in the game logic.
tokumaru wrote:
No, you just ignore any input in the game logic.
In the future I should probably have a reset_complete flag that gets set to 1 after the reset finishes. I could probably key off of that for all the things that may run when they shouldn't during the reset.
Thanks
Good to hear you found it.
So it was a sprite 0 bug. I would have never guessed by debugging (I did check a little bit) since I never programmed one but I kind of knew it was something timing related since debugging caused it to make it work fine, somehow.