From 4f969e22713ee510ef29741773b8d6721ebe9e49 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Mon, 12 Feb 2018 19:40:19 -0500
Subject: [PATCH 1/3] TransactParcel: Move WriteBlock to narrowest scope.

---
 src/core/hle/service/vi/vi.cpp | 23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index dd4d3e517a..7d9a41ded7 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -442,18 +442,20 @@ private:
     void TransactParcel(u32 id, TransactionId transaction, const std::vector<u8>& input_data,
                         VAddr output_addr, u64 output_size) {
         auto buffer_queue = nv_flinger->GetBufferQueue(id);
-        std::vector<u8> response_buffer;
+
         if (transaction == TransactionId::Connect) {
             IGBPConnectRequestParcel request{input_data};
             IGBPConnectResponseParcel response{1280, 720};
-            response_buffer = response.Serialize();
+            std::vector<u8> response_buffer = response.Serialize();
+            Memory::WriteBlock(output_addr, response_buffer.data(), response_buffer.size());
         } else if (transaction == TransactionId::SetPreallocatedBuffer) {
             IGBPSetPreallocatedBufferRequestParcel request{input_data};
 
             buffer_queue->SetPreallocatedBuffer(request.data.slot, request.buffer);
 
             IGBPSetPreallocatedBufferResponseParcel response{};
-            response_buffer = response.Serialize();
+            std::vector<u8> response_buffer = response.Serialize();
+            Memory::WriteBlock(output_addr, response_buffer.data(), response_buffer.size());
         } else if (transaction == TransactionId::DequeueBuffer) {
             IGBPDequeueBufferRequestParcel request{input_data};
 
@@ -461,21 +463,24 @@ private:
                                                    request.data.height);
 
             IGBPDequeueBufferResponseParcel response{slot};
-            response_buffer = response.Serialize();
+            std::vector<u8> response_buffer = response.Serialize();
+            Memory::WriteBlock(output_addr, response_buffer.data(), response_buffer.size());
         } else if (transaction == TransactionId::RequestBuffer) {
             IGBPRequestBufferRequestParcel request{input_data};
 
             auto& buffer = buffer_queue->RequestBuffer(request.slot);
 
             IGBPRequestBufferResponseParcel response{buffer};
-            response_buffer = response.Serialize();
+            std::vector<u8> response_buffer = response.Serialize();
+            Memory::WriteBlock(output_addr, response_buffer.data(), response_buffer.size());
         } else if (transaction == TransactionId::QueueBuffer) {
             IGBPQueueBufferRequestParcel request{input_data};
 
             buffer_queue->QueueBuffer(request.data.slot, request.data.transform);
 
             IGBPQueueBufferResponseParcel response{1280, 720};
-            response_buffer = response.Serialize();
+            std::vector<u8> response_buffer = response.Serialize();
+            Memory::WriteBlock(output_addr, response_buffer.data(), response_buffer.size());
         } else if (transaction == TransactionId::Query) {
             IGBPQueryRequestParcel request{input_data};
 
@@ -483,13 +488,11 @@ private:
                 buffer_queue->Query(static_cast<NVFlinger::BufferQueue::QueryType>(request.type));
 
             IGBPQueryResponseParcel response{value};
-            response_buffer = response.Serialize();
-
+            std::vector<u8> response_buffer = response.Serialize();
+            Memory::WriteBlock(output_addr, response_buffer.data(), response_buffer.size());
         } else {
             ASSERT_MSG(false, "Unimplemented");
         }
-
-        Memory::WriteBlock(output_addr, response_buffer.data(), output_size);
     }
 
     void TransactParcel(Kernel::HLERequestContext& ctx) {

From a9e4e8294a937397ae164242415c21615c9092b3 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Mon, 12 Feb 2018 21:15:53 -0500
Subject: [PATCH 2/3] vi: Stub TransactParcel CancelBuffer.

---
 src/core/hle/service/vi/vi.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 7d9a41ded7..cfdd4bf2a6 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -490,6 +490,8 @@ private:
             IGBPQueryResponseParcel response{value};
             std::vector<u8> response_buffer = response.Serialize();
             Memory::WriteBlock(output_addr, response_buffer.data(), response_buffer.size());
+        } else if (transaction == TransactionId::CancelBuffer) {
+            LOG_WARNING(Service_VI, "(STUBBED) called, transaction=CancelBuffer");
         } else {
             ASSERT_MSG(false, "Unimplemented");
         }

From 91e19deb3931dcb1ee2b692b3d9b039bc601e2c3 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Mon, 12 Feb 2018 21:17:04 -0500
Subject: [PATCH 3/3] vi: Add FENCE_HACK, which is useful for booting BOTW.

---
 src/core/hle/service/vi/vi.cpp | 28 +++++++++++++++++++++-------
 1 file changed, 21 insertions(+), 7 deletions(-)

diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index cfdd4bf2a6..8b4ed30d2d 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -262,6 +262,11 @@ public:
     Data data;
 };
 
+// TODO(bunnei): Remove this. When set to 1, games will think a fence is valid and boot further.
+// This will break libnx and potentially other apps that more stringently check this. This is here
+// purely as a convenience, and should go away once we implement fences.
+static constexpr u32 FENCE_HACK = 0;
+
 class IGBPDequeueBufferResponseParcel : public Parcel {
 public:
     explicit IGBPDequeueBufferResponseParcel(u32 slot) : Parcel(), slot(slot) {}
@@ -269,11 +274,20 @@ public:
 
 protected:
     void SerializeData() override {
-        Write(slot);
-        // TODO(Subv): Find out how this Fence is used.
-        std::array<u32_le, 11> fence = {};
-        Write(fence);
-        Write<u32_le>(0);
+        // TODO(bunnei): Find out what this all means. Writing anything non-zero here breaks libnx.
+        Write<u32>(0);
+        Write<u32>(FENCE_HACK);
+        Write<u32>(0);
+        Write<u32>(0);
+        Write<u32>(0);
+        Write<u32>(0);
+        Write<u32>(0);
+        Write<u32>(0);
+        Write<u32>(0);
+        Write<u32>(0);
+        Write<u32>(0);
+        Write<u32>(0);
+        Write<u32>(0);
     }
 
     u32_le slot;
@@ -304,7 +318,7 @@ protected:
     void SerializeData() override {
         // TODO(bunnei): Find out what this all means. Writing anything non-zero here breaks libnx.
         Write<u32_le>(0);
-        Write<u32_le>(0);
+        Write<u32_le>(FENCE_HACK);
         Write<u32_le>(0);
         Write(buffer);
         Write<u32_le>(0);
@@ -560,7 +574,7 @@ private:
     }
 
     std::shared_ptr<NVFlinger::NVFlinger> nv_flinger;
-};
+}; // namespace VI
 
 class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> {
 public: