øAslickproductions.org/forum/index.php?PHPSESSID=5f0fck550j2m4m2fpbtkj2vkm1&topic=2219.15e:/My Web Sites/Slick Productions - FFIV Message Board/slickproductions.org/forum/index15bc-2.htmlslickproductions.org/forum/index.php?PHPSESSID=5f0fck550j2m4m2fpbtkj2vkm1&board=8.80e:/My Web Sites/Slick Productions - FFIV Message Board/slickproductions.org/forum/index15bc-2.html.zx %h^ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈ0Pdu™OKtext/htmlISO-8859-1gzip0|Öu™ÿÿÿÿÿÿÿÿTue, 10 Mar 2020 23:55:14 GMT0ó°° ®0®P®€§²ð® %h^ÿÿÿÿÿÿÿÿDu™ 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 #15 on: May 02, 2016, 05:08:38 PM »
Something like that, yeah.

:edit:
The only problem with that solution, now that I think about it, is that the value in the accumulator isn't preserved by Function 1211, which means you might end up screwing up some of the checks that come after.
« Last Edit: May 02, 2016, 05:51:24 PM by 13375K31C43R »
"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 #16 on: May 02, 2016, 06:35:45 PM »
given C2/4BB2 is being made *more* permissive by the suggested patch, i hope this would not be an issue.
what i think could happen is the reverse:
[...]
- ..........does that bother us?

Yes, I just tested it by simply hitting Terra with Stop, and letting her Morph gauge run out during the casting animation for Stop, and her Revert does indeed slip through the time freeze. The case was the same with Quick.

...it does bother me a tiny little bit. It does shorten the time before Terra can act again slightly, since she sneaks in Revert during the duration of Stop. But that's a non-issue, it's the same with Sleep and Freeze, and it has virtually no impact on game mechanics. It's another purely graphical issue; characters frozen in time shouldn't be moving or changing form. Then again, I suppose a character frozen in ice shouldn't either...

Quote
as for waiting for the Revert on Sleep/Freeze, i've considered having C2/1211 check for those statuses, and if so, refusing to perform the final Morph tick (i.e. one where the deduction exceeds the current timer).  this should be effectively pretty similar, without trying to wrangle the disconnect between expiration and reversion that other coding approaches might have.

