Merged
Conversation
jonathanpeppers
added a commit
that referenced
this pull request
Mar 6, 2026
Fixes #33 The 6502 is an 8-bit CPU, so IntPtr.Size returns 1. Two IL patterns are handled: - IntPtr.Size emits 'call IntPtr::get_Size()' -> handled in the Call switch as a compile-time constant (LDA #1) - sizeof(nint) emits the Sizeof IL opcode -> new case in the int operand handler (LDA #1) Both produce identical output: a single LDA #1 instruction. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jonathanpeppers
added a commit
that referenced
this pull request
Mar 6, 2026
Fixes #33 The 6502 is an 8-bit CPU, so IntPtr.Size returns 1. Two IL patterns are handled: - IntPtr.Size emits 'call IntPtr::get_Size()' -> handled in the Call switch as a compile-time constant (LDA #1) - sizeof(nint) emits the Sizeof IL opcode -> new case in the int operand handler (LDA #1) Both produce identical output: a single LDA #1 instruction. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jonathanpeppers
added a commit
that referenced
this pull request
Mar 6, 2026
Fixes #33 The 6502 is an 8-bit CPU, so IntPtr.Size returns 1. Two IL patterns are handled: - IntPtr.Size emits 'call IntPtr::get_Size()' -> handled in the Call switch as a compile-time constant (LDA #1) - sizeof(nint) emits the Sizeof IL opcode -> new case in the int operand handler (LDA #1) Both produce identical output: a single LDA #1 instruction. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jonathanpeppers
added a commit
that referenced
this pull request
Mar 6, 2026
Fixes #33 The 6502 is an 8-bit CPU, so IntPtr.Size returns 1. Two IL patterns are handled: - IntPtr.Size emits 'call IntPtr::get_Size()' -> handled in the Call switch as a compile-time constant (LDA #1) - sizeof(nint) emits the Sizeof IL opcode -> new case in the int operand handler (LDA #1) Both produce identical output: a single LDA #1 instruction. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jonathanpeppers
added a commit
that referenced
this pull request
Mar 9, 2026
When an intervening ldelem+stloc (e.g., byte nm = names[idx]) occurs between a value load and its dup cascade (e.g., if (st == 1) ... if (st == 2)), the stloc clears _runtimeValueInA. The dup handler now scans backward for STA TEMP () and emits LDA to reload the value. Also fixes EmitBranchCompare to handle LDA ZeroPage with ImmediateOperand (ZeroPage mode creates ImmediateOperand, not AbsoluteOperand). This fixes the climber sample where CMP #1 compared isEnemy instead of st (actor state), causing the player sprite to not render. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jonathanpeppers
added a commit
that referenced
this pull request
Mar 14, 2026
) * Fix climber gameplay: PAD constants, enemy sprites, blue platforms - Fix PAD_UP (0x08->0x10) and PAD_DOWN (0x04->0x20) to match NES controller spec - Differentiate enemy sprites from player using ai!=0 check (enemies use playerRJump/playerLJump tiles E8-EB, player keeps D8-DB tiles) - Set attribute tables to palette 1 (0x55) for blue platform colors matching the cc65 reference ROM - Update test DLLs and verified.bin snapshot - Add ANESE screenshot Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix attribute table address and simplify enemy walking sprites - Use 0x2BC0 (nametable C) instead of 0x27C0 (nametable B) for second attribute table fill, matching NTADR_A/NTADR_C usage in stage rendering - Simplify enemy WALKING to always use jump metasprite (playerRJump/ playerLJump) since enemies only move left/right - Update test DLLs and verified.bin Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Use built-in PAD enum instead of redefining constants - Remove local PAD_A/PAD_LEFT/PAD_RIGHT/PAD_UP/PAD_DOWN constants - Use PAD.A, PAD.LEFT, PAD.RIGHT, PAD.UP, PAD.DOWN from neslib Enums.cs - Change joy from byte to PAD type (pad_poll already returns PAD) - Cast to (byte)PAD.LEFT for enemy AI random byte comparison - Update copilot-instructions.md to never redefine built-in constants Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Match climber.c draw_actor: same sprites for all actors, add regression tests - Revert ai!=0 enemy sprite differentiation — original climber.c uses identical metasprites for all actors, differentiated only by palette - Add PadPollUpDown_CorrectAndValues test: verifies PAD.UP emits AND #\ and PAD.DOWN emits AND #\ (not 0x08/0x04 START/SELECT) - Add VramFillAttributeTable_CorrectAddresses test: verifies vram_adr uses \ and \ (not \) for attribute table fill Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix _padPollResultAvailable not cleared after non-pad_poll calls The AND handler reloads from _padReloadAddress when _padPollResultAvailable is true, which is correct for pad_poll results. However, the flag was never cleared after other calls like rand8(), causing subsequent AND operations (e.g., enemy direction checks: ej & 0x40) to incorrectly reload from the player's joy address instead of the enemy's local variable. Fixed by clearing _padPollResultAvailable in the call return value handler for any non-pad_poll call. pad_poll sets its own flag before this code runs, so the check is safe. Added regression test PadPollAndRand8_IndependentAndOperations. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address code review: differentiate enemy/player sprites, rename test Enemies now use jump sprites for STANDING/WALKING states while the player keeps stand/run animations, matching the reference ROM behavior. Renamed PadPollUpDown_CorrectAndValues → PadPollUpDown_UsesCorrectAndImmediateOperands for clarity. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix dup cascade stale register bug and add regression test When an intervening ldelem+stloc (e.g., byte nm = names[idx]) occurs between a value load and its dup cascade (e.g., if (st == 1) ... if (st == 2)), the stloc clears _runtimeValueInA. The dup handler now scans backward for STA TEMP () and emits LDA to reload the value. Also fixes EmitBranchCompare to handle LDA ZeroPage with ImmediateOperand (ZeroPage mode creates ImmediateOperand, not AbsoluteOperand). This fixes the climber sample where CMP #1 compared isEnemy instead of st (actor state), causing the player sprite to not render. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix EmitBranchCompare stripping runtime SBC/ADC instructions When _runtimeValueInA is true, WriteLdc returns without emitting LDA #imm. EmitBranchCompare's default path blindly called RemoveLastInstructions(1), which removed the preceding computation (SBC, ADC, AND) instead of an LDA. This caused ladder climbing proximity checks like: (byte)(actor_x[pi] - ladx) < 16 to lose the SBC instruction, making the check always fail. Fix: only remove the last instruction if it's actually LDA Immediate. Also adds SubThenCompare_RuntimeSubNotStripped regression test and updates climber verified.bin snapshot. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add nametable attribute computation for correct ladder/item colors After floor rendering, briefly turn PPU off to write nametable attributes via direct VRAM access. Floor surface rows (dy <= 1) use palette 1 (teal blocks), all other rows use palette 0 (yellow ladders/items). This replaces the TODO that noted vrambuf_put with runtime-filled arrays caused stack leaks. The fix avoids vrambuf entirely by using ppu_off + vram_adr/vram_put for direct writes during level setup. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix WriteStloc removing LDA Absolute for local-to-local copy When writing stloc for a scalar local (byte), WriteStloc's optimization would RemoveLastInstructions(1) and re-emit LDA #constant. This was correct when the previous instruction was LDA Immediate (from WriteLdc), but wrong when it was LDA Absolute (from WriteLdloc loading another local). The fix checks LastLDA before removing: if the last instruction was not LDA Immediate, just emit STA without removing the previous LDA. This fixes ladder climbing in the climber sample where 'lx = ladx' (local-to-local copy) was always storing 0 instead of the runtime value. Adds regression test LdlocStloc_LocalToLocalCopy that verifies the body of a conditional local-to-local copy emits LDA Absolute (AD xx xx) rather than LDA Immediate (A9 00). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix dup cascade stale flag and ushort hi-byte extraction Two bugs fixed: 1. _dupCascadeActive stale flag: after a dup cascade (if-else chain), the flag stayed true, causing later non-cascade dups to incorrectly emit LDA \ (TEMP_HI). Fix: clear the flag when IsDupCascadeStart() returns false for a subsequent dup. 2. Ushort hi-byte extraction (dup+shr pattern): when extracting lo/hi bytes from a ushort (dup; conv_u1; stloc lo; ldc 8; shr; stloc hi), the shr handler didn't know X still held the high byte from the original ushort computation. Fix: track via _dupPreservedUshortHi flag, emit TXA instead of 8 LSR instructions. Both bugs caused floor_yy_hi and ceil_yy_hi to be 0 instead of the correct values, preventing ladder climbing from working. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address review: rename isEnemy to actorType, use nameof() for pad_poll - Rename isEnemy to actorType in climber sample (reflects 3-state value: player/enemy/rescue) - Replace string literal 'pad_poll' with nameof(NESLib.pad_poll) for maintainability Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Trigger CI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix player sprite rendering: inline actor_name[ai] to avoid IL stack interleaving The C# compiler interleaved the actor_name[ai] load between the actor_state[ai] load and its dup cascade, causing the transpiler to compare the wrong value (actorType instead of st) against STANDING. Fix: use actor_name[ai] inline inside each if block instead of pre-computing to a local variable, avoiding the problematic IL pattern. Also rebuild test DLLs from updated Program.cs (11776 -> 12288 bytes) and update verified.bin snapshot. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jonathanpeppers
added a commit
that referenced
this pull request
Mar 15, 2026
- Resolve merge conflict in RoslynTests.cs (keep both ComputedArg and ByteMaxValue tests) - Add Ldsfld to nextIsLoad gate so look-ahead runs when next arg is a static field (review comment #1) - Add Xor and Div_un to binary ops list for complete stack depth tracking (review comment #2) - Strengthen ComputedArg test to assert JSR opcode (0x20) immediately before the second LDA, not just gap existence (review comment #3) 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.
No description provided.