Fix explosion position: cross-array copy in stelem.i1#230
Fix explosion position: cross-array copy in stelem.i1#230jonathanpeppers merged 3 commits intomainfrom
Conversation
…positioning The transpiler's HandleStelemI1 didn't handle the pattern arr1[i] = arr2[j] (cross-array copy with different indices). For shoot2's explosion code (exp_x[xi] = enemy_x[ei]), no LDA was emitted so the stored value was whatever was left in A from a previous operation. Added source index tracking (sourceIndex1Idx) in the ldelem scan and a new pattern handler that emits: LDX srcIdx; LDA srcArr,X; (then existing store code handles LDX dstIdx; STA dstArr,X). Co-authored-by: jonathanpeppers <840039+jonathanpeppers@users.noreply.github.com>
jonathanpeppers
left a comment
There was a problem hiding this comment.
🤖 Reviewed and verified. Approving this PR.
What I checked
Code review:
- The
sourceIndex1Idxscanning inHandleStelemI1correctly identifies the source array index from theldlocimmediately beforeldelem_u1 - The cross-array copy emission block (lines 1111-1134) correctly emits
LDX source_index; LDA source_array,Xthen falls through to the shared target store code that emitsLDX target_index; STA target_array,X - The condition ordering is correct — the cross-array handler (line 1111) only triggers when
sourceArray1Idx != targetArrayLocalIdx, so it won't conflict with the same-array self-update handler (line 1084)
6502 disassembly verification:
After a full rebuild, I disassembled the explosion assignment area and confirmed the correct cross-array copy pattern:
$8928: LDX $0382 ; X = ei (enemy index)
$892B: LDA $033B,X ; A = enemy_x[ei]
$892E: LDX $0383 ; X = xi (explosion index)
$8931: STA $036B,X ; exp_x[xi] = A ✓
$8934: LDX $0382 ; X = ei
$8937: LDA $0341,X ; A = enemy_y[ei]
$893A: LDX $0383 ; X = xi
$893D: STA $036E,X ; exp_y[xi] = A ✓
Tests: All 498 tests pass (64 analyzer + 434 transpiler).
The verified.bin update is expected — the old codegen was storing 0 (the timer check result) into exp_x/exp_y instead of loading from the enemy arrays.
|
🤖 CI is green. Ready for human review. Verified the fix by disassembling the explosion assignment area — the cross-array copy now correctly loads |
There was a problem hiding this comment.
Pull request overview
Fixes a transpiler codegen gap in stelem.i1 so assignments like arr1[i] = arr2[j] correctly load the source element before storing, resolving the wrong-position explosion bug in the shoot2 sample ROM output.
Changes:
- Extend
HandleStelemI1’sldelem_u1scan to capture the source index local (sourceIndex1Idx). - Add a cross-array element-copy emission path that loads
Afrom the source array using the source index before the existing target store logic runs. - Update the
shoot2verified ROM snapshot to reflect the corrected codegen.
Reviewed changes
Copilot reviewed 1 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/dotnes.tasks/Utilities/IL2NESWriter.ArrayHandling.cs | Adds source-index tracking and a new cross-array stelem.i1 codegen path to load A from the source array before storing. |
| src/dotnes.tests/TranspilerTests.Write.shoot2.verified.bin | Updates the verified binary snapshot for shoot2 to match the new correct ROM output. |
Only set sourceIndex1Idx when Locals.TryGetValue succeeds and the local is a scalar (ArraySize == 0). Previously, the condition also accepted untracked locals (!TryGetValue), which would throw KeyNotFoundException when the cross-array handler later accessed Locals[sourceIndex1Idx]. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
HandleStelemI1had no codegen path for cross-array element copy (arr1[i] = arr2[j]). In shoot2's collision code,exp_x[xi] = enemy_x[ei]emitted noLDA— the accumulator held garbage from the preceding branch check, so explosions rendered at wrong positions.Changes
ldelem_u1scan — capture the non-arrayldlocimmediately beforeldelem_u1assourceIndex1IdxsourceArray != targetArrayand we have a source index, emitLDX srcIdx; LDA srcArr,Xbefore the existing target store codeBefore (no value load):
After:
Original prompt
💬 Send tasks to Copilot coding agent from Slack and Teams to turn conversations into code. Copilot posts an update in your thread when it's finished.