Author Topic: CHRONO CROSS ROOM SCRIPT INVESTIGATION THREAD (formerly event script thread)  (Read 23618 times)

FaustWolf

  • Guru of Time Emeritus
  • Arbiter (+8000)
  • *
  • Posts: 8972
  • Fan Power Advocate
    • View Profile
Although Chrono Cross hacking is yet in its infancy, I believe it will soon be time to explore the possibility of locating and interpreting the game's event code -- the instructions that say, "create a dialogue box (with this dude's portrait)," or "make this character walk five steps to her left," or "load this character model."

So, anyone who's worked with event code before (for any game), could you provide some insight as to what we'd be looking for? I assume that each room will have associated with it some code that defines what happens during the scenarios that play out in that room. Would event code consist of pointers to instructions defined in the game executable?

One clue key to exploring Chrono Cross' event code may lie in the fact that each room contains its own code for dialogue and its own overworld NPC character and enemy models, meaning the event code must refer to the data only in that room. This is why we see so many duplicate character and enemy textures strewn throughout the Chrono Cross game image -- each room that has a Cybot enemy, for example, has its very own Cybot model. It also explains why we see so many Kid overworld models -- Kid's NPC model exists separately in each room in which she appears as an NPC. This happens quite often if you decide not to take Kid with you; the game uses Kid's NPC models as opposed to her in-party overworld model.

A twist on the "room segregation of data" phenomenon is that in-battle models are defined only once on the game disc (though player characters have a copy of their battle model sans some animation data for status screen purposes, as Gemini pointed out long ago). Therefore, instructions for loading battle models refer not to any single room, but to a communal battle model collection.

I know so little about event code right now that I'm probably muddling up my own questions on the matter. Anyone happen to know if The Great Ones (Geiger, Chickenlump, JLukas, et al) left notes regarding the intricacies of Chrono Trigger's event code? Their notes, if accessible, may not be perfectly applicable to the event code in Chrono Cross, but they would probably help myself and other hacking novitiates learn some basics.

Also, for those experienced in PSX programming, I'm seeing lots of instruction sets defiined in the game executable (things like "kz_getmodel()" and such). Would each of these pre-defined game instructions have an index number, and the event code simply specifies that index number to get things to happen during storyline scenes? I assume the event code would also be responsible for things like making a loaded character model walk from one point to another, which would necessarily involve specifying the character model's displacement within the room (starting coordinates and ending coordinates). Anyone know what would have to be done in a debugger to observe a game's event code?
« Last Edit: April 18, 2008, 01:19:07 pm by FaustWolf »

halkun

  • Architect of Kajar
  • Earthbound (+15)
  • *
  • Posts: 50
  • Ayumi Hamasaki Fanboy
    • View Profile
Re: Event Code -- what makes it tick?
« Reply #1 on: April 17, 2008, 06:03:52 am »
Chrono Cross uses a later version of the FF7 engine. The "event code" that you care calling is actually called "fieldscript". To better understand the guts of it, you have to know how the whole game system works.

