øAslickproductions.org/forum/index.php?PHPSESSID=5f0fck550j2m4m2fpbtkj2vkm1&topic=2219.30e:/My Web Sites/Slick Productions - FFIV Message Board/slickproductions.org/forum/indexdb89.htmlslickproductions.org/forum/index.php?PHPSESSID=5f0fck550j2m4m2fpbtkj2vkm1&board=8.80e:/My Web Sites/Slick Productions - FFIV Message Board/slickproductions.org/forum/indexdb89.html.zx %h^ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈ ,/>OKtext/htmlISO-8859-1gzip8:Ö>ÿÿÿÿÿÿÿÿTue, 10 Mar 2020 23:55:14 GMT0ó°° ®0®P®€§²ð® %h^ÿÿÿÿÿÿÿÿ±2> WIP Patch: Permanent Morph bugfix

Author Topic: WIP Patch: Permanent Morph bugfix  (Read 8421 times)

13375K31C43R

  • Ultros
  • *
  • Posts: 675
  • Gender: Male
    • View Profile
    • Leet Sketcher's Final Fantasy III Patches
Re: WIP Patch: Permanent Morph bugfix
« Reply #30 on: May 05, 2016, 10:40:32 PM »
I notice a bunch of command pointers at C2/1A03 that seem to get called automatically (Enemy Roulette, periodic damage/healing, timed status removal etc.). There are also some pointers in there that just jump to RTS. Maybe you could find a way to leverage one of those RTS pointers.
"Do not meddle in the affairs of wizards, for they are subtle and quick to anger." -Gildor from The Lord of the Rings

assassin

  • Bane of Retards
  • *
  • Posts: 1,033
  • space bears are not gentle!
    • View Profile
    • My Barren Webpage
Re: WIP Patch: Permanent Morph bugfix
« Reply #31 on: May 05, 2016, 11:05:08 PM »
don't those commands' executions still make use of Function C2/13D3, and thus its "JSR ($19C7,X)"?

13375K31C43R

  • Ultros
  • *
  • Posts: 675
  • Gender: Male
    • View Profile
    • Leet Sketcher's Final Fantasy III Patches
Re: WIP Patch: Permanent Morph bugfix
« Reply #32 on: May 05, 2016, 11:43:16 PM »
Yes. Is that a problem?
"Do not meddle in the affairs of wizards, for they are subtle and quick to anger." -Gildor from The Lord of the Rings

assassin

  • Bane of Retards
  • *
  • Posts: 1,033
  • space bears are not gentle!
    • View Profile
    • My Barren Webpage
Re: WIP Patch: Permanent Morph bugfix
« Reply #33 on: May 06, 2016, 12:00:29 AM »
guess i didn't follow your post, and thought you were suggesting that the pointers to automatically-called commands could also be re-used.

regarding just the RTS pointers: how much can be done with 10 bytes, particularly when only 6 are contiguous?  can you elaborate on how they might be leveraged?

13375K31C43R

  • Ultros
  • *
  • Posts: 675
  • Gender: Male
    • View Profile
    • Leet Sketcher's Final Fantasy III Patches
Re: WIP Patch: Permanent Morph bugfix
« Reply #34 on: May 06, 2016, 12:07:13 AM »
Well, currently five of those pointers jump to RTS, meaning they don't actually do anything. My idea is, instead of relying on the Morph timer depletion function to queue Revert, write a new function that checks to see if various conditions hold, i.e. is the Morph gauge empty, is Terra still Morphed, is she not asleep or Frozen etc. before queueing Revert. Then add a pointer to replace one of those five RTS pointers. In other words, this new function serves as the middle man, and the depletion function queues it instead of Revert.

The mindset is, seeing as how Enemy Roulette always kicks in immediately after someone's turn finishes (assuming the target was determined while something else was going on), treating Revert the same way seems logical.
"Do not meddle in the affairs of wizards, for they are subtle and quick to anger." -Gildor from The Lord of the Rings

magitek

  • Antlion
  • *
  • Posts: 67
  • Gender: Male
  • Juggler
    • View Profile
Re: WIP Patch: Permanent Morph bugfix
« Reply #35 on: May 06, 2016, 09:14:25 PM »
i realize you're just thinking aloud here, but nooooo... :P  don't try to rely on one flaw to balance out another.  the various end-of-battle issues *are* tackle-able, such as with your $3EE2-clearing fix.  maybe with my proposed C2/5C54 call added on.

It's as simple as inserting a call to C2/0B36 (or C2/4903) at the end of function C2/47FB. At least for Gau Leaping/Returning; I haven't tested any others.

Speaking of that scamp, Gau, try using Leap, then quckly use a Potion (or any item). Gau will Leap, and the Potion will be gone even though it didn't get used. Gau illegitimately restoring your Morph supply hardly makes up for him taking your items and running off with them. :P
I thought calling C2/4903 would fix this, but I was mistaken...

And in other news, I took Leet Sketchers suggestion to move the call to C2/1211 and built on it, fixing the problem with the Morph timer not stopping when Terra is no longer present in battle (having ran away, for example).

Code: [Select]

org $C21211
dec_morph_timer_check:

org $C21184
next_target:

org $C21143
LDA $3AA0,X
LSR
BCS is_present
JMP clear_morph ;---------> clear_morph:
                            ;CPX $3EE2
                            ;BNE not_morphed:
                            ;LDA #$FF
                            ;STA $3EE2
                            ;not_morphed:
                            ;JMP next_target
is_present:
PHA                         ;(Preserve accumulator [C2/1211 overwrites it])
JSR check_morph ;---------> check_morph:
                            ;CPX $3EE2
                            ;BNE is_present_not_morphed
                            ;JSR dec_morph_timer_check
                            ;is_present_not_morphed:
                            ;RTS
PLA                 ;(Restore accumulator [if overwritten by C2/1211])

$org $C2A65A ;wherever the free space is
clear_morph:
CPX $3EE2
BNE not_morphed:
LDA #$FF
STA $3EE2
not_morphed:
JMP next_target

check_morph:
CPX $3EE2
BNE is_present_not_morphed
JSR dec_morph_timer_check
is_present_not_morphed:
RTS
Don't feed the trolls. Use proper grammar, spelling, and punctuation. Eat your vegetables.

magitek

  • Antlion
  • *
  • Posts: 67
  • Gender: Male
  • Juggler
    • View Profile
Re: WIP Patch: Permanent Morph bugfix
« Reply #36 on: May 06, 2016, 10:16:10 PM »
By the way, I found an awesome menu patch for Swdtech and Blitz in this very forum: http://slickproductions.org/forum/index.php?topic=1902

I'd like to modify it to separate Swdtech from Blitz, though.
Don't feed the trolls. Use proper grammar, spelling, and punctuation. Eat your vegetables.

assassin

  • Bane of Retards
  • *
  • Posts: 1,033
  • space bears are not gentle!
    • View Profile
    • My Barren Webpage
Re: WIP Patch: Permanent Morph bugfix
« Reply #37 on: May 07, 2016, 01:51:28 AM »
1) try the "For What Ails Ya" patch from this website.  it fixes that sort of bug, though I don't recall offhand whether Leap was accounted for.

EDIT: nope, it doesn't directly address end-of-battle code.

not sure why your C2/4903 call wouldn't work.  where in C2/47FB are you putting it?  try in C2/48E0.  you'll want to do it before C2/4936 is called, because that's what copies the in-battle Item menu to the more persistent Item list.[/EDIT]

2) ah, i knew it!  my subconscious must have remembered LightPhoenix's expansion.
« Last Edit: May 07, 2016, 06:57:01 AM by assassin »

magitek

  • Antlion
  • *
  • Posts: 67
  • Gender: Male
  • Juggler
    • View Profile
Re: WIP Patch: Permanent Morph bugfix
« Reply #38 on: May 07, 2016, 10:52:20 AM »
not sure why your C2/4903 call wouldn't work.  where inC2/47FB are you putting it?  try in C2/48E0.  you'll want to do it before C2/4936 is called, because that's what copies the in-battle Item menu to the more persistent Item list.

I see. I was hooking the jump at the very end, since Leap/Return branches to there. I'll try hooking it earlier in the function and change the branches for Leap/Return.
Don't feed the trolls. Use proper grammar, spelling, and punctuation. Eat your vegetables.

assassin

  • Bane of Retards
  • *
  • Posts: 1,033
  • space bears are not gentle!
    • View Profile
    • My Barren Webpage
Re: WIP Patch: Permanent Morph bugfix
« Reply #39 on: May 07, 2016, 07:45:57 PM »
i don't think you want to do it until you actually know Gau is Leaping or re-joining, which is why i recommended in C2/48E0.  do it too early, and it might be called twice.

magitek

  • Antlion
  • *
  • Posts: 67
  • Gender: Male
  • Juggler
    • View Profile
Re: WIP Patch: Permanent Morph bugfix
« Reply #40 on: May 07, 2016, 10:01:49 PM »
Someone kill me. I figured I'd try just a simple rework of the Morph Haste/Slow code: modifying C2/01B1 C2/0B01 to set the Morph decrementor to (255 * ATB Multiplier + 2) / Morph Supply / [4 or 2]) + 1, and then calling that code from C2/09D2 to update it when the ATB Multiplier changes.

I've been trying to get that to work for the best part of the day. My brain just isn't working today.
« Last Edit: May 07, 2016, 11:48:24 PM by magitek »
Don't feed the trolls. Use proper grammar, spelling, and punctuation. Eat your vegetables.

assassin

  • Bane of Retards
  • *
  • Posts: 1,033
  • space bears are not gentle!
    • View Profile
    • My Barren Webpage
Re: WIP Patch: Permanent Morph bugfix
« Reply #41 on: May 07, 2016, 11:30:52 PM »
i hope you meant C2/0B01 and not C2/01B1.

and i see a problem with calling that if Hasted or Slowed mid-Morph: it'll calculate the decrementor based off the old Morph Supply.  why not stick with your old May 5th code of keeping the decrementor, and modifying a copy as needed in C2/1211?

magitek

  • Antlion
  • *
  • Posts: 67
  • Gender: Male
  • Juggler
    • View Profile
Re: WIP Patch: Permanent Morph bugfix
« Reply #42 on: May 08, 2016, 12:03:17 AM »
I did mean C2/0B01. I'm pretty tired.

and i see a problem with calling that if Hasted or Slowed mid-Morph: it'll calculate the decrementor based off the old Morph Supply.

I see that as working as intended. The gauge shouldn't change speed mid-Morph other than from Haste/Slow status, and what was established when executing Morph should still be the base speed until Terra Reverts. The supply isn't updated until Morph has ended, which is what makes this approach even possible. This way mirrors the function of my other patch, I just think it's a little more elegant to update the Morph decrementor along with the ATB multiplier, as they are very similar in function and use.

Quote
why not stick with your old May 5th code of keeping the decrementor, and modifying a copy as needed in C2/1211?

Cruel fate, why dost thou mock me so. I actually don't see a problem with doing it that way, I just wanted to see if I could get this slightly more elegant way to work. It seems like such a simple task, but alas, it has become my nemesis and I am vanquished by it.
Don't feed the trolls. Use proper grammar, spelling, and punctuation. Eat your vegetables.

assassin

  • Bane of Retards
  • *
  • Posts: 1,033
  • space bears are not gentle!
    • View Profile
    • My Barren Webpage
Re: WIP Patch: Permanent Morph bugfix
« Reply #43 on: May 08, 2016, 01:20:37 AM »
you're right.  i got myself confused somehow.  maybe i thought you'd be using the current Morph timer, rather than always 255, on later calls to C2/0B01.

i'm not sure how you're reworking a function that normally exits whenever there's a Morpher in $3EE2.  best post your code.

