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

Dreamcast-Kita e Series .cb and .pvr

Featured Replies

Hi everyone, I'm trying to extract texture files from two Dreamcast games—Kita e White Illumination and Kita e Photo Memories—and I'm stuck on two issues. First, for White Illumination, the .CB file (which I opened with a hex editor and found to contain .dds and .set files) was extracted using a script generated by DeepSeek, but the resulting .dds files won't open in any image viewer I've tried (see SSYF.zip). Second, for Photo Memories, the PVR files have GBIX and PVRT headers, but none of the usual tools—pvr2image, Noesis, sprt2png, or PVRTexTool—can convert or even open them (yuko_PVR.zip). I suspect the data might be compressed, encrypted, or using non‑standard headers. I know I can use the Flycast emulator to dump textures as the game runs, but that's pretty tedious. Has anyone successfully extracted these formats, or does anyone know of a working tool or script that can handle them? Any help would be greatly appreciated.

yuko_PVR.zip SSYF.zip

What offset are you seeing a DDS subfile in SSFY.CB? Scrolling through it, there are very few regular block patterns, and changing the wrap width rapidly, you can see wavy patterns indicative of variable length compression. Does the exported DDS have a standard DDS header at least (e.g. this)? The "PVR" files are also wrapped in some variable length compression (not PVR standard blocks).

Edited by piken

11 hours ago, Tefolium said:

Hi everyone, I'm trying to extract texture files from two Dreamcast games—Kita e White Illumination and Kita e Photo Memories—and I'm stuck on two issues. First, for White Illumination, the .CB file (which I opened with a hex editor and found to contain .dds and .set files) was extracted using a script generated by DeepSeek, but the resulting .dds files won't open in any image viewer I've tried (see SSYF.zip). Second, for Photo Memories, the PVR files have GBIX and PVRT headers, but none of the usual tools—pvr2image, Noesis, sprt2png, or PVRTexTool—can convert or even open them (yuko_PVR.zip). I suspect the data might be compressed, encrypted, or using non‑standard headers. I know I can use the Flycast emulator to dump textures as the game runs, but that's pretty tedious. Has anyone successfully extracted these formats, or does anyone know of a working tool or script that can handle them? Any help would be greatly appreciated.

yuko_PVR.zip SSYF.zip

The PVR files look to be LZSS0 compressed from offset 8, and one of the files I tested (IMG0088_A) is 512x512 BGRA5551 with DC swizzling. Something like this:

image.png

  • Author
13 hours ago, piken said:

What offset are you seeing a DDS subfile in SSFY.CB? Scrolling through it, there are very few regular block patterns, and changing the wrap width rapidly, you can see wavy patterns indicative of variable length compression. Does the exported DDS have a standard DDS header at least (e.g. this)? The "PVR" files are also wrapped in some variable length compression (not PVR standard blocks).

there are not standard DDS header. I don't know the offset, but the first 76 bytes of the extracted file header are:

CLSS<bh:10><bh:00><bh:00><bh:00>CTRFImageBuffer<bh:00>IBUF<bh:81><bh:97><bh:00><bh:00><bh:00><bh:00><bh:00><bh:00><bh:00><bh:01><bh:00><bh:01><bh:00><bh:02><bh:01><bh:00><bh:00><bh:00><bh:10><bh:00><bh:00><bh:80><bh:00><bh:00><bh:00>|<bh:00><bh:00><bh:e0><bh:03><bh:00><bh:00><bh:1f><bh:00><bh:00><bh:00><bh:01><bh:05><bh:05><bh:05><bh:0f><bh:0e><bh:09><bh:04>LZSS

The DDS files(bag2.dds) not inside the .cb file (presumably icons from the game) have this header:

CLSS<bh:10><bh:00><bh:00><bh:00>CTRFImageBuffer<bh:00>IBUF<bh:19><bh:05><bh:00><bh:00><bh:00><bh:00><bh:00><bh:00>@<bh:00>@<bh:00><bh:80><bh:00><bh:01><bh:00><bh:00><bh:00><bh:10><bh:00><bh:00><bh:80><bh:00><bh:00><bh:00>|<bh:00><bh:00><bh:e0><bh:03><bh:00><bh:00><bh:1f><bh:00><bh:00><bh:00><bh:01><bh:05><bh:05><bh:05><bh:0f><bh:0e><bh:09><bh:04>LZSS

BAG2.DDS

  • Author
11 hours ago, DKDave said:

The PVR files look to be LZSS0 compressed from offset 8, and one of the files I tested (IMG0088_A) is 512x512 BGRA5551 with DC swizzling. Something like this:

image.png

LZSS0 compressed from offset 8, 512x512 BGRA5551, swizzle morton swap, then I got the picture... 7.py is the python script for test by DeepSeek:Decompresses the LZSS0 stream using the confirmed parameters.

  • Takes the first width * height * 2 bytes (default 512×512 = 524288 bytes).

  • Applies five different reverse‑swizzle algorithms:

    • linear – no reordering

    • morton_swap – the confirmed DC swizzle with swapped Morton coordinates

    • morton_noswap – standard Morton coordinates

    • block_4x4_morton – 4×4 tiles, Morton order inside each tile

    • block_8x8_morton – 8×8 tiles, Morton order inside each tile

  • Converts the resulting BGRA5551 data to RGBA8888 and writes a PNG for each algorithm.

IMG0088_A_swizzle_morton_swap.png

7.py

Edited by Tefolium

  • Supporter

But not sure how to decompress. The LZSS sign it's just coincidence I guess.

//------------------------------------------------
//--- 010 Editor v14.0 Binary Template
//
//      File: 
//   Authors: 
//   Version: 
//   Purpose: 
//  Category: 
// File Mask: 
//  ID Bytes: 
//   History: 
//------------------------------------------------
LittleEndian();OutputPaneClear();

local uint32 i,j,k,l,SignCheck;

char CABSign[4];
uint32 FCBSize;

FSeek(FCBSize + 8);
struct
{
    char STRSign[4];
    uint32 STRSize;
    struct
    {
        uint32 StrCount;
        struct
        {
            FSkip(3);
            string ResourcePathName;
        }STRDefinition[StrCount]<optimize=false>;
    }STRDefinition;
}ResourcePathDefinition;

FSeek(startof(FCBSize) + sizeof(FCBSize));
struct
{
    char FCBSign[4];
    uint32 INFOSize;
    struct
    {
        char INFOSign[4];
        uint32 TOCSize;
        struct
        {
            uint32 ResourceCount;
            struct
            {
                uint32 Unknown_0;
                uint32 Unknown_1;
                uint32 ResourceSize;
                uint32 ResourceOffset;
                uint32 ResourceNameId;
            }ResourceDefinition[ResourceCount]<optimize=false>;
        }TOCDefinition;
        
        char STRSign[4];
        uint32 STRSize;
        struct
        {
            uint32 StrCount;
            struct
            {
                string ResourceName;
            }STRDefinition[StrCount]<optimize=false>;
        }STRDefinition;
    }INFODefinition;
    
    struct
    {
        for (i=0; i < INFODefinition.TOCDefinition.ResourceCount; i++)
        {
            FSeek(INFODefinition.TOCDefinition.ResourceDefinition[i].ResourceOffset);
            struct
            {
                char Sign[4];
                if (Sign == "ENC2")
                {
                    uint32 Size;
                    byte ENC2Data[Size];
                    FSeek(startof(ResourcePathDefinition.STRDefinition.STRDefinition[INFODefinition.TOCDefinition.ResourceDefinition[i].ResourceNameId].ResourcePathName));
                    string ResourceName;
                }
                else if (Sign == "ENC0")
                {
                    uint32 CLSSSize;
                    struct
                    {
                        char CLSSSign[4];
                        uint32 StrLen;
                        char CTRFSign[StrLen];
                        struct
                        {
                            char IBUFSign[4];
                            uint32 IBUFSize;
                            uint32 Unknown_0;
                            uint16 TextureWidth;
                            uint16 TextureHeight;
                            uint32 Unknown_1;
                            uint32 Unknown_2;
                            uint32 Unknown_3;
                            uint32 Unknown_4;
                            uint32 Unknown_5;
                            uint32 Unknown_6;
                            uint32 Unknown_7;
                            uint32 Unknown_8;
                            
                            struct
                            {
                                do
                                {
                                    struct
                                    {
                                        char LZSSSign[4];
                                        uint32 Size;
                                        byte LZSSData[Size];
                                        SignCheck=ReadUInt(FTell());
                                    }LZSSDefinition;
                                 }while(SignCheck == 1397971532);
                            }LZSSDefinition;
                        }IBUFDefinition;
                    }CLSSDefinition;
                    FSeek(startof(ResourcePathDefinition.STRDefinition.STRDefinition[INFODefinition.TOCDefinition.ResourceDefinition[i].ResourceNameId].ResourcePathName));
                    string ResourceName;
                }
            }Resource;
        }
    }Resources;
}FCBDefinition;

Edited by h3x3r

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.