parent
1204f35f1e
commit
17bc561045
|
@ -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) {
|
int InstrEmit_vsro_(PPCHIRBuilder& f, uint32_t vd, uint32_t va, uint32_t vb) {
|
||||||
// (VD) <- (VA) >> (VB.b[F] & 0x78) (by octet)
|
// (VD) <- (VA) >> (VB.b[F] & 0x78) (by octet)
|
||||||
// TODO(benvanik): flag for shift-by-octet as optimization.
|
// TODO(benvanik): flag for shift-by-octet as optimization.
|
||||||
Value* sh =
|
Value* sh = f.And(f.Extract(f.LoadVR(vb), 15, INT8_TYPE),
|
||||||
f.And(f.Extract(f.LoadVR(vb), 15, INT8_TYPE), f.LoadConstant(0x78));
|
f.LoadConstant(uint8_t(0x78)));
|
||||||
Value* v = f.Permute(f.LoadVectorShr(sh), f.LoadVR(va),
|
Value* v = f.Permute(f.LoadVectorShr(sh), f.LoadVR(va),
|
||||||
f.LoadZero(VEC128_TYPE), INT8_TYPE);
|
f.LoadZero(VEC128_TYPE), INT8_TYPE);
|
||||||
f.StoreVR(vd, v);
|
f.StoreVR(vd, v);
|
||||||
|
|
|
@ -26,7 +26,8 @@ using alloy::runtime::FunctionInfo;
|
||||||
#define ASSERT_FLOAT_TYPE(value)
|
#define ASSERT_FLOAT_TYPE(value)
|
||||||
#define ASSERT_NON_VECTOR_TYPE(value)
|
#define ASSERT_NON_VECTOR_TYPE(value)
|
||||||
#define ASSERT_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() {
|
HIRBuilder::HIRBuilder() {
|
||||||
arena_ = new Arena();
|
arena_ = new Arena();
|
||||||
|
|
|
@ -272,8 +272,7 @@ uint64_t AudioSystem::ReadRegister(uint64_t addr) {
|
||||||
// To prevent games from seeing a stuck XMA context, return a rotating
|
// To prevent games from seeing a stuck XMA context, return a rotating
|
||||||
// number
|
// number
|
||||||
registers_.current_context = registers_.next_context;
|
registers_.current_context = registers_.next_context;
|
||||||
registers_.next_context =
|
registers_.next_context = (registers_.next_context + 1) % kXmaContextCount;
|
||||||
(registers_.next_context + 1) % kXmaContextCount;
|
|
||||||
value = registers_.current_context;
|
value = registers_.current_context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,18 +289,19 @@ void AudioSystem::WriteRegister(uint64_t addr, uint64_t value) {
|
||||||
assert_true(r % 4 == 0);
|
assert_true(r % 4 == 0);
|
||||||
register_file_[r / 4] = uint32_t(value);
|
register_file_[r / 4] = uint32_t(value);
|
||||||
|
|
||||||
if (r >= 0x1940 && r <= 0x1949) {
|
if (r >= 0x1940 && r <= 0x1940 + 9 * 4) {
|
||||||
// Context kick command.
|
// Context kick command.
|
||||||
// This will kick off the given hardware contexts.
|
// This will kick off the given hardware contexts.
|
||||||
for (int i = 0; value && i < 32; ++i) {
|
for (int i = 0; value && i < 32; ++i) {
|
||||||
if (value & 1) {
|
if (value & 1) {
|
||||||
uint32_t context_id = i + (r - 0x1940) * 32;
|
uint32_t context_id = i + (r - 0x1940) / 4 * 32;
|
||||||
XELOGD("AudioSystem: kicking context %d", context_id);
|
XELOGAPU("AudioSystem: kicking context %d", context_id);
|
||||||
// Games check bits 20/21 of context[0].
|
// Games check bits 20/21 of context[0].
|
||||||
// If both bits are set buffer full, otherwise room available.
|
// If both bits are set buffer full, otherwise room available.
|
||||||
// Right after a kick we always set buffers to invalid so games keep
|
// Right after a kick we always set buffers to invalid so games keep
|
||||||
// feeding data.
|
// 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);
|
auto context_ptr = memory()->Translate(guest_ptr);
|
||||||
uint32_t dword0 = poly::load_and_swap<uint32_t>(context_ptr + 0);
|
uint32_t dword0 = poly::load_and_swap<uint32_t>(context_ptr + 0);
|
||||||
bool has_valid_input = (dword0 & 0x00300000) != 0;
|
bool has_valid_input = (dword0 & 0x00300000) != 0;
|
||||||
|
@ -316,24 +316,24 @@ void AudioSystem::WriteRegister(uint64_t addr, uint64_t value) {
|
||||||
}
|
}
|
||||||
value >>= 1;
|
value >>= 1;
|
||||||
}
|
}
|
||||||
} else if (r >= 0x1A40 && r <= 0x1A49) {
|
} else if (r >= 0x1A40 && r <= 0x1A40 + 9 * 4) {
|
||||||
// Context lock command.
|
// Context lock command.
|
||||||
// This requests a lock by flagging the context.
|
// This requests a lock by flagging the context.
|
||||||
for (int i = 0; value && i < 32; ++i) {
|
for (int i = 0; value && i < 32; ++i) {
|
||||||
if (value & 1) {
|
if (value & 1) {
|
||||||
uint32_t context_id = i + (r - 0x1A40) * 32;
|
uint32_t context_id = i + (r - 0x1A40) / 4 * 32;
|
||||||
XELOGD("AudioSystem: set context lock %d", context_id);
|
XELOGAPU("AudioSystem: set context lock %d", context_id);
|
||||||
// TODO(benvanik): set lock?
|
// TODO(benvanik): set lock?
|
||||||
}
|
}
|
||||||
value >>= 1;
|
value >>= 1;
|
||||||
}
|
}
|
||||||
} else if (r >= 0x1A80 && r <= 0x1A89) {
|
} else if (r >= 0x1A80 && r <= 0x1A80 + 9 * 4) {
|
||||||
// Context clear command.
|
// Context clear command.
|
||||||
// This will reset the given hardware contexts.
|
// This will reset the given hardware contexts.
|
||||||
for (int i = 0; value && i < 32; ++i) {
|
for (int i = 0; value && i < 32; ++i) {
|
||||||
if (value & 1) {
|
if (value & 1) {
|
||||||
uint32_t context_id = i + (r - 0x1A80) * 32;
|
uint32_t context_id = i + (r - 0x1A80) / 4 * 32;
|
||||||
XELOGD("AudioSystem: reset context %d", context_id);
|
XELOGAPU("AudioSystem: reset context %d", context_id);
|
||||||
// TODO(benvanik): something?
|
// TODO(benvanik): something?
|
||||||
}
|
}
|
||||||
value >>= 1;
|
value >>= 1;
|
||||||
|
|
|
@ -35,6 +35,9 @@ class AudioSystem {
|
||||||
virtual X_STATUS Setup();
|
virtual X_STATUS Setup();
|
||||||
virtual void Shutdown();
|
virtual void Shutdown();
|
||||||
|
|
||||||
|
uint32_t xma_context_array_ptr() const {
|
||||||
|
return registers_.xma_context_array_ptr;
|
||||||
|
}
|
||||||
uint32_t AllocateXmaContext();
|
uint32_t AllocateXmaContext();
|
||||||
void ReleaseXmaContext(uint32_t guest_ptr);
|
void ReleaseXmaContext(uint32_t guest_ptr);
|
||||||
|
|
||||||
|
|
|
@ -50,64 +50,6 @@ namespace kernel {
|
||||||
// XAudio2 uses XMA under the covers, and seems to map with the same
|
// XAudio2 uses XMA under the covers, and seems to map with the same
|
||||||
// restrictions of frame/subframe/etc:
|
// restrictions of frame/subframe/etc:
|
||||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.xaudio2.xaudio2_buffer(v=vs.85).aspx
|
// 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) {
|
SHIM_CALL XMACreateContext_shim(PPCContext* ppc_state, KernelState* state) {
|
||||||
uint32_t context_out_ptr = SHIM_GET_ARG_32(0);
|
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);
|
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<uint32_t*>(this),
|
||||||
|
reinterpret_cast<const uint32_t*>(ptr),
|
||||||
|
sizeof(XMAContextData) / 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Store(void* ptr) {
|
||||||
|
poly::copy_and_swap_32_aligned(reinterpret_cast<uint32_t*>(ptr),
|
||||||
|
reinterpret_cast<const uint32_t*>(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<uint32_t>(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 kernel
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
void xe::kernel::xboxkrnl::RegisterAudioXmaExports(ExportResolver* export_resolver,
|
void xe::kernel::xboxkrnl::RegisterAudioXmaExports(
|
||||||
KernelState* state) {
|
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", XMACreateContext, state);
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", XMAReleaseContext, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", XMAReleaseContext, state);
|
||||||
|
|
||||||
//SHIM_SET_MAPPING("xboxkrnl.exe", XMAInitializeContext, state);
|
// Only used in older games.
|
||||||
//SHIM_SET_MAPPING("xboxkrnl.exe", XMASetLoopData, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", XMAInitializeContext, state);
|
||||||
//SHIM_SET_MAPPING("xboxkrnl.exe", XMAGetInputBufferReadOffset, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", XMASetLoopData, state);
|
||||||
//SHIM_SET_MAPPING("xboxkrnl.exe", XMASetInputBufferReadOffset, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", XMAGetInputBufferReadOffset, state);
|
||||||
//SHIM_SET_MAPPING("xboxkrnl.exe", XMASetInputBuffer0, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", XMASetInputBufferReadOffset, state);
|
||||||
//SHIM_SET_MAPPING("xboxkrnl.exe", XMAIsInputBuffer0Valid, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", XMASetInputBuffer0, state);
|
||||||
//SHIM_SET_MAPPING("xboxkrnl.exe", XMASetInputBuffer0Valid, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", XMAIsInputBuffer0Valid, state);
|
||||||
//SHIM_SET_MAPPING("xboxkrnl.exe", XMASetInputBuffer1, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", XMASetInputBuffer0Valid, state);
|
||||||
//SHIM_SET_MAPPING("xboxkrnl.exe", XMAIsInputBuffer1Valid, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", XMASetInputBuffer1, state);
|
||||||
//SHIM_SET_MAPPING("xboxkrnl.exe", XMASetInputBuffer1Valid, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", XMAIsInputBuffer1Valid, state);
|
||||||
//SHIM_SET_MAPPING("xboxkrnl.exe", XMAIsOutputBufferValid, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", XMASetInputBuffer1Valid, state);
|
||||||
//SHIM_SET_MAPPING("xboxkrnl.exe", XMASetOutputBufferValid, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", XMAIsOutputBufferValid, state);
|
||||||
//SHIM_SET_MAPPING("xboxkrnl.exe", XMASetOutputBufferReadOffset, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", XMASetOutputBufferValid, state);
|
||||||
//SHIM_SET_MAPPING("xboxkrnl.exe", XMAGetOutputBufferReadOffset, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", XMASetOutputBufferReadOffset, state);
|
||||||
//SHIM_SET_MAPPING("xboxkrnl.exe", XMAGetOutputBufferWriteOffset, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", XMAGetOutputBufferReadOffset, state);
|
||||||
//SHIM_SET_MAPPING("xboxkrnl.exe", XMAGetPacketMetadata, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", XMAGetOutputBufferWriteOffset, state);
|
||||||
//SHIM_SET_MAPPING("xboxkrnl.exe", XMAEnableContext, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", XMAGetPacketMetadata, state);
|
||||||
//SHIM_SET_MAPPING("xboxkrnl.exe", XMADisableContext, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", XMAEnableContext, state);
|
||||||
//SHIM_SET_MAPPING("xboxkrnl.exe", XMABlockWhileInUse, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", XMADisableContext, state);
|
||||||
|
SHIM_SET_MAPPING("xboxkrnl.exe", XMABlockWhileInUse, state);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue