# Totk Msbt Mals Editor

> Edit, inspect, patch, and validate Tears of the Kingdom Mals locale archives and MSBT message files. Use when Codex needs to add or replace ActorMsg display names, EventFlowMsg dialogue or choice labels, ChallengeMsg quest text, preserve or repair MSBT control tags, wrap text for in-game message boxes, or validate EventTalk MessageId-to-Mals wiring. Cross-reference totk-local-operator for compact local inspection, totk-eventflow-editor for EVFL graph edits, and totk-actor-cloner for actor clone outputs that need Mals labels.

- Skill: `cargocult-mods/totk-msbt-mals-editor` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add cargocult-mods/totk-msbt-mals-editor`
- Raw SKILL.md: https://api.skillmd.com/api/skills/cargocult-mods/totk-msbt-mals-editor/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: cargocult-mods (https://skillmd.com/u/cargocult-mods)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/cargocult-mods/totk-msbt-mals-editor

---


# TOTK MSBT/Mals Editor

## Vanilla RomFS Rule

Use a vanilla TOTK `romfs` path already supplied in the current turn or registered project guidance. Otherwise ask the user for it before inspecting game files. Treat the path as read-only; do not search unrelated folders or guess a location.

Use this skill for the message-file mechanics of TOTK text edits. Keep prose/content decisions task-local; do not bake line content style preferences into this skill.

## Workflow

1. Identify the target archive and member:
   - Detect the locale archive from the source romfs or current mod, e.g. `Mals/<locale>.Product.*.sarc.zs`. Do not copy product suffixes from another project.
   - `EventFlowMsg/<FlowchartName>.msbt` supplies `EventTalk.MessageId` text and choices.
   - `ActorMsg/*.msbt` supplies actor/item display names such as `<Actor>_Name`.
   - `ChallengeMsg/Info_<ChallengeName>.msbt` supplies quest log text.
2. Choose the safest source:
   - For direct edits to an existing mod, patch the existing mod copy and back it up first when approved.
   - For new overlays, start from vanilla or the user-approved base archive, then patch only the required MSBT members.
   - Avoid wholesale Mals replacement when the task only needs a few labels; it can discard unrelated local edits.
3. Patch MSBT structurally:
   - Do not string-replace raw binary except as a last resort. Parse sections, edit labels/texts, rebuild offsets, then reparse.
   - Preserve unknown sections and attributes if present. Do not collapse a file to only `LBL1`/`TXT2` unless the input file had only those sections and validation confirms that is expected.
   - Labels live in `LBL1` as UTF-8 strings with a one-byte byte length, so a label cannot exceed 255 encoded bytes.
   - Text lives in `TXT2` as UTF-16LE text. Each message should remain null-terminated with `00 00`.
   - Rebuild `TXT2` count/offset tables, update the MSBT file length in the header, and preserve 16-byte section padding.
   - When adding a label, place it in the correct hash bucket: start with `0`, then for each character use `(value * 0x492 + ord(char)) & 0xffffffff`; bucket is `value % group_count`.
   - Make edits idempotent: if the label already exists, replace its text entry instead of duplicating the label.
4. Handle control tags as binary controls:
   - Treat MSBT tags as control bytes embedded in UTF-16LE text, not printable markup.
   - Prefer cloning an existing vanilla tag sequence from the same UI context, then changing only surrounding text.
   - If a tool accepts readable markup, verify that export converts it back into the intended control bytes. Do not leave `{color}`, `<color>`, or similar markup as literal dialogue text.
   - Bubble Wrap's TOTK MSBT Editor export uses readable syntax such as `{{color id="1"}}`, `{{color id="65535"}}`, `{{size value="80"}}`, `{{delay1}}`, `{{delay frames="30"}}`, `{{anim type="..."}}`, and `{{playSound id="..."}}`. Treat this as editor interchange syntax, not raw MSBT storage.
   - Bubble Wrap maps common color IDs as red `0`, blue `1`, grey `2`, and reset `65535`; text sizes are `80`, `100`, and `125`.
   - Keep paired controls balanced, such as color start/end or size start/end. Do not insert line breaks inside a control sequence.
   - Validate both the parsed display text and the raw bytes for tagged lines; a parser that strips tags can hide malformed controls.
   - Use MSBT Editor's TotK game config as the source of truth for tag names and encodings. It displays tags as `{{tag arg="value"}}`, not older angle-bracket markup.
   - Fixed delay aliases are native no-arg tags: `{{delay8}}` is group 5/type 0, `{{delay15}}` is group 5/type 1, and `{{delay30}}` is group 5/type 2. Generic frame delays are different: `{{delay frames="10"}}` is group 1/type 0 with u16 little-endian frame data.
   - TotK color is group 0/type 3 with signed 16-bit ids. The known ids are `-1` through `5`. Do not treat old output such as `<FontColor UnknownColor="10"/>` as valid color syntax. UnknownColor 8/15/30 from old bindings can indicate fixed-delay tags, but encode delays through the TotK config forms instead.
   - Do not invent raw control-byte snippets for pauses. If the toolchain cannot encode a verified delay tag, omit the delay and use plain line pacing.
5. Wrap for the target UI context:
   - Read `references/text-box-limits.md` before writing or reflowing text.
   - For ordinary NPC `EventTalk` dialogue, keep each box to at most 3 visible lines and target 40 or fewer visible characters per rendered line.
   - Treat 41-42 visible characters as review-worthy, 43-45 as the caution zone, and anything over 45 as needing a split/rewrap unless it has been validated in game.
   - EventTalk dialogue is batched by raw lines in groups of three. Do not fill all three lines by default; pad shorter intentional bubbles with LF blank slots so the rendered one- or two-line bubble stays vertically centered.
   - Use `line\n\n` for one visible line, `line 1\nline 2\n` for two visible lines, and no blank padding for three visible lines. For multiple bubbles in one entry, pad each bubble before starting the next raw three-line group.
   - For blank slots, clone vanilla raw newline padding from the same MSBT context. In raw `TXT2`, vanilla manual blank slots are literal UTF-16LE LF units (`0A 00`), not spaces, empty controls, or GUI-specific blank-line syntax.
   - Count visible characters after stripping MSBT control tags; lower the target toward 36-40 for all-caps, wide punctuation, many numbers, size tags, or variable placeholders.
   - Use explicit line breaks only where the target context expects them. Avoid wrapping inside tags or immediately before tag end controls.
   - If a context is not listed, compare nearby vanilla messages in the same MSBT file and keep edited lines no wider and no taller than those examples.
6. Validate from written output:
   - Decompress `Mals/*.sarc.zs` with vanilla `Pack/ZsDic.pack.zs` `zs.zsdic`, reopen the SARC, and confirm the target MSBT member exists.
   - Reparse the target MSBT and confirm each label maps to the intended UTF-16LE text.
   - Confirm the raw label bytes and raw UTF-16LE text bytes exist after recompression.
   - For EventFlow text, reparse the EVFL and verify every `EventTalk.MessageId` uses `EventFlowMsg/<file>:<label>` and resolves to a label in the patched Mals archive.
   - Compare changed SARC members against the source archive and report only intentional changed or added members.
   - For TKMM or other merge workflows, inspect the final merged output when diagnosing missing text. Source overlays are not the runtime source of truth.

## Common Failure Modes

- Literal markup appears in-game: the text exporter did not compile tags into MSBT control bytes.
- Text vanishes or a box breaks after a tag edit: a control tag was truncated, unbalanced, or split by a line break.
- Dialogue looks squeezed or overruns the box: a rendered line is past the safe 40-45 visible-character range for normal dialogue.
- EventFlow runs but old text appears: `MessageId` points at a different `EventFlowMsg` file, label, locale archive, or final merged Mals output.
- A new actor has no display name: the `<Actor>_Name` label was added to the wrong `ActorMsg/*.msbt` file or wrong locale archive.
- Another manual dialogue edit disappears: a whole Mals archive was copied from the wrong base instead of patching the current file.

## Related Skills

- Use `totk-eventflow-editor` for EVFL graph edits, event actions, queries, subflows, and `EventTalk.MessageId` creation.
- Use `totk-actor-cloner` for actor clone outputs and actor display-name labels.
- Use `totk-local-operator` for compact archive inventories, merged-output checks, and validation summaries.

