1
0
Fork 0
mirror of https://github.com/imjasonh/nescript synced 2026-07-16 20:26:23 +00:00
nescript/tests/emulator/goldens/uxrom_user_banked.audio.hash

2 lines
16 B
Text
Raw Normal View History

codegen: user code in switchable banks via cross-bank trampolines Adds a `bank Foo { fun bar() { ... } }` parser form so user functions can opt into living in a switchable PRG bank instead of the fixed bank, plus the IR codegen, runtime, and linker work to make calls across the bank boundary actually run. Programs that don't use the new syntax produce byte-identical ROMs to before — verified by rebuilding every existing example and diffing. Pipeline shape: * Parser accepts both `bank Foo: prg` (legacy reserved slot) and `bank Foo { fun ... }` (functions land in the named bank). Nested functions get tagged `bank: Some("Foo")` on the FunDecl + IrFunction. * Analyzer bumps the user zero-page start past `$10` whenever the program declares any banked function, so `__bank_select`'s STA into ZP_BANK_CURRENT can't clobber a user variable. Programs without banked functions keep the legacy `$10` start. * IrCodeGen emits each banked function into its own per-bank instruction stream (`banked_streams: HashMap<String, Vec<Instruction>>`) while the fixed-bank stream gets the dispatcher loop + state handlers + top-level functions, exactly like before. Cross-bank calls from the fixed bank rewrite `JSR __ir_fn_<name>` to `JSR __tramp_<name>`; in-bank calls stay direct. Banked → fixed calls are direct (the fixed bank is always mapped at $C000-$FFFF). Banked → other-banked calls aren't supported in this pass and panic loudly during codegen. * Runtime's `gen_bank_trampoline` takes the trampoline label and entry label as parameters now (one trampoline per banked function, not one per bank) so the linker can request any number of stubs. * Linker assembles banked banks twice: a discovery pass to learn each bank's labels, then a final pass that seeds the merged label table so banked code can JSR into the fixed bank's runtime helpers (math, audio, etc.). The fixed-bank assembler is also seeded with the cross-bank labels so the trampolines' `JSR __ir_fn_<name>` resolves into the bank's $8000 window. New `asm::assemble_with_labels` / `asm::assemble_discover_labels` helpers wire this up. * PrgBank carries `Vec<Instruction>` + a list of `BankTrampoline` requests now, replacing the old `data: Vec<u8>` + single `entry_label: Option<String>` shape. The compiler populates both from the codegen output; the linker's two-pass assembly handles the rest. New example: `examples/uxrom_user_banked.ne` puts a sprite-stepping helper inside `bank Extras { fun step_animation() { ... } }`. The fixed-bank state handler calls it via the generated trampoline, and the harness golden locks in pixel + audio output at frame 180. UxROM is the only mapper exercised by the new example. MMC1 and MMC3 also work through the same path (the linker emits the right mapper-specific bank-select code), but no example uses them yet — the existing `mmc1_banked.ne` / `mmc3_per_state_split.ne` keep their fixed-bank-only layout. Limitations carried forward: * No banked → banked cross-bank calls (panics in codegen). * No greedy size-packing; placement is explicit-only. * MMC3 state handlers don't get banked (the per-state split path is untouched).
2026-04-14 11:41:20 +00:00
a82b6ff5 132084