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.0 KiB

1# DRAGON QUEST XI S: Echoes of an Elusive Age – Definitive Edition: Square Enix, Unreal Engine 4.18 (legacy version 4 paks, LZ5-compressed), SDK 7.3.2, NVN, Square Enix's own sound driver
2# Started from the NSP script's provisional profile (dm/games/profile_guess.py) and brought up on the Mac (docs/agents); plays on the Mac and on the iPhone
3# ---- Identity ----
4title_id01006C300E9F0000
5program_id01006C300E9F0000
6# ---- App ----
7nameDRAGON QUEST XI S: Echoes of an Elusive Age – Definitive Edition
8ipaDragonQuestXIS.ipa
9app_categorypublic.app-category.role-playing-games
10# ---- Versions ----
11buildv2621441.0.4main=1719aabfa5eae42b132b65770b871288subsdk0=93ff8252d975adf07230cb86c83301c5sdk=fcf93a41b08c5193a1410d262602dc62
12packagev262144
13shader_versionsv262144
14# ---- Files ----
15# subsdk0 is NintendoSDK_movie (main imports from it)
16modulesmain subsdk0 sdk
17romfs_markerJackGame/Content/Paks/pakchunk1-Switch.pak
18zip_store.pak:.webm:.metallib
19# ---- Graphics ----
20# 60 fps (30 on the Switch): the game's config caps Unreal at 30 (FrameRateLimit=30 in DefaultGameUserSettings.ini, which sets t.MaxFPS, and nvn.SyncInterval=2 in SwitchEngine.ini, the present
21# interval 2 it asks for); the host writes t.MaxFPS 60 and nvn.SyncInterval 1 into its console variables (hle_fpslock.c), so the game asks for present interval 1 itself. Unreal steps the game by
22# the time that really passed. DM_FPS_TARGET=30 (Documents/env.txt on the iPhone) keeps the game's 30 and saves power
23fps_target60
24# ---- Input ----
25# a 3D game: D-pad, right stick (camera) and L3 / R3 on the iPhone's virtual gamepad
26pad_layoutfull
27# ---- Memory ----
28# Unreal Engine 4.18: nninitStartup takes one address region for the whole engine (16 GB by default), which a NumberLineAllocator (main+0x177c4d0) hands out; the game's argument
29# -SwitchVirtualAddressSpaceSize= caps it, in MB up to 4095 (main+0x177c440: atoi, and a larger number is taken as bytes; 4224 gave a 4 KB region and a crash in the allocator's
30# Compaction at boot). Two cuts on the SDK 7.3.2 build (dm/tools/sdk_patches.py) put it 64 MB into the alias region: the node area 62 MB instead of 1 GB, and regions of 1 GB and more
31# 32 MB aligned instead of 1 GB. Engage's 5 GB block: 256 MB in front + 4.375 GB alias region + 256 MB stack region + 128 MB heap region (the game sets no heap)
32game_args-SwitchVirtualAddressSpaceSize=4064
33mem_reserve0x140000000
34mem_alias0x118000000
35mem_stack0x10000000
36app_pool0xCD500000
37# ---- Shader split ----
38# The engine's global shaders (Engine/GlobalShaderCache-GLSL_SWITCH.bin), the engine's own materials and the game's. Unreal Engine 4.18 keeps every shader inline in the cooked packages,
39# zlib-compressed, in paks whose blocks are LZ5-compressed; the NSP script decodes them on the Mac with the game's own LZ5 (uepak.py, shader_split.py ue_legacy_jobs, DM_OODLE_SERVE)
40shader_groupsGlobalShaderCache=global #Engine/=engine #JackGame/=game
41shader_noteDRAGON QUEST XI S shaders