This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

PPU writes causing stack explosion

PPU writes causing stack explosion
by on (#151511)
I added only a few more PPU writes during VBlank and then I got an unexpected error: my stack blew up with repeated numbers and this ultimately is very bad. It didn't do the screen flicker that happens when you write to the PPU outside of VBlank but rather wrecked my stack. I believe the extra PPU writes were the cause of this because I deleted different PPU writes nearby that were working just fine and then the stack explosion didn't happen so I diagnosed the problem as too many PPU writes during VBlank. Why does this happen?
Re: PPU writes causing stack explosion
by on (#151514)
There's absolutely no correlation between PPU writes and stack overflows. It's probably just a coincidence that your PPU code happens to have one of the following errors:

- PHA without PLA;
- JSR without RTS;
- RTS instead of RTI in interrupts;
- Anything else that might be abandoning bytes in the stack.

Revise all your stack handling, specially if you're making flow decisions (branching) around stack operations. It's very common to place something on the stack expecting to use it later and then a decision changes the flow of the program and you end up never taking it off the stack.
Re: PPU writes causing stack explosion
by on (#151524)
Emulator features like trace logging (start log, reproduce, stop log, then examine log) and write breakpoints (set a write breakpoint on the stack area you don't expect to be touched) can be useful to figure out this type of stuff, if the problem is reproducible.
Re: PPU writes causing stack explosion
by on (#151526)
Vblank period was ended and last PPU writes failure. Try optimize code for PPU writes, or replace code to near starting NMI.
Re: PPU writes causing stack explosion
by on (#151651)
evgeny wrote:
Vblank period was ended and last PPU writes failure. Try optimize code for PPU writes, or replace code to near starting NMI.

This is common problem, but has nothing to do with the stack.
Re: PPU writes causing stack explosion
by on (#151652)
So you're having a stack overflow. Fortunately, there's a website that knows all about stack overflows and other kinds of problems that arise when programming:

Image Stack Overflow

The first thing to do is read its guidance on how to cut down your program into a minimal, complete, and verifiable example (MCVE) or a short, self-contained, compilable example (SSCCE). Watch your stack pointer in a debugging emulator, and cut things out of your engine one at a time until the stack overflow disappears. Then you know where to look to begin a fix.

Without an MCVE, I can't do much more than guess that reentrancy is involved. If you're doing these PPU writes in your NMI handler, I'd recommend adding a lockout variable so that the NMI handler can't run if the NMI handler is already running.


answered July 26 at 23:07
Image
Re: PPU writes causing stack explosion
by on (#151657)
I don't think drastically altering the program into a minimal example is the first thing to do at all. That's only useful in a narrow class of situations.

The first thing to do is what TheFox suggested. Start a trace log. Run until the bug happens. Save the log. Follow it backwards from the end until execution becomes normal. You'll see exactly where it broke.
Re: PPU writes causing stack explosion
by on (#151703)
If you have a stack growing up in size, but that your game do not crash, it definitely happens in the "main routine". If you do a PHA without a corresponding PLA (or a PHP without a corresponding PLP) in any subroutine, the program will crash when exiting that subroutine. If you do not RTI properly from an interrupt then the same, it will lead to program crash. This is an exhaustive list of what can happen.

  • PHA/PHP without corresponding PLA/PLP in main routine
  • You call a function that never returns, but calls itself again instead as a form of infinite game loop.
  • You don't ever return from your interrupt, but since you do all your logic in the interrupt this does not crash the game and keeps pushing values on the stack every frame

It's easily spottable by which size the patterns which repeats itself on the stack is. If a single byte is repeated, it's case 1), if two bytes repeats, it's case 2), if three bytes repeats, it's case 3).
Re: PPU writes causing stack explosion
by on (#151726)
Bregalad wrote:
You call a function that never returns, but calls itself again instead as a form of infinite game loop.

Doesn't have to call itself. Could be a function that was branched into as a subroutine (causing a stack push), but exits by jumping to another function (skipping the stack pop).
Re: PPU writes causing stack explosion
by on (#151748)
No, if you call a function that jumps to another function it will return at the RTS of that another function, leaving the stack in its original state. The function calling itself, or having a calling circle somehow across multiple function, is the only way to have a "working case" that pushes data to the stack but do not crash.
Re: PPU writes causing stack explosion
by on (#151799)
Actually yeah nevermind, I was thinking on the reverse case: using a jump to subroutine when it should have been a normal jump.