From 8daef932070cef9e8b606a3bdd125c59b98fbc51 Mon Sep 17 00:00:00 2001
From: gibbed <rick@gibbed.us>
Date: Mon, 28 Jun 2021 19:23:38 -0500
Subject: [PATCH] [APU] XMA register table cleanup, documentation.

- [APU] Clean up XMA register table.
- [APU] Document observed register ranges in the XMA register table.
---
 src/xenia/apu/xma_decoder.cc         |  37 +++++-----
 src/xenia/apu/xma_decoder.h          |   4 +-
 src/xenia/apu/xma_register_file.cc   |   5 +-
 src/xenia/apu/xma_register_file.h    |  21 ++----
 src/xenia/apu/xma_register_table.inc | 100 +++++++++++++++++----------
 5 files changed, 94 insertions(+), 73 deletions(-)

diff --git a/src/xenia/apu/xma_decoder.cc b/src/xenia/apu/xma_decoder.cc
index b15bd7fe2..cd04ebd91 100644
--- a/src/xenia/apu/xma_decoder.cc
+++ b/src/xenia/apu/xma_decoder.cc
@@ -123,7 +123,7 @@ X_STATUS XmaDecoder::Setup(kernel::KernelState* kernel_state) {
       sizeof(XMA_CONTEXT_DATA) * kContextCount, 256, kSystemHeapPhysical);
   context_data_last_ptr_ =
       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_);
 
   // Setup XMA contexts.
@@ -134,7 +134,7 @@ X_STATUS XmaDecoder::Setup(kernel::KernelState* kernel_state) {
       assert_always();
     }
   }
-  register_file_[XE_XMA_REG_NEXT_CONTEXT_INDEX].u32 = 1;
+  register_file_[XmaRegister::NextContextIndex] = 1;
   context_bitmap_.Resize(kContextCount);
 
   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 r = (addr & 0xFFFF) / 4;
+  auto r = (addr & 0xFFFF) / 4;
 
   assert_true(r < XmaRegisterFile::kRegisterCount);
 
   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
       // context being processed.
       // 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?).
       uint32_t& current_context_index =
-          register_file_[XE_XMA_REG_CURRENT_CONTEXT_INDEX].u32;
+          register_file_[XmaRegister::CurrentContextIndex];
       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
       // number.
       current_context_index = next_context_index;
       next_context_index = (next_context_index + 1) % kContextCount;
       break;
     }
