From f15c679fea693368422b2f35897c1b087579506b Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Tue, 27 Jan 2015 17:14:15 +0200 Subject: [PATCH 1/4] Add support for "test mode" Since @devmapal hasn't made a PR for this and this would be probably useful for Coveralls and unit tests I'm making a PR for it myself. More info: https://github.com/devmapal/rpcs3/commit/c72f5d40f521b955faec024e6b788aa1e027ccfc --- rpcs3/rpcs3.cpp | 41 +++++++++++++++++++++++++++++++++++++---- rpcs3/rpcs3.h | 7 ++++++- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/rpcs3/rpcs3.cpp b/rpcs3/rpcs3.cpp index d7549972fe..4f2bc92078 100644 --- a/rpcs3/rpcs3.cpp +++ b/rpcs3/rpcs3.cpp @@ -202,6 +202,22 @@ void compile_shader(std::string path) bool Rpcs3App::OnInit() { + static const wxCmdLineEntryDesc desc[] + { + { wxCMD_LINE_SWITCH, "h", "help", "Command line options:\nh (help): Help and commands\nt (test): For directly executing a (S)ELF", wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP }, + { wxCMD_LINE_SWITCH, "t", "test", "Run in test mode on (S)ELF", wxCMD_LINE_VAL_NONE }, + { wxCMD_LINE_PARAM, NULL, NULL, "(S)ELF", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, + { wxCMD_LINE_NONE } + }; + + parser.SetDesc(desc); + parser.SetCmdLine(argc, argv); + if (parser.Parse()) + { + // help was given, terminating + this->Exit(); + } + SetSendDbgCommandCallback([](DbgCommand id, CPUThread* t) { wxGetApp().SendDbgCommand(id, t); @@ -296,7 +312,7 @@ bool Rpcs3App::OnInit() m_MainFrame->Show(); m_MainFrame->DoSettings(true); - OnArguments(); + OnArguments(parser); //compile_shader("compile_shader0.spo"); //compile_shader("compile_shader1.spo"); @@ -304,14 +320,26 @@ bool Rpcs3App::OnInit() return true; } -void Rpcs3App::OnArguments() +void Rpcs3App::OnArguments(const wxCmdLineParser& parser) { // Usage: // rpcs3-*.exe Initializes RPCS3 // rpcs3-*.exe [(S)ELF] Initializes RPCS3, then loads and runs the specified (S)ELF file. - if (Rpcs3App::argc > 1) { - Emu.SetPath(fmt::ToUTF8(argv[1])); + if (parser.FoundSwitch("t")) + { + HLEExitOnStop = Ini.HLEExitOnStop.GetValue(); + Ini.HLEExitOnStop.SetValue(true); + if (parser.GetParamCount() != 1) + { + wxLogDebug(wxT("A (S)ELF file needs to be given in test mode, exiting.")); + this->Exit(); + } + } + + if (parser.GetParamCount() > 0) + { + Emu.SetPath(fmt::ToUTF8(parser.GetParam(0))); Emu.Load(); Emu.Run(); } @@ -319,6 +347,11 @@ void Rpcs3App::OnArguments() void Rpcs3App::Exit() { + if (parser.FoundSwitch("t")) + { + Ini.HLEExitOnStop.SetValue(HLEExitOnStop); + } + Emu.Stop(); Ini.Save(); diff --git a/rpcs3/rpcs3.h b/rpcs3/rpcs3.h index 77b35aa7fc..bf745cdfe1 100644 --- a/rpcs3/rpcs3.h +++ b/rpcs3/rpcs3.h @@ -3,6 +3,7 @@ #include "Emu/DbgCommand.h" #include "Utilities/Thread.h" #include +#include class CPUThread; @@ -11,11 +12,15 @@ wxDECLARE_EVENT(wxEVT_DBG_COMMAND, wxCommandEvent); class Rpcs3App : public wxApp { +private: + wxCmdLineParser parser; + // Used to restore the configuration state after a test run + bool HLEExitOnStop; public: MainFrame* m_MainFrame; virtual bool OnInit(); // RPCS3's entry point - virtual void OnArguments(); // Handle arguments: Rpcs3App::argc, Rpcs3App::argv + virtual void OnArguments(const wxCmdLineParser& parser); // Handle arguments: Rpcs3App::argc, Rpcs3App::argv virtual void Exit(); Rpcs3App(); From 3a51a6ded7be80d0e24052161167218a52e78449 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Tue, 27 Jan 2015 19:22:56 +0200 Subject: [PATCH 2/4] Revert RSXIO changes This revert fixes many games, while seeming to break none. --- rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index 96e693d4ea..a279e2b57c 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -1196,7 +1196,7 @@ s32 cellGcmCallback(vm::ptr context, u32 count) //cmd[3] = 0; // some incrementing by module value //context->current += 0x10; - if (1) + if (0) { const u32 address = context->begin; const u32 upper = offsetTable.ioAddress[address >> 20]; // 12 bits From e12cfc89deedc7046d3f5756f504a3ef920ab559 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Tue, 27 Jan 2015 21:04:40 +0200 Subject: [PATCH 3/4] 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 From 084106ced6808f3e5be4e7ef9280159152da5e80 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Wed, 28 Jan 2015 15:17:13 +0200 Subject: [PATCH 4/4] Disable DMA writes and add copyright notices --- rpcs3/Emu/RSX/RSXDMA.cpp | 3 ++- rpcs3/Emu/RSX/RSXDMA.h | 1 + rpcs3/Emu/RSX/RSXThread.cpp | 15 +++++++-------- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/rpcs3/Emu/RSX/RSXDMA.cpp b/rpcs3/Emu/RSX/RSXDMA.cpp index 476448474f..ad6bc06a74 100644 --- a/rpcs3/Emu/RSX/RSXDMA.cpp +++ b/rpcs3/Emu/RSX/RSXDMA.cpp @@ -1,3 +1,4 @@ +// Copyright (C) 2015 AlexAltea (https://github.com/AlexAltea/nucleus) #include "stdafx.h" #include "RSXDMA.h" #include "Emu/Memory/Memory.h" @@ -18,7 +19,7 @@ DMAObject dma_address(u32 dma_object) 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); + LOG_WARNING(RSX, "Unknown DMA object (0x%08x)", dma_object); return DMAObject{}; } } diff --git a/rpcs3/Emu/RSX/RSXDMA.h b/rpcs3/Emu/RSX/RSXDMA.h index b432375506..e5da8918eb 100644 --- a/rpcs3/Emu/RSX/RSXDMA.h +++ b/rpcs3/Emu/RSX/RSXDMA.h @@ -1,3 +1,4 @@ +// Copyright (C) 2015 AlexAltea (https://github.com/AlexAltea/nucleus) #pragma once enum { diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index ed7b539005..d4041f8571 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -1866,15 +1866,14 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const // Get timestamp, and convert it from microseconds to nanoseconds 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) - // 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); + // NOTE: DMA broken, implement proper lpar mapping (sys_rsx) + //dma_write64(dma_report, offset + 0x0, timestamp); + //dma_write32(dma_report, offset + 0x8, value); + //dma_write32(dma_report, offset + 0xc, 0); - dma_write64(dma_report, offset + 0x0, timestamp); - dma_write32(dma_report, offset + 0x8, value); - dma_write32(dma_report, offset + 0xc, 0); + 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); } break;