Author Topic: What do we know about the FFVII battle script language?  (Read 1808 times)

Bosola

  • Fire hazard!
  • *
  • Posts: 1752
    • View Profile
    • My YouTube Channel
FFVII's battles run on a fairly powerful scripting system that has been explored in serious depth on these forums. We know a lot about

- the script format;
- data addressable within scripts;
- the runtime that actually executes the scripts

But I don't think we know a lot about how scripts were authored.

I think it's reasonable to say the FFVII battle planners did not work in the bytecode format, manually entering numeric opcodes or calculating jump offsets. These people were designers, script writers, and artists. They needed something far more human-friendly.

For a bit of context, here's some FFVII battle bytecode

Code: [Select]
70 0123 ; jump to 0123 - I have to keep on top of this offset
12 2070 ; push address of "target mask"
02 20A0 ; read value of "opponents mask"
90 ; store, clear stack
60 03 ; push "summon" command
60 3F ; push "Bahamut" ID
92 ; summon bahamut on action queue, clear stack

Some things I think we know about these scripts:

- Square probably had a DSL (domain specific language) adapted from previous titles, and managed by the core programmers of BATTLE.X for assisting with battle scripts
- These scripts could probably be authored with and linked to other battle data, making it simpler to re-use them
- Square anticipated some things going wrong with these scripts - thus the DATA ERROR fallback condition - but only implemented rudimentary error detection in BATTLE.X (example: if you run 86 "MP cost" for an attack ID not in the scene, the game just crashes)
- Debugging was enough of a concern that there's an opcode (A0) that pushes sprintf format lines to the debug console (I think dev PlayStations had a mechanism for the BIOS to push this text to an attached TTY)

Things we could speculate:

- Square had existing tooling coming off of FFVI, but their goals for VII were much more ambitious. They may have sought a ground-up rethink of battle authoring
- Square wouldn't have had the benefit of modern language toolkits, but that wouldn't stop them implementing simple languages. FORTH in particular is a natural fit for a stack-based programming model
- They may have used latin characters in their scripts just for convenience with the operating systems and tooling of the time
- As far as I know, there is no documentation around about how Square wrote their battle scripts for FFVII, or any of the other PSX era games
- The focus of a scripting language is rapid iteration and ease of use. There would be only simple validation, basic control flow, and a lightweight compilation step.

Some ideas in my head:

- it is not very clear to me how battles exactly were developed. Was it possible to execute an ad-hoc battle on a running debug console? Was it even possible to flash battle and character scripts over the serial port? It would seem risky to do "hot reloading" as the battle engine would not tolerate scripts being rewritten in-place, but perhaps some other form of rapid dev loop was possible
- would the DSL have been upfront about the stack based data structure, our would it have attempted to disguise it with variables? The latter seems to add complexity and disguise the constraints of the platform.
- authors would have probably not have had to worry about "types" (bits / counts of bytes). And the DSL probably provided something like if conditions over jumps

What do we know? What can we speculate? It's something I've been thinking about a lot

Quid?

  • *
  • Posts: 46
    • View Profile
Re: What do we know about the FFVII battle script language?
« Reply #1 on: 2023-05-09 15:15:25 »
I often think about it myself since I am doing a lot of AI scripting. I can't picture the original devs working with raw stacks of opcodes of course, though I don't have any insight on what tool and scripting langage they used while making the games.

I think we will never know but it likely was a text and friendlier format as you speculate.
If
Then Do
Else
And so on.

I got used to FFVII battle opcodes, but I probably never would have even tried to if most of the decoding groundwork hadn't been done here by giants. Sorry I don't have more good ideas than you on how the original devs worked.

Tirlititi

  • *
  • Posts: 874
    • View Profile
Re: What do we know about the FFVII battle script language?
« Reply #2 on: 2023-05-09 20:56:41 »
I naturally picked a scripting format that looks like C when decompiling FF9 scripts (and IA).
They had if/then/else but also switches, while and do/while loops, at least for that opus.

Code: [Select]
/********************************************************************
 *
 * Here are the different structures of the code controls.
 * On the left, the binary code,
 * On the right, corresponding C-like code.
 *
 * ************************* if/then *********************************
 * 05 Condition                 * if (Condition) {
 * 02 IfnJump --\               *   CODE_A()
 * CODE_A       |               * }
 *        <-----/               *
 *                              *
 * *********************** if/then/else ******************************
 * 05 Condition                 * if (Condition) {
 * 02 IfnJump --\               *   CODE_A()
 * CODE_A       |               * } else {
 * 01 Jump -----|--\            *   CODE_B()
 * CODE_B <-----/  |            * }
 *        <--------/            *
 *                              *
 * ************************ ifnot/then *******************************
 * 05 Condition                 * ifnot (Condition) {
 * 03 IfJump ---\               *   CODE_A()
 * CODE_A       |               * }
 *        <-----/               *
 *                              *
 * ************************** while **********************************
 * 01 Jump ----------\          * while (Condition) {
 * CODE_A <-------\  |          *   CODE_A()
 * 05 Condition <-|--/          * }
 * 03 IfJump -----/             *
 *                              *
 * ************************* do/while ********************************
 * CODE_A <------\              * do {
 * 05 Condition  |              *   CODE_A()
 * 03 IfJump ----/              * } while (Condition)
 *                              *
 * ************************ switch(ex) *******************************
 * 05 Condition                 * switch (Condition) from X {
 * 0B Switches 0  1 DEFAULT     * case 0:
 * CODE_A <----/  |    |        *   CODE_A()
 * 01 Jump -------|----|        *   break
 * CODE_B <-------/    |        * case 1:
 * 01 Jump ------------|        *   CODE_B()
 *        <------------/        *   break
 *                              * }
 *                              *
 * ******************** switch(ex)+default ***************************
 * 05 Condition                 * switch (Condition) from X {
 * 0B Switches 0  1 DEFAULT     * case 0:
 * CODE_A <----/  |    |        *   CODE_A()
 * 01 Jump -------|----|---\    *   break
 * CODE_B <-------/    |   |    * case 1:
 * 01 Jump ------------|---|    *   CODE_B()
 * CODE_C <------------/   |    *   break
 * 01 Jump ----------------|    * default:
 *        <----------------/    *   CODE_C()
 *                              *   break
 *                              * }
 *                              *
 * *************************** loop **********************************
 * FUNC_START <---\             * function {
 * CODE_A         |             *   CODE_A()
 * 01 Jump -------/             *   loop
 *                              * }
 *                              *
 *********************************************************************/
« Last Edit: 2023-05-09 21:19:45 by Tirlititi »