Apply Pokémon Legends: Z-A's allocator cut to other builds by function match (#266)
The base game 1.0.0 (main 7222e13e…) aborted in nninitStartup: the 12 GB → 4 GB StandardAllocator cut was registered for 2.0.2's main only. The same function (an exact fingerprint match, main+0x19f8480 in v0) now gets it through MATCH_CUTS.
This commit is contained in:
1 parent
58f74014f4
commit
ceb5046b3f
2 files changed
+11
-1
No files matched your search
@@ -6,7 +6,7 @@ Update 2.0.2 (v393216) over the base game, SDK 19.3.11 (NVN 55). Game Freak's Tr
|
||||
|
||||
| Setting | Where | Why |
|
||||
|---|---|---|
|
||||
| Allocator address space 12 GB → 4 GB | [`patches.py`](patches.py), `main` `b1f12fd9…` at `main+0x1b3e3e4` | `StandardAllocator::Initialize(nullptr, 0x300000000)` does not fit a phone; see [Memory](#memory) |
|
||||
| Allocator address space 12 GB → 4 GB | [`patches.py`](patches.py), `main` `b1f12fd9…` at `main+0x1b3e3e4`; other builds through `MATCH_CUTS` (the base game's `7222e13e…` at `main+0x19f84b4`) | `StandardAllocator::Initialize(nullptr, 0x300000000)` does not fit a phone; see [Memory](#memory) |
|
||||
| Node area cut 1 GB → 62 MB | `dm/tools/sdk_patches.py`, `sdk` build `df7a3960…` (`sdk+0x1423fc` / `+0x142468`) | the alias region must hold the node area and the allocator's region |
|
||||
| 5 GB guest layout: `mem_reserve 0x140000000`, `mem_alias 0x110000000`, `mem_stack 0x10000000`, `app_pool 0xCD500000` | [`game.tsv`](game.tsv) | the 4.25 GB alias region holds 62 MB + 4 GB (SDK 19 puts the region 4 MB aligned right after the node area); the 5 GB block Tears of the Kingdom runs in |
|
||||
| `mem_map_limit on` | `game.tsv` | the SDK keeps the pages of `nninitStartup`'s probe mapped until a map fails; the pool is enforced as on Horizon, so it gives them back |
|
||||
@@ -19,6 +19,7 @@ Update 2.0.2 (v393216) over the base game, SDK 19.3.11 (NVN 55). Game Freak's Tr
|
||||
|
||||
- With virtual address memory (a 16 MB system resource), `nninitStartup` (`main+0x1b2e650`) initializes its StandardAllocator over 12 GB of address space, `StandardAllocator::Initialize(nullptr, 0x300000000)` (`main+0x1b3e3ec`), as the Switch's 64 GB alias region allows.
|
||||
- **Resolved: `StandardAllocator::Initialize` aborted in `nninitStartup`** (`main+0x1b2e690`). The alias region had to hold the SDK's 1 GB node area and that region, 13 GB, more than a phone gives a process (one 6 GB reservation). The two cuts above make it fit the 5 GB block: 4 GB of address space for the allocator (the pool, 3.2 GB, bounds what it maps; its largest block is `nninitStartup`'s own probe of pool − used, 3.15 GB, allocated and freed at once) and Engage's node area cut. SDK 19's AddressRegionManager puts the region right after the node area (+0x3fe2c000 before the cut), not 1 GB aligned as Engage's SDK did, so a 4.25 GB alias region holds both. `QueryMemoryInfo` reporting more than 4 GB would take the game's big-memory path (heaps of allocatable − 4.27 GB instead of − 2.76 GB).
|
||||
- **Resolved: the base game 1.0.0 (v0) aborted in `nninitStartup`** (GitHub issue #266; `nn::diag` abort at `sdk+0x134214`, called from `main+0x19e8760`, the v0 place of `main+0x1b2e690`). The NSP script packs a folder holding only the base game from a derived profile, and the allocator cut was registered for 2.0.2's `main` only. v0's `main` (`7222e13e…`) makes the same call at `main+0x19f84b4` in a function (`main+0x19f8480`) that `nso_fnmap.py` matches exactly to 2.0.2's `main+0x1b3e3b0`, with the same `nso_match.py` fingerprint; its `sdk` is 2.0.2's (`df7a3960…`), so the node area cut and the 5 GB layout apply to it unchanged. The cut is now in `MATCH_CUTS` too ([Function-matched cuts](../../../docs/reference/rewriter.md#function-matched-cuts-for-unregistered-builds)), so v0 and any later build with that function get it (`[function match]` in `main.cuts.tsv`). Measured on the Mac (M4 Pro, v0's own RomFS, the 2.0.2 shader libraries, headless, no input): without the cut the abort; with it `nnMain`, the startup map refused once at a full pool as on 2.0.2, then 90 s to frame 2418 at 30 fps, with no crash and no shader key missing from the map. The reporter's v0 run reached Lumiose City at 30 fps on an M1. v0 is not a `build` row: the shader tables are 2.0.2's, so v0 is packed from a derived profile with its own shaders either way. **Open:** v0 has not been played with input on this Mac, packed through the NSP script, or tested on an iPhone.
|
||||
- **Resolved: the alias region's mapped total ran past the application pool in the first minute.** `nninitStartup` allocates and frees everything allocatable (pool − used, 3.15 GB, mapped at the top of the region) and the SDK keeps the freed pages mapped; later allocations map new pages at the bottom until a map fails, and only then does it unmap the cached block and retry. The host never refused a map, so the block stayed mapped beside the 0.4 GB the game used. **Current:** with `mem_map_limit` (`hle_svc.c`) a map past the pool fails with ResultLimitReached, and the used memory `GetInfo` reports counts the mapped pages, as on Horizon (without that, the startup probe itself, sized as total − used, was refused). Measured: one refused 4 MB map, the 3.15 GB unmap, the same map again.
|
||||
- **Current:** a memory pool created while the game maps and unmaps its 4 GB region was sometimes refused once by `newBufferWithBytesNoCopy`, then accepted. `mtl_pool_add` retries up to 12 times with a short back-off and prints `[RED] memory pool … created at retry N` (one of the red lines on the Mac route); on a final failure it logs the VM regions around the pool.
|
||||
|
||||
|
||||
@@ -8,3 +8,12 @@ CUTS = {
|
||||
(0x1b3e3e4, '6200c0d2', '2200c0d2', 'StandardAllocator::Initialize(nullptr, size): address space mov x2,#0x300000000 → mov x2,#0x100000000 (12 GB → 4 GB)'),
|
||||
],
|
||||
}
|
||||
# The same cut for builds without registered CUTS (dm/tools/nso_match.py), found by the fingerprint of the function that makes the call (132 bytes, the mov at +52) and its direct
|
||||
# callees' (the allocator option getter it calls first, StandardAllocator::Initialize). The base game 1.0.0 (v0, main 7222e13e…, GitHub issue #266) has it at main+0x19f84b4
|
||||
# (function main+0x19f8480: an exact nso_fnmap.py match of 2.0.2's main+0x1b3e3b0, the same fingerprint) and ships 2.0.2's sdk (df7a3960…), so the node area cut and the
|
||||
# 5 GB layout hold for it unchanged
|
||||
allocator = 'StandardAllocator::Initialize(nullptr, size): address space 12 GB → 4 GB'
|
||||
MATCH_CUTS = {'main': [
|
||||
{'name': allocator, 'size': 132, 'fingerprints': ['af8eeda3d34bbfbfee1896ee0469ada1804c957695f3c7f2b8a970a20f495879'],
|
||||
'cuts': [(52, '6200c0d2', '2200c0d2', allocator + ': mov x2,#0x300000000 → mov x2,#0x100000000 (as 2.0.2 main+0x1b3e3e4)')]},
|
||||
]}
|
||||
Reference in new issue
Block a user