Tomba!/Technical information

From Tomba! Wiki
Revision as of 13:48, 30 January 2025 by SiergiejW (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Understanding Tomba

File:Tombaexplain.pngSchematic explanation of FLA, LDAR, GAM files by vervalkon

This is an eternally unfinished document that tries its best to explain how Tomba and its various file formats work. There might be mistakes, there might be misinformation, but all of the things written have been verified to be true in a sense that exporters and converters based off this info work and produce legitimate output.

There might be things we've missed and there might be things we just don't know, so if you're a PSX hacker and/or know r3000 well, please join our Discord group: https://discord.gg/RXgDnkv

The ISO

There are four retail versions of the game and a varying amount of demos per region.

SLPS-01144for the JP version SCUS-94236for the US version SCES-01330and `SCES-01331for the PAL versions

The notable visual differences between these are obviously the languages, but also the fact that the Japanese version uses few to no polygons with vertex coloring (gouraud shading, vertex shading, shaded polygons, gradated polygons, whatever you want to call it) on.

Structurally the JP version is very different to the US and PAL releases, but more on that later. Unless otherwise noted, I will be talking about the US retail version.

The Contents

Unpacking the ISO will give you the following:

AREA00 to AREA19

These are the folders corresponding to the areas in the game, with the exception of the empty folders found in the JP version and the AREA15 folder found in all versions. When you see a loading screen in-game, the game is looking up files from one of these folders.

The numbers correspond to the AREAS found in the Areas and sections chapter.

These folders contain all the files used for creating an area, including images to put into VRAM, area dialogue, collision, models, assets and their placement.

MOVIE

Contains all the FMV sequences in the game. Standard STR files, nothing special.

SCUS_942.36

The executable itself. This file runs when the game is booted and besides critical code, it contains important arrays related to file linkage and camera coordinates, among others. The executable in the Japanese version has much more data in it, including the LDAR data. For the rest of the doc, this file will be referred to as the Executable.

SOUND

Contains standard SEQ and WVD data - sequenced music and wavetables. Nothing special.

SYS

Contains the LDARs. See the LDAR section for more information. Note: this folder is not in the JP version of the game.

SYSTEM

Contains all kinds of miscellaneous stuff, including graphics, models and Xfiles. These don't particularly fit into any single area folder, as there are things like the Game Over models and the Map models (and textures) here.

Additionally, there are several unused graphics to be found.

SYSTEM.CNF

This small 68 byte file contains the following ASCII:

 // BOOT = cdrom:\SCUS_942.36;1
 // TCB = 4
 // EVENT = 10
 // STACK = 80200000 

Likely just boot information for the game, guessing that this is the first file the PSX reads.

ZZZ

Contains a file called DUMMY.DAT, filled with $1A5E000zeroes. There is probably an anti-piracy or file lookup efficiency related reason for why this file exists, but generally it's useless and of no concern.

Understanding LDARs

The SYS folder's LDAR files are as follows:

LDAR00.BIN, LDAR01.BIN, LDAR02.BIN, LDAR03.BIN,
LDAR04.BIN, LDAR05.BIN, LDAR06.BIN, LDAR07.BIN,
LDAR08.BIN, LDAR09.BIN, LDAR10.BIN, LDAR11.BIN,
LDAR12.BIN, LDAR13.BIN, LDAR14.BIN, LDAR16.BIN,
LDAR17.BIN, LDAR18.BIN, LDAR19.BIN, LDSYS.BIN

Essentially, this folder contains an LDAR file for every AREA, excluding the AREA15. The LDAR files contain instructions that tell the game to fetch files and either split them into smaller pieces to push into RAM or just take and draw into the VRAM. Once the data is decompressed or written into (V)RAM,

An LDAR is a "bill of materials", if you will.

Reading the LDAR files is relatively straightforward: you read Entries that consist of byte groups of size $14bytes until you encounter an group of exactly:

FF FF FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00

The following bytes are an excerpt from LDAR00. I've annotated the columns on the top, and a legend is provided after the bytes. Some bytes have been grouped to little endian longs for readability's sake.

xxxxxxxx fidx ftpe ram-info fs-or-xy wdth hght`_ `00000006 0149 10FF 80141000 00800000 0040 0080 00000001 014A 10FF 80141000 010000C0 0040 0100 00000001 014B 10FF 80141000 00000240 01C0 0100 00000001 014C 10FF 80141000 01000000 00C0 0100 00000001 014D F0FF 00000000 00053F38 0000 0000 00000002 014E 60FF 80140000 0002E008 0000 0000 00000004 0000 62FF 00000000 00014CDC 0000 0000 FFFFFFFF 014F 63FF 00000000 000018C8 0000 0000 00000003 0000 30FF 00000000 00003248 0000 0000 FFFFFFFF 0000 35FF 00000000 0000067C 0000 0000 FFFFFFFF 0000 31FF 00000000 0000008C 0000 0000 FFFFFFFF 0000 3FFF 00000000 000003C0 0000 0000 FFFFFFFF 0000 32FF 00000000 00001C98 0000 0000 FFFFFFFF 0000 33FF 00000000 00002488 0000 0000 FFFFFFFF 0000 34FF 00000000 00004CDC 0000 0000 FFFFFFFF 0000 37FF 00000000 000002BC 0000 0000 FFFFFFFF 0000 39FF 00000000 00001EBC 0000 0000 FFFFFFFF 0000 53FF 00000000 000001F4 0000 0000 FFFFFFFF 0000 71FF 00000000 00005980 0000 0000 FFFFFFFF 0000 52FF 00000000 00000978 0000 0000 FFFFFFFF 0000 54FF 00000000 00001694 0000 0000 FFFFFFFF 0000 B2FF 00000000 00000528 0000 0000 FFFFFFFF 0000 B3FF 00000000 000003D0 0000 0000 FFFFFFFF 0000 D1FF 00000000 0000412C 0000 0000 FFFFFFFF 0000 86FF 00000000 00000400 0000 0000 FFFFFFFF FFFF 0000 00000000 00000000 0000 0000 etc...

Legend:

  • xxxxxxxx: These bytes can be ignored.
  • fidx: The file index. If nonzero,this tells what file to load into memory, either into the address that's in the group's `ram-info`, or in the case of `wdthand`hghtbeing nonzero, into the VRAM to the coordinates that the`fs-or-xy describes. If `fidx itself is zero, the 'keep reading' flag is set, and the next byte group won't load a new file for reading,but instead keeps reading the same file's data from where it left off. First such instance can be found in the sixth row in thee xample above. You first write $0002E008bytes from file index$14E`, then start a new file where you keep reading file $14Efor$00014CDCadditional bytes.
  • ftpe: File type. If nonzero, thistells the game what type of data we're dealing with. For more information see the file types section.
  • ram-info: If nonzero, contains aRAM address where the game pushes the data for decompression or simply for storage. To-be-decompressed data usually goes to$80141000`, while static data into $80140000`(?). If the value iszero, the file is a raw file so no decompression is involved.
  • fs-or-xy: If `wdthand `hghtarezero, read as a 4-byte word for file size. Essentially, how many bytes to decompress (or read if it's a raw file). If `wdthand`hghtare nonzero, read as two 2-byte words for X and Y coordinatesfor the spot where to start writing the data in VRAM.
  • wwww: If nonzero, the width of thegraphic to write in VRAM.
  • hhhh: If nonzero, the height of the graphic to write in VRAM.

The LDARtool does exactly this; it takes an LDAR file as input, makes a folder for the entry, reads the byte groups and acts accordingly; reading files and decompressing them into the folder until a terminator is found, after which a new folder is created and the next set of byte groups is scoured through. This repeats until a `00 00 00 00 AC 7F 09 80occurs. This is an unconventional and probably incorrect, but it works.

The LDARtool's output naming convention is as follows: The first folder is always called 'base' as it's the baseline files you _need_ to first get before you can do anything, really. After that, the following folders are indexed from 0 upwards in decimal. These numbers correspond to the SECTIONS found in the Areas and sections chapter.

Understanding File Links

The LDARs don't refer to filenames or use some kind of pointers, but file indexes. What that means is that whenever, say, file index $0149is called, the game looks up the entry of index $0149(or in decimal, 329) in the **File Link Array.**

- In the US version, the File Link Array is located in **the Executable** at address $699A0and contains $41Eentries. - In the JP version, it's at $634CCand contains $33Centries.

For the sake of brevity, here are the File Link Array's indexes 0 to 3. The legend is below:

mm ss SS nn fs......`_ `21 23 10 00 00001E18 21 22 59 00 00000890 21 22 61 00 0000079C 21 22 62 00 0000087C

mm: Minute

ss: Second

SS: Sector

nn: Unused

fs: File size. Essentially, how many bytes to read.

Now, the minute, second and sector alone don't tell you very much, so you must look at the ISO file itself. It would be wise to open the ISO (or BIN) in a hex editor now.

The ISO is built from exactly 119130 chunks of $930(2352 in decimal) bytes. A single chunk is called a **Sector** and consists of seven parts:

`Sync: $0C bytes Header: $04 bytes Sub-Header: $04 bytes Copy of Sub-Header: $04 bytes Data: $800 bytes EDC: $04 bytes ECC: $114 bytes

The only thing that interests us about any of the sectors is the **Header**. The header consists of four bytes: Minute, Second, Sector and Mode. While Mode can be ignored, the triplet of bytes the Sector Header's values form _is the sector the File Link Array is looking for.

So let's recap one more time:

1. LDAR calls File Index $01492. In the File Link Array, the "mm ss SStriplet" of index $0149is 00 05 733. If you were to skip through the entire ISO, one sector at a time, you would eventually find a sector that's **Header** is _also_ `00 05 73`. 4. This sector is _the_ sector that's **Data** the game reads to get what the LDAR asks for.

Notes:

  • There might be (and probably is) a method of calculating the address/sector in the ISO just by the "mm ss SStriplet" alone. That's just math I never looked into.
  • You can't simply go to the Data section of the sector and start reading the `fsamount of bytes, as you will hit the EDC after $800bytes. Please refer to the nocash docs if you wish to look into the issue deeper.
  • You will lose filename context if you just dump yourself a list of binaries based on whatever the File Link Array tells you.

This is a convoluted process to do manually, so ISOtool helps with this a bit, by generating a plaintext file that pairs up the filenames with their file indexes automatically, albeit only for the US version for the time being.

GAMs

Most of the files in the game are compressed with the GAM compression. You can use the Japanese Ungammer to decompress any number of GAMs, but the specification is below for educational and inspirational purposes:

47 41 4D 00 / cccc / magicnumber, $00-terminated "GAM" in ASCII 00 80 00 00 / i4le / outputfilesize, ($800 here) C0 00 / i2le / commandword

must be read as binary:

                    0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0

(data...)

The decompression is relatively straightforward.

Shift the command word right:

- If overflowing bit is `0`, read one byte from the GAM and print it to output file. Repeat step 1 (unless it's EOF)
- If overflowing bit is `1`, read _two bytes_ from the GAM as `distand `amnt`. In the output file, seek backwards `distbytes and read `amntbytes. Write them into the output. Go back to step 1 (unless it's EOF)
- If all 16 bits have been shifted, read another two bytes as a commandword (unless it's EOF)

Notes:

  • While a GAM decompressor has been programmed, a GAM compressor is yet to be done.
  • EOF (End-Of-File) condition is true immediately when either `outputfilesizebytes have been written to output or there is no bytes in the GAM left to read.

What the LDARs give us

Using the LDARtool, we get a folders filled with several kinds of files. Although the only hint of their file _type_ is the ftpevalue in the LDAR bytegroups, research has shown us what kind of files these values represent. Some original filetype extensions could also be determined. Below is a non-exhaustive list of all known filetypes and their `ftpevalues:

Areas and Sections

AREAs are what the game indexes the AREA folders by, and they correspond to the following areas in the game. Every AREA has a varying amount of SECTIONs, and you can access them with the level select debug mode. SECTIONs are also what the LDAR entries correspond to.

00: Village of All Beginnings

00: Village of All Beginnings  
01: Forest of All Beginnings  
02: Forest of All Beginnings (hut entrance)  
03: 100 Year Old Man's Hut  
04: Behind the Hut  
05: Ol' Pond  

01: Dwarf Forest

00: Forest of 100 Flowers  
01: Forest of 100 Flowers (right entrance)  
02: Wobbly Wharf  
03: Watch Tower  
04: Charity Square  

02: Dwarf village

00: Dwarf village  
01: Dwarf Elder's Hut  
02: Underground Prison  
03: Underground Maze  
04: Million Year Old Man's Room  
05: The Strange Small Room  

03: Phoenix mountain

00: Stormy Mountain  
01: Stormy Mountain (second part)  
02: Lava Caves  
03: Phoenix's nest  
04: Stormy Mountain (purified)  
05: Stormy Mountain (purified, second part)  

04: Haunted Mansion

00: North Side of Mansion  
01: West Side of Mansion  
02: South Side of Mansion  
03: East Side of Mansion  
04: Sunny Room  
05: Thief's Room One  
06: Swimming Room  
07: Keyhole Room  
08: Hiding Room  
09: Room of Tribulation  
10: Laughing Room  
11: Civilization Room  
12: Trap Room  
13: Trick Room  
14: Sun Torch Stand  
15: 1,000 Year Old Man's Room  
16: Shadow Room  
17: Thief's Room Two  
18: Thief's Room Three  
19: Crying Room  

05: Baccus Village

00: Baccus Village  
01: Central Park  
02: Baccus Village  
03: Central Park  

06: Motocross segment

00: Dirt Motocross  
01: The Mermaid's Singing Rock (beach)  
02: The Mermaid's Singing Rock (mermaid)  

07: Dwarf Forest (purified)

00: Forest of 100 Flowers  
01: Forest of 100 Flowers (right entrance)  
02: Wobbly Wharf  
03: Watch Tower  
04: Charity Square  

08: Baccus Lake

00: Baccus Pier  
01: Baccus Lake  
02: Baccus Pier  
03: Baccus Lake  

09: Mushroom village

00: Mushroom Forest  
01: Lake  
02: Mansion (Grandfather clock room)  
03: Mansion (Chandelier room)  
04: Mansion (descending stairs)  
05: Mansion (ascending stairs)  
06: Leaf Slider  

10: Deep Jungle

00: Masakari Jungle  
01: Masakari River  
02: Old Tree Hill  
03: Trick Village  
04: Masakari Jungle (purified)  
05: Masakari River (purified)  
06: Old Tree Hill (purified)  
07: Trick Village (purified)  
08: 10,000 Year Old Man's Room  

11: Village of Civilization

00: Lumberjack Town (crashes/soft locks the game)  
01: Lumberjack Factory  
02: Dried Wishing Well  

12: Haunted Mansion (purified)

00: North Side of Mansion  
01: West Side of Mansion  
02: South Side of Mansion  
03: East Side of Mansion  
04: Sunny Room  
05: Thief's Room One  
06: Swimming Room  
07: Keyhole Room  
08: Hiding Room  
09: Room of Tribulation  
10: Laughing Room  
11: Civilization Room  
12: Trap Room  
13: Trick Room  
14: Sun Torch Stand  
15: 1,000 Year Old Man's Room  
16: Shadow Room  
17: Thief's Room Two  
18: Thief's Room Three  
19: Crying Room  

13: Pig Island

00: Outer Walls of Pig Island (Flower Tower)  
01: x Year Old Men Ending  

14: Evil Pigs

00: Evil Pig Area One  
01: Evil Pig Area Two  
02: Evil Pig Area Three  
03: Evil Pig Area Four  
04: Evil Pig Area Five  
05: Evil Pig Area Six  
06: Evil Pig Area Seven  
07: Evil Pig Area Eight  

16: Village of Civilization (Clock Tower)

00: Stonestown (soft locks the game)  
01: Clock Tower (soft locks the game)  
02: Clock Tower (crash)  
03: Clock Tower (Engine room)  
04: Clock Tower (Entrance)  
05: Clock Tower (Halfway up)  
06: Clock Tower (Engine room, no exit)  

17: Village of Civilization (Iron Tower)

00: Iron Town (crashes the game)  
01: Iron Castle (entrance)  
02: Iron Castle (main room)  
03: Iron Castle (left room)  
04: Iron Castle (right room)  
05: Iron Castle (engine room)  
06: Iron Castle (soft lock)  
06: Iron Castle (soft lock)  
07: Iron Castle (soft lock)  
08: Iron Castle (crashes the game)  
09: Iron Castle (soft lock, "Y Crossing" music plays)  
10: Iron Castle (soft lock, "Witch's Hut" music plays)  

18: Village of Civilization (Y Crossing)

00: Village of Civilization (crash/soft lock)  
01: Y crossing  
02: Witch's Hut  

19: Village of Civilization (Purified Dwarf village / Hidden Village)

00: Dwarf Elder's Hut  
01: Dwarf Elder's Hut  
02: Hidden Village