Compare commits

...

45 Commits

Author SHA1 Message Date
Rosalie Wanders bfbbbdda7b 3rdParty: update mupen64plus-input-gcn 2023-05-06 00:03:19 +02:00
Rosalie Wanders 67a885b43b 3rdParty: update mupen64plus-input-gcn 2023-05-05 23:26:50 +02:00
Rosalie Wanders a49fe03fc2 3rdParty: update mupen64plus-input-gcn 2023-05-05 22:21:29 +02:00
Rosalie Wanders a7b07dc0f9 ci: install libusb 2023-05-05 22:02:50 +02:00
Rosalie Wanders f9a767f8ae 3rdParty: remove mupen64plus-input-gca and add mupen64plus-input-gcn 2023-05-05 21:57:47 +02:00
Rosalie Wanders 42a4786a25 cmake: remove NO_RUST option 2023-05-05 21:57:29 +02:00
Rosalie Wanders b166eac200 Package: update InGame.png 2023-05-04 23:29:12 +02:00
Rosalie Wanders c06316f4aa Package: update RomBrowser.png 2023-05-04 23:27:22 +02:00
Rosalie Wanders 09d96d9e4d README: improve Support section 2023-05-04 23:18:23 +02:00
Rosalie Wanders 66703970b6 Package: v0.4.0 2023-05-04 22:49:45 +02:00
Rosalie Wanders 0d3314a39b 3rdParty: update mupen64plus-input-gca 2023-05-04 22:41:22 +02:00
Rosalie Wanders 748492cc68 Data: add more custom cheats from Gent 2023-05-04 22:25:00 +02:00
Rosalie Wanders e18ad31c53 RMG: set default QSurfaceFormat with vsync disabled in main.cpp 2023-05-04 22:24:32 +02:00
Rosalie Wanders 0dd297f0f8 3rdParty: update angrylion-rdp-plus 2023-04-24 16:42:52 +02:00
Rosalie Wanders 0da4becd46 3rdParty: update parallel-rsp 2023-04-24 16:40:35 +02:00
Rosalie Wanders d284911d4a Installer: don't skip Run when silent 2023-04-16 00:12:11 +02:00
Rosalie Wanders e772eb3906 RMG: don't install desktop icon on update on windows 2023-04-16 00:11:48 +02:00
Rosalie Wanders 577ee4c3e0 3rdParty: update GLideN64 2023-04-15 16:00:58 +02:00
Rosalie Wanders c534df8303 RMG: disable floating on toolbar 2023-04-13 17:47:47 +02:00
Rosalie Wanders a36c8f7de8 3rdParty: update SDL_GameControllerDB 2023-04-07 22:42:11 +02:00
Rosalie Wanders dfb5f1b687 Package: update InputSettings.png 2023-04-07 21:58:29 +02:00
Rosalie Wanders d8eea015fd RMG: allow the toolbar to be moved 2023-04-07 20:54:20 +02:00
Rosalie Wanders f17b7eb2c9 RMG-Core: add GUI_ToolbarArea setting 2023-04-07 20:52:06 +02:00
Rosalie Wanders 33146626a9 Package: v0.3.9 2023-04-06 14:34:29 +02:00
Rosalie Wanders 78e12f774d RMG: add "Edit Game Input Settings" to the context menu of the ROM browser 2023-04-06 14:11:58 +02:00
Rosalie Wanders 689d8debb1 RMG-Input: implement PluginConfig2() and PluginConfig2HasRomConfig() 2023-04-06 14:11:20 +02:00
Rosalie Wanders 8be1ed8af5 RMG-Core: introduce CorePluginsHasROMConfig() and CorePluginsOpenROMConfig() 2023-04-06 14:09:34 +02:00
Rosalie Wanders 0fabdb3f3a RMG-Input: account for versions which didn't have the sensitivity setting in main.cpp 2023-04-06 08:56:49 +02:00
Rosalie Wanders 7a64e7e479 RMG: show progress status in the loading screen of the ROM browser 2023-04-06 01:20:48 +02:00
Rosalie Wanders 8c1589d7cd RMG-Core: correct error message in read_7zip_file 2023-04-06 00:37:31 +02:00
Rosalie Wanders 5a74b137f2 RMG: implement 7-Zip support 2023-04-06 00:28:31 +02:00
Rosalie Wanders 52ba182610 RMG-Core: implement 7-Zip support 2023-04-06 00:28:31 +02:00
Rosalie Wanders b07eb79609 3rdParty: add 7-Zip 2023-04-06 00:28:31 +02:00
Rosalie Wanders 4e3915f527 RMG: only show 'Don't check for updates again' checkbox when needed 2023-04-05 16:22:27 +02:00
Rosalie Wanders 9f620f276d RMG-Input: account for versions which didn't have the sensitivity setting 2023-04-05 16:18:56 +02:00
JaxonWasTaken e3787b5ccf RMG-Input: implement "Analog Stick Sensitivity" 2023-03-31 19:47:31 +02:00
Rosalie Wanders 3d81a052c6 cmake: add NO_RUST option 2023-03-25 20:34:37 +01:00
Rosalie Wanders 6353be1599 RMG: expose CoreOverlay_SaveFileNameFormat setting 2023-03-12 21:47:20 +01:00
Rosalie Wanders bc6ee4877b RMG-Core: use {Core,CoreOverlay}_SaveFileNameFormat settings 2023-03-12 21:47:20 +01:00
Rosalie Wanders 6b38cc3740 RMG-Core: introduce {Core,CoreOverlay}_SaveFileNameFormat settings 2023-03-12 21:47:20 +01:00
Rosalie Wanders 9285fb9fdf 3rdParty: update mupen64plus-core 2023-03-12 21:47:19 +01:00
Rosalie Wanders f5c609413a Package: update archlinux PKGBUILD 2023-03-04 23:33:08 +01:00
RetraCarteR a304f11b1d RMG: introduce more columns (#119) 2023-03-04 23:10:01 +01:00
Rosalie Wanders e10ac1086f RMG: show window after opening ROM 2023-02-25 14:45:28 +01:00
Rosalie Wanders 4533ed61ac 3rdParty: update GLideN64 2023-02-25 14:44:15 +01:00
54 changed files with 1413 additions and 254 deletions
+2 -1
View File
@@ -18,7 +18,7 @@ jobs:
sudo add-apt-repository ppa:okirby/qt6-backports --yes
sudo apt-get -qq update
sudo apt-get upgrade
sudo apt-get -y install cmake ninja-build libhidapi-dev libsamplerate0-dev libspeex-dev libminizip-dev libsdl2-dev libfreetype6-dev libgl1-mesa-dev libglu1-mesa-dev pkg-config zlib1g-dev binutils-dev libspeexdsp-dev qt6-base-dev libqt6svg6-dev build-essential nasm git zip appstream
sudo apt-get -y install cmake ninja-build libusb-1.0-0-dev libhidapi-dev libsamplerate0-dev libspeex-dev libminizip-dev libsdl2-dev libfreetype6-dev libgl1-mesa-dev libglu1-mesa-dev pkg-config zlib1g-dev binutils-dev libspeexdsp-dev qt6-base-dev libqt6svg6-dev build-essential nasm git zip appstream
- name: Prepare Environment
run: |
echo "GIT_REVISION=$(git describe --tags --always)" >> $GITHUB_ENV
@@ -66,6 +66,7 @@ jobs:
mingw-w64-x86_64-SDL2
mingw-w64-x86_64-qt6
mingw-w64-x86_64-SDL2
mingw-w64-x86_64-libusb
mingw-w64-x86_64-hidapi
mingw-w64-x86_64-speexdsp
mingw-w64-x86_64-libsamplerate
+2 -1
View File
@@ -76,6 +76,7 @@ else()
endif()
add_subdirectory(Source/3rdParty)
add_subdirectory(Source/3rdParty/7-Zip)
add_subdirectory(Source/RMG-Core)
add_subdirectory(Source/RMG)
@@ -125,7 +126,7 @@ install(FILES ${MUPEN64PLUS_PLUGIN_RSP_PARALLEL}
install(FILES ${MUPEN64PLUS_PLUGIN_INPUT_RAPHNET}
DESTINATION ${PLUGIN_INSTALL_PATH}/Input
)
install(FILES ${MUPEN64PLUS_PLUGIN_INPUT_GCA}
install(FILES ${MUPEN64PLUS_PLUGIN_INPUT_GCN}
DESTINATION ${PLUGIN_INSTALL_PATH}/Input
)
install(FILES ${MUPEN64PLUS_PLUGIN_GFX_ANGRYLION}
@@ -0,0 +1,64 @@
[1FBAF161-2C1C54F1-C:41]
Name=1080 Snowboarding (JU) (M2)
$Enable All Levels & Boarders
80255089 00FF
8025508B 0005
81255096 FCFF
80255098 0007
$Have All\Contest First Place Done
80244098 0007
$Have All\Match Levels Completed
8025508A 0005
$Have All\Trick Attacks Done
81255096 FCFF
$Infinite Damage All Players & Levels
803F4C3C 0024
807F4C3C 0024
$Infinite Lives & Continues
8026B1CB 0003
$Always First Place (Player 1)
81267B88 2400
Note=The game will still show you in 2nd when you are behind. But when you cross the finish line, you will win!
$Open Level Character Select
Note=With these codes, you have to press the buttons listed below when you are viewing a certain boarders stats. Highlight Akari Hayami's stats, and then hold down the C-Left button and then press the A button to be the Crystal Boarder. Highlight Kensuke Kimachi's stats, and then hold down the C-Up button and then press the A button to be the Metal Boarder. Hightlight Rob Haywood's stats, and then hold down the C-Right button and then press the A button to be the Panda Boarder
8125508A 00??
01 Easy Level
02 Easy & Normal Level
03 Easy Normal & Hard Levels
04 Easy Normal Hard Levels & Crystal Boarder
05 Easy Normal Hard Levels & Crystal & Metal Boarders
$Play As
800200E7 00??
00 Dion Blaster
01 Kensuke Kimachi
02 Akari Hayami
03 Ricky Winterborn
04 Rob Haywood
05 Silver Boarder
06 Gold Boarder
07 Panda Boarder
$Freeze Timer In\Match Race
D1267B20 05E1
81267B20 1000
$Freeze Timer In\Time Attack
D12660CC 05E1
812660CC 1000
$Freeze Timer In\Trick Attack
D1266138 05E1
81266138 1000
$Freeze Timer In\Contest
D126628C 05E1
8126628C 1000
@@ -0,0 +1,55 @@
[58FD3F25-D92EAA8D-C:50]
Name=1080 Snowboarding (E) (M4)
$Enable All Levels & Boarders
80250AB9 00FF
80250ABB 0005
81250AC6 FCFF
80250AC8 0007
$Infinite Damage All Players and Levels
803F4C00 0024
807F4C00 0024
$Infinite Lives & Continues
802648A4 0003
$Open Level Character Select
Note=With these codes, you have to press the buttons listed below when you are viewing a certain boarders stats. Highlight Akari Hayami's stats, and then hold down the C-Left button and then press the A button to be the Crystal Boarder. Highlight Kensuke Kimachi's stats, and then hold down the C-Up button and then press the A button to be the Metal Boarder. Hightlight Rob Haywood's stats, and then hold down the C-Right button and then press the A button to be the Panda Boarder
8125508A 00??
01 Easy Level
02 Easy & Normal Level
03 Easy Normal & Hard Levels
04 Easy Normal Hard Levels & Crystal Boarder
05 Easy Normal Hard Levels & Crystal & Metal Boarders
$Play As
8001A0E7 00??
00 Dion Blaster
01 Kensuke Kimachi
02 Akari Hayami
03 Ricky Winterborn
04 Rob Haywood
05 Silver Boarder
06 Gold Boarder
07 Panda Boarder
$Always First Place (Player 1)
812679BC 2400
Note=The game will still show you in 2nd when you are behind. But when you cross the finish line, you will win!
$Freeze Timer In\Match Race
D1267954 05E1
81267954 1000
$Freeze Timer In\Time Attack
D1265D4C 05E1
81265D4C 1000
$Freeze Timer In\Trick Attack
D1265DB8 05E1
81265DB8 1000
$Freeze Timer In\Contest
D1265F48 05E1
81265F48 1000
+4 -3
View File
@@ -1,14 +1,14 @@
# Maintainer: Rosalie Wanders <rosalie@mailbox.org>
pkgname=rmg
pkgver=0.3.8
pkgver=0.3.9
pkgrel=1
pkgdesc="Rosalie's Mupen GUI"
arch=('x86_64')
url="https://github.com/Rosalie241/$pkgname"
license=('GPL3')
depends=("hidapi" "libsamplerate" "minizip" "sdl2" "zlib" "freetype2" "qt6-base" "qt6-svg" "xdg-user-dirs")
makedepends=("git" "nasm" "cmake" "cargo" "ninja")
depends=("hidapi" "libsamplerate" "speexdsp" "minizip" "sdl2" "zlib" "freetype2" "qt6-base" "qt6-svg" "xdg-user-dirs")
makedepends=("git" "nasm" "cmake" "ninja")
source=("git+https://github.com/Rosalie241/$pkgname.git#tag=v$pkgver")
sha256sums=('SKIP')
@@ -24,6 +24,7 @@ build()
-DCMAKE_BUILD_TYPE="Release" \
-DPORTABLE_INSTALL="OFF" \
-DCMAKE_INSTALL_PREFIX="/usr" \
-DNO_RUST="ON" \
-G "Ninja"
cmake --build "$srcdir/$pkgname/build"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 318 KiB

After

Width:  |  Height:  |  Size: 302 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 85 KiB

+34 -5
View File
@@ -1,4 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<!-- Copyright 2022 Rosalie Wanders -->
<component type="desktop">
<!--Created with jdAppdataEdit 2.1-->
<id>com.github.Rosalie241.RMG</id>
@@ -11,27 +12,55 @@
<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>
<caption>01 - 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>
<caption>02 - During A Game</caption>
<image type="source">https://github.com/Rosalie241/RMG/raw/master/Package/Screenshots/InGame.png</image>
</screenshot>
<screenshot type="default">
<caption>Cheats</caption>
<caption>03 - Cheats</caption>
<image type="source">https://github.com/Rosalie241/RMG/raw/master/Package/Screenshots/Cheats.png</image>
</screenshot>
<screenshot type="default">
<caption>Settings</caption>
<caption>04 - Settings</caption>
<image type="source">https://github.com/Rosalie241/RMG/raw/master/Package/Screenshots/Settings.png</image>
</screenshot>
<screenshot type="default">
<caption>Input Settings</caption>
<caption>05 - Input Settings</caption>
<image type="source">https://github.com/Rosalie241/RMG/raw/master/Package/Screenshots/InputSettings.png</image>
</screenshot>
</screenshots>
<releases>
<release version="v0.4.0" date="2023-05-04" type="stable">
<description>
<p>Changes:</p>
<ul>
<li>Fix updater on windows always installing the desktop icon</li>
<li>Fix updater on windows not re-launching RMG after installation</li>
<li>Fix the speed limiter toggle and speed factor options not working on linux on some systems</li>
<li>Fix the 1080 Snowboarding cheats (thank you Gent)</li>
<li>Add support for moving the toolbar (changes to the docked position are persistent across application runs)</li>
<li>Update GLideN64 and mupen64plus-input-gca</li>
</ul>
</description>
</release>
<release version="v0.3.9" date="2023-04-06" type="stable">
<description>
<p>Changes:</p>
<ul>
<li>Fix "Don't check for updates again" checkbox appearing when requesting an update check through Help -> Check For Updates</li>
<li>Add game format, file name, file extension, file size, game I.D. and game region columns to the list view of the ROM browser which can be toggled in the "Show/Hide Columns" menu of the context menu in the list view of the ROM browser (thank you RetraCarteR)</li>
<li>Add "Reset Column Sizes" to context menu of the list view of the ROM browser (thank you RetraCarteR)</li>
<li>Add "Analog Stick Sensitivity" setting to RMG-Input (thank you JaxonWasTaken)</li>
<li>Add "Save Filename Format" setting to the Core tab of the settings dialog</li>
<li>Add "Edit Game Input Settings" to the context menu of the ROM browser</li>
<li>Add support for 7z files</li>
<li>Add progress status to the loading screen in the ROM browser when loading takes more than 5 seconds</li>
</ul>
</description>
</release>
<release version="v0.3.8" date="2023-02-24" type="stable">
<description>
<p>Changes:</p>
+3 -1
View File
@@ -17,7 +17,9 @@ You can download Rosalie's Mupen GUI on
## Support
Join the [Rosalie's Mupen GUI Discord Server](https://discord.gg/k9GuyJ2PpF) for support
You can ask for help or report issues on
* [Github](https://github.com/Rosalie241/RMG/issues/new)
* [Discord](https://discord.gg/k9GuyJ2PpF)
## License
+40
View File
@@ -0,0 +1,40 @@
#
# 7-Zip CMakeLists.txt
#
project(7Zip)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(7ZIP_SOURCES
${CMAKE_CURRENT_BINARY_DIR}/C/Bcj2.c
${CMAKE_CURRENT_BINARY_DIR}/C/Bra.c
${CMAKE_CURRENT_BINARY_DIR}/C/Bra86.c
${CMAKE_CURRENT_BINARY_DIR}/C/BraIA64.c
${CMAKE_CURRENT_BINARY_DIR}/C/CpuArch.c
${CMAKE_CURRENT_BINARY_DIR}/C/Delta.c
${CMAKE_CURRENT_BINARY_DIR}/C/Lzma2Dec.c
${CMAKE_CURRENT_BINARY_DIR}/C/LzmaDec.c
${CMAKE_CURRENT_BINARY_DIR}/C/Ppmd7.c
${CMAKE_CURRENT_BINARY_DIR}/C/Ppmd7Dec.c
${CMAKE_CURRENT_BINARY_DIR}/C/7zCrc.c
${CMAKE_CURRENT_BINARY_DIR}/C/7zCrcOpt.c
${CMAKE_CURRENT_BINARY_DIR}/C/Sha256.c
${CMAKE_CURRENT_BINARY_DIR}/C/Sha256Opt.c
${CMAKE_CURRENT_BINARY_DIR}/C/7zAlloc.c
${CMAKE_CURRENT_BINARY_DIR}/C/7zArcIn.c
${CMAKE_CURRENT_BINARY_DIR}/C/7zBuf.c
${CMAKE_CURRENT_BINARY_DIR}/C/7zBuf2.c
${CMAKE_CURRENT_BINARY_DIR}/C/7zDec.c
${CMAKE_CURRENT_BINARY_DIR}/C/7zFile.c
${CMAKE_CURRENT_BINARY_DIR}/C/7zStream.c
)
add_custom_command(
OUTPUT ${7ZIP_SOURCES}
COMMAND ${CMAKE_COMMAND} -E tar "xvz" "${CMAKE_CURRENT_SOURCE_DIR}/lzma2201.tar.gz"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
add_definitions(-D_7ZIP_PPMD_SUPPPORT -DNDEBUG -D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE)
add_library(7Zip STATIC ${7ZIP_SOURCES})
+2
View File
@@ -0,0 +1,2 @@
# 7-Zip SDK v22.01
Downloaded from https://www.7-zip.org/sdk.html
Binary file not shown.
+20 -35
View File
@@ -5,22 +5,12 @@ 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 OFF)
else()
set(BUILD_INPUT_GCA ON)
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)
@@ -37,7 +27,7 @@ endif(USE_CCACHE)
if(NOT NO_GIT_CLONE)
set(MUPEN64PLUSCORE_URL "https://github.com/mupen64plus/mupen64plus-core")
set(MUPEN64PLUSCORE_TAG "7ee312cb282a7794c62d5d284bf93151c585dd1f")
set(MUPEN64PLUSCORE_TAG "d4f3e12db0609158c7b4e0beef2bb950aad0ccb9")
set(MUPEN64PLUS_RSP_CXD4_URL "https://github.com/mupen64plus/mupen64plus-rsp-cxd4")
set(MUPEN64PLUS_RSP_CXD4_TAG "39f79201baa15890c4cbae92f2215a634cc3ee6d")
@@ -46,19 +36,19 @@ if(NOT NO_GIT_CLONE)
set(MUPEN64PLUS_RSP_HLE_TAG "88093cb43499eff53d343653cddcae2132af17ef")
set(MUPEN64PLUS_RSP_PARALLEL_URL "https://github.com/Rosalie241/parallel-rsp")
set(MUPEN64PLUS_RSP_PARALLEL_TAG "cfeea3a0f89ba5bc4265acb75778e1267ed1e424")
set(MUPEN64PLUS_RSP_PARALLEL_TAG "dbecbe3a120e428436c5972fa7b872cfc2c9db3e")
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 "21639fb13dfa797a7c0949ffd9bbda9a3456fc69")
set(MUPEN64PLUS_INPUT_GCN_URL "https://github.com/Rosalie241/mupen64plus-input-gcn")
set(MUPEN64PLUS_INPUT_GCN_TAG "e220115fa8ad223be783c822a251d7e0f873ed4c")
set(MUPEN64PLUS_GFX_ANGRYLION_URL "https://github.com/Rosalie241/angrylion-rdp-plus")
set(MUPEN64PLUS_GFX_ANGRYLION_TAG "158e74d4ec1c818289cd19c3a05e498c3ceff758")
set(MUPEN64PLUS_GFX_ANGRYLION_TAG "670abbc972bd430fa77291b0967dd73128314317")
set(MUPEN64PLUS_GFX_GLIDEN64_URL "https://github.com/Rosalie241/GLideN64")
set(MUPEN64PLUS_GFX_GLIDEN64_TAG "937e2a082c63b917654ff59cfc0b5125ad525dce")
set(MUPEN64PLUS_GFX_GLIDEN64_URL "https://github.com/gonetz/GLideN64")
set(MUPEN64PLUS_GFX_GLIDEN64_TAG "0fee30d010d1feda7d343654871b3dfd05ccab70")
set(MUPEN64PLUS_GFX_PARALLEL_URL "https://github.com/Rosalie241/parallel-rdp-standalone")
set(MUPEN64PLUS_GFX_PARALLEL_TAG "2c2226517c4c8929e08ec944654867e26efe0cf5")
@@ -70,7 +60,7 @@ if(NOT NO_GIT_CLONE)
set(IMGUI_TAG "d7c8516a4b848c0291e3d75b627c0843f515f591")
set(SDL_GAMECONTROLLERDB_URL "https://github.com/gabomdq/SDL_GameControllerDB")
set(SDL_GAMECONTROLLERDB_TAG "0562b00eaf5c0308c49d329b79263d2dae1c3a85")
set(SDL_GAMECONTROLLERDB_TAG "b7e5701da82fc97beeede64d3818ef0f4d015aba")
endif(NOT NO_GIT_CLONE)
ExternalProject_Add(mupen64plus-core
@@ -161,23 +151,20 @@ ExternalProject_Add(mupen64plus-input-raphnetraw
DEPENDS mupen64plus-core
)
if (BUILD_INPUT_GCA)
ExternalProject_Add(mupen64plus-input-gca
SOURCE_DIR mupen64plus-input-gca/
ExternalProject_Add(mupen64plus-input-gcn
SOURCE_DIR mupen64plus-input-gcn
CONFIGURE_COMMAND ""
INSTALL_COMMAND ""
GIT_REPOSITORY ${MUPEN64PLUS_INPUT_GCN_URL}
GIT_TAG ${MUPEN64PLUS_INPUT_GCN_TAG}
GIT_REPOSITORY ${MUPEN64PLUS_INPUT_GCA_URL}
GIT_TAG ${MUPEN64PLUS_INPUT_GCA_TAG}
INSTALL_COMMAND ""
BUILD_COMMAND cargo build --release --features "m64p_compat"
BUILD_IN_SOURCE True
BUILD_IN_SOURCE True
CMAKE_ARGS ${CMAKE_CONFIGURE_ARGS}
BUILD_BYPRODUCTS ${THIRDPARTY_DIR}/mupen64plus-input-gca/target/release/${GCA_LIB}
DEPENDS mupen64plus-core
)
endif(BUILD_INPUT_GCA)
BUILD_BYPRODUCTS ${THIRDPARTY_DIR}/mupen64plus-input-gcn/mupen64plus-input-gcn.${SO_EXT}
DEPENDS mupen64plus-core
)
set(GLIDEN64_DIR "${THIRDPARTY_DIR}/mupen64plus-video-GLideN64")
set(GLIDEN64_BUILD_DIR "${GLIDEN64_DIR}/projects/cmake")
@@ -326,10 +313,8 @@ set(MUPEN64PLUS_PLUGIN_RSP_PARALLEL ${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)
ExternalProject_Get_property(mupen64plus-input-gca BUILD_BYPRODUCTS)
set(MUPEN64PLUS_PLUGIN_INPUT_GCA ${BUILD_BYPRODUCTS} PARENT_SCOPE)
endif(BUILD_INPUT_GCA)
ExternalProject_Get_property(mupen64plus-input-gcn BUILD_BYPRODUCTS)
set(MUPEN64PLUS_PLUGIN_INPUT_GCN ${BUILD_BYPRODUCTS} PARENT_SCOPE)
ExternalProject_Get_property(mupen64plus-video-angrylion-plus BUILD_BYPRODUCTS)
set(MUPEN64PLUS_PLUGIN_GFX_ANGRYLION ${BUILD_BYPRODUCTS} PARENT_SCOPE)
+1 -1
View File
@@ -55,5 +55,5 @@ Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall
+1
View File
@@ -80,6 +80,7 @@ endif(WIN32)
target_link_libraries(RMG-Core
${MINIZIP_LIBRARIES}
7Zip
)
if (DISCORD_RPC)
+26 -2
View File
@@ -36,11 +36,13 @@
#define ROMHEADER_NAME_LEN 256
#define GOODNAME_LEN 256
#define MD5_LEN 33
#define GAMEID_LEN 5
#define REGION_LEN 18
#ifdef _WIN32
#define CACHE_FILE_MAGIC "RMGCoreHeaderAndSettingsCacheWindows_05"
#define CACHE_FILE_MAGIC "RMGCoreHeaderAndSettingsCacheWindows_06"
#else // Linux
#define CACHE_FILE_MAGIC "RMGCoreHeaderAndSettingsCacheLinux_05"
#define CACHE_FILE_MAGIC "RMGCoreHeaderAndSettingsCacheLinux_06"
#endif // _WIN32
#define CACHE_FILE_ITEMS_MAX 10000
@@ -103,6 +105,8 @@ void CoreReadRomHeaderAndSettingsCache(void)
char magicBuf[sizeof(CACHE_FILE_MAGIC)];
wchar_t fileNameBuf[MAX_FILENAME_LEN];
char headerNameBuf[ROMHEADER_NAME_LEN];
char gameIDBuf[GAMEID_LEN];
char regionBuf[REGION_LEN];
char goodNameBuf[GOODNAME_LEN];
char md5Buf[MD5_LEN];
uint32_t size;
@@ -131,6 +135,8 @@ void CoreReadRomHeaderAndSettingsCache(void)
size = 0;
memset(fileNameBuf, 0, sizeof(fileNameBuf));
memset(headerNameBuf, 0, sizeof(headerNameBuf));
memset(gameIDBuf, 0, sizeof(gameIDBuf));
memset(regionBuf, 0, sizeof(regionBuf));
memset(goodNameBuf, 0, sizeof(goodNameBuf));
memset(md5Buf, 0, sizeof(md5Buf));
@@ -144,7 +150,13 @@ void CoreReadRomHeaderAndSettingsCache(void)
// header
FREAD(size);
FREAD_STR(headerNameBuf, size);
FREAD(size);
FREAD_STR(gameIDBuf, size);
FREAD(size);
FREAD_STR(regionBuf, size);
cacheEntry.header.Name = std::string(headerNameBuf);
cacheEntry.header.GameID = std::string(gameIDBuf);
cacheEntry.header.Region = std::string(regionBuf);
FREAD(cacheEntry.header.CRC1);
FREAD(cacheEntry.header.CRC2);
// (partial) settings
@@ -169,6 +181,8 @@ bool CoreSaveRomHeaderAndSettingsCache(void)
std::ofstream outputStream;
wchar_t fileNameBuf[MAX_FILENAME_LEN];
char headerNameBuf[ROMHEADER_NAME_LEN];
char gameIDBuf[GAMEID_LEN];
char regionBuf[REGION_LEN];
char goodNameBuf[GOODNAME_LEN];
char md5Buf[MD5_LEN];
uint32_t size;
@@ -200,12 +214,16 @@ bool CoreSaveRomHeaderAndSettingsCache(void)
size = 0;
memset(fileNameBuf, 0, sizeof(fileNameBuf));
memset(headerNameBuf, 0, sizeof(headerNameBuf));
memset(gameIDBuf, 0, sizeof(gameIDBuf));
memset(regionBuf, 0, sizeof(regionBuf));
memset(goodNameBuf, 0, sizeof(goodNameBuf));
memset(md5Buf, 0, sizeof(md5Buf));
// copy strings into buffers
wcsncpy(fileNameBuf, cacheEntry.fileName.wstring().c_str(), MAX_FILENAME_LEN);
strncpy(headerNameBuf, cacheEntry.header.Name.c_str(), sizeof(headerNameBuf));
strncpy(gameIDBuf, cacheEntry.header.GameID.c_str(), sizeof(gameIDBuf));
strncpy(regionBuf, cacheEntry.header.Region.c_str(), sizeof(regionBuf));
strncpy(goodNameBuf, cacheEntry.settings.GoodName.c_str(), sizeof(goodNameBuf));
strncpy(md5Buf, cacheEntry.settings.MD5.c_str(), sizeof(md5Buf));
@@ -220,6 +238,12 @@ bool CoreSaveRomHeaderAndSettingsCache(void)
size = cacheEntry.header.Name.size();
FWRITE(size);
FWRITE_STR(headerNameBuf, size);
size = cacheEntry.header.GameID.size();
FWRITE(size);
FWRITE_STR(gameIDBuf, size);
size = cacheEntry.header.Region.size();
FWRITE(size);
FWRITE_STR(regionBuf, size);
FWRITE(cacheEntry.header.CRC1);
FWRITE(cacheEntry.header.CRC2);
// (partial) settings
+1
View File
@@ -54,6 +54,7 @@ static void apply_coresettings_overlay(void)
CoreSettingsSetValue(SettingsID::Core_CountPerOp, CoreSettingsGetIntValue(SettingsID::CoreOverlay_CountPerOp));
CoreSettingsSetValue(SettingsID::Core_CountPerOpDenomPot, CoreSettingsGetIntValue(SettingsID::CoreOverlay_CountPerOpDenomPot));
CoreSettingsSetValue(SettingsID::Core_SiDmaDuration, CoreSettingsGetIntValue(SettingsID::CoreOverlay_SiDmaDuration));
CoreSettingsSetValue(SettingsID::Core_SaveFileNameFormat, CoreSettingsGetIntValue(SettingsID::CoreOverLay_SaveFileNameFormat));
}
static void apply_game_coresettings_overlay(void)
+91 -38
View File
@@ -285,6 +285,78 @@ bool apply_plugin_settings(std::string pluginSettings[4])
return true;
}
bool open_plugin_config(CorePluginType type, bool romConfig)
{
std::string error;
m64p_error ret;
bool resumeEmulation = false;
m64p::PluginApi* plugin;
std::string functionName;
if (!romConfig && !CorePluginsHasConfig(type))
{
error = "open_plugin_config Failed: ";
error += get_plugin_type_name(type);
error += " doesn't have the config or config2 function!";
CoreSetError(error);
return false;
}
else if (romConfig && !CorePluginsHasROMConfig(type))
{
error = "open_plugin_config Failed: ";
error += get_plugin_type_name(type);
error += " doesn't support ROM specific configuration!";
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();
}
plugin = get_plugin(type);
// check if the plugin has the Config2
// or Config function, the Config2 function
// has priority
if (plugin->Config2 != nullptr)
{
ret = plugin->Config2(romConfig ? 1 : 0);
functionName = "Config2";
}
else
{
ret = plugin->Config();
functionName = "Config";
}
if (ret != M64ERR_SUCCESS)
{
error = "CorePluginsOpenConfig (";
error += get_plugin_type_name(type);
error += ")->";
error += functionName;
error += "() Failed: ";
error += m64p::Core.ErrorMessage(ret);
CoreSetError(error);
}
// try to resume emulation when needed
if (resumeEmulation)
{
CoreResumeEmulation();
}
return ret == M64ERR_SUCCESS;
}
//
// Exported Functions
//
@@ -384,52 +456,33 @@ bool CoreArePluginsReady(void)
bool CorePluginsHasConfig(CorePluginType type)
{
return get_plugin(type)->Config != nullptr;
m64p::PluginApi* plugin;
plugin = get_plugin(type);
return plugin->Config != nullptr ||
plugin->Config2 != nullptr;
}
bool CorePluginsOpenConfig(CorePluginType type)
{
std::string error;
m64p_error ret;
bool resumeEmulation = false;
return open_plugin_config(type, false);
}
if (!CorePluginsHasConfig(type))
{
error = "CorePluginsOpenConfig Failed: ";
error += get_plugin_type_name(type);
error += " doesn't have config function!";
CoreSetError(error);
return false;
}
bool CorePluginsHasROMConfig(CorePluginType type)
{
m64p::PluginApi* plugin;
// 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();
}
plugin = get_plugin(type);
ret = get_plugin(type)->Config();
if (ret != M64ERR_SUCCESS)
{
error = "CorePluginsOpenConfig (";
error += get_plugin_type_name(type);
error += ")->Config() Failed: ";
error += m64p::Core.ErrorMessage(ret);
CoreSetError(error);
}
return plugin->Config2 != nullptr &&
plugin->Config2HasRomConfig != nullptr &&
plugin->Config2HasRomConfig() > 0;
}
// try to resume emulation when needed
if (resumeEmulation)
{
CoreResumeEmulation();
}
return ret == M64ERR_SUCCESS;
bool CorePluginsOpenROMConfig(CorePluginType type)
{
return open_plugin_config(type, true);
}
bool CoreAttachPlugins(void)
+8
View File
@@ -52,6 +52,14 @@ bool CorePluginsHasConfig(CorePluginType type);
// used plugin of given type
bool CorePluginsOpenConfig(CorePluginType type);
// returns wether the currently used plugin
// of the given type has a ROM config GUI
bool CorePluginsHasROMConfig(CorePluginType type);
// opens the ROM config GUI for the currently
// used plugin of given type
bool CorePluginsOpenROMConfig(CorePluginType type);
// attaches all used plugins
bool CoreAttachPlugins(void);
+174 -5
View File
@@ -16,6 +16,16 @@
#include "Cheats.hpp"
#include "osal/osal_files.hpp"
// 7-Zip includes
#include "../3rdParty/7-Zip/C/7zTypes.h"
#include "../3rdParty/7-Zip/C/7z.h"
#include "../3rdParty/7-Zip/C/7zAlloc.h"
#include "../3rdParty/7-Zip/C/7zBuf.h"
#include "../3rdParty/7-Zip/C/7zCrc.h"
#include "../3rdParty/7-Zip/C/7zFile.h"
#include "../3rdParty/7-Zip/C/7zVersion.h"
#include <string>
#include <unzip.h>
#include <fstream>
#include <cstdlib>
@@ -140,7 +150,7 @@ static bool read_zip_file(std::filesystem::path file, std::filesystem::path* ext
filefuncs.zclose_file = zlib_filefunc_close;
filefuncs.zerror_file = zlib_filefunc_testerror;
filefuncs.opaque = nullptr;
zipFile = unzOpen2_64((const void*)&file, &filefuncs);
if (zipFile == nullptr)
{
@@ -293,6 +303,155 @@ static bool read_zip_file(std::filesystem::path file, std::filesystem::path* ext
return false;
}
static bool read_7zip_file(std::filesystem::path file, std::filesystem::path* extractedFileName, bool* isDisk, char** buf, int* size)
{
std::string error;
const ISzAlloc alloc = { SzAlloc, SzFree };
const size_t bufSize = ((size_t)1 << 18);
ISzAlloc allocImp;
ISzAlloc allocTempImp;
CFileInStream archiveStream;
CLookToRead2 lookStream;
CSzArEx db;
SRes res;
// initialize allocator
allocImp = alloc;
allocTempImp = alloc;
// try to open file
#ifdef _WIN32
WRes wres = InFile_OpenW(&archiveStream.file, file.wstring().c_str());
#else
WRes wres = InFile_Open(&archiveStream.file, file.string().c_str());
#endif // _WIN32
if (wres != 0)
{
error = "read_7zip_file Failed: InFile_Open Failed: ";
error += std::to_string(wres);
CoreSetError(error);
return false;
}
// create vtables for streams
FileInStream_CreateVTable(&archiveStream);
archiveStream.wres = 0;
LookToRead2_CreateVTable(&lookStream, 0);
lookStream.buf = nullptr;
// allocate memory look reader
lookStream.buf = (Byte*)ISzAlloc_Alloc(&allocImp, bufSize);
if (lookStream.buf == nullptr)
{
error = "read_7zip_file Failed: ISzAlloc_Alloc Failed!";
CoreSetError(error);
return false;
}
// initialize look reader
lookStream.bufSize = bufSize;
lookStream.realStream = &archiveStream.vt;
LookToRead2_Init(&lookStream);
// initialize CRC table
CrcGenerateTable();
// initialize archive
SzArEx_Init(&db);
// try to open file
res = SzArEx_Open(&db, &lookStream.vt, &allocImp, &allocTempImp);
if (res != SZ_OK)
{
error = "read_7zip_file Failed: SzArEx_Open Failed: ";
error += std::to_string(res);
CoreSetError(error);
SzArEx_Free(&db, &allocImp);
ISzAlloc_Free(&allocImp, lookStream.buf);
return false;
}
for (int i = 0; i < db.NumFiles; i++)
{
size_t filename_size = 0;
uint16_t fileName[PATH_MAX];
// skip directories
if (SzArEx_IsDir(&db, i))
{
continue;
}
// skip when filename size exceeds our buffer size
filename_size = SzArEx_GetFileNameUtf16(&db, i, nullptr);
if (filename_size > PATH_MAX)
{
continue;
}
SzArEx_GetFileNameUtf16(&db, i, fileName);
std::filesystem::path fileNamePath((char16_t*)fileName);
std::string fileExtension = fileNamePath.has_extension() ? fileNamePath.extension().string() : "";
fileExtension = to_lower_str(fileExtension);
if (fileExtension == ".z64" ||
fileExtension == ".v64" ||
fileExtension == ".n64" ||
fileExtension == ".ndd" ||
fileExtension == ".d64")
{
uint32_t blockIndex = 0xFFFFFFFF;
uint8_t* outBuffer = nullptr;
size_t outBufferSize = 0;
size_t offset = 0;
size_t outSizeProcessed = 0;
res = SzArEx_Extract(&db, &lookStream.vt, i,
&blockIndex, &outBuffer, &outBufferSize,
&offset, &outSizeProcessed,
&allocImp, &allocTempImp);
if (res != SZ_OK)
{
error = "read_7zip_file Failed: SzArEx_Extract Failed: ";
error += std::to_string(res);
CoreSetError(error);
SzArEx_Free(&db, &allocImp);
ISzAlloc_Free(&allocImp, lookStream.buf);
File_Close(&archiveStream.file);
ISzAlloc_Free(&allocImp, outBuffer);
return false;
}
*size = outSizeProcessed;
// we have to memcpy it into buf, otherwise
// the free() in CoreOpenRom() crashes
*buf = (char*)malloc(outSizeProcessed);
memcpy(*buf, (outBuffer + offset), outSizeProcessed);
*extractedFileName = fileNamePath;
*isDisk = (fileExtension == ".ndd" || fileExtension == ".d64");
SzArEx_Free(&db, &allocImp);
ISzAlloc_Free(&allocImp, lookStream.buf);
File_Close(&archiveStream.file);
ISzAlloc_Free(&allocImp, outBuffer);
return true;
}
}
// cleanup
SzArEx_Free(&db, &allocImp);
ISzAlloc_Free(&allocImp, lookStream.buf);
File_Close(&archiveStream.file);
error = "read_7zip_file Failed: no valid ROMs found in 7zip!";
CoreSetError(error);
return false;
}
static bool read_raw_file(std::filesystem::path file, char** buf, int* size)
{
std::string error;
@@ -362,7 +521,6 @@ static bool write_file(std::filesystem::path file, char* buf, int size)
// write buffer to file
fileStream.write(buf, size);
fileStream.close();
return true;
}
@@ -395,14 +553,25 @@ bool CoreOpenRom(std::filesystem::path file)
file_extension = file.has_extension() ? file.extension().string() : "";
file_extension = to_lower_str(file_extension);
if (file_extension == ".zip")
if (file_extension == ".zip" ||
file_extension == ".7z")
{
std::filesystem::path extracted_file;
bool is_disk = false;
if (!read_zip_file(file, &extracted_file, &is_disk, &buf, &buf_size))
if (file_extension == ".zip")
{
return false;
if (!read_zip_file(file, &extracted_file, &is_disk, &buf, &buf_size))
{
return false;
}
}
else
{
if (!read_7zip_file(file, &extracted_file, &is_disk, &buf, &buf_size))
{
return false;
}
}
if (is_disk)
+94 -1
View File
@@ -21,6 +21,97 @@
#include "Error.hpp"
#include "Rom.hpp"
//
// Local Functions
//
static std::string get_gameid_from_header(m64p_rom_header header)
{
std::string gameID;
if (header.Manufacturer_ID == 0)
{
return "????";
}
gameID.push_back(char(ntohl(header.Manufacturer_ID)));
gameID.push_back(char(header.Cartridge_ID % 256));
gameID.push_back(char(header.Cartridge_ID / 256));
gameID.push_back(char(header.Country_code));
return gameID;
}
static std::string get_region_from_countrycode(char countryCode)
{
std::string region;
switch (countryCode)
{
case 'A':
region = "Region-Free";
break;
case 'B':
region = "Brazil";
break;
case 'C':
region = "China";
break;
case 'D':
region = "Germany";
break;
case 'E':
region = "North America";
break;
case 'F':
region = "France";
break;
case 'G':
region = "Gateway 64 (NTSC)";
break;
case 'H':
region = "Netherlands";
break;
case 'I':
region = "Italy";
break;
case 'J':
region = "Japan";
break;
case 'K':
region = "Korea";
break;
case 'L':
region = "Gateway 64 (PAL)";
break;
case 'N':
region = "Canada";
break;
case 'P':
case 'X':
region = "Europe/Australia";
break;
case 'S':
region = "Spain";
break;
case 'U':
region = "Australia";
break;
case 'W':
region = "Scandanavia";
break;
case 'Y':
case 'Z':
region = "Europe";
break;
default:
region = "Unknown";
break;
}
return region;
}
//
// Exported Functions
//
@@ -49,6 +140,8 @@ bool CoreGetCurrentRomHeader(CoreRomHeader& header)
header.CRC2 = ntohl(m64p_header.CRC2);
header.CountryCode = m64p_header.Country_code;
header.Name = CoreConvertStringEncoding((char*)m64p_header.Name, CoreStringEncoding::Shift_JIS);
header.GameID = get_gameid_from_header(m64p_header);
header.Region = get_region_from_countrycode((char)header.CountryCode);
return true;
}
+2
View File
@@ -19,6 +19,8 @@ struct CoreRomHeader
uint32_t CRC2;
uint32_t CountryCode;
std::string Name;
std::string GameID;
std::string Region;
};
// retrieves the currently opened ROM header
+26 -16
View File
@@ -13,6 +13,7 @@
#include "RomHeader.hpp"
#include "Error.hpp"
#include "Settings/Settings.hpp"
#include "m64p/Api.hpp"
#include <algorithm>
@@ -122,28 +123,37 @@ bool CoreGetSaveStatePath(int slot, std::filesystem::path& path)
}
// else use new filename
if (romSettings.GoodName.find("(unknown rom)") == std::string::npos)
{
if (romSettings.GoodName.size() < 32)
{
saveStatePath += romSettings.GoodName;
}
else
{
saveStatePath += romSettings.GoodName.substr(0, 32);
}
}
else if (!romHeader.Name.empty())
int format = CoreSettingsGetIntValue(SettingsID::Core_SaveFileNameFormat);
if (format == 0)
{
saveStatePath += romHeader.Name;
saveStatePath += saveStateExtension;
}
else
{
saveStatePath += "unknown";
if (romSettings.GoodName.find("(unknown rom)") == std::string::npos)
{
if (romSettings.GoodName.size() < 32)
{
saveStatePath += romSettings.GoodName;
}
else
{
saveStatePath += romSettings.GoodName.substr(0, 32);
}
}
else if (!romHeader.Name.empty())
{
saveStatePath += romHeader.Name;
}
else
{
saveStatePath += "unknown";
}
saveStatePath += "-";
saveStatePath += romSettings.MD5.substr(0, 8);
saveStatePath += saveStateExtension;
}
saveStatePath += "-";
saveStatePath += romSettings.MD5.substr(0, 8);
saveStatePath += saveStateExtension;
// retrieve filename from path
saveStateFileName = saveStatePath.filename().string();
+15 -3
View File
@@ -183,6 +183,9 @@ static l_Setting get_setting(SettingsID settingId)
case SettingsID::GUI_Toolbar:
setting = {SETTING_SECTION_GUI, "Toolbar", true};
break;
case SettingsID::GUI_ToolbarArea:
setting = {SETTING_SECTION_GUI, "ToolbarArea", 0};
break;
case SettingsID::GUI_StatusBar:
setting = {SETTING_SECTION_GUI, "StatusBar", true};
break;
@@ -277,6 +280,9 @@ static l_Setting get_setting(SettingsID settingId)
case SettingsID::Core_SiDmaDuration:
setting = {SETTING_SECTION_M64P, "SiDmaDuration", -1};
break;
case SettingsID::Core_SaveFileNameFormat:
setting = {SETTING_SECTION_M64P, "SaveFilenameFormat", 1};
break;
case SettingsID::CoreOverlay_RandomizeInterrupt:
setting = {SETTING_SECTION_OVERLAY, "RandomizeInterrupt", true};
@@ -299,6 +305,9 @@ static l_Setting get_setting(SettingsID settingId)
case SettingsID::CoreOverlay_SiDmaDuration:
setting = {SETTING_SECTION_OVERLAY, "SiDmaDuration", -1};
break;
case SettingsID::CoreOverLay_SaveFileNameFormat:
setting = {SETTING_SECTION_OVERLAY, "SaveFilenameFormat", 1};
break;
case SettingsID::Core_ScreenshotPath:
setting = {SETTING_SECTION_M64P, "ScreenshotPath", CoreGetDefaultScreenshotDirectory(), "", true};
@@ -545,13 +554,13 @@ static l_Setting get_setting(SettingsID settingId)
setting = {SETTING_SECTION_ROMBROWSER, "MaxItems", 250};
break;
case SettingsID::RomBrowser_ColumnVisibility:
setting = {SETTING_SECTION_ROMBROWSER, "ColumnVisibility", std::vector<int>({1, 1, 1})};
setting = {SETTING_SECTION_ROMBROWSER, "ColumnVisibility", std::vector<int>({1, 1, 1, 0, 0, 0, 0, 0, 0})};
break;
case SettingsID::RomBrowser_ColumnOrder:
setting = {SETTING_SECTION_ROMBROWSER, "ColumnOrder", std::vector<int>({0, 1, 2})};
setting = {SETTING_SECTION_ROMBROWSER, "ColumnOrder", std::vector<int>({0, 1, 2, 3, 4, 5, 6, 7, 8})};
break;
case SettingsID::RomBrowser_ColumnSizes:
setting = {SETTING_SECTION_ROMBROWSER, "ColumnSizes", std::vector<int>({-1, -1, -1})};
setting = {SETTING_SECTION_ROMBROWSER, "ColumnSizes", std::vector<int>({-1, -1, -1, -1, -1, -1, -1, -1, -1})};
break;
case SettingsID::RomBrowser_SortAfterSearch:
setting = {SETTING_SECTION_ROMBROWSER, "SortAfterSearch", true};
@@ -631,6 +640,9 @@ static l_Setting get_setting(SettingsID settingId)
case SettingsID::Input_Deadzone:
setting = {"", "Deadzone"};
break;
case SettingsID::Input_Sensitivity:
setting = {"", "Sensitivity"};
break;
case SettingsID::Input_Pak:
setting = {"", "Pak"};
break;
+4
View File
@@ -20,6 +20,7 @@ enum class SettingsID
GUI_OnScreenDisplayOpacity,
GUI_OnScreenDisplayDuration,
GUI_Toolbar,
GUI_ToolbarArea,
GUI_StatusBar,
GUI_Theme,
GUI_IconTheme,
@@ -64,6 +65,7 @@ enum class SettingsID
Core_CountPerOp,
Core_CountPerOpDenomPot,
Core_SiDmaDuration,
Core_SaveFileNameFormat,
// (mupen64plus) Overlay Core Settings
CoreOverlay_RandomizeInterrupt,
@@ -73,6 +75,7 @@ enum class SettingsID
CoreOverlay_CountPerOp,
CoreOverlay_CountPerOpDenomPot,
CoreOverlay_SiDmaDuration,
CoreOverLay_SaveFileNameFormat,
// (mupen64plus) Core Directory Settings
Core_ScreenshotPath,
@@ -186,6 +189,7 @@ enum class SettingsID
Input_DeviceName,
Input_DeviceNum,
Input_Deadzone,
Input_Sensitivity,
Input_Pak,
Input_GameboyRom,
Input_GameboySave,
+4
View File
@@ -28,6 +28,8 @@ bool PluginApi::Hook(m64p_dynlib_handle handle)
HOOK_FUNC(handle, Plugin, Startup);
HOOK_FUNC(handle, Plugin, Shutdown);
HOOK_FUNC_OPT(handle, Plugin, Config);
HOOK_FUNC_OPT(handle, Plugin, Config2);
HOOK_FUNC_OPT(handle, Plugin, Config2HasRomConfig);
HOOK_FUNC(handle, Plugin, GetVersion);
this->handle = handle;
@@ -40,6 +42,8 @@ bool PluginApi::Unhook(void)
UNHOOK_FUNC(Plugin, Startup);
UNHOOK_FUNC(Plugin, Shutdown);
UNHOOK_FUNC(Plugin, Config);
UNHOOK_FUNC(Plugin, Config2);
UNHOOK_FUNC(Plugin, Config2HasRomConfig);
UNHOOK_FUNC(Plugin, GetVersion);
this->handle = nullptr;
+2
View File
@@ -34,6 +34,8 @@ class PluginApi
ptr_PluginStartup Startup;
ptr_PluginShutdown Shutdown;
ptr_PluginConfig Config;
ptr_PluginConfig2 Config2;
ptr_PluginConfig2HasRomConfig Config2HasRomConfig;
ptr_PluginGetVersion GetVersion;
private:
+23
View File
@@ -21,6 +21,29 @@ typedef m64p_error (*ptr_PluginConfig)(void);
EXPORT m64p_error CALL PluginConfig(void);
#endif
/* PluginConfig2(int romConfig)
*
* This optional function opens a configuration GUI for the plugin
* https://github.com/mupen64plus/mupen64plus-core/pull/774
*
* romConfig argument determines if it should open the ROM specific config
*/
typedef m64p_error (*ptr_PluginConfig2)(int);
#if defined(M64P_PLUGIN_PROTOTYPES) || defined(M64P_CORE_PROTOTYPES)
EXPORT m64p_error CALL PluginConfig2(int);
#endif
/* PluginConfig2HasRomConfig(void)
*
* This optional function returns wether the plugin supports ROM specific config
* using PluginConfig2
*
*/
typedef int (*ptr_PluginConfig2HasRomConfig)(void);
#if defined(M64P_PLUGIN_PROTOTYPES) || defined(M64P_CORE_PROTOTYPES)
EXPORT int CALL PluginConfig2HasRomConfig(void);
#endif
#ifdef __cplusplus
}
#endif
@@ -18,7 +18,7 @@
using namespace UserInterface;
MainDialog::MainDialog(QWidget* parent, Thread::SDLThread* sdlThread) : QDialog(parent)
MainDialog::MainDialog(QWidget* parent, Thread::SDLThread* sdlThread, bool romConfig) : QDialog(parent)
{
this->setupUi(this);
this->setWindowIcon(QIcon(":Resource/RMG.png"));
@@ -41,6 +41,7 @@ MainDialog::MainDialog(QWidget* parent, Thread::SDLThread* sdlThread) : QDialog(
for (int i = 0; i < this->tabWidget->count(); i++)
{
Widget::ControllerWidget* widget = new Widget::ControllerWidget(this, this->eventFilter);
widget->SetOnlyLoadGameProfile(romConfig);
widget->SetSettingsSection("Player " + QString::number(i + 1), "Rosalie's Mupen GUI - Input Plugin Profile " + QString::number(i));
widget->LoadSettings();
this->tabWidget->widget(i)->layout()->addWidget(widget);
@@ -59,7 +59,7 @@ private:
void closeInputDevice();
public:
MainDialog(QWidget *parent, Thread::SDLThread*);
MainDialog(QWidget *parent, Thread::SDLThread*, bool);
~MainDialog(void);
public slots:
@@ -10,8 +10,8 @@
#include "ControllerImageWidget.hpp"
#include <QSvgRenderer>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <QPainter>
#include <QResizeEvent>
@@ -62,6 +62,15 @@ void ControllerImageWidget::SetDeadzone(int value)
}
}
void ControllerImageWidget::SetSensitivity(int value)
{
if (this->sensitivityValue != value)
{
this->sensitivityValue = value;
this->needImageUpdate = true;
}
}
void ControllerImageWidget::ClearControllerState()
{
// reset button state
@@ -153,27 +162,35 @@ void ControllerImageWidget::paintEvent(QPaintEvent *event)
renderer.setAspectRatioMode(Qt::AspectRatioMode::KeepAspectRatio);
QRectF rectF = renderer.viewBoxF();
double offsetx = 0, offsety = 0;
const int width = rectF.width();
const int height = rectF.height();
// we'll move the analog stick by a percentage
// of the total width/height from the image
const double maxOffsety = ((double)(height * 0.12265f) / 2);
const double maxOffsetx = maxOffsety;
const double dist = sqrt(pow(this->xAxisState, 2) + pow(this->yAxisState, 2));
const double absoluteMaxOffset = ((double)(height * 0.12265f) / 2);
// slope as in line gradient
const double offsetSlope = absoluteMaxOffset / 100;
// take sensitivity into account
const double sensitivityFactor = this->sensitivityValue / 100.0;
const double sensitivityAdjustedMaxOffset = absoluteMaxOffset * std::min(sensitivityFactor, 1.0);
double offsetDeadzone = this->deadzoneValue * sensitivityFactor * offsetSlope;
int offsetx = this->xAxisState * sensitivityFactor * offsetSlope;
int offsety = this->yAxisState * sensitivityFactor * offsetSlope;
const double offsetDist = sqrt(pow(offsetx, 2) + pow(offsety, 2));
// take deadzone into account
if (dist > this->deadzoneValue)
// deadzone grows with sensitivity such that the deadzone
// is always a percentage of the real stick range
if (offsetDist <= offsetDeadzone)
{
offsetx = (maxOffsetx / 100 * this->xAxisState);
offsety = (maxOffsety / 100 * this->yAxisState);
offsetx = 0;
offsety = 0;
}
// take circle range into account
if (dist > 100)
if (offsetDist > sensitivityAdjustedMaxOffset)
{
offsetx = (maxOffsetx / 100 * (this->xAxisState / dist * 100));
offsety = (maxOffsety / 100 * (this->yAxisState / dist * 100));
offsetx = (offsetx / offsetDist) * sensitivityAdjustedMaxOffset;
offsety = (offsety / offsetDist) * sensitivityAdjustedMaxOffset;
}
// adjust rect with offset
@@ -31,6 +31,8 @@ private:
int yAxisState = 0;
// deadzone value, 0-100
int deadzoneValue = 0;
// sensitivity value, 25-175
int sensitivityValue = 100;
bool needImageUpdate = false;
public:
@@ -41,6 +43,7 @@ public:
void SetXAxisState(int xAxis);
void SetYAxisState(int yAxis);
void SetDeadzone(int value);
void SetSensitivity(int value);
void ClearControllerState();
void UpdateImage();
@@ -323,6 +323,7 @@ void ControllerWidget::setPluggedIn(bool value)
this->analogStickDownButton, this->analogStickDownAddButton, this->analogStickDownRemoveButton,
this->analogStickLeftButton, this->analogStickLeftAddButton, this->analogStickLeftRemoveButton,
this->analogStickRightButton, this->analogStickRightAddButton, this->analogStickRightRemoveButton,
this->analogStickSensitivitySlider,
// cbuttons
this->cButtonsGroupBox,
this->cbuttonUpButton, this->cbuttonUpAddButton, this->cbuttonUpRemoveButton,
@@ -354,6 +355,67 @@ void ControllerWidget::setPluggedIn(bool value)
this->ClearControllerImage();
}
bool ControllerWidget::hasAnyGameSettingChanged(void)
{
std::string section = this->getCurrentSettingsSection().toStdString();
// fallback to main section
if (!CoreSettingsSectionExists(section))
{
section = this->settingsSection.toStdString();
}
// retrieve data from settings
bool settingsIsPluggedIn = CoreSettingsGetBoolValue(SettingsID::Input_PluggedIn, section);
int settingsDeadZone = CoreSettingsGetIntValue(SettingsID::Input_Deadzone, section);
int settingsAnalogSensitivity = 100;
// account for profiles before v0.3.9
if (CoreSettingsKeyExists(section, "Sensitivity"))
{
settingsAnalogSensitivity = CoreSettingsGetIntValue(SettingsID::Input_Sensitivity, section);
}
// retrieve current data
bool currentIsPluggedIn = this->inputDeviceComboBox->currentText() != "None";
int currentDeadZone = this->deadZoneSlider->value();
int currentAnalogSensitivity = this->analogStickSensitivitySlider->value();
// compare data
if (settingsIsPluggedIn != currentIsPluggedIn ||
settingsDeadZone != currentDeadZone ||
settingsAnalogSensitivity != currentAnalogSensitivity)
{
return true;
}
// compare button mappings with settings
for (auto& buttonSetting : this->buttonSettingMappings)
{
// retrieve data from settings
std::vector<int> settingsTypes = CoreSettingsGetIntListValue(buttonSetting.inputTypeSettingsId, section);
std::vector<std::string> settingsNames = CoreSettingsGetStringListValue(buttonSetting.nameSettingsId, section);
std::vector<int> settingsData = CoreSettingsGetIntListValue(buttonSetting.dataSettingsId, section);
std::vector<int> settingsExtraData = CoreSettingsGetIntListValue(buttonSetting.extraDataSettingsId, section);
// retrieve current data
std::vector<int> currentTypes = buttonSetting.button->GetInputType();
std::vector<std::string> currentNames = buttonSetting.button->GetInputText();
std::vector<int> currentData = buttonSetting.button->GetInputData();
std::vector<int> currentExtraData = buttonSetting.button->GetExtraInputData();
// compare data
if (settingsTypes != currentTypes ||
settingsNames != currentNames ||
settingsData != currentData ||
settingsExtraData != currentExtraData)
{
return true;
}
}
// no differences found
return false;
}
void ControllerWidget::showErrorMessage(QString text, QString details)
{
QMessageBox msgBox(this);
@@ -509,6 +571,16 @@ void ControllerWidget::on_deadZoneSlider_valueChanged(int value)
this->controllerImageWidget->SetDeadzone(value);
}
void ControllerWidget::on_analogStickSensitivitySlider_valueChanged(int value)
{
QString title = tr("Analog Stick Sensitivity: ");
title += QString::number(value);
title += "%";
this->analogStickSensitivityGroupBox->setTitle(title);
this->controllerImageWidget->SetSensitivity(value);
}
void ControllerWidget::on_profileComboBox_currentIndexChanged(int value)
{
// save profile when switching profile
@@ -622,7 +694,7 @@ void ControllerWidget::on_removeProfileButton_clicked()
{
bool ret;
if (this->profileComboBox->currentIndex() == 0)
if (this->profileComboBox->currentData().toString() == this->settingsSection)
{
QMessageBox messageBox(this);
messageBox.setIcon(QMessageBox::Icon::Warning);
@@ -678,6 +750,13 @@ void ControllerWidget::on_removeProfileButton_clicked()
this->previousProfileComboBoxIndex = -1;
this->profileComboBox->setCurrentIndex(0);
}
// force a re-load when
// we're only loading the game profile
if (this->onlyLoadGameProfile)
{
this->LoadSettings(this->settingsSection);
}
}
void ControllerWidget::on_resetButton_clicked()
@@ -1093,10 +1172,21 @@ bool ControllerWidget::IsPluggedIn()
return this->inputDeviceComboBox->currentData().toInt() != (int)InputDeviceType::None;
}
void ControllerWidget::SetOnlyLoadGameProfile(bool value)
{
this->onlyLoadGameProfile = value;
// update UI element
this->addProfileButton->setDisabled(value);
}
void ControllerWidget::SetSettingsSection(QString profile, QString section)
{
this->settingsSection = section;
this->profileComboBox->addItem(profile, section);
if (!this->onlyLoadGameProfile)
{
this->profileComboBox->addItem(profile, section);
}
}
void ControllerWidget::SetInitialized(bool value)
@@ -1145,41 +1235,53 @@ void ControllerWidget::LoadSettings()
// if a game specific section exists,
// select it in the profile combobox
// and use it to load the settings
if (CoreSettingsSectionExists(this->gameSection.toStdString()))
if (CoreSettingsSectionExists(this->gameSection.toStdString()) ||
this->onlyLoadGameProfile)
{
// check if the key 'UseGameProfile' exists,
// if it doesn't then use the profile,
// else check if it's true and use it
if (!CoreSettingsKeyExists(this->gameSection.toStdString(), "UseGameProfile") ||
// else check if it's true and use it,
// or if we're only loading the game profile
if (this->onlyLoadGameProfile ||
!CoreSettingsKeyExists(this->gameSection.toStdString(), "UseGameProfile") ||
CoreSettingsGetBoolValue(SettingsID::Input_UseGameProfile, this->gameSection.toStdString()))
{
this->profileComboBox->setCurrentText(internalName);
section = this->gameSection;
// only use game section if it exists
if (CoreSettingsSectionExists(this->gameSection.toStdString()))
{
section = this->gameSection;
}
}
}
}
// clear profiles list
profiles.clear();
// try to add all the user's profiles
userProfiles = CoreSettingsGetStringListValue(SettingsID::Input_Profiles);
for (const std::string& profile : userProfiles)
// try to add all the user's profiles when we're not only loading the
// game profile
if (!this->onlyLoadGameProfile)
{
QString profileSection = this->getUserProfileSectionName(QString::fromStdString(profile));
// clear profiles list
profiles.clear();
// ensure the profile section exists,
// if it does, add it when it doesn't
// exist yet
if (CoreSettingsSectionExists(profileSection.toStdString()))
userProfiles = CoreSettingsGetStringListValue(SettingsID::Input_Profiles);
for (const std::string& profile : userProfiles)
{
// add to profiles list
this->profiles.push_back(profileSection);
QString profileSection = this->getUserProfileSectionName(QString::fromStdString(profile));
int index = this->profileComboBox->findData(profileSection);
if (index == -1)
// ensure the profile section exists,
// if it does, add it when it doesn't
// exist yet
if (CoreSettingsSectionExists(profileSection.toStdString()))
{
this->profileComboBox->addItem(QString::fromStdString(profile), profileSection);
// add to profiles list
this->profiles.push_back(profileSection);
int index = this->profileComboBox->findData(profileSection);
if (index == -1)
{
this->profileComboBox->addItem(QString::fromStdString(profile), profileSection);
}
}
}
}
@@ -1219,7 +1321,7 @@ void ControllerWidget::LoadSettings(QString sectionQString, bool loadUserProfile
// if it does, see if that profile exists, then load
// that instead
useProfile = CoreSettingsGetStringValue(SettingsID::Input_UseProfile, section);
if (loadUserProfile && !useProfile.empty())
if (!this->onlyLoadGameProfile && loadUserProfile && !useProfile.empty())
{
QString profileSection = this->getUserProfileSectionName(QString::fromStdString(useProfile));
@@ -1232,6 +1334,16 @@ void ControllerWidget::LoadSettings(QString sectionQString, bool loadUserProfile
}
}
// keep backwards compatibility with versions before v0.3.9
if (CoreSettingsKeyExists(section, "Sensitivity"))
{
this->analogStickSensitivitySlider->setValue(CoreSettingsGetIntValue(SettingsID::Input_Sensitivity, section));
}
else
{
this->analogStickSensitivitySlider->setValue(100);
}
this->deadZoneSlider->setValue(CoreSettingsGetIntValue(SettingsID::Input_Deadzone, section));
this->optionsDialogSettings.RemoveDuplicateMappings = CoreSettingsGetBoolValue(SettingsID::Input_RemoveDuplicateMappings, section);
this->optionsDialogSettings.ControllerPak = CoreSettingsGetIntValue(SettingsID::Input_Pak, section);
@@ -1309,6 +1421,7 @@ void ControllerWidget::SaveDefaultSettings()
CoreSettingsSetValue(SettingsID::Input_DeviceName, section, std::string("None"));
CoreSettingsSetValue(SettingsID::Input_DeviceNum, section, (int)InputDeviceType::None);
CoreSettingsSetValue(SettingsID::Input_Deadzone, section, 9);
CoreSettingsSetValue(SettingsID::Input_Sensitivity, section, 100);
CoreSettingsSetValue(SettingsID::Input_Pak, section, 0);
CoreSettingsSetValue(SettingsID::Input_RemoveDuplicateMappings, section, true);
CoreSettingsSetValue(SettingsID::Input_FilterEventsForButtons, section, true);
@@ -1330,6 +1443,14 @@ void ControllerWidget::SaveSettings()
return;
}
// when we're only loading the game profile,
// we should only save when anything has changed
if (this->onlyLoadGameProfile &&
!this->hasAnyGameSettingChanged())
{
return;
}
this->SaveSettings(this->getCurrentSettingsSection());
// delete all removed profile sections
@@ -1393,6 +1514,7 @@ void ControllerWidget::SaveSettings(QString section)
CoreSettingsSetValue(SettingsID::Input_DeviceName, sectionStr, deviceName.toStdString());
CoreSettingsSetValue(SettingsID::Input_DeviceNum, sectionStr, deviceNum);
CoreSettingsSetValue(SettingsID::Input_Deadzone, sectionStr, this->deadZoneSlider->value());
CoreSettingsSetValue(SettingsID::Input_Sensitivity, sectionStr, this->analogStickSensitivitySlider->value());
CoreSettingsSetValue(SettingsID::Input_Pak, sectionStr, this->optionsDialogSettings.ControllerPak);
CoreSettingsSetValue(SettingsID::Input_GameboyRom, sectionStr, this->optionsDialogSettings.GameboyRom);
CoreSettingsSetValue(SettingsID::Input_GameboySave, sectionStr, this->optionsDialogSettings.GameboySave);
@@ -1425,6 +1547,14 @@ void ControllerWidget::RevertSettings()
CoreSettingsRevertSection(section.toStdString());
}
// don't compare profiles,
// when we're only loading
// the game profile
if (this->onlyLoadGameProfile)
{
return;
}
// delete all sections for added & removed profiles,
// which aren't in the base profile section list
sections.clear();
@@ -95,6 +95,8 @@ private:
void setPluggedIn(bool value);
bool hasAnyGameSettingChanged(void);
void showErrorMessage(QString text, QString details = "");
SDL_JoystickID currentJoystickId = -1;
@@ -102,6 +104,8 @@ private:
int previousProfileComboBoxIndex = -1;
bool onlyLoadGameProfile = false;
public:
ControllerWidget(QWidget* parent, EventFilter* eventFilter);
~ControllerWidget();
@@ -116,6 +120,8 @@ public:
void GetCurrentInputDevice(QString& deviceName, int& deviceNum, bool ignoreDeviceNotFound = false);
bool IsPluggedIn();
void SetOnlyLoadGameProfile(bool value);
void SetSettingsSection(QString profile, QString section);
void SetInitialized(bool value);
@@ -138,6 +144,7 @@ public:
private slots:
void on_deadZoneSlider_valueChanged(int value);
void on_analogStickSensitivitySlider_valueChanged(int value);
void on_profileComboBox_currentIndexChanged(int value);
@@ -601,6 +601,43 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="analogStickSensitivityGroupBox">
<property name="title">
<string>Analog Stick Sensitivity: 100%</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_15">
<item>
<widget class="QSlider" name="analogStickSensitivitySlider">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimum">
<number>25</number>
</property>
<property name="maximum">
<number>175</number>
</property>
<property name="value">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>15</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
+29 -12
View File
@@ -21,7 +21,7 @@
#include <QApplication>
#include <SDL.h>
#include <iostream>
#include <algorithm>
#include <chrono>
//
@@ -60,6 +60,7 @@ struct InputProfile
{
bool PluggedIn = false;
int DeadzoneValue = 0;
int SensitivityValue = 100;
N64ControllerPak ControllerPak = N64ControllerPak::None;
@@ -223,6 +224,16 @@ static void load_settings(void)
profile->GameboyRom = CoreSettingsGetStringValue(SettingsID::Input_GameboyRom, section);
profile->GameboySave = CoreSettingsGetStringValue(SettingsID::Input_GameboySave, section);
// keep compatibility with profiles before version v0.3.9
if (CoreSettingsKeyExists(section, "Sensitivity"))
{
profile->SensitivityValue = CoreSettingsGetIntValue(SettingsID::Input_Sensitivity, section);
}
else
{
profile->SensitivityValue = 100;
}
// load inputmapping settings
load_inputmapping_settings(&profile->Button_A, section, SettingsID::Input_A_Name, SettingsID::Input_A_InputType, SettingsID::Input_A_Data, SettingsID::Input_A_ExtraData);
load_inputmapping_settings(&profile->Button_B, section, SettingsID::Input_B_Name, SettingsID::Input_B_InputType, SettingsID::Input_B_Data, SettingsID::Input_B_ExtraData);
@@ -406,7 +417,7 @@ static void close_controllers(void)
for (int i = 0; i < NUM_CONTROLLERS; i++)
{
InputProfile* profile = &l_InputProfiles[i];
profile->InputDevice.CloseDevice();
}
}
@@ -537,16 +548,17 @@ static double simulate_deadzone(const double n64InputAxis, const double maxAxis,
return axisAbsolute;
}
// Credit: MerryMage
static void simulate_octagon(const double inputX, const double inputY, const double deadzoneFactor, int& outputX, int& outputY)
// Credit: MerryMage & fzurita
static void simulate_octagon(const double inputX, const double inputY, const double deadzoneFactor, const double sensitivityFactor, int& outputX, int& outputY)
{
const double maxAxis = N64_AXIS_PEAK;
const double maxDiagonal = MAX_DIAGONAL_VALUE;
const int deadzone = (int)(deadzoneFactor * N64_AXIS_PEAK);
// don't increase emulated range at higher than 100% sensitivity
const double maxAxis = N64_AXIS_PEAK * std::min(sensitivityFactor, 1.0);
const double maxDiagonal = MAX_DIAGONAL_VALUE * std::min(sensitivityFactor, 1.0);
const int deadzone = (int)(deadzoneFactor * N64_AXIS_PEAK * sensitivityFactor);
const double axisRange = maxAxis - deadzone;
// scale to [-maxAxis, maxAxis]
double ax = inputX * maxAxis;
double ay = inputY * maxAxis;
double ax = std::min(inputX * sensitivityFactor, 1.0) * maxAxis;
double ay = std::min(inputY * sensitivityFactor, 1.0) * maxAxis;
// check whether (ax, ay) is within the circle of radius MAX_AXIS
double len = std::sqrt(ax*ax + ay*ay);
@@ -719,7 +731,7 @@ EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *pluginType, int *plugi
// Custom Plugin Functions
//
EXPORT m64p_error CALL PluginConfig()
EXPORT m64p_error CALL PluginConfig2(int romConfig)
{
if (l_SDLThread == nullptr)
{
@@ -731,7 +743,7 @@ EXPORT m64p_error CALL PluginConfig()
l_SDLThread->SetAction(SDLThreadAction::SDLPumpEvents);
UserInterface::MainDialog dialog(nullptr, l_SDLThread);
UserInterface::MainDialog dialog(nullptr, l_SDLThread, romConfig);
dialog.exec();
l_SDLThread->SetAction(SDLThreadAction::None);
@@ -742,7 +754,6 @@ EXPORT m64p_error CALL PluginConfig()
QThread::msleep(5);
}
// reload settings
load_settings();
@@ -758,6 +769,11 @@ EXPORT m64p_error CALL PluginConfig()
return M64ERR_SUCCESS;
}
EXPORT int CALL PluginConfig2HasRomConfig(void)
{
return 1;
}
//
// Input Plugin Functions
//
@@ -879,6 +895,7 @@ EXPORT void CALL GetKeys(int Control, BUTTONS* Keys)
inputX, // inputX
inputY, // inputY
profile->DeadzoneValue / 100.0, // deadzoneFactor
profile->SensitivityValue / 100.0, // sensitivityFactor
octagonX, // outputX
octagonY // outputY
);
+10 -7
View File
@@ -70,6 +70,7 @@ void RomSearcherThread::searchDirectory(QString directory)
filter << "*.NDD";
filter << "*.D64";
filter << "*.ZIP";
filter << "*.7Z";
QDirIterator::IteratorFlag flag = this->recursive ?
QDirIterator::Subdirectories :
@@ -82,9 +83,16 @@ void RomSearcherThread::searchDirectory(QString directory)
bool ret;
int count = 0;
QList<QString> roms;
while (romDirIt.hasNext())
{
QString file = romDirIt.next();
roms.push_back(romDirIt.next());
}
int romAmount = std::min(this->maxItems, (int)roms.size());
for (int i = 0; i < romAmount; i++)
{
QString file = roms.at(i);
QElapsedTimer timer;
timer.start();
@@ -111,12 +119,7 @@ void RomSearcherThread::searchDirectory(QString directory)
if (ret)
{
if (count++ >= this->maxItems)
{
break;
}
emit this->RomFound(file, type, header, settings);
emit this->RomFound(file, type, header, settings, (i + 1), romAmount);
}
if (this->stop)
+1 -1
View File
@@ -40,7 +40,7 @@ class RomSearcherThread : public QThread
void searchDirectory(QString);
signals:
void RomFound(QString file, CoreRomType type, CoreRomHeader header, CoreRomSettings settings);
void RomFound(QString file, CoreRomType type, CoreRomHeader header, CoreRomSettings settings, int index, int count);
void Finished(bool canceled);
};
} // namespace Thread
@@ -66,7 +66,7 @@ void InstallUpdateDialog::install(void)
" echo == Attemping to kill PID " + appPid + outputToLogLine,
" taskkill /F /PID:" + appPid + outputToLogLine,
" echo == Attemping to start \'" + fullFilePath + "\'" + outputToLogLine,
" \"" + fullFilePath + "\" /CLOSEAPPLICATIONS /NOCANCEL /SILENT /DIR=\"" + appPath + "\"" + outputToLogLine,
" \"" + fullFilePath + "\" /CLOSEAPPLICATIONS /NOCANCEL /MERGETASKS=\"!desktopicon\" /SILENT /DIR=\"" + appPath + "\"" + outputToLogLine,
")",
"IF NOT ERRORLEVEL 0 (",
" start \"\" cmd /c \"echo Rosalie's Mupen GUI failed to update, check the updater.log file in the Cache directory for more information && pause\"",
@@ -30,7 +30,8 @@ RomInfoDialog::RomInfoDialog(QString file, CoreRomHeader romHeader, CoreRomSetti
this->locationLineEdit->setCursorPosition(0);
this->crc1LineEdit->setText(QString::number(romHeader.CRC1, 16).toUpper());
this->crc2LineEdit->setText(QString::number(romHeader.CRC2, 16).toUpper());
this->countryCodeLineEdit->setText(QString((char)romHeader.CountryCode));
this->gameIDLineEdit->setText(QString::fromStdString(romHeader.GameID));
this->gameRegionLineEdit->setText(QString::fromStdString(romHeader.Region));
}
RomInfoDialog::~RomInfoDialog(void)
@@ -199,12 +199,36 @@
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<string>Country Code</string>
<string>Game I.D.</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="countryCodeLineEdit">
<widget class="QLineEdit" name="gameIDLineEdit">
<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_8">
<item>
<widget class="QLabel" name="label_8">
<property name="text">
<string>Game Region</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="gameRegionLineEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
@@ -214,6 +214,7 @@ void SettingsDialog::loadCoreSettings(void)
bool disableExtraMem = false;
int counterFactor = 0;
int cpuEmulator = 0;
int saveFilenameFormat = 0;
int siDmaDuration = -1;
bool randomizeInterrupt = true;
bool debugger = false;
@@ -222,12 +223,14 @@ void SettingsDialog::loadCoreSettings(void)
disableExtraMem = CoreSettingsGetBoolValue(SettingsID::CoreOverlay_DisableExtraMem);
counterFactor = CoreSettingsGetIntValue(SettingsID::CoreOverlay_CountPerOp);
cpuEmulator = CoreSettingsGetIntValue(SettingsID::CoreOverlay_CPU_Emulator);
saveFilenameFormat = CoreSettingsGetIntValue(SettingsID::CoreOverLay_SaveFileNameFormat);
siDmaDuration = CoreSettingsGetIntValue(SettingsID::CoreOverlay_SiDmaDuration);
randomizeInterrupt = CoreSettingsGetBoolValue(SettingsID::CoreOverlay_RandomizeInterrupt);
debugger = CoreSettingsGetBoolValue(SettingsID::CoreOverlay_EnableDebugger);
overrideGameSettings = CoreSettingsGetBoolValue(SettingsID::Core_OverrideGameSpecificSettings);
this->coreCpuEmulatorComboBox->setCurrentIndex(cpuEmulator);
this->coreSaveFilenameFormatComboBox->setCurrentIndex(saveFilenameFormat);
this->coreRandomizeTimingCheckBox->setChecked(randomizeInterrupt);
//this->coreDebuggerCheckBox->setChecked(debugger);
@@ -437,6 +440,7 @@ void SettingsDialog::loadDefaultCoreSettings(void)
bool disableExtraMem = false;
int counterFactor = 0;
int cpuEmulator = 0;
int saveFilenameFormat = 0;
int siDmaDuration = -1;
bool randomizeInterrupt = true;
bool debugger = false;
@@ -446,11 +450,13 @@ void SettingsDialog::loadDefaultCoreSettings(void)
counterFactor = CoreSettingsGetDefaultIntValue(SettingsID::CoreOverlay_CountPerOp);
cpuEmulator = CoreSettingsGetDefaultIntValue(SettingsID::CoreOverlay_CPU_Emulator);
siDmaDuration = CoreSettingsGetDefaultIntValue(SettingsID::CoreOverlay_SiDmaDuration);
saveFilenameFormat = CoreSettingsGetDefaultIntValue(SettingsID::CoreOverLay_SaveFileNameFormat);
randomizeInterrupt = CoreSettingsGetDefaultBoolValue(SettingsID::CoreOverlay_RandomizeInterrupt);
debugger = CoreSettingsGetDefaultBoolValue(SettingsID::CoreOverlay_EnableDebugger);
overrideGameSettings = CoreSettingsGetDefaultBoolValue(SettingsID::Core_OverrideGameSpecificSettings);
this->coreCpuEmulatorComboBox->setCurrentIndex(cpuEmulator);
this->coreSaveFilenameFormatComboBox->setCurrentIndex(saveFilenameFormat);
this->coreRandomizeTimingCheckBox->setChecked(randomizeInterrupt);
//this->coreDebuggerCheckBox->setChecked(debugger);
@@ -603,12 +609,14 @@ void SettingsDialog::saveCoreSettings(void)
bool disableExtraMem = (this->coreMemorySizeComboBox->currentIndex() == 0);
int counterFactor = this->coreCounterFactorComboBox->currentIndex() + 1;
int cpuEmulator = this->coreCpuEmulatorComboBox->currentIndex();
int saveFilenameFormat = this->coreSaveFilenameFormatComboBox->currentIndex();
int siDmaDuration = this->coreSiDmaDurationSpinBox->value();
bool randomizeInterrupt = this->coreRandomizeTimingCheckBox->isChecked();
//bool debugger = this->coreDebuggerCheckBox->isChecked();
bool overrideGameSettings = this->coreOverrideGameSettingsGroup->isChecked();
CoreSettingsSetValue(SettingsID::CoreOverlay_CPU_Emulator, cpuEmulator);
CoreSettingsSetValue(SettingsID::CoreOverLay_SaveFileNameFormat, saveFilenameFormat);
CoreSettingsSetValue(SettingsID::CoreOverlay_RandomizeInterrupt, randomizeInterrupt);
//CoreSettingsSetValue(SettingsID::CoreOverlay_EnableDebugger, debugger);
CoreSettingsSetValue(SettingsID::Core_OverrideGameSpecificSettings, overrideGameSettings);
@@ -1500,7 +1500,7 @@
<attribute name="title">
<string>Core</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_19">
<layout class="QVBoxLayout" name="verticalLayout_17">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_43">
<item>
@@ -1531,6 +1531,31 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_46">
<item>
<widget class="QLabel" name="label_25">
<property name="text">
<string>Save Filename Format</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="coreSaveFilenameFormatComboBox">
<item>
<property name="text">
<string>Internal ROM Name</string>
</property>
</item>
<item>
<property name="text">
<string>Automatic</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="coreOverrideGameSettingsGroup">
<property name="enabled">
@@ -23,7 +23,7 @@
using namespace UserInterface::Dialog;
UpdateDialog::UpdateDialog(QWidget *parent, QJsonObject jsonObject) : QDialog(parent)
UpdateDialog::UpdateDialog(QWidget *parent, QJsonObject jsonObject, bool forced) : QDialog(parent)
{
this->setupUi(this);
@@ -35,6 +35,10 @@ UpdateDialog::UpdateDialog(QWidget *parent, QJsonObject jsonObject) : QDialog(pa
// change ok button text to 'Update'
QPushButton* button = this->buttonBox->button(QDialogButtonBox::Ok);
button->setText("Update");
// don't show the 'Don't check for updates again' checkbox,
// when the user requested we check for updates
this->disableUpdateCheckCheckBox->setHidden(forced);
}
UpdateDialog::~UpdateDialog(void)
@@ -36,7 +36,7 @@ class UpdateDialog : public QDialog, private Ui::UpdateDialog
#endif // _WIN32
public:
UpdateDialog(QWidget *parent, QJsonObject jsonObject);
UpdateDialog(QWidget *parent, QJsonObject jsonObject, bool forced);
~UpdateDialog(void);
QString GetFileName(void);
+101 -6
View File
@@ -128,9 +128,13 @@ void MainWindow::closeEvent(QCloseEvent *event)
if (!this->ui_QuitAfterEmulation &&
!this->emulationThread->isRunning())
{
this->storeGeometry();
this->storeGeometry();
}
// store toolbar location to settings
Qt::ToolBarArea toolbarArea = this->toolBarArea(this->toolBar);
CoreSettingsSetValue(SettingsID::GUI_ToolbarArea, this->getToolbarSettingAreaFromArea(toolbarArea));
this->ui_NoSwitchToRomBrowser = true;
this->on_Action_System_Shutdown();
@@ -169,6 +173,8 @@ void MainWindow::initializeUI(void)
&MainWindow::on_RomBrowser_PlayGameWith);
connect(this->ui_Widget_RomBrowser, &Widget::RomBrowserWidget::EditGameSettings, this,
&MainWindow::on_RomBrowser_EditGameSettings);
connect(this->ui_Widget_RomBrowser, &Widget::RomBrowserWidget::EditGameInputSettings, this,
&MainWindow::on_RomBrowser_EditGameInputSettings);
connect(this->ui_Widget_RomBrowser, &Widget::RomBrowserWidget::Cheats, this,
&MainWindow::on_RomBrowser_Cheats);
connect(this->ui_Widget_RomBrowser, &Widget::RomBrowserWidget::ChangeRomDirectory, this,
@@ -220,6 +226,15 @@ void MainWindow::configureUI(QApplication* app, bool showUI)
this->statusBar()->setVisible(this->ui_ShowStatusbar);
this->statusBar()->addPermanentWidget(this->ui_StatusBar_Label, 1);
// set toolbar position according to setting
int toolbarAreaSetting = CoreSettingsGetIntValue(SettingsID::GUI_ToolbarArea);
Qt::ToolBarArea toolbarArea = this->getToolbarAreaFromSettingArea(toolbarAreaSetting);
if (this->toolBarArea(this->toolBar) != toolbarArea)
{
this->removeToolBar(this->toolBar);
this->addToolBar(toolbarArea, this->toolBar);
}
this->ui_TimerTimeout = CoreSettingsGetIntValue(SettingsID::GUI_StatusbarMessageDuration);
this->ui_Widgets->addWidget(this->ui_Widget_RomBrowser);
@@ -745,6 +760,41 @@ QString MainWindow::getSaveStateSlotText(QAction* action, int slot)
return saveStateSlotText;
}
int MainWindow::getToolbarSettingAreaFromArea(Qt::ToolBarArea area)
{
switch (area)
{
case Qt::ToolBarArea::TopToolBarArea:
return 0;
case Qt::ToolBarArea::BottomToolBarArea:
return 1;
case Qt::ToolBarArea::LeftToolBarArea:
return 2;
case Qt::ToolBarArea::RightToolBarArea:
return 3;
default:
return 0;
}
}
Qt::ToolBarArea MainWindow::getToolbarAreaFromSettingArea(int value)
{
switch (value)
{
default:
case 0:
return Qt::ToolBarArea::TopToolBarArea;
case 1:
return Qt::ToolBarArea::BottomToolBarArea;
case 2:
return Qt::ToolBarArea::LeftToolBarArea;
case 3:
return Qt::ToolBarArea::RightToolBarArea;
}
}
void MainWindow::configureActions(void)
{
// configure actions list
@@ -1092,7 +1142,7 @@ void MainWindow::on_networkAccessManager_Finished(QNetworkReply* reply)
int ret = 0;
Dialog::UpdateDialog updateDialog(this, jsonObject);
Dialog::UpdateDialog updateDialog(this, jsonObject, !this->ui_SilentUpdateCheck);
ret = updateDialog.exec();
if (ret != QDialog::Accepted)
{
@@ -1131,7 +1181,7 @@ void MainWindow::on_Action_System_OpenRom(void)
QString romFile;
romFile = QFileDialog::getOpenFileName(this, "", "", "N64 ROMs & Disks (*.n64 *.z64 *.v64 *.ndd *.d64 *.zip)");
romFile = QFileDialog::getOpenFileName(this, "", "", "N64 ROMs & Disks (*.n64 *.z64 *.v64 *.ndd *.d64 *.zip *.7z)");
if (romFile.isEmpty())
{
@@ -1162,7 +1212,7 @@ void MainWindow::on_Action_System_OpenCombo(void)
QString cartRom, diskRom;
cartRom = QFileDialog::getOpenFileName(this, "", "", "N64 ROMs (*.n64 *.z64 *.v64 *.zip)");
cartRom = QFileDialog::getOpenFileName(this, "", "", "N64 ROMs (*.n64 *.z64 *.v64 *.zip *.7z)");
if (cartRom.isEmpty())
{
@@ -1671,7 +1721,7 @@ void MainWindow::on_RomBrowser_PlayGameWith(CoreRomType type, QString file)
}
else
{ // disk
mainRom = QFileDialog::getOpenFileName(this, "", "", "N64 ROMs (*.n64 *.z64 *.v64 *.zip)");
mainRom = QFileDialog::getOpenFileName(this, "", "", "N64 ROMs (*.n64 *.z64 *.v64 *.zip *.7z)");
otherRom = file;
}
@@ -1774,6 +1824,34 @@ void MainWindow::on_RomBrowser_EditGameSettings(QString file)
}
}
void MainWindow::on_RomBrowser_EditGameInputSettings(QString file)
{
bool isRefreshingRomList = this->ui_Widget_RomBrowser->IsRefreshingRomList();
if (isRefreshingRomList)
{
this->ui_Widget_RomBrowser->StopRefreshRomList();
}
if (!CoreOpenRom(file.toStdU32String()))
{
this->showErrorMessage("CoreOpenRom() Failed", QString::fromStdString(CoreGetError()));
return;
}
CorePluginsOpenROMConfig(CorePluginType::Input);
if (!CoreCloseRom())
{
this->showErrorMessage("CoreCloseRom() Failed", QString::fromStdString(CoreGetError()));
return;
}
if (isRefreshingRomList)
{
this->ui_Widget_RomBrowser->RefreshRomList();
}
}
void MainWindow::on_RomBrowser_Cheats(QString file)
{
bool isRefreshingRomList = this->ui_Widget_RomBrowser->IsRefreshingRomList();
@@ -1910,7 +1988,24 @@ void MainWindow::on_VidExt_ResizeWindow(int width, int height)
if (!this->toolBar->isHidden())
{
height += this->toolBar->height();
Qt::ToolBarArea area = this->toolBarArea(this->toolBar);
// dont resize when toolbar is floating
if (this->toolBar->isFloating())
{
return;
}
if (area == Qt::ToolBarArea::TopToolBarArea ||
area == Qt::ToolBarArea::BottomToolBarArea)
{
height += this->toolBar->height();
}
else if (area == Qt::ToolBarArea::LeftToolBarArea ||
area == Qt::ToolBarArea::RightToolBarArea)
{
width += this->toolBar->width();
}
}
if (!this->statusBar()->isHidden())
+4
View File
@@ -119,6 +119,9 @@ class MainWindow : public QMainWindow, private Ui::MainWindow
QString getSaveStateSlotDateTimeText(QAction* action);
QString getSaveStateSlotText(QAction* action, int slot);
int getToolbarSettingAreaFromArea(Qt::ToolBarArea area);
Qt::ToolBarArea getToolbarAreaFromSettingArea(int value);
void configureActions(void);
void connectActionSignals(void);
void updateActions(bool inEmulation, bool isPaused);
@@ -189,6 +192,7 @@ class MainWindow : public QMainWindow, private Ui::MainWindow
void on_RomBrowser_ChangeRomDirectory(void);
void on_RomBrowser_RomInformation(QString file);
void on_RomBrowser_EditGameSettings(QString file);
void on_RomBrowser_EditGameInputSettings(QString file);
void on_RomBrowser_Cheats(QString file);
public slots:
+4 -1
View File
@@ -162,11 +162,14 @@
<string>toolBar</string>
</property>
<property name="movable">
<bool>false</bool>
<bool>true</bool>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextUnderIcon</enum>
</property>
<property name="floatable">
<bool>false</bool>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
@@ -11,6 +11,7 @@
#include <QLabel>
#include <QHBoxLayout>
#include <QTimerEvent>
using namespace UserInterface::Widget;
@@ -36,6 +37,12 @@ void RomBrowserLoadingWidget::SetWidgetIndex(int index)
this->widgetIndex = index;
}
void RomBrowserLoadingWidget::SetCurrentRomIndex(int index, int count)
{
this->romIndex = index;
this->romCount = count;
}
void RomBrowserLoadingWidget::on_RomBrowserWidget_currentChanged(int index)
{
// start timer when it isnt running
@@ -45,6 +52,12 @@ void RomBrowserLoadingWidget::on_RomBrowserWidget_currentChanged(int index)
{
if (this->loadingLabelTimerId == -1)
{
this->dotCount = 0;
this->romIndex = 0;
this->romCount = 0;
this->elapsedTimeSinceLoading.start();
// reset loading text
this->updateLoadingText();
this->loadingLabelTimerId = this->startTimer(1000);
}
}
@@ -52,20 +65,52 @@ void RomBrowserLoadingWidget::on_RomBrowserWidget_currentChanged(int index)
{
if (this->loadingLabelTimerId != -1)
{
this->elapsedTimeSinceLoading.invalidate();
this->killTimer(this->loadingLabelTimerId);
this->loadingLabelTimerId = -1;
}
}
}
void RomBrowserLoadingWidget::timerEvent(QTimerEvent *event)
void RomBrowserLoadingWidget::updateLoadingText()
{
if (this->loadingLabel->text().size() >= 10)
QString loadingText = "Loading";
if (this->elapsedTimeSinceLoading.isValid() &&
this->elapsedTimeSinceLoading.elapsed() >= 5000)
{
this->loadingLabel->setText("Loading");
QString romCountString = QString::number(this->romCount);
loadingText += " [";
loadingText += QString::number(this->romIndex).rightJustified(romCountString.size(), '0', false);
loadingText += "/";
loadingText += romCountString;
loadingText += "]";
}
if (dotCount <= 3)
{
for (int i = 0; i < dotCount; i++)
{
loadingText += ".";
}
dotCount++;
}
else
{
this->loadingLabel->setText(this->loadingLabel->text() + ".");
dotCount = 1;
}
this->loadingLabel->setText(loadingText);
}
void RomBrowserLoadingWidget::timerEvent(QTimerEvent *event)
{
if (event->timerId() != this->loadingLabelTimerId)
{
return;
}
this->updateLoadingText();
}
@@ -12,6 +12,7 @@
#include <QWidget>
#include <QLabel>
#include <QElapsedTimer>
namespace UserInterface
{
@@ -26,6 +27,8 @@ public:
void SetWidgetIndex(int index);
void SetCurrentRomIndex(int index, int count);
public slots:
void on_RomBrowserWidget_currentChanged(int index);
@@ -33,6 +36,13 @@ private:
QLabel* loadingLabel;
int loadingLabelTimerId = -1;
int widgetIndex = -1;
int romIndex = 0;
int romCount = 0;
int dotCount = 0;
QElapsedTimer elapsedTimeSinceLoading;
void updateLoadingText();
protected:
void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE;
@@ -105,14 +105,31 @@ RomBrowserWidget::RomBrowserWidget(QWidget *parent) : QStackedWidget(parent)
connect(this->listViewWidget, &Widget::RomBrowserListViewWidget::ZoomIn, this, &RomBrowserWidget::on_ZoomIn);
connect(this->listViewWidget, &Widget::RomBrowserListViewWidget::ZoomOut, this, &RomBrowserWidget::on_ZoomOut);
// TODO
// set up list view's columns
QStringList labels;
labels << "Name";
labels << "Internal Name";
labels << "MD5";
labels << "Format";
labels << "File Name";
labels << "File Ext.";
labels << "File Size";
labels << "I.D.";
labels << "Region";
this->listViewModel->setColumnCount(labels.size());
this->listViewModel->setHorizontalHeaderLabels(labels);
// set full names of list view's columns
this->columnNames << labels.at(0);
this->columnNames << labels.at(1);
this->columnNames << labels.at(2);
this->columnNames << "Game Format";
this->columnNames << labels.at(4);
this->columnNames << "File Extension";
this->columnNames << labels.at(6);
this->columnNames << "Game I.D.";
this->columnNames << "Game Region";
// configure grid view widget
this->gridViewWidget = new Widget::RomBrowserGridViewWidget(this);
this->gridViewModel = new QStandardItemModel(this);
@@ -151,7 +168,9 @@ RomBrowserWidget::RomBrowserWidget(QWidget *parent) : QStackedWidget(parent)
this->action_ChangeRomDirectory = new QAction(this);
this->action_RomInformation = new QAction(this);
this->action_EditGameSettings = new QAction(this);
this->action_EditGameInputSettings = new QAction(this);
this->action_EditCheats = new QAction(this);
this->action_ResetColumnSizes = new QAction(this);
this->action_SetCoverImage = new QAction(this);
this->action_RemoveCoverImage = new QAction(this);
@@ -167,10 +186,12 @@ RomBrowserWidget::RomBrowserWidget(QWidget *parent) : QStackedWidget(parent)
this->action_ChangeRomDirectory->setText("Change ROM Directory...");
this->action_RomInformation->setText("ROM Information");
this->action_EditGameSettings->setText("Edit Game Settings");
this->action_EditGameInputSettings->setText("Edit Game Input Settings");
this->action_EditCheats->setText("Edit Cheats");
this->action_ResetColumnSizes->setText("Reset Column Sizes");
this->menu_Columns->menuAction()->setText("Show/Hide Columns");
this->action_SetCoverImage->setText("Set Cover Image...");
this->action_RemoveCoverImage->setText("Remove Cover Image");
this->menu_Columns->menuAction()->setText("Show/Hide Columns");
connect(this->action_PlayGame, &QAction::triggered, this, &RomBrowserWidget::on_Action_PlayGame);
connect(this->action_PlayGameWith, &QAction::triggered, this, &RomBrowserWidget::on_Action_PlayGameWith);
connect(this->action_RefreshRomList, &QAction::triggered, this, &RomBrowserWidget::on_Action_RefreshRomList);
@@ -178,7 +199,9 @@ RomBrowserWidget::RomBrowserWidget(QWidget *parent) : QStackedWidget(parent)
connect(this->action_ChangeRomDirectory, &QAction::triggered, this, &RomBrowserWidget::on_Action_ChangeRomDirectory);
connect(this->action_RomInformation, &QAction::triggered, this, &RomBrowserWidget::on_Action_RomInformation);
connect(this->action_EditGameSettings, &QAction::triggered, this, &RomBrowserWidget::on_Action_EditGameSettings);
connect(this->action_EditGameInputSettings, &QAction::triggered, this, &RomBrowserWidget::on_Action_EditGameInputSettings);
connect(this->action_EditCheats, &QAction::triggered, this, &RomBrowserWidget::on_Action_EditCheats);
connect(this->action_ResetColumnSizes, &QAction::triggered, this, &RomBrowserWidget::on_Action_ResetColumnSizes);
connect(this->action_SetCoverImage, &QAction::triggered, this, &RomBrowserWidget::on_Action_SetCoverImage);
connect(this->action_RemoveCoverImage, &QAction::triggered, this, &RomBrowserWidget::on_Action_RemoveCoverImage);
@@ -194,11 +217,13 @@ RomBrowserWidget::RomBrowserWidget(QWidget *parent) : QStackedWidget(parent)
this->contextMenu->addAction(this->action_RomInformation);
this->contextMenu->addSeparator();
this->contextMenu->addAction(this->action_EditGameSettings);
this->contextMenu->addAction(this->action_EditGameInputSettings);
this->contextMenu->addAction(this->action_EditCheats);
this->contextMenu->addSeparator();
this->contextMenu->addAction(this->action_ResetColumnSizes);
this->contextMenu->addMenu(this->menu_Columns);
this->contextMenu->addAction(this->action_SetCoverImage);
this->contextMenu->addAction(this->action_RemoveCoverImage);
this->contextMenu->addMenu(this->menu_Columns);
// configure current view widget
int currentView = CoreSettingsGetIntValue(SettingsID::RomBrowser_ViewMode);
@@ -464,12 +489,14 @@ void RomBrowserWidget::customContextMenuRequested(QPoint position)
this->action_PlayGameWith->setEnabled(hasSelection);
this->action_RomInformation->setEnabled(hasSelection);
this->action_EditGameSettings->setEnabled(hasSelection);
this->action_EditGameInputSettings->setEnabled(hasSelection && CorePluginsHasROMConfig(CorePluginType::Input));
this->action_EditCheats->setEnabled(hasSelection);
this->action_ResetColumnSizes->setVisible(view == this->listViewWidget);
this->menu_Columns->menuAction()->setVisible(view == this->listViewWidget);
this->action_SetCoverImage->setEnabled(hasSelection);
this->action_SetCoverImage->setVisible(view == this->gridViewWidget);
this->action_RemoveCoverImage->setEnabled(hasSelection && !data.coverFile.isEmpty());
this->action_RemoveCoverImage->setVisible(view == this->gridViewWidget);
this->menu_Columns->menuAction()->setVisible(view == this->listViewWidget);
if (hasSelection && data.type == CoreRomType::Disk)
{ // disk selected
@@ -480,6 +507,11 @@ void RomBrowserWidget::customContextMenuRequested(QPoint position)
this->action_PlayGameWith->setText("Play Game with Disk");
}
if (view == this->listViewWidget)
{ // list view
this->generateColumnsMenu();
}
if (view == this->gridViewWidget)
{ // grid view
if (data.coverFile.isEmpty())
@@ -492,11 +524,6 @@ void RomBrowserWidget::customContextMenuRequested(QPoint position)
}
}
if (view == this->listViewWidget)
{ // list view
this->generateColumnsMenu();
}
this->contextMenu->popup(this->mapToGlobal(position));
}
@@ -508,7 +535,7 @@ void RomBrowserWidget::generateColumnsMenu(void)
{
int column = this->listViewWidget->horizontalHeader()->logicalIndex(i);
this->action_ColumnsMenuEntry = menu_Columns->addAction(this->listViewModel->horizontalHeaderItem(column)->text());
this->action_ColumnsMenuEntry = menu_Columns->addAction(this->columnNames.at(column));
this->action_ColumnsMenuEntry->setCheckable(true);
this->action_ColumnsMenuEntry->setChecked(!this->listViewWidget->horizontalHeader()->isSectionHidden(column));
connect(this->action_ColumnsMenuEntry, &QAction::toggled, [this, column](bool checked)
@@ -526,33 +553,42 @@ void RomBrowserWidget::on_listViewWidget_sortIndicatorChanged(int logicalIndex,
void RomBrowserWidget::on_listViewWidget_sectionResized(int logicalIndex, int oldWidth, int newWidth)
{
std::vector<int> columnVisibility = CoreSettingsGetIntListValue(SettingsID::RomBrowser_ColumnVisibility);
std::vector<int> columnSizes = CoreSettingsGetIntListValue(SettingsID::RomBrowser_ColumnSizes);
if (newWidth == 0)
if (!this->listViewWidget->horizontalHeader()->stretchLastSection())
{
columnVisibility.at(logicalIndex) = 0;
CoreSettingsSetValue(SettingsID::RomBrowser_ColumnVisibility, columnVisibility);
columnSizes.at(logicalIndex) = newWidth;
CoreSettingsSetValue(SettingsID::RomBrowser_ColumnSizes, columnSizes);
}
else
{
columnVisibility.at(logicalIndex) = 1;
CoreSettingsSetValue(SettingsID::RomBrowser_ColumnVisibility, columnVisibility);
std::vector<int> columnVisibility = CoreSettingsGetIntListValue(SettingsID::RomBrowser_ColumnVisibility);
int lastVisibleColumn = -1;
for (int i = 0; i < this->listViewModel->columnCount(); i++)
if (newWidth == 0)
{
int column = this->listViewWidget->horizontalHeader()->logicalIndex(i);
if (!this->listViewWidget->horizontalHeader()->isSectionHidden(column))
{
lastVisibleColumn = column;
}
columnVisibility.at(logicalIndex) = 0;
CoreSettingsSetValue(SettingsID::RomBrowser_ColumnVisibility, columnVisibility);
}
if (!this->listViewWidget->horizontalHeader()->stretchLastSection() || logicalIndex != lastVisibleColumn)
else
{
columnSizes.at(logicalIndex) = newWidth;
CoreSettingsSetValue(SettingsID::RomBrowser_ColumnSizes, columnSizes);
columnVisibility.at(logicalIndex) = 1;
CoreSettingsSetValue(SettingsID::RomBrowser_ColumnVisibility, columnVisibility);
int lastVisibleColumn = -1;
for (int i = 0; i < this->listViewModel->columnCount(); i++)
{
int column = this->listViewWidget->horizontalHeader()->logicalIndex(i);
if (!this->listViewWidget->horizontalHeader()->isSectionHidden(column))
{
lastVisibleColumn = column;
}
}
if (logicalIndex != lastVisibleColumn)
{
columnSizes.at(logicalIndex) = newWidth;
CoreSettingsSetValue(SettingsID::RomBrowser_ColumnSizes, columnSizes);
}
}
}
}
@@ -603,9 +639,12 @@ void RomBrowserWidget::on_ZoomOut(void)
view->setIconSize(view->iconSize() - QSize(10, 10));
}
void RomBrowserWidget::on_RomBrowserThread_RomFound(QString file, CoreRomType type, CoreRomHeader header, CoreRomSettings settings)
void RomBrowserWidget::on_RomBrowserThread_RomFound(QString file, CoreRomType type, CoreRomHeader header, CoreRomSettings settings, int index, int count)
{
QString name;
QString gameFormat;
float fileSize;
QString fileSizeString;
QString coverFile;
QIcon coverIcon;
QVariant itemData;
@@ -622,6 +661,24 @@ void RomBrowserWidget::on_RomBrowserThread_RomFound(QString file, CoreRomType ty
name = QFileInfo(file).fileName();
}
// generate game format to use in UI
if (type == CoreRomType::Disk)
{
gameFormat = "Disk";
}
else
{
gameFormat = "Cartridge";
}
// generate file size to use in UI
fileSize = QFileInfo(file).size()/1048576.0;
fileSizeString = (QString::number(fileSize, 'f', 2)).append(" MB");
if (fileSizeString.size() == 7)
{
fileSizeString = fileSizeString.prepend(" ");
}
// retrieve cover image
coverIcon = this->getCurrentCover(file, header, settings, coverFile);
modelData.coverFile = coverFile;
@@ -645,6 +702,36 @@ void RomBrowserWidget::on_RomBrowserThread_RomFound(QString file, CoreRomType ty
listViewItem3->setText(QString::fromStdString(settings.MD5));
listViewItem3->setData(itemData);
listViewRow.append(listViewItem3);
// game format
QStandardItem* listViewItem4 = new QStandardItem();
listViewItem4->setText(gameFormat);
listViewItem4->setData(itemData);
listViewRow.append(listViewItem4);
// file name
QStandardItem* listViewItem5 = new QStandardItem();
listViewItem5->setText(QFileInfo(file).completeBaseName());
listViewItem5->setData(itemData);
listViewRow.append(listViewItem5);
// file extension
QStandardItem* listViewItem6 = new QStandardItem();
listViewItem6->setText(((QFileInfo(file).suffix()).prepend(".")).toUpper());
listViewItem6->setData(itemData);
listViewRow.append(listViewItem6);
// file size
QStandardItem* listViewItem7 = new QStandardItem();
listViewItem7->setText(fileSizeString);
listViewItem7->setData(itemData);
listViewRow.append(listViewItem7);
// game i.d.
QStandardItem* listViewItem8 = new QStandardItem();
listViewItem8->setText(QString::fromStdString(header.GameID));
listViewItem8->setData(itemData);
listViewRow.append(listViewItem8);
// region
QStandardItem* listViewItem9 = new QStandardItem();
listViewItem9->setText(QString::fromStdString(header.Region));
listViewItem9->setData(itemData);
listViewRow.append(listViewItem9);
this->listViewModel->appendRow(listViewRow);
QStandardItem* gridViewItem = new QStandardItem();
@@ -652,6 +739,9 @@ void RomBrowserWidget::on_RomBrowserThread_RomFound(QString file, CoreRomType ty
gridViewItem->setText(name);
gridViewItem->setData(itemData);
this->gridViewModel->appendRow(gridViewItem);
// update loading widget
this->loadingWidget->SetCurrentRomIndex(index, count);
}
void RomBrowserWidget::on_RomBrowserThread_Finished(bool canceled)
@@ -664,34 +754,13 @@ void RomBrowserWidget::on_RomBrowserThread_Finished(bool canceled)
}
// retrieve column settings
std::vector<int> columnVisibility = CoreSettingsGetIntListValue(SettingsID::RomBrowser_ColumnVisibility);
std::vector<int> columnOrder = CoreSettingsGetIntListValue(SettingsID::RomBrowser_ColumnOrder);
std::vector<int> columnSizes = CoreSettingsGetIntListValue(SettingsID::RomBrowser_ColumnSizes);
std::vector<int> columnOrder = CoreSettingsGetIntListValue(SettingsID::RomBrowser_ColumnOrder);
std::vector<int> columnVisibility = CoreSettingsGetIntListValue(SettingsID::RomBrowser_ColumnVisibility);
// temporarily disable stretching last column in list view
this->listViewWidget->horizontalHeader()->setStretchLastSection(false);
// reset column visibility setting in config file if number of values is incorrect
if (!columnVisibility.empty() &&
columnVisibility.size() != this->listViewModel->columnCount())
{
columnVisibility.clear();
columnVisibility.resize(this->listViewModel->columnCount(), 1);
CoreSettingsSetValue(SettingsID::RomBrowser_ColumnVisibility, columnVisibility);
}
// reset column order setting in config file if number of values is incorrect
if (!columnOrder.empty() &&
columnOrder.size() != this->listViewModel->columnCount())
{
columnOrder.clear();
for (int i = 0; i < this->listViewModel->columnCount(); i++)
{
columnOrder.push_back(i);
}
CoreSettingsSetValue(SettingsID::RomBrowser_ColumnOrder, columnOrder);
}
// reset column sizes setting in config file if number of values is incorrect
if (!columnSizes.empty() &&
columnSizes.size() != this->listViewModel->columnCount())
@@ -701,21 +770,6 @@ void RomBrowserWidget::on_RomBrowserThread_Finished(bool canceled)
CoreSettingsSetValue(SettingsID::RomBrowser_ColumnSizes, columnSizes);
}
// update list view's column visibilities
for (int i = 0; i < columnVisibility.size(); i++)
{
if (columnVisibility.at(i) == 0)
{
this->listViewWidget->horizontalHeader()->setSectionHidden(i, true);
}
}
// update list view's column order
for (int i = 0; i < columnOrder.size(); i++)
{
this->listViewWidget->horizontalHeader()->moveSection(this->listViewWidget->horizontalHeader()->visualIndex(i), columnOrder.at(i));
}
// update list view's column sizes
for (int i = 0; i < columnSizes.size(); i++)
{
@@ -733,6 +787,46 @@ void RomBrowserWidget::on_RomBrowserThread_Finished(bool canceled)
// enable stretching last column in list view
this->listViewWidget->horizontalHeader()->setStretchLastSection(true);
// reset column order setting in config file if number of values is incorrect
if (!columnOrder.empty() &&
columnOrder.size() != this->listViewModel->columnCount())
{
columnOrder.clear();
for (int i = 0; i < this->listViewModel->columnCount(); i++)
{
columnOrder.push_back(i);
}
CoreSettingsSetValue(SettingsID::RomBrowser_ColumnOrder, columnOrder);
}
// update list view's column order
for (int i = 0; i < columnOrder.size(); i++)
{
this->listViewWidget->horizontalHeader()->moveSection(this->listViewWidget->horizontalHeader()->visualIndex(i), columnOrder.at(i));
}
// reset column visibility setting in config file if number of values is incorrect
if (!columnVisibility.empty() &&
columnVisibility.size() != this->listViewModel->columnCount())
{
columnVisibility.clear();
columnVisibility.resize(this->listViewModel->columnCount(), 0);
for (int i = 0; i < 3; i++)
{
columnVisibility.at(i) = 1;
}
CoreSettingsSetValue(SettingsID::RomBrowser_ColumnVisibility, columnVisibility);
}
// update list view's column visibilities
for (int i = 0; i < columnVisibility.size(); i++)
{
if (columnVisibility.at(i) == 0)
{
this->listViewWidget->horizontalHeader()->setSectionHidden(i, true);
}
}
if (!canceled)
{
if (this->listViewModel->rowCount() == 0)
@@ -803,11 +897,38 @@ void RomBrowserWidget::on_Action_EditGameSettings(void)
emit this->EditGameSettings(this->getCurrentRom());
}
void RomBrowserWidget::on_Action_EditGameInputSettings(void)
{
emit this->EditGameInputSettings(this->getCurrentRom());
}
void RomBrowserWidget::on_Action_EditCheats(void)
{
emit this->Cheats(this->getCurrentRom());
}
void RomBrowserWidget::on_Action_ResetColumnSizes(void)
{
std::vector<int> columnVisibility = CoreSettingsGetIntListValue(SettingsID::RomBrowser_ColumnVisibility);
this->listViewWidget->horizontalHeader()->setStretchLastSection(false);
for (int i = 0; i < this->listViewModel->columnCount(); i++)
{
this->listViewWidget->horizontalHeader()->setSectionHidden(i, false);
}
this->listViewWidget->resizeColumnsToContents();
this->listViewWidget->horizontalHeader()->setStretchLastSection(true);
for (int i = 0; i < columnVisibility.size(); i++)
{
if (columnVisibility.at(i) == 0)
{
this->listViewWidget->horizontalHeader()->setSectionHidden(i, true);
}
}
}
void RomBrowserWidget::on_Action_SetCoverImage(void)
{
QString sourceFile;
@@ -72,6 +72,8 @@ class RomBrowserWidget : public QStackedWidget
int listViewSortSection = 0;
int listViewSortOrder = 0;
QStringList columnNames;
QMenu* contextMenu;
QAction* action_PlayGame;
QAction* action_PlayGameWith;
@@ -80,7 +82,9 @@ class RomBrowserWidget : public QStackedWidget
QAction* action_ChangeRomDirectory;
QAction* action_RomInformation;
QAction* action_EditGameSettings;
QAction* action_EditGameInputSettings;
QAction* action_EditCheats;
QAction* action_ResetColumnSizes;
QAction* action_SetCoverImage;
QAction* action_RemoveCoverImage;
@@ -115,7 +119,7 @@ class RomBrowserWidget : public QStackedWidget
void on_ZoomIn(void);
void on_ZoomOut(void);
void on_RomBrowserThread_RomFound(QString file, CoreRomType type, CoreRomHeader header, CoreRomSettings settings);
void on_RomBrowserThread_RomFound(QString file, CoreRomType type, CoreRomHeader header, CoreRomSettings settings, int index, int count);
void on_RomBrowserThread_Finished(bool canceled);
void on_Action_PlayGame(void);
@@ -125,7 +129,9 @@ class RomBrowserWidget : public QStackedWidget
void on_Action_ChangeRomDirectory(void);
void on_Action_RomInformation(void);
void on_Action_EditGameSettings(void);
void on_Action_EditGameInputSettings(void);
void on_Action_EditCheats(void);
void on_Action_ResetColumnSizes(void);
void on_Action_SetCoverImage(void);
void on_Action_RemoveCoverImage(void);
@@ -133,6 +139,7 @@ class RomBrowserWidget : public QStackedWidget
void PlayGame(QString);
void PlayGameWith(CoreRomType, QString);
void EditGameSettings(QString);
void EditGameInputSettings(QString);
void Cheats(QString);
void ChangeRomDirectory(void);
void RomInformation(QString);
+12 -1
View File
@@ -94,6 +94,15 @@ int main(int argc, char **argv)
setenv("QT_QPA_PLATFORM", "xcb", 1);
#endif // FORCE_XCB
#ifndef _WIN32
// ensure the default OpenGL format
// doesn't have vsync enabled by default,
// only needed for linux (for now)
QSurfaceFormat format = QSurfaceFormat::defaultFormat();
format.setSwapInterval(0);
QSurfaceFormat::setDefaultFormat(format);
#endif
QApplication app(argc, argv);
UserInterface::MainWindow window;
@@ -167,7 +176,6 @@ int main(int argc, char **argv)
{
return 1;
}
window.show();
QStringList args = parser.positionalArguments();
if (!args.empty())
@@ -175,5 +183,8 @@ int main(int argc, char **argv)
window.OpenROM(args.at(0), parser.value(diskOption), parser.isSet(fullscreenOption), parser.isSet(quitAfterEmulationOption));
}
// show window
window.show();
return app.exec();
}