Absolum (0100A83022A22000)
Update 1.1.1 (v393216) over the base game (v0), SDK 18.3.2. FNA (XNA 4 reimplemented in C#) compiled with .NET NativeAOT (NativeAOT-NX; its own GC, regions enabled), SDL3, FNA3D's NVN driver (FNA3D_Driver_NVN.cpp), Wwise. Modules main, subsdk2 (the movie module, for FNA3D's video player: H.264 logos) and sdk; NVIDIA's Vulkan and OpenGL drivers (subsdk0, subsdk1) are not loaded. Epic Online Services comes as an NRO the host does not load; the game plays offline without it. Playable on an iPhone.
Status: brought up on the Mac: the logo movie, the licence agreement, the main menu, the campfire character select, the intro and the first level (the "Strike / Skill" tutorial and the cave after it), at 60 fps with real sound and saves; about 2.5 GB resident.
What it needs
| Setting | Where | Why |
|---|---|---|
malloc region cut 40 GB → 2.5 GB: main+0x28bff4 mov x0,#0xa00000000 → mov x0,#0xa0000000 |
patches.py, main 916f5b8d… |
malloc's StandardAllocator takes 40 GB of address space; 2.19 GB is used into the first level; see Memory |
game_env DOTNET_GCRegionRange=60000000 |
game.tsv, hle_os.c |
the .NET GC's region range 1.5 GB instead of 5 × its hard limit (3.75 GB) |
Node area cut 1 GB → 62 MB (sdk+0x13be4c / +0x13bee0) and 32 MB alignment for regions of 1 GB and more (sdk+0x13c03c) |
dm/tools/sdk_patches.py, sdk build f118ae1c… |
the 1 GB alignment lost up to 1 GB before each of the two large regions |
Engage's 5 GB block: mem_reserve 0x140000000, mem_alias 0x118000000, mem_stack 0x10000000, app_pool 0xCD500000 |
game.tsv |
256 MB in front + 4.375 GB alias region + 256 MB stack region + 128 MB heap region (never used) |
No pad_layout key: the iPhone gamepad starts in the 2D layout (README).
Memory
- The NPDM declares 16 MB of system resource (virtual address memory), and
mainnever callsSetMemoryHeapSize: everything lives in address regions of the alias region.profile_guess.pygives every game with an NPDM system resource the 5 GB block, and this game came out right with it (Unity 6 takes its memory with no StandardAllocator and no heap). - Resolved:
nn::diagabort atsdk+0x12dad0innninitStartup, called frommain+0x756310. That is malloc'sStandardAllocator::Initialize(nullptr, 0xa00000000): 40 GB of address space (main+0x28bff4;nninitStartupis atmain+0x1b54d0, the call goes throughmain+0x7562d0). - How the needs were measured: one boot on the Mac with a 64 GB alias region (
mem_reserve 0x1030000000,mem_alias 0x1008000000), probingVammManager::AllocateAddressRegion's success path (sdk+0x13bf8c: x21 size, x22 address) withDM_SVC=1's map log. The regions, from boot into the first level:- malloc's: 2.19 GB used, 1.75 GB of it FNA3D's GPU heap, allocated whole at
FNA3D_CreateDevice(main+0xc03660→main+0x563370); its blocks reach 332 MB from the region's start and 1.82 GB from its end, and no more after the title. The cut gives it 2.5 GB, 300 MB to spare. - the .NET GC's region range: 5 × its hard limit (768 MB = 75% of the 1 GB its
GetPhysicalMemoryLimit,main+0x28bffc, reports), 3.75 GB. The GC readsDOTNET_GCRegionRangethroughgetenvfirst; the host answersgetenvfrom the profile keygame_env(hle_os.c; every other name goes to the SDK's owngetenv, an empty environment), which sets 1.5 GB. The GC then uses its range from both ends, 756 MB from the start and 748 MB from the end (718 MB mapped into the first level), where it used only the first 1.14 GB of 3.75. - a few small regions (bookkeeping, thread-local blocks), under 5 MB.
- malloc's: 2.19 GB used, 1.75 GB of it FNA3D's GPU heap, allocated whole at
- Resolved: the regions did not fit even then. SDK 18's
AllocateAddressRegion(sdk+0x13bfd0) aligns a region by its size: 64 KB under 2 MB, 2 MB under 4 MB, 4 MB under 32 MB, 32 MB under 1 GB, else 1 GB in absolute address (+0x13c03c), and places it first-fit after the regions already there. The two large regions, with a 4 KB one between them, lost up to 1 GB each to alignment, depending on wheremmapput the guest block (measured with a 64 GB alias region: 0.6 GB before malloc's at that run's alias base, 1 GB before the GC's). A cut on that build aligns them to 32 MB as well (what the SDK gives regions from 32 MB up; nothing in the SDK or the game reads the region's alignment), beside the node-area cut. Thesdk's AddressRegionManager is at the offsets of Super Mario Galaxy's SDK 18.3.5 build. - Current: the regions end 4.13 GB into the 4.375 GB alias region of Engage's 5 GB block. The mapped total peaks at 2.9 GB, under the hardware pool.
Rendering
The effects (.xnb) are XNA's D3D9 effects (MOJOSHADER is linked in and parses them for the parameters). Every binding decodes with the usual layout.
- Resolved: the whole picture upside down (the title logo and "Press Any Button" mirrored top to bottom). The game keeps NVN's lower-left window origin (handled as for Link's Awakening, 01006BB00C6F0000) and, twice a frame, sets viewport 0's swizzle with
nvnCommandBufferSetViewportSwizzlesto (x, −y, z, w), which negates clip-space y: how a renderer with OpenGL heritage flips its picture. The host had it as a red-reporting stub. It is recorded now (OP_VP_SWIZZLE) and applied at the draw as a viewport flipped about its centre, the same mapping. Facing is decided after the swizzle on the GPU as in Metal, so the winding stays. Other swizzles (axis exchanges, negated x / z / w) give a red line and are drawn unswizzled. - Resolved: the logo movie as a strip of small grey copies at the top of the screen (FNA3D's
nx_video_player.cpp: type 1, output 3, mode 2). The texture held NV12 bytes: in RGBA8, 405 rows of 1920 pixels are exactly a 1920×1080 NV12 frame, rows 0–270 the luma at video black (16) and rows 270–405 the chroma (128). This game's MP4 demuxer hands the parameter sets toConfigure(csd-0/csd-1), which made the H.264 decoder there without switching it to RGBA, and the first packet then found it made. Both paths now go throughmd_avc_open(hle_movie.c).
Files and shaders
- The shaders the GPU runs are 163 GLSLC outputs in
rom:/shaders.nx.bin(a u32 count, then per entry a u32 hash, a u32 size and one whole output), whichshader_split.pyreads as a loose file no other reader takes: 162 unique shaders, 83 pixel and 79 vertex, every vertex shader paired with the single-stage cover. Groupsfnaanddata(shader_groups). romfs_marker:data/textures.
Code
- Resolved:
RuntimeError: 788 ldr x18, #0xd1eb0inpatch_nso.py. The text segment starts with 1.7 MB of data (main+0x0–+0x1b5000, high-entropy, no FDE covers it, and noadrpor relocation points into it): 62% of its words do not decode, and 6,858 of the rest read as instructions that usex18, plus three "svc" words with numbers such as#0x91e7. The linear sweep rewrote them all.dm/tools/nso_code.pyfinds such data blocks (a stretch of at least 4 KB between the.eh_frameFDE ranges in which more than a quarter of the words do not decode); the sweep skips them (DATA_BLOCKS, logged asdata blocks left alone), and so doesinsn_census.py, whose counts then match the rewriter's again (11,744x18sites in thismain). Code without unwind information is still swept: it decodes (zlib atmain+0x75261c, libunwind's register restore atmain+0x28dbd4). - Padding halfword jump tables only to their largest entry (
half_count) changed one to six tables in thismain, as in a few other games' (Halfword jump table landing pads sized to the largest entry).
Services
- Resolved: SIGSEGV in
vi::CreateLayer(Layer**, Display*, int, int)(sdk+0x3f9bc4, from SDL3's Switch video driver atmain+0x239304): the overload with the layer's size; the host had only the two-argument one. It returns the static layer (hle_vi.c). The survey's import table had listed every vi call as unhooked:nso_syms.py host_hooksread onlydm/host, and the vi hooks are indm/gfx(it readsdm/gfxanddm/gfx/nvnnow). - AudioIn (SDL3's audio driver lists the input devices when its audio starts): the host has no microphone.
ListAudioInsreports none, both opens fail, and the calls that need an open AudioIn answer without touching the game's object (hle_audio.c). - Epic Online Services in an NRO (
rom:/nro/EOSSDK-Switch-Shipping.nro, loaded withro::LoadModule;mainimports theEOS_*functions). Before the host loaded NROs, the imports stayedUNIMPLstubs andEOS_Platform_Createhanded back a garbage handle; the game checks it ([EOS] Failed to create platform) and plays offline. Current: the host never loads an online SDK: an NRO that exportsEOS_Platform_Createis left out of the pack (dm/tools/nro_collect.pyONLINE_SDKS, arefusedrow innro.tsv) andro::LoadModulerefuses it with one log line (refused …: an online SDK (Epic Online Services), not loaded). Offline, local saves. - The modules:
mainimports EGL (SDL3's GL support, the same 13 EGL functions as Digimon Story Cyber Sleuth) andvkGetInstanceProcAddr(its Vulkan support), but FNA3D renders with NVN and names no GL function. NVIDIA's OpenGL and Vulkan drivers program the GPU through NvRm, which the host does not have, so they are never loaded (profile_guess.pyGPU_DRIVERS); the EGL imports stay unbound stubs that nothing calls.
Mac routes
- A fresh save reaches the first level at about frame 9,000 with
DM_KEYS="f1500:A,f1900:A,f2300:A,f2700:A,f3000:A,f3300:A,f3600:A,f4000:A,f4400:A,f4800:A,f5400:A*30/150"(any button, accept the licence, New game, the character select, then A through the intro and the first dialogue);LRightwalks, Y strikes and X uses the skill.
Found on this game
General host changes first needed here; each applies to every game:
- Data blocks at the start of the text left alone (
nso_code.py,DATA_BLOCKS): Data blocks at the start of the text. getenvanswered from the profile (game_env,hle_os.c) and the 32 MB alignment cut for large regions on SDK 18, later taken by Paper Mario: The Thousand-Year Door's and Celeste's SDK 15.3.2 build: .NET NativeAOT malloc and the GC region range, 1 GB alignment of regions of 1 GB and more.vi::CreateLayerwith a size, AudioIn absent, online SDK NROs refused (ONLINE_SDKS),nso_syms.py host_hooksreadingdm/gfx, NVIDIA's GPU drivers never loaded (GPU_DRIVERS):vi::CreateLayerwith the layer's size, No audio input devices, Online SDKs in NROs are never loaded, Listing a game's unhooked imports before they are met, GPU driver modules that are never loaded.- H.264 decoders made at
Configureswitched to RGBA (md_avc_open): Parameter sets inConfiguremade the H.264 decoder without RGBA. - Viewport swizzles (
OP_VP_SWIZZLE): Viewport swizzles applied as a flipped viewport. - GLSLC outputs in loose RomFS files: GLSLC outputs in main and in loose files.
Open
- Shader counts differ: development.md says 162 GLSLC outputs in
shaders.nx.bin; 04 anddm/games/README.mdsay 163 outputs (162 unique). - Loading online SDKs: always load, refuse them (as now), or decide per profile is an open question for the maintainer (Online SDKs in NROs are never loaded).