If I understand you correctly, this would be similar to what I do with Stop/Quick at the beginning of C2/1211, right? Except that you would allow the Morph timer to (almost) run out during Sleep/Freeze (since they aren't time Freezes) and then let it run out after Sleep/Freeze ends, to clear $3EE2 and queue Revert when it's "safe" to do so. You'd effectively be stalling Revert until it can be safely executed.

Quote
note that because this change would probably be done _instead_ of relaxing C2/4BB2, i wonder if it might allow the worse scenario you asked about above.

If you don't allow Revert to slip through time (relaxing C2/4BB2), and you don't allow it to be re-queued (ignoring $3EE2), then allowing C2/1211 to queue up Revert (and clear $3EE2) during the casting animation of Stop/Sleep/Freeze/Quick will still trigger the bug. Revert will be queued during the casting animation, but be thwarted by the status (or Quick) being in effect. When Terra can act again, she won't Revert because C2/1211 will never be called if $3EE2 is unset.

Either relaxing C2/4BB2 or ignoring $3EE2 is essentially what fixes the bug. Stalling the Morph timer during Stop/Sleep/Freeze/Quick just makes it slightly harder to trigger on accident. It doesn't even require particularly great timing if one is trying to trigger it deliberately. Those casting animations are several seconds long.
« Last Edit: May 02, 2016, 06:42:22 PM by magitek »
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 #17 on: May 02, 2016, 07:26:43 PM »
The only problem with that solution, now that I think about it, is that the value in the accumulator isn't preserved by Function 1211, which means you might end up screwing up some of the checks that come after.

Oh, you mean the other checks for bits in $3AA0,X, right after our call? You're right. :blush:

Well, it's simple enough to fit a PHA and PLA at the start and end of function C2/1211 since I'm relocating a bunch of stuff in there anyway.

Code: [Select]
C2/1156: 89 3A        BIT #$3A
C2/1158: D0 2A        BNE $1184      (If any of bits 6, 5, 4, or 2 are set in $3AA0,X ,
                                      branch to next target)
C2/115A: 89 04        BIT #$04
C2/115C: F0 1E        BEQ $117C      (If bit 3 isn't set in $3AA0,X , branch to load
                                      this target's ATB)

What do these bits do, anyway?
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 #18 on: May 03, 2016, 03:50:18 AM »
Quote from: magitek
Yes, I just tested it by simply hitting Terra with Stop, and letting her Morph gauge run out during the casting animation for Stop, and her Revert does indeed slip through the time freeze. The case was the same with Quick.

haha; or do that.  guess i overthought my test scenario.  :blush:

--------

to reiterate an earlier point: i still think it's a bad idea to drop the "JSR $0B36" for space savings.  relying on Revert to always happen doesn't sit well with me, particularly in a version where you're not relaxing C2/4BB2.  and conceptually, failure to revert shouldn't make your "fuel" depletion fail to stick.  more generally, i've come to see this issue as fairly separate of the ongoing debate on $3EE2.

--------

regarding the rest of your 5/2/16 06:35:45 PM CDT post: overall, a good summary/digestion/analysis of things, and a must-read for people new to the topic, or foggily returning weeks later.

---------

Quote from: 13375K31C43R
If I'm right, then all you need to do before queueing Revert is to make sure it's not already queued. There's a bit of code in my "Dead in the Air" Fix A that can help you out.

or something like Bit 4 of $3AA1,index for periodic damage/healing?  is Bit 3 of that byte indeed unused, or am i overlooking something?

and how'd i go so long without commenting Function C2/0A41? :/

----------

Quote from: magitek
What do these [$3AA0,index] bits do, anyway?

torment our souls with eternal hellfire?

some of those are regularly being set or unset; they'll combine multiple sets or clears at once; they'll change the combination of which bits are being altered together.  truly evil.

it's largely luck that i gave Bit 4 of $3AA0,index a chance and decoded the thing.  the madness with this byte also infests parts of others, like $3AA1 and $3204.  in fact, it mostly explains my extreme tardiness in commenting Function C2/0A41 (will upload an update eventually).  when i see another one of these damn toggles, my brain shuts down as a protective measure.  it might stall the Bank C2 progress, but it's kept me alive so far.
« Last Edit: May 03, 2016, 04:27:22 AM by assassin »

magitek

  • Antlion
  • *
  • Posts: 67
  • Gender: Male
  • Juggler
    • View Profile
Re: WIP Patch: Permanent Morph bugfix
« Reply #19 on: May 03, 2016, 08:22:49 AM »
to reiterate an earlier point: i still think it's a bad idea to drop the "JSR $0B36" for space savings.  relying on Revert to always happen doesn't sit well with me, particularly in a version where you're not relaxing C2/4BB2.  and conceptually, failure to revert shouldn't make your "fuel" depletion fail to stick.  more generally, i've come to see this issue as fairly separate of the ongoing debate on $3EE2.

If your spidey senses are tingling, I'll definitely keep this in mind. However, from what I can understand, C2/1211 always gets called every (other) frame as long as $3EE2 is set, and if only C2/0AA8 clears it, Revert is forced to happen at the soonest possible moment as long as the Morph timer is zero. The function to update Morph-related stuff (C2/0AA8) is called every turn and both clears $3EE2 and calls C2/0B36. C2/0B36 updates the Morph supply from the Morph timer ($3F30-$3F31) and that variable never changes outside of C2/1211 (except for being initialized by Morph and cleared by Revert). I can't see how waiting for C2/0AA8 to update the Morph supply would be an issue, unless you think there's another way Revert could get thwarted. Sorry if I seem hard-headed about this, I just want to make sure I didn't miss anything. :)

Now that I think of it, I suppose the battle ending would thwart Revert. Not updating the supply immediately when the timer runs out actually kind of silently fixes the problem with the timer running out during end-of-battle messages, but certain special battle endings don't update the Morph supply, such as Gau Leaping or Returning, or Shadow leaving, and in those cases the supply wouldn't get updated even if the timer ran out just as the battle ended. That's a pretty good tradeoff though, in my opinion (but it's easy to fix).

I agree that it is a separate issue though, and I've largely settled on leaving it in, since the many different issues to fix with Morph requires gobbling up some free space anyway. However, do make note that by dropping this instruction, it is possible to make a bare-bones bugfix that doesn't require any free space, which I think is of some value.

