I was just going through it and came the same realisation. It is adjusting both vLR and vPC at the same time and from there it is too late because we have already entered the loaded program.
Code: Select all
d746 0129 ld [$29] ;Execute
d747 a002 suba $02
d748 c216 st [$16] ;<-- vPC
d749 c21a st [$1a] ;<-- vLR
It should have done something like this:
Code: Select all
d746 0129 ld [$29] ;Execute
d747 c21a st [$1a] ;<-- vLR (unadjusted because RET subtracts 2)
d748 a002 suba $02
d749 c216 st [$16] ;<-- vPC (adjusted because NEXT adds 2)
One idea is then to load a tiny patch anywhere in unused RAM that sets up vLR correctly before jumping to the intended execution address. That idea is half-broken because jumping, with CALL, changes vLR and that defeats the purpose. And jumping by performing a STW into vPC doesn't work either, because NEXT doesn't reload the Y register. (The vCPU tries to keep the code page in Y when not leaving its primary page.) We need to pass REENTER to reload the vPC high byte into Y. Only instructions that escape from the primary page will do that. Looking for such vCPU instructions to abuse, I think we can do our jump with ... DOKE!
Replace the last 3 bytes in the GT1 file
with
Code: Select all
0x5b, 0x7e, 0x0e, // Patch segment, 14 bytes at $5b7e (looks nicely aligned with Loader)
0x11, 0x00, 0x02, // LDWI $0200
0x2b, 0x1a, // STW vLR
0x59, 0x16, // LDI vPC
0x2b, 0x24, // STW sysArgs0
0x11, 0xfe, 0x02, // LDWI $02fe
0xf3, 0x24, // DOKE sysArgs0
0x00, 0x5b, 0x7e, // Execute: run patch first
I quickly tested this, any now the program starts reliably on my board. \o/
Although in principle the GT1 file doesn't have to change for this (the external device can inject the patch in the last frame transmitted), it is much better to carry such patch around in the GT1 files that need it for their setup phase. Otherwise also emulators need adjustment and spreading complexity to innocent bystanders is a sign of a wrong idea.
Follow-up: The dilemma is, are we going to fix the ROM routine bug at some point in time? I tend to say "better not!", because it invites incompatibility down the road. Here we see the birth of legacy... At least what happens to vLR is well-defined, albeit a bit useless. And oh well, ROM v1 already has legacy in it: it still has a debounce delay loop for the reset button that only exists on my breadboard prototype...