7

As a personal project I've been trying to reverse engineer the art assets for the old Dynamix game Earthsiege 2 (this game has long been abandonware and was recently released for free by Hi-Rez, the current copyright holder). It was child's play to decode the images/textures, but I've been having trouble with the binary 3D model format.

As some background, the 3D models are saved as DTS files. DTS is a proprietary binary format (little-Endian), short for "Dynamix Three-Space". I wasn't able to find any resources on reversing ES2-era DTS files.

For this post I'll focus on the Apocalypse.

The Apocalypse in-game; take note there are discrete parts rather than a single mesh

The Apocalypse model is stored in Apoca.dts . The file starts out like this (in hex, with annotations):

  | File size |     ?     |ChunkMarker|Chunk Length
02|7C 7F 01 00|4B 1F 3D 7F|03 00 1E 00|FC 5F 00 
00|FF FF 00 00 0E 08 BF FF CC FF 23 04 01 00 15 
00 14 00 70 46 00 00 FF FF 00 00 B7 06 BF FF CC 
FF 23 04 1B 00 14 00 14 00 4A 01 00 00 01 00 0C 
00 AB 01 FB FF 22 00 7B 05 18 00 0F 00 10 00 06  <-Faces
00 02 00 03 00 04 00 05 00 02 00 05 00 07 00 08 
00 0A 00 0B 00 04 00 03 00 03 00 02 00 08 00 0A 
00 0B 00 07 00 05 00 04 00 0A 00 08 00 07 00 0B 
00 00 00 1D 00 FF 07 00 00 00 00 00 00 24 FF 72  <-Some vertices here
01 82 05 DC 00 72 01 82 05 DC 00 C0 FE 8C 05 24  <-
FF C0 FE 8C 05 00 F8 00 00 00 00 24 FF E8 FE 00  <-
05 24 FF 04 01 60 04 00 08 00 00 00 00 DC 00 04  <-
01 60 04 DC 00 E8 FE 00 05 00 00 7A 07 2A FD 00  <-
00 4F F8 CE FD 00 00 BB FD 55 F8 02 00 00 04 02 
00 00 04 00 00 00 14 00 00 00 14 00 00 00 00 FF 
FF FF FF FF FF FF FF FF FF FF FF 1B 00 00 00 FF 
FF FF FF FF FF FF FF FF FF FF FF 19 00 00 00 FF 
FF FF FF FF FF FF FF FF FF FF FF 03 00 14 00 0A 
00 00 00 00 00 02 00 04 00 00 00 00 00 03 00 14

For formatted/color-coded analysis, see http://postimg.org/image/8e56re90n/

To see the first 3 chunks of the file in their entirety, see http://pastebin.com/RTFkdiBd

Current knowledge

Each DTS file is broken into chunks. The 10th - 13th bytes are a start-of-chunk marker; I think this is 03 00 1E 00 in each file. The next four bytes are the size of the chunk, always followed by FF 00. A new chunk will begin immediately after the previous ends. I don't know how the chunks divvy up data right now, but it does appear that multiple chunks contain vertices. This may be related to the fact that the model is noticeably divided into discrete parts, rather than a single mesh.

Each vertex is a set of 6 bytes, consisting of 3 signed shorts for the X, Y, and Z coordinates of that vertex. The first vertex in this file is 24 FF 62 01 82 05, which has coordinates -220, 354, 1401 when converted to decimal. The sample I've provided contains the following vertices:

24 FF 72 01 82 05 
DC 00 72 01 82 05 
DC 00 C0 FE 8C 05 
24 FF C0 FE 8C 05
24 FF E8 FE 00 05
24 FF 04 01 60 04
DC 00 04 01 60 04 
DC 00 E8 FE 00 05

These vertices define the crotch. Interestingly, the crotch is actually located above the head in 3D space as defined in the file, so it must get translated somewhere. I have tested and verified that the above bytes contain the crotch by editing them in RAM while the game is running, which distorts the model immediately when I click back into the game window.

