Skip to content

Repository files navigation

totk-meshcodec

tests lint License: MIT Python 3.8+ Format spec

A packer for .bfres.mc model files from The Legend of Zelda: Tears of the Kingdom.

Existing tools only go one way. MeshCodec and the GameBanana decompressors unpack these files; Switch Toolbox reads them too, and its CompressMeshCodec writes a plain zstd stream with no FMSH section — which the game rejects by hanging on the boot logo.

This library writes files the game actually loads, including the FMSH geometry section. As far as I can tell, no other public tool does.

📄 Full format specification — every field, verified against retail files.

🇷🇺 Читать по-русски


Why it was hard

Three findings decided the whole thing, and each cost a failed attempt on real hardware:

The game requires an FMSH section. A file without one never loads, even when its decompressed buffer is byte-identical to the original. Bit 4 of the MCPK flags field announces the section — set it without shipping one and the game hangs looking for geometry that is not there.

The zstd stream has to look like Nintendo's. A 128 KiB window (windowLog = 17), because the game streams the frame through ZSTD_decompressContinue with a matching buffer. And few blocks — every shipped asset is a single block, while compression levels above 15 split the stream into dozens.

Large buffers must be split across frames. NullCodec::Decompress copies at most min(remaining, 0x40000) bytes per call and runs once per frame. Miss this and the tail of your geometry is never copied: the model comes out shredded into spikes, or the game hangs outright.

Install

git clone https://github.com/UltimateBomb/totk-meshcodec
cd totk-meshcodec
pip install -e .

Requires Python 3.8+ and zstandard.

Command line

# inspect a file
mcpack info Link.Link_RaulSkin.bfres.mc

# repack a model, reusing the geometry of the original
mcpack pack model.bfres out.bfres.mc --fmsh-from original.bfres.mc

# pull the BFRES body back out
mcpack unpack Link.Link_RaulSkin.bfres.mc model.bfres
Link.Link_RaulSkin.bfres.mc  (76123 bytes)
  MCPK version   : 0.1.1
  flags          : 0x0000079c
  buffer size    : 245760
  zstd stream    : 15012 bytes
  FMSH @0x3ab0   : 61099 bytes
    indexOut=35632  vertexOut=139768

Library

from mcpack import pack, build_fmsh, split_geometry

buffer = open("model.bfres", "rb").read()

# geometry lives outside the BFRES body
indices, vertices = split_geometry(buffer, geom_offset=0x107d0,
                                   index_size=35632, vertex_size=139768)

fmsh = build_fmsh(indices, vertices)      # frames are split automatically
data, info = pack(buffer, fmsh)

open("out.bfres.mc", "wb").write(data)
print(info["buffer_size"])                # 245760

Verification

Repacking a retail asset and decoding it with the original MeshCodec decompressor reproduces the source byte for byte:

Link.Link_RaulSkin            245760 bytes  sha256 b24acc3e4ba5cb1a  identical
Link.Link_RaulSkin_RightHand  557056 bytes  sha256 b2a7676caa2aba4a  identical

The MCPK header comes out identical to Nintendo's, down to the flags field. Custom geometry built with this library loads on a real Switch.

pytest tests/
ruff check mcpack tests examples

A worked example lives in examples/repack_model.py: it locates the geometry in a decompressed buffer, encodes an FMSH section and writes a loadable file.

Also worth knowing

Replacing a model needs RESTBL updated too — it stores the buffer size the game allocates per resource, and an oversized asset silently fails to load. Paths there are hashed without the .mc suffix. The structure is documented in docs/FORMAT.md.

Credits

  • dt-12345/MeshCodec — the decompressor this work builds on. The format could not have been read without it.
  • Watertoon and Lord Bubbles — earlier decompression tools for the community.

License

MIT — see LICENSE.

Ships no game assets. You need your own legally obtained copy of the game.

About

Packer for Tears of the Kingdom .bfres.mc model files — writes the FMSH geometry section no other public tool emits

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages