
- Title ID
- 010051701FB46000
- Tested build
- 1.1.1
- Nintendo SDK
- 18.3.5
- Engine
- Unity 2022.3.54f1 IL2CPP
- Graphics API
- NVN
Build this game
Keep [010051701FB46000] in your file names, put the base game, update and DLC in one folder and run the script. Follow the build guide, then the sideloading guide. Needs an iPhone 15 Pro or newer, or an M1 iPad or later.
Technical notes
The project's own record of bringing this game up: what its profile needs and why, what was found and what is still open.
Update 1.1.1 (v131072) over the base game, SDK 18.3.5. Unity 2022.3.54f1 IL2CPP with FMOD on NVN. Modules main, subsdk0 (the movie module, whose movie::Extractor demuxes the intro) and sdk; the sdk is Super Mario Galaxy's build (010099C022B96000). Plays on the iPhone; 60 fps (30 on the Switch). On the Mac: the title, the 90 s intro movie with its sound, the tutorial battle (deployment, three waves, enemies on two floors), the merchant and the route map, at 60 fps with music and saves (the intro plays once per save); no red line, about 2.17 GB resident and 1.21 GB of Metal allocations, flat over twelve minutes.
What it needs
| Setting | Where | Why |
|---|---|---|
present_interval display |
game.tsv |
60 fps: the game asks for interval 2 and its animations follow the time that passed; see Frame rate |
pad_layout full |
game.tsv |
the 3D layout, whose right stick scrolls the route map as the game's prompt shows |
sys_resource 0x1000000 |
game.tsv |
the NPDM's 16 MB of system resource: virtual address memory |
5 GB guest layout: mem_reserve 0x140000000, mem_alias 0x118000000, mem_stack 0x10000000, app_pool 0x40000000 |
game.tsv |
Ace Attorney Investigations Collection's layout (010005501E68C000): with the hardware pool (3.2 GB) StandardAllocator's region alone reached +3.9 GB of the 4.38 GB alias region in nninitStartup; see Memory |
| Node area cut 1 GB → 62 MB and regions of 4 MB and more aligned to 2 MB, as SDK 20 | dm/tools/sdk_patches.py, the SDK-wide rules (MATCH_CUTS) on sdk build 60751516… (Super Mario Galaxy's and Galaxy 2's; the constructor at sdk+0x13be3c, the movs at +0x13be4c and +0x13bee0, the placement's constants at sdk+0x13c034 / +0x13c03c / +0x13c040) |
the 0.94 GB region sits at alias +0.06 GB either way; the build's row (the node area cut alone) was removed on 2026-10-30 after a smoke run with the rules |
svcGetInfo type 24 (FreeThreadCount) |
host, hle_svc.c / thr_limit_used (every game) |
Unity creates a thread only when the count is at least 1; see Threads |
| Movie audio decoder output slots | host, hle_movie.c (every game) |
the intro hung on a black screen; see Movies |
shader_groups /Data/=data |
game.tsv |
everything is under Data/: the player's serialized files (the post-processing compute shaders in sharedassets2.assets) and the StreamingAssets bundles |
Frame rate
- Current: 60 fps (30 on the Switch). The game asks for present interval 2 (Unity's 30 fps setting) and nothing else holds it at 30:
present_interval displaypresents a frame every display tick, and the iPhone's display link runs at 60 Hz. The GPU takes about 2 ms a frame in battle and on the route map (M4 Pro). - Its animations follow the time that passed (Unity's
deltaTime; the PC versions run at any refresh rate). From one save, screenshots every third of a second through the move to the merchant (its fade-in, the greeting) match at 30 and 60 fps: mean difference 3.9, against 11.0 (up to 89 in the fade) for what frame counting would show. DM_PRESENT_INTERVAL=game(Documents/env.txton the iPhone) keeps 30 and saves power.- Resolved:
[RED] fs ReadFile into … failed at +0 (EFAULT): VM region … protection 1, now and then at 60 fps (two runs in three as the route map loads, never at 30 fps). The destination was texture pool memory, which the dirty-page tracker write-protects after each upload (nvn_dirty.c);ReadFilelifts the protection first, but the graphics layer can protect the pages again beforepreadwrites them, and at 60 fps uploads come twice as often. On EFAULT the host now prepares the rest of the buffer again and reads on, up to eight times (h_fs_ReadFile; the first case is logged,[fs] ReadFile … prepared again). Four runs at 60 fps: one retry, no failed read.
Memory
- The NPDM declares 16 MB of system resource, so
IsVirtualAddressMemoryEnabledis true:nninitStartuphands application pool − used memory to StandardAllocator as virtual address memory and never callsSetMemoryHeapSize(no heap), as in Ace Attorney Investigations Collection, Brain Memory Training Academy and Patrick's Parabox. The node-area cut was already on thissdkbuild. - With the hardware pool (3.2 GB), StandardAllocator's region alone took the alias region to +3.9 GB of 4.38 GB in
nninitStartup; hence their 1 GB pool and 5 GB block (256 MB in front + 4.375 GB alias region + 256 MB stack region + 128 MB heap region). - Measured on the Mac: the alias region is mapped up to +3.25 GB within 90 s and stays there for 12 minutes (+3.5 GB in a run to the first shop), at most 1.75 GB of it in use. The host does not hold the game to the pool, as for Ace Attorney.
Threads
- Resolved: the main thread waited forever on an event right after
nnMainstarted, with only three or four threads created.main+0x3e7288starts a thread and waits for it to signalmain+0x539cf80. Unity's thread start (main+0x3e1a50) creates a thread only whennn::os::GetFreeThreadCount()is at least 1, and that issvcGetInfotype 24 (FreeThreadCount, Horizon 11 and later), which the host answered 0 like every type it did not know: the thread was never asked for (DM_THR=1showed noCreateThreadfor it). The host now answers 96 less the game's threads that have not exited (thr_limit_used). Of the 20 games extracted on that machine, only thismainimports the function. With it the game creates 40 threads and reaches its title.
Movies
- The intro is
StreamingAssets/intro_fmv.mp4, 90 s of H.264 High with 2 reorder frames and AAC interleaved packet by packet, played by Unity 2022.3's movie player:movie::Extractorinsubsdk0feeds both decoders from one thread in file order. The game's A, B and + do not skip it. - Resolved: the movie stayed black after its first picture, the sound never started, and the game kept presenting frames. The player takes every output a decoder offers and starts playing only once it holds about half a second of audio. The host then gave each decoder 8 output slots and takes input only while one is free (as MediaCodec does).
DM_MOVIE_TRACE=1(each line names the decoder): Unity held all 8 audio outputs, the audio decoder kept the next 4 packets and handed out no input index, the video packets behind them in the file never came, and the video decoder had given out one picture (the host releases H.264 pictures once more than 4 are queued). Slot counts per decoder kind, measured: 8 audio / 8 video and 8 audio / 32 video hang; 64 audio / 8 video plays, starting with 27 audio and 8 video outputs held (peak 30 audio). Audio decoders then got 64 slots (they had 8 when the game was brought up, 32 since DRAGON QUEST XI S). - Current: an AAC decoder has 32 output slots (
MD_NOUT_AAC, set for Mario vs. Donkey Kong (0100B99019412000), with this game's peak of 30 held as the reason it is enough), Vorbis 64 (MD_NOUT), video 16 (MD_NOUT_VIDEO). A PCM slot is 128 KB, allocated when first used.
Services
nvnSyncSetDebugLabel(a no-op).
Input
- Controller only: the game reads no touch, docked or handheld (taps on the title and on route map nodes in handheld mode did nothing). It stays docked at 1920x1080 with the 3D pad layout, whose right stick scrolls the route map. A selects and plays cards, B goes back, Y ends the turn.
Files and shaders
- 15,937 shaders: 15,841 vertex, pixel and geometry shaders in the player's serialized files and bundles, the player's 11 GLSLC outputs in
main(one of them compute), and 85 kernels of the post-processing stack'sComputeShaderobjects inData/sharedassets2.assets. TheShaderobjects use the Unity 2022.3 layout already inunityfs.py. The built-in VR blit's geometry shader does not build. - Resolved: the 3D battle scene was black behind a correct UI, with
[RED] shader 854a8afc9d07f88d is not in the shader mapandthe dispatched program has no compute shader.DM_NVN_SHDUMPsaved the program; its code bytes were inData/sharedassets2.assets, uncompressed, inside aComputeShader(class 72): the post-processing stack's colour grading LUT baker (Lut3DBaker#KGenLut3D_AcesTonemap), so the LUT the scene is graded through was never baked and stayed black. The split read onlyShaderobjects. AComputeShaderholds per platform variant a list of kernels, each with its unique variants; a variant'scodeis the program code of aShadersubprogram (the 0x60-byte stage header, only the compute block present) and itsthreadGroupSizematches control +0x748.unity_computeinshader_split.pyreads them beside theShaderobjects of every serialized file. No file carries a class 72 type tree, sounityfs.pycarries Unity 2022.3.54f1's layout (COMPUTE_2022_3inKNOWN_TREES, written from AssetRipper's TypeTreeDumps for that version): all 12 objects decode,resourcesResolvedtrue at each end. 85 compute shaders came in (86 with the player's own).
Saves
- The intro plays once per save. A save past the intro starts at the title, and A there continues the run.
Mac routes
- From a fresh save,
DM_KEYS="14:A"starts the game; the intro movie plays to its end and the tutorial battle loads at about frame 3,400. DM_KEYS="14:A,110:A*90/2,111:Y*20/9"plays through the tutorial battle to the merchant by about frame 8,000.
Found on this game
General host changes first needed here; each applies to every game:
svcGetInfotype 24, FreeThreadCount (thr_limit_used): Free thread count (svcGetInfotype 24).- Movie decoder output slots per decoder kind (
MD_NOUT,MD_NOUT_AAC,MD_NOUT_VIDEO): Output slot counts per decoder kind, Audio output slots for players that hold every output. nvnSyncSetDebugLabelas a no-op (no other source describes it).ReadFilere-prepared on EFAULT against the dirty-page tracker (h_fs_ReadFile): ReadFile into write-protected texture pool pages.- Unity
ComputeShaderobjects (unity_compute,COMPUTE_2022_3): Unity ComputeShader objects. present_interval displayfor a game that steps by frame time: dm/games/README.md, Keys.- The spin-wait search takes the movie library's thread loop wider in this game's
subsdk0: development.md, Power.
Open
- docs/development.md says audio decoders have 64 output slots and the 03 entry says video keeps 8; the host now has 32 for AAC (
MD_NOUT_AAC) and 16 for video (MD_NOUT_VIDEO). No source says the intro was played again after those changes. - The built-in VR blit's geometry shader does not build.
These notes are republished from the nxnative repository under its MIT license (license and attribution). The original, which may be newer, is the game's notes on GitHub. This site hosts no game files.