435a2310511b924767f71ac2878e08a31f08c5e7
20
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
435a231051 |
Preserve Horizon audio renderer work-buffer requirements
DSP callers were charged the local SDK CPU server budget, whose command representation is larger than the Horizon service representation. For Age of Calamity the service requires 0x61d000 while the local SDK requires 0x760000, exhausting the fixed sound heap. Calculate the service requirement through renderer revision 15 and supply larger local backend storage separately, with cleanup on failed open and after renderer close. Remove the two game heap cuts and add sizing, nested-open, failure and lifetime regression coverage. Validation: 360 seeded cases match isolated Horizon machine-code execution across REV1-REV15; the original game heaps initialize all five players and produce audio; the host suite, documentation and patch checks, SDK 8/20 smoke checks and iOS C compilation pass. iOS runtime and long battles remain untested. |
||
|
|
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 | ||
|
|
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 | ||
|
|
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 | ||
|
|
e72a06510e |
DRAGON QUEST VII Reimagined plays on the Mac: profile 0100A9D01C446000 (update 1.2.0, SDK 19.3.1)
- Files and shaders: Unreal Engine 4.27 with IoStore containers beside one pak (version 11, its footer magic 0xcc bytes from the end, uepak.py magic_back); the 62,901 shaders of the pak's two shader code archives are LZ4 blocks, which uepak.py decodes itself (lz4_shaders), so the NSP script runs no Oodle host when no record is Oodle. One global shader writes integers into an R8Uint target (shader_facts_manual.tsv) - Shader chain, for every game: a texture query on an image handle (c2 0x120 + 8 r: Unreal's GetDimensions on the RWTexture3D a compute shader writes) had no type in a facts table built without PC shaders, and the 2D default took a 3D image's depth from its width; the translator now translates such a shader again with the image types of its first translation (dmsh_xlate ImageTypesOf; dmsh_xlate.dll rebuilt, dmsh_chain.lock updated). Host, for every game: a texture binding of slot 32-39 reads the image bound in the image slot that shares its c2 word (nvn_mtl.m tex_slot_h; Hades II's texture slot 34 without an image still reads the texture). Unreal's volumetric lightmap indirection patch (7b958a7b21e72801) read the empty texture slot 32's 1x1 size and wrote only cell (0, 0, 0), so in the opening cutscene every character and prop sampled the atlas origin, a daytime level's bricks baked 2^15 brighter (white figures about 10^4 too bright). Monster Hunter Rise has four such queries. Every other profile's dmsh_chain.h rewritten with its c1_full / cb_extent lists carried over (the change touches no c1 or uniform read); DRAGON QUEST VII Reimagined rebuilt for Mac and iOS - Host, for every game: stencil-mode texture builders (nvnTextureBuilderSetDepthStencilMode STENCIL) read the stencil of their depth-stencil storage (the hero was drawn as a dithered silhouette); the audio renderer at 32 kHz on the CPU path (the SDK makes its upsampler only for DSP rendering: UpsamplerManager::Allocate returns null and the host resamples 3:2); GetAudioDeviceOutputVolume; the shop and Nintendo Account calls of the title (ec Finalize / Cancel / GetErrorCode / ShowShopSubscriptionDetails, GetAuthorizationCode / GetState); kpr::GetKeyCodeMap; the movie output format's nv12-width / nv12-height beside nv12-uv-stride (Sofdec's VP9 movies were grey with bands) - Memory: MallocBinned3 reserves 37 GB of pools in the engine region; its creation is cut and an observation gate hands the engine the host's malloc zone (patch_nso.py cut + gate OBS_UE_MALLOC, hle_uemalloc.c layout UE4_27; patch_nso.py places a gate where the scratch registers it uses are dead, scratch_dead); the region is 2 GB (game_args) with the SDK's node-area cut on this sdk build, in a 3.75 GB guest block; about 2.6 GB resident on the Mac - Frame rate: this build's t.MaxFPS and rhi.SyncInterval in hle_fpslock.c; the profile keeps the game's 30 fps - Diagnostics: DM_CTL (Mac) drives a running game line by line: presses, shots, pass and texture dumps, texlist (textures of a target with storage and block-linear layout), memdump, peek, Unreal console variables (cvarf / cvari), env; the pass dump prints buffer-to-texture copies and buffer textures' format, size and storage, and DM_NVN_CBDUMP saves the source bytes of 3D uploads (docs/agents 04, 05) - Mac: the logos and opening movie, the title, a new adventure log, the opening cutscene (the well, the night scene with Maribel by the boat) into play at Pilchard Bay, and a saved log continued, at 30 fps with saves; no red line at run time apart from 62 of the 63 geometry shaders (one-pass cube shadow maps), which do not build. Unit tests: the graphics tests that build pass (t_refl's two sample libraries are not on this machine); 13 that compile nvn_mtl.m with hle_nvn.c already failed to build on main (g_ft defined in both, hle_nvn.c symbols missing from their stubs) |
||
|
|
df0820eb68 |
DRAGON QUEST XI S plays on the Mac: profile 01006C300E9F0000 (update 1.0.4, SDK 7.3.2)
New profile for Square Enix's Unreal Engine 4.18 game: from the opening movie and the title through the prologue into free play at Cobblestone Tor, 30 fps with sound and saves, no red line. An IPA builds from the NSP folder; it has not run on an iPhone yet. - Files and shaders: Unreal 4.18 legacy (version 4) paks with LZ5 blocks, decoded on the Mac with the game's own LZ5_decompress_safe (uepak.py, hle_oodle.c serving after nninitStartup); 38,892 shaders inline in the cooked packages as zlib-compressed LSLG records (shader_split.py ue_legacy_jobs, ue_inline_shaders; the NSP script and profile_guess know both pak kinds). - Memory: Unreal's address region capped at 4064 MB (game_args, MB up to 4095); SDK 7.3.2 cuts in patch_nso.py (node area 62 MB, 32 MB alignment for large regions; the build Odyssey shares, which boots unchanged) for Engage's 5 GB block. Rewriter: a jump table whose bounds check sits right before the load (check_before_copy). - Host, for every game: audio catch-up frames wait for queue space (Square Enix's sound driver never waits on the renderer event: 11,000 updates a second before); movie decoder events read at signal time as the SDK does, audio decoders keep 32 outputs (the player plays only once every track holds one: the opening movie never started in half the boots), and no input after an end-of-stream packet until Flush / Stop (a skipped movie mapped 2.25 GB of end-of-stream samples); ec shop accessors, friends, auto-sleep, album, file data cache and movie hooks. - Graphics, for every game: a geometry shader that only picks the layer (Unreal's FWriteToSliceGS, the colour-grading LUT) folded into the vertex shader's layer entry points (dmsh_build.py gs_slice / vs_layer_entry, nvn_mtl.m prog_fold_gs); cube-map array depth counted in layer-faces in the Metal texture, the upload and the guest layout (t_nvn checks it); nvnTextureGetTextureAddress and the command memory size / free getters. - Shader chain changed (dmsh_build.py): DQ11 rebuilt for Mac and iOS; every other profile's dmsh_chain.h rewritten with its c1_full / cb_extent lists carried over (no c1 or uniform read touched). Mac checks on this host: Big Brain Academy (movie loops, 23 catch-up renders as before), Monster Hunter Rise (movies), Super Mario Odyssey (boot on the cut sdk). |
||
|
|
9d941f8604 |
Rhythm Heaven Groove plays into its first rhythm game on the Mac: SDK 21 calls and audio, pool initial content, NVN block height
New profile 0100D9F01D474000 (base game 1.0.0, SDK 21.4.0, Nintendo's own 2D engine; one BNSH of 35 shaders, Mario's binding layout). On the Mac it plays from a first boot through the setup, the main menu and Play Solo into Hoop Trundling at 60 fps with sound and no red line. Not yet run on an iPhone. - SDK 21 calls: nn::pl::GetSharedFont (every shared font at once; the SDK opened the pl service and aborted in sm::Initialize) returns the stand-in TTFs past the BFTTF header, as the service's offsets point there and the game hands them straight to ScalableFontEngine::LoadFont; vi::GetDefaultDisplayPanelIdentifier (SIGSEGV through the vi service object) answers an all-zero panel. - Audio: SDK 21's DSP command header has no magic (+0 enabled, +1 command ID, +2 size) and DeviceSink is 0x140 bytes with its fields 8 bytes earlier. capture() recognizes that layout on the first non-empty command list (the walk bounded by the generated list's length); the game was silent. - Pool initial content (all games): a new texture in a CPU_NO_ACCESS pool whose storage holds data is filled from it once, as NVN keeps a pool's storage content at nvnMemoryPoolInitialize (tex_init_fill); it stays a GPU texture that can be rendered into. Linear textures are made on the pool buffer in any pool. The game reads each texture file into memory and makes a CPU_NO_ACCESS pool on it; every texture read 0 and the screen stayed black. COMPRESSIBLE, multisample, depth / stencil and sparse textures and storage of zeros are left out. - NVN block height (all games): the automatic block height truncates height in blocks x 1.5 / 8 (MacNativeGames' finding, confirmed on this game's 40-block-row BC7 textures and by Touchable on 16 of its files); rounding up scrambled the calibration screen's beat numbers. Only data a game lays out itself without a packaged layout changes (Tears of the Kingdom's flushed and Monster Hunter Rise's sparse textures were not re-checked). - Profile key perf_mode (follow by default): boost reports Boost whatever the operation mode. This game plays handheld with Boost: docked means a TV to it, which asks for a latency calibration, and Boost alone picks its 1920x1080 draw size. - The NSP script's survey no longer calls nn::ro missing (hle_ro.c answers it; it now counts the .nro files); sdis.py --callers takes imported names and scans to the end of the PLT. The dm/gfx unit tests give the same results as before; Unicorn Overlord renders the same with the old and new host (no texture takes the initial-content path there). |
||
|
|
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. |
||
|
|
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. |
||
|
|
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. |
||
|
|
8b21049d2a |
Age of Calamity and Three Houses play on the Mac; indirect NVN draws; Dread GPU leak fixed
Hyrule Warriors: Age of Calamity (01002B00111A2000, 1.3.0) reaches its first battle on the Mac: - shader_split.py reads Koei Tecmo's RDB / IDRK archives (G2S `_S2G` / `_DOK`). - Profile key mem_used (DM_GAME_MEM_USED) for svc GetInfo UsedMem; the default stays 0x4000000 for every other game. - patch_nso.py: jump tables indexed by x30 / x29 (capstone names them lr / fp); a per-build cut for AoC's KTSL sound heaps. - NVN: the compute program is bound apart from the graphics stages (cprog); nvnTexturePoolRegisterImage; DrawArraysIndirect; reflection c1 on the heap. - oe copyright-frame calls and the hardware multi-stream Opus decoder answered. Fire Emblem: Three Houses (010055D009F78000, 1.2.0, SDK 6.5, KTGL) plays its prologue on the Mac: - shader_split.py reads LINKDATA / SPKG with KT chunked zlib and keeps GLSLC outputs with 0x848 / 0x850 controls and headerless compute; 9 run-time GLSLC compiles are captured once with DM_GLSLC_CAPTURE (hle_glslc.c, profile key shader_glslc_capture). - NVN: submissions serialized across the two queues; GetCommandMemoryUsed counts from AddCommandMemory; per-pool texture / sampler ID ranges; depth clamp replayed; integer vertex inputs fed half / unorm / snorm / packed formats get float32 bits converted on the CPU (also fixes AoC's flat soldiers). - SDK 6: OpenPreselectedUser returns a Result; the audio renderer's DSP command header layout. DM_KEYS steps run in time order. NVN indirect paths: quads and triangle fans from DrawArraysIndirect, and DrawElementsIndirect, go through a GPU compute conversion into indexed indirect draws; DispatchComputeIndirect is implemented (AoC's battle effects; red line 88 gone). Metroid Dread GPU leak: defer_drain() runs in its own autorelease pool. Run on the guest submit thread, whose implicit pool never drains, it kept every retired object (and its upload staging block) alive; under CPU load Dread climbed to the 24 GB watchdog. The committed tree had the same leak; it is also behind Breath of the Wild's memory growth in issue #9. NVN pass dump diagnostics (TOTK): TEXSNAP copies the attachments after the pass on the Metal 4 stream; DM_NVN_DEPTHOVR=<fs key prefixes> forces depth ALWAYS; D lines show the depth range and logic op; recorded clears are logged. Docs: game notes, bring-up and graphics catalogue entries, the README's list of games being ported. .gitignore: __pycache__/. Checked on the Mac with the 9-game smoke test (Wonder, Engage, 13 Sentinels, 3D World, Breath of the Wild, Dread, Link's Awakening, Odyssey, Hades): known red lines only, screenshots match the earlier runs, Dread flat at 1769 MB to frame 24300. iPhone builds of the new games are untested. |
||
|
|
723f6407db |
Link's Awakening playable on iPhone; Super Mario Odyssey port started (boots to its frame loop on the Mac)
- README / AGENTS.md: The Legend of Zelda: Link's Awakening moves into the playable table (tested on an iPhone with the physics, blur and sunlight fixes); Super Mario Odyssey listed as being ported; the app takes the game's version. - Super Mario Odyssey (update 1.4.1, SDK 7.3.2): profile dm/games/0100000000010000 from the NSP script's provisional one (3D touch layout). Host stand-ins for the services it calls at startup that no other game did: account OpenPreselectedUser / GetLastOpenedUser, bcat (Initialize, a failing MountDeliveryCacheStorage: the game's own "nothing delivered" path), oe HOME-button blocking / screenshot orientation / inactivity query, pctl stereo-vision restriction, vi SetLayerScalingMode, time ToPosixTimeFromUtc, hid debug pad and IsSevenSixAxisSensorAtRest, and the SDK 7 names of the audio device notification and channel count. It now reaches its frame loop (past frame 8,700 in 150 s); its Mac shader libraries are still building, so nothing is drawn yet. - c1_full.tsv for Breath of the Wild, Super Mario 3D World and Metroid Dread rebuilt for the vertex-output chain (all seven playable games now match their chain headers). |
||
|
|
ab5c8ff1f4 |
Link's Awakening: game sound, doorway lighting tiles and missing foliage fixed
- Sound: SDK 8 numbers the DSP commands differently and its DeviceSink is 0x10, not 0x13, so every rendered frame played silence (only the movies had sound). capture() now takes the one 0x148-byte command with 1-6 inputs as the sink when the expected ID is missing. - Lighting: the light-culling compute shader reads its workgroup count from NVN's driver segment c0 (+0x200). dmsh_build's drv_reads scan only matches fragment-shader names, so compute and vertex shaders got an all-zero c0: every tile row wrote row 0, and the doorway step flickered with white 64-pixel tiles. A declared driver-segment binding now counts as read, and compute c0 carries the dispatch size (0x200) and the uniform buffer table (0x210 + 16 r). BotW and SM3DW render as before. - Foliage: the shadow / depth pre-pass pipeline 147c829e79fb322f failed (uint4 inputs fed 16-bit normalized formats), so with depth test EQUAL the palm tree and flowers never drew. New profile file shader_facts_manual.tsv (merged by shader_split.py) declares those inputs float; Link's Awakening's chain is now ccb18ba743bf. |
||
|
|
e734ced7d9 |
Zelda Link's Awakening runs on the Mac (profile 01006BB00C6F0000, 1.1.0, SDK 8); BotW HUD prompt boxes fixed
BotW: the button-prompt shadow samples an R8 blur whose swizzle (R,0,0,1) made alpha 1, so every prompt got a solid box. New profile key alpha_from_red takes alpha from red for the named shader. Link's Awakening: - NVN lower-left window origin (negative viewport height, winding flip, flipped present and raw screenshots) - texture copies with format change, scaling, mirroring and depth (copy_t2t_draw); SetCopyImageStride; nvnWindowGetPresentInterval - oe::PopNotificationMessage, vi SetLayerCrop / DestroyLayer / CloseDisplay / Finalize, audren P_SIZE 0x40 for SDK 8, hid style-set update event signalled once on bind - Vorbis movie audio through stb_vorbis (dm/third_party/stb_vorbis) - patch_nso jump tables: other index registers, mov copies, masked copies |
||
|
|
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). |
||
|
|
4a5582ad8c | Breath of the Wild holds 60 fps docked on the Mac: the replay hands its command buffer to the GPU every 64 draws; SDK 20 audio rendering goes through the host's locked path | ||
|
|
abcfdf9215 |
The Legend of Zelda: Breath of the Wild (1.9.0) reaches the Shrine of Resurrection on the Mac, with a 60 fps cut; deferred texture binds read at execution
- Profile 01007EF00011E000 (SDK 20.5.22, NVN 55, main + subsdk0 + sdk): 19,592 shaders, all translated (chain bd3979ea9b3d). - Loader applies DT_RELR relative relocations (SDK 20; main has 223,994); nvn_slots_got.py and DM_LOADHASH read them too. - 60 fps: five rewriter cuts lower the GameFrameworkNx dynamic-interval floor from 2 to 1; ksys::VFR scales the logic time step by the interval (ratio 0.5 at 60 fps, falls back to 30 with ratio 1 when frames run long). - Black 3D scene: nvnCommandBufferBindTexturesDeferred reads the handles at execution (bh_fresh); the engine records once and fills the handles later, so the lighting composite sampled texture 0. - A texture attached at two colour slots is attached once (TBDR tile stores raced, albedo kept scattered tiles). - Cube textures are 6-layer 2D arrays so tex_fit can bind cube-array views (1,512 shaders sample cube arrays). - NVN functions other than command recording run on the per-thread host stack (Metal compiled on a small guest stack). - Address-to-pool lookups use the last hit plus a sorted index (1,760 pools): submit time 21 ms -> 7 ms per frame. - SDK 20: ARUID hook, audio renderer layout (Span GenerateCommand, new offsets, DeviceSink ID 0x14), nfp events, VR mode, seven-six-axis sensor, steady clock, launch parameter, stereo vision permission. - Compressed render targets (BC4 via an RGBA16UI view) are skipped with a red line instead of a Metal abort. - DM_KEYS takes frame numbers (f2500:A); TEXDUMP saves 2D-array layers; PASSDUMP prints skipped passes. - NSP script skips empty NSP files and keeps one copy per DLC. |
||
|
|
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. |
||
|
|
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 |
||
|
|
f68dea7add |
Boot Mario Wonder into its game loop: VA memory, audio, settings, fs
- hle_svc.c: guest AS 6 GB with a 1.25 GB alias region (newer SDK's AddressRegionManager always takes ~1 GB of it as its node area), MapPhysicalMemory rounded to 16 KB host pages, GetInfo(UserExceptionContext) backed by a real buffer, program id now SMBW (DM_PROGRAM_ID overrides) - hle_audren.c (new): silent AudioRenderer, event fired every 5 ms - hle_fs.c: SetPriorityOnCurrentThread / IsEnabledAccessLog (fsp-srv) - hle_sdk16.c: settings language comparison; diag aborts report the call site and backtrace - NVN: nvnProgramSetShadersExt (0x18-byte stage entries) The game now runs ~40 threads; the main thread waits on job events while render commands (CallCommands, BindTexture, BindVertexBuffer, DrawElements, WriteTexels) are still unimplemented. |