9.9 KiB
9.9 KiB
Super Mario Odyssey (0100000000010000)
Update 1.4.1 (v393216) over the base game, SDK 7.3.2. Nintendo EPD's sead / agl engine with NintendoWare (G3d / Ui2d / Vfx), on NVN. Modules main, subsdk0 (the movie module) and sdk; DRAGON QUEST XI S 1.0.4 runs the same sdk build. Plays on the iPhone. The README lists its IPA at about 6 GB.
What it needs
| Setting | Where | Why |
|---|---|---|
alpha_from_red with the 26 layout pixel shaders (main's BNSH at 0x132c000) |
game.tsv |
the HUD's coin counters came out as solid white cards; inert on the Mac since the nvnTextureCompare fix, kept until an iPhone run; see Rendering |
pad_layout full |
game.tsv |
the 3D gamepad layout |
4 GB layout: mem_reserve 0x100000000, mem_alias 0x10000000, mem_stack 0x10000000, app_pool 0xCD500000 |
game.tsv |
from the NSP script's provisional profile |
| Node area cut and 32 MB alignment of large regions | dm/tools/sdk_patches.py, sdk build fcf93a41… |
registered for DRAGON QUEST XI S on the same build; Odyssey has no virtual address memory and never allocates an address region |
No patches.py. op_mode stays docked: Odyssey only takes its motion moves in its default docked mode.
Input
- Resolved: buttons and menus worked, the sticks did nothing in play (its first hint, "Look Around", waited forever). The game reads all 16 entries of the controller history (
GetNpadStates) and ignores the returned count; the host filled only the newest. It polls every controller slot each frame, which moves the shared sampling number on by about 16, so the stick samples it combined were mostly empty, while buttons and the stick's direction bits (which menus use) still came through. The host now fills every requested entry with the current state under consecutive sampling numbers. - Resolved: motion moves never happened; shaking did nothing (cap throws by shaking). The host handed out six-axis handles but reported no sensor; it now reports one per connected controller. The game reads the six-axis history the same way (16 entries per sensor, the count ignored,
main+0x93fd84). Its motion analyzer (main+0x5d5590) turns the newest acceleration, seen against the controller's pose, into a swing value per hand and sets the swing flags above 0.2. A still controller gives 0, and the host's shake (±3 G side to side) gives up to 1.5, so aShakesets the left, right and any-swing flags for its length. To find the swing detector, probe the accelerometer value it reads (DM_PROBE=main:626248@x8+10in 1.4.1). On the iPhone, shake the phone (a sharp flick); on the Mac, Space.
Rendering
- HUD (layout captures). The coin counters (coin, regional coin) and other layout panes take their alpha from single-channel render targets, as in Breath of the Wild; read literally they were solid white cards, which
alpha_from_redfixed. Odyssey's layouts rebuild their captures through the same agl code (main+0x982320replaces the registered descriptor only ifnvnTextureComparereports a difference), so the comparison fix covers them too. Current: on the Mac smoke route to frame 20,100 the list converted no texture (the host before the fix converted its first, a 640×80 R8 target, at frame 4129), and the HUD at frames 17,300 and 17,600 is pixel-identical. The list stays until the change has been seen on an iPhone. - Resolved: the Cap Kingdom fog never parted around Mario (reported on an iPhone; fix checked on the Mac). The fog's shading reads velocity fields that a small fluid simulation updates every frame: two 256×256 and two 128×128 RG16F targets, with a two-pass blur and a blended composite. Its only input is a point-sprite splat per mover, drawn with
alPointSpriteShader: one vertex per mover, its size in the vertex data (Mario's main splat about 18 px, others 3–5 px) and a soft disc in the fragment shader (clamp(1 - 4r², 0, 1)× velocity). The vertex shader writesgl_PointSize = min(size, c0[0x610]), and the host had nothing at that offset of the driver segment, so every splat had size 0 and the fields stayed exactly zero (raw dumps withDM_NVN_TEXDUMP+DM_NVN_SNAPRAW). The host now writes the largest point size, 2047, atc0 + 0x610for the graphics stages. Writing theSetPointSizevalue instead (always 1 here) left one-pixel splats whose disc weight came out 0 (the fields held-0.0). After the fix the fields hold velocities up to ±44 and the fog clears around Mario. - Resolved: the Cap Kingdom ground showed 32×32 blocks of a stale image on every fourth frame (Mac). Presents 4k were brighter and blocky, 4k+1 and 4k+2 clean, 4k+3 partly blocked, repeating to the decimal across runs; only with the ground's material (
b6384a85afd3ef94) drawn. In some frames the game first draws a depth pre-pass (alRenderDepthOnly) for objects its occlusion queries report visible (the queries rotate through three slots, hence the cycle), then the G-buffer with other vertex shaders and depth test less-or-equal, without clearing the colour targets. Metal compiled the two vertex shaders' identical position math to slightly different depths, the G-buffer fragments failed the test and kept the previous content. Every Metal compile now uses-fpreserve-invariance. Ruled out on the way: the TBDR optimizations, same-pass feedback, the present path; evaluating the game's conditional rendering on the CPU from earlier frames' results made it worse (the condition belongs to the same frame on the GPU), so the host still ignores the condition here and draws (norender_cond). - Its three geometry shaders (a thunder effect) do not translate.
Movies
- MP4 / H.264: the videos in its tutorial hint boxes and the kingdom travel videos, 41 of 44 High or Main profile with B-frames. The host decodes them with VideoToolbox; the SDK's demuxer passes the parameter sets as the
avccrecord (the MP4avcCbox), and pictures leave in presentation order through a small queue.
Services
- Start-up calls no game before it made, each answered by the host: the aborting
account::OpenPreselectedUserandGetLastOpenedUser(a null read), news delivery (bcat: the delivery storage does not mount, which the game treats as "nothing delivered"), HOME-button blocking, the parental 3D-mode setting,vi::SetLayerScalingMode,time::ToPosixTimeFromUtc, the debug pad, and the SDK 7 names of two audio-device calls (audio::AcquireAudioDeviceSwitchNotificationaborted). Each aborted with no message in the SDK's IPC; frames resolved withsdis.py --sym. - Command memory: it hands out many 512-byte command memory grants before recording; with no recording to reclaim them by, 256 KB host segments each reached the cap entering the Wooded Kingdom, so an empty-pool grant of at most 4 KB outside a recording gets a 4 KB segment (
hostseg_size). TheGetCommandMemoryUsedcount from the lastAddCommandMemory(found on Three Houses) left it unchanged. - Shared fonts: SDK 7, so the address is the plain TTF. Focus handling mode 3 (no focus notifications; the system suspends the game out of focus).
- Its SDK 7 driver's GPU code range (1.5–1.14,
nvnDeviceGetInteger0x2E–0x31) was measured here; the host now reports newer versions for newer SDKs.
Audio
- It is silent for its first minute with either audio renderer update lock: the old SDK 16 offset and the one
update_locknow reads off the SDK's ownUpdate(MutexTypeat +0x1d8 on SDK 6.4–8.2) (The renderer's update lock).
Files and shaders
- 27,984 shaders: agl
sharcbandbfshainShaderData, particles inEffectData; groups per RomFS folder ingame.tsv. - The spin-wait rewrite leaves its modules byte for byte as before the lock and store rules.
Mac routes
- A fresh save wakes Mario in the Cap Kingdom with
DM_KEYS="f1000:A,f8200:RLeft~6,f9200:LUp~4": the "Look Around" hint waits for the right stick held about 6 s one way (left then right cancels out). Play starts at about frame 9,900, and the game saves there. - From that save,
f1000:A,f1300:Aresumes into play at about frame 1,500, andf1600:LUp~7walks straight across the fog to the hills by the bridge, where Cappy flees from Mario. DM_KEYStakesRLeft/RUp/RRight/RDownfor the right stick andShakefor the controller.
Found on this game
General host changes first needed here; each applies to every game:
- Largest point size at
c0 + 0x610: 04, section 3 and Graphicsc0 + 0x610: the largest point size. - Invariant positions (
-fpreserve-invarianceindmsh_build.pyandios_metal.py): Position invariance across shaders. - Full controller and six-axis histories, six-axis sensors and the shake (
DM_BTN_SHAKE), SDK 7 start-up services: History reads fill every requested entry, Six-axis sensors, SDK calls that open a system service through sm. - H.264 movies through VideoToolbox (the
avccrecord, a presentation-order queue): described under Movies;hle_movie.c. - Small host segments for small grants (
hostseg_size): Host-lent command memory segments.
Open
alpha_from_redis inert on the Mac but stays until an iPhone run shows the HUD without it.- The three thunder geometry shaders do not translate.
- The silent first minute of sound.
- development.md calls SDK 7.3.2 "the oldest so far"; Mario Kart 8 Deluxe (SDK 4.4.0) is older now.
game.tsvsays values marked "Mario's" are not measured yet, but none is marked.