4.8 KiB
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 ---- | |||||
| 6 | title_id | 0100606026F12000 | ||||
| 7 | program_id | 0100606026F12000 | ||||
| 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) | |||||
| 10 | name | FINAL FANTASY RESONANCE | ||||
| 11 | ipa | FinalFantasyResonance.ipa | ||||
| 12 | app_category | public.app-category.games | ||||
| 13 | # ---- Versions ---- | |||||
| 14 | build | v65536 | 1.0.1 | main=84e182f72ee1da4f477804bd05b54c15 | subsdk0=ab62fe8edd07a6a293f885d54359e559 | sdk=0023a1b06130cd795f7bc4613772af0a |
| 15 | package | v65536 | ||||
| 16 | shader_versions | v65536 | ||||
| 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) | |||||
| 19 | modules | main subsdk0 sdk | ||||
| 20 | romfs_marker | FFRS/Content/Paks/FFRS-Switch.ucas | ||||
| 21 | zip_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 | |||||
| 27 | fps_target | 60 | ||||
| 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 | |||||
| 37 | game_args | -SwitchVirtualAddressSpaceSize=4064 | ||||
| 38 | mem_reserve | 0x140000000 | ||||
| 39 | mem_alias | 0x118000000 | ||||
| 40 | mem_stack | 0x10000000 | ||||
| 41 | app_pool | 0xCD500000 | ||||
| 42 | # the NPDM declares 20 MB of system resource | |||||
| 43 | sys_resource | 0x1400000 | ||||
| 44 | # ---- Input ---- | |||||
| 45 | # A 3D field whose camera the right stick tilts and turns: the 3D pad layout. It plays docked (1920x1080) | |||||
| 46 | pad_layout | full | ||||
| 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) | |||||
| 50 | tex_dyn_slots | on | ||||
| 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) | |||||
| 55 | shader_groups | ShaderArchive-Global-=global ShaderArchive-=game | ||||
| 56 | shader_note | FINAL FANTASY RESONANCE shaders |