a well-timed Haste or Slow casting might mitigate the problem of the "a possible loophole ..." scenario laid out in my May 5th post.  the now-recalculated, post-timer-expiration Morph decrementor will be rather large, so that will minimize the wait for a follow-up Revert to be queued.  (a wait that should really be infinitesimal or nonexistent, so this is an improvement, however weird).

i appreciate you trying to not waste cycles with constant calculations, and recognize your striving for parallelism with the ATB multiplier, but that variable only gets its value from one source.  the hypothetically-reworked Morph decrementor gets its value from TWO separate sources, so maybe it's best to keep a backup of the thing and modify a copy like you were doing, since those sources can change independently of each other.

again, i can be more useful if you post your code.

magitek

  • Antlion
  • *
  • Posts: 67
  • Gender: Male
  • Juggler
    • View Profile
Re: WIP Patch: Permanent Morph bugfix
« Reply #44 on: May 08, 2016, 09:17:06 PM »
I finally got this thing working and cleaned up the source and comments. It's complete, and almost ready for release (I just have to relocate some code). I've removed all the swearing from the comments but I hope my sense of frustration is still imbued in the code. :P

With this, and the nonstandard battle endings updating the Morph supply, I think my Morph mega-fix is mostly complete. I still have to follow that lead on the Revert queueing bit from Assassin for a possible improvement to the main bugfix, but unless anyone knows of some other oddities with Morph, I will compile all the fixes into one .asm file in the coming week and produce some IPS patches. God, I dread writing the documentation for this. :angry:

On a side note, does xkas support calling or branching to straight addresses instead of labels? I keep declaring my labels using "org $address" and then put nothing but my label in there, just so I can jump or branch to that address. If I'm just making a call and not inserting code, can't I just type in the address? I can never get that to work but maybe I'm doing it wrong. :/

Quick description: I modify C2/0B01 so it can be called upon to either initialize Morph or to just update the Morph decrementor, which now factors in the ATB multiplier. Then I hook the ATB recalculation call to a tiny new function that tells the end-of-turn function at C2/083F to update all Morph-related stuff whenever the ATB variables are recalculated (when Haste/Slow status is changed, for example).

Or, well, that's what it will do when it's completely finished. For now, it does something kind of hackish and silly instead.   :omghax:

Code: [Select]
;Morph timer affected by Haste and Slow, v2

;This sets the Morph decrementor in init_morph, then calls init_morph
;every time ATB variables are recalculated (When Haste and Stop is
;set or removed, for example.


hirom
;header
!freespace = $C2A65A

;Change Haste multiplier for testing
org $C209E3
db $80                    ;(Haste multiplier = 2x speed)

;Can't be too careful...
!phaxyp = "PHA : PHX : PHY : PHP"
!plpyxa = "PLP : PLY : PLX : PLA"

;hook
org $C2089D
JSR newfunc

;freespace
org !freespace
newfunc:
JSR recalc_atb
!phaxyp         ;Preserve all the registers
CPX $3EE2       ;Exit if target isn't Morphed
BNE end

;The proper way

;LDA #$80
;ORA $3204,X
;STA $3204,X    ;Always call C2/0AA8 after setting ATB variables
                ;So, at battle start and whenever Haste/Slow changes and maybe
                ;some other times

;To use this, we need to modify init_morph to set 16-bit A both in set_morpher
;and update_decrementor, but there's no room for an extra "REP #$20" without
;relocating parts of that function.


;The silly way
           
;BRA end        ;(ignore this; used for testing the above)
REP #$20        ;We need to set 16-bit A so update_decrementor works,
                ;but init_morph loads $3EE2, expecting it to be 8-bit
                ;What do...?
SEP #$10
LDY $3EE3       ;(Commandeer Y to preserve $3EE3 briefly)
TDC
STA $3EE2       ;We only care about the n flag being clear, so zero $3EE3
JSR init_morph  ;Now init_morph won't reset the Morph timer
STY $3EE3       ;Restore $3EE3
end:
!plpyxa
RTS


;Start Morph timer and establish amount to decrement it
org $C20B01
init_morph:
PHX
PHP
LDA $3EE2

;(New code, 2 bytes added)
BMI set_morpher ;If no one is morphed, set morpher, init timer, and set decrementor
;(Modified code)
BRA set_decrementor ;If somone is, only update decrementor
;(End of new and modified code)

;Unchanged code, for reference)
set_morpher:
LDA $3EBB
LSR
LSR
ROR
BCS exit        ;(Exit function if bit 2 of $3EBB is set..
                ; Set for just Phunbaba battle #4 [i.e. Terra's
                ; second Phunbaba encounter])
