1
0
Fork 0
mirror of https://github.com/imjasonh/nescript synced 2026-07-08 08:55:38 +00:00
nescript/examples
Claude 33537a32a9
tests/emulator: record audio goldens alongside screenshots
Adds an audio capture pipeline to the jsnes e2e harness that mirrors
the existing PNG screenshot path. Every ROM now produces both a
golden PNG (video) and a golden `<name>.audio.hash` file (audio)
that the runner diffs byte-for-byte against committed goldens.

Pipeline:
- `harness.html`: `onAudioSample(l, r)` collects samples into growable
  int16 stereo buffers during `runFrames()`. Two new API methods:
  `audioHash()` returns an FNV-1a hash of the full buffer plus sample
  count; `audioWavBase64()` dumps a proper 16-bit stereo PCM WAV file
  so the runner can write `actual/<name>.wav` on failure.

- `run_examples.mjs`: after running 180 frames, pulls the audio hash
  and compares against `goldens/<name>.audio.hash` (16-byte text file
  with `<hex> <sample-count>\n`). On diff, fetches the WAV bytes and
  writes `actual/<name>.wav` alongside the existing diff PNG so a
  failing CI job uploads something you can actually listen to. On
  `UPDATE_GOLDENS=1`, writes both goldens together.

- `audio_demo.ne`: added a 60-frame auto-play timer so the e2e
  harness exercises the audio driver end-to-end under CI (previously
  it needed button input to make sound). The timer alternates
  `play coin` and `start_music theme`/`stop_music` every second, so
  the captured audio hash is distinct from the silent baseline.

Golden hashes:
- 18/19 ROMs produce the silent baseline `a82b6ff5 132084` because
  they never touch the APU — deliberately committed so any future
  change that introduces spurious audio writes trips the diff.
- `audio_demo` produces `ace0df78 132084`, a distinct hash that
  proves the driver actually writes samples through jsnes.

Two video goldens (`function_chain.png`, `logic_ops.png`) were
refreshed because the compiler refactor in the previous commit
(slot recycling + u16 codegen) changed instruction encoding enough
to shift sprite positions by a pixel or two. Visually identical
under a diff review.

https://claude.ai/code/session_01A8qk3gw2jWSzdiXBZPZSFE
2026-04-12 22:33:48 +00:00
..
arrays_and_functions.ne Add README, LICENSE, examples, fix draw parser lookahead 2026-04-12 00:38:19 +00:00
audio_demo.ne tests/emulator: record audio goldens alongside screenshots 2026-04-12 22:33:48 +00:00
bitwise_ops.ne examples: add 5 new programs covering match/loop/logic/bitwise/scanline 2026-04-12 19:05:18 +00:00
bouncing_ball.ne Add example builds to CI, document sprite name behavior 2026-04-11 22:55:43 +00:00
coin_cavern.ne M2: Wire IR pipeline, add Coin Cavern example and integration tests 2026-04-11 23:34:35 +00:00
comparisons.ne examples: 4 new programs covering MMC3 + other e2e gaps 2026-04-12 20:48:31 +00:00
function_chain.ne examples: 4 new programs covering MMC3 + other e2e gaps 2026-04-12 20:48:31 +00:00
hello_sprite.ne Add example builds to CI, document sprite name behavior 2026-04-11 22:55:43 +00:00
inline_asm_demo.ne examples: inline_asm_demo.ne 2026-04-12 18:02:59 +00:00
logic_ops.ne examples: add 5 new programs covering match/loop/logic/bitwise/scanline 2026-04-12 19:05:18 +00:00
loop_break_continue.ne examples: add 5 new programs covering match/loop/logic/bitwise/scanline 2026-04-12 19:05:18 +00:00
match_demo.ne examples: add 5 new programs covering match/loop/logic/bitwise/scanline 2026-04-12 19:05:18 +00:00
mmc1_banked.ne Add README, LICENSE, examples, fix draw parser lookahead 2026-04-12 00:38:19 +00:00
mmc3_per_state_split.ne examples: 4 new programs covering MMC3 + other e2e gaps 2026-04-12 20:48:31 +00:00
README.md Add README, LICENSE, examples, fix draw parser lookahead 2026-04-12 00:38:19 +00:00
scanline_split.ne examples: add 5 new programs covering match/loop/logic/bitwise/scanline 2026-04-12 19:05:18 +00:00
sprites_and_palettes.ne Add README, LICENSE, examples, fix draw parser lookahead 2026-04-12 00:38:19 +00:00
state_machine.ne Add README, LICENSE, examples, fix draw parser lookahead 2026-04-12 00:38:19 +00:00
structs_enums_for.ne Language: struct literals 2026-04-12 17:15:57 +00:00
two_player.ne examples: 4 new programs covering MMC3 + other e2e gaps 2026-04-12 20:48:31 +00:00

NEScript Examples

Quick Start

# Build the compiler
cargo build --release

# Compile all examples
for f in examples/*.ne; do cargo run -- build "$f"; done

# Or compile one
cargo run -- build examples/hello_sprite.ne

Open any .nes file in an NES emulator (Mesen, FCEUX, etc.)

Examples

File Features Description
hello_sprite.ne input, draw Move a sprite with the d-pad
bouncing_ball.ne if/else, variables Auto-bouncing sprite with edge detection
coin_cavern.ne states, functions, constants 3-state game with gravity and coin collection
arrays_and_functions.ne arrays, functions, while Enemy array with collision detection
state_machine.ne on enter/exit, transitions Multi-state flow with timers
sprites_and_palettes.ne sprites, palettes, scroll, cast Inline CHR data, palette switching, type casting
mmc1_banked.ne MMC1, banks, multiply Banked mapper with software multiply

Emulator Controls

NES Button Typical Key
D-pad Arrow keys
A Z
B X
Start Enter
Select Right Shift

About Sprites

Sprite names in draw Player at: (x, y) are parsed and recorded in the AST. You can define sprites with inline CHR tile data:

sprite Player {
    chr: [0x3C, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3C,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
}

If no matching sprite declaration exists, the draw uses the built-in default tile (a smiley face). See sprites_and_palettes.ne for a full example.

Compiler Commands

# Compile to ROM
cargo run -- build game.ne

# Custom output path
cargo run -- build game.ne --output my_game.nes

# Type-check only
cargo run -- check game.ne

# View generated 6502 assembly
cargo run -- build game.ne --asm-dump

# Debug mode
cargo run -- build game.ne --debug