diff --git a/Utilities/AutoPause.cpp b/Utilities/AutoPause.cpp index ad7e3ddd80..5182d91aad 100644 --- a/Utilities/AutoPause.cpp +++ b/Utilities/AutoPause.cpp @@ -23,7 +23,7 @@ AutoPause::AutoPause(void) m_pause_syscall.reserve(16); initialized = false; //Reload(false, false); - Reload(true, true); //Temporarily use auto enable + Reload(); } //Notice: I would not allow to write the binary to file in this command. @@ -79,17 +79,11 @@ void AutoPause::Reload(void) { LOG_WARNING(HLE, "No Pause ID specified in pause.bin, Auto-Pause would not act."); } - + m_pause_syscall_enable = Ini.DBGAutoPauseSystemCall.GetValue(); + m_pause_function_enable = Ini.DBGAutoPauseFunctionCall.GetValue(); initialized = true; } -void AutoPause::Reload(bool enable_pause_syscall, bool enable_pause_function) -{ - Reload(); - m_pause_syscall_enable = enable_pause_syscall; - m_pause_function_enable = enable_pause_function; -} - void AutoPause::TryPause(u32 code) { if (code < 1024) { diff --git a/Utilities/AutoPause.h b/Utilities/AutoPause.h index b62ed47eb9..208097a55d 100644 --- a/Utilities/AutoPause.h +++ b/Utilities/AutoPause.h @@ -20,8 +20,6 @@ namespace Debug { public: static AutoPause& getInstance(void); - void Reload(bool enable_pause_syscall, bool enable_pause_function); - void Reload(void); void TryPause(u32 code); diff --git a/rpcs3/Gui/AutoPauseManager.cpp b/rpcs3/Gui/AutoPauseManager.cpp new file mode 100644 index 0000000000..9faebb5cc3 --- /dev/null +++ b/rpcs3/Gui/AutoPauseManager.cpp @@ -0,0 +1,302 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "AutoPauseManager.h" + +enum +{ + id_add, + id_remove, + id_config +}; + +//TODO::Get the enable configuration from ini. +AutoPauseManagerDialog::AutoPauseManagerDialog(wxWindow* parent) + : wxDialog(parent, wxID_ANY, "Auto-Pause Manager") +{ + SetSizeHints(wxSize(400, 300), wxDefaultSize); + + wxBoxSizer* s_main = new wxBoxSizer(wxVERTICAL); + + m_entry_convert.clear(); + m_entry_convert.str(""); + m_entry_convert << "To use Auto-Pause: need the IDs of Function call or System call. Need Restart game." + << " Disable/enable using setting Misc."; + + wxStaticText* s_description = new wxStaticText(this, wxID_ANY, m_entry_convert.str(),wxDefaultPosition, wxDefaultSize, 0); + s_description->Wrap(400); + s_main->Add(s_description, 0, wxALL, 5); + + m_list = new wxListView(this); + m_list->InsertColumn(0, "Call ID"); + m_list->InsertColumn(1, "Type"); + + m_list->Bind(wxEVT_LIST_ITEM_ACTIVATED, &AutoPauseManagerDialog::OnEntryConfig, this); + m_list->Bind(wxEVT_RIGHT_DOWN, &AutoPauseManagerDialog::OnRightClick, this); + + s_main->Add(m_list, 1, wxALL | wxEXPAND, 5); + + wxBoxSizer* s_action = new wxBoxSizer(wxHORIZONTAL); + + s_action->Add(new wxButton(this, wxID_CLEAR, wxT("Cl&ear"), wxDefaultPosition, wxDefaultSize, 0), 0, wxALL, 5); + s_action->Add(new wxButton(this, wxID_REFRESH, wxT("&Reload"), wxDefaultPosition, wxDefaultSize, 0), 1, wxALL, 5); + s_action->Add(new wxButton(this, wxID_SAVE, wxT("&Save"), wxDefaultPosition, wxDefaultSize, 0), 2, wxALL, 5); + s_action->Add(new wxButton(this, wxID_CANCEL, wxT("&Close"), wxDefaultPosition, wxDefaultSize, 0), 3, wxALL, 5); + + s_main->Add(s_action, 2, wxALL, 5); + + Bind(wxEVT_MENU, &AutoPauseManagerDialog::OnAdd, this, id_add); + Bind(wxEVT_MENU, &AutoPauseManagerDialog::OnRemove, this, id_remove); + Bind(wxEVT_MENU, &AutoPauseManagerDialog::OnEntryConfig, this, id_config); + + Bind(wxEVT_BUTTON, &AutoPauseManagerDialog::OnClear, this, wxID_CLEAR); + Bind(wxEVT_BUTTON, &AutoPauseManagerDialog::OnReload, this, wxID_REFRESH); + Bind(wxEVT_BUTTON, &AutoPauseManagerDialog::OnSave, this, wxID_SAVE); + //Bind(wxEVT_BUTTON, &AutoPauseManagerDialog::OnClose, this, wxID_CLOSE); + + Emu.Stop(); + + LoadEntries(); + UpdateList(); + + SetSizerAndFit(s_main); + SetSize(wxSize(400, 360)); + Layout(); + Centre(wxBOTH); +} + +//Copied some from AutoPause. +void AutoPauseManagerDialog::LoadEntries(void) +{ + m_entries.clear(); + m_entries.reserve(16); + + if (rExists("pause.bin")) + { + rFile list; + list.Open("pause.bin", rFile::read); + //System calls ID and Function calls ID are all u32 iirc. + u32 num; + size_t fmax = list.Length(); + size_t fcur = 0; + list.Seek(0); + while (fcur <= fmax - sizeof(u32)) + { + list.Read(&num, sizeof(u32)); + fcur += sizeof(u32); + if (num == 0xFFFFFFFF) break; + + m_entries.emplace_back(num); + } + list.Close(); + } +} + +//Copied some from AutoPause. +//Tip: This one doesn't check for the file is being read or not. +//This would always use a 0xFFFFFFFF as end of the pause.bin +void AutoPauseManagerDialog::SaveEntries(void) +{ + if (rExists("pause.bin")) + { + rRemoveFile("pause.bin"); + } + rFile list; + list.Open("pause.bin", rFile::write); + //System calls ID and Function calls ID are all u32 iirc. + u32 num = 0; + list.Seek(0); + for (size_t i = 0; i < m_entries.size(); ++i) + { + if (num == 0xFFFFFFFF) continue; + num = m_entries[i]; + list.Write(&num, sizeof(u32)); + } + num = 0xFFFFFFFF; + list.Write(&num, sizeof(u32)); + list.Close(); +} + +void AutoPauseManagerDialog::UpdateList(void) +{ + m_list->Freeze(); + m_list->DeleteAllItems(); + for (size_t i = 0; i < m_entries.size(); ++i) + { + m_list->InsertItem(i, i); + if (m_entries[i] != 0xFFFFFFFF) + { + m_entry_convert.clear(); + m_entry_convert.str(""); + m_entry_convert << std::hex << std::setw(8) << std::setfill('0') << m_entries[i]; + m_list->SetItem(i, 0, m_entry_convert.str()); + } + else + { + m_list->SetItem(i, 0, "Unset"); + } + + if (m_entries[i] < 1024) + { + m_list->SetItem(i, 1, "System Call"); + } + else + { + m_list->SetItem(i, 1, "Function Call"); + } + } + m_list->SetColumnWidth(0, wxLIST_AUTOSIZE_USEHEADER); + m_list->SetColumnWidth(1, wxLIST_AUTOSIZE_USEHEADER); + m_list->Thaw(); +} + +void AutoPauseManagerDialog::OnEntryConfig(wxCommandEvent& event) +{ + int idx = m_list->GetFirstSelected(); + if (idx != wxNOT_FOUND) + { + AutoPauseSettingsDialog(this, &m_entries[idx]).ShowModal(); + UpdateList(); + } +} + +void AutoPauseManagerDialog::OnRightClick(wxMouseEvent& event) +{ + wxMenu* menu = new wxMenu(); + int idx = m_list->GetFirstSelected(); + + menu->Append(id_add, "&Add"); + menu->Append(id_remove, "&Remove")->Enable(idx != wxNOT_FOUND); + menu->AppendSeparator(); + menu->Append(id_config, "&Config")->Enable(idx != wxNOT_FOUND); + + PopupMenu(menu); +} + +void AutoPauseManagerDialog::OnAdd(wxCommandEvent& event) +{ + m_entries.emplace_back(0xFFFFFFFF); + UpdateList(); + + u32 idx = m_entries.size() - 1; + for (int i = 0; i < m_list->GetItemCount(); ++i) + { + m_list->SetItemState(i, i == idx ? wxLIST_STATE_SELECTED : ~wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); + } + + wxCommandEvent ce; + OnEntryConfig(ce); +} + +void AutoPauseManagerDialog::OnRemove(wxCommandEvent& event) +{ + for (int sel = m_list->GetNextSelected(-1), offs = 0; sel != wxNOT_FOUND; sel = m_list->GetNextSelected(sel), --offs) + { + m_entries.erase(m_entries.begin() + (sel + offs)); + } + UpdateList(); +} + +void AutoPauseManagerDialog::OnSave(wxCommandEvent& event) +{ + SaveEntries(); + LOG_SUCCESS(HLE,"Auto-Pause: File pause.bin was updated."); + //event.Skip(); +} + +void AutoPauseManagerDialog::OnClear(wxCommandEvent& event) +{ + m_entries.clear(); + UpdateList(); +} + +void AutoPauseManagerDialog::OnReload(wxCommandEvent& event) +{ + LoadEntries(); + UpdateList(); +} + +AutoPauseSettingsDialog::AutoPauseSettingsDialog(wxWindow* parent, u32 *entry) + : wxDialog(parent, wxID_ANY, "Auto-Pause Setting") + , m_presult(entry) +{ + m_entry = *m_presult; + SetSizeHints(wxSize(400, -1), wxDefaultSize); + + wxBoxSizer* s_main = new wxBoxSizer(wxVERTICAL); + + m_entry_convert.clear(); + m_entry_convert.str(""); + m_entry_convert << "Specify ID of System Call or Function Call below." + << " Please remember give the Hexidemical id."; + + wxStaticText* s_description = new wxStaticText(this, wxID_ANY, m_entry_convert.str(), wxDefaultPosition, wxDefaultSize, 0); + s_description->Wrap(400); + s_main->Add(s_description, 0, wxALL, 5); + + wxBoxSizer* s_config = new wxBoxSizer(wxHORIZONTAL); + + m_id = new wxTextCtrl(this, wxID_STATIC, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0); + s_config->Add(m_id, 0, wxALL | wxEXPAND, 5); + s_config->Add(new wxButton(this, wxID_OK, wxT("&OK"), wxDefaultPosition, wxDefaultSize, 0), 1, wxALL, 5); + s_config->Add(new wxButton(this, wxID_CANCEL, wxT("&Cancel"), wxDefaultPosition, wxDefaultSize, 0), 1, wxALL, 5); + + s_main->Add(s_config, 1, wxEXPAND, 5); + + m_current_converted = new wxStaticText(this, wxID_ANY, wxT("Currently it gets an id of \"Unset\"."), wxDefaultPosition, wxDefaultSize, 0); + s_main->Add(m_current_converted, 2, wxALL | wxEXPAND, 5); + + m_entry_convert.clear(); + m_entry_convert.str(""); + m_entry_convert << std::hex << std::setw(8) << std::setfill('0') << m_entry; + m_id->SetValue(m_entry_convert.str()); + + SetTitle("Auto-Pause Setting: "+m_entry_convert.str()); + + Bind(wxEVT_BUTTON, &AutoPauseSettingsDialog::OnOk, this, wxID_OK); + Bind(wxEVT_TEXT, &AutoPauseSettingsDialog::OnUpdateValue, this, wxID_STATIC); + + SetSizerAndFit(s_main); + SetSize(wxSize(400, -1)); + Layout(); + Centre(wxBOTH); + + wxCommandEvent ce; + OnUpdateValue(ce); +} + +void AutoPauseSettingsDialog::OnOk(wxCommandEvent& event) +{ + //Luckily StringStream omit those not hex. + m_entry_convert.clear(); + m_entry_convert.str(""); + m_entry_convert << std::hex << m_id->GetValue(); + m_entry_convert >> m_entry; + + *m_presult = m_entry; + + EndModal(wxID_OK); +} + +void AutoPauseSettingsDialog::OnUpdateValue(wxCommandEvent& event) +{ + //Luckily StringStream omit those not hex. + m_entry_convert.clear(); + m_entry_convert.str(""); + m_entry_convert << std::hex << m_id->GetValue(); + m_entry_convert >> m_entry; + + m_entry_convert.clear(); + m_entry_convert.str(""); + m_entry_convert << "Currently it gets an id of \"" + << std::hex << std::setw(8) << std::setfill('0') << m_entry; + m_entry_convert.clear(); + m_entry_convert << "\"."; + if (m_entry_convert.str() == m_id->GetValue()) + { + m_entry_convert << " SAME."; + } + + m_current_converted->SetLabelText(m_entry_convert.str()); + + event.Skip(); +} \ No newline at end of file diff --git a/rpcs3/Gui/AutoPauseManager.h b/rpcs3/Gui/AutoPauseManager.h new file mode 100644 index 0000000000..fa1aad3964 --- /dev/null +++ b/rpcs3/Gui/AutoPauseManager.h @@ -0,0 +1,46 @@ +#pragma once +#include "stdafx.h" +#include +#include +#include "Utilities/Log.h" +#include "Utilities/rFile.h" + +class AutoPauseManagerDialog : public wxDialog +{ + wxListView *m_list; + std::vector m_entries; + //Used when i want to convert u32 id to string + std::stringstream m_entry_convert; + +public: + AutoPauseManagerDialog(wxWindow* parent); + + void UpdateList(void); + + void OnEntryConfig(wxCommandEvent& event); + void OnRightClick(wxMouseEvent& event); + void OnAdd(wxCommandEvent& event); + void OnRemove(wxCommandEvent& event); + + void OnClear(wxCommandEvent& event); + void OnReload(wxCommandEvent& event); + void OnSave(wxCommandEvent& event); + //void OnClose(wxCommandEvent& event); + + void LoadEntries(void); + void SaveEntries(void); +}; + +class AutoPauseSettingsDialog : public wxDialog +{ + u32 m_entry; + u32 *m_presult; + wxTextCtrl* m_id; + wxStaticText* m_current_converted; + std::stringstream m_entry_convert; + +public: + AutoPauseSettingsDialog(wxWindow* parent, u32 *entry); + void OnOk(wxCommandEvent& event); + void OnUpdateValue(wxCommandEvent& event); +}; \ No newline at end of file diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index 923390d63d..3d34a85305 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -16,6 +16,7 @@ #include "Gui/VFSManager.h" #include "Gui/AboutDialog.h" #include "Gui/GameViewer.h" +#include "Gui/AutoPauseManager.h" #include #include "Loader/PKG.h" @@ -37,6 +38,7 @@ enum IDs id_config_pad, id_config_vfs_manager, id_config_vhdd_manager, + id_config_autopause_manager, id_tools_compiler, id_tools_memory_viewer, id_tools_rsx_debugger, @@ -85,8 +87,10 @@ MainFrame::MainFrame() menu_conf->Append(id_config_emu, "Settings"); menu_conf->Append(id_config_pad, "PAD Settings"); menu_conf->AppendSeparator(); + menu_conf->Append(id_config_autopause_manager, "Auto-Pause Settings"); + menu_conf->AppendSeparator(); menu_conf->Append(id_config_vfs_manager, "Virtual File System Manager"); - menu_conf->Append(id_config_vhdd_manager, "Virtual HDD Manager"); + menu_conf->Append(id_config_vhdd_manager, "Virtual HDD Manager"); wxMenu* menu_tools = new wxMenu(); menubar->Append(menu_tools, "Tools"); @@ -123,6 +127,7 @@ MainFrame::MainFrame() Bind(wxEVT_MENU, &MainFrame::ConfigPad, this, id_config_pad); Bind(wxEVT_MENU, &MainFrame::ConfigVFS, this, id_config_vfs_manager); Bind(wxEVT_MENU, &MainFrame::ConfigVHDD, this, id_config_vhdd_manager); + Bind(wxEVT_MENU, &MainFrame::ConfigAutoPause, this, id_config_autopause_manager); Bind(wxEVT_MENU, &MainFrame::OpenELFCompiler, this, id_tools_compiler); Bind(wxEVT_MENU, &MainFrame::OpenMemoryViewer, this, id_tools_memory_viewer); @@ -389,6 +394,9 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) wxCheckBox* chbox_hle_savetty = new wxCheckBox(p_hle, wxID_ANY, "Save TTY output to file"); wxCheckBox* chbox_hle_exitonstop = new wxCheckBox(p_hle, wxID_ANY, "Exit RPCS3 when process finishes"); wxCheckBox* chbox_hle_always_start = new wxCheckBox(p_hle, wxID_ANY, "Always start after boot"); + //Auto-Pause related + wxCheckBox* chbox_dbg_ap_systemcall = new wxCheckBox(p_hle, wxID_ANY, "Auto-Pause at System Call"); + wxCheckBox* chbox_dbg_ap_functioncall = new wxCheckBox(p_hle, wxID_ANY, "Auto-Pause at Function Call"); cbox_cpu_decoder->Append("PPU Interpreter & DisAsm"); cbox_cpu_decoder->Append("PPU Interpreter"); @@ -464,6 +472,9 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) chbox_hle_savetty ->SetValue(Ini.HLESaveTTY.GetValue()); chbox_hle_exitonstop ->SetValue(Ini.HLEExitOnStop.GetValue()); chbox_hle_always_start ->SetValue(Ini.HLEAlwaysStart.GetValue()); + //Auto-Pause related + chbox_dbg_ap_systemcall ->SetValue(Ini.DBGAutoPauseSystemCall.GetValue()); + chbox_dbg_ap_functioncall->SetValue(Ini.DBGAutoPauseFunctionCall.GetValue()); cbox_cpu_decoder ->SetSelection(Ini.CPUDecoderMode.GetValue() ? Ini.CPUDecoderMode.GetValue() - 1 : 0); cbox_spu_decoder ->SetSelection(Ini.SPUDecoderMode.GetValue() ? Ini.SPUDecoderMode.GetValue() - 1 : 0); @@ -532,6 +543,9 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) s_subpanel_hle->Add(chbox_hle_savetty, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_hle->Add(chbox_hle_exitonstop, wxSizerFlags().Border(wxALL, 5).Expand()); s_subpanel_hle->Add(chbox_hle_always_start, wxSizerFlags().Border(wxALL, 5).Expand()); + //Auto-Pause + s_subpanel_hle->Add(chbox_dbg_ap_systemcall, wxSizerFlags().Border(wxALL, 5).Expand()); + s_subpanel_hle->Add(chbox_dbg_ap_functioncall, wxSizerFlags().Border(wxALL, 5).Expand()); // System s_subpanel_system->Add(s_round_sys_lang, wxSizerFlags().Border(wxALL, 5).Expand()); @@ -576,6 +590,9 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) Ini.HLELogLvl.SetValue(cbox_hle_loglvl->GetSelection()); Ini.SysLanguage.SetValue(cbox_sys_lang->GetSelection()); Ini.HLEAlwaysStart.SetValue(chbox_hle_always_start->GetValue()); + //Auto-Pause + Ini.DBGAutoPauseFunctionCall.SetValue(chbox_dbg_ap_functioncall->GetValue()); + Ini.DBGAutoPauseSystemCall.SetValue(chbox_dbg_ap_systemcall->GetValue()); Ini.Save(); } @@ -598,6 +615,11 @@ void MainFrame::ConfigVHDD(wxCommandEvent& WXUNUSED(event)) VHDDManagerDialog(this).ShowModal(); } +void MainFrame::ConfigAutoPause(wxCommandEvent& WXUNUSED(event)) +{ + AutoPauseManagerDialog(this).ShowModal(); +} + void MainFrame::OpenELFCompiler(wxCommandEvent& WXUNUSED(event)) { (new CompilerELF(this)) -> Show(); diff --git a/rpcs3/Gui/MainFrame.h b/rpcs3/Gui/MainFrame.h index 975230eef7..5dea885e34 100644 --- a/rpcs3/Gui/MainFrame.h +++ b/rpcs3/Gui/MainFrame.h @@ -38,6 +38,7 @@ private: void ConfigPad(wxCommandEvent& event); void ConfigVFS(wxCommandEvent& event); void ConfigVHDD(wxCommandEvent& event); + void ConfigAutoPause(wxCommandEvent& event); void OpenELFCompiler(wxCommandEvent& evt); void OpenMemoryViewer(wxCommandEvent& evt); void OpenRSXDebugger(wxCommandEvent& evt); diff --git a/rpcs3/Ini.h b/rpcs3/Ini.h index b41bd0d1c9..f812f6296e 100644 --- a/rpcs3/Ini.h +++ b/rpcs3/Ini.h @@ -152,6 +152,10 @@ public: IniEntry HLELogLvl; IniEntry HLEAlwaysStart; + //Auto-Pause + IniEntry DBGAutoPauseSystemCall; + IniEntry DBGAutoPauseFunctionCall; + // Language IniEntry SysLanguage; @@ -217,6 +221,10 @@ public: HLELogLvl.Init("HLE_HLELogLvl", path); HLEAlwaysStart.Init("HLE_HLEAlwaysStart", path); + // Auto-Pause + DBGAutoPauseFunctionCall.Init("DBG_AutoPauseFunctionCall", path); + DBGAutoPauseSystemCall.Init("DBG_AutoPauseSystemCall", path); + // Language SysLanguage.Init("Sytem_SysLanguage", path); } @@ -277,6 +285,9 @@ public: HLEExitOnStop.Load(false); HLELogLvl.Load(3); HLEAlwaysStart.Load(true); + //Auto-Pause + DBGAutoPauseFunctionCall.Load(false); + DBGAutoPauseSystemCall.Load(false); // Language SysLanguage.Load(1); @@ -339,6 +350,9 @@ public: HLEExitOnStop.Save(); HLELogLvl.Save(); HLEAlwaysStart.Save(); + //Auto-Pause + DBGAutoPauseFunctionCall.Save(); + DBGAutoPauseSystemCall.Save(); // Language SysLanguage.Save(); diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index b3befe689e..aa7a3dd570 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -164,6 +164,7 @@ + @@ -206,6 +207,7 @@ + @@ -229,4 +231,4 @@ - + \ No newline at end of file diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index f1a38b6bb4..ab5d60bf39 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -96,6 +96,9 @@ Gui + + Gui + @@ -203,5 +206,8 @@ Utilities + + Gui + - + \ No newline at end of file