mirror of
https://github.com/xenia-project/xenia.git
synced 2025-12-06 07:12:03 +01:00
[APU] XMA register table cleanup, documentation.
- [APU] Clean up XMA register table. - [APU] Document observed register ranges in the XMA register table.
This commit is contained in:
parent
ead4818e25
commit
8daef93207
|
|
@ -123,7 +123,7 @@ X_STATUS XmaDecoder::Setup(kernel::KernelState* kernel_state) {
|
||||||
sizeof(XMA_CONTEXT_DATA) * kContextCount, 256, kSystemHeapPhysical);
|
sizeof(XMA_CONTEXT_DATA) * kContextCount, 256, kSystemHeapPhysical);
|
||||||
context_data_last_ptr_ =
|
context_data_last_ptr_ =
|
||||||
context_data_first_ptr_ + (sizeof(XMA_CONTEXT_DATA) * kContextCount - 1);
|
context_data_first_ptr_ + (sizeof(XMA_CONTEXT_DATA) * kContextCount - 1);
|
||||||
register_file_[XE_XMA_REG_CONTEXT_ARRAY_ADDRESS].u32 =
|
register_file_[XmaRegister::ContextArrayAddress] =
|
||||||
memory()->GetPhysicalAddress(context_data_first_ptr_);
|
memory()->GetPhysicalAddress(context_data_first_ptr_);
|
||||||
|
|
||||||
// Setup XMA contexts.
|
// Setup XMA contexts.
|
||||||
|
|
@ -134,7 +134,7 @@ X_STATUS XmaDecoder::Setup(kernel::KernelState* kernel_state) {
|
||||||
assert_always();
|
assert_always();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
register_file_[XE_XMA_REG_NEXT_CONTEXT_INDEX].u32 = 1;
|
register_file_[XmaRegister::NextContextIndex] = 1;
|
||||||
context_bitmap_.Resize(kContextCount);
|
context_bitmap_.Resize(kContextCount);
|
||||||
|
|
||||||
worker_running_ = true;
|
worker_running_ = true;
|
||||||
|
|
@ -254,27 +254,29 @@ bool XmaDecoder::BlockOnContext(uint32_t guest_ptr, bool poll) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t XmaDecoder::ReadRegister(uint32_t addr) {
|
uint32_t XmaDecoder::ReadRegister(uint32_t addr) {
|
||||||
uint32_t r = (addr & 0xFFFF) / 4;
|
auto r = (addr & 0xFFFF) / 4;
|
||||||
|
|
||||||
assert_true(r < XmaRegisterFile::kRegisterCount);
|
assert_true(r < XmaRegisterFile::kRegisterCount);
|
||||||
|
|
||||||
switch (r) {
|
switch (r) {
|
||||||
case XE_XMA_REG_CURRENT_CONTEXT_INDEX: {
|
case XmaRegister::ContextArrayAddress:
|
||||||
|
break;
|
||||||
|
case XmaRegister::CurrentContextIndex: {
|
||||||
// 0606h (1818h) is rotating context processing # set to hardware ID of
|
// 0606h (1818h) is rotating context processing # set to hardware ID of
|
||||||
// context being processed.
|
// context being processed.
|
||||||
// If bit 200h is set, the locking code will possibly collide on hardware
|
// If bit 200h is set, the locking code will possibly collide on hardware
|
||||||
// IDs and error out, so we should never set it (I think?).
|
// IDs and error out, so we should never set it (I think?).
|
||||||
uint32_t& current_context_index =
|
uint32_t& current_context_index =
|
||||||
register_file_[XE_XMA_REG_CURRENT_CONTEXT_INDEX].u32;
|
register_file_[XmaRegister::CurrentContextIndex];
|
||||||
uint32_t& next_context_index =
|
uint32_t& next_context_index =
|
||||||
register_file_[XE_XMA_REG_NEXT_CONTEXT_INDEX].u32;
|
register_file_[XmaRegister::NextContextIndex];
|
||||||
// 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.
|
||||||
current_context_index = next_context_index;
|
current_context_index = next_context_index;
|
||||||
next_context_index = (next_context_index + 1) % kContextCount;
|
next_context_index = (next_context_index + 1) % kContextCount;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default:
|
||||||
const auto register_info = register_file_.GetRegisterInfo(r);
|
const auto register_info = register_file_.GetRegisterInfo(r);
|
||||||
if (register_info) {
|
if (register_info) {
|
||||||
XELOGW("XMA: Read from unhandled register ({:04X}, {})", r,
|
XELOGW("XMA: Read from unhandled register ({:04X}, {})", r,
|
||||||
|
|
@ -283,10 +285,9 @@ uint32_t XmaDecoder::ReadRegister(uint32_t addr) {
|
||||||
XELOGW("XMA: Read from unknown register ({:04X})", r);
|
XELOGW("XMA: Read from unknown register ({:04X})", r);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return xe::byte_swap(register_file_.values[r].u32);
|
return xe::byte_swap(register_file_[r]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void XmaDecoder::WriteRegister(uint32_t addr, uint32_t value) {
|
void XmaDecoder::WriteRegister(uint32_t addr, uint32_t value) {
|
||||||
|
|
@ -296,16 +297,16 @@ void XmaDecoder::WriteRegister(uint32_t addr, uint32_t value) {
|
||||||
value = xe::byte_swap(value);
|
value = xe::byte_swap(value);
|
||||||
|
|
||||||
assert_true(r < XmaRegisterFile::kRegisterCount);
|
assert_true(r < XmaRegisterFile::kRegisterCount);
|
||||||
register_file_.values[r].u32 = value;
|
register_file_[r] = value;
|
||||||
|
|
||||||
if (r >= XE_XMA_REG_CONTEXT_KICK_0 && r <= XE_XMA_REG_CONTEXT_KICK_9) {
|
if (r >= XmaRegister::Context0Kick && r <= XmaRegister::Context9Kick) {
|
||||||
// Context kick command.
|
// Context kick command.
|
||||||
// This will kick off the given hardware contexts.
|
// This will kick off the given hardware contexts.
|
||||||
// Basically, this kicks the SPU and says "hey, decode that audio!"
|
// Basically, this kicks the SPU and says "hey, decode that audio!"
|
||||||
// XMAEnableContext
|
// XMAEnableContext
|
||||||
|
|
||||||
// The context ID is a bit in the range of the entire context array.
|
// The context ID is a bit in the range of the entire context array.
|
||||||
uint32_t base_context_id = (r - XE_XMA_REG_CONTEXT_KICK_0) * 32;
|
uint32_t base_context_id = (r - XmaRegister::Context0Kick) * 32;
|
||||||
for (int i = 0; value && i < 32; ++i, value >>= 1) {
|
for (int i = 0; value && i < 32; ++i, value >>= 1) {
|
||||||
if (value & 1) {
|
if (value & 1) {
|
||||||
uint32_t context_id = base_context_id + i;
|
uint32_t context_id = base_context_id + i;
|
||||||
|
|
@ -315,11 +316,11 @@ void XmaDecoder::WriteRegister(uint32_t addr, uint32_t value) {
|
||||||
}
|
}
|
||||||
// Signal the decoder thread to start processing.
|
// Signal the decoder thread to start processing.
|
||||||
work_event_->Set();
|
work_event_->Set();
|
||||||
} else if (r >= XE_XMA_REG_CONTEXT_LOCK_0 && r <= XE_XMA_REG_CONTEXT_LOCK_9) {
|
} else if (r >= XmaRegister::Context0Lock && r <= XmaRegister::Context9Lock) {
|
||||||
// Context lock command.
|
// Context lock command.
|
||||||
// This requests a lock by flagging the context.
|
// This requests a lock by flagging the context.
|
||||||
// XMADisableContext
|
// XMADisableContext
|
||||||
uint32_t base_context_id = (r - XE_XMA_REG_CONTEXT_LOCK_0) * 32;
|
uint32_t base_context_id = (r - XmaRegister::Context0Lock) * 32;
|
||||||
for (int i = 0; value && i < 32; ++i, value >>= 1) {
|
for (int i = 0; value && i < 32; ++i, value >>= 1) {
|
||||||
if (value & 1) {
|
if (value & 1) {
|
||||||
uint32_t context_id = base_context_id + i;
|
uint32_t context_id = base_context_id + i;
|
||||||
|
|
@ -328,12 +329,12 @@ void XmaDecoder::WriteRegister(uint32_t addr, uint32_t value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Signal the decoder thread to start processing.
|
// Signal the decoder thread to start processing.
|
||||||
work_event_->Set();
|
// work_event_->Set();
|
||||||
} else if (r >= XE_XMA_REG_CONTEXT_CLEAR_0 &&
|
} else if (r >= XmaRegister::Context0Clear &&
|
||||||
r <= XE_XMA_REG_CONTEXT_CLEAR_9) {
|
r <= XmaRegister::Context9Clear) {
|
||||||
// Context clear command.
|
// Context clear command.
|
||||||
// This will reset the given hardware contexts.
|
// This will reset the given hardware contexts.
|
||||||
uint32_t base_context_id = (r - XE_XMA_REG_CONTEXT_CLEAR_0) * 32;
|
uint32_t base_context_id = (r - XmaRegister::Context0Clear) * 32;
|
||||||
for (int i = 0; value && i < 32; ++i, value >>= 1) {
|
for (int i = 0; value && i < 32; ++i, value >>= 1) {
|
||||||
if (value & 1) {
|
if (value & 1) {
|
||||||
uint32_t context_id = base_context_id + i;
|
uint32_t context_id = base_context_id + i;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
* Copyright 2021 Ben Vanik. All rights reserved. *
|
||||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
@ -37,7 +37,7 @@ class XmaDecoder {
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
uint32_t context_array_ptr() const {
|
uint32_t context_array_ptr() const {
|
||||||
return register_file_.values[XE_XMA_REG_CONTEXT_ARRAY_ADDRESS].u32;
|
return register_file_[XmaRegister::ContextArrayAddress];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t AllocateContext();
|
uint32_t AllocateContext();
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
* Copyright 2021 Ben Vanik. All rights reserved. *
|
||||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
@ -20,10 +20,9 @@ XmaRegisterFile::XmaRegisterFile() { std::memset(values, 0, sizeof(values)); }
|
||||||
|
|
||||||
const XmaRegisterInfo* XmaRegisterFile::GetRegisterInfo(uint32_t index) {
|
const XmaRegisterInfo* XmaRegisterFile::GetRegisterInfo(uint32_t index) {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
#define XE_XMA_REGISTER(index, type, name) \
|
#define XE_XMA_REGISTER(index, name) \
|
||||||
case index: { \
|
case index: { \
|
||||||
static const XmaRegisterInfo reg_info = { \
|
static const XmaRegisterInfo reg_info = { \
|
||||||
XmaRegisterInfo::Type::type, \
|
|
||||||
#name, \
|
#name, \
|
||||||
}; \
|
}; \
|
||||||
return ®_info; \
|
return ®_info; \
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
* Copyright 2021 Ben Vanik. All rights reserved. *
|
||||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
@ -16,18 +16,13 @@
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace apu {
|
namespace apu {
|
||||||
|
|
||||||
enum XmaRegister {
|
struct XmaRegister {
|
||||||
#define XE_XMA_REGISTER(index, type, name) XE_XMA_REG_##name = index,
|
#define XE_XMA_REGISTER(index, name) static const uint32_t name = index;
|
||||||
#include "xenia/apu/xma_register_table.inc"
|
#include "xenia/apu/xma_register_table.inc"
|
||||||
#undef XE_XMA_REGISTER
|
#undef XE_XMA_REGISTER
|
||||||
};
|
};
|
||||||
|
|
||||||
struct XmaRegisterInfo {
|
struct XmaRegisterInfo {
|
||||||
enum class Type {
|
|
||||||
kDword,
|
|
||||||
kFloat,
|
|
||||||
};
|
|
||||||
Type type;
|
|
||||||
const char* name;
|
const char* name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -38,14 +33,10 @@ class XmaRegisterFile {
|
||||||
static const XmaRegisterInfo* GetRegisterInfo(uint32_t index);
|
static const XmaRegisterInfo* GetRegisterInfo(uint32_t index);
|
||||||
|
|
||||||
static const size_t kRegisterCount = (0xFFFF + 1) / 4;
|
static const size_t kRegisterCount = (0xFFFF + 1) / 4;
|
||||||
union RegisterValue {
|
uint32_t values[kRegisterCount];
|
||||||
uint32_t u32;
|
|
||||||
float f32;
|
|
||||||
};
|
|
||||||
RegisterValue values[kRegisterCount];
|
|
||||||
|
|
||||||
RegisterValue& operator[](int reg) { return values[reg]; }
|
uint32_t operator[](uint32_t reg) const { return values[reg]; }
|
||||||
RegisterValue& operator[](XmaRegister reg) { return values[reg]; }
|
uint32_t& operator[](uint32_t reg) { return values[reg]; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace apu
|
} // namespace apu
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
* Copyright 2021 Ben Vanik. All rights reserved. *
|
||||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
@ -10,42 +10,72 @@
|
||||||
// This is a partial file designed to be included by other files when
|
// This is a partial file designed to be included by other files when
|
||||||
// constructing various tables.
|
// constructing various tables.
|
||||||
|
|
||||||
//#define XE_XMA_REGISTER(index, type, name)
|
#ifndef XE_XMA_REGISTER
|
||||||
|
#define XE_XMA_REGISTER(index, name)
|
||||||
|
#define __XE_XMA_REGISTER_UNSET
|
||||||
|
#endif
|
||||||
|
|
||||||
XE_XMA_REGISTER(0x0600, kDword, CONTEXT_ARRAY_ADDRESS)
|
#ifndef XE_XMA_REGISTER_CONTEXT_GROUP
|
||||||
|
#define XE_XMA_REGISTER_CONTEXT_GROUP(index, suffix) \
|
||||||
|
XE_XMA_REGISTER(index + 0, Context0##suffix) \
|
||||||
|
XE_XMA_REGISTER(index + 1, Context1##suffix) \
|
||||||
|
XE_XMA_REGISTER(index + 2, Context2##suffix) \
|
||||||
|
XE_XMA_REGISTER(index + 3, Context3##suffix) \
|
||||||
|
XE_XMA_REGISTER(index + 4, Context4##suffix) \
|
||||||
|
XE_XMA_REGISTER(index + 5, Context5##suffix) \
|
||||||
|
XE_XMA_REGISTER(index + 6, Context6##suffix) \
|
||||||
|
XE_XMA_REGISTER(index + 7, Context7##suffix) \
|
||||||
|
XE_XMA_REGISTER(index + 8, Context8##suffix) \
|
||||||
|
XE_XMA_REGISTER(index + 9, Context9##suffix)
|
||||||
|
#endif
|
||||||
|
|
||||||
XE_XMA_REGISTER(0x0606, kDword, CURRENT_CONTEXT_INDEX)
|
// 0x0000..0x001F : ???
|
||||||
XE_XMA_REGISTER(0x0607, kDword, NEXT_CONTEXT_INDEX)
|
// 0x0020..0x03FF : all 0xFFs?
|
||||||
|
// 0x0400..0x043F : ???
|
||||||
|
// 0x0440..0x047F : all 0xFFs?
|
||||||
|
// 0x0480..0x048B : ???
|
||||||
|
// 0x048C..0x04C0 : all 0xFFs?
|
||||||
|
// 0x04C1..0x04CB : ???
|
||||||
|
// 0x04CC..0x04FF : all 0xFFs?
|
||||||
|
// 0x0500..0x051F : ???
|
||||||
|
// 0x0520..0x057F : all 0xFFs?
|
||||||
|
// 0x0580..0x058F : ???
|
||||||
|
// 0x0590..0x05FF : all 0xFFs?
|
||||||
|
|
||||||
XE_XMA_REGISTER(0x0650, kDword, CONTEXT_KICK_0)
|
// XMA stuff is probably only 0x0600..0x06FF
|
||||||
XE_XMA_REGISTER(0x0651, kDword, CONTEXT_KICK_1)
|
//---------------------------------------------------------------------------//
|
||||||
XE_XMA_REGISTER(0x0652, kDword, CONTEXT_KICK_2)
|
|
||||||
XE_XMA_REGISTER(0x0653, kDword, CONTEXT_KICK_3)
|
|
||||||
XE_XMA_REGISTER(0x0654, kDword, CONTEXT_KICK_4)
|
|
||||||
XE_XMA_REGISTER(0x0655, kDword, CONTEXT_KICK_5)
|
|
||||||
XE_XMA_REGISTER(0x0656, kDword, CONTEXT_KICK_6)
|
|
||||||
XE_XMA_REGISTER(0x0657, kDword, CONTEXT_KICK_7)
|
|
||||||
XE_XMA_REGISTER(0x0658, kDword, CONTEXT_KICK_8)
|
|
||||||
XE_XMA_REGISTER(0x0659, kDword, CONTEXT_KICK_9)
|
|
||||||
|
|
||||||
XE_XMA_REGISTER(0x0690, kDword, CONTEXT_LOCK_0)
|
XE_XMA_REGISTER(0x0600, ContextArrayAddress)
|
||||||
XE_XMA_REGISTER(0x0691, kDword, CONTEXT_LOCK_1)
|
// 0x0601..0x0605 : ???
|
||||||
XE_XMA_REGISTER(0x0692, kDword, CONTEXT_LOCK_2)
|
XE_XMA_REGISTER(0x0606, CurrentContextIndex)
|
||||||
XE_XMA_REGISTER(0x0693, kDword, CONTEXT_LOCK_3)
|
XE_XMA_REGISTER(0x0607, NextContextIndex)
|
||||||
XE_XMA_REGISTER(0x0694, kDword, CONTEXT_LOCK_4)
|
// 0x0608 : ???
|
||||||
XE_XMA_REGISTER(0x0695, kDword, CONTEXT_LOCK_5)
|
// 0x0609..0x060F : zero?
|
||||||
XE_XMA_REGISTER(0x0696, kDword, CONTEXT_LOCK_6)
|
XE_XMA_REGISTER_CONTEXT_GROUP(0x0610, Unknown610)
|
||||||
XE_XMA_REGISTER(0x0697, kDword, CONTEXT_LOCK_7)
|
// 0x061A..0x061F : zero?
|
||||||
XE_XMA_REGISTER(0x0698, kDword, CONTEXT_LOCK_8)
|
XE_XMA_REGISTER_CONTEXT_GROUP(0x0620, Unknown620)
|
||||||
XE_XMA_REGISTER(0x0699, kDword, CONTEXT_LOCK_9)
|
// 0x062A..0x0641 : zero?
|
||||||
|
// 0x0642..0x0644 : ???
|
||||||
|
// 0x0645..0x064F : zero?
|
||||||
|
XE_XMA_REGISTER_CONTEXT_GROUP(0x0650, Kick)
|
||||||
|
// 0x065A..0x065F : zero?
|
||||||
|
XE_XMA_REGISTER_CONTEXT_GROUP(0x0660, Unknown660)
|
||||||
|
// 0x066A..0x0681 : zero?
|
||||||
|
// 0x0682..0x0684 : ???
|
||||||
|
// 0x0685..0x068F : zero?
|
||||||
|
XE_XMA_REGISTER_CONTEXT_GROUP(0x0690, Lock)
|
||||||
|
// 0x069A..0x069F : zero?
|
||||||
|
XE_XMA_REGISTER_CONTEXT_GROUP(0x06A0, Clear)
|
||||||
|
|
||||||
XE_XMA_REGISTER(0x06A0, kDword, CONTEXT_CLEAR_0)
|
//---------------------------------------------------------------------------//
|
||||||
XE_XMA_REGISTER(0x06A1, kDword, CONTEXT_CLEAR_1)
|
|
||||||
XE_XMA_REGISTER(0x06A2, kDword, CONTEXT_CLEAR_2)
|
// 0x0700..0x07FF : all 0xFFs?
|
||||||
XE_XMA_REGISTER(0x06A3, kDword, CONTEXT_CLEAR_3)
|
// 0x0800..0x17FF : ???
|
||||||
XE_XMA_REGISTER(0x06A4, kDword, CONTEXT_CLEAR_4)
|
// 0x1800..0x2FFF : all 0xFFs?
|
||||||
XE_XMA_REGISTER(0x06A5, kDword, CONTEXT_CLEAR_5)
|
// 0x3000..0x30FF : ???
|
||||||
XE_XMA_REGISTER(0x06A6, kDword, CONTEXT_CLEAR_6)
|
// 0x3100..0x3FFF : all 0xFFs?
|
||||||
XE_XMA_REGISTER(0x06A7, kDword, CONTEXT_CLEAR_7)
|
|
||||||
XE_XMA_REGISTER(0x06A8, kDword, CONTEXT_CLEAR_8)
|
#ifdef __XE_XMA_REGISTER_UNSET
|
||||||
XE_XMA_REGISTER(0x06A9, kDword, CONTEXT_CLEAR_9)
|
#undef __XE_XMA_REGISTER_UNSET
|
||||||
|
#undef XE_XMA_REGISTER
|
||||||
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue