diff --git a/src/alloy/frontend/ppc/ppc_emit_altivec.cc b/src/alloy/frontend/ppc/ppc_emit_altivec.cc index b2f9ab80d..0f8dce4ac 100644 --- a/src/alloy/frontend/ppc/ppc_emit_altivec.cc +++ b/src/alloy/frontend/ppc/ppc_emit_altivec.cc @@ -1610,8 +1610,8 @@ XEEMITTER(vsrh, 0x10000244, VX)(PPCHIRBuilder& f, InstrData& i) { int InstrEmit_vsro_(PPCHIRBuilder& f, uint32_t vd, uint32_t va, uint32_t vb) { // (VD) <- (VA) >> (VB.b[F] & 0x78) (by octet) // TODO(benvanik): flag for shift-by-octet as optimization. - Value* sh = - f.And(f.Extract(f.LoadVR(vb), 15, INT8_TYPE), f.LoadConstant(0x78)); + Value* sh = f.And(f.Extract(f.LoadVR(vb), 15, INT8_TYPE), + f.LoadConstant(uint8_t(0x78))); Value* v = f.Permute(f.LoadVectorShr(sh), f.LoadVR(va), f.LoadZero(VEC128_TYPE), INT8_TYPE); f.StoreVR(vd, v); diff --git a/src/alloy/hir/hir_builder.cc b/src/alloy/hir/hir_builder.cc index 45c09bad2..6eb3f5cc2 100644 --- a/src/alloy/hir/hir_builder.cc +++ b/src/alloy/hir/hir_builder.cc @@ -26,7 +26,8 @@ using alloy::runtime::FunctionInfo; #define ASSERT_FLOAT_TYPE(value) #define ASSERT_NON_VECTOR_TYPE(value) #define ASSERT_VECTOR_TYPE(value) -#define ASSERT_TYPES_EQUAL(value1, value2) +#define ASSERT_TYPES_EQUAL(value1, value2) \ + assert_true((value1->type) == (value2->type)) HIRBuilder::HIRBuilder() { arena_ = new Arena(); diff --git a/src/xenia/apu/audio_system.cc b/src/xenia/apu/audio_system.cc index 12e77d195..52b86be40 100644 --- a/src/xenia/apu/audio_system.cc +++ b/src/xenia/apu/audio_system.cc @@ -272,8 +272,7 @@ uint64_t AudioSystem::ReadRegister(uint64_t addr) { // To prevent games from seeing a stuck XMA context, return a rotating // number registers_.current_context = registers_.next_context; - registers_.next_context = - (registers_.next_context + 1) % kXmaContextCount; + registers_.next_context = (registers_.next_context + 1) % kXmaContextCount; value = registers_.current_context; } @@ -290,18 +289,19 @@ void AudioSystem::WriteRegister(uint64_t addr, uint64_t value) { assert_true(r % 4 == 0); register_file_[r / 4] = uint32_t(value); - if (r >= 0x1940 && r <= 0x1949) { + if (r >= 0x1940 && r <= 0x1940 + 9 * 4) { // Context kick command. // This will kick off the given hardware contexts. for (int i = 0; value && i < 32; ++i) { if (value & 1) { - uint32_t context_id = i + (r - 0x1940) * 32; - XELOGD("AudioSystem: kicking context %d", context_id); + uint32_t context_id = i + (r - 0x1940) / 4 * 32; + XELOGAPU("AudioSystem: kicking context %d", context_id); // Games check bits 20/21 of context[0]. // If both bits are set buffer full, otherwise room available. // Right after a kick we always set buffers to invalid so games keep // feeding data. - uint32_t guest_ptr = registers_.xma_context_array_ptr + context_id * kXmaContextSize; + uint32_t guest_ptr = + registers_.xma_context_array_ptr + context_id * kXmaContextSize; auto context_ptr = memory()->Translate(guest_ptr); uint32_t dword0 = poly::load_and_swap(context_ptr + 0); bool has_valid_input = (dword0 & 0x00300000) != 0; @@ -316,24 +316,24 @@ void AudioSystem::WriteRegister(uint64_t addr, uint64_t value) { } value >>= 1; } - } else if (r >= 0x1A40 && r <= 0x1A49) { + } else if (r >= 0x1A40 && r <= 0x1A40 + 9 * 4) { // Context lock command. // This requests a lock by flagging the context. for (int i = 0; value && i < 32; ++i) { if (value & 1) { - uint32_t context_id = i + (r - 0x1A40) * 32; - XELOGD("AudioSystem: set context lock %d", context_id); + uint32_t context_id = i + (r - 0x1A40) / 4 * 32; + XELOGAPU("AudioSystem: set context lock %d", context_id); // TODO(benvanik): set lock? } value >>= 1; } - } else if (r >= 0x1A80 && r <= 0x1A89) { + } else if (r >= 0x1A80 && r <= 0x1A80 + 9 * 4) { // Context clear command. // This will reset the given hardware contexts. for (int i = 0; value && i < 32; ++i) { if (value & 1) { - uint32_t context_id = i + (r - 0x1A80) * 32; - XELOGD("AudioSystem: reset context %d", context_id); + uint32_t context_id = i + (r - 0x1A80) / 4 * 32; + XELOGAPU("AudioSystem: reset context %d", context_id); // TODO(benvanik): something? } value >>= 1; diff --git a/src/xenia/apu/audio_system.h b/src/xenia/apu/audio_system.h index e83775e22..b76e2b42f 100644 --- a/src/xenia/apu/audio_system.h +++ b/src/xenia/apu/audio_system.h @@ -35,6 +35,9 @@ class AudioSystem { virtual X_STATUS Setup(); virtual void Shutdown(); + uint32_t xma_context_array_ptr() const { + return registers_.xma_context_array_ptr; + } uint32_t AllocateXmaContext(); void ReleaseXmaContext(uint32_t guest_ptr); diff --git a/src/xenia/kernel/xboxkrnl_audio_xma.cc b/src/xenia/kernel/xboxkrnl_audio_xma.cc index 0fa3865db..ff4bde159 100644 --- a/src/xenia/kernel/xboxkrnl_audio_xma.cc +++ b/src/xenia/kernel/xboxkrnl_audio_xma.cc @@ -50,64 +50,6 @@ namespace kernel { // XAudio2 uses XMA under the covers, and seems to map with the same // restrictions of frame/subframe/etc: // https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.xaudio2.xaudio2_buffer(v=vs.85).aspx -// -// -//static const uint32_t kBytesPerBlock = 2048; -//static const uint32_t kSamplesPerFrame = 512; -//static const uint32_t kSamplesPerSubframe = 128; -// -//// This is unused; just for documentation of reversing. -//struct XMAContextType { -// // 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; -//}; SHIM_CALL XMACreateContext_shim(PPCContext* ppc_state, KernelState* state) { uint32_t context_out_ptr = SHIM_GET_ARG_32(0); @@ -136,31 +78,422 @@ 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) { + poly::copy_and_swap_32_aligned(reinterpret_cast(this), + reinterpret_cast(ptr), + sizeof(XMAContextData) / 4); + } + + void Store(void* ptr) { + poly::copy_and_swap_32_aligned(reinterpret_cast(ptr), + reinterpret_cast(this), + sizeof(XMAContextData) / 4); + } +}; +static_assert(sizeof(XMAContextData) == 4 * 10, "Must be packed"); + +void StoreXmaRegister(uint8_t* membase, uint32_t num, uint32_t value) { + poly::store(membase + (0x7FEA0000 + num), value); +} + +void StoreXmaContextIndexedRegister(KernelState* state, uint32_t base_reg, + uint32_t context_ptr) { + auto audio_system = state->emulator()->audio_system(); + uint32_t hw_index = (context_ptr - audio_system->xma_context_array_ptr()) / + XMAContextData::kSize; + uint32_t reg_num = base_reg + (hw_index >> 5) * 4; + uint32_t reg_value = 1 << (hw_index & 0x1F); + StoreXmaRegister(state->memory()->membase(), reg_num, reg_value); +} + +SHIM_CALL XMAInitializeContext_shim(PPCContext* ppc_state, KernelState* state) { + uint32_t context_ptr = SHIM_GET_ARG_32(0); + uint32_t context_init_ptr = SHIM_GET_ARG_32(1); + + XELOGD("XMAInitializeContext(%.8X, %.8X)", context_ptr, context_init_ptr); + + std::memset(SHIM_MEM_ADDR(context_ptr), 0, XMAContextData::kSize); + + XMAContextData context(SHIM_MEM_ADDR(context_ptr)); + + context.input_buffer_0_ptr = SHIM_MEM_32(context_init_ptr + 0 * 4); + context.input_buffer_0_block_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_block_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.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); + + 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.Store(SHIM_MEM_ADDR(context_ptr)); + + StoreXmaContextIndexedRegister(state, 0x1A80, context_ptr); + + SHIM_SET_RETURN_32(0); +} + +SHIM_CALL XMASetLoopData_shim(PPCContext* ppc_state, KernelState* state) { + uint32_t context_ptr = SHIM_GET_ARG_32(0); + uint32_t loop_data_ptr = SHIM_GET_ARG_32(1); + + XELOGD("XMASetLoopData(%.8X, %.8X)", context_ptr, loop_data_ptr); + + XMAContextData context(SHIM_MEM_ADDR(context_ptr)); + + 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.Store(SHIM_MEM_ADDR(context_ptr)); + + SHIM_SET_RETURN_32(0); +} + +SHIM_CALL XMAGetInputBufferReadOffset_shim(PPCContext* ppc_state, + KernelState* state) { + uint32_t context_ptr = SHIM_GET_ARG_32(0); + + XELOGD("XMAGetInputBufferReadOffset(%.8X)", context_ptr); + + XMAContextData context(SHIM_MEM_ADDR(context_ptr)); + + uint32_t result = context.input_buffer_read_offset; + + SHIM_SET_RETURN_32(result); +} + +SHIM_CALL XMASetInputBufferReadOffset_shim(PPCContext* ppc_state, + KernelState* state) { + uint32_t context_ptr = SHIM_GET_ARG_32(0); + uint32_t value = SHIM_GET_ARG_32(1); + + XELOGD("XMASetInputBufferReadOffset(%.8X, %.8X)", context_ptr, value); + + XMAContextData context(SHIM_MEM_ADDR(context_ptr)); + + context.input_buffer_read_offset = value; + + context.Store(SHIM_MEM_ADDR(context_ptr)); + + SHIM_SET_RETURN_32(0); +} + +SHIM_CALL XMASetInputBuffer0_shim(PPCContext* ppc_state, KernelState* state) { + uint32_t context_ptr = SHIM_GET_ARG_32(0); + uint32_t buffer_ptr = SHIM_GET_ARG_32(1); + uint32_t block_count = SHIM_GET_ARG_32(2); + + XELOGD("XMASetInputBuffer0(%.8X, %.8X, %d)", context_ptr, buffer_ptr, + block_count); + + XMAContextData context(SHIM_MEM_ADDR(context_ptr)); + + context.input_buffer_0_ptr = buffer_ptr; + context.input_buffer_0_block_count = block_count; + context.input_buffer_read_offset = 32; // in bits + context.input_buffer_0_valid = buffer_ptr ? 1 : 0; + + context.Store(SHIM_MEM_ADDR(context_ptr)); + + SHIM_SET_RETURN_32(0); +} + +SHIM_CALL XMAIsInputBuffer0Valid_shim(PPCContext* ppc_state, + KernelState* state) { + uint32_t context_ptr = SHIM_GET_ARG_32(0); + + XELOGD("XMAIsInputBuffer0Valid(%.8X)", context_ptr); + + XMAContextData context(SHIM_MEM_ADDR(context_ptr)); + + uint32_t result = context.input_buffer_0_valid; + + SHIM_SET_RETURN_32(result); +} + +SHIM_CALL XMASetInputBuffer0Valid_shim(PPCContext* ppc_state, + KernelState* state) { + uint32_t context_ptr = SHIM_GET_ARG_32(0); + + XELOGD("XMASetInputBuffer0Valid(%.8X)", context_ptr); + + XMAContextData context(SHIM_MEM_ADDR(context_ptr)); + + context.input_buffer_0_valid = 1; + + context.Store(SHIM_MEM_ADDR(context_ptr)); + + SHIM_SET_RETURN_32(0); +} + +SHIM_CALL XMASetInputBuffer1_shim(PPCContext* ppc_state, KernelState* state) { + uint32_t context_ptr = SHIM_GET_ARG_32(0); + uint32_t buffer_ptr = SHIM_GET_ARG_32(1); + uint32_t block_count = SHIM_GET_ARG_32(2); + + XELOGD("XMASetInputBuffer1(%.8X, %.8X, %d)", context_ptr, buffer_ptr, + block_count); + + XMAContextData context(SHIM_MEM_ADDR(context_ptr)); + + context.input_buffer_1_ptr = buffer_ptr; + context.input_buffer_1_block_count = block_count; + context.input_buffer_read_offset = 32; // in bits + context.input_buffer_1_valid = buffer_ptr ? 1 : 0; + + context.Store(SHIM_MEM_ADDR(context_ptr)); + + SHIM_SET_RETURN_32(0); +} + +SHIM_CALL XMAIsInputBuffer1Valid_shim(PPCContext* ppc_state, + KernelState* state) { + uint32_t context_ptr = SHIM_GET_ARG_32(0); + + XELOGD("XMAIsInputBuffer1Valid(%.8X)", context_ptr); + + XMAContextData context(SHIM_MEM_ADDR(context_ptr)); + + uint32_t result = context.input_buffer_1_valid; + + SHIM_SET_RETURN_32(result); +} + +SHIM_CALL XMASetInputBuffer1Valid_shim(PPCContext* ppc_state, + KernelState* state) { + uint32_t context_ptr = SHIM_GET_ARG_32(0); + + XELOGD("XMASetInputBuffer1Valid(%.8X)", context_ptr); + + XMAContextData context(SHIM_MEM_ADDR(context_ptr)); + + context.input_buffer_1_valid = 1; + + context.Store(SHIM_MEM_ADDR(context_ptr)); + + SHIM_SET_RETURN_32(0); +} + +SHIM_CALL XMAIsOutputBufferValid_shim(PPCContext* ppc_state, + KernelState* state) { + uint32_t context_ptr = SHIM_GET_ARG_32(0); + + XELOGD("XMAIsOutputBufferValid(%.8X)", context_ptr); + + XMAContextData context(SHIM_MEM_ADDR(context_ptr)); + + uint32_t result = context.output_buffer_valid; + + SHIM_SET_RETURN_32(result); +} + +SHIM_CALL XMASetOutputBufferValid_shim(PPCContext* ppc_state, + KernelState* state) { + uint32_t context_ptr = SHIM_GET_ARG_32(0); + + XELOGD("XMASetOutputBufferValid(%.8X)", context_ptr); + + XMAContextData context(SHIM_MEM_ADDR(context_ptr)); + + context.output_buffer_valid = 1; + + context.Store(SHIM_MEM_ADDR(context_ptr)); + + SHIM_SET_RETURN_32(0); +} + +SHIM_CALL XMAGetOutputBufferReadOffset_shim(PPCContext* ppc_state, + KernelState* state) { + uint32_t context_ptr = SHIM_GET_ARG_32(0); + + XELOGD("XMAGetOutputBufferReadOffset(%.8X)", context_ptr); + + XMAContextData context(SHIM_MEM_ADDR(context_ptr)); + + uint32_t result = context.output_buffer_read_offset; + + SHIM_SET_RETURN_32(result); +} + +SHIM_CALL XMASetOutputBufferReadOffset_shim(PPCContext* ppc_state, + KernelState* state) { + uint32_t context_ptr = SHIM_GET_ARG_32(0); + uint32_t value = SHIM_GET_ARG_32(1); + + XELOGD("XMASetOutputBufferReadOffset(%.8X, %.8X)", context_ptr, value); + + XMAContextData context(SHIM_MEM_ADDR(context_ptr)); + + context.output_buffer_read_offset = value; + + context.Store(SHIM_MEM_ADDR(context_ptr)); + + SHIM_SET_RETURN_32(0); +} + +SHIM_CALL XMAGetOutputBufferWriteOffset_shim(PPCContext* ppc_state, + KernelState* state) { + uint32_t context_ptr = SHIM_GET_ARG_32(0); + + XELOGD("XMAGetOutputBufferWriteOffset(%.8X)", context_ptr); + + XMAContextData context(SHIM_MEM_ADDR(context_ptr)); + + uint32_t result = context.output_buffer_write_offset; + + SHIM_SET_RETURN_32(result); +} + +SHIM_CALL XMAGetPacketMetadata_shim(PPCContext* ppc_state, KernelState* state) { + uint32_t context_ptr = SHIM_GET_ARG_32(0); + + XELOGD("XMAGetPacketMetadata(%.8X)", context_ptr); + + XMAContextData context(SHIM_MEM_ADDR(context_ptr)); + + uint32_t result = context.packet_metadata; + + SHIM_SET_RETURN_32(result); +} + +SHIM_CALL XMAEnableContext_shim(PPCContext* ppc_state, KernelState* state) { + uint32_t context_ptr = SHIM_GET_ARG_32(0); + + XELOGD("XMAEnableContext(%.8X)", context_ptr); + + StoreXmaContextIndexedRegister(state, 0x1940, context_ptr); + + SHIM_SET_RETURN_32(0); +} + +SHIM_CALL XMADisableContext_shim(PPCContext* ppc_state, KernelState* state) { + uint32_t context_ptr = SHIM_GET_ARG_32(0); + uint32_t wait = SHIM_GET_ARG_32(1); + + XELOGD("XMADisableContext(%.8X, %d)", context_ptr, wait); + + X_HRESULT result = X_E_SUCCESS; + StoreXmaContextIndexedRegister(state, 0x1A40, context_ptr); + XMAContextData context(SHIM_MEM_ADDR(context_ptr)); + + SHIM_SET_RETURN_32(result); +} + +SHIM_CALL XMABlockWhileInUse_shim(PPCContext* ppc_state, KernelState* state) { + uint32_t context_ptr = SHIM_GET_ARG_32(0); + + XELOGD("XMABlockWhileInUse(%.8X)", context_ptr); + + do { + XMAContextData context(SHIM_MEM_ADDR(context_ptr)); + if (!context.input_buffer_0_valid && !context.input_buffer_1_valid) { + break; + } + Sleep(1); + } while (true); + + SHIM_SET_RETURN_32(0); +} + } // namespace kernel } // namespace xe -void xe::kernel::xboxkrnl::RegisterAudioXmaExports(ExportResolver* export_resolver, - KernelState* state) { +void xe::kernel::xboxkrnl::RegisterAudioXmaExports( + ExportResolver* export_resolver, KernelState* state) { + // Used for both XMA* methods and direct register access. SHIM_SET_MAPPING("xboxkrnl.exe", XMACreateContext, state); SHIM_SET_MAPPING("xboxkrnl.exe", XMAReleaseContext, state); - //SHIM_SET_MAPPING("xboxkrnl.exe", XMAInitializeContext, state); - //SHIM_SET_MAPPING("xboxkrnl.exe", XMASetLoopData, state); - //SHIM_SET_MAPPING("xboxkrnl.exe", XMAGetInputBufferReadOffset, state); - //SHIM_SET_MAPPING("xboxkrnl.exe", XMASetInputBufferReadOffset, state); - //SHIM_SET_MAPPING("xboxkrnl.exe", XMASetInputBuffer0, state); - //SHIM_SET_MAPPING("xboxkrnl.exe", XMAIsInputBuffer0Valid, state); - //SHIM_SET_MAPPING("xboxkrnl.exe", XMASetInputBuffer0Valid, state); - //SHIM_SET_MAPPING("xboxkrnl.exe", XMASetInputBuffer1, state); - //SHIM_SET_MAPPING("xboxkrnl.exe", XMAIsInputBuffer1Valid, state); - //SHIM_SET_MAPPING("xboxkrnl.exe", XMASetInputBuffer1Valid, state); - //SHIM_SET_MAPPING("xboxkrnl.exe", XMAIsOutputBufferValid, state); - //SHIM_SET_MAPPING("xboxkrnl.exe", XMASetOutputBufferValid, state); - //SHIM_SET_MAPPING("xboxkrnl.exe", XMASetOutputBufferReadOffset, state); - //SHIM_SET_MAPPING("xboxkrnl.exe", XMAGetOutputBufferReadOffset, state); - //SHIM_SET_MAPPING("xboxkrnl.exe", XMAGetOutputBufferWriteOffset, state); - //SHIM_SET_MAPPING("xboxkrnl.exe", XMAGetPacketMetadata, state); - //SHIM_SET_MAPPING("xboxkrnl.exe", XMAEnableContext, state); - //SHIM_SET_MAPPING("xboxkrnl.exe", XMADisableContext, state); - //SHIM_SET_MAPPING("xboxkrnl.exe", XMABlockWhileInUse, state); + // Only used in older games. + SHIM_SET_MAPPING("xboxkrnl.exe", XMAInitializeContext, state); + SHIM_SET_MAPPING("xboxkrnl.exe", XMASetLoopData, state); + SHIM_SET_MAPPING("xboxkrnl.exe", XMAGetInputBufferReadOffset, state); + SHIM_SET_MAPPING("xboxkrnl.exe", XMASetInputBufferReadOffset, state); + SHIM_SET_MAPPING("xboxkrnl.exe", XMASetInputBuffer0, state); + SHIM_SET_MAPPING("xboxkrnl.exe", XMAIsInputBuffer0Valid, state); + SHIM_SET_MAPPING("xboxkrnl.exe", XMASetInputBuffer0Valid, state); + SHIM_SET_MAPPING("xboxkrnl.exe", XMASetInputBuffer1, state); + SHIM_SET_MAPPING("xboxkrnl.exe", XMAIsInputBuffer1Valid, state); + SHIM_SET_MAPPING("xboxkrnl.exe", XMASetInputBuffer1Valid, state); + SHIM_SET_MAPPING("xboxkrnl.exe", XMAIsOutputBufferValid, state); + SHIM_SET_MAPPING("xboxkrnl.exe", XMASetOutputBufferValid, state); + SHIM_SET_MAPPING("xboxkrnl.exe", XMASetOutputBufferReadOffset, state); + SHIM_SET_MAPPING("xboxkrnl.exe", XMAGetOutputBufferReadOffset, state); + SHIM_SET_MAPPING("xboxkrnl.exe", XMAGetOutputBufferWriteOffset, state); + SHIM_SET_MAPPING("xboxkrnl.exe", XMAGetPacketMetadata, state); + SHIM_SET_MAPPING("xboxkrnl.exe", XMAEnableContext, state); + SHIM_SET_MAPPING("xboxkrnl.exe", XMADisableContext, state); + SHIM_SET_MAPPING("xboxkrnl.exe", XMABlockWhileInUse, state); }