The game consists of several modules. Kernel, Menu, Field, Worldmap, and Battle. (In FF7 there was also "Minigame", but I think that module was not compiled in. Also The worldmap system is 2D in CC while in FF7 it's 3D)

Kernel is the core program that manages all the other modules. It has the low-level functions and does memory management,  disc access, sound/music and the like. The kernel is multitasking threaded system and can run mutiple tasks at once

Menu is actually the next most powerful. It manages the game variables and also manages game save/load system. Menu is also quasi-responsible for the opening game "start" menu. It also displays the menu ^_^. If it's anything the FF7/FF8/PE and the like, there is a huge global area called a "savemap" where all gamedata is kept. This is mirrored to the memory card on save.

Battle is the stand-alone battle module. This has it's own scripting language for the enemy AI.

Lastly, and the biggest is Field. A single field is a "room" that is "ran" by the field interpreter. A field file is completely self-contained and does not access data from another room. (It can, however access the global savemap for variables) 

The data in the Each "room" has has a 2D layerd background and a 3D "walkmesh" that the characters walk on. The field file contains all the entities in that scene, and all entities have a script that is called to them.

You best bet is to get caught up with FF7's system because it's the simple framework that all other games were based from.

Engine Basics
The Kernel
Menu Overview
Field module
Fieldscript Opcode index

Fieldscript and Battlescript are different. I'm lacking battlescript info in my wiki, but we have a good deal of that reversed too.

I can answer any question of fieldscript. You can use that to experiment with what CC's fieldscript system. The are both most likely very very similar.

FaustWolf

  • Guru of Time Emeritus
  • Arbiter (+8000)
  • *
  • Posts: 8972
  • Fan Power Advocate
    • View Profile
Re: Event Code -- what makes it tick?
« Reply #2 on: April 17, 2008, 03:12:55 pm »
YEAH! Thanks for sharing your uber knowledge again halkun. I'm sure I'll barrage you with a ton of questions once I've studied your notes on FF7. Now I know to ask about fieldscript at least.

BTW, Chrono Cross Model Project, or my part in it, shall kick back into full gear by May 11. I'll be copying various notes onto the Compendium wiki till then.
« Last Edit: April 17, 2008, 03:43:08 pm by FaustWolf »

halkun

  • Architect of Kajar
  • Earthbound (+15)
  • *
  • Posts: 50
  • Ayumi Hamasaki Fanboy
    • View Profile
Re: Event Code -- what makes it tick?
« Reply #3 on: April 18, 2008, 02:15:11 am »
Looking at the release dates, it appears that CC may use a slightly modded version of the FF8 fieldscript system. Because this hasn't been reversed very far, I can gave you some tips over what to look for.

1) The fieldscript system starts with a "Base script" that runs every loop. Looking at Square's code, to appears this is actually called the "Directer script" and commonly has an entity name of "Dic" In FF7 and FF8, the entities in the fieldscript actually are labeled in text and not stripped. Look for this in the uncompressed fieldscript data.

2) Find the debug room if one exists and start there. In the case of FF7 and FF8, the debug room is an overhead view with the camera located at 0,0,0 and looking down at 0,0,0. There were minimal variables set. I don't think CC has one though. In this case look for the first scene.

3) Remember that all field files are self-contained. They do not pull data from other "rooms". Each field file is likely split up into sections. (background, palette, walkmesh, entity models, script) if you can find the "top" of one of these data fields and then walk backwards to a referencing header, you can see where a field file "begins" and "ends". They are also most likely compressed with some kind of lzs compression.

ZeaLitY

  • Entity
  • End of Timer (+10000)
  • *
  • Posts: 10795
  • Spring Breeze Dancin'
    • View Profile
    • My Compendium Staff Profile
