sundry datamining

Last week I posted about the Genesis wolf3d-clone Zero Tolerance. I was tempted to play it, but instead went and did some datamining.

The game apparently already had a level editor, but it was nearly completely non-graphical to the point of being useless. I assume the reason for this is that the game’s 3D engine used a non-standard graphics format.

To help locate and decipher the game’s graphics data, I used Brad Smith’s Binxelview, which is an invaluable tool for reverse engineering any kind of uncompressed grid-based data format.

Given that the game is a raycaster on a limited environment, I figured that the graphics were uncompressed and stored column-wise. Binxelview helped quickly confirm this hypothesis. I found that the game’s textures are 32x32 pixels, with 4-bits-per-pixel of color, and stored column-wise in a weird fashion — each column of data is 2 pixels wide (or rather, 1 byte wide). With that knowledge, I could rip the game’s 255 wall-textures:

This texture format applies to every texture in the game, including enemies, like these crabs-like fellows:

textures_0x001AD938

Now, regarding the wall textures, I noticed that in the game a single block on the map appeared to be 4 textures wide and 2 textures tall. I hypothesized several ways this could have been encoded, and used a hex editor to search for a pattern until I came up with a correct hypothesis. This approach worked (eventually). I found that each of the game’s 3 “worlds” began with data that defined how these bigger textures (“metatextures”) were assembled. Here’s what the metatexture set of the first world (the space station) looks like:

(Billboarded sprites appear to use a different format to assemble themselves.)

Now, regarding what I said about “worlds”, each world in the ROM appears to begin with the ASCII string “ZMAP”, which looks like this in a hex editor:

zmap

If we fiddle around this area in Binxelview, a structure begins to become apparent:

0b

The level data is easy to see. Each level is a 32x32 block sized thing, and located right next to each other. Before the level data, I was able to find three different chunks of data. There’s the definitions for all 256 possible metatextures, then what I assume is a list of what metatextures each of the 256 map blocks uses, and then what I assume are the properties for each of those map blocks. After the level data and before the next occurence of “ZMAP” in the ROM is some data that is probably important but I don’t yet understand.

so yeah, I’m not sure where I’m going to go with this… maybe not a full-fledged level editor, but a level viewer would at least be nice. the real pipe dream though would be to give this thing a 4K HD remaster, but that’s still a long shot at the moment.

If you’re really curious you can look at the code I wrote here.

Feel free to post in here about your own datamining adventures!

15 Likes

When I did a partial Phoenix Wright 3 fan translation, a similar tile-oriented visualizer was really useful to figure out the layout of the ROM. The font glyphs were the only thing that I could see per se in the vizualization, but the various gibberish color patterns had distinctly different styles such that I could tell mystery data X started at this offset, mystery data Y started at another offset, and then I could examine the start of them to check for characteristic compression format headers, and check the code blocks to see where the address of the start offset was mentioned. I found it overall surprisingly easy to unravel because nobody planned to obsfuscate anything.

4 Likes