diff --git a/rpcs3/Emu/RSX/RSXDMA.cpp b/rpcs3/Emu/RSX/RSXDMA.cpp
new file mode 100644
index 0000000000..476448474f
--- /dev/null
+++ b/rpcs3/Emu/RSX/RSXDMA.cpp
@@ -0,0 +1,124 @@
+#include "stdafx.h"
+#include "RSXDMA.h"
+#include "Emu/Memory/Memory.h"
+#include "Utilities/Log.h"
+
+DMAObject dma_address(u32 dma_object)
+{
+ // NOTE: RAMIN is not emulated, therefore DMA Objects are hardcoded in this function
+ switch (dma_object) {
+ case RSX_CONTEXT_DMA_REPORT_LOCATION_LOCAL:
+ return DMAObject{ 0x40300000, 0x8000, DMAObject::READWRITE }; // TODO: Inconsistency: Gitbrew says R starting at 0x1400, test says RW starting at 0x0.
+ case RSX_CONTEXT_DMA_DEVICE_RW:
+ return DMAObject{ 0x40000000, 0x1000, DMAObject::READWRITE };
+ case RSX_CONTEXT_DMA_DEVICE_R:
+ return DMAObject{ 0x40000000, 0x1000, DMAObject::READWRITE }; // TODO: Inconsistency: Gitbrew says R, test says RW
+ case RSX_CONTEXT_DMA_SEMAPHORE_RW:
+ return DMAObject{ 0x40100000, 0x1000, DMAObject::READWRITE };
+ case RSX_CONTEXT_DMA_SEMAPHORE_R:
+ return DMAObject{ 0x40100000, 0x1000, DMAObject::READWRITE }; // TODO: Inconsistency: Gitbrew says R, test says RW
+ default:
+ LOG_WARNING(RSX, "Unknown DMA object (0x%08X)", dma_object);
+ return DMAObject{};
+ }
+}
+
+u8 dma_read8(u32 dma_object, u8 offset)
+{
+ const DMAObject& dma = dma_address(dma_object);
+
+ if (dma.addr && dma.flags & DMAObject::READ)
+ {
+ return vm::read8(dma.addr + offset);
+ }
+
+ LOG_WARNING(RSX, "Illegal DMA 8-bit read");
+ return 0;
+}
+
+u16 dma_read16(u32 dma_object, u16 offset)
+{
+ const DMAObject& dma = dma_address(dma_object);
+
+ if (dma.addr && dma.flags & DMAObject::READ)
+ {
+ return vm::read16(dma.addr + offset);
+ }
+
+ LOG_WARNING(RSX, "Illegal DMA 16-bit read");
+ return 0;
+}
+
+u32 dma_read32(u32 dma_object, u32 offset)
+{
+ const DMAObject& dma = dma_address(dma_object);
+
+ if (dma.addr && dma.flags & DMAObject::READ)
+ {
+ return vm::read32(dma.addr + offset);
+ }
+
+ LOG_WARNING(RSX, "Illegal DMA 32-bit read");
+ return 0;
+}
+
+u64 dma_read64(u32 dma_object, u64 offset)
+{
+ const DMAObject& dma = dma_address(dma_object);
+
+ if (dma.addr && dma.flags & DMAObject::READ)
+ {
+ return vm::read64(dma.addr + offset);
+ }
+
+ LOG_WARNING(RSX, "Illegal DMA 64-bit read");
+ return 0;
+}
+
+void dma_write8(u32 dma_object, u32 offset, u8 value)
+{
+ const DMAObject& dma = dma_address(dma_object);
+
+ if (dma.addr && dma.flags & DMAObject::WRITE)
+ {
+ return vm::write8(dma.addr + offset, value);
+ }
+
+ LOG_WARNING(RSX, "Illegal DMA 32-bit write");
+}
+
+void dma_write16(u32 dma_object, u32 offset, u16 value)
+{
+ const DMAObject& dma = dma_address(dma_object);
+
+ if (dma.addr && dma.flags & DMAObject::WRITE)
+ {
+ return vm::write16(dma.addr + offset, value);
+ }
+
+ LOG_WARNING(RSX, "Illegal DMA 32-bit write");
+}
+
+void dma_write32(u32 dma_object, u32 offset, u32 value)
+{
+ const DMAObject& dma = dma_address(dma_object);
+
+ if (dma.addr && dma.flags & DMAObject::WRITE)
+ {
+ return vm::write32(dma.addr + offset, value);
+ }
+
+ LOG_WARNING(RSX, "Illegal DMA 32-bit write");
+}
+
+void dma_write64(u32 dma_object, u32 offset, u64 value)
+{
+ const DMAObject& dma = dma_address(dma_object);
+
+ if (dma.addr && dma.flags & DMAObject::WRITE)
+ {
+ return vm::write64(dma.addr + offset, value);
+ }
+
+ LOG_WARNING(RSX, "Illegal DMA 64-bit write");
+}
\ No newline at end of file
diff --git a/rpcs3/Emu/RSX/RSXDMA.h b/rpcs3/Emu/RSX/RSXDMA.h
new file mode 100644
index 0000000000..b432375506
--- /dev/null
+++ b/rpcs3/Emu/RSX/RSXDMA.h
@@ -0,0 +1,45 @@
+#pragma once
+
+enum {
+ RSX_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY0 = 0x66604200, // Target: lpar_reports[0x1000 : 0x????]
+ RSX_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY1 = 0x66604201, // Target: lpar_reports[0x1000 : 0x????]
+ RSX_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY2 = 0x66604202, // Target: lpar_reports[0x1000 : 0x????]
+ RSX_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY3 = 0x66604203, // Target: lpar_reports[0x1000 : 0x????]
+ RSX_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY4 = 0x66604204, // Target: lpar_reports[0x1000 : 0x????]
+ RSX_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY5 = 0x66604205, // Target: lpar_reports[0x1000 : 0x????]
+ RSX_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY6 = 0x66604206, // Target: lpar_reports[0x1000 : 0x????]
+ RSX_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY7 = 0x66604207, // Target: lpar_reports[0x1000 : 0x????]
+ RSX_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY8 = 0x66604208, // Target: lpar_reports[0x1000 : 0x????]
+ RSX_CONTEXT_DMA_NOTIFY_MAIN_0 = 0x6660420F,
+ RSX_CONTEXT_DMA_SEMAPHORE_RW = 0x66606660, // Target: lpar_reports[0x0000 : 0x1000] (Read/Write)
+ RSX_CONTEXT_DMA_SEMAPHORE_R = 0x66616661, // Target: lpar_reports[0x0000 : 0x1000] (Read)
+ RSX_CONTEXT_DMA_REPORT_LOCATION_LOCAL = 0x66626660, // Target: lpar_reports[0x1400 : 0x9400]
+ RSX_CONTEXT_DMA_REPORT_LOCATION_MAIN = 0xBAD68000,
+ RSX_CONTEXT_DMA_DEVICE_RW = 0x56616660,
+ RSX_CONTEXT_DMA_DEVICE_R = 0x56616661,
+};
+
+struct DMAObject {
+ // Flags
+ enum {
+ READ = 1 << 0,
+ WRITE = 1 << 1,
+ READWRITE = READ | WRITE,
+ };
+ u32 addr;
+ u32 size;
+ u32 flags;
+};
+
+// RSX Direct Memory Access
+DMAObject dma_address(u32 dma_object);
+
+u8 dma_read8(u32 dma_object, u32 offset);
+u16 dma_read16(u32 dma_object, u32 offset);
+u32 dma_read32(u32 dma_object, u32 offset);
+u64 dma_read64(u32 dma_object, u32 offset);
+
+void dma_write8(u32 dma_object, u32 offset, u8 value);
+void dma_write16(u32 dma_object, u32 offset, u16 value);
+void dma_write32(u32 dma_object, u32 offset, u32 value);
+void dma_write64(u32 dma_object, u32 offset, u64 value);
\ No newline at end of file
diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp
index 906b0281c3..ed7b539005 100644
--- a/rpcs3/Emu/RSX/RSXThread.cpp
+++ b/rpcs3/Emu/RSX/RSXThread.cpp
@@ -4,6 +4,7 @@
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/RSX/GSManager.h"
+#include "Emu/RSX/RSXDMA.h"
#include "RSXThread.h"
#include "Emu/SysCalls/Callback.h"
@@ -333,6 +334,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
{
LOG_WARNING(RSX, "TODO: NV4097_SET_CONTEXT_DMA_REPORT: 0x%x", ARGS(0));
}
+
+ dma_report = ARGS(0);
}
break;
@@ -891,9 +894,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_CLEAR_SURFACE:
{
- const u32 mask = ARGS(0);
-
- ClearSurface(mask);
+ ClearSurface(ARGS(0));
}
break;
@@ -901,8 +902,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
{
const u32 value = ARGS(0);
- ClearStencil(value & 0xff);
ClearDepth(value >> 8);
+ ClearStencil(value & 0xff);
}
break;
@@ -1076,7 +1077,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
{
m_cur_fragment_prog = &m_fragment_progs[m_cur_fragment_prog_num];
- const u32 a0 = ARGS(0);
+ const u32 a0 = ARGS(0);
m_cur_fragment_prog->offset = a0 & ~0x3;
m_cur_fragment_prog->addr = GetAddress(m_cur_fragment_prog->offset, (a0 & 0x3) - 1);
m_cur_fragment_prog->ctrl = 0x40;
@@ -1091,8 +1092,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_SET_SHADE_MODE:
{
- const u32 value = ARGS(0);
- ShadeModel(value);
+ ShadeModel(ARGS(0));
}
break;
@@ -1867,9 +1867,14 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
u64 timestamp = get_system_time() * 1000;
// TODO: Reports can be written to the main memory or the local memory (controlled by NV4097_SET_CONTEXT_DMA_REPORT)
- vm::write64(m_local_mem_addr + offset + 0x0, timestamp);
- vm::write32(m_local_mem_addr + offset + 0x8, value);
- vm::write32(m_local_mem_addr + offset + 0xc, 0);
+ // NOTE: Uncomment these, if DMA implementation is broken
+ //vm::write64(m_local_mem_addr + offset + 0x0, timestamp);
+ //vm::write32(m_local_mem_addr + offset + 0x8, value);
+ //vm::write32(m_local_mem_addr + offset + 0xc, 0);
+
+ dma_write64(dma_report, offset + 0x0, timestamp);
+ dma_write32(dma_report, offset + 0x8, value);
+ dma_write32(dma_report, offset + 0xc, 0);
}
break;
diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h
index 618573d21a..4a5fe782ca 100644
--- a/rpcs3/Emu/RSX/RSXThread.h
+++ b/rpcs3/Emu/RSX/RSXThread.h
@@ -136,6 +136,9 @@ public:
u32 m_ctxt_addr;
u32 m_report_main_addr;
+ // DMA
+ u32 dma_report;
+
u32 m_local_mem_addr, m_main_mem_addr;
bool m_strict_ordering[0x1000];
diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj
index 4b4a2d6539..b52ff1c3ba 100644
--- a/rpcs3/emucore.vcxproj
+++ b/rpcs3/emucore.vcxproj
@@ -107,6 +107,7 @@
+
@@ -348,6 +349,7 @@
+
diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters
index fdd71b410a..d222f71c07 100644
--- a/rpcs3/emucore.vcxproj.filters
+++ b/rpcs3/emucore.vcxproj.filters
@@ -665,6 +665,9 @@
Emu\CPU\ARMv7
+
+ Emu\GPU\RSX
+
@@ -1294,5 +1297,8 @@
Emu\CPU\ARMv7\Modules
+
+ Emu\GPU\RSX
+
\ No newline at end of file