Skip to content

Decode the tkmk00 textures instead of writing compressed bytes - #775

Open
quarrel07 wants to merge 1 commit into
n64decomp:masterfrom
quarrel07:tkmk00-decode
Open

Decode the tkmk00 textures instead of writing compressed bytes#775
quarrel07 wants to merge 1 commit into
n64decomp:masterfrom
quarrel07:tkmk00-decode

Conversation

@quarrel07

@quarrel07 quarrel07 commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

The 63 PNGs extracted to textures/*.rgba16.png are noise. They have never been correct on a clean checkout.

Each tkmk00 block is described twice in assets.json at the same ROM offset - the .tkmk00 blob under bin/, which is the build input, and a decoded .png under textures/:

"bin/background_blue_sky.rgba16.tkmk00":     {"meta":{"size":"0xCE00"}, "offsets":{"us":["0x8094C0","0x0"]}},
"textures/background_blue_sky.rgba16.png":   {"meta":{"dims":[320,240],"alpha":"0x01"}, "offsets":{"us":["0x8094C0","0x0"]}},

Extraction groups entries by ROM offset, then decides whether to decode by looking only at the first entry in the group:

elif magic == b"TKMK" and assets[0][0].endswith(".png"):

The .tkmk00 entries are listed first in assets.json, so assets[0][0] never ends in .png, the branch is skipped, and the PNG is written straight from the compressed bytes.

The underlying issue is that both entries share one buffer, so whichever ordering wins, the other gets the wrong bytes: the blob needs the compressed data, the png needs the decoded data. Reordering assets.json would just swap which one is broken.

This decodes alongside instead. The blob keeps the compressed bytes it is .incbin'd from, and the png gets the decoded image.

Verified on a cold extraction (textures/, bin/*.tkmk00 and .assets-local.txt all removed first):

  • before: 63 PNGs of noise. 'background_blue_sky' came out 258,704 bytes, because noise does not compress.
  • after: all 63 decode, each matching the dimensions assets.json declares. 'background_blue_sky' is 108,512 bytes and is the title screen artwork.
  • all 63 bin/*.tkmk00 blobs still begin with TKMK magic and still match the cartridge byte for byte.
  • mk64.us: OK - unchanged, as expected. Nothing in the build consumes these PNGs; TEXTURE_DIRS is textures/common and Makefile.split uses textures/standalone and textures/raw.

That last point is why this went unnoticed: the output is decorative until a byte-matching tkmk00 compressor exists, so nothing depended on it being right. It also only ever looked correct on an incremental run that already had the blob on disk.

Before:
background_blue_sky-BEFORE

After:
background_blue_sky-AFTER

A tkmk00 block is described twice in assets.json at the same ROM offset:
the .tkmk00 blob under bin/ is the build input, and the .png beside it
under textures/ is a decoded copy. Extraction groups entries by offset
and then decided whether to decode by looking at the first one in the
group, so whichever was listed first won.

The .tkmk00 entries come first in the file, so all 63 of the textures/
PNGs were written straight from the compressed bytes and came out as
noise. They only ever looked right on an incremental run that already
had the blob on disk.

Decode alongside instead: the blob keeps the compressed bytes it needs
and the png gets the decoded image. Nothing in the build consumes those
PNGs, so no ROM changes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants