Files
nxnative-easy/docs/agents/symptoms.md
T
seeddsandSuraj Mandal 09f3778c36 Make repeated IPA and Mac app builds incremental (#279)
Reuse unchanged IPA entries through the packing index and APFS clones,
and keep Mac app and derived-profile shader outputs while their inputs
match. Preserve main's shader regression checks and .NET discovery.

Count uncompressed bytes in streamed files so a size change aborts the
pack without replacing the previous IPA or index. Cover both deflated
and stored streams with growth and shrinkage regression tests, and
record the cause and fix in the packing reference.

Co-authored-by: Suraj Mandal <surajmandalcell@gmail.com>
2026-10-27 00:10:35 +08:00

116 KiB
Raw Blame History

Symptom index

One line per symptom in the subsystem references: what you see (an assertion, a [RED] line, an abort or crash site, a visible result) and the entry that explains it. Search this page for the text in your log first (grep -i the function name, the [RED] text or the address form), then read the entry and the game notes it names. Generated by dm/tools/docs_symptoms.py from the entries' Symptom bullets: change the entry, then run it.

Packing

Rewriter

Memory and address space

Threads

  • a parent returns from StartThread before a newly runnable higher-priority child pinned to its core finishes its work (deterministic regression, not attributed to a game failure). → Starting a higher-priority thread on the caller's core
  • per-core job queues never drained. → Core mask changes move the ideal core into the new mask
  • crash indexing a per-core table with a huge offset (index −2). → Ideal core −2 resolves to the process default core
  • the main thread waits forever on an event right after nnMain starts, with only three or four threads created; DM_THR=1 shows no CreateThread for the thread it waits on. → Free thread count (svcGetInfo type 24)
  • in garbage-collected titles (Unity / IL2CPP), live objects freed, with their finalizers releasing native resources. → Pausing threads and reading their context for garbage collectors
  • crashes around movie changes in the game's own player threads, about one run in two: SignalEvent → MultiWaitImpl::NotifyAndWakeupThread on a null MultiWait at address 0x20; WaitAny walking freed holders; a worker reading a freed object at main+0x225338. The other way round, a handoff that waits too widely: a black screen at boot that never loads a texture (packaged textures: first uploads 0), or a load that never ends behind an animated loading screen, with the thread dump's same-core handoffs N, total T ms larger than the run itself. → Same-core wake handoffs
  • several threads crash at once and the dumps interleave, then the process hangs instead of exiting. → Simultaneous crashes of several threads
  • none seen; found while investigating Fire Emblem Engage's demo crash, which it did not change (that was the address-space shortage, Size-aligned regions exhaust the alias address space). → SignalToAddress type 2 with count ≤ 0
  • a 64-bit wait could return at once or block when it should not (not met in a game). → WaitForAddress type 3: 64-bit wait if equal
  • a PhysX worker crashes in a task's removeReference with a null task manager, right as the game switches to 30 fps (pc=main+0x10ccf28, lr=main+0x13c236c); on the iPhone and in 2 of 5 Mac runs, in every Mac run with 12 busy loops loading the CPU. → Late PhysX task destructor after the unlock
  • a 30 Hz game thread runs at 27 Hz, and whatever it paces comes out slow (cutscenes at 36 ms per frame instead of 33.3; gameplay was fine at 60). → Timer slack in guest sleeps (sleep_precise)
  • a guest thread keeps a core at 100% with billions of SleepThread calls. → Sleeps under 20 µs take the yield path
  • a loading screen sits for a minute with the CPU nearly idle; one thread yields thousands of times a second, every yield a back-off sleep (the power line's top yielder, with as many back-off sleeps). → Yields that make progress return at once (thr_yield)
  • a host helper thread aborts when signalling a destroyed SystemEvent; repeated vi::GetDisplayVsyncEvent calls double the event's tick rate. Rapid replacement can abort with too many vsync events, or a retired vsync worker can signal another service's event at reused storage. → Service-event producers follow the binding lifetime
  • the main thread waits forever on a job's done event at boot while every worker sleeps, two of them on one event (main+0x1426c waiting on Job::m_doneEvent); 4 of 6 Mac runs. → One auto-clear event shared by a pool's workers
  • abort in os::WaitSystemEvent under oe::PopNotificationMessage (The Legend of Zelda: Link's Awakening); one guest thread at about 1000 ms/s on the iPhone only, the phone hot, CPU energy 5–7 W (Monster Hunter Rise's MessageSuperviseThread, priority 32, in the [nvn] threads lines). → The oe notification event and its queue
  • Paper Mario: The Thousand-Year Door 1.0.1 stays black before its first frame. The main thread stops at main+0x32796c, after starting SYS_Notification; the priority-28 notifier is in oe::PopNotificationMessage, while the priority-44 main thread waits for its same-core wake handoff. → Native HLE waits release the guest core

Services and SDK calls

Movies

Audio

Frame rate

NVN objects

Rendering

Shaders

Game state