diff --git a/src/xenia/apu/audio_system.cc b/src/xenia/apu/audio_system.cc index 8f2c24f14..22e719c35 100644 --- a/src/xenia/apu/audio_system.cc +++ b/src/xenia/apu/audio_system.cc @@ -103,8 +103,6 @@ X_STATUS AudioSystem::Setup() { } registers_.next_context = 1; - // Threads - worker_running_ = true; worker_thread_ = kernel::object_ref(new kernel::XHostThread( @@ -366,10 +364,29 @@ void AudioSystem::ReleaseXmaContext(uint32_t guest_ptr) { context.decoder->DiscardPacket(); context.lock.unlock(); + break; } } } +bool AudioSystem::BlockOnXmaContext(uint32_t guest_ptr, bool poll) { + std::lock_guard lock(lock_); + for (uint32_t n = 0; n < kXmaContextCount; n++) { + XMAContext& context = xma_context_array_[n]; + if (context.guest_ptr == guest_ptr) { + if (!context.lock.try_lock()) { + if (poll) { + return false; + } + context.lock.lock(); + } + context.lock.unlock(); + return true; + } + } + return true; +} + X_STATUS AudioSystem::RegisterClient(uint32_t callback, uint32_t callback_arg, size_t* out_index) { assert_true(unused_clients_.size()); @@ -450,6 +467,8 @@ uint64_t AudioSystem::ReadRegister(uint32_t addr) { } void AudioSystem::WriteRegister(uint32_t addr, uint64_t value) { + SCOPE_profile_cpu_f("apu"); + uint32_t r = addr & 0xFFFF; value = xe::byte_swap(uint32_t(value)); XELOGAPU("WriteRegister(%.4X, %.8X)", r, value); @@ -486,12 +505,12 @@ void AudioSystem::WriteRegister(uint32_t addr, uint64_t value) { data.Store(context_ptr); context.lock.unlock(); - - // Signal the decoder thread - decoder_fence_.Signal(); } value >>= 1; } + + // Signal the decoder thread to start processing. + decoder_fence_.Signal(); } else if (r >= 0x1A40 && r <= 0x1A40 + 9 * 4) { // Context lock command. // This requests a lock by flagging the context. diff --git a/src/xenia/apu/audio_system.h b/src/xenia/apu/audio_system.h index 80c084410..53b3a0ec0 100644 --- a/src/xenia/apu/audio_system.h +++ b/src/xenia/apu/audio_system.h @@ -126,6 +126,7 @@ class AudioSystem { } uint32_t AllocateXmaContext(); void ReleaseXmaContext(uint32_t guest_ptr); + bool BlockOnXmaContext(uint32_t guest_ptr, bool poll); X_STATUS RegisterClient(uint32_t callback, uint32_t callback_arg, size_t* out_index); diff --git a/src/xenia/cpu/mmio_handler_win.cc b/src/xenia/cpu/mmio_handler_win.cc index 86beca9ec..184cf1163 100644 --- a/src/xenia/cpu/mmio_handler_win.cc +++ b/src/xenia/cpu/mmio_handler_win.cc @@ -11,6 +11,8 @@ #include +#include "xenia/profiling.h" + namespace xe { void CrashDump(); } // namespace xe @@ -61,6 +63,8 @@ WinMMIOHandler::~WinMMIOHandler() { // addresses in our range and call into the registered handlers, if any. // If there are none, we continue. LONG CALLBACK MMIOExceptionHandler(PEXCEPTION_POINTERS ex_info) { + SCOPE_profile_cpu_i("cpu", "MMIOExceptionHandler"); + // http://msdn.microsoft.com/en-us/library/ms679331(v=vs.85).aspx // http://msdn.microsoft.com/en-us/library/aa363082(v=vs.85).aspx auto code = ex_info->ExceptionRecord->ExceptionCode; diff --git a/src/xenia/kernel/xboxkrnl_audio_xma.cc b/src/xenia/kernel/xboxkrnl_audio_xma.cc index a2c51b79c..4ec2c182a 100644 --- a/src/xenia/kernel/xboxkrnl_audio_xma.cc +++ b/src/xenia/kernel/xboxkrnl_audio_xma.cc @@ -87,8 +87,7 @@ void StoreXmaContextIndexedRegister(KernelState* state, uint32_t base_reg, XMAContextData::kSize; uint32_t reg_num = base_reg + (hw_index >> 5) * 4; uint32_t reg_value = 1 << (hw_index & 0x1F); - xe::store(state->memory()->TranslateVirtual(0x7FEA0000 + reg_num), - reg_value); + audio_system->WriteRegister(reg_num, xe::byte_swap(reg_value)); } SHIM_CALL XMAInitializeContext_shim(PPCContext* ppc_state, KernelState* state) { @@ -372,7 +371,9 @@ SHIM_CALL XMADisableContext_shim(PPCContext* ppc_state, KernelState* state) { X_HRESULT result = X_E_SUCCESS; StoreXmaContextIndexedRegister(state, 0x1A40, context_ptr); - XMAContextData context(SHIM_MEM_ADDR(context_ptr)); + if (!state->emulator()->audio_system()->BlockOnXmaContext(context_ptr, !wait)) { + result = X_E_FALSE; + } SHIM_SET_RETURN_32(result); }