Users browsing this thread: 1 Guest(s)
X-Zone -> Runic Softlock Fix
03-16-2023, 08:50 PM
(This post was last modified: 03-16-2023, 08:54 PM by C-Dude.
Edit Reason: Tidy code box
)
There are a pair of Vanilla bugs that have been afflicting the Beyond Chaos Randomizer. I was asked to investigate them both.
The first is the X-Zone -> Life 3 bug, which has previously been addressed by other patches and also can be dodged with a careful animation tweak.
The second is more insidious, and I have dubbed it the "X-Zone -> Runic Softlock".
The second bug is Vanilla-in-Principle, because only one enemy is ever in possession of Runic (Airforce's Bit) and without serious arbitrary code execution shenanigans there is no possible way to subject that enemy to an X-Zone cast.
This is the bug:
(1) X-Zone hides any monster it successfully strikes, regardless of if it actually KILLS the monster.
(2) A runic or enemy auto-runic monster will be struck by X-Zone, but not killed.
(3) Once hidden, an enemy cannot be selected by the player's cursor, thereby preventing completion of battle under normal circumstances.
It's not possible to address this problem directly in the Runic function, because the animation plays out AFTER all of Runic's calculations are complete.
Instead, I've solved the problem by setting a previously unused spell property bit ($11A7 bit #$04) aside as a "Don't hide character/monster" bit. This could then be referenced during the animation command to bypass the monster erasure.
When applied, a Runicking monster will appear to be caught in the X-Zone portal, but will immediately reappear once the spell is complete. Regular monsters killed by X-Zone will continue to stay vanished in the portal when they are struck.
Note that if you use this fix, you may also set the $11A7 bit #$04 manually (the ? bit in USME immediately beneath the Monster Text bit in spell data), to reuse animations for spells that should not otherwise hide their targets (such as, say, Smoke Bomb for a non-escape style spell).
The code is presented here as annotated RAW hex, because I don't feel like converting it to assembly. It currently uses the very last 43 bytes of the freespace in the $C4 bank.
The first is the X-Zone -> Life 3 bug, which has previously been addressed by other patches and also can be dodged with a careful animation tweak.
The second is more insidious, and I have dubbed it the "X-Zone -> Runic Softlock".
The second bug is Vanilla-in-Principle, because only one enemy is ever in possession of Runic (Airforce's Bit) and without serious arbitrary code execution shenanigans there is no possible way to subject that enemy to an X-Zone cast.
This is the bug:
(1) X-Zone hides any monster it successfully strikes, regardless of if it actually KILLS the monster.
(2) A runic or enemy auto-runic monster will be struck by X-Zone, but not killed.
(3) Once hidden, an enemy cannot be selected by the player's cursor, thereby preventing completion of battle under normal circumstances.
It's not possible to address this problem directly in the Runic function, because the animation plays out AFTER all of Runic's calculations are complete.
Instead, I've solved the problem by setting a previously unused spell property bit ($11A7 bit #$04) aside as a "Don't hide character/monster" bit. This could then be referenced during the animation command to bypass the monster erasure.
When applied, a Runicking monster will appear to be caught in the X-Zone portal, but will immediately reappear once the spell is complete. Regular monsters killed by X-Zone will continue to stay vanished in the portal when they are struck.
Note that if you use this fix, you may also set the $11A7 bit #$04 manually (the ? bit in USME immediately beneath the Monster Text bit in spell data), to reuse animations for spells that should not otherwise hide their targets (such as, say, Smoke Bomb for a non-escape style spell).
The code is presented here as annotated RAW hex, because I don't feel like converting it to assembly. It currently uses the very last 43 bytes of the freespace in the $C4 bank.
Code:
------------------------------------
X-Zone Runic Fix (CDude)
------------------------------------
Converts bit #$04 of Spell properties byte $11A7 (previously unused) to a "Don't hide character/monster" bit.
This bit gets set during the Runic Function, and referenced to bypass hiding a character/monster during the $F1 animation code.
C2/35A3 [Hook in Runic Function] org $0235A3
22 D5 B9 C4 JSL $C4B9D5 [Set the new "Don't hide character/monster" bit]
EA NOP
C4/B9D5 [Set the new "Don't hide character/monster" bit] org $04B9D5
A9 04 LDA #$04
0C A7 11 TSB $11A7 [Formerly unused bit on Monster Text attack byte, now "Don't hide character/monster" bit]
A9 03 LDA #$03
1C A7 11 TRB $11A7 [Displaced code, turn off text if hits and miss if status isn't set]
6B RTL
C1/E2EE [Don't hide monster] org $01E2EE
22 E0 B9 C4 JSL $C4B9E0 [Check for "Don't hide character/monster" bit
EA EA EA EA NOP #4
C4/B9E0 [Hide or don't hide monster] org $04B9E0
AD A7 11 LDA $11A7
89 04 BIT #$04 [Is our new "Don't hide character/monster" bit set?]
D0 08 BNE #$08 [If so, don't hide monster]
AD AB 61 LDA $61AB
25 10 AND $10
8D AB 61 STA $61AB [Hide monster]
6B RTL
C1/E31C [Don't hide character] org $01E31C
22 F0 B9 C4 JSL $C4B9F0 [Check for "Don't hide character/monster" bit]
EA EA EA EA NOP #4
C4/B9F0 [Hide or don't hide character] org $04B9F0
AD A7 11 LDA $11A7
89 04 BIT #$04 [Is our new "Don't hide character/monster" bit set?]
D0 08 BNE #$08 [If so, don't hide character]
AD AC 61 LDA $61AC
25 10 AND $10
8D AC 61 STA $61AC [Hide character]
6B RTL
Nice work C-Dude!
« Next Oldest | Next Newest »
Users browsing this thread: 1 Guest(s)