Jump to content

Help: Issues decompressing unknown-LZO compressed data (.ghx2)


Go to solution Solved by barncastle,

Recommended Posts

Figured this was the best place to post this: my original post is here.

I am currently having difficulty on trying to decompress the LZO data from a .ghx2 file, or the original project file for music made with the GAX Sound Engine.
I would like to be able to decompress the data so I can easily reverse-engineer the sequence data format.

The only known "decompressors" I can find readily available are GAXPlay.exe and GAX.ocx.

I could not find any matching LZO algorithms for the data; QuickBMS didn't find any matches (even with brute-forcing). The few LZO decompression executables that I could find didn't even know what to do.

The LZO data is unheadered (i.e no LZOD header). I have separated the relevant data into a .bin file.

ghx2_lzo.zip

Edited by beanieaxolotl
Small correction
Link to comment
Share on other sites

Posted (edited)

I managed to find a portion of the uncompressed sample data stream in GAXPlay's memory (via Cheat Engine), and found a corresponding portion in the raw LZO stream.

I ripped both of these from the .ghx2 project file for Tak - The Great Juju Challenge (tak_3_04.ghx2). compressed.bin is from the file data itself, and uncompressed.bin was ripped from GAXPlay's memory.

The samples are formatted in an uncompressed signed 16-bit PCM stream, if this helps.

tak_examples.zip

Edited by beanieaxolotl
Clarification, and fixed silly error
  • Confused 1
Link to comment
Share on other sites

  • beanieaxolotl changed the title to Help: Issues decompressing unknown-LZO compressed data (.ghx2)
  • 3 months later...
  • Solution

I've written a C# script that reimplements the decompression algorithm here, this is reversed from the GAX.ocx library

Some random bits I noted whilst working on this:

- The "LoadFile" library call reassigns the decompressed data to an in-memory format which differs from the decompressed format you're documenting

- The checksum is a variant of Fletcher 32 that processes in 0x15B0 byte blocks (also reimplemented). It is calculated on the compressed data which begins after the LZOD "Compressed Data Size" field

- "0153" is a version string. The version of GAX.ocx I was reversing throws an exception if this is less than "0110"

- All chunks have a 4 character magic/signature followed by a uint32_t size field

- Your "EXP" chunk documentation isn't quite right; there are two chunks, "EXPP" and "AUTH". "EXPP" appears to be referenced when exporting (I didn't fully reverse it's use), and "AUTH" contains the author's name

struct
{
  uint32_t magic; // "EXPP"
  uint32_t size;
  char value[size];
} EXPP

struct
{
  uint32_t magic; // "AUTH"
  uint32_t size;
  char author[size];
} AUTH


- There is no footer, the last chunk (usually WAVE) goes to EOF
 

Hope this helps!

 

  • Thanks 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...