Files
seeddsandaldomrodriguez 15805ef525 Defer audio layout detection until a valid command list (#331)
An incomplete startup command list consumed both layout detection and the
one-time DeviceSink scan, leaving valid SDK 4 audio frames permanently
silent. Keep both decisions pending until a supported layout walks the
whole list, as proposed in PR #331.

Extend the reproducer with valid-first and incomplete-startup stereo PCM
checks for SDK 4, 6, 16 and 21, and document the finding.

Co-authored-by: aldomrodriguez <rodriguez.aldo.91@hotmail.com>
2026-10-27 08:56:25 +08:00
..
2026-10-27 07:58:05 +08:00
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
2026-10-23 20:36:56 +08:00
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
2026-10-23 20:36:56 +08:00
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
2026-10-24 11:31:10 +08:00
Haptics: a Core Haptics engine that fails to start is replaced, not retried for good (general, from PR #143). A Bluetooth Switch Pro controller that vibrates through iOS Settings' Identify stayed silent in a game, which logged Core Haptics -4810 (server init failed): the adapter made each engine once per route and called startAndReturnError on that same broken engine at every later effect, and its stop/reset handlers were installed only after the start. Now haptics_apple.m makes an engine when the first effect needs it (the phone's too, so after the audio session is active), installs the handlers before starting it, and a failure to make or start the engine, make or start its player or send its parameters releases that engine: a fresh game signal makes a new one after a backoff of 1, 2, 4 or 8 s, effects from before the failure are not replayed, and the old engine's callbacks are stale (generation). A controller whose left and right handle engines cannot be made or started falls back to its default locality until it reconnects; a player or parameter failure (a service reset, say) is retried on the same handle. Idle release (1 s of silence), focus loss and engine resets stop an engine but keep it, so the next effect restarts the same engine, as before. Errors name the target, the stage, the error domain and code and the underlying error, and the log names the controller, its localities and the output channels. From PR #143 (nanda86), with two changes: the PR dropped the engine at every stop, so each rumble after a second of silence made a new engine (a new connection to the haptics service on a controller, a new initWithAudioSession: engine on the phone), and any handle failure moved the route to the default locality for good. t_haptics_apple covers each failure stage, the backoff, the fallback (and no fallback on a player failure), stale callbacks, a restarted engine after idle release, a disconnect and a controller without haptics, with fake controllers and engines. Checked: the host unit tests pass (GAME=0100DCA0064A6000), haptics_apple.m compiles for iOS arm64 with -Wall -Werror. Not checked: a physical controller or the iPhone's own haptics
2026-10-25 09:55:44 +08:00
2026-10-27 07:58:05 +08:00
2026-10-27 07:58:05 +08:00
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
2026-10-24 22:17:57 +08:00