Merge pull request #334 from DrChat/xma_fixes

XMA Fixes
This commit is contained in:
Ben Vanik 2015-07-10 21:53:43 -07:00
commit 601310c8bb
2 changed files with 104 additions and 204 deletions

View File

@ -132,10 +132,6 @@ void XmaContext::Enable() {
(data.input_buffer_0_packet_count + data.input_buffer_1_packet_count) *
kBytesPerPacket);
// Reset valid flags so our audio decoder knows to process this one.
data.input_buffer_0_valid = data.input_buffer_0_ptr != 0;
data.input_buffer_1_valid = data.input_buffer_1_ptr != 0;
data.Store(context_ptr);
set_is_enabled(true);
@ -227,6 +223,11 @@ void XmaContext::DecodePackets(XMA_CONTEXT_DATA& data) {
// SPUs also support stereo decoding. (data.is_stereo)
// Quick die if there's no data.
if (!data.input_buffer_0_valid && !data.input_buffer_1_valid) {
return;
}
// Check the output buffer - we cannot decode anything else if it's
// unavailable.
if (!data.output_buffer_valid) {
@ -329,8 +330,10 @@ int XmaContext::StartPacket(XMA_CONTEXT_DATA& data) {
// See if we've finished with the input.
// Block count is in packets, so expand by packet size.
uint32_t input_size_0_bytes = (data.input_buffer_0_packet_count) * 2048;
uint32_t input_size_1_bytes = (data.input_buffer_1_packet_count) * 2048;
uint32_t input_size_0_bytes =
data.input_buffer_0_valid ? (data.input_buffer_0_packet_count) * 2048 : 0;
uint32_t input_size_1_bytes =
data.input_buffer_1_valid ? (data.input_buffer_1_packet_count) * 2048 : 0;
// Total input size
uint32_t input_size_bytes = input_size_0_bytes + input_size_1_bytes;
@ -346,7 +349,7 @@ int XmaContext::StartPacket(XMA_CONTEXT_DATA& data) {
uint32_t input_offset_bytes = seq_offset_bytes;
auto input_buffer = in0;
if (seq_offset_bytes >= input_size_0_bytes) {
if (seq_offset_bytes >= input_size_0_bytes && input_size_1_bytes) {
// Size overlap, select input buffer 1.
// TODO: This needs testing.
input_offset_bytes -= input_size_0_bytes;

View File

@ -120,17 +120,11 @@ struct XMA_CONTEXT_INIT {
};
static_assert_size(XMA_CONTEXT_INIT, 56);
SHIM_CALL XMAInitializeContext_shim(PPCContext* ppc_context,
KernelState* kernel_state) {
uint32_t context_ptr = SHIM_GET_ARG_32(0);
uint32_t context_init_ptr = SHIM_GET_ARG_32(1);
dword_result_t XMAInitializeContext(lpvoid_t context_ptr,
pointer_t<XMA_CONTEXT_INIT> context_init) {
std::memset(context_ptr, 0, sizeof(XMA_CONTEXT_DATA));
XELOGD("XMAInitializeContext(%.8X, %.8X)", context_ptr, context_init_ptr);
std::memset(SHIM_MEM_ADDR(context_ptr), 0, sizeof(XMA_CONTEXT_DATA));
XMA_CONTEXT_DATA context(SHIM_MEM_ADDR(context_ptr));
auto context_init = (XMA_CONTEXT_INIT*)SHIM_MEM_ADDR(context_init_ptr);
XMA_CONTEXT_DATA context(context_ptr);
context.input_buffer_0_ptr = context_init->input_buffer_0_ptr;
context.input_buffer_0_packet_count =
@ -153,12 +147,14 @@ SHIM_CALL XMAInitializeContext_shim(PPCContext* ppc_context,
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));
context.Store(context_ptr);
StoreXmaContextIndexedRegister(kernel_state, 0x1A80, context_ptr);
StoreXmaContextIndexedRegister(kernel_state(), 0x1A80, context_ptr);
SHIM_SET_RETURN_32(0);
return 0;
}
DECLARE_XBOXKRNL_EXPORT(XMAInitializeContext,
ExportTag::kImplemented | ExportTag::kAudio);
SHIM_CALL XMASetLoopData_shim(PPCContext* ppc_context,
KernelState* kernel_state) {
@ -181,215 +177,134 @@ SHIM_CALL XMASetLoopData_shim(PPCContext* ppc_context,
SHIM_SET_RETURN_32(0);
}
SHIM_CALL XMAGetInputBufferReadOffset_shim(PPCContext* ppc_context,
KernelState* kernel_state) {
uint32_t context_ptr = SHIM_GET_ARG_32(0);
XELOGD("XMAGetInputBufferReadOffset(%.8X)", context_ptr);
XMA_CONTEXT_DATA context(SHIM_MEM_ADDR(context_ptr));
uint32_t result = context.input_buffer_read_offset;
SHIM_SET_RETURN_32(result);
dword_result_t XMAGetInputBufferReadOffset(lpvoid_t context_ptr) {
XMA_CONTEXT_DATA context(context_ptr);
return context.input_buffer_read_offset;
}
DECLARE_XBOXKRNL_EXPORT(XMAGetInputBufferReadOffset,
ExportTag::kImplemented | ExportTag::kAudio);
SHIM_CALL XMASetInputBufferReadOffset_shim(PPCContext* ppc_context,
KernelState* kernel_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);
XMA_CONTEXT_DATA context(SHIM_MEM_ADDR(context_ptr));
dword_result_t XMASetInputBufferReadOffset(lpvoid_t context_ptr,
dword_t value) {
XMA_CONTEXT_DATA context(context_ptr);
context.input_buffer_read_offset = value;
context.Store(context_ptr);
context.Store(SHIM_MEM_ADDR(context_ptr));
SHIM_SET_RETURN_32(0);
return 0;
}
DECLARE_XBOXKRNL_EXPORT(XMASetInputBufferReadOffset,
ExportTag::kImplemented | ExportTag::kAudio);
SHIM_CALL XMASetInputBuffer0_shim(PPCContext* ppc_context,
KernelState* kernel_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);
dword_result_t XMASetInputBuffer0(lpvoid_t context_ptr, lpvoid_t buffer,
dword_t packet_count) {
XMA_CONTEXT_DATA context(context_ptr);
XELOGD("XMASetInputBuffer0(%.8X, %.8X, %d)", context_ptr, buffer_ptr,
block_count);
context.input_buffer_0_ptr = buffer.guest_address();
context.input_buffer_0_packet_count = packet_count;
XMA_CONTEXT_DATA context(SHIM_MEM_ADDR(context_ptr));
context.Store(context_ptr);
context.input_buffer_0_ptr = buffer_ptr;
context.input_buffer_0_packet_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);
return 0;
}
DECLARE_XBOXKRNL_EXPORT(XMASetInputBuffer0,
ExportTag::kImplemented | ExportTag::kAudio);
SHIM_CALL XMAIsInputBuffer0Valid_shim(PPCContext* ppc_context,
KernelState* kernel_state) {
uint32_t context_ptr = SHIM_GET_ARG_32(0);
XELOGD("XMAIsInputBuffer0Valid(%.8X)", context_ptr);
XMA_CONTEXT_DATA context(SHIM_MEM_ADDR(context_ptr));
uint32_t result = context.input_buffer_0_valid;
SHIM_SET_RETURN_32(result);
dword_result_t XMAIsInputBuffer0Valid(lpvoid_t context_ptr) {
XMA_CONTEXT_DATA context(context_ptr);
return context.input_buffer_0_valid;
}
DECLARE_XBOXKRNL_EXPORT(XMAIsInputBuffer0Valid,
ExportTag::kImplemented | ExportTag::kAudio);
SHIM_CALL XMASetInputBuffer0Valid_shim(PPCContext* ppc_context,
KernelState* kernel_state) {
uint32_t context_ptr = SHIM_GET_ARG_32(0);
XELOGD("XMASetInputBuffer0Valid(%.8X)", context_ptr);
XMA_CONTEXT_DATA context(SHIM_MEM_ADDR(context_ptr));
dword_result_t XMASetInputBuffer0Valid(lpvoid_t context_ptr) {
XMA_CONTEXT_DATA context(context_ptr);
context.input_buffer_0_valid = 1;
context.Store(context_ptr);
context.Store(SHIM_MEM_ADDR(context_ptr));
SHIM_SET_RETURN_32(0);
return 0;
}
DECLARE_XBOXKRNL_EXPORT(XMASetInputBuffer0Valid,
ExportTag::kImplemented | ExportTag::kAudio);
SHIM_CALL XMASetInputBuffer1_shim(PPCContext* ppc_context,
KernelState* kernel_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);
dword_result_t XMASetInputBuffer1(lpvoid_t context_ptr, lpvoid_t buffer,
dword_t packet_count) {
XMA_CONTEXT_DATA context(context_ptr);
XELOGD("XMASetInputBuffer1(%.8X, %.8X, %d)", context_ptr, buffer_ptr,
block_count);
context.input_buffer_1_ptr = buffer.guest_address();
context.input_buffer_1_packet_count = packet_count;
XMA_CONTEXT_DATA context(SHIM_MEM_ADDR(context_ptr));
context.Store(context_ptr);
context.input_buffer_1_ptr = buffer_ptr;
context.input_buffer_1_packet_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);
return 0;
}
DECLARE_XBOXKRNL_EXPORT(XMASetInputBuffer1,
ExportTag::kImplemented | ExportTag::kAudio);
SHIM_CALL XMAIsInputBuffer1Valid_shim(PPCContext* ppc_context,
KernelState* kernel_state) {
uint32_t context_ptr = SHIM_GET_ARG_32(0);
XELOGD("XMAIsInputBuffer1Valid(%.8X)", context_ptr);
XMA_CONTEXT_DATA context(SHIM_MEM_ADDR(context_ptr));
uint32_t result = context.input_buffer_1_valid;
SHIM_SET_RETURN_32(result);
dword_result_t XMAIsInputBuffer1Valid(lpvoid_t context_ptr) {
XMA_CONTEXT_DATA context(context_ptr);
return context.input_buffer_1_valid;
}
DECLARE_XBOXKRNL_EXPORT(XMAIsInputBuffer1Valid,
ExportTag::kImplemented | ExportTag::kAudio);
SHIM_CALL XMASetInputBuffer1Valid_shim(PPCContext* ppc_context,
KernelState* kernel_state) {
uint32_t context_ptr = SHIM_GET_ARG_32(0);
XELOGD("XMASetInputBuffer1Valid(%.8X)", context_ptr);
XMA_CONTEXT_DATA context(SHIM_MEM_ADDR(context_ptr));
dword_result_t XMASetInputBuffer1Valid(lpvoid_t context_ptr) {
XMA_CONTEXT_DATA context(context_ptr);
context.input_buffer_1_valid = 1;
context.Store(context_ptr);
context.Store(SHIM_MEM_ADDR(context_ptr));
SHIM_SET_RETURN_32(0);
return 0;
}
DECLARE_XBOXKRNL_EXPORT(XMASetInputBuffer1Valid,
ExportTag::kImplemented | ExportTag::kAudio);
SHIM_CALL XMAIsOutputBufferValid_shim(PPCContext* ppc_context,
KernelState* kernel_state) {
uint32_t context_ptr = SHIM_GET_ARG_32(0);
XELOGD("XMAIsOutputBufferValid(%.8X)", context_ptr);
XMA_CONTEXT_DATA context(SHIM_MEM_ADDR(context_ptr));
uint32_t result = context.output_buffer_valid;
SHIM_SET_RETURN_32(result);
dword_result_t XMAIsOutputBufferValid(lpvoid_t context_ptr) {
XMA_CONTEXT_DATA context(context_ptr);
return context.output_buffer_valid;
}
DECLARE_XBOXKRNL_EXPORT(XMAIsOutputBufferValid,
ExportTag::kImplemented | ExportTag::kAudio);
SHIM_CALL XMASetOutputBufferValid_shim(PPCContext* ppc_context,
KernelState* kernel_state) {
uint32_t context_ptr = SHIM_GET_ARG_32(0);
XELOGD("XMASetOutputBufferValid(%.8X)", context_ptr);
XMA_CONTEXT_DATA context(SHIM_MEM_ADDR(context_ptr));
dword_result_t XMASetOutputBufferValid(lpvoid_t context_ptr) {
XMA_CONTEXT_DATA context(context_ptr);
context.output_buffer_valid = 1;
context.Store(context_ptr);
context.Store(SHIM_MEM_ADDR(context_ptr));
SHIM_SET_RETURN_32(0);
return 0;
}
DECLARE_XBOXKRNL_EXPORT(XMASetOutputBufferValid,
ExportTag::kImplemented | ExportTag::kAudio);
SHIM_CALL XMAGetOutputBufferReadOffset_shim(PPCContext* ppc_context,
KernelState* kernel_state) {
uint32_t context_ptr = SHIM_GET_ARG_32(0);
XELOGD("XMAGetOutputBufferReadOffset(%.8X)", context_ptr);
XMA_CONTEXT_DATA context(SHIM_MEM_ADDR(context_ptr));
uint32_t result = context.output_buffer_read_offset;
SHIM_SET_RETURN_32(result);
dword_result_t XMAGetOutputBufferReadOffset(lpvoid_t context_ptr) {
XMA_CONTEXT_DATA context(context_ptr);
return context.output_buffer_read_offset;
}
DECLARE_XBOXKRNL_EXPORT(XMAGetOutputBufferReadOffset,
ExportTag::kImplemented | ExportTag::kAudio);
SHIM_CALL XMASetOutputBufferReadOffset_shim(PPCContext* ppc_context,
KernelState* kernel_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);
XMA_CONTEXT_DATA context(SHIM_MEM_ADDR(context_ptr));
dword_result_t XMASetOutputBufferReadOffset(lpvoid_t context_ptr,
dword_t value) {
XMA_CONTEXT_DATA context(context_ptr);
context.output_buffer_read_offset = value;
context.Store(context_ptr);
context.Store(SHIM_MEM_ADDR(context_ptr));
SHIM_SET_RETURN_32(0);
return 0;
}
DECLARE_XBOXKRNL_EXPORT(XMASetOutputBufferReadOffset,
ExportTag::kImplemented | ExportTag::kAudio);
SHIM_CALL XMAGetOutputBufferWriteOffset_shim(PPCContext* ppc_context,
KernelState* kernel_state) {
uint32_t context_ptr = SHIM_GET_ARG_32(0);
XELOGD("XMAGetOutputBufferWriteOffset(%.8X)", context_ptr);
XMA_CONTEXT_DATA context(SHIM_MEM_ADDR(context_ptr));
uint32_t result = context.output_buffer_write_offset;
SHIM_SET_RETURN_32(result);
dword_result_t XMAGetOutputBufferWriteOffset(lpvoid_t context_ptr) {
XMA_CONTEXT_DATA context(context_ptr);
return context.output_buffer_write_offset;
}
DECLARE_XBOXKRNL_EXPORT(XMAGetOutputBufferWriteOffset,
ExportTag::kImplemented | ExportTag::kAudio);
SHIM_CALL XMAGetPacketMetadata_shim(PPCContext* ppc_context,
KernelState* kernel_state) {
uint32_t context_ptr = SHIM_GET_ARG_32(0);
XELOGD("XMAGetPacketMetadata(%.8X)", context_ptr);
XMA_CONTEXT_DATA context(SHIM_MEM_ADDR(context_ptr));
uint32_t result = context.packet_metadata;
SHIM_SET_RETURN_32(result);
dword_result_t XMAGetPacketMetadata(lpvoid_t context_ptr) {
XMA_CONTEXT_DATA context(context_ptr);
return context.packet_metadata;
}
DECLARE_XBOXKRNL_EXPORT(XMAGetPacketMetadata,
ExportTag::kImplemented | ExportTag::kAudio);
SHIM_CALL XMAEnableContext_shim(PPCContext* ppc_context,
KernelState* kernel_state) {
@ -446,26 +361,8 @@ void xe::kernel::xboxkrnl::RegisterAudioXmaExports(
SHIM_SET_MAPPING("xboxkrnl.exe", XMAReleaseContext, 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);