Dissecting Vanish/spell

Talk about all aspects of the gameplay of Final Fantasy 3us/6j.

Moderators: General Moderator, Game Moderator

Dissecting Vanish/spell

Postby Lenophis » Tue Oct 14, 2014 6:17 pm

So I've been looking into Vanish and it allowing Doom to kill something. The aim is to make a patch so the game follows what FF6A does, the spell hits, but the status doesn't. Vanish gets removed and the target isn't killed. This seems like it is the correct behavior of how Vanish should work, so that's what I wanted to work towards.

We obviously know that the immunity isn't getting checked properly, or at all. To add to the confusion, Dessyreqt drops this reminder on me:
"Vanish and Break will miss the target."

I had forgotten about Break not working like Doom in that sense.

So into bank C2 I go. I think the only two routines that are relevant for this are going to be C2/220D and C2/4406. C2/220D is the "Determine if the attack should hit" routine, and C2/4406 is the "Determine which statuses should be applied/removed" routine.

I did a couple of tests with our best friend, the Tyranosaur. Tyranosaur is immune to both Break and Doom, so this should be an easy test. Vanish and Doom obviously kills the poor thing, while Vanish and Break do not. Careful observation shows no "miss" indicator for Vanish/Break, so I am theorizing that Break IS being applied, but dropped somewhere afterwards. This means immunity isn't being checked at all, but somehow enforced anyway with some spells?

I looked further into the Vanish/Doom scenario, and did some scrounging around C2/4406. Looking at the code...
Code: Select all
(Determine statuses that will be set/removed when attack hits;
miss if attack doesn't change target's status)

C2/4406: 08           PHP
C2/4407: C2 20        REP #$20
C2/4409: B9 E4 3E     LDA $3EE4,Y    (get current status bytes 1-2)
C2/440C: 85 F8        STA $F8
C2/440E: B9 F8 3E     LDA $3EF8,Y    (get current status bytes 3-4)
C2/4411: 85 FA        STA $FA
C2/4413: 20 90 44     JSR $4490      (Initialize intermediate "status to set" bytes in
                                      $F4 - $F7 and "status to clear" bytes in $FC - $FF.
                                      Mark Clear / Freeze to be removed if necessary.)
C2/4416: E2 20        SEP #$20
C2/4418: A5 B3        LDA $B3
C2/441A: 30 04        BMI $4420      (if not Ignore Clear)
C2/441C: A9 10        LDA #$10
C2/441E: 14 F4        TRB $F4        (remove Vanish from Status to Clear)
C2/4420: B9 95 3C     LDA $3C95,Y
C2/4423: 10 18        BPL $443D      (Branch if not undead)
C2/4425: A9 08        LDA #$08
C2/4427: 2C A2 11     BIT $11A2
C2/442A: F0 11        BEQ $443D      (Branch if attack doesn't reverse damage on undead)
C2/442C: 4A           LSR
C2/442D: 2C A4 11     BIT $11A4
C2/4430: F0 0B        BEQ $443D      (Branch if not lift status)
C2/4432: AD AA 11     LDA $11AA
C2/4435: 89 82        BIT #$82
C2/4437: F0 04        BEQ $443D      (Branch if attack doesn't involve Death or Zombie)
C2/4439: A9 80        LDA #$80
C2/443B: 04 FC        TSB $FC        (mark Death in Status to set)
C2/443D: C2 20        REP #$20
C2/443F: A5 FC        LDA $FC
C2/4441: 20 32 0E     JSR $0E32      (update Status to set Bytes 1-2)
C2/4444: A5 FE        LDA $FE
C2/4446: 19 E8 3D     ORA $3DE8,Y
C2/4449: 99 E8 3D     STA $3DE8,Y    (update Status to set Bytes 3-4)
C2/444C: A5 F4        LDA $F4
C2/444E: 19 FC 3D     ORA $3DFC,Y
C2/4451: 99 FC 3D     STA $3DFC,Y    (update Status to clear Bytes 1-2)
C2/4454: A5 F6        LDA $F6
C2/4456: 19 10 3E     ORA $3E10,Y
C2/4459: 99 10 3E     STA $3E10,Y    (update Status to clear Bytes 3-4)
C2/445C: AD A7 11     LDA $11A7
C2/445F: 4A           LSR         
C2/4460: 90 1B        BCC $447D      (if "spell misses if protected from ailments" bit
                                      is unset, exit function)
C2/4462: A5 FC        LDA $FC   
C2/4464: 05 F4        ORA $F4
C2/4466: 39 1C 33     AND $331C,Y    (are there any statuses we're trying to set or clear
                                      that aren't blocked?)  (bytes 1-2)
C2/4469: D0 12        BNE $447D      (if there are, exit function)
C2/446B: A5 FE        LDA $FE
C2/446D: 05 F6        ORA $F6
C2/446F: 39 30 33     AND $3330,Y    (are there any statuses we're trying to set or clear
                                      that aren't blocked?)  (bytes 3-4)
C2/4472: D0 09        BNE $447D      (if there are, exit function)
C2/4474: B9 18 30     LDA $3018,Y
C2/4477: 8D 48 3A     STA $3A48
C2/447A: 0C 5A 3A     TSB $3A5A      (Spell misses if protected from ailments)
C2/447D: 28           PLP
C2/447E: 60           RTS

It seems like there's 3 or so logic errors in this routine. A breakdown of the routine reads like so, if I'm reading this correctly:
1) Initialize some scratch RAM so we know what we're trying to set and clear.
2) Is "Vanish" being ignored? Remove it from the list of status being cleared if so.
3) Is the target undead?
3a) Is the attack reversing damage on undead? (Like Cure, poison, etc)
3b) Is the attack removing a status? (Life, etc)
4) Is the attack involving the statuses death or zombie? Add death as a status to set if so. It seems like this point can never be reached?
5) Update statuses to set and clear in bytes 1, 2, 3, and 4.
6) Is "Miss if protected from ailments" CLEAR? Exit if so. We don't want to bother checking immunity if there's no need, after all.
6a) Load status bytes 1 and 2 to set and also status to clear. Are ANY of these statuses not blocked? In other words, the 2-way immunity rule should apply here. Skip checking bytes 3 and 4 and exit if any aren't blocked.
6b) Load status bytes 3 and 4 to set and also status to clear. Are ANY of these statues not blocked? Exit if so.
7) Load this entity and set a flag in $3A48 and $3A5A to flag a miss on this target.
8) Exit goes here.

I believe the flaws are in the ordering of steps 5, 6, and 7. Five will set/clear the status without bothering to check if the target is immune, although it's possible another routine down the road checks for this. Since death is applied, I'm doubting this theory. I think step 6 gets the branch logic backwards, and I believe Square may have gotten confused with their double-negatives again, a la Genji Glove damage reduction.

Am I crazy thinking this routine is all messed up?

Image
I ended up looking into C2/220D more, thanks to Dessyreqt just kinda driving the point home. I managed to optimize enough of the routine to make Vanish behave as I wanted/FF6A's way and the spell still misses. A patch will be forthcoming.
Image
Lenophis
Veteran
Veteran
 
Posts: 588
Joined: Sat Mar 26, 2005 5:52 am
Location: Duluth, MN

Re: Dissecting Vanish/spell

Postby Lenophis » Mon Oct 20, 2014 2:38 pm

Here is the patch. It's a dropbox link for now, since the site is going to be undergoing some maintainence soon. This patch isn't fully tested, and this patch doesn't have any changes in the C2/4406 function yet. Still working on what should be tweaked there.

If anyone that downloads it could test it out to make sure I didn't break anything, that would be awesome. :D
Image
Lenophis
Veteran
Veteran
 
Posts: 588
Joined: Sat Mar 26, 2005 5:52 am
Location: Duluth, MN

Re: Dissecting Vanish/spell

Postby Assassin » Mon Oct 20, 2014 4:32 pm

- C2/4406 doesn't need to be edited.

- the reason you can have Vanish+Break yield no "Miss" message yet the target still not be petrified is:
a) C2/4406 skips flagging a miss if a status was changed; Clear being removed fits the bill.
b) entities can be inherently immune to Petrify status. in contrast, they cannot be inherently immune to Wound status without being bloody immortal. so Vanish+Doom will behave differently than Vanish+Status_spell (e.g. Break, Mute, Muddle). not to mention, there are non-fatal spells in the instant death "class" (e.g. Demi).

-----------

