Author Topic: [FF7] Vincent Mug Glitch *EXPLAINED AND SOLVED*  (Read 9376 times)

nfitc1

  • *
  • Posts: 3011
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
[FF7] Vincent Mug Glitch *EXPLAINED AND SOLVED*
« on: 2014-10-22 20:58:45 »
If you've been keeping up with all my posts on things (I don't blame you if you haven't. Most of them are pretty technical) then you know I've been reversing the animation scripts in the AB files. I'd provide links to these, but I'll just re-provide relevant info here.

So, about the VMG:

WHAT IS IT?
There's an entire article on Final Fantasy wikia about it. Basically, if Vincent performs a Mug with the Shortbarrel, Winchester, Long Barrel R, Sniper CR, or Death Penalty equipped then the next action's effects are entirely skipped, but the action will still take place and do damage/heal. This includes items, summons, magics, enemy attacks, damage indicators, et al. This is so well known that it's a legitimate speed running tactic for skipping summons like Ultimate End.

WHY IS IT?
This is a three-fold explanation.

First of all it's important to understand that Vincent has three battle models. Yep, three. One for shotguns, one for pistols, and one for rifles. It's the rifle one that's bugged so we'll focus on that. Each of these has an animation file associated with it. The glitched one is SHAB. These AB files have pointers to animation scripts that tell the engine how to act (I'll get to that in part two). This particular one has a single byte different in its mug script compared to the others. For reference, this is script 36 in 0-based decimal. They each have different arguments to their F7 code and this one is set to 18 decimal.

Secondly, let's talk about what animation code F7 does. Each AB script code gets run in "chunks" between the animations. Valid codes start at a value of 8Eh and any value below that is considered an animation index (not to be confused with animation script index). This particular function tells the game to queue the damage indicator (how much damage has been done), the 2D strike effect, and the sound associated with the action to play in X frames.

Finally, let's talk about thread. More specifically, how the game handles all these effects. As some of you may know from my previous posts, there are thread queues for 2D and 3D effects in battle. Their handlers are queued when the effect starts and they are self-terminating (they remove themselves from the queue when they are done). the damage indicator is actually a 2D effect that runs for 11 frames. While this script is running the "animation thread indicator" is set to active because there are still effects in the queue. Once the animation is complete it marks the thread as complete and the effect queue as empty for the next animation to come around.

HOW IS IT?
Have you spotted the problem yet? If not, don't blame yourself. The QA team at Square didn't either. Here it is: The animation finishes before the effect starts. In fact, the animation ends on the same frame that the effect gets added to the queue. This is a problem. If the effect had started before the animation finishes then it would be cleaned up at the end of the animation. Because animation frames (and by extention, scripts) are handled BEFORE effect handlers this effect doesn't get correctly associated with the animation script. The animation script thread is marked as complete and ready to accept the next animation, but the effect queue is still marked as in-use. When the next animation comes it runs the script, but can't queue anything because it's not granted access to queue anything. All the mechanics still run in the background though so enemies are marked as dead, poisoned, or whatever. And at the "end" of the animation script (that doesn't actually do any animating) everything is correctly marked as empty/complete.

SOLUTION:
There are actually several solutions to this. By far the easiest is to DECREASE the delay the F7 creates (as mentioned above). Even decreasing this by one frame is enough to prevent this glitch. The following solution works for all PC versions of the game:

1. Open the ff7/battle/battle.lgp file in a hex editor.
2. Search for the case-sensitive ascii string "SHAB" without quotes.
3. Search for the byte sequence 17h 1Ch from the point you found the SHAB.
4. The byte preceding the 17h should be 12h. My mostly-unaltered battle.lgp file has this at address 0x3A7D7F2.
5. Change this 12h to something less. I tried 0Ch and it looks nice.

