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.

[PS1] Captain Tsubasa J - Custom texture container format, need decompression help

Featured Replies

Captain Tsubasa J - Get in the Tomorrow (PS1) — Texture/Asset Container Format Analysis

Game: Captain Tsubasa J: Get in the Tomorrow (PSX) Engine: Based on Konami's Winning Eleven 2002 / ISS Pro Evolution engine Goal: Extract and re-inject player sprites, team logos, and menu/background graphics.

I've done manual hex analysis and light MIPS disassembly (no Ghidra/IDA available on my end) and found a consistent, custom, engine-wide container format used across multiple asset files. Posting my findings here in hopes someone with proper tooling can finish cracking the pixel/compression format.


1. File map (extracted from strings in the main executable, CAPTIN.EXE)

BRDATA\BR.TEX
BRDATA\T00.BIN ... T2A.BIN   (many sequential files)
DATA\BG0.BIN ... BG6.BIN
DATA\BOX.BIN
DATA\HUMAN.TEX
DATA\MATER.BIN
SOUND\GAMESE.BIN, M00-M05.BIN, MBR.BIN
STR0\A_DEMO.BIN, A_SWAZA.BIN
TEAMD0\TEAM00.BIN ... TEAM09.BIN

HUMAN.TEX = player character sprites. TEAM0X.BIN = per-team data (likely includes logos). BG*.BIN = background/menu screens. BR.TEX = border/UI graphics.

2. Top-level container format (confirmed in HUMAN.TEX, TEAM00.BIN, BR.TEX)

All three files begin with an offset table:

u32 count
u32 offset[count]   // absolute file offsets, ABSOLUTE from file start

The first offset value always equals 4 + count*4 (i.e., points exactly to the end of the table), confirming this parsing is correct. Some offset values repeat (multiple table entries point to the same sub-block — shared/reused assets, e.g. duplicate frames).

Example (HUMAN.TEX): count = 162, 119 unique blocks after dedup. Example (BR.TEX): count = 0x23 (35).

Note: BG0.BIN uses a slightly different variant:

u32 unknown (always 0)
u32 count
u32 offset[count]   // RELATIVE to the count field's position (add 4 to get absolute)

3. Second-level "chunk" header (found inside sub-blocks of HUMAN.TEX/TEAM00.BIN)

Each top-level sub-block in HUMAN.TEX / TEAM00.BIN starts with its own nested table:

u32 sub_count (e.g. 8 in HUMAN.TEX block 0)
u32 sub_offset[sub_count]   // relative to start of this sub-block

Followed by a fixed 6-byte marker: 00 00 03 BF 01 FF (HUMAN.TEX) or 00 00 03 3F variant (TEAM00.BIN) — only differs by one bit (0xBF vs 0x3F), likely a flag (bpp mode / has-alpha / etc).

After this marker, data strongly resembles a 16-color CLUT (palette) in native PS1 BGR555 16-bit format — confirmed by extracting plausible skin-tone/hair colors when interpreted this way. However, interpreting the remaining bytes as raw packed 4bpp pixel indices produces visual noise, not a coherent sprite — meaning the pixel data itself is compressed with an unknown RLE-like scheme (not raw packed nibbles).

Repeating byte patterns of the form [byte][byte] where one side is frequently 0x00 suggest a (count,value) or (value,count) RLE pair scheme, but I could not confirm the exact bit order/escape logic through data inspection alone.

4. Different container type found in BG0.BIN / BR.TEX

Unlike HUMAN.TEX, the sub-blocks in BG0.BIN and BR.TEX start with a different, distinct chunk header:

u32 magic       // 0x00000041 ('A')
u32 zero
u32 type        // observed: 1 (BG0.BIN) and 2 (BR.TEX)
u32 size
  • Type 1 blocks (BG0.BIN) appear to contain raw PS1 GPU primitive packets — repeating 16-byte records matching the structure of GP0 command 0x30 (flat-shaded opaque triangle: color word + 3 vertices). This suggests some backgrounds are drawn live using solid-color polygons rather than stored as bitmaps.

  • Type 2 blocks (BR.TEX) contain further nested numeric tables (possibly frame/sprite descriptor tables with width/height-like fields), not yet decoded.

5. Executable analysis (CAPTIN.EXE)

Standard PS-EXE header, confirmed valid:

  • Entry point (PC0): 0x800781fc

  • Load address (T_ADDR): 0x80012000

  • Code size: 0x000a3000 (matches file size exactly)