- as i mentioned on AIM, i started work on a patch in October 2013 with 4 goals in mind (besides fixing the primary bug, and making Vanish be removed like you favor):

  1. address the Vanish+Life bug. the code's in the same area, and this bug has yet to be fixed, so it makes sense to do it here.

  2. avoid a problem with terii senshi's patch:
    "also, i just found an issue in terii's patch. casting Doom on an Instant Death-protected, Reflective target, will just give a simple "Miss!". in the original game, the spell will reflect. i understand why the patch does this (it reorders code), but i consider it screwy, and an unnecessary side effect (though a remedy might involve using extra space; the horror)."

  3. avoid a problem with the GBA remedy:
    "[GBA] has oddity that if you use Reflect+Vanish on instant death-protected enemy, the damn spell (whether Death or normal one like Fire) will reflect before unvanishing the foe. on non ID-protected enemies (as well as on SNES in general), vanish trumps reflect, so the (Fire) spell hits. this oddity sounds familiar, because i remember saying how ZED was finally right about witnessing Reflect trumping Vanish -- a hallucination he had on SNES/ROM years before the GBA version ever came out."

  4. finally, Square has a check to make L.X spells remove Vanish even if they miss. i plan to narrow this so it won't do so for hypothetical physical L.X attacks -- just relevant for hacks.

there's not much point to making a new patch if you don't get these things right. and i can't imagine getting them right _and_ fitting everything inline.

you seemed to agree with me on proper behavior of #1-3 on AIM a year ago.

#4 is up for the most debate, because it raises the issue of how fictional physical L.X attacks should behave on Clear targets more generally. should they even be able to hit them? this hinges on why Square has L.X spells miss a Vanished target whose level doesn't match. is it because:
a) the success was meant as Vanish-agnostic? in that case, if Clear doesn't ensure that magical L.X hits, it shouldn't ensure that physical L.X misses.
b) the level check was meant as an extra barrier to success (but not to failure)? in that case, physical L.X would miss a Vanished target just like anything else physical would.

