Compare commits

..

1 Commits

Author SHA1 Message Date
Rosalie Wanders 0bf19e6c44 3rdParty: apply RSP opcode fixes patch to mupen64plus-core 2024-03-27 13:54:29 +01:00
16 changed files with 182 additions and 432 deletions
+1 -1
View File
@@ -72,7 +72,7 @@ ExternalProject_Add(mupen64plus-core
SRCDIR=${CMAKE_CURRENT_SOURCE_DIR}/mupen64plus-core/src
SUBDIR=${CMAKE_CURRENT_SOURCE_DIR}/mupen64plus-core/subprojects
OSD=0 NEW_DYNAREC=1 NO_ASM=$<BOOL:${NO_ASM}> KEYBINDINGS=0 ACCURATE_FPU=1
TARGET=${CORE_FILE} DEBUG=${MAKE_DEBUG} DBG_COMPARE=1
TARGET=${CORE_FILE} DEBUG=${MAKE_DEBUG}
CC=${MAKE_CC_COMPILER} CXX=${MAKE_CXX_COMPILER}
OPTFLAGS=${MAKE_OPTFLAGS}
BUILD_IN_SOURCE False
@@ -64,6 +64,10 @@ static void do_sp_dma(struct rsp_core* sp, const struct sp_dma* dma)
post_framebuffer_write(&sp->dp->fb, dramaddr - length, length);
dramaddr+=skip;
}
sp->regs[SP_MEM_ADDR_REG] = memaddr & 0xfff;
sp->regs[SP_DRAM_ADDR_REG] = dramaddr & 0xffffff;
sp->regs[SP_RD_LEN_REG] = 0xff8;
}
else
{
@@ -77,6 +81,10 @@ static void do_sp_dma(struct rsp_core* sp, const struct sp_dma* dma)
}
dramaddr+=skip;
}
sp->regs[SP_MEM_ADDR_REG] = memaddr & 0xfff;
sp->regs[SP_DRAM_ADDR_REG] = dramaddr & 0xffffff;
sp->regs[SP_RD_LEN_REG] = 0xff8;
}
/* schedule end of dma event */
@@ -137,68 +145,68 @@ static void fifo_pop(struct rsp_core* sp)
static void update_sp_status(struct rsp_core* sp, uint32_t w)
{
/* clear / set halt */
if (w & 0x1) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_HALT;
if (w & 0x2) sp->regs[SP_STATUS_REG] |= SP_STATUS_HALT;
if ((w & 0x3) == 0x1) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_HALT;
if ((w & 0x3) == 0x2) sp->regs[SP_STATUS_REG] |= SP_STATUS_HALT;
/* clear broke */
if (w & 0x4) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_BROKE;
/* clear SP interrupt */
if (w & 0x8)
if ((w & 0x18) == 0x8)
{
clear_rcp_interrupt(sp->mi, MI_INTR_SP);
}
/* set SP interrupt */
if (w & 0x10)
if ((w & 0x18) == 0x10)
{
signal_rcp_interrupt(sp->mi, MI_INTR_SP);
}
/* clear / set single step */
if (w & 0x20) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SSTEP;
if (w & 0x40) sp->regs[SP_STATUS_REG] |= SP_STATUS_SSTEP;
if ((w & 0x60) == 0x20) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SSTEP;
if ((w & 0x60) == 0x40) sp->regs[SP_STATUS_REG] |= SP_STATUS_SSTEP;
/* clear / set interrupt on break */
if (w & 0x80) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_INTR_BREAK;
if (w & 0x100) sp->regs[SP_STATUS_REG] |= SP_STATUS_INTR_BREAK;
if ((w & 0x180) == 0x80) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_INTR_BREAK;
if ((w & 0x180) == 0x100) sp->regs[SP_STATUS_REG] |= SP_STATUS_INTR_BREAK;
/* clear / set signal 0 */
if (w & 0x200) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG0;
if (w & 0x400) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG0;
if ((w & 0x600) == 0x200) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG0;
if ((w & 0x600) == 0x400) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG0;
/* clear / set signal 1 */
if (w & 0x800) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG1;
if (w & 0x1000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG1;
if ((w & 0x1800) == 0x800) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG1;
if ((w & 0x1800) == 0x1000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG1;
/* clear / set signal 2 */
if (w & 0x2000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG2;
if (w & 0x4000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG2;
if ((w & 0x6000) == 0x2000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG2;
if ((w & 0x6000) == 0x4000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG2;
/* clear / set signal 3 */
if (w & 0x8000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG3;
if (w & 0x10000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG3;
if ((w & 0x18000) == 0x8000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG3;
if ((w & 0x18000) == 0x10000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG3;
/* clear / set signal 4 */
if (w & 0x20000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG4;
if (w & 0x40000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG4;
if ((w & 0x60000) == 0x20000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG4;
if ((w & 0x60000) == 0x40000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG4;
/* clear / set signal 5 */
if (w & 0x80000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG5;
if (w & 0x100000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG5;
if ((w & 0x180000) == 0x80000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG5;
if ((w & 0x180000) == 0x100000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG5;
/* clear / set signal 6 */
if (w & 0x200000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG6;
if (w & 0x400000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG6;
if ((w & 0x600000) == 0x200000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG6;
if ((w & 0x600000) == 0x400000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG6;
/* clear / set signal 7 */
if (w & 0x800000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG7;
if (w & 0x1000000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG7;
if ((w & 0x1800000) == 0x800000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG7;
if ((w & 0x1800000) == 0x1000000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG7;
if (sp->rsp_task_locked && (get_event(&sp->mi->r4300->cp0.q, SP_INT))) return;
if (!(w & 0x1) && !(w & 0x4) && !sp->rsp_task_locked)
if (!((w & 0x3) == 1) && !(w & 0x4) && !sp->rsp_task_locked)
return;
if (!(sp->regs[SP_STATUS_REG] & (SP_STATUS_HALT | SP_STATUS_BROKE)))
if (!(sp->regs[SP_STATUS_REG] & SP_STATUS_HALT))
do_SP_Task(sp);
}
@@ -224,6 +232,8 @@ void poweron_rsp(struct rsp_core* sp)
sp->rsp_task_locked = 0;
sp->mi->r4300->cp0.interrupt_unsafe_state &= ~INTR_UNSAFE_RSP;
sp->regs[SP_STATUS_REG] = 1;
sp->regs[SP_RD_LEN_REG] = 0xff8;
sp->regs[SP_WR_LEN_REG] = 0xff8;
}
@@ -294,6 +304,10 @@ void read_rsp_regs2(void* opaque, uint32_t address, uint32_t* value)
uint32_t reg = rsp_reg2(address);
*value = sp->regs2[reg];
if (reg == SP_PC_REG)
*value &= 0xffc;
}
void write_rsp_regs2(void* opaque, uint32_t address, uint32_t value, uint32_t mask)
@@ -301,6 +315,9 @@ void write_rsp_regs2(void* opaque, uint32_t address, uint32_t value, uint32_t ma
struct rsp_core* sp = (struct rsp_core*)opaque;
uint32_t reg = rsp_reg2(address);
if (reg == SP_PC_REG)
mask &= 0xffc;
masked_write(&sp->regs2[reg], value, mask);
}
+2 -2
View File
@@ -6,7 +6,7 @@
[subrepo]
remote = git@github.com:/Rosalie241/parallel-rsp.git
branch = RMG
commit = f7c164cf0c4131f6cfbcaefba9af3c8eaf6df1b0
parent = eb6dd8068ef4d82e47807ebccca0444d2e3300e2
commit = 71f52c492ac5896a02725152a0e6c59036ee9576
parent = e8f10693c73eeed017f45cf8289a3763ae16c257
method = merge
cmdver = 0.4.6
-2
View File
@@ -40,7 +40,6 @@ extern "C"
}
#endif
#if 0 // FIXME: this is broken with upstream mupen64plus-core
if (rd == CP0_REGISTER_SP_SEMAPHORE)
{
if (*rsp->cp0.cr[CP0_REGISTER_SP_SEMAPHORE])
@@ -57,7 +56,6 @@ extern "C"
else
*rsp->cp0.cr[CP0_REGISTER_SP_SEMAPHORE] = 1;
}
#endif
//if (rd == 4) // SP_STATUS_REG
// fprintf(stderr, "READING STATUS REG!\n");
-2
View File
@@ -28,7 +28,6 @@ set(RMG_CORE_SOURCES
m64p/Api.cpp
m64p/CoreApi.cpp
m64p/ConfigApi.cpp
m64p/DebugApi.cpp
m64p/PluginApi.cpp
CachedRomHeaderAndSettings.cpp
ConvertStringEncoding.cpp
@@ -51,7 +50,6 @@ set(RMG_CORE_SOURCES
Video.cpp
Error.cpp
Unzip.cpp
Debug.cpp
Core.cpp
Key.cpp
Rom.cpp
-8
View File
@@ -120,14 +120,6 @@ bool CoreInit(void)
return false;
}
ret = m64p::Debug.Hook(l_CoreLibHandle);
if (!ret)
{
error = m64p::Debug.GetLastError();
CoreSetError(error);
return false;
}
m64p_ret = m64p::Core.Startup(FRONTEND_API_VERSION, CoreGetUserConfigDirectory().string().c_str(), CoreGetSharedDataDirectory().string().c_str(), (void*)l_CoreContextString, CoreDebugCallback, nullptr, CoreStateCallback);
if (m64p_ret != M64ERR_SUCCESS)
{
-1
View File
@@ -29,7 +29,6 @@
#include "Error.hpp"
#include "Unzip.hpp"
#include "Video.hpp"
#include "Debug.hpp"
#include "Key.hpp"
#include "Rom.hpp"
#ifdef CORE_PLUGIN
-117
View File
@@ -1,117 +0,0 @@
/*
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
* Copyright (C) 2020 Rosalie Wanders <rosalie@mailbox.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "Debug.hpp"
#include "Error.hpp"
#include "Emulation.hpp"
#include "SaveState.hpp"
#include "m64p/Api.hpp"
#include <fstream>
//
// Local Variables
//
static CoreCompareMode l_CoreCompareMode;
static std::fstream l_RecordingFileStream;
//
// Internal Functions
//
#include <iostream>
static void core_compare_check(uint32_t op)
{
}
static void core_compare_sync(int length, void* value)
{
if (l_CoreCompareMode == CoreCompareMode::Replay)
{
l_RecordingFileStream.read((char*)value, length);
if (l_RecordingFileStream.gcount() != length)
{
CoreCompareStop();
}
}
else
{
l_RecordingFileStream.write((char*)value, length);
}
}
//
// Exported Functions
//
bool CoreCompareStart(CoreCompareMode mode)
{
std::string error;
m64p_error ret;
l_CoreCompareMode = mode;
if (l_CoreCompareMode == CoreCompareMode::Replay)
{
if (!CoreLoadSaveState("rmg_recording.state"))
{
return false;
}
}
else
{
if (!CoreSaveState("rmg_recording.state"))
{
return false;
}
}
ret = m64p::Debug.SetCoreCompare(core_compare_check, core_compare_sync);
if (ret != M64ERR_SUCCESS)
{
error = "CoreCompareInit: m64p::Debug.SetCoreCompare() Failed: ";
error += m64p::Core.ErrorMessage(ret);
CoreSetError(error);
return false;
}
if (l_CoreCompareMode == CoreCompareMode::Replay)
{
l_RecordingFileStream.open("rmg_recording", std::ios_base::binary | std::ios_base::in);
}
else
{
l_RecordingFileStream.open("rmg_recording", std::ios_base::binary | std::ios_base::out);
}
return true;
}
bool CoreCompareStop(void)
{
std::string error;
m64p_error ret;
ret = m64p::Debug.SetCoreCompare(nullptr, nullptr);
if (ret != M64ERR_SUCCESS)
{
error = "CoreCompareInit: m64p::Debug.SetCoreCompare() Failed: ";
error += m64p::Core.ErrorMessage(ret);
CoreSetError(error);
}
l_RecordingFileStream.close();
return ret == M64ERR_SUCCESS;
}
-23
View File
@@ -1,23 +0,0 @@
/*
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
* Copyright (C) 2020 Rosalie Wanders <rosalie@mailbox.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef CORE_DEBUG_HPP
#define CORE_DEBUG_HPP
enum class CoreCompareMode
{
Record = 0,
Replay = 1
};
bool CoreCompareStart(CoreCompareMode mode);
bool CoreCompareStop(void);
#endif // CORE_DEBUG_HPP
-1
View File
@@ -13,5 +13,4 @@ namespace m64p
{
m64p::CoreApi Core;
m64p::ConfigApi Config;
m64p::DebugApi Debug;
} // namespace m64p
-2
View File
@@ -11,14 +11,12 @@
#define M64P_API_HPP
#include "ConfigApi.hpp"
#include "DebugApi.hpp"
#include "CoreApi.hpp"
namespace m64p
{
extern m64p::CoreApi Core;
extern m64p::ConfigApi Config;
extern m64p::DebugApi Debug;
} // namespace m64p
#endif // M64P_API_HPP
-52
View File
@@ -1,52 +0,0 @@
/*
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
* Copyright (C) 2020 Rosalie Wanders <rosalie@mailbox.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "DebugApi.hpp"
#include "Macros.hpp"
using namespace m64p;
DebugApi::DebugApi(void)
{
this->Unhook();
}
DebugApi::~DebugApi(void)
{
}
bool DebugApi::Hook(m64p_dynlib_handle handle)
{
this->errorMessage = "DebugApi::Hook Failed: ";
HOOK_FUNC(handle, Debug, SetCoreCompare);
HOOK_FUNC(handle, Debug, GetCPUDataPtr);
this->hooked = true;
return true;
}
bool DebugApi::Unhook(void)
{
UNHOOK_FUNC(Debug, SetCoreCompare);
UNHOOK_FUNC(Debug, GetCPUDataPtr);
this->hooked = false;
return true;
}
bool DebugApi::IsHooked(void)
{
return this->hooked;
}
std::string DebugApi::GetLastError(void)
{
return this->errorMessage;
}
-43
View File
@@ -1,43 +0,0 @@
/*
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
* Copyright (C) 2020 Rosalie Wanders <rosalie@mailbox.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef M64P_DEBUGAPI_HPP
#define M64P_DEBUGAPI_HPP
#include "api/m64p_common.h"
#include "api/m64p_debugger.h"
#include <string>
namespace m64p
{
class DebugApi
{
public:
DebugApi();
~DebugApi();
bool Hook(m64p_dynlib_handle handle);
bool Unhook(void);
bool IsHooked(void);
std::string GetLastError(void);
ptr_DebugSetCoreCompare SetCoreCompare;
ptr_DebugGetCPUDataPtr GetCPUDataPtr;
private:
bool hooked = false;
std::string errorMessage;
m64p_dynlib_handle handle;
};
} // namespace m64p
#endif // M64P_DEBUGAPI_HPP
+14 -38
View File
@@ -1054,9 +1054,6 @@ void MainWindow::connectActionSignals(void)
connect(this->action_View_ClearRomCache, &QAction::triggered, this, &MainWindow::on_Action_View_ClearRomCache);
connect(this->action_View_Log, &QAction::triggered, this, &MainWindow::on_Action_View_Log);
connect(this->action_Debug_CompareRecord, &QAction::triggered, this, &MainWindow::on_action_Debug_CompareRecord);
connect(this->action_Debug_CompareReplay, &QAction::triggered, this, &MainWindow::on_action_Debug_CompareReplay);
connect(this->action_Help_Github, &QAction::triggered, this, &MainWindow::on_Action_Help_Github);
connect(this->action_Help_About, &QAction::triggered, this, &MainWindow::on_Action_Help_About);
connect(this->action_Help_Update, &QAction::triggered, this, &MainWindow::on_Action_Help_Update);
@@ -1784,39 +1781,6 @@ void MainWindow::on_Action_View_Log(void)
this->logDialog.show();
}
#include <iostream>
void MainWindow::on_action_Debug_CompareRecord(void)
{
static bool recording = false;
if (!recording)
{
if (!CoreCompareStart(CoreCompareMode::Record))
{
this->showErrorMessage("CoreCompareStart() Failed", QString::fromStdString(CoreGetError()));
}
}
else
{
if (!CoreCompareStop())
{
this->showErrorMessage("CoreCompareStop() Failed", QString::fromStdString(CoreGetError()));
}
}
// toggle
recording = !recording;
}
void MainWindow::on_action_Debug_CompareReplay(void)
{
if (!CoreCompareStart(CoreCompareMode::Replay))
{
this->showErrorMessage("CoreCompareStart() Failed", QString::fromStdString(CoreGetError()));
}
}
void MainWindow::on_Action_Help_Github(void)
{
QDesktopServices::openUrl(QUrl("https://github.com/Rosalie241/RMG"));
@@ -1837,12 +1801,24 @@ void MainWindow::on_Action_Help_Update(void)
void MainWindow::on_Action_Audio_IncreaseVolume(void)
{
CoreIncreaseVolume();
if (!CoreIncreaseVolume())
{
// It's rather annoying to have an error message pop-up everytime
// you use the increase volume hotkey when the volume is already
// at 100%, so we'll disable the error message
//this->showErrorMessage("CoreIncreaseVolume() Failed", QString::fromStdString(CoreGetError()));
}
}
void MainWindow::on_Action_Audio_DecreaseVolume(void)
{
CoreDecreaseVolume();
if (!CoreDecreaseVolume())
{
// It's rather annoying to have an error message pop-up everytime
// you use the decrease volume hotkey when the volume is already
// at 0%, so we'll disable the error message
//this->showErrorMessage("CoreDecreaseVolume() Failed", QString::fromStdString(CoreGetError()));
}
}
void MainWindow::on_Action_Audio_ToggleVolumeMute(void)
-3
View File
@@ -201,9 +201,6 @@ class MainWindow : public QMainWindow, private Ui::MainWindow
void on_Action_View_ClearRomCache(void);
void on_Action_View_Log(void);
void on_action_Debug_CompareRecord(void);
void on_action_Debug_CompareReplay(void);
void on_Action_Help_Github(void);
void on_Action_Help_About(void);
void on_Action_Help_Update(void);
+122 -111
View File
@@ -31,24 +31,26 @@
</property>
<widget class="QMenu" name="menuSystem">
<property name="title">
<string>S&amp;ystem</string>
<string>System</string>
</property>
<widget class="QMenu" name="menuReset">
<property name="title">
<string>&amp;Reset</string>
<string>Reset</string>
</property>
<property name="icon">
<iconset theme="restart-line"/>
<iconset theme="restart-line">
<normaloff>.</normaloff>.</iconset>
</property>
<addaction name="action_System_SoftReset"/>
<addaction name="action_System_HardReset"/>
</widget>
<widget class="QMenu" name="menuCurrent_Save_State">
<property name="title">
<string>&amp;Current Save State</string>
<string>Current Save State</string>
</property>
<property name="icon">
<iconset theme="save-3-line"/>
<iconset theme="save-3-line">
<normaloff>.</normaloff>.</iconset>
</property>
<addaction name="actionSlot_0"/>
<addaction name="actionSlot_1"/>
@@ -66,10 +68,11 @@
<bool>true</bool>
</property>
<property name="title">
<string>Speed &amp;Factor</string>
<string>Speed Factor</string>
</property>
<property name="icon">
<iconset theme="speed-line"/>
<iconset theme="speed-line">
<normaloff>.</normaloff>.</iconset>
</property>
<addaction name="actionSpeed25"/>
<addaction name="actionSpeed50"/>
@@ -110,7 +113,7 @@
</widget>
<widget class="QMenu" name="menuSettings">
<property name="title">
<string>Setti&amp;ngs</string>
<string>Settings</string>
</property>
<addaction name="action_Settings_Graphics"/>
<addaction name="action_Settings_Audio"/>
@@ -140,7 +143,7 @@
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>He&amp;lp</string>
<string>Help</string>
</property>
<addaction name="action_Help_Github"/>
<addaction name="separator"/>
@@ -148,23 +151,9 @@
<addaction name="separator"/>
<addaction name="action_Help_About"/>
</widget>
<widget class="QMenu" name="menuDebug">
<property name="title">
<string>&amp;Debug</string>
</property>
<widget class="QMenu" name="menuCore_Compare">
<property name="title">
<string>&amp;Core Compare</string>
</property>
<addaction name="action_Debug_CompareRecord"/>
<addaction name="action_Debug_CompareReplay"/>
</widget>
<addaction name="menuCore_Compare"/>
</widget>
<addaction name="menuSystem"/>
<addaction name="menuSettings"/>
<addaction name="menuView"/>
<addaction name="menuDebug"/>
<addaction name="menuHelp"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
@@ -201,42 +190,47 @@
</widget>
<action name="action_System_StartRom">
<property name="icon">
<iconset theme="file-line"/>
<iconset theme="file-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Start ROM</string>
<string>Start ROM</string>
</property>
</action>
<action name="action_System_OpenCombo">
<property name="icon">
<iconset theme="file-line"/>
<iconset theme="file-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Start Co&amp;mbo</string>
<string>Start Combo</string>
</property>
</action>
<action name="action_System_Shutdown">
<property name="icon">
<iconset theme="shut-down-line"/>
<iconset theme="shut-down-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>S&amp;hutdown</string>
<string>Shutdown</string>
</property>
</action>
<action name="action_System_SoftReset">
<property name="icon">
<iconset theme="restart-line"/>
<iconset theme="restart-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Soft Reset</string>
<string>Soft Reset</string>
</property>
</action>
<action name="action_System_HardReset">
<property name="icon">
<iconset theme="restart-line"/>
<iconset theme="restart-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Hard Reset</string>
<string>Hard Reset</string>
</property>
</action>
<action name="action_System_Pause">
@@ -244,18 +238,20 @@
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="pause-line"/>
<iconset theme="pause-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Pause</string>
<string>Pause</string>
</property>
</action>
<action name="action_System_Screenshot">
<property name="icon">
<iconset theme="screenshot-2-line"/>
<iconset theme="screenshot-2-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Scree&amp;nshot</string>
<string>Screenshot</string>
</property>
</action>
<action name="action_System_LimitFPS">
@@ -263,23 +259,26 @@
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="speed-line"/>
<iconset theme="speed-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Limit FPS</string>
<string>Limit FPS</string>
</property>
</action>
<action name="action_System_SaveState">
<property name="icon">
<iconset theme="save-3-line"/>
<iconset theme="save-3-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Sa&amp;ve State</string>
<string>Save State</string>
</property>
</action>
<action name="action_System_SaveAs">
<property name="icon">
<iconset theme="save-3-line"/>
<iconset theme="save-3-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Save As...</string>
@@ -287,18 +286,20 @@
</action>
<action name="action_System_LoadState">
<property name="icon">
<iconset theme="folder-open-line"/>
<iconset theme="folder-open-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>L&amp;oad State</string>
<string>Load State</string>
</property>
</action>
<action name="action_System_Load">
<property name="icon">
<iconset theme="folder-open-line"/>
<iconset theme="folder-open-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Loa&amp;d...</string>
<string>Load...</string>
</property>
</action>
<action name="actionSlot_0">
@@ -306,7 +307,7 @@
<bool>true</bool>
</property>
<property name="text">
<string>&amp;Slot 0</string>
<string>Slot 0</string>
</property>
</action>
<action name="actionSlot_1">
@@ -314,7 +315,7 @@
<bool>true</bool>
</property>
<property name="text">
<string>Slot &amp;1</string>
<string>Slot 1</string>
</property>
</action>
<action name="actionSlot_2">
@@ -322,7 +323,7 @@
<bool>true</bool>
</property>
<property name="text">
<string>Slot &amp;2</string>
<string>Slot 2</string>
</property>
</action>
<action name="actionSlot_3">
@@ -330,7 +331,7 @@
<bool>true</bool>
</property>
<property name="text">
<string>Slot &amp;3</string>
<string>Slot 3</string>
</property>
</action>
<action name="actionSlot_4">
@@ -338,7 +339,7 @@
<bool>true</bool>
</property>
<property name="text">
<string>Slot &amp;4</string>
<string>Slot 4</string>
</property>
</action>
<action name="actionSlot_5">
@@ -346,7 +347,7 @@
<bool>true</bool>
</property>
<property name="text">
<string>Slot &amp;5</string>
<string>Slot 5</string>
</property>
</action>
<action name="actionSlot_6">
@@ -354,7 +355,7 @@
<bool>true</bool>
</property>
<property name="text">
<string>Slot &amp;6</string>
<string>Slot 6</string>
</property>
</action>
<action name="actionSlot_7">
@@ -362,7 +363,7 @@
<bool>true</bool>
</property>
<property name="text">
<string>Slot &amp;7</string>
<string>Slot 7</string>
</property>
</action>
<action name="actionSlot_8">
@@ -370,7 +371,7 @@
<bool>true</bool>
</property>
<property name="text">
<string>Slot &amp;8</string>
<string>Slot 8</string>
</property>
</action>
<action name="actionSlot_9">
@@ -378,12 +379,13 @@
<bool>true</bool>
</property>
<property name="text">
<string>Slot &amp;9</string>
<string>Slot 9</string>
</property>
</action>
<action name="action_System_Cheats">
<property name="icon">
<iconset theme="code-box-line"/>
<iconset theme="code-box-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Cheats...</string>
@@ -391,82 +393,92 @@
</action>
<action name="action_System_GSButton">
<property name="icon">
<iconset theme="checkbox-blank-circle-line"/>
<iconset theme="checkbox-blank-circle-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;GS Button</string>
<string>GS Button</string>
</property>
</action>
<action name="action_System_Exit">
<property name="icon">
<iconset theme="door-open-line"/>
<iconset theme="door-open-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Exit</string>
<string>Exit</string>
</property>
</action>
<action name="action_Settings_Graphics">
<property name="icon">
<iconset theme="brush-line"/>
<iconset theme="brush-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Graphics</string>
<string>Graphics</string>
</property>
</action>
<action name="action_Settings_Input">
<property name="icon">
<iconset theme="gamepad-line"/>
<iconset theme="gamepad-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Input</string>
<string>Input</string>
</property>
</action>
<action name="action_Settings_Rsp">
<property name="icon">
<iconset theme="settings-3-line"/>
<iconset theme="settings-3-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;RSP</string>
<string>RSP</string>
</property>
</action>
<action name="action_Settings_Audio">
<property name="icon">
<iconset theme="volume-up-line"/>
<iconset theme="volume-up-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Audio</string>
<string>Audio</string>
</property>
</action>
<action name="action_Settings_Settings">
<property name="icon">
<iconset theme="settings-3-line"/>
<iconset theme="settings-3-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Settings</string>
<string>Settings</string>
</property>
</action>
<action name="action_View_Fullscreen">
<property name="icon">
<iconset theme="fullscreen-line"/>
<iconset theme="fullscreen-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Fullscreen</string>
<string>Fullscreen</string>
</property>
</action>
<action name="action_Help_Github">
<property name="icon">
<iconset theme="github-fill"/>
<iconset theme="github-fill">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Github Repository</string>
<string>Github Repository</string>
</property>
</action>
<action name="action_Help_About">
<property name="icon">
<iconset theme="information-line"/>
<iconset theme="information-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;About RMG</string>
<string>About RMG</string>
</property>
</action>
<action name="action_View_Toolbar">
@@ -474,10 +486,11 @@
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="tools-line"/>
<iconset theme="tools-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Toolbar</string>
<string>Toolbar</string>
</property>
</action>
<action name="action_View_StatusBar">
@@ -485,50 +498,56 @@
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="information-line"/>
<iconset theme="information-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Status Bar</string>
<string>Status Bar</string>
</property>
</action>
<action name="action_View_GameList">
<property name="icon">
<iconset theme="list-check"/>
<iconset theme="list-check">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Game List</string>
<string>Game List</string>
</property>
</action>
<action name="action_View_GameGrid">
<property name="icon">
<iconset theme="function-line"/>
<iconset theme="function-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Ga&amp;me Grid</string>
<string>Game Grid</string>
</property>
</action>
<action name="action_View_RefreshRoms">
<property name="icon">
<iconset theme="refresh-line"/>
<iconset theme="refresh-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Refresh ROMs</string>
<string>Refresh ROMs</string>
</property>
</action>
<action name="action_View_Log">
<property name="icon">
<iconset theme="file-list-line"/>
<iconset theme="file-list-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Log</string>
<string>Log</string>
</property>
</action>
<action name="action_View_ClearRomCache">
<property name="icon">
<iconset theme="delete-bin-line"/>
<iconset theme="delete-bin-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Clear ROM Cache</string>
<string>Clear ROM Cache</string>
</property>
</action>
<action name="action_View_UniformSize">
@@ -536,10 +555,11 @@
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="function-line"/>
<iconset theme="function-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Uniform Size (Grid View)</string>
<string>Uniform Size (Grid View)</string>
</property>
</action>
<action name="actionSpeed25">
@@ -547,17 +567,17 @@
<bool>false</bool>
</property>
<property name="text">
<string>&amp;25%</string>
<string>25%</string>
</property>
</action>
<action name="actionSpeed50">
<property name="text">
<string>&amp;50%</string>
<string>50%</string>
</property>
</action>
<action name="actionSpeed100">
<property name="text">
<string>&amp;100%</string>
<string>100%</string>
</property>
</action>
<action name="actionSpeed125">
@@ -572,12 +592,12 @@
</action>
<action name="actionSpeed200">
<property name="text">
<string>2&amp;00%</string>
<string>200%</string>
</property>
</action>
<action name="actionSpeed75">
<property name="text">
<string>&amp;75%</string>
<string>75%</string>
</property>
</action>
<action name="actionSpeed175">
@@ -602,25 +622,16 @@
</action>
<action name="actionSpeed300">
<property name="text">
<string>&amp;300%</string>
<string>300%</string>
</property>
</action>
<action name="action_Help_Update">
<property name="icon">
<iconset theme="download-line"/>
<iconset theme="download-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Check For Updates</string>
</property>
</action>
<action name="action_Debug_CompareRecord">
<property name="text">
<string>&amp;Record</string>
</property>
</action>
<action name="action_Debug_CompareReplay">
<property name="text">
<string>R&amp;eplay</string>
<string>Check For Updates</string>
</property>
</action>
</widget>