From e663751f8b6cc6fd469d3974b3e68e434ebee9db Mon Sep 17 00:00:00 2001
From: Lectem <lectem@gmail.com>
Date: Sat, 25 Jul 2015 22:00:40 +0200
Subject: [PATCH] citra-qt/command list: Add mask column

---
 src/citra_qt/debugger/graphics_cmdlists.cpp | 18 ++++++------
 src/video_core/command_processor.cpp        | 31 +++++++++++----------
 src/video_core/debug_utils/debug_utils.cpp  |  4 +--
 src/video_core/debug_utils/debug_utils.h    | 14 ++++------
 4 files changed, 34 insertions(+), 33 deletions(-)

diff --git a/src/citra_qt/debugger/graphics_cmdlists.cpp b/src/citra_qt/debugger/graphics_cmdlists.cpp
index 9034b120e1..0427ebc95e 100644
--- a/src/citra_qt/debugger/graphics_cmdlists.cpp
+++ b/src/citra_qt/debugger/graphics_cmdlists.cpp
@@ -175,29 +175,29 @@ int GPUCommandListModel::rowCount(const QModelIndex& parent) const {
 }
 
 int GPUCommandListModel::columnCount(const QModelIndex& parent) const {
-    return 3;
+    return 4;
 }
 
 QVariant GPUCommandListModel::data(const QModelIndex& index, int role) const {
     if (!index.isValid())
         return QVariant();
 
-    const auto& writes = pica_trace.writes;
-    const Pica::CommandProcessor::CommandHeader cmd{writes[index.row()].Id()};
-    const u32 val{writes[index.row()].Value()};
+    const auto& write = pica_trace.writes[index.row()];
 
     if (role == Qt::DisplayRole) {
         QString content;
         switch ( index.column() ) {
         case 0:
-            return QString::fromLatin1(Pica::Regs::GetCommandName(cmd.cmd_id).c_str());
+            return QString::fromLatin1(Pica::Regs::GetCommandName(write.cmd_id).c_str());
         case 1:
-            return QString("%1").arg(cmd.cmd_id, 3, 16, QLatin1Char('0'));
+            return QString("%1").arg(write.cmd_id, 3, 16, QLatin1Char('0'));
         case 2:
-            return QString("%1").arg(val, 8, 16, QLatin1Char('0'));
+            return QString("%1").arg(write.mask, 4, 2, QLatin1Char('0'));
+        case 3:
+            return QString("%1").arg(write.value, 8, 16, QLatin1Char('0'));
         }
     } else if (role == CommandIdRole) {
-        return QVariant::fromValue<int>(cmd.cmd_id.Value());
+        return QVariant::fromValue<int>(write.cmd_id);
     }
 
     return QVariant();
@@ -213,6 +213,8 @@ QVariant GPUCommandListModel::headerData(int section, Qt::Orientation orientatio
         case 1:
             return tr("Register");
         case 2:
+            return tr("Mask");
+        case 3:
             return tr("New Value");
         }
 
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp
index 43ae06181a..deed244121 100644
--- a/src/video_core/command_processor.cpp
+++ b/src/video_core/command_processor.cpp
@@ -35,7 +35,15 @@ static u32 default_attr_write_buffer[3];
 
 Common::Profiling::TimingCategory category_drawing("Drawing");
 
-static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
+// Expand a 4-bit mask to 4-byte mask, e.g. 0b0101 -> 0x00FF00FF
+static const u32 expand_bits_to_bytes[] = {
+    0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
+    0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
+    0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff,
+    0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff
+};
+
+static void WritePicaReg(u32 id, u32 value, u32 mask) {
     auto& regs = g_state.regs;
 
     if (id >= regs.NumIds())
@@ -47,13 +55,16 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
 
     // TODO: Figure out how register masking acts on e.g. vs.uniform_setup.set_value
     u32 old_value = regs[id];
-    regs[id] = (old_value & ~mask) | (value & mask);
+
+    const u32 write_mask = expand_bits_to_bytes[mask];
+
+    regs[id] = (old_value & ~write_mask) | (value & write_mask);
+
+    DebugUtils::OnPicaRegWrite({ (u16)id, (u16)mask, regs[id] });
 
     if (g_debug_context)
         g_debug_context->OnEvent(DebugContext::Event::PicaCommandLoaded, reinterpret_cast<void*>(&id));
 
-    DebugUtils::OnPicaRegWrite(id, regs[id]);
-
     switch(id) {
         // Trigger IRQ
         case PICA_REG_INDEX(trigger_irq):
@@ -436,13 +447,6 @@ void ProcessCommandList(const u32* list, u32 size) {
     g_state.cmd_list.length = size / sizeof(u32);
 
     while (g_state.cmd_list.current_ptr < g_state.cmd_list.head_ptr + g_state.cmd_list.length) {
-        // Expand a 4-bit mask to 4-byte mask, e.g. 0b0101 -> 0x00FF00FF
-        static const u32 expand_bits_to_bytes[] = {
-            0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
-            0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
-            0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff,
-            0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff
-        };
 
         // Align read pointer to 8 bytes
         if ((g_state.cmd_list.head_ptr - g_state.cmd_list.current_ptr) % 2 != 0)
@@ -450,14 +454,13 @@ void ProcessCommandList(const u32* list, u32 size) {
 
         u32 value = *g_state.cmd_list.current_ptr++;
         const CommandHeader header = { *g_state.cmd_list.current_ptr++ };
-        const u32 write_mask = expand_bits_to_bytes[header.parameter_mask];
         u32 cmd = header.cmd_id;
 
-        WritePicaReg(cmd, value, write_mask);
+        WritePicaReg(cmd, value, header.parameter_mask);
 
         for (unsigned i = 0; i < header.extra_data_length; ++i) {
             u32 cmd = header.cmd_id + (header.group_commands ? i + 1 : 0);
-            WritePicaReg(cmd, *g_state.cmd_list.current_ptr++, write_mask);
+            WritePicaReg(cmd, *g_state.cmd_list.current_ptr++, header.parameter_mask);
          }
     }
 }
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp
index c3f8321c69..827b09dffe 100644
--- a/src/video_core/debug_utils/debug_utils.cpp
+++ b/src/video_core/debug_utils/debug_utils.cpp
@@ -280,7 +280,7 @@ bool IsPicaTracing()
     return is_pica_tracing != 0;
 }
 
-void OnPicaRegWrite(u32 id, u32 value)
+void OnPicaRegWrite(PicaTrace::Write write)
 {
     // Double check for is_pica_tracing to avoid pointless locking overhead
     if (!is_pica_tracing)
@@ -291,7 +291,7 @@ void OnPicaRegWrite(u32 id, u32 value)
     if (!is_pica_tracing)
         return;
 
-    pica_trace->writes.emplace_back(id, value);
+    pica_trace->writes.push_back(write);
 }
 
 std::unique_ptr<PicaTrace> FinishPicaTracing()
diff --git a/src/video_core/debug_utils/debug_utils.h b/src/video_core/debug_utils/debug_utils.h
index 3f109dcb7b..acb75a4b26 100644
--- a/src/video_core/debug_utils/debug_utils.h
+++ b/src/video_core/debug_utils/debug_utils.h
@@ -183,21 +183,17 @@ void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data
 
 // Utility class to log Pica commands.
 struct PicaTrace {
-    struct Write : public std::pair<u32,u32> {
-        Write(u32 id, u32 value) : std::pair<u32,u32>(id, value) {}
-
-        u32& Id() { return first; }
-        const u32& Id() const { return first; }
-
-        u32& Value() { return second; }
-        const u32& Value() const { return second; }
+    struct Write {
+        u16 cmd_id;
+        u16 mask;
+        u32 value;
     };
     std::vector<Write> writes;
 };
 
 void StartPicaTracing();
 bool IsPicaTracing();
-void OnPicaRegWrite(u32 id, u32 value);
+void OnPicaRegWrite(PicaTrace::Write write);
 std::unique_ptr<PicaTrace> FinishPicaTracing();
 
 struct TextureInfo {