Code: [Select]
;(Decrease Morph timer.  If it's run out, queue the Revert command, unless it's already queued.)
org $C21211
REP #$20       ;(Set 16-bit Accumulator)
SEC            ;
LDA $3F30      ;(Load the morph timer)
SBC $3F32      ;(Subtract morph decrement amount)
STA $3F30      ;(Save the new morph timer)
SEP #$20       ;(Set 8-bit Accumulator)
BCS gauge      ;(Branch if it's greater than zero)
 STZ $3F31     ;(zero top byte of Morph timer.  i assume we're
               ; neglecting to zero $3F30 just to avoid adding a
               ; "REP" instruction.)
 LDA $3A7A     ;(Check current command)
 CMP #$04      ;(Is it Revert?)
 BEQ gauge     ;(This prevents queueing multiple Reverts)
 LDA #$04      ;(If it wasn't, make it Revert)
 STA $3A7A     ;(Store Revert as command)
 JSR $4EB2     ;(queue it?)
 NOP           ;padding
gauge:
LDA $3F31      ;(Load the remaining amount of morph time DIV 256, if any)
STA $3B04,X    ;(Store it to the character's Morph gauge?)
RTS

This only fixes the bug, it doesn't take care of the issues with the Morph timer being unaffected by time stoppage, the battle having ended, or even Terra not being present.


Quote
or something like Bit 4 of $3AA1,index for periodic damage/healing?  is Bit 3 of that byte indeed unused, or am i overlooking something?

Could you elaborate on this? You mean periodically queuing up Revert via another function that doesn't depend on $3EE2 being set, like C2/5A83, conditional on bit 3 of $3AA1,index being set instead? Would you then be setting that bit in C2/1211 to allow Revert to be queued up, and then clear it when Revert is executed? Essentially offloading the responsibility for Revert onto an unused bit instead of $3EE2?

Quote
and how'd i go so long without commenting Function C2/0A41? :/
Quote
when i see another one of these damn toggles, my brain shuts down as a protective measure

I think you answered your own question. :cycle:
« Last Edit: May 03, 2016, 10:23:10 AM by magitek »
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 #20 on: May 03, 2016, 08:42:12 AM »
By the way, adding in a another conditional check for Hide status before executing C2/1211 is another way of fixing the issue with the timer still ticking away even if Terra has escaped from battle (which I've now dubbed the "Runaway Esper" bug). I'm not sure if Hide status cover all the cases (Escape, BabaBreath, Sneeze, Engulf, Spiraler, Pep Up...any others?) but it does offer a convenient opportunity to check for the Freeze status at the same time, which I think makes sense. Being frozen should stop whatever energy expenditure goes on with Morph, unless you'd argue that the time limit imposed on Morph is set by higher beings and not by Terra's innate energy. Cryogenics in the FFVI world are pretty advanced.

Speaking of the Morph gauge being affected by other things than Stop and Quick - if we're arguing that time stoppage should pause the Morph gauge, then I think a case could be made that it should be similarly affected by Haste and Slow, being time magics and all. Thoughts?
Don't feed the trolls. Use proper grammar, spelling, and punctuation. Eat your vegetables.

13375K31C43R

  • Ultros
  • *
  • Posts: 675
  • Gender: Male
    • View Profile
    • Leet Sketcher's Final Fantasy III Patches
Re: WIP Patch: Permanent Morph bugfix
« Reply #21 on: May 03, 2016, 11:01:45 AM »
I'm not sure if Hide status cover all the cases (Escape, BabaBreath, Sneeze, Engulf, Spiraler, Pep Up...any others?) but it does offer a convenient opportunity to check for the Freeze status at the same time, which I think makes sense.

I think it will cover all of those cases, but I also think it will include Jump, which we don't want.

Speaking of the Morph gauge being affected by other things than Stop and Quick - if we're arguing that time stoppage should pause the Morph gauge, then I think a case could be made that it should be similarly affected by Haste and Slow, being time magics and all. Thoughts?

I had the same thought. I don't know if that's strictly necessary, but I do agree with that sentiment for the sake of consistency.
"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 #22 on: May 03, 2016, 05:13:43 PM »
re the code: save 2 bytes by going "LDA #$04 / CMP $3A7A" and dropping an instruction.

Quote
Could you elaborate on this? You mean periodically queuing up Revert via another function that doesn't depend on $3EE2 being set, like C2/5A83, conditional on bit 3 of $3AA1,index being set instead? Would you then be setting that bit in C2/1211 to allow Revert to be queued up, and then clear it when Revert is executed? Essentially offloading the responsibility for Revert onto an unused bit instead of $3EE2?

no, you'd still be queuing up Revert from the same place.  yes on clearing the bit when Revert is executed.  what it'd be doing is adopting periodic damage/healing's just-one-queued-at-a-time system (as achieved by bit 4 of $3AA1,index , but we'd use our own flag), which is more robust.

the check you're currently using will prevent multiple sequential queued Reverts, which is probably the prime offender in terms of that pause, but it'll be fooled if anything gets queued or run in between them.  obvious culprits are high-priority stuff, like statuses auto-expiring or equipment magic activations on low HP.  also, i believe a Revert that gets queued during a string of an enemy's counters (which are equal-priority, but the first actor gets precedence), as it'll wait until the monster is done to execute.  another equal-priority way: attack whacks ally with Retort, Interceptor, or Black Belt on; Revert gets queued during attack animation; counter executes and overwrites $3A7A.  really, lots of things can overwrite $3A7A (like a party of Cure Ring wearers queuing their Regen healing), so this approach has its holes.  Square's way is more thorough.  but if our only concern is aesthetics of a visible lag, and the prime offender IS being taken care of, then maybe it's not worth claiming the extra RAM bit to be more thorough.

magitek

  • Antlion
  • *
  • Posts: 67
  • Gender: Male
  • Juggler
    • View Profile
Re: WIP Patch: Permanent Morph bugfix
« Reply #23 on: May 03, 2016, 08:00:54 PM »
re the code: save 2 bytes by going "LDA #$04 / CMP $3A7A" and dropping an instruction.

Awesome. Now that check fits nice and neat within the five bytes freed from removing the instructions to clear $3EE2, and there's no need to remove the call to C2/0B36. I guess that settles that.


Quote
no, you'd still be queuing up Revert from the same place.  yes on clearing the bit when Revert is executed.  what it'd be doing is adopting periodic damage/healing's just-one-queued-at-a-time system (as achieved by bit 4 of $3AA1,index , but we'd use our own flag), which is more robust.

I don't think I follow. Where is the bit set, and where is it checked?


Quote
the check you're currently using will prevent multiple sequential queued Reverts, which is probably the prime offender in terms of that pause, but it'll be fooled if anything gets queued or run in between them.  obvious culprits are high-priority stuff, like statuses auto-expiring or equipment magic activations on low HP.  also, i believe a Revert that gets queued during a string of an enemy's counters (which are equal-priority, but the first actor gets precedence), as it'll wait until the monster is done to execute.  another equal-priority way: attack whacks ally with Retort, Interceptor, or Black Belt on; Revert gets queued during attack animation; counter executes and overwrites $3A7A.  really, lots of things can overwrite $3A7A (like a party of Cure Ring wearers queuing their Regen healing), so this approach has its holes.  Square's way is more thorough.  but if our only concern is aesthetics of a visible lag, and the prime offender IS being taken care of, then maybe it's not worth claiming the extra RAM bit to be more thorough.

I think it's fine that counterattacks get priority over Revert, it would look weird to have Terra Revert in between attacks. As for Revert getting delayed by Relic activation, periodical damage, or status expiration, that could get a little weird. The delay might be noticeable if a lot of automatic actions happen in succession and one may wonder why Terra is waiting for things that are happening to others before she transforms. Of course, it's an artifact of the battle system that things can't happen simultaneously, but there should be the illusion of things happening independently of each other, and that requires fair queueing. It's not a big issue, but I, too, appreciate when things are done right.
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 #24 on: May 03, 2016, 08:14:20 PM »
I think it will cover all of those cases, but I also think it will include Jump, which we don't want.

I didn't know Jump set Hide. :/ Oh well.

Quote
slow, haste

I think I have an idea how to accomplish that. Halve $3F32 in C2/0B01, and in C2/1211, subtract it once for Slow, twice if normal, and three times if Hasted. It doesn't exactly correspond to the way the ATB gauge is affected by Haste, but it's close enough.
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 #25 on: May 03, 2016, 09:13:42 PM »
Quote
no, you'd still be queuing up Revert from the same place.  yes on clearing the bit when Revert is executed.  what it'd be doing is adopting periodic damage/healing's just-one-queued-at-a-time system (as achieved by bit 4 of $3AA1,index , but we'd use our own flag), which is more robust.

