Friday, October 30, 2009

So very, very close. I'm still not entirely sure where the triangle strips split. I should step through and dump each seg and compare.

Monday, October 26, 2009

Almost there! I need to figure out how it seperates triangle strips. Heres a snippet of how some of the data looks. Colors added so its easier for me to see.

Seg: 0

glColor3ub: 255, 0, 0
glVertex3f: -0.000037, -0.608202, 0.081231
glNormal3f: 0.000000, -0.964665, -0.263480
glColor3ub: 255, 3, 15
glVertex3f: -0.032418, -0.628641, 0.168047
glNormal3f: -0.486626, -0.869009, -0.089545
glColor3ub: 255, 6, 30
glVertex3f: -0.000037, -0.639352, 0.165360
glNormal3f: -0.000000, -0.994484, -0.104884
glColor3ub: 255, 9, 45
glVertex3f: -0.000037, -0.632022, 0.292810
glNormal3f: 0.023657, -0.978470, 0.205027
glColor3ub: 255, 12, 60
glVertex3f: 0.032344, -0.628641, 0.168047
glNormal3f: 0.486626, -0.869009, -0.089545
glColor3ub: 255, 15, 75
glVertex3f: 0.032344, -0.620568, 0.288912
glNormal3f: 0.485757, -0.855460, 0.179521
glColor3ub: 255, 18, 90
glVertex3f: 0.061969, -0.606039, 0.174220
glNormal3f: 0.818140, -0.572090, -0.057962
glColor3ub: 255, 21, 105
glVertex3f: 0.062988, -0.596447, 0.288289
glNormal3f: 0.811773, -0.571966, 0.117813

Tuesday, October 20, 2009

IMD Update

Progress happens slowly sometimes. I know that verts with Z = 1.0f are texture coordinates. Verts with the 0x00003f80 flag seem to be related to normals. Furthermore, verts with 0x0000bf80 or 0x00000001 flag appear to be the actual verts used marked in the above image as green and red accordingly. I already know the PS2 doesn't support quads so the data must represent triangles or triangle strips but I am unclear on how the vertices are ordered in the file.

Thursday, October 15, 2009

Metal Gear Solid KMD

I documented the KMD format to the best of my knowledge on the Xentax wiki.

I got a bunch of PSX games recently and I was bored today so I looked at a few. Great show, shitty game, simple data. This game uses PSX TMD format for meshes and packs of TIM format for all images and textures.

Wednesday, October 14, 2009

The rundown...

I've never given a rundown of all the projects I've got rolling around, so here we go!  First up is Jet Set Radio for Sega Dreamcast. All game data is stored in CRI's AFS format. The most common use I've seen for AFS is for storing music, but the container can hold any file type. Textures are Dreamcast specific PVR format, viewable with IrfanView. Details of other formats are as of now unknown.

Also of note is Bionic Commando: Rearmed, lots of wild data in there. The game runs on compiled Lua code and keeps all its data stored in a huge file store. Individual pieces of data are stored in XBox formats that I haven't investigated much. The music is available as OGG.

I did some work on Bust a Move 2(the dancing game) also. The meshes look like they store a lot of animation data and the verts are hard to make out. Textures are a modified 8-bit format that I haven't fully worked out yet.

The Wipeout series has been interesting. Wipeout and Wipeout XL use almost the exact same data types between them. There is some simple LZSS-type compression. I'd assume that the engines are not very different. Basic track data is stored as a linked list of quads with some fixed data that I dont know and some translation info that I haven't worked on. Wipeout 3 is a little different and stores data in a large file that looks compressed. Wipeout Fusion on PS2 has been a lot of fun. I found all the music in uncompressed 48khz 16-bit stereo RIFF WAV format. I haven't fully reverse engineered the data store format, but it's pretty straightforward.

I also did Magical Battle Arena; a doujin game similar to the Dragonball Budokai series, but with magical girls. Meshes are in .X format and textures in .DDS format. Both of these are DirectX specific and can be imported and edited with various available tools. Sound effects are normal WAV files and music is in MP3 format.

