Skip to content

Setup CI with Github Actions#1

Merged
jonathanpeppers merged 11 commits intomainfrom
github-actions
Dec 8, 2021
Merged

Setup CI with Github Actions#1
jonathanpeppers merged 11 commits intomainfrom
github-actions

Conversation

@jonathanpeppers
Copy link
Copy Markdown
Owner

No description provided.

@jonathanpeppers jonathanpeppers merged commit ded4f95 into main Dec 8, 2021
@jonathanpeppers jonathanpeppers deleted the github-actions branch December 8, 2021 23:13
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant