Files
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

3.7 KiB

1# DRAGON QUEST VII Reimagined: Square Enix / HEXA DRIVE, Unreal Engine 4.27 (IoStore containers beside one pak, PhysX 3.4, MallocBinned3), SDK 19.3.1, NVN, CRIWARE sound and Sofdec movies
2# (VP9 through the SDK's movie decoder); update 1.2.0 (v131072).
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_id0100A9D01C446000
7program_id0100A9D01C446000
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)
10nameDRAGON QUEST VII Reimagined
11ipaDragonQuestViiReimagined.ipa
12app_categorypublic.app-category.games
13# ---- Versions ----
14buildv1310721.2.0main=f7ec03e4cb9de3bd8319d4e899d2e9ccsubsdk0=92ef43cb1f9917ab206ac5c9e36240bcsdk=145dde94fb574acc9e09780a11995bd3
15packagev131072
16shader_versionsv131072
17# ---- Files ----
18# load order as on Horizon: main, subsdk*, sdk (subsdk0 = NintendoSDK_movie, which Sofdec feeds its VP9 video to)
19modulesmain subsdk0 sdk
20romfs_markerDOLL/Content/Paks/pakchunk0-Switch.ucas
21zip_store.pak:.ttf:.ucas:.usm:.utoc:.metallib
22# ---- Graphics ----
23# 60 fps (30 on the Switch): the game's config caps Unreal at 30 (FrameRateLimit=30 in DefaultGameUserSettings.ini and SwitchGameUserSettings.ini, which UEngine::SetMaxFPS, main+0x134d2c0, puts
24# in t.MaxFPS; rhi.syncinterval=2 in SwitchDeviceProfiles.ini, the present interval 2 it asks for while BaseSwitchEngine.ini's r.VSync=1 locks presents to vsync); the host writes t.MaxFPS 60 and
25# rhi.SyncInterval 1 into its console variables (hle_fpslock.c), so the game asks for present interval 1 itself. Unreal steps the game by the time that really passed.
26# 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 4.27: nninitStartup (main+0xe89fa4) needs virtual address memory, sets a 6 MB heap for the C library's malloc and reserves one address region for the engine
30# (-SwitchVirtualAddressSpaceSize= in MB, game_args below; 62 GB by default). Its allocator, an FMallocBinned3 made on the first allocation, cuts 37 GB of pools out of that region; the
31# constructor call is cut and the host runs Unreal's heap on a malloc zone outside the guest block (patches.py, hle_uemalloc.c), and the SDK's node area is cut to 62 MB, as for
32# Octopath Traveler 0 on the same SDK. The region then holds what the engine maps itself: on the Mac up to +0.75 GB of the alias region with 0.5 GB mapped through the opening and
33# the new-game menus, beside an Unreal heap of 1 GB and 0.9 GB of Metal allocations (about 2.3 GB resident). Alias region = node area + up to 1 GB of alignment (regions of 1 GB and
34# more are 1 GB aligned) + the 2 GB region; 256 MB stacks, 384 MB heap region
35game_args-SwitchVirtualAddressSpaceSize=2048
36mem_reserve0xF0000000
37mem_alias0xC8000000
38mem_stack0x10000000
39app_pool0xCD500000
40# the NPDM declares 80 MB of system resource
41sys_resource0x5000000
42# ---- Input ----
43# A 3D game with a free camera on the right stick: the 3D pad layout. It reads the controller only, so it stays docked (1920x1080)
44pad_layoutfull
45# ---- Shader split ----
46# The shader code archives of pakchunk0-Switch.pak (ShaderArchive-*.ushaderbytecode), each shader LZ4-compressed (uepak.py lz4_shaders): the engine's global shaders and the game's
47# material shaders. Unreal combines vertex and pixel shaders per draw from its pipeline state, so every vertex shader is made to link with any pixel shader (shader_split.py separable_pairs)
48shader_groupsShaderArchive-Global-=global ShaderArchive-=game
49shader_noteDRAGON QUEST VII Reimagined shaders