Notice that between some of these vertices are two sets of six bytes that do not appear to be vertices (they don't correspond to any point on the model and have no effect when altered in RAM). I don't know what the deal with these is:

00 F8 00 00 00 00
00 08 00 00 00 00

The rest of the model is defined in pieces throughout the file. Vertices are clustered into small groups, which I think define one shape at a time. I can find vertices for everything but the weapons and legs. The legs are animated, so they might be defined differently, or located in a different file. The weapons are defined in a separate file.

Preceding the vertices are some shorts with small values, e.g. 06 00 02 00. These have something to do with the faces; my guess is that they refer to vertices by index to define a face. I have verified that these affect the faces by editing them in RAM while the game is running, but haven't fully decoded them yet.

There is always 6 bytes of 0s (00 00 00 00 00 00) between the faces and the vertices. There is always the marker 04 00 00 00 14 00 00 00 14 00 00 00 shortly after the vertices end. Using this knowledge, I'm able to parse vertices from a file by looking between those two markers; however, this is imprecise and I end up with a bunch of junk vertices forming a partial spherical shell around the model.

Here is a rendering of a point cloud of vertices I am able to read out of the Apocalypse DTS file; I have filtered out some of the junk vertices here, but there are still some present around the edges and in the middle. Take note that the hips and crotch are located above the torso in the file. enter image description here

What's next?

I'm not hoping to decode the entire DTS file from start to finish - it's much too long and complex - but I'd like to at least be able to read the vertices, and hopefully faces, out of the files.

The biggest struggle I've been having at the moment is trying to figure out how to know exactly where a set of faces/vertices start and end. My main question would be how to precisely determine where a group of faces/vertices start and end, as they are not in the exact same place in every file. Any other information you can spot that I've missed would be awesome, but that's my main objective.

3
  • I'm currently having a same project for a 2001 korean MMORPG that has long been abandoned. Like you, the textures was easy. But the objects is where I'm currently stuck. Can you share any resource or book that helped you finally decode the object file?
    – majidarif
    Commented Aug 20, 2016 at 15:27
  • 1
    @majidarif First, it's very unlikely there is any similarity in file format between the two titles. Secondly, if you read the accepted answer, you will learn everything that I learned.
    – user45623
    Commented Aug 26, 2016 at 0:10
  • Is this still being worked on? Just wanted to say that I was able to convert some models from Earthsiege 1 with booto's script.
    – robosalad
    Commented Mar 17, 2019 at 16:13

1 Answer 1

6

To determine where the faces/vertices are laid out purely via inspection can be pretty time consuming and hit-and-miss. Given the executable is available that processes these files, I think it's probably a better starting point - it definitively knows how to process the format.

I used IDA Pro to analyse the code in the executable that's involved in loading the data, using the some magic numbers [including the 0x001e0003 you noted as the ChunkMarker] to locate the relevant parts and expanding from there.

You'll find that there are some duplications of surfaces in the mesh - I think the base mesh is just solid-shaded, but uses textures sparingly like decals over the base mesh.

Here's an example imported into Blender. enter image description here

You can access the code I wrote to generate that on github.

11
  • And here I had given up on ever getting a reply. You sir, win all of the internets. I wish I could give you more upvotes than this. I can't wait to give your script a whirl. I had considered trying to go into the EXE with a debugger, but I've never attempted that before and didn't even know where to start.
    – user45623
    Commented Dec 18, 2015 at 23:26
  • I assume you were looking at DBSIM.exe? If you can easily explain how to do what you did, I'd certainly appreciate it, but if it's the kind of thing that's a huge hassle to explain to someone unfamiliar with IDA or disassemblers in general, no worries. Thanks either way!
    – user45623
    Commented Dec 18, 2015 at 23:33
  • Could you specify what version of Python and lib3ds? I'm guessing Python 2.x from the lack of parens in your print statements?
    – user45623
    Commented Dec 19, 2015 at 1:05
  • 1
    Python 2.7 from the looks of things.
    – booto
    Commented Dec 19, 2015 at 4:12
  • 1
    Indeed, it was "dbsim.exe". Starting at 0x00405F09 (via that magic number) and tracing from there. You'll find that 0xc bytes before the start of a vtable is a pointer to a struct that contains meta data about the class (it might be whatever borland's c++ stuff uses for rtti?) Lib3ds version seems to be 1.3.0? I just installed whatever version debian had packaged up.
    – booto
    Commented Dec 19, 2015 at 4:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.