I don't think I follow. Where is the bit set, and where is it checked?

Bit 4 of $3AA1,index is set and checked in the C2/5A83-invoked functions that queue periodic damage/healing.  it's cleared in the functions that (try to) execute the periodic damage/healing.

the hypothetical bit would be set and checked in Function C2/1211 (provided the timer has expired), and cleared in the Revert execution code.

Quote
Quote
the check you're currently using will prevent multiple sequential queued Reverts, which is probably the prime offender in terms of that pause, but it'll be fooled if anything gets queued or run in between them.  obvious culprits are high-priority stuff, like statuses auto-expiring or equipment magic activations on low HP.  also, i believe a Revert that gets queued during a string of an enemy's counters (which are equal-priority, but the first actor gets precedence), as it'll wait until the monster is done to execute.  another equal-priority way: attack whacks ally with Retort, Interceptor, or Black Belt on; Revert gets queued during attack animation; counter executes and overwrites $3A7A.  really, lots of things can overwrite $3A7A (like a party of Cure Ring wearers queuing their Regen healing), so this approach has its holes.  Square's way is more thorough.  but if our only concern is aesthetics of a visible lag, and the prime offender IS being taken care of, then maybe it's not worth claiming the extra RAM bit to be more thorough.

I think it's fine that counterattacks get priority over Revert, it would look weird to have Terra Revert in between attacks. As for Revert getting delayed by Relic activation, periodical damage, or status expiration, that could get a little weird. The delay might be noticeable if a lot of automatic actions happen in succession and one may wonder why Terra is waiting for things that are happening to others before she transforms. Of course, it's an artifact of the battle system that things can't happen simultaneously, but there should be the illusion of things happening independently of each other, and that requires fair queueing. It's not a big issue, but I, too, appreciate when things are done right.

