1
0
Fork 0
mirror of https://github.com/imjasonh/nescript synced 2026-07-08 08:55:38 +00:00

Merge pull request #15 from imjasonh/claude/platformer-game-demo-WK8XS

Commit built .nes ROMs alongside .ne sources
This commit is contained in:
Jason Hall 2026-04-13 11:23:25 -04:00 committed by GitHub
commit 59905147b4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 71 additions and 9 deletions

View file

@ -58,12 +58,26 @@ jobs:
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo build --release
- name: Compile all .ne examples
- name: Verify committed ROMs match their .ne sources
# Every example has a committed .nes file under examples/. The
# compiler is deterministic (verified: same input → byte-identical
# output), so rebuilding each example into a tmp directory and
# diffing against the committed ROM catches "someone edited a .ne
# file but forgot to regenerate the ROM" at PR time.
run: |
mkdir -p /tmp/reprotest
fail=0
for f in examples/*.ne; do
echo "==> Compiling $f"
cargo run --release -- build "$f"
name=$(basename "$f" .ne)
./target/release/nescript build "$f" --output "/tmp/reprotest/$name.nes"
if ! cmp -s "examples/$name.nes" "/tmp/reprotest/$name.nes"; then
echo "::error file=examples/$name.ne::committed examples/$name.nes is stale; rerun \`cargo run --release -- build examples/$name.ne\` and commit the new ROM"
fail=1
fi
done
if [ $fail -ne 0 ]; then
exit 1
fi
- name: Verify ROMs are valid iNES
run: |
for f in examples/*.nes; do
@ -113,6 +127,14 @@ jobs:
- name: Build compiler
run: cargo build --release
- name: Compile all .ne examples
# Overwrites the committed examples/*.nes in the CI workspace
# (the workspace is ephemeral; the committed ROMs aren't
# touched). This is load-bearing: the goldens must be diffed
# against what *this* compiler produces, not against the ROMs
# an earlier commit happened to ship, otherwise a broken
# compiler change can still pass the emulator job as long as
# the contributor forgot to rebuild the ROMs. The `examples`
# job catches that second case via its reproducibility diff.
run: |
for f in examples/*.ne; do
echo "==> Compiling $f"
@ -121,7 +143,7 @@ jobs:
- name: Install emulator harness dependencies
working-directory: tests/emulator
run: npm ci
- name: Diff each ROM's framebuffer against its committed golden
- name: Diff each ROM's framebuffer against its golden
working-directory: tests/emulator
run: node run_examples.mjs
- name: Upload actual + diff PNGs on failure

1
.gitignore vendored
View file

@ -1,4 +1,3 @@
/target
*.nes
*.dbg
*.map

View file

@ -15,6 +15,13 @@ re-derive the project conventions from scratch.
pipeline.
- Examples live in `examples/*.ne`. Every example is expected to compile
cleanly and has a pinned emulator golden — see below.
- **`examples/*.nes` is committed.** The compiler is deterministic
(same source → byte-identical ROM), so the ROMs travel with the
repo. If you edit any `.ne` file you **must** rebuild its `.nes`
in the same commit — CI's `examples` job rebuilds each ROM into a
tmp path and fails if the committed version differs, pointing at
the exact `cargo run -- build examples/<name>.ne` to run. The
pre-commit hook under `scripts/pre-commit` catches this locally.
- `docs/future-work.md` lists the remaining gaps. If you implement
something from that file, update the doc in the same PR.
@ -63,8 +70,9 @@ tests/emulator/
The harness is **separate** from `cargo test`. You have to run it by hand:
```bash
# 1. Build every example first. The harness reads pre-built .nes files
# from examples/ — it will not invoke cargo.
# 1. Rebuild every example with the current compiler. The harness
# reads whatever sits under examples/*.nes — if you want to test
# your working copy you have to rebuild them first.
cargo build --release
for f in examples/*.ne; do ./target/release/nescript build "$f"; done
@ -72,13 +80,22 @@ for f in examples/*.ne; do ./target/release/nescript build "$f"; done
cd tests/emulator
npm install # or `npm ci` in CI
# 3. Verify every example still matches its golden.
# 3. Verify every ROM still matches its golden.
node run_examples.mjs
# → "21/21 ROMs match their goldens" on success
# → "22/22 ROMs match their goldens" on success
# → FAIL / MISS lines + `actual/<name>.png`, `actual/<name>.diff.png`,
# `actual/<name>.wav` written for any ROM that mismatched
```
The harness always runs against whatever sits in `examples/*.nes`,
so iterating on the compiler means rebuilding the example first.
CI's `emulator` job does this too — it builds the compiler, compiles
every `.ne` into the workspace (overwriting the committed ROMs,
which are ephemeral in the CI checkout), and then runs the harness.
The committed ROMs are a PR-review convenience and a "did this
change affect codegen" tripwire via the `examples` job's
reproducibility diff; they are **not** what the emulator job tests.
### Updating goldens
If a change is supposed to flip goldens (you added a new example, changed

Binary file not shown.

BIN
examples/audio_demo.nes Normal file

Binary file not shown.

BIN
examples/bitwise_ops.nes Normal file

Binary file not shown.

BIN
examples/bouncing_ball.nes Normal file

Binary file not shown.

BIN
examples/coin_cavern.nes Normal file

Binary file not shown.

BIN
examples/comparisons.nes Normal file

Binary file not shown.

BIN
examples/function_chain.nes Normal file

Binary file not shown.

BIN
examples/hello_sprite.nes Normal file

Binary file not shown.

Binary file not shown.

BIN
examples/logic_ops.nes Normal file

Binary file not shown.

Binary file not shown.

BIN
examples/match_demo.nes Normal file

Binary file not shown.

BIN
examples/mmc1_banked.nes Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
examples/platformer.nes Normal file

Binary file not shown.

BIN
examples/scanline_split.nes Normal file

Binary file not shown.

Binary file not shown.

BIN
examples/state_machine.nes Normal file

Binary file not shown.

Binary file not shown.

BIN
examples/two_player.nes Normal file

Binary file not shown.

BIN
examples/uxrom_banked.nes Normal file

Binary file not shown.

View file

@ -15,4 +15,28 @@ cargo clippy --all-targets -- -D warnings
echo " Running tests..."
cargo test --all-targets
# Committed ROMs must match their .ne sources — the compiler is
# deterministic, so any example whose on-disk .nes differs from a
# fresh build means someone edited the .ne file but forgot to
# rebuild. Rebuild each to a tmp path and fail if any differ, then
# point the user at the exact `cargo run` command to fix it.
echo " Checking committed ROMs match .ne sources..."
cargo build --release --quiet
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT
stale=0
for f in examples/*.ne; do
name=$(basename "$f" .ne)
./target/release/nescript build "$f" --output "$tmp/$name.nes" >/dev/null
if ! cmp -s "examples/$name.nes" "$tmp/$name.nes"; then
echo " STALE: examples/$name.nes"
echo " rerun: cargo run --release -- build $f"
stale=1
fi
done
if [ $stale -ne 0 ]; then
echo "one or more committed ROMs are out of date"
exit 1
fi
echo "All pre-commit checks passed."