Halamix2 Posted November 22, 2023 Share Posted November 22, 2023 Hello, I've been working a bit on reversing file formats used in a Gamewave game console and I'm stuck on image color encoding (I doubt this is RGB, might be YUV420 or something completely different): I know mostly how the image header looks like (https://github.com/namgo/GameWaveFans/wiki/Image,-Music-formats), all data from byte 0x30 is zlib packed: looks like either each two pixels are swapped, or somehow interconnected (maybe 4633 is just two pixels of separate 46 (4alpha and 6sth) and two connected values spread across two pixels (3+3 & 3+3?) I've found mentions in the game binary to "4633", this looks like a correct-ish packing of 4 unknown values into each two bytes the left most value (4xxx) looks like alpha channel data Files in the archive: .zbm is the original image file .data is the unpacked zlib stream. activate_remotes_bg.png is taken from a mpg video included with the game, so I assume this is how the .zbm image should look like. naive_unpack.png is me just assuming the remaining fields are just storing RGB data ( ARGB4633) (code for the converter is stored at the same repo as the wiki) activateblue.zbm should be ok for testing/finding alpha channel data zbm_format.zip Link to comment Share on other sites More sharing options...
Solution piken Posted November 22, 2023 Solution Share Posted November 22, 2023 (edited) The data sample is 16bit x 720 x 480 with each pixel having fields: struct PixelCr3Cb3Cy6a4 // nomenclature listed consistently with increasing bit field order, like PFNC and DXGI. { uint3 cr; // chromatic red (bits 0-2) uint3 cb; // chromatic blue (bits 3-5) uint6 cy; // luminance (bits 6-11) uint4 alpha; // 0xF = opaque (bits 12-15) } Note because it's MIPS, there will be some endianness issues, needing to unravel 8 bits per every 32 bits (and oddly not the usual byte swapped 8 bits per 16 bit element), or else you get columns that look swapped. So if your memory stream had {0x03, 0x02, 0x01, 0x00, 0x07, 0x06, 0x05, 0x04}, reorder to -> {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}. Some quick and dirty code for color space conversion: auto luminance = uint8_t(((sourceWord >> 6) & 0x3F) << 2); auto cr = uint8_t(((sourceWord >> 0) & 0x07) << 5); // simple left shift, no rescale auto cb = uint8_t(((sourceWord >> 3) & 0x07) << 5); auto alpha = uint8_t(((sourceWord >> 12) & 0x0F) * 17); // Convert YCbCr to RGB ElementB8G8R8A8 adjustedColor = { .b = uint8_t(std::clamp(y + ((113 * cb ) / 64), 0, 255)), .g = uint8_t(std::clamp(y - (( 11 * cb + 23 * cr) / 32), 0, 255)), .r = uint8_t(std::clamp(y + (( 45 * cr) / 32), 0, 255)), .a = alpha, // equivalent floating point: // std::clamp(1.164f * (luminance - 16) + 2.018f * (cb - 128), 0.0f, 255.0f)) // std::clamp(1.164f * (luminance - 16) - 0.813f * (cr - 128) - 0.391f * (cb - 128), 0.0f, 255.0f)) // std::clamp(1.164f * (luminance - 16) + 1.596f * (cr - 128), 0.0f, 255.0f)) }; I tried using rescaling or bit replication too (mapping chromatic red 0-7 to 0-255), but simple left shifting looked more faithful to your reference image: Edited November 23, 2023 by piken Add alpha image 1 Link to comment Share on other sites More sharing options...
Halamix2 Posted November 23, 2023 Author Share Posted November 23, 2023 (edited) Thank you for your help, I was able to fix my tool for files extraction (https://github.com/gamewavefans/GameWaveFans/releases/tag/v0.0.3). Local copy of the tools: Gamewave tools Edited November 23, 2023 by Halamix2 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