3 hours ago
Problem 1 the status bar (SOLVED )
This was the big one. The old bar faked a "static" HUD by cycling through a bunch of pre-shifted tile variants it ate a lot of tiles and, as several of you predicted, the raster trick that worked in the emulator did not hold up on real hardware.
We finally got it working properly with a MicroDMA raster split: instead of a CPU interrupt rewriting the scroll registers every scanline (which flickered on hardware because the interrupt timing jitters during heavy scrolling), a MicroDMA channel triggered by Timer0/HBlank rewrites the scroll register per line with zero CPU cost and no jitter. The bar is now rock-solid on real hardware, and it freed up ~126 tiles.
Huge thanks to Tixu (NgpCraft / kuroi_dokutsu) studying that engine and its docs is what pointed us to the MicroDMA approach. The CPU-interrupt version taught us a lot, but MicroDMA was the real fix.
Problem 2 disappearing sprites (root cause found )
It wasn't a sprite-count problem. The bug: enemy spawn coordinates were stored as unsigned 8-bit but read back as signed, so any coordinate ≥ 128 was interpreted as negative and the sprite got culled as "off-screen" after a short time.
Switching those to signed 16-bit fixed it all enemies stay on screen now, confirmed on hardware. Also worth noting for anyone hitting this: the NGPC has no per-scanline sprite limit, only the 64 total so if sprites vanish, it's almost certainly a logic/coordinate bug, not a hardware limit.
Problem 3 framerate drops (understood, not a mystery anymore )
The scary part random ~3-second drops to single-digit fps turned out to be a measurement bug, not a real slowdown: the fps counter used an 8-bit VBlank counter that wraps every ~4.3 s, and the maths broke at the wrap. Tixu independently confirmed the same diagnosis.
On top of that we made real optimizations (only scanning spawn triggers when the scroll row actually changes, dropping a redundant per-sprite write). Heavy scenes (8–10 enemies + bullets) are genuinely close to the hardware's per-object budget, so we locked the game to a rock-solid 30 fps and rescaled all movement speeds to feel right much better than a fluctuating framerate.
Current status: now integrating a bigger level/enemy set the tiles freed by the new bar approach are exactly what makes it fit. Sorting out some sprite-numbering after the map update, but the hard structural problems are behind me.
Honestly couldn't have gotten here without this sub and Tixu's work being open. Thank you all
This was the big one. The old bar faked a "static" HUD by cycling through a bunch of pre-shifted tile variants it ate a lot of tiles and, as several of you predicted, the raster trick that worked in the emulator did not hold up on real hardware.
We finally got it working properly with a MicroDMA raster split: instead of a CPU interrupt rewriting the scroll registers every scanline (which flickered on hardware because the interrupt timing jitters during heavy scrolling), a MicroDMA channel triggered by Timer0/HBlank rewrites the scroll register per line with zero CPU cost and no jitter. The bar is now rock-solid on real hardware, and it freed up ~126 tiles.
Huge thanks to Tixu (NgpCraft / kuroi_dokutsu) studying that engine and its docs is what pointed us to the MicroDMA approach. The CPU-interrupt version taught us a lot, but MicroDMA was the real fix.
Problem 2 disappearing sprites (root cause found )
It wasn't a sprite-count problem. The bug: enemy spawn coordinates were stored as unsigned 8-bit but read back as signed, so any coordinate ≥ 128 was interpreted as negative and the sprite got culled as "off-screen" after a short time.
Switching those to signed 16-bit fixed it all enemies stay on screen now, confirmed on hardware. Also worth noting for anyone hitting this: the NGPC has no per-scanline sprite limit, only the 64 total so if sprites vanish, it's almost certainly a logic/coordinate bug, not a hardware limit.
Problem 3 framerate drops (understood, not a mystery anymore )
The scary part random ~3-second drops to single-digit fps turned out to be a measurement bug, not a real slowdown: the fps counter used an 8-bit VBlank counter that wraps every ~4.3 s, and the maths broke at the wrap. Tixu independently confirmed the same diagnosis.
On top of that we made real optimizations (only scanning spawn triggers when the scroll row actually changes, dropping a redundant per-sprite write). Heavy scenes (8–10 enemies + bullets) are genuinely close to the hardware's per-object budget, so we locked the game to a rock-solid 30 fps and rescaled all movement speeds to feel right much better than a fluctuating framerate.
Current status: now integrating a bigger level/enemy set the tiles freed by the new bar approach are exactly what makes it fit. Sorting out some sprite-numbering after the map update, but the hard structural problems are behind me.
Honestly couldn't have gotten here without this sub and Tixu's work being open. Thank you all

