rexglue-skate3/include/rex/audio/xma/decoder.h
2026-05-18 22:41:13 +01:00

92 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. *
******************************************************************************
*
* @modified Tom Clay, 2026 - Adapted for ReXGlue runtime
*/
#pragma once
#include <atomic>
#include <mutex>
#include <queue>
#include <rex/audio/xma/context.h>
#include <rex/audio/xma/register_file.h>
#include <rex/bit.h>
#include <rex/kernel.h>
#include <rex/system/xthread.h>
namespace rex::runtime {
class FunctionDispatcher;
} // namespace rex::runtime
namespace rex::audio {
struct XMA_CONTEXT_DATA;
class XmaDecoder {
public:
explicit XmaDecoder(runtime::FunctionDispatcher* function_dispatcher);
~XmaDecoder();
memory::Memory* memory() const { return memory_; }
runtime::FunctionDispatcher* function_dispatcher() const { return function_dispatcher_; }
X_STATUS Setup(system::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_; }
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* memory_ = nullptr;
runtime::FunctionDispatcher* function_dispatcher_ = nullptr;
std::atomic<bool> worker_running_ = {false};
system::object_ref<system::XHostThread> worker_thread_;
std::unique_ptr<rex::thread::Event> work_event_ = nullptr;
std::atomic<bool> paused_ = false;
rex::thread::Fence pause_fence_; // Signaled when worker paused.
rex::thread::Fence resume_fence_; // Signaled when resume requested.
XmaRegisterFile register_file_;
static const uint32_t kContextCount = 320;
XmaContext contexts_[kContextCount];
bit::BitMap context_bitmap_;
uint32_t context_data_first_ptr_ = 0;
uint32_t context_data_last_ptr_ = 0;
};
} // namespace rex::audio