Name the settings, files and tools NX2navi

The names are NX2NAVI, NX2navi or nx2navi: the settings prefix (NX2NAVI_*), the ini file
(nx2navi.ini), the shader translator (nx2navi_xlate), the Windows resources, the installer and the docs. The 8-byte
file magics keep their size (NX2NSANS, NX2NSPRG, NX2NSPRP, NX2NPKEY, NX2NRFS1), so caches and the RomFS index from
older builds are not read. cfg.c and the settings pages took the prefix length as 5; it now follows the prefix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
chrg6
2026-11-06 03:43:15 -05:00
parent 77d0c0b84e
commit c8738a948c
28 changed files with 61 additions and 61 deletions

View File

@@ -19,7 +19,7 @@ body:
id: version
attributes:
label: Version
description: The title line of the settings menu (F1), for example "NX2navi Recomp 0.1.0, game 1.4.3".
description: The title line of the settings menu (F1), for example "NX2navi 0.1.0, game 1.4.3".
validations:
required: true
- type: input

View File

@@ -19,7 +19,7 @@ body:
id: version
attributes:
label: Version
description: The title line of the settings menu (F1), for example "NX2navi Recomp 0.1.0, game 1.4.3".
description: The title line of the settings menu (F1), for example "NX2navi 0.1.0, game 1.4.3".
validations:
required: true
- type: input

View File

@@ -21,7 +21,7 @@ body:
id: version
attributes:
label: Version
description: The title line of the settings menu (F1), for example "NX2navi Recomp 0.1.0, game 1.4.3".
description: The title line of the settings menu (F1), for example "NX2navi 0.1.0, game 1.4.3".
validations:
required: true
- type: input

View File

@@ -32,7 +32,7 @@ body:
id: version
attributes:
label: Version
description: The title line of the settings menu (F1), for example "NX2navi Recomp 0.1.0, game 1.4.3". For the installer, the version of NX2navi-Setup.
description: The title line of the settings menu (F1), for example "NX2navi 0.1.0, game 1.4.3". For the installer, the version of NX2navi-Setup.
validations:
required: true
- type: input

View File

@@ -1,4 +1,4 @@
# NX2navi Recomp
# NX2navi
Static recompilation of *Ocarina of Time* (Switch, ARM64) into a native Windows x86-64 exe with a Vulkan renderer. Design: [docs/architecture.md](docs/architecture.md). Toolchain, build commands and tests: [docs/building.md](docs/building.md).

View File

