Miscellaneous Forums > Scripting and Reverse Engineering
FF7.exe battle routine questions
quantumpencil:
I've been going through the exe battle routines and have a few questions/observations
1: The routine at 0x5D173F chooses the damage formula to call from a pointer table located at 0x8FF1F8. This same routine calls a sub 0x5DC880 which is quite daunting, but appears to be being passed a "0" and a "1" via the stack (as is standard with cdecl calls like this) and is called both before and after the damage formula pulled from the ability data in this routine is called via function pointer. Interestingly enough I can't see where this argument is used within the sub at 0x5dC880. Due to it's size I'm not totally sure what this sub does, does but it seems to have some roll in preparing the battle context object pointed to in all damage formulas. Anyone made any substantial progress understanding this big guy?
2: The large data structure which is referenced throughout damage calculation and formula selection (and is pointed to by the pointer at 0x99CE0C) seems to contain a lot of information from my inspection, it contains at the very least attacker/target stats, ability data, and some attack flags like whether or not something crit. Has this data structure pointed to by 0x99CE0C been mapped by anyone in the modding community? I've got myself a little loader/dll injector for redirecting routines, but in order to make the redirected routines (and hopefully expose a C api for redirecting exe routines at runtime) I need a better understanding of this data structure -- it looks rather amorphous, I don't see evidence of a clear ability data struct or anything like that at the offsets which seem to correspond to ability flags (like context_ptr+ 48h, which is definitely ability power, or context_ptr + 6Ch which appears to some flags, one of which is "auto-critical")"
Thank you for your help =)
nfitc1:
I can answer both questions for you in excruciating detail, but I can only answer the first one right now since I don't have access to my notes right now.
That method you're seeing before and after the damage routine call is the additional effects handler. It has to run before the damage calculation and after to be able to influence pre damage and post damage calculation manipulation when applicable. The 0 and 1 are handled in the individual effects and will only apply if the action has an effect assigned. I had some detailed notes on the wiki if those still exist on one of the new ones.
quantumpencil:
Fantastic! So that method corresponds to the "effects" that can be assigned to an ability (Multiple Hits, Fills allied limit guages, etc)? Or do you mean additional effects more broadly.
As for the data structure referenced for calculation, I've noticed that there also appears to be a separate array of actor data structs of size 68h stored around 0x9AB070 (I think it starts here, not sure because instead of offsetting from the beginning of the struct, things are offset from the particular thing being fetched in the first actors struct), which seems to have some stats that aren't accessible from what I'm calling the "context" pointer. Target Level, Actor Status Masks, etc are often gotten by taking target ID from the context ptr and doing 68*target ID byte offset math to fetch the relevant actor data.
Now these structs are only 0x68h in size as opposed to the AI script accessible actor blocks of 0x3ff (masked addresses of 4000 - 43ff) so they clearly aren't the AI accessible actor blocks, but they also seem to be affected by changes made to the AI blocks. Do you/anyone else happen to know where information from the AI script accessible actor blocks gets gathered up into these smaller engine accessible blocks?
Depending on how that consolidation happens, I think it may be possible to implement *actual* new status effects within the engine with a nice C API. If the unused actor data (4300 - 433f) is not already being saved (via an object copy) to these blocks, they can be resized (by just relocating the data at runtime) to include new masks for new status effects, that can then be handled by damage calc, or elemental modifer routines, and possibly display visual effects =p
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ASIDE: NFTC1 btw if you want to sync IDA files (In case you have a lot of stuff labeled in it), I've got a plugin for exporting/importing the IDA db to json format for version control purposes. I'm planning to host this json file on github for modders along side this routine replacement toolkit so it's easy for any information about the .exe currently known to be accessed by anyone.
UPDATE: I've successfully replaced the physical damage routine with a routine which always deals 1 damage, and the game runs fine with it. I'd like to have some #includes (read: big structs) for all known data structures used in battle so they can be referenced in C++ in a human readable way and not as offsets. As long as the function signatures match (well, the argument counts match) so that the stack is not corrupted, we can in theory replace any function without needing to do rewrites on the exe, or worry about space constraints.
In particular, I think it will be very easy to add new formulas, once I get passed the data protection issues, we can relocate the function ptr table somewhere else in VRAM with more space and then register new formulas by function_ptr. I'll try this next while waiting for more info on data.
nfitc1:
the struct you speak of that's only 68h in size...is actually 260h in size. There's a monstrous 512 alignment after that 68h that picks back up at 200h. That's where target stats exist and it can change per target. The first 68h stays consistent for the duration of the calculation.
I love the idea of an ida to json exporter. I'd happily apply it to my database. I've marked thousands of lines and don't even remember all the changes I've made. I've annotated nearly every routine used in accuracy/damage calculation and still have to hunt through them to find details.
quantumpencil:
PM'd you about IDA-Sync =)
I'm confused:
1: Are you saying the total struct has size 0x260h or that each actor has a struct of size 0x260h? Also, as I often express myself poorly, a clarification: I'm not talking about the struct pointed to by the battle pointer in my last post (I was in the first post tho), I think that is a different struct (and that one is 260h, I think) but a separate array that is sometimes used to access target/actor data that isn't retreived from the battle pointer. Example here:
From Magic Hit formula (Intel syntax):
mov edx, BattleContextPtr
mov eax, [edx+208h]
imul eax, 68h
xor ecx, ecx
mov cl, byte_9AB0E5[eax]
This is only getting the "target id" (an integer) from the battle context_ptr and then referencing an array of contiguous structs starting somewhere around 9AB0E5 (but that's not the real start, that's the "level" of the first actor) and then getting the level of the target by offsetting 0x9AB0E5 by target_id*68h
That is in fact a contiguous array of structs of size 68h right?
Navigation
[0] Message Index
[#] Next page
Go to full version