mirror of
https://github.com/imjasonh/nescript
synced 2026-07-08 08:55:38 +00:00
IR codegen: clear OAM shadow at frame handler entry
Each frame handler now begins with a short 64-slot loop that writes \$FE to the Y-position byte of every OAM entry, hiding any sprites the previous frame drew that the current frame doesn't. Without this, stopping a \`draw\` call one frame leaves the sprite lingering at its last position forever. Cost: ~384 cycles per frame (2.3% of the ~16 666 cycles available between vblanks). The per-frame \`draw\` calls overwrite the slots they actually use, so the clear is free at runtime for sprites that ARE drawn. https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
This commit is contained in:
parent
d2075bc8f9
commit
2fd3a6e545
1 changed files with 18 additions and 0 deletions
|
|
@ -356,6 +356,24 @@ impl<'a> IrCodeGen<'a> {
|
|||
|
||||
self.emit_label(&format!("__ir_fn_{}", func.name));
|
||||
|
||||
// At the start of every frame handler, clear the OAM shadow
|
||||
// buffer so stale sprites from the previous frame (or from a
|
||||
// different state's handler) don't linger on screen. We set
|
||||
// the Y position byte of every OAM entry to $FE (off-screen).
|
||||
// The actual drawing code overwrites the slots it needs.
|
||||
if self.in_frame_handler {
|
||||
let clear_loop = format!("__ir_oam_clear_{}", func.name);
|
||||
self.emit(LDX, AM::Immediate(0));
|
||||
self.emit(LDA, AM::Immediate(0xFE));
|
||||
self.emit_label(&clear_loop);
|
||||
self.emit(STA, AM::AbsoluteX(0x0200));
|
||||
self.emit(INX, AM::Implied);
|
||||
self.emit(INX, AM::Implied);
|
||||
self.emit(INX, AM::Implied);
|
||||
self.emit(INX, AM::Implied);
|
||||
self.emit(BNE, AM::LabelRelative(clear_loop));
|
||||
}
|
||||
|
||||
for block in &func.blocks {
|
||||
self.gen_block(block);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue