Final Fantasy VII Field Script Debugger: Difference between revisions
| Revision as of 23:54, 1 November 2026 RemmyLee (Games: the section's first page, Final Fantasy VII, with its field script debugger, BROM.X battle-test screen and unused menu commands) | Revision as of 00:33, 2 November 2026 RemmyLee (Final Fantasy VII: both pages rewritten in the Sony manual voice (connected paragraphs, the reason with each fact, no signposts); SYSTEM.CNF defaults cited to the OS manual) | ||
| Line 10: | Line 10: | ||
| ## Overview | ## Overview | ||
| − | The field module of [Final Fantasy VII](/games/final-fantasy-vii/), FIELD/FIELD.BIN, contains the event debugger that Square used to follow a room's scripts. It draws text windows over the field screen that give the room's script author, the room name, Go, Stop and Step commands, the current actor with its position, and the script command that is running. The retail game keeps the code and its text but never draws the windows.[^d1][^bench] | + | The field module of [Final Fantasy VII](/games/final-fantasy-vii/), FIELD/FIELD.BIN, contains the event debugger that Square used to follow the scripts of a room while they run. The debugger draws text windows over the field screen that show the script author and the name of the room, the Go, Stop and Step commands, the current actor and its position, and the script command being executed. In the retail game the code and its text remain in the module; however, the windows are never drawn.[^d1][^bench] |
| − | Each script command handler calls a trace routine that names the command with its internal name, such as mes, mjump or kawai, and gives its argument bytes. The module's strings include "Authr", "Word:", "Actor:", "RqLv", "Actor OFF", "Bad Event code!" and "Bad Event arg!".[^d1][^bench] | + | Every script command handler calls a trace routine, which reports the internal name of the command and its argument bytes. The internal names are short words such as mes, mjump and kawai. The module also holds the labels and error messages of the debugger, among them "Authr", "Word:", "Actor:", "RqLv", "Actor OFF", "Bad Event code!" and "Bad Event arg!".[^d1][^bench] |
| ## Windows | ## Windows | ||
| − | The debugger has six text windows of 17Ah bytes each at 800E0748h. At each room load the setup routine at 800D7F9Ch opens windows 1, 3, 4 and 5 and fills window 5 with the author line, the room line and the Go, Stop, Step, Actor OFF and Info OFF rows. It then hides each window, and the draw routine skips a hidden window.[^bench] | + | The debugger uses six text windows, which are records of 17Ah bytes each in a table at 800E0748h. When a room is loaded, the setup routine at 800D7F9Ch opens windows 1, 3, 4 and 5 and writes the author line, the room line and the Go, Stop, Step, Actor OFF and Info OFF rows into window 5. The same routine then marks each window as hidden, and because the draw routine skips any hidden window, nothing appears on the screen. The contents of each window are shown below.[^bench] |
| Table: Debugger windows | Table: Debugger windows | ||
| Line 23: | Line 23: | ||
| | --- | --- | | | --- | --- | | ||
| | 1 | Controller rows ("ctrl:"); no retail call fills it | | | 1 | Controller rows ("ctrl:"); no retail call fills it | | ||
| − | | 3 | "Word:" and the script command that is running | | + | | 3 | "Word:" and the script command being executed | |
| | 4 | "Actor:", the entity, RqLv, its script line and its position | | | 4 | "Actor:", the entity, RqLv, its script line and its position | | ||
| | 5 | "Authr:" and the script author, "Event:" and the room name, Go, Stop, Step, Actor OFF, Info OFF | | | 5 | "Authr:" and the script author, "Event:" and the room name, Go, Stop, Step, Actor OFF, Info OFF | | ||
| Line 29: | Line 29: | ||
| ## Switches | ## Switches | ||
| − | The retail program turns the debugger off in three places. The two enable flags at 8009D820h and 80071E24h are written only by the setup routine, which stores 0 to them at 800D8160h and 800D8158h. The window draw routine at 800D85FCh has no caller: no jal instruction, pointer or address load in FIELD.BIN or SCUS_941.63 names it. The per-frame call at 800BA7A8h is jal 800BC438h, which draws the field pointer instead.[^d1] | + | The retail program disables the debugger in three ways. The enable flags at 8009D820h and 80071E24h are written only by the room setup routine, which stores 0 to them at 800D8160h and 800D8158h. The window draw routine at 800D85FCh is never called, since no jal instruction, pointer or address load in FIELD.BIN or SCUS_941.63 refers to it. Finally, the room setup routine hides each window that it opens.[^d1][^bench] |
| − | The state byte at 80099FFCh holds 3 while the scripts run and 4 when they stop. Value 5 is step mode: one script command runs per frame. The retail program never stores 5.[^bench] | + | A state byte at 80099FFCh controls script execution: 3 means that the scripts run and 4 means that they are stopped. A value of 5 selects step mode, in which one script command is executed per frame; however, the retail program stores only 3 and 4 to this byte, so step mode is never entered.[^bench] |
| ## Operation | ## Operation | ||
| − | The debugger appears when the frame call at 800BA7A8h is changed to jal 800D85FCh, the enable flags at 8009D820h and 80071E24h are set to 1, and the hide bytes of windows 1, 3, 4 and 5 at 800E0A3Ah, 800E0D2Eh, 800E0EA8h and 800E1022h are set to 0. A room load hides the windows again, and a return from battle loads FIELD.BIN again, so the changes are made again after each.[^bench] | + | The debugger can be shown by making three changes in memory while the field module runs. The per-frame call at 800BA7A8h is changed from jal 800BC438h to jal 800D85FCh so that the windows are drawn every frame, the enable flags at 8009D820h and 80071E24h are set to 1, and the hide bytes of windows 1, 3, 4 and 5 (800E0A3Ah, 800E0D2Eh, 800E0EA8h and 800E1022h) are set to 0. Because each room load hides the windows again, and each return from battle reloads FIELD.BIN with the original call, the changes must be repeated after either event.[^d1][^bench] |
| − | On a SCPH-5501 on 31 October 2026, with these changes made in room MDS5_3, the screen showed AUTHR:AKIYAMA, EVENT:MDS5_3, the GO, STOP, STEP, ACTOR OFF and INFO OFF rows, ACTOR:FURYOB with its RQLV, MAN, DIR and X FE32 Y FF34 rows, and WORD:RET.[^run] | + | These changes were made on a SCPH-5501 on 31 October 2026 in room MDS5_3. The screen then showed AUTHR:AKIYAMA and EVENT:MDS5_3 in window 5 with the GO, STOP, STEP, ACTOR OFF and INFO OFF rows below them. Window 4 showed ACTOR:FURYOB with its RQLV, MAN, DIR and position rows (X FE32, Y FF34), and window 3 showed WORD:RET.[^run] |
| − | The text draw routine at 800D9C04h draws at most 344 character sprites a frame, and the four windows together need about 400. In the StationX emulator with all four windows open, window 5 stopped partway through its author line. With the sprite buffer extended into the unused field pointer code, the four windows drew complete with 357 sprites.[^bench] | + | The text draw routine at 800D9C04h draws at most 344 character sprites in one frame, whereas the four windows together need about 400. Consequently, when all four windows are open, the text is cut off: in the StationX emulator, window 5 stopped partway through its author line. When the sprite buffer was extended into the unused field pointer code, all four windows were drawn in full with 357 sprites.[^bench] |
| ## References | ## References | ||