Compare commits

...

77 Commits

Author SHA1 Message Date
Rosalie Wanders d3280ff811 Package: v0.1.2 2022-01-21 13:38:12 +01:00
Rosalie Wanders cc8c1adaac cmake: remove FLATPAK_BUILD option & simplify install 2022-01-21 13:35:56 +01:00
Rosalie Wanders dd2b9bec13 Package: correct appdata & move files 2022-01-21 13:35:43 +01:00
Rosalie Wanders 34a29271a7 3rdParty: enable USE_SYSTEM_LIBS for mupen64plus-video-GLideN64 2022-01-21 13:21:24 +01:00
Rosalie Wanders d72c5196de Package: v0.1.1 2022-01-19 17:29:57 +01:00
Rosalie Wanders a08647ea88 3rdParty: always disable BUILD_INPUT_GCA due to ci build failure 2022-01-19 17:08:59 +01:00
Rosalie Wanders 549eca9158 cmake: add FLATPAK_BUILD option 2022-01-19 16:48:34 +01:00
Rosalie Wanders d7e72287dd RMG: rename diskRom to romFile in MainWindow::on_Action_File_OpenRom() 2022-01-19 15:44:08 +01:00
Rosalie Wanders 2af19a57ca RMG-Core: don't use settings in CoreGetSharedDataDirectory()
CoreGetSharedDataDirectory() is called in CoreInit() before mupen64plus
has started, so the settings function will return an empty string, which
is not expected.
2022-01-19 15:43:38 +01:00
Rosalie Wanders 33d9edcbd7 RMG: use QFileDialog::getExistingDirectory() instead of QFileDialog 2022-01-17 12:14:49 +01:00
Rosalie Wanders 3c52f25706 RMG: use QFileDialog::getOpenFileName() instead of QFileDialog 2022-01-17 12:11:45 +01:00
Rosalie Wanders 4e89dc5cb8 PKGBUILD: strip v prefix in pkgver() 2022-01-17 12:09:00 +01:00
Rosalie Wanders e01521f8f1 Package: introduce archlinux PKGBUILD 2022-01-16 19:14:15 +01:00
Rosalie Wanders bcd84abb3a cmake: simplify PORTABLE_INSTALL 2022-01-16 18:19:08 +01:00
Rosalie Wanders 3e12c8c928 RMG-Core: introduce & use Config.hpp 2022-01-16 18:18:50 +01:00
Rosalie Wanders ef50bd90b7 Build.sh: disable RMG_PORTABLE variable support, always set it to ON 2022-01-16 18:18:24 +01:00
Rosalie Wanders c49352be17 ci: remove 'env RMG_PORTABLE=ON' 2022-01-16 18:17:50 +01:00
Rosalie Wanders aa30a6b9b5 cmake: add NO_GIT_CLONE option 2022-01-14 18:37:26 +01:00
Rosalie Wanders cabfcc9f75 RMG-Core: introduce CoreGetDefault*Directory() 2022-01-14 18:18:19 +01:00
Rosalie Wanders 56e4206765 ci: don't build non-portable build on windows 2022-01-14 18:11:28 +01:00
Rosalie Wanders d95677402b cmake: re-enable portable build when PORTABLE_INSTALL=OFF on windows 2022-01-14 18:10:39 +01:00
Rosalie Wanders cd26941059 RMG-Core: remove support for non-portable builds on windows 2022-01-14 18:10:25 +01:00
Rosalie Wanders b09e73bc2b README: document linux installation/packaging building method 2022-01-14 13:53:45 +01:00
Rosalie Wanders a2b094131e cmake: install desktop file & icon on linux 2022-01-14 13:26:45 +01:00
Rosalie Wanders 09a7bf63d1 cmake: support 'make install' properly on linux 2022-01-14 13:12:14 +01:00
Rosalie Wanders 94651bab91 RMG-Core: use CoreGetPluginDirectory() in Settings.cpp for plugins 2022-01-13 16:01:45 +01:00
Rosalie Wanders 9b589c50e1 RMG-Core: remove trailing slash in Directories.cpp 2022-01-13 16:01:05 +01:00
Rosalie Wanders f7f41d330d RMG-Core: introduce CoreGetSave{,State}Directory() 2022-01-13 15:33:39 +01:00
Rosalie Wanders 5d29531a20 RMG: put stylesheet.qss in the data directory 2022-01-13 15:16:27 +01:00
Rosalie Wanders ba015b6698 RMG-Core: use CoreGet*Directory() for m64p::Core.Startup() 2022-01-13 14:49:38 +01:00
Rosalie Wanders 30c31cab40 ci: use RMG_PORTABLE variable 2022-01-13 14:25:27 +01:00
Rosalie Wanders 7e79aa0fff RMG-Core: introduce & use CoreGet*Directory functions 2022-01-13 14:25:12 +01:00
Rosalie Wanders 6b49544ac2 RMG: remove unintentional iostream include in RomInfoDialog.cpp 2022-01-13 13:06:11 +01:00
Rosalie Wanders 93c7ef1de8 RMG-Core: link to winsock2 & correct included header 2022-01-09 13:55:19 +01:00
Rosalie Wanders 98ab96db6a RMG-Core: swap byteorder of CRC1 & CRC2 in CoreGetCurrentRomHeader() 2022-01-09 13:38:07 +01:00
Rosalie Wanders c891528f1e RMG: implement 'ROM Information' from RomBrowserWidget 2022-01-08 13:52:14 +01:00
Rosalie Wanders 2b11653a44 RMG: implement 'Play Game With Disk' from RomBrowserWidget 2022-01-08 12:53:24 +01:00
Rosalie Wanders c66a2f34bc RMG: remove dead code in EventFilter 2022-01-08 12:45:38 +01:00
Rosalie Wanders 8976401695 RMG: implement 'Choose ROM Directory' from RomBrowserWidget 2022-01-08 12:44:48 +01:00
Rosalie Wanders 11f9d9d9a0 RMG: quit RomSearcherThread gracefully instead of using terminate() 2022-01-07 23:23:16 +01:00
Rosalie Wanders 01ca2c66b6 RMG: implement restore default in plugins tab in SettingsDialog 2022-01-07 22:24:48 +01:00
Rosalie Wanders 919a5623e8 RMG: don't show unneeded emulation text in SettingsDialog 2022-01-07 22:02:08 +01:00
Rosalie Wanders 5a4f938502 RMG: implement 'Edit Game Settings' from RomBrowserWidget 2022-01-07 21:52:11 +01:00
Rosalie Wanders 8ca95bc89b ci: use path-type: inherit in msys2 for windows 2022-01-07 20:52:07 +01:00
Rosalie Wanders 2cb20cc209 3rdParty: correct mupen64plus-input-gca filename for windows 2022-01-07 20:50:53 +01:00
Rosalie Wanders 6420a636d1 3rdParty: add mupen64plus-input-gca 2022-01-06 15:54:42 +01:00
Rosalie Wanders a4111f2efa RMG-Core: minor fixes in Plugins.cpp 2022-01-06 14:52:00 +01:00
Rosalie Wanders 972e88b74f RMG-Core: restore plugin settings during failure in CoreStartEmulation() 2022-01-06 14:51:38 +01:00
Rosalie Wanders d4adca5af8 RMG: clear plugin comboboxes first in SettingsDialog
Fixes plugins never being removed when clicking on 'defaults' in the
plugins tab
2022-01-06 14:42:26 +01:00
Rosalie Wanders 8bc0c6ce67 RMG: handle plugin failures in SettingsDialog 2022-01-06 14:38:12 +01:00
Rosalie Wanders f2d89bd1c9 RMG-Core: Shutdown() plugins before Unhook() 2022-01-06 14:29:39 +01:00
Rosalie Wanders a96bc6e748 RMG-Core: improve error handling in Plugins.cpp 2022-01-06 14:18:39 +01:00
Rosalie Wanders 0b38302556 RMG: call CoreApplyPluginSettings() in MainWindow::Init() 2022-01-06 14:17:34 +01:00
Rosalie Wanders 7147dfa858 RMG-Core: don't call CoreApplyPluginSettings() in CoreInit()
This allows for better plugin failure handling
2022-01-06 14:17:13 +01:00
JakobDev 9702d048a4 RMG: provide visible feedback when KeyBindButton is in focus 2022-01-05 23:51:49 +01:00
JakobDev 1e1e8cc455 RMG: disable some contextmenu items when nothing is selected in RomBrowserWidget 2022-01-05 22:14:07 +01:00
Rosalie Wanders e6b561e240 RMG: implement pause/resume on focus loss/gain 2022-01-05 17:50:57 +01:00
Rosalie Wanders b5cec10f97 RMG-Core: add GUI_{Pause,Resume}EmulationOnFocus settings 2022-01-05 17:50:19 +01:00
Rosalie Wanders 74c4fff060 RMG-Audio: add RMG window icon 2022-01-05 16:59:24 +01:00
Rosalie Wanders f1b8401ecb RMG-Core: include Rom.hpp in Core.hpp 2022-01-05 16:48:29 +01:00
Rosalie Wanders e9ebc5ecd0 RMG-Core: close ROM on failure in CoreStartEmulation() 2022-01-05 16:40:36 +01:00
Rosalie Wanders 8814d5a9a6 3rdParty: correct wrong build order 2021-12-26 20:35:21 +01:00
Rosalie Wanders 4a21907fee 3rdParty: remove mupen64plus-audio-sdl 2021-12-26 16:56:43 +01:00
Rosalie Wanders be03f352dd Introduce RMG-Audio 2021-12-26 16:56:22 +01:00
Rosalie Wanders e7b0147eb4 RMG-Core: add audio plugin settings 2021-12-26 16:52:11 +01:00
Rosalie Wanders 4227469427 RMG-Core: turn on CMAKE_POSITION_INDEPENDENT_CODE 2021-12-26 16:51:53 +01:00
Rosalie Wanders 802fd2ca12 RMG-Core: add a version of CoreInit() for plugins 2021-12-26 16:51:33 +01:00
Rosalie Wanders b5990826df RMG-Core: pause & resume emulation in CorePluginsOpenConfig() 2021-12-26 15:56:40 +01:00
Rosalie Wanders e063e8745f RMG-Core: correct some comments in Plugins.cpp 2021-12-25 12:48:28 +01:00
Rosalie Wanders 25978727d8 RMG: save all game settings in SettingsDialog
This is needed to make sure we aren't using wrong values in RMG-Core's
CoreApplyRomSettingsOverlay()
2021-12-25 12:46:22 +01:00
Rosalie Wanders e4dc4fd1b5 RMG: filter out IS viewer messages from the statusbar 2021-12-24 15:37:44 +01:00
Rosalie Wanders e1464d2d30 RMG-Core: attempt to fix read_raw_file in Rom.cpp (again)
For some reason, some users are experiencing issues when using gcount()
here, so just use fileStreamLen instead, which fixes it for them weirdly
enough.
2021-12-24 15:20:32 +01:00
Rosalie Wanders 8350b7bfe7 3rdParty: add mupen64plus-video-parallel 2021-12-24 13:35:52 +01:00
Rosalie Wanders a15f6c85e3 3rdParty: add mupen64plus-rsp-parallel 2021-12-24 13:32:25 +01:00
Rosalie Wanders e01fed88ee 3rdParty: add mupen64plus-input-raphnetraw 2021-12-24 13:26:24 +01:00
Rosalie Wanders b66dbd7544 RMG-Core: introduce & use Settings_HasForceUsedSetOnce in Settings
This fixes some core settings reverting on each launch, like the
screenshot directory and save state/sram directory settings.
2021-12-24 13:20:20 +01:00
Rosalie Wanders d42f770e06 RMG-Core: improve read_raw_file in Rom.cpp 2021-12-23 16:36:11 +01:00
52 changed files with 3868 additions and 458 deletions
+8 -6
View File
@@ -15,9 +15,10 @@ jobs:
- name: Prepare Environment
run: |
echo "GIT_REVISION=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
- name: Build RMG
run: bash ./Source/Script/Build.sh Release
- name: Upload RMG
- name: Build RMG (Portable)
run: ./Source/Script/Build.sh Release
shell: bash
- name: Upload RMG (Portable)
uses: actions/upload-artifact@v2
with:
name: RMG-Portable-Linux64-${{ env.GIT_REVISION }}
@@ -29,6 +30,7 @@ jobs:
- uses: actions/checkout@v2
- uses: msys2/setup-msys2@v2
with:
path-type: inherit
update: true
install: >-
make
@@ -52,17 +54,17 @@ jobs:
$env:revision = git rev-parse --short HEAD
echo "GIT_REVISION=$env:revision" >> $env:GITHUB_ENV
shell: pwsh
- name: Build RMG
- name: Build RMG (Portable)
run: ./Source/Script/Build.sh Release
shell: msys2 {0}
- name: Create Installer
run: .\Build\Release\Source\Installer\CreateInstaller.bat
- name: Upload RMG
- name: Upload RMG (Portable)
uses: actions/upload-artifact@v2
with:
name: RMG-Portable-Windows64-${{ env.GIT_REVISION }}
path: Bin/Release/*
- name: Upload Installer
- name: Upload RMG (Installer)
uses: actions/upload-artifact@v2
with:
name: RMG-Setup-Windows64-${{ env.GIT_REVISION }}

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

+72 -16
View File
@@ -3,6 +3,9 @@
#
cmake_minimum_required(VERSION 3.15)
option(PORTABLE_INSTALL "Portable Installation" ON)
option(NO_GIT_CLONE "Disables git clone usage for 3rdParty dependencies" OFF)
project(RMG)
find_package(Git REQUIRED)
@@ -14,13 +17,48 @@ execute_process(
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(CMAKE_INSTALL_PREFIX "")
set(INSTALL_PATH Bin/${CMAKE_BUILD_TYPE})
if (FLATPAK_BUILD AND (WIN32 OR MSYS))
message(ERROR "FLATPAK_BUILD is not supported on windows, disabling FLATPAK_BUILD!")
set(FLATPAK_BUILD OFF)
endif()
if(FLATPAK_BUILD)
set(NO_GIT_CLONE ON)
set(PORTABLE_INSTALL OFF)
endif(FLATPAK_BUILD)
if (NOT PORTABLE_INSTALL AND (WIN32 OR MSYS))
message(WARNING "Not-Portable build not supported on windows, re-enabling PORTABLE_INSTALL!")
set(PORTABLE_INSTALL ON)
endif()
if (PORTABLE_INSTALL)
set(CMAKE_INSTALL_PREFIX "")
set(INSTALL_PATH "Bin/${CMAKE_BUILD_TYPE}")
set(RMG_INSTALL_PATH "${INSTALL_PATH}")
set(CORE_INSTALL_PATH "${INSTALL_PATH}/Core")
set(PLUGIN_INSTALL_PATH "${INSTALL_PATH}/Plugin")
set(DATA_INSTALL_PATH "${INSTALL_PATH}/Data")
set(INSTALL_DESKTOP_FILE OFF)
else()
set(RMG_INSTALL_PATH "bin")
set(CORE_INSTALL_PATH "lib/RMG/Core")
set(PLUGIN_INSTALL_PATH "lib/RMG/Plugin")
set(DATA_INSTALL_PATH "share/RMG")
set(INSTALL_DESKTOP_FILE ON)
set(APPDATA_INSTALL_PATH "share/metainfo/")
set(DESKTOP_INSTALL_PATH "share/applications")
set(ICON_INSTALL_PATH "share/icons/hicolor/scalable/apps/")
endif()
add_subdirectory(Source/RMG-Core)
add_subdirectory(Source/RMG)
add_subdirectory(Source/RMG-Audio)
install(TARGETS RMG
DESTINATION ${INSTALL_PATH}
DESTINATION ${RMG_INSTALL_PATH}
)
install(TARGETS RMG-Audio
DESTINATION ${PLUGIN_INSTALL_PATH}/Audio
)
if (WIN32)
@@ -33,23 +71,41 @@ endif()
add_subdirectory(Source/3rdParty)
install(FILES ${MUPEN64PLUSCORE_LIB}
DESTINATION ${INSTALL_PATH}/Core
DESTINATION ${CORE_INSTALL_PATH}
)
install(FILES ${MUPEN64PLUSCORE_INI} ${MUPEN64PLUSCORE_CHT} Data/font.ttf
DESTINATION ${INSTALL_PATH}/Data
install(FILES ${MUPEN64PLUSCORE_INI} ${MUPEN64PLUSCORE_CHT} Data/font.ttf Data/stylesheet.qss
DESTINATION ${DATA_INSTALL_PATH}
)
install(FILES Config/stylesheet.qss
DESTINATION ${INSTALL_PATH}/Config
install(FILES ${MUPEN64PLUS_PLUGIN_RSP_HLE}
DESTINATION ${PLUGIN_INSTALL_PATH}/RSP
)
install(FILES ${MUPEN64PLUS_PLUGIN_AUDIO}
DESTINATION ${INSTALL_PATH}/Plugin/Audio
install(FILES ${MUPEN64PLUS_PLUGIN_RSP_PARALLEL}
DESTINATION ${PLUGIN_INSTALL_PATH}/RSP
)
install(FILES ${MUPEN64PLUS_PLUGIN_RSP}
DESTINATION ${INSTALL_PATH}/Plugin/RSP
install(FILES ${MUPEN64PLUS_PLUGIN_INPUT_QT}
DESTINATION ${PLUGIN_INSTALL_PATH}/Input
)
install(FILES ${MUPEN64PLUS_PLUGIN_INPUT}
DESTINATION ${INSTALL_PATH}/Plugin/Input
install(FILES ${MUPEN64PLUS_PLUGIN_INPUT_RAPHNET}
DESTINATION ${PLUGIN_INSTALL_PATH}/Input
)
install(FILES ${MUPEN64PLUS_PLUGIN_GFX}
DESTINATION ${INSTALL_PATH}/Plugin/GFX
install(FILES ${MUPEN64PLUS_PLUGIN_INPUT_GCA}
DESTINATION ${PLUGIN_INSTALL_PATH}/Input
)
install(FILES ${MUPEN64PLUS_PLUGIN_GFX_GLIDEN64}
DESTINATION ${PLUGIN_INSTALL_PATH}/GFX
)
install(FILES ${MUPEN64PLUS_PLUGIN_GFX_PARALLEL}
DESTINATION ${PLUGIN_INSTALL_PATH}/GFX
)
if (INSTALL_DESKTOP_FILE)
install(FILES Package/com.github.Rosalie241.RMG.desktop
DESTINATION ${DESKTOP_INSTALL_PATH}
)
install(FILES Package/com.github.Rosalie241.RMG.svg
DESTINATION ${ICON_INSTALL_PATH}
)
install(FILES Package/com.github.Rosalie241.RMG.appdata.xml
DESTINATION ${APPDATA_INSTALL_PATH}
)
endif(INSTALL_DESKTOP_FILE)
+51
View File
@@ -0,0 +1,51 @@
# Maintainer: Rosalie Wanders <rosalie@mailbox.org>
_pkgname=rmg
pkgname=${_pkgname}-git
pkgver=git
pkgrel=1
pkgdesc="Rosalie's Mupen GUI"
arch=('x86_64')
url="https://github.com/Rosalie241/${_pkgname}"
license=('GPLv3')
provides=("$_pkgname")
conflicts=("$_pkgname")
depends=("hidapi" "libsamplerate" "minizip" "sdl2" "zlib" "freetype2" "qt5-base" "qt5-svg")
makedepends=("git" "pkg-config" "nasm" "cmake" "rustup")
source=("git+https://github.com/Rosalie241/${_pkgname}.git")
sha256sums=('SKIP')
pkgver()
{
cd "$_pkgname"
git describe --tags --always | sed -e 's|^v||;s|-|.|g'
}
prepare()
{
cd "$srcdir/${_pkgname}"
mkdir -p build
}
build()
{
cd "$srcdir/${_pkgname}/build"
cmake -S "$srcdir/${_pkgname}" -B "$srcdir/${_pkgname}/build" \
-DCMAKE_BUILD_TYPE="Release" \
-DPORTABLE_INSTALL="OFF" \
-DCMAKE_INSTALL_PREFIX="/usr" \
-G "Unix Makefiles"
make
}
package()
{
cd "$srcdir/${_pkgname}/build"
make install DESTDIR="$pkgdir"
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

@@ -0,0 +1,54 @@
<?xml version='1.0' encoding='utf-8'?>
<component type="desktop">
<!--Created with jdAppdataEdit 2.1-->
<id>com.github.Rosalie241.RMG</id>
<name>Rosalie's Mupen GUI</name>
<summary>An easy to use &amp; cross-platform mupen64plus front-end written in C++ &amp; Qt</summary>
<developer_name>Rosalie</developer_name>
<launchable type="desktop-id">com.github.Rosalie241.RMG.desktop</launchable>
<metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-3.0-only</project_license>
<description><p>Rosalie's Mupen GUI is an easy to use yet customizable mupen64plus front-end, allowing you to easily play N64 games.</p></description>
<screenshots>
<screenshot type="default">
<caption>The Rom Browser</caption>
<image type="source">https://github.com/Rosalie241/RMG/raw/master/Package/Screenshots/RomBrowser.png</image>
</screenshot>
<screenshot type="default">
<caption>During A Game</caption>
<image type="source">https://github.com/Rosalie241/RMG/raw/master/Package/Screenshots/InGame.png</image>
</screenshot>
<screenshot type="default">
<caption>Settings</caption>
<image type="source">https://github.com/Rosalie241/RMG/raw/master/Package/Screenshots/Settings.png</image>
</screenshot>
</screenshots>
<description/>
<releases>
<release version="v0.1.2" date="2022-01-21" type="stable"/>
<release version="v0.1.1" date="2022-01-19" type="stable"/>
<release version="v0.1.0" date="2022-01-07" type="stable"/>
<release version="v0.0.9" date="2021-12-25" type="stable"/>
<release version="v0.0.8" date="2021-12-24" type="stable"/>
<release version="v0.0.7" date="2021-12-23" type="stable"/>
<release version="v0.0.6" date="2021-10-18" type="stable"/>
<release version="v0.0.5" date="2021-10-17" type="stable"/>
<release version="v0.0.4" date="2021-10-06" type="stable"/>
<release version="v0.0.3" date="2021-10-04" type="stable"/>
<release version="v0.0.2" date="2021-09-26" type="stable"/>
</releases>
<url type="homepage">https://github.com/Rosalie241/RMG</url>
<url type="bugtracker">https://github.com/Rosalie241/RMG/issues</url>
<categories>
<category>Game</category>
</categories>
<recommends>
<control>pointing</control>
<control>keyboard</control>
</recommends>
<content_rating type="oars-1.1"/>
<keywords>
<keyword>mupen64plus</keyword>
<keyword>RMG</keyword>
</keywords>
</component>
@@ -0,0 +1,8 @@
[Desktop Entry]
Type=Application
Name=Rosalie's Mupen GUI
Comment=An easy to use & cross-platform mupen64plus front-end written in C++ & Qt
Exec=RMG
Icon=com.github.Rosalie241.RMG
Terminal=false
Categories=Game;
File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 54 KiB

+8 -5
View File
@@ -18,18 +18,21 @@ It offers a simple-to-use user interface.
## Building
#### Linux
**NOTE:** installation is **not** supported on linux at the moment, only running it portable will work
* Portable
```
# for debian based distros
sudo apt-get -y install cmake libhidapi-dev libsamplerate0-dev libminizip-dev libsdl2-dev libfreetype6-dev libgl1-mesa-dev libglu1-mesa-dev pkg-config zlib1g-dev binutils-dev libspeexdsp-dev qt5-default build-essential nasm git zip
# for arch based distros
sudo pacman -S base-devel git hidapi libsamplerate minizip sdl2 freetype2 pkg-config zlib qt5 nasm
# building
./Source/Script/Build.sh Release
```
When it's done building, executables can be found in `Bin/Release`
* Installation/Packaging
```
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE="Release" -DPORTABLE_INSTALL="OFF" -G "Unix Makefiles"
make install
```
#### Windows
* Download & Install [MSYS2](https://www.msys2.org/)
```
+129 -33
View File
@@ -5,23 +5,60 @@ include(ExternalProject)
set(THIRDPARTY_DIR ${CMAKE_BINARY_DIR}/Source/3rdParty)
find_program(RUST_CARGO cargo)
if(${RUST_CARGO} STREQUAL "RUST_CARGO-NOTFOUND")
message(WARNING "mupen64plus-input-gca will not be built due to not having cargo installed")
set(BUILD_INPUT_GCA "0")
else()
# disabled because build failure
set(BUILD_INPUT_GCA "0")
endif()
set(M64P_CORE_DIR ${THIRDPARTY_DIR}/mupen64plus-core)
if(WIN32)
set(SO_EXT "dll")
set(GCA_LIB "mupen64plus_input_gca.${SO_EXT}")
set(CORE_FILE "mupen64plus.dll")
else(WIN32)
set(SO_EXT "so")
set(GCA_LIB "libmupen64plus_input_gca.${SO_EXT}")
set(CORE_FILE "libmupen64plus.so")
endif(WIN32)
if(NOT NO_GIT_CLONE)
set(MUPEN64PLUSCORE_URL "https://github.com/mupen64plus/mupen64plus-core")
set(MUPEN64PLUSCORE_TAG "57828d930280554c7400bb2bcf1e46c7f2ee8373")
set(MUPEN64PLUS_RSP_HLE_URL "https://github.com/mupen64plus/mupen64plus-rsp-hle")
set(MUPEN64PLUS_RSP_HLE_TAG "88093cb43499eff53d343653cddcae2132af17ef")
set(MUPEN64PLUS_RSP_PARALLEL_URL "https://github.com/loganmc10/parallel-rsp")
set(MUPEN64PLUS_RSP_PARALLEL_TAG "a9646b27c2ef399e5917735b4d84ebe93edcce39")
set(MUPEN64PLUS_INPUT_QT_URL "https://github.com/Rosalie241/mupen64plus-input-qt")
set(MUPEN64PLUS_INPUT_QT_TAG "e6cacb7fe6513cac4b30f7171d8ca7d1cd5fdb81")
set(MUPEN64PLUS_INPUT_RAPHNET_URL "https://github.com/raphnet/mupen64plus-input-raphnetraw")
set(MUPEN64PLUS_INPUT_RAPHNET_TAG "86112413e98a8648edb11d199673cc24d5799af8")
set(MUPEN64PLUS_INPUT_GCA_URL "https://github.com/amatho/mupen64plus-input-gca")
set(MUPEN64PLUS_INPUT_GCA_TAG "d440611d3639fa974c7d52bd0ed2079d16428d5e")
set(MUPEN64PLUS_GFX_GLIDEN64_URL "https://github.com/gonetz/GLideN64")
set(MUPEN64PLUS_GFX_GLIDEN64_TAG "8343fd05c9a01ce2d73f7e32bb8355036759a05b")
set(MUPEN64PLUS_GFX_PARALLEL_URL "https://github.com/loganmc10/parallel-rdp-standalone")
set(MUPEN64PLUS_GFX_PARALLEL_TAG "2efeaf014bad03ec26e081c22d8ca3566003b1ea")
endif(NOT NO_GIT_CLONE)
ExternalProject_Add(mupen64plus-core
SOURCE_DIR mupen64plus-core/
CONFIGURE_COMMAND ""
INSTALL_COMMAND ""
GIT_REPOSITORY https://github.com/mupen64plus/mupen64plus-core
GIT_TAG 57828d930280554c7400bb2bcf1e46c7f2ee8373
GIT_REPOSITORY ${MUPEN64PLUSCORE_URL}
GIT_TAG ${MUPEN64PLUSCORE_TAG}
BUILD_COMMAND make all OSD=0 NEW_DYNAREC=1 TARGET=${CORE_FILE} DEBUG=$<CONFIG:Debug> KEYBINDINGS=0
BUILD_IN_SOURCE False
@@ -33,32 +70,14 @@ ExternalProject_Add(mupen64plus-core
set(APIDIR "${CMAKE_BINARY_DIR}/Source/3rdParty/mupen64plus-core/src/api")
ExternalProject_Add(mupen64plus-audio-sdl
SOURCE_DIR mupen64plus-audio-sdl2/
CONFIGURE_COMMAND ""
INSTALL_COMMAND ""
GIT_REPOSITORY https://github.com/Rosalie241/mupen64plus-audio-sdl2
GIT_TAG cc6aca5a13b0b8ca7a2f9f5fa472ed3bb7f817db
BUILD_COMMAND make all APIDIR=${APIDIR} DEBUG=$<CONFIG:Debug>
BUILD_IN_SOURCE False
BINARY_DIR ${THIRDPARTY_DIR}/mupen64plus-audio-sdl2/projects/unix
BUILD_BYPRODUCTS ${THIRDPARTY_DIR}/mupen64plus-audio-sdl2/projects/unix/mupen64plus-audio-sdl2.${SO_EXT}
DEPENDS mupen64plus-core
)
ExternalProject_Add(mupen64plus-rsp-hle
SOURCE_DIR mupen64plus-rsp-hle/
CONFIGURE_COMMAND ""
INSTALL_COMMAND ""
GIT_REPOSITORY https://github.com/mupen64plus/mupen64plus-rsp-hle
GIT_TAG 88093cb43499eff53d343653cddcae2132af17ef
GIT_REPOSITORY ${MUPEN64PLUS_RSP_HLE_URL}
GIT_TAG ${MUPEN64PLUS_RSP_HLE_TAG}
BUILD_COMMAND make all APIDIR=${APIDIR} DEBUG=$<CONFIG:Debug>
BUILD_IN_SOURCE False
@@ -69,14 +88,29 @@ ExternalProject_Add(mupen64plus-rsp-hle
DEPENDS mupen64plus-core
)
ExternalProject_Add(mupen64plus-rsp-parallel
SOURCE_DIR mupen64plus-rsp-parallel
GIT_REPOSITORY ${MUPEN64PLUS_RSP_PARALLEL_URL}
GIT_TAG ${MUPEN64PLUS_RSP_PARALLEL_TAG}
INSTALL_COMMAND ""
BUILD_IN_SOURCE True
CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
BUILD_BYPRODUCTS ${THIRDPARTY_DIR}/mupen64plus-rsp-parallel/mupen64plus-rsp-parallel.${SO_EXT}
DEPENDS mupen64plus-core
)
ExternalProject_Add(mupen64plus-input-qt
SOURCE_DIR mupen64plus-input-qt
CMAKE_ARGS -DAPIDIR=${APIDIR} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
INSTALL_COMMAND ""
GIT_REPOSITORY https://github.com/Rosalie241/mupen64plus-input-qt
GIT_TAG e6cacb7fe6513cac4b30f7171d8ca7d1cd5fdb81
GIT_REPOSITORY ${MUPEN64PLUS_INPUT_QT_URL}
GIT_TAG ${MUPEN64PLUS_INPUT_QT_TAG}
BUILD_COMMAND make all APIDIR=${APIDIR} DEBUG=$<CONFIG:Debug>
BUILD_IN_SOURCE True
@@ -85,6 +119,42 @@ ExternalProject_Add(mupen64plus-input-qt
DEPENDS mupen64plus-core
)
ExternalProject_Add(mupen64plus-input-raphnetraw
SOURCE_DIR mupen64plus-input-raphnetraw/
CONFIGURE_COMMAND ""
INSTALL_COMMAND ""
GIT_REPOSITORY ${MUPEN64PLUS_INPUT_RAPHNET_URL}
GIT_TAG ${MUPEN64PLUS_INPUT_RAPHNET_TAG}
BUILD_COMMAND make all APIDIR=${APIDIR} DEBUG=$<CONFIG:Debug>
BUILD_IN_SOURCE False
BINARY_DIR ${THIRDPARTY_DIR}/mupen64plus-input-raphnetraw/projects/unix
BUILD_BYPRODUCTS ${THIRDPARTY_DIR}/mupen64plus-input-raphnetraw/projects/unix/mupen64plus-input-raphnetraw.${SO_EXT}
DEPENDS mupen64plus-core
)
if (${BUILD_INPUT_GCA} STREQUAL "1")
ExternalProject_Add(mupen64plus-input-gca
SOURCE_DIR mupen64plus-input-gca/
CONFIGURE_COMMAND ""
INSTALL_COMMAND ""
GIT_REPOSITORY ${MUPEN64PLUS_INPUT_GCA_URL}
GIT_TAG ${MUPEN64PLUS_INPUT_GCA_TAG}
BUILD_COMMAND cargo build --release
BUILD_IN_SOURCE True
BUILD_BYPRODUCTS ${THIRDPARTY_DIR}/mupen64plus-input-gca/target/release/${GCA_LIB}
DEPENDS mupen64plus-core
)
endif()
set(GLIDEN64_DIR "${THIRDPARTY_DIR}/mupen64plus-video-GLideN64")
set(GLIDEN64_BUILD_DIR "${GLIDEN64_DIR}/projects/cmake")
if (MSYS)
@@ -101,13 +171,13 @@ endforeach()
ExternalProject_Add(mupen64plus-video-GLideN64
SOURCE_DIR mupen64plus-video-GLideN64
GIT_REPOSITORY https://github.com/gonetz/GLideN64
GIT_TAG 8343fd05c9a01ce2d73f7e32bb8355036759a05b
GIT_REPOSITORY ${MUPEN64PLUS_GFX_GLIDEN64_URL}
GIT_TAG ${MUPEN64PLUS_GFX_GLIDEN64_TAG}
INSTALL_COMMAND ""
BUILD_IN_SOURCE False
CMAKE_ARGS -DMUPENPLUSAPI=1 -DMUPENPLUSAPI_GLIDENUI=1 -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -Wno-dev
CMAKE_ARGS -DMUPENPLUSAPI=1 -DMUPENPLUSAPI_GLIDENUI=1 -DUSE_SYSTEM_LIBS=ON -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
SOURCE_SUBDIR ./src/
BINARY_DIR ${GLIDEN64_BUILD_DIR}
@@ -117,19 +187,45 @@ ExternalProject_Add(mupen64plus-video-GLideN64
BUILD_BYPRODUCTS ${GLIDENUI_TRANSLATIONS}
)
ExternalProject_Add(mupen64plus-video-parallel
SOURCE_DIR mupen64plus-video-parallel
GIT_REPOSITORY ${MUPEN64PLUS_GFX_PARALLEL_URL}
GIT_TAG ${MUPEN64PLUS_GFX_PARALLEL_TAG}
INSTALL_COMMAND ""
BUILD_IN_SOURCE True
CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
BUILD_BYPRODUCTS ${THIRDPARTY_DIR}/mupen64plus-video-parallel/mupen64plus-video-parallel.${SO_EXT}
DEPENDS mupen64plus-core
)
ExternalProject_Get_property(mupen64plus-core BUILD_BYPRODUCTS)
set(MUPEN64PLUSCORE_LIB ${BUILD_BYPRODUCTS} PARENT_SCOPE)
set(MUPEN64PLUSCORE_INI ${M64P_CORE_DIR}/data/mupen64plus.ini PARENT_SCOPE)
set(MUPEN64PLUSCORE_CHT ${M64P_CORE_DIR}/data/mupencheat.txt PARENT_SCOPE)
ExternalProject_Get_property(mupen64plus-audio-sdl BUILD_BYPRODUCTS)
set(MUPEN64PLUS_PLUGIN_AUDIO ${BUILD_BYPRODUCTS} PARENT_SCOPE)
ExternalProject_Get_property(mupen64plus-rsp-hle BUILD_BYPRODUCTS)
set(MUPEN64PLUS_PLUGIN_RSP ${BUILD_BYPRODUCTS} PARENT_SCOPE)
set(MUPEN64PLUS_PLUGIN_RSP_HLE ${BUILD_BYPRODUCTS} PARENT_SCOPE)
ExternalProject_Get_property(mupen64plus-rsp-parallel BUILD_BYPRODUCTS)
set(MUPEN64PLUS_PLUGIN_RSP_PARALLEL ${BUILD_BYPRODUCTS} PARENT_SCOPE)
ExternalProject_Get_property(mupen64plus-input-qt BUILD_BYPRODUCTS)
set(MUPEN64PLUS_PLUGIN_INPUT ${BUILD_BYPRODUCTS} PARENT_SCOPE)
set(MUPEN64PLUS_PLUGIN_INPUT_QT ${BUILD_BYPRODUCTS} PARENT_SCOPE)
ExternalProject_Get_property(mupen64plus-input-raphnetraw BUILD_BYPRODUCTS)
set(MUPEN64PLUS_PLUGIN_INPUT_RAPHNET ${BUILD_BYPRODUCTS} PARENT_SCOPE)
if (${BUILD_INPUT_GCA} STREQUAL "1")
ExternalProject_Get_property(mupen64plus-input-gca BUILD_BYPRODUCTS)
set(MUPEN64PLUS_PLUGIN_INPUT_GCA ${BUILD_BYPRODUCTS} PARENT_SCOPE)
endif()
ExternalProject_Get_property(mupen64plus-video-GLideN64 BUILD_BYPRODUCTS)
set(MUPEN64PLUS_PLUGIN_GFX ${BUILD_BYPRODUCTS} PARENT_SCOPE)
set(MUPEN64PLUS_PLUGIN_GFX_GLIDEN64 ${BUILD_BYPRODUCTS} PARENT_SCOPE)
ExternalProject_Get_property(mupen64plus-video-parallel BUILD_BYPRODUCTS)
set(MUPEN64PLUS_PLUGIN_GFX_PARALLEL ${BUILD_BYPRODUCTS} PARENT_SCOPE)
+37
View File
@@ -0,0 +1,37 @@
#
# RMG-Audio CMakeLists.txt
#
project(RMG-Audio)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
find_package(Qt5 COMPONENTS Gui Widgets Core REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(SDL2 REQUIRED sdl2)
set(RMG_AUDIO_SOURCES
UserInterface/MainDialog.cpp
UserInterface/MainDialog.ui
UserInterface/UIResources.qrc
main.cpp
)
add_library(RMG-Audio SHARED ${RMG_AUDIO_SOURCES})
set_target_properties(RMG-Audio PROPERTIES PREFIX "")
target_link_libraries(RMG-Audio
RMG-Core
${SDL2_LIBRARIES}
Qt5::Gui Qt5::Widgets
)
target_include_directories(RMG-Audio PRIVATE
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/../
${SDL2_INCLUDE_DIRS}
)
+2
View File
@@ -0,0 +1,2 @@
# Rosalie's Mupen GUI - Audio Plugin
This is a simple SDL2 audio plugin, based on https://github.com/m64p/mupen64plus-audio-sdl2
@@ -0,0 +1,46 @@
/*
* 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 "MainDialog.hpp"
#include <RMG-Core/Core.hpp>
using namespace UserInterface;
MainDialog::MainDialog(QWidget* parent) : QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint)
{
this->setupUi(this);
this->setWindowIcon(QIcon(":Resource/RMG.png"));
this->volumeSlider->setValue(CoreSettingsGetIntValue(SettingsID::Audio_Volume));
this->mutedCheckbox->setChecked(CoreSettingsGetBoolValue(SettingsID::Audio_Muted));
}
MainDialog::~MainDialog()
{
}
void MainDialog::on_volumeSlider_valueChanged(int value)
{
this->volumeLabel->setText(QString::number(value) + "%");
}
void MainDialog::on_buttonBox_clicked(QAbstractButton* button)
{
QPushButton *pushButton = (QPushButton *)button;
QPushButton *okButton = this->buttonBox->button(QDialogButtonBox::Ok);
int volume = this->volumeSlider->value();
bool muted = this->mutedCheckbox->isChecked();
if (pushButton == okButton)
{
CoreSettingsSetValue(SettingsID::Audio_Volume, volume);
CoreSettingsSetValue(SettingsID::Audio_Muted, muted);
CoreSettingsSave();
}
}
@@ -0,0 +1,33 @@
/*
* 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 MAINWINDOW_HPP
#define MAINWINDOW_HPP
#include <QDialog>
#include <QAbstractButton>
#include "ui_MainDialog.h"
namespace UserInterface
{
class MainDialog : public QDialog, private Ui::MainDialog
{
Q_OBJECT
public:
MainDialog(QWidget *parent);
~MainDialog(void);
private slots:
void on_volumeSlider_valueChanged(int value);
void on_buttonBox_clicked(QAbstractButton* button);
};
}
#endif // MAINWINDOW_HPP
@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainDialog</class>
<widget class="QDialog" name="MainDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>330</width>
<height>476</height>
</rect>
</property>
<property name="windowTitle">
<string>Rosalie's Mupen GUI - Audio Plugin</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item alignment="Qt::AlignHCenter">
<widget class="QSlider" name="volumeSlider">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="pageStep">
<number>10</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QLabel" name="volumeLabel">
<property name="text">
<string>0%</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="mutedCheckbox">
<property name="text">
<string>Muted</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>MainDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>MainDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

@@ -0,0 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>Resource/RMG.png</file>
</qresource>
</RCC>
+351
View File
@@ -0,0 +1,351 @@
/*
* 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/>.
*/
#define CORE_PLUGIN 1
#define M64P_PLUGIN_PROTOTYPES 1
#define AUDIO_PLUGIN_API_VERSION 0x020100
#include <SDL.h>
#include <SDL_audio.h>
#include <UserInterface/MainDialog.hpp>
#include <RMG-Core/Core.hpp>
//
// Local variables
//
static SDL_AudioDeviceID l_SDLDevice;
static SDL_AudioSpec* l_HardwareSpec = nullptr;
static bool l_PluginInit = false;
static int l_GameFreq = 0;
static AUDIO_INFO l_AudioInfo;
static bool l_VolIsMuted = false;
static bool l_Paused = false;
static bool l_FastForward = false;
static int l_VolSDL = SDL_MIX_MAXVOLUME;
static SDL_AudioStream* l_AudioStream = nullptr;
static uint8_t l_PrimaryBuffer[0x40000];
static uint8_t l_OutputBuffer[0x40000];
static uint8_t l_MixBuffer[0x40000];
//
// Local Functions
//
static void load_settings(void)
{
l_VolIsMuted = CoreSettingsGetBoolValue(SettingsID::Audio_Muted);
l_VolSDL = SDL_MIX_MAXVOLUME * CoreSettingsGetIntValue(SettingsID::Audio_Volume) / 100;
l_FastForward = false;
}
//
// Basic Plugin Functions
//
EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context, void (*DebugCallback)(void *, int, const char *))
{
if (l_PluginInit)
{
return M64ERR_ALREADY_INIT;
}
if (SDL_Init(SDL_INIT_AUDIO) < 0)
{
return M64ERR_SYSTEM_FAIL;
}
if (!CoreInit(CoreLibHandle))
{
return M64ERR_SYSTEM_FAIL;
}
load_settings();
l_PluginInit = true;
return M64ERR_SUCCESS;
}
EXPORT m64p_error CALL PluginShutdown(void)
{
if (!l_PluginInit)
{
return M64ERR_NOT_INIT;
}
if (l_HardwareSpec != nullptr)\
{
free(l_HardwareSpec);
l_HardwareSpec = NULL;
}
SDL_QuitSubSystem(SDL_INIT_AUDIO);
l_PluginInit = false;
return M64ERR_SUCCESS;
}
EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *pluginType, int *pluginVersion,
int *apiVersion, const char **pluginNamePtr, int *capabilities)
{
if (pluginType != nullptr)
{
*pluginType = M64PLUGIN_AUDIO;
}
if (pluginVersion != nullptr)
{
*pluginVersion = 0x010000;
}
if (apiVersion != nullptr)
{
*apiVersion = AUDIO_PLUGIN_API_VERSION;
}
if (pluginNamePtr != nullptr)
{
*pluginNamePtr = "Rosalie's Mupen GUI - Audio Plugin";
}
if (capabilities != nullptr)
{
*capabilities = 0;
}
return M64ERR_SUCCESS;
}
//
// Custom Plugin Functions
//
EXPORT m64p_error CALL PluginConfig(void)
{
if (!l_PluginInit)
{
return M64ERR_NOT_INIT;
}
UserInterface::MainDialog dialog(nullptr);
dialog.exec();
// reload settings
load_settings();
return M64ERR_SUCCESS;
}
//
// Audio Plugin Functions
//
EXPORT void CALL AiDacrateChanged( int SystemType )
{
if (!l_PluginInit)
{
return;
}
switch (SystemType)
{
case SYSTEM_NTSC:
l_GameFreq = 48681812 / (*l_AudioInfo.AI_DACRATE_REG + 1);
break;
case SYSTEM_PAL:
l_GameFreq = 49656530 / (*l_AudioInfo.AI_DACRATE_REG + 1);
break;
case SYSTEM_MPAL:
l_GameFreq = 48628316 / (*l_AudioInfo.AI_DACRATE_REG + 1);
break;
}
SDL_FreeAudioStream(l_AudioStream);
l_AudioStream = SDL_NewAudioStream(AUDIO_S16SYS, 2, l_GameFreq, l_HardwareSpec->format, 2, l_HardwareSpec->freq);
}
EXPORT void CALL AiLenChanged( void )
{
if (!l_PluginInit)
{
return;
}
unsigned int LenReg = *l_AudioInfo.AI_LEN_REG;
unsigned char *p = l_AudioInfo.RDRAM + (*l_AudioInfo.AI_DRAM_ADDR_REG & 0xFFFFFF);
unsigned int i;
for ( i = 0 ; i < LenReg ; i += 4 )
{
// Left channel
l_PrimaryBuffer[ i ] = p[ i + 2 ];
l_PrimaryBuffer[ i + 1 ] = p[ i + 3 ];
// Right channel
l_PrimaryBuffer[ i + 2 ] = p[ i ];
l_PrimaryBuffer[ i + 3 ] = p[ i + 1 ];
}
if (!l_VolIsMuted && !l_FastForward)
{
unsigned int audio_queued = SDL_GetQueuedAudioSize(l_SDLDevice);
unsigned int acceptable_latency = (l_HardwareSpec->freq * 0.2) * 4;
unsigned int min_latency = (l_HardwareSpec->freq * 0.02) * 4;
if (!l_Paused && audio_queued < min_latency)
{
SDL_PauseAudioDevice(l_SDLDevice, 1);
l_Paused = true;
}
else if (l_Paused && audio_queued >= (min_latency * 2))
{
SDL_PauseAudioDevice(l_SDLDevice, 0);
l_Paused = true;
}
if (audio_queued < acceptable_latency)
{
SDL_AudioStreamPut(l_AudioStream, l_PrimaryBuffer, LenReg);
}
int output_length = SDL_AudioStreamGet(l_AudioStream, l_OutputBuffer, sizeof(l_OutputBuffer));
if (output_length > 0)
{
SDL_memset(l_MixBuffer, 0, output_length);
SDL_MixAudioFormat(l_MixBuffer, l_OutputBuffer, l_HardwareSpec->format, output_length, l_VolSDL);
SDL_QueueAudio(l_SDLDevice, l_MixBuffer, output_length);
}
}
}
EXPORT int CALL InitiateAudio( AUDIO_INFO Audio_Info )
{
if (!l_PluginInit)
{
return 0;
}
l_GameFreq = 33600;
l_AudioInfo = Audio_Info;
return 1;
}
EXPORT int CALL RomOpen(void)
{
if (!l_PluginInit)
{
return 0;
}
SDL_AudioSpec *desired, *obtained;
if (l_HardwareSpec != nullptr)
{
free(l_HardwareSpec);
}
desired = (SDL_AudioSpec*)malloc(sizeof(SDL_AudioSpec));
obtained = (SDL_AudioSpec*)malloc(sizeof(SDL_AudioSpec));
desired->freq = 44100;
desired->format = AUDIO_S16SYS;
desired->channels = 2;
desired->samples = 1024;
desired->callback = nullptr;
desired->userdata = nullptr;
const char *dev_name = SDL_GetAudioDeviceName(-1, 0);
l_SDLDevice = SDL_OpenAudioDevice(dev_name, 0, desired, obtained, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
free(desired);
l_HardwareSpec = obtained;
SDL_PauseAudioDevice(l_SDLDevice, 0);
l_Paused = 0;
l_AudioStream = SDL_NewAudioStream(AUDIO_S16SYS, 2, l_GameFreq, l_HardwareSpec->format, 2, l_HardwareSpec->freq);
return 1;
}
EXPORT void CALL RomClosed( void )
{
if (!l_PluginInit)
{
return;
}
SDL_ClearQueuedAudio(l_SDLDevice);
SDL_CloseAudioDevice(l_SDLDevice);
if (l_HardwareSpec != nullptr)
{
free(l_HardwareSpec);
l_HardwareSpec = nullptr;
}
SDL_FreeAudioStream(l_AudioStream);
l_AudioStream = nullptr;
}
EXPORT void CALL ProcessAList(void)
{
}
EXPORT void CALL SetSpeedFactor(int percentage)
{
if (percentage > 100)
{
l_FastForward = true;
}
else
{
l_FastForward = false;
}
}
EXPORT void CALL VolumeMute(void)
{
if (!l_PluginInit)
{
return;
}
l_VolIsMuted = !l_VolIsMuted;
}
EXPORT void CALL VolumeUp(void)
{
}
EXPORT void CALL VolumeDown(void)
{
}
EXPORT int CALL VolumeGetLevel(void)
{
return l_VolIsMuted ? 0 : 100;
}
EXPORT void CALL VolumeSetLevel(int level)
{
if (level < 0)
{
level = 0;
}
else if (level > 100)
{
level = 100;
}
l_VolSDL = SDL_MIX_MAXVOLUME * level / 100;
}
EXPORT const char * CALL VolumeGetString(void)
{
return "";
}
+13 -1
View File
@@ -4,11 +4,14 @@
project(RMG-Core)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
find_package(PkgConfig REQUIRED)
pkg_check_modules(SDL2 REQUIRED sdl2)
pkg_check_modules(MINIZIP REQUIRED minizip)
configure_file(Config.hpp.in Config.hpp)
set(RMG_CORE_SOURCES
m64p/Api.cpp
m64p/CoreApi.cpp
@@ -17,8 +20,9 @@ set(RMG_CORE_SOURCES
Settings/Settings.cpp
SpeedLimiter.cpp
RomSettings.cpp
RomHeader.cpp
Directories.cpp
Screenshot.cpp
RomHeader.cpp
Emulation.cpp
SaveState.cpp
Callback.cpp
@@ -41,12 +45,20 @@ else()
)
endif()
if (PORTABLE_INSTALL)
add_definitions(-DPORTABLE_INSTALL)
endif(PORTABLE_INSTALL)
add_library(RMG-Core STATIC ${RMG_CORE_SOURCES})
if(UNIX)
target_link_libraries(RMG-Core dl)
endif(UNIX)
if(WIN32)
target_link_libraries(RMG-Core wsock32 ws2_32)
endif(WIN32)
target_link_libraries(RMG-Core
${MINIZIP_LIBRARIES}
)
+17
View File
@@ -0,0 +1,17 @@
/*
* 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_CONFIG_HPP
#define CORE_CONFIG_HPP
#ifndef PORTABLE_INSTALL
#define CORE_INSTAlL_PREFIX "${CMAKE_INSTALL_PREFIX}"
#endif // PORTABLE_INSTALL
#endif // CORE_CONFIG_HPP
+27 -3
View File
@@ -27,7 +27,7 @@ static osal_dynlib_lib_handle l_CoreLibHandle;
std::string find_core_lib(void)
{
for (const auto& entry : std::filesystem::recursive_directory_iterator("Core"))
for (const auto& entry : std::filesystem::recursive_directory_iterator(CoreGetCoreDirectory()))
{
std::string path = entry.path().string();
if (path.ends_with(OSAL_DYNLIB_LIB_EXT_STR))
@@ -110,7 +110,7 @@ bool CoreInit(void)
return false;
}
m64p_ret = m64p::Core.Startup(FRONTEND_API_VERSION, "Config", "Data", nullptr, CoreDebugCallback, nullptr, CoreStateCallback);
m64p_ret = m64p::Core.Startup(FRONTEND_API_VERSION, CoreGetUserConfigDirectory().c_str(), CoreGetSharedDataDirectory().c_str(), nullptr, CoreDebugCallback, nullptr, CoreStateCallback);
if (m64p_ret != M64ERR_SUCCESS)
{
error = "CoreInit M64P::Core.Startup() Failed: ";
@@ -130,7 +130,7 @@ bool CoreInit(void)
return false;
}
ret = CoreApplyPluginSettings();
ret = CoreCreateDirectories();
if (!ret)
{
return false;
@@ -139,6 +139,30 @@ bool CoreInit(void)
return true;
}
bool CoreInit(m64p_dynlib_handle handle)
{
std::string error;
bool ret = false;
ret = m64p::Core.Hook(handle);
if (!ret)
{
error = m64p::Core.GetLastError();
CoreSetError(error);
return false;
}
ret = m64p::Config.Hook(handle);
if (!ret)
{
error = m64p::Config.GetLastError();
CoreSetError(error);
return false;
}
return true;
}
void CoreShutdown(void)
{
CorePluginsShutdown();
+17
View File
@@ -13,6 +13,7 @@
#include "Settings/Settings.hpp"
#include "SpeedLimiter.hpp"
#include "RomSettings.hpp"
#include "Directories.hpp"
#include "Screenshot.hpp"
#include "Emulation.hpp"
#include "SaveState.hpp"
@@ -22,11 +23,27 @@
#include "Error.hpp"
#include "Video.hpp"
#include "Key.hpp"
#include "Rom.hpp"
#ifdef CORE_PLUGIN
#include "m64p/api/m64p_common.h"
#include "m64p/api/m64p_custom.h"
#include "m64p/api/m64p_types.h"
#include "m64p/api/m64p_config.h"
#include "m64p/api/m64p_plugin.h"
#include "m64p/api/version.h"
#endif // CORE_PLUGIN
// initializes the core library,
// returns false when failed
bool CoreInit(void);
#ifdef CORE_PLUGIN
// initializes the core library for plugins,
// returns false when failed
bool CoreInit(m64p_dynlib_handle handle);
#endif // CORE_PLUGIN
// shuts down the core library
void CoreShutdown(void);
+201
View File
@@ -0,0 +1,201 @@
/*
* 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 "Directories.hpp"
#include "Config.hpp"
#include "Error.hpp"
#include "Core.hpp"
#include <cstdio>
#include <iostream>
#include <filesystem>
//
// Local Functions
//
static std::string get_var_directory(std::string var, std::string append, std::string fallbackVar, std::string fallbackAppend)
{
std::string directory;
const char* env = std::getenv(var.c_str());
if (env == nullptr)
{
env = std::getenv(fallbackVar.c_str());
if (env == nullptr)
{
std::cerr << "get_var_directory: fallbackVar: $" << fallbackVar << " cannot be nullptr!" << std::endl;
std::terminate();
}
directory = env;
directory += fallbackAppend;
}
else
{
directory = env;
directory += append;
}
return directory;
}
//
// Exported Functions
//
bool CoreCreateDirectories(void)
{
std::string error;
std::string directories[] =
{
#ifdef PORTABLE_INSTALL
CoreGetCoreDirectory(),
CoreGetPluginDirectory(),
CoreGetSharedDataDirectory(),
#endif // PORTABLE_INSTALL
CoreGetUserConfigDirectory(),
CoreGetUserDataDirectory(),
CoreGetUserCacheDirectory(),
CoreGetSaveDirectory(),
CoreGetSaveStateDirectory()
};
for (const auto& dir : directories)
{
try
{
std::filesystem::create_directories(dir);
}
catch (...)
{
error = "CoreCreateDirectories Failed: cannot create the '";
error += dir;
error += "' directory!";
CoreSetError(error);
return false;
}
}
return true;
}
std::string CoreGetCoreDirectory(void)
{
std::string directory;
#ifdef PORTABLE_INSTALL
directory = "Core";
#else // Not Portable
directory = CORE_INSTAlL_PREFIX;
directory += "/lib/RMG/Core";
#endif // PORTABLE_INSTALL
return directory;
}
std::string CoreGetPluginDirectory(void)
{
std::string directory;
#ifdef PORTABLE_INSTALL
directory = "Plugin";
#else // Not Portable
directory = CORE_INSTAlL_PREFIX;
directory += "/lib/RMG/Plugin";
#endif // PORTABLE_INSTALL
return directory;
}
std::string CoreGetUserConfigDirectory(void)
{
std::string directory;
#ifdef PORTABLE_INSTALL
directory = "Config";
#else // Not Portable
directory = get_var_directory("XDG_CONFIG_HOME", "/RMG", "HOME", "/.config/RMG");
#endif // PORTABLE_INSTALL
return directory;
}
std::string CoreGetDefaultUserDataDirectory(void)
{
std::string directory;
#ifdef PORTABLE_INSTALL
directory = "Data";
#else // Not Portable
directory = get_var_directory("XDG_DATA_HOME", "/RMG", "HOME", "/.local/share/RMG");
#endif // PORTABLE_INSTALL
return directory;
}
std::string CoreGetDefaultUserCacheDirectory(void)
{
std::string directory;
#ifdef PORTABLE_INSTALL
directory = "Cache";
#else // Not Portable
directory = get_var_directory("XDG_CACHE_HOME", "/RMG", "HOME", "/.cache/RMG");
#endif // PORTABLE_INSTALL
return directory;
}
std::string CoreGetDefaultSaveDirectory(void)
{
std::string directory;
#ifdef PORTABLE_INSTALL
directory = "Save/Game";
#else
directory = CoreGetUserDataDirectory();
directory += "/Save/Game";
#endif // PORTABLE_INSTALL
return directory;
}
std::string CoreGetDefaultSaveStateDirectory(void)
{
std::string directory;
#ifdef PORTABLE_INSTALL
directory = "Save/State";
#else
directory = CoreGetUserDataDirectory();
directory += "/Save/State";
#endif // PORTABLE_INSTALL
return directory;
}
std::string CoreGetUserDataDirectory(void)
{
return CoreSettingsGetStringValue(SettingsID::Core_UserDataDirOverride);
}
std::string CoreGetUserCacheDirectory(void)
{
return CoreSettingsGetStringValue(SettingsID::Core_UserCacheDirOverride);
}
std::string CoreGetSharedDataDirectory(void)
{
std::string directory;
#ifdef PORTABLE_INSTALL
directory = "Data";
#else // Not Portable
directory = CORE_INSTAlL_PREFIX;
directory += "/share/RMG";
#endif // PORTABLE_INSTALL
return directory;
}
std::string CoreGetSaveDirectory(void)
{
return CoreSettingsGetStringValue(SettingsID::Core_SaveSRAMPath);
}
std::string CoreGetSaveStateDirectory(void)
{
return CoreSettingsGetStringValue(SettingsID::Core_SaveStatePath);
}
+68
View File
@@ -0,0 +1,68 @@
/*
* 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 DIRECTORIES_HPP
#define DIRECTORIES_HPP
#include <string>
// tries to create the needed directories,
// returns false when failed
bool CoreCreateDirectories(void);
// returns the core directory where
// the mupen64plus library should be
// located
std::string CoreGetCoreDirectory(void);
// returns the plugin directory where
// plugins should be located
std::string CoreGetPluginDirectory(void);
// returns the default user data directory where
// data files should be located
std::string CoreGetDefaultUserDataDirectory(void);
// returns the default user cache directory where
// cache files should be located
std::string CoreGetDefaultUserCacheDirectory(void);
// returns the default save directory where
// game saves should be located
std::string CoreGetDefaultSaveDirectory(void);
// returns the default save state directory where
// save states should be located
std::string CoreGetDefaultSaveStateDirectory(void);
// returns the user config directory where
// configuration files should be located
std::string CoreGetUserConfigDirectory(void);
// returns the user data directory where
// data files should be located
std::string CoreGetUserDataDirectory(void);
// returns the user cache directory where
// cache files should be located
std::string CoreGetUserCacheDirectory(void);
// returns the shared data directory where
// shared data files should be located
std::string CoreGetSharedDataDirectory(void);
// returns the save directory where
// game saves should be located
std::string CoreGetSaveDirectory(void);
// returns the save state directory where
// save states should be located
std::string CoreGetSaveStateDirectory(void);
#endif // DIRECTORIES_HPP
+6
View File
@@ -49,16 +49,22 @@ bool CoreStartEmulation(std::string n64rom, std::string n64ddrom)
if (!CoreApplyRomPluginSettings())
{
CoreApplyPluginSettings();
CoreCloseRom();
return false;
}
if (!CoreArePluginsReady())
{
CoreApplyPluginSettings();
CoreCloseRom();
return false;
}
if (!CoreAttachPlugins())
{
CoreApplyPluginSettings();
CoreCloseRom();
return false;
}
+184 -156
View File
@@ -8,7 +8,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "Plugins.hpp"
#include "Directories.hpp"
#include "Error.hpp"
#include "Emulation.hpp"
#include "RomSettings.hpp"
#include "Settings/Settings.hpp"
@@ -71,6 +73,138 @@ std::string get_plugin_name(m64p::PluginApi* plugin, std::string filename)
return std::string(name);
}
std::string get_plugin_type_name(CorePluginType type)
{
std::string name;
switch (type)
{
default:
name = "Unknown";
break;
case CorePluginType::Rsp:
name = "Rsp";
break;
case CorePluginType::Gfx:
name = "Gfx";
break;
case CorePluginType::Audio:
name = "Audio";
break;
case CorePluginType::Input:
name = "Input";
break;
case CorePluginType::Invalid:
name = "Invalid";
break;
}
return name + " Plugin";
}
bool apply_plugin_settings(std::string pluginSettings[4])
{
std::string error;
std::string settingValue;
m64p::PluginApi* plugin;
CorePluginType pluginType;
osal_dynlib_lib_handle handle;
m64p_error ret;
for (int i = 0; i < 4; i++)
{
settingValue = pluginSettings[i];
if (settingValue.empty() ||
!std::filesystem::is_regular_file(settingValue))
{ // skip invalid setting value
continue;
}
pluginType = (CorePluginType)(i + 1);
if (settingValue != l_PluginFiles[i])
{
plugin = &l_Plugins[i];
// shutdown plugin when hooked
if (plugin->IsHooked())
{
ret = plugin->Shutdown();
if (ret != M64ERR_SUCCESS)
{
error = "apply_plugin_settings (";
error += get_plugin_type_name(pluginType);
error += ")->Shutdown() Failed: ";
error += m64p::Core.ErrorMessage(ret);
CoreSetError(error);
return false;
}
// reset plugin
plugin->Unhook();
}
// attempt to open the library
handle = osal_dynlib_open(settingValue.c_str());
if (handle == nullptr)
{
error = "apply_plugin_settings osal_dynlib_open Failed: ";
error += osal_dynlib_strerror();
CoreSetError(error);
return false;
}
// attempt to hook the library
if (!plugin->Hook(handle))
{
error = "apply_plugin_settings (";
error += get_plugin_type_name(pluginType);
error += ")->Hook() Failed: ";
error += plugin->GetLastError();
CoreSetError(error);
plugin->Unhook();
return false;
}
// make sure the plugin type is the expected type
if (get_plugin_type(plugin) != pluginType)
{
error = "apply_plugin_settings plugin type ";
error += get_plugin_type_name(get_plugin_type(plugin));
error += " doesn't match expected type ";
error += get_plugin_type_name(pluginType);
error += "!";
CoreSetError(error);
plugin->Unhook();
return false;
}
// attempt to start plugin
ret = plugin->Startup(m64p::Core.GetHandle(), nullptr, nullptr);
if (ret != M64ERR_SUCCESS)
{
error = "apply_plugin_settings (";
error += get_plugin_type_name(pluginType);
error += ")->Startup() Failed: ";
error += m64p::Core.ErrorMessage(ret);
CoreSetError(error);
plugin->Shutdown();
plugin->Unhook();
// force a re-load next time,
// because this plugin isn't
// the one we've stored in
// l_PluginFiles[i]
l_PluginFiles[i].clear();
return false;
}
l_PluginFiles[i] = settingValue;
}
}
return true;
}
//
// Exported Functions
//
@@ -83,7 +217,7 @@ std::vector<CorePlugin> CoreGetAllPlugins(void)
osal_dynlib_lib_handle handle;
m64p::PluginApi plugin;
for (const auto& entry : std::filesystem::recursive_directory_iterator("Plugin"))
for (const auto& entry : std::filesystem::recursive_directory_iterator(CoreGetPluginDirectory()))
{
std::string path = entry.path().string();
if (!entry.is_directory() &&
@@ -116,170 +250,35 @@ std::vector<CorePlugin> CoreGetAllPlugins(void)
bool CoreApplyPluginSettings(void)
{
std::string error;
std::string settingValue;
m64p::PluginApi* plugin;
osal_dynlib_lib_handle handle;
m64p_error ret;
SettingsID settings[] =
std::string settings[] =
{
SettingsID::Core_RSP_Plugin,
SettingsID::Core_GFX_Plugin,
SettingsID::Core_AUDIO_Plugin,
SettingsID::Core_INPUT_Plugin
CoreSettingsGetStringValue(SettingsID::Core_RSP_Plugin),
CoreSettingsGetStringValue(SettingsID::Core_GFX_Plugin),
CoreSettingsGetStringValue(SettingsID::Core_AUDIO_Plugin),
CoreSettingsGetStringValue(SettingsID::Core_INPUT_Plugin)
};
for (int i = 0; i < 4; i++)
{
settingValue = CoreSettingsGetStringValue(settings[i]);
if (settingValue.empty() ||
!std::filesystem::is_regular_file(settingValue))
{ // skip invalid setting value
continue;
}
if (settingValue != l_PluginFiles[i])
{
plugin = &l_Plugins[i];
// shutdown plugin when hooked
if (plugin->IsHooked())
{
ret = plugin->Shutdown();
if (ret != M64ERR_SUCCESS)
{
error = "CoreApplyPluginSettings m64p::PluginApi.Shutdown() Failed: ";
error += m64p::Core.ErrorMessage(ret);
CoreSetError(error);
return false;
}
// reset plugin
plugin->Unhook();
}
// attempt to open the library
handle = osal_dynlib_open(settingValue.c_str());
if (handle == nullptr)
{
error = "CoreApplyPluginSettings osal_dynlib_open Failed: ";
error += osal_dynlib_strerror();
CoreSetError(error);
return false;
}
// attempt to hook the library
if (!plugin->Hook(handle))
{
error = "CoreApplyPluginSettings m64p::PluginApi.Hook() Failed: ";
error += plugin->GetLastError();
CoreSetError(error);
return false;
}
// attempt to start plugin
ret = plugin->Startup(m64p::Core.GetHandle(), nullptr, nullptr);
if (ret != M64ERR_SUCCESS)
{
error = "CoreApplyPluginSettings m64p::PluginApi.Startup() Failed: ";
error += m64p::Core.ErrorMessage(ret);
CoreSetError(error);
return false;
}
l_PluginFiles[i] = settingValue;
}
}
return true;
return apply_plugin_settings(settings);
}
bool CoreApplyRomPluginSettings(void)
{
std::string error;
std::string settingValue;
m64p::PluginApi* plugin;
osal_dynlib_lib_handle handle;
m64p_error ret;
CoreRomSettings romSettings;
SettingsID settings[] =
{
SettingsID::Game_RSP_Plugin,
SettingsID::Game_GFX_Plugin,
SettingsID::Game_AUDIO_Plugin,
SettingsID::Game_INPUT_Plugin
};
CoreRomSettings romSettings;
if (!CoreGetCurrentDefaultRomSettings(romSettings))
{
return false;
}
for (int i = 0; i < 4; i++)
std::string settings[] =
{
settingValue = CoreSettingsGetStringValue(settings[i], romSettings.MD5);
if (settingValue.empty() ||
!std::filesystem::is_regular_file(settingValue))
{ // skip invalid setting value
continue;
}
CoreSettingsGetStringValue(SettingsID::Game_RSP_Plugin, romSettings.MD5),
CoreSettingsGetStringValue(SettingsID::Game_GFX_Plugin, romSettings.MD5),
CoreSettingsGetStringValue(SettingsID::Game_AUDIO_Plugin, romSettings.MD5),
CoreSettingsGetStringValue(SettingsID::Game_INPUT_Plugin, romSettings.MD5)
};
if (settingValue != l_PluginFiles[i])
{
plugin = &l_Plugins[i];
// shutdown plugin when hooked
if (plugin->IsHooked())
{
ret = plugin->Shutdown();
if (ret != M64ERR_SUCCESS)
{
error = "CoreApplyPluginSettings m64p::PluginApi.Shutdown() Failed: ";
error += m64p::Core.ErrorMessage(ret);
CoreSetError(error);
return false;
}
// reset plugin
plugin->Unhook();
}
// attempt to open the library
handle = osal_dynlib_open(settingValue.c_str());
if (handle == nullptr)
{
error = "CoreApplyPluginSettings osal_dynlib_open Failed: ";
error += osal_dynlib_strerror();
CoreSetError(error);
return false;
}
// attempt to hook the library
if (!plugin->Hook(handle))
{
error = "CoreApplyPluginSettings m64p::PluginApi.Hook() Failed: ";
error += plugin->GetLastError();
CoreSetError(error);
return false;
}
// attempt to start plugin
ret = plugin->Startup(m64p::Core.GetHandle(), nullptr, nullptr);
if (ret != M64ERR_SUCCESS)
{
error = "CoreApplyPluginSettings m64p::PluginApi.Startup() Failed: ";
error += m64p::Core.ErrorMessage(ret);
CoreSetError(error);
return false;
}
l_PluginFiles[i] = settingValue;
}
}
return true;
return apply_plugin_settings(settings);
}
bool CoreArePluginsReady(void)
@@ -291,7 +290,9 @@ bool CoreArePluginsReady(void)
if (!l_Plugins[i].IsHooked())
{
error = "CoreArePluginsReady Failed: ";
error += "PluginApi::IsHooked returned false!";
error += "(";
error += get_plugin_type_name((CorePluginType)(i + 1));
error += ")->IsHooked returned false!";
CoreSetError(error);
return false;
}
@@ -309,23 +310,44 @@ bool CorePluginsOpenConfig(CorePluginType type)
{
std::string error;
m64p_error ret;
bool resumeEmulation = false;
if (!CorePluginsHasConfig(type))
{
error = "CorePluginsOpenConfig Failed: ";
error += "plugin with given type doesn't have config function!";
error += get_plugin_type_name(type);
error += " doesn't have config function!";
CoreSetError(error);
return false;
}
// try to pause emulation,
// when emulation is running
// and try to resume afterwards
if (CoreIsEmulationRunning())
{
// only resume emulation
// after running the config function
// when pausing succeeds
resumeEmulation = CorePauseEmulation();
}
ret = get_plugin(type)->Config();
if (ret != M64ERR_SUCCESS)
{
error = "CorePluginsOpenConfig m64p::PluginApi.Config() Failed: ";
error = "CorePluginsOpenConfig (";
error += get_plugin_type_name(type);
error += ")->Config() Failed: ";
error += m64p::Core.ErrorMessage(ret);
CoreSetError(error);
}
// try to resume emulation when needed
if (resumeEmulation)
{
CoreResumeEmulation();
}
return ret == M64ERR_SUCCESS;
}
@@ -346,7 +368,9 @@ bool CoreAttachPlugins(void)
ret = m64p::Core.AttachPlugin(plugin_types[i], get_plugin((CorePluginType)plugin_types[i])->GetHandle());
if (ret != M64ERR_SUCCESS)
{
error = "CoreAttachPlugins m64p::Core.AttachPlugin() Failed: ";
error = "CoreAttachPlugins m64p::Core.AttachPlugin(";
error += get_plugin_type_name((CorePluginType)plugin_types[i]);
error += ") Failed: ";
error += m64p::Core.ErrorMessage(ret);
CoreSetError(error);
break;
@@ -366,7 +390,9 @@ bool CoreDetachPlugins(void)
ret = m64p::Core.DetachPlugin((m64p_plugin_type)(i + 1));
if (ret != M64ERR_SUCCESS)
{
error = "CoreDetachPlugins m64p::Core.DetachPlugin() Failed: ";
error = "CoreDetachPlugins m64p::Core.DetachPlugin(";
error += get_plugin_type_name((CorePluginType)(i + 1));
error += ") Failed: ";
error += m64p::Core.ErrorMessage(ret);
CoreSetError(error);
break;
@@ -392,7 +418,9 @@ bool CorePluginsShutdown(void)
ret = plugin->Shutdown();
if (ret != M64ERR_SUCCESS)
{
error = "CorePluginsShutdown m64p::PluginApi.Shutdown() Failed: ";
error = "CorePluginsShutdown (";
error += get_plugin_type_name((CorePluginType)(i + 1));
error += ")->Shutdown() Failed: ";
error += m64p::Core.ErrorMessage(ret);
CoreSetError(error);
break;
-11
View File
@@ -214,17 +214,6 @@ static bool read_raw_file(std::string file, char** buf, int* size)
// read file
fileStream.read(fileStreamBuf, fileStreamLen);
// make sure that we've read the entire file
if (fileStream.tellg() != fileStreamLen)
{
error = "read_raw_file Failed: ";
error += "failed to read entire file!";
CoreSetError(error);
free(fileStreamBuf);
fileStream.close();
return false;
}
*buf = fileStreamBuf;
*size = fileStreamLen;
+8 -2
View File
@@ -13,6 +13,12 @@
#include "Error.hpp"
#include "Rom.hpp"
#ifdef _WIN32
#include <winsock2.h>
#else // Unix
#include <arpa/inet.h>
#endif // _WIN32
//
// Exported Functions
//
@@ -32,8 +38,8 @@ bool CoreGetCurrentRomHeader(CoreRomHeader& header)
return false;
}
header.CRC1 = m64p_header.CRC1;
header.CRC2 = m64p_header.CRC2;
header.CRC1 = ntohl(m64p_header.CRC1);
header.CRC2 = ntohl(m64p_header.CRC2);
header.Name = std::string((char*)m64p_header.Name);
return true;
}
+108 -75
View File
@@ -9,6 +9,7 @@
*/
#include "Settings.hpp"
#include "Directories.hpp"
#include "m64p/Api.hpp"
#include "Error.hpp"
#include "m64p/api/m64p_types.h"
@@ -64,6 +65,12 @@ struct l_DynamicValue
valueType = M64TYPE_STRING;
}
l_DynamicValue(std::string value)
{
stringValue = value;
valueType = M64TYPE_STRING;
}
l_DynamicValue(std::vector<int> value)
{
intListValue = value;
@@ -79,14 +86,14 @@ struct l_DynamicValue
}
};
typedef struct
struct l_Setting
{
std::string Section;
std::string Key;
l_DynamicValue DefaultValue;
std::string Description;
bool ForceUseSet;
} l_Setting;
std::string Description = "";
bool ForceUseSetOnce = false;
};
//
// Local Variables
@@ -104,7 +111,9 @@ static std::vector<std::string> l_sectionList;
#define SETTING_SECTION_OVERLAY SETTING_SECTION_CORE " Overlay"
#define SETTING_SECTION_KEYBIND SETTING_SECTION_GUI " KeyBindings"
#define SETTING_SECTION_ROMBROWSER SETTING_SECTION_GUI " RomBrowser"
#define SETTING_SECTION_SETTINGS SETTING_SECTION_CORE " Settings"
#define SETTING_SECTION_M64P "Core"
#define SETTING_SECTION_AUDIO SETTING_SECTION_GUI " - Audio Plugin"
// retrieves l_Setting from settingId
static l_Setting get_setting(SettingsID settingId)
@@ -118,222 +127,239 @@ static l_Setting get_setting(SettingsID settingId)
break;
case SettingsID::GUI_SettingsDialogWidth:
setting = {SETTING_SECTION_GUI, "SettingsDialogWidth", 0, "", false};
setting = {SETTING_SECTION_GUI, "SettingsDialogWidth", 0};
break;
case SettingsID::GUI_SettingsDialogHeight:
setting = {SETTING_SECTION_GUI, "SettingsDialogHeight", 0, "", false};
setting = {SETTING_SECTION_GUI, "SettingsDialogHeight", 0};
break;
case SettingsID::GUI_AllowManualResizing:
setting = {SETTING_SECTION_GUI, "AllowManualResizing", true, "", false};
setting = {SETTING_SECTION_GUI, "AllowManualResizing", true};
break;
case SettingsID::GUI_HideCursorInEmulation:
setting = {SETTING_SECTION_GUI, "HideCursorInEmulation", false, "", false};
setting = {SETTING_SECTION_GUI, "HideCursorInEmulation", false};
break;
case SettingsID::GUI_StatusbarMessageDuration:
setting = {SETTING_SECTION_GUI, "StatusbarMessageDuration", 3, "", false};
setting = {SETTING_SECTION_GUI, "StatusbarMessageDuration", 3};
break;
case SettingsID::GUI_PauseEmulationOnFocusLoss:
setting = {SETTING_SECTION_GUI, "PauseEmulationOnFocusLoss", true};
break;
case SettingsID::GUI_ResumeEmulationOnFocus:
setting = {SETTING_SECTION_GUI, "ResumeEmulationOnFocus", true};
break;
case SettingsID::Core_GFX_Plugin:
setting = {SETTING_SECTION_CORE, "GFX_Plugin",
#ifdef _WIN32
"Plugin\\GFX\\mupen64plus-video-GLideN64.dll",
CoreGetPluginDirectory() + "\\GFX\\mupen64plus-video-GLideN64.dll",
#else
"Plugin/GFX/mupen64plus-video-GLideN64.so",
CoreGetPluginDirectory() + "/GFX/mupen64plus-video-GLideN64.so",
#endif // _WIN32
"", false};
};
break;
case SettingsID::Core_AUDIO_Plugin:
setting = {SETTING_SECTION_CORE, "AUDIO_Plugin",
#ifdef _WIN32
"Plugin\\Audio\\mupen64plus-audio-sdl2.dll",
CoreGetPluginDirectory() + "\\Audio\\RMG-Audio.dll",
#else
"Plugin/Audio/mupen64plus-audio-sdl2.so",
CoreGetPluginDirectory() + "/Audio/RMG-Audio.so",
#endif // _WIN32
"", false};
};
break;
case SettingsID::Core_INPUT_Plugin:
setting = {SETTING_SECTION_CORE, "INPUT_Plugin",
#ifdef _WIN32
"Plugin\\Input\\libmupen64plus-input-qt.dll",
CoreGetPluginDirectory() + "\\Input\\libmupen64plus-input-qt.dll",
#else
"Plugin/Input/libmupen64plus-input-qt.so",
CoreGetPluginDirectory() + "/Input/libmupen64plus-input-qt.so",
#endif // _WIN32
"", false};
};
break;
case SettingsID::Core_RSP_Plugin:
setting = {SETTING_SECTION_CORE, "RSP_Plugin",
#ifdef _WIN32
"Plugin\\RSP\\mupen64plus-rsp-hle.dll",
CoreGetPluginDirectory() + "\\RSP\\mupen64plus-rsp-hle.dll",
#else
"Plugin/RSP/mupen64plus-rsp-hle.so",
CoreGetPluginDirectory() + "/RSP/mupen64plus-rsp-hle.so",
#endif // _WIN32
"", false};
};
break;
case SettingsID::Core_OverrideUserDirs:
setting = {SETTING_SECTION_CORE, "OverrideUserDirectories", true, "", false};
setting = {SETTING_SECTION_CORE, "OverrideUserDirectories", true};
break;
case SettingsID::Core_UserDataDirOverride:
setting = {SETTING_SECTION_CORE, "UserDataDirectory", "Data", "", false};
setting = {SETTING_SECTION_CORE, "UserDataDirectory", CoreGetDefaultUserDataDirectory()};
break;
case SettingsID::Core_UserCacheDirOverride:
setting = {SETTING_SECTION_CORE, "UserCacheDirectory", "Cache", "", false};
setting = {SETTING_SECTION_CORE, "UserCacheDirectory", CoreGetDefaultUserCacheDirectory()};
break;
case SettingsID::Core_OverrideGameSpecificSettings:
setting = {SETTING_SECTION_CORE, "OverrideGameSpecificSettings", false, "", false};
setting = {SETTING_SECTION_CORE, "OverrideGameSpecificSettings", false};
break;
case SettingsID::Core_RandomizeInterrupt:
setting = {SETTING_SECTION_OVERLAY, "RandomizeInterrupt", true, "", false};
setting = {SETTING_SECTION_OVERLAY, "RandomizeInterrupt", true};
break;
case SettingsID::Core_CPU_Emulator:
setting = {SETTING_SECTION_OVERLAY, "CPU_Emulator", 2, "", false};
setting = {SETTING_SECTION_OVERLAY, "CPU_Emulator", 2};
break;
case SettingsID::Core_DisableExtraMem:
setting = {SETTING_SECTION_OVERLAY, "DisableExtraMem", false, "", false};
setting = {SETTING_SECTION_OVERLAY, "DisableExtraMem", false};
break;
case SettingsID::Core_EnableDebugger:
setting = {SETTING_SECTION_OVERLAY, "EnableDebugger", false, "", false};
setting = {SETTING_SECTION_OVERLAY, "EnableDebugger", false};
break;
case SettingsID::Core_CountPerOp:
setting = {SETTING_SECTION_OVERLAY, "CountPerOp", 0, "", false};
setting = {SETTING_SECTION_OVERLAY, "CountPerOp", 0};
break;
case SettingsID::Core_SiDmaDuration:
setting = {SETTING_SECTION_OVERLAY, "SiDmaDuration", -1, "", false};
setting = {SETTING_SECTION_OVERLAY, "SiDmaDuration", -1};
break;
case SettingsID::Core_ScreenshotPath:
setting = {SETTING_SECTION_M64P, "ScreenshotPath", "Screenshots", "", true};
break;
case SettingsID::Core_SaveStatePath:
setting = {SETTING_SECTION_M64P, "SaveStatePath", "Save/State", "", true};
setting = {SETTING_SECTION_M64P, "SaveStatePath", CoreGetDefaultSaveStateDirectory(), "", true};
break;
case SettingsID::Core_SaveSRAMPath:
setting = {SETTING_SECTION_M64P, "SaveSRAMPath", "Save/Game", "", true};
setting = {SETTING_SECTION_M64P, "SaveSRAMPath", CoreGetDefaultSaveDirectory(), "", true};
break;
case SettingsID::Core_SharedDataPath:
setting = {SETTING_SECTION_M64P, "SharedDataPath", "Data", "", true};
setting = {SETTING_SECTION_M64P, "SharedDataPath", CoreGetSharedDataDirectory(), "", true};
break;
case SettingsID::Core_64DD_RomFile:
setting = {SETTING_SECTION_CORE, "64DD_RomFile", "", "", false};
setting = {SETTING_SECTION_CORE, "64DD_RomFile", ""};
break;
case SettingsID::Game_DisableExtraMem:
setting = {"", "DisableExtraMem", false, "", false};
setting = {"", "DisableExtraMem", false};
break;
case SettingsID::Game_SaveType:
setting = {"", "SaveType", 0, "", false};
setting = {"", "SaveType", 0};
break;
case SettingsID::Game_CountPerOp:
setting = {"", "CountPerOp", 2, "", false};
setting = {"", "CountPerOp", 2};
break;
case SettingsID::Game_SiDmaDuration:
setting = {"", "SiDmaDuration", 2304, "", false};
setting = {"", "SiDmaDuration", 2304};
break;
case SettingsID::Game_OverrideCoreSettings:
setting = {"", "OverrideCoreSettings", false, "", false};
setting = {"", "OverrideCoreSettings", false};
break;
case SettingsID::Game_CPU_Emulator:
setting = {"", "CPU_Emulator", 2, "", false};
setting = {"", "CPU_Emulator", 2};
break;
case SettingsID::Game_RandomizeInterrupt:
setting = {"", "RandomizeInterrupt", true, "", false};
setting = {"", "RandomizeInterrupt", true};
break;
case SettingsID::Game_GFX_Plugin:
setting = {"", "GFX_Plugin", "", "", false};
setting = {"", "GFX_Plugin", ""};
break;
case SettingsID::Game_AUDIO_Plugin:
setting = {"", "AUDIO_Plugin", "", "", false};
setting = {"", "AUDIO_Plugin", ""};
break;
case SettingsID::Game_INPUT_Plugin:
setting = {"", "INPUT_Plugin", "", "", false};
setting = {"", "INPUT_Plugin", ""};
break;
case SettingsID::Game_RSP_Plugin:
setting = {"", "RSP_Plugin", "", "", false};
setting = {"", "RSP_Plugin", ""};
break;
case SettingsID::KeyBinding_OpenROM:
setting = {SETTING_SECTION_KEYBIND, "OpenROM", "Ctrl+O", "", false};
setting = {SETTING_SECTION_KEYBIND, "OpenROM", "Ctrl+O"};
break;
case SettingsID::KeyBinding_OpenCombo:
setting = {SETTING_SECTION_KEYBIND, "OpenCombo", "Ctrl+Shift+O", "", false};
setting = {SETTING_SECTION_KEYBIND, "OpenCombo", "Ctrl+Shift+O"};
break;
case SettingsID::KeyBinding_StartEmulation:
setting = {SETTING_SECTION_KEYBIND, "StartEmulation", "F11", "", false};
setting = {SETTING_SECTION_KEYBIND, "StartEmulation", "F11"};
break;
case SettingsID::KeyBinding_EndEmulation:
setting = {SETTING_SECTION_KEYBIND, "EndEmulation", "F12", "", false};
setting = {SETTING_SECTION_KEYBIND, "EndEmulation", "F12"};
break;
case SettingsID::KeyBinding_RefreshROMList:
setting = {SETTING_SECTION_KEYBIND, "RefreshROMList", "F5", "", false};
setting = {SETTING_SECTION_KEYBIND, "RefreshROMList", "F5"};
break;
case SettingsID::KeyBinding_Exit:
setting = {SETTING_SECTION_KEYBIND, "Exit", "Alt+F4", "", false};
setting = {SETTING_SECTION_KEYBIND, "Exit", "Alt+F4"};
break;
case SettingsID::KeyBinding_SoftReset:
setting = {SETTING_SECTION_KEYBIND, "SoftReset", "F1", "", false};
setting = {SETTING_SECTION_KEYBIND, "SoftReset", "F1"};
break;
case SettingsID::KeyBinding_HardReset:
setting = {SETTING_SECTION_KEYBIND, "HardReset", "Shift+F1", "", false};
setting = {SETTING_SECTION_KEYBIND, "HardReset", "Shift+F1"};
break;
case SettingsID::KeyBinding_Resume:
setting = {SETTING_SECTION_KEYBIND, "Resume", "F2", "", false};
setting = {SETTING_SECTION_KEYBIND, "Resume", "F2"};
break;
case SettingsID::KeyBinding_GenerateBitmap:
setting = {SETTING_SECTION_KEYBIND, "GenerateBitmap", "F3", "", false};
setting = {SETTING_SECTION_KEYBIND, "GenerateBitmap", "F3"};
break;
case SettingsID::KeyBinding_LimitFPS:
setting = {SETTING_SECTION_KEYBIND, "LimitFPS", "F4", "", false};
setting = {SETTING_SECTION_KEYBIND, "LimitFPS", "F4"};
break;
case SettingsID::KeyBinding_SwapDisk:
setting = {SETTING_SECTION_KEYBIND, "SwapDisk", "Ctrl+D", "", false};
setting = {SETTING_SECTION_KEYBIND, "SwapDisk", "Ctrl+D"};
break;
case SettingsID::KeyBinding_SaveState:
setting = {SETTING_SECTION_KEYBIND, "SaveState", "F5", "", false};
setting = {SETTING_SECTION_KEYBIND, "SaveState", "F5"};
break;
case SettingsID::KeyBinding_SaveAs:
setting = {SETTING_SECTION_KEYBIND, "SaveAs", "Ctrl+S", "", false};
setting = {SETTING_SECTION_KEYBIND, "SaveAs", "Ctrl+S"};
break;
case SettingsID::KeyBinding_LoadState:
setting = {SETTING_SECTION_KEYBIND, "LoadState", "F7", "", false};
setting = {SETTING_SECTION_KEYBIND, "LoadState", "F7"};
break;
case SettingsID::KeyBinding_Load:
setting = {SETTING_SECTION_KEYBIND, "Load", "Ctrl+L", "", false};
setting = {SETTING_SECTION_KEYBIND, "Load", "Ctrl+L"};
break;
case SettingsID::KeyBinding_Cheats:
setting = {SETTING_SECTION_KEYBIND, "Cheats", "Ctrl+C", "", false};
setting = {SETTING_SECTION_KEYBIND, "Cheats", "Ctrl+C"};
break;
case SettingsID::KeyBinding_GSButton:
setting = {SETTING_SECTION_KEYBIND, "GSButton", "F9", "", false};
setting = {SETTING_SECTION_KEYBIND, "GSButton", "F9"};
break;
case SettingsID::KeyBinding_Fullscreen:
setting = {SETTING_SECTION_KEYBIND, "Fullscreen", "Alt+Return", "", false};
setting = {SETTING_SECTION_KEYBIND, "Fullscreen", "Alt+Return"};
break;
case SettingsID::KeyBinding_Settings:
setting = {SETTING_SECTION_KEYBIND, "Settings", "Ctrl+T", "", false};
setting = {SETTING_SECTION_KEYBIND, "Settings", "Ctrl+T"};
break;
case SettingsID::RomBrowser_Directory:
setting = {SETTING_SECTION_ROMBROWSER, "Directory", "", "", false};
setting = {SETTING_SECTION_ROMBROWSER, "Directory", ""};
break;
case SettingsID::RomBrowser_Geometry:
setting = {SETTING_SECTION_ROMBROWSER, "Geometry", "", "", false};
setting = {SETTING_SECTION_ROMBROWSER, "Geometry", ""};
break;
case SettingsID::RomBrowser_Recursive:
setting = {SETTING_SECTION_ROMBROWSER, "Recursive", true, "", false};
setting = {SETTING_SECTION_ROMBROWSER, "Recursive", true};
break;
case SettingsID::RomBrowser_MaxItems:
setting = {SETTING_SECTION_ROMBROWSER, "MaxItems", 50, "", false};
setting = {SETTING_SECTION_ROMBROWSER, "MaxItems", 50};
break;
case SettingsID::RomBrowser_Columns:
setting = {SETTING_SECTION_ROMBROWSER, "Columns", std::vector<int>({0, 1, 2}), "", false};
setting = {SETTING_SECTION_ROMBROWSER, "Columns", std::vector<int>({0, 1, 2})};
break;
case SettingsID::RomBrowser_ColumnSizes:
setting = {SETTING_SECTION_ROMBROWSER, "ColumnSizes", std::vector<int>({0, 250, 1, 100, 2, 100}), "", false};
setting = {SETTING_SECTION_ROMBROWSER, "ColumnSizes", std::vector<int>({0, 250, 1, 100, 2, 100})};
break;
case SettingsID::Settings_HasForceUsedSetOnce:
setting = {SETTING_SECTION_SETTINGS, "HasForceUsedSetOnce", false};
break;
case SettingsID::Audio_Volume:
setting = {SETTING_SECTION_AUDIO, "Volume", 100};
break;
case SettingsID::Audio_Muted:
setting = {SETTING_SECTION_AUDIO, "Muted", false};
break;
}
@@ -509,7 +535,9 @@ bool CoreSettingsSave(void)
bool CoreSettingsSetupDefaults(void)
{
l_Setting setting;
bool ret;
bool ret, hasForceUsedSetOnce;
hasForceUsedSetOnce = CoreSettingsGetBoolValue(SettingsID::Settings_HasForceUsedSetOnce);
for (int i = 0; i < (int)SettingsID::Invalid; i++)
{
@@ -524,11 +552,11 @@ bool CoreSettingsSetupDefaults(void)
{
case M64TYPE_STRING:
{
if (setting.ForceUseSet)
if (setting.ForceUseSetOnce && !hasForceUsedSetOnce)
{
ret = config_option_set(setting.Section, setting.Key, M64TYPE_STRING, (void*)setting.DefaultValue.stringValue.c_str());
}
else
else if (!setting.ForceUseSetOnce)
{
ret = config_option_default_set(setting.Section, setting.Key, M64TYPE_STRING, (void*)setting.DefaultValue.stringValue.c_str(), setting.Description.c_str());
}
@@ -550,6 +578,11 @@ bool CoreSettingsSetupDefaults(void)
}
}
if (!hasForceUsedSetOnce)
{
CoreSettingsSetValue(SettingsID::Settings_HasForceUsedSetOnce, true);
}
return true;
}
+9
View File
@@ -9,6 +9,8 @@ enum class SettingsID
GUI_AllowManualResizing,
GUI_HideCursorInEmulation,
GUI_StatusbarMessageDuration,
GUI_PauseEmulationOnFocusLoss,
GUI_ResumeEmulationOnFocus,
// Core Plugin Settings
Core_GFX_Plugin,
@@ -86,6 +88,13 @@ enum class SettingsID
RomBrowser_Columns,
RomBrowser_ColumnSizes,
// Settings Settings
Settings_HasForceUsedSetOnce,
// Audio Plugin Settings
Audio_Volume,
Audio_Muted,
Invalid
};
+2
View File
@@ -20,6 +20,8 @@ set(RMG_SOURCES
UserInterface/Dialog/SettingsDialog.cpp
UserInterface/Dialog/SettingsDialog.ui
UserInterface/Dialog/SettingsDialog.qrc
UserInterface/Dialog/RomInfoDialog.cpp
UserInterface/Dialog/RomInfoDialog.ui
UserInterface/NoFocusDelegate.cpp
UserInterface/EventFilter.cpp
UserInterface/UIResources.rc
-1
View File
@@ -6,6 +6,5 @@
#define WINDOW_WIDGET_SIZE_H 480
#define APP_URL_HOMEPAGE "https://github.com/Rosalie241/RMG"
#define APP_STYLESHEET_FILE "Config/stylesheet.qss"
#endif // CONFIG_HPP
+16 -6
View File
@@ -23,12 +23,7 @@ RomSearcherThread::RomSearcherThread(QObject *parent) : QThread(parent)
RomSearcherThread::~RomSearcherThread(void)
{
// kill the thread when we're running
if (this->isRunning())
{
this->terminate();
this->wait();
}
this->Stop();
}
void RomSearcherThread::SetDirectory(QString directory)
@@ -46,8 +41,18 @@ void RomSearcherThread::SetMaximumFiles(int value)
this->rom_Search_MaxItems = value;
}
void RomSearcherThread::Stop(void)
{
this->rom_Search_Stop = true;
while (this->isRunning())
{
this->wait();
}
}
void RomSearcherThread::run(void)
{
this->rom_Search_Stop = false;
this->rom_Search(this->rom_Directory);
return;
}
@@ -95,6 +100,11 @@ void RomSearcherThread::rom_Search(QString directory)
emit this->on_Rom_Found(file, header, settings);
}
if (this->rom_Search_Stop)
{
break;
}
}
}
+2
View File
@@ -28,6 +28,7 @@ class RomSearcherThread : public QThread
void SetDirectory(QString);
void SetRecursive(bool);
void SetMaximumFiles(int);
void Stop(void);
void run(void) override;
@@ -35,6 +36,7 @@ class RomSearcherThread : public QThread
QString rom_Directory;
bool rom_Search_Recursive;
int rom_Search_MaxItems;
bool rom_Search_Stop = false;
void rom_Search(QString);
@@ -0,0 +1,76 @@
/*
* 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 "RomInfoDialog.hpp"
#include <QMessageBox>
#include <QFileInfo>
using namespace UserInterface::Dialog;
RomInfoDialog::RomInfoDialog(QString file, QWidget *parent) : QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint)
{
this->setupUi(this);
bool needCloseRom = false;
CoreRomHeader romHeader;
CoreRomSettings romSettings;
// try to open ROM
if (!CoreOpenRom(file.toStdString()))
{
this->showErrorMessage(parent, "CoreOpenRom() Failed", QString::fromStdString(CoreGetError()));
return;
}
// try to retrieve ROM header
if (!CoreGetCurrentRomHeader(romHeader))
{
this->showErrorMessage(parent, "CoreGetCurrentRomHeader() Failed", QString::fromStdString(CoreGetError()));
return;
}
// try to retrieve ROM settings
if (!CoreGetCurrentRomSettings(romSettings))
{
this->showErrorMessage(parent, "CoreGetCurrentRomSettings() Failed", QString::fromStdString(CoreGetError()));
return;
}
QFileInfo qFileInfo(file);
this->romNameLineEdit->setText(QString::fromStdString(romHeader.Name));
this->md5LineEdit->setText(QString::fromStdString(romSettings.MD5));
this->fileNameLineEdit->setText(qFileInfo.fileName());
this->locationLineEdit->setText(qFileInfo.absolutePath());
this->crc1LineEdit->setText(QString::number(romHeader.CRC1, 16).toUpper());
this->crc2LineEdit->setText(QString::number(romHeader.CRC2, 16).toUpper());
if (!CoreCloseRom())
{
this->showErrorMessage(parent, "CoreCloseRom() Failed", QString::fromStdString(CoreGetError()));
return;
}
}
RomInfoDialog::~RomInfoDialog(void)
{
}
void RomInfoDialog::showErrorMessage(QWidget* parent, QString error, QString details)
{
QMessageBox msgBox(parent);
msgBox.setIcon(QMessageBox::Icon::Critical);
msgBox.setWindowTitle("Error");
msgBox.setText(error);
msgBox.setDetailedText(details);
msgBox.addButton(QMessageBox::Ok);
msgBox.exec();
}
@@ -0,0 +1,38 @@
/*
* 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 ROMINFODIALOG_HPP
#define ROMINFODIALOG_HPP
#include <QWidget>
#include <QDialog>
#include <RMG-Core/Core.hpp>
#include "ui_RomInfoDialog.h"
namespace UserInterface
{
namespace Dialog
{
class RomInfoDialog : public QDialog, private Ui::RomInfoDialog
{
Q_OBJECT
private:
void showErrorMessage(QWidget* parent, QString error, QString details);
public:
RomInfoDialog(QString file, QWidget *parent);
~RomInfoDialog(void);
};
} // namespace Dialog
} // namespace UserInterface
#endif // ROMINFODIALOG_HPP
@@ -0,0 +1,251 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>RomInfoDialog</class>
<widget class="QDialog" name="RomInfoDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>376</width>
<height>456</height>
</rect>
</property>
<property name="windowTitle">
<string>ROM Information</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>ROM Name:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="romNameLineEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>File Name:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="fileNameLineEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Location:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="locationLineEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>MD5:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="md5LineEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>CRC1:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="crc1LineEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>CRC2</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="crc2LineEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>161</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>RomInfoDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>RomInfoDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
@@ -10,6 +10,7 @@
#include "SettingsDialog.hpp"
#include <QFileDialog>
#include <QMessageBox>
using namespace UserInterface::Dialog;
@@ -17,12 +18,19 @@ SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent, Qt::WindowSyst
{
this->setupUi(this);
this->inGame = CoreIsEmulationRunning() || CoreIsEmulationPaused();
if (inGame)
this->romOpened = CoreHasRomOpen();
if (romOpened)
{
CoreGetCurrentRomSettings(this->currentGameSettings);
CoreGetCurrentDefaultRomSettings(this->defaultGameSettings);
this->gameSection = this->currentGameSettings.MD5;
// no need to show emulation info text,
// when we're not running/paused
if (!CoreIsEmulationRunning() && !CoreIsEmulationPaused())
{
this->hideEmulationInfoText();
}
}
else
{
@@ -55,6 +63,11 @@ SettingsDialog::~SettingsDialog(void)
CoreSettingsSave();
}
void SettingsDialog::ShowGameTab(void)
{
this->tabWidget->setCurrentIndex(1);
}
int SettingsDialog::currentIndex(void)
{
int currentIndex = this->tabWidget->currentIndex();
@@ -88,7 +101,7 @@ void SettingsDialog::restoreDefaults(int stackedWidgetIndex)
loadDefaultGamePluginSettings();
break;
case 4:
loadPluginSettings();
loadDefaultPluginSettings();
break;
case 5:
loadDefaultDirectorySettings();
@@ -243,40 +256,7 @@ void SettingsDialog::loadGamePluginSettings(void)
void SettingsDialog::loadPluginSettings(void)
{
QComboBox *comboBoxArray[] = {this->rspPluginsComboBox, this->videoPluginsComboBox,
this->audioPluginsComboBox, this->inputPluginsComboBox};
SettingsID settingsIdArray[] = {SettingsID::Core_RSP_Plugin, SettingsID::Core_GFX_Plugin,
SettingsID::Core_AUDIO_Plugin, SettingsID::Core_INPUT_Plugin};
bool pluginFound[] = {false, false, false, false};
QComboBox *comboBox;
std::string pluginFileName;
int index = 0;
for (const auto &p : this->pluginList)
{
index = ((int)p.Type - 1);
comboBox = comboBoxArray[index];
pluginFileName = CoreSettingsGetStringValue(settingsIdArray[index]);
comboBox->addItem(QString::fromStdString(p.Name), QString::fromStdString(p.File));
if (pluginFileName == p.File)
{
comboBox->setCurrentText(QString::fromStdString(p.Name));
pluginFound[index] = true;
}
}
for (int i = 0; i < 4; i++)
{
comboBox = comboBoxArray[i];
if (!pluginFound[i])
{
comboBox->addItem("", "");
comboBox->setCurrentText("");
}
}
this->commonPluginSettings(0);
}
void SettingsDialog::loadDirectorySettings(void)
@@ -316,6 +296,8 @@ void SettingsDialog::loadHotkeySettings(void)
void SettingsDialog::loadInterfaceSettings(void)
{
this->manualResizingCheckBox->setChecked(CoreSettingsGetBoolValue(SettingsID::GUI_AllowManualResizing));
this->pauseEmulationOnFocusCheckbox->setChecked(CoreSettingsGetBoolValue(SettingsID::GUI_PauseEmulationOnFocusLoss));
this->resumeEmulationOnFocusCheckBox->setChecked(CoreSettingsGetBoolValue(SettingsID::GUI_ResumeEmulationOnFocus));
this->hideCursorCheckBox->setChecked(CoreSettingsGetBoolValue(SettingsID::GUI_HideCursorInEmulation));
this->statusBarMessageDurationSpinBox->setValue(CoreSettingsGetIntValue(SettingsID::GUI_StatusbarMessageDuration));
this->searchSubDirectoriesCheckbox->setChecked(CoreSettingsGetBoolValue(SettingsID::RomBrowser_Recursive));
@@ -392,6 +374,11 @@ void SettingsDialog::loadDefaultGamePluginSettings(void)
}
}
void SettingsDialog::loadDefaultPluginSettings(void)
{
this->commonPluginSettings(1);
}
void SettingsDialog::loadDefaultDirectorySettings(void)
{
this->screenshotDirLineEdit->setText(QString::fromStdString(CoreSettingsGetDefaultStringValue(SettingsID::Core_ScreenshotPath)));
@@ -411,6 +398,8 @@ void SettingsDialog::loadDefaultHotkeySettings(void)
void SettingsDialog::loadDefaultInterfaceSettings(void)
{
this->manualResizingCheckBox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::GUI_AllowManualResizing));
this->pauseEmulationOnFocusCheckbox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::GUI_PauseEmulationOnFocusLoss));
this->resumeEmulationOnFocusCheckBox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::GUI_ResumeEmulationOnFocus));
this->hideCursorCheckBox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::GUI_HideCursorInEmulation));
this->statusBarMessageDurationSpinBox->setValue(CoreSettingsGetDefaultIntValue(SettingsID::GUI_StatusbarMessageDuration));
this->searchSubDirectoriesCheckbox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::RomBrowser_Recursive));
@@ -420,7 +409,7 @@ void SettingsDialog::loadDefaultInterfaceSettings(void)
void SettingsDialog::saveSettings(void)
{
this->saveCoreSettings();
if (inGame)
if (romOpened)
{
// clean 'game settings'
CoreSettingsDeleteSection(this->gameSection);
@@ -468,20 +457,14 @@ void SettingsDialog::saveGameSettings(void)
int countPerOp = this->gameCounterFactorComboBox->currentIndex() + 1;
int siDmaDuration = this->gameSiDmaDurationSpinBox->value();
if (this->defaultGameSettings.DisableExtraMem != disableExtraMem)
if ((this->defaultGameSettings.DisableExtraMem != disableExtraMem) ||
(this->defaultGameSettings.SaveType != saveType) ||
(this->defaultGameSettings.CountPerOp != countPerOp) ||
(this->defaultGameSettings.SiDMADuration != siDmaDuration))
{
CoreSettingsSetValue(SettingsID::Game_DisableExtraMem, this->gameSection, disableExtraMem);
}
if (this->defaultGameSettings.SaveType != saveType)
{
CoreSettingsSetValue(SettingsID::Game_SaveType, this->gameSection, saveType);
}
if (this->defaultGameSettings.CountPerOp != countPerOp)
{
CoreSettingsSetValue(SettingsID::Game_CountPerOp, this->gameSection, countPerOp);
}
if (this->defaultGameSettings.SiDMADuration != siDmaDuration)
{
CoreSettingsSetValue(SettingsID::Game_SiDmaDuration, this->gameSection, siDmaDuration);
}
}
@@ -545,13 +528,6 @@ void SettingsDialog::savePluginSettings(void)
CoreSettingsSetValue(settingId, comboBox->currentData().toString().toStdString());
}
// only apply plugin settings when
// emulation isn't running
if (!CoreIsEmulationPaused() && !CoreIsEmulationRunning())
{
CoreApplyPluginSettings();
}
}
void SettingsDialog::saveDirectorySettings(void)
@@ -575,6 +551,8 @@ void SettingsDialog::saveInterfaceSettings(void)
{
CoreSettingsSetValue(SettingsID::GUI_AllowManualResizing, this->manualResizingCheckBox->isChecked());
CoreSettingsSetValue(SettingsID::GUI_HideCursorInEmulation, this->hideCursorCheckBox->isChecked());
CoreSettingsSetValue(SettingsID::GUI_PauseEmulationOnFocusLoss, this->pauseEmulationOnFocusCheckbox->isChecked());
CoreSettingsSetValue(SettingsID::GUI_ResumeEmulationOnFocus, this->resumeEmulationOnFocusCheckBox->isChecked());
CoreSettingsSetValue(SettingsID::GUI_StatusbarMessageDuration, this->statusBarMessageDurationSpinBox->value());
CoreSettingsSetValue(SettingsID::RomBrowser_Recursive, this->searchSubDirectoriesCheckbox->isChecked());
CoreSettingsSetValue(SettingsID::RomBrowser_MaxItems, this->romSearchLimitSpinBox->value());
@@ -628,9 +606,58 @@ void SettingsDialog::commonHotkeySettings(int action)
}
}
void SettingsDialog::commonPluginSettings(int action)
{
QComboBox *comboBoxArray[] = {this->rspPluginsComboBox, this->videoPluginsComboBox,
this->audioPluginsComboBox, this->inputPluginsComboBox};
SettingsID settingsIdArray[] = {SettingsID::Core_RSP_Plugin, SettingsID::Core_GFX_Plugin,
SettingsID::Core_AUDIO_Plugin, SettingsID::Core_INPUT_Plugin};
bool pluginFound[] = {false, false, false, false};
QComboBox *comboBox;
std::string pluginFileName;
int index = 0;
// clear combobox items
for (const auto& c : comboBoxArray)
{
c->clear();
}
for (const auto &p : this->pluginList)
{
index = ((int)p.Type - 1);
comboBox = comboBoxArray[index];
pluginFileName = action == 0 ?
CoreSettingsGetStringValue(settingsIdArray[index]) :
CoreSettingsGetDefaultStringValue(settingsIdArray[index]);
comboBox->addItem(QString::fromStdString(p.Name), QString::fromStdString(p.File));
if (pluginFileName == p.File)
{
comboBox->setCurrentText(QString::fromStdString(p.Name));
pluginFound[index] = true;
}
}
for (int i = 0; i < 4; i++)
{
comboBox = comboBoxArray[i];
if (!pluginFound[i])
{
comboBox->addItem("", "");
comboBox->setCurrentText("");
}
}
}
void SettingsDialog::hideEmulationInfoText(void)
{
QHBoxLayout *layouts[] = {this->emulationInfoLayout_0, this->emulationInfoLayout_1, this->emulationInfoLayout_2};
QHBoxLayout *layouts[] = {this->emulationInfoLayout_0, this->emulationInfoLayout_1,
this->emulationInfoLayout_2, this->emulationInfoLayout_9,
this->emulationInfoLayout_13};
for (const auto &layout : layouts)
{
@@ -666,6 +693,33 @@ void SettingsDialog::on_buttonBox_clicked(QAbstractButton *button)
QPushButton *cancelButton = this->buttonBox->button(QDialogButtonBox::Cancel);
QPushButton *okButton = this->buttonBox->button(QDialogButtonBox::Ok);
if (pushButton == cancelButton || pushButton == okButton)
{
if (pushButton == okButton)
{
this->saveSettings();
}
// attempt to apply plugin settings when emulation
// isn't running, when it fails, show the user the error and
// don't allow the user to save invalid settings
if (!CoreIsEmulationPaused() && !CoreIsEmulationRunning())
{
if (!CoreApplyPluginSettings())
{
QMessageBox msgBox(this);
msgBox.setIcon(QMessageBox::Icon::Critical);
msgBox.setWindowTitle("Error");
msgBox.setText("CoreApplyPluginSettings() Failed");
msgBox.setDetailedText(QString::fromStdString(CoreGetError()));
msgBox.addButton(QMessageBox::Ok);
msgBox.exec();
return;
}
}
}
if (pushButton == defaultButton)
{
this->restoreDefaults(this->currentIndex());
@@ -676,7 +730,6 @@ void SettingsDialog::on_buttonBox_clicked(QAbstractButton *button)
}
else if (pushButton == okButton)
{
this->saveSettings();
this->accept();
}
}
@@ -34,7 +34,7 @@ class SettingsDialog : public QDialog, private Ui::SettingsDialog
Q_OBJECT
private:
bool inGame = false;
bool romOpened = false;
CoreRomSettings currentGameSettings;
CoreRomSettings defaultGameSettings;
@@ -61,6 +61,7 @@ class SettingsDialog : public QDialog, private Ui::SettingsDialog
void loadDefaultGameSettings(void);
void loadDefaultGameCoreSettings(void);
void loadDefaultGamePluginSettings(void);
void loadDefaultPluginSettings(void);
void loadDefaultDirectorySettings(void);
void loadDefaultHotkeySettings(void);
void loadDefaultInterfaceSettings(void);
@@ -76,6 +77,7 @@ class SettingsDialog : public QDialog, private Ui::SettingsDialog
void saveInterfaceSettings(void);
void commonHotkeySettings(int);
void commonPluginSettings(int);
void hideEmulationInfoText(void);
@@ -94,6 +96,8 @@ class SettingsDialog : public QDialog, private Ui::SettingsDialog
public:
SettingsDialog(QWidget *parent);
~SettingsDialog(void);
void ShowGameTab(void);
};
} // namespace Dialog
} // namespace UserInterface
@@ -1588,6 +1588,20 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="pauseEmulationOnFocusCheckbox">
<property name="text">
<string>Pause Emulation On Focus Loss</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="resumeEmulationOnFocusCheckBox">
<property name="text">
<string>Resume Emulation On Focus Gain</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
-11
View File
@@ -27,17 +27,6 @@ bool EventFilter::eventFilter(QObject *object, QEvent *event)
case QEvent::Type::KeyRelease:
emit this->on_EventFilter_KeyReleased((QKeyEvent *)event);
return true;
// it seems like Qt loses focus whenever you click on the menubar,
// even when re-implementing QMenuBar's focusIn/Out, it wont work correctly.
/*case QEvent::Type::FocusIn:
lastFocusObject = object;
std::cout << object << std::endl;
emit this->on_EventFilter_FocusIn((QFocusEvent *)event);
return true;
case QEvent::Type::FocusOut:
if (lastFocusObject == object)
emit this->on_EventFilter_FocusOut((QFocusEvent *)event);
return true;*/
default:
break;
}
+136 -63
View File
@@ -39,7 +39,7 @@ MainWindow::~MainWindow()
{
}
bool MainWindow::Init(void)
bool MainWindow::Init(QGuiApplication* app)
{
if (!CoreInit())
{
@@ -47,6 +47,11 @@ bool MainWindow::Init(void)
return false;
}
if (!CoreApplyPluginSettings())
{
this->ui_MessageBox("Error", "CoreApplyPluginSettings() Failed", QString::fromStdString(CoreGetError()));
}
this->ui_Init();
this->ui_Setup();
@@ -73,6 +78,7 @@ bool MainWindow::Init(void)
}
connect(coreCallBacks, &CoreCallbacks::OnCoreDebugCallback, this, &MainWindow::on_Core_DebugCallback);
connect(app, &QGuiApplication::applicationStateChanged, this, &MainWindow::on_QGuiApplication_applicationStateChanged);
return true;
}
@@ -86,6 +92,8 @@ void MainWindow::closeEvent(QCloseEvent *event)
{
this->on_Action_File_EndEmulation();
this->ui_Widget_RomBrowser->StopRefreshRomList();
this->coreCallBacks->Stop();
while (this->emulationThread->isRunning())
@@ -119,8 +127,16 @@ void MainWindow::ui_Init(void)
this->ui_Widget_RomBrowser->SetDirectory(dir);
this->ui_Widget_RomBrowser->RefreshRomList();
connect(this->ui_Widget_RomBrowser, &Widget::RomBrowserWidget::on_RomBrowser_Select, this,
&MainWindow::on_RomBrowser_Selected);
connect(this->ui_Widget_RomBrowser, &Widget::RomBrowserWidget::on_RomBrowser_PlayGame, this,
&MainWindow::on_RomBrowser_PlayGame);
connect(this->ui_Widget_RomBrowser, &Widget::RomBrowserWidget::on_RomBrowser_PlayGameWithDisk, this,
&MainWindow::on_RomBrowser_PlayGameWithDisk);
connect(this->ui_Widget_RomBrowser, &Widget::RomBrowserWidget::on_RomBrowser_EditGameSettings, this,
&MainWindow::on_RomBrowser_EditGameSettings);
connect(this->ui_Widget_RomBrowser, &Widget::RomBrowserWidget::on_RomBrowser_ChooseRomDirectory, this,
&MainWindow::on_Action_File_ChooseDirectory);
connect(this->ui_Widget_RomBrowser, &Widget::RomBrowserWidget::on_RomBrowser_RomInformation, this,
&MainWindow::on_RomBrowser_RomInformation);
connect(this->ui_Widget_RomBrowser, &Widget::RomBrowserWidget::on_RomBrowser_FileDropped, this,
&MainWindow::on_EventFilter_FileDropped);
@@ -130,10 +146,6 @@ void MainWindow::ui_Init(void)
&MainWindow::on_EventFilter_KeyReleased);
connect(this->ui_EventFilter, &EventFilter::on_EventFilter_FileDropped, this,
&MainWindow::on_EventFilter_FileDropped);
/*
connect(this->ui_EventFilter, &EventFilter::on_EventFilter_FocusIn, this, &MainWindow::on_EventFilter_FocusIn);
connect(this->ui_EventFilter, &EventFilter::on_EventFilter_FocusOut, this, &MainWindow::on_EventFilter_FocusOut);
*/
}
void MainWindow::ui_Setup(void)
@@ -172,7 +184,11 @@ void MainWindow::ui_Setup(void)
void MainWindow::ui_Stylesheet_Setup(void)
{
QFile stylesheet(APP_STYLESHEET_FILE);
QString stylesheetFile;
stylesheetFile = QString::fromStdString(CoreGetSharedDataDirectory());
stylesheetFile += "/stylesheet.qss";
QFile stylesheet(stylesheetFile);
if (!stylesheet.open(QIODevice::ReadOnly))
{
@@ -282,7 +298,6 @@ void MainWindow::menuBar_Setup(bool inEmulation, bool isPaused)
this->menuBar_Menu = this->menuBar->addMenu("File");
this->menuBar_Menu->addAction(this->action_File_OpenRom);
this->menuBar_Menu->addAction(this->action_File_OpenCombo);
this->menuBar_Menu->addAction(this->action_File_RomInfo);
this->menuBar_Menu->addSeparator();
this->menuBar_Menu->addAction(this->action_File_StartEmulation);
this->menuBar_Menu->addAction(this->action_File_EndEmulation);
@@ -460,7 +475,6 @@ void MainWindow::ui_Actions_Init(void)
{
this->action_File_OpenRom = new QAction(this);
this->action_File_OpenCombo = new QAction(this);
this->action_File_RomInfo = new QAction(this);
this->action_File_StartEmulation = new QAction(this);
this->action_File_EndEmulation = new QAction(this);
this->action_File_Language = new QAction(this);
@@ -504,7 +518,6 @@ void MainWindow::ui_Actions_Setup(bool inEmulation, bool isPaused)
keyBinding = QString::fromStdString(CoreSettingsGetStringValue(SettingsID::KeyBinding_OpenCombo));
this->action_File_OpenCombo->setText("Open Combo");
this->action_File_OpenCombo->setShortcut(QKeySequence(keyBinding));
this->action_File_RomInfo->setText("ROM Info....");
keyBinding = QString::fromStdString(CoreSettingsGetStringValue(SettingsID::KeyBinding_StartEmulation));
this->action_File_StartEmulation->setText("Start Emulation");
this->action_File_StartEmulation->setShortcut(QKeySequence(keyBinding));
@@ -733,32 +746,38 @@ void MainWindow::on_EventFilter_FileDropped(QDropEvent *event)
this->emulationThread_Launch(file);
}
/* TODO for some day
void MainWindow::on_EventFilter_FocusIn(QFocusEvent *event)
void MainWindow::on_QGuiApplication_applicationStateChanged(Qt::ApplicationState state)
{
std::cout << "MainWindow::on_EventFilter_FocusIn" << std::endl;
if (g_Settings.GetBoolValue(SettingsID::GUI_ResumeEmulationOnFocus))
bool isRunning = CoreIsEmulationRunning();
bool isPaused = CoreIsEmulationPaused();
bool pauseOnFocusLoss = CoreSettingsGetBoolValue(SettingsID::GUI_PauseEmulationOnFocusLoss);
bool resumeOnFocus = CoreSettingsGetBoolValue(SettingsID::GUI_ResumeEmulationOnFocus);
switch (state)
{
if (CoreIsEmulationPaused())
this->on_Action_System_Pause();
default:
break;
case Qt::ApplicationState::ApplicationInactive:
{
if (pauseOnFocusLoss && isRunning && !isPaused)
{
this->on_Action_System_Pause();
this->ui_ManuallyPaused = false;
}
} break;
case Qt::ApplicationState::ApplicationActive:
{
if (resumeOnFocus && isPaused && !this->ui_ManuallyPaused)
{
this->on_Action_System_Pause();
}
} break;
}
QMainWindow::focusInEvent(event);
}
void MainWindow::on_EventFilter_FocusOut(QFocusEvent *event)
{
std::cout << "MainWindow::on_EventFilter_FocusOut" << std::endl;
if (g_Settings.GetBoolValue(SettingsID::GUI_PauseEmulationOnFocusLoss))
{
if (CoreIsEmulationRunning())
this->on_Action_System_Pause();
}
QMainWindow::focusOutEvent(event);
}
*/
void MainWindow::on_Action_File_OpenRom(void)
{
bool isRunning = CoreIsEmulationRunning();
@@ -769,15 +788,11 @@ void MainWindow::on_Action_File_OpenRom(void)
this->on_Action_System_Pause();
}
QFileDialog dialog(this);
int ret;
QString dir;
QString romFile;
dialog.setFileMode(QFileDialog::FileMode::ExistingFile);
dialog.setNameFilter("N64 ROMs & Disks (*.n64 *.z64 *.v64 *.ndd *.d64 *.zip)");
romFile = QFileDialog::getOpenFileName(this, "", "", "N64 ROMs & Disks (*.n64 *.z64 *.v64 *.ndd *.d64 *.zip)");
ret = dialog.exec();
if (!ret)
if (romFile.isEmpty())
{
if (isRunning && !isPaused)
{
@@ -791,7 +806,7 @@ void MainWindow::on_Action_File_OpenRom(void)
this->ui_NoSwitchToRomBrowser = true;
}
this->emulationThread_Launch(dialog.selectedFiles().first());
this->emulationThread_Launch(romFile);
}
void MainWindow::on_Action_File_OpenCombo(void)
@@ -804,15 +819,11 @@ void MainWindow::on_Action_File_OpenCombo(void)
this->on_Action_System_Pause();
}
QFileDialog dialog(this);
int ret;
QString dir, cartRom, diskRom;
QString cartRom, diskRom;
dialog.setFileMode(QFileDialog::FileMode::ExistingFile);
dialog.setNameFilter("N64 ROMs (*.n64 *.z64 *.v64 *.zip)");
ret = dialog.exec();
if (!ret)
cartRom = QFileDialog::getOpenFileName(this, "", "", "N64 ROMs (*.n64 *.z64 *.v64 *.zip)");
if (cartRom.isEmpty())
{
if (isRunning && !isPaused)
{
@@ -821,11 +832,10 @@ void MainWindow::on_Action_File_OpenCombo(void)
return;
}
cartRom = dialog.selectedFiles().first();
dialog.setNameFilter("N64DD Disk Image (*.ndd *.d64)");
ret = dialog.exec();
if (!ret)
diskRom = QFileDialog::getOpenFileName(this, "", "", "N64DD Disk Image (*.ndd *.d64)");
if (diskRom.isEmpty())
{
if (isRunning && !isPaused)
{
@@ -834,8 +844,6 @@ void MainWindow::on_Action_File_OpenCombo(void)
return;
}
diskRom = dialog.selectedFiles().first();
if (this->ui_Widgets->currentIndex() != 0)
{
this->ui_NoSwitchToRomBrowser = true;
@@ -864,18 +872,12 @@ void MainWindow::on_Action_File_EndEmulation(void)
void MainWindow::on_Action_File_ChooseDirectory(void)
{
QFileDialog dialog;
QString dir;
int ret;
dialog.setFileMode(QFileDialog::Directory);
dialog.setOption(QFileDialog::ShowDirsOnly, true);
dialog.setWindowIcon(this->ui_Icon);
dir = QFileDialog::getExistingDirectory(this);
ret = dialog.exec();
if (ret)
if (!dir.isEmpty())
{
dir = dialog.selectedFiles().first();
CoreSettingsSetValue(SettingsID::RomBrowser_Directory, dir.toStdString());
this->ui_Widget_RomBrowser->SetDirectory(dir);
this->ui_Widget_RomBrowser->RefreshRomList();
@@ -933,6 +935,7 @@ void MainWindow::on_Action_System_Pause(void)
}
this->menuBar_Setup(true, !isPaused);
this->ui_ManuallyPaused = true;
}
void MainWindow::on_Action_System_GenerateBitmap(void)
@@ -1129,11 +1132,75 @@ void MainWindow::on_Emulation_Finished(bool ret)
this->ui_InEmulation(false, false);
}
void MainWindow::on_RomBrowser_Selected(QString file)
void MainWindow::on_RomBrowser_PlayGame(QString file)
{
this->emulationThread_Launch(file);
}
void MainWindow::on_RomBrowser_PlayGameWithDisk(QString file)
{
QString diskRom;
diskRom = QFileDialog::getOpenFileName(this, "", "", "N64DD Disk Image (*.ndd *.d64)");
if (diskRom.isEmpty())
{
return;
}
this->emulationThread_Launch(file, diskRom);
}
void MainWindow::on_RomBrowser_EditGameSettings(QString file)
{
bool isRefreshingRomList = this->ui_Widget_RomBrowser->IsRefreshingRomList();
if (isRefreshingRomList)
{
this->ui_Widget_RomBrowser->StopRefreshRomList();
}
if (!CoreOpenRom(file.toStdString()))
{
this->ui_MessageBox("Error", "CoreOpenRom() Failed", QString::fromStdString(CoreGetError()));
return;
}
Dialog::SettingsDialog dialog(this);
dialog.ShowGameTab();
dialog.exec();
this->ui_InEmulation(false, false);
if (!CoreCloseRom())
{
this->ui_MessageBox("Error", "CoreCloseRom() Failed", QString::fromStdString(CoreGetError()));
return;
}
if (isRefreshingRomList)
{
this->ui_Widget_RomBrowser->RefreshRomList();
}
}
void MainWindow::on_RomBrowser_RomInformation(QString file)
{
bool isRefreshingRomList = this->ui_Widget_RomBrowser->IsRefreshingRomList();
if (isRefreshingRomList)
{
this->ui_Widget_RomBrowser->StopRefreshRomList();
}
Dialog::RomInfoDialog dialog(file, this);
dialog.exec();
if (isRefreshingRomList)
{
this->ui_Widget_RomBrowser->RefreshRomList();
}
}
void MainWindow::on_VidExt_Init(void)
{
this->ui_VidExt_Geometry_Saved = false;
@@ -1324,6 +1391,12 @@ void MainWindow::on_Core_DebugCallback(CoreDebugMessageType type, QString messag
return;
}
// drop IS64 messages
if (message.startsWith("IS64:"))
{
return;
}
if (type == CoreDebugMessageType::Error)
{
this->ui_MessageBox("Error", "Core Error", message);
+10 -3
View File
@@ -12,6 +12,7 @@
#include "Thread/EmulationThread.hpp"
#include "Dialog/SettingsDialog.hpp"
#include "Dialog/RomInfoDialog.hpp"
#include "EventFilter.hpp"
#include "Widget/OGLWidget.hpp"
#include "Widget/RomBrowserWidget.hpp"
@@ -23,6 +24,7 @@
#include <QOpenGLWidget>
#include <QSettings>
#include <QStackedWidget>
#include <QGuiApplication>
namespace UserInterface
{
@@ -34,7 +36,7 @@ class MainWindow : public QMainWindow
MainWindow(void);
~MainWindow(void);
bool Init(void);
bool Init(QGuiApplication*);
void OpenROM(QString);
private:
@@ -54,7 +56,6 @@ class MainWindow : public QMainWindow
QMenu *menuBar_Menu;
QAction *action_File_OpenRom;
QAction *action_File_OpenCombo;
QAction *action_File_RomInfo;
QAction *action_File_StartEmulation;
QAction *action_File_EndEmulation;
QAction *action_File_Language;
@@ -97,6 +98,7 @@ class MainWindow : public QMainWindow
bool ui_VidExtForceSetMode;
bool ui_RefreshRomListAfterEmulation = false;
bool ui_ManuallyPaused = true;
int ui_TimerId = 0;
int ui_TimerTimeout = 0;
@@ -133,6 +135,8 @@ class MainWindow : public QMainWindow
void on_EventFilter_KeyReleased(QKeyEvent *);
void on_EventFilter_FileDropped(QDropEvent *);
void on_QGuiApplication_applicationStateChanged(Qt::ApplicationState);
void on_Action_File_OpenRom(void);
void on_Action_File_OpenCombo(void);
void on_Action_File_EndEmulation(void);
@@ -164,7 +168,10 @@ class MainWindow : public QMainWindow
void on_Emulation_Started(void);
void on_Emulation_Finished(bool);
void on_RomBrowser_Selected(QString);
void on_RomBrowser_PlayGame(QString);
void on_RomBrowser_PlayGameWithDisk(QString);
void on_RomBrowser_EditGameSettings(QString);
void on_RomBrowser_RomInformation(QString);
public slots:
@@ -58,7 +58,7 @@ void KeyBindButton::keyPressEvent(QKeyEvent * event)
void KeyBindButton::keyReleaseEvent(QKeyEvent *event)
{
this->setText(this->keySequence.toString());
this->currentText = this->keySequence.toString();
this->clearFocus();
}
@@ -69,3 +69,14 @@ void KeyBindButton::mousePressEvent(QMouseEvent *event)
this->setText("");
}
}
void KeyBindButton::focusInEvent(QFocusEvent *event)
{
currentText = this->text();
this->setText("...");
}
void KeyBindButton::focusOutEvent(QFocusEvent *event)
{
this->setText(this->currentText);
}
@@ -14,6 +14,7 @@ class KeyBindButton : public QPushButton
{
private:
QKeySequence keySequence;
QString currentText;
public:
KeyBindButton(QWidget *);
@@ -23,6 +24,8 @@ private:
void keyPressEvent(QKeyEvent *);
void keyReleaseEvent(QKeyEvent *);
void mousePressEvent(QMouseEvent *);
void focusInEvent(QFocusEvent *event);
void focusOutEvent(QFocusEvent *event);
};
} // namespace Widget
} // namespace UserInterface
@@ -80,7 +80,7 @@ void RomBrowserWidget::StopRefreshRomList(void)
{
if (this->romSearcher_Thread->isRunning())
{
this->romSearcher_Thread->terminate();
this->romSearcher_Thread->Stop();
}
}
@@ -148,6 +148,17 @@ void RomBrowserWidget::contextMenu_Actions_Connect(void)
connect(this->action_EditCheats, &QAction::triggered, this, &RomBrowserWidget::on_Action_EditCheats);
}
void RomBrowserWidget::contextMenu_Actions_Update(void)
{
bool enabled = this->selectedIndexes().count() > 0;
this->action_PlayGame->setEnabled(enabled);
this->action_PlayGameWithDisk->setEnabled(enabled);
this->action_RomInformation->setEnabled(enabled);
this->action_EditGameSettings->setEnabled(enabled);
this->action_EditCheats->setEnabled(enabled);
}
void RomBrowserWidget::model_Init(void)
{
this->model_Model = new QStandardItemModel(this);
@@ -289,10 +300,13 @@ int RomBrowserWidget::column_GetSizeSettingIndex(int column)
void RomBrowserWidget::launchSelectedRom(void)
{
QModelIndex index = this->selectedIndexes().first();
QString rom = this->model()->itemData(index).last().toString();
emit this->on_RomBrowser_PlayGame(this->getCurrentRom());
}
emit this->on_RomBrowser_Select(rom);
QString RomBrowserWidget::getCurrentRom(void)
{
QModelIndex index = this->selectedIndexes().first();
return this->model()->itemData(index).last().toString();
}
void RomBrowserWidget::dragMoveEvent(QDragMoveEvent *event)
@@ -316,6 +330,7 @@ void RomBrowserWidget::dropEvent(QDropEvent *event)
void RomBrowserWidget::customContextMenuRequested(QPoint position)
{
this->contextMenu_Actions_Update();
this->contextMenu->popup(this->viewport()->mapToGlobal(position));
}
@@ -344,6 +359,7 @@ void RomBrowserWidget::on_Action_PlayGame(void)
void RomBrowserWidget::on_Action_PlayGameWithDisk(void)
{
this->on_RomBrowser_PlayGameWithDisk(this->getCurrentRom());
}
void RomBrowserWidget::on_Action_RefreshRomList(void)
@@ -353,14 +369,17 @@ void RomBrowserWidget::on_Action_RefreshRomList(void)
void RomBrowserWidget::on_Action_ChooseRomDirectory(void)
{
this->on_RomBrowser_ChooseRomDirectory();
}
void RomBrowserWidget::on_Action_RomInformation(void)
{
this->on_RomBrowser_RomInformation(this->getCurrentRom());
}
void RomBrowserWidget::on_Action_EditGameSettings(void)
{
this->on_RomBrowser_EditGameSettings(this->getCurrentRom());
}
void RomBrowserWidget::on_Action_EditCheats(void)
@@ -60,6 +60,7 @@ class RomBrowserWidget : public QTableView
void contextMenu_Actions_Init(void);
void contextMenu_Actions_Setup(void);
void contextMenu_Actions_Connect(void);
void contextMenu_Actions_Update(void);
QStandardItemModel *model_Model;
std::vector<int> model_Columns;
@@ -80,6 +81,8 @@ class RomBrowserWidget : public QTableView
void launchSelectedRom(void);
QString getCurrentRom(void);
protected:
void dragMoveEvent(QDragMoveEvent *);
void dragEnterEvent(QDragEnterEvent *);
@@ -102,8 +105,12 @@ class RomBrowserWidget : public QTableView
void on_RomBrowserThread_Received(QString file, CoreRomHeader header, CoreRomSettings settings);
signals:
void on_RomBrowser_Select(QString);
void on_RomBrowser_PlayGame(QString);
void on_RomBrowser_PlayGameWithDisk(QString);
void on_RomBrowser_FileDropped(QDropEvent *);
void on_RomBrowser_EditGameSettings(QString);
void on_RomBrowser_ChooseRomDirectory(void);
void on_RomBrowser_RomInformation(QString);
};
} // namespace Widget
} // namespace UserInterface
+1 -1
View File
@@ -21,7 +21,7 @@ int main(int argc, char **argv)
QDir::setCurrent(app.applicationDirPath());
if (!window.Init())
if (!window.Init(&app))
{
return 1;
}
+1 -1
View File
@@ -27,7 +27,7 @@ then
generator="MSYS Makefiles"
fi
cmake -S "$toplvl_dir" -B "$build_dir" -DCMAKE_BUILD_TYPE="$build_config" -G "$generator"
cmake -S "$toplvl_dir" -B "$build_dir" -DCMAKE_BUILD_TYPE="$build_config" -DPORTABLE_INSTALL=ON -G "$generator"
make install DESTDIR="$toplvl_dir" -j$threads