From 38918c86a8b526126acb032a8648a3797bee93ea Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Tue, 19 May 2015 21:52:21 -0500 Subject: [PATCH] Cleanup some audio system code --- src/xenia/apu/audio_system.cc | 26 ++++++--- src/xenia/apu/audio_system.h | 73 +++++++++++++++++++++++++ src/xenia/kernel/xboxkrnl_audio_xma.cc | 75 +------------------------- 3 files changed, 94 insertions(+), 80 deletions(-) diff --git a/src/xenia/apu/audio_system.cc b/src/xenia/apu/audio_system.cc index da1d8cab2..61618f9c0 100644 --- a/src/xenia/apu/audio_system.cc +++ b/src/xenia/apu/audio_system.cc @@ -295,16 +295,20 @@ void AudioSystem::WriteRegister(uint32_t addr, uint64_t value) { uint32_t guest_ptr = registers_.xma_context_array_ptr + context_id * kXmaContextSize; auto context_ptr = memory()->TranslateVirtual(guest_ptr); - uint32_t dword0 = xe::load_and_swap(context_ptr + 0); - bool has_valid_input = (dword0 & 0x00300000) != 0; + XMAContextData data(context_ptr); + + bool has_valid_input = data.input_buffer_0_valid || + data.input_buffer_1_valid; if (has_valid_input) { - dword0 = dword0 & ~0x00300000; - xe::store_and_swap(context_ptr + 0, dword0); + // Invalidate the buffers. + data.input_buffer_0_valid = 0; + data.input_buffer_1_valid = 0; + // Set output buffer to invalid. - uint32_t dword1 = xe::load_and_swap(context_ptr + 4); - dword1 = dword1 & ~0x80000000; - xe::store_and_swap(context_ptr + 4, dword1); + data.output_buffer_valid = false; } + + data.Store(context_ptr); } value >>= 1; } @@ -327,6 +331,14 @@ void AudioSystem::WriteRegister(uint32_t addr, uint64_t value) { uint32_t context_id = i + (r - 0x1A80) / 4 * 32; XELOGAPU("AudioSystem: reset context %d", context_id); // TODO(benvanik): something? + uint32_t guest_ptr = + registers_.xma_context_array_ptr + context_id * kXmaContextSize; + auto context_ptr = memory()->TranslateVirtual(guest_ptr); + XMAContextData data(context_ptr); + + + + data.Store(context_ptr); } value >>= 1; } diff --git a/src/xenia/apu/audio_system.h b/src/xenia/apu/audio_system.h index fc2f61381..89327533c 100644 --- a/src/xenia/apu/audio_system.h +++ b/src/xenia/apu/audio_system.h @@ -26,6 +26,79 @@ namespace apu { class AudioDriver; +// This is stored in guest space in big-endian order. +// We load and swap the whole thing to splat here so that we can +// use bitfields. +struct XMAContextData { + static const uint32_t kSize = 64; + static const uint32_t kBytesPerBlock = 2048; + static const uint32_t kSamplesPerFrame = 512; + static const uint32_t kSamplesPerSubframe = 128; + + // DWORD 0 + uint32_t input_buffer_0_block_count : 12; // XMASetInputBuffer0, number of + // 2KB blocks. + uint32_t loop_count : 8; // +12bit, XMASetLoopData + uint32_t input_buffer_0_valid : 1; // +20bit, XMAIsInputBuffer0Valid + uint32_t input_buffer_1_valid : 1; // +21bit, XMAIsInputBuffer1Valid + uint32_t output_buffer_block_count : 5; // +22bit + uint32_t + output_buffer_write_offset : 5; // +27bit, XMAGetOutputBufferWriteOffset + + // DWORD 1 + uint32_t input_buffer_1_block_count : 12; // XMASetInputBuffer1, number of + // 2KB blocks. + uint32_t loop_subframe_end : 2; // +12bit, XMASetLoopData + uint32_t unk_dword_1_a : 3; // ? + uint32_t loop_subframe_skip : 3; // +17bit, XMASetLoopData + uint32_t subframe_decode_count : 4; // +20bit + uint32_t unk_dword_1_b : 3; // ? + uint32_t sample_rate : 2; // +27bit + uint32_t is_stereo : 1; // +29bit + uint32_t unk_dword_1_c : 1; // ? + uint32_t output_buffer_valid : 1; // +31bit, XMAIsOutputBufferValid + + // DWORD 2 + uint32_t input_buffer_read_offset : 30; // XMAGetInputBufferReadOffset + uint32_t unk_dword_2 : 2; // ? + + // DWORD 3 + uint32_t loop_start : 26; // XMASetLoopData + uint32_t unk_dword_3 : 6; // ? + + // DWORD 4 + uint32_t loop_end : 26; // XMASetLoopData + uint32_t packet_metadata : 5; // XMAGetPacketMetadata + uint32_t current_buffer : 1; // ? + + // DWORD 5 + uint32_t input_buffer_0_ptr; // physical address + // DWORD 6 + uint32_t input_buffer_1_ptr; // physical address + // DWORD 7 + uint32_t output_buffer_ptr; // physical address + // DWORD 8 + uint32_t unk_dword_8; // Some kind of pointer like output_buffer_ptr + + // DWORD 9 + uint32_t + output_buffer_read_offset : 5; // +0bit, XMAGetOutputBufferReadOffset + uint32_t unk_dword_9 : 27; + + XMAContextData(const void* ptr) { + xe::copy_and_swap_32_aligned(reinterpret_cast(this), + reinterpret_cast(ptr), + sizeof(XMAContextData) / 4); + } + + void Store(void* ptr) { + xe::copy_and_swap_32_aligned(reinterpret_cast(ptr), + reinterpret_cast(this), + sizeof(XMAContextData) / 4); + } +}; +static_assert(sizeof(XMAContextData) == 4 * 10, "Must be packed"); + class AudioSystem { public: virtual ~AudioSystem(); diff --git a/src/xenia/kernel/xboxkrnl_audio_xma.cc b/src/xenia/kernel/xboxkrnl_audio_xma.cc index 708af52d6..a2c51b79c 100644 --- a/src/xenia/kernel/xboxkrnl_audio_xma.cc +++ b/src/xenia/kernel/xboxkrnl_audio_xma.cc @@ -15,6 +15,8 @@ #include "xenia/kernel/xboxkrnl_private.h" #include "xenia/xbox.h" +using namespace xe::apu; + namespace xe { namespace kernel { @@ -78,79 +80,6 @@ SHIM_CALL XMAReleaseContext_shim(PPCContext* ppc_state, KernelState* state) { SHIM_SET_RETURN_32(0); } -// This is stored in guest space in big-endian order. -// We load and swap the whole thing to splat here so that we can -// use bitfields. -struct XMAContextData { - static const uint32_t kSize = 64; - static const uint32_t kBytesPerBlock = 2048; - static const uint32_t kSamplesPerFrame = 512; - static const uint32_t kSamplesPerSubframe = 128; - - // DWORD 0 - uint32_t input_buffer_0_block_count : 12; // XMASetInputBuffer0, number of - // 2KB blocks. - uint32_t loop_count : 8; // +12bit, XMASetLoopData - uint32_t input_buffer_0_valid : 1; // +20bit, XMAIsInputBuffer0Valid - uint32_t input_buffer_1_valid : 1; // +21bit, XMAIsInputBuffer1Valid - uint32_t output_buffer_block_count : 5; // +22bit - uint32_t - output_buffer_write_offset : 5; // +27bit, XMAGetOutputBufferWriteOffset - - // DWORD 1 - uint32_t input_buffer_1_block_count : 12; // XMASetInputBuffer1, number of - // 2KB blocks. - uint32_t loop_subframe_end : 2; // +12bit, XMASetLoopData - uint32_t unk_dword_1_a : 3; // ? - uint32_t loop_subframe_skip : 3; // +17bit, XMASetLoopData - uint32_t subframe_decode_count : 4; // +20bit - uint32_t unk_dword_1_b : 3; // ? - uint32_t sample_rate : 2; // +27bit - uint32_t is_stereo : 1; // +29bit - uint32_t unk_dword_1_c : 1; // ? - uint32_t output_buffer_valid : 1; // +31bit, XMAIsOutputBufferValid - - // DWORD 2 - uint32_t input_buffer_read_offset : 30; // XMAGetInputBufferReadOffset - uint32_t unk_dword_2 : 2; // ? - - // DWORD 3 - uint32_t loop_start : 26; // XMASetLoopData - uint32_t unk_dword_3 : 6; // ? - - // DWORD 4 - uint32_t loop_end : 26; // XMASetLoopData - uint32_t packet_metadata : 5; // XMAGetPacketMetadata - uint32_t current_buffer : 1; // ? - - // DWORD 5 - uint32_t input_buffer_0_ptr; // top bits lopped off? - // DWORD 6 - uint32_t input_buffer_1_ptr; // top bits lopped off? - // DWORD 7 - uint32_t output_buffer_ptr; // top bits lopped off? - // DWORD 8 - uint32_t unk_dword_8; // Some kind of pointer like output_buffer_ptr - - // DWORD 9 - uint32_t - output_buffer_read_offset : 5; // +0bit, XMAGetOutputBufferReadOffset - uint32_t unk_dword_9 : 27; - - XMAContextData(const void* ptr) { - xe::copy_and_swap_32_aligned(reinterpret_cast(this), - reinterpret_cast(ptr), - sizeof(XMAContextData) / 4); - } - - void Store(void* ptr) { - xe::copy_and_swap_32_aligned(reinterpret_cast(ptr), - reinterpret_cast(this), - sizeof(XMAContextData) / 4); - } -}; -static_assert(sizeof(XMAContextData) == 4 * 10, "Must be packed"); - void StoreXmaContextIndexedRegister(KernelState* state, uint32_t base_reg, uint32_t context_ptr) { auto audio_system = state->emulator()->audio_system();