Relic activation and status expiration are put in an uber-high-priority queue on purpose, so Revert waiting makes total sense.

to be clear, i have no objection to the fact that other things can be queued and/or executed in between Revert's queuing and execution.  i was pointing out that in doing so, they overwrite $3A7A, and thus thwart your method of checking for "is Revert already queued?".  a system that follows the Squaresoft one i've mentioned would not be fooled by this.

but as i've acknowledged, the $3A7A check does get rid of the major pause contributor of multiple sequential queued Reverts, so it might be good enough for our goals, even if not fully robust.

-------------

there is some precedent to a timer-based thing ignoring Haste and Slow: Cyan's SwdTech.  of course, it's a much-maligned ability, which multiple people patch with speed-ups or menus just to make it competitive. :P

13375K31C43R

  • Ultros
  • *
  • Posts: 675
  • Gender: Male
    • View Profile
    • Leet Sketcher's Final Fantasy III Patches
Re: WIP Patch: Permanent Morph bugfix
« Reply #26 on: May 04, 2016, 09:34:43 AM »
is Bit 3 of that byte indeed unused, or am i overlooking something?

I don't think you are. I've looked through your entire disassembly and bit 3 doesn't seem to be used or altered anywhere.
"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 #27 on: May 05, 2016, 06:10:12 PM »
Bit 4 of $3AA1,index is set and checked in the C2/5A83-invoked functions that queue periodic damage/healing.  it's cleared in the functions that (try to) execute the periodic damage/healing.

the hypothetical bit would be set and checked in Function C2/1211 (provided the timer has expired), and cleared in the Revert execution code.

You've peaked my curiosity; I'll have to try it out and see if I can get this to work. Or did you already make something like this?

Quote
there is some precedent to a timer-based thing ignoring Haste and Slow: Cyan's SwdTech.  of course, it's a much-maligned ability, which multiple people patch with speed-ups or menus just to make it competitive. :P

It always bugged me that Cyan's SwdTech gauge wasn't affected by his Speed nor Haste or Slow. Although, his charge bar is technically a type of command input, so it's different than the Morph gauge. It wouldn't make sense for it to be interrupted by Stop or Quick, since other characters don't have their command input interrupted by those. However, I still feel that there's maybe a case for it being affected by Speed and Haste/Slow, since waiting for it affects battle flow.