ASL             ;(Put Bit 1 into Carry)
STX $3EE2       ;(store target in X as Morphed character)
TDC
REP #$20        ;(Set 16-bit Accumulator)
DEC             ;(A is $FFFF)
STA $3F30       ;(Morph timer = 65535)
;(End of unchanged code)

;(New code, adds 9 bytes [total: 11 bytes])
set_decrementor:
;REP #$20        ;This should be here, but my silly code handles it for now
LDA #$FF00
ORA $3ADD,X     ;Low byte holds ATB multiplier, high byte holds FFh
JSR multiply16  ;(16-bit A = FFh * ATB multiplier)
;INC #2         ;(Division is a bit inaccurate, would this help?
;(End of new code)

;(Shifted code)
LDX $1CF6      ;(Morph supply)
JSR divide     ;((ATB Multiplier * 255) / Morph supply) (16-bit A / 8-bit X)
BCC upgrade    ;(Branch if bit 1 of $3EBB not set.
               ; This bit is set in Terra's 2nd Phunbaba battle
               ; [i.e. Phunbaba #4], and lasts afterward.  So
               ; Terra gains some resolve here. ^__^)
LSR            ;(A = (255 * ATB multiplier + 2 / Morph supply) / 2 [pre-Phunbaba])
upgrade:
LSR            ;(A = (255 * ATB multiplier + 2 / Morph supply) / 4 [post-Phunbaba])
;(End of shifted code)

;(Removed code, for reference. Removes 11 bytes)
;LSR
;LSR
;CMP #$0800 
;BCC nocap
;LDA #$07FF     ;(this will cap amount to decrement morph time
;               ; counter at 2048)
;               ;
;               ;Removed for space. Morph is disabled unless Morph
;               ;supply is at least 16, in which case amount to decrement
;               ;will be at most 512 (old), or 2033 (new).
;               ;Old: (65535 / 16) / 8 + 1 = 512)
;               ;New: ([255 * 255 + 1] / 16) / 2 + 1 = 2033
;               ;That's with the Haste multiplier being maxed.
;nocap:
;INC            ;Sacrificed to make that extra branch, for now
;(End of removed code)

;(Unchanged code, for reference)
STA $3F32      ;(Amount to decrement morph time counter)
exit:
PLP
PLX
RTS
;(End of unchanged code)


;Called addresses (for labeling)
;Multiplies low byte of A * high byte of A.  Stores result in 16-bit A.
org $C24781
multiply16:

;Divides 16-bit A / 8-bit X
;Stores answer in 16-bit A.  Stores remainder in 8-bit X.
org $C24792
divide:

;Recalculate ATB
org $C209D2
recalc_atb:


;Notes:

;$3EE2 is set in init_morph unless its already set
;(and only ever in init_morph)
;init_morph is called whenever C2/0AA8 discovers Morph status on target
;C2/0AA8 is called once whenever bit 1 of 3204,X has been set
;bit 1 of 3204,X is set whenever C2/23ED detects target is morphed (via $3EE2)

;So it goes:
;if C2/23ED detects target is morphed, set bit
;if bit is set, clear it and call C2/0AA8
;(always update menu)
;if target has Morph status, call init_morph
;   if $3EE2 is clear
;      set $3EE2, and set timer and decrementor
;   if $3EE2 is set
;      set decrementor only
;if no Morph status
;   clear $3EE2, timer, and gauge, and update supply
« Last Edit: May 08, 2016, 09:47:04 PM by magitek »
Don't feed the trolls. Use proper grammar, spelling, and punctuation. Eat your vegetables.