diff --git a/dm/games/010015100B514000/README.md b/dm/games/010015100B514000/README.md index c535225..560cb18 100644 --- a/dm/games/010015100B514000/README.md +++ b/dm/games/010015100B514000/README.md @@ -1,12 +1,12 @@ # Super Mario Bros. Wonder (`010015100B514000`) -Base game v0 (1.0.0, SDK 16.2.0) and update 1.2.1 (v327680, a new `main` build on SDK 16.2.12); the profile carries both builds and packs 1.2.1 by default. Nintendo EPD's engine (sead, agl), on NVN 55 (it requires 55.x with minor ≥ 15). Modules `main` and `sdk`. The first game of this repository, after Diablo II: Resurrected in d2r-mobile: much of the host was brought up on it. Plays on the iPhone. The README lists its IPA at about 4 GB. +Base game v0 (1.0.0, SDK 16.2.0), update 1.0.1 (v65536, SDK 16.2.0; short Mac crash regression only) and update 1.2.1 (v327680, a new `main` build on SDK 16.2.12); the profile records these builds and packs 1.2.1 by default. Nintendo EPD's engine (sead, agl), on NVN 55 (it requires 55.x with minor ≥ 15). Modules `main` and `sdk`. The first game of this repository, after Diablo II: Resurrected in d2r-mobile: much of the host was brought up on it. Plays on the iPhone. The README lists its IPA at about 4 GB. ## What it needs | Setting | Where | Why | |---|---|---| -| Resource heap +16 KB | [`patches.py`](patches.py) `CUTS`, v0 `main` `cd6e42ae…` at `main+0x1e62fc`, 1.2.1 `main` `ff773e90…` at `main+0x1cf9b0` | a resource heap came up about 0x70 bytes short; see [Memory](#memory) | +| Resource heap +16 KB | [`patches.py`](patches.py) `CUTS`, v0 `main` `cd6e42ae…` at `main+0x1e62fc`, 1.0.1 `main` `f91868b8…` at `main+0x1f6890`, 1.2.1 `main` `ff773e90…` at `main+0x1cf9b0` | a resource heap came up about 0x70 bytes short; see [Memory](#memory) | | 5 GB guest layout: `mem_reserve 0x140000000`, `mem_alias 0xB8000000`, `mem_stack 0x10000000`, `app_pool 0xCD500000` | [`game.tsv`](game.tsv) | 256 MB in front + 2.875 GB alias region + 256 MB stack region + 1.625 GB heap region: the game maps 1.75 GB of virtual address memory on demand into the alias region and asks for a 1.47 GB heap | | `shader_versions v0 v327680` | `game.tsv` | the shader tables are the union of both versions, so packing either needs both NSPs | @@ -14,13 +14,15 @@ No `dm/tools/sdk_patches.py` cut for its `sdk` builds (`3053b229…` v0, `e4bd58 ## Versions -- v0 (1.0.0) and 1.2.1 (v327680). With the update layered over v0, unchanged files become APFS clones, so the merged RomFS adds only about 114 MB to the 3.5 GB base. +- v0 (1.0.0), 1.0.1 (v65536) and 1.2.1 (v327680). With 1.2.1 layered over v0, unchanged files become APFS clones, so the merged RomFS adds only about 114 MB to the 3.5 GB base. - 1.2.1 is a new `main` build (SDK 16.2.12). Its resource-heap cut was carried over from v0 with `dm/tools/nso_fnmap.py` (containing function `0x1e603c` → `0x1cf6f0`, identical after address masking; `ExpHeap::create` `0x4aac38` → `0x4c4a18`). - 1.2.1 imports 28 SDK functions v0 did not, which the host answers: `nn::nfp` (amiibo, initialized at boot) finds none, `pl::IsRunningOnOunce` (is this a Switch 2) is false, `ec::ShowShopApplicationInformationForUpgrade` is a no-op, `account::PopOpenUsers` returns none and `aoc::CountAddOnContent` none. Mario only reads the count from `PopOpenUsers` and falls back to `TryOpenPreselectedUser` on 0, and counts add-on content only on a Switch 2 (`hle_sdk16.c`, `hle_account.c`, `hle_misc.c`). - 1.2.1 compresses the NACP's title area (a u16 size, then raw deflate inflating to 32 entries of 0x300 bytes), which LibHac 0.19 does not decode; `nx_extract` and the NSP script do. Its patch NCA (key generation 17) makes hactool stop with `Invalid BKTR layout!`, which is why `nx_extract` uses LibHac. ## Memory +- **Resolved for the tested 1.0.1 startup path: null memory pool after resource allocation.** The unpatched build (`main` `f91868b88f60d3d59009db3389fde314`, `sdk` `3053b22935e32ddf15ef81997603e5c2`) logged `BufferInitialize: pool has no storage (pool 0x0 ... size 0x280)` and crashed with `sig=11 addr=0x4 pc=h_nvnMemoryPoolGetFlags+0`. Its heap-size setup function is the unique full 1,420-byte address-masked match of v0's `0x1e603c`, at `0x1f65d0`; both calls of v0's `ExpHeap::create` (`0x4aac38`) map to `0x48b134`, whose full masked function also matches. The existing +16 KB cut therefore maps from `0x1e62fc` to `0x1f6890`, with the same asserted original word. On an Apple M5 Pro Mac, isolated saves and module copies reproduced the unpatched crash after 10.99 s (last reported frame 471); changing only this word ran for 35.74 s (last reported frame 1827), with no null-pool diagnostic or crash, before controlled termination. These are short headless correctness runs, not full gameplay, save, iPhone or performance acceptance. When only v0 and 1.0.1 are supplied, the script still derives this version's own shader tables because the checked-in union also needs 1.2.1. + - The game reserves "virtual address memory" (1.75 GB in `System/HeapSize/*.HeapDef.byml`) and maps it into the alias region with `MapPhysicalMemory` on demand. With the alias region left after the node area too small, large resources were silently skipped and a null deref followed where they were used, also visible as `SetHeapSize` asking for much less than the pool. The 5 GB layout above fixed it. - Its two modules are about 74 MB, and its heap request matches hardware with the host's 64 MB of "used" memory. - **Current: every resource heap gets +16 KB.** Each resource gets its own `sead::ExpHeap` sized resource-size-table value + 0x1008 (`main+0x1e603c` → `ExpHeap::create` `main+0x4aac38`, v0). The table values are Nintendo's measured peaks with almost no margin (Yoshi's animation file `PlayerYoshiAnm` uses 99% of its budget). `Model/NpcCommonerA.bfres` in the opening course (Course900) came up about 0x70 bytes short: its last GPU chunk (MatBlock, 0x9000 bytes, 4 KB aligned, `main+0x4290c0`) fit, but the chunk's 0x598-byte descriptor did not; a buffer was then built on a null memory pool and the game crashed on a null read at `main+0x106f5c8`. The cut makes `mov x0,x23` → `add x0,x23,#0x4000` (the `ExpHeap::create` size argument). diff --git a/dm/games/010015100B514000/game.tsv b/dm/games/010015100B514000/game.tsv index fd229a7..ba038d3 100644 --- a/dm/games/010015100B514000/game.tsv +++ b/dm/games/010015100B514000/game.tsv @@ -16,6 +16,7 @@ app_category public.app-category.action-games # ---- Versions ---- # build =...: the NSP script accepts only these builds (fixed addresses do not hold on other builds); the host reports the display version by main's build ID build v0 1.0.0 main=cd6e42aee7934f4d8393cd43893ae25e sdk=3053b22935e32ddf15ef81997603e5c2 +build v65536 1.0.1 main=f91868b88f60d3d59009db3389fde314 sdk=3053b22935e32ddf15ef81997603e5c2 build v327680 1.2.1 main=ff773e90972d544eb79406eaa65396d5 sdk=e4bd58cac28cf13a08fb417aa013cdcb # version packed into the IPA by default package v327680 diff --git a/dm/games/010015100B514000/patches.py b/dm/games/010015100B514000/patches.py index 150d619..4900482 100644 --- a/dm/games/010015100B514000/patches.py +++ b/dm/games/010015100B514000/patches.py @@ -9,6 +9,13 @@ CUTS = { # Where this differs from hardware is not known (every allocation size before this block is determined by game code and data); for now every resource heap gets +16 KB. (0x1e62fc, 'e00317aa', 'e0124091', 'resource heap size: mov x0,x23 → add x0,x23,#0x4000 (ExpHeap::create size argument +16 KB)'), ], + # Super Mario Bros. Wonder 1.0.1 (v65536), main f91868b8...: resource heap slack as above. + # Ported from v0 by the unique address-masked match of the complete 1,420-byte function + # 0x1e603c -> 0x1f65d0; both ExpHeap::create call sites also map to the same callee + # (0x4aac38 -> 0x48b134). The original instruction is asserted by the rewriter. + 'f91868b88f60d3d59009db3389fde314': [ + (0x1f6890, 'e00317aa', 'e0124091', 'resource heap size: mov x0,x23 -> add x0,x23,#0x4000 (ExpHeap::create size argument +16 KB)'), + ], # Super Mario Bros. Wonder 1.2.1 (v327680) main: same as above. Location carried over from v0 by dm/tools/nso_fnmap.py (containing function 0x1e603c → 0x1cf6f0 identical after address masking, ExpHeap::create 0x4aac38 → 0x4c4a18) 'ff773e90972d544eb79406eaa65396d5': [ (0x1cf9b0, 'e00317aa', 'e0124091', 'resource heap size: mov x0,x23 → add x0,x23,#0x4000 (ExpHeap::create size argument +16 KB)'),