Qhimm.com Forums

Miscellaneous Forums => Scripting and Reverse Engineering => Topic started by: RoSoDude on 2025-02-09 00:23:38

Title: [FF7 PSX] ATB Recommended/Wait Pause Logic
Post by: RoSoDude on 2025-02-09 00:23:38
I have become rather obsessed with the intricacies of the Active Time Battle system in Final Fantasy games. In particular, I find it very interesting how and when the games decide to pause ATB; FF4, FF5, and FF8 all pause during battle animations, while FF6 and FF9 let ATB run in the background (to rather deleterious effects). FF7 is in the middle; in Active mode it works like FF6/9, while in Recommended/Wait mode it works more like FF4/5/8... but with some notable quirks.

The FF7 manual states the following for ATB Recommended: "For moderately skilled players. Time stops while the screen effects are displayed when using Magic and Items."

Yeah, turns out it's much, much more complicated than this. In an earlier post (https://forums.qhimm.com/index.php?topic=14938.msg250010#msg250010) on the issue, Sega Chief theorized that animation sequences had "hooks" to tell the battle engine to pause ATB, but these hooks were getting missed somehow due to menus. This seemed like a plausible theory since I myself had noticed that ATB pausing was inconsistent; sometimes ATB would pause after the startup phase of a spell command, while sometimes it would keep running. Limit Breaks usually fail to pause ATB, but if ATB was already paused going into a limit break, it would stay paused. I decided to go into the debugger to work it out myself, and see if I could fix any "bugs" in the code. It turns out this theory about animation sequences is totally wrong, and ATB pausing is broken by design rather than by any coding bugs.

The basic conditions for ATB pausing are:


The animation timer is the tricky part here. First of all, the increment is determined by the Battle Speed, in particular Speed_mod = (65536/(2*(120+(480*Bat_Spd)/256)). Once each frame (at 60fps), this Speed_mod is added to the timer. For example, if the Battle Speed is 0 (fastest), the increment is 273 and so the timer takes 1 second to reach 16385; if Battle Speed is 128 (default), the increment is 91 and the timer takes 3 seconds; if Battle Speed is 255 (slowest), the increment is 54 and the timer takes 5 seconds. This is why you can sometimes see basic attacks pause ATB on the fastest Battle Speed, but you will never see this on slower settings.

More importantly, the timer only increments under specific conditions, and frequently resets before it can reach [1-5] seconds. Let's break it down further. The animation timer only ticks up if the variable I'm calling the "pause flag" is equal to 0x0003, and the timer is usually reset when the pause flag is changed. Here's how it works (the following applies only to Recommended/Wait mode):


Taking it all together, we can explain some common scenarios with ATB (assuming default Battle Speed):

We can glean several goals of this ATB design from the implementation. In addition to keeping the command queue from getting backlogged, a primary goal is to maintain relatively equal turn counts between players and enemies. Active mode's turn dynamic already does this, but characters spend a lot of time waiting with queued moves while status effects tick away. A secondary goal is to maintain the flow of battle in contrast to the strict animation pausing of FF4/5/8, such that turns come up during animations like in FF6/9/Active but without the balance drawbacks that these bring. A final goal is to make this all scale with the Battle Speed setting, such that the ATB pauses more often at high Battle Speed but less often at low Battle Speed. However, despite these reasonable goals, the implementation is a bit of a failure in my view, since there are so many conditions that reset (or fail to set) the timer that the ATB pause ends up feeling random and unpredictable, which is not ideal for strategic gameplay.

I will be updating this thread later with commented MIPS disassembly that details the implementation. I already programmed a patch which simplifies the system; I removed the check for player/enemy turn counts and set the pause flag on all attacks (whether player, enemy, or limit break) to 0x0001 always, and pause ATB as soon as the pause flag is updated to 0x0003 by a character getting full ATB. This puts a greater emphasis on the effect of Dexterity on character speed (rather than equalizing turn counts), and lets ATB flow until the next move is ready to go onto the queue.