From a39a65cbe0d787587ad686fbd9474703ac58090c Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Wed, 7 Feb 2018 22:03:04 -0500
Subject: [PATCH] nvhost_as_gpu: Implement AllocateSpace and MapBufferEx.

---
 .../service/nvdrv/devices/nvhost_as_gpu.cpp   | 37 ++++++++++++++-----
 .../hle/service/nvdrv/devices/nvhost_as_gpu.h |  6 ++-
 2 files changed, 33 insertions(+), 10 deletions(-)

diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
index 3701c182fa..cf3601f02c 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
@@ -41,9 +41,16 @@ u32 nvhost_as_gpu::InitalizeEx(const std::vector<u8>& input, std::vector<u8>& ou
 u32 nvhost_as_gpu::AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output) {
     IoctlAllocSpace params{};
     std::memcpy(&params, input.data(), input.size());
-    LOG_WARNING(Service_NVDRV, "(STUBBED) called, pages=%x, page_size=%x, flags=%x", params.pages,
-                params.page_size, params.flags);
-    params.offset = 0xdeadbeef; // TODO(ogniK): Actually allocate space and give a real offset
+    LOG_DEBUG(Service_NVDRV, "called, pages=%x, page_size=%x, flags=%x", params.pages,
+              params.page_size, params.flags);
+
+    const u64 size{static_cast<u64>(params.pages) * static_cast<u64>(params.page_size)};
+    if (params.flags & 1) {
+        params.offset = memory_manager->AllocateSpace(params.offset, size, 1);
+    } else {
+        params.offset = memory_manager->AllocateSpace(size, params.align);
+    }
+
     std::memcpy(output.data(), &params, output.size());
     return 0;
 }
@@ -52,12 +59,24 @@ u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& ou
     IoctlMapBufferEx params{};
     std::memcpy(&params, input.data(), input.size());
 
-    LOG_WARNING(Service_NVDRV,
-                "(STUBBED) called, flags=%x, nvmap_handle=%x, buffer_offset=%lx, mapping_size=%lx, "
-                "offset=%lx",
-                params.flags, params.nvmap_handle, params.buffer_offset, params.mapping_size,
-                params.offset);
-    params.offset = 0x0; // TODO(ogniK): Actually map and give a real offset
+    LOG_DEBUG(Service_NVDRV,
+              "called, flags=%x, nvmap_handle=%x, buffer_offset=%lx, mapping_size=%lx, offset=%lx",
+              params.flags, params.nvmap_handle, params.buffer_offset, params.mapping_size,
+              params.offset);
+
+    if (!params.nvmap_handle) {
+        return 0;
+    }
+
+    auto object = nvmap_dev->GetObject(params.nvmap_handle);
+    ASSERT(object);
+
+    if (params.flags & 1) {
+        params.offset = memory_manager->MapBufferEx(object->addr, params.offset, object->size);
+    } else {
+        params.offset = memory_manager->MapBufferEx(object->addr, object->size);
+    }
+
     std::memcpy(output.data(), &params, output.size());
     return 0;
 }
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
index 6b3b67113e..9d37b971a0 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
@@ -10,6 +10,7 @@
 #include "common/common_types.h"
 #include "common/swap.h"
 #include "core/hle/service/nvdrv/devices/nvdevice.h"
+#include "core/hle/service/nvdrv/memory_manager.h"
 
 namespace Service {
 namespace Nvidia {
@@ -19,7 +20,9 @@ class nvmap;
 
 class nvhost_as_gpu final : public nvdevice {
 public:
-    nvhost_as_gpu(std::shared_ptr<nvmap> nvmap_dev) : nvdevice(), nvmap_dev(std::move(nvmap_dev)) {}
+    nvhost_as_gpu(std::shared_ptr<nvmap> nvmap_dev) : nvdevice(), nvmap_dev(std::move(nvmap_dev)) {
+        memory_manager = std::make_shared<MemoryManager>();
+    }
     ~nvhost_as_gpu() override = default;
 
     u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
@@ -98,6 +101,7 @@ private:
     u32 GetVARegions(const std::vector<u8>& input, std::vector<u8>& output);
 
     std::shared_ptr<nvmap> nvmap_dev;
+    std::shared_ptr<MemoryManager> memory_manager;
 };
 
 } // namespace Devices