On another note, someone made a menu Swdtech patch? I'd like to see that. There's a patch for the SNES version by HatZen08 that allows you to select a SwdTech (via a sped-up charge bar) and have the delay simply be added to Cyan's wait timer. Since the charge bar is made redundant by it, it would be nice to select techniques from a menu, instead. I consider that patch pretty much officially sanctioned, since Square revised Bushido in the iOS remake to work exactly like that (including a menu). Despite the iOS remake being largely atrocious, that is one thing they got right.

Anyway, speaking of things being affected by Haste and Slow, the Morph gauge not being affected by Time magic isn't strictly part of the Permanent Morph bug, but since I already made it check for Stop and Quick, I figured it wouldn't be complete without doing so for Haste and Slow. I wrote some code for that, but I'm not sure I should include the changes regarding Time magic with the main Permanent Morph bugfix patch. Maybe I'll split up the patches into one with all things concerning Morph/Revert and the Morph supply being updated correctly, and make a separate Time magic patch.

The Time magic patch would fix Morph not being affected by Haste/Slow/Stop/Quick, and also get Cyan's SwdTech gauge in on the action. Any other things that aren't affected by Time magic but feel like maybe they should be?

Here's the code for allowing Morph to be affected by Haste/Slow. It's a little sloppy, but it should be ok. If you have suggestions for improving it, I'd appreciate that.

Code: [Select]
;Make Slow and Haste affect the speed of the Morph timer

hirom
;header

;--For testing-----------------------------------------------------------------
;org $C209E3
;db $7F              ;(ATB multiplier = 127 if hasted)
;You may want to change the Haste multiplier here to try this out.
;------------------------------------------------------------------------------

;Multiplication Function 2
org $C247B7
multiply:

;Modified function
org $C21214         ;(Originally: LDA $3F30 [Load the morph timer])
JMP load_timer

;Modified function
org $C21217         ;(Originally: SBC $3F32 [Subtract morph decrement amount])
subtract:
SBC $01,S           ;(Subtract the Morph decrementor on the stack)
STA $3F30           ;(Save the new morph timer)
PLA                 ;(Clean up the stack)

