Removed XMAContextData::kSize constant, moved kXmaContextCount, changes to use newer ringbuffer, cleaned up XMAInitializeContext a bit (with fixes for loop_data handling).

This commit is contained in:
gibbed 2015-06-19 09:54:10 -05:00
parent f1e9c36f00
commit f3547a832f
3 changed files with 56 additions and 35 deletions

View File

@ -56,11 +56,6 @@ namespace apu {
using namespace xe::cpu;
// Size of a hardware XMA context.
const uint32_t kXmaContextSize = 64;
// Total number of XMA contexts available.
const uint32_t kXmaContextCount = 320;
AudioSystem::AudioSystem(Emulator* emulator)
: emulator_(emulator),
memory_(emulator->memory()),
@ -99,10 +94,10 @@ X_STATUS AudioSystem::Setup() {
// Setup XMA contexts ptr.
registers_.xma_context_array_ptr = memory()->SystemHeapAlloc(
kXmaContextSize * kXmaContextCount, 256, kSystemHeapPhysical);
sizeof(XMAContextData) * kXmaContextCount, 256, kSystemHeapPhysical);
// Add all contexts to the free list.
for (int i = kXmaContextCount - 1; i >= 0; --i) {
uint32_t ptr = registers_.xma_context_array_ptr + i * kXmaContextSize;
uint32_t ptr = registers_.xma_context_array_ptr + i * sizeof(XMAContextData);
XMAContext& context = xma_context_array_[i];
@ -268,7 +263,7 @@ void AudioSystem::ReleaseXmaContext(uint32_t guest_ptr) {
context.in_use = false;
auto context_ptr = memory()->TranslateVirtual(guest_ptr);
std::memset(context_ptr, 0, kXmaContextSize); // Zero it.
std::memset(context_ptr, 0, sizeof(XMAContextData)); // Zero it.
context.decoder->DiscardPacket();
context.lock.unlock();
@ -380,9 +375,8 @@ void AudioSystem::ProcessXmaContext(XMAContext& context, XMAContextData& data) {
uint32_t output_write_offset_bytes = data.output_buffer_write_offset * 256;
uint32_t output_read_offset_bytes = data.output_buffer_read_offset * 256;
RingBuffer output_buffer(out, output_size_bytes, output_write_offset_bytes);
size_t output_remaining_bytes
= output_buffer.DistanceToOffset(output_read_offset_bytes);
RingBuffer output_buffer(out, output_size_bytes, output_read_offset_bytes, output_write_offset_bytes);
size_t output_remaining_bytes = output_buffer.write_size();
if (!output_remaining_bytes) {
// Can't write any more data. Break.
@ -618,8 +612,8 @@ void AudioSystem::WriteRegister(uint32_t addr, uint64_t value) {
XMAContext& context = xma_context_array_[context_id];
XELOGAPU("AudioSystem: reset context %d", context_id);
uint32_t guest_ptr =
registers_.xma_context_array_ptr + context_id * kXmaContextSize;
uint32_t guest_ptr = registers_.xma_context_array_ptr +
context_id * sizeof(XMAContextData);
context.lock.lock();
auto context_ptr = memory()->TranslateVirtual(context.guest_ptr);
XMAContextData data(context_ptr);

View File

@ -38,7 +38,6 @@ class AudioDecoder;
// http://pastebin.com/9amqJ2kQ
struct XMAContextData {
static const uint32_t kSize = 64;
static const uint32_t kBytesPerPacket = 2048;
static const uint32_t kSamplesPerFrame = 512;
static const uint32_t kSamplesPerSubframe = 128;
@ -100,6 +99,9 @@ struct XMAContextData {
uint32_t output_buffer_read_offset : 5;
uint32_t unk_dword_9 : 27; // StopWhenDone/InterruptWhenDone(?)
// DWORD 10-15
uint32_t unk_dwords_10_15[6]; // reserved?
XMAContextData(const void* ptr) {
xe::copy_and_swap_32_aligned(reinterpret_cast<uint32_t*>(this),
reinterpret_cast<const uint32_t*>(ptr),
@ -112,7 +114,7 @@ struct XMAContextData {
sizeof(XMAContextData) / 4);
}
};
static_assert(sizeof(XMAContextData) == 4 * 10, "Must be packed");
static_assert_size(XMAContextData, 64);
class AudioSystem {
protected:
@ -211,7 +213,8 @@ class AudioSystem {
AudioDecoder* decoder;
};
XMAContext xma_context_array_[320];
static const uint32_t kXmaContextCount = 320; // // Total number of XMA contexts available.
XMAContext xma_context_array_[kXmaContextCount];
std::vector<uint32_t> xma_context_free_list_;
std::vector<uint32_t> xma_context_used_list_; // XMA contexts in use

View File

@ -88,12 +88,36 @@ void StoreXmaContextIndexedRegister(KernelState* kernel_state,
uint32_t base_reg, uint32_t context_ptr) {
auto audio_system = kernel_state->emulator()->audio_system();
uint32_t hw_index = (context_ptr - audio_system->xma_context_array_ptr()) /
XMAContextData::kSize;
sizeof(XMAContextData);
uint32_t reg_num = base_reg + (hw_index >> 5) * 4;
uint32_t reg_value = 1 << (hw_index & 0x1F);
audio_system->WriteRegister(reg_num, xe::byte_swap(reg_value));
}
struct X_XMA_CONTEXT_INIT_LOOP_DATA {
xe::be<uint32_t> loop_start;
xe::be<uint32_t> loop_end;
xe::be<uint8_t> loop_count;
xe::be<uint8_t> loop_subframe_end;
xe::be<uint8_t> loop_subframe_skip;
};
struct X_XMA_CONTEXT_INIT {
xe::be<uint32_t> input_buffer_0_ptr;
xe::be<uint32_t> input_buffer_0_packet_count;
xe::be<uint32_t> input_buffer_1_ptr;
xe::be<uint32_t> input_buffer_1_packet_count;
xe::be<uint32_t> input_buffer_read_offset;
xe::be<uint32_t> output_buffer_ptr;
xe::be<uint32_t> output_buffer_block_count;
xe::be<uint32_t> work_buffer;
xe::be<uint32_t> subframe_decode_count;
xe::be<uint32_t> channel_count;
xe::be<uint32_t> sample_rate;
X_XMA_CONTEXT_INIT_LOOP_DATA loop_data;
};
static_assert_size(X_XMA_CONTEXT_INIT, 56);
SHIM_CALL XMAInitializeContext_shim(PPCContext* ppc_context,
KernelState* kernel_state) {
uint32_t context_ptr = SHIM_GET_ARG_32(0);
@ -101,29 +125,29 @@ SHIM_CALL XMAInitializeContext_shim(PPCContext* ppc_context,
XELOGD("XMAInitializeContext(%.8X, %.8X)", context_ptr, context_init_ptr);
std::memset(SHIM_MEM_ADDR(context_ptr), 0, XMAContextData::kSize);
std::memset(SHIM_MEM_ADDR(context_ptr), 0, sizeof(XMAContextData));
XMAContextData context(SHIM_MEM_ADDR(context_ptr));
auto context_init = (X_XMA_CONTEXT_INIT*)SHIM_MEM_ADDR(context_init_ptr);
context.input_buffer_0_ptr = SHIM_MEM_32(context_init_ptr + 0 * 4);
context.input_buffer_0_packet_count = SHIM_MEM_32(context_init_ptr + 1 * 4);
context.input_buffer_1_ptr = SHIM_MEM_32(context_init_ptr + 2 * 4);
context.input_buffer_1_packet_count = SHIM_MEM_32(context_init_ptr + 3 * 4);
context.input_buffer_read_offset = SHIM_MEM_32(context_init_ptr + 4 * 4);
context.output_buffer_ptr = SHIM_MEM_32(context_init_ptr + 5 * 4);
context.output_buffer_block_count = SHIM_MEM_32(context_init_ptr + 6 * 4);
context.input_buffer_0_ptr = context_init->input_buffer_0_ptr;
context.input_buffer_0_packet_count = context_init->input_buffer_0_packet_count;
context.input_buffer_1_ptr = context_init->input_buffer_1_ptr;
context.input_buffer_1_packet_count = context_init->input_buffer_1_packet_count;
context.input_buffer_read_offset = context_init->input_buffer_read_offset;
context.output_buffer_ptr = context_init->output_buffer_ptr;
context.output_buffer_block_count = context_init->output_buffer_block_count;
// context.work_buffer = SHIM_MEM_32(context_init_ptr + 7 * 4); // ?
context.subframe_decode_count = SHIM_MEM_32(context_init_ptr + 8 * 4);
context.is_stereo = SHIM_MEM_32(context_init_ptr + 9 * 4) == 2;
context.sample_rate = SHIM_MEM_32(context_init_ptr + 10 * 4);
// context.work_buffer = context_init->work_buffer; // ?
context.subframe_decode_count = context_init->subframe_decode_count;
context.is_stereo = context_init->channel_count == 2;
context.sample_rate = context_init->sample_rate;
uint32_t loop_data_ptr = context_init_ptr + 11 * 4;
context.loop_start = SHIM_MEM_32(loop_data_ptr + 0);
context.loop_end = SHIM_MEM_32(loop_data_ptr + 4);
context.loop_count = SHIM_MEM_8(loop_data_ptr + 6);
context.loop_subframe_end = SHIM_MEM_8(loop_data_ptr + 6);
context.loop_subframe_skip = SHIM_MEM_8(loop_data_ptr + 7);
context.loop_start = context_init->loop_data.loop_start;
context.loop_end = context_init->loop_data.loop_end;
context.loop_count = context_init->loop_data.loop_count;
context.loop_subframe_end = context_init->loop_data.loop_subframe_end;
context.loop_subframe_skip = context_init->loop_data.loop_subframe_skip;
context.Store(SHIM_MEM_ADDR(context_ptr));