Problem solved! The effect is queued before the animation completes and the animation correctly associates the damage indicator with the animation script. Now everything gets cleared correctly and the summons can no longer be skipped.
« Last Edit: 2014-11-18 16:21:54 by NFITC1 »

Vgr

  • Global moderator
  • *
  • Posts: 2163
  • If it quacks like a duck, it must be a duck
    • View Profile
Re: [FF7] Vincent Mug Glitch *EXPLAINED AND SOLVED*
« Reply #1 on: 2014-10-22 21:18:22 »
Whoa, that's badass. Pretty awesome finding there NFI!

obesebear

  • *
  • Posts: 1389
    • View Profile
Re: [FF7] Vincent Mug Glitch *EXPLAINED AND SOLVED*
« Reply #2 on: 2014-10-22 21:55:25 »
Nice find.  I didn't even know that was a thing.

nfitc1

  • *
  • Posts: 3011
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
Re: [FF7] Vincent Mug Glitch *EXPLAINED AND SOLVED*
« Reply #3 on: 2014-10-22 22:04:18 »
Nice find.  I didn't even know that was a thing.

I didn't either until I saw it listed in the TASing tricks for this game.

obesebear

  • *
  • Posts: 1389
    • View Profile
Re: [FF7] Vincent Mug Glitch *EXPLAINED AND SOLVED*
« Reply #4 on: 2014-10-22 22:07:43 »
Well if we're fixing the problems with FF7, I think I heard that the PC world map battles aren't random.  I'll see if I can find a link

It's field battles
http://speeddemosarchive.com/FinalFantasy7.html  Segment 19
« Last Edit: 2014-10-22 22:11:19 by obesebear »

nfitc1

  • *
  • Posts: 3011
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
Re: [FF7] Vincent Mug Glitch *EXPLAINED AND SOLVED*
« Reply #5 on: 2014-10-23 19:38:11 »
Well if we're fixing the problems with FF7, I think I heard that the PC world map battles aren't random.  I'll see if I can find a link
World Map battles are actually nicely random. It's based on the OS's RNG and is seeded by time the game is loaded AND cycles upon moving between map polygons. It's probably the only truly random game-play mechanic in the game. ;)

It's field battles
http://speeddemosarchive.com/FinalFantasy7.html  Segment 19
Yep. The randomization here sucks. I see how it works and it's not random at all. There's a method at 0x60B2A7 that is used for determining the next encounter and whether or not it will be a special encounter (pre-emp, back attack, etc) if that's allowed. It works like the KERNEL.BIN's RNGLUT that just pulls a byte from a hard-coded table and uses that value to determine which formation in the field is the one to be encountered. The problem is the pointer to that table is a single byte that is only incremented when an encounter happens. Since this always inits as 0, any battle in a given field will always be the same on hard-resets. After querying the RNGLUT it increments this pointer by 1 and never touches it until the next battle. This is where the "randomness" falls apart. It should be using something else like, the game's timer fraction to point at the table. THAT would introduce a great degree of randomness to it:

Code: [Select]
CurrentRandEncLUT = (GameTimerFraction >> 2) AND 255  //this manipulation is required to get the full range in a byte because the fraction is increased by 1092 each tic.
Now it's based on a moderate-frequency timer (goes through all 256 values in ~4.25 seconds) and will likely NEVER be the same between resets. Frequency of encounters would still be handled the same so that wouldn't change.

Xinlus

  • *
  • Posts: 20
    • View Profile
Re: [FF7] Vincent Mug Glitch *EXPLAINED AND SOLVED*
« Reply #6 on: 2014-10-24 16:56:05 »
Thanks for the fix!

In PSX the file is/ENEMY6/ VINSENT3.LZS and the adress is 0x7840 of the decoded file.

nfitc1

  • *
  • Posts: 3011
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
Re: [FF7] Vincent Mug Glitch *EXPLAINED AND SOLVED*
« Reply #7 on: 2014-10-24 18:35:49 »
Thank you! I was hoping someone would provide that info.