Aight. So almost definitely it's crashing because you're writing to $2007 while rendering. (or... like the code you added is not in the fixed bank, but it seems like that's a thing you'd know about. I'm gonna... not check that out unless I really have to!) The deal is you can't write to $2007 at anytime. You can write to it when rendering is disabled. You can write to it for a short time after vblank begins (usually when the NMI routine fires, if NMIs are enabled). If you're aware of this, tell me so! If not, here's a plan that may or may not work because I don't have access to what you're doing.
First, ask yourself this question: Is it possible for my pause check code (that also writes $2007) to run on a frame where I can actually see the pause screen (instead of like... black)? If yes, you're writing to $2007 during rendering, no question. Unless... the code you said was doing an identical thing (using different data) to the pause screen already disables rendering if which case I have no idea, I'd have to look at the patch.
If yes, here's a super hacky plan to try to fix it.
1. I'm assuming your debug active flag currently has two states. Zero (we'll say for off), and non zero (we'll say for on).
2. Based on this assumption, you want to give it a third state. #$00 = off, #$01 = on, have not drawn pause screen, #$02 = on, have drawn pause screen.
Your routine that hooks the pause screen probably looks something like this:
Code:
JSR $EB39;Junk copied from the original EE71
lda $38;check pause flag
beq PauseStubEnd;if zero, do nothing
lda $06F0;Check debugflag
beq PauseStubEnd
LDA #$22
STA $2006
LDA #$08
STA $2006
LDA $whatever
STA $2007
PauseStubEnd:
rts
Of course, that means you'll end up writing to $2007 during rendering at some point. Because if this runs every frame, and rendering is not disabled every frame then...
3. So try changing it to something like this:
Code:
JSR $EB39;Junk copied from the original EE71
ldy $06F0;Check debugflag
beq PauseStubEnd;If zero, do nothing
;If here, debug mode is active
lda $38;Check pause mode
bne PauseStubCheckDebug;if active, continue
;If here, debug mode is active,
;But the game is NOT paused
lda #$01
sta $06F0;Set debugflag to on, have not drawn pause screen
;We do that every time the game isn't paused
;So the next time the game is paused
;We'll know to draw the screen just once...
bne PauseStubEnd;bne will always branch here. Exit routine, because game is not paused.
PauseStubCheckDebug:
;If here, the game is paused
;and debugmode is enabled.
;Debugmode flag is still in y
dey;If after subtracting 1, it's still above 0, that means it was 2.
bne PauseStubEnd;Which means we already drew the pause screen and shouldn't again
;If here, debug flag is 1. Debug is on, we're paused, but we haven't drawn the extra stuff.
lda #$00;DISABLE RENDERING!
sta $2001;
;The reason we do the whole song and dance
;with the extra debug state
;Is that if rendering was disabled
;every frame, some odd things
;might prevent the player
;from seeing the screen!
;The extra state allows us to
;disable it ONCE to draw
;and then the text will
;remain there without
;us drawing it again
;bit $2002;Try it without first, if you're tight on space. if it still fails, try with
;As stated in the previous post, it's only REALLY needed in weird cases
LDA #$22
STA $2006
LDA #$08
STA $2006
LDA $whatever
STA $2007
lda #%00011110;Turn rendering back on
sta $2001;I think this is how Kid Icarus would have it set.
;If not, read the docs here to get a better value
;http://wiki.nesdev.com/w/index.php/PPU_registers#Mask_.28.242001.29_.3E_write
lda #$02;Set debug mode flag
sta $06F0;to on, have drawn pause screen.
PauseStubEnd:
rts
It's commented, but the short version is the new checks set it up so
1. When the game is not paused, your debug flag knows.
2. Thanks to the above, you can detect the first frame of being paused
3. When you've drawn the screen, you can detect that and not draw it again.
Be aware! The above code is based entirely on a guess. I have not run this game through a debugger, yet. (I'll only do that if I need to, and it won't take me ALL DAY to figure out.) There are all kinds of things that could go wrong, like $EB39 returns a value in A, X, or Y or sets flags that you're destroying with your routine before it gets used after your own RTS. (which would bring it back to the next thing that would use $EB39 info.) But I assume you checked that. (If you didn't or aren't sure there's a fix for that by storing all of that to the stack, then restoring it all when you finish. It's the next thing I'd try if this doesn't work.) Also, it could be this doesn't crash, but you see nothing changed on the pause screen. Which probably means your code is drawing to the pause screen before the pause screen is fully drawn, and then it's overwritten by the actual pause screen. (Which you can easily fix by just waiting more frames to draw yours.)
Quote:
I haven't had the patience to find out more about this.
Err... you need to find it, or you should give up. Because reading your plan, it sounds much harder than just this.
PS, and it's probably bad news! If you really want to make the pause screen also react to input, this method isn't really great for that. Because every time the player makes an input that would change the menu, you'd need to disable rendering which will... look weird. You'll need to figure out how this game updates the screen in the NMI if you want to draw without disabling rendering. (Could actually just do a similar check for pause inside the NMI, and draw what you need while paused.) Or use sprites for the interactive stuff, while the text stays put.
Apologies in advance is none of that is any help. It seems like you know the obvious stuff, but I'm trying to cover all the bases here. If it ain't helpful, yeah... post a patch and I'll take a look but no guarantees if I gotta go super deep.
Edit: Correct big whoops. Said $2000 disables rendering instead of $2001.
Edit2: While I'm at it, Kid Icarus shows sprites and the background on the left 8 pixels of the screen.
Edit3: Oh snap. And for extra safety, probably also want to set $2000 to be sure $2007 writes increment by one as stated in the previous post. I'm starting to bet there won't be room for all this in one place... I didn't add any $2000 stuff to the code in this post, though. More curious if it doesn't crash. We can go from there.