feat(texts): the ocarina microphone hint says your microphone, not the console's #604

Open
lg wants to merge 1 commit from lg/Longshot:feat/pc-wording-texts into main
First-time contributor

Type: feat · Risk: low · Tested on: Windows 11, RTX 4090 (621.24) · Needs: Linux; native speakers for the wordings

Why

The hint for playing the ocarina by microphone tells the player to use the console's built-in microphone. A PC has no
such thing: the game listens to the microphone chosen in the menu (Gameplay, Microphone). It is the same kind of
leftover as the console's button icons were in the texts, which the button prompts already replace with the player's
own controller's.

No issue asks for this (tracker searched: "microphone", "wording", "text", "console name").

What changed

The build now rewords that one hint in the player's own text files, in all 16 of the game's languages, and the game
reads the reworded files. It follows the button prompts: made at build time from the player's files, served at run
time, and a mod's own file wins.

  • build: nx2/text_assets.py (new). reword() edits the string in its own room and pads it with NULs, so no MSBT or
    SARC offset moves and the archive keeps its size (the resource size table goes by it). STRINGS names the string by
    its MSBT and label, and each wording by a fingerprint with the bytes to replace: no game text is in the file. Only
    the words for the console's microphone change; the rest of the sentence, the menu's icon and the reading aids stay
    the game's. A text that is not a known wording (another game version) is left as it is. nx2/make_game.py runs it
    in the finish stage (0.25 s for 16 languages). --show prints the result from your own files, to check a wording.
  • runtime: host/texts.c (new). hos_texts_romfs() serves the game folder's texts/<archive> for Mals/<archive>.
    host/mods.c asks it only when no mod and no prompt has the path.
  • tests: tests/test_text_assets.py (new), on an authored SARC and MSBT. tests/test_mods_size_table.py compiles
    texts.c with mods.c and checks three cases over real folders: ours served, a mod's own first, HOS_TEXTS=0.
  • docs: the README's Mods section and update table, HOS_TEXTS in docs/development.md, host/game_layout.c's note.

Measurements

Verdict: it works in the game: the hint reads "Use your microphone ..." with this PR and names the console on main, from
the same save and spot. Both held the 60 fps cap there (one run each, so not a performance comparison; the change only
serves a different file when the game opens its texts).

The run in the game and the screenshots were made with this change on main 7494ce4, built both ways from that commit.
The branch was rebased twice since (onto a0dac82, then 40aec7c) with no conflicts and no change to its own code, so they
were not retaken. The full suite was run on a0dac82; after the last rebase the change's two tests were run again.

Hardware: Windows 11, RTX 4090 24 GB, driver 621.24, Core i9-10900K, 32 GB
Scene: the village, by the gate guard, daytime; 3840x2160, DLAA, DLSS Frame Generation 2x, 60 fps cap, HDR off, English (US)
Method: one run each; the hint read on screen and in a screenshot, the served file from longshot_log.txt, the frame rate from the log's last three vi: lines. No median: it is not a performance comparison
How to reproduce: load a save where Link has the ocarina, press the ocarina button (D-pad left), read the hint; HOS_TEXTS=0 in longshot_env.txt shows the game's own again

Before: main @ 40aec7c After: this PR @ 77d3b46
The hint's wording (English) names the console's built-in mic "Use your microphone ..."
Languages reworded 0 16
Frame rate at that spot (60 cap, last 15 s of the log) 60.0, 60.0, 59.9 60.0, 59.9, 60.0
tests/test_text_assets.py the file does not exist 5 tests pass
tests/test_mods_size_table.py 10 cases 13 cases
texts: mals/usen.product.110.sarc.zs <- C:\Games\Longshot-prtest\texts/usen.product.110.sarc.zs (the console's wording made the PC's)
texts: 16 languages reworded for a PC
ok: 13 cases served as they should: ... the texts' PC wording (ours, a mod's, off)

Flags and settings

One new switch.

