[WIP] Audio/threading fixes + crash investigation; NEW ORACLE: crash is ours not the game
Some checks failed
Orchestrator / Commit Message Validation (push) Has been skipped
Orchestrator / Lint (push) Failing after 1m34s
Orchestrator / Windows (x86-64) (push) Has been skipped
Orchestrator / Linux (x86-64) (push) Has been skipped
Orchestrator / Create Release (push) Has been skipped
Some checks failed
Orchestrator / Commit Message Validation (push) Has been skipped
Orchestrator / Lint (push) Failing after 1m34s
Orchestrator / Windows (x86-64) (push) Has been skipped
Orchestrator / Linux (x86-64) (push) Has been skipped
Orchestrator / Create Release (push) Has been skipped
Snapshot for handoff. Contains the mission-audio + threading fixes and the
crash-investigation instrumentation (all diagnostic cvars default-OFF).
Fixes (behavioral):
- threading_posix.cc: reap-once guard on PosixCondition<Thread>::post_execution
(double pthread_join at mission teardown -> fault loop -> audio death + freeze).
- xma_decoder.cc: work_event_->Set() in Pause() so the idle XMA worker observes
paused_ and signals pause_fence_ (Pause() deadlock -> permanent audio death).
- audio_system / xma_context_master / xboxkrnl_audio / apu_flags / alsa: mission
audio keepalive + guest_audio_flags + watchdogs.
Instrumentation (additive, default-off): xboxkrnl_debug cache-throw diag +
guest-catch dispatcher, xex_module PE/PDATA/EH scans, kernel_state mem_watch
(NOTE: mem_watch DEFAULTS TRUE -- an always-on host poll thread; prime crash suspect).
NEW ORACLE (see HANDOFF-crash-oracle-2026-07-16.md): stock 6e5b8324f built with
our toolchain + zero custom code = NO crash, NO sound-stop, plays the Ready Room.
=> the Ready-Room out_of_range crash is introduced by THESE changes, not the game
and not the (LTO-broken) build chain. Bisection plan + suspect ranking in the note.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,18 @@
|
||||
|
||||
#include "xenia/apu/xma_context_master.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
|
||||
#include "xenia/base/cvar.h"
|
||||
|
||||
// [Phase-A / audio RE] Log each XMA stream's true params (channels/sample rate)
|
||||
// + head bytes so raw sound.pak entries can be matched to real decode params.
|
||||
DEFINE_bool(xma_param_probe, false,
|
||||
"Log XMA per-stream params (channels/rate/head bytes) for audio RE.",
|
||||
"APU");
|
||||
|
||||
#include "xenia/apu/xma_decoder.h"
|
||||
#include "xenia/apu/xma_helpers.h"
|
||||
@@ -317,6 +328,39 @@ void XmaContextMaster::Decode(XMA_CONTEXT_DATA* data) {
|
||||
: nullptr;
|
||||
uint8_t* current_input_buffer = data->current_buffer ? in1 : in0;
|
||||
|
||||
// [Phase-A / audio RE] Additive, cvar-gated probe: capture the true XMA
|
||||
// per-stream parameters (channels + sample rate) the game supplies, keyed by
|
||||
// the stream's head bytes so they can be matched back to a sound.pak entry
|
||||
// offline. One line per unique stream (deduped on the first 8 bytes). No
|
||||
// behaviour change — read-only, default-off.
|
||||
if (cvars::xma_param_probe && in0 && data->input_buffer_0_valid &&
|
||||
data->input_buffer_0_packet_count) {
|
||||
static std::mutex xma_probe_mu;
|
||||
static std::set<uint64_t> xma_probe_seen;
|
||||
uint64_t key;
|
||||
std::memcpy(&key, in0, sizeof(key));
|
||||
bool fresh;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(xma_probe_mu);
|
||||
fresh = xma_probe_seen.insert(key).second;
|
||||
}
|
||||
if (fresh) {
|
||||
char head[65];
|
||||
for (int i = 0; i < 32; ++i) {
|
||||
std::snprintf(head + i * 2, 3, "%02x", in0[i]);
|
||||
}
|
||||
// Warning level so it surfaces even at the audio-safe --log_level=1 the
|
||||
// interactive runner uses (Info/Debug would starve the audio thread).
|
||||
XELOGW(
|
||||
"XMA-PARAM stereo={} channels={} rate_id={} rate={} packets={} "
|
||||
"head={}",
|
||||
static_cast<uint32_t>(data->is_stereo),
|
||||
data->is_stereo ? 2 : 1, static_cast<uint32_t>(data->sample_rate),
|
||||
GetSampleRate(data->sample_rate),
|
||||
static_cast<uint32_t>(data->input_buffer_0_packet_count), head);
|
||||
}
|
||||
}
|
||||
|
||||
// XELOGAPU("Processing context {} (offset {}, buffer {}, ptr {:p})", id(),
|
||||
// data->input_buffer_read_offset, data->current_buffer,
|
||||
// current_input_buffer);
|
||||
|
||||
Reference in New Issue
Block a user