Modding Star Wars Clone Wars

Reverse engineering the gcm file (or .msh)

XXD, python and coding

In the first article, I had a glance at the various files that can be found on the disc. That was it. Now it is time to look at them more closely. I figured out that the gcm files could be important, as they basically had the names of all possible vehicle of the game.

I never had any previous experience in reverse engineering a file. So I randomly opened it with xxd.

xxd bluelightsaber.gcm | head -n 20
00000000: 4845 4452 7808 0000 4d53 4832 6808 0000  HEDRx...MSH2h...
00000010: 5349 4e46 6400 0000 4e41 4d45 1400 0000  SINFd...NAME....
00000020: 6c69 6768 7473 6162 6572 5f61 6e61 6b69  lightsaber_anaki
00000030: 6e00 0000 4652 414d 0c00 0000 0100 0000  n...FRAM........
00000040: 6400 0000 9fc2 ef41 4242 4f58 2c00 0000  d......ABBOX,...
00000050: 0000 0000 0000 0000 0000 0000 0000 803f  ...............?
00000060: 0000 0000 0000 4033 95fd 67bf faff 7f3e  ......@3..g....>
00000070: fbff 7f3e d6d8 e33f 3c4c e83f 4341 4d52  ...>...?<L.?CAMR
00000080: 4000 0000 4e41 4d45 0800 0000 4361 6d65  @...NAME....Came
00000090: 7261 0000 4441 5441 2800 0000 e2e5 b1c0  ra..DATA(.......
000000a0: d1eb 7540 3a9b 0541 85ed 1abf 6bdd cc3f  ..u@:..A....k..?
000000b0: f33f 0b3f 0000 0000 29a8 6f3f cdcc cc3d  .?.?....).o?...=
000000c0: 0000 0047 4d41 544c f000 0000 0200 0000  ...GMATL........
000000d0: 4d41 5444 6000 0000 4e41 4d45 1000 0000  MATD`...NAME....
000000e0: 5363 656e 655f 4d61 7465 7269 616c 3000  Scene_Material0.
000000f0: 4441 5441 3400 0000 3333 333f 3333 333f  DATA4...333?333?
00000100: 3333 333f 0000 803f 0000 803f 0000 803f  333?...?...?...?
00000110: 0000 803f 0000 803f 9a99 993e 9a99 993e  ...?...?...>...>
00000120: 9a99 993e 0000 803f 0000 4842 4154 5242  ...>...?..HBATRB
00000130: 0400 0000 0000 0000 4d41 5444 7c00 0000  ........MATD|...

I do not have a clue of how other people figure out patterns. I do not have any method at all, just random guessing and testing. The strings HEDR, MSH2, SINF … seemed to be present on other files as well. Besides, the four bytes following them seemd to represent (big endian) integers, with small values.

More particulary, the NAME, was followed by the value 20 (in hex), with is exactly the length of the string “lightsaber_anakin…”. I just made the hypothesis that the file was cut in sections defined by char[4]:title int32:section_size. Which I could test with the following python code.

from struct import unpack_from


def read_array(buffer, offset, length):
    return buffer[offset:offset + length]


def read_float(buffer, offset):
    return unpack_from(">f", buffer, offset)[0]


def read_int32(buffer, offset):
    return unpack_from(">i", buffer, offset)[0]


def read_uint32(buffer, offset):
    return unpack_from(">I", buffer, offset)[0]


def read_uint32_big_endian(buffer, offset):
    return unpack_from("<I", buffer, offset)[0]


def read_uint16(buffer, offset):
    return unpack_from(">H", buffer, offset)[0]


def read_uint8(buffer, offset):
    return unpack_from("B", buffer, offset)[0]


def represent(input_object):
    attrs = vars(input_object)
    return ', '.join("%s: %s" % item for item in attrs.items())


class GamecubeModel(object):

    def __init__(self):
        pass

    def from_file(self, f):
        current_data = f.read()
        self._header = current_data[:0x04]
        self._filesize = read_uint32_big_endian(current_data, 0x04) # the file size (minus 8 bytes)

        self._header1 = current_data[0x08:0x0C] 
        self._unk1 = read_uint32_big_endian(current_data, 0x0C)

        self._header2 = current_data[0x10:0x14]
        self._unk2 = read_uint32_big_endian(current_data, 0x14)

        self._header3 = current_data[0x18:0x1C]
        self._unk3 = read_uint32_big_endian(current_data, 0x1C)

        self._name1 = current_data[0x20:(0x20 + self._unk3)]

        self._next = current_data[(0x20 + self._unk3):(0x24 + self._unk3)]
        self._next_size = read_uint32_big_endian(current_data, 0x24 + self._unk3)

        new_offset = 0x24 + self._unk3 + self._next_size + 0x04

        self._next2 = current_data[new_offset:(new_offset+0x04)]

        self._size = len(current_data)
        return self


if __name__ == "__main__":
    model = GamecubeModel()
    with open("./rep_inf_anakin_anims.gcm", "rb") as f:
        my_data = model.from_file(f)
        print represent(my_data)

    model2 = GamecubeModel()
    with open("./bluelightsaber.gcm", "rb") as f:
        my_data = model2.from_file(f)
        print represent(my_data)

    model3 = GamecubeModel()
    with open("./rep_walk_assault_skel.gcm", "rb") as f:
        my_data = model2.from_file(f)
        print represent(my_data)

    model4 = GamecubeModel()
    with open("./objective_arrow_1.gcm", "rb") as f:
        my_data = model4.from_file(f)
        print represent(my_data)

The results were quite consistent:

_header1: MSH2, _header2: SINF, _header3: NAME, _next2: BBOX, _next_size: 12, _name1: REP_inf_anakin_masterfile_cin_head, _unk2: 116, _unk3: 36, _unk1: 131936, _next: FRAM, _filesize: 452680, _size: 452688, _header: HEDR
_header1: MSH2, _header2: SINF, _header3: NAME, _next2: BBOX, _next_size: 12, _name1: lightsaber_anakin, _unk2: 100, _unk3: 20, _unk1: 2152, _next: FRAM, _filesize: 2168, _size: 2176, _header: HEDR
_header1: MSH2, _header2: SINF, _header3: NAME, _next2: BBOX, _next_size: 12, _name1: REP_walk_assault_multiAnim_V4, _unk2: 112, _unk3: 32, _unk1: 101084, _next: FRAM, _filesize: 117148, _size: 117156, _header: HEDR
_header1: MSH2, _header2: SINF, _header3: NAME, _next2: BBOX, _next_size: 12, _name1: Objective_Arrow, _unk2: 96, _unk3: 16, _unk1: 1564, _next: FRAM, _filesize: 1580, _size: 1588, _header: HEDR

It seemed, however, that in some cases, a section did not pay attention to the length that is stated before jumping to another section. Therefore, I made the hypothesis that there was some kind of xml/json tree-like structure, where a node could have many elements.

After some trial and errors, some nodes are terminal (they cannot be decomposed into sub-nodes), and other can. The following code parses the files and shows the tree in the console output.

class GamecubeModel(object):

    def __init__(self):
        self._terminal_states = {"NAME",
                "FRAM",
                "BBOX",
                "DATA",
                "ATRB",
                "MATL",
                "MTYP",
                "MNDX",
                "TRAN",
                "MATI",
                "POSL",
                "NRML",
                "UV0L",
                "STRP",
                "PRNT",
                "FLGS",
                "CL1L",
                "SKL2",
                "BLN2",
                "CYCL",
                "KFR3"}

    def from_file_rec(self, current_data, cursor, depth):
        section_name = current_data[cursor:(cursor + 0x04)]
        cursor = cursor + 0x04
        section_size = read_uint32_big_endian(current_data, cursor)
        cursor = cursor + 0x04
        print('\t' * depth + section_name + '\t' + str(section_size))

        if section_name in self._terminal_states:
            pass
        else:
            self.from_file_rec(current_data[cursor:(cursor + section_size)], 0, depth + 1)

        if cursor + section_size < len(current_data) :
            self.from_file_rec(current_data, cursor + section_size, depth)

    def show_in_console(self, current_data):
        self.from_file_rec(current_data, 0,0)

if __name__ == "__main__":
    model = GamecubeModel()
    with open("./bluelightsaber.gcm", "rb") as f:
        my_data = model.show_in_console(f.read())

And the result seem to be consistent as the sum over a section is equal to the sum of the sizes of the subsections. Example:

(SINF) 100 = (NAME) 8+20 + (FRAM) 8+12 + (BBOX) 8+44

Here is the decomposition of bluelightsaber.gcm according to these hypothesis.

HEDR	2168
	MSH2	2152
		SINF	100
			NAME	20
			FRAM	12
			BBOX	44
		CAMR	64
			NAME	8
			DATA	40
		MATL	240
		MODL	1252
			MTYP	4
			MNDX	4
			NAME	16
			TRAN	40
			GEOM	1148
				BBOX	44
				GSEG	312
					MATI	4
					POSL	100
					NRML	76
					STRP	100
				GSEG	768
					MATI	4
					POSL	208
					NRML	112
					UV0L	220
					STRP	184
		MODL	456
			MTYP	4
			MNDX	4
			NAME	12
			PRNT	16
			FLGS	4
			TRAN	40
			GEOM	320
				BBOX	44
				GSEG	260
					MATI	4
					POSL	76
					NRML	64
					STRP	84
	CL1L	0

The next step ?

Well, time to look for what these attributes stand for ! NRML could mean “normal”, NAME is obviously the name of a section, MAT. can stand for matrices… Looking for these keyword on the web, I discover this git page : schlechtwetterfront. Basically, this file format is used by the ZeroEngine, which has been reversed engineered (already…) for mods to Star Wars Battlefront… And a plugin already exists to read and write these files with SoftImage… xsizetools.

So, not much to do any more… Vehicles can be modified, and reimported.

Remaining work ?

It seems that I did not manage to import the six leg walker instead of another character in the game. But with these progress, many new things can be changed. What happens if a gcm file is replaced with another ? With this can I rescale a model ? Change the texture, add an add for my blog on the vehicles ? More answers to come…

The lost Dekoboko track

So cool !

Yes, an extra track in Mario Kart Double Dash. Do not expect too much, unfortunately, it seems to be an early version of the Sherbet track in the final version of the game. But it works. Look :)

The magic of kiosk disks

Where does this come from ? From a kiosk demo disk. The kiosk demo discs are the discs containing multiple games, on which you could play many games. Just to tease you. Developers put a large part of the game on these disc and rely on poor “security” mechanisms to prevent the user to access the full game.

In Luigi’s Mansion, you cannot play for more than 15 minutes. But the whole game is on the first demo disc.

With Mario Kart Double Dash, you cannot use up and down on the race selection menu and you can only choose one race. This forces you to play on Luigi’s Circuit. But most of the final version of the tracks are present on the disc.

I guess there are many (many) more differences with the final version of the games and, as prototypes will (hopefully) be released, more and more beta tracks will become available!

The tools you will need.

First, you will need images (isos) of the following gamecube discs :

  • European Demo Disc 10 Demo
  • Mario Kart Double Dash (any version should work)

Then, there are very talented people who built tools to navigate through the files. Here are the ones you will need.

Tool Address Purpose
Dolphin https://dolphin-emu.org/ Run a Gamecube image on a computer (testing purpose)
TgcToGcm https://www.romhacking.net/utilities/1096/ Enables to turn tgc to gcm files (and play them)
GCREeX http://www.wii-info.fr/download-696-gcreex-v0-3-discex-v0-9-gci2nmm-v0-1b-outils-pour-dios-mios.htm?page2=2 ISO decompression and recompression
ArcExtract https://github.com/LordNed/WindEditor/tree/master/WindViewer/ExternalTools Decompression tool
ArcPack https://github.com/LordNed/WindEditor/tree/master/WindViewer/ExternalTools Compression tool

Your turn !

Step 1 : Extracting the kiosk demo disc

This can be done with GCREeX.

Assuming the iso is called kiosk_demo.iso, and gcreex.exe is in the same folder than the iso, create a text (run.txt) file with the following :

gcreex -x kiosk_demo.iso 
pause

Rename it run.bat and click on it. (or type the command in the command line directly)

Step 2 : Extracting the kiosk version of Mario Kart Double Dash

Now, you have to find the demo version of Mario Kart which should be on the disc. It is the following.

/D88P01/files/zz_MarioKartP.tgc

You need to extract it with tgc. Using the command line (or writing a bat file). Assuming tgc2gcm.exe and zz_MarioKartP.tgc are in the same folder, type the follwing command line and expect the following output.

user@:~/ISOs/D88P01/P-D88P/files$ ./tgc2gcm zz_MarioKartP.tgc zz_MarioKartP.gcm
TGCtoGCM by Plootid 2004

Target filesize: 182812672 bytes
Copying GCM, please wait...
Updating GCM...
All Done!

Now you need to extract zz_MarioKartP.gcm with gcreex once again, to access the files of this game.

Step 3 : Getting the files

Now, in the new folder, you need to find Dekoboko.arc.

zz_MarioKart/files/Course/Dekoboko.arc

Now drag and drop this file on ArcExtract.exe. You should have many files appearing. Only keep :

  • dekoboko_course.bco (the collision mask)
  • dekoboko_course.bmd (the graphical model)

(simply copy them)

Step 4 : Extracting Mario Kart Double Dash iso

Same as step one,

gcreex -x mkdd.iso 
pause

Step 5 : Building the beta track

Find

GM4E01/files/Course/Snow.arc

and drop it on ArcExtract. Move the contents in a folder named Snow. Delete the files

  • snow_course.bmd
  • snow_course.bco

And add their dekokoboko equivalents. Rename:

  • dekoboko_course.bco to snow_course.bco
  • dekoboko_course.bmd to snow_course.bmd

Step 6 : Compressing the beta track

Now drag and drop the folder Snow on ArcPack. You should have a new Snow.arc file. Replace the Snow.arc file in the Course folder of mkdd (extracted) iso.

Step 7 : Compressing MKDDs iso

Using:

gcreex -c GM4E01

Will generate a new (playable) iso file.

Step 8 : Play

You must be excited. And willing to select the Sherbet Kingdom. If you do so the game will freeze. Instead, just start a track you DID NOT modify. Wait for the race to begin. Now you can press start, select another track and select the Sherbet Kingdom. And it will load. And you will play.

What is next ?

With more tools and more work, you can import pretty much anything. I will write an article soon on how to get this kind of thing working :)

Feel like playing the game again ?

Compiling tgctogcm.c on Linux

Pure technicalities!

This is a boring, but how necessary, part of game modding. Here is the story. Some tools were developed on Windows machines for game modding. Most of my machines are Linux. And I do not like to execute .exe files from the internet randomly. So I do my best to find the sources of the files and compile them.

I am not an expert in compiling C stuff, the details that matters when compiling 32 or 64 bits programs, or fluent with the C language. So, it may seem really simple for someone with a vast experience in that field, but it was quite instructive to me ;)

tgctogcm plays quite an important role for finding hiddent elements in multi game disc, as we may see in future posts. Fortunately, it is available with the source. I did not write it, all the credit goes to Plootid (the source is at the end of the article).

The story

If you want to have a working version of the tool and do not care about my errings with compilers, C and whatnot, just jump to the last section.

I first tried :

g++ tgctogcm.c -o tgc2gcm

It did not work.

tgcbis.c:25:61: error: ntohl was not declared in this scope

So, the trouble comes from the small functions ntohl, htonl… What they are supposed to do is to modify the machine representation of integers.

They are available on Linux and Windows, but the way to import them are different. You can add the following line to import it.

#include <arpa/inet.h>

Not, it compiles. And it works. Almost. If you use the executable, it will turn a tgc to a gcm file. But the gcm file will be corrupted. The issue was that the program has to be compiled in 32 bits. Once done, this works. The way to figure this out was to have a look at the .exe file. You can infer the compilation looking at some printable characters, and the following answer was quite useful : SuperUser

In a nutshell.

Simply run:

g++ -m32 tgctogcm.c tgc2gcm32

So you will have a 32 bits executable file, that will reproduce the behavior of the windows file exe :)

// tgctogcm.c -- Plootid 2004

#include <stdio.h>
#include <arpa/inet.h>

int main(int argc, char **argv) {

  FILE *tgcin, *gcmout;
  unsigned long tgcheader[14];
  unsigned long temp[3];
  int i;

  if (argc < 2) {
    printf("Usage: %s <infile.tgc> <outfile.gcm>\n", argv[0]);
    return 1;
  }

  if (!(tgcin = fopen(argv[1], "rb"))) {
    printf("Error: Couldn't open file %s\n", argv[1]);
    return 1;
  }

  fread(tgcheader, 4, 14, tgcin);

  for (i = 0; i < 14; i++) tgcheader[i] = ntohl(tgcheader[i]); //Byte-swap
  tgcheader[4] = tgcheader[4] - tgcheader[2]; // Update FST location
  tgcheader[7] = tgcheader[7] - tgcheader[2]; // Update DOL location
  tgcheader[9] = tgcheader[9] - tgcheader[2]; // Update File Area location
  //  for (i = 0; i < 14; i++) printf("%08X\n", tgcheader[i]); // Print tgc header

  if (tgcheader[0] != 0xAE0F38A2) {
    printf("Error: Input file does not appear to be a .tgc file\n");
    fclose(tgcin);
    return 1;
  }

  if (!(gcmout = fopen(argv[2], "w+b"))) {
    printf("Error: Couldn't open file %s\n", argv[2]);
    fclose(tgcin);
    return 1;
  }

  printf("TGCtoGCM by Plootid 2004\n\n");

  printf("Target filesize: %d bytes\n", tgcheader[9] + tgcheader[10]);
  printf("Copying GCM, please wait...\n");
  fseek(tgcin, tgcheader[2], SEEK_SET);
  while ( (i = getc(tgcin)) != EOF) putc(i, gcmout); //Copy gcm from tgc
  fflush(gcmout);
  fclose(tgcin);

  printf("Updating GCM...\n");

  // Update DOL and FST locations
  temp[0] = htonl(tgcheader[7]);
  temp[1] = htonl(tgcheader[4]);
  fseek(gcmout, 0x420L, SEEK_SET);
  fwrite(temp, 4, 2, gcmout);

  // Update FST
  fseek(gcmout, tgcheader[4], SEEK_SET);
  fread(temp, 4, 3, gcmout);
  for (i = ntohl(temp[2]) - 1; i > 0; i--) {
    fread(temp, 4, 3, gcmout);
    if (!(ntohl(temp[0]) & 0x01000000)) {
      temp[1] = htonl(ntohl(temp[1]) - tgcheader[13] + tgcheader[9]);
      fseek(gcmout, -12, SEEK_CUR);
      fwrite(temp, 4, 3, gcmout);
      fflush(gcmout);
    }
  }
  fclose(gcmout);
  printf("All Done!\n");
  return 0;
}
Modding MKDD

Yes. You can do it. You can customize the tracks, move items, make the computer players throw themselves in the water remove the ennemies that bother you, even better, put them in the lava.Internet’s imagination will be the limit to the mods we will be offered.

Why Mario Kart Double Dash ? Wii has mods already, loads of tracks… But I do not like the game engine on Wii. I prefer the nervous style of MKDD. That’s it, that is the only reason :) A dream would be to port the tracks of Mario Kart Arcade Grand Prix (the game engine sucks even more) on Double Dash. But I do not know enough about the track formats to know how hard it would be.

End of introductory bullshit.

Basically, Gamecube games are like these old PC Games : if you wanted to see the last animation of a game, or the alternate endings, you could (back in the days) navigate throught the files on the CD. I am thinking about Myst, because this is how I spoiled myself.

But, it is slightly harder when it comes to Gamecube Games. Why ? (don’t do that - I did this already) If you try to insert a Gamecube game in your disc drive, nothing will happen. It may also freeze your computer. And I decline every responsibility in case something happens to you or your computer :)

So, the first step to obtain the contents of a disc is to rip it. You can do it from a Wii, with the right channel… But I will assume that you have a clean .iso file of Mario Kart Double Dash.

What’s next ? Now we want to look in this ISO. For this, the best tool is GC rebuilder. It allows you to navigate through the files of the game, like any explorer. (I will link the relevant pages to get these tool at the bottom of the page, no need to rush, you have to understand every step if you want to produce something decent).

So far, everything looks quite easy. What is so difficult ? Well. Opening the files with the correct editor is the hard part. But with Gamecube games, the format are not common. Besides, files are often compressed. And Nintendo did not use the most usual compression algorithms, so you need specific decompression tools. And then, when you have uncompressed the files, you still have to edit them. On old computer games, some movies of the game could be in Quicktime format / avi… But it is not that easy !

Assuming you modified the files (per example, the position of the ennemies on a track), you have to recompress them (ArcPack allows you to do this), and recompress the whole ISO, and at last, play (Dolphin, the emulator, is a good way to try quickly your modifications).

No Step Tool
1 Extracting files from the iso GCREeX (GCIT or GC Rebuilder may work as well)
2 Decompress the tracks ArcExtract
3 Edit the tracks douBOL
4 Recompress the tracks ArcPack
5 Rebuild the ISO GCREeX (or GCIT or GC Rebuilder)
6 Play Dolphin or your console

Congratulations for making it this far! Below are the tools and a short explanation of what they do. In some cases, they are game specific. They are at the bottom of the table.

Tool Address Purpose
Dolphin https://dolphin-emu.org/ Run a Gamecube image on a computer (testing purpose)
GCREeX http://www.wii-info.fr/download-696-gcreex-v0-3-discex-v0-9-gci2nmm-v0-1b-outils-pour-dios-mios.htm?page2=2 ISO decompression and recompression
ArcExtract https://github.com/LordNed/WindEditor/tree/master/WindViewer/ExternalTools Decompression tool
ArcPack https://github.com/LordNed/WindEditor/tree/master/WindViewer/ExternalTools Compression tool
douBOL https://github.com/shibbo/DouBOL-Dash MKDD : editing the course files

That’s it, you do not need anything else! So with these in hands, let’s continue step by step.

Needed

Step 1 - extracting and decompressing the track.

Put the ISO and gcreex in the same folder and enter the following command (either using the command line). If you do not know how to do that, but work in a Windows environment, just create a text file, put the following in it, rename it “extract.bat”, and double click on the bat file.

gcreex -x mkdd.iso

On modern machines, this should take less than 10 seconds. Now you should have a folder (GSM04 I think) containing all the data, that you can now explore.

Step 2 - extracting the track

Once you found the track you are looking for, copy it. Drag it and drop in on “ArcExtract.exe” (or, in the console, type “ArcExtract mytrack.arc”). Now you should have a directory, named after your track containing files wiht BMO, BOL… extensions. Now open douBOL, and select the BOL file. You should have a screen like this.

Step 3 - edit the track

Now you can perform the modifications you want. Everything that is listed in the program can be changed. Don’t forget to save your files :)

DouBOL Capture

Pro tip: The coordinate system is not really intuitive. However, the fact that nearby items on the map are usually close to each other on the item list allows to guess more easily what are left and right, large and small, in terms of X,Y,Z.

Pro tip 2: You can go beyond the use of the GUI of douBOL, and use the source for more tedious operations ! If you want your opponents to go backwards, per example !

Step 4 - recompress the track

Once you are done editing the track files, just drop the folder on ArcPack, it will produce a new .arc file, which you have to put back in the game folder (replacing the previous .arc file)

Step 5 - recompress the ISO

Once the replacement of the arc files has been performed, you need to use gcreex once again.

gcreex -x folder_name [should be GSMO4]

This should take 10 seconds on modern computers. Do not worry if the created file is much lighter than the original ISO. The game is actually much smaller than the image.

Step 6 - play

Launch the file out.iso (which appeared in the same place as gcreex) with Dolphin, select the track you modded, and enjoy :)

Side note: If you modified one of Luigi Luigi2 arc file, note that they are selected depending on the power you choose (50cc, 100cc or 150cc). The Grand Prix in 50cc loads Luigi.arc, and 100cc (150cc) loads Luigi2.arc. These tracks differ by a small wall, separing the two roads (which are not separated usually)

What is next ?

So, you went this far without any idea of what to do ? Well, some fun modes could be a race in Luigi’s mansion (yes, you can import the tracks from the battle mode, but the modifications, building the checkpoints… Are up to you ! Or create a harder version of the game, with more (and faster) cars on the cities…

At last, thank you https://www.smwcentral.net/?p=profile&id=32431richardldb> for your help :)

Or simply play the game again ?

Modding Star Wars Clone Wars

As I am writing, this is just a work in progress. The aim is to change the game, so that the multiplayer mode becomes the coolest Star Wars multiplayer game on Earth. If you played this game as much as I did, you probably dragged your friends playing the “conquest mode”, which happens to be OK. Now, how cool this mode would be if the unit produced were droids, clones, or six feet walkers ?

I am just trying to keep my notes clean, as I explore the files of the game. It actually seems that a lot of files do are not supposed to be on the game disc. But it is a good thing that they are here, they will probably save us a lot of time.

The files on the disc

Extension Number of files Purpose
.AIM (30) UNKOWN
.BAT (2) Windows command file
.BMF (1) UNKOWN
.CIN (32) Readable text / (?) in game movie
.PTH (33) UNKOWN (?) … contains some strings …
.SKY (1) UNKOWN
.WAV (3) Sound file (VLC)
.act (1) UNKOWN
.adp (42) Music (?)
.ani (6) UNKOWN
.bat (4) Windows command file
.bik (45) Bink video file
.bin (35) UNKOWN
.bmf (6) UNKOWN
.bnr (1) GC Banner, common to GC Games
.cfg (74) Readable text / Game parameters.
.col (447) UNKOWN
.ddf (1) Readable text / Disc Info
.def (2) Readable text / particle engine related (?)
.dlf (1) Readable text / list of the files of the disc (and adresses)
.dol (1) GC SYS file
.dsf (1) UNKOWN
.elf (1) UNKOWN
.fff (4) UNKOWN (most of them seem to be loaded at boot)
.gcm (1159) UNKOWN
.gct (1249) Texture and / or video
.gxw (33) UNKOWN (?) … contains some strings and refers to tga files …
.img (1) GC SYS file
.inc (1) Readable text / automatically generated, sound related
.ini (2) Readable text / Engine parameters
.odf (1034) Readable text / Character parameters.
.prp (13) Readable text / Planet parameters
.pse (188) Readable text / explosion, laser, particle parameters.
.sky (39) Readable text / Sky parameters (3*13 = 39 …)
.spd (1) UNKOWN
.spt (1) UNKOWN
.ssc (4) Readable text / various roles (sound, script…)
.stb (1) UNKOWN
.tpl (2) Common GC file. banner.tpl can be opened with TPLEditor, icon.tpl won’t open.
.wav (957) Sound file (VLC)
.wld (34) Readable text / world parameters
e.pl (1) UNKOWN

This is more or less everything I gathered so far. I used various tools to navigate through the files and their purposes. As I could not decompress the ISO and recompress it (well, I could perform these two steps, but the game would not go beyond the title screens). I started using the following script.

import sys

host_filepath = sys.argv[1]
payload_filepath = sys.argv[2]

input_filepath = sys.argv[3]
output_filepath = sys.argv[4]

print("Trying to replace [" + host_filepath + "] with [" + payload_filepath + " in [" + input_filepath + "]")

host = open(host_filepath, 'rb').read()
payload = open(payload_filepath, 'rb').read()

if(host==payload):
    print("WARNING : the host and the payload are identical!")

input_file  = open(input_filepath, 'rb')
output_file = open(output_filepath, 'wb')

piece = input_file.read()  
if host in piece:
    piece = piece.replace(host, payload)
    print("Success!")

output_file.write(piece)
        
output_file.close()
input_file.close()

It just looks for a sequence of bytes and replaces it with another. Therefore, with an extracted version of the ISO, I can look for two files and overwrite one with the other. I could per example notice that the .gct files are images or sequence of images (I just replaced the icon of the tank assault with other 22k files). If you know the game, the icon on the bottom left should puzzle you. It is probably the foot of a six leg walker :)

Needed

For the other files, well, it depends. It turns out that a lot of files are just text files! But it seems that they are not used by the games (trying to change the values and injecting them in the ISO did not produce any result). Some people think that they shipped a debug version of game (accidentaly). It makes sense, some folders are actually called UnitTest!

My first guess is that, while most of these files are not called by the game (Dolphin File IO showed that some of these files are actually opened), they are compiled somewhere in the same disc, under another format. The fact that they let us know float / integer values may be useful later on.<p>

Multiplayer maps.

While I was trying to load some elements of a level to another level, I noted that the order of the maps in the game is not the order of the maps on the disc. Per example, the first map (Kashyyk Duel) actually refers to multi4. The following table summarizes the mapping.

Planet Type Number
Kashyyyk Duel 4
Rhen Var Duel 3
Geonosis Duel 1
Thule Duel 15
Raxus Duel 2
Thule Control zone 14
Raxus Control zone 13
Thule Moon Control zone 9
Geonosis Conquest 8
Kashyyk Conquest 12
Thule Moon Conquest 10
Rhen Var Conquest 6
Thule Moon Academy 5
Geonosis Academy 17

Yes, 7 and 11 are not present. There are no movies corresponding or maps where they should be.