-    default: {
+    default:
       const auto register_info = register_file_.GetRegisterInfo(r);
       if (register_info) {
         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);
       }
       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) {
@@ -296,16 +297,16 @@ void XmaDecoder::WriteRegister(uint32_t addr, uint32_t value) {
   value = xe::byte_swap(value);
 
   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.
     // This will kick off the given hardware contexts.
     // Basically, this kicks the SPU and says "hey, decode that audio!"
     // XMAEnableContext
 
     // 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) {
       if (value & 1) {
         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.
     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.
     // This requests a lock by flagging the context.
     // 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) {
       if (value & 1) {
         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.
-    work_event_->Set();
-  } else if (r >= XE_XMA_REG_CONTEXT_CLEAR_0 &&
-             r <= XE_XMA_REG_CONTEXT_CLEAR_9) {
+    // work_event_->Set();
+  } else if (r >= XmaRegister::Context0Clear &&
+             r <= XmaRegister::Context9Clear) {
     // Context clear command.
     // 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) {
       if (value & 1) {
         uint32_t context_id = base_context_id + i;
diff --git a/src/xenia/apu/xma_decoder.h b/src/xenia/apu/xma_decoder.h
index 228a7290d..73da02c2e 100644
--- a/src/xenia/apu/xma_decoder.h
+++ b/src/xenia/apu/xma_decoder.h
@@ -2,7 +2,7 @@
  ******************************************************************************
  * 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. *
  ******************************************************************************
  */
@@ -37,7 +37,7 @@ class XmaDecoder {
   void Shutdown();
 
   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();
diff --git a/src/xenia/apu/xma_register_file.cc b/src/xenia/apu/xma_register_file.cc
index d3383b9cb..ee45b2811 100644
--- a/src/xenia/apu/xma_register_file.cc
+++ b/src/xenia/apu/xma_register_file.cc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * 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. *
  ******************************************************************************
  */
@@ -20,10 +20,9 @@ XmaRegisterFile::XmaRegisterFile() { std::memset(values, 0, sizeof(values)); }
 
 const XmaRegisterInfo* XmaRegisterFile::GetRegisterInfo(uint32_t index) {
   switch (index) {
-#define XE_XMA_REGISTER(index, type, name)    \
+#define XE_XMA_REGISTER(index, name)          \
   case index: {                               \
     static const XmaRegisterInfo reg_info = { \
-        XmaRegisterInfo::Type::type,          \
         #name,                                \
     };                                        \
     return &reg_info;                         \
diff --git a/src/xenia/apu/xma_register_file.h b/src/xenia/apu/xma_register_file.h
index 09154b9ad..e2e924c57 100644
--- a/src/xenia/apu/xma_register_file.h
+++ b/src/xenia/apu/xma_register_file.h
@@ -2,7 +2,7 @@
  ******************************************************************************
  * 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. *
  ******************************************************************************
  */
@@ -16,18 +16,13 @@
 namespace xe {
 namespace apu {
 
-enum XmaRegister {
-#define XE_XMA_REGISTER(index, type, name) XE_XMA_REG_##name = index,
+struct XmaRegister {
+#define XE_XMA_REGISTER(index, name) static const uint32_t name = index;
 #include "xenia/apu/xma_register_table.inc"
 #undef XE_XMA_REGISTER
 };
 
 struct XmaRegisterInfo {
-  enum class Type {
-    kDword,
-    kFloat,
-  };
-  Type type;
   const char* name;
 };
 
@@ -38,14 +33,10 @@ class XmaRegisterFile {
   static const XmaRegisterInfo* GetRegisterInfo(uint32_t index);
 
   static const size_t kRegisterCount = (0xFFFF + 1) / 4;
-  union RegisterValue {
-    uint32_t u32;
-    float f32;
-  };
-  RegisterValue values[kRegisterCount];
+  uint32_t values[kRegisterCount];
 
-  RegisterValue& operator[](int reg) { return values[reg]; }
-  RegisterValue& operator[](XmaRegister reg) { return values[reg]; }
+  uint32_t operator[](uint32_t reg) const { return values[reg]; }
+  uint32_t& operator[](uint32_t reg) { return values[reg]; }
 };
 
 }  // namespace apu
diff --git a/src/xenia/apu/xma_register_table.inc b/src/xenia/apu/xma_register_table.inc
index 49b32e26f..1703c2e9f 100644
--- a/src/xenia/apu/xma_register_table.inc
+++ b/src/xenia/apu/xma_register_table.inc
@@ -2,7 +2,7 @@
  ******************************************************************************
  * 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. *
  ******************************************************************************
  */
@@ -10,42 +10,72 @@
 // This is a partial file designed to be included by other files when
 // 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)
-XE_XMA_REGISTER(0x0607, kDword, NEXT_CONTEXT_INDEX)
+// 0x0000..0x001F : ???
+// 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)
-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)
+// XMA stuff is probably only 0x0600..0x06FF
+//---------------------------------------------------------------------------//
 
-XE_XMA_REGISTER(0x0690, kDword, CONTEXT_LOCK_0)
-XE_XMA_REGISTER(0x0691, kDword, CONTEXT_LOCK_1)
-XE_XMA_REGISTER(0x0692, kDword, CONTEXT_LOCK_2)
-XE_XMA_REGISTER(0x0693, kDword, CONTEXT_LOCK_3)
-XE_XMA_REGISTER(0x0694, kDword, CONTEXT_LOCK_4)
-XE_XMA_REGISTER(0x0695, kDword, CONTEXT_LOCK_5)
-XE_XMA_REGISTER(0x0696, kDword, CONTEXT_LOCK_6)
-XE_XMA_REGISTER(0x0697, kDword, CONTEXT_LOCK_7)
-XE_XMA_REGISTER(0x0698, kDword, CONTEXT_LOCK_8)
-XE_XMA_REGISTER(0x0699, kDword, CONTEXT_LOCK_9)
+XE_XMA_REGISTER(0x0600, ContextArrayAddress)
+// 0x0601..0x0605 : ???
+XE_XMA_REGISTER(0x0606, CurrentContextIndex)
+XE_XMA_REGISTER(0x0607, NextContextIndex)
+// 0x0608         : ???
+// 0x0609..0x060F : zero?
+XE_XMA_REGISTER_CONTEXT_GROUP(0x0610, Unknown610)
+// 0x061A..0x061F : zero?
+XE_XMA_REGISTER_CONTEXT_GROUP(0x0620, Unknown620)
+// 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)
-XE_XMA_REGISTER(0x06A3, kDword, CONTEXT_CLEAR_3)
-XE_XMA_REGISTER(0x06A4, kDword, CONTEXT_CLEAR_4)
-XE_XMA_REGISTER(0x06A5, kDword, CONTEXT_CLEAR_5)
-XE_XMA_REGISTER(0x06A6, kDword, CONTEXT_CLEAR_6)
-XE_XMA_REGISTER(0x06A7, kDword, CONTEXT_CLEAR_7)
-XE_XMA_REGISTER(0x06A8, kDword, CONTEXT_CLEAR_8)
-XE_XMA_REGISTER(0x06A9, kDword, CONTEXT_CLEAR_9)
+//---------------------------------------------------------------------------//
+
+// 0x0700..0x07FF : all 0xFFs?
+// 0x0800..0x17FF : ???
+// 0x1800..0x2FFF : all 0xFFs?
+// 0x3000..0x30FF : ???
+// 0x3100..0x3FFF : all 0xFFs?
+
+#ifdef __XE_XMA_REGISTER_UNSET
+#undef __XE_XMA_REGISTER_UNSET
+#undef XE_XMA_REGISTER
+#endif