;New function
org $C2A65A         ;(CHANGE THIS TO WHERE YOU HAVE FREE SPACE)
load_timer:
LDA $3ADD,X         ;(ATB multiplier, 32 if Slow, 64 if normal, 84 if Haste)
STA $E8             ;(Store it for multiplication)
LDA $3F32           ;(Morph decrementor)
JSR multiply        ;(24-bit $E8 = (16-bit A * 8-bit $E8)
LDA $E8             ;(Get bottom two bytes of result)

                    ;This method is a bit sloppy, because if the result of the
                    ;multiplication is larger than 16-bit, the decrementor will
                    ;overflow and result in a very slow moving gauge.
                    ;In vanilla, the result of the multiplication will never be
                    ;bigger than 16-bit because Morph is unavailable if the
                    ;Morph supply is less than 16, which means the maximum
                    ;possible Morph decrementor = ([65535 / 16] / 8 + 1) = 512.
                    ;The Haste multiplier is 84, so 16-bit $E8 will be at most:
                    ;(512 * 84 = 43008 [= A800h]).
                   
                    ;If you change the Haste multiplier to be >127, then
                    ;having a Morph supply of 16 (the minimum) and being
                    ;Hasted will cause the decrementor to overflow.
                   
                    ;To remedy this hypothetical sitation, lower the cap on the
                    ;Morph decrementor at C2/0B27. For a 128 Haste multiplier
                    ;(double speed) set it to 511 to prevent overflow.
                    ;I'm not sure why that's set to 2048, since it should never
                    ;get that high.
                   
LSR #6              ;(Divide by 64 [the "Normal" ATB multiplier])
PHA                 ;(Push it onto the stack)
LDA $3F30           ;(Load remaining Morph timer)
JMP subtract        ;(Return from whence we came)
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 #28 on: May 05, 2016, 09:40:43 PM »
nope, i haven't made anything on the is-queued bit.

Quote
On another note, someone made a menu Swdtech patch? I'd like to see that.

oops, i must've been thinking of the iOS/Android remake, and Ronnen's Menu Blitz patch, or perhaps just prior talk of people wanting to make SwdTech use a menu.  so yes, the only SwdTech patches i know of so far are ArmorVil's and HatZen08's.

for reasons you gave differentiating that command from Morph, i don't necessarily think the two commands should be lumped into a single patch.  and while i agree that Morph honoring Haste/Slow would make sense, i'm not sure that it currently ignoring them falls into the "obvious bug" category that ignoring Stop/other-Quick does; the latter spits all over any recognition of time flow rules.  so i'm advocating for three separate patches, officially making me a pain in the ass. :P  well, actually four, given i still see merit to the C2/4BB2 relaxation method Morph fix.

Code: [Select]
;To remedy this hypothetical sitation, lower the cap on the
                    ;Morph decrementor at C2/0B27. For a 128 Haste multiplier
                    ;(double speed) set it to 511 to prevent overflow.
                    ;I'm not sure why that's set to 2048, since it should never
                    ;get that high.
                   
LSR #6              ;(Divide by 64 [the "Normal" ATB multiplier])

another way to deal with that situation:

Code: [Select]
PHX
LDX #$3F
CPX $EA         (if top byte of product is >= 64, it'll have a nonzero value
                 after routine C2/0DD1, meaning the decrementor exceeded
                 65535.)
BCC reduce_it
LDA #$0005
JSR $0DD1     (Divide 32-bit product by 64.  the product doesn't occupy
               more than 3 bytes going into this call, but the function
               operates on 32-bits.)
reduce_it:
TDC
DEC
PLX

maybe that's TOO paranoid about a hypothetical giant 24-bit decrementor, in which case the hacker just needs the "LDA #$0005 / JSR $0DD1". :)

assassin

  • Bane of Retards
  • *
  • Posts: 1,033
  • space bears are not gentle!
    • View Profile
    • My Barren Webpage
Re: WIP Patch: Permanent Morph bugfix
« Reply #29 on: May 05, 2016, 10:18:44 PM »
Quote from: magitek
If your spidey senses are tingling, I'll definitely keep this in mind. However, from what I can understand, C2/1211 always gets called every (other) frame as long as $3EE2 is set, and if only C2/0AA8 clears it, Revert is forced to happen at the soonest possible moment as long as the Morph timer is zero. The function to update Morph-related stuff (C2/0AA8) is called every turn and both clears $3EE2 and calls C2/0B36. C2/0B36 updates the Morph supply from the Morph timer ($3F30-$3F31) and that variable never changes outside of C2/1211 (except for being initialized by Morph and cleared by Revert). I can't see how waiting for C2/0AA8 to update the Morph supply would be an issue, unless you think there's another way Revert could get thwarted. Sorry if I seem hard-headed about this, I just want to make sure I didn't miss anything. :)

this is basically moot since you agreed to keep the C2/0B36 call in, but what the hey...

a possible loophole is if the Morph timer gets reduced to something like FFFFh (and then 00FFh) when a Revert-prohibiting status is in effect, and you have a VERY small Morph decrementor (e.g. 16d).  once the status is gone, Revert won't necessarily be queued right after, as the next few calls to C2/1211 won't zero Morph's timer.  should the battle end quickly, you're now hoping that the end-of-battle code calls C2/0B36.  i don't like relying on it for this, especially given there are multiple ways for a battle to end, and thus multiple holes to plug for patchmakers.

more simple scenario: just having the Revert-prohibiting status in effect through finishing the fight makes you dependent on the end-of-battle code calling C2/0B36.  but the prior example is more obnoxious, given the Morph timer initially expired _during_ battle.

and as i've said, honoring cause and effect is important.  running out of "fuel" causes Terra to Revert, not vice versa.  so making recognition of the former be contingent on the latter ignores cause and effect.

Quote
Now that I think of it, I suppose the battle ending would thwart Revert. Not updating the supply immediately when the timer runs out actually kind of silently fixes the problem with the timer running out during end-of-battle messages, but certain special battle endings don't update the Morph supply, such as Gau Leaping or Returning, or Shadow leaving, and in those cases the supply wouldn't get updated even if the timer ran out just as the battle ended. That's a pretty good tradeoff though, in my opinion (but it's easy to fix).

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.