Files
nxnative-easy/dm/games/0100606026F12000/game.tsv
T
seedds f4f0a85d6e patch_nso.py split into the general rewriter and per-build patch files (GitHub issue #63): every game's bring-up edited the one file, so PRs for unrelated games conflicted. dm/tools/patch_nso.py (1,711 → about 1,100 lines) keeps the general passes and the driver; the instruction encoders move unchanged to dm/tools/nso_asm.py; a game's own patches (CUTS, OBS and the frame-step stubs, now FRAME_STEP = {build ID: stub(ctx)}) move verbatim with their comments to dm/games/<id>/patches.py (16 profiles: Tears of the Kingdom, Breath of the Wild, Age of Calamity and Paper Mario: The Thousand-Year Door with their stubs), and the cuts of Nintendo's sdk module builds, 6 of the 15 shipped by 2 to 4 games, to dm/tools/sdk_patches.py. The rewriter loads every patch file, whatever the game, and applies those of a module's build ID at the points it did before (cuts before the scan, gates after the rewrite, stubs after the gates); a build ID claimed twice stops it, and its command line needs no DM_GAME. build_src.sha256 lists the rewriter's files and every patch file (the same for every module). NSP script: the rewrite step's reuse key counts nso_asm.py and only the patch files that name one of the game's builds (patch_files), profile_files leaves patches.py out (only the rewrite step reads it), and a derived profile gets none. dm/tools/tests/test_patches.py: no build claimed twice, the entries' forms, a game's file names only its own profile's non-sdk builds, sdk_patches.py only sdk builds some profile ships, and the reuse key's patch files. Checked byte-identical: every extracted module on the game drive (131 builds) rewritten with the previous and the new rewriter gives the same outputs but build_src.sha256, 28 of the 30 patched builds among them (all four frame-step mains), and 7 fail alike (rtld, and New Super Mario Bros. U Deluxe's, which no profile rewrites); the other two (Super Mario Bros. Wonder's mains and Absolum's, no game files here) by their CUTS / OBS data, equal to the previous tables. AGENTS.md, docs, dm/games/README.md, the profiles' comments and the host comments that named a game's cut in patch_nso.py now name its patches.py or sdk_patches.py
2026-10-23 23:36:21 +08:00

4.8 KiB

1# FINAL FANTASY RESONANCE: Square Enix, Unreal Engine 5.6.1 (SDK MW+EpicGames+UnrealEngine-5_6_1 in main; the desktop renderer, SF_GLSL_SWITCH shaders), SDK 20.5.17, NVN, CRIWARE sound;
2# update 1.0.1 (v65536). Everything is in one IoStore container beside one pak; the shader libraries are IoStore chunks (uepak.py).
3# Started from the NSP script's provisional profile (dm/games/profile_guess.py) and brought up on the Mac (docs/agents)
4# Format: see dm/games/README.md
5# ---- Identity ----
6title_id0100606026F12000
7program_id0100606026F12000
8# ---- App ----
9# Game name: only a label for profile listings and the Mac window title; the iOS app name is the game name in the base NSP, and the bundle ID comes from the base game title ID (build_ipa.sh / NSP script)
10nameFINAL FANTASY RESONANCE
11ipaFinalFantasyResonance.ipa
12app_categorypublic.app-category.games
13# ---- Versions ----
14buildv655361.0.1main=84e182f72ee1da4f477804bd05b54c15subsdk0=ab62fe8edd07a6a293f885d54359e559sdk=0023a1b06130cd795f7bc4613772af0a
15packagev65536
16shader_versionsv65536
17# ---- Files ----
18# load order as on Horizon: main, subsdk*, sdk (subsdk0 = NintendoSDK_movie, which main imports from; the sdk is STEINS;GATE RE:BOOT's build)
19modulesmain subsdk0 sdk
20romfs_markerFFRS/Content/Paks/FFRS-Switch.ucas
21zip_store.pak:.ttf:.txt:.ucas:.utoc:.metallib
22# ---- Graphics ----
23# 60 fps (30 on the Switch): the engine's Switch device profile sets rhi.syncinterval=2 (BaseSwitchDeviceProfiles.ini), so the game asks for present interval 2, and the game sets no t.MaxFPS.
24# The host writes rhi.SyncInterval 1 into its console variable (hle_fpslock.c), whenever the game sets it back (at level loads), so the game asks for present interval 1 itself. Unreal steps
25# the game by the time that really passed: DM_NVN_REGLUM traces of the same keys from the same save at 30 and 60 fps (59.8 fps, frame time p99 18 ms on the Mac) match from the load
26# through a 3 s walk (thumbnail difference ≤ 0.006). DM_FPS_TARGET=30 (Documents/env.txt on the iPhone) keeps the game's 30 and saves power
27fps_target60
28# ---- Memory ----
29# Unreal Engine 5.6.1: nninitStartup (main+0x13370) reserves one 62 GB region for the engine (-SwitchVirtualAddressSpaceSize= in MB up to 4095, game_args below), and its FMallocBinned3
30# (38 GB of address space) is constructed in place in the bss; the constructor call is cut and the host runs Unreal's heap on a malloc zone (patches.py, hle_uemalloc.c layout UE5_6),
31# and the SDK's node area is cut to 62 MB. The engine hands the region out with a page allocator of its own (main+0x13ef0): a bump pointer, and freed blocks kept in free lists by size
32# class, so its address use only grows, and past the region's end OnOutOfMemory (main+0x13c74) aborts. Probed at main+0x13fcc from the save in the first field, through the first battle:
33# a 1 GB block at boot (a static constructor), the high-water mark at +1.50 GB 15 s in, +1.77 GB at 56 s, +2.02 GB at 166 s; a 2 GB region (DRAGON QUEST VII Reimagined's) aborted in that
34# battle. This SDK build aligns regions of 2 MB and more to 2 MB only (VammManager::AllocateAddressRegion, sdk+0x145e00), so the region starts right after the node area: a 4064 MB region
35# in Engage's 5 GB block (256 MB in front + 4.375 GB alias region + 256 MB stack region + 128 MB heap region), as DRAGON QUEST XI S's. On the Mac in the field and the first battle:
36# about 1 GB of the alias region mapped, an Unreal heap of 1 GB, 2.2-2.4 GB resident and 1.2-1.5 GB of Metal allocations
37game_args-SwitchVirtualAddressSpaceSize=4064
38mem_reserve0x140000000
39mem_alias0x118000000
40mem_stack0x10000000
41app_pool0xCD500000
42# the NPDM declares 20 MB of system resource
43sys_resource0x1400000
44# ---- Input ----
45# A 3D field whose camera the right stick tilts and turns: the 3D pad layout. It plays docked (1920x1080)
46pad_layoutfull
47# ---- NVN ----
48# 2,077 vertex shaders (Unreal's particle vertex factories) pick one of several c2 table slots at run time: texture table words 0x168-0x1c0 and sampler table words 0x568-0x590, and no other
49# word of c2. The translator cannot trace them to one slot: slot indices in c2, the bound slots in its arrays (without the key the first one aborted the host in a double free, now fixed)
50tex_dyn_slotson
51# ---- Shader split ----
52# The two shader libraries of the IoStore container FFRS-Switch.utoc / .ucas (no shader code archive in the pak): the engine's global shaders and the game's material shaders. Their tables and
53# shader groups are Oodle-compressed, which the game's own decoder undoes in the Mac host's tool mode (uepak.py Toc / io_archive / OodleHost, no boot). Unreal combines vertex and pixel
54# shaders per draw from its pipeline state, so every vertex shader is made to link with any pixel shader (shader_split.py separable_pairs)
55shader_groupsShaderArchive-Global-=global ShaderArchive-=game
56shader_noteFINAL FANTASY RESONANCE shaders