Thursday, December 3, 2015

Decompiling Final Fantasy VII

Some years ago, I started the task of reversing back to C code the executable file from the game "Final Fantasy VII". More exactly, from the patched version 1.02.

From a technical point of view, the program is divided into major "systems":
- main dispatcher: the first system of the game, and the one that makes the transition between the others.
- field
- world map
- battle
- menu
- chocobo race[minigame]
- highway[minigame]
- roller coaster[minigame]
- submarine[minigame]
- condor fort[minigame]
- snowboard[minigame]
- credits: logo+opening and ending
- swirl: the animation before a battle
- request CD
- game over

Each system can be view as a standalone program (only one system at a time is running) and is defined by 5 callback functions:
- BEGIN: called once to initialize the system
- UPDATE: called every frame to update state and display
- END: called once to cleanup the system
- ONKEY: called in case of a keyboard event(almost never used)
- MOUSE: called in case of a mouse event(almost never used)

Some of the systems, like request CD or game over, are defined in only one ".C" file(or module), while others, like battle, can take dozens.

Those systems are pretty high-level stuff, and can rely on a big library to do the low-level tasks: file access, memory management, lists, heaps, inflating, matrix operations, graphic stuff ...

This library can be found at the runtime adresses ranging from 0x0065ec20 to 0x006bf4e0.
For music/sound, the library is between 0x0740d80 and 0x0074ba80.

Let's have a look at the WinMain:

#include "ff7.h"

#include "sw.h"

#include 



if(lolo.bp_53cc->f_9f0.f_10) {
 lolo.bp_53cc->f_9f0.f_10(lolo.bp_53cc);
 lolo.bp_53cc->f_040 += 1.0;
}
the current "REFRESH" callback is called (and some frame counter is incremented)


Then we have:
if(lolo.bp_53cc->f_020 == 0)
 C_0066059C(lolo.bp_53cc);//G_DRV_10:Flip
That is the graphic's driver's "Flip" functions is called; i.e the backbuffer which has been updated during the "REFRESH" call is presented to the used.

That is the core of the program file. Pretty simple, isn't it ?

To give you an idea of how far I went, let's say that except for the Battle system (the biggest of all), the Condor Fort system and part of the Menu system related to the battle system, I could reverse all the executable file to C source code (some parts harder to read than others) and recompile to a runnable file. Which means that the fun starts ... now !

Next time, we will take a look at the Game Over system, the simplest of all.

No comments: