
- Title ID
- 0100217023F6C000
- Tested build
- 1.0.0
- Nintendo SDK
- 22.2.0
- Engine
- GameMaker Studio 2 (its runner)
- Graphics API
- OpenGL
Build this game
Keep [0100217023F6C000] 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.
Version 1.0.0, SDK 22.2.0 (nnSdk-22_2_0, NintendoSDK_NVN-22_2_0, NintendoSDK_OpenGL-22_2_0). A GameMaker Studio 2 game: the RomFS holds the runner's data file (game.win, 229 MB, FORM/GEN8), its entitlements, three audiogroup*.dat banks, options.ini with [LLVM-Switch] SDKDir=…, and its pictures.
It renders with OpenGL, not NVN: main imports exactly nine EGL entry points (eglChooseConfig, eglCreateContext, eglCreateWindowSurface, eglDestroySurface, eglGetDisplay, eglGetProcAddress, eglInitialize, eglMakeCurrent, eglSwapBuffers) and every GL function through eglGetProcAddress. The context is OpenGL 3.2. Modules main, subsdk1 (NintendoSDK_movie) and sdk; subsdk0 (NVIDIA's GL driver) is never loaded.
On the Mac: the language list, the title screen, the opening story and the first room with its dialog render at 60 fps with sound, played with the keyboard (WASD + J/K) or a pad.
What it needs
| Setting | Where | Why |
|---|---|---|
modules main subsdk1 sdk |
game.tsv |
main takes nothing from NVIDIA's GL driver: the GL layer answers its EGL imports, so subsdk0 stays unloaded |
sys_resource 0x0; mem_reserve 0x100000000, mem_alias 0x10000000, mem_stack 0x10000000, app_pool 0xCD500000, mem_used 0x6a00000 |
game.tsv |
the NPDM declares no system resource, so nninitStartup gives its malloc a heap of the pool minus used memory (3.10 GB), mapped as it is touched |
gl_capture.tsv |
profile | the 93 shaders the runner puts together at run time, which no game file holds; the NSP script captures them on the Mac; see Shaders |
shader_groups /=romfs |
game.tsv |
no NVN shaders: the profile's NVN tables stay empty and the GL library comes from gl_shaders.py |
Rendering (OpenGL)
- Shaders at run time: the runner writes each variant of its GLSL as text, in GLSL ES 1.00 without a
#versionline (attribute,varying,gl_FragColor,precision mediump), names a variablesample, and declares its light environment and a few others as struct uniforms (uniform LightEnv { … };, which the game addresses by dotted member names such asu_LightEnv.m_dirLights_dir). Both needed the translator: GLSL ES 1.00 sources without a#versionline, Struct uniforms become member rows. - Draws from client memory: every sprite, the room background and the screen composite are drawn from client-memory vertex arrays (
glVertexAttribPointerwith no buffer bound); only the text path uses a real buffer, which is why the window first showed text alone. Dropped draws went from 11,885 per 300 frames to 0: Draws from client memory. - Two targets: the runner renders its room into a 1280x720 surface of its own (framebuffer 1, colour texture 5) and composites that surface onto the 1920x1080 window with one 4-vertex
GL_TRIANGLE_STRIPsampling texture 5, whose matrix has a negative y scale, since the runner keeps its surfaces y down while the window is y up. A second surface (framebuffer 2, colour texture 189) carries the rotation and scaling of the first. So a draw log that shows 1280x720 targets under a window that looks right is expected here. glFlushat the pause menu: the runner calls it when it opens the menu; without it the game jumped to address 0 (CRASH sig=11 addr=0 pc=0 lr=main+0x3409a78):glFlushhands the frame so far to the GPU.- Small gaps filled while bringing it up:
glDepthRange/glDepthRangef(0..1 only),GL_DEPTH_CLAMP(Metal clamps to the depth range already) andGL_MAX_TEXTURE_MAX_ANISOTROPY(16).
Shaders
- Current: 93 sources in
gl_capture.tsv— the runner's sprite, text, lighting, fog and outline programs and their variants — captured on the Mac withDM_GL_CAPTUREand translated to one.metallibbygl_shaders.py. The set is stable from boot through the first room's dialog; a room with an effect no earlier scene used would add one, which the capture table makes the build report.
Audio
- With
DM_AUDIO=1on the Mac the first room's music plays: 0 underruns after the boot's first 194 padded callbacks.
Found on this game
General host changes first needed here; each applies to every game on the same SDK or path:
- Resolved: ZBIC modules (NSO flag bit 7, system 22.0.0 on):
maincould not be read at all: ZBIC-compressed NSO segments. - Resolved: the thread ID at ThreadLocalRegion+0x110 (SDK 22): an
nn::diagabort withResult 0at the first heap lock, inmain's static initialisers: The thread ID at ThreadLocalRegion+0x110 (SDK 22). - Resolved:
clock_gettime(CLOCK_MONOTONIC)(SDK 22): an uncaughtstd::system_errorfromstd::chrono::steady_clock::now():clock_gettimeisnn::time's steady clock (SDK 22). - SDK aborts with a message (
nn::diag::detail::VAbortImpl) log their format before the abort, which is how thesystem_errorabove was named:clock_gettimeisnn::time's steady clock (SDK 22). - Resolved: no audio,
OpenAudioOutwithout a release event (SDK 22):OpenAudioOutwithout a release event (SDK 22). - Resolved: a crash at
pc 0innv::GetGraphicsMemoryInfoon a title with no NVN device:nv::GetGraphicsMemoryInfowith no graphics device. - The GL layer: client-memory vertex arrays,
glFlush, and the bring-up switchesDM_GL_DRAWLOG,DM_GL_FBLOGandDM_GL_MISSES(see env_switches.tsv); the translator's ES 1.00 dialect and struct uniforms (links above).
Open
save:/Settings.savis never written. The runner asks the language on every launch (fs path not found: save:/Settings.sav, thensave:/Settings.savis not on the RomFS either).save:/WELLDWELLER/blob.savis written and committed (save commit #1 … swapped atomically), so the save mount works: the settings file is written on a clean quit, which the host's kill does not give the runner.- Verified up to the first room, its dialog and the pause menu (OPTIONS with its CONTROLS/GRAPHICS/AUDIO/GAMEPLAY tabs, STATS, PAGES, MAP). Later rooms, the map itself and the save flow after a room are unverified.
- Audio and video were not measured against each other (the report of
DM_AUDIO_DUMPshows music, and the video runs at 60 fps, but no lip-sync or cutscene timing was checked).
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.