mirror of
https://github.com/imjasonh/nescript
synced 2026-07-08 00:45:38 +00:00
runtime: reset PPU scroll after VRAM buffer drain
Each $2006 write inside __vram_buf_drain updates the PPU's `t` (scroll) register, so leaving it pointing at the last buffer entry's address shifted the next frame's rendering up/right by however many cells we wrote past $2000. Reset by writing $00 to $2006 twice (clears `t` and resets the write-toggle to high) followed by $00 to $2005 twice (zero X/Y scroll). The HUD demo golden flips from "smileys offset by ~16px" to the intended red bar with white hearts and a yellow score digit. https://claude.ai/code/session_01F7dHsgh7UX7SAK3wZ7JiKc
This commit is contained in:
parent
a806bfd3bd
commit
1c00d20121
5 changed files with 16 additions and 0 deletions
Binary file not shown.
Binary file not shown.
|
|
@ -2045,6 +2045,22 @@ pub fn gen_vram_buf_drain() -> Vec<Instruction> {
|
||||||
out.push(Instruction::new(LDA, AM::Immediate(0)));
|
out.push(Instruction::new(LDA, AM::Immediate(0)));
|
||||||
out.push(Instruction::new(STA, AM::Absolute(VRAM_BUF_HEAD)));
|
out.push(Instruction::new(STA, AM::Absolute(VRAM_BUF_HEAD)));
|
||||||
out.push(Instruction::new(STA, AM::Absolute(VRAM_BUF_BASE)));
|
out.push(Instruction::new(STA, AM::Absolute(VRAM_BUF_BASE)));
|
||||||
|
// Reset the PPU's internal scroll/address state. Each `$2006`
|
||||||
|
// write during the drain updated the PPU's `t` register
|
||||||
|
// (which holds the next scroll value); leaving it pointing
|
||||||
|
// at our last buffer entry's address would cause the next
|
||||||
|
// frame's rendering to start from a non-zero offset and the
|
||||||
|
// visible image would shift up/right by however many cells
|
||||||
|
// we wrote past `$2000`. The standard fix is to write `0` to
|
||||||
|
// `$2006` twice (resetting `t` to nametable 0 / cell 0) and
|
||||||
|
// then `0` to `$2005` twice (zero X / Y scroll). Two `$2006`
|
||||||
|
// writes also reset the `$2006`/`$2005` write-toggle latch
|
||||||
|
// to "high" so the next frame's drain sees a clean state.
|
||||||
|
out.push(Instruction::new(LDA, AM::Immediate(0)));
|
||||||
|
out.push(Instruction::new(STA, AM::Absolute(0x2006)));
|
||||||
|
out.push(Instruction::new(STA, AM::Absolute(0x2006)));
|
||||||
|
out.push(Instruction::new(STA, AM::Absolute(0x2005)));
|
||||||
|
out.push(Instruction::new(STA, AM::Absolute(0x2005)));
|
||||||
out.push(Instruction::implied(RTS));
|
out.push(Instruction::implied(RTS));
|
||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 36 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
Loading…
Add table
Add a link
Reference in a new issue