From e12cfc89deedc7046d3f5756f504a3ef920ab559 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Tue, 27 Jan 2015 21:04:40 +0200 Subject: [PATCH] Experimental DMA implementation, bug fixes The experimental DMA implementation is ported from Nucleus. --- rpcs3/Emu/RSX/RSXDMA.cpp | 124 ++++++++++++++++++++++++++++++++++ rpcs3/Emu/RSX/RSXDMA.h | 45 ++++++++++++ rpcs3/Emu/RSX/RSXThread.cpp | 25 ++++--- rpcs3/Emu/RSX/RSXThread.h | 3 + rpcs3/emucore.vcxproj | 2 + rpcs3/emucore.vcxproj.filters | 6 ++ 6 files changed, 195 insertions(+), 10 deletions(-) create mode 100644 rpcs3/Emu/RSX/RSXDMA.cpp create mode 100644 rpcs3/Emu/RSX/RSXDMA.h 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