Add metacursor sample with controller input#88
Merged
jonathanpeppers merged 2 commits intomainfrom Feb 15, 2026
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
This PR implements the metacursor sample from 8bitworkshop, demonstrating two-player controller input using pad_poll() to control metasprite cursors with the d-pad. The implementation also includes a critical transpiler fix for array element stores with multiplication/division in the value expression.
Changes:
- Fixed
HandleStelemI1stack depth tracking to properly account forMul/DivIL opcodes (pop 2, push 1), enabling correct identification of array targets in expressions likeactor_x[i] = (byte)(i * 32) - Added metacursor sample with 8 actors controlled via
pad_poll(0)andpad_poll(1)for two-player input, demonstrating runtime array operations combined with arithmetic - Updated documentation to mark metacursor as implemented and adjust summary counts
Reviewed changes
Copilot reviewed 8 out of 11 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/dotnes.tasks/Utilities/IL2NESWriter.cs | Fixed stack tracking in HandleStelemI1 to include Mul and Div opcodes alongside existing binary operators |
| src/dotnes.tests/TranspilerTests.cs | Added test cases for metacursor sample (debug and release builds) |
| src/dotnes.tests/TranspilerTests.Write.metacursor.verified.bin | Verified binary output for metacursor ROM |
| src/dotnes.tests/Data/metacursor.debug.dll | Debug build DLL for metacursor test |
| src/dotnes.tests/Data/metacursor.release.dll | Release build DLL for metacursor test |
| samples/samples.sln | Added metacursor project to solution with all build configurations |
| samples/metacursor/metacursor.csproj | Project configuration for metacursor sample |
| samples/metacursor/Program.cs | Sample implementation with controller input and array operations |
| samples/metacursor/chr_generic.s | CHR ROM graphics data (standard tileset) |
| samples/metacursor/metacursor.c | Original C reference implementation |
| docs/8bitworkshop-samples.md | Updated status from "Moderate" to "Implemented" and adjusted counts |
04a6686 to
6b8add4
Compare
Implements the metacursor.c 8bitworkshop sample demonstrating: - pad_poll(0) and pad_poll(1) for two-player controller input - PAD.LEFT/RIGHT/UP/DOWN bitflag checking - 8 actors with metasprite rendering via oam_meta_spr - Runtime array element stores (actor_dx[0] = 254 for d-pad velocity) Transpiler fixes: 1. HandleStelemI1 stack depth tracking now accounts for Mul/Div opcodes (pop 2, push 1). Previously these fell through to the default case, causing the backward IL walk to identify the wrong local as the array target. 2. NTADR_A/B/C/D handlers no longer double-pop args from the Stack. The handler pops 2 args for compile-time address computation, but the generic post-Call loop was also popping N args, consuming the byte array negative marker needed by pal_all to load the PALETTE address. This caused gray/colorless output. 3. HandleStelemI1 now supports constant-index stores to runtime arrays (e.g. actor_dx[0] = 254). Previously, constant-index stelem was treated as a no-op (for ROM array initialization), but runtime arrays need actual LDA/STA code. Without this fix, d-pad velocity stores were silently dropped, causing random movement and crashes. Simplifications vs original C: - 8 actors instead of 16 (zero-page memory limits) - Single metasprite for all actors (no animation frame cycling) - No boundary checks (actors wrap around screen edges) - Inlined setup_graphics() into main body Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
6b8add4 to
7a642c8
Compare
… pad reload - HandleStelemI1: Add value expression support for Mul (power-of-2 shifts), Mul+Add, and simple constant patterns. Previously, the init loop actor_x[i] = (byte)(i * 32) and actor_dx[i] = 0 generated no value loads (A was never set before STA array,X). - pad_poll: Replace fixed tempVar () with dynamically allocated address from local space. The hardcoded address collided with runtime arrays (actor_x[2] in metacursor). Now allocates on first pad_poll call at local + LocalCount. - pad_poll: Remove exclusion from _runtimeValueInA, allowing stloc to correctly store the return value via STA. Add _runtimeValueInA = false in Pop handler for samples that discard the return value. - AND handler: Continue using _padReloadAddress for pad value reloads (renamed from tempVar). Guard conditions unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the metacursor.c 8bitworkshop sample.
Features demonstrated
Transpiler fix
\HandleStelemI1\ stack depth tracking now accounts for \Mul/\Div\ opcodes (pop 2, push 1). Previously these fell through to the default case with no stack effect, causing the backward IL walk to identify the wrong local as the array target when expressions like \�ctor_x[i] = (byte)(i * 32)\ were used.
Simplifications vs original C
All 170 tests pass.