Relevant debug strings found:

  • "clut: (%d,%d)" at VA 0x800147e8

  • "DATA\HUMAN.TEX" at VA 0x80012138

Found and disassembled (by hand — MIPS) the function referencing the clut debug string at 0x800784ac0x8007857c. This turned out to be a standard debug-print helper that decodes a packed 16-bit CLUT id into (X,Y) VRAM coordinates and calls a function-pointer (likely a printf-style TTY function from a table at 0x800bd054). This confirms the game uses real PSY-Q libgpu CLUT conventions, but is not the custom pixel-decompression routine itself. I was not able to further pinpoint the actual decompression function via manual byte-pattern scanning (searching for the 0x03BF/0x033F-style magic as immediate loads produced no reliable hits — too many false positives without proper xref/decompiler tooling).

A disassembler with jump table / call graph analysis (e.g. Ghidra with a PS1/MIPS loader, or an existing PSX ISO project in IDA) would very likely find the actual decompression loop quickly by tracing what function is called right after the top-level offset table lookup for HUMAN.TEX/TEAM0X.BIN.

6. Files attached

  • HUMAN.TEX (raw, extracted top-level + level-2 sub-blocks included)

  • TEAM00.BIN

  • BG0.BIN

  • BR.TEX

  • CAPTIN.EXE (main executable, for disassembly)

7. What I'm looking for

  • Confirmation/correction of the nested offset-table structure above

  • The actual pixel decompression algorithm for the 00 00 03 BF 01 FF-style chunks (HUMAN.TEX/TEAM0X.BIN)

  • Whether BR.TEX's type-2 chunks are compressed the same way or differently

  • Any existing tools/scripts for Winning Eleven 2002-family PS1 titles that might already handle this container format, since this engine is shared across several Konami PS1 sports titles from the same era.

Thanks in advance to anyone who can take this further!

Captain Tsubasa J - Get in the Tomorrow (Japan)77.zip

  • Supporter
3 hours ago, CRUYFFORD said:

Captain Tsubasa J - Get in the Tomorrow (PS1) — Texture/Asset Container Format Analysis

Game: Captain Tsubasa J: Get in the Tomorrow (PSX) Engine: Based on Konami's Winning Eleven 2002 / ISS Pro Evolution engine Goal: Extract and re-inject player sprites, team logos, and menu/background graphics.

I've done manual hex analysis and light MIPS disassembly (no Ghidra/IDA available on my end) and found a consistent, custom, engine-wide container format used across multiple asset files. Posting my findings here in hopes someone with proper tooling can finish cracking the pixel/compression format.


1. File map (extracted from strings in the main executable, CAPTIN.EXE)

BRDATA\BR.TEX
BRDATA\T00.BIN ... T2A.BIN   (many sequential files)
DATA\BG0.BIN ... BG6.BIN
DATA\BOX.BIN
DATA\HUMAN.TEX
DATA\MATER.BIN
SOUND\GAMESE.BIN, M00-M05.BIN, MBR.BIN
STR0\A_DEMO.BIN, A_SWAZA.BIN
TEAMD0\TEAM00.BIN ... TEAM09.BIN

HUMAN.TEX = player character sprites. TEAM0X.BIN = per-team data (likely includes logos). BG*.BIN = background/menu screens. BR.TEX = border/UI graphics.

2. Top-level container format (confirmed in HUMAN.TEX, TEAM00.BIN, BR.TEX)

All three files begin with an offset table:

u32 count
u32 offset[count]   // absolute file offsets, ABSOLUTE from file start

The first offset value always equals 4 + count*4 (i.e., points exactly to the end of the table), confirming this parsing is correct. Some offset values repeat (multiple table entries point to the same sub-block — shared/reused assets, e.g. duplicate frames).

Example (HUMAN.TEX): count = 162, 119 unique blocks after dedup. Example (BR.TEX): count = 0x23 (35).

Note: BG0.BIN uses a slightly different variant:

u32 unknown (always 0)
u32 count
u32 offset[count]   // RELATIVE to the count field's position (add 4 to get absolute)

3. Second-level "chunk" header (found inside sub-blocks of HUMAN.TEX/TEAM00.BIN)

Each top-level sub-block in HUMAN.TEX / TEAM00.BIN starts with its own nested table:

u32 sub_count (e.g. 8 in HUMAN.TEX block 0)
u32 sub_offset[sub_count]   // relative to start of this sub-block

Followed by a fixed 6-byte marker: 00 00 03 BF 01 FF (HUMAN.TEX) or 00 00 03 3F variant (TEAM00.BIN) — only differs by one bit (0xBF vs 0x3F), likely a flag (bpp mode / has-alpha / etc).

After this marker, data strongly resembles a 16-color CLUT (palette) in native PS1 BGR555 16-bit format — confirmed by extracting plausible skin-tone/hair colors when interpreted this way. However, interpreting the remaining bytes as raw packed 4bpp pixel indices produces visual noise, not a coherent sprite — meaning the pixel data itself is compressed with an unknown RLE-like scheme (not raw packed nibbles).

Repeating byte patterns of the form [byte][byte] where one side is frequently 0x00 suggest a (count,value) or (value,count) RLE pair scheme, but I could not confirm the exact bit order/escape logic through data inspection alone.

4. Different container type found in BG0.BIN / BR.TEX

Unlike HUMAN.TEX, the sub-blocks in BG0.BIN and BR.TEX start with a different, distinct chunk header:

u32 magic       // 0x00000041 ('A')
u32 zero
u32 type        // observed: 1 (BG0.BIN) and 2 (BR.TEX)
u32 size
  • Type 1 blocks (BG0.BIN) appear to contain raw PS1 GPU primitive packets — repeating 16-byte records matching the structure of GP0 command 0x30 (flat-shaded opaque triangle: color word + 3 vertices). This suggests some backgrounds are drawn live using solid-color polygons rather than stored as bitmaps.

  • Type 2 blocks (BR.TEX) contain further nested numeric tables (possibly frame/sprite descriptor tables with width/height-like fields), not yet decoded.

5. Executable analysis (CAPTIN.EXE)

Standard PS-EXE header, confirmed valid:

  • Entry point (PC0): 0x800781fc

  • Load address (T_ADDR): 0x80012000

  • Code size: 0x000a3000 (matches file size exactly)

Relevant debug strings found:

  • "clut: (%d,%d)" at VA 0x800147e8

  • "DATA\HUMAN.TEX" at VA 0x80012138

Found and disassembled (by hand — MIPS) the function referencing the clut debug string at 0x800784ac0x8007857c. This turned out to be a standard debug-print helper that decodes a packed 16-bit CLUT id into (X,Y) VRAM coordinates and calls a function-pointer (likely a printf-style TTY function from a table at 0x800bd054). This confirms the game uses real PSY-Q libgpu CLUT conventions, but is not the custom pixel-decompression routine itself. I was not able to further pinpoint the actual decompression function via manual byte-pattern scanning (searching for the 0x03BF/0x033F-style magic as immediate loads produced no reliable hits — too many false positives without proper xref/decompiler tooling).

A disassembler with jump table / call graph analysis (e.g. Ghidra with a PS1/MIPS loader, or an existing PSX ISO project in IDA) would very likely find the actual decompression loop quickly by tracing what function is called right after the top-level offset table lookup for HUMAN.TEX/TEAM0X.BIN.

6. Files attached

  • HUMAN.TEX (raw, extracted top-level + level-2 sub-blocks included)

  • TEAM00.BIN

  • BG0.BIN

  • BR.TEX

  • CAPTIN.EXE (main executable, for disassembly)

7. What I'm looking for

  • Confirmation/correction of the nested offset-table structure above

  • The actual pixel decompression algorithm for the 00 00 03 BF 01 FF-style chunks (HUMAN.TEX/TEAM0X.BIN)

  • Whether BR.TEX's type-2 chunks are compressed the same way or differently

  • Any existing tools/scripts for Winning Eleven 2002-family PS1 titles that might already handle this container format, since this engine is shared across several Konami PS1 sports titles from the same era.

Thanks in advance to anyone who can take this further!

Captain Tsubasa J - Get in the Tomorrow (Japan)77.zip

The game uses a simple LZSS: flag byte bit by bit, 1 = literal, 0 = offset/length copy.
These files use the same decompression routine, but not the same "container".
Human.tex below
Load screen

human_tex.png

LOAD_0000_idx000_off000010.pngLOAD_0001_idx001_off004784.pngLOAD_0002_idx002_off006D64.png

TITTIM_0025_idx025_off010B20.pngTITTIM_0001_idx001_off000C3C.pngTITTIM_0002_idx002_off0012B0.pngTITTIM_0003_idx003_off00166C.pngTITTIM_0008_idx008_off005954.pngTITTIM_0010_idx010_off006908.png

Edited by Rabatini

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.