Of course theres R-Type Delta and Final and Metal Gear Solid which I've talked about before.

To the left are all the vertices in the R9A mesh visualized as a point cloud. In the red square is the R9A itself. The surrounding point cloud are lighting normals. The rectangular area in the bottom left are the texture coordinates.

R-Type Delta

So I ripped up R-Type Delta PSX a little while back. Lots of VB/VH pairs(audio) and a lot of PSX EXE's(0x09 and 0x04 types according to the PAK header) that don't disassemble properly. Self modifying code maybe or libraries or something... The real meat seems to be in the 0x08 file type but I can't make heads or tails of it, looks compressed :( But I now know what a pBAV four-cc is and what VB/VH files look like, seen em other places before.


This is another part-time project of mine. I ported the last available source for Keropi(WinX68k) 0.76 from full on win32 nasty to SDL. There are already working Windows and Linux builds. There is some performance issue in the Linux port, perhaps a timer resolution issue or something.

I was fortunate that someone else had ported the existing inline assembly to GAS format and added C fallbacks for many things while still including the MASM version. Great work nonaka!

A Mac OS X port is in the works but has some issues with NASM producing broken object files or otherwise the linker isn't finding the exports. A similar issue was previously resolved for the Linux port.

Tuesday, October 6, 2009

Just for fun, some notes I made on MGS.

short x
short y
short z


5 sides, 6?

2 sided faces?

number of meshes and number of faces?
01 00 00 00 01 00 00 00
01 00 00 00 0A 00 00 00

header data might be bounding boxes

fe89   ffff   fe76   ffff   fee9   ffff
65161, 65535, 65142, 65535, 65257, 65535

375,  0, 355, 0, 721, 0, 1, 0, 10, 0

looks like vertex data in the playstation fixed point format
short x
short y
short z
short pad

vert list
00000078h: 0000 6301 D102 FFFF 8AFE 6301 D102 FFFF
00000088h: 8AFE 76FE D102 FFFF 0000 76FE D102 FFFF
00000098h: 7701 76FE D002 FFFF 7601 76FE E9FE FFFF
000000a8h: 7601 6301 E9FE FFFF 7701 6301 D002 FFFF
000000b8h: 0000 6301 EAFE FFFF 0000 76FE EAFE FFFF
000000c8h: 89FE 76FE EAFE FFFF 89FE 6301 EAFE FFFF

verts at each point
03 02 01 00
07 06 05 04
09 05 06 08
0B 01 02 0A
00 07 04 03
08 06 07 00
00 01 0B 08
08 0B 0A 09
09 0A 02 03
03 04 05 09          

00000100h: FCFF B0F4 B0F4 FFFF 3909 C4F6 C0F6 FFFF
00000110h: 3909 3C09 C0F6 FFFF FCFF 500B B0F4 FFFF
00000120h: C0F6 3C09 C7F6 FFFF C7F6 3C09 4009 FFFF
00000130h: C7F6 C4F6 4009 FFFF C0F6 C4F6 C7F6 FFFF
00000140h: 0400 B0F4 500B FFFF 0400 500B 500B FFFF
00000150h: 4009 3C09 3909 FFFF 4009 C4F6 3909 FFFF 

    0  1  2  3
0  03 02 01 00
1  07 06 05 04
2  09 05 06 08
3  0B 01 02 0A
4  00 07 04 03
5  08 06 07 00
6  00 01 0B 08
7  08 0B 0A 09
8  09 0A 02 03
9  03 04 05 09

7FF4 00
F4 0000
7F00 00
00 F700
F7F4 00
F4 7FF4
00F4 00
00 7F00
0000 F7
00 F7F4
00F4 7F
00 F400
F4F4 7F
F4 F77F
F700 00
00 007F
007F 00
F77F 7F
00 F400
F4F4 7F
F4 743D
723D 72
3F 743F
743F 77
3F 773D

texture coordinates
DC AD 6C 55
6C 55 DC AD


20 verts

it goes like this!!

list of verts
verts used in faces!   

must be followed by tex coords and normals

6C 00 00 00
66 00 00 00     

00000028h: 30 F8 FF FF E4 DA FF FF 65 87 FF FF 35 0C 00 00 ; 0øÿÿäÚÿÿe‡ÿÿ5...
00000038h: 68 42 00 00 5E 9D FF FF 00 00 00 00 00 00 00 00 ; hB..^ÿÿ........
00000048h: 00 00 00 00 FF FF FF FF FF FF FF FF 61 00 00 00 ; ....ÿÿÿÿÿÿÿÿa...
00000058h: 20 37 00 00 28 3A 00 00 09 00 00 00 28 3B 00 00 ;  7..(:......(;..
00000068h: 70 3B 00 00 70 3C 00 00 70 3E 00 00 00 00 00 00 ; p;..p<..p>......

first header for entire file
first word in first dword is number of meshes defined
first word in second dword always matches the first word in first dword
next 6 dwords might be translation and rotation data or maybe rotation and bounding box

header for each mesh defined
first word in first dword is number of meshes defined
first word in second dword is number of verts in index table?
next 6 dwords might be translation and rotation data
5 dwords following, unknown


for each mesh defined
first word in first dword is number of verts defined
first word in second dword is offset to beginning of vert list
first word in third dword is beginning of vertex index table

first word in fourth dword is number of verts in second set of data
first word in fifth dword is beginning of second vert data
first word in sixth dword is beginning of second vert index table

first word in seventh dword is beginning of normal data?
first word in eighth dword is beginning of tex coord data?
last dword is empty

88 bytes per header per mesh(meshcount-1) in multi mesh instances
verts are signed

first short = num

Monday, October 5, 2009

R-Type Final

Been a while, not much interest lately. Heres the deal. I decoded the P6T format and am at 90% or so on the IMD format.

To the left are skins for the ships. There are a little more than 2000 textures. The blue, black, garbage looking textures are 4-bit swizzled and I haven't yet worked that out. I'll try to describe the P6T format as best as I have understood it.

The beginning of the file is a header, its size is 0x0000-0x002C. It contains an 8 character identifying code from 0x00 followed by the width and height as 16-bits each. All data except for colors and pixels are 16-bit values null padded to 32-bit. For example, a width of 128 pixels would be stored as 0x80000000. (This also applies to IMD format where all data except vertices is 16-bit, where verts are 32-bit IEEE floats.) Width and height are followed by an offset to the CLUT, or NULL if the image is 32-bit direct color. This is followed by an offset to the pixel data itself. I dont know what the next 10 bytes are used for but there are at least two 16-bit values at 0x1C and 0x1E(often 0x0200 0000 0100 0000). The next 16-bits are the 'index flag'. This flag indicates if the file is 32-bit direct color or 4/8-bit indexed. Known values are 0x0000 for 32-bit and 0x0100 for indexed. There is one more unknown 16-bit value after this.

As far as pixel format goes there are three verisons. 32-bit indexed color in RGBA format and 8 or 4-bit swizzled indexed color. The oddball is the swizzled format. Swizzling is an optimization technique for PS2(and other GPU's) that rearranges the pixels in such a way that the GPU can read sequential blocks of pixels. I'm not really clear on the algorithm and admittedly borrowed my 8-bit deswizzle code from another project. I don't yet have 4-bit working, I have a borrowed deswizzle that works but I dont yet have a 4-bit to 8-bit conversion. The other hitch is that the CLUT for indexed color is arranged in an unusual way. Instead of each color in order, 0-255, they are in blocks. Color 0-3, 9-12, 4-7, 12-15, etc...

The pixels are simple, either 4 or 8 bit indices into the CLUT or 32-bit RGBA direct color.