[FF7PSX NTSC-U/C/PAL-UK] MDef bug fix

  • Thread starter Thread starter Gemini
  • Start date Start date
Status
Not open for further replies.
G

Gemini

Guest
Yesterday I made a very small patch that corrects one of the most infamous bugs on this game: the spirit+m.def bug. Works for both NTSC U/C and PAL UK versions (see readme for specific compatibility).

Notice the difference? :-)
bug-a-nugen.png
 
Last edited:
This looks promising; I'm going to try it. Of course, one can use wall market to add spirit to armour, but this way is much nicer and neater ;-)
 
But that's not hacking or fixing, it's cheating. :evil:
Boooo! I resent that. . . . . Actually, no I don't. You're absolutely right. :) This is a great development. Something that's been needed for a while. Can this be done for the PC version(s) as well?
 
But that's not hacking or fixing, it's cheating. :evil:
You're right. It's not hacking or fixing, but making the exact same spr on equipment as mdef will have the exact same effect as this patch (unless I'm missing something :P). Good to see someone actually fixing this annoying bug!
 
Same effect, really. This is just more of a... "proper?" way to do it, and looks cleaner since it doesn't jack your spirit up in the stat screen. Technically it can lead to a higher overall magic defense since you can stack M.Def over top of 255 spirit (if you collect the boosters), if for whatever reason you wanted to do that.

For those wanting a fix for the PC *cough* better *cough* version, Wall Market CAN be used without having to get into the nuts and bolts of the game, but it's a poor man's method. Spirit's only function is magic defense. M. Def is basically a second Spirit stat that combines with it for your over all defense against magic.
 
So, has anyone worked out how to make a PC version of this yet? I forgot to make ISOs of my FF7 PSX discs when I was home over Christmas *facepalm* and I don't take my PSX games to uni, so I can't really find out what it changes. Would making a PC fix be as easy as comparing the modded and unmodded files from the PSX game in a hex editor and then searching for the hex values that were changed in the PSX version in ff7.exe, or is that stupid, n00bish nonsense?
 
Psx and PC code are encoded into two entirely different binary languages (MIPS R3000 vs x86)... There is no way a simple search could lead to *anything*.
 
Oh dear. I was worried that something like that would be the case :-(
 
The easiest way to find out how to fix it for the PC is to figure out where the armor is being equipped and follow that logic. Only thing is, I don't even know how to use debuggers. Can anyone suggest one? I've got one called IDA, but it's confusing.
 
The easiest way to find out how to fix it for the PC is to figure out where the armor is being equipped and follow that logic. Only thing is, I don't even know how to use debuggers. Can anyone suggest one? I've got one called IDA, but it's confusing.
Ollydbg?

http://www.ollydbg.de/

Afaik, it is used for cr...ing of programs.. Not sure though. :P
 
I'm getting closer to finding the routine that updates the stats. I found the one that switches the Armor index for the character and the memory address that that's stored at, but now I have to find the actual MDef memory address and see what SHOULD be writing to that.

EDIT: The problem exists around binary address 0x1CE8F7. That's where it calls the function that (should) applies armors' MDef to the character. It uses that same function for Def, Def%, and MDef%. So the problem is probably in the set up or saving. That is between 0x1CE8F0 and the command at 0x1CE8FF where it writes memory to the word located at 0xBF7F3A.

That's as far as I got today. I'll try a little more later now that I found the location of the errant call (I think).
 
Last edited:
So the problem is probably in the set up or saving.
The function that applies M.Def takes 2 parameters, a first one that I never cared to look into, and a second one that determines which value to retrieve. 0 returns a strenght bonus, 1 is for vitality, while 2 and 3 return 0 no matter what. 2 is the one that corresponds to M.Def, so you have to add a case for that, and the procedure is pretty much similar to case 1. Taken from the readme of my patch:
Code: [Select]
Code:
.org 0x800104C4 spirit_fix:   sll     v0, a3, 2   addu    v0, a0   lw      v1, 0(v0)       ; character id   nop   sll     v0, v1, 5       ; *132   addu    v0, v1          ; --   sll     v0, 2           ; --   la      at, 0x8009C621  ; armor pointer   addu    at, v0   lbu     v1, 0(at)       ; armor id   nop   sll     v0, v1, 3       ; *36   addu    v0, v1          ; --  sll     v0, 2           ; --   la      at, 0x80071D2B  ; pointer to spirit value   addu    at, v0   lbu     a2, 0(at)       ; load spirit   j       @@return   move    v0, a2
 
Last edited:
It's the 2 that's causing the problem? I was focusing on the 1. This may be a problem with how it's stored in the armor data and displayed on the menu. In the menu it goes Def, Def%, MDef, then MDef% while in the data it's stored Def, MDef, Def%, MDef%.  It looked to me that the 0, 1, 2, and 3 were getting the data stored at (armormemoryaddress + ArmorIndex + EquippedArmorIndex * 36 + 2 + x)  then applying it to characterIDmemory + something. I'm still not sure what that something was. The function was often returning 0 in some AX register that doesn't show up in the general registers in my debugger. I'll try to follow it more closely today. I'll be able to look at it again in about an hour so I'll check it out then.
 
It looked to me that the 0, 1, 2, and 3 were getting the data stored at (armormemoryaddress + ArmorIndex + EquippedArmorIndex * 36 + 2 + x)  then applying it to characterIDmemory + something.
0 takes data from just weapons, 1 from armors, 2 and 3 return a NULL value no matter what. Unless they changed the code for that function during the port process, but I doubt so.
 
It looked to me that the 0, 1, 2, and 3 were getting the data stored at (armormemoryaddress + ArmorIndex + EquippedArmorIndex * 36 + 2 + x)  then applying it to characterIDmemory + something.
0 takes data from just weapons, 1 from armors, 2 and 3 return a NULL value no matter what. Unless they changed the code for that function during the port process, but I doubt so.
OK, I see what you're saying now. What happens in this function is that it adds the weapon's atk to the character's strength to get the new attack power and stores it...somewhere (haven't looked into that yet). Then it takes the armor's Def and adds it to the players Vit to get the defense, but it never even looks at the MDef of the armor. For the other things, Atk%, Def%, and MDef% it just uses whatever the weapon/armor has for those values during damage calculation so those never really get stored anywhere on the characters' data. It's starting to make me wonder if there is even a place for "adjusted MDef" on the character's immediate data... That's something else to look into. *sigh* and I was hoping that it was just an incorrect pointer. :( It looks like just a small injection might work, but that gets hairy because all the absolute addresses would be changed.
You're right though. Passing 2 or 3 just makes it 0 it's other argument and return. Weird. Maybe at one point there were two accessory slots?

UPDATE: I've narrowed the problem down! The problem IS with that function. That function applies Equipment changes to the variables that damage calculation use for Atk, Def, MAtk, MDef and happens every time a weapon/armor/accessory is equipped.
This is what happens:

1. Character ID and update type (0-Atk; 1-Def; 2-MAtk; 3-MDef) is passed to this function
2. The function does one of four things depending on the update type:
      0. It gets the Weapon's Atk and assigns that number to a temporary Atk based on character ID which is later added to str to get the final attack
      1. It gets the Armor's Def and assigns that number to a temporary Def based on, etc.
      2. It does NOTHING. This is where MAtk WOULD get updated, but since no equipment modifies MAtk (might modify Magic stat instead) this is just skipped and always returns a 0.
      3. Same as #2

The case for update type 1 does this:
Code: [Select]
Code:
.text:006C51AD loc_6C51AD:                             ; CODE XREF: ApplyBonusStats+2Aj.text:006C51AD                 mov     eax, [ebp+var_8].text:006C51B0                 mov     ecx, dword_919928[eax*4].text:006C51B7                 imul    ecx, 84h.text:006C51BD                 xor     edx, edx.text:006C51BF                 mov     dl, byte_DBFDA9[ecx].text:006C51C5                 imul    edx, 24h.text:006C51C8                 xor     eax, eax.text:006C51CA                 mov     al, byte_DBCCE2[edx].text:006C51D0                 mov     [ebp+var_4], eax.text:006C51D3                 jmp     short loc_6C51E5
The case for update type 3 SHOULD be this: (ignore the addresses, it shouldn't overwrite condition 1)
Code: [Select]
Code:
.text:006C51AD loc_6C51AD:                             ; CODE XREF: ApplyBonusStats+2Aj.text:006C51AD                 mov     eax, [ebp+var_8].text:006C51B0                 mov     ecx, dword_919928[eax*4].text:006C51B7                 imul    ecx, 84h.text:006C51BD                 xor     edx, edx.text:006C51BF                 mov     dl, byte_DBFDAE[ecx].text:006C51C5                 imul    edx, 24h.text:006C51C8                 xor     eax, eax.text:006C51CA                 mov     al, byte_DBCCE3[edx].text:006C51D0                 mov     [ebp+var_4], eax.text:006C51D3                 jmp     short loc_6C51E5
but of course, it's not. This would require replacing a 7-byte statement with a 40 byte block. I don't know how to safely inject code so it might be better to do it your way, Gemini. An absolute jump to anywhere takes 5 bytes so either followed by two no-ops, or a re-targeted relative jump. So point me to an unused spot in the executable and I can fix it for ya. XD Of course, I'll have to test this theory out.


NEW UPDATE: I have successfully patched the PC executable to account for the MDef of the Armor! See proof. I have submitted my changes to dziugo who will make it compatible with YAMP. Hopefully, it'll be done this weekend.
I did end up using Gemini's method because code injection's a pain to attempt and this worked just fine. I haven't tested it in battle yet because I don't have a very suitable save to test it. Anyone want to donate a save with the airship and normal stats so I CAN test it?
 
Last edited:
@ Gemini and NFITC1: Wonderful!  This'll be great!  Though imo, unless you've modded the scene to make the enemies harder, this just makes an already-too-easy game even easier.  Still, at least now there's actually a good reason to equip certain armor such as that Wizard Bracelet.
 
Last edited:
@ Gemini and NFITC1: Wonderful!  This'll be great!  Though imo, unless you've modded the scene to make the enemies harder, this just makes an already-too-easy game even easier.  Still, at least now there's actually a good reason now to equip certain armor such as that Wizard Bracelet.
I was thinking this too after I got it to work. There was a difference done, but it wasn't great. The magic attack has to be powerful in order for it to be very devastating. Barret with 34 Spirit was attacked with Fire3 by Cloud who had a magic of 255 (teehee). He took around 7300 damage wearing the Bronze Bangle (0 MDef) and around 6200 dmg wearing the Wizard Bracelet (85 MDef). I thought the patch wasn't working right until I remembered that the Wizard Bracelet and most weapons increase the Magic stat. :) So now the PC version (at least the v1.02 US version) has a fix for it!
I just left a message with dziugo saying that his YAMP patch worked. So we'll probably get an additional patch for it soon. I've got a link, but I don't know if he wants me to share that one or not. We'll know soon, I hope.
 
Hi @ all,

First of all i must thank you for the great work!

Second one is a favour i ask for, becouse i`m from germany i use the PAL/German version of the game and the patch PAL/US didn`t work. The game simply ignore it....
Well to simply ask you people to make it work for me isnt me style so i hope you can help me a little to try it my self eg. let me know whot file i have to edit ore some hintes for the adress to look for it.

Many thx in advance to you guy`s

Shadow
 
Status
Not open for further replies.
Back
Top