diff --git a/rpcs3/Emu/RSX/RSXDMA.cpp b/rpcs3/Emu/RSX/RSXDMA.cpp new file mode 100644 index 0000000000..ad6bc06a74 --- /dev/null +++ b/rpcs3/Emu/RSX/RSXDMA.cpp @@ -0,0 +1,125 @@ +// Copyright (C) 2015 AlexAltea (https://github.com/AlexAltea/nucleus) +#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..e5da8918eb --- /dev/null +++ b/rpcs3/Emu/RSX/RSXDMA.h @@ -0,0 +1,46 @@ +// Copyright (C) 2015 AlexAltea (https://github.com/AlexAltea/nucleus) +#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 2c7f2086ba..961c1eb641 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" @@ -329,6 +330,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const if (ARGS(0)) { LOG_WARNING(RSX, "TODO: NV4097_SET_CONTEXT_DMA_REPORT: 0x%x", ARGS(0)); + dma_report = ARGS(0); } break; } @@ -887,9 +889,9 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_ZSTENCIL_CLEAR_VALUE: { - const u32 a0 = ARGS(0); - m_clear_s = a0 & 0xff; - m_clear_z = a0 >> 8; + const u32 value = ARGS(0); + m_clear_s = value & 0xff; + m_clear_z = value >> 8; break; } @@ -1065,7 +1067,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; @@ -1819,7 +1821,11 @@ 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: 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); + 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); diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 9732c8a418..bb6a177ab0 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/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index b128f96398..de40d05383 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -1192,7 +1192,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 diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 8864e59975..daed4a06ea 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -166,6 +166,7 @@ + @@ -417,6 +418,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index b45c4de188..0720c265c4 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -581,6 +581,9 @@ Emu\GPU\RSX + + Emu\GPU\RSX + Emu\GPU\RSX @@ -667,7 +670,7 @@ Emu\CPU\ARMv7 - + Emu\CPU\ARMv7 @@ -693,7 +696,7 @@ Emu\CPU\ARMv7\Modules - Emu\CPU\ARMv7\Modules + Emu\CPU\ARMv7\Modules Emu\CPU\ARMv7\Modules @@ -1345,6 +1348,9 @@ Emu\GPU\RSX + + Emu\GPU\RSX + Emu\GPU\RSX @@ -1473,7 +1479,7 @@ Emu\CPU\ARMv7\Modules - + Emu\CPU\ARMv7 @@ -1484,7 +1490,7 @@ Emu\CPU\ARMv7\Objects - Emu\CPU\ARMv7\Modules + Emu\CPU\ARMv7\Modules Emu\CPU\ARMv7\Modules 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();