Skip to content
View in the app

A better way to browse. Learn more.

ResHax

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.
Help us keep the site running.
Zero Tolerance for Disrespect

Gamewave texture .zbm format

Featured Replies

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

Solved by piken

  • Solution

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:

activate_remotes_bg.data.png

image.png.f655742bf1578bdb295e217596a37190.png

Edited by piken
Add alpha image

Create an account or sign in to comment

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.