@@ -1,6 +1,6 @@
# NX2navi Recomp
# NX2navi
**NX2navi Recomp** is a static recompilation of *The Legend of Zelda: Ocarina of Time* (Nintendo Switch, 2023) into a native x86-64 application for Windows and Linux ([docs/architecture.md](docs/architecture.md)).
**NX2navi** is a static recompilation of *The Legend of Zelda: Ocarina of Time* (Nintendo Switch, 2023) into a native x86-64 application for Windows and Linux ([docs/architecture.md](docs/architecture.md)).
> [!IMPORTANT]
> **No game files are included.** You need your own legally obtained copy of *Ocarina of Time*, dumped from your own console: the base game and the 1.1.0, 1.2.1 or 1.4.3 update. Instructions for obtaining those files will not be provided.
@@ -26,7 +26,7 @@ Report problems as issues, following [CONTRIBUTING.md](CONTRIBUTING.md).
- 16:10 (Steam Deck, handhelds), 3:2 (Surface, Framework), 21:9 and 32:9 (ultrawide) game resolutions, with the camera and the interface in that shape
- Anisotropic texture filtering up to 16x, for sharp ground into the distance
- In-game settings menu (F1) and performance overlay (F10)
- Discord Rich Presence ("Playing NX2navi Recomp" with the play time), off by default, own application id supported
- Discord Rich Presence ("Playing NX2navi" with the play time), off by default, own application id supported
- Setup and in-game menu in English, Russian, Brazilian Portuguese and Simplified Chinese
- Keyboard, mouse and gamepad with remapping, rumble and gyro
- Stereo or 5.1 surround sound output
@@ -67,7 +67,7 @@ To update, run a newer setup on the same folder; saves and settings are kept. Se
## Credits
NX2navi Recomp builds on the projects below. What was taken from each, with its license, is listed in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
NX2navi builds on the projects below. What was taken from each, with its license, is listed in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
- [LAS Recomp](https://github.com/peiikai/LASRecomp)
- [MacNativeGames](https://github.com/ly05010419/MacNativeGames)
@@ -83,7 +83,7 @@ NX2navi Recomp builds on the projects below. What was taken from each, with its
The project's own code is under the [MIT License](LICENSE); third-party code keeps its own license ([THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)). The license grants nothing for Nintendo's game.
NX2navi Recomp is an independent, non-commercial fan project, not affiliated with or endorsed by Nintendo. *The Legend of Zelda*, *Ocarina of Time* and *Nintendo Switch* are trademarks of Nintendo.
NX2navi is an independent, non-commercial fan project, not affiliated with or endorsed by Nintendo. *The Legend of Zelda*, *Ocarina of Time* and *Nintendo Switch* are trademarks of Nintendo.
## Building from source

View File

@@ -16,7 +16,7 @@ Code copied or adapted from another project is listed here with its source, the
| RenoDX NX2navi mod (game mod by souperman9, tonemapper by Musa, RenoDX framework by ShortFuse, RenoVK fork by Ritsu): the approach of the HDR tonemap (the game's 1 - e^-x curve kept below a pivot and continued along its tangent above it, the saturation grade applied to the colour scaled into 0..1) and the observation that the passes after the tonemap keep values above 1. No code copied; the shader is our own | https://github.com/clshortfuse/renodx @ `b6f87272ad1bfdc0e6444910a93606815944a085` (`src/games/<game>/tonemap.slang`, `addon.cpp`), Copyright (c) 2025 Carlos Lopez Jr. | MIT | `runtime/shaders/hdr_tonemap.frag`, `runtime/vk_hdr.c` |
| an ultrawide mod, the community mod for emulators: the list of UI panes the ultrawide layout edits and the distances they move (data only, no code copied; the edit code is our own, and MacNativeGames' `ultrawide_layout.py` in the row above already carries the same values). The mod's repository URL and licence version are not recorded in this repository | an ultrawide mod (community mod; URL not recorded here) | GPL (version not recorded here) | `tools/ultrawide_layout.py` (`KEEP_ROOT`, `edits`, `anim_edits`) |
| MacNativeGames NX2navi virtual-core preemption: asynchronous preemption of an owner in top-level game code, priority inheritance through guest mutexes, the SDK's preemption-disable protocol (TLR+0x100/+0x102, SVC 0x36), the core-wait diagnostics | https://github.com/ly05010419/MacNativeGames @ `33e8fa83052ea1ae09a3583137008e9797e12950` (`games/<game>/runtime/threads.c`, commits 8bf0893 and 19730cd), Copyright (c) 2026 MacNativeGames contributors | MIT | `runtime/kernel.c` (SuspendThread and a register-saving stub replace SIGUSR2), `runtime/hostfn.c`, `runtime/svc.c` (host depth) |
| MacNativeGames RomFS index builder (`NX2NAVIRFS1` layout) | https://github.com/ly05010419/MacNativeGames @ `b75be8cfa704df3701e86130c8ced268e79d6b11` (`games/<game>/scripts/prepare_romfs_backend.py`), Copyright (c) 2026 MacNativeGames contributors | MIT | `tools/romfs_index.py` |
| MacNativeGames RomFS index builder (`NX2NRFS1` layout) | https://github.com/ly05010419/MacNativeGames @ `b75be8cfa704df3701e86130c8ced268e79d6b11` (`games/<game>/scripts/prepare_romfs_backend.py`), Copyright (c) 2026 MacNativeGames contributors | MIT | `tools/romfs_index.py` |
| d2r-mobile host thread environment (TLR, TLS, thread object), the origin of MacNativeGames' thread layer; d2r-mobile NVN host object layouts, command record format and NVN front end, as adapted for NX2navi in MacNativeGames' `d2r_gfx` copy | https://github.com/jhaizhou-ops/d2r-mobile @ `53e7c5bb9ca3ea53e2160005be8fbe920cd9cb53` (`dm/host/thread.c`, `dm/host/hle_thread.c`); the NVN layouts and front end via https://github.com/ly05010419/MacNativeGames @ `b75be8cfa704df3701e86130c8ced268e79d6b11` (`games/<game>/third_party/d2r_gfx/gfx/nvn/nvn_obj.h`, the two types of `nvn_tex.h`, `hle_nvn.c`, `nx2navi_nvn_ext.c`, `nvn_impl.h`, `nvn_hmap.h`, `nvn_pool_index.h`, the request checks and mapping semantics of `nx2navi_vpool.c`, the generation stamps of `nvn_dirty.c`, texture mirroring and texel copies of `nvn_mtl.m`; licence in `games/<game>/third_party/d2r_gfx/LICENSE`), Copyright (c) 2026 jhaizhou | MIT | `runtime/kernel.c`; `runtime/nvn_obj.h`; `runtime/nvn_api.h`, `runtime/nvn_api_core.c`, `runtime/nvn_hmap.h`, `runtime/nvn_pool_index.h`; `runtime/nvn_api_obj.c` (also `nvn_pace.h`); `runtime/nvn_api_cmd.c`, `runtime/nvn_ext.c`; `runtime/vk_memory.c`, `runtime/vk_texture.c`; `runtime/vk_sync.c` (side effects written after GPU completion, `hle_nvn.c`); `runtime/vk_pipeline.c` (pipeline key and state mapping of `nvn_mtl.m` `pso_key_fill` / `pso_desc`, its `vfmt` vertex formats and the missing-varying fix-up of `msl_varyings`); `runtime/vk_exec.c`, `runtime/vk_exec.h` (op loop, pure-state ops and state defaults of `nvn_mtl.m` `mtl_exec` / `state_op` / `state_reset`); `runtime/vk_exec_xfer.c` (copy, clear, event, counter and conditional-render semantics of `nvn_mtl.m` `copy_t2b` / `copy_b2t` / `copy_t2t` / `clear_tex` / `cond_eval`); `runtime/vk_exec_draw.c` (bind ops, draw and dispatch flow, vertex streams of `nvn_mtl.m` `state_op` / `bind_vertex_streams` / `draw_inner` / `dispatch`) |
| nxnative NVN front end (d2r-mobile's successor): texture view depth-stencil mode bits, stencil-view rule, `Downsample` and indirect draw and dispatch records | https://github.com/seedds/nxnative @ `d5b380b3a80495609c2e751bb994911a638935ad` (`dm/gfx/nvn/hle_nvn.c`, `nvn_obj.h`, `nvn_mtl.m`), Copyright (c) 2026 jhaizhou | MIT | `runtime/nvn_obj.h`, `runtime/nvn_ext.c`, `runtime/nvn_api_cmd.c`, `runtime/vk_exec_draw.c` |
| nxnative spin wait search and gate: loops that only another thread can end, polls that take a spin lock, the gate's wait and hand-off rule; MacNativeGames' NX2navi port of the gate | https://github.com/seedds/nxnative @ `6d349844880eb0527be77d7e0e4b8d999c0ae2f4` (`dm/tools/patch_nso.py` "Spin waits", `dm/tools/tests/test_spin_waits.py`, `dm/host/hle_thread.c` dm_spin_wait), Copyright (c) 2026 seedds; https://github.com/ly05010419/MacNativeGames @ `a038e6be7608e6f4eba6fc0381026cebf24ef4a3` (`games/<game>/runtime/threads.c` runtime_spin_wait), Copyright (c) 2026 MacNativeGames contributors | MIT | `tools/spin_waits.py`, `tests/spin_waits_test.py`, `runtime/kernel.c` (rt_spin_gate) |

View File

@@ -1,6 +1,6 @@
# Mods
NX2navi Recomp loads the mods players make for the Switch emulators (Ryujinx, the hardware and its forks): texture and model
NX2navi loads the mods players make for the Switch emulators (Ryujinx, the hardware and its forks): texture and model
packs, gameplay and text changes from GameBanana and similar sites, a mod manager's merged output, code patches (`.ips`,
`.pchtxt`) and Atmosphère cheat files. No mod or cheat file ships with the port.
@@ -43,7 +43,7 @@ The menu saves the order and the switches in `nx2navi.ini`, under `[mods]`, by f
### Mods that change the same files
Two mods that edit the same game file do not combine: the higher one wins the whole file. Merge such mods with
a mod manager and set its export location to an empty folder inside
[a mod manager](https://github.com/a mod manager-Team/mod manager) (NX2navi Mod Manager) and set its export location to an empty folder inside
`mods`, for example `mods\merged`. The exported folder then counts as one mod here. Mods packaged for a mod manager only
(`.tkcl` files) go the same way.

View File

@@ -1,4 +1,4 @@
# Tester guide: running NX2navi Recomp on your GPU
# Tester guide: running NX2navi on your GPU
This guide is for testing the build on a GPU other than the developer's (AMD RX 9070). You build it from source with
your own copy of the game and your own console keys. Nothing from the game is in this repository, and nothing you build

View File

@@ -247,12 +247,12 @@
# menu_lang = en
[discord]
# Rich Presence: "Playing NX2navi Recomp" with the play time in your Discord status while the game runs, through the
# Rich Presence: "Playing NX2navi" with the play time in your Discord status while the game runs, through the
# local IPC of a running Discord client. 1 = on; the Menu tab of the settings menu (F1) switches it too, and the
# change reaches the presence thread at once.
# discord_rpc = 0
# The application whose name and artwork the status shows. The default is the project's own application,
# registered as "NX2navi Recomp" with the port's green ring icon as its art. Register your own at
# registered as "NX2navi" with the port's green ring icon as its art. Register your own at
# discord.com/developers (name and art are yours to choose) and put its id here.
# discord_app_id = 1567232599846293504
# The key of the application's uploaded art asset shown as the status's large image.

View File

@@ -16,7 +16,7 @@
#include "platform/platform.h"
#define PREFIX "NX2NAVI_"
#define PREFIX_LEN 5
#define PREFIX_LEN (sizeof PREFIX - 1)
#define CFG_MAX_KEYS 512
typedef struct { char *key, *value; int dirty, removed; } CfgEntry; // key upper-case, without the prefix; value NULL after cfg_reset

View File

@@ -1,8 +1,8 @@
// Discord Rich Presence: "Playing NX2navi Recomp" with the elapsed play time in the player's Discord status, through
// Discord Rich Presence: "Playing NX2navi" with the elapsed play time in the player's Discord status, through
// the local IPC of a running Discord client (platform.h's plat_ipc_*). Nothing leaves the machine but the activity
// itself, and nothing is sent while NX2NAVI_DISCORD_RPC is off (the default: the status is information about the
// player's session). NX2NAVI_DISCORD_APP_ID names the application whose name and artwork Discord shows — the default
// is the project's own application, registered as "NX2navi Recomp"; a player who wants their own name or
// is the project's own application, registered as "NX2navi"; a player who wants their own name or
// art registers an application at discord.com/developers and puts its id in nx2navi.ini — and NX2NAVI_DISCORD_IMAGE the
// key of its uploaded art asset.
//
@@ -170,7 +170,7 @@ static int send_activity(PlatIpc *p, const char *image) {
snprintf(json, sizeof json,
"{\"cmd\":\"SET_ACTIVITY\",\"nonce\":\"%u\",\"args\":{\"pid\":%lu,\"activity\":{\"details\":\"Game "
"%d.%d.%d \\u00b7 Recomp %.*s\",\"timestamps\":{\"start\":%llu},\"assets\":{\"large_image\":\"%s\","
"\"large_text\":\"NX2navi Recomp %s\"}}}}",
"\"large_text\":\"NX2navi %s\"}}}}",
next_nonce(), (unsigned long)plat_process_id(), v / 100, v / 10 % 10, v % 10, port_len, rt_port_version,
(unsigned long long)start, image, rt_port_version);
if (!write_frame(p, OP_FRAME, json)) return 0;

View File

@@ -1868,13 +1868,13 @@ void gfx_shader_local_size(const GfxShader *s, uint32_t local[3]) { memcpy(local
// census) does not match the keys play asks for. Every (program, answers) that a gfx_shader_get* call resolves is
// recorded next to pipeline-keys.bin, so the first-start preparation (Task 2.6, here the NX2NAVI_TEST_PREPARE_SHADERS hook)
// translates exactly the variants play needs, from these files alone:
// shader-answers.bin "NX2NAVISANS", version, record size; records: stage (u32), code hash, input id, pack_answers bytes
// shader-answers.bin "NX2NSANS", version, record size; records: stage (u32), code hash, input id, pack_answers bytes
// of the full answers, zero padding. One record per input id: answers outside the shader's use
// mask do not change its SPIR-V, are out of its input id and cache key (mask_answers) and so do
// not make records of their own (a fight run meets 4126 full pairs, 1238 input ids). The full
// answers are kept so a translator with a wider mask still gets them. Under a new translator
// the masks, hence the input ids, are new, and play appends records for them.
// shader-programs.bin "NX2NAVISPRG", version, 0; records: stage, length, c1 length (u32 each), code hash, control section,
// shader-programs.bin "NX2NSPRG", version, 0; records: stage, length, c1 length (u32 each), code hash, control section,
// code[length], c1. One per code hash; written before the answers that name it. Game content:
// it stays in the ignored pipeline cache directory.
// A file with another header is rewritten; a torn tail (killed process) is cut off at open.
@@ -2002,12 +2002,12 @@ void gfx_shader_record_at(const char *keys_path) {
snprintf(RC.prg_path, sizeof RC.prg_path, "%.*sshader-programs.bin", dir, keys_path);
uint8_t *b;
size_t n;
if (rec_read(RC.ans_path, "NX2NAVISANS", ANS_VERSION, ANS_REC, &b, &n)) {
if (rec_read(RC.ans_path, "NX2NSANS", ANS_VERSION, ANS_REC, &b, &n)) {
for (size_t o = 0; o + ANS_REC <= n; o += ANS_REC) set_add(&RC.pairs, hash8(b + o + 36));
if (n % ANS_REC) truncate_to(RC.ans_path, sizeof(RecHeader) + n / ANS_REC * ANS_REC);
}
free(b);
if (rec_read(RC.prg_path, "NX2NAVISPRG", PRG_VERSION, 0, &b, &n)) {
if (rec_read(RC.prg_path, "NX2NSPRG", PRG_VERSION, 0, &b, &n)) {
size_t whole = prg_walk(b, n, prg_seen, &RC.progs);
if (whole != n) truncate_to(RC.prg_path, sizeof(RecHeader) + whole);
}
@@ -2069,8 +2069,8 @@ void gfx_shader_record_flush(int force) {
RC.ans = (Bytes){0}, RC.prg = (Bytes){0};
uint64_t total = RC.pairs.n, added = RC.pairs_new;
plat_mutex_unlock(&RC.lock);
if (prg.n && !rec_append(RC.prg_path, "NX2NAVISPRG", PRG_VERSION, 0, &prg)) rt_log("gfx_shader: cannot write %s", RC.prg_path);
if (ans.n && !rec_append(RC.ans_path, "NX2NAVISANS", ANS_VERSION, ANS_REC, &ans)) rt_log("gfx_shader: cannot write %s", RC.ans_path);
if (prg.n && !rec_append(RC.prg_path, "NX2NSPRG", PRG_VERSION, 0, &prg)) rt_log("gfx_shader: cannot write %s", RC.prg_path);
if (ans.n && !rec_append(RC.ans_path, "NX2NSANS", ANS_VERSION, ANS_REC, &ans)) rt_log("gfx_shader: cannot write %s", RC.ans_path);
plat_mutex_unlock(&rec_io);
if (ans.n) rt_log("gfx_shader: answers: %zu new records appended (%llu new this run, %llu recorded)", ans.n / ANS_REC,
(unsigned long long)added, (unsigned long long)total);
@@ -2132,8 +2132,8 @@ static long long prepare_files(const char *ans_path, const char *prg_path, int t
double t0 = (double)plat_now_ms();
uint8_t *ab = NULL, *pb = NULL;
size_t an = 0, pn = 0;
if (!rec_read(ans_path, "NX2NAVISANS", ANS_VERSION, ANS_REC, &ab, &an) ||
!rec_read(prg_path, "NX2NAVISPRG", PRG_VERSION, 0, &pb, &pn)) {
if (!rec_read(ans_path, "NX2NSANS", ANS_VERSION, ANS_REC, &ab, &an) ||
!rec_read(prg_path, "NX2NSPRG", PRG_VERSION, 0, &pb, &pn)) {
rt_log("gfx_shader: prepare: no %s (%s)", what, ans_path);
free(ab), free(pb);
return -1;
@@ -2175,7 +2175,7 @@ void gfx_shader_prepare_recorded(int threads, int procs) {
}
// ---- prepared variants (shader-prepared.bin next to pipeline-keys.bin)
// "NX2NAVISPRP", version, record size; records: stage, priority, 2 zero bytes, input id. gfx_shader_prepare_seed writes
// "NX2NSPRP", version, record size; records: stage, priority, 2 zero bytes, input id. gfx_shader_prepare_seed writes
// them in priority order, one per input id; gfx_shader_warm_list reads them at boot.
#define PRP_VERSION 1
#define PRP_REC 36
@@ -2203,7 +2203,7 @@ int gfx_shader_prepare_seed(const char *dir, int threads, int procs) {
by[r[1]]++, stages[r[0]]++, u++;
}
free(seen.v);
RecHeader h = {{'T', 'O', 'T', 'K', 'S', 'P', 'R', 'P'}, PRP_VERSION, PRP_REC};
RecHeader h = {{'N', 'X', '2', 'N', 'S', 'P', 'R', 'P'}, PRP_VERSION, PRP_REC};
uint8_t *file = recs ? malloc(sizeof h + u * PRP_REC + 1) : NULL;
int ok = file != NULL;
if (ok) {
@@ -2233,9 +2233,9 @@ size_t gfx_shader_warm_list(GfxWarmEnt **out) {
uint8_t *ab = NULL, *pb = NULL;
size_t an = 0, pn = 0;
plat_mutex_lock(&rec_io); // no append meanwhile
rec_read(RC.ans_path, "NX2NAVISANS", ANS_VERSION, ANS_REC, &ab, &an);
rec_read(RC.ans_path, "NX2NSANS", ANS_VERSION, ANS_REC, &ab, &an);
plat_mutex_unlock(&rec_io);
rec_read(prp, "NX2NAVISPRP", PRP_VERSION, PRP_REC, &pb, &pn);
rec_read(prp, "NX2NSPRP", PRP_VERSION, PRP_REC, &pb, &pn);
size_t na = an / ANS_REC, np = pn / PRP_REC, n = 0;
GfxWarmEnt *e = calloc(na + np + 1, sizeof *e);
Set64 seen = {0};

View File

@@ -196,7 +196,7 @@ static void handle(const SDL_Event *e) {
static void window_main(void *arg) {
(void)arg;
g_window_tid = plat_thread_id();
SDL_SetHint(SDL_HINT_APP_ID, "nx2navi-recomp"); // Wayland's app id: the desktop file and the taskbar match it
SDL_SetHint(SDL_HINT_APP_ID, "nx2navi"); // Wayland's app id: the desktop file and the taskbar match it
SDL_SetHint(SDL_HINT_VIDEO_ALLOW_SCREENSAVER, "0");
g_video_ok = SDL_Init(SDL_INIT_VIDEO);
if (!g_video_ok) rt_log("gfx: SDL video init failed (%s)", SDL_GetError());
@@ -255,7 +255,7 @@ static void open_window(void *arg) {
(void)arg;
int w, h;
gfx_cfg_window_size(&w, &h);
g_win = SDL_CreateWindow("NX2navi Recomp", w, h, SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY);
g_win = SDL_CreateWindow("NX2navi", w, h, SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY);
if (!g_win) {
rt_log("gfx: SDL_CreateWindow failed (%s)", SDL_GetError());
return;

View File

@@ -317,7 +317,7 @@ static void window_main(void *arg) {
// button flashes, and NX2NAVI_FULLSCREEN waits for the first activation.
// NX2NAVI_BACKGROUND_WINDOW=1 (test runs): no flashing, never fullscreen at start, and F11 keeps the window's place.
int background = g_background = cfg_get("NX2NAVI_BACKGROUND_WINDOW") && atoi(cfg_get("NX2NAVI_BACKGROUND_WINDOW"));
g_hwnd = CreateWindowExW(0, wc.lpszClassName, L"NX2navi Recomp", WND_STYLE, CW_USEDEFAULT, CW_USEDEFAULT, ow, oh, NULL,
g_hwnd = CreateWindowExW(0, wc.lpszClassName, L"NX2navi", WND_STYLE, CW_USEDEFAULT, CW_USEDEFAULT, ow, oh, NULL,
NULL, inst, NULL);
if (!g_hwnd) {
rt_log("gfx: CreateWindowEx failed (%lu)", GetLastError());

View File

@@ -514,7 +514,7 @@ static void portable_paths(RtConfig *c) {
int main(int argc, char **argv) {
mem_init(); // first: claim the guest address space before anything else can land there; reads nx2navi.ini
// The build that wrote the log, at its top: an attached log from another install or version shows at a glance.
rt_log("version: NX2navi Recomp %s, game %d.%d.%d", rt_port_version, rt_game_version / 100, rt_game_version / 10 % 10,
rt_log("version: NX2navi %s, game %d.%d.%d", rt_port_version, rt_game_version / 100, rt_game_version / 10 % 10,
rt_game_version % 10);
// A restart from the settings menu (gfx_present.c gfx_window_closed) starts this process while the one it replaces
// is still exiting: its log, RomFS and saves are free once it is gone.

View File

@@ -946,7 +946,7 @@ static void load_index(void) {
if (strcmp(hex, ROMFS_INDEX_SHA256))
rt_fatal("RomFS index %s has SHA-256 %s, this build expects %s (rebuild with tools/build_game.py)", path, hex,
ROMFS_INDEX_SHA256);
need(!memcmp(index_bytes, "NX2NAVIRFS1", 8), "index format");
need(!memcmp(index_bytes, "NX2NRFS1", 8), "index format");
memcpy(&file_count, index_bytes + 8, 8);
memcpy(&strings_offset, index_bytes + 16, 8);
need(file_count == ROMFS_FILE_COUNT && file_count < 1000000 && strings_offset == 24 + file_count * 24 &&

View File

@@ -61,7 +61,7 @@ int sysinfo_text(char *buf, size_t n) {
Out o = {buf, n, 0};
buf[0] = 0;
char s[256];
put(&o, "NX2navi Recomp system info\n");
put(&o, "NX2navi system info\n");
put(&o, "OS: %s\n", plat_os_version(s, sizeof s) ? s : "unknown");
sysinfo_cpu_name(s, sizeof s);
put(&o, "CPU: %s, %u logical processors\n", s[0] ? s : "unknown", plat_cpu_count());

View File

@@ -118,7 +118,7 @@ static void write_lines(const InputMap *m) {
if (line[0]) {
cfg_set(var, line);
} else {
const char *k = var + 5;
const char *k = var + strlen("NX2NAVI_");
cfg_reset(&k, 1);
}
rt_log("menu: bind_%s = %s", input_action_name(a), line[0] ? line : "(default)");

View File

@@ -437,7 +437,7 @@ static void test_parse(void) {
TestSet &t = g_test.sets[g_test.n_sets++];
t.frame = f;
int kn = (int)(eq - s), vn = (int)(s + n - eq - 1);
snprintf(t.key, sizeof t.key, "%s%.*s", strncmp(s, "NX2NAVI_", 5) ? "NX2NAVI_" : "", kn, s);
snprintf(t.key, sizeof t.key, "%s%.*s", strncmp(s, "NX2NAVI_", strlen("NX2NAVI_")) ? "NX2NAVI_" : "", kn, s);
snprintf(t.value, sizeof t.value, "%.*s", vn, eq + 1);
}
s += n;

View File

@@ -45,7 +45,7 @@ static const char *const text_en[UI_TEXT_COUNT] = {
[UI_MENU_ON] = "On", [UI_MENU_OFF] = "Off", [UI_MENU_AUTO] = "Automatic", [UI_MENU_DEFAULT_MARK] = "default",
[UI_MENU_AFTER_RESTART] = "after restart", [UI_MENU_SET_BY_ENV] = "set by environment variable",
[UI_MENU_SAVE_FAILED] = "could not save settings",
[UI_MENU_VERSION] = "NX2navi Recomp %s, game %s",
[UI_MENU_VERSION] = "NX2navi %s, game %s",
[UI_MENU_FULLSCREEN] = "Fullscreen", [UI_MENU_FULLSCREEN_DESC] = "Fills the screen with the game; F11 toggles it.",
[UI_MENU_WINDOW_SIZE] = "Window size", [UI_MENU_WINDOW_SIZE_DESC] = "Size of the game window when not fullscreen.",
@@ -363,7 +363,7 @@ static const char *const text_en[UI_TEXT_COUNT] = {
[UI_MENU_MENU_LANG] = "Menu language", [UI_MENU_MENU_LANG_DESC] = "Language of this menu and the overlay.",
[UI_MENU_MENU_LANG_AUTO] = "Automatic (from Windows)",
[UI_MENU_DISCORD_RPC] = "Discord Rich Presence",
[UI_MENU_DISCORD_RPC_DESC] = "Shows \"Playing NX2navi Recomp\" with the play time in your Discord status while the "
[UI_MENU_DISCORD_RPC_DESC] = "Shows \"Playing NX2navi\" with the play time in your Discord status while the "
"game runs. discord_app_id and discord_image in nx2navi.ini choose the application.",
[UI_MENU_ADV_WARNING] = "These settings are for testing and troubleshooting. Change them only when you know why.",
@@ -507,7 +507,7 @@ static const char *const text_ru[UI_TEXT_COUNT] = {
[UI_MENU_DEFAULT_MARK] = "по умолчанию",
[UI_MENU_AFTER_RESTART] = "после перезапуска", [UI_MENU_SET_BY_ENV] = "задано переменной окружения",
[UI_MENU_SAVE_FAILED] = "не удалось сохранить настройки",
[UI_MENU_VERSION] = "NX2navi Recomp %s, игра %s",
[UI_MENU_VERSION] = "NX2navi %s, игра %s",
[UI_MENU_FULLSCREEN] = "Полный экран", [UI_MENU_FULLSCREEN_DESC] = "Игра на весь экран; F11 переключает режим.",
[UI_MENU_WINDOW_SIZE] = "Размер окна", [UI_MENU_WINDOW_SIZE_DESC] = "Размер окна игры вне полноэкранного режима.",
@@ -828,7 +828,7 @@ static const char *const text_ru[UI_TEXT_COUNT] = {
[UI_MENU_MENU_LANG] = "Язык меню", [UI_MENU_MENU_LANG_DESC] = "Язык этого меню и индикатора.",
[UI_MENU_MENU_LANG_AUTO] = "Автоматически (из Windows)",
[UI_MENU_DISCORD_RPC] = "Discord Rich Presence",
[UI_MENU_DISCORD_RPC_DESC] = "Пока игра запущена, показывает «Играю в NX2navi Recomp» со временем игры в статусе "
[UI_MENU_DISCORD_RPC_DESC] = "Пока игра запущена, показывает «Играю в NX2navi» со временем игры в статусе "
"Discord. Приложение выбирают discord_app_id и discord_image в nx2navi.ini.",
[UI_MENU_ADV_WARNING] = "Эти настройки нужны для тестов и поиска неполадок. Меняйте их, только если знаете зачем.",
@@ -1004,7 +1004,7 @@ static const char *const text_pt_br[UI_TEXT_COUNT] = {
[UI_MENU_DEFAULT_MARK] = "padrão",
[UI_MENU_AFTER_RESTART] = "após reiniciar", [UI_MENU_SET_BY_ENV] = "definido por variável de ambiente",
[UI_MENU_SAVE_FAILED] = "não foi possível salvar as configurações",
[UI_MENU_VERSION] = "NX2navi Recomp %s, jogo %s",
[UI_MENU_VERSION] = "NX2navi %s, jogo %s",
[UI_MENU_FULLSCREEN] = "Tela cheia", [UI_MENU_FULLSCREEN_DESC] = "O jogo ocupa a tela inteira; F11 alterna.",
[UI_MENU_WINDOW_SIZE] = "Tamanho da janela",
@@ -1184,7 +1184,7 @@ static const char *const text_pt_br[UI_TEXT_COUNT] = {
[UI_MENU_MENU_LANG] = "Idioma do menu", [UI_MENU_MENU_LANG_DESC] = "Idioma deste menu e do indicador.",
[UI_MENU_MENU_LANG_AUTO] = "Automático (do Windows)",
[UI_MENU_DISCORD_RPC] = "Discord Rich Presence",
[UI_MENU_DISCORD_RPC_DESC] = "Mostra \"Jogando NX2navi Recomp\" com o tempo de jogo no seu status do Discord "
[UI_MENU_DISCORD_RPC_DESC] = "Mostra \"Jogando NX2navi\" com o tempo de jogo no seu status do Discord "
"enquanto o jogo roda. discord_app_id e discord_image no nx2navi.ini escolhem a "
"aplicação.",
@@ -1503,7 +1503,7 @@ static const char *const text_zh_hans[UI_TEXT_COUNT] = {
[UI_MENU_AFTER_RESTART] = "重启后生效",
[UI_MENU_SET_BY_ENV] = "由环境变量设定",
[UI_MENU_SAVE_FAILED] = "无法保存设置",
[UI_MENU_VERSION] = "NX2navi Recomp %s,游戏 %s",
[UI_MENU_VERSION] = "NX2navi %s,游戏 %s",
[UI_MENU_FULLSCREEN] = "全屏",
[UI_MENU_FULLSCREEN_DESC] = "游戏铺满屏幕;按 F11 切换。",
[UI_MENU_WINDOW_SIZE] = "窗口大小",
@@ -1774,7 +1774,7 @@ static const char *const text_zh_hans[UI_TEXT_COUNT] = {
[UI_MENU_MENU_LANG_DESC] = "本菜单和性能浮层的语言。",
[UI_MENU_MENU_LANG_AUTO] = "自动(跟随 Windows)",
[UI_MENU_DISCORD_RPC] = "Discord Rich Presence",
[UI_MENU_DISCORD_RPC_DESC] = "游戏运行时在 Discord 状态中显示“正在玩 NX2navi Recomp”及游戏时长。nx2navi.ini 中的 "
[UI_MENU_DISCORD_RPC_DESC] = "游戏运行时在 Discord 状态中显示“正在玩 NX2navi”及游戏时长。nx2navi.ini 中的 "
"discord_app_id 和 discord_image 选择应用。",
[UI_MENU_ADV_WARNING] = "这些设置用于测试和排查问题,请在了解原因后再修改。",
[UI_MENU_GROUP_SCHED] = "调度",

View File

@@ -22,7 +22,7 @@ typedef enum {
UI_MENU_AFTER_RESTART, // note on a setting that is read at start
UI_MENU_SET_BY_ENV, // note on a setting an environment variable fixes
UI_MENU_SAVE_FAILED,
UI_MENU_VERSION, // "NX2navi Recomp %s, game %s": the port version and the game update, beside the title
UI_MENU_VERSION, // "NX2navi %s, game %s": the port version and the game update, beside the title
// Screen
UI_MENU_FULLSCREEN, UI_MENU_FULLSCREEN_DESC,

View File

@@ -80,8 +80,8 @@ static int create_instance(void) {
if (vk_hdr_wanted() && instance_ext_present(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME)) // HDR10 surface formats
ext[n_ext++] = VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME;
vk_dlaa_instance_exts(ext, &n_ext, 12);
VkApplicationInfo app = {.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, .pApplicationName = "NX2navi Recomp",
.pEngineName = "NX2navi Recomp", .apiVersion = VK_API_VERSION_1_3};
VkApplicationInfo app = {.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, .pApplicationName = "NX2navi",
.pEngineName = "NX2navi", .apiVersion = VK_API_VERSION_1_3};
VkInstanceCreateInfo ci = {.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, .pApplicationInfo = &app,
.enabledExtensionCount = n_ext, .ppEnabledExtensionNames = ext,
.enabledLayerCount = validate ? 1 : 0, .ppEnabledLayerNames = layers};

View File

@@ -2066,7 +2066,7 @@ static void keys_flush(void) {
FILE *f = fopen(K.path, K.header_ok ? "ab" : "wb");
int ok = f != NULL;
if (ok && !K.header_ok) {
KeysHeader h = {{'T', 'O', 'T', 'K', 'P', 'K', 'E', 'Y'}, KEYS_VERSION, sizeof(KeyRec)};
KeysHeader h = {{'N', 'X', '2', 'N', 'P', 'K', 'E', 'Y'}, KEYS_VERSION, sizeof(KeyRec)};
ok = fwrite(&h, sizeof h, 1, f) == 1;
}
if (ok) ok = fwrite(r, sizeof *r, n, f) == n;
@@ -2093,7 +2093,7 @@ static void keys_open(void) {
fseek(f, 0, SEEK_END);
long len = ftell(f);
fseek(f, 0, SEEK_SET);
if (len >= (long)sizeof h && fread(&h, sizeof h, 1, f) == 1 && !memcmp(h.magic, "NX2NAVIPKEY", 8) &&
if (len >= (long)sizeof h && fread(&h, sizeof h, 1, f) == 1 && !memcmp(h.magic, "NX2NPKEY", 8) &&
h.version == KEYS_VERSION && h.rec_size == sizeof(KeyRec)) {
K.header_ok = 1;
size_t n = ((size_t)len - sizeof h) / sizeof(KeyRec);

View File

@@ -28,7 +28,7 @@ BLOCKED_SUFFIXES = {
BLOCKED_NAMES = {"main", "sdk", "rtld", "subsdk0", "subsdk1", "main.npdm"}
# Written by the code generator into every file it emits.
GENERATED_MARKER = "NX2NAVI_RECOMP_" + "GENERATED_FROM_GAME_CODE"
GENERATED_MARKER = "NX2NAVI_" + "GENERATED_FROM_GAME_CODE"
# A prod.keys / title.keys line: name containing key, kek or seed, then hex.
KEY_LINE = re.compile(

View File

@@ -433,7 +433,7 @@ exec "$HERE/python/bin/python3" -m installer.gui "$@"
DESKTOP = '''[Desktop Entry]
Type=Application
Name=NX2navi Recomp Setup
Name=NX2navi Setup
Comment=Builds Ocarina of Time for this PC from your own game files
Exec=AppRun
Icon=nx2navi-setup

View File

@@ -9,8 +9,8 @@ default variant (every texture slot a 2D texture, float vertex inputs and colour
translates every shader for its default bind state: prepare_shader_seed.py all_default), and writes them next to the
build's nx2navi.exe in the record layouts of runtime/gfx_shader.c ("answers met in play"):
seed-programs.bin "NX2NAVISPRG": stage, length, c1 length, runtime code hash, control section, code, c1
seed-answers.bin "NX2NAVISANS": stage, code hash, input id (zero: the runtime computes it), answers, priority
seed-programs.bin "NX2NSPRG": stage, length, c1 length, runtime code hash, control section, code, c1
seed-answers.bin "NX2NSANS": stage, code hash, input id (zero: the runtime computes it), answers, priority
Priority (the pad byte): 0 shaders the list's warm rows flag as title/menu (t), 1 other warm rows (S, C, R), 2 the
rest; a default variant takes its shader's priority. Then it runs `nx2navi.exe --prepare-shaders`, which translates every record into the build's shader cache, writes
@@ -192,11 +192,11 @@ def main():
recs.sort(key=lambda r: r[0]) # stable: list order within a priority
out = a.build.resolve()
with open(out / 'seed-programs.bin', 'wb') as f:
f.write(b'NX2NAVISPRG' + struct.pack('<II', 1, 0))
f.write(b'NX2NSPRG' + struct.pack('<II', 1, 0))
for _, body in progs.values():
f.write(body)
with open(out / 'seed-answers.bin', 'wb') as f:
f.write(b'NX2NAVISANS' + struct.pack('<II', 1, ANS_REC))
f.write(b'NX2NSANS' + struct.pack('<II', 1, ANS_REC))
for _, rec in recs:
f.write(rec)
by = [sum(1 for p, _ in recs if p == i) for i in range(3)]

View File

@@ -6,7 +6,7 @@ MacNativeGames contributors).
Input: <romfs>/index.json ({status, romfs_size, romfs_sha256, files: [{path, offset, size}]}) as tools/extract.py
writes it, and <romfs>/romfs.bin, whose size must match. Output, both in the build directory (never in the repo):
romfs-index.bin NX2NAVIRFS1 layout: header <8sQQ (magic, count, strings offset), count 24-byte rows <QQII (offset,
romfs-index.bin NX2NRFS1 layout: header <8sQQ (magic, count, strings offset), count 24-byte rows <QQII (offset,
size, name offset, name length including the NUL), then the NUL-terminated names; rows sorted by
the UTF-8 bytes of the path, which is the order strcmp sees
romfs_config.h ROMFS_IMAGE_SIZE, ROMFS_IMAGE_SHA256, ROMFS_INDEX_SHA256, ROMFS_FILE_COUNT
@@ -27,7 +27,7 @@ from pathlib import Path
from check_content import GENERATED_MARKER
MAGIC = b'NX2NAVIRFS1'
MAGIC = b'NX2NRFS1'
HEADER = struct.Struct('<8sQQ')
ROW = struct.Struct('<QQII')