Commit Graph
24 Commits
Author SHA1 Message Date
seeddsandparsifal295 40b643bbe6 Keep Mac audio buffers near 5 ms across output changes
Apply PR #262's device-buffer fix for clicks caused by audio underruns.
Reconfigure on both output-device and hardware sample-rate changes, respect
the device's frame range, and read back the actual buffer size. Avoid
rewriting unchanged sizes when buffer changes notify the format listener.
Remove listeners before teardown, including failed initialization, so they
cannot configure a device that the AudioUnit has already released.

Add hardware-independent regression coverage for switching, rate changes,
scope filtering, limits, synchronous notifications, diagnostic overrides,
absent devices, and listener cleanup. Record the original gameplay evidence
and the additional silent Core Audio validation in the audio reference.

Validation: full host tests, Mac host build, docs checks, and the iOS source
compile check (178 files) passed. Silent USB/speaker switching and speaker
rates of 44.1/96/48 kHz verified 221/480/240 frames. HDMI switching and
gameplay listening after these listener changes remain unvalidated.

Co-authored-by: parsifal295 <130349765+parsifal295@users.noreply.github.com>
2026-10-27 00:41:13 +08:00
seedds ecbeae164c Port Pokemon Brilliant Diamond 1.3.0 at 60 fps
Add the registered profile, Unity 2019 compute shaders, VP8 decoding, depth initialization and AudioOut stop fixes. Include build-gated frame limiting, regression coverage and Mac validation notes.
2026-10-26 15:40:36 +08:00
seedds 3a993fa3fe Subsystem references and a symptom index: the failure catalogue of docs/agents/03-bringup.md and the per-title material of docs/agents/04-graphics.md (section 1's container list, section 6 and its "Seen in <game>" subsections) move into docs/reference/, one heading per mechanism: rewriter.md, memory.md, threads.md, services.md, movies.md, audio.md, frame-rate.md, nvn-objects.md, rendering.md (with the Vulkan and OpenGL layers), shaders.md and game-state.md, indexed by docs/reference/README.md. Each entry gives the symptom, the cause, the fix (file and function), the games it was found on (linked to their notes in dm/games/<id>/README.md) and any check, caveat or later change; one mechanism met on several games is one entry. docs/agents/symptoms.md lists every entry's symptom (an assertion, a [RED] line, an abort or crash site, a visible result) with a link to it, 350 lines, generated from the Symptom bullets. 03 keeps the loop and reading the log, and its Failure catalogue section now points to the references, the index and where a new finding goes; 04 keeps sections 1-5 and 7 (the container list is shaders.md's Containers by engine), and section 6 says where each kind of finding is. Facts in the old sections about one game only were checked against that game's note, where they already were. Statements the code no longer matches are marked as history beside the current value (movie output slots: MD_NOUT 64, MD_NOUT_AAC 32, MD_NOUT_VIDEO 16; APP_POOL is the profile key app_pool; Engage's layout is 5 / 4.375 GB; inline uniform updates are deferred by default; scaled copies are drawn), and Tears of the Kingdom joins the node-area entry's build list (issue #70). The game notes, docs/agents/README.md, 02 and 05 link to the exact entries, and so do the comments in nvn_mtl.m (nvnTextureCompare) and hle_audio.c (the RemoteIO buffer) and the provisional-profile note in profile_guess.py. 03 goes from 29,600 to 470 words, 04 from 34,400 to 3,500. Checked: every backticked span, module address, issue / PR number and 16-digit hash of AGENTS.md, development.md, dm/games/README.md and docs/agents/01-05 at 6a06877 (4,600 items) still appears in the repository's Markdown (the same five file patterns as before appear as the full names they stood for), every relative link and heading anchor in the repository's Markdown resolves, and the tool tests pass (the four that need capstone or lz4 in the T7 venv) 2026-10-25 12:31:58 +08:00
seeddsandJoão Karalkovas 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)
Co-authored-by: João Karalkovas <117093313+Jpkovas@users.noreply.github.com>
2026-10-24 14:58:04 +08:00
Jpkovas 8e8ea51cda AudioOut: explicitly downmix six-channel PCM for stereo output 2026-10-24 09:12:59 +08:00
seedds 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
The watchdog read the clock before it took g_aos_lock. The return from the background restarts the AudioUnit under that lock and stamps its last callback time (au_go), so a watchdog tick that had read the clock just before waited for the lock and then compared an older time with the newer stamp: the unsigned difference wrapped ("has not called back for 18446744073662 ms", DRAGON QUEST VII Reimagined on an iPhone after 10.7 s in the background) and a running AudioUnit was handed to the silent sink and restarted. The clock is now read after the lock is taken, as every au_go caller does. Mac: 30 s of Luigi's Mansion 3 with real output, no watchdog line
2026-10-23 10:33:35 +08:00
seeddsandRaghav Agarwal e61b142c56 Movie output buffers written from their start, AudioUnit setup off the game's stack, clock snapshot arithmetic answered by the host (from PR #36)
- movie::Buffer::Data() is Base() + Offset() and Capacity() the whole buffer (STEINS;GATE RE:BOOT's subsdk0), so a PCM or picture output whose read offset the client had advanced was written past its end, over the guest heap. GetOutputBuffer resets the range first. Native-texture mode is left as it is: there Data() is the texture object the client points it at. An end-of-stream packet as long as the whole input buffer carries no data, as one with time -1 already did.
- Creating the output AudioUnit takes about 24 KB of stack (measured on the Mac), more than some game threads have left, and OpenAudioOut runs on the game's thread: it now runs on a host thread, once per AudioOut. Not HLE_FORCE_BIG, which would hide the call site the open hooks log.
- CalculateSpanBetween and CalculateStandardUserSystemClockDifferenceByUser go through the time service session, which the host never opens: AbortImpl in the SDKs of STEINS;GATE RE:BOOT and Tears of the Kingdom, which imports both. The host computes what the service does: the span from the steady time points (the network times when the sources differ, else an error), and the user clock difference from the user clock offsets (0 when their sources differ or both have automatic correction on). CalculateSpanBetween is not in the PR.
- Snapshots carry the user clock context of GetSystemClockContext, which stays the same until the host clock is set; worked out per snapshot, it moved by a second at random, which the user difference would report as a clock change.
- t_time: 14 checks on host snapshots and edited copies; it fails without the two hooks.

Mac: Monster Hunter Rise headless for 75 s with real (muted) audio: OpenAudioOut from the game's thread, AAC and H.264 movies through GetOutputBuffer, 60 fps, no movie red lines. No profile with a matching shader cache on this drive calls the two time functions.

Co-authored-by: Raghav Agarwal <88780872+futurist-raghav@users.noreply.github.com>
2026-10-22 01:27:49 +08:00
seedds 1a782136af Patrick's Parabox plays on the Mac: profile 0100E44016C22000 (update 1.0.1, SDK 13.3.7) 2026-10-22 01:23:24 +08:00
seedds 37c24c6841 STEINS;GATE RE:BOOT plays on the Mac and the iPhone: profile 01008BC024FDE000 (update 1.0.3, SDK 20.5.17)
- M2's ADV engine (m2lib, E-mote characters, PSB archives); 87 H.264 / AAC movies through the SDK's movie library in subsdk0; 487 shaders in five BNSH in main; 60 fps, 1280x720 in both modes by the game's own choice
- nn::audio::SetAudioOutVolume / GetAudioOutVolume: a gain on the samples the host plays; the SDK's versions read the audout session the host never made (null read at the first movie)
- Storage-sharing texture table: a new texture that takes over the storage of an entry under another description evicts it, unless a live texture object still resolves to it or a lookup found it in the last 16 submissions. The game decodes every picture into one reused region of a pool that lives for good: 1.58 GB of GPU memory 24,000 frames into a new game before, about 1.0-1.15 GB over 15 minutes of story after. Captain Toad's opening course unchanged (no takeover). The memory line counts unreferenced entries and takeovers
- DM_PROBE_WATCH=<address>[+<length>]: who writes a guest word, with the page kept protected and every store to it carried out by the fault handler through a writable alias; found the game's render size setter
- Probe backtraces read each frame with vm_read_overwrite (code without frame pointers keeps data in x29)
- Prewarm list recorded from boot through the prologue into the story
2026-10-21 23:18:16 +08:00
seedds e63b8eca43 Absolum plays on the Mac into its first level: profile 0100A83022A22000 (update 1.1.1, SDK 18.3.2)
- FNA on .NET NativeAOT with SDL3 and FNA3D's NVN driver; 162 GLSLC outputs in shaders.nx.bin
- Rewriter: data blocks in the text segment are left alone (dm/tools/nso_code.py; main starts with 1.7 MB of data that read as x18 sites); the census applies the same rule. The 52 modules of the 19 other games on hand rewrite byte-identically
- Upside-down picture: nvnCommandBufferSetViewportSwizzles is recorded and a NEGATIVE_Y swizzle flips the viewport
- Logo movie: an H.264 decoder made at Configure (parameter sets in csd-0 / csd-1) now gives RGBA in the native texture mode, not NV12
- SDK calls: vi::CreateLayer with a size; AudioIn (no microphone); the EOS NRO stays unloaded and the game plays offline
- Memory for a 5 GB block: getenv answers the new profile key game_env (DOTNET_GCRegionRange: the GC range 3.75 → 1.5 GB); build cuts for malloc's address space (40 → 2.5 GB), the SDK node area and the SDK's 1 GB alignment of large regions
- Modules: NVIDIA's OpenGL and Vulkan drivers are never loaded (profile_guess.py); the survey's hook list reads dm/gfx too
- dm/host/Makefile: a build for another game always relinks (two builds in the same second kept the first game's host)
2026-10-21 18:44:33 +08:00
seedds d34e0446aa Pokémon Legends: Z-A plays on the Mac: Trinity packs through the game's Oodle, transform feedback, stencil views, the base instance in the driver segment
- Profile 0100F43008C44000 (2.0.2, SDK 19.3.11): 5 GB layout with two cuts (StandardAllocator 12 → 4 GB, node area), mem_map_limit (the pool enforced as on Horizon), shader_oodle.
- Shaders: Trinity packs (arc/data.trpfs, FlatBuffers, Oodle Mermaid) decoded with the game's own OodleLZ_Decompress in the Mac host; 28,603 shaders.
- SDK 19: GetAudioOutBufferCount, crypto random bytes, ToPosixTime with a rule, NVN state getters, CommandBufferFenceSync, the 64-bit WaitForAddress type.
- Graphics: transform feedback (vertex capture entry point, rasterizer discard), layered passes (the colour grading LUT), point size dropped beside a layer output,
  function constants specialized, a stencil-only view for STENCIL-mode texture views (striped lighting), sampler min / max reduction (Metal 26),
  the draw's base instance at c0 + 0x644 (occlusion boxes; characters' legs folded back from the hips), the zero cube for a 2D texture in a cube slot.
- Shader chain changed (dmsh_build.py): every profile's dmsh_chain.h rewritten; the other profiles' c1_full lists carried over (that change touches no c1 read).
2026-10-21 03:47:16 +08:00
seedds 45b01ee91c iOS app: screen stays awake, game audio comes back after interruptions
- The idle timer is off while the app is active: only touches reset it, so with a controller or in a cutscene the screen dimmed and locked.
- Open file limit raised from 256 to 4096 at host start; Documents/romfs and temp are kept out of device backups.
- Audio: observers for audio session interruptions (Siri, alarms, calls) and media services resets (dm_audio_reset recreates the AudioUnits); becoming active ends an interruption whose "ended" never came.
- A watchdog switches a started output whose device has not called back for 200 ms to the silent sink and retries the AudioUnit after 1, 2, 4, 8 s; a start that fails falls back the same way instead of aborting. t_audio scenario 3 stops a playing AudioUnit behind the host's back.
- GetCurrentProcessorNumber: a thread with no ideal core reports the lowest core of its mask, not core 0.
2026-10-20 09:57:43 +08:00
seedds c5955d42a6 English only: no Chinese left in code, scripts, logs, tables or docs
- Log messages, script output, test labels, Makefile errors and comments are English. Red log lines start with "[RED] " (was 【红】).
- Shader map stage column: vertex / pixel / compute / geometry / hull / domain (generators, dmsh_build / dmsh_facts and nvn_mtl.m stage_of follow).
- The NSP script's regexes match the new shader_split.py / dmsh_build.py summary lines; patch_nso cut scopes are all / host-only.
- Host UI text table (dm_i18n_tab.h) is English only; dm_lang_zh() removed.
- Text that matches game data (t_swkbd.c, t_textbox.c) is written as \x escapes.
- Shader chain: the chain files lose their bilingual comments, so every profile has a new chain version. dmsh_xlate.dll rebuilt from the translated Program.cs (SPIR-V byte-identical on 4,500 shaders of Wonder, TOTK and Age of Calamity), lock and dmsh_chain.h headers regenerated. c1_full.tsv restamped for Dread, 13 Sentinels and Wonder; the other profiles follow when their rebuild finishes.
- AGENTS.md and docs/agents: the language rule now covers logs; quoted log lines updated.
2026-10-19 15:34:57 +08:00
seedds 9020ca4edf Power lines show render-target traffic and guest CPU by Switch priority; DM_QOS_MAP maps priority to QoS (off by default)
- hle_nvn.c power_line: the 驻留集 line ends with attachment bytes loaded and stored per frame, passes that load and store everything, and the stores DM_NVN_UNWRITTEN_DC saved (mtl_bw, so far only in the per-frame TSV, which phone runs do not send). A new 线程 line gives guest-thread CPU in ms per second by priority band (<= 44, 45-59, >= 60) and the three busiest threads (dm_thread_cpu in hle_thread.c).
- hle_thread.c DM_QOS_MAP=1 (DM_QOS_EDGES=44,59): priority <= 44 user-interactive, 45-59 user-initiated, above utility, at thread start and on SetThreadPriority (applied by the thread itself at its next SVC). A thread waiting in ArbitrateLock lends its class to the owner until the hand-off (pthread_override_qos_class_start_np). Host helper threads then set their own class instead of inheriting the creating guest thread's: AudioOut notify, silent sink and vsync user-interactive, movie decode user-initiated.

Measured on the Mac: BotW runs 527 ms/s of guest CPU at priority <= 44 and 65 at 45-59, Mario Wonder 138 and 4.5, Three Houses all at <= 44, so the map has little to move; it stays off for a phone A/B. The same runs settle the TBDR question: DM_NVN_TBDR=1 cuts BotW's stores 13% and Wonder's 42% but raises GPU p50 (8.8 → 10.4 ms, 2.8 → 3.5 ms) and CPU energy (+22%, +73%).
2026-10-19 09:52:00 +08:00
seedds 49ee623d9b Host races: audio backends change under one lock, renderer thread joined on close, map registry locked over lookup and change, SystemEvent bindings end with their handle
- hle_audio.c: Start, Stop and the background suspend/resume change an output's consumer only under g_aos_lock and act on an explicit backend (AudioUnit / silent sink). Start used to mark the output started and pick its backend outside the lock: a suspend in between gave one output two silent sinks (or a sink beside the AudioUnit), and a Stop racing a suspend joined a sink that never existed. A stress test (two threads toggling Start/Stop on three outputs while another toggles suspend) hung or crashed in every run before, and runs clean now with never two sinks on one output.
- hle_audren.c: CloseAudioRenderer joins the render thread (dm_guest_thread_join) instead of sleeping 20 ms, and the thread closes its PCM output when it ends (new dm_pcmout_close), so the output no longer keeps running and holding an AudioOut slot.
- hle_svc.c: g_map_lock is held over MapMemory's and UnmapMemory's whole lookup, check and change, and over QueryMemory's reads. Concurrent unmaps deleted through a stale index (map_del moves the last entry): 8 threads mapping and unmapping stack ranges failed about 2,000 maps and unmaps per run and left ranges registered; zero now.
- hle_thread.c: closing a SystemEvent's write handle removes its binding, and signalling looks up and signals under one hold of G. A SystemEvent destroyed and created again at the same address used to keep the dead binding: the new kernel event was never created and signals went to the closed (or recycled) handle. Tested with 2,000 create/destroy rounds and a decoy event taking the freed handle numbers.
- dm/gfx/README.md: the shader-cache key gap (shader_pairs.tsv, profile nvn_*/shader_* rows, paired pixel shader inputs) is recorded, with the workaround, until the next chain change fixes it.
2026-10-19 09:15:06 +08:00
seedds df7badd23a Power: no busy-wait yields, no per-frame GPU allocations, cheaper replay, uniform updates inside passes
General host changes so the games stop doing work the Switch never did; frames and frame rate unchanged
(Mac A/B with the same routes, 11 games, no crash, red lines as before; dm/gfx/tests results as HEAD).
- Yield back-off: a run of SleepThread(0) with no other SVC sleeps an eighth of the wait after 200 us
  (10-250 us; DM_YIELD_BACKOFF). Three Houses' frame limiter yielded 228k times a frame on the iPhone;
  Mac CPU energy 3.5 W -> 0.5 W. BotW's PlacementMgr / RadarMgr spun the same way.
- SVC exit takes the global lock only while a pause is pending; a signalled event wakes only its
  waiters; the audio renderer and upload / QueueFinish waits block instead of polling.
- Upload staging: each upload slot keeps its block (BotW allocated, made resident and freed a 32 MB
  block per re-upload, ~3 GB/s); a re-uploaded texture alternates with a kept spare (movie frames,
  Link's Awakening title: submit 1.64 -> 0.37 ms); the residency set skips repeated adds / removals;
  copy parameters from the frame arena; host pre-writes unprotect page runs with one mprotect.
- Replay: per-thread memory-pool address cache, per-encoder state filter, GPU-only texture IDs stay
  cached across guest writes, kept dirty-range handle per packaged texture. Instructions per draw:
  TOTK -40%, Dread -32%, Odyssey -19%, 13 Sentinels -20%; replay kernel time BotW 1.3 -> 0.1 ms.
- Inline uniform updates inside a render pass are deferred to the pass end; later draws read a
  shadow made of the deferred updates when they cover the bound range, else the pass ends first
  (DM_NVN_UB_DEFER=0). Dread: 272 -> 26 passes a frame, GPU 8.3 -> 2.8 ms, CPU energy 1.2 -> 0.4 W.
- Whole-level format-changing copies do not load the destination.
- Measurement: [nvn] 功耗 (CPU energy W and mJ/frame, CPU, P-core share, wakeups, thermal state, top
  yielders) and [nvn] 驻留集 (residency churn by source line, pass barriers, cuts, pass splits) every
  300 frames; iOS thermal state and brightness. Opt-in switches for A/B: DM_RT=0, DM_NVN_BARRIER=game.
Docs: development.md Power section, 04 section 7 switches, 05 power lines, dm/gfx/README fixes.
2026-10-19 07:21:08 +08:00
seedds b68ac089a3 SM3DW magenta blocks fixed (same-pass feedback snapshot); English default language; English-only comments, bilingual README
- Magenta 16x16 blocks in Super Mario 3D World 1-1 (iPhone only): the composite shader 66a71a3081b91b9a
  renders into the RGB10A2 image while sampling it in the same pass. That is undefined in Metal: the
  M4 Pro reads the old content, the A20 Pro sometimes returns whole 16x16 blocks as (1,0,1). Found with
  the new device self-check DM_NVN_MAGSCAN (blocks first appear on that attachment, and still appear
  with the suspected particle dropped). fb_prepare ends the pass, copies the attachment level into a
  snapshot and binds the snapshot for that draw, only for shaders in the new profile key feedback_snap
  (doing it for every shader cost BotW 16.6 -> 36.6 ms). DM_NVN_FB_SNAP=0 / all / <keys> overrides.
- The game language now defaults to English (nn::oe::GetDesiredLanguage returns en-US; DM_LANG=zh-Hans
  in Documents/env.txt for Chinese).
- Code comments, docstrings and docs are English only; the zh-CN doc twins are removed. README.md has the
  English text followed by the same text in Chinese. Files the shader chain version hashes keep their
  bilingual comments (editing them changes every game's chain version).
2026-10-17 00:41:10 +08:00
seedds 550db7dc5a 13 Sentinels: Aegis Rim (1.10) reaches its first battle on the Mac; Mario holds interval-2 frames for two display ticks
- New profile 01003FC01670C000: sdk and subsdk0 are byte-identical to Metroid Dread's; data is six CRI CPKs; the 751 shaders are GLSLC outputs compiled into main (shader_split.py: shader_main_glslc), built as single-stage programs and paired per draw (shader_separable: every vertex shader is paired with a cover of the pixel shader inputs, so vs_pad lets any pair link)
- Host hooks for SDK 11 calls that reach a service: hid::GetMouseState, fs::CleanDirectoryRecursively, fs::EnableGlobalFileDataCache, oe::SetUserInactivityDetectionTimeExtendedUnsafe, time::ToPosixTime, audio::GetAudioOutName
- StandardAllocator::Allocate(size): on this build only, blocks of 64 KB or more are 64 KB aligned; the engine cuts three ring heaps out of a GPU pool at 64 KB alignment relative to its GPU address, and with the host's 4 KB-aligned address the third heap kept base 0 (null write when the prologue enters its first battle)
- NVN: triangle fans and indexed quads, vertex streams 14 and 15 on Metal slots 14 / 15 (Metal assertion buffer index 31), TextureBuilderSetPackagedTextureData copied into the storage at TextureInitialize, InsertDebugMarker as a no-op
- Mario 1.2.1 sets present interval 2 for single frames after a slow one and advances its time step by the interval; frames were shown for one tick and the game jumped ahead on the iPhone. The display link now keeps a frame for its whole period, and the 30 fps target waits until interval 2 has held for a second (Engage, which asks for 1 with its 60 fps cut, is unchanged). Test switch DM_TEST_PRESENT_LAG
- Survey notes: extra modules are supported, GLSLC outputs in main are counted
- Regression: Mario 1.2.1, Engage and Metroid Dread runs show only their known red lines; t_nvn 63/63; t_present_crop / t_mip_extent build again (t_mip_extent's one failure is the same at a9c56fd)
2026-10-15 23:41:10 +08:00
seedds a1e388fbc8 Audio: per-output logs, Mac background round trip, no catch-up burst after suspend
- Each AudioOut is logged as audio #N: the open with its guest call site, Start / Stop / Close (first 32 per output), and the 2000-callback stats line per output. An Engage phone log had two outputs after a background round trip, one fed and one starved; the combined stats read as "every other callback underruns"
- DM_OE_SCRIPT gains bg=1 / bg=0, the same sequence as the iOS lifecycle callbacks (focus, audio take-over, guest clock freeze, graphics suspend); DM_AUDIO_MUTE=1 silences the real Core Audio path for such tests on the Mac
- The silent sink no longer makes up time the process was suspended (it pulled seconds' worth at once and logged hundreds of underruns)
- Host tests t_audio, t_audio_spsc and t_oe build again (game profile include, stubs) and pass
- docs/agents/03-bringup.md: several outputs, background round trip on the Mac
2026-10-15 10:16:17 +08:00
seedds 779e5097f3 Host and rewriter: fixes for Unity / SDK 12 titles (Engage bring-up)
- patch_nso.py: three more x18 forms from IL2CPP code: an offset jump
  table (targets read at rewrite time), blr x18 (original return
  address kept for C++ unwinding) and an sp write from x18 (alloca).
  Mario's rewrite output stays byte-identical.
- loader.c: symbols resolve globally in load order, also for a
  module's references to its own exports (local / non-default
  visibility excepted). Engage's main overrides operator new / delete;
  sdk bound its own copies and freed Unity's blocks into the SDK heap.
- hle_svc.c: QueryMemory reports each module's Horizon layout (code,
  read-only, data, patch area) and other host memory as free, which
  the SDK's C++ unwinder (nn::ro::detail::GetExceptionInfo) needs.
- New takeovers: nn::fs::IsMounted, nn::ro (hle_ro.c), prepo
  Initialize, SDK 12 audio device names and OpenDefaultAudioOut, an
  SDK 12 hid block (single GetNpadState, modes, touch, gestures,
  six-axis details, colors, applets), movie::Decoder with no impl
  (hle_movie.c) and failing nvdrv opens (hle_nvdrv.c), and NVN getters
  / no-ops Engage calls. nvn.h: TextureGetMemoryPool returns a pointer.
- Makefile: a game stamp, so changing GAME rebuilds the host.
- docs/agents/03-bringup.md: catalogue entries for all of the above.
- Mario 1.2.1 scripted run still reaches the opening course with the
  same single red line.
2026-10-14 18:09:30 +08:00
seedds 527fa29007 Remove the [DEBUG-flk1] instrumentation
- hle_nvn.c: drop the command memory callback / grant / caller
  logging, the overflow details, the +0x10 write log, the one-off
  NVN table dump, and the DM_DBG_GRANTS, DM_DBG_CALLSITES,
  DM_DBG_CMDMEM_SHRINK and DM_DBG_OLD_USED switches.
- nvn_mtl.m: drop the per-draw NaN probe (DM_DBG_NANPROBE), the
  colour target statistics (DM_DBG_TEXSTAT) and the PASSDUMP
  completion timing.
- Kept as regular diagnostics: the audio callback line every 2000
  callbacks (frames per callback, queued blocks, underruns) and
  DM_DBG_AU_FRAMES (docs/agents/03-bringup.md, crackling on iOS);
  DM_NVN_SHOT up to 4096 frames (the 05-debugging burst recipe).
- Mac 1.2.1 scripted run reaches the opening course with the same
  single red line as before.
2026-10-14 13:02:16 +08:00
seedds 3a1e6a3915 iPhone: command-buffer byte +0x10, command memory, audio buffer size
Fixes the flicker / black band in the opening course and the crash after
the first scene on the iPhone (A20 Pro), confirmed on the device.

- nvn_obj.h: cmd_t leaves byte +0x10 of NVNcommandBuffer to the game.
  Mario's inlined NVN code writes 1 there (main+0x4da5c, main+0xb8dec).
  It used to hit the low byte of `end`: the game's 512-byte material
  setup blocks shrank and overflowed into host segments,
  GetCommandMemoryUsed (cur - begin) returned 0, the game marked the
  setups empty and skipped calling them, and draws ran with the previous
  vertex buffers (out-of-range vertices, NaN).
- hle_nvn.c: GetCommandMemoryUsed counts bytes across host segments plus
  16 for the jump. Host segments are released only when the game
  re-grants memory overlapping the recording's guest bytes (the game
  keeps calling recorded setup blocks for many frames); the 8-frame
  recycling is gone.
- nvn_mtl.m: failed pipelines are cached and reported once with their
  vertex / fragment keys instead of being rebuilt on every draw.
- front_ios.m / main.m: the audio session asks for a 5 ms I/O buffer at
  boot and on return to the foreground. The default (~21 ms, 1024
  frames per callback) outran the 4 x 5 ms the renderer keeps queued:
  every callback underran (crackling). Device: 240-frame callbacks,
  0 underruns.

Still contains [DEBUG-flk1] instrumentation (tagged, mostly behind
DM_DBG_* switches; audio statistics every 2000 callbacks in
hle_audio.c). To be removed with one grep.
2026-10-14 01:21:04 +08:00
seedds 874001eaee Sound, button icons, fountain water: CPU audio renderer, extension font, ordered copies
- Audio: run the sdk's own audio renderer on the CPU in manual mode (hle_audren.c),
  feed its DeviceSink output to the AudioOut sink; catch-up render on back-to-back
  updates fixes the ApplyLightLimiterEffect crash at the title screen
- Button icons: make_ext_font.py generates a stand-in Nintendo extension font
  (A/B/X/Y, L/R/ZL/ZR/SL/SR, +/-, D-pad, stick arrows); served as shared font type 5;
  the iOS bundle now carries both shared fonts
- Fountain panels: Metal 4 does not order copies inside one encoder; add barriers
  when ranges overlap, so the GPU wave simulation no longer reads a stale uniform
- Zero-fill new colour textures; scissored zero clears; uniform-update snapshots
- Docs: graphics ordering, audio, diagnostics, intermittent-glitch method
2026-10-13 13:16:42 +08:00
seedds d1b17080ed smbw-mobile: Mac host boots Mario Wonder v0 into its frame loop
Generic host, gfx and tools taken from d2r-mobile (MIT), with the D2R
gameplay, diagnostics and Blizzard/Granny/movie layers removed.

- hle_hid.c: generic standard-controller layer (all Npad styles)
- hle_sdk16.c: newer-SDK oe/time/pl/vsync/diag hooks
- hle_offline.c: offline stubs for prepo/ldn/socket/ssl/nifm/nsd/friends/ngc/err
- hle_fs.c, hle_account.c: SDK 16 overloads
- loader.c: unreferenced forced hooks only logged (DM_FORCE_STRICT=1 aborts)
- NVN: API 55.15, 13 newer names, ~45 state-only functions, tex_t packed
  to 0x80 (Mario allocates NVNtexture as 0x80; 0x88 corrupted the heap)

Frontier: null read at main+0x64763c inside the frame loop.
2026-10-12 22:04:20 +08:00