diff --git a/rpcs3/Emu/FS/VFS.cpp b/rpcs3/Emu/FS/VFS.cpp index 148a6b15eb..e73832909e 100644 --- a/rpcs3/Emu/FS/VFS.cpp +++ b/rpcs3/Emu/FS/VFS.cpp @@ -176,6 +176,11 @@ void VFS::SaveLoadDevices(Array& res, bool is_load) res[idx].mount = "/dev_hdd1/"; res[idx].device = vfsDevice_LocalFile; + idx = res.Move(new VFSManagerEntry()); + res[idx].path = "$(EmulatorDir)\\dev_flash\\"; + res[idx].mount = "/dev_flash/"; + res[idx].device = vfsDevice_LocalFile; + idx = res.Move(new VFSManagerEntry()); res[idx].path = "$(EmulatorDir)\\dev_usb000\\"; res[idx].mount = "/dev_usb000/"; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp index fce3c5960f..81a16f804c 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp @@ -527,6 +527,109 @@ int cellMsgDialogOpen2(u32 type, char* msgString, u32 callback_addr, u32 userDat return CELL_OK; } +int cellMsgDialogOpenErrorCode(u32 errorCode, u32 callback_addr, u32 userData, u32 extParam) +{ + cellSysutil.Warning("cellMsgDialogOpenErrorCode(errorCode=0x%x, callback_addr=0x%x, userData=%d, extParam=%d)", + errorCode, callback_addr, userData, extParam); + + std::string errorMessage; + switch(errorCode) + { + // Generic errors + case 0x80010001: errorMessage = "The resource is temporarily unavailable."; break; + case 0x80010002: errorMessage = "Invalid argument or flag."; break; + case 0x80010003: errorMessage = "The feature is not yet implemented."; break; + case 0x80010004: errorMessage = "Memory allocation failed."; break; + case 0x80010005: errorMessage = "The resource with the specified identifier does not exist."; break; + case 0x80010006: errorMessage = "The file does not exist."; break; + case 0x80010007: errorMessage = "The file is in unrecognized format / The file is not a valid ELF file."; break; + case 0x80010008: errorMessage = "Resource deadlock is avoided."; break; + case 0x80010009: errorMessage = "Operation not permitted."; break; + case 0x8001000A: errorMessage = "The device or resource is bus."; break; + case 0x8001000B: errorMessage = "The operation is timed ou."; break; + case 0x8001000C: errorMessage = "The operation is aborte."; break; + case 0x8001000D: errorMessage = "Invalid memory access."; break; + case 0x8001000F: errorMessage = "State of the target thread is invalid."; break; + case 0x80010010: errorMessage = "Alignment is invalid."; break; + case 0x80010011: errorMessage = "Shortage of the kernel resources."; break; + case 0x80010012: errorMessage = "The file is a directory."; break; + case 0x80010013: errorMessage = "Operation canceled."; break; + case 0x80010014: errorMessage = "Entry already exists."; break; + case 0x80010015: errorMessage = "Port is already connected."; break; + case 0x80010016: errorMessage = "Port is not connected."; break; + case 0x80010017: errorMessage = "Failure in authorizing SELF. Program authentication fail."; break; + case 0x80010018: errorMessage = "The file is not MSELF."; break; + case 0x80010019: errorMessage = "System version error."; break; + case 0x8001001A: errorMessage = "Fatal system error occurred while authorizing SELF. SELF auth failure."; break; + case 0x8001001B: errorMessage = "Math domain violation."; break; + case 0x8001001C: errorMessage = "Math range violation."; break; + case 0x8001001D: errorMessage = "Illegal multi-byte sequence in input."; break; + case 0x8001001E: errorMessage = "File position error."; break; + case 0x8001001F: errorMessage = "Syscall was interrupted."; break; + case 0x80010020: errorMessage = "File too large."; break; + case 0x80010021: errorMessage = "Too many links."; break; + case 0x80010022: errorMessage = "File table overflow."; break; + case 0x80010023: errorMessage = "No space left on device."; break; + case 0x80010024: errorMessage = "Not a TTY."; break; + case 0x80010025: errorMessage = "Broken pipe."; break; + case 0x80010026: errorMessage = "Read-only filesystem."; break; + case 0x80010027: errorMessage = "Illegal seek."; break; + case 0x80010028: errorMessage = "Arg list too long."; break; + case 0x80010029: errorMessage = "Access violation."; break; + case 0x8001002A: errorMessage = "Invalid file descriptor."; break; + case 0x8001002B: errorMessage = "Filesystem mounting failed."; break; + case 0x8001002C: errorMessage = "Too many files open."; break; + case 0x8001002D: errorMessage = "No device."; break; + case 0x8001002E: errorMessage = "Not a directory."; break; + case 0x8001002F: errorMessage = "No such device or IO."; break; + case 0x80010030: errorMessage = "Cross-device link error."; break; + case 0x80010031: errorMessage = "Bad Message."; break; + case 0x80010032: errorMessage = "In progress."; break; + case 0x80010033: errorMessage = "Message size error."; break; + case 0x80010034: errorMessage = "Name too long."; break; + case 0x80010035: errorMessage = "No lock."; break; + case 0x80010036: errorMessage = "Not empty."; break; + case 0x80010037: errorMessage = "Not supported."; break; + case 0x80010038: errorMessage = "File-system specific error."; break; + case 0x80010039: errorMessage = "Overflow occured."; break; + case 0x8001003A: errorMessage = "Filesystem not mounted."; break; + case 0x8001003B: errorMessage = "Not SData."; break; + case 0x8001003C: errorMessage = "Incorrect version in sys_load_param."; break; + case 0x8001003D: errorMessage = "Pointer is null."; break; + case 0x8001003E: errorMessage = "Pointer is null."; break; + default: errorMessage = "An error has occurred."; break; + } + + char errorCodeHex [9]; + sprintf(errorCodeHex, "%08x", errorCode); + errorMessage.append("\n("); + errorMessage.append(errorCodeHex); + errorMessage.append(")\n"); + + u64 status; + int res = wxMessageBox(errorMessage, wxGetApp().GetAppName(), wxICON_ERROR | wxOK); + switch(res) + { + case wxOK: status = CELL_MSGDIALOG_BUTTON_OK; break; + default: + if(res) + { + status = CELL_MSGDIALOG_BUTTON_INVALID; + break; + } + + status = CELL_MSGDIALOG_BUTTON_NONE; + break; + } + + // TODO: The following lines produce an infinite loop of cellMsgDialogOpenErrorCode's + /*Callback2 callback(0, callback_addr, userData); + callback.Handle(status); + callback.Branch(true);*/ + + return CELL_OK; +} + int cellAudioOutGetSoundAvailability(u32 audioOut, u32 type, u32 fs, u32 option) { @@ -794,6 +897,7 @@ void cellSysutil_init() cellSysutil.AddFunc(0x02ff3c1b, cellSysutilUnregisterCallback); cellSysutil.AddFunc(0x7603d3db, cellMsgDialogOpen2); + cellSysutil.AddFunc(0x3e22cb4b, cellMsgDialogOpenErrorCode); cellSysutil.AddFunc(0xf4e3caa0, cellAudioOutGetState); cellSysutil.AddFunc(0x4692ab35, cellAudioOutConfigure); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp index 1947275a3f..7d7d866995 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp @@ -161,14 +161,17 @@ int sys_memory_get_user_memory_size(u32 mem_info_addr) return CELL_OK; } -int sys_memory_get_page_attribute(u32 addr, mem_ptr_t a) +int sys_memory_get_page_attribute(u32 addr, mem_ptr_t attr) { - sc_mem.Warning("sys_memory_get_page_attribute(addr=0x%x, attr=0x%x)", addr, a.GetAddr()); + sc_mem.Warning("sys_memory_get_page_attribute(addr=0x%x, attr_addr=0x%x)", addr, attr.GetAddr()); - a -> attribute = 0; - a -> page_size = 0; - a -> access_right = 0; - a -> pad = 0; + if (!attr.IsGood()) + return CELL_EFAULT; + + attr->attribute = 0; + attr->page_size = 0; + attr->access_right = 0; + attr->pad = 0; return CELL_OK; } \ No newline at end of file diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index f2fb857920..91dc1b0cb5 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -2,6 +2,7 @@ #include "MainFrame.h" #include "CompilerELF.h" #include "MemoryViewer.h" +#include "RSXDebugger.h" #include "git-version.h" #include "Emu/System.h" @@ -33,6 +34,7 @@ enum IDs id_config_vhdd_manager, id_tools_compiler, id_tools_memory_viewer, + id_tools_rsx_debugger, id_help_about, id_update_dbg, }; @@ -150,6 +152,7 @@ MainFrame::MainFrame() menu_tools.Append(id_tools_compiler, "ELF Compiler"); menu_tools.Append(id_tools_memory_viewer, "Memory Viewer"); + menu_tools.Append(id_tools_rsx_debugger, "RSX Debugger"); menu_help.Append(id_help_about, "About..."); @@ -158,26 +161,27 @@ MainFrame::MainFrame() m_game_viewer = new GameViewer(this); AddPane(m_game_viewer, "Game List", wxAUI_DOCK_BOTTOM); - Connect( id_boot_game, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::BootGame) ); - Connect( id_install_pkg, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::InstallPkg) ); - Connect( id_boot_elf, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::BootElf) ); + Connect( id_boot_game, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::BootGame) ); + Connect( id_install_pkg, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::InstallPkg) ); + Connect( id_boot_elf, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::BootElf) ); - Connect( id_sys_pause, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Pause) ); - Connect( id_sys_stop, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Stop) ); - Connect( id_sys_send_open_menu, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::SendOpenCloseSysMenu) ); - Connect( id_sys_send_exit, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::SendExit) ); + Connect( id_sys_pause, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Pause) ); + Connect( id_sys_stop, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Stop) ); + Connect( id_sys_send_open_menu, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::SendOpenCloseSysMenu) ); + Connect( id_sys_send_exit, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::SendExit) ); - Connect( id_config_emu, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Config) ); - Connect( id_config_pad, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::ConfigPad) ); - Connect( id_config_vfs_manager, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::ConfigVFS) ); - Connect( id_config_vhdd_manager,wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::ConfigVHDD) ); + Connect( id_config_emu, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Config) ); + Connect( id_config_pad, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::ConfigPad) ); + Connect( id_config_vfs_manager, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::ConfigVFS) ); + Connect( id_config_vhdd_manager, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::ConfigVHDD) ); - Connect( id_tools_compiler, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OpenELFCompiler)); - Connect( id_tools_memory_viewer,wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OpenMemoryViewer)); + Connect( id_tools_compiler, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OpenELFCompiler)); + Connect( id_tools_memory_viewer, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OpenMemoryViewer)); + Connect( id_tools_rsx_debugger, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OpenRSXDebugger)); - Connect( id_help_about, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::AboutDialogHandler) ); + Connect( id_help_about, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::AboutDialogHandler) ); - Connect( id_update_dbg, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::UpdateUI) ); + Connect( id_update_dbg, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::UpdateUI) ); m_app_connector.Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainFrame::OnKeyDown), (wxObject*)0, this); m_app_connector.Connect(wxEVT_DBG_COMMAND, wxCommandEventHandler(MainFrame::UpdateUI), (wxObject*)0, this); @@ -739,6 +743,11 @@ void MainFrame::OpenMemoryViewer(wxCommandEvent& WXUNUSED(event)) (new MemoryViewerPanel(this)) -> Show(); } +void MainFrame::OpenRSXDebugger(wxCommandEvent& WXUNUSED(event)) +{ + (new RSXDebugger(this)) -> Show(); +} + void MainFrame::AboutDialogHandler(wxCommandEvent& WXUNUSED(event)) { AboutDialog(this).ShowModal(); diff --git a/rpcs3/Gui/MainFrame.h b/rpcs3/Gui/MainFrame.h index b27e029ea7..ea4e1d0bce 100644 --- a/rpcs3/Gui/MainFrame.h +++ b/rpcs3/Gui/MainFrame.h @@ -32,6 +32,7 @@ private: void ConfigVHDD(wxCommandEvent& event); void OpenELFCompiler(wxCommandEvent& evt); void OpenMemoryViewer(wxCommandEvent& evt); + void OpenRSXDebugger(wxCommandEvent& evt); void AboutDialogHandler(wxCommandEvent& event); void UpdateUI(wxCommandEvent& event); void OnKeyDown(wxKeyEvent& event); diff --git a/rpcs3/Gui/RSXDebugger.cpp b/rpcs3/Gui/RSXDebugger.cpp new file mode 100644 index 0000000000..3ef1c6086e --- /dev/null +++ b/rpcs3/Gui/RSXDebugger.cpp @@ -0,0 +1,385 @@ +#include "stdafx.h" +#include "RSXDebugger.h" +#include "Emu/Memory/Memory.h" +#include "Emu/GS/sysutil_video.h" + +const char* s_rsx_flags [] = { + "Alpha test", + "Blend", + "Cull face", + "Depth bounds test", + "Depth test", + "Dither", + "Line smooth", + "Logic op", + "Poly smooth", + "Poly offset fill", + "Poly offset line", + "Poly offset point", + "Stencil test", +}; + +RSXDebugger::RSXDebugger(wxWindow* parent) + : wxFrame(parent, wxID_ANY, "RSX Debugger", wxDefaultPosition, wxSize(700, 450)) + , m_item_count(23) +{ + exit = false; + m_addr = 0x0; + m_colcount = 16; + + this->SetBackgroundColour(wxColour(240,240,240)); //This fix the ugly background color under Windows + wxBoxSizer& s_panel = *new wxBoxSizer(wxHORIZONTAL); + + //Tools + wxBoxSizer& s_tools = *new wxBoxSizer(wxVERTICAL); + + //Controls: Memory Viewer Options + wxStaticBoxSizer& s_controls = *new wxStaticBoxSizer(wxHORIZONTAL, this, "Memory Viewer Options"); + + wxStaticBoxSizer& s_controls_addr = *new wxStaticBoxSizer(wxHORIZONTAL, this, "Address:"); + t_addr = new wxTextCtrl(this, wxID_ANY, "00000000", wxDefaultPosition, wxSize(60,-1)); + t_addr->SetMaxLength(8); + s_controls_addr.Add(t_addr); + + wxStaticBoxSizer& s_controls_goto = *new wxStaticBoxSizer(wxHORIZONTAL, this, "Go to:"); + wxButton* b_goto_get = new wxButton(this, wxID_ANY, "Get", wxDefaultPosition, wxSize(40,-1)); + wxButton* b_goto_put = new wxButton(this, wxID_ANY, "Put", wxDefaultPosition, wxSize(40,-1)); + s_controls_goto.Add(b_goto_get); + s_controls_goto.Add(b_goto_put); + + //Controls: Breaks + wxStaticBoxSizer& s_controls_breaks = *new wxStaticBoxSizer(wxHORIZONTAL, this, "Break on:"); + wxButton* b_break_frame = new wxButton(this, wxID_ANY, "Frame", wxDefaultPosition, wxSize(60,-1)); + wxButton* b_break_text = new wxButton(this, wxID_ANY, "Texture", wxDefaultPosition, wxSize(60,-1)); + wxButton* b_break_draw = new wxButton(this, wxID_ANY, "Draw", wxDefaultPosition, wxSize(60,-1)); + wxButton* b_break_prim = new wxButton(this, wxID_ANY, "Primitive", wxDefaultPosition, wxSize(60,-1)); + wxButton* b_break_inst = new wxButton(this, wxID_ANY, "Command", wxDefaultPosition, wxSize(60,-1)); + s_controls_breaks.Add(b_break_frame); + s_controls_breaks.Add(b_break_text); + s_controls_breaks.Add(b_break_draw); + s_controls_breaks.Add(b_break_prim); + s_controls_breaks.Add(b_break_inst); + + // TODO: This feature is not yet implemented + b_break_frame->Disable(); + b_break_text->Disable(); + b_break_draw->Disable(); + b_break_prim->Disable(); + b_break_inst->Disable(); + + s_controls.Add(&s_controls_addr); + s_controls.Add(&s_controls_goto); + s_controls.Add(&s_controls_breaks); + + //Tabs + wxNotebook* nb_rsx = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxSize(482,475)); + wxPanel* p_commands = new wxPanel(nb_rsx, wxID_ANY); + wxPanel* p_flags = new wxPanel(nb_rsx, wxID_ANY); + wxPanel* p_lightning = new wxPanel(nb_rsx, wxID_ANY); + wxPanel* p_texture = new wxPanel(nb_rsx, wxID_ANY); + wxPanel* p_settings = new wxPanel(nb_rsx, wxID_ANY); + + nb_rsx->AddPage(p_commands, wxT("RSX Commands")); + nb_rsx->AddPage(p_flags, wxT("Flags")); + nb_rsx->AddPage(p_lightning, wxT("Lightning")); + nb_rsx->AddPage(p_texture, wxT("Texture")); + nb_rsx->AddPage(p_settings, wxT("Settings")); + + //Tabs: Lists + m_list_commands = new wxListView(p_commands, wxID_ANY, wxPoint(1,3), wxSize(470,444)); + m_list_flags = new wxListView(p_flags, wxID_ANY, wxPoint(1,3), wxSize(470,444)); + m_list_lightning = new wxListView(p_lightning, wxID_ANY, wxPoint(1,3), wxSize(470,444)); + m_list_texture = new wxListView(p_texture, wxID_ANY, wxPoint(1,3), wxSize(470,444)); + m_list_settings = new wxListView(p_settings, wxID_ANY, wxPoint(1,3), wxSize(470,444)); + + //Tabs: List Style + m_list_commands ->SetFont(wxFont(8, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)); + m_list_flags ->SetFont(wxFont(8, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)); + m_list_lightning->SetFont(wxFont(8, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)); + m_list_texture ->SetFont(wxFont(8, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)); + m_list_settings ->SetFont(wxFont(8, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)); + + //Tabs: List Columns + m_list_commands->InsertColumn(0, "Address", 0, 100); + m_list_commands->InsertColumn(1, "Value", 0, 100); + m_list_commands->InsertColumn(2, "Command", 0, 250); + m_list_flags->InsertColumn(0, "Name", 0, 150); + m_list_flags->InsertColumn(1, "Value", 0, 300); + m_list_lightning->InsertColumn(0, "Name"); + m_list_lightning->InsertColumn(1, "Value"); + m_list_texture->InsertColumn(0, "Name"); + m_list_texture->InsertColumn(1, "Value"); + m_list_settings->InsertColumn(0, "Name"); + m_list_settings->InsertColumn(1, "Value"); + + for(u32 i=0; iInsertItem(m_list_commands->GetItemCount(), wxEmptyString); + } + + for(u32 i=0; i < sizeof(s_rsx_flags)/sizeof(s_rsx_flags[0]); i++) + { + m_list_flags->InsertItem(m_list_flags->GetItemCount(), s_rsx_flags[i]); + } + + //Tools: Tools = Memory Viewer Options + Raw Image Preview Options + Buttons + s_tools.AddSpacer(10); + s_tools.Add(&s_controls); + s_tools.AddSpacer(10); + s_tools.Add(nb_rsx); + s_tools.AddSpacer(10); + + //Buffers + wxBoxSizer& s_buffers1 = *new wxBoxSizer(wxVERTICAL); + wxBoxSizer& s_buffers2 = *new wxBoxSizer(wxVERTICAL); + wxStaticBoxSizer& s_buffers_colorA = *new wxStaticBoxSizer(wxHORIZONTAL, this, "Color Buffer A"); + wxStaticBoxSizer& s_buffers_colorB = *new wxStaticBoxSizer(wxHORIZONTAL, this, "Color Buffer B"); + wxStaticBoxSizer& s_buffers_colorC = *new wxStaticBoxSizer(wxHORIZONTAL, this, "Color Buffer C"); + wxStaticBoxSizer& s_buffers_colorD = *new wxStaticBoxSizer(wxHORIZONTAL, this, "Color Buffer D"); + wxStaticBoxSizer& s_buffers_depth = *new wxStaticBoxSizer(wxHORIZONTAL, this, "Depth Buffer"); + wxStaticBoxSizer& s_buffers_stencil = *new wxStaticBoxSizer(wxHORIZONTAL, this, "Stencil Buffer"); + wxStaticBoxSizer& s_buffers_text = *new wxStaticBoxSizer(wxHORIZONTAL, this, "Texture"); + + //Buffers and textures + CellVideoOutResolution res = ResolutionTable[ResolutionIdToNum(Ini.GSResolution.GetValue())]; + m_buffers_width = res.width; + m_buffers_height = res.height; + m_panel_width = (m_buffers_width*108)/m_buffers_height; + m_panel_height = 108; + m_text_width = 108; + m_text_height = 108; + + //Panels for displaying the buffers + p_buffer_colorA = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(m_panel_width, m_panel_height)); + p_buffer_colorB = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(m_panel_width, m_panel_height)); + p_buffer_colorC = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(m_panel_width, m_panel_height)); + p_buffer_colorD = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(m_panel_width, m_panel_height)); + p_buffer_depth = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(m_panel_width, m_panel_height)); + p_buffer_stencil = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(m_panel_width, m_panel_height)); + p_buffer_text = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(m_text_width, m_text_height)); + s_buffers_colorA.Add(p_buffer_colorA); + s_buffers_colorB.Add(p_buffer_colorB); + s_buffers_colorC.Add(p_buffer_colorC); + s_buffers_colorD.Add(p_buffer_colorD); + s_buffers_depth.Add(p_buffer_depth); + s_buffers_stencil.Add(p_buffer_stencil); + s_buffers_text.Add(p_buffer_text); + + //Merge and display everything + s_buffers1.AddSpacer(10); + s_buffers1.Add(&s_buffers_colorA); + s_buffers1.AddSpacer(10); + s_buffers1.Add(&s_buffers_colorC); + s_buffers1.AddSpacer(10); + s_buffers1.Add(&s_buffers_depth); + s_buffers1.AddSpacer(10); + s_buffers1.Add(&s_buffers_text); + s_buffers1.AddSpacer(10); + + s_buffers2.AddSpacer(10); + s_buffers2.Add(&s_buffers_colorB); + s_buffers2.AddSpacer(10); + s_buffers2.Add(&s_buffers_colorD); + s_buffers2.AddSpacer(10); + s_buffers2.Add(&s_buffers_stencil); + s_buffers2.AddSpacer(10); + + s_panel.AddSpacer(10); + s_panel.Add(&s_tools); + s_panel.AddSpacer(10); + s_panel.Add(&s_buffers1); + s_panel.AddSpacer(10); + s_panel.Add(&s_buffers2); + s_panel.AddSpacer(10); + SetSizerAndFit(&s_panel); + + //Events + Connect(wxID_ANY, wxEVT_KEY_DOWN, wxKeyEventHandler(RSXDebugger::OnKeyDown), NULL, this); + Connect(t_addr->GetId(), wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(RSXDebugger::OnChangeToolsAddr)); + + Connect(b_goto_get->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(RSXDebugger::GoToGet)); + Connect(b_goto_put->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(RSXDebugger::GoToPut)); + + m_list_commands->Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler(RSXDebugger::OnScrollMemory), NULL, this); + m_list_flags->Connect(wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler(RSXDebugger::ModifyFlags), NULL, this); + + //Fill the frame + UpdateInformation(); +}; + +void RSXDebugger::OnKeyDown(wxKeyEvent& event) +{ + switch(event.GetKeyCode()) + { + case WXK_F5: UpdateInformation(); break; + } +} + +void RSXDebugger::OnChangeToolsAddr(wxCommandEvent& event) +{ + t_addr->GetValue().ToULong((unsigned long *)&m_addr, 16); + t_addr->SetValue(wxString::Format("%08x", m_addr)); + UpdateInformation(); + event.Skip(); +} + +void RSXDebugger::OnScrollMemory(wxMouseEvent& event) +{ + m_addr -= (event.ControlDown() ? m_item_count : 1) * 4 * (event.GetWheelRotation() / event.GetWheelDelta()); + t_addr->SetValue(wxString::Format("%08x", m_addr)); + UpdateInformation(); + event.Skip(); +} + +void RSXDebugger::GoToGet(wxCommandEvent& event) +{ + if (!RSXReady()) return; + CellGcmControl* ctrl = (CellGcmControl*)&Memory[Emu.GetGSManager().GetRender().m_ctrlAddress]; + m_addr = Emu.GetGSManager().GetRender().m_ioAddress + re(ctrl->get); + t_addr->SetValue(wxString::Format("%08x", m_addr)); + UpdateInformation(); + event.Skip(); +} + +void RSXDebugger::GoToPut(wxCommandEvent& event) +{ + if (!RSXReady()) return; + CellGcmControl* ctrl = (CellGcmControl*)&Memory[Emu.GetGSManager().GetRender().m_ctrlAddress]; + m_addr = Emu.GetGSManager().GetRender().m_ioAddress + re(ctrl->put); + t_addr->SetValue(wxString::Format("%08x", m_addr)); + UpdateInformation(); + event.Skip(); +} + +void RSXDebugger::UpdateInformation() +{ + ShowMemory(); + ShowBuffers(); + ShowFlags(); + this->SetFocus(); +} + +void RSXDebugger::ShowMemory() +{ + for(u32 i=0; iSetItem(i, 0, wxString::Format("%08x", addr)); + + if (Memory.IsGoodAddr(addr)) + { + u32 cmd = Memory.Read32(addr); + m_list_commands->SetItem(i, 1, wxString::Format("%08x", cmd)); + } + else + { + m_list_commands->SetItem(i, 1, "????????"); + } + } +} + +void RSXDebugger::ShowBuffers() +{ + // TODO: This is a *very* ugly way of checking if m_render was initialized. It throws an error while debugging with VS + const GSRender& render = Emu.GetGSManager().GetRender(); + if (!&render) + return; + + // TODO: Currently it only supports color buffers + for (u32 bufferId=0; bufferId < render.m_gcm_buffers_count; bufferId++) + { + gcmBuffer* buffers = (gcmBuffer*)Memory.GetMemFromAddr(render.m_gcm_buffers_addr); + u32 RSXbuffer_addr = render.m_local_mem_addr + re(buffers[bufferId].offset); + unsigned char* RSXbuffer = (unsigned char*)Memory.VirtualToRealAddr(RSXbuffer_addr); + + u32 width = re(buffers[bufferId].width); + u32 height = re(buffers[bufferId].height); + unsigned char* buffer = (unsigned char*)malloc(width * height * 3); + + //ABGR to RGB and flip vertically + for (u32 y=0; yGetItemCount(); i++) + { + m_list_flags->SetItem(i, 1, "N/A"); + } + return; + } + const GSRender& render = Emu.GetGSManager().GetRender(); + int i=0; + m_list_flags->SetItem(i++, 1, render.m_set_alpha_test ? "Enabled" : "Disabled"); + m_list_flags->SetItem(i++, 1, render.m_set_blend ? "Enabled" : "Disabled"); + m_list_flags->SetItem(i++, 1, render.m_set_cull_face_enable ? "Enabled" : "Disabled"); + m_list_flags->SetItem(i++, 1, render.m_set_depth_bounds_test ? "Enabled" : "Disabled"); + m_list_flags->SetItem(i++, 1, render.m_depth_test_enable ? "Enabled" : "Disabled"); + m_list_flags->SetItem(i++, 1, render.m_set_dither ? "Enabled" : "Disabled"); + m_list_flags->SetItem(i++, 1, render.m_set_line_smooth ? "Enabled" : "Disabled"); + m_list_flags->SetItem(i++, 1, render.m_set_logic_op ? "Enabled" : "Disabled"); + m_list_flags->SetItem(i++, 1, render.m_set_poly_smooth ? "Enabled" : "Disabled"); + m_list_flags->SetItem(i++, 1, render.m_set_poly_offset_fill ? "Enabled" : "Disabled"); + m_list_flags->SetItem(i++, 1, render.m_set_poly_offset_line ? "Enabled" : "Disabled"); + m_list_flags->SetItem(i++, 1, render.m_set_poly_offset_point ? "Enabled" : "Disabled"); + m_list_flags->SetItem(i++, 1, render.m_set_stencil_test ? "Enabled" : "Disabled"); +} + +void RSXDebugger::ModifyFlags(wxListEvent& event) +{ + if (!RSXReady()) return; + GSRender& render = Emu.GetGSManager().GetRender(); + switch(event.m_itemIndex) + { + case 0: render.m_set_alpha_test ^= true; break; + case 1: render.m_set_blend ^= true; break; + case 2: render.m_set_cull_face_enable ^= true; break; + case 3: render.m_set_depth_bounds_test ^= true; break; + case 4: render.m_depth_test_enable ^= true; break; + case 5: render.m_set_dither ^= true; break; + case 6: render.m_set_line_smooth ^= true; break; + case 7: render.m_set_logic_op ^= true; break; + case 8: render.m_set_poly_smooth ^= true; break; + case 9: render.m_set_poly_offset_fill ^= true; break; + case 10: render.m_set_poly_offset_line ^= true; break; + case 11: render.m_set_poly_offset_point ^= true; break; + case 12: render.m_set_stencil_test ^= true; break; + } + UpdateInformation(); +} + +bool RSXDebugger::RSXReady() +{ + // TODO: This is a *very* ugly way of checking if m_render was initialized. It throws an error while debugging in VS + const GSRender& render = Emu.GetGSManager().GetRender(); + if (!&render) + { + return false; + } + return true; +} + diff --git a/rpcs3/Gui/RSXDebugger.h b/rpcs3/Gui/RSXDebugger.h new file mode 100644 index 0000000000..2460149bec --- /dev/null +++ b/rpcs3/Gui/RSXDebugger.h @@ -0,0 +1,59 @@ +#pragma once + +#include + +class RSXDebugger : public wxFrame +{ + u32 m_addr; + u32 m_colcount; + u32 m_rowcount; + + u32 m_buffers_width; + u32 m_buffers_height; + u32 m_panel_width; + u32 m_panel_height; + u32 m_text_width; + u32 m_text_height; + + wxTextCtrl* t_addr; + + u32 m_item_count; + wxListView* m_list_commands; + wxListView* m_list_flags; + wxListView* m_list_lightning; + wxListView* m_list_texture; + wxListView* m_list_settings; + + wxPanel* p_buffer_colorA; + wxPanel* p_buffer_colorB; + wxPanel* p_buffer_colorC; + wxPanel* p_buffer_colorD; + wxPanel* p_buffer_depth; + wxPanel* p_buffer_stencil; + wxPanel* p_buffer_text; + +public: + bool exit; + RSXDebugger(wxWindow* parent); + ~RSXDebugger() + { + exit = true; + } + + virtual void OnKeyDown(wxKeyEvent& event); + virtual void OnChangeToolsAddr(wxCommandEvent& event); + virtual void OnScrollMemory(wxMouseEvent& event); + + virtual void GoToGet(wxCommandEvent& event); + virtual void GoToPut(wxCommandEvent& event); + + virtual void UpdateInformation(); + virtual void ShowMemory(); + virtual void ShowBuffers(); + virtual void ShowFlags(); + + virtual void ModifyFlags(wxListEvent& event); + + bool RSXReady(); + void SetPC(const uint pc) { m_addr = pc; } +}; diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index 64533cf4a3..a5869454e0 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -1,4 +1,4 @@ - + @@ -291,6 +291,7 @@ + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index d9cf039b7b..18a4935b1e 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -358,6 +358,9 @@ Emu\Audio + + Gui +