Re: Event Code -- what makes it tick?
« Reply #4 on: April 18, 2008, 02:36:06 am »
Using the debug menu for Chrono Cross, you're given a second prompt for a numerical value after you deal with the first in selecting a map. The values of the second control scripted events. I don't have any real example, but say you go to the S.S. Invincible. Having 000 or 001, or whatever the default is (I can't remember), it'll load normally. But maybe 002 starts the cut scene when Serge first arrives, and 003 starts the ghost ship cut scene that also takes place on that map. Maybe you can follow that lead somehow.

FaustWolf

  • Guru of Time Emeritus
  • Arbiter (+8000)
  • *
  • Posts: 8972
  • Fan Power Advocate
    • View Profile
Re: Event Code -- what makes it tick?
« Reply #5 on: April 18, 2008, 02:44:02 am »
Thanks ZeaLitY! That will lead to event indices or something at least.

The tools created by Terminus Traductions, the French translation team, are able to separate the rooms into their constituent components and in each room there's a file called "8script" that contains all the room's dialogue when uncompressed. When I get some time I'll investigate the other files and see what the data looks like -- though I may need to develop some way to decompress the other file types in each room.

Provided the fieldscript is compressed, is there any way to see uncompressed fieldscript in game memory? I found that it wasn't too much of a hassle to figure out the compression algorithm used for Front Mission 2 character portraits by comparing the compressed data to the uncompressed data as loaded in VRAM. Obviously I'm not looking in VRAM for fieldscript, but could it be somewhere else in a savestate perhaps?

halkun

  • Architect of Kajar
  • Earthbound (+15)
  • *
  • Posts: 50
  • Ayumi Hamasaki Fanboy
    • View Profile
Re: Event Code -- what makes it tick?
« Reply #6 on: April 18, 2008, 04:21:50 am »
Yes, you will find the fieldscript uncompressed in memory. The problem is you are only going to have the tokenized opcodes and not command words.

For Q-gears, I wrote a script dumper. What makes it cool is I commented the sheer hell out of it in plain English so anyone can follow along.

http://q-gears.svn.sourceforge.net/viewvc/q-gears/trunk/src/utils/scriptdump/

Here is the source from the above link

scriptdump.c
script.c
script.h
The makefile
 
« Last Edit: April 18, 2008, 04:26:39 am by halkun »

FaustWolf

  • Guru of Time Emeritus
  • Arbiter (+8000)
  • *
  • Posts: 8972
  • Fan Power Advocate
    • View Profile
Re: Event Code -- what makes it tick?
« Reply #7 on: April 18, 2008, 01:09:39 pm »
Ooh, toys! Now, Q-Gears isn't compatible with Chrono Cross (yet), correct? I could use this to see what uncompressed fieldscript looks like in general though.

I did some snooping around in the compressed room files this morning, and found that the dialogue files are indeed lzss compressed -- though the tag at the beginning of the compressed file reads "sszl" -- could this be some type of compression not used in other Square games? A "backwards" lzss or something?

But the good news is, Terminus Traductions figured out this "sszl" compression scheme already, and I've been using their tools to decompress the game script without a hitch (though I've encountered problems re-compressing). Aaaaaand -- there's a whole collection of "sszl" compressed files. One (or more) of these might just be our fieldscript!

Important question for coders: I've not yet learned a programming language, so this is going to seem incredibly naive one way or the other. The "ScriptDecompress" tool created by Terminus Traductions targets the eighth file dumped by the "RoomDecompress" tool into each room's folder, yielding uncompressed dialogue script viewable in a text editor. Most of the other dumped files look like they're compressed with the exact same algorithm (this so-called "sszl") as the dialogue script files are. Would it be an easy task to "re-target" the ScriptDecompress tool by tweaking its source code? I've got source code for the script decompressor on hand, and will furnish it if anyone's interested. I can't guarantee 100% that, if successful, the uncompressed files will be the fieldscript, but I have a pretty good hunch that this is the case based on halkun's feedback. If what I'm asking is theoretically a really simple task, like, say, a monkey could do it, then I'll snoop around in the source and take care of it once I know what to look for.

Something to get out of the way for everyone's info: as far as I can tell, the Terminus Traductions tools labeled "RoomDecompress" are merely room dumpers -- they chunk up the compressed room files per the pointer table described by halkun several posts up. I'm not sure if Terminus originally labeled its room tool "decompress" or not; the tools have been circulating for awhile now, and the ones I have may have been renamed or something.
« Last Edit: April 18, 2008, 01:13:51 pm by FaustWolf »

FaustWolf

  • Guru of Time Emeritus
  • Arbiter (+8000)
  • *
  • Posts: 8972
  • Fan Power Advocate
    • View Profile
'kay, I've lifted this from the script decompressor source code:

for (room_number = 0; room_number < 537; room_number++)
    {

      printf ("\n%d ", room_number);
      sprintf (nom_temp, "..//rooms//disk1//%d//code//8script", room_number);
      f_room = fopen (nom_temp, "rb");

What the heck does an sprintf() function do in C/C++? printf is what goes on-screen in the DOS window as the program does its thing if I'm remembering the "Hello World" exercise I did 10 years ago correctly. This sprintf() is the only thing that has the 8script label anywhere in the source code -- 8script is the name of the dialogue script file targeted for decompression, but I suspect this is an output function and not an input function.
« Last Edit: April 18, 2008, 02:05:13 pm by FaustWolf »

Luminaire85

  • Guru of Time Emeritus
  • Chronopolitan (+300)
  • *
  • Posts: 311
    • View Profile
    • Chrono Cinema
The sprintf() function does exactly the same thing as printf(), but instead of outputting to the console window it outputs to a character buffer (nom_temp in this case). The line of code you've bolded is simply storing the path to a file in nom_temp, replacing the '%d' with the value of room_number. The next command opens that file for reading in binary mode.

FaustWolf

  • Guru of Time Emeritus
  • Arbiter (+8000)
  • *
  • Posts: 8972
  • Fan Power Advocate
    • View Profile
Hmm, so if if the fopen() opens the file specified by the path in sprintf(), could I re-target the file this program acts on by replacing the "8script" name in the sprintf() path with the name of some other file in that folder I'd like it to try to decompress? Am I understanding that right Luminaire?

EDIT: Just completed a series of tests in which I removed the 8script file from a folder, found another file that was "sszl" compressed, and renamed that file 8script in lieu of the original. The RoomDecompress program chokes on the renamed file, producing an empty "outscript" file (that's what the uncompressed dialogue script is labeled). Something else in the parameters of the source code must be specifically geared to work with the compressed dialogue and it cannot read compressed fieldscript unless some serious tweaking is done.
« Last Edit: April 18, 2008, 04:12:00 pm by FaustWolf »

halkun

  • Architect of Kajar
  • Earthbound (+15)
  • *
  • Posts: 50
  • Ayumi Hamasaki Fanboy
    • View Profile
if you have the files uncompressed, there is an lzs uncompressor in the qhimm forums somewhere.

FaustWolf

  • Guru of Time Emeritus
  • Arbiter (+8000)
  • *
  • Posts: 8972
  • Fan Power Advocate
    • View Profile
Thanks halkun, I've picked up your lzss.c from qhimm, the one you gave me in the Front Mission 2 portrait thread. How will this program work once compiled? Does it need a certain folder structure or anything? If so, I can find where that is in the source and hopefully alter it to suit our current needs if necessary.

JLukas

  • Fan Project Leader
  • Squaretable Knight (+400)
  • *
  • Posts: 426
    • View Profile
Their notes, if accessible, may not be perfectly applicable to the event code in Chrono Cross, but they would probably help myself and other hacking novitiates learn some basics.

Hmm, it's hard to think of what can be useful here since the game engines are so different.  One of the most important things IMO would first be to find a barebones room to study.  A spot in the game where it loads your PCs and that's about it.  Reptite Lair entrance in CT, for example.  Gato's event is another popular example, with a single NPC and battle.  Heavily document those basic areas before moving on.

Find where one event command stops and other begins.  If you're lost in a blob of event code with no clue where to start, look for familiar hex codes.  For example, if an NPC gives you X item, look in a list of Gameshark codes for the hex value.  You use this same method for music, textboxes (strings), NPCs, etc... anything you have a list of.  Search the event for that hex value, and change each one by one until you find the match that causes you to receive a different item.  Next, try to find the byte length of that specific event command.  Set a read breakpoint on surrounding bytes and see if it triggers a common execute address.  What you're looking for is the piece of code responsible for loading the next command.  When you use that as an execute breakpoint, it'll stop on each command loaded.  That will make your job much, much easier figuring out the lengths of individual commands.

As you decode the events, write a program that can convert those commands to something readable, like jsondag is currently doing in the Tech thread.

FaustWolf

  • Guru of Time Emeritus
  • Arbiter (+8000)
  • *
  • Posts: 8972
  • Fan Power Advocate
    • View Profile
Thank you for the methodological insight JLukas! First step is to get what may be the fieldscript decompressed, then we'll see what's up. Thanks to ZeaLitY's work on the debug menu, we've probably got an ordered list of rooms. From everyone's experience, would a given room's fieldscript/event code contain a command telling the game to load another room once the lead character has reached an exit point? If we see that each room's fieldscript contains one or more indices pertaining to other rooms, we might be able to use that to our advantage.