The current URL is datacrystal.tcrf.net.
Robotrek/Notes
The following article is a Notes Page for Robotrek.
Map Meta
There are two map meta tables: one at 0x040000, and another at 0x0D8000. These tables define how assets are loaded into each map/scene. Each map record in a meta table starts with a two-byte map ID, followed by an array of "asset" entries. There are 8 major types of assets, which are defined by the first byte of the asset entry itself. Each map record is terminated by a single byte 0x00 (asset 0). Each meta table ends with a single, empty map 0xFFFF record, followed by 0x2121. To find a map/marker, the entire meta table is scanned sequentially up to either the map or marker ID. This consumes a lot of CPU time.
{ mapId: Word, assets: meta[], terminator: Byte }
{ mapId: Word, assets: meta[], terminator: Byte }
...etc
{ mapId: 0xFFFF, assets: [], terminator: 0}
{ 0x2121 }
Control Commands
Meta asset 08 entries are Control commands. They define miscellaneous functions that are applied to the map loading process. The second byte of a Control command determines what function it serves. Each map record starts with a State Control (08 00) entry which defines a global post-marker, and a state index from which to load scene effect information.
Music Loading
Table D8000 begins with a special map with ID 7FFF which serves as a list of Music assets to be referenced by BGM Control (08 FC). Instead of defining a Music(02) asset in the map, there are instead BGM Control entries (to save space perhaps, 4 vs 6 bytes). A person could opt to use either it seems, at the cost of either space or CPU.
Separate Map Meta Tables
For some reason Quintet decided to use two tables for map definitions. Building on their process from Illusion of Gaia etc, since Robotrek has twice as many maps, they could not feasibly use a single table as the map load sequence would be painfully long. It is important to note that the map IDs from each table do not intersect, they are unique with the exception of map IDs 0000 and FFFF. Map 0000 from D8000 is loaded when the game boots.
Address Encoding
For some reason, each asset's data address is encoded using a process unique to this game, instead of using direct addresses. The process is somewhat complicated and involves shifting the upper bits 0x7F8000 << 1 and adding 0x8D or 0xC4 depending on which table is being read. The procedure for decoding them can be found here: https://github.com/Azarem/gaia-core/blob/main/src/rom/extraction/parser.ts#L291
| ID | Type | Parts | Description |
|---|---|---|---|
| 00 | NULL | Terminates map record | |
| 01 | Strangemap | { Byte, Word, Address } | Loads a compressed "strangemap" into memory. Not much is known, only two of these data files exist and only four 01 records total. |
| 02 | Music | state: Byte musicId: Byte data: Address |
Immediately loads music stored at data address, but only if the musicId and data address are not currently being played. |
| 04 | Unknown | ?? | This does not seem to be used anywhere |
| 08 00 |
State | markerId: Byte stateIndex: Byte |
Each map starts with a State Control asset. This sets a markerId to be jumped to after all other entries are processed (or 0). The stateIndex determines which set of transparency / background / effect modes that are set when the map is loaded. |
| 08 FC |
BGM | musicId: Byte null: Byte |
Immediately loads Music asset from map record 7FFF (first map in table D8000), determined by musicId |
| 08 FD |
Branch | flagId: Byte markerId: Byte |
Branches/jumps to marker defined with markerId, but only if flagId is satisfied |
| 08 FE |
Marker | markerId: Byte null: Byte |
Sets a marker to be used by Jump and Branch commands, defined by markerId |
| 08 FF |
Jump | markerId: Byte null: Byte |
Immediately stops reading assets and instead jumps to marker defined with markerId |
| 10 | Tilemap | layer: Byte data: Address |
Loads a tilemap |
| 20 | Tileset | srcOffset: Byte size: Byte dstOffset: Byte layer: Byte data: Address |
Copies tileset information into 0x7E2000 - 0x7E37FF after decompression. All tilesets are compressed. srcOffset bit 0x80 seems to denote that the tileset is not compressed but implementation was never added to handle this. srcOffset is << 6 and determines the offset from data in which to copy. size is also << 6 and determines the total size of the tileset data, but each tileset is exactly 0x800 bytes so this is not necessarily useful. dstOffset is << 6 and determines the offset from WRAM in which to copy data. layer determines which slot to copy the data into: 1, 2, 4 equates to 7E2000, 7E2800, and 7E3000, even though flag 4 seems to never be used. A tileset could potentially be copied into multiple layers. |
| 40 | Palette | srcOffset: Byte size: Byte dstOffset: Byte data: Address |
Copies palette information, which is not compressed, into 0x7E3800. srcOffset << 1 determines the offset from data in which to copy. size is << 1 and determines the total size of the palette file, not necessarily the size being copied. dstOffset is << 1 and determines the offset into 0x7E3800 in which to copy. The total data length copied is (size - srcOffset) << 1. |
| 80 | Bitmap | srcOffset: Byte size: Byte dstOffset: Byte data: Address |
Loads a bitmap into VRAM. srcOffset is << 9 bits (* 512), if srcOffset upper bit 0x80 is set it means the file is not compressed. Size is also << 9 bits (* 512) and determines the size of the bitmap data itself. dstOffset is the location in VRAM being copied to. The total length copied is (size - srcOffset & 0x7F) << 9 |
Internal Data for Robotrek
| |
|---|---|