Flag What it is Before this PR After this PR Effect Helps / doesn't help / untested Recommendation
HOS_TEXTS=0 Serves the game's own texts (none) Unset: the reworded texts are served The hint names the console again Unset: run in the game. =0: in the Linux test only On by default (unset): one sentence changes, and a mod's file still wins

Testing

Tested:

  • Game-free, Ubuntu 26.04: tests/test_text_assets.py (5 tests), tests/test_mods_size_table.py (13 cases, host/texts.c
    compiled with gcc and run over real folders) and python -I -B tests/run_all.py: 495 passed, 13 failed, 71 skipped.
    main a0dac82 on that PC: 494 passed and the same 13 failed (test_appimage_player_build, test_bake_portability,
    test_cpm_discovery, test_crash_dialog, test_env_on, test_lift_cache, test_lift_cleanup_error,
    test_linux_preflight, test_make_game_cache, test_readback_late, test_vk_pgo, test_vram_budget_row,
    test_walk_key).
  • On the author's own dump (version e0f3ccfa): all 16 languages reworded; each archive keeps its decompressed size.
  • The Windows game cross-built on Linux (RX_TARGET=windows, llvm-mingw 20261104): host/texts.c compiles and the finish
    stage made all 16 files in texts/.
  • In the game, Windows 11, RTX 4090 (driver 621.24), Core i9-10900K, 4K, DLAA, English (US): main 7494ce4 and this PR built
    from the same commit, the same save loaded in each (Kakariko, by the gate guard), the ocarina button pressed. main shows
    the console's wording; this PR shows "Use your microphone to perform ocarina music via mic input. ..." with the menu
    icon in place. The log names the served file. Screenshots below.

Not tested:

  • In the game: the other 15 languages, a text mod beside it, and HOS_TEXTS=0 (the last two are covered by the Linux test
    of host/texts.c only).
  • A Linux build of the whole game (the host file compiles and runs in the test above).
  • The wordings other than English were written by the author with AI help and not checked by native speakers.

Must be tested:

  • By hand, Windows, any GPU: put a mod with its own Mals/USen.Product.110.sarc.zs in mods, and separately set HOS_TEXTS=0, expecting the mod's text in the first case and the game's own hint in the second (request to open)
  • By hand, Linux, any GPU: build, load a save with the ocarina and press the ocarina button, expecting "Use your microphone ..." and a texts: line in the log (request to open)
  • By hand, a native speaker of each language but English: run python -I nx2/text_assets.py --romfs on your own romfs folder with --show and read your language's line, expecting a natural sentence that no longer names the console (request to open)

Screenshots

Before: main @ 7494ce4 · After: this PR on 7494ce4 (see Measurements). The same save, the same spot, 3840x2160. Attached in the first comment.

Risks

What could break: a text archive the game cannot read would leave its texts missing. Each archive has the game's
own size and layout, and only the hint's bytes differ.
Turning it off: HOS_TEXTS=0, or delete the game folder's texts.
Compatibility: an update makes texts/ again. Saves, the options file and the caches are not touched. A mod with
its own text file is not affected: its file wins.

Checklist

Everyone

  • One topic.
  • The title is a Conventional Commit (type(scope): description) of the status line's type.
  • Why gives the reason plainly and links the issues that fit (the tracker searched).
  • Measurements has a verdict, or one line saying why there is nothing to measure.
  • Testing names what was tested, what wasn't, and what must still be tested, where and how.
  • Rebased on current main. (main @ 40aec7c)
  • python -I -B tests/run_all.py passes (any failure that also fails on main is named).
  • No game files, dumps, build output or generated files.
  • third_party/ untouched (a new folder with a PROVENANCE.md instead).
  • The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled.

