beanieaxolotl Posted August 28, 2024 Share Posted August 28, 2024 (edited) 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 September 7, 2024 by beanieaxolotl Small correction Link to comment Share on other sites More sharing options...
beanieaxolotl Posted August 31, 2024 Author Share Posted August 31, 2024 (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 August 31, 2024 by beanieaxolotl Clarification, and fixed silly error 1 Link to comment Share on other sites More sharing options...
Solution barncastle Posted December 13, 2024 Solution Share Posted December 13, 2024 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! 1 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now