Repository navigation
Conversation
…9's nn::ro::LoadModule New profile 0100A00019DE0000 (base game v0, display version 0.0.126424, SDK 19.3.9), from the NSP script's provisional profile. Unlike Hades it renders with NVN: 88 BNSH shaders in Shaders/NVN/bin; the ExeFS holds only main and sdk. - Shaders bind textures at fixed, sparse slots (0, 1, 3, …, 31 and 34): SceneFade.frag reads c2 0x130 = 0x20 + 8 x 34, past Mario's 32 slots, so dmsh_build left that binding undecoded. nvn_tex_slots 35; the game has no image bindings. - hle_ro.c: SDK 19's LoadModule takes one more bool (…mib), which the older hook did not catch; it and ro::Finalize are hooked. The Epic Online Services NRO stays offline as in Hades (RegisterModuleInfo fails). - Memory: no system resource; the 3.10 GB heap fits the 4 GB layout; main's 82 MB bss gives mem_used 108 MB. - nvn_mtl.m: DM_NVN_HILITE set its keys and library up lazily on whichever thread built a pipeline first; with several keys two threads raced and one used a library the other had replaced (objc_msgSend crash in pso_desc). Set up once. On the Mac: title, a new save, the opening and Erebus with combat at 60 fps, resident memory flat at about 3.4 GB, one red line (the NRR). The two long lines through Melinoë while the staff's Omega attack charges are the game's own aim lines (WeaponStaffSwing5: AimLineCountOverride 2, AimLineAngleOffsetOverride 180), traced with vertex dumps and probes; docs/development.md says so. IPA HadesII.ipa (4.0 GB) built; awaits an iPhone test.
The IPA built from the Hades II profile plays on an iPhone. README lists it (~4 GB) with a screenshot from the Mac (Erebus, the first room of a run); AGENTS.md counts sixteen games and notes its texture slots up to 34 and the staff's Omega aim lines that look like a rendering bug; the game notes drop "not tested on an iPhone".
…Opus C interface, CSRNG, alloc_big_align Unicorn Overlord 1.05 (SDK 16.2.4, Vanillaware's engine as in 13 Sentinels) plays from boot through the title screen into the opening story scene. Three boots, three fixes: - the hardware multi-stream Opus decoder's C interface (CRI's Opus streams; the size query takes the SDK 12+ option argument) goes to the sdk's software OpusMultiStreamDecoder, as the single-stream one does (hle_codec.c); - nn::crypto::GenerateCryptographicallyRandomBytes, which the sdk's own getentropy calls under std::random_device, fills from the host's entropy stream instead of opening csrng (hle_os.c); - 13 Sentinels' 64 KB alignment of large StandardAllocator blocks becomes the profile key alloc_big_align. The engine cuts ring heaps out of a memory pool at 64 KB GPU alignment; with 4 KB aligned pool storage one kept base 0, and the game wrote to 0x268 right after the title screen. 13 Sentinels sets the key (its profile lists only the 1.10 build the old check named), so its behaviour is unchanged. The profile (dm/games/010069401ADB8000) holds 1,725 shaders from 2,188 GLSLC outputs in main, Mario's binding layout with every binding decoded, translation chain b-239c170b7616.
The IPA built from the Unicorn Overlord profile plays on an iPhone (A20 Pro: 60 fps, sound, a 2.88 GB footprint). README lists it (~4 GB) with a screenshot from the Mac (the opening scene in the castle garden); AGENTS.md counts seventeen games and notes the engine it shares with 13 Sentinels and their alloc_big_align key.
…ode, the host's allocator for Unreal Octopath Traveler 0 1.0.5 (Unreal Engine 4.26 / 4.27 mobile renderer, SDK 19.3.13) plays from boot through character creation into the story on the Mac (15 minutes with the iPhone memory layout, no crash); not yet run on an iPhone. - Shaders: the 10,324 are in the two shader code archives of the game's pak, each one Oodle-compressed. uepak.py reads the version 11 pak (AES-256 index; the key is the window of main that decrypts it, never printed or written; AES through CommonCrypto) and the archives; the Mac host decodes them with the game's own OodleLZ_Decompress (DM_OODLE_JOB, hle_oodle.c, build-gated) and shader_split.py reads the decoded LSLG records (profile key shader_ue_decode; the NSP script's decode_ue_shaders stage). Bindings measured: Engage's separate texture layout. - Memory: Unreal's nninitStartup reserves a 62 GB address region and its FMallocBinned3 37 GB of it. A cut skips the allocator's constructor and the host puts its own FMalloc vtable on a malloc zone in the object (hle_uemalloc.c); the region is capped at 2 GB with the game's own -SwitchVirtualAddressSpaceSize (new profile key game_args, also for the iOS app) and SDK 19's node area is cut to 62 MB as Engage's, for a 3.75 GB guest block. - Host: game arguments are set before nninitStartup, as on hardware; an undefined weak import nothing defines binds to 0, as rtld binds it (Tears of the Kingdom boots the same with the old and new hosts: its weak glslc* imports now resolve to 0); nvnCommandBufferFenceSync (OP_FENCE_SYNC), the texture / sampler pool getters, vi::GetLatestFrameNumber / ListFrameHistory; DM_ALIAS_WINDOWS for sizing fixed-window allocators. - Rewriter: a byte jump table whose add sits 17 instructions before its br (jump_bytes_far, tried last). - build_ipa.sh quotes FONT_PY (a python path with spaces failed the font step). Open: 61 vertex shaders pick a texture slot at run time (dynamic handle), 16 compute shaders with 3D image atomics do not build. The profile (dm/games/01005270232F2000) holds the shader tables, translation chain b-ba76ba138e78.
…slots, image atomics, save calls A 26-minute run from a fresh save goes through character creation and the story opening into free play with no red line; the game saves four times and a later boot continues from the saves. Not yet run on an iPhone. - Dynamic texture slots (profile key tex_dyn_slots, on for this game only): 61 vertex shaders (particles) pick one of several c2 table slots at run time, which the translator cannot trace to one slot (Ryujinx's 32-entry fallback arrays, <stage>_<t|tb|s>_cb0_40000000). The reflection reads them as NVN_RB_TEXD / NVN_RB_SAMPD arrays, the replay writes slot indices into that shader's c2 tables and binds slot k at element k. They used not to load; the castle scene's snow is back. Host only: no chain version changes. - Image atomics: SPIRV-Cross's MSL 2.3 emulation binds a device atomic pointer (<image>_atomic) beside the image, which the build reads as a second image of the slot, so the replay put a texture resource ID where an address belongs. NVN_RB_IMGA binds the storage of a buffer or linear image there (a buffer texture is a view of its pool); a block-linear image's atomics go to the dummy buffer (logged). 2,084 shaders in this game, at least ten run. - Buffer textures at an offset below Metal's reported 16-byte alignment are created when the offset is a multiple of the element size (measured on an M6: views at offsets 4, 8 and 12 read the right elements); they were dummies. - The first occlusion-query reset inside a pass without a visibility buffer splits the pass, so it is counted. - A buffer texture in a slot a shader reads as another type (a cube) reads 0 instead of undefined data. - Service calls: nn::fs::GetSaveDataSizeMax (SIGSEGV at the first save, about 13 minutes in), GetCacheStorageSize, GetFreeSpaceSize, account::PushOpenUsers, web::ShowOfflineHtmlPage, oe::ExecuteProgram, found by listing main's unhooked imports. - The engine is Unreal Engine 5 (its paged global distance field shaders and LowLevelTasks), not 4.26 / 4.27; the 16 compute shaders with 3D image atomics are that global distance field, which the mobile renderer does not dispatch. Tears of the Kingdom boots the same with the new host (no shader libraries there, so the new bindings are not exercised); the dm/gfx unit tests give the same results as before the change.
…one) A line under the playable table: on the Mac the game plays from a new game through character creation and the story opening into free play, and its saves load; its IPA (~4 GB, update 1.0.5) is packed the same way, but it has not been run on a phone, so it stays out of the table.
… 21 calls and audio, pool initial content, NVN block height New profile 0100D9F01D474000 (base game 1.0.0, SDK 21.4.0, Nintendo's own 2D engine; one BNSH of 35 shaders, Mario's binding layout). On the Mac it plays from a first boot through the setup, the main menu and Play Solo into Hoop Trundling at 60 fps with sound and no red line. Not yet run on an iPhone. - SDK 21 calls: nn::pl::GetSharedFont (every shared font at once; the SDK opened the pl service and aborted in sm::Initialize) returns the stand-in TTFs past the BFTTF header, as the service's offsets point there and the game hands them straight to ScalableFontEngine::LoadFont; vi::GetDefaultDisplayPanelIdentifier (SIGSEGV through the vi service object) answers an all-zero panel. - Audio: SDK 21's DSP command header has no magic (+0 enabled, +1 command ID, +2 size) and DeviceSink is 0x140 bytes with its fields 8 bytes earlier. capture() recognizes that layout on the first non-empty command list (the walk bounded by the generated list's length); the game was silent. - Pool initial content (all games): a new texture in a CPU_NO_ACCESS pool whose storage holds data is filled from it once, as NVN keeps a pool's storage content at nvnMemoryPoolInitialize (tex_init_fill); it stays a GPU texture that can be rendered into. Linear textures are made on the pool buffer in any pool. The game reads each texture file into memory and makes a CPU_NO_ACCESS pool on it; every texture read 0 and the screen stayed black. COMPRESSIBLE, multisample, depth / stencil and sparse textures and storage of zeros are left out. - NVN block height (all games): the automatic block height truncates height in blocks x 1.5 / 8 (MacNativeGames' finding, confirmed on this game's 40-block-row BC7 textures and by Touchable on 16 of its files); rounding up scrambled the calibration screen's beat numbers. Only data a game lays out itself without a packaged layout changes (Tears of the Kingdom's flushed and Monster Hunter Rise's sparse textures were not re-checked). - Profile key perf_mode (follow by default): boost reports Boost whatever the operation mode. This game plays handheld with Boost: docked means a TV to it, which asks for a latency calibration, and Boost alone picks its 1920x1080 draw size. - The NSP script's survey no longer calls nn::ro missing (hle_ro.c answers it; it now counts the .nro files); sdis.py --callers takes imported names and scans to the end of the PLT. The dm/gfx unit tests give the same results as before; Unicorn Overlord renders the same with the old and new host (no texture takes the initial-content path there).
…hone) Added to the line under the playable table: on the Mac the game plays from a first boot through the setup and the main menu into its first rhythm game, with sound, in handheld mode (no TV latency calibration); its IPA (~3.2 GB, base game 1.0.0) is packed the same way but has not been run on a phone, so it stays out of the table.
The IPA built from the Rhythm Heaven Groove profile (base game 1.0.0, handheld with Boost) works on an iPhone. README lists it (~3 GB) with a screenshot from the Mac (the title screen) and takes it off the Mac-only line; AGENTS.md counts eighteen games and notes its engine and SDK 21, and the handheld / Boost profile keys that skip the TV latency calibration.
…opath Traveler 0's sound stuttered on an iPhone) While swkbd::ShowKeyboard was up the host froze the guest clock (d2r-mobile's choice, so that monsters did not attack while the player typed). Unreal calls it off its game thread, so the game kept running, and every thread that waits on the clock spun while its audio mixing starved: on an iPhone the sound stuttered and the input box lagged (one 4.7 s frame, 5,035 wakeups a second while the box was up instead of about 1,800, no audio underruns). On the Switch the applet blocks only the caller while the clock runs, which the host now does too. The test switch DM_TEST_SWKBD_HOLD_MS (with DM_KBD) holds the keyboard up on the Mac: frozen, 8.8 fps and 7,936 wakeups a second in that window; running, 30 fps and 1,788. The inline keyboard keeps the freeze: its game (Monster Hunter Rise) does not block on hardware, and the host's input box blocks it.
…s name entry still stuttered on an iPhone) The previous commit let the guest clock run while swkbd::ShowKeyboard is up, but the iOS front end's input box froze it a second time around its own wait (front_ios.m front_text_input), so nothing changed on the phone: the game's frame loop stopped for as long as the box was up (4,977 ms and 2,577 ms frames, 5,181 wakeups a second). That freeze is gone too; the inline keyboard keeps the freeze it takes around its own call (hle_swkbd.c, Monster Hunter Rise). The Mac front end never froze, so the Mac runs with the keyboard held up (DM_TEST_SWKBD_HOLD_MS) were already the behaviour the phone now has: 30 fps and the usual wakeups.
A buffer texture on either side of a type mismatch has been bound as the dummy since the binding fix, but the line still said "bound as is" (Octopath Traveler 0 on an iPhone: a buffer texture in a slot a shader reads as a cube). It now says which of the two happens.
On an iPhone it plays at 30 fps through character creation, name entry and the story opening, with no audio underruns and three saves (a footprint of about 2.35 GB after 3.4 minutes). It joins the table with a screenshot of the castle in the snow; AGENTS.md lists it with the nineteen games and a sentence on its Unreal Engine 5 port; the game notes give the iPhone status.
D2R (Diablo II Resurrected) has no profile and its code could not run here: the host-call svcs its cuts emitted only died, the touch-run-v4 rule set needed a missing dm/PRODUCT, and the host files its hooks called were never in this repository. Removed with it: - rewriter: D2R cuts, observation gates and parameter slots, the touch-run-v4 rule set and private gates, the boot list, the cut scope column and the KRES / KASPECT key slots (fixups.tsv keeps the four thread slots; no params.tsv any more); dm/tools/product.sh - host: D2R save edits, add-on content, render-scale controller, time() takeover and Terror Zone clock, crash decoding at D2R offsets, host-call registry and stubs, i18n, UI-screen, shell-app loader, zero-stripped archives, boot profiling hooks with no implementation; D2R headers, tests and scripts; dm/ios/Sources/dm_touch_controls; dm/third_party/libdeflate - graphics: runtime extrapolation, world freeze, iPad UI shift, shop drag image, brightness LUT, visual ruler, bloom / FXAA shader hashes, DM_GFXUSE, the eco-fps setting, the loading-screen gate; shader_map.py, nometal_run.py, nvn_slots.py, nvn_slots.tsv and the PC-texture samples The legacy frame step (frame_step legacy, DM_FRAME_STEP) is retired: the Breath of the Wild and Tears of the Kingdom stubs lose their mode test. Breath of the Wild's interval-controller cuts stay: the framework keeps the controller's interval while the game's VFR override holds. patch_nso.py output is byte-identical for all 15 games on this machine except the two frame-step stubs; all 18 profiles build; the host tests pass (their Makefile now builds the general tests only).
… its name string - The loader reads the SDK version from the sdk module's NintendoSDK_nnSdk string (dm_sdk_major). SDK 10 and older report NVN API 53.313 and point the shared-font address at the TTF itself; later SDKs 55.15 and the BFTTF header. That is what every profile set, so device_api and shared_font leave the five that had them (Odyssey, 3D World, Link's Awakening, Age of Calamity, Three Houses) and profile_guess.py no longer guesses them; a profile can still override. - DM_OODLE_JOB finds OodleLZ_Decompress as the one function in main that takes the address of the library's own name string, with its start from .eh_frame_hdr, instead of an address per main build: Octopath Traveler 0 main+0x4f77e10 and Pokemon Legends: Z-A main+0x1a9c9e0. Octopath's 10,596 shaders decode byte-identical to before. - Rows that only restated defaults are gone (pad_layout simple, graphics nvn, present_interval game), and the NSP script writes no default rows into provisional profiles. No chain version changes. All 19 profiles build, the host tests pass; Mac boots of 3D World (SDK 10.4.0: API 53.313) and Engage (SDK 12.3.7) read the version.
… and rhi.SyncInterval
…'s Oodle, transform feedback, stencil views, the base instance in the driver segment - Profile 0100F43008C44000 (2.0.2, SDK 19.3.11): 5 GB layout with two cuts (StandardAllocator 12 → 4 GB, node area), mem_map_limit (the pool enforced as on Horizon), shader_oodle. - Shaders: Trinity packs (arc/data.trpfs, FlatBuffers, Oodle Mermaid) decoded with the game's own OodleLZ_Decompress in the Mac host; 28,603 shaders. - SDK 19: GetAudioOutBufferCount, crypto random bytes, ToPosixTime with a rule, NVN state getters, CommandBufferFenceSync, the 64-bit WaitForAddress type. - Graphics: transform feedback (vertex capture entry point, rasterizer discard), layered passes (the colour grading LUT), point size dropped beside a layer output, function constants specialized, a stencil-only view for STENCIL-mode texture views (striped lighting), sampler min / max reduction (Metal 26), the draw's base instance at c0 + 0x644 (occlusion boxes; characters' legs folded back from the hips), the zero cube for a 2D texture in a cube slot. - Shader chain changed (dmsh_build.py): every profile's dmsh_chain.h rewritten; the other profiles' c1_full lists carried over (that change touches no c1 read).
…me files The NVN driver's constant segments have the same layout in every game, so the nvn_* profile keys are gone. Combined textures are at c2 0x20 + 8 r (a slot past 31 shares the image table; Hades II binds 34), images at 0x120, separate textures at 0x168 (now always the host's slots 128 + n, as Monster Hunter Rise had them), samplers at 0x568, and the storage buffer tables at c0 0x110 / 0x310 / 0x510. dmsh_build.py decodes with that layout, the replay fills both texture tables, and the translator numbers slots the same way (rebuilt; its SPIR-V and reflection are byte-identical on 1,491 sample shaders, lock updated). The shader_* switches and graphics are gone too; the build reads them from the files (profile_guess.py shader_sources): - Vulkan when main imports Vulkan and not NVN; its capture when the RomFS has no SPIR-V. - A GLSLC capture when main holds GLSL sources and imports glslcCompile. - An Oodle decode for Unreal paks, and the tool-mode decoder for Trinity packs. - GLSLC outputs from every main. - A cover pairing for each single-stage vertex shader (GLSLC, Unreal). build_ipa.sh takes GFXAPI from the NSP script. Also removed: the last D2R pieces (the embedded-shader path in dmsh_build.py, dmsh_facts.py --freeze / --check, maxwell_refs.py, ref/hle_hid_d2r.c). Chain: every profile's dmsh_chain.h is regenerated. The c1_full lists are carried over: the change touches no c1 read, and the rebuilt Octopath Traveler 0, Hades II, Unicorn Overlord and Rhythm Heaven Groove gave the same lists, identical tables and the same reflection apart from separate texture slots + 128. Still to do: - Run the chain procedure for the other NVN profiles. - Engage's and Three Houses' shader tables need a new split: Engage gains Unity's 11 GLSLC shaders in main, and Three Houses' 17 BNSH vertex shaders lose their cover pairs. - Ace Attorney's new tables are in, but its libraries are not rebuilt.
A touch that lands in the right third of the screen on no control holds the right stick, centred where it lands; past the stick radius the centre is dragged along, so turning back responds at once. Controls in that third (A/B/X/Y, ZR, R, R3) keep their touches; in Super Mario Galaxy the pointer keeps the other unclaimed touches. Only the left stick is drawn now, so a right-stick swipe redraws nothing.
…Unity 2017.4, SDK 5.5.0) No host change was needed. The profile reports 84 MB of used memory (mem_used): the rewritten modules take 80 MB, and with the default 64 MB SetHeapSize fails and the game aborts at its first allocation. 3,118 shaders, every binding decoded; prewarm list recorded on the Mac (boot, title, storybook, Elder Kettle's house, Inkwell Isle One, Forest Follies). README, AGENTS.md and the game notes list it as playable on an iPhone.
…frames on time are not late (from PR seedds#27) - Asked for 60 Hz, the system fired the display link on every third refresh of a 165 Hz screen (55 Hz), so games paced by it ran at 55 fps. On screens whose rate is not a multiple of the link's, link_range (nvn_mtl.m) now runs the link at the screen's rate and counts as ticks only the refreshes nearest a steady 1/60 s clock; DM_LINK_VTICK=0 keeps the system's choice. front_screen_max_fps (front.h, front_mac.m) gives the window's screen's rate. - A tick lies up to half a refresh off its slot, so there the hold of frames over 25 ms tolerates one refresh more. Without it, 30 fps frames kept a third tick: 22.5 fps at 165 Hz and 24 at 144 in a simulation of the callback. This part is not in the PR. - The frame step (nvn_fstep.h shown_slack, hle_nvn.c fstep_tick) lets a frame on time show one refresh longer than its hold on such screens: a cheap 50 ms frame shows 54.5 ms at 165 Hz, and counted as late it kept the hold at 20 fps for good (Breath of the Wild, Tears of the Kingdom). Three new t_fstep checks. - Not taken from the PR: the responsive pacing mode, its uniform-buffer shadows (redone separately) and the Breath of the Wild resource-size-table overlay. docs/development.md records what the PR found about the world-load crash (the Obj_TreeConiferous resource heap) and the overlay runs; docs/agents/04-graphics.md describes the ticks. - Not yet run on a 144 or 165 Hz screen here (this Mac's is 120 Hz, where nothing changes); iOS screens are not affected. Co-authored-by: Yuecheng Liao <128268702+lyccccy@users.noreply.github.com>
…ript The app shows the frames put on screen each second in the top row (front_ios.m, from mtl_present_count, so NVN and Vulkan games alike). build_ipa.sh's DM_SHOW_FPS=1 sets DMShowFPS in Info.plist; DM_SHOW_FPS=0 / 1 in Documents/env.txt overrides it without a rebuild.
…ds#25) nn::fs::Commit(const char* const*, int) had no takeover, so the SDK's own code opened fsp-srv and aborted with the save writes left uncommitted (Animal Crossing: New Horizons). Both overloads now share one transaction engine. A list commits once when every name is the same host save; cache and temporary storage are skipped as the single-name Commit does, and a list of two separate saves is refused without committing either. t_fs_commit_list covers rollback, remount, aliases, clone failure, cache storage beside the save and the refused multi-save list. Co-authored-by: BeeeeeMo <14192706+BeeeeeMo@users.noreply.github.com>
…the host's frame step decides 60 or 30
The game steps a fixed amount per update, from three 30 fps values, and its updates are not held
by the presents:
- A KIDS task (main+0x166d980) waits until 1 / fps has passed and steps the game clock by a
frame-rate object's 1/30 s (the measured path runs only without the object).
- The battle steps 1 / the game's frame-rate block (main+0x269e150: {30, interval 2, 30, 30.0}),
read by the scene update's caller (main+0x8c3610) and its jobs; found with a sample profile.
- The event scripts step by the KTGL device's frame rate, 59.94 / the interval in its config.
The 60 fps cuts (d975e2e) changed only the task's wait and the interval, and were checked only on
cutscenes. DM_PROBE showed the game clock at 2.00 x real time, and battles ran twice as fast on an
iPhone. Fixing the clock alone was not enough: Link still covered twice the ground in a 3 s stick
hold, and the enemy waves came early.
AoC 1.3.0 main joins the rewriter's frame step (patch_nso.py FRAME_STEP), with three stubs. The
updates run at the cap: the task's fps and the frame-rate block become the cap; the object's step
is scaled by its fps x vsyncs per update / 60; the device frame rate becomes 59.94 / vsyncs; and
nnMain's device config gets interval 1 above a 30 fps cap. They replace the two CUTS entries.
Every step stays per update, as on the Switch. The host paces the presents: 60 fps, or 30 when 60
does not hold. Profile fps_target 60; DM_FPS_TARGET=30 runs at 30, and 0 is the Switch original.
On the Mac:
- Game time follows real time at 60 and 30.
- After the same stick hold at the same wall time, Link stops on the same spot at 60 fps as in
the 30 fps original.
- The battle loads at about 133 s in every run.
- The forced 30 matches the original.
Two variants were tried and dropped. Stepping by the measured time still ran battles at twice the
speed. A task wait that follows the step locked the hold at 3 vsyncs.
AoC's shader libraries were rebuilt for chain a9687d01ebfa (Mac and iOS); c1_full.tsv is
regenerated with the same list. The IPA HyruleWarriorsAgeOfCalamity-2026-10-21-speed.ipa, built
from 89b608d plus these changes, awaits an iPhone test.
…t bars A16 / older iPhones have no hardware BC texture sampling. Decode BC1-7 on the CPU, prefer an offline BCA1 ASTC cache, and package it with a split A16 build that limits the shared fonts to three slots. The A16 build is opt-in with A16=1 and can sit beside the normal app. Rhythm Heaven Groove uses a two-zone touch pad: B on the left, + / - on the right and A over the whole picture in A-only minigames. The scene tables cover the title, start menu, menus and the minigames; the full-screen present pass paints the side bars with a frosted ambient glow. Tests: t_touch_layout, t_rhythm_pad, Mac host build; the iOS build path uses A16=1.
The default NSP build path now exposes A16 = True / --a16. It selects the ASTC cache under <id>_build/astc-cache, writes a separate -a16.ipa, and gives the app a separate .a16 bundle ID so the standard build and the old-device build cannot overwrite each other. build_ipa.sh also makes the A16 name and bundle suffix idempotent for callers that already set them.
Other games built for A16 keep all six shared fonts; only Rhythm Heaven's profile asks for the three-slot memory saving. A missing ASTC cache is now a warning, not a build failure, so the generic software-BC fallback still works for other games.
Brings the branch up to main (f678e30) so PR seedds#29 merges again. The conflicts kept both intents: main's newer games and general host work, and the branch's Rhythm Heaven Groove A16 / rhythm-pad work. - Docs (AGENTS.md, README.md, dm/games/README.md, docs/): main's newer text everywhere it supersedes, plus the branch's `pad_layout` row, the two-zone rhythm pad paragraph and the A16 build bullets. "Twenty-seven" games matches the list. - dm/tools/patch_nso.py and dm/gfx/tools/shader_split.py: the conflicted regions were main's newer cuts and readers; the branch had no unique text there, so both are main's version. The Rhythm Heaven rewriter work lives in build_ipa_from_nsp.py (A16 blocks) and the profile. - dm/gfx/nvn/nvn_mtl.m: main's texture upload, MetalFX and variant work kept, with the A16 CPU BC decode (bc_soft_fmt / bc_decode_blocks / bc_astc_upload) re-expressed on top of it. hle_nvn.c, nvn_fstep.h, nvn_obj.h, nvn_refl.m and hle_vi.c are main's text: the branch's edits in their conflicted regions were already there. - Host and iOS: dm_touch_layout.c and its header stay in SRC, t_touch_layout and t_rhythm_pad stay in the test run, hle_sdk16.c keeps DM_SHARED_FONT_LIMIT (default 6, so main's behaviour); the Metal layer stays full screen because the present pass letterboxes the 16:9 picture and paints the ambient bars itself. front_ios.m had the same fps-label block twice from the auto-merge; one copy is left. - Profiles: Rhythm Heaven keeps `pad_layout rhythm`; Age of Calamity takes main's `fps_hold off`. Checks: dmhost builds for 0100D9F01D474000 (0 errors); dm/host tests pass except t_oe's 2 known failures and t_condvar / t_condvar_old, which fail to link; dm/gfx tests fail the same 13 targets and t_refl as main does — all verified against a clean origin/main worktree. Python tools compile (3.12). iOS sources (front_ios, DmGamepad, DmRhythmPad) pass a clang syntax check against the iPhoneOS SDK.
2 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This adds the A16 / older-iPhone support and the complete Rhythm Heaven Groove adaptation:
dm/third_party/bcdec), with an optional offline BC → ASTC cache (BCA1, keyed by the guest texture hash) and a guard for BC-format views of decoded textures.A16=1forces the software BC path, packagesdm/bc_astc, makes a split IPA by default, limits the rhythm profile to three shared-font slots, and gives the app its own.a16bundle suffix so it can sit beside the normal build.dm/tools/make_astc_cache.pygenerates the cache from aDM_NVN_BC_DUMPrun. The default NSP build path,scripts/build_ipa_from_nsp.py, exposes the same switch asA16 = True/--a16, uses<id>_build/astc-cache, and writes<game>-a16.ipa.Documents/touch_layouts.tsv.DM_AMBIENT=0restores black bars.The Rhythm Heaven profile opts into the rhythm layout with
pad_layout rhythm; the generic gamepad remains available withDM_RHYTHM_FULL=1.Test
make -C dm/host GAME=0100D9F01D474000t_touch_layout: okt_rhythm_pad: okmake -C dm/host GAME=010015100B514000(Mario profile,DM_GAME_PAD_RHYTHM=0) builds, so the shared host changes compile outside Rhythm Heaven.A16=1build: succeeded (split, unsigned, six-file ASTC cache; bundleorg.nxnative.0100d9f01d474000.a16; also built with the olderzh-Hantenv, exercising theDM_LEGACYshared-font fallback). The split IPA needs the RomFS inDocuments/romfs; device installation is left to the tester.The full host test suite still has the two pre-existing
t_oefailures unrelated to this change.