When it applies

  • AI assistance recorded with Assisted-by: / Co-Authored-By: trailers.
  • Switches documented (docs/development.md; the README for a menu row) and shipped at their recommended value.
  • Screenshots of the same spot, captioned like the Measurements columns, for a change that shows on screen.
  • A game-free test added for the fix, failing on main and passing here.
  • A check under tests/ that reads changed source updated in this PR, not weakened.
  • Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. (Windows: the whole game cross-built. Linux: host/texts.c and host/mods.c, the host code this PR adds or changes, compiled with gcc against host/posix and run by tests/test_mods_size_table.py; a whole Linux game build is under Must be tested.)
  • Docs updated.

🤖 Generated with Claude Code

**Type:** feat · **Risk:** low · **Tested on:** Windows 11, RTX 4090 (621.24) · **Needs:** Linux; native speakers for the wordings ## Why The hint for playing the ocarina by microphone tells the player to use the console's built-in microphone. A PC has no such thing: the game listens to the microphone chosen in the menu (Gameplay, Microphone). It is the same kind of leftover as the console's button icons were in the texts, which the button prompts already replace with the player's own controller's. No issue asks for this (tracker searched: "microphone", "wording", "text", "console name"). ## What changed The build now rewords that one hint in the player's own text files, in all 16 of the game's languages, and the game reads the reworded files. It follows the button prompts: made at build time from the player's files, served at run time, and a mod's own file wins. - build: `nx2/text_assets.py` (new). `reword()` edits the string in its own room and pads it with NULs, so no MSBT or SARC offset moves and the archive keeps its size (the resource size table goes by it). `STRINGS` names the string by its MSBT and label, and each wording by a fingerprint with the bytes to replace: no game text is in the file. Only the words for the console's microphone change; the rest of the sentence, the menu's icon and the reading aids stay the game's. A text that is not a known wording (another game version) is left as it is. `nx2/make_game.py` runs it in the finish stage (0.25 s for 16 languages). `--show` prints the result from your own files, to check a wording. - runtime: `host/texts.c` (new). `hos_texts_romfs()` serves the game folder's `texts/<archive>` for `Mals/<archive>`. `host/mods.c` asks it only when no mod and no prompt has the path. - tests: `tests/test_text_assets.py` (new), on an authored SARC and MSBT. `tests/test_mods_size_table.py` compiles `texts.c` with `mods.c` and checks three cases over real folders: ours served, a mod's own first, `HOS_TEXTS=0`. - docs: the README's Mods section and update table, `HOS_TEXTS` in `docs/development.md`, `host/game_layout.c`'s note. ## Measurements **Verdict:** it works in the game: the hint reads "Use your microphone ..." with this PR and names the console on main, from the same save and spot. Both held the 60 fps cap there (one run each, so not a performance comparison; the change only serves a different file when the game opens its texts). The run in the game and the screenshots were made with this change on main 7494ce4, built both ways from that commit. The branch was rebased twice since (onto a0dac82, then 40aec7c) with no conflicts and no change to its own code, so they were not retaken. The full suite was run on a0dac82; after the last rebase the change's two tests were run again. Hardware: Windows 11, RTX 4090 24 GB, driver 621.24, Core i9-10900K, 32 GB Scene: the village, by the gate guard, daytime; 3840x2160, DLAA, DLSS Frame Generation 2x, 60 fps cap, HDR off, English (US) Method: one run each; the hint read on screen and in a screenshot, the served file from `longshot_log.txt`, the frame rate from the log's last three `vi:` lines. No median: it is not a performance comparison How to reproduce: load a save where Link has the ocarina, press the ocarina button (D-pad left), read the hint; `HOS_TEXTS=0` in `longshot_env.txt` shows the game's own again | | Before: main @ 40aec7c | After: this PR @ 77d3b46 | |---|---|---| | The hint's wording (English) | names the console's built-in mic | "Use your microphone ..." | | Languages reworded | 0 | 16 | | Frame rate at that spot (60 cap, last 15 s of the log) | 60.0, 60.0, 59.9 | 60.0, 59.9, 60.0 | | `tests/test_text_assets.py` | the file does not exist | 5 tests pass | | `tests/test_mods_size_table.py` | 10 cases | 13 cases | ``` texts: mals/usen.product.110.sarc.zs <- C:\Games\Longshot-prtest\texts/usen.product.110.sarc.zs (the console's wording made the PC's) texts: 16 languages reworded for a PC ok: 13 cases served as they should: ... the texts' PC wording (ours, a mod's, off) ``` ### Flags and settings One new switch. | Flag | What it is | Before this PR | After this PR | Effect | Helps / doesn't help / untested | Recommendation | |---|---|---|---|---|---|---| | `HOS_TEXTS=0` | Serves the game's own texts | (none) | Unset: the reworded texts are served | The hint names the console again | Unset: run in the game. `=0`: in the Linux test only | On by default (unset): one sentence changes, and a mod's file still wins | ## Testing **Tested:** - Game-free, Ubuntu 26.04: `tests/test_text_assets.py` (5 tests), `tests/test_mods_size_table.py` (13 cases, `host/texts.c` compiled with gcc and run over real folders) and `python -I -B tests/run_all.py`: 495 passed, 13 failed, 71 skipped. main a0dac82 on that PC: 494 passed and the same 13 failed (`test_appimage_player_build`, `test_bake_portability`, `test_cpm_discovery`, `test_crash_dialog`, `test_env_on`, `test_lift_cache`, `test_lift_cleanup_error`, `test_linux_preflight`, `test_make_game_cache`, `test_readback_late`, `test_vk_pgo`, `test_vram_budget_row`, `test_walk_key`). - On the author's own dump (version e0f3ccfa): all 16 languages reworded; each archive keeps its decompressed size. - The Windows game cross-built on Linux (`RX_TARGET=windows`, llvm-mingw 20261104): `host/texts.c` compiles and the finish stage made all 16 files in `texts/`. - In the game, Windows 11, RTX 4090 (driver 621.24), Core i9-10900K, 4K, DLAA, English (US): main 7494ce4 and this PR built from the same commit, the same save loaded in each (Kakariko, by the gate guard), the ocarina button pressed. main shows the console's wording; this PR shows "Use your microphone to perform ocarina music via mic input. ..." with the menu icon in place. The log names the served file. Screenshots below. **Not tested:** - In the game: the other 15 languages, a text mod beside it, and `HOS_TEXTS=0` (the last two are covered by the Linux test of `host/texts.c` only). - A Linux build of the whole game (the host file compiles and runs in the test above). - The wordings other than English were written by the author with AI help and not checked by native speakers. **Must be tested:** - By hand, Windows, any GPU: put a mod with its own `Mals/USen.Product.110.sarc.zs` in `mods`, and separately set `HOS_TEXTS=0`, expecting the mod's text in the first case and the game's own hint in the second (request to open) - By hand, Linux, any GPU: build, load a save with the ocarina and press the ocarina button, expecting "Use your microphone ..." and a `texts:` line in the log (request to open) - By hand, a native speaker of each language but English: run `python -I nx2/text_assets.py --romfs` on your own romfs folder with `--show` and read your language's line, expecting a natural sentence that no longer names the console (request to open) ## Screenshots Before: main @ 7494ce4 · After: this PR on 7494ce4 (see Measurements). The same save, the same spot, 3840x2160. Attached in the first comment. ## Risks **What could break:** a text archive the game cannot read would leave its texts missing. Each archive has the game's own size and layout, and only the hint's bytes differ. **Turning it off:** `HOS_TEXTS=0`, or delete the game folder's `texts`. **Compatibility:** an update makes `texts/` again. Saves, the options file and the caches are not touched. A mod with its own text file is not affected: its file wins. ## Checklist ### Everyone - [x] One topic. - [x] The title is a Conventional Commit (`type(scope): description`) of the status line's type. - [x] Why gives the reason plainly and links the issues that fit (the tracker searched). - [x] Measurements has a verdict, or one line saying why there is nothing to measure. - [x] Testing names what was tested, what wasn't, and what must still be tested, where and how. - [x] Rebased on current `main`. (main @ 40aec7c) - [x] `python -I -B tests/run_all.py` passes (any failure that also fails on `main` is named). - [x] No game files, dumps, build output or generated files. - [x] `third_party/` untouched (a new folder with a `PROVENANCE.md` instead). - [x] The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled. ### When it applies - [x] AI assistance recorded with `Assisted-by:` / `Co-Authored-By:` trailers. - [x] Switches documented (docs/development.md; the README for a menu row) and shipped at their recommended value. - [x] Screenshots of the same spot, captioned like the Measurements columns, for a change that shows on screen. - [x] A game-free test added for the fix, failing on `main` and passing here. - [x] A check under `tests/` that reads changed source updated in this PR, not weakened. - [x] Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. (Windows: the whole game cross-built. Linux: `host/texts.c` and `host/mods.c`, the host code this PR adds or changes, compiled with gcc against `host/posix` and run by `tests/test_mods_size_table.py`; a whole Linux game build is under Must be tested.) - [x] Docs updated. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(texts): the ocarina microphone hint says your microphone, not the console's
Some checks are pending
CI / Conventional Commit title (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Blocked by required conditions
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Blocked by required conditions
CI / Workflow lint (actionlint) (pull_request) Blocked by required conditions
Third-party parts / As their notes say (pull_request) Blocked by required conditions
Third-party parts / The same as upstream (pull_request) Blocked by required conditions
PR description / Description follows the template (pull_request_target) Successful in 16s
Website / Website on Cloudflare (pull_request_target) Has been skipped
77d3b46bb6
The hint for playing the ocarina by microphone tells the player to use the console's built-in microphone. On a PC the
game listens to the microphone the menu chooses. The build now rewords that hint in the player's own text archives, in
all 16 languages (nx2/text_assets.py), and the game serves the reworded files (host/texts.c), as it does the button
prompts. A mod's own text file wins; HOS_TEXTS=0 shows the game's own.

Co-Authored-By: Claude Fable 5.2 <[email protected]>
Author
First-time contributor

Screenshots, 3840x2160, the same save and spot (a guard by the gate in the village, the ocarina button pressed), English (US). First: main @ 7494ce4. Second: this PR's change on 7494ce4. They were made before the rebases onto a0dac82 and 40aec7c, which did not change the PR's own code.

before-main-7494ce4.jpg

after-this-pr-on-7494ce4.jpg

Screenshots, 3840x2160, the same save and spot (a guard by the gate in the village, the ocarina button pressed), English (US). First: main @ 7494ce4. Second: this PR's change on 7494ce4. They were made before the rebases onto a0dac82 and 40aec7c, which did not change the PR's own code. ![before-main-7494ce4.jpg](https://git.magicbean.dev/attachments/7143a030-a32b-414a-91dd-0319d35ef004) ![after-this-pr-on-7494ce4.jpg](https://git.magicbean.dev/attachments/6371823f-19fd-475f-8463-5c185e738812)
lg changed title from WIP: feat(texts): the ocarina microphone hint says your microphone, not the console's to feat(texts): the ocarina microphone hint says your microphone, not the console's 2026-11-14 23:22:12 +00:00
Some checks are pending
CI / Conventional Commit title (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Blocked by required conditions
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Blocked by required conditions
CI / Workflow lint (actionlint) (pull_request) Blocked by required conditions
Third-party parts / As their notes say (pull_request) Blocked by required conditions
Third-party parts / The same as upstream (pull_request) Blocked by required conditions
PR description / Description follows the template (pull_request_target) Successful in 16s
Website / Website on Cloudflare (pull_request_target) Has been skipped
This pull request has changes conflicting with the target branch.
  • host/game_layout.c
Some workflows are waiting to be reviewed.
View command line instructions

Manual merge helper

Use this merge commit message when completing the merge manually.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u 'feat/pc-wording-texts:lg-feat/pc-wording-texts'
git switch 'lg-feat/pc-wording-texts'
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
MagicBeanDev/Longshot!604
No description provided.