b87a0cc6aa
Upload batches flushed outside a submission are handed to the encode thread at once (general, from PR #141). With the encode thread on (the iOS default, DM_NVN_ENC_THREAD), an upload batch's commit is a record in the encode thread's current block (rec_commit_upload), which is handed over when the block fills or a submission ends. Outside a submission (no replay command buffer: a texture zeroed at creation, tex_zero_fill, or a packaged texture uploaded between submissions) up_flush meant to commit the batch on the spot, but the record stayed in the block until the next submission, and every wait for it waited for that submission: nvnQueueFinish (mtl_finish_gpu, on any thread) or up_begin on a busy slot. A game whose last submitting thread creates a texture and then calls nvnQueueFinish before it submits again waited for good. up_flush now hands the block over when it runs outside a submission (it runs on the submit thread only, up_owner_check). From PR #141 (LNPANDY, found analysing a Hades II save-load freeze on an iPhone 14 Pro): mtl_finish_gpu hands over the block before it waits when it runs on the submit thread, as up_begin does since 9cb7af3 and q_cb does; nvnQueueFinish cannot run inside a submission (one nvnQueueSubmitCommands call, which ends with rec_drain), so that line matters for the window above and for the diagnostics that wait mid-submission (td_dump, DM_NVN_T2T_TRACE). Checked: dmhost builds for Super Mario Bros. Wonder (NVN) and Hades (Vulkan), the host unit tests pass, the graphics run list passes, and with DM_NVN_ENC_THREAD=1 every test passes but t_rt_range, which stops on main alike (DmRecEnc has no stand-in for the copyFromTexture:...toBuffer:...options: form). Not checked: a game, the iPhone
seedds2026-10-25 02:23:42 +08:00
156d3c2a18
CI on GitHub's macOS runners (from PR #132): .github/workflows/tests.yml runs, for pull requests, pushes to main and manual dispatch, three jobs on macos-26 in parallel: the host unit tests and the graphics tests that need no GPU (t_dirty_slots, t_dirty_race, t_pace, t_fstep, t_hmap, t_cover, t_pso_skey, t_refl and t_rt_range_ro, the last two skipping their sample checks); every test_*.py of dm/tools/tests, dm/ios/tests and dm/gfx/tests on Python 3.14 with lz4, capstone and fonttools; and a build check: dmhost for Wonder (NVN), Hades (Vulkan) and Digimon Story Cyber Sleuth (GL), every graphics test compiled but not run, and the iOS host sources compiled for the iPhone SDK by a new helper, dm/ios/tools/compile_check.py (the host Makefile's file list and flags as gen_build.py takes them, the host's own command first so its header paths come before libvpx's; 133 files, no game files, signing or Xcode project). Read-only permissions, superseded runs cancelled, a timeout per job, logs uploaded only on failure, actions pinned to commit SHAs (checkout v7.0.1, setup-python v7.1.0, upload-artifact v7.0.2, each checked against its tag). The GPU tests stay local (the hosted runners are virtual Macs without Metal 4, issue #112), and so does profile_guess.py --check (it reads game extractions). test_xcode_workflow.py: the stand-in profile carries the registered profile's title_id, which report_profile_status reads since ce17300 (the test had 3 errors on main). Checked by replaying the three jobs on this Mac on current main: all pass, the tool tests in a fresh Python 3.14 venv with only the three packages
seedds2026-10-25 01:58:01 +08:00
3f4d973ac5
Mario vs. Donkey Kong (0100B99019412000, update 1.0.1 over the cartridge base game, Nintendo's sead / agl / gsys engine on SDK 15.3.0): game profile plus three general host changes. Plays on the iPhone (IPA 1.6 GB, user). On the Mac: the opening movie with sound, the title (Press L+R), file select, the play style choice, the first cutscene, level 1-1 (both colour switches, the spring, a time-out and its restart), the pause menu, leaving the level, level select and the save it shows: 60 fps (frame interval p99 about 17 ms), sound, about 1 GB resident in the level and flat while it runs, CPU about 30% of a core, no red line on that route.
seedds2026-10-25 01:16:20 +08:00
6d34984488
Spin waits that take a spin lock (general, from PR #134, found on Breath of the Wild; fixes#129). In steady play on the Mac, Breath of the Wild had frames with 30-210 ms of CPU work every 1-10 s: the main thread and the two workers spinning in one job queue poll (main+0xef62dc). The first item of some of its jobs is for the thread of core 0; the others wait until it is taken, taking and releasing the queue's lock (an exclusive test-and-set, then a compare-and-clear) and writing a status word on every pass, so the spin wait search (a store or an exclusive store ends a path) did not take it. Polled at full speed by the two workers, the lock went back and forth between their cores, and the main thread, whose item it was, lost nearly every exclusive store: in a 40 s Time Profiler trace it never held the lock while each worker held it in about 750 samples. patch_nso.py "Spin waits": a lock taken and released on the same address on every path back to the head (spin_lock 'acq' / 'rel', counted like the exclusive adds), a test loop on a word inside the region ('tst', whose branch back goes to the original loop and its own gate), and up to four stores whose value and address registers the region never writes ('stc', only in a region that loads something). Such stores write fixed values to fixed addresses, so a loop can change its own state for a few hundred passes at most, well inside the gate's 2 ms of polling, before its passes repeat. A store of a value a pass changes ends its path and the search runs again without it (the path that takes an item stores the new cursor); when the region with stores does not cover the old one's back-edges, the old one is used. Through the gate the workers leave the lock a moment between passes and the main thread takes its item at once. Zora's Domain on an M2 Max at 120 Hz (one host, 42 s of steady play per run, three runs each, before -> after): standing still, frames with more than 30 ms of work 2.8 / 6.3 / 3.5 -> 0 per 30 s, the frame's work p99 20-21 -> 8.3-8.4 ms; turning the camera, CPU hitches 11.9 / 13.3 / 6.3 -> 0, p99 21-25 -> 9-15 ms; process CPU per frame unchanged. Every module on the game drives rewritten with the old and the new search (206: 108 NSOs and Super Smash Bros. Ultimate's 98 NROs): 175 byte for byte as before (Hades, Super Smash Bros. Ultimate, Super Mario Odyssey among them), 7 fail alike under both (every rtld, New Super Mario Bros. U Deluxe), and 24 take new or wider loops, all but Breath of the Wild's queue through the store rule alone: Monster Hunter Rise's main 90 -> 166 (72 of them one inlined countdown whose reset makes the next pass leave), BALL x PIT 87 -> 94, Animal Crossing: New Horizons 162 -> 166, Balatro 9 -> 12, Octopath Traveler 0 75 -> 78, Pikmin 4 80 -> 83, Bayonetta 3 35 -> 37, Breath of the Wild 308 -> 310, one more each in Big Brain Academy, Mario Kart 8 Deluxe, Metroid Dread, Pokemon Legends: Z-A, Stardew Valley, Super Mario Bros. Wonder (both builds) and Tears of the Kingdom; the movie library's thread loop is wider in the subsdk0 of Breath of the Wild, Mario Kart 8 Deluxe, Animal Crossing, BALL x PIT, Monster Train 2 and Octopath Traveler 0, and one loop is wider in the main of AI: THE SOMNIUM FILES and Advance Wars 1+2. No loop of the old search is lost or loses a back-edge. Each distinct shape was read in its disassembly: one-pass resets and state setters (the gate is reached only when another thread changes the word), parser states that leave on the next pass, and real flag waits. Rewriting all 206 takes about 4,100 s of CPU instead of 3,250. Diagnostics: DM_HITCH_DUMP=<ms>[:<s>] logs every guest thread (its wait, last SVC, where it is, x0-x2 and x19-x25 in guest code) when no NVN frame was presented for that long, and each guest thread names its pthread '<handle> <name>' (0x1008 Worker) before it enters guest code, the main thread '0x1001 main thread', so sample and Instruments' Time Profiler show which guest thread a sample belongs to. The graphics tests that link hle_nvn.c without the host define dm_present_ns (t_host_stubs.c weak, t_nvn.c). New test dm/tools/tests/test_spin_waits.py. Checked: the host builds, the host unit tests, the 46 tool tests and the gfx run list pass; Breath of the Wild into Zora's Domain and Mario Kart 8 Deluxe for 85 s from boot with the new rewrite (the PR's author), and Monster Hunter Rise from a fresh save for 180 s headless with each rewrite on one host (e72a065's, the chain of its Mac libraries): 60 fps, frame p95 about 17.5 ms, the same red lines, no hang. Not checked: Paper Mario: The Thousand-Year Door, DARK SOULS: REMASTERED, FINAL FANTASY TACTICS and FINAL FANTASY RESONANCE (no files on the drives), the iPhone. docs/development.md (Spin loops, Breath of the Wild) and docs/agents/05-debugging.md say so
seedds2026-10-25 00:48:21 +08:00
24c38e849a
README: the Mario and Zelda games first in the games gallery (Mario, then Zelda, each alphabetical), the other games after them in alphabetical order as before
seedds2026-10-25 00:32:04 +08:00
98bd33a4ef
BALL x PIT (010086A022444000, update 1.293, Unity 6000.0.62f1 on SDK 20.5.19): game profile and the SDK 20.5.19 sdk build's node-area cut, no host change. Plays on the iPhone (IPA 1.1 GB, user). On the Mac from a fresh save through the title, a new game, the intro and the descent into the pit, the first dive and its tutorial (moving, aiming with the right stick and shooting with ZR, gems and XP, the enemy waves that overrun the player and end it), and the base-building tutorial (the sidebar, the build menu, a wheat field and a forest placed, the first harvest): 60 fps (frame time p50 16.66 ms, p95 about 16.8 ms; GPU 1-5 ms a frame), FMOD sound through one stereo AudioOut, about 1.6 GB resident and 0.7 GB of Metal allocations, flat over 10 minutes, no red line. sdk_patches.py: like Hollow Knight: Silksong, Unity 6 takes all its memory through AllocateAddressRegion / AllocateMemoryPages with no heap; this sdk build's AddressRegionManager constructor is the SDK 20.5.22 build's at the same offsets (sdk+0x145cfc; the node area limit +0x145d0c and its occupied length +0x145d78 cut from 0x3fe00000 to 0x3e00000): the alias region's high-water mark +2.00 GB of 4.375 GB, 1.26 GB mapped. The provisional profile was otherwise right as generated (Engage's 5 GB block, sys_resource 16 MB; profile_guess.py --check: ok). Shaders: 38,099 (18,913 vertex, 18,917 pixel, 116 compute, 76 hull and domain, one geometry), 11 of them GLSLC outputs of Unity's player in main; the loose serialized files (resources.assets, sharedassets1.assets, the built-in resources) have no type trees and borrow the Shader tree 10 of the 11 Addressables bundles carry (the same type hash, shader_split.py's deferred pass), so unityfs.py needed no layout; all build for the Mac and iOS. The game draws 1280x720 into 1920x1080 window textures with a window crop (nvnWindowSetCrop 0,0 1280x720), which the present already scales. Profile: pad_layout full (the right stick aims in a dive), a prewarm list recorded on the Mac over the route above (297 lines). Checked: the NSP script packs it from the NSPs alone (Mac and iOS); after the rebase onto ded1cff the 44 tool tests pass. README (games gallery, a Mac picture of the first dive), AGENTS.md (56 -> 57), docs/development.md and docs/agents 03 / 04 say so
seedds2026-10-25 00:23:24 +08:00
ded1cff4ca
README: gallery cells aligned to the top (valign), so the pictures of a row line up when their captions take different numbers of lines; GitHub centred them vertically, and 10 of the 19 rows were uneven (measured with GitHub's rendered markdown and stylesheet in headless Chrome), none now
seedds2026-10-24 23:25:01 +08:00
ebc2a9a3a0
README: the games gallery as an HTML table whose three columns are each 33% wide. In a Markdown table GitHub sizes each column by its caption text and shows images at max-width 100%, so with width 256 the pictures still came out 230, 256 and 222 px wide; with equal columns all 56 are 251 px (measured with GitHub's rendered markdown and stylesheet in headless Chrome at GitHub's README width). At phone width a column cannot be narrower than its longest word, so they differ by a few pixels there
seedds2026-10-24 23:22:44 +08:00
02294dda9e
Stardew Valley (0100E65002BB8000, update 1.6.15.13, MonoGame on Sickhead's BRUTE, SDK 20.5.27): game profile, no host change. Plays on the iPhone (IPA 0.6 GB, user). On the Mac: the title, a new farm (character creation with the software keyboard, Skip Intro), the farmhouse, the farm and its tools, the bus stop, Pelican Town by day and night, Pierre's shop and a purchase, the game menu, the mail, a night's sleep and its save, Load from the title, and the Co-op menu (Online Communication goes back to the title with no network): 60 fps (frame time p50 16.67 ms, p95 16.8 ms; GPU about 0.6 ms a frame on an M6; CPU 8% of a core), sound, 0.93 GB resident in play and flat over the last 10 of 23 minutes, no red line. About one frame in 800 takes 24-47 ms of the game's own CPU time (no pipeline build, upload or present in it; the main thread otherwise sleeps 95% of each frame in SleepThread, whose host sleep is exact), probably BRUTE's Boehm collector, not checked further. The two changes this game needed came before it from PR #120 (compressed XNB shaders, the Mac text box releasing the buttons that opened it). Profile: the provisional profile's guesses held (no system resource, a 2.96 GB heap in the 4 GB layout, mem_used 218 MB for the rewritten modules); 65 shaders (64 MonoGame effects in main, one in the LZ4 XNB Content/Effects/ShadowRemove.xnb); pad_layout full (main imports no touch screen or mouse; the D-pad in menus, the right stick for the cursor); a prewarm list recorded on the Mac with prewarm off over the route above (6 lines: SpriteBatch's two shaders and four pipelines; with it nothing was built on demand). Checked: the NSP script packs it from the NSPs with the profile in dm/games; the 41 tool tests pass. README (gallery, a Mac picture of the farm), AGENTS.md (55 -> 56) and docs/development.md say so
seedds2026-10-24 23:19:27 +08:00
c33327c267
README: every gallery picture shown at one size (img width 256). GitHub sizes a table column by its widest content, so a long caption widened its column and the Markdown image stretched with it; all 55 pictures are 16:9
seedds2026-10-24 23:18:37 +08:00
399fd2ca32
README: the games gallery in 3 columns, sorted by title (ignoring case, accents and a leading The), with shorter captions: the IPA's size, "60 fps with <update>" where that update gives 60 fps (one line above the table says it is 30 on the Switch), and the notes that matter to a player (played by touch, controller only, Japanese, offline, no Mii heads). Update versions not needed for 60 fps are left out, as Pack an IPA says any version works. 55 games in 19 rows instead of 28
seedds2026-10-24 23:13:34 +08:00
66490fb5f8
README: point to NX2Apple (from issue #130), a community fork with a macOS app that runs the NSP pipeline and packs the RomFS into a sharded archive for a slimmer IPA, for people who prefer a graphical interface to the command line
seedds2026-10-24 23:09:49 +08:00
ce173001ce
NSP script: a title ID no profile has is looked up by its main build (general, from issue #114). A regional release of a build a profile registers has another title ID (Advance Wars 1+2: Re-Boot Camp's main 320a17744aefd67fec5738ca0c629795 under 0100300012FFF000 as well as 0100300012F2A000), so game.py by_title found nothing and the script surveyed it as an unknown game with a provisional profile. same_build now extracts only the code modules (nx_extract --manifest: no game files written) of the base game with its newest update, then of the base game alone, and game.py by_build looks main's build ID up in every profile's build rows; a match packs from a profile derived from that one (derive_profile), with the folder's title ID and main.npdm's program ID (the host reports that program ID and answers save data queries for it) and shaders split from the title's own files, since its RomFS may differ. The closing message says the derived build is the profile's registered build under another title ID instead of a version it was not brought up on. No two of the 56 registered main builds are in more than one profile. New test test_nsp_alias.py (by_build, the update-then-base order, the derived profile's IDs); the 44 tool tests pass. Checked: the script on Advance Wars' NSP with its title ID made to read as 0100300012FFF000 found profile 0100300012F2A000's v0 in 2 s, packed for the Mac (20,424 shaders) and the build ran 90 s headless with no red line; the real title packs as before, with no lookup. docs/development.md says so
seedds2026-10-24 23:05:05 +08:00
fa69e20a28
Compressed MonoGame XNB shaders and the Mac text box (general, from PR #120, found on Stardew Valley). shader_split.py: MonoGame's compressed XNB files, ContentCompressedLzx (flag 0x80: a CHMLib-style LZX decoder with a 2^16 window inside XNB block framing) and ContentCompressedLz4 (0x40: one raw LZ4 block), are decompressed before the readers (xnb_decompress); for LZX only the first block is decoded unless it names EffectReader. An MGFX shader whose length runs past the data is no effect (a red line in an XNB). Stardew Valley's 3,549 XNB files (3,535 LZ4, 8 LZX, 6 plain) all decode to their declared sizes, and its one content effect (Content/Effects/ShadowRemove.xnb, LZ4) is now split: 65 shaders, 64 before. Celeste's uncompressed XNBs give its profile's tables byte for byte. front_mac.m: while the text box is up the game window sees no key-up or mouse-up, so the button or click that opened it stayed pressed and was read the moment the box closed (Stardew Valley's character creation re-opened the keyboard after every OK); the keyboard buttons, the WASD stick and the touch are released when the box opens. The box also stays up, saying so, while the text is shorter than ShowKeyboardArg's minimum length (+0x3b0, hle_swkbd.c g_swkbd_min_chars), as the applet keeps OK disabled. Left out of the PR: writing the text's byte count into the String's +8. The SDK's ReadCloseResultAndString (Pikmin 4's sdk+0x39b7d0) reads String{pointer, capacity} and copies at most the capacity, and GetInteractiveOutStorageCallback restores +8 after changing it, so on hardware +8 stays the game's capacity; t_swkbd now checks it is unchanged on every path (17/17). Checked: Stardew Valley packs from its NSPs with a provisional profile and boots on the Mac to the title, and in character creation (DM_KBD) Name, Farm Name and Favorite Thing each take the text from one keyboard call and OK starts the intro, with +8 left as the capacity; the host unit tests and the 41 tool tests pass. Not checked: the Mac text box by hand (a scripted DM_KBD never shows it), and no game here asks for a minimum length. The NSP script's MonoGame survey note and docs/agents/04 say so
seedds2026-10-24 22:17:57 +08:00
fc6c0a2a11
NVN host-lent command segments sized by the request (general, from PR #121, found on Super Mario Odyssey). Odyssey 1.4.1 aborted entering the Wooded Kingdom with host-lent command segments at the 1 GB cap: it hands out many 512-byte grants from an empty pool before recording, each got a 256 KB segment, and a segment taken outside a recording has no guest range to be reclaimed by. The PR gated a 4 KB segment behind a profile key for Odyssey alone; nothing in it is Odyssey's, so hle_nvn.c hostseg_size now applies to every game: an empty-pool grant of 1 to 4 KB outside a recording gets a 4 KB segment (a recording that outgrows it JUMPs on as before), every other loan stays 256 KB, and a record larger than 256 KB with no callback gets a segment that holds it plus a JUMP's room (before, it was written past the segment's end). A free segment is taken again only for a request of its own size, the cap counts every segment's bytes (g_hostseg_bytes), and the overflow lookup matches a segment by its end too, since a small segment can end where another starts. New t_nvn case 5b'' (the request sizes, a small segment outgrown into a JUMP that replays whole through its first handle, an oversized record with OP_RESERVE after it, size-matched reuse, the byte count): 124 checks. Checked: the gfx run list, the host unit tests; on the Mac against main's host from a fresh save for 300 s each, Super Mario Odyssey (46,000 loans, a steady 18 segments of 256 KB on both) and Super Mario Bros. Wonder (no loans on either) run alike with the same single red line, and Pokémon Sword runs 80 s of frames from a save with no new red line. Not checked: the Wooded Kingdom itself (no save there) and the iPhone. docs/agents/03 says so
seedds2026-10-24 22:17:37 +08:00
46299bb3c3
Graphics tests: the whole run list passes on main again (from PR #118; tests only, no host change). Each failure was a test that no longer matched what the host does on purpose: t_reorder_chain, t_defer_chain, t_mip_extent, t_zskip and t_xv made textures with no pool at one offset, which the sharing table (g_alias) made one Metal texture, so two attachments of one pass overlapped and the validation layer aborted; each test texture now has its own storage offset. t_fuse_check set only S.prog, and the redraw takes the program again from the per-stage bindings (prog_resolve). t_mip_extent seeds and reads back through q_cb(), since new-texture zeroing is queued as an upload batch and wiped the seed, and a scissored colour clear is drawn as a triangle (clear_color_tri) that fills exactly its rectangle, which the test now checks instead of expecting nothing. t_rt_range sets DM_NVN_TBDR=1 (the depth-only pass mode and merged passes are off without it). t_refl and t_rt_range_ro print a SKIP line for each missing reflection sample instead of failing or aborting (the samples are not among Super Mario Bros. Wonder 1.2.1's shaders either; t_rt_range_ro still runs its 18 other cases). Checked: make -C dm/gfx/tests GAME=01007EF00011E000 run exits 0 on an M-series Mac
seedds2026-10-24 22:17:28 +08:00
7a029f66d9
Pikmin 4 (0100B7C00933A000, update 1.1.1, Unreal Engine 4.26.2 on SDK 10.4.8): game profile, the allocator and engine-region cuts, the SDK 10.4.8 sdk build's address-region cuts, two rewriter cases and a general nifm fix. Plays on the iPhone (IPA 10.8 GB, user). On the Mac from the boot through the title (a VP9 movie behind the logo), the main menu, a new game (the auto-save notice, players, creature activity level), the opening and its cutscenes into the Olimar prologue in play, and Continue from a save: 30 fps as on the Switch (the game steps a fixed frame time, bUseFixedFrameRate=True, and asks for rhi.SyncInterval=2), Wwise sound through its own AudioOut sink, about 2.6-2.8 GB resident and 1.7 GB of Metal allocations, no red line. patches.py: Unreal's FMallocBinned3 is made on the first allocation as in 4.27 (GCreateMalloc main+0x353f770 mallocs 0x1c38 bytes, constructor main+0x35ba610, the one store of the vtable main+0x8da4758 outside its two destructors, found from the Binned3 error strings through the relocated slots); the constructor call is cut and observation gate OBS_UE_MALLOC on the ldp x29, x30 after it hands the object the host allocator (hle_uemalloc.c, the 21-slot UE4_27 layout). This nninitStartup reserves the engine region only when -SwitchVirtualAddressSpaceSize= is absent (ldr x8,[x22,#0x130]; cbnz x8 past the default and its AllocateAddressRegion, main+0x353f564): with the argument the base stayed 0 and the first commit, AllocateMemoryPages(0, 2 MB) as the RHI started (main+0x353ff8c, 0xe03), went into Unreal's fatal error. The two orr #0xf80000000 (62 GB) are cut to mov #0xfe000000 (4064 MB) and the profile has no game_args, in Engage's 5 GB block. sdk_patches.py: the SDK 10.4.8 sdk build's AddressRegionManager is the 10.4.1 build's at the same offsets; the node area is cut to 62 MB and the 1 GB alignment of large regions to 32 MB. patch_nso.py (general): an adrp inside an exclusive window that uses x18 (main+0x43da14c: ldaxr; cmp; b.ne; adrp x10 + add; mov x18,x26; stlxr) is re-encoded for the copy's address (window_adrp), and scratch_dead accepts a ret as it does a bl (the gate sits on an epilogue, and the check reads the image after the cut, so the bl before it is a nop); both only apply where the rewrite used to stop, so every other module rewrites byte for byte as before. hle_net.c (general): a submitted nifm request stays on hold for 50 ms, then settles as unavailable, as Horizon's asynchronous request does. Answered at once, about one boot in six (3 in 4 with four Mac hosts at once) waited at the black loading screen for good: the boot state machine (main+0x1f2f0e0) sat in state 7 polling the BCAT runnable's status, whose constructor (main+0x203f3b0) starts FBCATThread and only then stores 1, and whose Run (main+0x203f510) submits the request, waits while on hold and stores 6; a thread that ran first finished before the constructor's store, which overwrote the 6. With the hold 12 of 12 boots under load reached the title. Profile: shader groups as DRAGON QUEST VII Reimagined's (15,727 distinct shaders, every one an LZ4 block in the pak's two shader code archives; all build for the Mac and iOS), pad_layout full, a prewarm list recorded on the Mac over the route above (806 lines). Checked: the NSP script packs it from the NSPs alone (Mac and iOS); after the rebase onto 0045c1d the 41 tool tests pass and the host builds. README (games table, a Mac picture of the prologue), AGENTS.md (54 -> 55), docs/development.md and docs/agents 01 / 03 say so
seedds2026-10-24 20:14:45 +08:00
0045c1dfb6
Pokémon Sword (0100ABF008968000, update 1.3.2, Game Freak's engine on SDK 7.3.2): game profile plus general changes to the shader split, the shader build, the NVN layer and HID / offline services. Plays on the iPhone (IPA 12.4 GB, user). On the Mac from a fresh save through the first boot's choices, the opening, Postwick, Hop's house, the walk to Wedgehurst and Leon's arrival, the starter choice (Scorbunny) and the first battle against Hop (won), and from a save in the bedroom through the title and out of the front door: 30 fps as on the Switch (frame time p50 33.3 / p95 about 35 ms, GPU 4-9 ms a frame on an M6, CPU about half a core), sound, 1.8 GB resident after the title and 2.4 GB after 17 minutes of new areas, 1.9 GB of Metal allocations, no red line on that route. The sdk and movie module (subsdk0) builds are Super Mario Odyssey 1.4.1's; subsdk1 is GLSLC, which main imports but never calls; no virtual address memory (a 3.13 GB heap in the 4 GB layout, mem_used 76 MB). shader_split.py: everything is in 7,699 GFPAK archives (GFLXPACK: file count at +0x10, 0x18-byte file entries of compression, length, stored length and offset; every entry LZ4, zlib and stored read too, Oodle a red line), whose BNSH entries the split now reads (gfpak_members): 3,126 shaders before, 38,361 after with the loose BNSH files and two in main. The 38 shaders still in no map at the title were Silicon Studio's YEBIS post effects: a .tfxo file (3,155 shaders, control sections each followed by its code area of control length + 0x704) in a 39.5 MB zlib stream in main (+0x1c98ed9), which tfxo_streams finds by its zlib header and the inflated file's magic (the header check inflates 4,096 bytes; 64 did not get past the first block header) and tfxo_shaders reads, single-stage programs: 41,516 shaders in all. Of the other games' mains the stream reader finds nothing, and main's loose control section reader (raw_shaders) finds nothing in this one, so every other profile's tables stay as they were. dmsh_build.py / nvn_mtl.m: the G-buffer pixel shaders write RGBA16Uint at colour 1 between two float targets, and the all-integer entry point (fs_uint, main0_u) made Metal refuse the pipeline for the float ones; a pixel shader whose outputs are partly integer bits now also has main0_m, which returns only those as integers (uint_mask_m in the reflection, 336 shaders here), and pso_desc takes it when the bound targets' integer formats are exactly those outputs (pso_mixed_uint). Chain version dec5ee141a9f. nvn_mtl.m tex_by_id: a cube view whose layer count is not a multiple of 6 (a view of one layer, as the player leaves the house) aborted in Metal; it now counts its layers in cubes when they fit, and is read as a 2D array with a red line otherwise. Packaged textures: the game writes beside its textures in the 16 KB host pages they share with other data, so each such write re-uploaded the texture, 73k re-uploads over a few minutes and frames from 33 to about 75 ms; the bytes of a texture's storage that lie in its shared first and last pages are kept after each upload (pkg_edges_take), and a dirty texture whose interior pages were not written and whose edge bytes are unchanged is re-protected without a re-upload (pkg_edges_clean; the packaged-textures log line counts them): 0 re-uploads on the route since. New t_nvn case 6c1 (writes beside a texture, then a real write), 110 checks. hle_nvn.c: nvnDeviceGetWindowOriginMode and nvnDeviceGetDepthMode, which the game reads without setting either. hle_hid.c: the Poké Ball Plus (Palma): boost mode a no-op, connection enable / disable succeed, GetPalmaConnectionHandle and every handle call fail with an invalid handle (the first boot crashed at SetPalmaBoostMode). hle_offline.c: pdm::QueryApplicationPlayStatistics answers each asked title as never played (the game asks about the Let's Go games; it crashed there next), err::ShowNetworkServiceError is logged. Profile: pad_layout full (the camera is on the right stick), shader groups bin / systemresource, a prewarm list recorded on the Mac over the route above (3,273 lines). Checked: the NSP script packs it from the NSPs alone (Mac and iOS); after the rebase onto 6d42bc9 the host unit tests, the 41 tool tests, t_nvn, t_dirty_slots, t_dirty_race, t_integer_blend, t_upgrade_alias, t_clear_ds and t_stencil_view (under validation) pass, and the route out of the house runs as before. README (games table, a Mac picture of Postwick), AGENTS.md (53 -> 54), docs/development.md and docs/agents 01 / 03 / 04 say so
seedds2026-10-24 18:45:45 +08:00
6d42bc9815
Advance Wars 1+2: Re-Boot Camp (0100300012F2A000, base game 1.0.0, Unity 2020.2.1f3 IL2CPP on SDK 10.4.1): game profile, the SDK 10.4.1 sdk build's address-region cuts and a shader split reader for control sections loose in main. Plays on the iPhone (IPA 7.1 GB, user). On the Mac from the boot through the Bink opening movie, the title, Nell's introduction, a new casual campaign and the first training battle (Field Training, Troop Orders): 60 fps in the menus, 30 fps in battle by the game's own limit (present interval 1, the frame's work 33 ms with CPU and GPU mostly idle), FMOD sound through AudioOut, about 2.5 GB resident and 1.6-1.9 GB of Metal allocations, level over a 15-minute run with no red line. sdk_patches.py: the sdk build is The Great Ace Attorney Chronicles' (no virtual address memory there, so it never needed a cut); this game's NPDM declares 16 MB of system resource and nninitStartup (main+0x365310) hands pool - used to StandardAllocator, whose Initialize (sdk+0x2edf90) aborted at boot. The AddressRegionManager constructor (sdk+0x340e90) loads the 1 GB node area with orr w8 / w9, wzr, #0x3fe00000 (the SDK 7 / 8 form, +0x340ea0 / +0x340f3c), cut to 62 MB, and AllocateAddressRegion's 1 GB alignment of regions of 1 GB and more (+0x34109c) to 32 MB, as on DRAGON QUEST XI S's SDK 7.3.2 build. Profile: the NSP script's heap check set a 1 GB pool, as for the other Unity games with virtual address memory, but the game's malloc then ran dry at the first loading screen and Unity's GPU pool allocation (main+0x96f430) halved its aligned_alloc request down to 0 and spun there (frames stopped 17 s in; found with sample on the Mac host); with 2 GB the alias region is mapped up to 2.26 GB (high-water mark +3.27 GB of 4.375) in Engage's 5 GB block. shader_split.py raw_shaders: Bink 2's Unity plugin builds its programs from 32 control sections and code areas in main's read-only segment that are in no GLSLC output and no BNSH file (2 vertex, 22 pixel, 8 compute), so the movies drew white (two shaders not in the map and a program without a vertex shader as the opening movie started). 26 are 0x20-byte records in .data ({code pointer, control pointer, u32 code length, u32 control length}, found through the relative relocations, RELA or RELR: rel_targets); the code takes the other 6 by address, their code area right after the control section's own length or right before it, and two share one; both neighbours can pass the header and length checks (main+0x4a2c670, a compute shader, would have taken the first 0x100 bytes of the next vertex shader's code), so only a code area whose address the code builds with adrp + add nearest to the control section's is taken (adrp_targets). Compute code areas have no header (SDK 10), so the stage is glslc_stage's, and a code area may not hold a control section. Control sections another reader took from main are left alone (Celeste's MonoGame effect). Of the 25 mains on the game drive the reader adds shaders only to this one, so every other profile's tables stay as they were (Celeste and the other games on the second drive not checked: not mounted). 20,424 shaders, all build for the Mac and iOS. Checked: the NSP script packs it from the NSP alone (Mac and iOS), the tool tests pass. README (games table, a Mac picture of the first battle), AGENTS.md (52 -> 53), dm/games/README.md (the heap check's 1 GB is a starting point), docs/development.md and docs/agents 03 / 04 say so
seedds2026-10-24 17:13:08 +08:00
7861e7c1a9
Stencil-only views of depth-stencil textures with the format-view usage (general, from PR #106, found on Luigi's Mansion 3): every depth-stencil texture in the NVN and Vulkan layers is made with MTLTextureUsagePixelFormatView. A stencil-mode view, a texture built in stencil mode and the depth-stencil copy read stencil through an X32_Stencil8 view of a Depth32Float_Stencil8 texture, which Metal allows only with that usage: Apple GPUs read the view correctly without it (an M4 Pro, 50 frames of a per-pixel stencil pattern at 256x256, no wrong value), but the API validation layer aborts the process at the first such view, so a validation run of Pokémon Legends: Z-A, DRAGON QUEST VII Reimagined or Luigi's Mansion 3 could not get past it. Upgrading the texture when the view appears would recreate a depth buffer in use, so the usage is set at creation (nvn_mtl.m tex_desc) and the stencil exception in tex_need_pfv is gone. The PR set it in tex_desc only; the Vulkan layer had the same gap, since Vulkan needs no mutable-format flag for a stencil-aspect view, so hle_vk.m vkCreateImage sets it on depth-stencil images too (the OpenGL layer makes no texture views). The cost I had expected when this PR was first left out (bc5ba1b: lossless compression) does not show: on an M4 Pro a 2560x1440 depth-stencil texture has the same allocated size with and without the usage, and eight load / store passes take the same GPU time (1.085 / 1.067 ms against 1.063 / 1.074 ms). New test t_stencil_view (16 checks under MTL_DEBUG_LAYER: both NVN depth-stencil formats filled with a per-pixel depth and stencil, the stencil-mode view and the stencil-built texture are views of the texture's own storage, the copy draw carries every depth and stencil value) and a stencil-aspect view case in t_vk_desc (both depth-stencil formats); with the change taken out both abort under validation, and without validation only the usage checks fail. Checked: every other gfx test gives the same result as without the change; on the Mac host against the same build without it, Breath of the Wild for 90 s from boot (60 fps, the same red line) and Super Mario Galaxy 2 for 60 s (60 fps, the same four red lines); Breath of the Wild on the iPhone with the change plays as before (user). docs/agents/04-graphics.md no longer says the stencil view needs no format-view usage
seedds2026-10-24 16:18:55 +08:00
54b91a9f14
iOS: an embedded module with an empty patch area is mapped without it (from PR #94). 87 of Super Smash Bros. Ultimate's 98 NROs have nothing to rewrite (no x18, SVC or TLS register use), so patch_nso.py writes no patch area and gen_embed.py packs a 0-byte x1 piece for them; map_image still remapped it, and vm_remap refuses 0 bytes (KERN_INVALID_ARGUMENT), which stopped the app at launch at the first such NRO, as the PR's author found on an iPhone (FATAL nro1 vm_remap ... (0 bytes) failed: 4). ff64352's iPhone run used a build from before d979c34's loader, so the merged build had not met it. Checked: loader.c compiles for iOS and the Mac with Smash's profile, and the host unit tests pass (the NRO loader test among them); not run on an iPhone (no Smash files here)
seeddsandv0lumehi2026-10-24 15:36:06 +08:00
14b68357a3
Run-time shader captures on a Mac without Metal 4 (GitHub issue #112: Balatro could not be packed on GitHub's macos-26 runner, a virtual Mac). The GL and Vulkan layers draw on classic Metal queues of their own and take only the device and the present path from the NVN layer, but mtl_device ran the NVN layer's whole start-up, which aborted on the paravirtualized GPU at the MTLResidencySet (and, past it, at the MTL4CommandQueue), so the GL capture boot stopped at eglGetDisplay and captured nothing. nvn_mtl.m mtl_init: a device without the Metal 4 GPU family, or one where the residency set or the Metal 4 queue cannot be made, now starts only the classic part (queue, shared event) when the caller came through mtl_device_classic (hle_gl.m, hle_vk.m), says so in one red line, and drops every present (present_enqueue gives ticket 0, so nothing waits on the present path), which a headless capture does not need; an NVN game still stops there, with a message naming the device and the reason. DM_TEST_NO_METAL4=1 takes the same path on any Mac. Checked on this Mac (M6): the NSP script for Balatro (--platform mac) with DM_TEST_NO_METAL4=1 captured the 35 shaders gl_capture.tsv lists in 1 s, translated them and built the Mac host; booted headless for 20 s without the switch, the host starts Metal 4 as before (35 shader table entries, no red line, graceful exit), and with the switch and the shader library the game runs the 20 s with presents dropped and exits gracefully. Not checked: the Vulkan capture (Super Mario Galaxy, Galaxy 2; same call, no NSPs here) and a real virtual Mac. docs/development.md (build step 4) says so
seedds2026-10-24 15:33:22 +08:00
bc5ba1b1c2
NVN and AudioOut fixes from PRs #105, #107, #108, #109 and #110 (general, found on Luigi's Mansion 3): no blending on integer targets, primitive restart in fan and quad expansion, partial depth-stencil clears, every name of an upgraded texture, the SDK's AudioOut fields. nvn_mtl.m pso_desc (#105): an integer colour target took the game's blend enable, and Metal refuses such a pipeline with an assertion even without the API validation layer (checked on this Mac); Maxwell ignores blending on integer targets, so it is off for them. draw (#110): indexed triangle fans and quads expanded on the CPU read the restart index as a vertex and joined the polygons across it, and the extra triangles cleared parts of Luigi's Mansion 3's cached shadow depth; nvn_primitive.h ends a polygon at the restart index (compared before the base vertex), at most as many triangles as before. OP_CLEAR_DS (#108): a depth-stencil clear whose scissor does not cover the target, or whose stencil mask is partial, cleared the whole target before the first draw, and a partial stencil mask did so in a pass too; both are drawn as a triangle now (clear_ds_tri), full clears stay load actions. Logs on the T7 show who takes the new path: Tears of the Kingdom clears 8x8 tiles of a 64x64 depth target (each clear wiped the whole target), AI: THE SOMNIUM FILES clears 1280x720 of a 1920x1080 one. tex_upgrade (#107): a texture recreated to add a usage replaced only the asking serial and one sharing-table entry, so other serials on the same storage read the old copy; every entry in g_by_serial, g_ghost and g_alias now moves to the new texture in place, g_alias_set follows, and the old one is retired after the submissions that used it. hle_audio.c (#109, reworked): the host left the guest AudioOut zero, and middleware that checks its first word before Stop / Close skipped the close, freed its PCM and the host's consumer read freed memory (SIGBUS on resume in Luigi's Mansion 3). The PR wrote 1 and cleared it on close; the SDK's OpenAudioOut (SDK 8, 12, 18 and 20 checked) writes sample rate, channel count, sample format and state at +0 / +4 / +8 / +0xc, its getters load from there, and CloseAudioOut only sets the state to stopped, so the host now writes the same (au_info). New tests t_integer_blend (63 checks), t_primitive_restart (37), t_clear_ds (43), t_upgrade_alias (10) in the gfx run list, and an AudioOut fields and lifetime case in t_audio (12 guarded open / close / unmap / resume cycles, silent sink and real output). Checked: the four new tests pass under Metal validation; every other gfx test gives the same result as on main (t_fuse_check, t_reorder_chain, t_defer_chain, t_mip_extent, t_rt_range_ro and t_rt_range fail the same cases on both; t_refl finds no reflection samples in this checkout's shader cache); the host unit tests pass; on the Mac host for 90 s from boot, against main built the same way: Breath of the Wild over the title, 60 fps and the same red lines; AI: THE SOMNIUM FILES (shaders built by the NSP script on this chain), whose 1280x720 depth clears at the start of a pass now take the triangle path too (from pass 119), 60 fps, no red line, 5 long frames against 12. Not taken from this batch: #106 (the stencil-only view of a depth-stencil texture works without format-view usage; only the validation layer asks for it, and the PR would put that usage on every depth-stencil buffer), #111 (an opt-in draft with no memory saving shown), #104 (Mac app bundle)
seeddsandJoão Karalkovas2026-10-24 14:58:04 +08:00
6034fcad89
Bayonetta 3 (01004A4010FEA000, update 1.2.0, PlatinumGames' engine on SDK 13.3.2): game profile plus general changes to the Oodle tool mode, the shader split and the NVN layer. Plays on the iPhone (IPA 14.2 GB). On the Mac from the boot through the title, a new game (Standard, Naive Angel Mode off, brightness, the auto-save notice), the VP9 opening movie and the prologue's first real-time scene and play: 60 fps in play (frame time p50 16.67 / p95 17.5 ms, GPU about 5 ms a frame on an M6), 30 where the game asks for it (title, loading screens), sound, about 2 GB resident and 3.1 GB of Metal allocations, flat after the first scene; the title is up about 15 s after launch with a warm shader cache. hle_oodle.c: everything is in 72 PKZ archives (14 GB) of DAT archives whose entries are Oodle Kraken or stored, and this main reads them only through Oodle's streaming decoder (main+0xcbc698 / +0xcbc7f8), so OodleLZ_Decompress was never linked in and its name string is not there; when a main has no such name the tool mode now finds OodleLZDecoder_MemorySizeNeeded / Create / Destroy / DecodeSome (the two functions that pass oodlelzcompressors.cpp to Oodle's error handler, the first also taking the legacy-compressor message, and the two functions between them, checked) and decodes each request with them; games with OodleLZ_Decompress take the same path as before. shader_split.py: PKZ archives (pkz_entries, pkz_jobs: every entry, decoded by the game's own decoder in the Mac host), DAT archives (pgdat_members; a file that only starts with DAT\0 but whose tables do not fit is scanned as before) and PlatinumGames' shader objects (pg_shader: VSO / PSO / CSO / HSO / DSO, a control section and a code area each, single-stage programs): 8,024 objects, all in root_000.pkz, 6,424 distinct keys; all build but two domain shaders (subgroup operations), which are never drawn. profile_guess.py turns on oodle_packs for Kraken PKZ archives, so the NSP script hands the split the Oodle host. hle_nvn.c: the engine checks each shader object's GPU code version against the driver's range (main+0xd0da20) and refused its first built-in shader, hwfillcolor.vso at 1.15, against the 1.14 the host reported (Super Mario Odyssey's SDK 7 table), so nnMain's start-up failed and the shutdown read an uninitialized pool (main+0xb8462c); a driver runs the code of its own SDK's GLSLC, so the newest version reported now follows the SDK: 1.15 from SDK 8, 1.16 from SDK 13, and at least a GLSLC the game carries, as before. Also nvnWindowGetCrop and nvnSamplerBuilderGetLodClamp, red stubs before. Profile: pad_layout full, mem_used 116 MB, shader groups core / eff, a prewarm list recorded on the Mac over the route above (678 lines). Checked: the NSP script packs it from the NSPs alone (Mac and iOS), the host unit tests and the six tool test files pass, and profile_guess.py --check gives the same results as before. README (games table, a Mac picture of the prologue), AGENTS.md (51 → 52), docs/development.md and docs/agents 01 / 03 / 04 say so
seedds2026-10-24 13:18:29 +08:00
ff64352885
Super Smash Bros. Ultimate (01006A800016E000, update 13.0.5, SDK 8.2.1): game profile, NRO modules on iOS, data.arc shaders. Plays on the iPhone (IPA 17.5 GB, all 99 DLC licences)
seedds2026-10-24 13:08:34 +08:00
066f2afc76
Pokémon Legends: Z-A's GPU page fault and crashes (GitHub issue #101): image atomics that are not followed go to a scratch buffer as large as the image, and the transform feedback draw ends the copy encoder before it opens its own
seedds2026-10-24 12:43:34 +08:00
d979c346b9
Integrate demand-first PSOs, far-base tracing and NRO loading
f596c75012
Taiko Risshiden V DX (0100346017304000, update 1.1.1, Koei Tecmo's KTGL on SDK 12.3.3): game profile plus two general host changes. Plays on the iPhone by touch (IPA 3.3 GB, Japanese; the game has no English). On the Mac from the notice, the logos and the opening movie through the title, a new game (1560, Kinoshita Tokichiro) with its opening story, the town, a council with a battle proposal, the territory map, a rest at home, a save and a load, and the field battle tutorial, docked with buttons and in handheld mode by touch: 60 fps (frame time p50 16.66 / p95 16.85 ms in the town), sound, about 0.7 GB resident and 1.6 GB of Metal allocations, flat over 15 minutes, no red line on that route. hle_oe.c: oe::SetCpuOverclockEnabled, the first boot's crash (nnMain at main+0x2e1e4c; the SDK's setter reads the apm session the host never opened, null read at sdk+0x362b8, as IsCpuOverclockEnabled did for Monster Hunter Rise); the host keeps the flag and the query reports it. hle_touch.c / hle_hid.c: gestures for hid::GetGestureStates, which answered no entries: the game takes its taps, drags and flicks only from there (main+0x42f1ac acts on types 5-9; its GetTouchScreenState read only tracks the finger), so no tap registered in handheld mode. The host now recognizes them from the same touch points, only in handheld mode as touches, by yuzu's rules (Touch, Press after 0.5 s, Pan, Pinch / Rotate, Cancel on a change in the finger count, then Tap with IsDoubleTap within 0.35 s, Swipe above 400 px/s or Complete, and Idle) plus an 8 px slop before a touch counts as moving, since a fingertip on a phone wobbles; DM_TOUCH_LOG=1 logs the entries, and a DM_CTL line drag <x0> <y0> <x1> <y1> [seconds] moves a finger for testing pans and swipes on the Mac. New unit test t_gesture (43 checks: tap, double tap, slop, slow pan, swipe, press, finger-count cancel, pinch, a press and lift between two reads). Profile: op_mode handheld and pad_layout touch (the Tap layout: the gamepad's corners would cover the cards, the menu icons and the on-screen B button; the layout button brings it back), shaders from eff/ (167 in the G2S container KTGLEffect.g1s, _S2G3000, and 45 GLSLC outputs in main, read by the existing splitter), a prewarm list recorded on the Mac over the route above (18 lines). patches.py: KTGL's frame end (main+0x443e8c) slept in 2 ms rounds until 1/60 s had passed since the frame started, which with about 2 ms of work ended at 18.2 ms: 55 fps in the menus and the town, every 11th frame on screen two vsyncs. The game presents at interval 1, so a cut on this build skips that wait (b.hs → b at main+0x443fd4) and the host's present pacing holds 60; wakeups 2,050 → 320 a second, CPU energy 1.7 → 0.7 mJ a frame. Checked: the NSP script packs it from the NSPs alone (Mac and iOS), the host unit tests and the four tool test files pass. README (games table, a Mac picture of the town), AGENTS.md (49 → 50), docs/development.md and docs/agents/03-bringup.md say so
seedds2026-10-24 11:29:59 +08:00
3eb1d76f5d
Add game rumble for iPhone and Apple game controllers
seedds2026-10-24 11:02:21 +08:00
ea3ed8690b
dm/gfx/tests/.gitignore: the binaries of t_readback (PR #98) and t_linear_readback (PR #97)
seedds2026-10-24 09:17:54 +08:00
43b35a689e
Present: commit the residency set after resolving the presented texture, for every game. Super Smash Bros. Ultimate 13.0.5 presents its window texture in its first frames before drawing into it; the texture was made on that first resolution in the present path and joined the residency set (res_add), which only a submission commits, so the display command buffer sampled it outside the committed set: kIOGPUCommandBufferCallbackErrorPageFault at the first presents, after which macOS ignored every command buffer of the process (194 command buffer and 174 upload errors in the user's run) and the window stayed pink. Headless runs never present, which is why they looked right. res_commit is free when nothing changed. Smash windowed now: the opening movie, the DLC first-boot screens, the title, the main menu and a first match render right, no GPU error. Breath of the Wild windowed with only this change on the sync-lag branch its libraries match: its title, 60 fps, no GPU error. docs/agents/04-graphics.md says so
v0lumehi2026-10-23 21:19:28 +02:00
9cb7af3237
up_begin hands the encode thread what is recorded before it waits for a busy upload slot: the slot's last batch could still be an uncommitted record
arielherselfandClaude Opus 5.52026-10-24 04:51:24 +08:00
6de59702ec
ROMANCE OF THE THREE KINGDOMS 8 REMAKE (0100C2A01A730000, update 1.1.3, Koei Tecmo's KTGL on SDK 17.5.3): game profile plus three general changes. Plays on the iPhone with a controller (IPA 16.8 GB); on the Mac from the logo movie, the intro and the title through a new game (the recommended setup, the opening story), the council, espionage, a month's missions, the 3D city view, a visit, a practice duel in 3D and a save and load, at 30 fps as on the Switch with sound, about 2 GB resident in the council and 2.5 GB in the duel, flat on a screen left idle. nx_extract: the update is a multi-program patch, the game's patch (…0000) beside a whole second program (…0001, 34 MB, its own Control NCA) that main starts with nn::oe::ExecuteProgram(1); nx_extract took the first Program NCA, the second program, and stopped with "NCA section 1 does not exist" layering it over the base game. It now takes the base NSP's lowest title ID (program index 0) and the update's Program and Control NCAs of that title ID (Balatro and Mario Kart 8 Deluxe extract as before; the host runs program 0 only). shader_split.py: a newer RDB than Age of Calamity's, 296 .fdata files (PDRK0000 and u64 0x10, then IDRK entries) beside data/*.file; flag 0x400000 marks chunks of a new form (u16 stored length, 8 bytes, the stream; a zero length ends; 16 KB inflated at most), LZ4 blocks with 0x100000 too, zlib otherwise; every other flag value is read as before. All 51,655 entries (49,620 LZ4, 2,026 zlib, 9 stored) inflate to the length in their header. The shaders are G2S (_S2G5000 / 6000 / 7000) and _DOK0000 containers again: 59,214 GLSLC outputs there and 149 in main (149 before the change), all built for the Mac and iOS. hle_audren.c: SDK 17.5.3's OpenAudioRenderer with an event calls the form without one through the PLT (sdk+0x1e489c), which the loader binds to the host's hook, so ar_open ran twice for one renderer: the inner call started the render thread before the event existed and the outer one logged a second renderer; the inner call (t_in_open) now goes straight to the SDK. Profile: pad_layout full (the dialogue boxes' auto and log buttons are the right stick and R3; the game reads a USB mouse, not the touch screen), mem_used 80 MB, a prewarm list recorded on the Mac over the route above (451 entries). Left as is: three shaders get textures of another type on some slots (texture type mismatch, once each), with nothing wrong on screen. Checked: the NSP script packs it from the NSPs alone (Mac and iOS shaders, 1 h 19 min and 1 h 29 min on a 12-core M6), the four tool test files pass (34 tests), profile_guess.py gives the profile's memory keys. README (games table, a Mac picture of the duel), AGENTS.md (48 → 49), docs/development.md and docs/agents say so
seedds2026-10-24 08:29:17 +08:00
ebe75c9d5d
test_xcode_workflow.py: the provisional-warning test calls report_profile_status with its artifact name ('Xcode project'), the argument 98a91a6 (--platform mac) put in place of prepare_xcode; it failed with a TypeError since. The five tool and workflow test files pass (37 tests)
seedds2026-10-24 01:52:16 +08:00
c392d56af0
Balatro (0100CD801CE5E000, update 1.1.3, LÖVE 11.4 "love-nx" with LuaJIT and SDL on SDK 18.3.2): game profile and the GL layer LÖVE needs, plus four general changes. Plays on the iPhone by touch; on the Mac from the intro and the title into a run and its tutorial, at 60 fps with sound, about 0.65 GB resident and flat over three minutes. The game is Lua source in the RomFS and renders with NVIDIA's desktop OpenGL through EGL, as Digimon does. GL layer (dm/gfx/gl/hle_gl.m): LÖVE reads GL_CONTEXT_PROFILE_MASK and takes its core-profile paths only when it says core (with a compatibility profile it streams vertices from client memory, which Metal cannot draw from), so the layer answers core and implements what those paths use, about 150 functions in all against Digimon's 79: persistently mapped buffers (glBufferStorage, glMapBufferRange: the shared MTLBuffer's own memory), glBufferSubData in command order, fences (a fence is the serial of the command buffer being recorded; a wait on one still recording commits it), glBindAttribLocation (the game's attribute index of each Metal input, set at the link) and current attribute values (glVertexAttrib4f: LÖVE's VertexColor and ConstantColor are disabled arrays), glGetActiveUniform and the uniform read-backs, every glUniform* form, glTexStorage2D / 3D with their level counts, 3D and 2D array textures (LÖVE makes a default of each type on 96 units), GL_TEXTURE_SWIZZLE_* (its font glyphs are RG8 read as R, R, R, G), glGenerateMipmap as a blit (the game's images are mipmapped), instanced and base-vertex draws, separate read and draw framebuffers, glBlitFramebuffer (colour, same size), glReadPixels, glClearBufferfv, glFrontFace and the EGL calls SDL makes; stack arguments of the functions with more than eight are 64-bit, as AAPCS64 lays them out. DM_GL_STUBS=1 gives every GL name the layer lacks a stub of its own that reports its first call, instead of a null pointer. Shaders: LÖVE puts its 35 GLSL sources together at run time in Lua, so the NSP script captures them on the Mac as it does Super Mario Galaxy's SPIR-V (capture_shaders now serves both, profile gl_capture.tsv; profile_guess.py's gl_capture rule: an OpenGL game with no GLSL source in its RomFS or main), and gl_shaders.py keeps a bool uniform's declared type (a uint in SPIR-V; LÖVE's Shader:send takes only a boolean for a bool) and takes from main only strings that start with '#version <number>' (Balatro's main has glslang's messages). General: profile_guess.py leaves vkGetInstanceProcAddr, SDL's Vulkan loader, out of its Vulkan count (Balatro's provisional profile said Vulkan; Hades and both Galaxies import 99 or 100 Vulkan functions); OpenAudioRenderer without an event now starts the host's render thread too (hle_audren.c ar_open: only the form with an event did, and such a game was silent); loader_census.py follows registers in a straight line (adrp, add, loads through relocated GOT entries, mov, csel), for LÖVE's glad, whose pointers are globals its code keeps the addresses of in registers; and the iPhone gamepad has a third layout, Tap (profile pad_layout touch, which needs op_mode handheld; DM_GAME_PAD_LAYOUT replaces DM_GAME_PAD_FULL): no control but the layout button, every touch to the game, offered in the layout cycle only in handheld mode. Profile: op_mode handheld (the Switch build plays by touch there), pad_layout touch, gl_capture.tsv. A Lua error makes Balatro quit (its Switch error handler), and love-nx's video worker is then deleted twice (main+0x339c00): the bring-up notes say how the errors were found. Checked: the NSP script packs it from the NSPs alone (the capture in under a second, 35 shaders for the Mac and iOS, an 82 MB IPA), tool tests pass, profile_guess.py --check changes no other profile; Digimon was not rerun (its files are not on hand). README (games table, a Mac picture of the title), AGENTS.md (47 → 48), docs/development.md, docs/agents and the READMEs of dm/games and dm/gfx say so
seedds2026-10-24 01:49:33 +08:00
4e91a3d053
Readable-tile variants compile again for pixel shaders with an integer-output entry point (main0_u), from PR #83seeddsandv0lumehi2026-10-24 01:36:50 +08:00
76545a58a7
Mac: each controller is a player of its own, for local co-op (GitHub issue #74), from PR #84seeddsandv0lumehi2026-10-24 01:11:57 +08:00
98a91a6749
NSP script: --platform mac (PLATFORM = 'mac') builds only what running a game on this Mac needs, from PR #82seeddsandv0lumehi2026-10-24 01:11:50 +08:00
e98a11562a
shader_split.py reads GLSLC outputs of several stages: Baba Is You (01002CD00A51C000, no profile) keeps its shaders as 120 GLSLC outputs in RomFS/Assets.dat, each a pixel and a vertex shader compiled together, then a reflection section, and glslc_shaders took only outputs of one control section, so the NSP script's split found 0 shaders and the pack stopped one step later with "no iOS shader libraries". An output with more than one control section is now read by its section headers (glslc_section returns every GPU code section, glslc_program checks each stage and needs distinct stages); its stages are labelled #GLSLC@<offset>#var, so var_pairs pairs them with each other and separable_pairs leaves them out of the single-stage cover. The NSP script stops at the split when it finds no shader, with the reason, instead of at the iOS shader step. Checked: Baba Is You splits into 131 shaders (115 pixel, 16 vertex) and 115 pairs, and its pack built BabaIsYou.ipa from the provisional profile with 131 of 131 shaders ready (not run on an iPhone); the split's tables for 13 Sentinels, AI: THE SOMNIUM FILES, Raging Loop, Metroid Dread and Age of Calamity are byte-identical to their profiles', and no main on the game drive holds an output of several stages. docs/agents/04-graphics.md says so
seedds2026-10-24 00:47:43 +08:00
a6787033eb
Mac, in fullscreen: a screen whose refresh rate is not a multiple of the game's frame rate switches to one that is (144 → 120 Hz), from PR #79seeddsandv0lumehi2026-10-24 00:39:05 +08:00
86d9ba1239
One translation chain version for every game: DMSH_CHAIN in dm/gfx/nvn/dmsh_chain.h replaces the 47 dm/games/<id>/dmsh_chain.h, which every chain change rewrote and some were left behind (GitHub issue #78). The version hashed each profile's shader tables and nvn_* / shader_* keys too, once the only thing that kept the host off a library built from older tables; each shader's cache key (dmsh_build.py shader_key) has covered them since, so the version now covers only the chain's tools (dmsh_chain.py, dmsh_build.py, dmsh_fetch.py, dmsh_vin.py, dmsh_geometry.py, dmsh_facts.py, the translator's source, ios_metal.py, the lock) and the options, and needs no DM_GAME. What the per-game part still did is done by the library itself: a full dmsh_build.py run stamps b-<V>/inputs.tsv (Mac and iOS) with the game and the digest of the profile's inputs (dmsh_chain.py inputs / --inputs: the four shader tables, bf_want.tsv, which the variants use but the version never counted, and the keys), starts from no shader outputs (a partial one from none of the keys it builds), so a key that left the map, a shader that no longer builds or a variant no longer made keeps no old library, refuses a directory stamped for another game, and writes the profile's c1_full.tsv and cb_extent.tsv from its Mac outputs; a partial build keeps the stamp only while it names the current inputs. c1_guard.py / cb_extent.py head their table with the library's chain version and stamp (table_head), and the host takes a table only beside that stamp, logs the stamp and reports one of another game; build_ipa.sh reads the one header and stops when the iOS libraries' stamp is not this profile's current inputs or c1_full.tsv names another. NSP script: chain_header writes the one header when stale, before any host is built; provisional and derived profiles no longer write one; chain_tables makes a table again when it does not name the reused library's stamp (False without one). Makefiles take the header beside nvn_mtl.m; Xcode projects prepared earlier point at a profile header that is gone and are told to prepare again. Tests: test_nsp_chain.py (the committed header is current, stale and missing ones are written, tables against the stamp). Checked on The Great Ace Attorney Chronicles: a full build gave 460 of 460 shaders and both tables (0 and 409 entries, as before), the Mac host booted with the stamp and both tables past frame 900; one added facts row rebuilt one shader under the same chain version with a new digest and new tables, and the host refused the old tables beside the new stamp; a full build removed planted outputs, another game's build into that directory stopped, a partial build after an input change dropped the stamp; build_ipa.sh stopped on a stale stamp, a missing one and a stale or old-form c1_full.tsv; three NSP packs built (no table lines: dmsh_build made them), reused everything, and remade deleted tables from the reused build. Graphics unit tests give the same results as before (on this Mac t_refl needs ~/dm-work's libraries and several GPU tests fail on the previous commit too). AGENTS.md's chain procedure (header once after a tool change; a full shader build makes the tables), dm/games/README.md, dm/gfx/README.md and docs/development.md say so
seedds2026-10-23 23:37:03 +08:00
f4f0a85d6e
patch_nso.py split into the general rewriter and per-build patch files (GitHub issue #63): every game's bring-up edited the one file, so PRs for unrelated games conflicted. dm/tools/patch_nso.py (1,711 → about 1,100 lines) keeps the general passes and the driver; the instruction encoders move unchanged to dm/tools/nso_asm.py; a game's own patches (CUTS, OBS and the frame-step stubs, now FRAME_STEP = {build ID: stub(ctx)}) move verbatim with their comments to dm/games/<id>/patches.py (16 profiles: Tears of the Kingdom, Breath of the Wild, Age of Calamity and Paper Mario: The Thousand-Year Door with their stubs), and the cuts of Nintendo's sdk module builds, 6 of the 15 shipped by 2 to 4 games, to dm/tools/sdk_patches.py. The rewriter loads every patch file, whatever the game, and applies those of a module's build ID at the points it did before (cuts before the scan, gates after the rewrite, stubs after the gates); a build ID claimed twice stops it, and its command line needs no DM_GAME. build_src.sha256 lists the rewriter's files and every patch file (the same for every module). NSP script: the rewrite step's reuse key counts nso_asm.py and only the patch files that name one of the game's builds (patch_files), profile_files leaves patches.py out (only the rewrite step reads it), and a derived profile gets none. dm/tools/tests/test_patches.py: no build claimed twice, the entries' forms, a game's file names only its own profile's non-sdk builds, sdk_patches.py only sdk builds some profile ships, and the reuse key's patch files. Checked byte-identical: every extracted module on the game drive (131 builds) rewritten with the previous and the new rewriter gives the same outputs but build_src.sha256, 28 of the 30 patched builds among them (all four frame-step mains), and 7 fail alike (rtld, and New Super Mario Bros. U Deluxe's, which no profile rewrites); the other two (Super Mario Bros. Wonder's mains and Absolum's, no game files here) by their CUTS / OBS data, equal to the previous tables. AGENTS.md, docs, dm/games/README.md, the profiles' comments and the host comments that named a game's cut in patch_nso.py now name its patches.py or sdk_patches.py
seedds2026-10-23 23:36:21 +08:00
4c7adf4619
c1_full.tsv and cb_extent.tsv are no longer committed: each checkout makes them from its own shader build's Mac outputs (git ignores them in dm/games/*/), as the NSP script does after its iOS shader build. They follow from the MSL this Mac built, every chain change rewrote about 90 of them, and 56704a0 could only carry most over unchecked; 81 files, 18.7 MB. The NSP script makes a missing one as a stale one (chain_tables now says whether both name the chain: with no Mac outputs a reuse builds again and a build stops), and no step's reuse key counts them (profile_files), so the run after they were made does not split again. build_ipa.sh stops for an NVN game whose c1_full.tsv is missing or names another chain, with the c1_guard.py command, before generating anything (the host would give every c1 its own 64 KiB). Checked on The Great Ace Attorney Chronicles from a checkout without them: the first pack made both (0 and 409 entries, as committed), the second reused the split and the iOS shaders with no table lines, a third with them deleted made them from the reused build's Mac outputs; build_ipa.sh stops on a missing and a stale c1_full.tsv. AGENTS.md's chain procedure, dm/games/README.md, dm/gfx/README.md and docs/development.md say so
seedds2026-10-23 22:24:10 +08:00
a2e6f4a18c
NSP script: a registered profile's chain files that a chain change left behind are made again (GitHub issue #78: after bb585cd, 45 of 47 profiles' dmsh_chain.h no longer held the version their source gives, and Breath of the Wild's pack stopped at dmsh_build). chain_header writes dmsh_chain.h again, before any host is built, when it does not hold the version dmsh_chain.py gives (it follows from the source alone; a current one is left untouched, so the host is not rebuilt). chain_tables makes c1_full.tsv (c1_guard.py) or cb_extent.tsv (cb_extent.py) again from the build's Mac outputs when its header names another chain, which the host would ignore (every c1 its own 64 KiB, whole uniform bindings copied), also when the libraries are reused; provisional and derived profiles make both as before. The two tables are the shader step's outputs, so its reuse key no longer counts them. Tests: dm/tools/tests/test_nsp_chain.py (stale, missing and current headers and tables), and chain_tables with the real tools on Breath of the Wild's Mac cache (47 s, the committed list's 2 entries)
seedds2026-10-23 22:11:08 +08:00
56704a0be1
Super Mario Galaxy 2's half-white Mario on the iPhone (GitHub issue 72): min / max / clamp with a NaN operand give the other operand on every GPU, in the Vulkan, GL and NVN shader chains
seedds2026-10-23 22:07:37 +08:00
11be43d882
README / AGENTS: Mario Kart 8 Deluxe plays on the iPhone (games table with a Mac picture of Mario Kart Stadium's anti-gravity section, IPA ~11.9 GB, Mii heads not drawn without the firmware; AGENTS.md list 46 → 47 with its notes; the profile says so). On an A20 Pro: 60 fps docked, about 6 ms of GPU time a frame, 2.4 GB footprint with 3.7 GB of headroom, no audio underruns
seedds2026-10-23 20:37:01 +08:00
6ec201c756
Mario Kart 8 Deluxe (0100152000022000, update 4.0.0, Nintendo's sead / agl / gsys on SDK 4.4.0, the oldest SDK so far): game profile and five general changes. Plays on the Mac and an iPhone from boot through the title's demo race, the Mii pick and the menus into Grand Prix races at 60 fps with sound, and a second boot loads the save. The Mii database (hle_mii.c: the six default Miis every console has, which the game lists at boot without reading the count, none of the console's own, random Miis for the demo race, the editor cancelled) and a MiiModel system data stand-in (0100000000000802 mounted as MiiResource:, written by the host with the layout main's Mii renderer reads: no textures and every shape one degenerate triangle, because the faceline is drawn without a check; the firmware is not the host's to ship, so Mii heads draw nothing). The add-on content cache sized as Horizon's RomFS working memory (its licence is decrypted in a 0x3130-byte heap that also holds the 4 KB the host used to answer). Device save data as a save of its own when main also imports MountSaveData (at boot the game deletes CommonSave:/userdata.dat, which in the shared directory was UserSave's; Animal Crossing, device save only, keeps its island where it was). SDK 4's DeviceSink (command 0xf, 0x130 bytes, byte input indices) and the audio renderer's update lock read off each SDK's own AudioRenderSystem::Update (LockMutex +0x1d0 / +0x1d8, SdkMutexType +0x1d8 / +0x1f0 / +0x1f8: it was SDK 16's for every SDK before 20; sound checked on Big Brain Academy and DRAGON QUEST XI S). The zero cube for a 2D array of fewer than six layers in a cube slot. Profile: render_cond on, a recorded prewarm list from boot into the first race; Breath of the Wild and Animal Crossing boot with their DLC caches resized, host unit tests pass
seedds2026-10-23 20:36:56 +08:00
eab15b5a7e
Merge remote-tracking branch 'origin/main' into codex/geometry
seedds2026-10-23 16:30:55 +08:00
7af6fedaad
README / AGENTS: AI: THE SOMNIUM FILES - nirvanA Initiative plays on the iPhone (games table with a Mac picture of the first investigation, IPA ~11.6 GB; AGENTS.md list 45 → 46 with its notes; the profile says so)
seedds2026-10-23 16:21:56 +08:00
0c03385dd9
AI: THE SOMNIUM FILES - nirvanA Initiative (0100713016CCC000, update 1.0.2, Unity 2020.3.30f1 IL2CPP with FMOD, SDK 13.3.5): game profile and three general changes. Plays on the Mac from boot through a new game into the first investigation (the Amabie-TV quiz, its conversation, camera and answer button tutorials) at 60 fps with no red line over 15 minutes; not yet run on the iPhone.
seedds2026-10-23 16:04:58 +08:00
3f73710bd6
NSP script: cli() restores os.environ after each run. main points DM_GAMES_DIR (and, for --provisional or a derived profile, DM_GAMES_FIRST) at the run's own profile folder for its tools, and Spyder runs the next F5 in the same process: the game lookup (game.py by_title) then found that profile and took it for a registered one. ASTRAL CHAIN's second run printed its profile without (provisional), skipped provisional_prep and the chain header, took the split tables as checked, and stopped at the iOS shaders with FileNotFoundError on the profile's dmsh_chain.h; after a derived build the next run would have packed from the derived profile in place of the game's own. Two runs in one process now both take the provisional path and leave the environment as it was; the progress tests pass
seedds2026-10-23 15:59:45 +08:00
7ca41c61f4
Rewriter: an offset jump table whose base was set more than 256 instructions back (ASTRAL CHAIN 1.0.1 main+0x6db4a0, SDK 6: cmp w18,#5; b.hi; ldrsw x18,[x24,x18,lsl #2]; add x18,x18,x24; br x18). The function's first block loads six table bases with adrp + add into registers its loop keeps (x24 441 instructions before this load) and a later block one more (x3, 549 before the load at +0x6db70c); jump_offsets followed the base's writer chain 256 instructions back, and the rewrite stopped with jump table 6db4a0. Where nothing writes the base in those 256, its last attempt (far_base) follows the chain to the function's start (table_base far), through no call when the base is caller-saved, and accepts the table only when every target is an instruction of the function. The function-wide search jump_adr_offsets uses for a hoisted base (the one adrp + add pair that fits) finds two for x3 there, the other the local table of a br x17 further on. Three of that main's five br x18 sites need it, their targets checked by hand; main and sdk rewrite. It runs only where every other form has failed: the Tears of the Kingdom, Age of Calamity, Cuphead, DARK SOULS: REMASTERED, Luigi's Mansion 3 and Metroid Dread mains come out byte-identical (patched image and site list)
seedds2026-10-23 15:44:16 +08:00
aea97ec65f
Add ANIMAL WELL port verified on iPhone
seedds2026-10-23 15:14:51 +08:00
e20eb1ff0d
README / AGENTS: AI: THE SOMNIUM FILES plays on the iPhone (games table with a Mac picture of the first investigation, IPA ~8.3 GB; AGENTS.md list 43 → 44 with its notes)
seedds2026-10-23 15:04:03 +08:00
fa7ad177cf
AI: THE SOMNIUM FILES (010089B00D09C000, update 1.0.1, Unity 2017.4.17f1 IL2CPP with FMOD, SDK 6.4.2): game profile (no system resource, a 3.11 GB heap in the 4 GB layout, mem_used for the rewritten modules, docked, 3D pad layout for the investigation's view on the right stick, 13,057 shaders from its AssetBundles with Cuphead's Unity 2017.4 layout, a prewarm list from boot to the first investigation) and two general host fixes. Movies: a released output slot also goes on with an H.264 drain, and the end-of-stream packet's own output takes the first queued picture (hle_movie.c); Unity held all 16 video outputs when the Spike Chunsoft logo movie's end-of-stream packet came, the last pictures and the end-of-stream flag never came out, and the game waited before its title for good (Raging Loop's opening movie still ends and reaches its title). Per-stage programs: each restore of the replay state takes the combined program again from the per-stage bindings (nvn_mtl.m prog_resolve); the precompile prediction over a 280-draw submission reused the ring slot the saved state named, and the draws after it ran another pair's shaders (a pipeline Metal refused, VertexLit's shadow vertex shader with BG_AlphaTest's pixel shader, and a cube / 2D texture mismatch; 2 of 2 old-host runs from one save, 0 of 2 fixed). Plays on the Mac from boot through a new game into the first investigation at 60 fps, 2.27 GB resident, and on the iPhone
seedds2026-10-23 15:03:57 +08:00
1822616144
Intel Macs (GitHub issue #54): the shader translator's launcher dm/gfx/tools/dmsh_xlate_bin/dmsh_xlate is a universal binary (arm64 and x86_64, the same .NET 10.0.13 host joined with lipo); it was arm64 only, and the NSP script stopped at dmsh_build with Bad CPU type in executable. The lock does not cover the launcher, so the chain version is unchanged. The x86_64 translator under Rosetta gives byte-identical output (Raging Loop, 452 shaders; Ryujinx's constant folding uses only exactly rounded arithmetic). The Mac host runs the game's own arm64 code, so on an Intel Mac a step that boots the game there (a run-time shader capture, a decode with the game's own Oodle or LZ5) stops with a plain error, and a provisional profile's heap check is skipped (build_ipa_from_nsp.py apple_silicon)
seedds2026-10-23 14:42:50 +08:00
7deea8eedc
Tears of the Kingdom: the SDK's address-region node area cut from ~1 GB to 62 MB on the sdk build it shares with Breath of the Wild 1.9.0 (patch_nso.py). The game's resource heaps are address regions in the 2.375 GB alias region; at the first descent from the Great Sky Island it was used up to +2.25 GB with 1.00 GB mapped, and the game took a memory shortage (MSF / R / Rf) and played the memory-shortage Blood Moon, which put Link back at the start (GitHub issue #70; 7 of 8 Mac runs from the issue's save). With the cut: +1.75 GB, no shortage in 3.7 minutes on the island. Probe tools: the write watch reports exclusive and atomic stores, and DM_PROBE_POLL snapshots every thread when a word changes
seedds2026-10-23 14:13:48 +08:00
0923c713d0
README: drop the project's former name from the d2r-mobile credit
seedds2026-10-23 13:58:24 +08:00
1482e123a8
Vulkan layer: a descriptor holds the Metal objects it was written with (texture, sampler state, buffer and offset, retained), not pointers to the layer's view / sampler / buffer structs. A set may still name a view the game has destroyed while the replay binds every element of an array the shader takes: Super Mario Galaxy 2 crashed in bind_res reading a freed image view's texture (element 1 of its 8-texture array) when the ship took off after the first galaxy (GitHub issue 68). New test t_vk_desc (make run)
seedds2026-10-23 13:44:13 +08:00
b3d9b24be7
NSP script: the iOS shaders build with the Mac's own Metal compiler and spirv-cross (dm/gfx/tools/own_compilers.py), one note line naming any that differ from dmsh_chain.lock; the translator must still match, and the lock and chain version stay as they are, so a player on another Xcode (GitHub issue #26: Xcode 27.2 beta, metal 32023.922) or a newer spirv-cross needs no --update-lock; a Metal toolchain that does not run is reported before the build (xcodebuild -downloadComponent MetalToolchain)
seedds2026-10-23 13:33:10 +08:00
a08bbdd3ba
Texture views from GitHub PR #66: mip counts cut to the texture's levels, and the swizzle composed with the format's own channel mapping (Echoes of Wisdom's hearts); the red / blue swap only for uploaded textures, image slots without the mapping
seeddsandnocmt2026-10-23 11:10:31 +08:00
f73c1e3ec6
iOS launcher: no notes under the settings
seedds2026-10-23 10:54:26 +08:00
fe23c10307
Audio watchdog: the time is read under g_aos_lock, so an AudioUnit just restarted on the return from the background is not restarted again
seedds2026-10-23 10:33:34 +08:00
2f69480260
iOS launcher: a settings screen before the game starts, drawn from one table of player-facing settings (dm/games/settings.tsv; GitHub PR #62, issue #64)
seeddsandv0lumehi2026-10-23 10:22:42 +08:00
8a4b1dc820
Faster NVN → Metal translation from GitHub PR #62: Metal encoding on its own thread (on by default on iOS), uniform shadows copied by a worker, uniform updates kept across render passes
seeddsandv0lumehi2026-10-23 09:28:55 +08:00
e454ac912a
Luigi's Mansion 3 plays on the iPhone: README games table, AGENTS.md list
seedds2026-10-23 08:38:28 +08:00
626e6a6188
Luigi's Mansion 3 plays on the Mac at 60 fps: profile 0100DCA0064A6000 (update 1.4.0, SDK 7.3.2)
seedds2026-10-23 08:33:56 +08:00
8d175f8d24
FINAL FANTASY RESONANCE plays on the iPhone: README games table, AGENTS.md list
seedds2026-10-23 07:25:33 +08:00
2000f9274a
FINAL FANTASY RESONANCE plays on the Mac at 60 fps: profile 0100606026F12000 (update 1.0.1, SDK 20.5.17)
seedds2026-10-23 07:22:06 +08:00
0b3c7b1200
Tears of the Kingdom's crash in mtl_exec after minutes of play (GitHub issue #61): a command memory link never writes past what GetCommandMemoryUsed reported
seedds2026-10-23 02:45:50 +08:00
8b4db4153e
DRAGON QUEST VII Reimagined at 60 fps (30 on the Switch): profile fps_target 60
seedds2026-10-23 02:15:45 +08:00
e10277be9a
Movies: 5.1 Vorbis sound decodes right, as stb_vorbis's type-2 residues span every channel of their submap (GitHub PR #60)
seeddsandohxiaoguang2026-10-23 01:10:18 +08:00
6da1882871
NSP script: --prepare-xcode makes a per-game Xcode project to sign and run with your own developer account (GitHub PR #59)
seeddsandAnimax Deng2026-10-23 00:37:52 +08:00
1c584dc3e9
DRAGON QUEST VII Reimagined plays on the iPhone: README games table, AGENTS.md list
seedds2026-10-23 00:05:08 +08:00
e72a06510e
DRAGON QUEST VII Reimagined plays on the Mac: profile 0100A9D01C446000 (update 1.2.0, SDK 19.3.1)
seedds2026-10-22 22:25:08 +08:00
7bb270cccc
Animal Crossing: New Horizons plays on the iPhone: README games table, AGENTS.md list
seedds2026-10-22 22:42:50 +08:00
c2750b89b8
Animal Crossing: New Horizons plays on the Mac: profile 01006F8002326000 (update 3.0.3, SDK 20.5.4)
seedds2026-10-22 22:41:39 +08:00
1765d53aba
Shared fonts: LoadFont gets the TTF when a game hands it the host's BFTTF header (GitHub PR #55): The Legend of Zelda: Echoes of Wisdom imports Decode but loads its shared fonts without it
seeddsandnocmt2026-10-22 21:15:31 +08:00
d5b380b3a8
Digimon Story Cyber Sleuth: Complete Edition plays on the iPhone: README games table, AGENTS.md list
seedds2026-10-22 20:48:44 +08:00
26231779dd
Digimon Story Cyber Sleuth: Complete Edition: the chain header for the current chain version; the survey's notes know OpenGL games
seedds2026-10-22 20:48:44 +08:00
298fa96f0b
Digimon Story Cyber Sleuth: Complete Edition plays on the Mac: profile 010014E00DB56000 (update 1.0.3, SDK 6.4.0), an OpenGL layer on Metal (dm/gfx/gl), its GLSL translated offline (gl_shaders.py), MVGL archives (mvgl.py)
seedds2026-10-22 20:42:38 +08:00
1eaaab88ca
Breath of the Wild's sky is blue again (GitHub issue #52): every game fills a texture from storage it flushed before the texture's first use
seedds2026-10-22 19:16:35 +08:00
e0cbc7bb2c
Catherine: Full Body plays on the iPhone: README games table, AGENTS.md list
seedds2026-10-22 18:49:44 +08:00
2bdad7d19c
Catherine: Full Body plays on the Mac: profile 0100BF00112C0000 (update 1.0.1a, SDK 8.2.1)
seedds2026-10-22 18:46:51 +08:00
4847d88c6a
README: DLC is optional, as the update is
seedds2026-10-22 18:26:29 +08:00
afa99e5831
NSP script: the update is optional and any version builds (a derived profile for versions the profile was not brought up on)
seedds2026-10-22 18:25:12 +08:00
e18a9fdc21
Hollow Knight: Silksong plays on the iPhone: README games table, AGENTS.md list
seedds2026-10-22 17:51:13 +08:00
33aa059ade
Hollow Knight: Silksong plays on the Mac: profile 010013C00E930000 (update 1.0.30000, SDK 20.5.8)
seedds2026-10-22 17:51:13 +08:00
677345b093
Paper Mario: The Thousand-Year Door plays on the iPhone: README games table, AGENTS.md list
seedds2026-10-22 16:36:07 +08:00
99c3f91481
Spin waits: the rewriter finds guest poll loops in every module and the host lets them sleep (Paper Mario: The Thousand-Year Door's job workers at 24 fps on the iPhone)
seedds2026-10-22 16:32:01 +08:00
51a3fb4442
README: Dark Souls Remastered's picture under a new name, so the cached old one is not shown
seedds2026-10-22 15:32:34 +08:00
f5607c2d7c
README: Dark Souls Remastered's picture is the character creation screen
seedds2026-10-22 15:31:06 +08:00