i realize this is entirely speculative, on account of there not BEING any physical L.X attacks :? , but i was hoping for your input (and anybody else's).

W-I-P code to follow.
User avatar
Assassin
Moderator
Moderator
 
Posts: 1195
Joined: Tue Sep 14, 2004 5:10 am

Re: Dissecting Vanish/spell

Postby Assassin » Mon Oct 20, 2014 5:53 pm

Code: Select all
; NOTE: C2/2217 and C2/221E will need their branches changed,
;  probably to label "continue".

org $C22220

LDA $11A2
LSR
BCS no_magic_vanish_remove   ; branch if physical

LDA $3DFC,Y
ORA #$10
STA $3DFC,Y    ; mark Clear status to be cleared.  that way,
               ;  it'll still be removed even if the attack
               ;  misses and C2/4406, which is what normally
               ;  removes Clear, is skipped.

no_magic_vanish_remove:

LDA $11A4
BIT #$40
BNE continue     ; Branch if L.X spell

BCS $22B5          ; miss if physical, as target is Vanished
JSR high_priority  ; do Instant Death, and Dead XOR Undead checks
BRA $22B3          ; hit or miss, depending on result of function call

continue:

; next 9 lines unchanged aside from branch sizes, and being shifted
LDA $11A3
BIT #$02       ; Check for not reflectable
BNE no_refl    ; Branch if ^
LDA $3EF8,Y
BPL no_refl    ; Branch if target does not have Reflect
REP #$20       ; set 16-bit accumulator
LDA $3018,Y
TSB $A6        ; turn on target in "reflected off of" byte
JMP $22E5      ; Always miss if target has Reflect

no_refl:

JSR high_priority  ; do Instant Death, and Dead XOR Undead checks

BCS $22B5      ; miss if any didn't pass

; might have up to 17 NOPs here, since i dunno how to relocate
;  just part of the 32-byte high_priority function.

; rest of function unchanged
; C2/2268: A5 B5        LDA $B5
; C2/226A: C9 00        CMP #$00
; ...

; -----------

high_priority:
; (somewhere in free space...)

SEC            ; assume missed to start
LDA $11A2
BIT #$02       ; Check for spell miss if instant death protected
BEQ next       ; Branch if not ^
LDA $3AA1,Y
BIT #$04
BNE missed     ; Always miss if Protected from instant death
next:
LDA $11A2
BIT #$04       ; Check for hit only (dead XOR undead) targets
BEQ hit
LDA $3EE4,Y
EOR $3C95,Y    ; death status XOR undead attribute
BPL missed     ; If neither or both of above set, then miss
hit:
CLC            ; indicate it could hit
missed:
RTS


best-case scenario, that takes 15 extra bytes; worst case, 32 [!]. it depends on how much of the added function i can relocate. it's a bitch with all the relative branches.
User avatar
Assassin
Moderator
Moderator
 
Posts: 1195
Joined: Tue Sep 14, 2004 5:10 am

Re: Dissecting Vanish/spell

Postby Lenophis » Tue Oct 21, 2014 11:56 am

Assassin wrote:i realize this is entirely speculative, on account of there not BEING any physical L.X attacks :? , but i was hoping for your input (and anybody else's).

I still agree with every point. Making the L.x attacks behave accordingly does seem like the logical thing to do, since even in a hypothetical situation, they would end up ignoring the game's intended (sic) logic. I gave you the code I came up with in an AIM message. I will admit I did not test Vanish+Reflect/spell with this code, since it never occurred to me. I won't be able to look at this today, but I'll have all day off tomorrow to fiddle around.

I guess my little patch can be Randomizer-specific, but if a better patch comes along, we'll gladly use that. :D
Image
Lenophis
Veteran
Veteran
 
Posts: 588
Joined: Sat Mar 26, 2005 5:52 am
Location: Duluth, MN

Re: Dissecting Vanish/spell

Postby Djibriel » Fri Nov 07, 2014 12:11 pm

As long as you're out there fixing all that's wrong with Vanish in this world, it has always bugged me that the animation for the Vanish spell contains the character turning transparant. When the spell is absorbed through Runic, the character turns invisible before *BAM* joke's on you. You weren't invisible. You were the opposite of that.
"The population in Iraq is over 80% Shi'ite. Couldn't the same be said about your music, Mr. Durst? "
User avatar
Djibriel
Regular User
Regular User
 
Posts: 354
Joined: Wed Sep 08, 2004 3:45 pm
Location: Outsider!

Re: Dissecting Vanish/spell

Postby Imzogelmo » Fri May 20, 2016 4:56 pm

Bump
User avatar
Imzogelmo
Veteran
Veteran
 
Posts: 659
Joined: Wed Sep 08, 2004 4:07 pm
Location: On the spirtual plane

Re: Dissecting Vanish/spell

Postby Assassin » Sat May 21, 2016 1:53 pm

regarding Djibriel's post: Leet Sketcher has fixed that:
http://l33t5k37ch3r.altervista.org/#vanish_runic

regarding Vanish/Doom redo: whatever i release shouldn't have too many pointless NOPs (though it will definitely use free space):
http://slickproductions.org/forum/index ... 8#msg24078

and there'll likely be a larger "tweak" variant to address the linked issue (which falls under questionable balance rather than bug).
User avatar
Assassin
Moderator
Moderator
 
Posts: 1195
Joined: Tue Sep 14, 2004 5:10 am

Re: Dissecting Vanish/spell

Postby Imzogelmo » Tue Jun 14, 2016 1:59 pm

I'm trying to get a handle on the possible variants in this code, from Vanilla to Terii's venerable fix, to assassin's WIP and possible tweaks to it, (that is, the Undead+ID-protected tweak and the physical L.X tweak).

I'm making a file that should, in theory, allow all the variants in one file, with a single byte to select which one you want. Should make testing easier.
User avatar
Imzogelmo
Veteran
Veteran
 
Posts: 659
Joined: Wed Sep 08, 2004 4:07 pm
Location: On the spirtual plane

Re: Dissecting Vanish/spell

Postby Assassin » Wed Jul 20, 2016 2:12 am

i was able to relocate and be NOP-free. also, a 3-byte optimization was had with Lenophis' help back on 10/22/2014. (he came up with a couple more later in the function, but i'm avoiding for now so as to invade as little as possible.)

http://assassin17.brinkster.net/forum-p ... locate.asm

and with the optional tweak to stop Fenix Down/etc. insta-kills of undeads who have "Protected from instant death" set:

http://assassin17.brinkster.net/forum-p ... dition.asm

the 3-byte optimization couldn't be kept, but the new code allowed another with a "LDA $11A2" drop. (and i avoided duplicating the $3AA1,Y check.) this version is still a bit heavy on free space use, though.

if you don't want protection against Revivify and co. to hinge on that property, but perhaps on some custom one, it shouldn't be too hard to adapt. you'll lose a couple optimizations, but then should be able to regain the initial 3-byte one.

as usual, everything is untested.
User avatar
Assassin
Moderator
Moderator
 
Posts: 1195
Joined: Tue Sep 14, 2004 5:10 am

Re: Dissecting Vanish/spell

Postby Lenophis » Sun Jan 08, 2017 1:35 am

I helped with that? Jeez, I have no memory of it :(

In any event, it's awesome that potential-game-breaking bugs are getting crushed, 23 years after the game's initial release. :D
Image
Lenophis
Veteran
Veteran
 
Posts: 588
Joined: Sat Mar 26, 2005 5:52 am
Location: Duluth, MN


Return to FF3 Gameplay Discussion

Who is online

Users browsing this forum: No registered users and 1 guest

cron