Files
Xenia-Canary/src/xenia/apu/xma_decoder.h
Herman S. 2d6b7c6ca1 [XMA] Fix dedicated thread stalls by blocking guest audio thread
Includes various other thread safety and timing related adjustments
2026-02-17 13:57:32 +09:00

95 lines
2.7 KiB
C++

/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2021 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_APU_XMA_DECODER_H_
#define XENIA_APU_XMA_DECODER_H_
#include <atomic>
#include <mutex>
#include <queue>
#include "xenia/apu/xma_context.h"
#include "xenia/apu/xma_register_file.h"
#include "xenia/base/bit_map.h"
#include "xenia/kernel/xthread.h"
#include "xenia/xbox.h"
namespace xe {
namespace apu {
struct XMA_CONTEXT_DATA;
class XmaDecoder {
public:
explicit XmaDecoder(cpu::Processor* processor);
~XmaDecoder();
Memory* memory() const { return memory_; }
cpu::Processor* processor() const { return processor_; }
X_STATUS Setup(kernel::KernelState* kernel_state);
void Shutdown();
uint32_t context_array_ptr() const {
return register_file_[XmaRegister::ContextArrayAddress];
}
uint32_t AllocateContext();
void ReleaseContext(uint32_t guest_ptr);
bool BlockOnContext(uint32_t guest_ptr, bool poll);
uint32_t ReadRegister(uint32_t addr);
void WriteRegister(uint32_t addr, uint32_t value);
bool is_paused() const { return paused_.load(std::memory_order_acquire); }
void Pause();
void Resume();
protected:
int GetContextId(uint32_t guest_ptr);
private:
void WorkerThreadMain();
static uint32_t MMIOReadRegisterThunk(void* ppc_context, XmaDecoder* as,
uint32_t addr) {
return as->ReadRegister(addr);
}
static void MMIOWriteRegisterThunk(void* ppc_context, XmaDecoder* as,
uint32_t addr, uint32_t value) {
as->WriteRegister(addr, value);
}
protected:
Memory* memory_ = nullptr;
cpu::Processor* processor_ = nullptr;
std::atomic<bool> worker_running_ = {false};
kernel::object_ref<kernel::XHostThread> worker_thread_;
std::unique_ptr<xe::threading::Event> work_event_ = nullptr;
std::atomic<bool> paused_ = false;
xe::threading::Fence pause_fence_; // Signaled when worker paused.
xe::threading::Fence resume_fence_; // Signaled when resume requested.
XmaRegisterFile register_file_;
static const uint32_t kContextCount = 320;
XmaContext* contexts_[kContextCount];
BitMap context_bitmap_;
uint32_t context_data_first_ptr_ = 0;
uint32_t context_data_last_ptr_ = 0;
};
} // namespace apu
} // namespace xe
#endif // XENIA_APU_XMA_DECODER_H_