From cbfd634a4b73096d4eb73f763e7363dc9ca8ebd5 Mon Sep 17 00:00:00 2001 From: Nayla Hanegan Date: Thu, 20 Apr 2023 20:32:13 -0400 Subject: [PATCH] update Cheat files --- CMake/FindSDL2.cmake | 250 ----------- CMakeLists.txt | 10 +- Data/Sys/GameSettings/GP5E01.ini | 17 +- Data/Sys/GameSettings/GP6E01.ini | 40 +- Data/Sys/GameSettings/GP7E01.ini | 58 +-- Externals/MoltenVK/CMakeLists.txt | 2 +- Externals/SDL/SDL | 2 +- Externals/rcheevos/rcheevos | 2 +- Readme.md | 2 +- Source/Android/app/build.gradle | 5 +- .../Android/app/src/main/AndroidManifest.xml | 4 +- .../dolphinemu/features/DocumentProvider.kt | 84 ++-- .../dolphinemu/ui/main/MainActivity.java | 1 + Source/Android/jni/Cheats/ARCheat.cpp | 6 +- Source/Android/jni/Cheats/GeckoCheat.cpp | 6 +- Source/Android/jni/Cheats/PatchCheat.cpp | 6 +- Source/Android/jni/IniFile.cpp | 2 + .../Android/jni/Input/EmulatedController.cpp | 6 +- Source/Core/Common/Arm64Emitter.cpp | 2 +- Source/Core/Common/CMakeLists.txt | 7 +- Source/Core/Common/CommonFuncs.cpp | 3 + Source/Core/Common/CommonFuncs.h | 3 + Source/Core/Common/CompatPatches.cpp | 2 +- Source/Core/Common/Crypto/bn.cpp | 27 +- Source/Core/Common/Crypto/bn.h | 14 +- Source/Core/Common/Debug/CodeTrace.cpp | 19 +- Source/Core/Common/{ENetUtil.cpp => ENet.cpp} | 6 +- Source/Core/Common/{ENetUtil.h => ENet.h} | 13 +- Source/Core/Common/FileUtil.cpp | 10 +- Source/Core/Common/GL/GLInterface/GLX.cpp | 6 +- Source/Core/Common/HookableEvent.h | 2 +- Source/Core/Common/HttpRequest.cpp | 13 +- Source/Core/Common/HttpRequest.h | 3 +- Source/Core/Common/IniFile.cpp | 3 + Source/Core/Common/IniFile.h | 3 + Source/Core/Common/LinearDiskCache.h | 3 + Source/Core/Common/MathUtil.cpp | 12 - Source/Core/Common/MathUtil.h | 6 +- Source/Core/Common/MemoryUtil.cpp | 2 +- Source/Core/Common/SettingsHandler.cpp | 2 - Source/Core/Common/TraversalClient.cpp | 14 +- Source/Core/Common/TraversalClient.h | 3 +- Source/Core/Common/TypeUtils.h | 3 +- Source/Core/Common/UPnP.cpp | 4 +- Source/Core/Common/UPnP.h | 4 +- Source/Core/Common/x64Emitter.h | 3 +- Source/Core/Core/AchievementManager.cpp | 311 ++++++++++++- Source/Core/Core/AchievementManager.h | 44 +- Source/Core/Core/ActionReplay.cpp | 9 +- Source/Core/Core/ActionReplay.h | 9 +- Source/Core/Core/Boot/Boot_BS2Emu.cpp | 5 +- Source/Core/Core/BootManager.cpp | 11 + Source/Core/Core/CheatCodes.h | 5 +- .../Core/Core/Config/AchievementSettings.cpp | 9 + Source/Core/Core/Config/AchievementSettings.h | 5 + .../Core/ConfigLoaders/BaseConfigLoader.cpp | 10 +- .../Core/ConfigLoaders/GameConfigLoader.cpp | 18 +- Source/Core/Core/ConfigManager.cpp | 18 +- Source/Core/Core/ConfigManager.h | 15 +- Source/Core/Core/Core.cpp | 23 +- Source/Core/Core/CoreTiming.cpp | 8 +- .../Core/Core/Debugger/Debugger_SymbolMap.cpp | 2 +- .../Core/Core/Debugger/PPCDebugInterface.cpp | 28 +- Source/Core/Core/FifoPlayer/FifoPlayer.cpp | 12 +- Source/Core/Core/FifoPlayer/FifoRecorder.cpp | 4 +- Source/Core/Core/GeckoCodeConfig.cpp | 6 +- Source/Core/Core/GeckoCodeConfig.h | 7 +- Source/Core/Core/HLE/HLE.cpp | 2 +- Source/Core/Core/HW/CPU.cpp | 30 +- Source/Core/Core/HW/CPU.h | 9 +- Source/Core/Core/HW/DSPHLE/UCodes/AESnd.cpp | 16 +- Source/Core/Core/HW/EXI/BBA/BuiltIn.cpp | 3 +- .../Core/Core/HW/EXI/BBA/TAPServer_Apple.cpp | 7 +- .../Core/Core/HW/EXI/EXI_DeviceEthernet.cpp | 5 +- Source/Core/Core/HW/MemoryInterface.cpp | 9 +- Source/Core/Core/HW/ProcessorInterface.cpp | 4 +- Source/Core/Core/HW/SystemTimers.cpp | 2 +- .../HW/WiimoteEmu/DesiredWiimoteState.cpp | 10 +- Source/Core/Core/HotkeyManager.cpp | 2 +- Source/Core/Core/IOS/DI/DI.cpp | 169 ++++--- Source/Core/Core/IOS/FS/FileSystem.h | 3 + Source/Core/Core/IOS/FS/FileSystemCommon.cpp | 8 + Source/Core/Core/IOS/FS/HostBackend/FS.cpp | 128 ++++-- Source/Core/Core/IOS/IOS.cpp | 5 +- Source/Core/Core/IOS/MIOS.cpp | 16 +- .../Core/Core/IOS/Network/KD/NetKDRequest.cpp | 1 + Source/Core/Core/IOS/Network/SSL.cpp | 10 +- Source/Core/Core/IOS/Network/Socket.cpp | 14 +- Source/Core/Core/IOS/USB/USB_HID/HIDv4.cpp | 2 +- Source/Core/Core/IOS/USB/USB_KBD.cpp | 2 +- Source/Core/Core/NetPlayClient.cpp | 11 +- Source/Core/Core/NetPlayServer.cpp | 21 +- Source/Core/Core/PatchEngine.cpp | 19 +- Source/Core/Core/PatchEngine.h | 7 +- Source/Core/Core/PowerPC/BreakPoints.cpp | 41 +- Source/Core/Core/PowerPC/BreakPoints.h | 24 +- .../CachedInterpreter/CachedInterpreter.cpp | 13 +- Source/Core/Core/PowerPC/Expression.cpp | 23 +- Source/Core/Core/PowerPC/Expression.h | 11 +- Source/Core/Core/PowerPC/GDBStub.cpp | 18 +- .../Core/PowerPC/Interpreter/Interpreter.cpp | 15 +- .../Interpreter/Interpreter_Branch.cpp | 2 +- .../Interpreter/Interpreter_Integer.cpp | 5 +- .../Interpreter_SystemRegisters.cpp | 6 +- Source/Core/Core/PowerPC/Jit64/Jit.cpp | 14 +- .../Core/Core/PowerPC/Jit64/Jit_Integer.cpp | 4 +- .../Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp | 11 +- .../PowerPC/Jit64/Jit_SystemRegisters.cpp | 4 +- .../Core/PowerPC/Jit64Common/EmuCodeBlock.cpp | 2 +- Source/Core/Core/PowerPC/JitArm64/Jit.cpp | 22 +- .../PowerPC/JitArm64/JitArm64_Integer.cpp | 12 +- .../PowerPC/JitArm64/JitArm64_LoadStore.cpp | 20 +- .../JitArm64/JitArm64_SystemRegisters.cpp | 5 +- .../Core/Core/PowerPC/JitCommon/JitBase.cpp | 7 +- Source/Core/Core/PowerPC/JitCommon/JitBase.h | 2 +- Source/Core/Core/PowerPC/JitInterface.cpp | 24 +- Source/Core/Core/PowerPC/JitInterface.h | 4 +- Source/Core/Core/PowerPC/MMU.cpp | 21 +- Source/Core/Core/PowerPC/MMU.h | 4 +- Source/Core/Core/PowerPC/PPCAnalyst.cpp | 17 +- Source/Core/Core/PowerPC/PPCCache.cpp | 14 +- Source/Core/Core/PowerPC/PPCSymbolDB.cpp | 2 +- Source/Core/Core/PowerPC/PPCTables.cpp | 20 +- Source/Core/Core/PowerPC/PPCTables.h | 8 +- Source/Core/Core/PowerPC/PowerPC.cpp | 420 +++++++++--------- Source/Core/Core/PowerPC/PowerPC.h | 107 +++-- Source/Core/Core/State.cpp | 2 +- Source/Core/Core/System.cpp | 20 +- Source/Core/Core/System.h | 2 + Source/Core/DolphinLib.props | 5 +- Source/Core/DolphinNoGUI/PlatformWin32.cpp | 8 +- Source/Core/DolphinQt/CMakeLists.txt | 4 +- Source/Core/DolphinQt/Config/ARCodeWidget.cpp | 7 +- .../Core/DolphinQt/Config/GameConfigWidget.h | 4 +- .../Core/DolphinQt/Config/GeckoCodeWidget.cpp | 7 +- .../Config/Graphics/GraphicsBool.cpp | 21 - .../DolphinQt/Config/Graphics/GraphicsBool.h | 14 - .../Config/Mapping/MappingWindow.cpp | 6 +- .../Core/DolphinQt/Config/PatchesWidget.cpp | 7 +- .../BalloonTip.cpp | 2 +- .../BalloonTip.h | 0 .../Config/ToolTipControls/ToolTipWidget.h | 2 +- .../DolphinQt/Debugger/BreakpointWidget.cpp | 58 ++- .../DolphinQt/Debugger/BreakpointWidget.h | 6 + .../DolphinQt/Debugger/CodeDiffDialog.cpp | 5 +- .../DolphinQt/Debugger/CodeViewWidget.cpp | 117 ++--- .../Core/DolphinQt/Debugger/CodeViewWidget.h | 5 +- Source/Core/DolphinQt/Debugger/CodeWidget.cpp | 88 ++-- Source/Core/DolphinQt/Debugger/CodeWidget.h | 6 + .../DolphinQt/Debugger/MemoryViewWidget.cpp | 20 +- .../DolphinQt/Debugger/MemoryViewWidget.h | 5 +- .../DolphinQt/Debugger/RegisterWidget.cpp | 141 +++--- .../Core/DolphinQt/Debugger/RegisterWidget.h | 6 + .../Core/DolphinQt/Debugger/ThreadWidget.cpp | 9 +- .../Core/DolphinQt/Debugger/WatchWidget.cpp | 84 ++-- Source/Core/DolphinQt/Debugger/WatchWidget.h | 5 +- Source/Core/DolphinQt/DolphinQt.vcxproj | 4 +- Source/Core/DolphinQt/Main.cpp | 4 +- Source/Core/DolphinQt/MenuBar.cpp | 5 +- Source/Core/DolphinQt/QtUtils/FlowLayout.cpp | 4 +- .../Core/DolphinQt/QtUtils/WinIconHelper.cpp | 2 +- Source/Core/DolphinQt/Settings.cpp | 4 +- .../Core/DolphinQt/Settings/GameCubePane.cpp | 4 +- .../Core/DolphinQt/Settings/InterfacePane.cpp | 2 + Source/Core/DolphinQt/TAS/IRWidget.cpp | 20 +- Source/Core/DolphinQt/TAS/StickWidget.cpp | 20 +- .../Core/DolphinQt/TAS/WiiTASInputWindow.cpp | 2 +- Source/Core/DolphinQt/ToolBar.cpp | 4 +- .../ControlGroup/ControlGroup.cpp | 4 +- .../ControllerEmu/ControlGroup/ControlGroup.h | 4 +- .../ControllerEmu/ControllerEmu.cpp | 6 +- .../InputCommon/ControllerEmu/ControllerEmu.h | 4 +- .../ControllerEmu/Setting/NumericSetting.h | 10 +- .../InputCommon/ControllerEmu/StickGate.cpp | 8 +- .../InputCommon/ControllerEmu/StickGate.h | 4 +- .../ControllerInterface/Xlib/XInput2.cpp | 4 +- .../DynamicInputTextureManager.cpp | 2 +- .../InputCommon/DynamicInputTextureManager.h | 3 +- .../DynamicInputTextures/DITConfiguration.cpp | 5 +- .../DynamicInputTextures/DITConfiguration.h | 12 +- Source/Core/InputCommon/InputConfig.cpp | 12 +- Source/Core/InputCommon/InputConfig.h | 7 +- Source/Core/InputCommon/InputProfile.cpp | 6 +- Source/Core/UICommon/AutoUpdate.cpp | 4 +- Source/Core/UICommon/CommandLineParse.cpp | 7 +- Source/Core/UICommon/Disassembler.cpp | 3 +- Source/Core/UICommon/ResourcePack/Manager.cpp | 14 +- .../UICommon/ResourcePack/ResourcePack.cpp | 4 +- Source/Core/UICommon/UICommon.cpp | 2 +- Source/Core/UpdaterCommon/UpdaterCommon.cpp | 4 +- Source/Core/VideoBackends/CMakeLists.txt | 2 +- .../Core/VideoBackends/D3D12/DX12Context.cpp | 2 +- .../VideoBackends/Metal/MTLStateTracker.h | 14 +- .../VideoBackends/Metal/MTLStateTracker.mm | 34 +- .../VideoBackends/OGL/OGLStreamBuffer.cpp | 2 +- Source/Core/VideoBackends/OGL/OGLTexture.cpp | 10 +- Source/Core/VideoBackends/OGL/OGLTexture.h | 2 +- .../Core/VideoBackends/Vulkan/ObjectCache.cpp | 8 +- Source/Core/VideoCommon/CPMemory.cpp | 12 +- Source/Core/VideoCommon/CommandProcessor.cpp | 8 +- Source/Core/VideoCommon/CommandProcessor.h | 2 +- Source/Core/VideoCommon/OpcodeDecoding.cpp | 4 +- Source/Core/VideoCommon/PostProcessing.cpp | 6 +- Source/Core/VideoCommon/ShaderCache.cpp | 34 +- Source/Core/VideoCommon/ShaderCache.h | 10 +- Source/Core/VideoCommon/TextureCacheBase.cpp | 206 ++++----- Source/Core/VideoCommon/TextureCacheBase.h | 18 + .../VideoCommon/TextureConversionShader.cpp | 11 +- Source/Core/VideoCommon/TextureInfo.cpp | 2 +- .../Core/VideoCommon/VertexLoaderManager.cpp | 11 +- Source/Core/WinUpdater/Main.cpp | 4 +- Source/Core/WinUpdater/WinUI.cpp | 12 +- Source/UnitTests/Common/MathUtilTest.cpp | 14 +- Source/UnitTests/Core/CoreTimingTest.cpp | 146 +++--- .../UnitTests/Core/PowerPC/JitArm64/FPRF.cpp | 24 +- .../UnitTests/Core/PowerPC/JitArm64/Fres.cpp | 2 +- .../Core/PowerPC/JitArm64/Frsqrte.cpp | 2 +- 217 files changed, 2263 insertions(+), 1880 deletions(-) delete mode 100644 CMake/FindSDL2.cmake rename Source/Core/Common/{ENetUtil.cpp => ENet.cpp} (95%) rename Source/Core/Common/{ENetUtil.h => ENet.h} (61%) delete mode 100644 Source/Core/Common/MathUtil.cpp rename Source/Core/DolphinQt/Config/{Graphics => ToolTipControls}/BalloonTip.cpp (99%) rename Source/Core/DolphinQt/Config/{Graphics => ToolTipControls}/BalloonTip.h (100%) diff --git a/CMake/FindSDL2.cmake b/CMake/FindSDL2.cmake deleted file mode 100644 index 08d8dc6080..0000000000 --- a/CMake/FindSDL2.cmake +++ /dev/null @@ -1,250 +0,0 @@ -# - Find SDL2 -# Find the SDL2 headers and libraries -# -# SDL2::SDL2 - Imported target to use for building a library -# SDL2::SDL2main - Imported interface target to use if you want SDL and SDLmain. -# SDL2_FOUND - True if SDL2 was found. -# SDL2_DYNAMIC - If we found a DLL version of SDL (meaning you might want to copy a DLL from SDL2::SDL2) -# -# Original Author: -# 2015 Ryan Pavlik -# -# Copyright Sensics, Inc. 2015. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -# Set up architectures (for windows) and prefixes (for mingw builds) -if(WIN32) - if(MINGW) - include(MinGWSearchPathExtras OPTIONAL) - if(MINGWSEARCH_TARGET_TRIPLE) - set(SDL2_PREFIX ${MINGWSEARCH_TARGET_TRIPLE}) - endif() - endif() - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(SDL2_LIB_PATH_SUFFIX lib/x64) - if(NOT MSVC AND NOT SDL2_PREFIX) - set(SDL2_PREFIX x86_64-w64-mingw32) - endif() - else() - set(SDL2_LIB_PATH_SUFFIX lib/x86) - if(NOT MSVC AND NOT SDL2_PREFIX) - set(SDL2_PREFIX i686-w64-mingw32) - endif() - endif() -endif() - -if(SDL2_PREFIX) - set(SDL2_ORIGPREFIXPATH ${CMAKE_PREFIX_PATH}) - if(SDL2_ROOT_DIR) - list(APPEND CMAKE_PREFIX_PATH "${SDL2_ROOT_DIR}") - endif() - if(CMAKE_PREFIX_PATH) - foreach(_prefix ${CMAKE_PREFIX_PATH}) - list(APPEND CMAKE_PREFIX_PATH "${_prefix}/${SDL2_PREFIX}") - endforeach() - endif() - if(MINGWSEARCH_PREFIXES) - list(APPEND CMAKE_PREFIX_PATH ${MINGWSEARCH_PREFIXES}) - endif() -endif() - -# Invoke pkgconfig for hints -find_package(PkgConfig QUIET) -set(SDL2_INCLUDE_HINTS) -set(SDL2_LIB_HINTS) -if(PKG_CONFIG_FOUND) - pkg_search_module(SDL2PC QUIET sdl2) - if(SDL2PC_INCLUDE_DIRS) - set(SDL2_INCLUDE_HINTS ${SDL2PC_INCLUDE_DIRS}) - endif() - if(SDL2PC_LIBRARY_DIRS) - set(SDL2_LIB_HINTS ${SDL2PC_LIBRARY_DIRS}) - endif() -endif() - -include(FindPackageHandleStandardArgs) - -find_library(SDL2_LIBRARY - NAMES - SDL2 - HINTS - ${SDL2_LIB_HINTS} - PATHS - ${SDL2_ROOT_DIR} - ENV SDL2DIR - PATH_SUFFIXES lib SDL2 ${SDL2_LIB_PATH_SUFFIX}) - -set(_sdl2_framework FALSE) -# Some special-casing if we've found/been given a framework. -# Handles whether we're given the library inside the framework or the framework itself. -if(APPLE AND "${SDL2_LIBRARY}" MATCHES "(/[^/]+)*.framework(/.*)?$") - set(_sdl2_framework TRUE) - set(SDL2_FRAMEWORK "${SDL2_LIBRARY}") - # Move up in the directory tree as required to get the framework directory. - while("${SDL2_FRAMEWORK}" MATCHES "(/[^/]+)*.framework(/.*)$" AND NOT "${SDL2_FRAMEWORK}" MATCHES "(/[^/]+)*.framework$") - get_filename_component(SDL2_FRAMEWORK "${SDL2_FRAMEWORK}" DIRECTORY) - endwhile() - if("${SDL2_FRAMEWORK}" MATCHES "(/[^/]+)*.framework$") - set(SDL2_FRAMEWORK_NAME ${CMAKE_MATCH_1}) - # If we found a framework, do a search for the header ahead of time that will be more likely to get the framework header. - find_path(SDL2_INCLUDE_DIR - NAMES - SDL_haptic.h # this file was introduced with SDL2 - HINTS - "${SDL2_FRAMEWORK}/Headers/") - else() - # For some reason we couldn't get the framework directory itself. - # Shouldn't happen, but might if something is weird. - unset(SDL2_FRAMEWORK) - endif() -endif() - -find_path(SDL2_INCLUDE_DIR - NAMES - SDL_haptic.h # this file was introduced with SDL2 - HINTS - ${SDL2_INCLUDE_HINTS} - PATHS - ${SDL2_ROOT_DIR} - ENV SDL2DIR - PATH_SUFFIXES include include/sdl2 include/SDL2 SDL2) - -if(WIN32 AND SDL2_LIBRARY) - find_file(SDL2_RUNTIME_LIBRARY - NAMES - SDL2.dll - libSDL2.dll - HINTS - ${SDL2_LIB_HINTS} - PATHS - ${SDL2_ROOT_DIR} - ENV SDL2DIR - PATH_SUFFIXES bin lib ${SDL2_LIB_PATH_SUFFIX}) -endif() - - -if(WIN32 OR ANDROID OR IOS OR (APPLE AND NOT _sdl2_framework)) - set(SDL2_EXTRA_REQUIRED SDL2_SDLMAIN_LIBRARY) - find_library(SDL2_SDLMAIN_LIBRARY - NAMES - SDL2main - PATHS - ${SDL2_ROOT_DIR} - ENV SDL2DIR - PATH_SUFFIXES lib ${SDL2_LIB_PATH_SUFFIX}) -endif() - -if(MINGW AND NOT SDL2PC_FOUND) - find_library(SDL2_MINGW_LIBRARY mingw32) - find_library(SDL2_MWINDOWS_LIBRARY mwindows) -endif() - -if(SDL2_PREFIX) - # Restore things the way they used to be. - set(CMAKE_PREFIX_PATH ${SDL2_ORIGPREFIXPATH}) -endif() - -# handle the QUIETLY and REQUIRED arguments and set QUATLIB_FOUND to TRUE if -# all listed variables are TRUE -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(SDL2 - DEFAULT_MSG - SDL2_LIBRARY - SDL2_INCLUDE_DIR - ${SDL2_EXTRA_REQUIRED}) - -if(SDL2_FOUND) - if(NOT TARGET SDL2::SDL2) - # Create SDL2::SDL2 - if(WIN32 AND SDL2_RUNTIME_LIBRARY) - set(SDL2_DYNAMIC TRUE) - add_library(SDL2::SDL2 SHARED IMPORTED) - set_target_properties(SDL2::SDL2 - PROPERTIES - IMPORTED_IMPLIB "${SDL2_LIBRARY}" - IMPORTED_LOCATION "${SDL2_RUNTIME_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${SDL2_INCLUDE_DIR}" - ) - else() - add_library(SDL2::SDL2 UNKNOWN IMPORTED) - if(SDL2_FRAMEWORK AND SDL2_FRAMEWORK_NAME) - # Handle the case that SDL2 is a framework and we were able to decompose it above. - set_target_properties(SDL2::SDL2 PROPERTIES - IMPORTED_LOCATION "${SDL2_FRAMEWORK}/${SDL2_FRAMEWORK_NAME}") - elseif(_sdl2_framework AND SDL2_LIBRARY MATCHES "(/[^/]+)*.framework$") - # Handle the case that SDL2 is a framework and SDL_LIBRARY is just the framework itself. - - # This takes the basename of the framework, without the extension, - # and sets it (as a child of the framework) as the imported location for the target. - # This is the library symlink inside of the framework. - set_target_properties(SDL2::SDL2 PROPERTIES - IMPORTED_LOCATION "${SDL2_LIBRARY}/${CMAKE_MATCH_1}") - else() - # Handle non-frameworks (including non-Mac), as well as the case that we're given the library inside of the framework - set_target_properties(SDL2::SDL2 PROPERTIES - IMPORTED_LOCATION "${SDL2_LIBRARY}") - endif() - set_target_properties(SDL2::SDL2 - PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${SDL2_INCLUDE_DIR}" - ) - endif() - - if(APPLE) - # Need Cocoa here, is always a framework - find_library(SDL2_COCOA_LIBRARY Cocoa) - list(APPEND SDL2_EXTRA_REQUIRED SDL2_COCOA_LIBRARY) - if(SDL2_COCOA_LIBRARY) - set_target_properties(SDL2::SDL2 PROPERTIES - IMPORTED_LINK_INTERFACE_LIBRARIES ${SDL2_COCOA_LIBRARY}) - endif() - endif() - - - # Compute what to do with SDL2main - set(SDL2MAIN_LIBRARIES SDL2::SDL2) - add_library(SDL2::SDL2main INTERFACE IMPORTED) - if(SDL2_SDLMAIN_LIBRARY) - add_library(SDL2::SDL2main_real STATIC IMPORTED) - set_target_properties(SDL2::SDL2main_real - PROPERTIES - IMPORTED_LOCATION "${SDL2_SDLMAIN_LIBRARY}") - set(SDL2MAIN_LIBRARIES SDL2::SDL2main_real ${SDL2MAIN_LIBRARIES}) - endif() - if(MINGW) - # MinGW requires some additional libraries to appear earlier in the link line. - if(SDL2PC_LIBRARIES) - # Use pkgconfig-suggested extra libraries if available. - list(REMOVE_ITEM SDL2PC_LIBRARIES SDL2main SDL2) - set(SDL2MAIN_LIBRARIES ${SDL2PC_LIBRARIES} ${SDL2MAIN_LIBRARIES}) - else() - # fall back to extra libraries specified in pkg-config in - # an official binary distro of SDL2 for MinGW I downloaded - if(SDL2_MINGW_LIBRARY) - set(SDL2MAIN_LIBRARIES ${SDL2_MINGW_LIBRARY} ${SDL2MAIN_LIBRARIES}) - endif() - if(SDL2_MWINDOWS_LIBRARY) - set(SDL2MAIN_LIBRARIES ${SDL2_MWINDOWS_LIBRARY} ${SDL2MAIN_LIBRARIES}) - endif() - endif() - set_target_properties(SDL2::SDL2main - PROPERTIES - INTERFACE_COMPILE_DEFINITIONS "main=SDL_main") - endif() - set_target_properties(SDL2::SDL2main - PROPERTIES - INTERFACE_LINK_LIBRARIES "${SDL2MAIN_LIBRARIES}") - endif() - mark_as_advanced(SDL2_ROOT_DIR) -endif() - -mark_as_advanced(SDL2_LIBRARY - SDL2_RUNTIME_LIBRARY - SDL2_INCLUDE_DIR - SDL2_SDLMAIN_LIBRARY - SDL2_COCOA_LIBRARY - SDL2_MINGW_LIBRARY - SDL2_MWINDOWS_LIBRARY) - diff --git a/CMakeLists.txt b/CMakeLists.txt index 115b2bd721..0300a1828c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,10 @@ cmake_minimum_required(VERSION 3.13) cmake_policy(SET CMP0079 NEW) # let target_link_libraries() link to a target defined in a different directory cmake_policy(SET CMP0080 OLD) # allow using BundleUtilities at configure time +if (POLICY CMP0099) + cmake_policy(SET CMP0099 NEW) # Propagate INTERFACE_LINK_OPTIONS from private dependencies, used by MacOS framework builds of SDL +endif() + # Weird chicken-and-egg problem: We can't check the compiler before the project() call, but we have to set the policies before it. # So we do this in two steps: Set the policies if they exist, then error out afterwards if we end up being MSVC and they don't exist. if (POLICY CMP0117) @@ -693,7 +697,11 @@ endif() add_subdirectory(Externals/imgui) add_subdirectory(Externals/implot) add_subdirectory(Externals/glslang) -add_subdirectory(Externals/spirv_cross) +# SPIRV-Cross is used on Windows for GLSL to HLSL conversion for the Direct3D 11 and Direct3D 12 +# video backends, and on Apple devices for the Metal video backend. +if(WIN32 OR APPLE) + add_subdirectory(Externals/spirv_cross) +endif() if(ENABLE_VULKAN) add_definitions(-DHAS_VULKAN) diff --git a/Data/Sys/GameSettings/GP5E01.ini b/Data/Sys/GameSettings/GP5E01.ini index 03591911ea..1f4be34c59 100644 --- a/Data/Sys/GameSettings/GP5E01.ini +++ b/Data/Sys/GameSettings/GP5E01.ini @@ -499,7 +499,6 @@ a9010014 39200002 04456F08 C0028008 0445650C 3BFF0004 E2000001 80008000 - *Board animations happen faster. $QOL - Increased Capsule Throwing Speed [gamemasterplc] @@ -523,7 +522,7 @@ $QOL - Instant Text Display [gamemasterplc] 0404a560 38000000 *Text is displayed instantly. -$QOL - Show Controller Port Number of Who Paused in Mini-Games [gamemasterplc] +$QOL - Show Controller Port Number of Who Paused [gamemasterplc] C2040178 00000002 807F0050 906D0000 38600000 00000000 @@ -710,30 +709,30 @@ C20C8FA0 0000001B *Improves the RNG of what items are received. *Null items can be retrieved. To Dispose of throw on any space. -$Mechanics - Last 5 Turns Happens on the First Turn [Nayla] +$Mechanics: "Last 5 Turns" Event - Happens on the First Turn [Nayla] 0480CB88 2C040001 0408CB8C 41800048 -$Mechanics - Last 5 Turns is x3 Coins on Spaces [Nayla] +$Mechanics: "Last 5 Turns" Event - is x3 Coins on Spaces [Nayla] 040FB87C 38A00000 040FB8EC 3A600000 *Last 5 Turns Event is always x3 Coins on Spaces. -$Mechanics - Last 5 Turns is 5 Star Spaces [Nayla] +$Mechanics: "Last 5 Turns" Event - is 5 Star Spaces [Nayla] 040FB87C 38A00003 040FB8EC 3A600003 *Last 5 Turns Event is always 5 Star Spaces. -$Mechanics - Last 5 Turns is Capsule Spaces on Every Space [Nayla] +$Mechanics: "Last 5 Turns" Event - is All Capsule Spaces [Nayla] 040FB87C 38A00001 040FB8EC 3A600001 *Last 5 Turns Event forces all spaces to Have Capsule Events. -$Mechanics - Last 5 Turns is Disabled [Nayla] +$Mechanics: "Last 5 Turns" Event - is Disabled [Nayla] 0408D1F4 41800048 *Last 5 Turns Event never happens. -$Mechanics - Last 5 Turns is Red Spaces are Bowser Spaces [Nayla] +$Mechanics: "Last 5 Turns" Event - is Red Spaces are Bowser Spaces [Nayla] 040FB87C 38A00002 040FB8EC 3A6000012 *Last 5 Turns Event forces Red Spaces to turn into Bowser Spaces. @@ -785,7 +784,7 @@ B00D8CD4 AAAD8CD4 $Mechanics - Same Space Duels Always Happen [Nayla] 04094740 60000000 -*Duels never happen if you are on the same space. +*Duels always happen if you are on the same space $Mechanics - Same Space Duels Don't Happen [Nayla] 04094740 48000030 diff --git a/Data/Sys/GameSettings/GP6E01.ini b/Data/Sys/GameSettings/GP6E01.ini index 0eb0726fd2..da177914e7 100644 --- a/Data/Sys/GameSettings/GP6E01.ini +++ b/Data/Sys/GameSettings/GP6E01.ini @@ -508,7 +508,7 @@ $QOL - Instant Text Display [Celerizer] 0404f51c 38000000 *Text is displayed instantly. -$QOL - Show Controller Port Number of Who Paused in Mini-Games [Celerizer] +$QOL - Show Controller Port Number of Who Paused [Celerizer] C20456D4 00000002 807F0050 906D0000 38600000 00000000 @@ -543,6 +543,12 @@ F6000001 80008180 80A405A0 38800001 14000000 38A0FFFF E0000000 80008000 +F6000002 80008180 +5460D808 54640FFE +7C040050 5400283E +14000020 3C80FFFF +14000024 6084FFFF +E0000000 80008000 *Unlocks Everything in the game. $Board - Faire Square: Free Whomps [gamemasterplc] @@ -791,7 +797,7 @@ $Mechanics - Gain 20 Coins on Blue Spaces $Mechanics - Gain 40 Coins on Blue Spaces 0415F1E8 3BC00028 -$Mechanics - Last 5 Turns Happens on the First Turn [Ralf] +$Mechanics: "Last 5 Turns" Event - Happens on the First Turn [Ralf] 06005170 0000001C 3C608026 88835B74 88035B75 7C040050 @@ -800,7 +806,7 @@ $Mechanics - Last 5 Turns Happens on the First Turn [Ralf] 0414B6C8 60000000 0414B704 4BEB9A6D -$Mechanics - Last 5 Turns Happens after Turn 5 [Ralf] +$Mechanics: "Last 5 Turns" Event - Happens after Turn 5 [Ralf] 06005170 0000001C 3C608026 88835B74 88035B75 7C040050 @@ -809,24 +815,24 @@ $Mechanics - Last 5 Turns Happens after Turn 5 [Ralf] 0414B6C8 60000000 0414B704 4BEB9A6D -$Mechanics - Last 5 Turns is x3 Coins on Spaces [gamemasterplc] +$Mechanics: "Last 5 Turns" Event - is x3 Coins on Spaces [gamemasterplc] 04202314 38000000 *Last 5 Turns Event is always x3 Coins on spaces. -$Mechanics - Last 5 Turns is 40 Coin Bonus [gamemasterplc] +$Mechanics: "Last 5 Turns" Event - is 40 Coin Bonus [gamemasterplc] 04202314 38000001 *Last 5 Turns Event is always a 40 coin bonus for last place. -$Mechanics - Last 5 Turns is 5 Character Spaces [gamemasterplc] +$Mechanics: "Last 5 Turns" Event - is 5 Character Spaces [gamemasterplc] 04202314 38000002 [gamemasterplc] *Last 5 Turns Event is always 5 extra character spaces for last place. -$Mechanics - Last 5 Turns is Bowser Revolution [gamemasterplc] +$Mechanics: "Last 5 Turns" Event - is Bowser Revolution [gamemasterplc] 04202314 38000003 *Last 5 Turns Event is always a Bowser Revolution. *This makes everyones coins equal. -$Mechanics - Last 5 Turns is Disabled [Ralf] +$Mechanics: "Last 5 Turns" Event - is Disabled [Ralf] 0414B6C8 4800007C *Last 5 Turns event is disabled @@ -903,10 +909,10 @@ e2000002 80008000 e2000002 80008000 *Harder to time the wheel in the minigame Body Builder. -$Minigame: Catch You Letter - All Letters Give 3 Points -204CBD6C 80010028 -044CBD6C 38000003 -E2000001 80008000 +$Minigame: Catch You Letter - All Letters Give 3 Points +204CBD6C 80010028 +044CBD6C 38000003 +E2000001 80008000 *This essentially nullifies love letters. $Minigame: Crate & Peril - 3 Players can Jump [Airsola, gamemasterplc] @@ -973,14 +979,14 @@ $Minigame: Mole It – All Moles are Worth 3 Points [gamemasterplc] E2000001 80008000 $Minigame: Snow Whirled – Just Mash A [gamemasterplc] -204CB568 38650001 -044CB568 38650004 +204CB568 38650001 +044CB568 38650004 E2000001 80008000 $Minigame: Snow Whirled – Displayed Score Equals Rotations [gamemasterplc] -204CB66C 1C84005A -044CB66C 1C840001 -E2000001 80008000 +204CB66C 1C84005A +044CB66C 1C840001 +E2000001 80008000 $Minigame: Odd Card Out - Spam Prevention [Airsola] 202c0254 00000007 diff --git a/Data/Sys/GameSettings/GP7E01.ini b/Data/Sys/GameSettings/GP7E01.ini index f18b08aec8..d956de488c 100644 --- a/Data/Sys/GameSettings/GP7E01.ini +++ b/Data/Sys/GameSettings/GP7E01.ini @@ -629,7 +629,7 @@ $QOL - Instant Text Display [gamemasterplc] 04050a70 38800000 *Text is displayed instantly. -$QOL - Show Controller Port Number of Who Paused in Mini-Games [gamemasterplc] +$QOL - Show Controller Port Number of Who Paused [gamemasterplc] c2047400 00000002 807f0050 906d0000 38600000 00000000 @@ -729,16 +729,16 @@ e2000001 80008000 *Use Koopa Kid's path for free instead of paying 10 coins in the board Neon Heights. $Board - Neon Heights: Rocket Minigame is Possible with 1 Player [Airsola] -202f2f3c 0000007d -28527bfa 00000256 -04527c78 4039999 -e2000002 80008000 -202f2f3c 0000007d -c24ec2b0 00000003 -a87e02e8 2803000f -41a20008 38600000 -60000000 00000000 -e2000001 80008000 +202f2f3c 0000007d +28527bfa 00000256 +04527c78 4039999 +e2000002 80008000 +202f2f3c 0000007d +c24ec2b0 00000003 +a87e02e8 2803000f +41a20008 38600000 +60000000 00000000 +e2000001 80008000 *It is now possible for 1 player to reach the star in the rocket happening event in the board Neon Heights. $Board - Pagoda Peak: Bottle Rocket Launch Always Succeeds [gamemasterplc] @@ -1039,10 +1039,6 @@ $Mechanics - Hammer Bro Orb Steals 20 Coins [Ralf] *Hammer Bro steals 20 coins instead of 10 when landing on his space. $Mechanics - Happening Star Becomes Star Star [Airsola] -204e4ae0 48000210 -044e4a38 48000014 -044e4a6c 38000000 -e2000001 80008000 204e16ec 8903001f 044e16ec 8903003b e2000001 80008000 @@ -1050,7 +1046,6 @@ e2000001 80008000 044e1a0c 8903003b e2000001 80008000 *The Happening Star will become a bonus star awarded to the player who held the highest amount of stars at any point of the game. Recommended only for Windmillville, or Pyramid Park. -*Incompatible with Fixed Bonus Star because it implements it. $Mechanics - Improved Duel Results [Airsola] c21d8ed0 00000007 @@ -1071,38 +1066,38 @@ C21D8ED0 00000003 60000000 00000000 *(X) -> 1/2 Coins -$Mechanics - Last 5 Turns Event Happens on the First Turn [Ralf] +$Mechanics: "Last 5 Turns" Event - Happens on the First Turn [Ralf] 04152070 2C040001 04152074 4080011C 041521AC 2C040001 041521B0 41800044 -$Mechanics - Last 5 Turns Event Happens after Turn 5 [Ralf] +$Mechanics: "Last 5 Turns" Event - Happens after Turn 5 [Ralf] 04152070 2C040006 04152074 4080011C 041521AC 2C040006 041521B0 41800044 -$Mechanics - Last 5 Turns Event Is Always x3 Coins on Spaces [gamemasterplc] +$Mechanics: "Last 5 Turns" Event - is x3 Coins on Spaces [gamemasterplc] 042311A8 38000000 -$Mechanics - Last 5 Turns Event Is Always 10 More Koopa Kid Spaces [gamemasterplc] +$Mechanics: "Last 5 Turns" Event - is Always 10 More Koopa Kid Spaces [gamemasterplc] 042311A8 38000001 -$Mechanics - Last 5 Turns Event Is Always 40 Coin Bonus [gamemasterplc] +$Mechanics: "Last 5 Turns" Event - is Always 40 Coin Bonus [gamemasterplc] 042311A8 38000002 -$Mechanics - Last 5 Turns Event Is Always Stars are 10 Coins [gamemasterplc] +$Mechanics: "Last 5 Turns" Event - is Always Stars are 10 Coins [gamemasterplc] 042311A8 38000003 -$Mechanics - Last 5 Turns Event Is Always Red Spaces are Bowser Spaces [gamemasterplc] +$Mechanics: "Last 5 Turns" Event - is Always Red Spaces are Bowser Spaces [gamemasterplc] 042311A8 38000004 -$Mechanics - Last 5 Turns Event Is Always Chain Chomp Ride for 5 Coins (Pyramid Park) [gamemasterplc] +$Mechanics: "Last 5 Turns" Event - is Always Chain Chomp Ride for 5 Coins (Pyramid Park) [gamemasterplc] 042311A8 38000005 *Only use on Pyramid Park -$Mechanics - Last 5 Turns Event Is Disabled [Ralf] +$Mechanics: "Last 5 Turns" Event - is Disabled [Ralf] 04152074 60000000 041521B0 48000044 @@ -1137,10 +1132,6 @@ $Mechanics - Microphone Always Off [gamemasterplc] *Microphone game setting stays off while playing Mario Party 7. $Mechanics - Orb Star Becomes Coin Star [Airsola] -204e4ae0 48000210 -044e4a38 48000014 -044e4a6c 38000000 -e2000001 80008000 204e16b0 a8ca003c 044e16b0 a8ca002c e2000001 80008000 @@ -1148,8 +1139,6 @@ e2000001 80008000 044e18d4 a8c3002c e2000001 80008000 *The return of the classic Coin Star. -*Incompatible with Fixed Bonus Star because it implements it. - $Mechanics - Orbs Can Only Be Placed On Your Current Space [gamemasterplc] 041e7128 60000000 @@ -1162,7 +1151,7 @@ $Mechanics - Piranha Plant Takes ALL Coins [gamemasterplc] $Mechanics - Slow Shroom Orb Rolls 1-3 [gamemasterplc] 0418CCC8 38000003 0418D1AC 40820020 -*Orb is morew balanced. +*Orb is more balanced. $Mechanics - Slow Shroom Orb Rolls 1-5 [gamemasterplc] 0418ccc8 38000005 @@ -1172,7 +1161,6 @@ $Mechanics - Slow Shroom Orb Rolls 1-5 [gamemasterplc] $Mechanics - Stars Cost 40 coins [Ralf] 0418876c 3b800005 04188774 3b80000A - *Only works in Grand Canal and Bowser's Enchanted Inferno $Mechanics - Use Multiple Orbs in the Same Turn [Ralf] @@ -1229,7 +1217,7 @@ $Minigame: La Bomba - Always 4 Bombs [Airsola, Rain] 044e8cf4 00000004 e2000001 80008000 -$Minigame: Jump Man - Player is Slower +$Minigame: Jump Man - Player is Slower [gamemasterplc] 204EF0C0 40768000 044EF0B8 3C430C12 E2000001 80008000 @@ -1263,7 +1251,7 @@ $Minigame: Target Tag - All Targets Worth 50 Points [gamemasterplc] 044EAC28 38800032 E2000001 80008000 -$Minigame: Vine Country - DK is Faster +$Minigame: Vine Country - DK is Faster [gamemasterplc] 204E5EE8 901F0174 044E5EE4 3803FFFE E2000001 80008000 diff --git a/Externals/MoltenVK/CMakeLists.txt b/Externals/MoltenVK/CMakeLists.txt index 7e59505e9c..09ad412112 100644 --- a/Externals/MoltenVK/CMakeLists.txt +++ b/Externals/MoltenVK/CMakeLists.txt @@ -1,6 +1,6 @@ include(ExternalProject) -set(MOLTENVK_VERSION "v1.2.2") +set(MOLTENVK_VERSION "v1.2.3") ExternalProject_Add(MoltenVK GIT_REPOSITORY https://github.com/KhronosGroup/MoltenVK.git diff --git a/Externals/SDL/SDL b/Externals/SDL/SDL index f741adc86c..ac13ca9ab6 160000 --- a/Externals/SDL/SDL +++ b/Externals/SDL/SDL @@ -1 +1 @@ -Subproject commit f741adc86c8f5e7fc5c1863cf0d5e08b899d6209 +Subproject commit ac13ca9ab691e13e8eebe9684740ddcb0d716203 diff --git a/Externals/rcheevos/rcheevos b/Externals/rcheevos/rcheevos index c5304a61bc..d9e990e6d1 160000 --- a/Externals/rcheevos/rcheevos +++ b/Externals/rcheevos/rcheevos @@ -1 +1 @@ -Subproject commit c5304a61bcf256ae80fcd1c8f64ad9646aaea757 +Subproject commit d9e990e6d13527532b7e2bb23164a1f3b7f33bb5 diff --git a/Readme.md b/Readme.md index 7723fc1fc0..242b459137 100644 --- a/Readme.md +++ b/Readme.md @@ -1,6 +1,6 @@ # Dolphin - A GameCube and Wii Emulator -[Homepage](https://dolphin-emu.org/) | [Project Site](https://github.com/dolphin-emu/dolphin) | [Buildbot](https://dolphin.ci/) | [Forums](https://forums.dolphin-emu.org/) | [Wiki](https://wiki.dolphin-emu.org/) | [GitHub Wiki](https://github.com/dolphin-emu/dolphin/wiki) | [Issue Tracker](https://bugs.dolphin-emu.org/projects/emulator/issues) | [Coding Style](https://github.com/dolphin-emu/dolphin/blob/master/Contributing.md) | [Transifex Page](https://explore.transifex.com/delroth/dolphin-emu/) +[Homepage](https://dolphin-emu.org/) | [Project Site](https://github.com/dolphin-emu/dolphin) | [Buildbot](https://dolphin.ci/) | [Forums](https://forums.dolphin-emu.org/) | [Wiki](https://wiki.dolphin-emu.org/) | [GitHub Wiki](https://github.com/dolphin-emu/dolphin/wiki) | [Issue Tracker](https://bugs.dolphin-emu.org/projects/emulator/issues) | [Coding Style](https://github.com/dolphin-emu/dolphin/blob/master/Contributing.md) | [Transifex Page](https://app.transifex.com/delroth/dolphin-emu/dashboard/) Dolphin is an emulator for running GameCube and Wii games on Windows, Linux, macOS, and recent Android devices. It's licensed under the terms diff --git a/Source/Android/app/build.gradle b/Source/Android/app/build.gradle index bbc5a410fb..36ed3baf02 100644 --- a/Source/Android/app/build.gradle +++ b/Source/Android/app/build.gradle @@ -40,7 +40,6 @@ android { } defaultConfig { - // TODO If this is ever modified, change application_id in strings.xml applicationId "org.dolphinemu.dolphinemu" minSdkVersion 21 targetSdkVersion 33 @@ -74,6 +73,7 @@ android { signingConfig signingConfigs.release } + resValue 'string', 'app_name_suffixed', 'Dolphin Emulator' minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile( @@ -86,13 +86,14 @@ android { // Signed by debug key disallowing distribution on Play Store. // Attaches 'debug' suffix to version and package name, allowing installation alongside the release build. debug { - // TODO If this is ever modified, change application_id in debug/strings.xml + resValue 'string', 'app_name_suffixed', 'Dolphin Debug' applicationIdSuffix ".debug" versionNameSuffix '-debug' jniDebuggable true } benchmark { + resValue 'string', 'app_name_suffixed', 'Dolphin Benchmark' signingConfig signingConfigs.debug matchingFallbacks = ['release'] debuggable false diff --git a/Source/Android/app/src/main/AndroidManifest.xml b/Source/Android/app/src/main/AndroidManifest.xml index ce871e67d4..f470bafee7 100644 --- a/Source/Android/app/src/main/AndroidManifest.xml +++ b/Source/Android/app/src/main/AndroidManifest.xml @@ -31,7 +31,7 @@ diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/DocumentProvider.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/DocumentProvider.kt index 089170125c..b637962177 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/DocumentProvider.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/DocumentProvider.kt @@ -54,12 +54,11 @@ class DocumentProvider : DocumentsProvider() { override fun queryRoots(projection: Array?): Cursor { val result = MatrixCursor(projection ?: DEFAULT_ROOT_PROJECTION) - rootDirectory = rootDirectory ?: DirectoryInitialization.getUserDirectoryPath(context) rootDirectory ?: return result result.newRow().apply { add(DocumentsContract.Root.COLUMN_ROOT_ID, ROOT_ID) - add(DocumentsContract.Root.COLUMN_TITLE, context!!.getString(R.string.app_name)) + add(DocumentsContract.Root.COLUMN_TITLE, context!!.getString(R.string.app_name_suffixed)) add(DocumentsContract.Root.COLUMN_ICON, R.drawable.ic_dolphin) add( DocumentsContract.Root.COLUMN_FLAGS, @@ -73,7 +72,6 @@ class DocumentProvider : DocumentsProvider() { override fun queryDocument(documentId: String, projection: Array?): Cursor { val result = MatrixCursor(projection ?: DEFAULT_DOCUMENT_PROJECTION) - rootDirectory = rootDirectory ?: DirectoryInitialization.getUserDirectoryPath(context) rootDirectory ?: return result val file = documentIdToPath(documentId) appendDocument(file, result) @@ -102,7 +100,9 @@ class DocumentProvider : DocumentsProvider() { documentId: String, mode: String, signal: CancellationSignal? - ): ParcelFileDescriptor { + ): ParcelFileDescriptor? { + rootDirectory ?: return null + val file = documentIdToPath(documentId) return ParcelFileDescriptor.open(file, ParcelFileDescriptor.parseMode(mode)) } @@ -111,7 +111,9 @@ class DocumentProvider : DocumentsProvider() { parentDocumentId: String, mimeType: String, displayName: String - ): String { + ): String? { + rootDirectory ?: return null + val folder = documentIdToPath(parentDocumentId) val file = findFileNameForNewFile(File(folder, displayName)) if (mimeType == DocumentsContract.Document.MIME_TYPE_DIR) { @@ -122,56 +124,40 @@ class DocumentProvider : DocumentsProvider() { return pathToDocumentId(file) } - override fun copyDocument(sourceDocumentId: String, targetParentDocumentId: String): String { - val file = documentIdToPath(sourceDocumentId) - val target = documentIdToPath(targetParentDocumentId) - val copy = copyRecursively(file, File(target, file.name)) - return pathToDocumentId(copy) - } + override fun deleteDocument(documentId: String) { + rootDirectory ?: return - override fun removeDocument(documentId: String, parentDocumentId: String) { val file = documentIdToPath(documentId) file.deleteRecursively() } - override fun moveDocument( - sourceDocumentId: String, - sourceParentDocumentId: String, - targetParentDocumentId: String - ): String { - val copy = copyDocument(sourceDocumentId, targetParentDocumentId) - val file = documentIdToPath(sourceDocumentId) - file.delete() - return copy + override fun renameDocument(documentId: String, displayName: String): String? { + rootDirectory ?: return null + + val file = documentIdToPath(documentId) + val dest = findFileNameForNewFile(File(file.parentFile, displayName)) + file.renameTo(dest) + return pathToDocumentId(dest) } - override fun renameDocument(documentId: String, displayName: String): String { - val file = documentIdToPath(documentId) - file.renameTo(findFileNameForNewFile(File(file.parentFile, displayName))) - return pathToDocumentId(file) - } - - override fun isChildDocument(parentDocumentId: String, documentId: String): Boolean { - val file = documentIdToPath(documentId) - val folder = documentIdToPath(parentDocumentId) - return file.relativeToOrNull(folder) != null - } + override fun isChildDocument(parentDocumentId: String, documentId: String): Boolean + = documentId.startsWith(parentDocumentId) private fun appendDocument(file: File, cursor: MatrixCursor) { var flags = 0 - if (file.isDirectory && file.canWrite()) { - flags = DocumentsContract.Document.FLAG_DIR_SUPPORTS_CREATE - } else if (file.canWrite()) { - flags = DocumentsContract.Document.FLAG_SUPPORTS_WRITE + if (file.canWrite()) { + flags = if (file.isDirectory) { + DocumentsContract.Document.FLAG_DIR_SUPPORTS_CREATE + } else { + DocumentsContract.Document.FLAG_SUPPORTS_WRITE + } flags = flags or DocumentsContract.Document.FLAG_SUPPORTS_DELETE - flags = flags or DocumentsContract.Document.FLAG_SUPPORTS_REMOVE - flags = flags or DocumentsContract.Document.FLAG_SUPPORTS_MOVE - flags = flags or DocumentsContract.Document.FLAG_SUPPORTS_COPY flags = flags or DocumentsContract.Document.FLAG_SUPPORTS_RENAME + // The system will handle copy + move for us } val name = if (file == rootDirectory) { - context!!.getString(R.string.app_name) + context!!.getString(R.string.app_name_suffixed) } else { file.name } @@ -217,22 +203,6 @@ class DocumentProvider : DocumentsProvider() { unusedFile = File("$pathWithoutExtension.$i.$extension") i++ } - return file - } - - private fun copyRecursively(src: File, dst: File): File { - val actualDst = findFileNameForNewFile(dst) - if (src.isDirectory) { - actualDst.mkdirs() - val children = src.listFiles() - if (children !== null) { - for (file in children) { - copyRecursively(file, File(actualDst, file.name)) - } - } - } else { - src.copyTo(actualDst) - } - return actualDst + return unusedFile } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java index 1b0ff8cc32..488f0909df 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java @@ -77,6 +77,7 @@ public final class MainActivity extends AppCompatActivity setInsets(); ThemeHelper.enableStatusBarScrollTint(this, mBinding.appbarMain); + mBinding.toolbarMain.setTitle(R.string.app_name); setSupportActionBar(mBinding.toolbarMain); // Set up the FAB. diff --git a/Source/Android/jni/Cheats/ARCheat.cpp b/Source/Android/jni/Cheats/ARCheat.cpp index a3af52827a..5214ee390c 100644 --- a/Source/Android/jni/Cheats/ARCheat.cpp +++ b/Source/Android/jni/Cheats/ARCheat.cpp @@ -137,12 +137,12 @@ Java_org_dolphinemu_dolphinemu_features_cheats_model_ARCheat_loadCodes(JNIEnv* e jint revision) { const std::string game_id = GetJString(env, jGameID); - IniFile game_ini_local; + Common::IniFile game_ini_local; // We don't use LoadLocalGameIni() here because user cheat codes that are installed via the UI // will always be stored in GS/${GAMEID}.ini game_ini_local.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + game_id + ".ini"); - const IniFile game_ini_default = SConfig::LoadDefaultGameIni(game_id, revision); + const Common::IniFile game_ini_default = SConfig::LoadDefaultGameIni(game_id, revision); const std::vector codes = ActionReplay::LoadCodes(game_ini_default, game_ini_local); @@ -167,7 +167,7 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_features_cheats_model_ARCh const std::string game_id = GetJString(env, jGameID); const std::string ini_path = File::GetUserPath(D_GAMESETTINGS_IDX) + game_id + ".ini"; - IniFile game_ini_local; + Common::IniFile game_ini_local; game_ini_local.Load(ini_path); ActionReplay::SaveCodes(&game_ini_local, vector); game_ini_local.Save(ini_path); diff --git a/Source/Android/jni/Cheats/GeckoCheat.cpp b/Source/Android/jni/Cheats/GeckoCheat.cpp index 8b09dc6130..70261b6dc2 100644 --- a/Source/Android/jni/Cheats/GeckoCheat.cpp +++ b/Source/Android/jni/Cheats/GeckoCheat.cpp @@ -146,12 +146,12 @@ Java_org_dolphinemu_dolphinemu_features_cheats_model_GeckoCheat_loadCodes(JNIEnv jint revision) { const std::string game_id = GetJString(env, jGameID); - IniFile game_ini_local; + Common::IniFile game_ini_local; // We don't use LoadLocalGameIni() here because user cheat codes that are installed via the UI // will always be stored in GS/${GAMEID}.ini game_ini_local.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + game_id + ".ini"); - const IniFile game_ini_default = SConfig::LoadDefaultGameIni(game_id, revision); + const Common::IniFile game_ini_default = SConfig::LoadDefaultGameIni(game_id, revision); const std::vector codes = Gecko::LoadCodes(game_ini_default, game_ini_local); @@ -175,7 +175,7 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_features_cheats_model_Geck const std::string game_id = GetJString(env, jGameID); const std::string ini_path = File::GetUserPath(D_GAMESETTINGS_IDX) + game_id + ".ini"; - IniFile game_ini_local; + Common::IniFile game_ini_local; game_ini_local.Load(ini_path); Gecko::SaveCodes(game_ini_local, vector); game_ini_local.Save(ini_path); diff --git a/Source/Android/jni/Cheats/PatchCheat.cpp b/Source/Android/jni/Cheats/PatchCheat.cpp index fb5be8d5b5..b9cb89ce60 100644 --- a/Source/Android/jni/Cheats/PatchCheat.cpp +++ b/Source/Android/jni/Cheats/PatchCheat.cpp @@ -124,12 +124,12 @@ Java_org_dolphinemu_dolphinemu_features_cheats_model_PatchCheat_loadCodes(JNIEnv jint revision) { const std::string game_id = GetJString(env, jGameID); - IniFile game_ini_local; + Common::IniFile game_ini_local; // We don't use LoadLocalGameIni() here because user cheat codes that are installed via the UI // will always be stored in GS/${GAMEID}.ini game_ini_local.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + game_id + ".ini"); - const IniFile game_ini_default = SConfig::LoadDefaultGameIni(game_id, revision); + const Common::IniFile game_ini_default = SConfig::LoadDefaultGameIni(game_id, revision); std::vector patches; PatchEngine::LoadPatchSection("OnFrame", &patches, game_ini_default, game_ini_local); @@ -154,7 +154,7 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_features_cheats_model_Patc const std::string game_id = GetJString(env, jGameID); const std::string ini_path = File::GetUserPath(D_GAMESETTINGS_IDX) + game_id + ".ini"; - IniFile game_ini_local; + Common::IniFile game_ini_local; game_ini_local.Load(ini_path); PatchEngine::SavePatchSection(&game_ini_local, vector); game_ini_local.Save(ini_path); diff --git a/Source/Android/jni/IniFile.cpp b/Source/Android/jni/IniFile.cpp index 56856feb9c..7172094bdf 100644 --- a/Source/Android/jni/IniFile.cpp +++ b/Source/Android/jni/IniFile.cpp @@ -7,6 +7,8 @@ #include "jni/AndroidCommon/AndroidCommon.h" #include "jni/AndroidCommon/IDCache.h" +using Common::IniFile; + static IniFile::Section* GetSectionPointer(JNIEnv* env, jobject obj) { return reinterpret_cast( diff --git a/Source/Android/jni/Input/EmulatedController.cpp b/Source/Android/jni/Input/EmulatedController.cpp index 6c8d64e22f..3d2676812f 100644 --- a/Source/Android/jni/Input/EmulatedController.cpp +++ b/Source/Android/jni/Input/EmulatedController.cpp @@ -91,7 +91,7 @@ Java_org_dolphinemu_dolphinemu_features_input_model_controlleremu_EmulatedContro ControllerEmu::EmulatedController* controller = EmulatedControllerFromJava(env, obj); // Loading an empty IniFile section clears everything. - IniFile::Section section; + Common::IniFile::Section section; controller->LoadConfig(§ion); controller->UpdateReferences(g_controller_interface); @@ -103,7 +103,7 @@ Java_org_dolphinemu_dolphinemu_features_input_model_controlleremu_EmulatedContro { ControllerEmu::EmulatedController* controller = EmulatedControllerFromJava(env, obj); - IniFile ini; + Common::IniFile ini; ini.Load(GetJString(env, j_path)); controller->LoadConfig(ini.GetOrCreateSection("Profile")); @@ -118,7 +118,7 @@ Java_org_dolphinemu_dolphinemu_features_input_model_controlleremu_EmulatedContro File::CreateFullPath(path); - IniFile ini; + Common::IniFile ini; EmulatedControllerFromJava(env, obj)->SaveConfig(ini.GetOrCreateSection("Profile")); ini.Save(path); diff --git a/Source/Core/Common/Arm64Emitter.cpp b/Source/Core/Common/Arm64Emitter.cpp index d4293971b0..d59fd13300 100644 --- a/Source/Core/Common/Arm64Emitter.cpp +++ b/Source/Core/Common/Arm64Emitter.cpp @@ -3092,7 +3092,7 @@ void ARM64FloatEmitter::FMOV(ARM64Reg Rd, uint8_t imm8) // Vector void ARM64FloatEmitter::ADD(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { - EmitThreeSame(0, IntLog2(size) - 3, 0b10000, Rd, Rn, Rm); + EmitThreeSame(0, MathUtil::IntLog2(size) - 3, 0b10000, Rd, Rn, Rm); } void ARM64FloatEmitter::AND(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index 1177363ec3..6d9636363d 100644 --- a/Source/Core/Common/CMakeLists.txt +++ b/Source/Core/Common/CMakeLists.txt @@ -41,8 +41,8 @@ add_library(common DebugInterface.h DynamicLibrary.cpp DynamicLibrary.h - ENetUtil.cpp - ENetUtil.h + ENet.cpp + ENet.h EnumFormatter.h EnumMap.h Event.h @@ -80,7 +80,6 @@ add_library(common Logging/Log.h Logging/LogManager.cpp Logging/LogManager.h - MathUtil.cpp MathUtil.h Matrix.cpp Matrix.h @@ -299,7 +298,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux") target_link_libraries(common PUBLIC dl rt) endif() -if(CMAKE_SYSTEM_NAME STREQUAL "Windows") +if(WIN32) target_sources(common PRIVATE HRWrap.h HRWrap.cpp) endif() diff --git a/Source/Core/Common/CommonFuncs.cpp b/Source/Core/Common/CommonFuncs.cpp index 68834209b3..4fdefa3a67 100644 --- a/Source/Core/Common/CommonFuncs.cpp +++ b/Source/Core/Common/CommonFuncs.cpp @@ -13,6 +13,8 @@ #define strerror_r(err, buf, len) strerror_s(buf, len, err) #endif +namespace Common +{ constexpr size_t BUFFER_SIZE = 256; // Wrapper function to get last strerror(errno) string. @@ -73,3 +75,4 @@ std::optional GetModuleName(void* hInstance) return name; } #endif +} // namespace Common diff --git a/Source/Core/Common/CommonFuncs.h b/Source/Core/Common/CommonFuncs.h index db6b8643a1..cd8dbe94ac 100644 --- a/Source/Core/Common/CommonFuncs.h +++ b/Source/Core/Common/CommonFuncs.h @@ -39,6 +39,8 @@ __declspec(dllimport) void __stdcall DebugBreak(void); } #endif // WIN32 ndef +namespace Common +{ // Wrapper function to get last strerror(errno) string. // This function might change the error code. std::string LastStrerrorString(); @@ -51,3 +53,4 @@ std::string GetLastErrorString(); // Obtains a full path to the specified module. std::optional GetModuleName(void* hInstance); #endif +} // namespace Common diff --git a/Source/Core/Common/CompatPatches.cpp b/Source/Core/Common/CompatPatches.cpp index da211248b5..5b99658665 100644 --- a/Source/Core/Common/CompatPatches.cpp +++ b/Source/Core/Common/CompatPatches.cpp @@ -170,7 +170,7 @@ static std::optional GetModulePath(const wchar_t* name) if (module == nullptr) return std::nullopt; - return GetModuleName(module); + return Common::GetModuleName(module); } static bool GetModuleVersion(const wchar_t* name, Version* version) diff --git a/Source/Core/Common/Crypto/bn.cpp b/Source/Core/Common/Crypto/bn.cpp index 3dc8c75280..28bd216824 100644 --- a/Source/Core/Common/Crypto/bn.cpp +++ b/Source/Core/Common/Crypto/bn.cpp @@ -3,42 +3,45 @@ #include "Common/Crypto/bn.h" +#include #include #include #include "Common/CommonTypes.h" -static void bn_zero(u8* d, int n) +static void bn_zero(u8* d, const size_t n) { std::memset(d, 0, n); } -static void bn_copy(u8* d, const u8* a, int n) +static void bn_copy(u8* d, const u8* a, const size_t n) { std::memcpy(d, a, n); } -int bn_compare(const u8* a, const u8* b, int n) +int bn_compare(const u8* a, const u8* b, const size_t n) { return std::memcmp(a, b, n); } -void bn_sub_modulus(u8* a, const u8* N, int n) +void bn_sub_modulus(u8* a, const u8* N, const size_t n) { u8 c = 0; - for (int i = n - 1; i >= 0; --i) + for (size_t i = n; i > 0;) { + --i; u32 dig = N[i] + c; c = (a[i] < dig); a[i] -= dig; } } -void bn_add(u8* d, const u8* a, const u8* b, const u8* N, int n) +void bn_add(u8* d, const u8* a, const u8* b, const u8* N, const size_t n) { u8 c = 0; - for (int i = n - 1; i >= 0; --i) + for (size_t i = n; i > 0;) { + --i; u32 dig = a[i] + b[i] + c; c = (dig >= 0x100); d[i] = dig; @@ -51,11 +54,11 @@ void bn_add(u8* d, const u8* a, const u8* b, const u8* N, int n) bn_sub_modulus(d, N, n); } -void bn_mul(u8* d, const u8* a, const u8* b, const u8* N, int n) +void bn_mul(u8* d, const u8* a, const u8* b, const u8* N, const size_t n) { bn_zero(d, n); - for (int i = 0; i < n; i++) + for (size_t i = 0; i < n; i++) { for (u8 mask = 0x80; mask != 0; mask >>= 1) { @@ -66,13 +69,13 @@ void bn_mul(u8* d, const u8* a, const u8* b, const u8* N, int n) } } -void bn_exp(u8* d, const u8* a, const u8* N, int n, const u8* e, int en) +void bn_exp(u8* d, const u8* a, const u8* N, const size_t n, const u8* e, const size_t en) { u8 t[512]; bn_zero(d, n); d[n - 1] = 1; - for (int i = 0; i < en; i++) + for (size_t i = 0; i < en; i++) { for (u8 mask = 0x80; mask != 0; mask >>= 1) { @@ -86,7 +89,7 @@ void bn_exp(u8* d, const u8* a, const u8* N, int n, const u8* e, int en) } // only for prime N -- stupid but lazy, see if I care -void bn_inv(u8* d, const u8* a, const u8* N, int n) +void bn_inv(u8* d, const u8* a, const u8* N, const size_t n) { u8 t[512], s[512]; diff --git a/Source/Core/Common/Crypto/bn.h b/Source/Core/Common/Crypto/bn.h index 4070fd5f00..2dcc8c864b 100644 --- a/Source/Core/Common/Crypto/bn.h +++ b/Source/Core/Common/Crypto/bn.h @@ -3,13 +3,15 @@ #pragma once +#include + #include "Common/CommonTypes.h" // bignum arithmetic -int bn_compare(const u8* a, const u8* b, int n); -void bn_sub_modulus(u8* a, const u8* N, int n); -void bn_add(u8* d, const u8* a, const u8* b, const u8* N, int n); -void bn_mul(u8* d, const u8* a, const u8* b, const u8* N, int n); -void bn_inv(u8* d, const u8* a, const u8* N, int n); // only for prime N -void bn_exp(u8* d, const u8* a, const u8* N, int n, const u8* e, int en); +int bn_compare(const u8* a, const u8* b, size_t n); +void bn_sub_modulus(u8* a, const u8* N, size_t n); +void bn_add(u8* d, const u8* a, const u8* b, const u8* N, size_t n); +void bn_mul(u8* d, const u8* a, const u8* b, const u8* N, size_t n); +void bn_inv(u8* d, const u8* a, const u8* N, size_t n); // only for prime N +void bn_exp(u8* d, const u8* a, const u8* N, size_t n, const u8* e, size_t en); diff --git a/Source/Core/Common/Debug/CodeTrace.cpp b/Source/Core/Common/Debug/CodeTrace.cpp index 49ad967382..88ff656a92 100644 --- a/Source/Core/Common/Debug/CodeTrace.cpp +++ b/Source/Core/Common/Debug/CodeTrace.cpp @@ -126,16 +126,18 @@ InstructionAttributes CodeTrace::GetInstructionAttributes(const TraceOutput& ins TraceOutput CodeTrace::SaveCurrentInstruction(const Core::CPUThreadGuard& guard) const { auto& system = guard.GetSystem(); - auto& ppc_state = system.GetPPCState(); + auto& power_pc = system.GetPowerPC(); + auto& ppc_state = power_pc.GetPPCState(); + auto& debug_interface = power_pc.GetDebugInterface(); // Quickly save instruction and memory target for fast logging. TraceOutput output; - const std::string instr = PowerPC::debug_interface.Disassemble(&guard, ppc_state.pc); + const std::string instr = debug_interface.Disassemble(&guard, ppc_state.pc); output.instruction = instr; output.address = ppc_state.pc; if (IsInstructionLoadStore(output.instruction)) - output.memory_target = PowerPC::debug_interface.GetMemoryAddressFromInstruction(instr); + output.memory_target = debug_interface.GetMemoryAddressFromInstruction(instr); return output; } @@ -189,16 +191,17 @@ AutoStepResults CodeTrace::AutoStepping(const Core::CPUThreadGuard& guard, bool else if (stop_on == AutoStop::Changed) stop_condition = HitType::ACTIVE; - PowerPC::breakpoints.ClearAllTemporary(); + auto& power_pc = guard.GetSystem().GetPowerPC(); + power_pc.GetBreakPoints().ClearAllTemporary(); using clock = std::chrono::steady_clock; clock::time_point timeout = clock::now() + std::chrono::seconds(4); - PowerPC::CoreMode old_mode = PowerPC::GetMode(); - PowerPC::SetMode(PowerPC::CoreMode::Interpreter); + PowerPC::CoreMode old_mode = power_pc.GetMode(); + power_pc.SetMode(PowerPC::CoreMode::Interpreter); do { - PowerPC::SingleStep(); + power_pc.SingleStep(); pc_instr = SaveCurrentInstruction(guard); hit = TraceLogic(pc_instr); @@ -210,7 +213,7 @@ AutoStepResults CodeTrace::AutoStepping(const Core::CPUThreadGuard& guard, bool if (clock::now() >= timeout) results.timed_out = true; - PowerPC::SetMode(old_mode); + power_pc.SetMode(old_mode); m_recording = false; results.reg_tracked = m_reg_autotrack; diff --git a/Source/Core/Common/ENetUtil.cpp b/Source/Core/Common/ENet.cpp similarity index 95% rename from Source/Core/Common/ENetUtil.cpp rename to Source/Core/Common/ENet.cpp index 3cdfbf8829..b694eba042 100644 --- a/Source/Core/Common/ENetUtil.cpp +++ b/Source/Core/Common/ENet.cpp @@ -1,12 +1,12 @@ // Copyright 2015 Dolphin Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "Common/ENetUtil.h" +#include "Common/ENet.h" #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" -namespace ENetUtil +namespace Common::ENet { void WakeupThread(ENetHost* host) { @@ -62,4 +62,4 @@ bool SendPacket(ENetPeer* socket, const sf::Packet& packet, u8 channel_id) return true; } -} // namespace ENetUtil +} // namespace Common::ENet diff --git a/Source/Core/Common/ENetUtil.h b/Source/Core/Common/ENet.h similarity index 61% rename from Source/Core/Common/ENetUtil.h rename to Source/Core/Common/ENet.h index 5b06e5a007..f1791ca41d 100644 --- a/Source/Core/Common/ENetUtil.h +++ b/Source/Core/Common/ENet.h @@ -3,15 +3,22 @@ // #pragma once -#include +#include #include +#include #include "Common/CommonTypes.h" -namespace ENetUtil +namespace Common::ENet { +struct ENetHostDeleter +{ + void operator()(ENetHost* host) const noexcept { enet_host_destroy(host); } +}; +using ENetHostPtr = std::unique_ptr; + void WakeupThread(ENetHost* host); int ENET_CALLBACK InterceptCallback(ENetHost* host, ENetEvent* event); bool SendPacket(ENetPeer* socket, const sf::Packet& packet, u8 channel_id); -} // namespace ENetUtil +} // namespace Common::ENet diff --git a/Source/Core/Common/FileUtil.cpp b/Source/Core/Common/FileUtil.cpp index b97185e769..9a494ab2e0 100644 --- a/Source/Core/Common/FileUtil.cpp +++ b/Source/Core/Common/FileUtil.cpp @@ -358,14 +358,14 @@ u64 GetSize(FILE* f) const u64 pos = ftello(f); if (fseeko(f, 0, SEEK_END) != 0) { - ERROR_LOG_FMT(COMMON, "GetSize: seek failed {}: {}", fmt::ptr(f), LastStrerrorString()); + ERROR_LOG_FMT(COMMON, "GetSize: seek failed {}: {}", fmt::ptr(f), Common::LastStrerrorString()); return 0; } const u64 size = ftello(f); if ((size != pos) && (fseeko(f, pos, SEEK_SET) != 0)) { - ERROR_LOG_FMT(COMMON, "GetSize: seek failed {}: {}", fmt::ptr(f), LastStrerrorString()); + ERROR_LOG_FMT(COMMON, "GetSize: seek failed {}: {}", fmt::ptr(f), Common::LastStrerrorString()); return 0; } @@ -379,7 +379,7 @@ bool CreateEmptyFile(const std::string& filename) if (!File::IOFile(filename, "wb")) { - ERROR_LOG_FMT(COMMON, "CreateEmptyFile: failed {}: {}", filename, LastStrerrorString()); + ERROR_LOG_FMT(COMMON, "CreateEmptyFile: failed {}: {}", filename, Common::LastStrerrorString()); return false; } @@ -486,7 +486,7 @@ FSTEntry ScanDirectoryTree(std::string directory, bool recursive) } else if (cur_depth < prev_depth) { - while (dir_fsts.size() - 1 != cur_depth) + while (dir_fsts.size() != static_cast(cur_depth) + 1u) { calc_dir_size(dir_fsts.top()); dir_fsts.pop(); @@ -726,7 +726,7 @@ std::string GetBundleDirectory() std::string GetExePath() { #ifdef _WIN32 - auto exe_path = GetModuleName(nullptr); + auto exe_path = Common::GetModuleName(nullptr); if (!exe_path) return {}; std::error_code error; diff --git a/Source/Core/Common/GL/GLInterface/GLX.cpp b/Source/Core/Common/GL/GLInterface/GLX.cpp index b04296d096..ce16bb2155 100644 --- a/Source/Core/Common/GL/GLInterface/GLX.cpp +++ b/Source/Core/Common/GL/GLInterface/GLX.cpp @@ -155,7 +155,8 @@ bool GLContextGLX::Initialize(const WindowSystemInfo& wsi, bool stereo, bool cor GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, None}}; s_glxError = false; - m_context = glXCreateContextAttribs(m_display, m_fbconfig, 0, True, &context_attribs[0]); + m_context = + glXCreateContextAttribs(m_display, m_fbconfig, nullptr, True, &context_attribs[0]); XSync(m_display, False); if (!m_context || s_glxError) continue; @@ -174,7 +175,8 @@ bool GLContextGLX::Initialize(const WindowSystemInfo& wsi, bool stereo, bool cor std::array context_attribs_legacy = { {GLX_CONTEXT_MAJOR_VERSION_ARB, 1, GLX_CONTEXT_MINOR_VERSION_ARB, 0, None}}; s_glxError = false; - m_context = glXCreateContextAttribs(m_display, m_fbconfig, 0, True, &context_attribs_legacy[0]); + m_context = + glXCreateContextAttribs(m_display, m_fbconfig, nullptr, True, &context_attribs_legacy[0]); XSync(m_display, False); m_attribs.clear(); m_attribs.insert(m_attribs.end(), context_attribs_legacy.begin(), context_attribs_legacy.end()); diff --git a/Source/Core/Common/HookableEvent.h b/Source/Core/Common/HookableEvent.h index ea012bddf0..be97a8ab9b 100644 --- a/Source/Core/Common/HookableEvent.h +++ b/Source/Core/Common/HookableEvent.h @@ -69,7 +69,7 @@ private: struct Storage { - std::mutex m_mutex; + std::recursive_mutex m_mutex; std::vector m_listeners; }; diff --git a/Source/Core/Common/HttpRequest.cpp b/Source/Core/Common/HttpRequest.cpp index a8ed0d26ed..b9c6756624 100644 --- a/Source/Core/Common/HttpRequest.cpp +++ b/Source/Core/Common/HttpRequest.cpp @@ -33,8 +33,8 @@ public: Response Fetch(const std::string& url, Method method, const Headers& headers, const u8* payload, size_t size, AllowedReturnCodes codes = AllowedReturnCodes::Ok_Only); - static int CurlProgressCallback(Impl* impl, double dlnow, double dltotal, double ulnow, - double ultotal); + static int CurlProgressCallback(Impl* impl, curl_off_t dltotal, curl_off_t dlnow, + curl_off_t ultotal, curl_off_t ulnow); std::string EscapeComponent(const std::string& string); private: @@ -95,11 +95,12 @@ HttpRequest::Response HttpRequest::Post(const std::string& url, const std::strin reinterpret_cast(payload.data()), payload.size(), codes); } -int HttpRequest::Impl::CurlProgressCallback(Impl* impl, double dlnow, double dltotal, double ulnow, - double ultotal) +int HttpRequest::Impl::CurlProgressCallback(Impl* impl, curl_off_t dltotal, curl_off_t dlnow, + curl_off_t ultotal, curl_off_t ulnow) { // Abort if callback isn't true - return !impl->m_callback(dlnow, dltotal, ulnow, ultotal); + return !impl->m_callback(static_cast(dltotal), static_cast(dlnow), + static_cast(ultotal), static_cast(ulnow)); } HttpRequest::Impl::Impl(std::chrono::milliseconds timeout_ms, ProgressCallback callback) @@ -116,7 +117,7 @@ HttpRequest::Impl::Impl(std::chrono::milliseconds timeout_ms, ProgressCallback c if (m_callback) { curl_easy_setopt(m_curl.get(), CURLOPT_PROGRESSDATA, this); - curl_easy_setopt(m_curl.get(), CURLOPT_PROGRESSFUNCTION, CurlProgressCallback); + curl_easy_setopt(m_curl.get(), CURLOPT_XFERINFOFUNCTION, CurlProgressCallback); } // Set up error buffer diff --git a/Source/Core/Common/HttpRequest.h b/Source/Core/Common/HttpRequest.h index 921051c9c2..17b9fd3413 100644 --- a/Source/Core/Common/HttpRequest.h +++ b/Source/Core/Common/HttpRequest.h @@ -25,8 +25,7 @@ public: }; // Return false to abort the request - using ProgressCallback = - std::function; + using ProgressCallback = std::function; explicit HttpRequest(std::chrono::milliseconds timeout_ms = std::chrono::milliseconds{3000}, ProgressCallback callback = nullptr); diff --git a/Source/Core/Common/IniFile.cpp b/Source/Core/Common/IniFile.cpp index 41f1917fef..2aed1b805f 100644 --- a/Source/Core/Common/IniFile.cpp +++ b/Source/Core/Common/IniFile.cpp @@ -15,6 +15,8 @@ #include "Common/FileUtil.h" #include "Common/StringUtil.h" +namespace Common +{ void IniFile::ParseLine(std::string_view line, std::string* keyOut, std::string* valueOut) { if (line.empty() || line.front() == '#') @@ -369,3 +371,4 @@ bool IniFile::Save(const std::string& filename) return 0; } */ +} // namespace Common diff --git a/Source/Core/Common/IniFile.h b/Source/Core/Common/IniFile.h index 9de68a3246..c37be55f43 100644 --- a/Source/Core/Common/IniFile.h +++ b/Source/Core/Common/IniFile.h @@ -13,6 +13,8 @@ #include "Common/CommonTypes.h" #include "Common/StringUtil.h" +namespace Common +{ struct CaseInsensitiveStringCompare { // Allow heterogenous lookup. @@ -166,3 +168,4 @@ private: static const std::string& NULL_STRING; }; +} // namespace Common diff --git a/Source/Core/Common/LinearDiskCache.h b/Source/Core/Common/LinearDiskCache.h index 46ebde56fa..f0a4815143 100644 --- a/Source/Core/Common/LinearDiskCache.h +++ b/Source/Core/Common/LinearDiskCache.h @@ -27,6 +27,8 @@ // value_type[value_size] value; //} +namespace Common +{ template class LinearDiskCacheReader { @@ -163,3 +165,4 @@ private: File::IOFile m_file; u32 m_num_entries = 0; }; +} // namespace Common diff --git a/Source/Core/Common/MathUtil.cpp b/Source/Core/Common/MathUtil.cpp deleted file mode 100644 index 23034aeb14..0000000000 --- a/Source/Core/Common/MathUtil.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2008 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "Common/MathUtil.h" - -#include - -// Calculate sum of a float list -float MathFloatVectorSum(const std::vector& Vec) -{ - return std::accumulate(Vec.begin(), Vec.end(), 0.0f); -} diff --git a/Source/Core/Common/MathUtil.h b/Source/Core/Common/MathUtil.h index d99d02d28f..1494a894d9 100644 --- a/Source/Core/Common/MathUtil.h +++ b/Source/Core/Common/MathUtil.h @@ -8,7 +8,6 @@ #include #include #include -#include #include "Common/CommonTypes.h" @@ -186,12 +185,9 @@ private: T m_variance{}; }; -} // namespace MathUtil - -float MathFloatVectorSum(const std::vector&); - // Rounds down. 0 -> undefined constexpr int IntLog2(u64 val) { return 63 - std::countl_zero(val); } +} // namespace MathUtil diff --git a/Source/Core/Common/MemoryUtil.cpp b/Source/Core/Common/MemoryUtil.cpp index f94af85822..b473705411 100644 --- a/Source/Core/Common/MemoryUtil.cpp +++ b/Source/Core/Common/MemoryUtil.cpp @@ -250,7 +250,7 @@ size_t MemPhysical() mib[1] = HW_PHYSMEM64; #endif size_t length = sizeof(size_t); - sysctl(mib, 2, &physical_memory, &length, NULL, 0); + sysctl(mib, 2, &physical_memory, &length, nullptr, 0); return physical_memory; #elif defined __HAIKU__ system_info sysinfo; diff --git a/Source/Core/Common/SettingsHandler.cpp b/Source/Core/Common/SettingsHandler.cpp index 109c80abb8..c36805d4ce 100644 --- a/Source/Core/Common/SettingsHandler.cpp +++ b/Source/Core/Common/SettingsHandler.cpp @@ -70,12 +70,10 @@ std::string SettingsHandler::GetValue(std::string_view key) const void SettingsHandler::Decrypt() { - const u8* str = m_buffer.data(); while (m_position < m_buffer.size()) { decoded.push_back((u8)(m_buffer[m_position] ^ m_key)); m_position++; - str++; m_key = (m_key >> 31) | (m_key << 1); } diff --git a/Source/Core/Common/TraversalClient.cpp b/Source/Core/Common/TraversalClient.cpp index f3ab481a51..b215e5d269 100644 --- a/Source/Core/Common/TraversalClient.cpp +++ b/Source/Core/Common/TraversalClient.cpp @@ -304,7 +304,7 @@ int ENET_CALLBACK TraversalClient::InterceptCallback(ENetHost* host, ENetEvent* } std::unique_ptr g_TraversalClient; -std::unique_ptr g_MainNetHost; +Common::ENet::ENetHostPtr g_MainNetHost; // The settings at the previous TraversalClient reset - notably, we // need to know not just what port it's on, but whether it was @@ -323,18 +323,18 @@ bool EnsureTraversalClient(const std::string& server, u16 server_port, u16 liste g_OldListenPort = listen_port; ENetAddress addr = {ENET_HOST_ANY, listen_port}; - ENetHost* host = enet_host_create(&addr, // address - 50, // peerCount - NetPlay::CHANNEL_COUNT, // channelLimit - 0, // incomingBandwidth - 0); // outgoingBandwidth + auto host = Common::ENet::ENetHostPtr{enet_host_create(&addr, // address + 50, // peerCount + NetPlay::CHANNEL_COUNT, // channelLimit + 0, // incomingBandwidth + 0)}; // outgoingBandwidth if (!host) { g_MainNetHost.reset(); return false; } host->mtu = std::min(host->mtu, NetPlay::MAX_ENET_MTU); - g_MainNetHost.reset(host); + g_MainNetHost = std::move(host); g_TraversalClient.reset(new TraversalClient(g_MainNetHost.get(), server, server_port)); } return true; diff --git a/Source/Core/Common/TraversalClient.h b/Source/Core/Common/TraversalClient.h index 1f33f01cef..40600eb8bd 100644 --- a/Source/Core/Common/TraversalClient.h +++ b/Source/Core/Common/TraversalClient.h @@ -11,6 +11,7 @@ #include #include "Common/CommonTypes.h" +#include "Common/ENet.h" #include "Common/Thread.h" #include "Common/TraversalProto.h" @@ -91,7 +92,7 @@ private: }; extern std::unique_ptr g_TraversalClient; // the NetHost connected to the TraversalClient. -extern std::unique_ptr g_MainNetHost; +extern Common::ENet::ENetHostPtr g_MainNetHost; // Create g_TraversalClient and g_MainNetHost if necessary. bool EnsureTraversalClient(const std::string& server, u16 server_port, u16 listen_port = 0); void ReleaseTraversalClient(); diff --git a/Source/Core/Common/TypeUtils.h b/Source/Core/Common/TypeUtils.h index ce2fd516cd..44ef1faf78 100644 --- a/Source/Core/Common/TypeUtils.h +++ b/Source/Core/Common/TypeUtils.h @@ -1,5 +1,4 @@ -// Copyright 2021 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later +// SPDX-License-Identifier: CC0-1.0 #pragma once diff --git a/Source/Core/Common/UPnP.cpp b/Source/Core/Common/UPnP.cpp index 9552236e69..be5474706b 100644 --- a/Source/Core/Common/UPnP.cpp +++ b/Source/Core/Common/UPnP.cpp @@ -164,14 +164,14 @@ static void UnmapPortThread() UnmapPort(s_mapped); } -void UPnP::TryPortmapping(u16 port) +void Common::UPnP::TryPortmapping(u16 port) { if (s_thread.joinable()) s_thread.join(); s_thread = std::thread(&MapPortThread, port); } -void UPnP::StopPortmapping() +void Common::UPnP::StopPortmapping() { if (s_thread.joinable()) s_thread.join(); diff --git a/Source/Core/Common/UPnP.h b/Source/Core/Common/UPnP.h index 3013cf56d2..5545097ec1 100644 --- a/Source/Core/Common/UPnP.h +++ b/Source/Core/Common/UPnP.h @@ -7,10 +7,10 @@ #include "Common/CommonTypes.h" -namespace UPnP +namespace Common::UPnP { void TryPortmapping(u16 port); void StopPortmapping(); -} // namespace UPnP +} // namespace Common::UPnP #endif diff --git a/Source/Core/Common/x64Emitter.h b/Source/Core/Common/x64Emitter.h index 6bf034b455..3eac996130 100644 --- a/Source/Core/Common/x64Emitter.h +++ b/Source/Core/Common/x64Emitter.h @@ -1106,7 +1106,8 @@ public: template void ABI_CallFunctionPR(FunctionPointer func, const void* ptr, X64Reg reg1) { - MOV(64, R(ABI_PARAM2), R(reg1)); + if (reg1 != ABI_PARAM2) + MOV(64, R(ABI_PARAM2), R(reg1)); MOV(64, R(ABI_PARAM1), Imm64(reinterpret_cast(ptr))); ABI_CallFunction(func); } diff --git a/Source/Core/Core/AchievementManager.cpp b/Source/Core/Core/AchievementManager.cpp index 7e0fa5a9d9..ac9d041b62 100644 --- a/Source/Core/Core/AchievementManager.cpp +++ b/Source/Core/Core/AchievementManager.cpp @@ -4,10 +4,17 @@ #ifdef USE_RETRO_ACHIEVEMENTS #include "Core/AchievementManager.h" + +#include +#include + #include "Common/HttpRequest.h" #include "Common/WorkQueueThread.h" #include "Config/AchievementSettings.h" #include "Core/Core.h" +#include "DiscIO/Volume.h" + +static constexpr bool hardcore_mode_enabled = false; AchievementManager* AchievementManager::GetInstance() { @@ -28,49 +35,337 @@ void AchievementManager::Init() AchievementManager::ResponseType AchievementManager::Login(const std::string& password) { + if (!m_is_runtime_initialized) + return AchievementManager::ResponseType::MANAGER_NOT_INITIALIZED; return VerifyCredentials(password); } -void AchievementManager::LoginAsync(const std::string& password, const LoginCallback& callback) +void AchievementManager::LoginAsync(const std::string& password, const ResponseCallback& callback) { + if (!m_is_runtime_initialized) + { + callback(AchievementManager::ResponseType::MANAGER_NOT_INITIALIZED); + return; + } m_queue.EmplaceItem([this, password, callback] { callback(VerifyCredentials(password)); }); } bool AchievementManager::IsLoggedIn() const { - return m_login_data.response.succeeded; + return !Config::Get(Config::RA_API_TOKEN).empty(); +} + +void AchievementManager::LoadGameByFilenameAsync(const std::string& iso_path, + const ResponseCallback& callback) +{ + if (!m_is_runtime_initialized) + { + callback(AchievementManager::ResponseType::MANAGER_NOT_INITIALIZED); + return; + } + struct FilereaderState + { + int64_t position = 0; + std::unique_ptr volume; + }; + rc_hash_filereader volume_reader{ + .open = [](const char* path_utf8) -> void* { + auto state = std::make_unique(); + state->volume = DiscIO::CreateVolume(path_utf8); + if (!state->volume) + return nullptr; + return state.release(); + }, + .seek = + [](void* file_handle, int64_t offset, int origin) { + switch (origin) + { + case SEEK_SET: + reinterpret_cast(file_handle)->position = offset; + break; + case SEEK_CUR: + reinterpret_cast(file_handle)->position += offset; + break; + case SEEK_END: + // Unused + break; + } + }, + .tell = + [](void* file_handle) { + return reinterpret_cast(file_handle)->position; + }, + .read = + [](void* file_handle, void* buffer, size_t requested_bytes) { + FilereaderState* filereader_state = reinterpret_cast(file_handle); + bool success = (filereader_state->volume->Read( + filereader_state->position, requested_bytes, reinterpret_cast(buffer), + DiscIO::PARTITION_NONE)); + if (success) + { + filereader_state->position += requested_bytes; + return requested_bytes; + } + else + { + return static_cast(0); + } + }, + .close = [](void* file_handle) { delete reinterpret_cast(file_handle); }}; + rc_hash_init_custom_filereader(&volume_reader); + std::array game_hash; + if (!rc_hash_generate_from_file(game_hash.data(), RC_CONSOLE_GAMECUBE, iso_path.c_str())) + return; + m_queue.EmplaceItem([this, callback, game_hash] { + const auto resolve_hash_response = ResolveHash(game_hash); + if (resolve_hash_response != ResponseType::SUCCESS || m_game_id == 0) + { + callback(resolve_hash_response); + return; + } + + const auto start_session_response = StartRASession(); + if (start_session_response != ResponseType::SUCCESS) + { + callback(start_session_response); + return; + } + + const auto fetch_game_data_response = FetchGameData(); + m_is_game_loaded = fetch_game_data_response == ResponseType::SUCCESS; + + // Claim the lock, then queue the fetch unlock data calls, then initialize the unlock map in + // ActivateDeactiveAchievements. This allows the calls to process while initializing the + // unlock map but then forces them to wait until it's initialized before making modifications to + // it. + { + std::lock_guard lg{m_lock}; + LoadUnlockData([](ResponseType r_type) {}); + ActivateDeactivateAchievements(); + } + ActivateDeactivateLeaderboards(); + ActivateDeactivateRichPresence(); + + callback(fetch_game_data_response); + }); +} + +void AchievementManager::LoadUnlockData(const ResponseCallback& callback) +{ + m_queue.EmplaceItem([this, callback] { + const auto hardcore_unlock_response = FetchUnlockData(true); + if (hardcore_unlock_response != ResponseType::SUCCESS) + { + callback(hardcore_unlock_response); + return; + } + + callback(FetchUnlockData(false)); + }); +} + +void AchievementManager::ActivateDeactivateAchievements() +{ + bool enabled = Config::Get(Config::RA_ACHIEVEMENTS_ENABLED); + bool unofficial = Config::Get(Config::RA_UNOFFICIAL_ENABLED); + bool encore = Config::Get(Config::RA_ENCORE_ENABLED); + for (u32 ix = 0; ix < m_game_data.num_achievements; ix++) + { + auto iter = + m_unlock_map.insert({m_game_data.achievements[ix].id, UnlockStatus{.game_data_index = ix}}); + ActivateDeactivateAchievement(iter.first->first, enabled, unofficial, encore); + } +} + +void AchievementManager::ActivateDeactivateLeaderboards() +{ + bool leaderboards_enabled = Config::Get(Config::RA_LEADERBOARDS_ENABLED); + for (u32 ix = 0; ix < m_game_data.num_leaderboards; ix++) + { + auto leaderboard = m_game_data.leaderboards[ix]; + if (m_is_game_loaded && leaderboards_enabled && hardcore_mode_enabled) + { + rc_runtime_activate_lboard(&m_runtime, leaderboard.id, leaderboard.definition, nullptr, 0); + } + else + { + rc_runtime_deactivate_lboard(&m_runtime, m_game_data.leaderboards[ix].id); + } + } +} + +void AchievementManager::ActivateDeactivateRichPresence() +{ + rc_runtime_activate_richpresence( + &m_runtime, + (m_is_game_loaded && Config::Get(Config::RA_RICH_PRESENCE_ENABLED)) ? + m_game_data.rich_presence_script : + "", + nullptr, 0); +} + +void AchievementManager::CloseGame() +{ + m_is_game_loaded = false; + m_game_id = 0; + m_queue.Cancel(); + m_unlock_map.clear(); + ActivateDeactivateAchievements(); + ActivateDeactivateLeaderboards(); + ActivateDeactivateRichPresence(); } void AchievementManager::Logout() { + CloseGame(); Config::SetBaseOrCurrent(Config::RA_API_TOKEN, ""); - rc_api_destroy_login_response(&m_login_data); - m_login_data.response.succeeded = 0; } void AchievementManager::Shutdown() { + CloseGame(); m_is_runtime_initialized = false; m_queue.Shutdown(); // DON'T log out - keep those credentials for next run. - rc_api_destroy_login_response(&m_login_data); - m_login_data.response.succeeded = 0; rc_runtime_destroy(&m_runtime); } AchievementManager::ResponseType AchievementManager::VerifyCredentials(const std::string& password) { + rc_api_login_response_t login_data{}; std::string username = Config::Get(Config::RA_USERNAME); std::string api_token = Config::Get(Config::RA_API_TOKEN); rc_api_login_request_t login_request = { .username = username.c_str(), .api_token = api_token.c_str(), .password = password.c_str()}; ResponseType r_type = Request( - login_request, &m_login_data, rc_api_init_login_request, rc_api_process_login_response); + login_request, &login_data, rc_api_init_login_request, rc_api_process_login_response); if (r_type == ResponseType::SUCCESS) - Config::SetBaseOrCurrent(Config::RA_API_TOKEN, m_login_data.api_token); + Config::SetBaseOrCurrent(Config::RA_API_TOKEN, login_data.api_token); + rc_api_destroy_login_response(&login_data); return r_type; } +AchievementManager::ResponseType +AchievementManager::ResolveHash(std::array game_hash) +{ + rc_api_resolve_hash_response_t hash_data{}; + std::string username = Config::Get(Config::RA_USERNAME); + std::string api_token = Config::Get(Config::RA_API_TOKEN); + rc_api_resolve_hash_request_t resolve_hash_request = { + .username = username.c_str(), .api_token = api_token.c_str(), .game_hash = game_hash.data()}; + ResponseType r_type = Request( + resolve_hash_request, &hash_data, rc_api_init_resolve_hash_request, + rc_api_process_resolve_hash_response); + if (r_type == ResponseType::SUCCESS) + m_game_id = hash_data.game_id; + rc_api_destroy_resolve_hash_response(&hash_data); + return r_type; +} + +AchievementManager::ResponseType AchievementManager::StartRASession() +{ + rc_api_start_session_response_t session_data{}; + std::string username = Config::Get(Config::RA_USERNAME); + std::string api_token = Config::Get(Config::RA_API_TOKEN); + rc_api_start_session_request_t start_session_request = { + .username = username.c_str(), .api_token = api_token.c_str(), .game_id = m_game_id}; + ResponseType r_type = Request( + start_session_request, &session_data, rc_api_init_start_session_request, + rc_api_process_start_session_response); + rc_api_destroy_start_session_response(&session_data); + return r_type; +} + +AchievementManager::ResponseType AchievementManager::FetchGameData() +{ + std::string username = Config::Get(Config::RA_USERNAME); + std::string api_token = Config::Get(Config::RA_API_TOKEN); + rc_api_fetch_game_data_request_t fetch_data_request = { + .username = username.c_str(), .api_token = api_token.c_str(), .game_id = m_game_id}; + return Request( + fetch_data_request, &m_game_data, rc_api_init_fetch_game_data_request, + rc_api_process_fetch_game_data_response); +} + +AchievementManager::ResponseType AchievementManager::FetchUnlockData(bool hardcore) +{ + rc_api_fetch_user_unlocks_response_t unlock_data{}; + std::string username = Config::Get(Config::RA_USERNAME); + std::string api_token = Config::Get(Config::RA_API_TOKEN); + rc_api_fetch_user_unlocks_request_t fetch_unlocks_request = {.username = username.c_str(), + .api_token = api_token.c_str(), + .game_id = m_game_id, + .hardcore = hardcore}; + ResponseType r_type = + Request( + fetch_unlocks_request, &unlock_data, rc_api_init_fetch_user_unlocks_request, + rc_api_process_fetch_user_unlocks_response); + if (r_type == ResponseType::SUCCESS) + { + std::lock_guard lg{m_lock}; + bool enabled = Config::Get(Config::RA_ACHIEVEMENTS_ENABLED); + bool unofficial = Config::Get(Config::RA_UNOFFICIAL_ENABLED); + bool encore = Config::Get(Config::RA_ENCORE_ENABLED); + for (AchievementId ix = 0; ix < unlock_data.num_achievement_ids; ix++) + { + auto it = m_unlock_map.find(unlock_data.achievement_ids[ix]); + if (it == m_unlock_map.end()) + continue; + it->second.remote_unlock_status = + hardcore ? UnlockStatus::UnlockType::HARDCORE : UnlockStatus::UnlockType::SOFTCORE; + ActivateDeactivateAchievement(unlock_data.achievement_ids[ix], enabled, unofficial, encore); + } + } + rc_api_destroy_fetch_user_unlocks_response(&unlock_data); + return r_type; +} + +void AchievementManager::ActivateDeactivateAchievement(AchievementId id, bool enabled, + bool unofficial, bool encore) +{ + auto it = m_unlock_map.find(id); + if (it == m_unlock_map.end()) + return; + const UnlockStatus& status = it->second; + u32 index = status.game_data_index; + bool active = (rc_runtime_get_achievement(&m_runtime, id) != nullptr); + + // Deactivate achievements if game is not loaded + bool activate = m_is_game_loaded; + // Activate achievements only if achievements are enabled + if (activate && !enabled) + activate = false; + // Deactivate if achievement is unofficial, unless unofficial achievements are enabled + if (activate && !unofficial && + m_game_data.achievements[index].category == RC_ACHIEVEMENT_CATEGORY_UNOFFICIAL) + { + activate = false; + } + // If encore mode is on, activate/deactivate regardless of current unlock status + if (activate && !encore) + { + // Encore is off, achievement has been unlocked in this session, deactivate + activate = (status.session_unlock_count == 0); + // Encore is off, achievement has been hardcore unlocked on site, deactivate + if (activate && status.remote_unlock_status == UnlockStatus::UnlockType::HARDCORE) + activate = false; + // Encore is off, hardcore is off, achievement has been softcore unlocked on site, deactivate + if (activate && !hardcore_mode_enabled && + status.remote_unlock_status == UnlockStatus::UnlockType::SOFTCORE) + { + activate = false; + } + } + + if (!active && activate) + { + rc_runtime_activate_achievement(&m_runtime, id, m_game_data.achievements[index].definition, + nullptr, 0); + } + if (active && !activate) + rc_runtime_deactivate_achievement(&m_runtime, id); +} + // Every RetroAchievements API call, with only a partial exception for fetch_image, follows // the same design pattern (here, X is the name of the call): // Create a specific rc_api_X_request_t struct and populate with the necessary values diff --git a/Source/Core/Core/AchievementManager.h b/Source/Core/Core/AchievementManager.h index 91fd9339ef..b759386721 100644 --- a/Source/Core/Core/AchievementManager.h +++ b/Source/Core/Core/AchievementManager.h @@ -8,37 +8,58 @@ #include #include #include +#include +#include #include #include #include "Common/Event.h" #include "Common/WorkQueueThread.h" +using AchievementId = u32; + class AchievementManager { public: enum class ResponseType { SUCCESS, + MANAGER_NOT_INITIALIZED, INVALID_CREDENTIALS, CONNECTION_FAILED, UNKNOWN_FAILURE }; - using LoginCallback = std::function; + using ResponseCallback = std::function; static AchievementManager* GetInstance(); void Init(); ResponseType Login(const std::string& password); - void LoginAsync(const std::string& password, const LoginCallback& callback); + void LoginAsync(const std::string& password, const ResponseCallback& callback); bool IsLoggedIn() const; + void LoadGameByFilenameAsync(const std::string& iso_path, const ResponseCallback& callback); + + void LoadUnlockData(const ResponseCallback& callback); + void ActivateDeactivateAchievements(); + void ActivateDeactivateLeaderboards(); + void ActivateDeactivateRichPresence(); + + void CloseGame(); void Logout(); void Shutdown(); private: AchievementManager() = default; + static constexpr int HASH_LENGTH = 33; + ResponseType VerifyCredentials(const std::string& password); + ResponseType ResolveHash(std::array game_hash); + ResponseType StartRASession(); + ResponseType FetchGameData(); + ResponseType FetchUnlockData(bool hardcore); + + void ActivateDeactivateAchievement(AchievementId id, bool enabled, bool unofficial, bool encore); template ResponseType Request(RcRequest rc_request, RcResponse* rc_response, @@ -47,8 +68,25 @@ private: rc_runtime_t m_runtime{}; bool m_is_runtime_initialized = false; - rc_api_login_response_t m_login_data{}; + unsigned int m_game_id = 0; + rc_api_fetch_game_data_response_t m_game_data{}; + bool m_is_game_loaded = false; + + struct UnlockStatus + { + AchievementId game_data_index = 0; + enum class UnlockType + { + LOCKED, + SOFTCORE, + HARDCORE + } remote_unlock_status = UnlockType::LOCKED; + int session_unlock_count = 0; + }; + std::unordered_map m_unlock_map; + Common::WorkQueueThread> m_queue; + std::recursive_mutex m_lock; }; // class AchievementManager #endif // USE_RETRO_ACHIEVEMENTS diff --git a/Source/Core/Core/ActionReplay.cpp b/Source/Core/Core/ActionReplay.cpp index 05b87e11b4..39a05d00b8 100644 --- a/Source/Core/Core/ActionReplay.cpp +++ b/Source/Core/Core/ActionReplay.cpp @@ -169,18 +169,17 @@ void AddCode(ARCode code) } } -void LoadAndApplyCodes(const IniFile& global_ini, const IniFile& local_ini) +void LoadAndApplyCodes(const Common::IniFile& global_ini, const Common::IniFile& local_ini) { ApplyCodes(LoadCodes(global_ini, local_ini)); } // Parses the Action Replay section of a game ini file. -std::vector LoadCodes(const IniFile& global_ini, const IniFile& local_ini) +std::vector LoadCodes(const Common::IniFile& global_ini, const Common::IniFile& local_ini) { std::vector codes; - const IniFile* inis[2] = {&global_ini, &local_ini}; - for (const IniFile* ini : inis) + for (const auto* ini : {&global_ini, &local_ini}) { std::vector lines; std::vector encrypted_lines; @@ -250,7 +249,7 @@ std::vector LoadCodes(const IniFile& global_ini, const IniFile& local_in return codes; } -void SaveCodes(IniFile* local_ini, std::span codes) +void SaveCodes(Common::IniFile* local_ini, std::span codes) { std::vector lines; std::vector enabled_lines; diff --git a/Source/Core/Core/ActionReplay.h b/Source/Core/Core/ActionReplay.h index 4681bb887c..3b05c1117c 100644 --- a/Source/Core/Core/ActionReplay.h +++ b/Source/Core/Core/ActionReplay.h @@ -10,7 +10,10 @@ #include "Common/CommonTypes.h" +namespace Common +{ class IniFile; +} namespace Core { @@ -47,10 +50,10 @@ void SetSyncedCodesAsActive(); void UpdateSyncedCodes(std::span codes); std::vector ApplyAndReturnCodes(std::span codes); void AddCode(ARCode new_code); -void LoadAndApplyCodes(const IniFile& global_ini, const IniFile& local_ini); +void LoadAndApplyCodes(const Common::IniFile& global_ini, const Common::IniFile& local_ini); -std::vector LoadCodes(const IniFile& global_ini, const IniFile& local_ini); -void SaveCodes(IniFile* local_ini, std::span codes); +std::vector LoadCodes(const Common::IniFile& global_ini, const Common::IniFile& local_ini); +void SaveCodes(Common::IniFile* local_ini, std::span codes); using EncryptedLine = std::string; std::variant DeserializeLine(const std::string& line); diff --git a/Source/Core/Core/Boot/Boot_BS2Emu.cpp b/Source/Core/Core/Boot/Boot_BS2Emu.cpp index be799ab1a2..c79c4a4520 100644 --- a/Source/Core/Core/Boot/Boot_BS2Emu.cpp +++ b/Source/Core/Core/Boot/Boot_BS2Emu.cpp @@ -57,13 +57,14 @@ void PresetTimeBaseTicks(Core::System& system, const Core::CPUThreadGuard& guard void CBoot::RunFunction(Core::System& system, u32 address) { - auto& ppc_state = system.GetPPCState(); + auto& power_pc = system.GetPowerPC(); + auto& ppc_state = power_pc.GetPPCState(); ppc_state.pc = address; LR(ppc_state) = 0x00; while (ppc_state.pc != 0x00) - PowerPC::SingleStep(); + power_pc.SingleStep(); } void CBoot::SetupMSR(PowerPC::PowerPCState& ppc_state) diff --git a/Source/Core/Core/BootManager.cpp b/Source/Core/Core/BootManager.cpp index d2c1483994..1c9e2f03d4 100644 --- a/Source/Core/Core/BootManager.cpp +++ b/Source/Core/Core/BootManager.cpp @@ -29,6 +29,7 @@ #include "Common/IniFile.h" #include "Common/Logging/Log.h" +#include "Core/AchievementManager.h" #include "Core/Boot/Boot.h" #include "Core/Config/MainSettings.h" #include "Core/Config/SYSCONFSettings.h" @@ -163,6 +164,16 @@ bool BootCore(std::unique_ptr boot, const WindowSystemInfo& wsi) } } +#ifdef USE_RETRO_ACHIEVEMENTS + std::string path = ""; + if (std::holds_alternative(boot->parameters)) + { + path = std::get(boot->parameters).path; + } + AchievementManager::GetInstance()->LoadGameByFilenameAsync( + path, [](AchievementManager::ResponseType r_type) {}); +#endif // USE_RETRO_ACHIEVEMENTS + const bool load_ipl = !StartUp.bWii && !Config::Get(Config::MAIN_SKIP_IPL) && std::holds_alternative(boot->parameters); if (load_ipl) diff --git a/Source/Core/Core/CheatCodes.h b/Source/Core/Core/CheatCodes.h index ff0d898655..fc73b10f56 100644 --- a/Source/Core/Core/CheatCodes.h +++ b/Source/Core/Core/CheatCodes.h @@ -9,7 +9,7 @@ #include "Common/IniFile.h" template -void ReadEnabledOrDisabled(const IniFile& ini, const std::string& section, bool enabled, +void ReadEnabledOrDisabled(const Common::IniFile& ini, const std::string& section, bool enabled, std::vector* codes) { std::vector lines; @@ -30,7 +30,8 @@ void ReadEnabledOrDisabled(const IniFile& ini, const std::string& section, bool } template -void ReadEnabledAndDisabled(const IniFile& ini, const std::string& section, std::vector* codes) +void ReadEnabledAndDisabled(const Common::IniFile& ini, const std::string& section, + std::vector* codes) { ReadEnabledOrDisabled(ini, section + "_Enabled", true, codes); ReadEnabledOrDisabled(ini, section + "_Disabled", false, codes); diff --git a/Source/Core/Core/Config/AchievementSettings.cpp b/Source/Core/Core/Config/AchievementSettings.cpp index f7ec642881..3499fcc791 100644 --- a/Source/Core/Core/Config/AchievementSettings.cpp +++ b/Source/Core/Core/Config/AchievementSettings.cpp @@ -13,4 +13,13 @@ namespace Config const Info RA_ENABLED{{System::Achievements, "Achievements", "Enabled"}, false}; const Info RA_USERNAME{{System::Achievements, "Achievements", "Username"}, ""}; const Info RA_API_TOKEN{{System::Achievements, "Achievements", "ApiToken"}, ""}; +const Info RA_ACHIEVEMENTS_ENABLED{ + {System::Achievements, "Achievements", "AchievementsEnabled"}, false}; +const Info RA_LEADERBOARDS_ENABLED{ + {System::Achievements, "Achievements", "LeaderboardsEnabled"}, false}; +const Info RA_RICH_PRESENCE_ENABLED{ + {System::Achievements, "Achievements", "RichPresenceEnabled"}, false}; +const Info RA_UNOFFICIAL_ENABLED{{System::Achievements, "Achievements", "UnofficialEnabled"}, + false}; +const Info RA_ENCORE_ENABLED{{System::Achievements, "Achievements", "EncoreEnabled"}, false}; } // namespace Config diff --git a/Source/Core/Core/Config/AchievementSettings.h b/Source/Core/Core/Config/AchievementSettings.h index 8f26769d7f..33318f7400 100644 --- a/Source/Core/Core/Config/AchievementSettings.h +++ b/Source/Core/Core/Config/AchievementSettings.h @@ -11,4 +11,9 @@ namespace Config extern const Info RA_ENABLED; extern const Info RA_USERNAME; extern const Info RA_API_TOKEN; +extern const Info RA_ACHIEVEMENTS_ENABLED; +extern const Info RA_LEADERBOARDS_ENABLED; +extern const Info RA_RICH_PRESENCE_ENABLED; +extern const Info RA_UNOFFICIAL_ENABLED; +extern const Info RA_ENCORE_ENABLED; } // namespace Config diff --git a/Source/Core/Core/ConfigLoaders/BaseConfigLoader.cpp b/Source/Core/Core/ConfigLoaders/BaseConfigLoader.cpp index 6b8ed12e7b..5356449cdb 100644 --- a/Source/Core/Core/ConfigLoaders/BaseConfigLoader.cpp +++ b/Source/Core/Core/ConfigLoaders/BaseConfigLoader.cpp @@ -113,14 +113,14 @@ public: LoadFromSYSCONF(layer); for (const auto& system : system_to_ini) { - IniFile ini; + Common::IniFile ini; ini.Load(File::GetUserPath(system.second)); - const std::list& system_sections = ini.GetSections(); + const auto& system_sections = ini.GetSections(); for (const auto& section : system_sections) { const std::string section_name = section.GetName(); - const IniFile::Section::SectionMap& section_map = section.GetValues(); + const auto& section_map = section.GetValues(); for (const auto& value : section_map) { @@ -141,7 +141,7 @@ public: { SaveToSYSCONF(layer->GetLayer()); - std::map inis; + std::map inis; for (const auto& system : system_to_ini) { @@ -176,7 +176,7 @@ public: if (value) { - IniFile::Section* ini_section = ini->second.GetOrCreateSection(location.section); + auto* ini_section = ini->second.GetOrCreateSection(location.section); ini_section->Set(location.key, *value); } else diff --git a/Source/Core/Core/ConfigLoaders/GameConfigLoader.cpp b/Source/Core/Core/ConfigLoaders/GameConfigLoader.cpp index 7b6466b20f..2ca46691d2 100644 --- a/Source/Core/Core/ConfigLoaders/GameConfigLoader.cpp +++ b/Source/Core/Core/ConfigLoaders/GameConfigLoader.cpp @@ -175,7 +175,7 @@ public: void Load(Config::Layer* layer) override { - IniFile ini; + Common::IniFile ini; if (layer->GetLayer() == Config::LayerType::GlobalGame) { for (const std::string& filename : GetGameIniFilenames(m_id, m_revision)) @@ -187,7 +187,7 @@ public: ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + filename, true); } - const std::list& system_sections = ini.GetSections(); + const auto& system_sections = ini.GetSections(); for (const auto& section : system_sections) { @@ -234,11 +234,11 @@ private: continue; } - IniFile profile_ini; + Common::IniFile profile_ini; profile_ini.Load(ini_path); - const IniFile::Section* ini_section = profile_ini.GetOrCreateSection("Profile"); - const IniFile::Section::SectionMap& section_map = ini_section->GetValues(); + const auto* ini_section = profile_ini.GetOrCreateSection("Profile"); + const auto& section_map = ini_section->GetValues(); for (const auto& value : section_map) { Config::Location location{std::get<2>(use_data), std::get<1>(use_data) + num, @@ -250,12 +250,12 @@ private: } } - void LoadFromSystemSection(Config::Layer* layer, const IniFile::Section& section) const + void LoadFromSystemSection(Config::Layer* layer, const Common::IniFile::Section& section) const { const std::string section_name = section.GetName(); // Regular key,value pairs - const IniFile::Section::SectionMap& section_map = section.GetValues(); + const auto& section_map = section.GetValues(); for (const auto& value : section_map) { @@ -280,7 +280,7 @@ void INIGameConfigLayerLoader::Save(Config::Layer* layer) if (layer->GetLayer() != Config::LayerType::LocalGame) return; - IniFile ini; + Common::IniFile ini; for (const std::string& file_name : GetGameIniFilenames(m_id, m_revision)) ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + file_name, true); @@ -298,7 +298,7 @@ void INIGameConfigLayerLoader::Save(Config::Layer* layer) if (value) { - IniFile::Section* ini_section = ini.GetOrCreateSection(ini_location.first); + auto* ini_section = ini.GetOrCreateSection(ini_location.first); ini_section->Set(ini_location.second, *value); } else diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp index f2eefe171c..cf33a27b2b 100644 --- a/Source/Core/Core/ConfigManager.cpp +++ b/Source/Core/Core/ConfigManager.cpp @@ -393,40 +393,40 @@ DiscIO::Language SConfig::GetLanguageAdjustedForRegion(bool wii, DiscIO::Region return language; } -IniFile SConfig::LoadDefaultGameIni() const +Common::IniFile SConfig::LoadDefaultGameIni() const { return LoadDefaultGameIni(GetGameID(), m_revision); } -IniFile SConfig::LoadLocalGameIni() const +Common::IniFile SConfig::LoadLocalGameIni() const { return LoadLocalGameIni(GetGameID(), m_revision); } -IniFile SConfig::LoadGameIni() const +Common::IniFile SConfig::LoadGameIni() const { return LoadGameIni(GetGameID(), m_revision); } -IniFile SConfig::LoadDefaultGameIni(const std::string& id, std::optional revision) +Common::IniFile SConfig::LoadDefaultGameIni(const std::string& id, std::optional revision) { - IniFile game_ini; + Common::IniFile game_ini; for (const std::string& filename : ConfigLoaders::GetGameIniFilenames(id, revision)) game_ini.Load(File::GetSysDirectory() + GAMESETTINGS_DIR DIR_SEP + filename, true); return game_ini; } -IniFile SConfig::LoadLocalGameIni(const std::string& id, std::optional revision) +Common::IniFile SConfig::LoadLocalGameIni(const std::string& id, std::optional revision) { - IniFile game_ini; + Common::IniFile game_ini; for (const std::string& filename : ConfigLoaders::GetGameIniFilenames(id, revision)) game_ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + filename, true); return game_ini; } -IniFile SConfig::LoadGameIni(const std::string& id, std::optional revision) +Common::IniFile SConfig::LoadGameIni(const std::string& id, std::optional revision) { - IniFile game_ini; + Common::IniFile game_ini; for (const std::string& filename : ConfigLoaders::GetGameIniFilenames(id, revision)) game_ini.Load(File::GetSysDirectory() + GAMESETTINGS_DIR DIR_SEP + filename, true); for (const std::string& filename : ConfigLoaders::GetGameIniFilenames(id, revision)) diff --git a/Source/Core/Core/ConfigManager.h b/Source/Core/Core/ConfigManager.h index 5f3f325983..5af0075134 100644 --- a/Source/Core/Core/ConfigManager.h +++ b/Source/Core/Core/ConfigManager.h @@ -14,7 +14,10 @@ #include "Common/Common.h" #include "Common/CommonTypes.h" +namespace Common +{ class IniFile; +} namespace Core { @@ -81,13 +84,13 @@ struct SConfig DiscIO::Language GetCurrentLanguage(bool wii) const; DiscIO::Language GetLanguageAdjustedForRegion(bool wii, DiscIO::Region region) const; - IniFile LoadDefaultGameIni() const; - IniFile LoadLocalGameIni() const; - IniFile LoadGameIni() const; + Common::IniFile LoadDefaultGameIni() const; + Common::IniFile LoadLocalGameIni() const; + Common::IniFile LoadGameIni() const; - static IniFile LoadDefaultGameIni(const std::string& id, std::optional revision); - static IniFile LoadLocalGameIni(const std::string& id, std::optional revision); - static IniFile LoadGameIni(const std::string& id, std::optional revision); + static Common::IniFile LoadDefaultGameIni(const std::string& id, std::optional revision); + static Common::IniFile LoadLocalGameIni(const std::string& id, std::optional revision); + static Common::IniFile LoadGameIni(const std::string& id, std::optional revision); SConfig(const SConfig&) = delete; SConfig& operator=(const SConfig&) = delete; diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index fbc87d18fd..435b26985d 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -38,6 +38,7 @@ #include "Common/Timer.h" #include "Common/Version.h" +#include "Core/AchievementManager.h" #include "Core/Boot/Boot.h" #include "Core/BootManager.h" #include "Core/Config/MainSettings.h" @@ -283,6 +284,10 @@ void Stop() // - Hammertime! if (GetState() == State::Stopping || GetState() == State::Uninitialized) return; +#ifdef USE_RETRO_ACHIEVEMENTS + AchievementManager::GetInstance()->CloseGame(); +#endif // USE_RETRO_ACHIEVEMENTS + s_is_stopping = true; CallOnStateChangedCallbacks(State::Stopping); @@ -435,7 +440,8 @@ static void FifoPlayerThread(const std::optional& savestate_path, { DeclareAsCPUThread(); - if (Core::System::GetInstance().IsDualCoreMode()) + auto& system = Core::System::GetInstance(); + if (system.IsDualCoreMode()) Common::SetCurrentThreadName("FIFO player thread"); else Common::SetCurrentThreadName("FIFO-GPU thread"); @@ -443,15 +449,14 @@ static void FifoPlayerThread(const std::optional& savestate_path, // Enter CPU run loop. When we leave it - we are done. if (auto cpu_core = FifoPlayer::GetInstance().GetCPUCore()) { - PowerPC::InjectExternalCPUCore(cpu_core.get()); + system.GetPowerPC().InjectExternalCPUCore(cpu_core.get()); s_is_started = true; CPUSetInitialExecutionState(); - auto& system = Core::System::GetInstance(); system.GetCPU().Run(); s_is_started = false; - PowerPC::InjectExternalCPUCore(nullptr); + system.GetPowerPC().InjectExternalCPUCore(nullptr); FifoPlayer::GetInstance().Close(); } else @@ -552,7 +557,7 @@ static void EmuThread(std::unique_ptr boot, WindowSystemInfo wsi HLE::Clear(); CPUThreadGuard guard(system); - PowerPC::debug_interface.Clear(guard); + system.GetPowerPC().GetDebugInterface().Clear(guard); }}; VideoBackendBase::PopulateBackendInfo(); @@ -590,7 +595,7 @@ static void EmuThread(std::unique_ptr boot, WindowSystemInfo wsi system.GetCPU().Break(); // Load GCM/DOL/ELF whatever ... we boot with the interpreter core - PowerPC::SetMode(PowerPC::CoreMode::Interpreter); + system.GetPowerPC().SetMode(PowerPC::CoreMode::Interpreter); // Determine the CPU thread function void (*cpuThreadFunc)(const std::optional& savestate_path, bool delete_savestate); @@ -628,11 +633,11 @@ static void EmuThread(std::unique_ptr boot, WindowSystemInfo wsi // Setup our core if (Config::Get(Config::MAIN_CPU_CORE) != PowerPC::CPUCore::Interpreter) { - PowerPC::SetMode(PowerPC::CoreMode::JIT); + system.GetPowerPC().SetMode(PowerPC::CoreMode::JIT); } else { - PowerPC::SetMode(PowerPC::CoreMode::Interpreter); + system.GetPowerPC().SetMode(PowerPC::CoreMode::Interpreter); } UpdateTitle(); @@ -901,7 +906,7 @@ void UpdateTitle() { // Settings are shown the same for both extended and summary info const std::string SSettings = fmt::format( - "{} {} | {} | {}", PowerPC::GetCPUName(), + "{} {} | {} | {}", Core::System::GetInstance().GetPowerPC().GetCPUName(), Core::System::GetInstance().IsDualCoreMode() ? "DC" : "SC", g_video_backend->GetDisplayName(), Config::Get(Config::MAIN_DSP_HLE) ? "HLE" : "LLE"); diff --git a/Source/Core/Core/CoreTiming.cpp b/Source/Core/Core/CoreTiming.cpp index aa7c501c92..3659d4fb80 100644 --- a/Source/Core/Core/CoreTiming.cpp +++ b/Source/Core/Core/CoreTiming.cpp @@ -303,8 +303,8 @@ void CoreTimingManager::MoveEvents() void CoreTimingManager::Advance() { - auto& system = m_system; - auto& ppc_state = m_system.GetPPCState(); + auto& power_pc = m_system.GetPowerPC(); + auto& ppc_state = power_pc.GetPPCState(); MoveEvents(); @@ -323,7 +323,7 @@ void CoreTimingManager::Advance() m_event_queue.pop_back(); Throttle(evt.time); - evt.type->callback(system, evt.userdata, m_globals.global_timer - evt.time); + evt.type->callback(m_system, evt.userdata, m_globals.global_timer - evt.time); } m_is_global_timer_sane = false; @@ -341,7 +341,7 @@ void CoreTimingManager::Advance() // It's important to do this after processing events otherwise any exceptions will be delayed // until the next slice: // Pokemon Box refuses to boot if the first exception from the audio DMA is received late - PowerPC::CheckExternalExceptions(); + power_pc.CheckExternalExceptions(); } void CoreTimingManager::Throttle(const s64 target_cycle) diff --git a/Source/Core/Core/Debugger/Debugger_SymbolMap.cpp b/Source/Core/Core/Debugger/Debugger_SymbolMap.cpp index cab601c83d..c44ef40245 100644 --- a/Source/Core/Core/Debugger/Debugger_SymbolMap.cpp +++ b/Source/Core/Core/Debugger/Debugger_SymbolMap.cpp @@ -32,7 +32,7 @@ void AddAutoBreakpoints() { Common::Symbol* symbol = g_symbolDB.GetSymbolFromName(bp); if (symbol) - PowerPC::breakpoints.Add(symbol->address, false); + Core::System::GetInstance().GetPowerPC().GetBreakPoints().Add(symbol->address, false); } #endif #endif diff --git a/Source/Core/Core/Debugger/PPCDebugInterface.cpp b/Source/Core/Core/Debugger/PPCDebugInterface.cpp index 6d363fd6bf..ff87e82300 100644 --- a/Source/Core/Core/Debugger/PPCDebugInterface.cpp +++ b/Source/Core/Core/Debugger/PPCDebugInterface.cpp @@ -36,6 +36,7 @@ void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, Common::Debug::MemoryPa if (!PowerPC::MMU::HostIsRAMAddress(guard, address)) return; + auto& power_pc = guard.GetSystem().GetPowerPC(); for (u32 offset = 0; offset < size; ++offset) { if (store_existing_value) @@ -50,11 +51,11 @@ void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, Common::Debug::MemoryPa } if (((address + offset) % 4) == 3) - PowerPC::ScheduleInvalidateCacheThreadSafe(Common::AlignDown(address + offset, 4)); + power_pc.ScheduleInvalidateCacheThreadSafe(Common::AlignDown(address + offset, 4)); } if (((address + size) % 4) != 0) { - PowerPC::ScheduleInvalidateCacheThreadSafe( + power_pc.ScheduleInvalidateCacheThreadSafe( Common::AlignDown(address + static_cast(size), 4)); } } @@ -347,40 +348,41 @@ bool PPCDebugInterface::IsAlive() const bool PPCDebugInterface::IsBreakpoint(u32 address) const { - return PowerPC::breakpoints.IsAddressBreakPoint(address); + return m_system.GetPowerPC().GetBreakPoints().IsAddressBreakPoint(address); } void PPCDebugInterface::SetBreakpoint(u32 address) { - PowerPC::breakpoints.Add(address); + m_system.GetPowerPC().GetBreakPoints().Add(address); } void PPCDebugInterface::ClearBreakpoint(u32 address) { - PowerPC::breakpoints.Remove(address); + m_system.GetPowerPC().GetBreakPoints().Remove(address); } void PPCDebugInterface::ClearAllBreakpoints() { - PowerPC::breakpoints.Clear(); + m_system.GetPowerPC().GetBreakPoints().Clear(); } void PPCDebugInterface::ToggleBreakpoint(u32 address) { - if (PowerPC::breakpoints.IsAddressBreakPoint(address)) - PowerPC::breakpoints.Remove(address); + auto& breakpoints = m_system.GetPowerPC().GetBreakPoints(); + if (breakpoints.IsAddressBreakPoint(address)) + breakpoints.Remove(address); else - PowerPC::breakpoints.Add(address); + breakpoints.Add(address); } void PPCDebugInterface::ClearAllMemChecks() { - PowerPC::memchecks.Clear(); + m_system.GetPowerPC().GetMemChecks().Clear(); } bool PPCDebugInterface::IsMemCheck(u32 address, size_t size) const { - return PowerPC::memchecks.GetMemCheck(address, size) != nullptr; + return m_system.GetPowerPC().GetMemChecks().GetMemCheck(address, size) != nullptr; } void PPCDebugInterface::ToggleMemCheck(u32 address, bool read, bool write, bool log) @@ -397,11 +399,11 @@ void PPCDebugInterface::ToggleMemCheck(u32 address, bool read, bool write, bool MemCheck.log_on_hit = log; MemCheck.break_on_hit = true; - PowerPC::memchecks.Add(std::move(MemCheck)); + m_system.GetPowerPC().GetMemChecks().Add(std::move(MemCheck)); } else { - PowerPC::memchecks.Remove(address); + m_system.GetPowerPC().GetMemChecks().Remove(address); } } diff --git a/Source/Core/Core/FifoPlayer/FifoPlayer.cpp b/Source/Core/Core/FifoPlayer/FifoPlayer.cpp index baf7b87760..9187728c29 100644 --- a/Source/Core/Core/FifoPlayer/FifoPlayer.cpp +++ b/Source/Core/Core/FifoPlayer/FifoPlayer.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "Common/Assert.h" #include "Common/CommonTypes.h" @@ -101,14 +102,9 @@ void FifoPlaybackAnalyzer::AnalyzeFrames(FifoDataFile* file, part_start = offset; // Copy cpmem now, because end_of_primitives isn't triggered until the first opcode after // primitive data, and the first opcode might update cpmem -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wclass-memaccess" -#endif - std::memcpy(&cpmem, &analyzer.m_cpmem, sizeof(CPState)); -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif + static_assert(std::is_trivially_copyable_v); + std::memcpy(static_cast(&cpmem), static_cast(&analyzer.m_cpmem), + sizeof(CPState)); } if (analyzer.m_end_of_primitives) { diff --git a/Source/Core/Core/FifoPlayer/FifoRecorder.cpp b/Source/Core/Core/FifoPlayer/FifoRecorder.cpp index 15063c3f02..7cedf8299b 100644 --- a/Source/Core/Core/FifoPlayer/FifoRecorder.cpp +++ b/Source/Core/Core/FifoPlayer/FifoRecorder.cpp @@ -268,9 +268,7 @@ void FifoRecorder::StartRecording(s32 numFrames, CallbackFunc finishedCb) RecordInitialVideoMemory(); } - auto& system = Core::System::GetInstance(); - auto& command_processor = system.GetCommandProcessor(); - const auto& fifo = command_processor.GetFifo(); + const auto& fifo = Core::System::GetInstance().GetCommandProcessor().GetFifo(); EndFrame(fifo.CPBase.load(std::memory_order_relaxed), fifo.CPEnd.load(std::memory_order_relaxed)); }, diff --git a/Source/Core/Core/GeckoCodeConfig.cpp b/Source/Core/Core/GeckoCodeConfig.cpp index e4fc7c4c68..350edc3e31 100644 --- a/Source/Core/Core/GeckoCodeConfig.cpp +++ b/Source/Core/Core/GeckoCodeConfig.cpp @@ -127,11 +127,11 @@ std::vector DownloadCodes(std::string gametdb_id, bool* succeeded, bo return gcodes; } -std::vector LoadCodes(const IniFile& globalIni, const IniFile& localIni) +std::vector LoadCodes(const Common::IniFile& globalIni, const Common::IniFile& localIni) { std::vector gcodes; - for (const IniFile* ini : {&globalIni, &localIni}) + for (const auto* ini : {&globalIni, &localIni}) { std::vector lines; ini->GetLines("Gecko", &lines, false); @@ -239,7 +239,7 @@ static void SaveGeckoCode(std::vector& lines, const GeckoCode& gcod lines.push_back('*' + note); } -void SaveCodes(IniFile& inifile, const std::vector& gcodes) +void SaveCodes(Common::IniFile& inifile, const std::vector& gcodes) { std::vector lines; std::vector enabled_lines; diff --git a/Source/Core/Core/GeckoCodeConfig.h b/Source/Core/Core/GeckoCodeConfig.h index 2497ab603e..941e6246f5 100644 --- a/Source/Core/Core/GeckoCodeConfig.h +++ b/Source/Core/Core/GeckoCodeConfig.h @@ -9,14 +9,17 @@ #include "Core/GeckoCode.h" +namespace Common +{ class IniFile; +} namespace Gecko { -std::vector LoadCodes(const IniFile& globalIni, const IniFile& localIni); +std::vector LoadCodes(const Common::IniFile& globalIni, const Common::IniFile& localIni); std::vector DownloadCodes(std::string gametdb_id, bool* succeeded, bool use_https = true); -void SaveCodes(IniFile& inifile, const std::vector& gcodes); +void SaveCodes(Common::IniFile& inifile, const std::vector& gcodes); std::optional DeserializeLine(const std::string& line); } // namespace Gecko diff --git a/Source/Core/Core/HLE/HLE.cpp b/Source/Core/Core/HLE/HLE.cpp index 6728160ae7..310aec6620 100644 --- a/Source/Core/Core/HLE/HLE.cpp +++ b/Source/Core/Core/HLE/HLE.cpp @@ -203,7 +203,7 @@ HookFlag GetHookFlagsByIndex(u32 index) bool IsEnabled(HookFlag flag) { return flag != HLE::HookFlag::Debug || Config::Get(Config::MAIN_ENABLE_DEBUGGING) || - PowerPC::GetMode() == PowerPC::CoreMode::Interpreter; + Core::System::GetInstance().GetPowerPC().GetMode() == PowerPC::CoreMode::Interpreter; } u32 UnPatch(Core::System& system, std::string_view patch_name) diff --git a/Source/Core/Core/HW/CPU.cpp b/Source/Core/Core/HW/CPU.cpp index 14031ef5d0..aa90ab54d2 100644 --- a/Source/Core/Core/HW/CPU.cpp +++ b/Source/Core/Core/HW/CPU.cpp @@ -19,19 +19,21 @@ namespace CPU { -CPUManager::CPUManager() = default; +CPUManager::CPUManager(Core::System& system) : m_system(system) +{ +} CPUManager::~CPUManager() = default; void CPUManager::Init(PowerPC::CPUCore cpu_core) { - PowerPC::Init(cpu_core); + m_system.GetPowerPC().Init(cpu_core); m_state = State::Stepping; } void CPUManager::Shutdown() { Stop(); - PowerPC::Shutdown(); + m_system.GetPowerPC().Shutdown(); } // Requires holding m_state_change_lock @@ -62,11 +64,11 @@ void CPUManager::ExecutePendingJobs(std::unique_lock& state_lock) void CPUManager::Run() { - auto& system = Core::System::GetInstance(); + auto& power_pc = m_system.GetPowerPC(); // Updating the host CPU's rounding mode must be done on the CPU thread. // We can't rely on PowerPC::Init doing it, since it's called from EmuThread. - PowerPC::RoundingModeUpdated(); + PowerPC::RoundingModeUpdated(power_pc.GetPPCState()); std::unique_lock state_lock(m_state_change_lock); while (m_state != State::PowerDown) @@ -85,22 +87,22 @@ void CPUManager::Run() // SingleStep so that the "continue", "step over" and "step out" debugger functions // work when the PC is at a breakpoint at the beginning of the block // If watchpoints are enabled, any instruction could be a breakpoint. - if (PowerPC::GetMode() != PowerPC::CoreMode::Interpreter) + if (power_pc.GetMode() != PowerPC::CoreMode::Interpreter) { - if (PowerPC::breakpoints.IsAddressBreakPoint(system.GetPPCState().pc) || - PowerPC::memchecks.HasAny()) + if (power_pc.GetBreakPoints().IsAddressBreakPoint(power_pc.GetPPCState().pc) || + power_pc.GetMemChecks().HasAny()) { m_state = State::Stepping; - PowerPC::CoreMode old_mode = PowerPC::GetMode(); - PowerPC::SetMode(PowerPC::CoreMode::Interpreter); - PowerPC::SingleStep(); - PowerPC::SetMode(old_mode); + PowerPC::CoreMode old_mode = power_pc.GetMode(); + power_pc.SetMode(PowerPC::CoreMode::Interpreter); + power_pc.SingleStep(); + power_pc.SetMode(old_mode); m_state = State::Running; } } // Enter a fast runloop - PowerPC::RunLoop(); + power_pc.RunLoop(); state_lock.lock(); m_state_cpu_thread_active = false; @@ -147,7 +149,7 @@ void CPUManager::Run() m_state_cpu_thread_active = true; state_lock.unlock(); - PowerPC::SingleStep(); + power_pc.SingleStep(); state_lock.lock(); m_state_cpu_thread_active = false; diff --git a/Source/Core/Core/HW/CPU.h b/Source/Core/Core/HW/CPU.h index 85f8885026..e328f645e8 100644 --- a/Source/Core/Core/HW/CPU.h +++ b/Source/Core/Core/HW/CPU.h @@ -12,7 +12,10 @@ namespace Common { class Event; } - +namespace Core +{ +class System; +} namespace PowerPC { enum class CPUCore; @@ -30,7 +33,7 @@ enum class State class CPUManager { public: - CPUManager(); + explicit CPUManager(Core::System& system); CPUManager(const CPUManager& other) = delete; CPUManager(CPUManager&& other) = delete; CPUManager& operator=(const CPUManager& other) = delete; @@ -130,5 +133,7 @@ private: bool m_state_cpu_step_instruction = false; Common::Event* m_state_cpu_step_instruction_sync = nullptr; std::queue> m_pending_jobs; + + Core::System& m_system; }; } // namespace CPU diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/AESnd.cpp b/Source/Core/Core/HW/DSPHLE/UCodes/AESnd.cpp index d656f81a4d..202145697e 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/AESnd.cpp +++ b/Source/Core/Core/HW/DSPHLE/UCodes/AESnd.cpp @@ -44,21 +44,21 @@ constexpr u32 VOICE_16_BIT_FLAG = 2; // These are used in the pre-2020 versions version constexpr u32 VOICE_PAUSE_OLD = 0x00000004; -constexpr u32 VOICE_LOOP_OLD = 0x00000008; // not used by the DSP -constexpr u32 VOICE_ONCE_OLD = 0x00000010; // not used by the DSP -constexpr u32 VOICE_STREAM_OLD = 0x00000020; // not used by the DSP +constexpr u32 VOICE_LOOP_OLD [[maybe_unused]] = 0x00000008; // not used by the DSP +constexpr u32 VOICE_ONCE_OLD [[maybe_unused]] = 0x00000010; // not used by the DSP +constexpr u32 VOICE_STREAM_OLD [[maybe_unused]] = 0x00000020; // not used by the DSP // These were changed in the 2020 version to account for the different flags constexpr u32 VOICE_PAUSE_NEW = 0x00000008; -constexpr u32 VOICE_LOOP_NEW = 0x00000010; // not used by the DSP -constexpr u32 VOICE_ONCE_NEW = 0x00000020; // not used by the DSP -constexpr u32 VOICE_STREAM_NEW = 0x00000040; // not used by the DSP +constexpr u32 VOICE_LOOP_NEW [[maybe_unused]] = 0x00000010; // not used by the DSP +constexpr u32 VOICE_ONCE_NEW [[maybe_unused]] = 0x00000020; // not used by the DSP +constexpr u32 VOICE_STREAM_NEW [[maybe_unused]] = 0x00000040; // not used by the DSP // These did not change between versions constexpr u32 VOICE_FINISHED = 0x00100000; -constexpr u32 VOICE_STOPPED = 0x00200000; // not used by the DSP +constexpr u32 VOICE_STOPPED [[maybe_unused]] = 0x00200000; // not used by the DSP constexpr u32 VOICE_RUNNING = 0x40000000; -constexpr u32 VOICE_USED = 0x80000000; // not used by the DSP +constexpr u32 VOICE_USED [[maybe_unused]] = 0x80000000; // not used by the DSP // 1<<4 = scale gain by 1/1, 2<<2 = PCM decoding from ARAM, 1<<0 = 8-bit reads constexpr u32 ACCELERATOR_FORMAT_8_BIT = 0x0019; diff --git a/Source/Core/Core/HW/EXI/BBA/BuiltIn.cpp b/Source/Core/Core/HW/EXI/BBA/BuiltIn.cpp index 4dfc0a30ee..6e5c3eac97 100644 --- a/Source/Core/Core/HW/EXI/BBA/BuiltIn.cpp +++ b/Source/Core/Core/HW/EXI/BBA/BuiltIn.cpp @@ -384,7 +384,8 @@ void CEXIETHERNET::BuiltInBBAInterface::HandleTCPFrame(const Common::TCPPacket& if (size > 0) { // only if contain data - if (static_cast(this_seq - ref->ack_num) >= 0 && data.size() >= size) + if (static_cast(this_seq - ref->ack_num) >= 0 && + data.size() >= static_cast(size)) { ref->tcp_socket.send(data.data(), size); ref->ack_num += size; diff --git a/Source/Core/Core/HW/EXI/BBA/TAPServer_Apple.cpp b/Source/Core/Core/HW/EXI/BBA/TAPServer_Apple.cpp index 77a8f74a9c..de71067c1b 100644 --- a/Source/Core/Core/HW/EXI/BBA/TAPServer_Apple.cpp +++ b/Source/Core/Core/HW/EXI/BBA/TAPServer_Apple.cpp @@ -45,7 +45,8 @@ bool CEXIETHERNET::TAPServerNetworkInterface::Activate() if (connect(fd, reinterpret_cast(&sun), sizeof(sun)) == -1) { - ERROR_LOG_FMT(SP1, "Couldn't connect socket ({}), unable to init BBA", LastStrerrorString()); + ERROR_LOG_FMT(SP1, "Couldn't connect socket ({}), unable to init BBA", + Common::LastStrerrorString()); close(fd); fd = -1; return false; @@ -99,14 +100,14 @@ void CEXIETHERNET::TAPServerNetworkInterface::ReadThreadHandler() u16 size; if (read(fd, &size, 2) != 2) { - ERROR_LOG_FMT(SP1, "Failed to read size field from BBA: {}", LastStrerrorString()); + ERROR_LOG_FMT(SP1, "Failed to read size field from BBA: {}", Common::LastStrerrorString()); } else { int read_bytes = read(fd, m_eth_ref->mRecvBuffer.get(), size); if (read_bytes < 0) { - ERROR_LOG_FMT(SP1, "Failed to read packet data from BBA: {}", LastStrerrorString()); + ERROR_LOG_FMT(SP1, "Failed to read packet data from BBA: {}", Common::LastStrerrorString()); } else if (readEnabled.IsSet()) { diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceEthernet.cpp b/Source/Core/Core/HW/EXI/EXI_DeviceEthernet.cpp index 83134941dc..0e7a1d0276 100644 --- a/Source/Core/Core/HW/EXI/EXI_DeviceEthernet.cpp +++ b/Source/Core/Core/HW/EXI/EXI_DeviceEthernet.cpp @@ -448,7 +448,7 @@ void CEXIETHERNET::SendFromDirectFIFO() const u8* frame = tx_fifo.get(); const u16 size = Common::BitCastPtr(&mBbaMem[BBA_TXFIFOCNT]); if (m_network_interface->SendFrame(frame, size)) - PowerPC::debug_interface.NetworkLogger()->LogBBA(frame, size); + m_system.GetPowerPC().GetDebugInterface().NetworkLogger()->LogBBA(frame, size); } void CEXIETHERNET::SendFromPacketBuffer() @@ -561,7 +561,8 @@ bool CEXIETHERNET::RecvHandlePacket() INFO_LOG_FMT(SP1, "{:x} {:x} {:x} {:x}", page_ptr(BBA_BP), page_ptr(BBA_RRP), page_ptr(BBA_RWP), page_ptr(BBA_RHBP)); #endif - PowerPC::debug_interface.NetworkLogger()->LogBBA(mRecvBuffer.get(), mRecvBufferLength); + m_system.GetPowerPC().GetDebugInterface().NetworkLogger()->LogBBA(mRecvBuffer.get(), + mRecvBufferLength); write_ptr = &mBbaMem[page_ptr(BBA_RWP) << 8]; descriptor = (Descriptor*)write_ptr; diff --git a/Source/Core/Core/HW/MemoryInterface.cpp b/Source/Core/Core/HW/MemoryInterface.cpp index 7bba5450fe..4841b083b4 100644 --- a/Source/Core/Core/HW/MemoryInterface.cpp +++ b/Source/Core/Core/HW/MemoryInterface.cpp @@ -61,14 +61,7 @@ MemoryInterfaceManager::~MemoryInterfaceManager() = default; void MemoryInterfaceManager::Init() { static_assert(std::is_trivially_copyable_v); -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wclass-memaccess" -#endif - std::memset(&m_mi_mem, 0, sizeof(MIMemStruct)); -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif + std::memset(static_cast(&m_mi_mem), 0, sizeof(MIMemStruct)); } void MemoryInterfaceManager::Shutdown() diff --git a/Source/Core/Core/HW/ProcessorInterface.cpp b/Source/Core/Core/HW/ProcessorInterface.cpp index 70b34ccc81..cea84a4ab4 100644 --- a/Source/Core/Core/HW/ProcessorInterface.cpp +++ b/Source/Core/Core/HW/ProcessorInterface.cpp @@ -24,8 +24,8 @@ namespace ProcessorInterface { -constexpr u32 FLIPPER_REV_A = 0x046500B0; -constexpr u32 FLIPPER_REV_B = 0x146500B1; +constexpr u32 FLIPPER_REV_A [[maybe_unused]] = 0x046500B0; +constexpr u32 FLIPPER_REV_B [[maybe_unused]] = 0x146500B1; constexpr u32 FLIPPER_REV_C = 0x246500B1; ProcessorInterfaceManager::ProcessorInterfaceManager(Core::System& system) : m_system(system) diff --git a/Source/Core/Core/HW/SystemTimers.cpp b/Source/Core/Core/HW/SystemTimers.cpp index 4f4089782d..988604d926 100644 --- a/Source/Core/Core/HW/SystemTimers.cpp +++ b/Source/Core/Core/HW/SystemTimers.cpp @@ -223,7 +223,7 @@ void TimeBaseSet() auto& system = Core::System::GetInstance(); auto& core_timing = system.GetCoreTiming(); core_timing.SetFakeTBStartTicks(core_timing.GetTicks()); - core_timing.SetFakeTBStartValue(PowerPC::ReadFullTimeBaseValue()); + core_timing.SetFakeTBStartValue(system.GetPowerPC().ReadFullTimeBaseValue()); } u64 GetFakeTimeBase() diff --git a/Source/Core/Core/HW/WiimoteEmu/DesiredWiimoteState.cpp b/Source/Core/Core/HW/WiimoteEmu/DesiredWiimoteState.cpp index 3d65694167..3157e8b9c8 100644 --- a/Source/Core/Core/HW/WiimoteEmu/DesiredWiimoteState.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/DesiredWiimoteState.cpp @@ -136,14 +136,8 @@ static bool DeserializeExtensionState(DesiredWiimoteState* state, return false; auto& e = state->extension.data.emplace(); static_assert(std::is_trivially_copyable_v); -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wclass-memaccess" -#endif - std::memcpy(&e, &serialized.data[offset], sizeof(T)); -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif + std::memcpy(static_cast(&e), static_cast(&serialized.data[offset]), + sizeof(T)); return true; } diff --git a/Source/Core/Core/HotkeyManager.cpp b/Source/Core/Core/HotkeyManager.cpp index b305db6fa9..bfff976d0f 100644 --- a/Source/Core/Core/HotkeyManager.cpp +++ b/Source/Core/Core/HotkeyManager.cpp @@ -251,7 +251,7 @@ bool IsPressed(int id, bool held) // TODO: Remove this at a future date when we're confident most configs are migrated. static void LoadLegacyConfig(ControllerEmu::EmulatedController* controller) { - IniFile inifile; + Common::IniFile inifile; if (inifile.Load(File::GetUserPath(D_CONFIG_IDX) + "Hotkeys.ini")) { if (!inifile.Exists("Hotkeys") && inifile.Exists("Hotkeys1")) diff --git a/Source/Core/Core/IOS/DI/DI.cpp b/Source/Core/Core/IOS/DI/DI.cpp index a270e7351a..40f818cef6 100644 --- a/Source/Core/Core/IOS/DI/DI.cpp +++ b/Source/Core/Core/IOS/DI/DI.cpp @@ -24,35 +24,18 @@ #include "Core/System.h" #include "DiscIO/Volume.h" -template -class RegisterWrapper -{ -public: - operator u32() const - { - auto& system = Core::System::GetInstance(); - auto& memory = system.GetMemory(); - return memory.GetMMIOMapping()->Read(addr); - } - void operator=(u32 rhs) - { - auto& system = Core::System::GetInstance(); - auto& memory = system.GetMemory(); - memory.GetMMIOMapping()->Write(addr, rhs); - } -}; -static RegisterWrapper<0x0D806000> DISR; -static RegisterWrapper<0x0D806004> DICVR; -static RegisterWrapper<0x0D806008> DICMDBUF0; -static RegisterWrapper<0x0D80600C> DICMDBUF1; -static RegisterWrapper<0x0D806010> DICMDBUF2; -static RegisterWrapper<0x0D806014> DIMAR; -static RegisterWrapper<0x0D806018> DILENGTH; -static RegisterWrapper<0x0D80601C> DICR; -static RegisterWrapper<0x0D806020> DIIMMBUF; +constexpr u32 ADDRESS_DISR = 0x0D806000; +constexpr u32 ADDRESS_DICVR = 0x0D806004; +constexpr u32 ADDRESS_DICMDBUF0 = 0x0D806008; +constexpr u32 ADDRESS_DICMDBUF1 = 0x0D80600C; +constexpr u32 ADDRESS_DICMDBUF2 = 0x0D806010; +constexpr u32 ADDRESS_DIMAR = 0x0D806014; +constexpr u32 ADDRESS_DILENGTH = 0x0D806018; +constexpr u32 ADDRESS_DICR = 0x0D80601C; +constexpr u32 ADDRESS_DIIMMBUF = 0x0D806020; -static RegisterWrapper<0x0D8000E0> HW_GPIO_OUT; -static RegisterWrapper<0x0D800194> HW_RESETS; +constexpr u32 ADDRESS_HW_GPIO_OUT = 0x0D8000E0; +constexpr u32 ADDRESS_HW_RESETS = 0x0D800194; namespace IOS::HLE { @@ -169,6 +152,7 @@ std::optional DIDevice::StartIOCtl(const IOCtlRequest& reque auto& system = Core::System::GetInstance(); auto& memory = system.GetMemory(); + auto* mmio = memory.GetMMIOMapping(); // DVDInterface's ExecuteCommand handles most of the work for most of these. // The IOCtl callback is used to generate a reply afterwards. @@ -176,14 +160,14 @@ std::optional DIDevice::StartIOCtl(const IOCtlRequest& reque { case DIIoctl::DVDLowInquiry: INFO_LOG_FMT(IOS_DI, "DVDLowInquiry"); - DICMDBUF0 = 0x12000000; - DICMDBUF1 = 0; + mmio->Write(ADDRESS_DICMDBUF0, 0x12000000); + mmio->Write(ADDRESS_DICMDBUF1, 0); return StartDMATransfer(0x20, request); case DIIoctl::DVDLowReadDiskID: INFO_LOG_FMT(IOS_DI, "DVDLowReadDiskID"); - DICMDBUF0 = 0xA8000040; - DICMDBUF1 = 0; - DICMDBUF2 = 0x20; + mmio->Write(ADDRESS_DICMDBUF0, 0xA8000040); + mmio->Write(ADDRESS_DICMDBUF1, 0); + mmio->Write(ADDRESS_DICMDBUF2, 0x20); return StartDMATransfer(0x20, request); // TODO: Include an additional read that happens on Wii discs, or at least // emulate its side effect of disabling DTK configuration @@ -225,7 +209,7 @@ std::optional DIDevice::StartIOCtl(const IOCtlRequest& reque return DIResult::CoverClosed; case DIIoctl::DVDLowGetCoverRegister: { - const u32 dicvr = DICVR; + const u32 dicvr = mmio->Read(ADDRESS_DICVR); DEBUG_LOG_FMT(IOS_DI, "DVDLowGetCoverRegister {:#010x}", dicvr); return WriteIfFits(request, dicvr); } @@ -240,27 +224,27 @@ std::optional DIDevice::StartIOCtl(const IOCtlRequest& reque { const u8 position = memory.Read_U8(request.buffer_in + 7); INFO_LOG_FMT(IOS_DI, "DVDLowReadDvdPhysical: position {:#04x}", position); - DICMDBUF0 = 0xAD000000 | (position << 8); - DICMDBUF1 = 0; - DICMDBUF2 = 0; + mmio->Write(ADDRESS_DICMDBUF0, 0xAD000000 | (position << 8)); + mmio->Write(ADDRESS_DICMDBUF1, 0); + mmio->Write(ADDRESS_DICMDBUF2, 0); return StartDMATransfer(0x800, request); } case DIIoctl::DVDLowReadDvdCopyright: { const u8 position = memory.Read_U8(request.buffer_in + 7); INFO_LOG_FMT(IOS_DI, "DVDLowReadDvdCopyright: position {:#04x}", position); - DICMDBUF0 = 0xAD010000 | (position << 8); - DICMDBUF1 = 0; - DICMDBUF2 = 0; + mmio->Write(ADDRESS_DICMDBUF0, 0xAD010000 | (position << 8)); + mmio->Write(ADDRESS_DICMDBUF1, 0); + mmio->Write(ADDRESS_DICMDBUF2, 0); return StartImmediateTransfer(request); } case DIIoctl::DVDLowReadDvdDiscKey: { const u8 position = memory.Read_U8(request.buffer_in + 7); INFO_LOG_FMT(IOS_DI, "DVDLowReadDvdDiscKey: position {:#04x}", position); - DICMDBUF0 = 0xAD020000 | (position << 8); - DICMDBUF1 = 0; - DICMDBUF2 = 0; + mmio->Write(ADDRESS_DICMDBUF0, 0xAD020000 | (position << 8)); + mmio->Write(ADDRESS_DICMDBUF1, 0); + mmio->Write(ADDRESS_DICMDBUF2, 0); return StartDMATransfer(0x800, request); } case DIIoctl::DVDLowGetLength: @@ -268,7 +252,7 @@ std::optional DIDevice::StartIOCtl(const IOCtlRequest& reque return WriteIfFits(request, m_last_length); case DIIoctl::DVDLowGetImmBuf: { - const u32 diimmbuf = DIIMMBUF; + const u32 diimmbuf = mmio->Read(ADDRESS_DIIMMBUF); INFO_LOG_FMT(IOS_DI, "DVDLowGetImmBuf {:#010x}", diimmbuf); return WriteIfFits(request, diimmbuf); } @@ -303,27 +287,27 @@ std::optional DIDevice::StartIOCtl(const IOCtlRequest& reque const bool spinup = memory.Read_U32(request.buffer_in + 4); // The GPIO *disables* spinning up the drive. Normally handled via syscall 0x4e. - const u32 old_gpio = HW_GPIO_OUT; + const u32 old_gpio = mmio->Read(ADDRESS_HW_GPIO_OUT); if (spinup) - HW_GPIO_OUT = old_gpio & ~static_cast(GPIO::DI_SPIN); + mmio->Write(ADDRESS_HW_GPIO_OUT, old_gpio & ~static_cast(GPIO::DI_SPIN)); else - HW_GPIO_OUT = old_gpio | static_cast(GPIO::DI_SPIN); + mmio->Write(ADDRESS_HW_GPIO_OUT, old_gpio | static_cast(GPIO::DI_SPIN)); // Syscall 0x46 check_di_reset - const bool was_resetting = (HW_RESETS & (1 << 10)) == 0; + const bool was_resetting = (mmio->Read(ADDRESS_HW_RESETS) & (1 << 10)) == 0; if (was_resetting) { // This route will not generally be taken in Dolphin but is included for completeness // Syscall 0x45 deassert_di_reset - HW_RESETS = HW_RESETS | (1 << 10); + mmio->Write(ADDRESS_HW_RESETS, mmio->Read(ADDRESS_HW_RESETS) | (1 << 10)); } else { // Syscall 0x44 assert_di_reset - HW_RESETS = HW_RESETS & ~(1 << 10); + mmio->Write(ADDRESS_HW_RESETS, mmio->Read(ADDRESS_HW_RESETS) & ~(1 << 10)); // Normally IOS sleeps for 12 microseconds here, but we can't easily emulate that // Syscall 0x45 deassert_di_reset - HW_RESETS = HW_RESETS | (1 << 10); + mmio->Write(ADDRESS_HW_RESETS, mmio->Read(ADDRESS_HW_RESETS) | (1 << 10)); } ResetDIRegisters(); return DIResult::Success; @@ -356,14 +340,14 @@ std::optional DIDevice::StartIOCtl(const IOCtlRequest& reque if (range.start <= position && position <= range.end && range.start <= end && end <= range.end) { - DICMDBUF0 = 0xA8000000; - DICMDBUF1 = position; - DICMDBUF2 = length; + mmio->Write(ADDRESS_DICMDBUF0, 0xA8000000); + mmio->Write(ADDRESS_DICMDBUF1, position); + mmio->Write(ADDRESS_DICMDBUF2, length); if (range.is_error_001_range && Config::Get(Config::SESSION_SHOULD_FAKE_ERROR_001)) { - DIMAR = request.buffer_out; + mmio->Write(ADDRESS_DIMAR, request.buffer_out); m_last_length = length; - DILENGTH = length; + mmio->Write(ADDRESS_DILENGTH, length); system.GetDVDInterface().ForceOutOfBoundsRead(DVD::ReplyType::IOS); return {}; } @@ -403,13 +387,13 @@ std::optional DIDevice::StartIOCtl(const IOCtlRequest& reque return DIResult::SecurityError; case DIIoctl::DVDLowGetStatusRegister: { - const u32 disr = DISR; + const u32 disr = mmio->Read(ADDRESS_DISR); INFO_LOG_FMT(IOS_DI, "DVDLowGetStatusRegister: {:#010x}", disr); return WriteIfFits(request, disr); } case DIIoctl::DVDLowGetControlRegister: { - const u32 dicr = DICR; + const u32 dicr = mmio->Read(ADDRESS_DICR); INFO_LOG_FMT(IOS_DI, "DVDLowGetControlRegister: {:#010x}", dicr); return WriteIfFits(request, dicr); } @@ -418,9 +402,9 @@ std::optional DIDevice::StartIOCtl(const IOCtlRequest& reque const u8 param1 = memory.Read_U8(request.buffer_in + 7); const u32 param2 = memory.Read_U32(request.buffer_in + 8); INFO_LOG_FMT(IOS_DI, "DVDLowReportKey: param1 {:#04x}, param2 {:#08x}", param1, param2); - DICMDBUF0 = 0xA4000000 | (param1 << 16); - DICMDBUF1 = param2 & 0xFFFFFF; - DICMDBUF2 = 0; + mmio->Write(ADDRESS_DICMDBUF0, 0xA4000000 | (param1 << 16)); + mmio->Write(ADDRESS_DICMDBUF1, param2 & 0xFFFFFF); + mmio->Write(ADDRESS_DICMDBUF2, 0); return StartDMATransfer(0x20, request); } case DIIoctl::DVDLowSeek: @@ -428,8 +412,8 @@ std::optional DIDevice::StartIOCtl(const IOCtlRequest& reque const u32 position = memory.Read_U32(request.buffer_in + 4); // 32-bit offset INFO_LOG_FMT(IOS_DI, "DVDLowSeek: position {:#010x}, translated to {:#010x}", position, position); // TODO: do partition translation! - DICMDBUF0 = 0xAB000000; - DICMDBUF1 = position; + mmio->Write(ADDRESS_DICMDBUF0, 0xAB000000); + mmio->Write(ADDRESS_DICMDBUF1, position); return StartImmediateTransfer(request, false); } case DIIoctl::DVDLowReadDvd: @@ -440,9 +424,9 @@ std::optional DIDevice::StartIOCtl(const IOCtlRequest& reque const u32 position = memory.Read_U32(request.buffer_in + 16); INFO_LOG_FMT(IOS_DI, "DVDLowReadDvd({}, {}): position {:#08x}, length {:#08x}", flag1, flag2, position, length); - DICMDBUF0 = 0xD0000000 | ((flag1 & 1) << 7) | ((flag2 & 1) << 6); - DICMDBUF1 = position & 0xFFFFFF; - DICMDBUF2 = length & 0xFFFFFF; + mmio->Write(ADDRESS_DICMDBUF0, 0xD0000000 | ((flag1 & 1) << 7) | ((flag2 & 1) << 6)); + mmio->Write(ADDRESS_DICMDBUF1, position & 0xFFFFFF); + mmio->Write(ADDRESS_DICMDBUF2, length & 0xFFFFFF); return StartDMATransfer(0x800 * length, request); } case DIIoctl::DVDLowReadDvdConfig: @@ -451,41 +435,41 @@ std::optional DIDevice::StartIOCtl(const IOCtlRequest& reque const u8 param2 = memory.Read_U8(request.buffer_in + 11); const u32 position = memory.Read_U32(request.buffer_in + 12); INFO_LOG_FMT(IOS_DI, "DVDLowReadDvdConfig({}, {}): position {:#08x}", flag1, param2, position); - DICMDBUF0 = 0xD1000000 | ((flag1 & 1) << 16) | param2; - DICMDBUF1 = position & 0xFFFFFF; - DICMDBUF2 = 0; + mmio->Write(ADDRESS_DICMDBUF0, 0xD1000000 | ((flag1 & 1) << 16) | param2); + mmio->Write(ADDRESS_DICMDBUF1, position & 0xFFFFFF); + mmio->Write(ADDRESS_DICMDBUF2, 0); return StartImmediateTransfer(request); } case DIIoctl::DVDLowStopLaser: INFO_LOG_FMT(IOS_DI, "DVDLowStopLaser"); - DICMDBUF0 = 0xD2000000; + mmio->Write(ADDRESS_DICMDBUF0, 0xD2000000); return StartImmediateTransfer(request); case DIIoctl::DVDLowOffset: { const u8 flag = memory.Read_U8(request.buffer_in + 7); const u32 offset = memory.Read_U32(request.buffer_in + 8); INFO_LOG_FMT(IOS_DI, "DVDLowOffset({}): offset {:#010x}", flag, offset); - DICMDBUF0 = 0xD9000000 | ((flag & 1) << 16); - DICMDBUF1 = offset; + mmio->Write(ADDRESS_DICMDBUF0, 0xD9000000 | ((flag & 1) << 16)); + mmio->Write(ADDRESS_DICMDBUF1, offset); return StartImmediateTransfer(request); } case DIIoctl::DVDLowReadDiskBca: INFO_LOG_FMT(IOS_DI, "DVDLowReadDiskBca"); - DICMDBUF0 = 0xDA000000; + mmio->Write(ADDRESS_DICMDBUF0, 0xDA000000); return StartDMATransfer(0x40, request); case DIIoctl::DVDLowRequestDiscStatus: INFO_LOG_FMT(IOS_DI, "DVDLowRequestDiscStatus"); - DICMDBUF0 = 0xDB000000; + mmio->Write(ADDRESS_DICMDBUF0, 0xDB000000); return StartImmediateTransfer(request); case DIIoctl::DVDLowRequestRetryNumber: INFO_LOG_FMT(IOS_DI, "DVDLowRequestRetryNumber"); - DICMDBUF0 = 0xDC000000; + mmio->Write(ADDRESS_DICMDBUF0, 0xDC000000); return StartImmediateTransfer(request); case DIIoctl::DVDLowSetMaximumRotation: { const u8 speed = memory.Read_U8(request.buffer_in + 7); INFO_LOG_FMT(IOS_DI, "DVDLowSetMaximumRotation: speed {}", speed); - DICMDBUF0 = 0xDD000000 | ((speed & 3) << 16); + mmio->Write(ADDRESS_DICMDBUF0, 0xDD000000 | ((speed & 3) << 16)); return StartImmediateTransfer(request, false); } case DIIoctl::DVDLowSerMeasControl: @@ -493,12 +477,12 @@ std::optional DIDevice::StartIOCtl(const IOCtlRequest& reque const u8 flag1 = memory.Read_U8(request.buffer_in + 7); const u8 flag2 = memory.Read_U8(request.buffer_in + 11); INFO_LOG_FMT(IOS_DI, "DVDLowSerMeasControl({}, {})", flag1, flag2); - DICMDBUF0 = 0xDF000000 | ((flag1 & 1) << 17) | ((flag2 & 1) << 16); + mmio->Write(ADDRESS_DICMDBUF0, 0xDF000000 | ((flag1 & 1) << 17) | ((flag2 & 1) << 16)); return StartDMATransfer(0x20, request); } case DIIoctl::DVDLowRequestError: INFO_LOG_FMT(IOS_DI, "DVDLowRequestError"); - DICMDBUF0 = 0xE0000000; + mmio->Write(ADDRESS_DICMDBUF0, 0xE0000000); return StartImmediateTransfer(request); case DIIoctl::DVDLowAudioStream: { @@ -507,17 +491,17 @@ std::optional DIDevice::StartIOCtl(const IOCtlRequest& reque const u32 position = memory.Read_U32(request.buffer_in + 12); INFO_LOG_FMT(IOS_DI, "DVDLowAudioStream({}): offset {:#010x} (byte {:#011x}), length {:#x}", mode, position, static_cast(position) << 2, length); - DICMDBUF0 = 0xE1000000 | ((mode & 3) << 16); - DICMDBUF1 = position; - DICMDBUF2 = length; + mmio->Write(ADDRESS_DICMDBUF0, 0xE1000000 | ((mode & 3) << 16)); + mmio->Write(ADDRESS_DICMDBUF1, position); + mmio->Write(ADDRESS_DICMDBUF2, length); return StartImmediateTransfer(request, false); } case DIIoctl::DVDLowRequestAudioStatus: { const u8 mode = memory.Read_U8(request.buffer_in + 7); INFO_LOG_FMT(IOS_DI, "DVDLowRequestAudioStatus({})", mode); - DICMDBUF0 = 0xE2000000 | ((mode & 3) << 16); - DICMDBUF1 = 0; + mmio->Write(ADDRESS_DICMDBUF0, 0xE2000000 | ((mode & 3) << 16)); + mmio->Write(ADDRESS_DICMDBUF1, 0); // Note that this command does not copy the value written to DIIMMBUF, which makes it rather // useless (to actually use it, DVDLowGetImmBuf would need to be used afterwards) return StartImmediateTransfer(request, false); @@ -527,8 +511,8 @@ std::optional DIDevice::StartIOCtl(const IOCtlRequest& reque const u8 eject = memory.Read_U8(request.buffer_in + 7); const u8 kill = memory.Read_U8(request.buffer_in + 11); INFO_LOG_FMT(IOS_DI, "DVDLowStopMotor({}, {})", eject, kill); - DICMDBUF0 = 0xE3000000 | ((eject & 1) << 17) | ((kill & 1) << 20); - DICMDBUF1 = 0; + mmio->Write(ADDRESS_DICMDBUF0, 0xE3000000 | ((eject & 1) << 17) | ((kill & 1) << 20)); + mmio->Write(ADDRESS_DICMDBUF1, 0); return StartImmediateTransfer(request); } case DIIoctl::DVDLowAudioBufferConfig: @@ -537,8 +521,8 @@ std::optional DIDevice::StartIOCtl(const IOCtlRequest& reque const u8 buffer_size = memory.Read_U8(request.buffer_in + 11); INFO_LOG_FMT(IOS_DI, "DVDLowAudioBufferConfig: {}, buffer size {}", enable ? "enabled" : "disabled", buffer_size); - DICMDBUF0 = 0xE4000000 | ((enable & 1) << 16) | (buffer_size & 0xf); - DICMDBUF1 = 0; + mmio->Write(ADDRESS_DICMDBUF0, 0xE4000000 | ((enable & 1) << 16) | (buffer_size & 0xf)); + mmio->Write(ADDRESS_DICMDBUF1, 0); // On the other hand, this command *does* copy DIIMMBUF, but the actual code in the drive never // writes anything to it, so it just copies over a stale value (e.g. from DVDLowRequestError). return StartImmediateTransfer(request); @@ -577,11 +561,13 @@ std::optional DIDevice::StartDMATransfer(u32 command_length, return DIResult::BadArgument; } - DIMAR = request.buffer_out; + auto& system = Core::System::GetInstance(); + auto* mmio = system.GetMemory().GetMMIOMapping(); + mmio->Write(ADDRESS_DIMAR, request.buffer_out); m_last_length = command_length; - DILENGTH = command_length; + mmio->Write(ADDRESS_DILENGTH, command_length); - Core::System::GetInstance().GetDVDInterface().ExecuteCommand(DVD::ReplyType::IOS); + system.GetDVDInterface().ExecuteCommand(DVD::ReplyType::IOS); // Reply will be posted when done by FinishIOCtl. return {}; } @@ -665,10 +651,11 @@ void DIDevice::FinishDICommand(DIResult result) auto& system = Core::System::GetInstance(); auto& memory = system.GetMemory(); + auto* mmio = memory.GetMMIOMapping(); IOCtlRequest request{m_executing_command->m_request_address}; if (m_executing_command->m_copy_diimmbuf) - memory.Write_U32(DIIMMBUF, request.buffer_out); + memory.Write_U32(mmio->Read(ADDRESS_DIIMMBUF), request.buffer_out); m_ios.EnqueueIPCReply(request, static_cast(result)); diff --git a/Source/Core/Core/IOS/FS/FileSystem.h b/Source/Core/Core/IOS/FS/FileSystem.h index 6b1d7ddf78..581df6fbee 100644 --- a/Source/Core/Core/IOS/FS/FileSystem.h +++ b/Source/Core/Core/IOS/FS/FileSystem.h @@ -134,10 +134,13 @@ struct FileStatus constexpr size_t MaxPathDepth = 8; /// The maximum number of characters a path can have. constexpr size_t MaxPathLength = 64; +/// The maximum number of characters a filename can have. +constexpr size_t MaxFilenameLength = 12; /// Returns whether a Wii path is valid. bool IsValidPath(std::string_view path); bool IsValidNonRootPath(std::string_view path); +bool IsValidFilename(std::string_view filename); struct SplitPathResult { diff --git a/Source/Core/Core/IOS/FS/FileSystemCommon.cpp b/Source/Core/Core/IOS/FS/FileSystemCommon.cpp index 8d246157bb..1ec5dbe068 100644 --- a/Source/Core/Core/IOS/FS/FileSystemCommon.cpp +++ b/Source/Core/Core/IOS/FS/FileSystemCommon.cpp @@ -3,6 +3,8 @@ #include "Core/IOS/FS/FileSystem.h" +#include + #include "Common/Assert.h" #include "Common/FileUtil.h" #include "Core/IOS/Device.h" @@ -21,6 +23,12 @@ bool IsValidNonRootPath(std::string_view path) path.back() != '/'; } +bool IsValidFilename(std::string_view filename) +{ + return filename.length() <= MaxFilenameLength && + !std::any_of(filename.begin(), filename.end(), [](char c) { return c == '/'; }); +} + SplitPathResult SplitPathAndBasename(std::string_view path) { const auto last_separator = path.rfind('/'); diff --git a/Source/Core/Core/IOS/FS/HostBackend/FS.cpp b/Source/Core/Core/IOS/FS/HostBackend/FS.cpp index 2b2cf16be1..991f1353d2 100644 --- a/Source/Core/Core/IOS/FS/HostBackend/FS.cpp +++ b/Source/Core/Core/IOS/FS/HostBackend/FS.cpp @@ -4,6 +4,7 @@ #include "Core/IOS/FS/HostBackend/FS.h" #include +#include #include #include #include @@ -11,6 +12,7 @@ #include +#include "Common/Align.h" #include "Common/Assert.h" #include "Common/ChunkFile.h" #include "Common/FileUtil.h" @@ -27,6 +29,21 @@ namespace IOS::HLE::FS { constexpr u32 BUFFER_CHUNK_SIZE = 65536; +// size of a single cluster in the NAND +constexpr u16 CLUSTER_SIZE = 16384; + +// total number of clusters available in the NAND +constexpr u16 TOTAL_CLUSTERS = 0x7ec0; + +// number of clusters reserved for bad blocks and similar, not accessible to normal writes +constexpr u16 RESERVED_CLUSTERS = 0x0300; + +// number of clusters actually usable by the file system +constexpr u16 USABLE_CLUSTERS = TOTAL_CLUSTERS - RESERVED_CLUSTERS; + +// total number of inodes available in the NAND +constexpr u16 TOTAL_INODES = 0x17ff; + HostFileSystem::HostFilename HostFileSystem::BuildFilename(const std::string& wii_path) const { for (const auto& redirect : m_nand_redirects) @@ -47,21 +64,6 @@ HostFileSystem::HostFilename HostFileSystem::BuildFilename(const std::string& wi return HostFilename{m_root_path, false}; } -// Get total filesize of contents of a directory (recursive) -// Only used for ES_GetUsage atm, could be useful elsewhere? -static u64 ComputeTotalFileSize(const File::FSTEntry& parent_entry) -{ - u64 sizeOfFiles = 0; - for (const File::FSTEntry& entry : parent_entry.children) - { - if (entry.isDirectory) - sizeOfFiles += ComputeTotalFileSize(entry); - else - sizeOfFiles += entry.size; - } - return sizeOfFiles; -} - namespace { struct SerializedFstEntry @@ -102,6 +104,45 @@ auto GetNamePredicate(const std::string& name) { return [&name](const auto& entry) { return entry.name == name; }; } + +// Convert the host directory entries into ones that can be exposed to the emulated system. +static u64 FixupDirectoryEntries(File::FSTEntry* dir, bool is_root) +{ + u64 removed_entries = 0; + for (auto it = dir->children.begin(); it != dir->children.end();) + { + // Drop files in the root of the Wii NAND folder, since we store extra files there that the + // emulated system shouldn't know about. + if (is_root && !it->isDirectory) + { + ++removed_entries; + it = dir->children.erase(it); + continue; + } + + // Decode escaped invalid file system characters so that games (such as Harry Potter and the + // Half-Blood Prince) can find what they expect. + if (it->virtualName.find("__") != std::string::npos) + it->virtualName = Common::UnescapeFileName(it->virtualName); + + // Drop files that have too long filenames. + if (!IsValidFilename(it->virtualName)) + { + if (it->isDirectory) + removed_entries += it->size; + ++removed_entries; + it = dir->children.erase(it); + continue; + } + + if (dir->isDirectory) + removed_entries += FixupDirectoryEntries(&*it, false); + + ++it; + } + dir->size -= removed_entries; + return removed_entries; +} } // namespace bool HostFileSystem::FstEntry::CheckPermission(Uid caller_uid, Gid caller_gid, @@ -645,12 +686,7 @@ Result> HostFileSystem::ReadDirectory(Uid uid, Gid gid, const std::string host_path = BuildFilename(path).host_path; File::FSTEntry host_entry = File::ScanDirectoryTree(host_path, false); - for (File::FSTEntry& child : host_entry.children) - { - // Decode escaped invalid file system characters so that games (such as - // Harry Potter and the Half-Blood Prince) can find what they expect. - child.virtualName = Common::UnescapeFileName(child.virtualName); - } + FixupDirectoryEntries(&host_entry, path == "/"); // Sort files according to their order in the FST tree (issue 10234). // The result should look like this: @@ -747,19 +783,33 @@ ResultCode HostFileSystem::SetMetadata(Uid caller_uid, const std::string& path, return ResultCode::Success; } +static u64 ComputeUsedClusters(const File::FSTEntry& parent_entry) +{ + u64 clusters = 0; + for (const File::FSTEntry& entry : parent_entry.children) + { + if (entry.isDirectory) + clusters += ComputeUsedClusters(entry); + else + clusters += Common::AlignUp(entry.size, CLUSTER_SIZE) / CLUSTER_SIZE; + } + return clusters; +} + Result HostFileSystem::GetNandStats() { - WARN_LOG_FMT(IOS_FS, "GET STATS - returning static values for now"); + const auto root_stats = GetDirectoryStats("/"); + if (!root_stats) + return root_stats.Error(); // TODO: is this right? can this fail on hardware? - // TODO: scrape the real amounts from somewhere... NandStats stats{}; - stats.cluster_size = 0x4000; - stats.free_clusters = 0x5DEC; - stats.used_clusters = 0x1DD4; - stats.bad_clusters = 0x10; - stats.reserved_clusters = 0x02F0; - stats.free_inodes = 0x146B; - stats.used_inodes = 0x0394; + stats.cluster_size = CLUSTER_SIZE; + stats.free_clusters = USABLE_CLUSTERS - root_stats->used_clusters; + stats.used_clusters = root_stats->used_clusters; + stats.bad_clusters = 0; + stats.reserved_clusters = RESERVED_CLUSTERS; + stats.free_inodes = TOTAL_INODES - root_stats->used_inodes; + stats.used_inodes = root_stats->used_inodes; return stats; } @@ -771,19 +821,25 @@ Result HostFileSystem::GetDirectoryStats(const std::string& wii_ DirectoryStats stats{}; std::string path(BuildFilename(wii_path).host_path); - if (File::IsDirectory(path)) + File::FileInfo info(path); + if (!info.Exists()) + { + return ResultCode::NotFound; + } + if (info.IsDirectory()) { File::FSTEntry parent_dir = File::ScanDirectoryTree(path, true); + FixupDirectoryEntries(&parent_dir, wii_path == "/"); + // add one for the folder itself - stats.used_inodes = 1 + (u32)parent_dir.size; + stats.used_inodes = static_cast(std::min(1 + parent_dir.size, TOTAL_INODES)); - u64 total_size = ComputeTotalFileSize(parent_dir); // "Real" size to convert to nand blocks - - stats.used_clusters = (u32)(total_size / (16 * 1024)); // one block is 16kb + const u64 clusters = ComputeUsedClusters(parent_dir); + stats.used_clusters = static_cast(std::min(clusters, USABLE_CLUSTERS)); } else { - WARN_LOG_FMT(IOS_FS, "fsBlock failed, cannot find directory: {}", path); + return ResultCode::Invalid; } return stats; } diff --git a/Source/Core/Core/IOS/IOS.cpp b/Source/Core/Core/IOS/IOS.cpp index 9f9478dc71..82f51dac33 100644 --- a/Source/Core/Core/IOS/IOS.cpp +++ b/Source/Core/Core/IOS/IOS.cpp @@ -200,8 +200,9 @@ static void ResetAndPausePPC() auto& system = Core::System::GetInstance(); auto& memory = system.GetMemory(); memory.Write_U32(0x48000000, 0x00000000); // b 0x0 - PowerPC::Reset(); - system.GetPPCState().pc = 0; + auto& power_pc = system.GetPowerPC(); + power_pc.Reset(); + power_pc.GetPPCState().pc = 0; } static void ReleasePPC() diff --git a/Source/Core/Core/IOS/MIOS.cpp b/Source/Core/Core/IOS/MIOS.cpp index ecd7a992a4..52fcb553c2 100644 --- a/Source/Core/Core/IOS/MIOS.cpp +++ b/Source/Core/Core/IOS/MIOS.cpp @@ -43,7 +43,7 @@ static void ReinitHardware() // (and not by MIOS), causing games that use DTK to break. Perhaps MIOS doesn't actually // reset DI fully, in such a way that the DTK config isn't cleared? // system.GetDVDInterface().ResetDrive(true); - PowerPC::Reset(); + system.GetPowerPC().Reset(); Wiimote::ResetAllWiimotes(); // Note: this is specific to Dolphin and is required because we initialised it in Wii mode. auto& dsp = system.GetDSP(); @@ -83,18 +83,18 @@ bool Load() Host_NotifyMapLoaded(); } - auto& ppc_state = system.GetPPCState(); - const PowerPC::CoreMode core_mode = PowerPC::GetMode(); - PowerPC::SetMode(PowerPC::CoreMode::Interpreter); - ppc_state.msr.Hex = 0; - ppc_state.pc = 0x3400; + auto& power_pc = system.GetPowerPC(); + const PowerPC::CoreMode core_mode = power_pc.GetMode(); + power_pc.SetMode(PowerPC::CoreMode::Interpreter); + power_pc.GetPPCState().msr.Hex = 0; + power_pc.GetPPCState().pc = 0x3400; NOTICE_LOG_FMT(IOS, "Loaded MIOS and bootstrapped PPC."); // IOS writes 0 to 0x30f8 before bootstrapping the PPC. Once started, the IPL eventually writes // 0xdeadbeef there, then waits for it to be cleared by IOS before continuing. while (memory.Read_U32(ADDRESS_INIT_SEMAPHORE) != 0xdeadbeef) - PowerPC::SingleStep(); - PowerPC::SetMode(core_mode); + power_pc.SingleStep(); + power_pc.SetMode(core_mode); memory.Write_U32(0x00000000, ADDRESS_INIT_SEMAPHORE); NOTICE_LOG_FMT(IOS, "IPL ready."); diff --git a/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp b/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp index 8c5f80b6d4..cc1469bdfa 100644 --- a/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp +++ b/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp @@ -233,6 +233,7 @@ NWC24::ErrorCode NetKDRequestDevice::KDDownload(const u16 entry_index, IPCReply NetKDRequestDevice::HandleNWC24DownloadNowEx(const IOCtlRequest& request) { + m_dl_list.ReadDlList(); auto& system = Core::System::GetInstance(); auto& memory = system.GetMemory(); const u32 flags = memory.Read_U32(request.buffer_in); diff --git a/Source/Core/Core/IOS/Network/SSL.cpp b/Source/Core/Core/IOS/Network/SSL.cpp index 524f2b81e8..a26d2451db 100644 --- a/Source/Core/Core/IOS/Network/SSL.cpp +++ b/Source/Core/Core/IOS/Network/SSL.cpp @@ -63,7 +63,10 @@ int SSLSendWithoutSNI(void* ctx, const unsigned char* buf, size_t len) // Log raw SSL packets if we don't dump unencrypted SSL writes if (!Config::Get(Config::MAIN_NETWORK_SSL_DUMP_WRITE) && ret > 0) - PowerPC::debug_interface.NetworkLogger()->LogWrite(buf, ret, *fd, nullptr); + { + Core::System::GetInstance().GetPowerPC().GetDebugInterface().NetworkLogger()->LogWrite( + buf, ret, *fd, nullptr); + } return ret; } @@ -76,7 +79,10 @@ int SSLRecv(void* ctx, unsigned char* buf, size_t len) // Log raw SSL packets if we don't dump unencrypted SSL reads if (!Config::Get(Config::MAIN_NETWORK_SSL_DUMP_READ) && ret > 0) - PowerPC::debug_interface.NetworkLogger()->LogRead(buf, ret, *fd, nullptr); + { + Core::System::GetInstance().GetPowerPC().GetDebugInterface().NetworkLogger()->LogRead( + buf, ret, *fd, nullptr); + } return ret; } diff --git a/Source/Core/Core/IOS/Network/Socket.cpp b/Source/Core/Core/IOS/Network/Socket.cpp index a1fe3d6a27..ff60c09b20 100644 --- a/Source/Core/Core/IOS/Network/Socket.cpp +++ b/Source/Core/Core/IOS/Network/Socket.cpp @@ -487,8 +487,8 @@ void WiiSocket::Update(bool read, bool write, bool except) if (ret >= 0) { - PowerPC::debug_interface.NetworkLogger()->LogSSLWrite(memory.GetPointer(BufferOut2), - ret, ssl->hostfd); + system.GetPowerPC().GetDebugInterface().NetworkLogger()->LogSSLWrite( + memory.GetPointer(BufferOut2), ret, ssl->hostfd); // Return bytes written or SSL_ERR_ZERO if none WriteReturnValue((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn); } @@ -521,8 +521,8 @@ void WiiSocket::Update(bool read, bool write, bool except) if (ret >= 0) { - PowerPC::debug_interface.NetworkLogger()->LogSSLRead(memory.GetPointer(BufferIn2), - ret, ssl->hostfd); + system.GetPowerPC().GetDebugInterface().NetworkLogger()->LogSSLRead( + memory.GetPointer(BufferIn2), ret, ssl->hostfd); // Return bytes read or SSL_ERR_ZERO if none WriteReturnValue((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn); } @@ -595,7 +595,7 @@ void WiiSocket::Update(bool read, bool write, bool except) const int ret = sendto(fd, data, BufferInSize, flags, to, tolen); ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_SENDTO", true); if (ret > 0) - PowerPC::debug_interface.NetworkLogger()->LogWrite(data, ret, fd, to); + system.GetPowerPC().GetDebugInterface().NetworkLogger()->LogWrite(data, ret, fd, to); INFO_LOG_FMT(IOS_NET, "{} = {} Socket: {:08x}, BufferIn: ({:08x}, {}), BufferIn2: ({:08x}, {}), " @@ -654,7 +654,7 @@ void WiiSocket::Update(bool read, bool write, bool except) ReturnValue = WiiSockMan::GetNetErrorCode(ret, BufferOutSize2 ? "SO_RECVFROM" : "SO_RECV", true); if (ret > 0) - PowerPC::debug_interface.NetworkLogger()->LogRead(data, ret, fd, from); + system.GetPowerPC().GetDebugInterface().NetworkLogger()->LogRead(data, ret, fd, from); INFO_LOG_FMT(IOS_NET, "{}({}, {}) Socket: {:08X}, Flags: {:08X}, " @@ -865,7 +865,7 @@ s32 WiiSockMan::AddSocket(s32 fd, bool is_rw) WiiSocket& sock = WiiSockets[wii_fd]; sock.SetFd(fd); sock.SetWiiFd(wii_fd); - PowerPC::debug_interface.NetworkLogger()->OnNewSocket(fd); + Core::System::GetInstance().GetPowerPC().GetDebugInterface().NetworkLogger()->OnNewSocket(fd); #ifdef __APPLE__ int opt_no_sigpipe = 1; diff --git a/Source/Core/Core/IOS/USB/USB_HID/HIDv4.cpp b/Source/Core/Core/IOS/USB/USB_HID/HIDv4.cpp index 62e8ec2987..610194ddfd 100644 --- a/Source/Core/Core/IOS/USB/USB_HID/HIDv4.cpp +++ b/Source/Core/Core/IOS/USB/USB_HID/HIDv4.cpp @@ -103,7 +103,7 @@ std::optional USB_HIDv4::GetDeviceChange(const IOCtlRequest& request) IPCReply USB_HIDv4::Shutdown(const IOCtlRequest& request) { std::lock_guard lk{m_devicechange_hook_address_mutex}; - if (m_devicechange_hook_request != 0) + if (m_devicechange_hook_request != nullptr) { auto& system = Core::System::GetInstance(); auto& memory = system.GetMemory(); diff --git a/Source/Core/Core/IOS/USB/USB_KBD.cpp b/Source/Core/Core/IOS/USB/USB_KBD.cpp index 35e34b07fc..5dcdb109c0 100644 --- a/Source/Core/Core/IOS/USB/USB_KBD.cpp +++ b/Source/Core/Core/IOS/USB/USB_KBD.cpp @@ -191,7 +191,7 @@ USB_KBD::USB_KBD(Kernel& ios, const std::string& device_name) : Device(ios, devi std::optional USB_KBD::Open(const OpenRequest& request) { INFO_LOG_FMT(IOS, "USB_KBD: Open"); - IniFile ini; + Common::IniFile ini; ini.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX)); ini.GetOrCreateSection("USB Keyboard")->Get("Layout", &m_keyboard_layout, KBD_LAYOUT_QWERTY); diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp index db5027fd08..56c6f08aa5 100644 --- a/Source/Core/Core/NetPlayClient.cpp +++ b/Source/Core/Core/NetPlayClient.cpp @@ -23,7 +23,7 @@ #include "Common/CommonPaths.h" #include "Common/CommonTypes.h" #include "Common/Crypto/SHA1.h" -#include "Common/ENetUtil.h" +#include "Common/ENet.h" #include "Common/FileUtil.h" #include "Common/Logging/Log.h" #include "Common/MsgHandler.h" @@ -168,7 +168,7 @@ NetPlayClient::NetPlayClient(const std::string& address, const u16 port, NetPlay { if (Connect()) { - m_client->intercept = ENetUtil::InterceptCallback; + m_client->intercept = Common::ENet::InterceptCallback; m_thread = std::thread(&NetPlayClient::ThreadFunc, this); } } @@ -254,7 +254,8 @@ bool NetPlayClient::Connect() // TODO: make this not hang ENetEvent netEvent; int net; - while ((net = enet_host_service(m_client, &netEvent, 5000)) > 0 && netEvent.type == 42) + while ((net = enet_host_service(m_client, &netEvent, 5000)) > 0 && + netEvent.type == ENetEventType(42)) // See PR #11381 and ENetUtil::InterceptCallback { // ignore packets from traversal server } @@ -1522,7 +1523,7 @@ void NetPlayClient::OnGameDigestAbort() void NetPlayClient::Send(const sf::Packet& packet, const u8 channel_id) { - ENetUtil::SendPacket(m_server, packet, channel_id); + Common::ENet::SendPacket(m_server, packet, channel_id); } void NetPlayClient::DisplayPlayersPing() @@ -1577,7 +1578,7 @@ void NetPlayClient::SendAsync(sf::Packet&& packet, const u8 channel_id) std::lock_guard lkq(m_crit.async_queue_write); m_async_queue.Push(AsyncQueueEntry{std::move(packet), channel_id}); } - ENetUtil::WakeupThread(m_client); + Common::ENet::WakeupThread(m_client); } // called from ---NETPLAY--- thread diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index 483ead7218..8108b124ee 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -20,7 +20,7 @@ #include #include "Common/CommonPaths.h" -#include "Common/ENetUtil.h" +#include "Common/ENet.h" #include "Common/FileUtil.h" #include "Common/HttpRequest.h" #include "Common/Logging/Log.h" @@ -111,7 +111,7 @@ NetPlayServer::~NetPlayServer() } #ifdef USE_UPNP - UPnP::StopPortmapping(); + Common::UPnP::StopPortmapping(); #endif } @@ -153,7 +153,7 @@ NetPlayServer::NetPlayServer(const u16 port, const bool forward_port, NetPlayUI* if (m_server != nullptr) { m_server->mtu = std::min(m_server->mtu, NetPlay::MAX_ENET_MTU); - m_server->intercept = ENetUtil::InterceptCallback; + m_server->intercept = Common::ENet::InterceptCallback; } SetupIndex(); @@ -168,7 +168,7 @@ NetPlayServer::NetPlayServer(const u16 port, const bool forward_port, NetPlayUI* #ifdef USE_UPNP if (forward_port) - UPnP::TryPortmapping(port); + Common::UPnP::TryPortmapping(port); #endif } } @@ -701,7 +701,7 @@ void NetPlayServer::SendAsync(sf::Packet&& packet, const PlayerId pid, const u8 std::lock_guard lkq(m_crit.async_queue_write); m_async_queue.Push(AsyncQueueEntry{std::move(packet), pid, TargetMode::Only, channel_id}); } - ENetUtil::WakeupThread(m_server); + Common::ENet::WakeupThread(m_server); } void NetPlayServer::SendAsyncToClients(sf::Packet&& packet, const PlayerId skip_pid, @@ -712,7 +712,7 @@ void NetPlayServer::SendAsyncToClients(sf::Packet&& packet, const PlayerId skip_ m_async_queue.Push( AsyncQueueEntry{std::move(packet), skip_pid, TargetMode::AllExcept, channel_id}); } - ENetUtil::WakeupThread(m_server); + Common::ENet::WakeupThread(m_server); } void NetPlayServer::SendChunked(sf::Packet&& packet, const PlayerId pid, const std::string& title) @@ -2027,10 +2027,10 @@ bool NetPlayServer::SyncCodes() // Find all INI files const auto game_id = game->GetGameID(); const auto revision = game->GetRevision(); - IniFile globalIni; + Common::IniFile globalIni; for (const std::string& filename : ConfigLoaders::GetGameIniFilenames(game_id, revision)) globalIni.Load(File::GetSysDirectory() + GAMESETTINGS_DIR DIR_SEP + filename, true); - IniFile localIni; + Common::IniFile localIni; for (const std::string& filename : ConfigLoaders::GetGameIniFilenames(game_id, revision)) localIni.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + filename, true); @@ -2183,7 +2183,7 @@ void NetPlayServer::SendToClients(const sf::Packet& packet, const PlayerId skip_ void NetPlayServer::Send(ENetPeer* socket, const sf::Packet& packet, const u8 channel_id) { - ENetUtil::SendPacket(socket, packet, channel_id); + Common::ENet::SendPacket(socket, packet, channel_id); } void NetPlayServer::KickPlayer(PlayerId player) @@ -2266,8 +2266,7 @@ u16 NetPlayServer::GetPort() const std::unordered_set NetPlayServer::GetInterfaceSet() const { std::unordered_set result; - auto lst = GetInterfaceListInternal(); - for (auto list_entry : lst) + for (const auto& list_entry : GetInterfaceListInternal()) result.emplace(list_entry.first); return result; } diff --git a/Source/Core/Core/PatchEngine.cpp b/Source/Core/Core/PatchEngine.cpp index b39339c1cd..c0c6c72bfd 100644 --- a/Source/Core/Core/PatchEngine.cpp +++ b/Source/Core/Core/PatchEngine.cpp @@ -102,11 +102,9 @@ std::string SerializeLine(const PatchEntry& entry) } void LoadPatchSection(const std::string& section, std::vector* patches, - const IniFile& globalIni, const IniFile& localIni) + const Common::IniFile& globalIni, const Common::IniFile& localIni) { - const IniFile* inis[2] = {&globalIni, &localIni}; - - for (const IniFile* ini : inis) + for (const auto* ini : {&globalIni, &localIni}) { std::vector lines; Patch currentPatch; @@ -152,7 +150,7 @@ void LoadPatchSection(const std::string& section, std::vector* patches, } } -void SavePatchSection(IniFile* local_ini, const std::vector& patches) +void SavePatchSection(Common::IniFile* local_ini, const std::vector& patches) { std::vector lines; std::vector lines_enabled; @@ -177,7 +175,7 @@ void SavePatchSection(IniFile* local_ini, const std::vector& patches) local_ini->SetLines("OnFrame", lines); } -static void LoadSpeedhacks(const std::string& section, IniFile& ini) +static void LoadSpeedhacks(const std::string& section, Common::IniFile& ini) { std::vector keys; ini.GetKeys(section, &keys); @@ -211,9 +209,10 @@ int GetSpeedhackCycles(const u32 addr) void LoadPatches() { - IniFile merged = SConfig::GetInstance().LoadGameIni(); - IniFile globalIni = SConfig::GetInstance().LoadDefaultGameIni(); - IniFile localIni = SConfig::GetInstance().LoadLocalGameIni(); + const auto& sconfig = SConfig::GetInstance(); + Common::IniFile merged = sconfig.LoadGameIni(); + Common::IniFile globalIni = sconfig.LoadDefaultGameIni(); + Common::IniFile localIni = sconfig.LoadLocalGameIni(); LoadPatchSection("OnFrame", &s_on_frame, globalIni, localIni); @@ -278,7 +277,7 @@ static void ApplyMemoryPatches(const Core::CPUThreadGuard& guard, std::lock_guard lock(s_on_frame_memory_mutex); for (std::size_t index : memory_patch_indices) { - PowerPC::debug_interface.ApplyExistingPatch(guard, index); + guard.GetSystem().GetPowerPC().GetDebugInterface().ApplyExistingPatch(guard, index); } } diff --git a/Source/Core/Core/PatchEngine.h b/Source/Core/Core/PatchEngine.h index 4218e65fcb..9232e4b099 100644 --- a/Source/Core/Core/PatchEngine.h +++ b/Source/Core/Core/PatchEngine.h @@ -9,7 +9,10 @@ #include "Common/CommonTypes.h" +namespace Common +{ class IniFile; +} namespace PatchEngine { @@ -47,8 +50,8 @@ int GetSpeedhackCycles(const u32 addr); std::optional DeserializeLine(std::string line); std::string SerializeLine(const PatchEntry& entry); void LoadPatchSection(const std::string& section, std::vector* patches, - const IniFile& globalIni, const IniFile& localIni); -void SavePatchSection(IniFile* local_ini, const std::vector& patches); + const Common::IniFile& globalIni, const Common::IniFile& localIni); +void SavePatchSection(Common::IniFile* local_ini, const std::vector& patches); void LoadPatches(); void AddMemoryPatch(std::size_t index); diff --git a/Source/Core/Core/PowerPC/BreakPoints.cpp b/Source/Core/Core/PowerPC/BreakPoints.cpp index fd30da2b91..c4555c7569 100644 --- a/Source/Core/Core/PowerPC/BreakPoints.cpp +++ b/Source/Core/Core/PowerPC/BreakPoints.cpp @@ -16,8 +16,15 @@ #include "Core/PowerPC/Expression.h" #include "Core/PowerPC/JitInterface.h" #include "Core/PowerPC/MMU.h" +#include "Core/PowerPC/PowerPC.h" #include "Core/System.h" +BreakPoints::BreakPoints(Core::System& system) : m_system(system) +{ +} + +BreakPoints::~BreakPoints() = default; + bool BreakPoints::IsAddressBreakPoint(u32 address) const { return std::any_of(m_breakpoints.begin(), m_breakpoints.end(), @@ -106,7 +113,7 @@ void BreakPoints::Add(TBreakPoint bp) if (IsAddressBreakPoint(bp.address)) return; - Core::System::GetInstance().GetJitInterface().InvalidateICache(bp.address, 4, true); + m_system.GetJitInterface().InvalidateICache(bp.address, 4, true); m_breakpoints.emplace_back(std::move(bp)); } @@ -142,7 +149,7 @@ void BreakPoints::Add(u32 address, bool temp, bool break_on_hit, bool log_on_hit m_breakpoints.emplace_back(std::move(bp)); } - Core::System::GetInstance().GetJitInterface().InvalidateICache(address, 4, true); + m_system.GetJitInterface().InvalidateICache(address, 4, true); } bool BreakPoints::ToggleBreakPoint(u32 address) @@ -166,14 +173,14 @@ void BreakPoints::Remove(u32 address) return; m_breakpoints.erase(iter); - Core::System::GetInstance().GetJitInterface().InvalidateICache(address, 4, true); + m_system.GetJitInterface().InvalidateICache(address, 4, true); } void BreakPoints::Clear() { for (const TBreakPoint& bp : m_breakpoints) { - Core::System::GetInstance().GetJitInterface().InvalidateICache(bp.address, 4, true); + m_system.GetJitInterface().InvalidateICache(bp.address, 4, true); } m_breakpoints.clear(); @@ -186,7 +193,7 @@ void BreakPoints::ClearAllTemporary() { if (bp->is_temporary) { - Core::System::GetInstance().GetJitInterface().InvalidateICache(bp->address, 4, true); + m_system.GetJitInterface().InvalidateICache(bp->address, 4, true); bp = m_breakpoints.erase(bp); } else @@ -196,6 +203,12 @@ void BreakPoints::ClearAllTemporary() } } +MemChecks::MemChecks(Core::System& system) : m_system(system) +{ +} + +MemChecks::~MemChecks() = default; + MemChecks::TMemChecksStr MemChecks::GetStrings() const { TMemChecksStr mc_strings; @@ -279,8 +292,8 @@ void MemChecks::Add(TMemCheck memory_check) // If this is the first one, clear the JIT cache so it can switch to // watchpoint-compatible code. if (!had_any) - Core::System::GetInstance().GetJitInterface().ClearCache(); - Core::System::GetInstance().GetMMU().DBATUpdated(); + m_system.GetJitInterface().ClearCache(); + m_system.GetMMU().DBATUpdated(); }); } @@ -308,8 +321,8 @@ void MemChecks::Remove(u32 address) Core::RunAsCPUThread([&] { m_mem_checks.erase(iter); if (!HasAny()) - Core::System::GetInstance().GetJitInterface().ClearCache(); - Core::System::GetInstance().GetMMU().DBATUpdated(); + m_system.GetJitInterface().ClearCache(); + m_system.GetMMU().DBATUpdated(); }); } @@ -317,8 +330,8 @@ void MemChecks::Clear() { Core::RunAsCPUThread([&] { m_mem_checks.clear(); - Core::System::GetInstance().GetJitInterface().ClearCache(); - Core::System::GetInstance().GetMMU().DBATUpdated(); + m_system.GetJitInterface().ClearCache(); + m_system.GetMMU().DBATUpdated(); }); } @@ -352,14 +365,14 @@ bool MemChecks::OverlapsMemcheck(u32 address, u32 length) const }); } -bool TMemCheck::Action(Common::DebugInterface* debug_interface, u64 value, u32 addr, bool write, - size_t size, u32 pc) +bool TMemCheck::Action(Core::System& system, Common::DebugInterface* debug_interface, u64 value, + u32 addr, bool write, size_t size, u32 pc) { if (!is_enabled) return false; if (((write && is_break_on_write) || (!write && is_break_on_read)) && - EvaluateCondition(this->condition)) + EvaluateCondition(system, this->condition)) { if (log_on_hit) { diff --git a/Source/Core/Core/PowerPC/BreakPoints.h b/Source/Core/Core/PowerPC/BreakPoints.h index 0be6981ebe..5494ee73e3 100644 --- a/Source/Core/Core/PowerPC/BreakPoints.h +++ b/Source/Core/Core/PowerPC/BreakPoints.h @@ -15,6 +15,10 @@ namespace Common { class DebugInterface; } +namespace Core +{ +class System; +} struct TBreakPoint { @@ -45,14 +49,21 @@ struct TMemCheck std::optional condition; // returns whether to break - bool Action(Common::DebugInterface* debug_interface, u64 value, u32 addr, bool write, size_t size, - u32 pc); + bool Action(Core::System& system, Common::DebugInterface* debug_interface, u64 value, u32 addr, + bool write, size_t size, u32 pc); }; // Code breakpoints. class BreakPoints { public: + explicit BreakPoints(Core::System& system); + BreakPoints(const BreakPoints& other) = delete; + BreakPoints(BreakPoints&& other) = delete; + BreakPoints& operator=(const BreakPoints& other) = delete; + BreakPoints& operator=(BreakPoints&& other) = delete; + ~BreakPoints(); + using TBreakPoints = std::vector; using TBreakPointsStr = std::vector; @@ -82,12 +93,20 @@ public: private: TBreakPoints m_breakpoints; + Core::System& m_system; }; // Memory breakpoints class MemChecks { public: + explicit MemChecks(Core::System& system); + MemChecks(const MemChecks& other) = delete; + MemChecks(MemChecks&& other) = delete; + MemChecks& operator=(const MemChecks& other) = delete; + MemChecks& operator=(MemChecks&& other) = delete; + ~MemChecks(); + using TMemChecks = std::vector; using TMemChecksStr = std::vector; @@ -109,4 +128,5 @@ public: private: TMemChecks m_mem_checks; + Core::System& m_system; }; diff --git a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp index bf75e3d0f1..28ee8fd77e 100644 --- a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp +++ b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp @@ -214,7 +214,7 @@ bool CachedInterpreter::CheckFPU(CachedInterpreter& cached_interpreter, u32 data if (!ppc_state.msr.FP) { ppc_state.Exceptions |= EXCEPTION_FPU_UNAVAILABLE; - PowerPC::CheckExceptions(); + cached_interpreter.m_system.GetPowerPC().CheckExceptions(); ppc_state.downcount -= data; return true; } @@ -226,7 +226,7 @@ bool CachedInterpreter::CheckDSI(CachedInterpreter& cached_interpreter, u32 data auto& ppc_state = cached_interpreter.m_ppc_state; if (ppc_state.Exceptions & EXCEPTION_DSI) { - PowerPC::CheckExceptions(); + cached_interpreter.m_system.GetPowerPC().CheckExceptions(); ppc_state.downcount -= data; return true; } @@ -238,7 +238,7 @@ bool CachedInterpreter::CheckProgramException(CachedInterpreter& cached_interpre auto& ppc_state = cached_interpreter.m_ppc_state; if (ppc_state.Exceptions & EXCEPTION_PROGRAM) { - PowerPC::CheckExceptions(); + cached_interpreter.m_system.GetPowerPC().CheckExceptions(); ppc_state.downcount -= data; return true; } @@ -247,7 +247,7 @@ bool CachedInterpreter::CheckProgramException(CachedInterpreter& cached_interpre bool CachedInterpreter::CheckBreakpoint(CachedInterpreter& cached_interpreter, u32 data) { - PowerPC::CheckBreakPoints(); + cached_interpreter.m_system.GetPowerPC().CheckBreakPoints(); if (cached_interpreter.m_system.GetCPU().GetState() != CPU::State::Running) { cached_interpreter.m_ppc_state.downcount -= data; @@ -295,7 +295,7 @@ void CachedInterpreter::Jit(u32 address) // Address of instruction could not be translated m_ppc_state.npc = nextPC; m_ppc_state.Exceptions |= EXCEPTION_ISI; - PowerPC::CheckExceptions(); + m_system.GetPowerPC().CheckExceptions(); WARN_LOG_FMT(POWERPC, "ISI exception at {:#010x}", nextPC); return; } @@ -329,7 +329,8 @@ void CachedInterpreter::Jit(u32 address) if (!op.skip) { const bool breakpoint = - m_enable_debugging && PowerPC::breakpoints.IsAddressBreakPoint(op.address); + m_enable_debugging && + m_system.GetPowerPC().GetBreakPoints().IsAddressBreakPoint(op.address); const bool check_fpu = (op.opinfo->flags & FL_USE_FPU) && !js.firstFPInstructionFound; const bool endblock = (op.opinfo->flags & FL_ENDBLOCK) != 0; const bool memcheck = (op.opinfo->flags & FL_LOADSTORE) && jo.memcheck; diff --git a/Source/Core/Core/PowerPC/Expression.cpp b/Source/Core/Core/PowerPC/Expression.cpp index bd089e3a01..2fe2d8c036 100644 --- a/Source/Core/Core/PowerPC/Expression.cpp +++ b/Source/Core/Core/PowerPC/Expression.cpp @@ -267,21 +267,22 @@ std::optional Expression::TryParse(std::string_view text) return Expression{text, std::move(ex), std::move(vars)}; } -double Expression::Evaluate() const +double Expression::Evaluate(Core::System& system) const { - SynchronizeBindings(SynchronizeDirection::From); + SynchronizeBindings(system, SynchronizeDirection::From); double result = expr_eval(m_expr.get()); - SynchronizeBindings(SynchronizeDirection::To); + SynchronizeBindings(system, SynchronizeDirection::To); Reporting(result); return result; } -void Expression::SynchronizeBindings(SynchronizeDirection dir) const +void Expression::SynchronizeBindings(Core::System& system, SynchronizeDirection dir) const { + auto& ppc_state = system.GetPPCState(); auto bind = m_binds.begin(); for (auto* v = m_vars->head; v != nullptr; v = v->next, ++bind) { @@ -293,25 +294,25 @@ void Expression::SynchronizeBindings(SynchronizeDirection dir) const break; case VarBindingType::GPR: if (dir == SynchronizeDirection::From) - v->value = static_cast(PowerPC::ppcState.gpr[bind->index]); + v->value = static_cast(ppc_state.gpr[bind->index]); else - PowerPC::ppcState.gpr[bind->index] = static_cast(static_cast(v->value)); + ppc_state.gpr[bind->index] = static_cast(static_cast(v->value)); break; case VarBindingType::FPR: if (dir == SynchronizeDirection::From) - v->value = PowerPC::ppcState.ps[bind->index].PS0AsDouble(); + v->value = ppc_state.ps[bind->index].PS0AsDouble(); else - PowerPC::ppcState.ps[bind->index].SetPS0(v->value); + ppc_state.ps[bind->index].SetPS0(v->value); break; case VarBindingType::SPR: if (dir == SynchronizeDirection::From) - v->value = static_cast(PowerPC::ppcState.spr[bind->index]); + v->value = static_cast(ppc_state.spr[bind->index]); else - PowerPC::ppcState.spr[bind->index] = static_cast(static_cast(v->value)); + ppc_state.spr[bind->index] = static_cast(static_cast(v->value)); break; case VarBindingType::PCtr: if (dir == SynchronizeDirection::From) - v->value = static_cast(PowerPC::ppcState.pc); + v->value = static_cast(ppc_state.pc); break; } } diff --git a/Source/Core/Core/PowerPC/Expression.h b/Source/Core/Core/PowerPC/Expression.h index 2c96e04f44..d9799caa82 100644 --- a/Source/Core/Core/PowerPC/Expression.h +++ b/Source/Core/Core/PowerPC/Expression.h @@ -15,7 +15,8 @@ struct expr_var_list; namespace Core { class CPUThreadGuard; -} +class System; +} // namespace Core struct ExprDeleter { @@ -36,7 +37,7 @@ class Expression public: static std::optional TryParse(std::string_view text); - double Evaluate() const; + double Evaluate(Core::System& system) const; std::string GetText() const; @@ -64,7 +65,7 @@ private: Expression(std::string_view text, ExprPointer ex, ExprVarListPointer vars); - void SynchronizeBindings(SynchronizeDirection dir) const; + void SynchronizeBindings(Core::System& system, SynchronizeDirection dir) const; void Reporting(const double result) const; std::string m_text; @@ -73,7 +74,7 @@ private: std::vector m_binds; }; -inline bool EvaluateCondition(const std::optional& condition) +inline bool EvaluateCondition(Core::System& system, const std::optional& condition) { - return !condition || condition->Evaluate() != 0.0; + return !condition || condition->Evaluate(system) != 0.0; } diff --git a/Source/Core/Core/PowerPC/GDBStub.cpp b/Source/Core/Core/PowerPC/GDBStub.cpp index 7a702e7188..d88d6a06b0 100644 --- a/Source/Core/Core/PowerPC/GDBStub.cpp +++ b/Source/Core/Core/PowerPC/GDBStub.cpp @@ -163,17 +163,19 @@ static void RemoveBreakpoint(BreakpointType type, u32 addr, u32 len) { if (type == BreakpointType::ExecuteHard || type == BreakpointType::ExecuteSoft) { - while (PowerPC::breakpoints.IsAddressBreakPoint(addr)) + auto& breakpoints = Core::System::GetInstance().GetPowerPC().GetBreakPoints(); + while (breakpoints.IsAddressBreakPoint(addr)) { - PowerPC::breakpoints.Remove(addr); + breakpoints.Remove(addr); INFO_LOG_FMT(GDB_STUB, "gdb: removed a breakpoint: {:08x} bytes at {:08x}", len, addr); } } else { - while (PowerPC::memchecks.GetMemCheck(addr, len) != nullptr) + auto& memchecks = Core::System::GetInstance().GetPowerPC().GetMemChecks(); + while (memchecks.GetMemCheck(addr, len) != nullptr) { - PowerPC::memchecks.Remove(addr); + memchecks.Remove(addr); INFO_LOG_FMT(GDB_STUB, "gdb: removed a memcheck: {:08x} bytes at {:08x}", len, addr); } } @@ -869,7 +871,8 @@ static bool AddBreakpoint(BreakpointType type, u32 addr, u32 len) { if (type == BreakpointType::ExecuteHard || type == BreakpointType::ExecuteSoft) { - PowerPC::breakpoints.Add(addr); + auto& breakpoints = Core::System::GetInstance().GetPowerPC().GetBreakPoints(); + breakpoints.Add(addr); INFO_LOG_FMT(GDB_STUB, "gdb: added {} breakpoint: {:08x} bytes at {:08x}", static_cast(type), len, addr); } @@ -886,7 +889,8 @@ static bool AddBreakpoint(BreakpointType type, u32 addr, u32 len) new_memcheck.break_on_hit = true; new_memcheck.log_on_hit = false; new_memcheck.is_enabled = true; - PowerPC::memchecks.Add(std::move(new_memcheck)); + auto& memchecks = Core::System::GetInstance().GetPowerPC().GetMemChecks(); + memchecks.Add(std::move(new_memcheck)); INFO_LOG_FMT(GDB_STUB, "gdb: added {} memcheck: {:08x} bytes at {:08x}", static_cast(type), len, addr); } @@ -1048,7 +1052,7 @@ void InitLocal(const char* socket) addr.sun_family = AF_UNIX; strcpy(addr.sun_path, socket); - InitGeneric(PF_LOCAL, (const sockaddr*)&addr, sizeof(addr), NULL, NULL); + InitGeneric(PF_LOCAL, (const sockaddr*)&addr, sizeof(addr), nullptr, nullptr); } #endif diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp index c41635c7e6..168df8deaf 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp @@ -120,13 +120,13 @@ int Interpreter::SingleStepInner() // TODO: Does it make sense to use m_prev_inst here? // It seems like we should use the num_cycles for the instruction at PC instead // (m_prev_inst has not yet been updated) - return PPCTables::GetOpInfo(m_prev_inst)->num_cycles; + return PPCTables::GetOpInfo(m_prev_inst, m_ppc_state.pc)->num_cycles; } m_ppc_state.npc = m_ppc_state.pc + sizeof(UGeckoInstruction); m_prev_inst.hex = m_mmu.Read_Opcode(m_ppc_state.pc); - const GekkoOPInfo* opinfo = PPCTables::GetOpInfo(m_prev_inst); + const GekkoOPInfo* opinfo = PPCTables::GetOpInfo(m_prev_inst, m_ppc_state.pc); // Uncomment to trace the interpreter // if ((m_ppc_state.pc & 0x00FFFFFF) >= 0x000AB54C && @@ -206,7 +206,7 @@ void Interpreter::SingleStep() if (m_ppc_state.Exceptions != 0) { - PowerPC::CheckExceptions(); + m_system.GetPowerPC().CheckExceptions(); m_ppc_state.pc = m_ppc_state.npc; } } @@ -224,6 +224,7 @@ void Interpreter::Run() { auto& core_timing = m_system.GetCoreTiming(); auto& cpu = m_system.GetCPU(); + auto& power_pc = m_system.GetPowerPC(); while (cpu.GetState() == CPU::State::Running) { // CoreTiming Advance() ends the previous slice and declares the start of the next @@ -255,7 +256,7 @@ void Interpreter::Run() #endif // 2: check for breakpoint - if (PowerPC::breakpoints.IsAddressBreakPoint(m_ppc_state.pc)) + if (power_pc.GetBreakPoints().IsAddressBreakPoint(m_ppc_state.pc)) { #ifdef SHOW_HISTORY NOTICE_LOG_FMT(POWERPC, "----------------------------"); @@ -280,8 +281,8 @@ void Interpreter::Run() cpu.Break(); if (GDBStub::IsActive()) GDBStub::TakeControl(); - if (PowerPC::breakpoints.IsTempBreakPoint(m_ppc_state.pc)) - PowerPC::breakpoints.Remove(m_ppc_state.pc); + if (power_pc.GetBreakPoints().IsTempBreakPoint(m_ppc_state.pc)) + power_pc.GetBreakPoints().Remove(m_ppc_state.pc); Host_UpdateDisasmDialog(); return; @@ -347,7 +348,7 @@ void Interpreter::ClearCache() void Interpreter::CheckExceptions() { - PowerPC::CheckExceptions(); + m_system.GetPowerPC().CheckExceptions(); m_end_block = true; } diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp index a1e3a5687d..e2cdff4fd6 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp @@ -145,6 +145,6 @@ void Interpreter::sc(Interpreter& interpreter, UGeckoInstruction inst) auto& ppc_state = interpreter.m_ppc_state; ppc_state.Exceptions |= EXCEPTION_SYSCALL; - PowerPC::CheckExceptions(); + interpreter.m_system.GetPowerPC().CheckExceptions(); interpreter.m_end_block = true; } diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp index 5cc41be37e..3cf0be2178 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp @@ -10,6 +10,7 @@ #include "Common/Logging/Log.h" #include "Core/PowerPC/Interpreter/ExceptionUtils.h" #include "Core/PowerPC/PowerPC.h" +#include "Core/System.h" void Interpreter::Helper_UpdateCR0(PowerPC::PowerPCState& ppc_state, u32 value) { @@ -150,7 +151,7 @@ void Interpreter::twi(Interpreter& interpreter, UGeckoInstruction inst) (u32(a) < u32(b) && (TO & 0x02) != 0) || (u32(a) > u32(b) && (TO & 0x01) != 0)) { GenerateProgramException(ppc_state, ProgramExceptionCause::Trap); - PowerPC::CheckExceptions(); + interpreter.m_system.GetPowerPC().CheckExceptions(); interpreter.m_end_block = true; // Dunno about this } } @@ -381,7 +382,7 @@ void Interpreter::tw(Interpreter& interpreter, UGeckoInstruction inst) ((u32(a) < u32(b)) && (TO & 0x02) != 0) || ((u32(a) > u32(b)) && (TO & 0x01) != 0)) { GenerateProgramException(ppc_state, ProgramExceptionCause::Trap); - PowerPC::CheckExceptions(); + interpreter.m_system.GetPowerPC().CheckExceptions(); interpreter.m_end_block = true; // Dunno about this } } diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp index 88314990da..80ddc8efc3 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp @@ -29,7 +29,7 @@ mffsx: 80036650 (huh?) static void FPSCRUpdated(PowerPC::PowerPCState& ppc_state) { UpdateFPExceptionSummary(ppc_state); - PowerPC::RoundingModeUpdated(); + PowerPC::RoundingModeUpdated(ppc_state); } void Interpreter::mtfsb0x(Interpreter& interpreter, UGeckoInstruction inst) @@ -184,7 +184,7 @@ void Interpreter::mtmsr(Interpreter& interpreter, UGeckoInstruction inst) // FE0/FE1 may have been set CheckFPExceptions(ppc_state); - PowerPC::CheckExceptions(); + interpreter.m_system.GetPowerPC().CheckExceptions(); interpreter.m_end_block = true; } @@ -249,7 +249,7 @@ void Interpreter::mfspr(Interpreter& interpreter, UGeckoInstruction inst) case SPR_TL: case SPR_TU: - PowerPC::WriteFullTimeBaseValue(SystemTimers::GetFakeTimeBase()); + interpreter.m_system.GetPowerPC().WriteFullTimeBaseValue(SystemTimers::GetFakeTimeBase()); break; case SPR_WPAR: diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 145a2c9d7e..c23414e930 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -593,7 +593,7 @@ void Jit64::WriteRfiExitDestInRSCRATCH() MOV(32, PPCSTATE(npc), R(RSCRATCH)); Cleanup(); ABI_PushRegistersAndAdjustStack({}, 0); - ABI_CallFunction(PowerPC::CheckExceptions); + ABI_CallFunctionP(PowerPC::CheckExceptionsFromJIT, &m_system.GetPowerPC()); ABI_PopRegistersAndAdjustStack({}, 0); SUB(32, PPCSTATE(downcount), Imm32(js.downcountAmount)); JMP(asm_routines.dispatcher, true); @@ -614,7 +614,7 @@ void Jit64::WriteExceptionExit() MOV(32, R(RSCRATCH), PPCSTATE(pc)); MOV(32, PPCSTATE(npc), R(RSCRATCH)); ABI_PushRegistersAndAdjustStack({}, 0); - ABI_CallFunction(PowerPC::CheckExceptions); + ABI_CallFunctionP(PowerPC::CheckExceptionsFromJIT, &m_system.GetPowerPC()); ABI_PopRegistersAndAdjustStack({}, 0); SUB(32, PPCSTATE(downcount), Imm32(js.downcountAmount)); JMP(asm_routines.dispatcher, true); @@ -626,7 +626,7 @@ void Jit64::WriteExternalExceptionExit() MOV(32, R(RSCRATCH), PPCSTATE(pc)); MOV(32, PPCSTATE(npc), R(RSCRATCH)); ABI_PushRegistersAndAdjustStack({}, 0); - ABI_CallFunction(PowerPC::CheckExternalExceptions); + ABI_CallFunctionP(PowerPC::CheckExternalExceptionsFromJIT, &m_system.GetPowerPC()); ABI_PopRegistersAndAdjustStack({}, 0); SUB(32, PPCSTATE(downcount), Imm32(js.downcountAmount)); JMP(asm_routines.dispatcher, true); @@ -740,7 +740,7 @@ void Jit64::Jit(u32 em_address, bool clear_cache_and_retry_on_failure) // Address of instruction could not be translated m_ppc_state.npc = nextPC; m_ppc_state.Exceptions |= EXCEPTION_ISI; - PowerPC::CheckExceptions(); + m_system.GetPowerPC().CheckExceptions(); WARN_LOG_FMT(POWERPC, "ISI exception at {:#010x}", nextPC); return; } @@ -1006,14 +1006,16 @@ bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC) } auto& cpu = m_system.GetCPU(); - if (m_enable_debugging && breakpoints.IsAddressBreakPoint(op.address) && !cpu.IsStepping()) + auto& power_pc = m_system.GetPowerPC(); + if (m_enable_debugging && power_pc.GetBreakPoints().IsAddressBreakPoint(op.address) && + !cpu.IsStepping()) { gpr.Flush(); fpr.Flush(); MOV(32, PPCSTATE(pc), Imm32(op.address)); ABI_PushRegistersAndAdjustStack({}, 0); - ABI_CallFunction(PowerPC::CheckBreakPoints); + ABI_CallFunctionP(PowerPC::CheckBreakPointsFromJIT, &power_pc); ABI_PopRegistersAndAdjustStack({}, 0); MOV(64, R(RSCRATCH), ImmPtr(cpu.GetStatePtr())); TEST(32, MatR(RSCRATCH), Imm32(0xFFFFFFFF)); diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp index 19c2890c9e..fb8e8fbaef 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp @@ -1223,7 +1223,7 @@ void Jit64::MultiplyImmediate(u32 imm, int a, int d, bool overflow) // power of 2; just a shift if (MathUtil::IsPow2(imm)) { - u32 shift = IntLog2(imm); + u32 shift = MathUtil::IntLog2(imm); // use LEA if it saves an op if (d != a && shift <= 3 && shift >= 1 && Ra.IsSimpleReg()) { @@ -1731,7 +1731,7 @@ void Jit64::divwx(UGeckoInstruction inst) TEST(32, R(dividend), R(dividend)); LEA(32, sum, MDisp(dividend, abs_val - 1)); CMOVcc(32, Rd, R(src), cond); - SAR(32, Rd, Imm8(IntLog2(abs_val))); + SAR(32, Rd, Imm8(MathUtil::IntLog2(abs_val))); if (divisor < 0) NEG(32, Rd); diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp index 65ac5dab21..6b7df45908 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp @@ -361,16 +361,13 @@ void Jit64::dcbx(UGeckoInstruction inst) ABI_PushRegistersAndAdjustStack(registersInUse, 0); if (make_loop) { - MOV(32, R(ABI_PARAM1), R(effective_address)); - MOV(32, R(ABI_PARAM2), R(loop_counter)); - MOV(64, R(ABI_PARAM3), Imm64(reinterpret_cast(&m_system.GetJitInterface()))); - ABI_CallFunction(JitInterface::InvalidateICacheLinesFromJIT); + ABI_CallFunctionPRR(JitInterface::InvalidateICacheLinesFromJIT, &m_system.GetJitInterface(), + effective_address, loop_counter); } else { - MOV(32, R(ABI_PARAM1), R(effective_address)); - MOV(64, R(ABI_PARAM3), Imm64(reinterpret_cast(&m_system.GetJitInterface()))); - ABI_CallFunction(JitInterface::InvalidateICacheLineFromJIT); + ABI_CallFunctionPR(JitInterface::InvalidateICacheLineFromJIT, &m_system.GetJitInterface(), + effective_address); } ABI_PopRegistersAndAdjustStack(registersInUse, 0); asm_routines.ResetStack(*this); diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp index 84692f0068..8fc44b3041 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp @@ -198,7 +198,7 @@ void Jit64::UpdateFPExceptionSummary(X64Reg fpscr, X64Reg tmp1, X64Reg tmp2) // fpscr.VX = (fpscr & FPSCR_VX_ANY) != 0 TEST(32, R(fpscr), Imm32(FPSCR_VX_ANY)); SETcc(CC_NZ, R(tmp1)); - SHL(32, R(tmp1), Imm8(IntLog2(FPSCR_VX))); + SHL(32, R(tmp1), Imm8(MathUtil::IntLog2(FPSCR_VX))); AND(32, R(fpscr), Imm32(~(FPSCR_VX | FPSCR_FEX))); OR(32, R(fpscr), R(tmp1)); @@ -212,7 +212,7 @@ void Jit64::UpdateFPExceptionSummary(X64Reg fpscr, X64Reg tmp1, X64Reg tmp2) // the TEST, and we can't use XOR right after the TEST since that would overwrite flags. However, // there is no false dependency, since SETcc depends on TEST's flags and TEST depends on tmp1. SETcc(CC_NZ, R(tmp1)); - SHL(32, R(tmp1), Imm8(IntLog2(FPSCR_FEX))); + SHL(32, R(tmp1), Imm8(MathUtil::IntLog2(FPSCR_FEX))); OR(32, R(fpscr), R(tmp1)); } diff --git a/Source/Core/Core/PowerPC/Jit64Common/EmuCodeBlock.cpp b/Source/Core/Core/PowerPC/Jit64Common/EmuCodeBlock.cpp index 006e3d6227..3871235493 100644 --- a/Source/Core/Core/PowerPC/Jit64Common/EmuCodeBlock.cpp +++ b/Source/Core/Core/PowerPC/Jit64Common/EmuCodeBlock.cpp @@ -97,7 +97,7 @@ FixupBranch EmuCodeBlock::BATAddressLookup(X64Reg addr, X64Reg tmp, const void* MOV(64, R(tmp), ImmPtr(bat_table)); SHR(32, R(addr), Imm8(PowerPC::BAT_INDEX_SHIFT)); MOV(32, R(addr), MComplex(tmp, addr, SCALE_4, 0)); - BT(32, R(addr), Imm8(IntLog2(PowerPC::BAT_MAPPED_BIT))); + BT(32, R(addr), Imm8(MathUtil::IntLog2(PowerPC::BAT_MAPPED_BIT))); return J_CC(CC_NC, m_far_code.Enabled()); } diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index ce01d560e2..4f1c81316f 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -514,10 +514,11 @@ void JitArm64::WriteExceptionExit(ARM64Reg dest, bool only_external, bool always static_assert(PPCSTATE_OFF(pc) + 4 == PPCSTATE_OFF(npc)); STP(IndexType::Signed, DISPATCHER_PC, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc)); + MOVP2R(ARM64Reg::X0, &m_system.GetPowerPC()); if (only_external) - MOVP2R(EncodeRegTo64(DISPATCHER_PC), &PowerPC::CheckExternalExceptions); + MOVP2R(EncodeRegTo64(DISPATCHER_PC), &PowerPC::CheckExternalExceptionsFromJIT); else - MOVP2R(EncodeRegTo64(DISPATCHER_PC), &PowerPC::CheckExceptions); + MOVP2R(EncodeRegTo64(DISPATCHER_PC), &PowerPC::CheckExceptionsFromJIT); BLR(EncodeRegTo64(DISPATCHER_PC)); LDR(IndexType::Unsigned, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(npc)); @@ -543,7 +544,7 @@ void JitArm64::WriteConditionalExceptionExit(int exception, ARM64Reg temp_gpr, A u64 increment_sp_on_exit) { LDR(IndexType::Unsigned, temp_gpr, PPC_REG, PPCSTATE_OFF(Exceptions)); - FixupBranch no_exception = TBZ(temp_gpr, IntLog2(exception)); + FixupBranch no_exception = TBZ(temp_gpr, MathUtil::IntLog2(exception)); const bool switch_to_far_code = !IsInFarCode(); @@ -742,7 +743,7 @@ void JitArm64::Jit(u32 em_address, bool clear_cache_and_retry_on_failure) // Address of instruction could not be translated m_ppc_state.npc = nextPC; m_ppc_state.Exceptions |= EXCEPTION_ISI; - PowerPC::CheckExceptions(); + m_system.GetPowerPC().CheckExceptions(); WARN_LOG_FMT(POWERPC, "ISI exception at {:#010x}", nextPC); return; } @@ -937,7 +938,7 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC) // Inline exception check LDR(IndexType::Unsigned, ARM64Reg::W30, PPC_REG, PPCSTATE_OFF(Exceptions)); - FixupBranch no_ext_exception = TBZ(ARM64Reg::W30, IntLog2(EXCEPTION_EXTERNAL_INT)); + FixupBranch no_ext_exception = TBZ(ARM64Reg::W30, MathUtil::IntLog2(EXCEPTION_EXTERNAL_INT)); FixupBranch exception = B(); SwitchToFarCode(); const u8* done_here = GetCodePtr(); @@ -973,7 +974,7 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC) ARM64Reg XA = EncodeRegTo64(WA); LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(Exceptions)); - FixupBranch no_ext_exception = TBZ(WA, IntLog2(EXCEPTION_EXTERNAL_INT)); + FixupBranch no_ext_exception = TBZ(WA, MathUtil::IntLog2(EXCEPTION_EXTERNAL_INT)); FixupBranch exception = B(); SwitchToFarCode(); const u8* done_here = GetCodePtr(); @@ -1033,8 +1034,8 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC) js.firstFPInstructionFound = true; } - if (m_enable_debugging && PowerPC::breakpoints.IsAddressBreakPoint(op.address) && - !cpu.IsStepping()) + if (m_enable_debugging && !cpu.IsStepping() && + m_system.GetPowerPC().GetBreakPoints().IsAddressBreakPoint(op.address)) { FlushCarry(); gpr.Flush(FlushMode::All, ARM64Reg::INVALID_REG); @@ -1045,8 +1046,9 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC) MOVI2R(DISPATCHER_PC, op.address); STP(IndexType::Signed, DISPATCHER_PC, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc)); - MOVP2R(ARM64Reg::X0, &PowerPC::CheckBreakPoints); - BLR(ARM64Reg::X0); + MOVP2R(ARM64Reg::X0, &m_system.GetPowerPC()); + MOVP2R(ARM64Reg::X1, &PowerPC::CheckBreakPointsFromJIT); + BLR(ARM64Reg::X1); LDR(IndexType::Unsigned, ARM64Reg::W0, ARM64Reg::X0, MOVPage2R(ARM64Reg::X0, cpu.GetStatePtr())); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index a9a0f540bb..1accdff380 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -909,7 +909,7 @@ bool JitArm64::MultiplyImmediate(u32 imm, int a, int d, bool rc) else if (MathUtil::IsPow2(imm)) { // Multiplication by a power of two (2^n). - const int shift = IntLog2(imm); + const int shift = MathUtil::IntLog2(imm); gpr.BindToRegister(d, d == a); LSL(gpr.R(d), gpr.R(a), shift); @@ -919,7 +919,7 @@ bool JitArm64::MultiplyImmediate(u32 imm, int a, int d, bool rc) else if (MathUtil::IsPow2(imm - 1)) { // Multiplication by a power of two plus one (2^n + 1). - const int shift = IntLog2(imm - 1); + const int shift = MathUtil::IntLog2(imm - 1); gpr.BindToRegister(d, d == a); ADD(gpr.R(d), gpr.R(a), gpr.R(a), ArithOption(gpr.R(a), ShiftType::LSL, shift)); @@ -929,7 +929,7 @@ bool JitArm64::MultiplyImmediate(u32 imm, int a, int d, bool rc) else if (MathUtil::IsPow2(~imm + 1)) { // Multiplication by a negative power of two (-(2^n)). - const int shift = IntLog2(~imm + 1); + const int shift = MathUtil::IntLog2(~imm + 1); gpr.BindToRegister(d, d == a); NEG(gpr.R(d), gpr.R(a), ArithOption(gpr.R(a), ShiftType::LSL, shift)); @@ -939,7 +939,7 @@ bool JitArm64::MultiplyImmediate(u32 imm, int a, int d, bool rc) else if (MathUtil::IsPow2(~imm + 2)) { // Multiplication by a negative power of two plus one (-(2^n) + 1). - const int shift = IntLog2(~imm + 2); + const int shift = MathUtil::IntLog2(~imm + 2); gpr.BindToRegister(d, d == a); SUB(gpr.R(d), gpr.R(a), gpr.R(a), ArithOption(gpr.R(a), ShiftType::LSL, shift)); @@ -1603,9 +1603,9 @@ void JitArm64::divwx(UGeckoInstruction inst) CSEL(WA, RA, WA, CCFlags::CC_PL); if (divisor < 0) - NEG(RD, WA, ArithOption(WA, ShiftType::ASR, IntLog2(abs_val))); + NEG(RD, WA, ArithOption(WA, ShiftType::ASR, MathUtil::IntLog2(abs_val))); else - ASR(RD, WA, IntLog2(abs_val)); + ASR(RD, WA, MathUtil::IntLog2(abs_val)); if (allocate_reg) gpr.Unlock(WA); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp index 9bc573ddd5..e353e87731 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp @@ -347,7 +347,7 @@ FixupBranch JitArm64::BATAddressLookup(ARM64Reg addr_out, ARM64Reg addr_in, ARM6 MOVP2R(tmp, bat_table); LSR(addr_out, addr_in, PowerPC::BAT_INDEX_SHIFT); LDR(addr_out, tmp, ArithOption(addr_out, true)); - FixupBranch pass = TBNZ(addr_out, IntLog2(PowerPC::BAT_MAPPED_BIT)); + FixupBranch pass = TBNZ(addr_out, MathUtil::IntLog2(PowerPC::BAT_MAPPED_BIT)); FixupBranch fail = B(); SetJumpTarget(pass); return fail; @@ -361,7 +361,7 @@ FixupBranch JitArm64::CheckIfSafeAddress(Arm64Gen::ARM64Reg addr, Arm64Gen::ARM6 MOVP2R(tmp2, m_mmu.GetDBATTable().data()); LSR(tmp1, addr, PowerPC::BAT_INDEX_SHIFT); LDR(tmp1, tmp2, ArithOption(tmp1, true)); - FixupBranch pass = TBNZ(tmp1, IntLog2(PowerPC::BAT_PHYSICAL_BIT)); + FixupBranch pass = TBNZ(tmp1, MathUtil::IntLog2(PowerPC::BAT_PHYSICAL_BIT)); FixupBranch fail = B(); SetJumpTarget(pass); return fail; @@ -647,11 +647,11 @@ void JitArm64::dcbx(UGeckoInstruction inst) js.op[1].inst.RA_6 == b && js.op[1].inst.RD_2 == b && js.op[2].inst.hex == 0x4200fff8; - gpr.Lock(ARM64Reg::W0); + gpr.Lock(ARM64Reg::W0, ARM64Reg::W1); if (make_loop) - gpr.Lock(ARM64Reg::W1); + gpr.Lock(ARM64Reg::W2); - ARM64Reg WA = gpr.GetReg(); + ARM64Reg WA = ARM64Reg::W0; if (make_loop) gpr.BindToRegister(b, true); @@ -668,8 +668,8 @@ void JitArm64::dcbx(UGeckoInstruction inst) ARM64Reg reg_cycle_count = gpr.GetReg(); ARM64Reg reg_downcount = gpr.GetReg(); - loop_counter = ARM64Reg::W1; - ARM64Reg WB = ARM64Reg::W0; + loop_counter = ARM64Reg::W2; + ARM64Reg WB = ARM64Reg::W1; // Figure out how many loops we want to do. const u8 cycle_count_per_loop = @@ -709,7 +709,7 @@ void JitArm64::dcbx(UGeckoInstruction inst) gpr.Unlock(reg_cycle_count, reg_downcount); } - ARM64Reg effective_addr = ARM64Reg::W0; + ARM64Reg effective_addr = ARM64Reg::W1; ARM64Reg physical_addr = gpr.GetReg(); if (a) @@ -770,8 +770,8 @@ void JitArm64::dcbx(UGeckoInstruction inst) ABI_PushRegisters(gprs_to_push); m_float_emit.ABI_PushRegisters(fprs_to_push, WA); - // The first two function call arguments are already in the correct registers - MOVP2R(ARM64Reg::X2, &m_system.GetJitInterface()); + MOVP2R(ARM64Reg::X0, &m_system.GetJitInterface()); + // effective_address and loop_counter are already in W1 and W2 respectively if (make_loop) MOVP2R(ARM64Reg::X8, &JitInterface::InvalidateICacheLinesFromJIT); else diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp index ceabebb3c9..6093ae2481 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp @@ -60,13 +60,13 @@ void JitArm64::UpdateFPExceptionSummary(ARM64Reg fpscr) MOVI2R(WA, FPSCR_VX_ANY); TST(WA, fpscr); CSET(WA, CCFlags::CC_NEQ); - BFI(fpscr, WA, IntLog2(FPSCR_VX), 1); + BFI(fpscr, WA, MathUtil::IntLog2(FPSCR_VX), 1); // fpscr.FEX = ((fpscr >> 22) & (fpscr & FPSCR_ANY_E)) != 0 AND(WA, fpscr, LogicalImm(FPSCR_ANY_E, 32)); TST(WA, fpscr, ArithOption(fpscr, ShiftType::LSR, 22)); CSET(WA, CCFlags::CC_NEQ); - BFI(fpscr, WA, IntLog2(FPSCR_FEX), 1); + BFI(fpscr, WA, MathUtil::IntLog2(FPSCR_FEX), 1); gpr.Unlock(WA); } @@ -78,6 +78,7 @@ void JitArm64::UpdateRoundingMode() ABI_PushRegisters(gprs_to_save); m_float_emit.ABI_PushRegisters(fprs_to_save, ARM64Reg::X8); + MOVP2R(ARM64Reg::X0, &m_ppc_state); MOVP2R(ARM64Reg::X8, &PowerPC::RoundingModeUpdated); BLR(ARM64Reg::X8); m_float_emit.ABI_PopRegisters(fprs_to_save, ARM64Reg::X8); diff --git a/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp b/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp index d0c32c743b..887e73a402 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp @@ -220,8 +220,11 @@ bool JitBase::CanMergeNextInstructions(int count) const // Be careful: a breakpoint kills flags in between instructions for (int i = 1; i <= count; i++) { - if (m_enable_debugging && PowerPC::breakpoints.IsAddressBreakPoint(js.op[i].address)) + if (m_enable_debugging && + m_system.GetPowerPC().GetBreakPoints().IsAddressBreakPoint(js.op[i].address)) + { return false; + } if (js.op[i].isBranchTarget) return false; } @@ -230,7 +233,7 @@ bool JitBase::CanMergeNextInstructions(int count) const void JitBase::UpdateMemoryAndExceptionOptions() { - bool any_watchpoints = PowerPC::memchecks.HasAny(); + bool any_watchpoints = m_system.GetPowerPC().GetMemChecks().HasAny(); jo.fastmem = m_fastmem_enabled && jo.fastmem_arena && (m_ppc_state.msr.DR || !any_watchpoints); jo.memcheck = m_mmu_enabled || m_pause_on_panic_enabled || any_watchpoints; jo.fp_exceptions = m_enable_float_exceptions; diff --git a/Source/Core/Core/PowerPC/JitCommon/JitBase.h b/Source/Core/Core/PowerPC/JitCommon/JitBase.h index fe9c7341b8..70c72ef105 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitBase.h +++ b/Source/Core/Core/PowerPC/JitCommon/JitBase.h @@ -32,7 +32,7 @@ struct PowerPCState; // Use these to control the instruction selection // #define INSTRUCTION_START FallBackToInterpreter(inst); return; -// #define INSTRUCTION_START PPCTables::CountInstruction(inst); +// #define INSTRUCTION_START PPCTables::CountInstruction(inst, m_ppc_state.pc); #define INSTRUCTION_START #define FALLBACK_IF(cond) \ diff --git a/Source/Core/Core/PowerPC/JitInterface.cpp b/Source/Core/Core/PowerPC/JitInterface.cpp index c2875ec82e..7ca17cbffc 100644 --- a/Source/Core/Core/PowerPC/JitInterface.cpp +++ b/Source/Core/Core/PowerPC/JitInterface.cpp @@ -163,14 +163,13 @@ JitInterface::GetHostCode(u32 address) const return GetHostCodeError::NoJitActive; } - JitBlock* block = - m_jit->GetBlockCache()->GetBlockFromStartAddress(address, PowerPC::ppcState.msr.Hex); + auto& ppc_state = m_system.GetPPCState(); + JitBlock* block = m_jit->GetBlockCache()->GetBlockFromStartAddress(address, ppc_state.msr.Hex); if (!block) { for (int i = 0; i < 500; i++) { - block = m_jit->GetBlockCache()->GetBlockFromStartAddress(address - 4 * i, - PowerPC::ppcState.msr.Hex); + block = m_jit->GetBlockCache()->GetBlockFromStartAddress(address - 4 * i, ppc_state.msr.Hex); if (block) break; } @@ -257,12 +256,12 @@ void JitInterface::InvalidateICacheLines(u32 address, u32 count) InvalidateICache(address & ~0x1f, 32 * count, false); } -void JitInterface::InvalidateICacheLineFromJIT(u32 address, u32 dummy, JitInterface& jit_interface) +void JitInterface::InvalidateICacheLineFromJIT(JitInterface& jit_interface, u32 address) { jit_interface.InvalidateICacheLine(address); } -void JitInterface::InvalidateICacheLinesFromJIT(u32 address, u32 count, JitInterface& jit_interface) +void JitInterface::InvalidateICacheLinesFromJIT(JitInterface& jit_interface, u32 address, u32 count) { jit_interface.InvalidateICacheLines(address, count); } @@ -287,25 +286,26 @@ void JitInterface::CompileExceptionCheck(ExceptionType type) break; } - if (PowerPC::ppcState.pc != 0 && - (exception_addresses->find(PowerPC::ppcState.pc)) == (exception_addresses->end())) + auto& ppc_state = m_system.GetPPCState(); + if (ppc_state.pc != 0 && + (exception_addresses->find(ppc_state.pc)) == (exception_addresses->end())) { if (type == ExceptionType::FIFOWrite) { ASSERT(Core::IsCPUThread()); - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); // Check in case the code has been replaced since: do we need to do this? const OpType optype = - PPCTables::GetOpInfo(PowerPC::MMU::HostRead_U32(guard, PowerPC::ppcState.pc))->type; + PPCTables::GetOpInfo(PowerPC::MMU::HostRead_U32(guard, ppc_state.pc), ppc_state.pc)->type; if (optype != OpType::Store && optype != OpType::StoreFP && optype != OpType::StorePS) return; } - exception_addresses->insert(PowerPC::ppcState.pc); + exception_addresses->insert(ppc_state.pc); // Invalidate the JIT block so that it gets recompiled with the external exception check // included. - m_jit->GetBlockCache()->InvalidateICache(PowerPC::ppcState.pc, 4, true); + m_jit->GetBlockCache()->InvalidateICache(ppc_state.pc, 4, true); } } diff --git a/Source/Core/Core/PowerPC/JitInterface.h b/Source/Core/Core/PowerPC/JitInterface.h index 1ba54cc2c9..00c4680d47 100644 --- a/Source/Core/Core/PowerPC/JitInterface.h +++ b/Source/Core/Core/PowerPC/JitInterface.h @@ -82,8 +82,8 @@ public: void InvalidateICache(u32 address, u32 size, bool forced); void InvalidateICacheLine(u32 address); void InvalidateICacheLines(u32 address, u32 count); - static void InvalidateICacheLineFromJIT(u32 address, u32 dummy, JitInterface& jit_interface); - static void InvalidateICacheLinesFromJIT(u32 address, u32 count, JitInterface& jit_interface); + static void InvalidateICacheLineFromJIT(JitInterface& jit_interface, u32 address); + static void InvalidateICacheLinesFromJIT(JitInterface& jit_interface, u32 address, u32 count); enum class ExceptionType { diff --git a/Source/Core/Core/PowerPC/MMU.cpp b/Source/Core/Core/PowerPC/MMU.cpp index 92786beec6..a1597b96a5 100644 --- a/Source/Core/Core/PowerPC/MMU.cpp +++ b/Source/Core/Core/PowerPC/MMU.cpp @@ -52,8 +52,8 @@ namespace PowerPC { -MMU::MMU(Core::System& system, Memory::MemoryManager& memory, PowerPC::PowerPCState& ppc_state) - : m_system(system), m_memory(memory), m_ppc_state(ppc_state) +MMU::MMU(Core::System& system, Memory::MemoryManager& memory, PowerPC::PowerPCManager& power_pc) + : m_system(system), m_memory(memory), m_power_pc(power_pc), m_ppc_state(power_pc.GetPPCState()) { } @@ -530,10 +530,10 @@ std::optional> MMU::HostTryReadInstruction(const Core::CPUThread void MMU::Memcheck(u32 address, u64 var, bool write, size_t size) { - if (!memchecks.HasAny()) + if (!m_power_pc.GetMemChecks().HasAny()) return; - TMemCheck* mc = memchecks.GetMemCheck(address, size); + TMemCheck* mc = m_power_pc.GetMemChecks().GetMemCheck(address, size); if (mc == nullptr) return; @@ -545,7 +545,8 @@ void MMU::Memcheck(u32 address, u64 var, bool write, size_t size) mc->num_hits++; - const bool pause = mc->Action(&debug_interface, var, address, write, size, m_ppc_state.pc); + const bool pause = mc->Action(m_system, &m_power_pc.GetDebugInterface(), var, address, write, + size, m_ppc_state.pc); if (!pause) return; @@ -891,7 +892,7 @@ std::optional> MMU::HostTryReadString(const Core::CPUThr bool MMU::IsOptimizableRAMAddress(const u32 address) const { - if (PowerPC::memchecks.HasAny()) + if (m_power_pc.GetMemChecks().HasAny()) return false; if (!m_ppc_state.msr.DR) @@ -1188,7 +1189,7 @@ void MMU::TouchDCacheLine(u32 address, bool store) u32 MMU::IsOptimizableMMIOAccess(u32 address, u32 access_size) const { - if (PowerPC::memchecks.HasAny()) + if (m_power_pc.GetMemChecks().HasAny()) return 0; if (!m_ppc_state.msr.DR) @@ -1211,7 +1212,7 @@ u32 MMU::IsOptimizableMMIOAccess(u32 address, u32 access_size) const bool MMU::IsOptimizableGatherPipeWrite(u32 address) const { - if (PowerPC::memchecks.HasAny()) + if (m_power_pc.GetMemChecks().HasAny()) return false; if (!m_ppc_state.msr.DR) @@ -1565,7 +1566,7 @@ void MMU::UpdateBATs(BatTable& bat_table, u32 base_spr) } // Fastmem doesn't support memchecks, so disable it for all overlapping virtual pages. - if (PowerPC::memchecks.OverlapsMemcheck(virtual_address, BAT_PAGE_SIZE)) + if (m_power_pc.GetMemChecks().OverlapsMemcheck(virtual_address, BAT_PAGE_SIZE)) valid_bit &= ~BAT_PHYSICAL_BIT; // (BEPI | j) == (BEPI & ~BL) | (j & BL). @@ -1585,7 +1586,7 @@ void MMU::UpdateFakeMMUBat(BatTable& bat_table, u32 start_addr) u32 p_address = 0x7E000000 | (i << BAT_INDEX_SHIFT & m_memory.GetFakeVMemMask()); u32 flags = BAT_MAPPED_BIT | BAT_PHYSICAL_BIT; - if (PowerPC::memchecks.OverlapsMemcheck(e_address << BAT_INDEX_SHIFT, BAT_PAGE_SIZE)) + if (m_power_pc.GetMemChecks().OverlapsMemcheck(e_address << BAT_INDEX_SHIFT, BAT_PAGE_SIZE)) flags &= ~BAT_PHYSICAL_BIT; bat_table[e_address] = p_address | flags; diff --git a/Source/Core/Core/PowerPC/MMU.h b/Source/Core/Core/PowerPC/MMU.h index a5dda345b8..2ee0173eb5 100644 --- a/Source/Core/Core/PowerPC/MMU.h +++ b/Source/Core/Core/PowerPC/MMU.h @@ -23,6 +23,7 @@ class MemoryManager; namespace PowerPC { +class PowerPCManager; struct PowerPCState; enum class RequestedAddressSpace @@ -108,7 +109,7 @@ enum class XCheckTLBFlag class MMU { public: - MMU(Core::System& system, Memory::MemoryManager& memory, PowerPC::PowerPCState& ppc_state); + MMU(Core::System& system, Memory::MemoryManager& memory, PowerPC::PowerPCManager& power_pc); MMU(const MMU& other) = delete; MMU(MMU&& other) = delete; MMU& operator=(const MMU& other) = delete; @@ -318,6 +319,7 @@ private: Core::System& m_system; Memory::MemoryManager& m_memory; + PowerPC::PowerPCManager& m_power_pc; PowerPC::PowerPCState& m_ppc_state; BatTable m_ibat_table; diff --git a/Source/Core/Core/PowerPC/PPCAnalyst.cpp b/Source/Core/Core/PowerPC/PPCAnalyst.cpp index 1d4f5fab2f..34501a5bbe 100644 --- a/Source/Core/Core/PowerPC/PPCAnalyst.cpp +++ b/Source/Core/Core/PowerPC/PPCAnalyst.cpp @@ -114,7 +114,7 @@ bool AnalyzeFunction(const Core::CPUThreadGuard& guard, u32 startAddr, Common::S } const PowerPC::TryReadInstResult read_result = mmu.TryReadInstruction(addr); const UGeckoInstruction instr = read_result.hex; - if (read_result.valid && PPCTables::IsValidInstruction(instr)) + if (read_result.valid && PPCTables::IsValidInstruction(instr, addr)) { // BLR or RFI // 4e800021 is blrl, not the end of a function @@ -209,10 +209,11 @@ bool PPCAnalyzer::CanSwapAdjacentOps(const CodeOp& a, const CodeOp& b) const u64 b_flags = b_info->flags; // can't reorder around breakpoints - if (m_is_debugging_enabled && (PowerPC::breakpoints.IsAddressBreakPoint(a.address) || - PowerPC::breakpoints.IsAddressBreakPoint(b.address))) + if (m_is_debugging_enabled) { - return false; + auto& breakpoints = Core::System::GetInstance().GetPowerPC().GetBreakPoints(); + if (breakpoints.IsAddressBreakPoint(a.address) || breakpoints.IsAddressBreakPoint(b.address)) + return false; } // Any instruction which can raise an interrupt is *not* a possible swap candidate: // see [1] for an example of a crash caused by this error. @@ -274,7 +275,7 @@ static void FindFunctionsFromBranches(const Core::CPUThreadGuard& guard, u32 sta const PowerPC::TryReadInstResult read_result = mmu.TryReadInstruction(addr); const UGeckoInstruction instr = read_result.hex; - if (read_result.valid && PPCTables::IsValidInstruction(instr)) + if (read_result.valid && PPCTables::IsValidInstruction(instr, addr)) { switch (instr.OPCD) { @@ -323,7 +324,7 @@ static void FindFunctionsFromHandlers(const Core::CPUThreadGuard& guard, PPCSymb for (const auto& entry : handlers) { const PowerPC::TryReadInstResult read_result = mmu.TryReadInstruction(entry.first); - if (read_result.valid && PPCTables::IsValidInstruction(read_result.hex)) + if (read_result.valid && PPCTables::IsValidInstruction(read_result.hex, entry.first)) { // Check if this function is already mapped Common::Symbol* f = func_db->AddFunction(guard, entry.first); @@ -357,7 +358,7 @@ static void FindFunctionsAfterReturnInstruction(const Core::CPUThreadGuard& guar location += 4; read_result = mmu.TryReadInstruction(location); } - if (read_result.valid && PPCTables::IsValidInstruction(read_result.hex)) + if (read_result.valid && PPCTables::IsValidInstruction(read_result.hex, location)) { // check if this function is already mapped Common::Symbol* f = func_db->AddFunction(guard, location); @@ -778,7 +779,7 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer, num_inst++; const UGeckoInstruction inst = result.hex; - const GekkoOPInfo* opinfo = PPCTables::GetOpInfo(inst); + const GekkoOPInfo* opinfo = PPCTables::GetOpInfo(inst, address); code[i] = {}; code[i].opinfo = opinfo; code[i].address = address; diff --git a/Source/Core/Core/PowerPC/PPCCache.cpp b/Source/Core/Core/PowerPC/PPCCache.cpp index 7818dcb616..d159eba1f2 100644 --- a/Source/Core/Core/PowerPC/PPCCache.cpp +++ b/Source/Core/Core/PowerPC/PPCCache.cpp @@ -392,19 +392,21 @@ void Cache::DoState(PointerWrap& p) u32 InstructionCache::ReadInstruction(u32 addr) { auto& system = Core::System::GetInstance(); - auto& memory = system.GetMemory(); + auto& ppc_state = system.GetPPCState(); - if (!HID0(PowerPC::ppcState).ICE || m_disable_icache) // instruction cache is disabled - return memory.Read_U32(addr); + if (!HID0(ppc_state).ICE || m_disable_icache) // instruction cache is disabled + return system.GetMemory().Read_U32(addr); u32 value; - Read(addr, &value, sizeof(value), HID0(PowerPC::ppcState).ILOCK); + Read(addr, &value, sizeof(value), HID0(ppc_state).ILOCK); return Common::swap32(value); } void InstructionCache::Invalidate(u32 addr) { - if (!HID0(PowerPC::ppcState).ICE || m_disable_icache) + auto& system = Core::System::GetInstance(); + auto& ppc_state = system.GetPPCState(); + if (!HID0(ppc_state).ICE || m_disable_icache) return; // Invalidates the whole set @@ -424,7 +426,7 @@ void InstructionCache::Invalidate(u32 addr) valid[set] = 0; modified[set] = 0; - Core::System::GetInstance().GetJitInterface().InvalidateICacheLine(addr); + system.GetJitInterface().InvalidateICacheLine(addr); } void InstructionCache::RefreshConfig() diff --git a/Source/Core/Core/PowerPC/PPCSymbolDB.cpp b/Source/Core/Core/PowerPC/PPCSymbolDB.cpp index 61e620248d..fea9a0b586 100644 --- a/Source/Core/Core/PowerPC/PPCSymbolDB.cpp +++ b/Source/Core/Core/PowerPC/PPCSymbolDB.cpp @@ -27,7 +27,7 @@ PPCSymbolDB g_symbolDB; -PPCSymbolDB::PPCSymbolDB() : debugger{&PowerPC::debug_interface} +PPCSymbolDB::PPCSymbolDB() : debugger{&Core::System::GetInstance().GetPowerPC().GetDebugInterface()} { } diff --git a/Source/Core/Core/PowerPC/PPCTables.cpp b/Source/Core/Core/PowerPC/PPCTables.cpp index dcd4d8417e..bf9392516b 100644 --- a/Source/Core/Core/PowerPC/PPCTables.cpp +++ b/Source/Core/Core/PowerPC/PPCTables.cpp @@ -613,7 +613,7 @@ constexpr Tables s_tables = []() consteval } (); -const GekkoOPInfo* GetOpInfo(UGeckoInstruction inst) +const GekkoOPInfo* GetOpInfo(UGeckoInstruction inst, u32 pc) { const GekkoOPInfo* info = &s_tables.all_instructions[s_tables.primary_table[inst.OPCD]]; if (info->type == OpType::Subtable) @@ -631,8 +631,7 @@ const GekkoOPInfo* GetOpInfo(UGeckoInstruction inst) case 63: return &s_tables.all_instructions[s_tables.table63[inst.SUBOP10]]; default: - ASSERT_MSG(POWERPC, 0, "GetOpInfo - invalid subtable op {:08x} @ {:08x}", inst.hex, - PowerPC::ppcState.pc); + ASSERT_MSG(POWERPC, 0, "GetOpInfo - invalid subtable op {:08x} @ {:08x}", inst.hex, pc); return &s_tables.all_instructions[s_tables.unknown_op_info]; } } @@ -640,8 +639,7 @@ const GekkoOPInfo* GetOpInfo(UGeckoInstruction inst) { if (info->type == OpType::Invalid) { - ASSERT_MSG(POWERPC, 0, "GetOpInfo - invalid op {:08x} @ {:08x}", inst.hex, - PowerPC::ppcState.pc); + ASSERT_MSG(POWERPC, 0, "GetOpInfo - invalid op {:08x} @ {:08x}", inst.hex, pc); return &s_tables.all_instructions[s_tables.unknown_op_info]; } return info; @@ -658,21 +656,21 @@ std::vector rsplocations; } #endif -const char* GetInstructionName(UGeckoInstruction inst) +const char* GetInstructionName(UGeckoInstruction inst, u32 pc) { - const GekkoOPInfo* info = GetOpInfo(inst); + const GekkoOPInfo* info = GetOpInfo(inst, pc); return info->opname; } -bool IsValidInstruction(UGeckoInstruction inst) +bool IsValidInstruction(UGeckoInstruction inst, u32 pc) { - const GekkoOPInfo* info = GetOpInfo(inst); + const GekkoOPInfo* info = GetOpInfo(inst, pc); return info->type != OpType::Invalid && info->type != OpType::Unknown; } -void CountInstruction(UGeckoInstruction inst) +void CountInstruction(UGeckoInstruction inst, u32 pc) { - const GekkoOPInfo* info = GetOpInfo(inst); + const GekkoOPInfo* info = GetOpInfo(inst, pc); info->stats->run_count++; } diff --git a/Source/Core/Core/PowerPC/PPCTables.h b/Source/Core/Core/PowerPC/PPCTables.h index 8d92f1811e..33a6e2a9fb 100644 --- a/Source/Core/Core/PowerPC/PPCTables.h +++ b/Source/Core/Core/PowerPC/PPCTables.h @@ -118,13 +118,13 @@ struct GekkoOPInfo namespace PPCTables { -const GekkoOPInfo* GetOpInfo(UGeckoInstruction inst); +const GekkoOPInfo* GetOpInfo(UGeckoInstruction inst, u32 pc); -bool IsValidInstruction(UGeckoInstruction inst); +bool IsValidInstruction(UGeckoInstruction inst, u32 pc); -void CountInstruction(UGeckoInstruction inst); +void CountInstruction(UGeckoInstruction inst, u32 pc); void CountInstructionCompile(const GekkoOPInfo* info, u32 pc); void PrintInstructionRunCounts(); void LogCompiledInstructions(); -const char* GetInstructionName(UGeckoInstruction inst); +const char* GetInstructionName(UGeckoInstruction inst, u32 pc); } // namespace PPCTables diff --git a/Source/Core/Core/PowerPC/PowerPC.cpp b/Source/Core/Core/PowerPC/PowerPC.cpp index fef24a482a..0f88f696a8 100644 --- a/Source/Core/Core/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/PowerPC/PowerPC.cpp @@ -35,19 +35,6 @@ namespace PowerPC { -// STATE_TO_SAVE -PowerPCState ppcState; - -static CPUCoreBase* s_cpu_core_base = nullptr; -static bool s_cpu_core_base_is_injected = false; -static CoreMode s_mode = CoreMode::Interpreter; - -BreakPoints breakpoints; -MemChecks memchecks; -PPCDebugInterface debug_interface(Core::System::GetInstance()); - -static CoreTiming::EventType* s_invalidate_cache_thread_safe; - double PairedSingle::PS0AsDouble() const { return Common::BitCast(ps0); @@ -70,7 +57,7 @@ void PairedSingle::SetPS1(double value) static void InvalidateCacheThreadSafe(Core::System& system, u64 userdata, s64 cyclesLate) { - ppcState.iCache.Invalidate(static_cast(userdata)); + system.GetPPCState().iCache.Invalidate(static_cast(userdata)); } std::istream& operator>>(std::istream& is, CPUCore& core) @@ -97,7 +84,14 @@ std::ostream& operator<<(std::ostream& os, CPUCore core) return os; } -void DoState(PointerWrap& p) +PowerPCManager::PowerPCManager(Core::System& system) + : m_breakpoints(system), m_memchecks(system), m_debug_interface(system), m_system(system) +{ +} + +PowerPCManager::~PowerPCManager() = default; + +void PowerPCManager::DoState(PointerWrap& p) { // some of this code has been disabled, because // it changes registers even in Mode::Measure (which is suspicious and seems like it could cause @@ -105,49 +99,49 @@ void DoState(PointerWrap& p) // and because the values it's changing have been added to CoreTiming::DoState, so it might // conflict to mess with them here. - // PowerPC::ppcState.spr[SPR_DEC] = SystemTimers::GetFakeDecrementer(); - // *((u64 *)&TL(PowerPC::ppcState)) = SystemTimers::GetFakeTimeBase(); //works since we are little + // m_ppc_state.spr[SPR_DEC] = SystemTimers::GetFakeDecrementer(); + // *((u64 *)&TL(m_ppc_state)) = SystemTimers::GetFakeTimeBase(); //works since we are little // endian and TL comes first :) - p.DoArray(ppcState.gpr); - p.Do(ppcState.pc); - p.Do(ppcState.npc); - p.DoArray(ppcState.cr.fields); - p.Do(ppcState.msr); - p.Do(ppcState.fpscr); - p.Do(ppcState.Exceptions); - p.Do(ppcState.downcount); - p.Do(ppcState.xer_ca); - p.Do(ppcState.xer_so_ov); - p.Do(ppcState.xer_stringctrl); - p.DoArray(ppcState.ps); - p.DoArray(ppcState.sr); - p.DoArray(ppcState.spr); - p.DoArray(ppcState.tlb); - p.Do(ppcState.pagetable_base); - p.Do(ppcState.pagetable_hashmask); + p.DoArray(m_ppc_state.gpr); + p.Do(m_ppc_state.pc); + p.Do(m_ppc_state.npc); + p.DoArray(m_ppc_state.cr.fields); + p.Do(m_ppc_state.msr); + p.Do(m_ppc_state.fpscr); + p.Do(m_ppc_state.Exceptions); + p.Do(m_ppc_state.downcount); + p.Do(m_ppc_state.xer_ca); + p.Do(m_ppc_state.xer_so_ov); + p.Do(m_ppc_state.xer_stringctrl); + p.DoArray(m_ppc_state.ps); + p.DoArray(m_ppc_state.sr); + p.DoArray(m_ppc_state.spr); + p.DoArray(m_ppc_state.tlb); + p.Do(m_ppc_state.pagetable_base); + p.Do(m_ppc_state.pagetable_hashmask); - p.Do(ppcState.reserve); - p.Do(ppcState.reserve_address); + p.Do(m_ppc_state.reserve); + p.Do(m_ppc_state.reserve_address); - ppcState.iCache.DoState(p); - ppcState.dCache.DoState(p); + m_ppc_state.iCache.DoState(p); + m_ppc_state.dCache.DoState(p); if (p.IsReadMode()) { - if (!ppcState.m_enable_dcache) + if (!m_ppc_state.m_enable_dcache) { INFO_LOG_FMT(POWERPC, "Flushing data cache"); - ppcState.dCache.FlushAll(); + m_ppc_state.dCache.FlushAll(); } else { - ppcState.dCache.Reset(); + m_ppc_state.dCache.Reset(); } - RoundingModeUpdated(); + RoundingModeUpdated(m_ppc_state); - auto& mmu = Core::System::GetInstance().GetMMU(); + auto& mmu = m_system.GetMMU(); mmu.IBATUpdated(); mmu.DBATUpdated(); } @@ -155,15 +149,15 @@ void DoState(PointerWrap& p) // SystemTimers::DecrementerSet(); // SystemTimers::TimeBaseSet(); - Core::System::GetInstance().GetJitInterface().DoState(p); + m_system.GetJitInterface().DoState(p); } -static void ResetRegisters() +void PowerPCManager::ResetRegisters() { - std::fill(std::begin(ppcState.ps), std::end(ppcState.ps), PairedSingle{}); - std::fill(std::begin(ppcState.sr), std::end(ppcState.sr), 0U); - std::fill(std::begin(ppcState.gpr), std::end(ppcState.gpr), 0U); - std::fill(std::begin(ppcState.spr), std::end(ppcState.spr), 0U); + std::fill(std::begin(m_ppc_state.ps), std::end(m_ppc_state.ps), PairedSingle{}); + std::fill(std::begin(m_ppc_state.sr), std::end(m_ppc_state.sr), 0U); + std::fill(std::begin(m_ppc_state.gpr), std::end(m_ppc_state.gpr), 0U); + std::fill(std::begin(m_ppc_state.spr), std::end(m_ppc_state.spr), 0U); // Gamecube: // 0x00080200 = lonestar 2.0 @@ -178,73 +172,72 @@ static void ResetRegisters() // 0x00087102 = broadway retail hw if (SConfig::GetInstance().bWii) { - ppcState.spr[SPR_PVR] = 0x00087102; + m_ppc_state.spr[SPR_PVR] = 0x00087102; } else { - ppcState.spr[SPR_PVR] = 0x00083214; + m_ppc_state.spr[SPR_PVR] = 0x00083214; } - ppcState.spr[SPR_HID1] = 0x80000000; // We're running at 3x the bus clock - ppcState.spr[SPR_ECID_U] = 0x0d96e200; - ppcState.spr[SPR_ECID_M] = 0x1840c00d; - ppcState.spr[SPR_ECID_L] = 0x82bb08e8; + m_ppc_state.spr[SPR_HID1] = 0x80000000; // We're running at 3x the bus clock + m_ppc_state.spr[SPR_ECID_U] = 0x0d96e200; + m_ppc_state.spr[SPR_ECID_M] = 0x1840c00d; + m_ppc_state.spr[SPR_ECID_L] = 0x82bb08e8; - ppcState.fpscr.Hex = 0; - ppcState.pc = 0; - ppcState.npc = 0; - ppcState.Exceptions = 0; + m_ppc_state.fpscr.Hex = 0; + m_ppc_state.pc = 0; + m_ppc_state.npc = 0; + m_ppc_state.Exceptions = 0; - ppcState.reserve = false; - ppcState.reserve_address = 0; + m_ppc_state.reserve = false; + m_ppc_state.reserve_address = 0; - for (auto& v : ppcState.cr.fields) + for (auto& v : m_ppc_state.cr.fields) { v = 0x8000000000000001; } - ppcState.SetXER({}); + m_ppc_state.SetXER({}); - RoundingModeUpdated(); + RoundingModeUpdated(m_ppc_state); - auto& mmu = Core::System::GetInstance().GetMMU(); + auto& mmu = m_system.GetMMU(); mmu.DBATUpdated(); mmu.IBATUpdated(); - TL(PowerPC::ppcState) = 0; - TU(PowerPC::ppcState) = 0; + TL(m_ppc_state) = 0; + TU(m_ppc_state) = 0; SystemTimers::TimeBaseSet(); // MSR should be 0x40, but we don't emulate BS1, so it would never be turned off :} - ppcState.msr.Hex = 0; - ppcState.spr[SPR_DEC] = 0xFFFFFFFF; + m_ppc_state.msr.Hex = 0; + m_ppc_state.spr[SPR_DEC] = 0xFFFFFFFF; SystemTimers::DecrementerSet(); } -static void InitializeCPUCore(CPUCore cpu_core) +void PowerPCManager::InitializeCPUCore(CPUCore cpu_core) { // We initialize the interpreter because // it is used on boot and code window independently. - auto& system = Core::System::GetInstance(); - auto& interpreter = system.GetInterpreter(); + auto& interpreter = m_system.GetInterpreter(); interpreter.Init(); switch (cpu_core) { case CPUCore::Interpreter: - s_cpu_core_base = &interpreter; + m_cpu_core_base = &interpreter; break; default: - s_cpu_core_base = system.GetJitInterface().InitJitCore(cpu_core); - if (!s_cpu_core_base) // Handle Situations where JIT core isn't available + m_cpu_core_base = m_system.GetJitInterface().InitJitCore(cpu_core); + if (!m_cpu_core_base) // Handle Situations where JIT core isn't available { WARN_LOG_FMT(POWERPC, "CPU core {} not available. Falling back to default.", static_cast(cpu_core)); - s_cpu_core_base = system.GetJitInterface().InitJitCore(DefaultCPUCore()); + m_cpu_core_base = m_system.GetJitInterface().InitJitCore(DefaultCPUCore()); } break; } - s_mode = s_cpu_core_base == &interpreter ? CoreMode::Interpreter : CoreMode::JIT; + m_mode = m_cpu_core_base == &interpreter ? CoreMode::Interpreter : CoreMode::JIT; } const std::vector& AvailableCPUCores() @@ -273,147 +266,143 @@ CPUCore DefaultCPUCore() #endif } -void Init(CPUCore cpu_core) +void PowerPCManager::Init(CPUCore cpu_core) { - s_invalidate_cache_thread_safe = Core::System::GetInstance().GetCoreTiming().RegisterEvent( - "invalidateEmulatedCache", InvalidateCacheThreadSafe); + m_invalidate_cache_thread_safe = + m_system.GetCoreTiming().RegisterEvent("invalidateEmulatedCache", InvalidateCacheThreadSafe); Reset(); InitializeCPUCore(cpu_core); - ppcState.iCache.Init(); - ppcState.dCache.Init(); + m_ppc_state.iCache.Init(); + m_ppc_state.dCache.Init(); - ppcState.m_enable_dcache = Config::Get(Config::MAIN_ACCURATE_CPU_CACHE); + m_ppc_state.m_enable_dcache = Config::Get(Config::MAIN_ACCURATE_CPU_CACHE); if (Config::Get(Config::MAIN_ENABLE_DEBUGGING)) - breakpoints.ClearAllTemporary(); + m_breakpoints.ClearAllTemporary(); } -void Reset() +void PowerPCManager::Reset() { - ppcState.pagetable_base = 0; - ppcState.pagetable_hashmask = 0; - ppcState.tlb = {}; + m_ppc_state.pagetable_base = 0; + m_ppc_state.pagetable_hashmask = 0; + m_ppc_state.tlb = {}; ResetRegisters(); - ppcState.iCache.Reset(); - ppcState.dCache.Reset(); + m_ppc_state.iCache.Reset(); + m_ppc_state.dCache.Reset(); } -void ScheduleInvalidateCacheThreadSafe(u32 address) +void PowerPCManager::ScheduleInvalidateCacheThreadSafe(u32 address) { - auto& system = Core::System::GetInstance(); - auto& cpu = system.GetCPU(); + auto& cpu = m_system.GetCPU(); if (cpu.GetState() == CPU::State::Running && !Core::IsCPUThread()) { - system.GetCoreTiming().ScheduleEvent(0, s_invalidate_cache_thread_safe, address, - CoreTiming::FromThread::NON_CPU); + m_system.GetCoreTiming().ScheduleEvent(0, m_invalidate_cache_thread_safe, address, + CoreTiming::FromThread::NON_CPU); } else { - PowerPC::ppcState.iCache.Invalidate(static_cast(address)); + m_ppc_state.iCache.Invalidate(static_cast(address)); } } -void Shutdown() +void PowerPCManager::Shutdown() { InjectExternalCPUCore(nullptr); - auto& system = Core::System::GetInstance(); - system.GetJitInterface().Shutdown(); - auto& interpreter = system.GetInterpreter(); - interpreter.Shutdown(); - s_cpu_core_base = nullptr; + m_system.GetJitInterface().Shutdown(); + m_system.GetInterpreter().Shutdown(); + m_cpu_core_base = nullptr; } -CoreMode GetMode() +CoreMode PowerPCManager::GetMode() const { - return !s_cpu_core_base_is_injected ? s_mode : CoreMode::Interpreter; + return !m_cpu_core_base_is_injected ? m_mode : CoreMode::Interpreter; } -static void ApplyMode() +void PowerPCManager::ApplyMode() { - auto& system = Core::System::GetInstance(); - auto& interpreter = system.GetInterpreter(); + auto& interpreter = m_system.GetInterpreter(); - switch (s_mode) + switch (m_mode) { case CoreMode::Interpreter: // Switching from JIT to interpreter - s_cpu_core_base = &interpreter; + m_cpu_core_base = &interpreter; break; case CoreMode::JIT: // Switching from interpreter to JIT. // Don't really need to do much. It'll work, the cache will refill itself. - s_cpu_core_base = system.GetJitInterface().GetCore(); - if (!s_cpu_core_base) // Has a chance to not get a working JIT core if one isn't active on host - s_cpu_core_base = &interpreter; + m_cpu_core_base = m_system.GetJitInterface().GetCore(); + if (!m_cpu_core_base) // Has a chance to not get a working JIT core if one isn't active on host + m_cpu_core_base = &interpreter; break; } } -void SetMode(CoreMode new_mode) +void PowerPCManager::SetMode(CoreMode new_mode) { - if (new_mode == s_mode) + if (new_mode == m_mode) return; // We don't need to do anything. - s_mode = new_mode; + m_mode = new_mode; // If we're using an external CPU core implementation then don't do anything. - if (s_cpu_core_base_is_injected) + if (m_cpu_core_base_is_injected) return; ApplyMode(); } -const char* GetCPUName() +const char* PowerPCManager::GetCPUName() const { - return s_cpu_core_base->GetName(); + return m_cpu_core_base->GetName(); } -void InjectExternalCPUCore(CPUCoreBase* new_cpu) +void PowerPCManager::InjectExternalCPUCore(CPUCoreBase* new_cpu) { // Previously injected. - if (s_cpu_core_base_is_injected) - s_cpu_core_base->Shutdown(); + if (m_cpu_core_base_is_injected) + m_cpu_core_base->Shutdown(); // nullptr means just remove if (!new_cpu) { - if (s_cpu_core_base_is_injected) + if (m_cpu_core_base_is_injected) { - s_cpu_core_base_is_injected = false; + m_cpu_core_base_is_injected = false; ApplyMode(); } return; } new_cpu->Init(); - s_cpu_core_base = new_cpu; - s_cpu_core_base_is_injected = true; + m_cpu_core_base = new_cpu; + m_cpu_core_base_is_injected = true; } -void SingleStep() +void PowerPCManager::SingleStep() { - s_cpu_core_base->SingleStep(); + m_cpu_core_base->SingleStep(); } -void RunLoop() +void PowerPCManager::RunLoop() { - s_cpu_core_base->Run(); + m_cpu_core_base->Run(); Host_UpdateDisasmDialog(); } -u64 ReadFullTimeBaseValue() +u64 PowerPCManager::ReadFullTimeBaseValue() const { u64 value; - std::memcpy(&value, &TL(PowerPC::ppcState), sizeof(value)); + std::memcpy(&value, &TL(m_ppc_state), sizeof(value)); return value; } -void WriteFullTimeBaseValue(u64 value) +void PowerPCManager::WriteFullTimeBaseValue(u64 value) { - std::memcpy(&TL(PowerPC::ppcState), &value, sizeof(value)); + std::memcpy(&TL(m_ppc_state), &value, sizeof(value)); } void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst, @@ -478,9 +467,9 @@ void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst, } } -void CheckExceptions() +void PowerPCManager::CheckExceptions() { - u32 exceptions = ppcState.Exceptions; + u32 exceptions = m_ppc_state.Exceptions; // Example procedure: // Set SRR0 to either PC or NPC @@ -505,79 +494,79 @@ void CheckExceptions() if (exceptions & EXCEPTION_ISI) { - SRR0(PowerPC::ppcState) = PowerPC::ppcState.npc; + SRR0(m_ppc_state) = m_ppc_state.npc; // Page fault occurred - SRR1(PowerPC::ppcState) = (PowerPC::ppcState.msr.Hex & 0x87C0FFFF) | (1 << 30); - PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE; - PowerPC::ppcState.msr.Hex &= ~0x04EF36; - PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000400; + SRR1(m_ppc_state) = (m_ppc_state.msr.Hex & 0x87C0FFFF) | (1 << 30); + m_ppc_state.msr.LE = m_ppc_state.msr.ILE; + m_ppc_state.msr.Hex &= ~0x04EF36; + m_ppc_state.pc = m_ppc_state.npc = 0x00000400; DEBUG_LOG_FMT(POWERPC, "EXCEPTION_ISI"); - ppcState.Exceptions &= ~EXCEPTION_ISI; + m_ppc_state.Exceptions &= ~EXCEPTION_ISI; } else if (exceptions & EXCEPTION_PROGRAM) { - SRR0(PowerPC::ppcState) = PowerPC::ppcState.pc; + SRR0(m_ppc_state) = m_ppc_state.pc; // SRR1 was partially set by GenerateProgramException, so bitwise or is used here - SRR1(PowerPC::ppcState) |= PowerPC::ppcState.msr.Hex & 0x87C0FFFF; - PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE; - PowerPC::ppcState.msr.Hex &= ~0x04EF36; - PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000700; + SRR1(m_ppc_state) |= m_ppc_state.msr.Hex & 0x87C0FFFF; + m_ppc_state.msr.LE = m_ppc_state.msr.ILE; + m_ppc_state.msr.Hex &= ~0x04EF36; + m_ppc_state.pc = m_ppc_state.npc = 0x00000700; DEBUG_LOG_FMT(POWERPC, "EXCEPTION_PROGRAM"); - ppcState.Exceptions &= ~EXCEPTION_PROGRAM; + m_ppc_state.Exceptions &= ~EXCEPTION_PROGRAM; } else if (exceptions & EXCEPTION_SYSCALL) { - SRR0(PowerPC::ppcState) = PowerPC::ppcState.npc; - SRR1(PowerPC::ppcState) = PowerPC::ppcState.msr.Hex & 0x87C0FFFF; - PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE; - PowerPC::ppcState.msr.Hex &= ~0x04EF36; - PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000C00; + SRR0(m_ppc_state) = m_ppc_state.npc; + SRR1(m_ppc_state) = m_ppc_state.msr.Hex & 0x87C0FFFF; + m_ppc_state.msr.LE = m_ppc_state.msr.ILE; + m_ppc_state.msr.Hex &= ~0x04EF36; + m_ppc_state.pc = m_ppc_state.npc = 0x00000C00; - DEBUG_LOG_FMT(POWERPC, "EXCEPTION_SYSCALL (PC={:08x})", PowerPC::ppcState.pc); - ppcState.Exceptions &= ~EXCEPTION_SYSCALL; + DEBUG_LOG_FMT(POWERPC, "EXCEPTION_SYSCALL (PC={:08x})", m_ppc_state.pc); + m_ppc_state.Exceptions &= ~EXCEPTION_SYSCALL; } else if (exceptions & EXCEPTION_FPU_UNAVAILABLE) { // This happens a lot - GameCube OS uses deferred FPU context switching - SRR0(PowerPC::ppcState) = PowerPC::ppcState.pc; // re-execute the instruction - SRR1(PowerPC::ppcState) = PowerPC::ppcState.msr.Hex & 0x87C0FFFF; - PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE; - PowerPC::ppcState.msr.Hex &= ~0x04EF36; - PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000800; + SRR0(m_ppc_state) = m_ppc_state.pc; // re-execute the instruction + SRR1(m_ppc_state) = m_ppc_state.msr.Hex & 0x87C0FFFF; + m_ppc_state.msr.LE = m_ppc_state.msr.ILE; + m_ppc_state.msr.Hex &= ~0x04EF36; + m_ppc_state.pc = m_ppc_state.npc = 0x00000800; DEBUG_LOG_FMT(POWERPC, "EXCEPTION_FPU_UNAVAILABLE"); - ppcState.Exceptions &= ~EXCEPTION_FPU_UNAVAILABLE; + m_ppc_state.Exceptions &= ~EXCEPTION_FPU_UNAVAILABLE; } else if (exceptions & EXCEPTION_FAKE_MEMCHECK_HIT) { - ppcState.Exceptions &= ~EXCEPTION_DSI & ~EXCEPTION_FAKE_MEMCHECK_HIT; + m_ppc_state.Exceptions &= ~EXCEPTION_DSI & ~EXCEPTION_FAKE_MEMCHECK_HIT; } else if (exceptions & EXCEPTION_DSI) { - SRR0(PowerPC::ppcState) = PowerPC::ppcState.pc; - SRR1(PowerPC::ppcState) = PowerPC::ppcState.msr.Hex & 0x87C0FFFF; - PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE; - PowerPC::ppcState.msr.Hex &= ~0x04EF36; - PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000300; + SRR0(m_ppc_state) = m_ppc_state.pc; + SRR1(m_ppc_state) = m_ppc_state.msr.Hex & 0x87C0FFFF; + m_ppc_state.msr.LE = m_ppc_state.msr.ILE; + m_ppc_state.msr.Hex &= ~0x04EF36; + m_ppc_state.pc = m_ppc_state.npc = 0x00000300; // DSISR and DAR regs are changed in GenerateDSIException() DEBUG_LOG_FMT(POWERPC, "EXCEPTION_DSI"); - ppcState.Exceptions &= ~EXCEPTION_DSI; + m_ppc_state.Exceptions &= ~EXCEPTION_DSI; } else if (exceptions & EXCEPTION_ALIGNMENT) { - SRR0(PowerPC::ppcState) = PowerPC::ppcState.pc; - SRR1(PowerPC::ppcState) = PowerPC::ppcState.msr.Hex & 0x87C0FFFF; - PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE; - PowerPC::ppcState.msr.Hex &= ~0x04EF36; - PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000600; + SRR0(m_ppc_state) = m_ppc_state.pc; + SRR1(m_ppc_state) = m_ppc_state.msr.Hex & 0x87C0FFFF; + m_ppc_state.msr.LE = m_ppc_state.msr.ILE; + m_ppc_state.msr.Hex &= ~0x04EF36; + m_ppc_state.pc = m_ppc_state.npc = 0x00000600; // TODO crazy amount of DSISR options to check out DEBUG_LOG_FMT(POWERPC, "EXCEPTION_ALIGNMENT"); - ppcState.Exceptions &= ~EXCEPTION_ALIGNMENT; + m_ppc_state.Exceptions &= ~EXCEPTION_ALIGNMENT; } // EXTERNAL INTERRUPT @@ -587,50 +576,49 @@ void CheckExceptions() } } -void CheckExternalExceptions() +void PowerPCManager::CheckExternalExceptions() { - u32 exceptions = ppcState.Exceptions; + u32 exceptions = m_ppc_state.Exceptions; // EXTERNAL INTERRUPT // Handling is delayed until MSR.EE=1. - if (exceptions && PowerPC::ppcState.msr.EE) + if (exceptions && m_ppc_state.msr.EE) { if (exceptions & EXCEPTION_EXTERNAL_INT) { // Pokemon gets this "too early", it hasn't a handler yet - SRR0(PowerPC::ppcState) = PowerPC::ppcState.npc; - SRR1(PowerPC::ppcState) = PowerPC::ppcState.msr.Hex & 0x87C0FFFF; - PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE; - PowerPC::ppcState.msr.Hex &= ~0x04EF36; - PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000500; + SRR0(m_ppc_state) = m_ppc_state.npc; + SRR1(m_ppc_state) = m_ppc_state.msr.Hex & 0x87C0FFFF; + m_ppc_state.msr.LE = m_ppc_state.msr.ILE; + m_ppc_state.msr.Hex &= ~0x04EF36; + m_ppc_state.pc = m_ppc_state.npc = 0x00000500; DEBUG_LOG_FMT(POWERPC, "EXCEPTION_EXTERNAL_INT"); - ppcState.Exceptions &= ~EXCEPTION_EXTERNAL_INT; + m_ppc_state.Exceptions &= ~EXCEPTION_EXTERNAL_INT; - DEBUG_ASSERT_MSG(POWERPC, (SRR1(PowerPC::ppcState) & 0x02) != 0, - "EXTERNAL_INT unrecoverable???"); + DEBUG_ASSERT_MSG(POWERPC, (SRR1(m_ppc_state) & 0x02) != 0, "EXTERNAL_INT unrecoverable???"); } else if (exceptions & EXCEPTION_PERFORMANCE_MONITOR) { - SRR0(PowerPC::ppcState) = PowerPC::ppcState.npc; - SRR1(PowerPC::ppcState) = PowerPC::ppcState.msr.Hex & 0x87C0FFFF; - PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE; - PowerPC::ppcState.msr.Hex &= ~0x04EF36; - PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000F00; + SRR0(m_ppc_state) = m_ppc_state.npc; + SRR1(m_ppc_state) = m_ppc_state.msr.Hex & 0x87C0FFFF; + m_ppc_state.msr.LE = m_ppc_state.msr.ILE; + m_ppc_state.msr.Hex &= ~0x04EF36; + m_ppc_state.pc = m_ppc_state.npc = 0x00000F00; DEBUG_LOG_FMT(POWERPC, "EXCEPTION_PERFORMANCE_MONITOR"); - ppcState.Exceptions &= ~EXCEPTION_PERFORMANCE_MONITOR; + m_ppc_state.Exceptions &= ~EXCEPTION_PERFORMANCE_MONITOR; } else if (exceptions & EXCEPTION_DECREMENTER) { - SRR0(PowerPC::ppcState) = PowerPC::ppcState.npc; - SRR1(PowerPC::ppcState) = PowerPC::ppcState.msr.Hex & 0x87C0FFFF; - PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE; - PowerPC::ppcState.msr.Hex &= ~0x04EF36; - PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000900; + SRR0(m_ppc_state) = m_ppc_state.npc; + SRR1(m_ppc_state) = m_ppc_state.msr.Hex & 0x87C0FFFF; + m_ppc_state.msr.LE = m_ppc_state.msr.ILE; + m_ppc_state.msr.Hex &= ~0x04EF36; + m_ppc_state.pc = m_ppc_state.npc = 0x00000900; DEBUG_LOG_FMT(POWERPC, "EXCEPTION_DECREMENTER"); - ppcState.Exceptions &= ~EXCEPTION_DECREMENTER; + m_ppc_state.Exceptions &= ~EXCEPTION_DECREMENTER; } else { @@ -641,17 +629,16 @@ void CheckExternalExceptions() } } -void CheckBreakPoints() +void PowerPCManager::CheckBreakPoints() { - const TBreakPoint* bp = PowerPC::breakpoints.GetBreakpoint(PowerPC::ppcState.pc); + const TBreakPoint* bp = m_breakpoints.GetBreakpoint(m_ppc_state.pc); - if (!bp || !bp->is_enabled || !EvaluateCondition(bp->condition)) + if (!bp || !bp->is_enabled || !EvaluateCondition(m_system, bp->condition)) return; if (bp->break_on_hit) { - auto& system = Core::System::GetInstance(); - system.GetCPU().Break(); + m_system.GetCPU().Break(); if (GDBStub::IsActive()) GDBStub::TakeControl(); } @@ -660,14 +647,13 @@ void CheckBreakPoints() NOTICE_LOG_FMT(MEMMAP, "BP {:08x} {}({:08x} {:08x} {:08x} {:08x} {:08x} {:08x} {:08x} {:08x} {:08x} " "{:08x}) LR={:08x}", - PowerPC::ppcState.pc, g_symbolDB.GetDescription(PowerPC::ppcState.pc), - PowerPC::ppcState.gpr[3], PowerPC::ppcState.gpr[4], PowerPC::ppcState.gpr[5], - PowerPC::ppcState.gpr[6], PowerPC::ppcState.gpr[7], PowerPC::ppcState.gpr[8], - PowerPC::ppcState.gpr[9], PowerPC::ppcState.gpr[10], PowerPC::ppcState.gpr[11], - PowerPC::ppcState.gpr[12], LR(PowerPC::ppcState)); + m_ppc_state.pc, g_symbolDB.GetDescription(m_ppc_state.pc), m_ppc_state.gpr[3], + m_ppc_state.gpr[4], m_ppc_state.gpr[5], m_ppc_state.gpr[6], m_ppc_state.gpr[7], + m_ppc_state.gpr[8], m_ppc_state.gpr[9], m_ppc_state.gpr[10], m_ppc_state.gpr[11], + m_ppc_state.gpr[12], LR(m_ppc_state)); } - if (PowerPC::breakpoints.IsTempBreakPoint(PowerPC::ppcState.pc)) - PowerPC::breakpoints.Remove(PowerPC::ppcState.pc); + if (m_breakpoints.IsTempBreakPoint(m_ppc_state.pc)) + m_breakpoints.Remove(m_ppc_state.pc); } void PowerPCState::SetSR(u32 index, u32 value) @@ -688,12 +674,26 @@ void PowerPCState::UpdateFPRFSingle(float fvalue) fpscr.FPRF = Common::ClassifyFloat(fvalue); } -void RoundingModeUpdated() +void RoundingModeUpdated(PowerPCState& ppc_state) { // The rounding mode is separate for each thread, so this must run on the CPU thread ASSERT(Core::IsCPUThread()); - Common::FPU::SetSIMDMode(PowerPC::ppcState.fpscr.RN, PowerPC::ppcState.fpscr.NI); + Common::FPU::SetSIMDMode(ppc_state.fpscr.RN, ppc_state.fpscr.NI); } +void CheckExceptionsFromJIT(PowerPCManager& power_pc) +{ + power_pc.CheckExceptions(); +} + +void CheckExternalExceptionsFromJIT(PowerPCManager& power_pc) +{ + power_pc.CheckExternalExceptions(); +} + +void CheckBreakPointsFromJIT(PowerPCManager& power_pc) +{ + power_pc.CheckBreakPoints(); +} } // namespace PowerPC diff --git a/Source/Core/Core/PowerPC/PowerPC.h b/Source/Core/Core/PowerPC/PowerPC.h index 53697cd0ef..42545f2c1f 100644 --- a/Source/Core/Core/PowerPC/PowerPC.h +++ b/Source/Core/Core/PowerPC/PowerPC.h @@ -20,6 +20,10 @@ class CPUCoreBase; class PointerWrap; +namespace CoreTiming +{ +struct EventType; +} namespace PowerPC { @@ -234,49 +238,86 @@ static_assert(offsetof(PowerPC::PowerPCState, above_fits_in_first_0x100) <= 0x10 #endif #endif -extern PowerPCState ppcState; - -extern BreakPoints breakpoints; -extern MemChecks memchecks; -extern PPCDebugInterface debug_interface; - const std::vector& AvailableCPUCores(); CPUCore DefaultCPUCore(); -void Init(CPUCore cpu_core); -void Reset(); -void Shutdown(); -void DoState(PointerWrap& p); -void ScheduleInvalidateCacheThreadSafe(u32 address); +class PowerPCManager +{ +public: + explicit PowerPCManager(Core::System& system); + PowerPCManager(const PowerPCManager& other) = delete; + PowerPCManager(PowerPCManager&& other) = delete; + PowerPCManager& operator=(const PowerPCManager& other) = delete; + PowerPCManager& operator=(PowerPCManager&& other) = delete; + ~PowerPCManager(); -CoreMode GetMode(); -// [NOT THREADSAFE] CPU Thread or CPU::PauseAndLock or Core::State::Uninitialized -void SetMode(CoreMode _coreType); -const char* GetCPUName(); + void Init(CPUCore cpu_core); + void Reset(); + void Shutdown(); + void DoState(PointerWrap& p); + void ScheduleInvalidateCacheThreadSafe(u32 address); -// Set the current CPU Core to the given implementation until removed. -// Remove the current injected CPU Core by passing nullptr. -// While an external CPUCoreBase is injected, GetMode() will return CoreMode::Interpreter. -// Init() will be called when added and Shutdown() when removed. -// [Threadsafety: Same as SetMode(), except it cannot be called from inside the CPU -// run loop on the CPU Thread - it doesn't make sense for a CPU to remove itself -// while it is in State::Running] -void InjectExternalCPUCore(CPUCoreBase* core); + CoreMode GetMode() const; + // [NOT THREADSAFE] CPU Thread or CPU::PauseAndLock or Core::State::Uninitialized + void SetMode(CoreMode _coreType); + const char* GetCPUName() const; -// Stepping requires the CPU Execution lock (CPU::PauseAndLock or CPU Thread) -// It's not threadsafe otherwise. -void SingleStep(); -void CheckExceptions(); -void CheckExternalExceptions(); -void CheckBreakPoints(); -void RunLoop(); + // Set the current CPU Core to the given implementation until removed. + // Remove the current injected CPU Core by passing nullptr. + // While an external CPUCoreBase is injected, GetMode() will return CoreMode::Interpreter. + // Init() will be called when added and Shutdown() when removed. + // [Threadsafety: Same as SetMode(), except it cannot be called from inside the CPU + // run loop on the CPU Thread - it doesn't make sense for a CPU to remove itself + // while it is in State::Running] + void InjectExternalCPUCore(CPUCoreBase* core); -u64 ReadFullTimeBaseValue(); -void WriteFullTimeBaseValue(u64 value); + // Stepping requires the CPU Execution lock (CPU::PauseAndLock or CPU Thread) + // It's not threadsafe otherwise. + void SingleStep(); + void CheckExceptions(); + void CheckExternalExceptions(); + void CheckBreakPoints(); + void RunLoop(); + + u64 ReadFullTimeBaseValue() const; + void WriteFullTimeBaseValue(u64 value); + + PowerPCState& GetPPCState() { return m_ppc_state; } + const PowerPCState& GetPPCState() const { return m_ppc_state; } + BreakPoints& GetBreakPoints() { return m_breakpoints; } + const BreakPoints& GetBreakPoints() const { return m_breakpoints; } + MemChecks& GetMemChecks() { return m_memchecks; } + const MemChecks& GetMemChecks() const { return m_memchecks; } + PPCDebugInterface& GetDebugInterface() { return m_debug_interface; } + const PPCDebugInterface& GetDebugInterface() const { return m_debug_interface; } + +private: + void InitializeCPUCore(CPUCore cpu_core); + void ApplyMode(); + void ResetRegisters(); + + PowerPCState m_ppc_state; + + CPUCoreBase* m_cpu_core_base = nullptr; + bool m_cpu_core_base_is_injected = false; + CoreMode m_mode = CoreMode::Interpreter; + + BreakPoints m_breakpoints; + MemChecks m_memchecks; + PPCDebugInterface m_debug_interface; + + CoreTiming::EventType* m_invalidate_cache_thread_safe = nullptr; + + Core::System& m_system; +}; void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst, PowerPCState& ppc_state); +void CheckExceptionsFromJIT(PowerPCManager& power_pc); +void CheckExternalExceptionsFromJIT(PowerPCManager& power_pc); +void CheckBreakPointsFromJIT(PowerPCManager& power_pc); + // Easy register access macros. #define HID0(ppc_state) ((UReg_HID0&)(ppc_state).spr[SPR_HID0]) #define HID2(ppc_state) ((UReg_HID2&)(ppc_state).spr[SPR_HID2]) @@ -297,6 +338,6 @@ void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst, #define TL(ppc_state) (ppc_state).spr[SPR_TL] #define TU(ppc_state) (ppc_state).spr[SPR_TU] -void RoundingModeUpdated(); +void RoundingModeUpdated(PowerPCState& ppc_state); } // namespace PowerPC diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index e8ab5a85ab..a82da71663 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -233,7 +233,7 @@ static void DoState(PointerWrap& p) HW::DoState(system, p); p.DoMarker("HW"); - PowerPC::DoState(p); + system.GetPowerPC().DoState(p); p.DoMarker("PowerPC"); if (SConfig::GetInstance().bWii) diff --git a/Source/Core/Core/System.cpp b/Source/Core/Core/System.cpp index 438b3c3014..33fb4a862f 100644 --- a/Source/Core/Core/System.cpp +++ b/Source/Core/Core/System.cpp @@ -38,11 +38,12 @@ namespace Core struct System::Impl { explicit Impl(System& system) - : m_audio_interface(system), m_core_timing(system), m_dsp(system), m_dvd_interface(system), - m_dvd_thread(system), m_expansion_interface(system), m_gp_fifo(system), m_memory(system), - m_ppc_state(PowerPC::ppcState), m_mmu(system, m_memory, m_ppc_state), - m_processor_interface(system), m_serial_interface(system), m_video_interface(system), - m_interpreter(system, m_ppc_state, m_mmu), m_jit_interface(system) + : m_audio_interface(system), m_core_timing(system), m_cpu(system), m_dsp(system), + m_dvd_interface(system), m_dvd_thread(system), m_expansion_interface(system), + m_gp_fifo(system), m_memory(system), m_power_pc(system), + m_mmu(system, m_memory, m_power_pc), m_processor_interface(system), + m_serial_interface(system), m_video_interface(system), + m_interpreter(system, m_power_pc.GetPPCState(), m_mmu), m_jit_interface(system) { } @@ -67,7 +68,7 @@ struct System::Impl MemoryInterface::MemoryInterfaceManager m_memory_interface; PixelEngine::PixelEngineManager m_pixel_engine; PixelShaderManager m_pixel_shader_manager; - PowerPC::PowerPCState& m_ppc_state; + PowerPC::PowerPCManager m_power_pc; PowerPC::MMU m_mmu; ProcessorInterface::ProcessorInterfaceManager m_processor_interface; SerialInterface::SerialInterfaceManager m_serial_interface; @@ -221,9 +222,14 @@ PixelShaderManager& System::GetPixelShaderManager() const return m_impl->m_pixel_shader_manager; } +PowerPC::PowerPCManager& System::GetPowerPC() const +{ + return m_impl->m_power_pc; +} + PowerPC::PowerPCState& System::GetPPCState() const { - return m_impl->m_ppc_state; + return m_impl->m_power_pc.GetPPCState(); } ProcessorInterface::ProcessorInterfaceManager& System::GetProcessorInterface() const diff --git a/Source/Core/Core/System.h b/Source/Core/Core/System.h index 6a6375f0d9..630be2abe7 100644 --- a/Source/Core/Core/System.h +++ b/Source/Core/Core/System.h @@ -73,6 +73,7 @@ class PixelEngineManager; namespace PowerPC { class MMU; +class PowerPCManager; struct PowerPCState; } // namespace PowerPC namespace ProcessorInterface @@ -142,6 +143,7 @@ public: PowerPC::MMU& GetMMU() const; PixelEngine::PixelEngineManager& GetPixelEngine() const; PixelShaderManager& GetPixelShaderManager() const; + PowerPC::PowerPCManager& GetPowerPC() const; PowerPC::PowerPCState& GetPPCState() const; ProcessorInterface::ProcessorInterfaceManager& GetProcessorInterface() const; SerialInterface::SerialInterfaceManager& GetSerialInterface() const; diff --git a/Source/Core/DolphinLib.props b/Source/Core/DolphinLib.props index 44048669a6..8a463f5a5e 100644 --- a/Source/Core/DolphinLib.props +++ b/Source/Core/DolphinLib.props @@ -42,7 +42,7 @@ - + @@ -753,7 +753,7 @@ - + @@ -773,7 +773,6 @@ - diff --git a/Source/Core/DolphinNoGUI/PlatformWin32.cpp b/Source/Core/DolphinNoGUI/PlatformWin32.cpp index a34ace70ce..4b5e5aa1ef 100644 --- a/Source/Core/DolphinNoGUI/PlatformWin32.cpp +++ b/Source/Core/DolphinNoGUI/PlatformWin32.cpp @@ -62,12 +62,12 @@ bool PlatformWin32::RegisterRenderWindowClass() wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = GetModuleHandle(nullptr); - wc.hIcon = LoadIcon(NULL, IDI_ICON1); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hIcon = LoadIcon(nullptr, IDI_ICON1); + wc.hCursor = LoadCursor(nullptr, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); - wc.lpszMenuName = NULL; + wc.lpszMenuName = nullptr; wc.lpszClassName = WINDOW_CLASS_NAME; - wc.hIconSm = LoadIcon(NULL, IDI_ICON1); + wc.hIconSm = LoadIcon(nullptr, IDI_ICON1); if (!RegisterClassEx(&wc)) { diff --git a/Source/Core/DolphinQt/CMakeLists.txt b/Source/Core/DolphinQt/CMakeLists.txt index 36693b83bc..f4bbaf268d 100644 --- a/Source/Core/DolphinQt/CMakeLists.txt +++ b/Source/Core/DolphinQt/CMakeLists.txt @@ -69,8 +69,6 @@ add_executable(dolphin-emu Config/GeckoCodeWidget.h Config/Graphics/AdvancedWidget.cpp Config/Graphics/AdvancedWidget.h - Config/Graphics/BalloonTip.cpp - Config/Graphics/BalloonTip.h Config/Graphics/EnhancementsWidget.cpp Config/Graphics/EnhancementsWidget.h Config/Graphics/GeneralWidget.cpp @@ -169,6 +167,8 @@ add_executable(dolphin-emu Config/PropertiesDialog.h Config/SettingsWindow.cpp Config/SettingsWindow.h + Config/ToolTipControls/BalloonTip.cpp + Config/ToolTipControls/BalloonTip.h Config/ToolTipControls/ToolTipCheckBox.cpp Config/ToolTipControls/ToolTipCheckBox.h Config/ToolTipControls/ToolTipComboBox.cpp diff --git a/Source/Core/DolphinQt/Config/ARCodeWidget.cpp b/Source/Core/DolphinQt/Config/ARCodeWidget.cpp index f201dcce9d..6a18a16937 100644 --- a/Source/Core/DolphinQt/Config/ARCodeWidget.cpp +++ b/Source/Core/DolphinQt/Config/ARCodeWidget.cpp @@ -33,13 +33,14 @@ ARCodeWidget::ARCodeWidget(std::string game_id, u16 game_revision, bool restart_ if (!m_game_id.empty()) { - IniFile game_ini_local; + Common::IniFile game_ini_local; // We don't use LoadLocalGameIni() here because user cheat codes that are installed via the UI // will always be stored in GS/${GAMEID}.ini game_ini_local.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini"); - const IniFile game_ini_default = SConfig::LoadDefaultGameIni(m_game_id, m_game_revision); + const Common::IniFile game_ini_default = + SConfig::LoadDefaultGameIni(m_game_id, m_game_revision); m_ar_codes = ActionReplay::LoadCodes(game_ini_default, game_ini_local); } @@ -185,7 +186,7 @@ void ARCodeWidget::SaveCodes() const auto ini_path = std::string(File::GetUserPath(D_GAMESETTINGS_IDX)).append(m_game_id).append(".ini"); - IniFile game_ini_local; + Common::IniFile game_ini_local; game_ini_local.Load(ini_path); ActionReplay::SaveCodes(&game_ini_local, m_ar_codes); game_ini_local.Save(ini_path); diff --git a/Source/Core/DolphinQt/Config/GameConfigWidget.h b/Source/Core/DolphinQt/Config/GameConfigWidget.h index f71ccbccd9..44ae2375f5 100644 --- a/Source/Core/DolphinQt/Config/GameConfigWidget.h +++ b/Source/Core/DolphinQt/Config/GameConfigWidget.h @@ -63,6 +63,6 @@ private: const UICommon::GameFile& m_game; std::string m_game_id; - IniFile m_gameini_local; - IniFile m_gameini_default; + Common::IniFile m_gameini_local; + Common::IniFile m_gameini_default; }; diff --git a/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp b/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp index d3fc411498..b94a544424 100644 --- a/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp +++ b/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp @@ -40,13 +40,14 @@ GeckoCodeWidget::GeckoCodeWidget(std::string game_id, std::string gametdb_id, u1 if (!m_game_id.empty()) { - IniFile game_ini_local; + Common::IniFile game_ini_local; // We don't use LoadLocalGameIni() here because user cheat codes that are installed via the UI // will always be stored in GS/${GAMEID}.ini game_ini_local.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini"); - const IniFile game_ini_default = SConfig::LoadDefaultGameIni(m_game_id, m_game_revision); + const Common::IniFile game_ini_default = + SConfig::LoadDefaultGameIni(m_game_id, m_game_revision); m_gecko_codes = Gecko::LoadCodes(game_ini_default, game_ini_local); } @@ -245,7 +246,7 @@ void GeckoCodeWidget::SaveCodes() const auto ini_path = std::string(File::GetUserPath(D_GAMESETTINGS_IDX)).append(m_game_id).append(".ini"); - IniFile game_ini_local; + Common::IniFile game_ini_local; game_ini_local.Load(ini_path); Gecko::SaveCodes(game_ini_local, m_gecko_codes); game_ini_local.Save(ini_path); diff --git a/Source/Core/DolphinQt/Config/Graphics/GraphicsBool.cpp b/Source/Core/DolphinQt/Config/Graphics/GraphicsBool.cpp index ceb459c57a..33ca546f48 100644 --- a/Source/Core/DolphinQt/Config/Graphics/GraphicsBool.cpp +++ b/Source/Core/DolphinQt/Config/Graphics/GraphicsBool.cpp @@ -9,7 +9,6 @@ #include "Common/Config/Config.h" -#include "DolphinQt/Config/Graphics/BalloonTip.h" #include "DolphinQt/Settings.h" GraphicsBool::GraphicsBool(const QString& label, const Config::Info& setting, bool reverse) @@ -32,23 +31,3 @@ void GraphicsBool::Update() { Config::SetBaseOrCurrent(m_setting, static_cast(isChecked() ^ m_reverse)); } - -GraphicsBoolEx::GraphicsBoolEx(const QString& label, const Config::Info& setting, - bool reverse) - : ToolTipRadioButton(label), m_setting(setting), m_reverse(reverse) -{ - connect(this, &QCheckBox::toggled, this, &GraphicsBoolEx::Update); - setChecked(Config::Get(m_setting) ^ reverse); - - if (Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base) - { - QFont bf = font(); - bf.setBold(true); - setFont(bf); - } -} - -void GraphicsBoolEx::Update() -{ - Config::SetBaseOrCurrent(m_setting, static_cast(isChecked() ^ m_reverse)); -} diff --git a/Source/Core/DolphinQt/Config/Graphics/GraphicsBool.h b/Source/Core/DolphinQt/Config/Graphics/GraphicsBool.h index c71bccfcd3..2a98971bfe 100644 --- a/Source/Core/DolphinQt/Config/Graphics/GraphicsBool.h +++ b/Source/Core/DolphinQt/Config/Graphics/GraphicsBool.h @@ -4,7 +4,6 @@ #pragma once #include "DolphinQt/Config/ToolTipControls/ToolTipCheckBox.h" -#include "DolphinQt/Config/ToolTipControls/ToolTipRadioButton.h" namespace Config { @@ -24,16 +23,3 @@ private: const Config::Info& m_setting; bool m_reverse; }; - -class GraphicsBoolEx : public ToolTipRadioButton -{ - Q_OBJECT -public: - GraphicsBoolEx(const QString& label, const Config::Info& setting, bool reverse = false); - -private: - void Update(); - - const Config::Info& m_setting; - bool m_reverse; -}; diff --git a/Source/Core/DolphinQt/Config/Mapping/MappingWindow.cpp b/Source/Core/DolphinQt/Config/Mapping/MappingWindow.cpp index c04d41280d..bb1a00d88d 100644 --- a/Source/Core/DolphinQt/Config/Mapping/MappingWindow.cpp +++ b/Source/Core/DolphinQt/Config/Mapping/MappingWindow.cpp @@ -299,7 +299,7 @@ void MappingWindow::OnLoadProfilePressed() const QString profile_path = m_profiles_combo->currentData().toString(); - IniFile ini; + Common::IniFile ini; ini.Load(profile_path.toStdString()); m_controller->LoadConfig(ini.GetOrCreateSection("Profile")); @@ -322,7 +322,7 @@ void MappingWindow::OnSaveProfilePressed() File::CreateFullPath(profile_path); - IniFile ini; + Common::IniFile ini; m_controller->SaveConfig(ini.GetOrCreateSection("Profile")); ini.Save(profile_path); @@ -542,7 +542,7 @@ void MappingWindow::OnDefaultFieldsPressed() void MappingWindow::OnClearFieldsPressed() { // Loading an empty inifile section clears everything. - IniFile::Section sec; + Common::IniFile::Section sec; // Keep the currently selected device. const auto default_device = m_controller->GetDefaultDevice(); diff --git a/Source/Core/DolphinQt/Config/PatchesWidget.cpp b/Source/Core/DolphinQt/Config/PatchesWidget.cpp index 2c08d932c0..a8abbf72ba 100644 --- a/Source/Core/DolphinQt/Config/PatchesWidget.cpp +++ b/Source/Core/DolphinQt/Config/PatchesWidget.cpp @@ -21,10 +21,11 @@ PatchesWidget::PatchesWidget(const UICommon::GameFile& game) : m_game_id(game.GetGameID()), m_game_revision(game.GetRevision()) { - IniFile game_ini_local; + Common::IniFile game_ini_local; game_ini_local.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini"); - IniFile game_ini_default = SConfig::GetInstance().LoadDefaultGameIni(m_game_id, m_game_revision); + Common::IniFile game_ini_default = + SConfig::GetInstance().LoadDefaultGameIni(m_game_id, m_game_revision); PatchEngine::LoadPatchSection("OnFrame", &m_patches, game_ini_default, game_ini_local); @@ -128,7 +129,7 @@ void PatchesWidget::SavePatches() { const std::string ini_path = File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini"; - IniFile game_ini_local; + Common::IniFile game_ini_local; game_ini_local.Load(ini_path); PatchEngine::SavePatchSection(&game_ini_local, m_patches); game_ini_local.Save(ini_path); diff --git a/Source/Core/DolphinQt/Config/Graphics/BalloonTip.cpp b/Source/Core/DolphinQt/Config/ToolTipControls/BalloonTip.cpp similarity index 99% rename from Source/Core/DolphinQt/Config/Graphics/BalloonTip.cpp rename to Source/Core/DolphinQt/Config/ToolTipControls/BalloonTip.cpp index 174745258e..7f5516bbd2 100644 --- a/Source/Core/DolphinQt/Config/Graphics/BalloonTip.cpp +++ b/Source/Core/DolphinQt/Config/ToolTipControls/BalloonTip.cpp @@ -1,7 +1,7 @@ // Copyright 2020 Dolphin Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "DolphinQt/Config/Graphics/BalloonTip.h" +#include "DolphinQt/Config/ToolTipControls/BalloonTip.h" #include diff --git a/Source/Core/DolphinQt/Config/Graphics/BalloonTip.h b/Source/Core/DolphinQt/Config/ToolTipControls/BalloonTip.h similarity index 100% rename from Source/Core/DolphinQt/Config/Graphics/BalloonTip.h rename to Source/Core/DolphinQt/Config/ToolTipControls/BalloonTip.h diff --git a/Source/Core/DolphinQt/Config/ToolTipControls/ToolTipWidget.h b/Source/Core/DolphinQt/Config/ToolTipControls/ToolTipWidget.h index bd4b0fb6a2..6e3658e8bb 100644 --- a/Source/Core/DolphinQt/Config/ToolTipControls/ToolTipWidget.h +++ b/Source/Core/DolphinQt/Config/ToolTipControls/ToolTipWidget.h @@ -7,7 +7,7 @@ #include -#include "DolphinQt/Config/Graphics/BalloonTip.h" +#include "DolphinQt/Config/ToolTipControls/BalloonTip.h" constexpr int TOOLTIP_DELAY = 300; diff --git a/Source/Core/DolphinQt/Debugger/BreakpointWidget.cpp b/Source/Core/DolphinQt/Debugger/BreakpointWidget.cpp index 019494491b..2412bef831 100644 --- a/Source/Core/DolphinQt/Debugger/BreakpointWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/BreakpointWidget.cpp @@ -18,6 +18,7 @@ #include "Core/PowerPC/Expression.h" #include "Core/PowerPC/PPCSymbolDB.h" #include "Core/PowerPC/PowerPC.h" +#include "Core/System.h" #include "DolphinQt/Debugger/BreakpointDialog.h" #include "DolphinQt/Debugger/MemoryWidget.h" @@ -34,7 +35,8 @@ enum CustomRole }; } -BreakpointWidget::BreakpointWidget(QWidget* parent) : QDockWidget(parent) +BreakpointWidget::BreakpointWidget(QWidget* parent) + : QDockWidget(parent), m_system(Core::System::GetInstance()) { setWindowTitle(tr("Breakpoints")); setObjectName(QStringLiteral("breakpoints")); @@ -172,8 +174,12 @@ void BreakpointWidget::Update() return item; }; + auto& power_pc = m_system.GetPowerPC(); + auto& breakpoints = power_pc.GetBreakPoints(); + auto& memchecks = power_pc.GetMemChecks(); + // Breakpoints - for (const auto& bp : PowerPC::breakpoints.GetBreakPoints()) + for (const auto& bp : breakpoints.GetBreakPoints()) { m_table->setRowCount(i + 1); @@ -215,7 +221,7 @@ void BreakpointWidget::Update() } // Memory Breakpoints - for (const auto& mbp : PowerPC::memchecks.GetMemChecks()) + for (const auto& mbp : memchecks.GetMemChecks()) { m_table->setRowCount(i + 1); auto* active = @@ -279,11 +285,11 @@ void BreakpointWidget::OnDelete() if (is_memcheck) { const QSignalBlocker blocker(Settings::Instance()); - PowerPC::memchecks.Remove(address); + m_system.GetPowerPC().GetMemChecks().Remove(address); } else { - PowerPC::breakpoints.Remove(address); + m_system.GetPowerPC().GetBreakPoints().Remove(address); } emit BreakpointsChanged(); @@ -292,10 +298,10 @@ void BreakpointWidget::OnDelete() void BreakpointWidget::OnClear() { - PowerPC::debug_interface.ClearAllBreakpoints(); + m_system.GetPowerPC().GetDebugInterface().ClearAllBreakpoints(); { const QSignalBlocker blocker(Settings::Instance()); - PowerPC::debug_interface.ClearAllMemChecks(); + m_system.GetPowerPC().GetDebugInterface().ClearAllMemChecks(); } m_table->setRowCount(0); @@ -314,12 +320,14 @@ void BreakpointWidget::OnEditBreakpoint(u32 address, bool is_instruction_bp) { if (is_instruction_bp) { - auto* dialog = new BreakpointDialog(this, PowerPC::breakpoints.GetBreakpoint(address)); + auto* dialog = + new BreakpointDialog(this, m_system.GetPowerPC().GetBreakPoints().GetBreakpoint(address)); dialog->exec(); } else { - auto* dialog = new BreakpointDialog(this, PowerPC::memchecks.GetMemCheck(address)); + auto* dialog = + new BreakpointDialog(this, m_system.GetPowerPC().GetMemChecks().GetMemCheck(address)); dialog->exec(); } @@ -329,7 +337,7 @@ void BreakpointWidget::OnEditBreakpoint(u32 address, bool is_instruction_bp) void BreakpointWidget::OnLoad() { - IniFile ini; + Common::IniFile ini; if (!ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().GetGameID() + ".ini", false)) { @@ -339,16 +347,18 @@ void BreakpointWidget::OnLoad() BreakPoints::TBreakPointsStr new_bps; if (ini.GetLines("BreakPoints", &new_bps, false)) { - PowerPC::breakpoints.Clear(); - PowerPC::breakpoints.AddFromStrings(new_bps); + auto& breakpoints = m_system.GetPowerPC().GetBreakPoints(); + breakpoints.Clear(); + breakpoints.AddFromStrings(new_bps); } MemChecks::TMemChecksStr new_mcs; if (ini.GetLines("MemoryBreakPoints", &new_mcs, false)) { - PowerPC::memchecks.Clear(); + auto& memchecks = m_system.GetPowerPC().GetMemChecks(); + memchecks.Clear(); const QSignalBlocker blocker(Settings::Instance()); - PowerPC::memchecks.AddFromStrings(new_mcs); + memchecks.AddFromStrings(new_mcs); } emit BreakpointsChanged(); @@ -357,11 +367,11 @@ void BreakpointWidget::OnLoad() void BreakpointWidget::OnSave() { - IniFile ini; + Common::IniFile ini; ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().GetGameID() + ".ini", false); - ini.SetLines("BreakPoints", PowerPC::breakpoints.GetStrings()); - ini.SetLines("MemoryBreakPoints", PowerPC::memchecks.GetStrings()); + ini.SetLines("BreakPoints", m_system.GetPowerPC().GetBreakPoints().GetStrings()); + ini.SetLines("MemoryBreakPoints", m_system.GetPowerPC().GetMemChecks().GetStrings()); ini.Save(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().GetGameID() + ".ini"); } @@ -381,7 +391,7 @@ void BreakpointWidget::OnContextMenu() if (!is_memory_breakpoint) { - const auto& inst_breakpoints = PowerPC::breakpoints.GetBreakPoints(); + const auto& inst_breakpoints = m_system.GetPowerPC().GetBreakPoints().GetBreakPoints(); const auto bp_iter = std::find_if(inst_breakpoints.begin(), inst_breakpoints.end(), [bp_address](const auto& bp) { return bp.address == bp_address; }); @@ -390,7 +400,7 @@ void BreakpointWidget::OnContextMenu() menu->addAction(tr("Show in Code"), [this, bp_address] { emit ShowCode(bp_address); }); menu->addAction(bp_iter->is_enabled ? tr("Disable") : tr("Enable"), [this, &bp_address]() { - PowerPC::breakpoints.ToggleBreakPoint(bp_address); + m_system.GetPowerPC().GetBreakPoints().ToggleBreakPoint(bp_address); emit BreakpointsChanged(); Update(); @@ -398,7 +408,7 @@ void BreakpointWidget::OnContextMenu() } else { - const auto& memory_breakpoints = PowerPC::memchecks.GetMemChecks(); + const auto& memory_breakpoints = m_system.GetPowerPC().GetMemChecks().GetMemChecks(); const auto mb_iter = std::find_if(memory_breakpoints.begin(), memory_breakpoints.end(), [bp_address](const auto& bp) { return bp.start_address == bp_address; }); @@ -407,7 +417,7 @@ void BreakpointWidget::OnContextMenu() menu->addAction(tr("Show in Memory"), [this, bp_address] { emit ShowMemory(bp_address); }); menu->addAction(mb_iter->is_enabled ? tr("Disable") : tr("Enable"), [this, &bp_address]() { - PowerPC::memchecks.ToggleBreakPoint(bp_address); + m_system.GetPowerPC().GetMemChecks().ToggleBreakPoint(bp_address); emit BreakpointsChanged(); Update(); @@ -428,7 +438,7 @@ void BreakpointWidget::AddBP(u32 addr) void BreakpointWidget::AddBP(u32 addr, bool temp, bool break_on_hit, bool log_on_hit, const QString& condition) { - PowerPC::breakpoints.Add( + m_system.GetPowerPC().GetBreakPoints().Add( addr, temp, break_on_hit, log_on_hit, !condition.isEmpty() ? Expression::TryParse(condition.toUtf8().constData()) : std::nullopt); @@ -452,7 +462,7 @@ void BreakpointWidget::AddAddressMBP(u32 addr, bool on_read, bool on_write, bool !condition.isEmpty() ? Expression::TryParse(condition.toUtf8().constData()) : std::nullopt; { const QSignalBlocker blocker(Settings::Instance()); - PowerPC::memchecks.Add(std::move(check)); + m_system.GetPowerPC().GetMemChecks().Add(std::move(check)); } emit BreakpointsChanged(); @@ -475,7 +485,7 @@ void BreakpointWidget::AddRangedMBP(u32 from, u32 to, bool on_read, bool on_writ !condition.isEmpty() ? Expression::TryParse(condition.toUtf8().constData()) : std::nullopt; { const QSignalBlocker blocker(Settings::Instance()); - PowerPC::memchecks.Add(std::move(check)); + m_system.GetPowerPC().GetMemChecks().Add(std::move(check)); } emit BreakpointsChanged(); diff --git a/Source/Core/DolphinQt/Debugger/BreakpointWidget.h b/Source/Core/DolphinQt/Debugger/BreakpointWidget.h index bff6d2b883..587366c1d0 100644 --- a/Source/Core/DolphinQt/Debugger/BreakpointWidget.h +++ b/Source/Core/DolphinQt/Debugger/BreakpointWidget.h @@ -12,6 +12,10 @@ class QCloseEvent; class QShowEvent; class QTableWidget; class QToolBar; +namespace Core +{ +class System; +} class BreakpointWidget : public QDockWidget { @@ -51,6 +55,8 @@ private: void UpdateIcons(); + Core::System& m_system; + QToolBar* m_toolbar; QTableWidget* m_table; QAction* m_new; diff --git a/Source/Core/DolphinQt/Debugger/CodeDiffDialog.cpp b/Source/Core/DolphinQt/Debugger/CodeDiffDialog.cpp index 11f2a9a287..533fa5e55f 100644 --- a/Source/Core/DolphinQt/Debugger/CodeDiffDialog.cpp +++ b/Source/Core/DolphinQt/Debugger/CodeDiffDialog.cpp @@ -487,8 +487,9 @@ void CodeDiffDialog::OnSetBLR() return; { - Core::CPUThreadGuard guard(Core::System::GetInstance()); - PowerPC::debug_interface.SetPatch(guard, symbol->address, 0x4E800020); + auto& system = Core::System::GetInstance(); + Core::CPUThreadGuard guard(system); + system.GetPowerPC().GetDebugInterface().SetPatch(guard, symbol->address, 0x4E800020); } int row = item->row(); diff --git a/Source/Core/DolphinQt/Debugger/CodeViewWidget.cpp b/Source/Core/DolphinQt/Debugger/CodeViewWidget.cpp index f954f57ccc..312cc1f190 100644 --- a/Source/Core/DolphinQt/Debugger/CodeViewWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/CodeViewWidget.cpp @@ -135,7 +135,7 @@ constexpr int CODE_VIEW_COLUMN_DESCRIPTION = 4; constexpr int CODE_VIEW_COLUMN_BRANCH_ARROWS = 5; constexpr int CODE_VIEW_COLUMNCOUNT = 6; -CodeViewWidget::CodeViewWidget() +CodeViewWidget::CodeViewWidget() : m_system(Core::System::GetInstance()) { setColumnCount(CODE_VIEW_COLUMNCOUNT); setShowGrid(false); @@ -168,11 +168,11 @@ CodeViewWidget::CodeViewWidget() &CodeViewWidget::FontBasedSizing); connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, [this] { - m_address = PowerPC::ppcState.pc; + m_address = m_system.GetPPCState().pc; Update(); }); connect(Host::GetInstance(), &Host::UpdateDisasmDialog, this, [this] { - m_address = PowerPC::ppcState.pc; + m_address = m_system.GetPPCState().pc; Update(); }); @@ -184,7 +184,7 @@ CodeViewWidget::~CodeViewWidget() = default; static u32 GetBranchFromAddress(const Core::CPUThreadGuard& guard, u32 addr) { - std::string disasm = PowerPC::debug_interface.Disassemble(&guard, addr); + std::string disasm = guard.GetSystem().GetPowerPC().GetDebugInterface().Disassemble(&guard, addr); size_t pos = disasm.find("->0x"); if (pos == std::string::npos) @@ -259,7 +259,7 @@ void CodeViewWidget::Update() if (Core::GetState() == Core::State::Paused) { - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); Update(&guard); } else @@ -294,7 +294,11 @@ void CodeViewWidget::Update(const Core::CPUThreadGuard* guard) for (int i = 0; i < rows; i++) setRowHeight(i, rowh); - const std::optional pc = guard ? std::make_optional(PowerPC::ppcState.pc) : std::nullopt; + auto& power_pc = m_system.GetPowerPC(); + auto& debug_interface = power_pc.GetDebugInterface(); + + const std::optional pc = + guard ? std::make_optional(power_pc.GetPPCState().pc) : std::nullopt; const bool dark_theme = qApp->palette().color(QPalette::Base).valueF() < 0.5; @@ -303,16 +307,16 @@ void CodeViewWidget::Update(const Core::CPUThreadGuard* guard) for (int i = 0; i < rowCount(); i++) { const u32 addr = AddressForRow(i); - const u32 color = PowerPC::debug_interface.GetColor(guard, addr); + const u32 color = debug_interface.GetColor(guard, addr); auto* bp_item = new QTableWidgetItem; auto* addr_item = new QTableWidgetItem(QStringLiteral("%1").arg(addr, 8, 16, QLatin1Char('0'))); - std::string disas = PowerPC::debug_interface.Disassemble(guard, addr); + std::string disas = debug_interface.Disassemble(guard, addr); auto split = disas.find('\t'); std::string ins = (split == std::string::npos ? disas : disas.substr(0, split)); std::string param = (split == std::string::npos ? "" : disas.substr(split + 1)); - std::string desc = PowerPC::debug_interface.GetDescription(addr); + std::string desc = debug_interface.GetDescription(addr); // Adds whitespace and a minimum size to ins and param. Helps to prevent frequent resizing while // scrolling. @@ -359,19 +363,19 @@ void CodeViewWidget::Update(const Core::CPUThreadGuard* guard) branch.dst_addr = branch_addr; branch.is_link = IsBranchInstructionWithLink(ins); - description_item->setText(tr("--> %1").arg( - QString::fromStdString(PowerPC::debug_interface.GetDescription(branch_addr)))); + description_item->setText( + tr("--> %1").arg(QString::fromStdString(debug_interface.GetDescription(branch_addr)))); param_item->setForeground(Qt::magenta); } if (ins == "blr") ins_item->setForeground(dark_theme ? QColor(0xa0FFa0) : Qt::darkGreen); - if (PowerPC::debug_interface.IsBreakpoint(addr)) + if (debug_interface.IsBreakpoint(addr)) { auto icon = Resources::GetScaledThemeIcon("debugger_breakpoint").pixmap(QSize(rowh - 2, rowh - 2)); - if (!PowerPC::breakpoints.IsBreakPointEnable(addr)) + if (!m_system.GetPowerPC().GetBreakPoints().IsBreakPointEnable(addr)) { QPixmap disabled_icon(icon.size()); disabled_icon.fill(Qt::transparent); @@ -533,10 +537,10 @@ void CodeViewWidget::SetAddress(u32 address, SetAddressUpdate update) void CodeViewWidget::ReplaceAddress(u32 address, ReplaceWith replace) { - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); - PowerPC::debug_interface.SetPatch(guard, address, - replace == ReplaceWith::BLR ? 0x4e800020 : 0x60000000); + m_system.GetPowerPC().GetDebugInterface().SetPatch( + guard, address, replace == ReplaceWith::BLR ? 0x4e800020 : 0x60000000); Update(&guard); } @@ -595,10 +599,11 @@ void CodeViewWidget::OnContextMenu() bool follow_branch_enabled = false; if (paused) { - Core::CPUThreadGuard guard(Core::System::GetInstance()); - const std::string disasm = PowerPC::debug_interface.Disassemble(&guard, PowerPC::ppcState.pc); + Core::CPUThreadGuard guard(m_system); + const u32 pc = m_system.GetPPCState().pc; + const std::string disasm = m_system.GetPowerPC().GetDebugInterface().Disassemble(&guard, pc); - if (addr == PowerPC::ppcState.pc) + if (addr == pc) { const auto target_it = std::find(disasm.begin(), disasm.end(), '\t'); const auto target_end = std::find(target_it, disasm.end(), ','); @@ -640,7 +645,8 @@ void CodeViewWidget::OnContextMenu() action->setEnabled(valid_load_store); } - restore_action->setEnabled(running && PowerPC::debug_interface.HasEnabledPatch(addr)); + restore_action->setEnabled(running && + m_system.GetPowerPC().GetDebugInterface().HasEnabledPatch(addr)); menu->exec(QCursor::pos()); Update(); @@ -651,7 +657,7 @@ void CodeViewWidget::AutoStep(CodeTrace::AutoStop option) // Autosteps and follows value in the target (left-most) register. The Used and Changed options // silently follows target through reshuffles in memory and registers and stops on use or update. - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); CodeTrace code_trace; bool repeat = false; @@ -741,16 +747,16 @@ void CodeViewWidget::OnCopyTargetAddress() const u32 addr = GetContextAddress(); - const std::string code_line = [addr] { - Core::CPUThreadGuard guard(Core::System::GetInstance()); - return PowerPC::debug_interface.Disassemble(&guard, addr); + const std::string code_line = [this, addr] { + Core::CPUThreadGuard guard(m_system); + return m_system.GetPowerPC().GetDebugInterface().Disassemble(&guard, addr); }(); if (!IsInstructionLoadStore(code_line)) return; const std::optional target_addr = - PowerPC::debug_interface.GetMemoryAddressFromInstruction(code_line); + m_system.GetPowerPC().GetDebugInterface().GetMemoryAddressFromInstruction(code_line); if (target_addr) { @@ -771,16 +777,16 @@ void CodeViewWidget::OnShowTargetInMemory() const u32 addr = GetContextAddress(); - const std::string code_line = [addr] { - Core::CPUThreadGuard guard(Core::System::GetInstance()); - return PowerPC::debug_interface.Disassemble(&guard, addr); + const std::string code_line = [this, addr] { + Core::CPUThreadGuard guard(m_system); + return m_system.GetPowerPC().GetDebugInterface().Disassemble(&guard, addr); }(); if (!IsInstructionLoadStore(code_line)) return; const std::optional target_addr = - PowerPC::debug_interface.GetMemoryAddressFromInstruction(code_line); + m_system.GetPowerPC().GetDebugInterface().GetMemoryAddressFromInstruction(code_line); if (target_addr) emit ShowMemory(*target_addr); @@ -790,9 +796,9 @@ void CodeViewWidget::OnCopyCode() { const u32 addr = GetContextAddress(); - const std::string text = [addr] { - Core::CPUThreadGuard guard(Core::System::GetInstance()); - return PowerPC::debug_interface.Disassemble(&guard, addr); + const std::string text = [this, addr] { + Core::CPUThreadGuard guard(m_system); + return m_system.GetPowerPC().GetDebugInterface().Disassemble(&guard, addr); }(); QApplication::clipboard()->setText(QString::fromStdString(text)); @@ -809,14 +815,15 @@ void CodeViewWidget::OnCopyFunction() std::string text = symbol->name + "\r\n"; { - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); // we got a function const u32 start = symbol->address; const u32 end = start + symbol->size; for (u32 addr = start; addr != end; addr += 4) { - const std::string disasm = PowerPC::debug_interface.Disassemble(&guard, addr); + const std::string disasm = + m_system.GetPowerPC().GetDebugInterface().Disassemble(&guard, addr); fmt::format_to(std::back_inserter(text), "{:08x}: {}\r\n", addr, disasm); } } @@ -828,9 +835,9 @@ void CodeViewWidget::OnCopyHex() { const u32 addr = GetContextAddress(); - const u32 instruction = [addr] { - Core::CPUThreadGuard guard(Core::System::GetInstance()); - return PowerPC::debug_interface.ReadInstruction(guard, addr); + const u32 instruction = [this, addr] { + Core::CPUThreadGuard guard(m_system); + return m_system.GetPowerPC().GetDebugInterface().ReadInstruction(guard, addr); }(); QApplication::clipboard()->setText( @@ -841,8 +848,8 @@ void CodeViewWidget::OnRunToHere() { const u32 addr = GetContextAddress(); - PowerPC::debug_interface.SetBreakpoint(addr); - PowerPC::debug_interface.RunToBreakpoint(); + m_system.GetPowerPC().GetDebugInterface().SetBreakpoint(addr); + m_system.GetPowerPC().GetDebugInterface().RunToBreakpoint(); Update(); } @@ -857,7 +864,7 @@ void CodeViewWidget::OnAddFunction() { const u32 addr = GetContextAddress(); - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); g_symbolDB.AddFunction(guard, addr); emit SymbolsChanged(); @@ -882,8 +889,8 @@ void CodeViewWidget::OnFollowBranch() { const u32 addr = GetContextAddress(); - const u32 branch_addr = [addr] { - Core::CPUThreadGuard guard(Core::System::GetInstance()); + const u32 branch_addr = [this, addr] { + Core::CPUThreadGuard guard(m_system); return GetBranchFromAddress(guard, addr); }(); @@ -917,7 +924,7 @@ void CodeViewWidget::OnRenameSymbol() void CodeViewWidget::OnSelectionChanged() { - if (m_address == PowerPC::ppcState.pc) + if (m_address == m_system.GetPPCState().pc) { setStyleSheet( QStringLiteral("QTableView::item:selected {background-color: #00FF00; color: #000000;}")); @@ -946,7 +953,7 @@ void CodeViewWidget::OnSetSymbolSize() if (!good) return; - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); PPCAnalyst::ReanalyzeFunction(guard, symbol->address, *symbol, size); emit SymbolsChanged(); @@ -974,7 +981,7 @@ void CodeViewWidget::OnSetSymbolEndAddress() if (!good) return; - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); PPCAnalyst::ReanalyzeFunction(guard, symbol->address, *symbol, address - symbol->address); emit SymbolsChanged(); @@ -983,7 +990,7 @@ void CodeViewWidget::OnSetSymbolEndAddress() void CodeViewWidget::OnReplaceInstruction() { - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); const u32 addr = GetContextAddress(); @@ -995,22 +1002,23 @@ void CodeViewWidget::OnReplaceInstruction() if (!read_result.valid) return; - PatchInstructionDialog dialog(this, addr, PowerPC::debug_interface.ReadInstruction(guard, addr)); + auto& debug_interface = m_system.GetPowerPC().GetDebugInterface(); + PatchInstructionDialog dialog(this, addr, debug_interface.ReadInstruction(guard, addr)); if (dialog.exec() == QDialog::Accepted) { - PowerPC::debug_interface.SetPatch(guard, addr, dialog.GetCode()); + debug_interface.SetPatch(guard, addr, dialog.GetCode()); Update(&guard); } } void CodeViewWidget::OnRestoreInstruction() { - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); const u32 addr = GetContextAddress(); - PowerPC::debug_interface.UnsetPatch(guard, addr); + m_system.GetPowerPC().GetDebugInterface().UnsetPatch(guard, addr); Update(&guard); } @@ -1089,10 +1097,11 @@ void CodeViewWidget::showEvent(QShowEvent* event) void CodeViewWidget::ToggleBreakpoint() { - if (PowerPC::debug_interface.IsBreakpoint(GetContextAddress())) - PowerPC::breakpoints.Remove(GetContextAddress()); + auto& power_pc = m_system.GetPowerPC(); + if (power_pc.GetDebugInterface().IsBreakpoint(GetContextAddress())) + power_pc.GetBreakPoints().Remove(GetContextAddress()); else - PowerPC::breakpoints.Add(GetContextAddress()); + power_pc.GetBreakPoints().Add(GetContextAddress()); emit BreakpointsChanged(); Update(); @@ -1100,7 +1109,7 @@ void CodeViewWidget::ToggleBreakpoint() void CodeViewWidget::AddBreakpoint() { - PowerPC::breakpoints.Add(GetContextAddress()); + m_system.GetPowerPC().GetBreakPoints().Add(GetContextAddress()); emit BreakpointsChanged(); Update(); diff --git a/Source/Core/DolphinQt/Debugger/CodeViewWidget.h b/Source/Core/DolphinQt/Debugger/CodeViewWidget.h index bf06b1e91d..2812d84a92 100644 --- a/Source/Core/DolphinQt/Debugger/CodeViewWidget.h +++ b/Source/Core/DolphinQt/Debugger/CodeViewWidget.h @@ -18,7 +18,8 @@ class QShowEvent; namespace Core { class CPUThreadGuard; -}; +class System; +} // namespace Core struct CodeViewBranch; class BranchDisplayDelegate; @@ -98,6 +99,8 @@ private: void CalculateBranchIndentation(); + Core::System& m_system; + bool m_updating = false; u32 m_address = 0; diff --git a/Source/Core/DolphinQt/Debugger/CodeWidget.cpp b/Source/Core/DolphinQt/Debugger/CodeWidget.cpp index 29d72faf18..1f82c969de 100644 --- a/Source/Core/DolphinQt/Debugger/CodeWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/CodeWidget.cpp @@ -28,7 +28,7 @@ #include "DolphinQt/Host.h" #include "DolphinQt/Settings.h" -CodeWidget::CodeWidget(QWidget* parent) : QDockWidget(parent) +CodeWidget::CodeWidget(QWidget* parent) : QDockWidget(parent), m_system(Core::System::GetInstance()) { setWindowTitle(tr("Code")); setObjectName(QStringLiteral("code")); @@ -51,7 +51,7 @@ CodeWidget::CodeWidget(QWidget* parent) : QDockWidget(parent) connect(Host::GetInstance(), &Host::UpdateDisasmDialog, this, [this] { if (Core::GetState() == Core::State::Paused) - SetAddress(PowerPC::ppcState.pc, CodeViewWidget::SetAddressUpdate::WithoutUpdate); + SetAddress(m_system.GetPPCState().pc, CodeViewWidget::SetAddressUpdate::WithoutUpdate); Update(); }); @@ -329,9 +329,9 @@ void CodeWidget::UpdateCallstack() std::vector stack; - const bool success = [&stack] { - Core::CPUThreadGuard guard(Core::System::GetInstance()); - return Dolphin_Debugger::GetCallstack(Core::System::GetInstance(), guard, stack); + const bool success = [this, &stack] { + Core::CPUThreadGuard guard(m_system); + return Dolphin_Debugger::GetCallstack(m_system, guard, stack); }(); if (!success) @@ -435,41 +435,41 @@ void CodeWidget::UpdateFunctionCallers(const Common::Symbol* symbol) void CodeWidget::Step() { - auto& system = Core::System::GetInstance(); - auto& cpu = system.GetCPU(); + auto& cpu = m_system.GetCPU(); if (!cpu.IsStepping()) return; Common::Event sync_event; - PowerPC::CoreMode old_mode = PowerPC::GetMode(); - PowerPC::SetMode(PowerPC::CoreMode::Interpreter); - PowerPC::breakpoints.ClearAllTemporary(); + auto& power_pc = m_system.GetPowerPC(); + PowerPC::CoreMode old_mode = power_pc.GetMode(); + power_pc.SetMode(PowerPC::CoreMode::Interpreter); + power_pc.GetBreakPoints().ClearAllTemporary(); cpu.StepOpcode(&sync_event); sync_event.WaitFor(std::chrono::milliseconds(20)); - PowerPC::SetMode(old_mode); + power_pc.SetMode(old_mode); Core::DisplayMessage(tr("Step successful!").toStdString(), 2000); // Will get a UpdateDisasmDialog(), don't update the GUI here. } void CodeWidget::StepOver() { - auto& system = Core::System::GetInstance(); - auto& cpu = system.GetCPU(); + auto& cpu = m_system.GetCPU(); if (!cpu.IsStepping()) return; const UGeckoInstruction inst = [&] { - Core::CPUThreadGuard guard(system); - return PowerPC::MMU::HostRead_Instruction(guard, PowerPC::ppcState.pc); + Core::CPUThreadGuard guard(m_system); + return PowerPC::MMU::HostRead_Instruction(guard, m_system.GetPPCState().pc); }(); if (inst.LK) { - PowerPC::breakpoints.ClearAllTemporary(); - PowerPC::breakpoints.Add(PowerPC::ppcState.pc + 4, true); + auto& breakpoints = m_system.GetPowerPC().GetBreakPoints(); + breakpoints.ClearAllTemporary(); + breakpoints.Add(m_system.GetPPCState().pc + 4, true); cpu.EnableStepping(false); Core::DisplayMessage(tr("Step over in progress...").toStdString(), 2000); } @@ -480,23 +480,21 @@ void CodeWidget::StepOver() } // Returns true on a rfi, blr or on a bclr that evaluates to true. -static bool WillInstructionReturn(UGeckoInstruction inst) +static bool WillInstructionReturn(Core::System& system, UGeckoInstruction inst) { // Is a rfi instruction if (inst.hex == 0x4C000064u) return true; - bool counter = - (inst.BO_2 >> 2 & 1) != 0 || (CTR(PowerPC::ppcState) != 0) != ((inst.BO_2 >> 1 & 1) != 0); - bool condition = - inst.BO_2 >> 4 != 0 || PowerPC::ppcState.cr.GetBit(inst.BI_2) == (inst.BO_2 >> 3 & 1); + const auto& ppc_state = system.GetPPCState(); + bool counter = (inst.BO_2 >> 2 & 1) != 0 || (CTR(ppc_state) != 0) != ((inst.BO_2 >> 1 & 1) != 0); + bool condition = inst.BO_2 >> 4 != 0 || ppc_state.cr.GetBit(inst.BI_2) == (inst.BO_2 >> 3 & 1); bool isBclr = inst.OPCD_7 == 0b010011 && (inst.hex >> 1 & 0b10000) != 0; return isBclr && counter && condition && !inst.LK_3; } void CodeWidget::StepOut() { - auto& system = Core::System::GetInstance(); - auto& cpu = system.GetCPU(); + auto& cpu = m_system.GetCPU(); if (!cpu.IsStepping()) return; @@ -505,51 +503,53 @@ void CodeWidget::StepOut() using clock = std::chrono::steady_clock; clock::time_point timeout = clock::now() + std::chrono::seconds(5); + auto& power_pc = m_system.GetPowerPC(); + auto& ppc_state = power_pc.GetPPCState(); + auto& breakpoints = power_pc.GetBreakPoints(); { - Core::CPUThreadGuard guard(system); + Core::CPUThreadGuard guard(m_system); - PowerPC::breakpoints.ClearAllTemporary(); + breakpoints.ClearAllTemporary(); - PowerPC::CoreMode old_mode = PowerPC::GetMode(); - PowerPC::SetMode(PowerPC::CoreMode::Interpreter); + PowerPC::CoreMode old_mode = power_pc.GetMode(); + power_pc.SetMode(PowerPC::CoreMode::Interpreter); // Loop until either the current instruction is a return instruction with no Link flag // or a breakpoint is detected so it can step at the breakpoint. If the PC is currently // on a breakpoint, skip it. - UGeckoInstruction inst = PowerPC::MMU::HostRead_Instruction(guard, PowerPC::ppcState.pc); + UGeckoInstruction inst = PowerPC::MMU::HostRead_Instruction(guard, ppc_state.pc); do { - if (WillInstructionReturn(inst)) + if (WillInstructionReturn(m_system, inst)) { - PowerPC::SingleStep(); + power_pc.SingleStep(); break; } if (inst.LK) { // Step over branches - u32 next_pc = PowerPC::ppcState.pc + 4; + u32 next_pc = ppc_state.pc + 4; do { - PowerPC::SingleStep(); - } while (PowerPC::ppcState.pc != next_pc && clock::now() < timeout && - !PowerPC::breakpoints.IsAddressBreakPoint(PowerPC::ppcState.pc)); + power_pc.SingleStep(); + } while (ppc_state.pc != next_pc && clock::now() < timeout && + !breakpoints.IsAddressBreakPoint(ppc_state.pc)); } else { - PowerPC::SingleStep(); + power_pc.SingleStep(); } - inst = PowerPC::MMU::HostRead_Instruction(guard, PowerPC::ppcState.pc); - } while (clock::now() < timeout && - !PowerPC::breakpoints.IsAddressBreakPoint(PowerPC::ppcState.pc)); + inst = PowerPC::MMU::HostRead_Instruction(guard, ppc_state.pc); + } while (clock::now() < timeout && !breakpoints.IsAddressBreakPoint(ppc_state.pc)); - PowerPC::SetMode(old_mode); + power_pc.SetMode(old_mode); } emit Host::GetInstance()->UpdateDisasmDialog(); - if (PowerPC::breakpoints.IsAddressBreakPoint(PowerPC::ppcState.pc)) + if (breakpoints.IsAddressBreakPoint(ppc_state.pc)) Core::DisplayMessage(tr("Breakpoint encountered! Step out aborted.").toStdString(), 2000); else if (clock::now() >= timeout) Core::DisplayMessage(tr("Step out timed out!").toStdString(), 2000); @@ -559,19 +559,19 @@ void CodeWidget::StepOut() void CodeWidget::Skip() { - PowerPC::ppcState.pc += 4; + m_system.GetPPCState().pc += 4; ShowPC(); } void CodeWidget::ShowPC() { - m_code_view->SetAddress(PowerPC::ppcState.pc, CodeViewWidget::SetAddressUpdate::WithUpdate); + m_code_view->SetAddress(m_system.GetPPCState().pc, CodeViewWidget::SetAddressUpdate::WithUpdate); Update(); } void CodeWidget::SetPC() { - PowerPC::ppcState.pc = m_code_view->GetAddress(); + m_system.GetPPCState().pc = m_code_view->GetAddress(); Update(); } diff --git a/Source/Core/DolphinQt/Debugger/CodeWidget.h b/Source/Core/DolphinQt/Debugger/CodeWidget.h index f198e004cc..1e933a8c70 100644 --- a/Source/Core/DolphinQt/Debugger/CodeWidget.h +++ b/Source/Core/DolphinQt/Debugger/CodeWidget.h @@ -22,6 +22,10 @@ namespace Common { struct Symbol; } +namespace Core +{ +class System; +} class CodeWidget : public QDockWidget { @@ -66,6 +70,8 @@ private: void closeEvent(QCloseEvent*) override; void showEvent(QShowEvent* event) override; + Core::System& m_system; + CodeDiffDialog* m_diff_dialog = nullptr; QLineEdit* m_search_address; QPushButton* m_code_diff; diff --git a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp index 46db6477d4..41b406536b 100644 --- a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp @@ -170,7 +170,8 @@ private: MemoryViewWidget* m_view; }; -MemoryViewWidget::MemoryViewWidget(QWidget* parent) : QWidget(parent) +MemoryViewWidget::MemoryViewWidget(QWidget* parent) + : QWidget(parent), m_system(Core::System::GetInstance()) { auto* layout = new QHBoxLayout(); layout->setContentsMargins(0, 0, 0, 0); @@ -437,6 +438,9 @@ void MemoryViewWidget::Update() void MemoryViewWidget::UpdateColumns() { + if (!isVisible()) + return; + // Check if table is created if (m_table->item(1, 1) == nullptr) return; @@ -568,7 +572,7 @@ void MemoryViewWidget::UpdateBreakpointTags() } if (m_address_space == AddressSpace::Type::Effective && - PowerPC::memchecks.GetMemCheck(address, GetTypeSize(m_type)) != nullptr) + m_system.GetPowerPC().GetMemChecks().GetMemCheck(address, GetTypeSize(m_type)) != nullptr) { row_breakpoint = true; cell->setBackground(Qt::red); @@ -805,15 +809,17 @@ void MemoryViewWidget::ToggleBreakpoint(u32 addr, bool row) const int breaks = row ? (m_bytes_per_row / length) : 1; bool overlap = false; + auto& memchecks = m_system.GetPowerPC().GetMemChecks(); + // Row breakpoint should either remove any breakpoint left on the row, or activate all // breakpoints. - if (row && PowerPC::memchecks.OverlapsMemcheck(addr, m_bytes_per_row)) + if (row && memchecks.OverlapsMemcheck(addr, m_bytes_per_row)) overlap = true; for (int i = 0; i < breaks; i++) { u32 address = addr + length * i; - TMemCheck* check_ptr = PowerPC::memchecks.GetMemCheck(address, length); + TMemCheck* check_ptr = memchecks.GetMemCheck(address, length); if (check_ptr == nullptr && !overlap) { @@ -826,12 +832,12 @@ void MemoryViewWidget::ToggleBreakpoint(u32 addr, bool row) check.log_on_hit = m_do_log; check.break_on_hit = true; - PowerPC::memchecks.Add(std::move(check)); + memchecks.Add(std::move(check)); } else if (check_ptr != nullptr) { // Using the pointer fixes misaligned breakpoints (0x11 breakpoint in 0x10 aligned view). - PowerPC::memchecks.Remove(check_ptr->start_address); + memchecks.Remove(check_ptr->start_address); } } @@ -885,7 +891,7 @@ void MemoryViewWidget::OnContextMenu(const QPoint& pos) auto* copy_hex = menu->addAction(tr("Copy Hex"), this, [this, addr] { OnCopyHex(addr); }); copy_hex->setEnabled(item_has_value); - auto* copy_value = menu->addAction(tr("Copy Value"), this, [this, item_selected] { + auto* copy_value = menu->addAction(tr("Copy Value"), this, [item_selected] { QApplication::clipboard()->setText(item_selected->text()); }); copy_value->setEnabled(item_has_value); diff --git a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.h b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.h index e5e15f5abe..1b8bed117a 100644 --- a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.h +++ b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.h @@ -18,7 +18,8 @@ enum class Type; namespace Core { class CPUThreadGuard; -} +class System; +} // namespace Core class MemoryViewTable; @@ -85,6 +86,8 @@ private: void ScrollbarSliderReleased(); QString ValueToString(const Core::CPUThreadGuard& guard, u32 address, Type type); + Core::System& m_system; + MemoryViewTable* m_table; QScrollBar* m_scrollbar; AddressSpace::Type m_address_space{}; diff --git a/Source/Core/DolphinQt/Debugger/RegisterWidget.cpp b/Source/Core/DolphinQt/Debugger/RegisterWidget.cpp index 9d7079e04a..b41fffb39a 100644 --- a/Source/Core/DolphinQt/Debugger/RegisterWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/RegisterWidget.cpp @@ -20,7 +20,8 @@ #include "DolphinQt/Host.h" #include "DolphinQt/Settings.h" -RegisterWidget::RegisterWidget(QWidget* parent) : QDockWidget(parent) +RegisterWidget::RegisterWidget(QWidget* parent) + : QDockWidget(parent), m_system(Core::System::GetInstance()) { setWindowTitle(tr("Registers")); setObjectName(QStringLiteral("registers")); @@ -295,8 +296,8 @@ void RegisterWidget::AutoStep(const std::string& reg) const while (true) { - const AutoStepResults results = [&trace] { - Core::CPUThreadGuard guard(Core::System::GetInstance()); + const AutoStepResults results = [this, &trace] { + Core::CPUThreadGuard guard(m_system); return trace.AutoStepping(guard, true); }(); @@ -318,18 +319,19 @@ void RegisterWidget::PopulateTable() { // General purpose registers (int) AddRegister( - i, 0, RegisterType::gpr, "r" + std::to_string(i), [i] { return PowerPC::ppcState.gpr[i]; }, - [i](u64 value) { PowerPC::ppcState.gpr[i] = value; }); + i, 0, RegisterType::gpr, "r" + std::to_string(i), + [this, i] { return m_system.GetPPCState().gpr[i]; }, + [this, i](u64 value) { m_system.GetPPCState().gpr[i] = value; }); // Floating point registers (double) AddRegister( i, 2, RegisterType::fpr, "f" + std::to_string(i), - [i] { return PowerPC::ppcState.ps[i].PS0AsU64(); }, - [i](u64 value) { PowerPC::ppcState.ps[i].SetPS0(value); }); + [this, i] { return m_system.GetPPCState().ps[i].PS0AsU64(); }, + [this, i](u64 value) { m_system.GetPPCState().ps[i].SetPS0(value); }); AddRegister( - i, 4, RegisterType::fpr, "", [i] { return PowerPC::ppcState.ps[i].PS1AsU64(); }, - [i](u64 value) { PowerPC::ppcState.ps[i].SetPS1(value); }); + i, 4, RegisterType::fpr, "", [this, i] { return m_system.GetPPCState().ps[i].PS1AsU64(); }, + [this, i](u64 value) { m_system.GetPPCState().ps[i].SetPS1(value); }); } // The IBAT and DBAT registers have a large gap between @@ -340,32 +342,36 @@ void RegisterWidget::PopulateTable() // IBAT registers AddRegister( i, 5, RegisterType::ibat, "IBAT" + std::to_string(i), - [i] { - return (static_cast(PowerPC::ppcState.spr[SPR_IBAT0U + i * 2]) << 32) + - PowerPC::ppcState.spr[SPR_IBAT0L + i * 2]; + [this, i] { + const auto& ppc_state = m_system.GetPPCState(); + return (static_cast(ppc_state.spr[SPR_IBAT0U + i * 2]) << 32) + + ppc_state.spr[SPR_IBAT0L + i * 2]; }, nullptr); AddRegister( i + 4, 5, RegisterType::ibat, "IBAT" + std::to_string(4 + i), - [i] { - return (static_cast(PowerPC::ppcState.spr[SPR_IBAT4U + i * 2]) << 32) + - PowerPC::ppcState.spr[SPR_IBAT4L + i * 2]; + [this, i] { + const auto& ppc_state = m_system.GetPPCState(); + return (static_cast(ppc_state.spr[SPR_IBAT4U + i * 2]) << 32) + + ppc_state.spr[SPR_IBAT4L + i * 2]; }, nullptr); // DBAT registers AddRegister( i + 8, 5, RegisterType::dbat, "DBAT" + std::to_string(i), - [i] { - return (static_cast(PowerPC::ppcState.spr[SPR_DBAT0U + i * 2]) << 32) + - PowerPC::ppcState.spr[SPR_DBAT0L + i * 2]; + [this, i] { + const auto& ppc_state = m_system.GetPPCState(); + return (static_cast(ppc_state.spr[SPR_DBAT0U + i * 2]) << 32) + + ppc_state.spr[SPR_DBAT0L + i * 2]; }, nullptr); AddRegister( i + 12, 5, RegisterType::dbat, "DBAT" + std::to_string(4 + i), - [i] { - return (static_cast(PowerPC::ppcState.spr[SPR_DBAT4U + i * 2]) << 32) + - PowerPC::ppcState.spr[SPR_DBAT4L + i * 2]; + [this, i] { + const auto& ppc_state = m_system.GetPPCState(); + return (static_cast(ppc_state.spr[SPR_DBAT4U + i * 2]) << 32) + + ppc_state.spr[SPR_DBAT4L + i * 2]; }, nullptr); } @@ -375,114 +381,113 @@ void RegisterWidget::PopulateTable() // Graphics quantization registers AddRegister( i + 16, 7, RegisterType::gqr, "GQR" + std::to_string(i), - [i] { return PowerPC::ppcState.spr[SPR_GQR0 + i]; }, nullptr); + [this, i] { return m_system.GetPPCState().spr[SPR_GQR0 + i]; }, nullptr); } // HID registers AddRegister( - 24, 7, RegisterType::hid, "HID0", [] { return PowerPC::ppcState.spr[SPR_HID0]; }, - [](u64 value) { PowerPC::ppcState.spr[SPR_HID0] = static_cast(value); }); + 24, 7, RegisterType::hid, "HID0", [this] { return m_system.GetPPCState().spr[SPR_HID0]; }, + [this](u64 value) { m_system.GetPPCState().spr[SPR_HID0] = static_cast(value); }); AddRegister( - 25, 7, RegisterType::hid, "HID1", [] { return PowerPC::ppcState.spr[SPR_HID1]; }, - [](u64 value) { PowerPC::ppcState.spr[SPR_HID1] = static_cast(value); }); + 25, 7, RegisterType::hid, "HID1", [this] { return m_system.GetPPCState().spr[SPR_HID1]; }, + [this](u64 value) { m_system.GetPPCState().spr[SPR_HID1] = static_cast(value); }); AddRegister( - 26, 7, RegisterType::hid, "HID2", [] { return PowerPC::ppcState.spr[SPR_HID2]; }, - [](u64 value) { PowerPC::ppcState.spr[SPR_HID2] = static_cast(value); }); + 26, 7, RegisterType::hid, "HID2", [this] { return m_system.GetPPCState().spr[SPR_HID2]; }, + [this](u64 value) { m_system.GetPPCState().spr[SPR_HID2] = static_cast(value); }); AddRegister( - 27, 7, RegisterType::hid, "HID4", [] { return PowerPC::ppcState.spr[SPR_HID4]; }, - [](u64 value) { PowerPC::ppcState.spr[SPR_HID4] = static_cast(value); }); + 27, 7, RegisterType::hid, "HID4", [this] { return m_system.GetPPCState().spr[SPR_HID4]; }, + [this](u64 value) { m_system.GetPPCState().spr[SPR_HID4] = static_cast(value); }); for (int i = 0; i < 16; i++) { // SR registers AddRegister( - i, 7, RegisterType::sr, "SR" + std::to_string(i), [i] { return PowerPC::ppcState.sr[i]; }, - [i](u64 value) { PowerPC::ppcState.sr[i] = value; }); + i, 7, RegisterType::sr, "SR" + std::to_string(i), + [this, i] { return m_system.GetPPCState().sr[i]; }, + [this, i](u64 value) { m_system.GetPPCState().sr[i] = value; }); } // Special registers // TB - AddRegister(16, 5, RegisterType::tb, "TB", PowerPC::ReadFullTimeBaseValue, nullptr); + AddRegister( + 16, 5, RegisterType::tb, "TB", + [this] { return m_system.GetPowerPC().ReadFullTimeBaseValue(); }, nullptr); // PC AddRegister( - 17, 5, RegisterType::pc, "PC", [] { return PowerPC::ppcState.pc; }, - [](u64 value) { PowerPC::ppcState.pc = value; }); + 17, 5, RegisterType::pc, "PC", [this] { return m_system.GetPPCState().pc; }, + [this](u64 value) { m_system.GetPPCState().pc = value; }); // LR AddRegister( - 18, 5, RegisterType::lr, "LR", [] { return PowerPC::ppcState.spr[SPR_LR]; }, - [](u64 value) { PowerPC::ppcState.spr[SPR_LR] = value; }); + 18, 5, RegisterType::lr, "LR", [this] { return m_system.GetPPCState().spr[SPR_LR]; }, + [this](u64 value) { m_system.GetPPCState().spr[SPR_LR] = value; }); // CTR AddRegister( - 19, 5, RegisterType::ctr, "CTR", [] { return PowerPC::ppcState.spr[SPR_CTR]; }, - [](u64 value) { PowerPC::ppcState.spr[SPR_CTR] = value; }); + 19, 5, RegisterType::ctr, "CTR", [this] { return m_system.GetPPCState().spr[SPR_CTR]; }, + [this](u64 value) { m_system.GetPPCState().spr[SPR_CTR] = value; }); // CR AddRegister( - 20, 5, RegisterType::cr, "CR", [] { return PowerPC::ppcState.cr.Get(); }, - [](u64 value) { PowerPC::ppcState.cr.Set(value); }); + 20, 5, RegisterType::cr, "CR", [this] { return m_system.GetPPCState().cr.Get(); }, + [this](u64 value) { m_system.GetPPCState().cr.Set(value); }); // XER AddRegister( - 21, 5, RegisterType::xer, "XER", [] { return PowerPC::ppcState.GetXER().Hex; }, - [](u64 value) { PowerPC::ppcState.SetXER(UReg_XER(value)); }); + 21, 5, RegisterType::xer, "XER", [this] { return m_system.GetPPCState().GetXER().Hex; }, + [this](u64 value) { m_system.GetPPCState().SetXER(UReg_XER(value)); }); // FPSCR AddRegister( - 22, 5, RegisterType::fpscr, "FPSCR", [] { return PowerPC::ppcState.fpscr.Hex; }, - [](u64 value) { PowerPC::ppcState.fpscr = static_cast(value); }); + 22, 5, RegisterType::fpscr, "FPSCR", [this] { return m_system.GetPPCState().fpscr.Hex; }, + [this](u64 value) { m_system.GetPPCState().fpscr = static_cast(value); }); // MSR AddRegister( - 23, 5, RegisterType::msr, "MSR", [] { return PowerPC::ppcState.msr.Hex; }, - [](u64 value) { PowerPC::ppcState.msr.Hex = value; }); + 23, 5, RegisterType::msr, "MSR", [this] { return m_system.GetPPCState().msr.Hex; }, + [this](u64 value) { m_system.GetPPCState().msr.Hex = value; }); // SRR 0-1 AddRegister( - 24, 5, RegisterType::srr, "SRR0", [] { return PowerPC::ppcState.spr[SPR_SRR0]; }, - [](u64 value) { PowerPC::ppcState.spr[SPR_SRR0] = value; }); + 24, 5, RegisterType::srr, "SRR0", [this] { return m_system.GetPPCState().spr[SPR_SRR0]; }, + [this](u64 value) { m_system.GetPPCState().spr[SPR_SRR0] = value; }); AddRegister( - 25, 5, RegisterType::srr, "SRR1", [] { return PowerPC::ppcState.spr[SPR_SRR1]; }, - [](u64 value) { PowerPC::ppcState.spr[SPR_SRR1] = value; }); + 25, 5, RegisterType::srr, "SRR1", [this] { return m_system.GetPPCState().spr[SPR_SRR1]; }, + [this](u64 value) { m_system.GetPPCState().spr[SPR_SRR1] = value; }); // Exceptions AddRegister( - 26, 5, RegisterType::exceptions, "Exceptions", [] { return PowerPC::ppcState.Exceptions; }, - [](u64 value) { PowerPC::ppcState.Exceptions = value; }); + 26, 5, RegisterType::exceptions, "Exceptions", + [this] { return m_system.GetPPCState().Exceptions; }, + [this](u64 value) { m_system.GetPPCState().Exceptions = value; }); // Int Mask AddRegister( 27, 5, RegisterType::int_mask, "Int Mask", - [] { - auto& system = Core::System::GetInstance(); - return system.GetProcessorInterface().GetMask(); - }, - nullptr); + [this] { return m_system.GetProcessorInterface().GetMask(); }, nullptr); // Int Cause AddRegister( 28, 5, RegisterType::int_cause, "Int Cause", - [] { - auto& system = Core::System::GetInstance(); - return system.GetProcessorInterface().GetCause(); - }, - nullptr); + [this] { return m_system.GetProcessorInterface().GetCause(); }, nullptr); // DSISR AddRegister( - 29, 5, RegisterType::dsisr, "DSISR", [] { return PowerPC::ppcState.spr[SPR_DSISR]; }, - [](u64 value) { PowerPC::ppcState.spr[SPR_DSISR] = value; }); + 29, 5, RegisterType::dsisr, "DSISR", [this] { return m_system.GetPPCState().spr[SPR_DSISR]; }, + [this](u64 value) { m_system.GetPPCState().spr[SPR_DSISR] = value; }); // DAR AddRegister( - 30, 5, RegisterType::dar, "DAR", [] { return PowerPC::ppcState.spr[SPR_DAR]; }, - [](u64 value) { PowerPC::ppcState.spr[SPR_DAR] = value; }); + 30, 5, RegisterType::dar, "DAR", [this] { return m_system.GetPPCState().spr[SPR_DAR]; }, + [this](u64 value) { m_system.GetPPCState().spr[SPR_DAR] = value; }); // Hash Mask AddRegister( 31, 5, RegisterType::pt_hashmask, "Hash Mask", - [] { return (PowerPC::ppcState.pagetable_hashmask << 6) | PowerPC::ppcState.pagetable_base; }, + [this] { + const auto& ppc_state = m_system.GetPPCState(); + return (ppc_state.pagetable_hashmask << 6) | ppc_state.pagetable_base; + }, nullptr); emit RequestTableUpdate(); diff --git a/Source/Core/DolphinQt/Debugger/RegisterWidget.h b/Source/Core/DolphinQt/Debugger/RegisterWidget.h index f57a3b04d9..13432692a6 100644 --- a/Source/Core/DolphinQt/Debugger/RegisterWidget.h +++ b/Source/Core/DolphinQt/Debugger/RegisterWidget.h @@ -13,6 +13,10 @@ class QTableWidget; class QCloseEvent; class QShowEvent; +namespace Core +{ +class System; +} class RegisterWidget : public QDockWidget { @@ -49,6 +53,8 @@ private: void AutoStep(const std::string& reg) const; void Update(); + Core::System& m_system; + QTableWidget* m_table; bool m_updating = false; }; diff --git a/Source/Core/DolphinQt/Debugger/ThreadWidget.cpp b/Source/Core/DolphinQt/Debugger/ThreadWidget.cpp index 3905700f2b..3ba804acb1 100644 --- a/Source/Core/DolphinQt/Debugger/ThreadWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/ThreadWidget.cpp @@ -314,7 +314,7 @@ void ThreadWidget::Update() m_queue_tail->setText(format_hex_from(guard, 0x800000E0)); // Thread group - m_threads = PowerPC::debug_interface.GetThreads(guard); + m_threads = guard.GetSystem().GetPowerPC().GetDebugInterface().GetThreads(guard); int i = 0; m_thread_table->setRowCount(i); @@ -458,9 +458,10 @@ void ThreadWidget::UpdateThreadCallstack(const Core::CPUThreadGuard& guard, { const u32 lr_save = PowerPC::MMU::HostRead_U32(guard, sp + 4); m_callstack_table->setItem(i, 2, new QTableWidgetItem(format_hex(lr_save))); - m_callstack_table->setItem(i, 3, - new QTableWidgetItem(QString::fromStdString( - PowerPC::debug_interface.GetDescription(lr_save)))); + m_callstack_table->setItem( + i, 3, + new QTableWidgetItem(QString::fromStdString( + guard.GetSystem().GetPowerPC().GetDebugInterface().GetDescription(lr_save)))); } else { diff --git a/Source/Core/DolphinQt/Debugger/WatchWidget.cpp b/Source/Core/DolphinQt/Debugger/WatchWidget.cpp index fdb1279072..16d327835e 100644 --- a/Source/Core/DolphinQt/Debugger/WatchWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/WatchWidget.cpp @@ -23,7 +23,8 @@ #include "DolphinQt/Resources.h" #include "DolphinQt/Settings.h" -WatchWidget::WatchWidget(QWidget* parent) : QDockWidget(parent) +WatchWidget::WatchWidget(QWidget* parent) + : QDockWidget(parent), m_system(Core::System::GetInstance()) { // i18n: This kind of "watch" is used for watching emulated memory. // It's not related to timekeeping devices. @@ -167,15 +168,16 @@ void WatchWidget::Update() m_table->setDisabled(false); m_table->clearContents(); - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); + auto& debug_interface = guard.GetSystem().GetPowerPC().GetDebugInterface(); - int size = static_cast(PowerPC::debug_interface.GetWatches().size()); + int size = static_cast(debug_interface.GetWatches().size()); m_table->setRowCount(size + 1); for (int i = 0; i < size; i++) { - const auto& entry = PowerPC::debug_interface.GetWatch(i); + const auto& entry = debug_interface.GetWatch(i); auto* label = new QTableWidgetItem(QString::fromStdString(entry.name)); auto* address = @@ -263,7 +265,7 @@ void WatchWidget::OnDelete() void WatchWidget::OnClear() { - PowerPC::debug_interface.ClearWatches(); + m_system.GetPowerPC().GetDebugInterface().ClearWatches(); Update(); } @@ -287,7 +289,7 @@ void WatchWidget::OnNewWatch() void WatchWidget::OnLoad() { - IniFile ini; + Common::IniFile ini; std::vector watches; @@ -297,16 +299,17 @@ void WatchWidget::OnLoad() return; } - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); if (ini.GetLines("Watches", &watches, false)) { - for (const auto& watch : PowerPC::debug_interface.GetWatches()) + auto& debug_interface = guard.GetSystem().GetPowerPC().GetDebugInterface(); + for (const auto& watch : debug_interface.GetWatches()) { - PowerPC::debug_interface.UnsetPatch(guard, watch.address); + debug_interface.UnsetPatch(guard, watch.address); } - PowerPC::debug_interface.ClearWatches(); - PowerPC::debug_interface.LoadWatchesFromStrings(watches); + debug_interface.ClearWatches(); + debug_interface.LoadWatchesFromStrings(watches); } Update(); @@ -314,10 +317,10 @@ void WatchWidget::OnLoad() void WatchWidget::OnSave() { - IniFile ini; + Common::IniFile ini; ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().GetGameID() + ".ini", false); - ini.SetLines("Watches", PowerPC::debug_interface.SaveWatchesToStrings()); + ini.SetLines("Watches", m_system.GetPowerPC().GetDebugInterface().SaveWatchesToStrings()); ini.Save(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().GetGameID() + ".ini"); } @@ -394,7 +397,7 @@ void WatchWidget::OnItemChanged(QTableWidgetItem* item) if (item->text().isEmpty()) DeleteWatchAndUpdate(row); else - PowerPC::debug_interface.UpdateWatchName(row, item->text().toStdString()); + m_system.GetPowerPC().GetDebugInterface().UpdateWatchName(row, item->text().toStdString()); break; case COLUMN_INDEX_ADDRESS: case COLUMN_INDEX_HEX: @@ -407,19 +410,20 @@ void WatchWidget::OnItemChanged(QTableWidgetItem* item) if (good) { - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); + auto& debug_interface = m_system.GetPowerPC().GetDebugInterface(); if (column == COLUMN_INDEX_ADDRESS) { - const auto& watch = PowerPC::debug_interface.GetWatch(row); - PowerPC::debug_interface.UnsetPatch(guard, watch.address); - PowerPC::debug_interface.UpdateWatchAddress(row, value); + const auto& watch = debug_interface.GetWatch(row); + debug_interface.UnsetPatch(guard, watch.address); + debug_interface.UpdateWatchAddress(row, value); if (watch.locked) LockWatchAddress(guard, value); } else { - PowerPC::MMU::HostWrite_U32(guard, value, PowerPC::debug_interface.GetWatch(row).address); + PowerPC::MMU::HostWrite_U32(guard, value, debug_interface.GetWatch(row).address); } } else @@ -430,13 +434,14 @@ void WatchWidget::OnItemChanged(QTableWidgetItem* item) } case COLUMN_INDEX_LOCK: { - PowerPC::debug_interface.UpdateWatchLockedState(row, item->checkState() == Qt::Checked); - const auto& watch = PowerPC::debug_interface.GetWatch(row); - Core::CPUThreadGuard guard(Core::System::GetInstance()); + auto& debug_interface = m_system.GetPowerPC().GetDebugInterface(); + debug_interface.UpdateWatchLockedState(row, item->checkState() == Qt::Checked); + const auto& watch = debug_interface.GetWatch(row); + Core::CPUThreadGuard guard(m_system); if (watch.locked) LockWatchAddress(guard, watch.address); else - PowerPC::debug_interface.UnsetPatch(guard, watch.address); + debug_interface.UnsetPatch(guard, watch.address); break; } } @@ -455,13 +460,13 @@ void WatchWidget::LockWatchAddress(const Core::CPUThreadGuard& guard, u32 addres bytes.push_back(static_cast(c)); } - PowerPC::debug_interface.SetFramePatch(guard, address, bytes); + m_system.GetPowerPC().GetDebugInterface().SetFramePatch(guard, address, bytes); } void WatchWidget::DeleteSelectedWatches() { { - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); std::vector row_indices; for (const auto& index : m_table->selectionModel()->selectedRows()) { @@ -486,14 +491,15 @@ void WatchWidget::DeleteSelectedWatches() void WatchWidget::DeleteWatch(const Core::CPUThreadGuard& guard, int row) { - PowerPC::debug_interface.UnsetPatch(guard, PowerPC::debug_interface.GetWatch(row).address); - PowerPC::debug_interface.RemoveWatch(row); + auto& debug_interface = m_system.GetPowerPC().GetDebugInterface(); + debug_interface.UnsetPatch(guard, debug_interface.GetWatch(row).address); + debug_interface.RemoveWatch(row); } void WatchWidget::DeleteWatchAndUpdate(int row) { { - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); DeleteWatch(guard, row); } @@ -502,24 +508,25 @@ void WatchWidget::DeleteWatchAndUpdate(int row) void WatchWidget::AddWatchBreakpoint(int row) { - emit RequestMemoryBreakpoint(PowerPC::debug_interface.GetWatch(row).address); + emit RequestMemoryBreakpoint(m_system.GetPowerPC().GetDebugInterface().GetWatch(row).address); } void WatchWidget::ShowInMemory(int row) { - emit ShowMemory(PowerPC::debug_interface.GetWatch(row).address); + emit ShowMemory(m_system.GetPowerPC().GetDebugInterface().GetWatch(row).address); } void WatchWidget::AddWatch(QString name, u32 addr) { - PowerPC::debug_interface.SetWatch(addr, name.toStdString()); + m_system.GetPowerPC().GetDebugInterface().SetWatch(addr, name.toStdString()); Update(); } void WatchWidget::LockSelectedWatches() { { - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); + auto& debug_interface = m_system.GetPowerPC().GetDebugInterface(); for (const auto& index : m_table->selectionModel()->selectedRows()) { const auto* item = m_table->item(index.row(), index.column()); @@ -527,10 +534,10 @@ void WatchWidget::LockSelectedWatches() if (row_variant.isNull()) continue; const int row = row_variant.toInt(); - const auto& watch = PowerPC::debug_interface.GetWatch(row); + const auto& watch = debug_interface.GetWatch(row); if (watch.locked) continue; - PowerPC::debug_interface.UpdateWatchLockedState(row, true); + debug_interface.UpdateWatchLockedState(row, true); LockWatchAddress(guard, watch.address); } } @@ -541,7 +548,8 @@ void WatchWidget::LockSelectedWatches() void WatchWidget::UnlockSelectedWatches() { { - Core::CPUThreadGuard guard(Core::System::GetInstance()); + auto& debug_interface = m_system.GetPowerPC().GetDebugInterface(); + Core::CPUThreadGuard guard(m_system); for (const auto& index : m_table->selectionModel()->selectedRows()) { const auto* item = m_table->item(index.row(), index.column()); @@ -549,11 +557,11 @@ void WatchWidget::UnlockSelectedWatches() if (row_variant.isNull()) continue; const int row = row_variant.toInt(); - const auto& watch = PowerPC::debug_interface.GetWatch(row); + const auto& watch = debug_interface.GetWatch(row); if (!watch.locked) continue; - PowerPC::debug_interface.UpdateWatchLockedState(row, false); - PowerPC::debug_interface.UnsetPatch(guard, watch.address); + debug_interface.UpdateWatchLockedState(row, false); + debug_interface.UnsetPatch(guard, watch.address); } } diff --git a/Source/Core/DolphinQt/Debugger/WatchWidget.h b/Source/Core/DolphinQt/Debugger/WatchWidget.h index 7d8711e39c..62e5c7b42a 100644 --- a/Source/Core/DolphinQt/Debugger/WatchWidget.h +++ b/Source/Core/DolphinQt/Debugger/WatchWidget.h @@ -17,7 +17,8 @@ class QToolBar; namespace Core { class CPUThreadGuard; -}; +class System; +}; // namespace Core class WatchWidget : public QDockWidget { @@ -62,6 +63,8 @@ private: void LockSelectedWatches(); void UnlockSelectedWatches(); + Core::System& m_system; + QAction* m_new; QAction* m_delete; QAction* m_clear; diff --git a/Source/Core/DolphinQt/DolphinQt.vcxproj b/Source/Core/DolphinQt/DolphinQt.vcxproj index 6ff16a13d2..033b89dfa4 100644 --- a/Source/Core/DolphinQt/DolphinQt.vcxproj +++ b/Source/Core/DolphinQt/DolphinQt.vcxproj @@ -73,7 +73,6 @@ - @@ -123,6 +122,7 @@ + @@ -273,7 +273,6 @@ - @@ -319,6 +318,7 @@ + diff --git a/Source/Core/DolphinQt/Main.cpp b/Source/Core/DolphinQt/Main.cpp index 849a5b5550..4b01bdcc27 100644 --- a/Source/Core/DolphinQt/Main.cpp +++ b/Source/Core/DolphinQt/Main.cpp @@ -143,7 +143,7 @@ int main(int argc, char* argv[]) // code, which makes mouse inputs work again. // For more information: https://bugs.dolphin-emu.org/issues/12913 #if (QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)) - putenv("QT_XCB_NO_XI2=1"); + setenv("QT_XCB_NO_XI2", "1", true); #endif #endif @@ -257,8 +257,6 @@ int main(int argc, char* argv[]) MainWindow win{std::move(boot), static_cast(options.get("movie"))}; Settings::Instance().SetCurrentUserStyle(Settings::Instance().GetCurrentUserStyle()); - if (options.is_set("debugger")) - Settings::Instance().SetDebugModeEnabled(true); win.Show(); #if defined(USE_ANALYTICS) && USE_ANALYTICS diff --git a/Source/Core/DolphinQt/MenuBar.cpp b/Source/Core/DolphinQt/MenuBar.cpp index 1c0634ce6e..b8ecc01526 100644 --- a/Source/Core/DolphinQt/MenuBar.cpp +++ b/Source/Core/DolphinQt/MenuBar.cpp @@ -779,7 +779,8 @@ void MenuBar::AddJITMenu() PowerPC::CPUCore::Interpreter); connect(m_jit_interpreter_core, &QAction::toggled, [](bool enabled) { - PowerPC::SetMode(enabled ? PowerPC::CoreMode::Interpreter : PowerPC::CoreMode::JIT); + Core::System::GetInstance().GetPowerPC().SetMode(enabled ? PowerPC::CoreMode::Interpreter : + PowerPC::CoreMode::JIT); }); m_jit->addSeparator(); @@ -1678,7 +1679,7 @@ void MenuBar::SearchInstruction() addr += 4) { const auto ins_name = QString::fromStdString( - PPCTables::GetInstructionName(PowerPC::MMU::HostRead_U32(guard, addr))); + PPCTables::GetInstructionName(PowerPC::MMU::HostRead_U32(guard, addr), addr)); if (op == ins_name) { NOTICE_LOG_FMT(POWERPC, "Found {} at {:08x}", op.toStdString(), addr); diff --git a/Source/Core/DolphinQt/QtUtils/FlowLayout.cpp b/Source/Core/DolphinQt/QtUtils/FlowLayout.cpp index 5ef3e0aa08..b2c4eb75d5 100644 --- a/Source/Core/DolphinQt/QtUtils/FlowLayout.cpp +++ b/Source/Core/DolphinQt/QtUtils/FlowLayout.cpp @@ -75,7 +75,7 @@ QLayoutItem* FlowLayout::takeAt(int index) if (index >= 0 && index < m_item_list.size()) return m_item_list.takeAt(index); else - return 0; + return nullptr; } Qt::Orientations FlowLayout::expandingDirections() const @@ -167,7 +167,7 @@ int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const else if (parent->isWidgetType()) { QWidget* pw = static_cast(parent); - return pw->style()->pixelMetric(pm, 0, pw); + return pw->style()->pixelMetric(pm, nullptr, pw); } else { diff --git a/Source/Core/DolphinQt/QtUtils/WinIconHelper.cpp b/Source/Core/DolphinQt/QtUtils/WinIconHelper.cpp index f1c39a4c09..7dc558371b 100644 --- a/Source/Core/DolphinQt/QtUtils/WinIconHelper.cpp +++ b/Source/Core/DolphinQt/QtUtils/WinIconHelper.cpp @@ -42,7 +42,7 @@ static QPixmap PixmapFromHICON(HICON icon) const int h = iconinfo.yHotspot * 2; BITMAPINFO bitmapInfo = GetBMI(w, h, false); DWORD* bits; - HBITMAP winBitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (VOID**)&bits, NULL, 0); + HBITMAP winBitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (VOID**)&bits, nullptr, 0); HGDIOBJ oldhdc = reinterpret_cast(SelectObject(hdc, winBitmap)); DrawIconEx(hdc, 0, 0, icon, iconinfo.xHotspot * 2, iconinfo.yHotspot * 2, 0, 0, DI_NORMAL); diff --git a/Source/Core/DolphinQt/Settings.cpp b/Source/Core/DolphinQt/Settings.cpp index bfc2f36ea1..d915f4e916 100644 --- a/Source/Core/DolphinQt/Settings.cpp +++ b/Source/Core/DolphinQt/Settings.cpp @@ -465,9 +465,9 @@ void Settings::SetDebugModeEnabled(bool enabled) { Config::SetBaseOrCurrent(Config::MAIN_ENABLE_DEBUGGING, enabled); emit DebugModeToggled(enabled); + if (enabled) + SetCodeVisible(true); } - if (enabled) - SetCodeVisible(true); } bool Settings::IsDebugModeEnabled() const diff --git a/Source/Core/DolphinQt/Settings/GameCubePane.cpp b/Source/Core/DolphinQt/Settings/GameCubePane.cpp index 55510fd9f9..a19fce31fb 100644 --- a/Source/Core/DolphinQt/Settings/GameCubePane.cpp +++ b/Source/Core/DolphinQt/Settings/GameCubePane.cpp @@ -410,7 +410,7 @@ void GameCubePane::BrowseMemcard(ExpansionInterface::Slot slot) const QString filename = DolphinFileDialog::getSaveFileName( this, tr("Choose a file to open or create"), QString::fromStdString(File::GetUserPath(D_GCUSER_IDX)), - tr("GameCube Memory Cards (*.raw *.gcp)"), 0, QFileDialog::DontConfirmOverwrite); + tr("GameCube Memory Cards (*.raw *.gcp)"), nullptr, QFileDialog::DontConfirmOverwrite); if (!filename.isEmpty()) SetMemcard(slot, filename); @@ -618,7 +618,7 @@ void GameCubePane::BrowseAGPRom(ExpansionInterface::Slot slot) QString filename = DolphinFileDialog::getSaveFileName( this, tr("Choose a file to open"), QString::fromStdString(File::GetUserPath(D_GCUSER_IDX)), - tr("Game Boy Advance Carts (*.gba)"), 0, QFileDialog::DontConfirmOverwrite); + tr("Game Boy Advance Carts (*.gba)"), nullptr, QFileDialog::DontConfirmOverwrite); if (!filename.isEmpty()) SetAGPRom(slot, filename); diff --git a/Source/Core/DolphinQt/Settings/InterfacePane.cpp b/Source/Core/DolphinQt/Settings/InterfacePane.cpp index f4d2222943..cd650520b8 100644 --- a/Source/Core/DolphinQt/Settings/InterfacePane.cpp +++ b/Source/Core/DolphinQt/Settings/InterfacePane.cpp @@ -204,6 +204,8 @@ void InterfacePane::CreateInGame() groupbox_layout->addWidget(mouse_groupbox); #ifdef _WIN32 groupbox_layout->addWidget(m_checkbox_lock_mouse); +#else + m_checkbox_lock_mouse->hide(); #endif } diff --git a/Source/Core/DolphinQt/TAS/IRWidget.cpp b/Source/Core/DolphinQt/TAS/IRWidget.cpp index 7bab30186b..1efa6748c5 100644 --- a/Source/Core/DolphinQt/TAS/IRWidget.cpp +++ b/Source/Core/DolphinQt/TAS/IRWidget.cpp @@ -79,6 +79,9 @@ void IRWidget::mouseMoveEvent(QMouseEvent* event) void IRWidget::handleMouseEvent(QMouseEvent* event) { + u16 prev_x = m_x; + u16 prev_y = m_y; + if (event->button() == Qt::RightButton) { m_x = std::round(ir_max_x / 2.); @@ -94,7 +97,18 @@ void IRWidget::handleMouseEvent(QMouseEvent* event) m_y = std::max(0, std::min(static_cast(ir_max_y), new_y)); } - emit ChangedX(m_x); - emit ChangedY(m_y); - update(); + bool changed = false; + if (prev_x != m_x) + { + emit ChangedX(m_x); + changed = true; + } + if (prev_y != m_y) + { + emit ChangedY(m_y); + changed = true; + } + + if (changed) + update(); } diff --git a/Source/Core/DolphinQt/TAS/StickWidget.cpp b/Source/Core/DolphinQt/TAS/StickWidget.cpp index 7a8842477a..fd43496930 100644 --- a/Source/Core/DolphinQt/TAS/StickWidget.cpp +++ b/Source/Core/DolphinQt/TAS/StickWidget.cpp @@ -82,6 +82,9 @@ void StickWidget::mouseMoveEvent(QMouseEvent* event) void StickWidget::handleMouseEvent(QMouseEvent* event) { + u16 prev_x = m_x; + u16 prev_y = m_y; + if (event->button() == Qt::RightButton) { m_x = std::round(m_max_x / 2.); @@ -97,7 +100,18 @@ void StickWidget::handleMouseEvent(QMouseEvent* event) m_y = std::max(0, std::min(static_cast(m_max_y), new_y)); } - emit ChangedX(m_x); - emit ChangedY(m_y); - update(); + bool changed = false; + if (prev_x != m_x) + { + emit ChangedX(m_x); + changed = true; + } + if (prev_y != m_y) + { + emit ChangedY(m_y); + changed = true; + } + + if (changed) + update(); } diff --git a/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp b/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp index b9bfc2802c..dc08148b79 100644 --- a/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp +++ b/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp @@ -353,7 +353,7 @@ WiiTASInputWindow::WiiTASInputWindow(QWidget* parent, int num) : TASInputWindow( } else { - IniFile ini; + Common::IniFile ini; ini.Load(File::GetUserPath(D_CONFIG_IDX) + "WiimoteNew.ini"); const std::string section_name = "Wiimote" + std::to_string(num + 1); diff --git a/Source/Core/DolphinQt/ToolBar.cpp b/Source/Core/DolphinQt/ToolBar.cpp index a72a4db63a..d921cc6227 100644 --- a/Source/Core/DolphinQt/ToolBar.cpp +++ b/Source/Core/DolphinQt/ToolBar.cpp @@ -157,14 +157,14 @@ void ToolBar::UpdatePausePlayButtonState(const bool playing_state) { if (playing_state) { - disconnect(m_pause_play_action, 0, 0, 0); + disconnect(m_pause_play_action, nullptr, nullptr, nullptr); m_pause_play_action->setText(tr("Pause")); m_pause_play_action->setIcon(Resources::GetScaledThemeIcon("pause")); connect(m_pause_play_action, &QAction::triggered, this, &ToolBar::PausePressed); } else { - disconnect(m_pause_play_action, 0, 0, 0); + disconnect(m_pause_play_action, nullptr, nullptr, nullptr); m_pause_play_action->setText(tr("Local Play")); m_pause_play_action->setIcon(Resources::GetScaledThemeIcon("play")); connect(m_pause_play_action, &QAction::triggered, this, &ToolBar::PlayPressed); diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.cpp index 0b69c7e6c2..2896acd070 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.cpp +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.cpp @@ -50,7 +50,7 @@ void ControlGroup::AddDeadzoneSetting(SettingValue* value, double maximu ControlGroup::~ControlGroup() = default; -void ControlGroup::LoadConfig(IniFile::Section* sec, const std::string& defdev, +void ControlGroup::LoadConfig(Common::IniFile::Section* sec, const std::string& defdev, const std::string& base) { const std::string group(base + name + "/"); @@ -103,7 +103,7 @@ void ControlGroup::LoadConfig(IniFile::Section* sec, const std::string& defdev, } } -void ControlGroup::SaveConfig(IniFile::Section* sec, const std::string& defdev, +void ControlGroup::SaveConfig(Common::IniFile::Section* sec, const std::string& defdev, const std::string& base) { const std::string group(base + name + "/"); diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.h index fb10bab074..f51fff6015 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.h +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.h @@ -68,9 +68,9 @@ public: DefaultValue default_value = DefaultValue::AlwaysEnabled); virtual ~ControlGroup(); - virtual void LoadConfig(IniFile::Section* sec, const std::string& defdev = "", + virtual void LoadConfig(Common::IniFile::Section* sec, const std::string& defdev = "", const std::string& base = ""); - virtual void SaveConfig(IniFile::Section* sec, const std::string& defdev = "", + virtual void SaveConfig(Common::IniFile::Section* sec, const std::string& defdev = "", const std::string& base = ""); void SetControlExpression(int index, const std::string& expression); diff --git a/Source/Core/InputCommon/ControllerEmu/ControllerEmu.cpp b/Source/Core/InputCommon/ControllerEmu/ControllerEmu.cpp index dc9830de3f..0f6f004d10 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControllerEmu.cpp +++ b/Source/Core/InputCommon/ControllerEmu/ControllerEmu.cpp @@ -139,7 +139,7 @@ void EmulatedController::SetDefaultDevice(ciface::Core::DeviceQualifier devq) } } -void EmulatedController::LoadConfig(IniFile::Section* sec, const std::string& base) +void EmulatedController::LoadConfig(Common::IniFile::Section* sec, const std::string& base) { const auto lock = GetStateLock(); std::string defdev = GetDefaultDevice().ToString(); @@ -153,7 +153,7 @@ void EmulatedController::LoadConfig(IniFile::Section* sec, const std::string& ba cg->LoadConfig(sec, defdev, base); } -void EmulatedController::SaveConfig(IniFile::Section* sec, const std::string& base) +void EmulatedController::SaveConfig(Common::IniFile::Section* sec, const std::string& base) { const auto lock = GetStateLock(); const std::string defdev = GetDefaultDevice().ToString(); @@ -168,7 +168,7 @@ void EmulatedController::LoadDefaults(const ControllerInterface& ciface) { const auto lock = GetStateLock(); // load an empty inifile section, clears everything - IniFile::Section sec; + Common::IniFile::Section sec; LoadConfig(&sec); const std::string& default_device_string = ciface.GetDefaultDeviceString(); diff --git a/Source/Core/InputCommon/ControllerEmu/ControllerEmu.h b/Source/Core/InputCommon/ControllerEmu/ControllerEmu.h index e7e957e608..2f505622eb 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControllerEmu.h +++ b/Source/Core/InputCommon/ControllerEmu/ControllerEmu.h @@ -182,8 +182,8 @@ public: virtual void LoadDefaults(const ControllerInterface& ciface); - virtual void LoadConfig(IniFile::Section* sec, const std::string& base = ""); - virtual void SaveConfig(IniFile::Section* sec, const std::string& base = ""); + virtual void LoadConfig(Common::IniFile::Section* sec, const std::string& base = ""); + virtual void SaveConfig(Common::IniFile::Section* sec, const std::string& base = ""); bool IsDefaultDeviceConnected() const; const ciface::Core::DeviceQualifier& GetDefaultDevice() const; diff --git a/Source/Core/InputCommon/ControllerEmu/Setting/NumericSetting.h b/Source/Core/InputCommon/ControllerEmu/Setting/NumericSetting.h index d123117eb0..67d2fce1c7 100644 --- a/Source/Core/InputCommon/ControllerEmu/Setting/NumericSetting.h +++ b/Source/Core/InputCommon/ControllerEmu/Setting/NumericSetting.h @@ -60,8 +60,10 @@ public: virtual ~NumericSettingBase() = default; - virtual void LoadFromIni(const IniFile::Section& section, const std::string& group_name) = 0; - virtual void SaveToIni(IniFile::Section& section, const std::string& group_name) const = 0; + virtual void LoadFromIni(const Common::IniFile::Section& section, + const std::string& group_name) = 0; + virtual void SaveToIni(Common::IniFile::Section& section, + const std::string& group_name) const = 0; virtual InputReference& GetInputReference() = 0; virtual const InputReference& GetInputReference() const = 0; @@ -111,7 +113,7 @@ public: void SetToDefault() override { m_value.SetValue(m_default_value); } - void LoadFromIni(const IniFile::Section& section, const std::string& group_name) override + void LoadFromIni(const Common::IniFile::Section& section, const std::string& group_name) override { std::string str_value; if (section.Get(group_name + m_details.ini_name, &str_value)) @@ -125,7 +127,7 @@ public: } } - void SaveToIni(IniFile::Section& section, const std::string& group_name) const override + void SaveToIni(Common::IniFile::Section& section, const std::string& group_name) const override { if (IsSimpleValue()) { diff --git a/Source/Core/InputCommon/ControllerEmu/StickGate.cpp b/Source/Core/InputCommon/ControllerEmu/StickGate.cpp index ce9259f06f..a476cce9ed 100644 --- a/Source/Core/InputCommon/ControllerEmu/StickGate.cpp +++ b/Source/Core/InputCommon/ControllerEmu/StickGate.cpp @@ -226,8 +226,8 @@ void ReshapableInput::SetCenter(ReshapableInput::ReshapeData center) m_center = center; } -void ReshapableInput::LoadConfig(IniFile::Section* section, const std::string& default_device, - const std::string& base_name) +void ReshapableInput::LoadConfig(Common::IniFile::Section* section, + const std::string& default_device, const std::string& base_name) { ControlGroup::LoadConfig(section, default_device, base_name); @@ -269,8 +269,8 @@ void ReshapableInput::LoadConfig(IniFile::Section* section, const std::string& d } } -void ReshapableInput::SaveConfig(IniFile::Section* section, const std::string& default_device, - const std::string& base_name) +void ReshapableInput::SaveConfig(Common::IniFile::Section* section, + const std::string& default_device, const std::string& base_name) { ControlGroup::SaveConfig(section, default_device, base_name); diff --git a/Source/Core/InputCommon/ControllerEmu/StickGate.h b/Source/Core/InputCommon/ControllerEmu/StickGate.h index 831762fda3..c618a0a4b4 100644 --- a/Source/Core/InputCommon/ControllerEmu/StickGate.h +++ b/Source/Core/InputCommon/ControllerEmu/StickGate.h @@ -117,8 +117,8 @@ protected: virtual Control* GetModifierInput() const; private: - void LoadConfig(IniFile::Section*, const std::string&, const std::string&) override; - void SaveConfig(IniFile::Section*, const std::string&, const std::string&) override; + void LoadConfig(Common::IniFile::Section*, const std::string&, const std::string&) override; + void SaveConfig(Common::IniFile::Section*, const std::string&, const std::string&) override; CalibrationData m_calibration; SettingValue m_deadzone_setting; diff --git a/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp b/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp index 36371fd368..e9f8d2fff2 100644 --- a/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp @@ -3,10 +3,8 @@ #include "InputCommon/ControllerInterface/Xlib/XInput2.h" -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wregister" #include -#pragma GCC diagnostic pop + #include #include #include diff --git a/Source/Core/InputCommon/DynamicInputTextureManager.cpp b/Source/Core/InputCommon/DynamicInputTextureManager.cpp index 8a325f8f7e..d3b47089a6 100644 --- a/Source/Core/InputCommon/DynamicInputTextureManager.cpp +++ b/Source/Core/InputCommon/DynamicInputTextureManager.cpp @@ -39,7 +39,7 @@ void DynamicInputTextureManager::Load() } } -void DynamicInputTextureManager::GenerateTextures(const IniFile& file, +void DynamicInputTextureManager::GenerateTextures(const Common::IniFile& file, const std::vector& controller_names) { bool any_dirty = false; diff --git a/Source/Core/InputCommon/DynamicInputTextureManager.h b/Source/Core/InputCommon/DynamicInputTextureManager.h index 8d7eeb8472..e4cba93ffa 100644 --- a/Source/Core/InputCommon/DynamicInputTextureManager.h +++ b/Source/Core/InputCommon/DynamicInputTextureManager.h @@ -20,7 +20,8 @@ public: DynamicInputTextureManager(); ~DynamicInputTextureManager(); void Load(); - void GenerateTextures(const IniFile& file, const std::vector& controller_names); + void GenerateTextures(const Common::IniFile& file, + const std::vector& controller_names); private: std::vector m_configuration; diff --git a/Source/Core/InputCommon/DynamicInputTextures/DITConfiguration.cpp b/Source/Core/InputCommon/DynamicInputTextures/DITConfiguration.cpp index fcdf879e8d..8b12fdff10 100644 --- a/Source/Core/InputCommon/DynamicInputTextures/DITConfiguration.cpp +++ b/Source/Core/InputCommon/DynamicInputTextures/DITConfiguration.cpp @@ -11,6 +11,7 @@ #include "Common/CommonPaths.h" #include "Common/FileUtil.h" +#include "Common/IniFile.h" #include "Common/Logging/Log.h" #include "Common/StringUtil.h" #include "Core/ConfigManager.h" @@ -86,7 +87,7 @@ Configuration::Configuration(const std::string& json_file) Configuration::~Configuration() = default; -bool Configuration::GenerateTextures(const IniFile& file, +bool Configuration::GenerateTextures(const Common::IniFile& file, const std::vector& controller_names) const { bool any_dirty = false; @@ -98,7 +99,7 @@ bool Configuration::GenerateTextures(const IniFile& file, return any_dirty; } -bool Configuration::GenerateTexture(const IniFile& file, +bool Configuration::GenerateTexture(const Common::IniFile& file, const std::vector& controller_names, const Data& texture_data) const { diff --git a/Source/Core/InputCommon/DynamicInputTextures/DITConfiguration.h b/Source/Core/InputCommon/DynamicInputTextures/DITConfiguration.h index 635e1883a1..4835fa6619 100644 --- a/Source/Core/InputCommon/DynamicInputTextures/DITConfiguration.h +++ b/Source/Core/InputCommon/DynamicInputTextures/DITConfiguration.h @@ -4,13 +4,16 @@ #pragma once #include -#include #include #include "Common/CommonTypes.h" -#include "Common/IniFile.h" #include "InputCommon/DynamicInputTextures/DITData.h" +namespace Common +{ +class IniFile; +} + namespace InputCommon::DynamicInputTextures { class Configuration @@ -18,11 +21,12 @@ class Configuration public: explicit Configuration(const std::string& json_file); ~Configuration(); - bool GenerateTextures(const IniFile& file, + bool GenerateTextures(const Common::IniFile& file, const std::vector& controller_names) const; private: - bool GenerateTexture(const IniFile& file, const std::vector& controller_names, + bool GenerateTexture(const Common::IniFile& file, + const std::vector& controller_names, const Data& texture_data) const; std::vector m_dynamic_input_textures; diff --git a/Source/Core/InputCommon/InputConfig.cpp b/Source/Core/InputCommon/InputConfig.cpp index 9605aa8c33..64610ba768 100644 --- a/Source/Core/InputCommon/InputConfig.cpp +++ b/Source/Core/InputCommon/InputConfig.cpp @@ -29,7 +29,7 @@ InputConfig::~InputConfig() = default; bool InputConfig::LoadConfig(InputClass type) { - IniFile inifile; + Common::IniFile inifile; bool useProfile[MAX_BBMOTES] = {false, false, false, false, false}; static constexpr std::array num = {"1", "2", "3", "4", "BB"}; std::string profile[MAX_BBMOTES]; @@ -57,8 +57,8 @@ bool InputConfig::LoadConfig(InputClass type) break; } - IniFile game_ini = SConfig::GetInstance().LoadGameIni(); - IniFile::Section* control_section = game_ini.GetOrCreateSection("Controls"); + Common::IniFile game_ini = SConfig::GetInstance().LoadGameIni(); + auto* control_section = game_ini.GetOrCreateSection("Controls"); for (int i = 0; i < 4; i++) { @@ -95,7 +95,7 @@ bool InputConfig::LoadConfig(InputClass type) std::vector controller_names; for (auto& controller : m_controllers) { - IniFile::Section config; + Common::IniFile::Section config; // Load settings from ini if (useProfile[n]) { @@ -146,7 +146,7 @@ void InputConfig::SaveConfig() { std::string ini_filename = File::GetUserPath(D_CONFIG_IDX) + m_ini_name + ".ini"; - IniFile inifile; + Common::IniFile inifile; inifile.Load(ini_filename); std::vector controller_names; @@ -212,7 +212,7 @@ bool InputConfig::IsControllerControlledByGamepadDevice(int index) const controller.name == "Keyboard Mouse")); // Windows Keyboard/Mouse } -void InputConfig::GenerateControllerTextures(const IniFile& file) +void InputConfig::GenerateControllerTextures(const Common::IniFile& file) { std::vector controller_names; for (auto& controller : m_controllers) diff --git a/Source/Core/InputCommon/InputConfig.h b/Source/Core/InputCommon/InputConfig.h index 2c3f290576..a0d0203df6 100644 --- a/Source/Core/InputCommon/InputConfig.h +++ b/Source/Core/InputCommon/InputConfig.h @@ -11,6 +11,11 @@ #include "InputCommon/ControllerInterface/ControllerInterface.h" #include "InputCommon/DynamicInputTextureManager.h" +namespace Common +{ +class IniFile; +} + namespace ControllerEmu { class EmulatedController; @@ -53,7 +58,7 @@ public: void RegisterHotplugCallback(); void UnregisterHotplugCallback(); - void GenerateControllerTextures(const IniFile& file); + void GenerateControllerTextures(const Common::IniFile& file); private: ControllerInterface::HotplugCallbackHandle m_hotplug_callback_handle; diff --git a/Source/Core/InputCommon/InputProfile.cpp b/Source/Core/InputCommon/InputProfile.cpp index 492b45975e..81d04cf75a 100644 --- a/Source/Core/InputCommon/InputProfile.cpp +++ b/Source/Core/InputCommon/InputProfile.cpp @@ -78,7 +78,7 @@ void ProfileCycler::UpdateToProfile(const std::string& profile_filename, std::string base; SplitPath(profile_filename, nullptr, &base, nullptr); - IniFile ini_file; + Common::IniFile ini_file; if (ini_file.Load(profile_filename)) { Core::DisplayMessage("Loading input profile '" + base + "' for device '" + @@ -180,8 +180,8 @@ void ProfileCycler::CycleProfileForGame(CycleDirection cycle_direction, std::string ProfileCycler::GetWiimoteInputProfilesForGame(int controller_index) { - IniFile game_ini = SConfig::GetInstance().LoadGameIni(); - const IniFile::Section* const control_section = game_ini.GetOrCreateSection("Controls"); + Common::IniFile game_ini = SConfig::GetInstance().LoadGameIni(); + const auto* const control_section = game_ini.GetOrCreateSection("Controls"); std::string result; control_section->Get(fmt::format("WiimoteProfile{}", controller_index + 1), &result); diff --git a/Source/Core/UICommon/AutoUpdate.cpp b/Source/Core/UICommon/AutoUpdate.cpp index fab935282a..c71ebd11b8 100644 --- a/Source/Core/UICommon/AutoUpdate.cpp +++ b/Source/Core/UICommon/AutoUpdate.cpp @@ -250,13 +250,13 @@ void AutoUpdateChecker::TriggerUpdate(const AutoUpdateChecker::NewVersionInforma } else { - const std::string error = GetLastErrorString(); + const std::string error = Common::GetLastErrorString(); CriticalAlertFmtT("Could not start updater process: {0}", error); } #else if (popen(command_line.c_str(), "r") == nullptr) { - const std::string error = LastStrerrorString(); + const std::string error = Common::LastStrerrorString(); CriticalAlertFmtT("Could not start updater process: {0}", error); } #endif diff --git a/Source/Core/UICommon/CommandLineParse.cpp b/Source/Core/UICommon/CommandLineParse.cpp index 54093f219a..a37f0f2561 100644 --- a/Source/Core/UICommon/CommandLineParse.cpp +++ b/Source/Core/UICommon/CommandLineParse.cpp @@ -22,7 +22,7 @@ class CommandLineConfigLayerLoader final : public Config::ConfigLayerLoader { public: CommandLineConfigLayerLoader(const std::list& args, const std::string& video_backend, - const std::string& audio_backend, bool batch) + const std::string& audio_backend, bool batch, bool debugger) : ConfigLayerLoader(Config::LayerType::CommandLine) { if (!video_backend.empty()) @@ -39,6 +39,9 @@ public: if (batch) m_values.emplace_back(Config::MAIN_RENDER_TO_MAIN.GetLocation(), ValueToString(false)); + if (debugger) + m_values.emplace_back(Config::MAIN_ENABLE_DEBUGGING.GetLocation(), ValueToString(true)); + // Arguments are in the format of .
.=Value for (const auto& arg : args) { @@ -134,7 +137,7 @@ static void AddConfigLayer(const optparse::Values& options) Config::AddLayer(std::make_unique( std::move(config_args), static_cast(options.get("video_backend")), static_cast(options.get("audio_emulation")), - static_cast(options.get("batch")))); + static_cast(options.get("batch")), static_cast(options.get("debugger")))); } optparse::Values& ParseArguments(optparse::OptionParser* parser, int argc, char** argv) diff --git a/Source/Core/UICommon/Disassembler.cpp b/Source/Core/UICommon/Disassembler.cpp index 840af8ec1f..a4cd3ad344 100644 --- a/Source/Core/UICommon/Disassembler.cpp +++ b/Source/Core/UICommon/Disassembler.cpp @@ -47,7 +47,8 @@ HostDisassemblerLLVM::HostDisassemblerLLVM(const std::string& host_disasm, int i LLVMInitializeAllTargetMCs(); LLVMInitializeAllDisassemblers(); - m_llvm_context = LLVMCreateDisasmCPU(host_disasm.c_str(), cpu.c_str(), nullptr, 0, 0, nullptr); + m_llvm_context = + LLVMCreateDisasmCPU(host_disasm.c_str(), cpu.c_str(), nullptr, 0, nullptr, nullptr); // Couldn't create llvm context if (!m_llvm_context) diff --git a/Source/Core/UICommon/ResourcePack/Manager.cpp b/Source/Core/UICommon/ResourcePack/Manager.cpp index 2d1cf128ec..8d5e934c55 100644 --- a/Source/Core/UICommon/ResourcePack/Manager.cpp +++ b/Source/Core/UICommon/ResourcePack/Manager.cpp @@ -17,11 +17,11 @@ namespace std::vector packs; std::string packs_path; -IniFile GetPackConfig() +Common::IniFile GetPackConfig() { packs_path = File::GetUserPath(D_RESOURCEPACK_IDX) + "/Packs.ini"; - IniFile file; + Common::IniFile file; file.Load(packs_path); return file; @@ -34,7 +34,7 @@ bool Init() const std::vector pack_list = Common::DoFileSearch({File::GetUserPath(D_RESOURCEPACK_IDX)}, {".zip"}); - IniFile file = GetPackConfig(); + Common::IniFile file = GetPackConfig(); auto* order = file.GetOrCreateSection("Order"); @@ -123,7 +123,7 @@ ResourcePack* Add(const std::string& path, int offset) if (!pack.IsValid()) return nullptr; - IniFile file = GetPackConfig(); + Common::IniFile file = GetPackConfig(); auto* order = file.GetOrCreateSection("Order"); @@ -150,7 +150,7 @@ bool Remove(ResourcePack& pack) if (pack_iterator == packs.end()) return false; - IniFile file = GetPackConfig(); + Common::IniFile file = GetPackConfig(); auto* order = file.GetOrCreateSection("Order"); @@ -170,7 +170,7 @@ bool Remove(ResourcePack& pack) void SetInstalled(const ResourcePack& pack, bool installed) { - IniFile file = GetPackConfig(); + Common::IniFile file = GetPackConfig(); auto* install = file.GetOrCreateSection("Installed"); @@ -184,7 +184,7 @@ void SetInstalled(const ResourcePack& pack, bool installed) bool IsInstalled(const ResourcePack& pack) { - IniFile file = GetPackConfig(); + Common::IniFile file = GetPackConfig(); auto* install = file.GetOrCreateSection("Installed"); diff --git a/Source/Core/UICommon/ResourcePack/ResourcePack.cpp b/Source/Core/UICommon/ResourcePack/ResourcePack.cpp index 355dc8acf2..7f670e7748 100644 --- a/Source/Core/UICommon/ResourcePack/ResourcePack.cpp +++ b/Source/Core/UICommon/ResourcePack/ResourcePack.cpp @@ -36,7 +36,7 @@ ResourcePack::ResourcePack(const std::string& path) : m_path(path) return; } - if (unzLocateFile(file, "manifest.json", 0) == UNZ_END_OF_LIST_OF_FILE) + if (unzLocateFile(file, "manifest.json", nullptr) == UNZ_END_OF_LIST_OF_FILE) { m_valid = false; m_error = "Resource pack is missing a manifest."; @@ -63,7 +63,7 @@ ResourcePack::ResourcePack(const std::string& path) : m_path(path) return; } - if (unzLocateFile(file, "logo.png", 0) != UNZ_END_OF_LIST_OF_FILE) + if (unzLocateFile(file, "logo.png", nullptr) != UNZ_END_OF_LIST_OF_FILE) { unz_file_info64 logo_info{}; unzGetCurrentFileInfo64(file, &logo_info, nullptr, 0, nullptr, 0, nullptr, 0); diff --git a/Source/Core/UICommon/UICommon.cpp b/Source/Core/UICommon/UICommon.cpp index 6b345e3b81..464646eb17 100644 --- a/Source/Core/UICommon/UICommon.cpp +++ b/Source/Core/UICommon/UICommon.cpp @@ -547,7 +547,7 @@ std::string FormatSize(u64 bytes, int decimals) // div 10 to get largest named unit less than size // 10 == log2(1024) (number of B in a KiB, KiB in a MiB, etc) // Max value is 63 / 10 = 6 - const int unit = IntLog2(std::max(bytes, 1)) / 10; + const int unit = MathUtil::IntLog2(std::max(bytes, 1)) / 10; // Don't need exact values, only 5 most significant digits const double unit_size = std::pow(2, unit * 10); diff --git a/Source/Core/UpdaterCommon/UpdaterCommon.cpp b/Source/Core/UpdaterCommon/UpdaterCommon.cpp index 408c313c95..bba12b8f48 100644 --- a/Source/Core/UpdaterCommon/UpdaterCommon.cpp +++ b/Source/Core/UpdaterCommon/UpdaterCommon.cpp @@ -58,7 +58,7 @@ void LogToFile(const char* fmt, ...) va_end(args); } -bool ProgressCallback(double total, double now, double, double) +bool ProgressCallback(s64 total, s64 now, s64, s64) { UI::SetCurrentProgress(static_cast(now), static_cast(total)); return true; @@ -373,7 +373,7 @@ bool UpdateFiles(const std::vector& to_update, const std::string& install_base_path, const std::string& temp_path) { #ifdef _WIN32 - const auto self_path = std::filesystem::path(GetModuleName(nullptr).value()); + const auto self_path = std::filesystem::path(Common::GetModuleName(nullptr).value()); const auto self_filename = self_path.filename(); #endif diff --git a/Source/Core/VideoBackends/CMakeLists.txt b/Source/Core/VideoBackends/CMakeLists.txt index 55b44f8c5d..9d20d6d2b5 100644 --- a/Source/Core/VideoBackends/CMakeLists.txt +++ b/Source/Core/VideoBackends/CMakeLists.txt @@ -2,7 +2,7 @@ add_subdirectory(OGL) add_subdirectory(Null) add_subdirectory(Software) -if(CMAKE_SYSTEM_NAME STREQUAL "Windows") +if(WIN32) add_subdirectory(D3DCommon) add_subdirectory(D3D) add_subdirectory(D3D12) diff --git a/Source/Core/VideoBackends/D3D12/DX12Context.cpp b/Source/Core/VideoBackends/D3D12/DX12Context.cpp index 8343e39a6e..19a13f64b4 100644 --- a/Source/Core/VideoBackends/D3D12/DX12Context.cpp +++ b/Source/Core/VideoBackends/D3D12/DX12Context.cpp @@ -221,7 +221,7 @@ bool DXContext::CreateFence() return false; m_fence_event = CreateEvent(nullptr, FALSE, FALSE, nullptr); - ASSERT_MSG(VIDEO, m_fence_event != NULL, "Failed to create fence event"); + ASSERT_MSG(VIDEO, m_fence_event != nullptr, "Failed to create fence event"); if (!m_fence_event) return false; diff --git a/Source/Core/VideoBackends/Metal/MTLStateTracker.h b/Source/Core/VideoBackends/Metal/MTLStateTracker.h index f425cd2884..54e16cac7e 100644 --- a/Source/Core/VideoBackends/Metal/MTLStateTracker.h +++ b/Source/Core/VideoBackends/Metal/MTLStateTracker.h @@ -17,6 +17,7 @@ #include "VideoBackends/Metal/MTLTexture.h" #include "VideoBackends/Metal/MTLUtil.h" +#include "VideoCommon/Constants.h" #include "VideoCommon/FramebufferManager.h" #include "VideoCommon/PerfQueryBase.h" @@ -194,6 +195,8 @@ private: // MARK: State u8 m_dirty_textures; u8 m_dirty_samplers; + static_assert(sizeof(m_dirty_textures) * 8 >= VideoCommon::MAX_PIXEL_SHADER_SAMPLERS, + "Make these bigger"); union Flags { struct @@ -249,11 +252,11 @@ private: Util::Viewport viewport; const Pipeline* render_pipeline = nullptr; const ComputePipeline* compute_pipeline = nullptr; - std::array, 8> textures = {}; - std::array, 8> samplers = {}; - std::array sampler_min_lod; - std::array sampler_max_lod; - std::array sampler_states; + std::array, VideoCommon::MAX_PIXEL_SHADER_SAMPLERS> textures = {}; + std::array, VideoCommon::MAX_PIXEL_SHADER_SAMPLERS> samplers = {}; + std::array sampler_min_lod; + std::array sampler_max_lod; + std::array sampler_states; const Texture* compute_texture = nullptr; std::unique_ptr utility_uniform; u32 utility_uniform_size = 0; @@ -267,6 +270,7 @@ private: u32 texel_buffer_offset0; u32 texel_buffer_offset1; PerfQueryGroup perf_query_group = static_cast(-1); + u32 perf_query_id; } m_state; u32 m_perf_query_tracker_counter = 0; diff --git a/Source/Core/VideoBackends/Metal/MTLStateTracker.mm b/Source/Core/VideoBackends/Metal/MTLStateTracker.mm index 53462b9bdf..f699657ade 100644 --- a/Source/Core/VideoBackends/Metal/MTLStateTracker.mm +++ b/Source/Core/VideoBackends/Metal/MTLStateTracker.mm @@ -371,8 +371,8 @@ void Metal::StateTracker::BeginRenderPass(MTLRenderPassDescriptor* descriptor) m_current.cull_mode = MTLCullModeNone; m_current.perf_query_group = static_cast(-1); m_flags.NewEncoder(); - m_dirty_samplers = 0xff; - m_dirty_textures = 0xff; + m_dirty_samplers = (1 << VideoCommon::MAX_PIXEL_SHADER_SAMPLERS) - 1; + m_dirty_textures = (1 << VideoCommon::MAX_PIXEL_SHADER_SAMPLERS) - 1; CheckScissor(); CheckViewport(); ASSERT_MSG(VIDEO, m_current_render_encoder, "Failed to create render encoder!"); @@ -386,8 +386,8 @@ void Metal::StateTracker::BeginComputePass() if (m_manual_buffer_upload) [m_current_compute_encoder waitForFence:m_fence]; m_flags.NewEncoder(); - m_dirty_samplers = 0xff; - m_dirty_textures = 0xff; + m_dirty_samplers = (1 << VideoCommon::MAX_PIXEL_SHADER_SAMPLERS) - 1; + m_dirty_textures = (1 << VideoCommon::MAX_PIXEL_SHADER_SAMPLERS) - 1; } void Metal::StateTracker::EndRenderPass() @@ -674,6 +674,7 @@ std::shared_ptr Metal::StateTracker::NewP m_perf_query_tracker_counter++]]; tracker->buffer = MRCTransfer(buffer); tracker->contents = static_cast([buffer contents]); + tracker->query_id = m_state.perf_query_id; return tracker; } } @@ -682,6 +683,8 @@ std::shared_ptr Metal::StateTracker::NewP // Reuse an old one std::shared_ptr tracker = std::move(m_perf_query_tracker_cache.back()); m_perf_query_tracker_cache.pop_back(); + tracker->groups.clear(); + tracker->query_id = m_state.perf_query_id; return tracker; } } @@ -689,15 +692,26 @@ std::shared_ptr Metal::StateTracker::NewP void Metal::StateTracker::EnablePerfQuery(PerfQueryGroup group, u32 query_id) { m_state.perf_query_group = group; + m_state.perf_query_id = query_id; if (!m_current_perf_query || m_current_perf_query->query_id != query_id || m_current_perf_query->groups.size() == PERF_QUERY_BUFFER_SIZE) { if (m_current_render_encoder) EndRenderPass(); - if (!m_current_perf_query) - m_current_perf_query = NewPerfQueryTracker(); - m_current_perf_query->groups.clear(); - m_current_perf_query->query_id = query_id; + if (m_current_perf_query) + { + [m_current_render_cmdbuf + addCompletedHandler:[backref = m_backref, q = std::move(m_current_perf_query)](id) { + std::lock_guard guard(backref->mtx); + if (StateTracker* tracker = backref->state_tracker) + { + if (PerfQuery* query = static_cast(g_perf_query.get())) + query->ReturnResults(q->contents, q->groups.data(), q->groups.size(), q->query_id); + tracker->m_perf_query_tracker_cache.emplace_back(std::move(q)); + } + }]; + m_current_perf_query.reset(); + } } } @@ -801,13 +815,13 @@ void Metal::StateTracker::PrepareRender() if (m_state.vertices) SetVertexBufferNow(0, m_state.vertices, 0); } - if (u8 dirty = m_dirty_textures & pipe->GetTextures()) + if (u32 dirty = m_dirty_textures & pipe->GetTextures()) { m_dirty_textures &= ~pipe->GetTextures(); NSRange range = RangeOfBits(dirty); [enc setFragmentTextures:&m_state.textures[range.location] withRange:range]; } - if (u8 dirty = m_dirty_samplers & pipe->GetSamplers()) + if (u32 dirty = m_dirty_samplers & pipe->GetSamplers()) { m_dirty_samplers &= ~pipe->GetSamplers(); NSRange range = RangeOfBits(dirty); diff --git a/Source/Core/VideoBackends/OGL/OGLStreamBuffer.cpp b/Source/Core/VideoBackends/OGL/OGLStreamBuffer.cpp index b4f26db453..1d5deadfcf 100644 --- a/Source/Core/VideoBackends/OGL/OGLStreamBuffer.cpp +++ b/Source/Core/VideoBackends/OGL/OGLStreamBuffer.cpp @@ -25,7 +25,7 @@ static u32 GenBuffer() StreamBuffer::StreamBuffer(u32 type, u32 size) : m_buffer(GenBuffer()), m_buffertype(type), m_size(MathUtil::NextPowerOf2(size)), - m_bit_per_slot(IntLog2(MathUtil::NextPowerOf2(size) / SYNC_POINTS)) + m_bit_per_slot(MathUtil::IntLog2(MathUtil::NextPowerOf2(size) / SYNC_POINTS)) { m_iterator = 0; m_used_iterator = 0; diff --git a/Source/Core/VideoBackends/OGL/OGLTexture.cpp b/Source/Core/VideoBackends/OGL/OGLTexture.cpp index ad0e32bb39..4e90211c59 100644 --- a/Source/Core/VideoBackends/OGL/OGLTexture.cpp +++ b/Source/Core/VideoBackends/OGL/OGLTexture.cpp @@ -296,7 +296,7 @@ OGLStagingTexture::OGLStagingTexture(StagingTextureType type, const TextureConfi OGLStagingTexture::~OGLStagingTexture() { - if (m_fence != 0) + if (m_fence != nullptr) glDeleteSync(m_fence); if (m_map_pointer) { @@ -418,7 +418,7 @@ void OGLStagingTexture::CopyFromTexture(const AbstractTexture* src, // If we support buffer storage, create a fence for synchronization. if (UsePersistentStagingBuffers()) { - if (m_fence != 0) + if (m_fence != nullptr) glDeleteSync(m_fence); glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT); @@ -479,7 +479,7 @@ void OGLStagingTexture::CopyToTexture(const MathUtil::Rectangle& src_rect, // If we support buffer storage, create a fence for synchronization. if (UsePersistentStagingBuffers()) { - if (m_fence != 0) + if (m_fence != nullptr) glDeleteSync(m_fence); m_fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); @@ -493,7 +493,7 @@ void OGLStagingTexture::Flush() { // No-op when not using buffer storage, as the transfers happen on Map(). // m_fence will always be zero in this case. - if (m_fence == 0) + if (m_fence == nullptr) { m_needs_flush = false; return; @@ -501,7 +501,7 @@ void OGLStagingTexture::Flush() glClientWaitSync(m_fence, 0, GL_TIMEOUT_IGNORED); glDeleteSync(m_fence); - m_fence = 0; + m_fence = nullptr; m_needs_flush = false; } diff --git a/Source/Core/VideoBackends/OGL/OGLTexture.h b/Source/Core/VideoBackends/OGL/OGLTexture.h index 9d1c119505..f80aa98725 100644 --- a/Source/Core/VideoBackends/OGL/OGLTexture.h +++ b/Source/Core/VideoBackends/OGL/OGLTexture.h @@ -75,7 +75,7 @@ private: GLenum m_target; GLuint m_buffer_name; size_t m_buffer_size; - GLsync m_fence = 0; + GLsync m_fence = nullptr; }; class OGLFramebuffer final : public AbstractFramebuffer diff --git a/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp b/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp index 68683790e7..b603ad36d4 100644 --- a/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp +++ b/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp @@ -473,7 +473,7 @@ void ObjectCache::DestroyRenderPassCache() m_render_pass_cache.clear(); } -class PipelineCacheReadCallback : public LinearDiskCacheReader +class PipelineCacheReadCallback : public Common::LinearDiskCacheReader { public: PipelineCacheReadCallback(std::vector* data) : m_data(data) {} @@ -488,7 +488,7 @@ private: std::vector* m_data; }; -class PipelineCacheReadIgnoreCallback : public LinearDiskCacheReader +class PipelineCacheReadIgnoreCallback : public Common::LinearDiskCacheReader { public: void Read(const u32& key, const u8* value, u32 value_size) override {} @@ -525,7 +525,7 @@ bool ObjectCache::LoadPipelineCache() m_pipeline_cache_filename = GetDiskShaderCacheFileName(APIType::Vulkan, "Pipeline", false, true); std::vector disk_data; - LinearDiskCache disk_cache; + Common::LinearDiskCache disk_cache; PipelineCacheReadCallback read_callback(&disk_data); if (disk_cache.OpenAndRead(m_pipeline_cache_filename, read_callback) != 1) disk_data.clear(); @@ -651,7 +651,7 @@ void ObjectCache::SavePipelineCache() // We write a single key of 1, with the entire pipeline cache data. // Not ideal, but our disk cache class does not support just writing a single blob // of data without specifying a key. - LinearDiskCache disk_cache; + Common::LinearDiskCache disk_cache; PipelineCacheReadIgnoreCallback callback; disk_cache.OpenAndRead(m_pipeline_cache_filename, callback); disk_cache.Append(1, data.data(), static_cast(data.size())); diff --git a/Source/Core/VideoCommon/CPMemory.cpp b/Source/Core/VideoCommon/CPMemory.cpp index 3d72a6f70b..a42ee8fc2e 100644 --- a/Source/Core/VideoCommon/CPMemory.cpp +++ b/Source/Core/VideoCommon/CPMemory.cpp @@ -4,6 +4,7 @@ #include "VideoCommon/CPMemory.h" #include +#include #include "Common/ChunkFile.h" #include "Common/Logging/Log.h" @@ -17,14 +18,9 @@ CPState g_preprocess_cp_state; void CopyPreprocessCPStateFromMain() { -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wclass-memaccess" -#endif - std::memcpy(&g_preprocess_cp_state, &g_main_cp_state, sizeof(CPState)); -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif + static_assert(std::is_trivially_copyable_v); + std::memcpy(static_cast(&g_preprocess_cp_state), + static_cast(&g_main_cp_state), sizeof(CPState)); } std::pair GetCPRegInfo(u8 cmd, u32 value) diff --git a/Source/Core/VideoCommon/CommandProcessor.cpp b/Source/Core/VideoCommon/CommandProcessor.cpp index 75cedcf96f..3174c2983a 100644 --- a/Source/Core/VideoCommon/CommandProcessor.cpp +++ b/Source/Core/VideoCommon/CommandProcessor.cpp @@ -637,7 +637,8 @@ void CommandProcessorManager::SetCpClearRegister() { } -void CommandProcessorManager::HandleUnknownOpcode(u8 cmd_byte, const u8* buffer, bool preprocess) +void CommandProcessorManager::HandleUnknownOpcode(Core::System& system, u8 cmd_byte, + const u8* buffer, bool preprocess) { const auto& fifo = m_fifo; @@ -665,6 +666,7 @@ void CommandProcessorManager::HandleUnknownOpcode(u8 cmd_byte, const u8* buffer, // PC and LR are meaningless when using the fifoplayer, and will generally not be helpful if the // unknown opcode is inside of a display list. Also note that the changes in GPFifo.h are not // accurate and may introduce timing issues. + const auto& ppc_state = system.GetPPCState(); GENERIC_LOG_FMT( Common::Log::LogType::VIDEO, log_level, "FIFO: Unknown Opcode {:#04x} @ {}, preprocessing = {}, CPBase: {:#010x}, CPEnd: " @@ -686,8 +688,8 @@ void CommandProcessorManager::HandleUnknownOpcode(u8 cmd_byte, const u8* buffer, fifo.bFF_Breakpoint.load(std::memory_order_relaxed) ? "true" : "false", fifo.bFF_GPLinkEnable.load(std::memory_order_relaxed) ? "true" : "false", fifo.bFF_HiWatermarkInt.load(std::memory_order_relaxed) ? "true" : "false", - fifo.bFF_LoWatermarkInt.load(std::memory_order_relaxed) ? "true" : "false", - PowerPC::ppcState.pc, LR(PowerPC::ppcState)); + fifo.bFF_LoWatermarkInt.load(std::memory_order_relaxed) ? "true" : "false", ppc_state.pc, + LR(ppc_state)); if (!m_is_fifo_error_seen && !suppress_panic_alert) { diff --git a/Source/Core/VideoCommon/CommandProcessor.h b/Source/Core/VideoCommon/CommandProcessor.h index 34b1e8701f..ccc381b535 100644 --- a/Source/Core/VideoCommon/CommandProcessor.h +++ b/Source/Core/VideoCommon/CommandProcessor.h @@ -177,7 +177,7 @@ public: void SetCpControlRegister(Core::System& system); void SetCpStatusRegister(Core::System& system); - void HandleUnknownOpcode(u8 cmd_byte, const u8* buffer, bool preprocess); + void HandleUnknownOpcode(Core::System& system, u8 cmd_byte, const u8* buffer, bool preprocess); // This one is shared between gfx thread and emulator thread. // It is only used by the Fifo and by the CommandProcessor. diff --git a/Source/Core/VideoCommon/OpcodeDecoding.cpp b/Source/Core/VideoCommon/OpcodeDecoding.cpp index 9ffb59a277..4d43c6e66a 100644 --- a/Source/Core/VideoCommon/OpcodeDecoding.cpp +++ b/Source/Core/VideoCommon/OpcodeDecoding.cpp @@ -219,8 +219,8 @@ public: } else { - Core::System::GetInstance().GetCommandProcessor().HandleUnknownOpcode(opcode, data, - is_preprocess); + auto& system = Core::System::GetInstance(); + system.GetCommandProcessor().HandleUnknownOpcode(system, opcode, data, is_preprocess); m_cycles += 1; } } diff --git a/Source/Core/VideoCommon/PostProcessing.cpp b/Source/Core/VideoCommon/PostProcessing.cpp index 7f4faed582..601d340b0b 100644 --- a/Source/Core/VideoCommon/PostProcessing.cpp +++ b/Source/Core/VideoCommon/PostProcessing.cpp @@ -151,7 +151,7 @@ void PostProcessingConfiguration::LoadOptions(const std::string& code) if (current_strings) { std::string key, value; - IniFile::ParseLine(line, &key, &value); + Common::IniFile::ParseLine(line, &key, &value); if (!(key.empty() && value.empty())) current_strings->m_options.emplace_back(key, value); @@ -238,7 +238,7 @@ void PostProcessingConfiguration::LoadOptions(const std::string& code) void PostProcessingConfiguration::LoadOptionsConfiguration() { - IniFile ini; + Common::IniFile ini; ini.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX)); std::string section = m_current_shader + "-options"; @@ -272,7 +272,7 @@ void PostProcessingConfiguration::LoadOptionsConfiguration() void PostProcessingConfiguration::SaveOptionsConfiguration() { - IniFile ini; + Common::IniFile ini; ini.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX)); std::string section = m_current_shader + "-options"; diff --git a/Source/Core/VideoCommon/ShaderCache.cpp b/Source/Core/VideoCommon/ShaderCache.cpp index 1c01356c99..d1deef8424 100644 --- a/Source/Core/VideoCommon/ShaderCache.cpp +++ b/Source/Core/VideoCommon/ShaderCache.cpp @@ -228,11 +228,11 @@ static void UnserializePipelineUid(const SerializedUidType& uid, UidType& real_u template void ShaderCache::LoadShaderCache(T& cache, APIType api_type, const char* type, bool include_gameid) { - class CacheReader : public LinearDiskCacheReader + class CacheReader : public Common::LinearDiskCacheReader { public: CacheReader(T& cache_) : cache(cache_) {} - void Read(const K& key, const u8* value, u32 value_size) + void Read(const K& key, const u8* value, u32 value_size) override { auto shader = g_gfx->CreateShaderFromBinary(stage, value, value_size); if (shader) @@ -276,15 +276,15 @@ void ShaderCache::ClearShaderCache(T& cache) } template -void ShaderCache::LoadPipelineCache(T& cache, LinearDiskCache& disk_cache, +void ShaderCache::LoadPipelineCache(T& cache, Common::LinearDiskCache& disk_cache, APIType api_type, const char* type, bool include_gameid) { - class CacheReader : public LinearDiskCacheReader + class CacheReader : public Common::LinearDiskCacheReader { public: CacheReader(ShaderCache* this_ptr_, T& cache_) : this_ptr(this_ptr_), cache(cache_) {} bool AnyFailed() const { return failed; } - void Read(const DiskKeyType& key, const u8* value, u32 value_size) + void Read(const DiskKeyType& key, const u8* value, u32 value_size) override { KeyType real_uid; UnserializePipelineUid(key, real_uid); @@ -608,14 +608,10 @@ AbstractPipelineConfig ShaderCache::GetGXPipelineConfig( static GXPipelineUid ApplyDriverBugs(const GXPipelineUid& in) { GXPipelineUid out; -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wclass-memaccess" -#endif - memcpy(&out, &in, sizeof(out)); // copy padding -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif + // TODO: static_assert(std::is_trivially_copyable_v); + // GXPipelineUid is not trivially copyable because RasterizationState and BlendingState aren't + // either, but we can pretend it is for now. This will be improved after PR #10848 is finished. + memcpy(static_cast(&out), static_cast(&in), sizeof(out)); // copy padding pixel_shader_uid_data* ps = out.ps_uid.GetUidData(); BlendingState& blend = out.blending_state; @@ -785,14 +781,10 @@ ShaderCache::GetGXPipelineConfig(const GXPipelineUid& config_in) static GXUberPipelineUid ApplyDriverBugs(const GXUberPipelineUid& in) { GXUberPipelineUid out; -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wclass-memaccess" -#endif - memcpy(&out, &in, sizeof(out)); // Copy padding -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif + // TODO: static_assert(std::is_trivially_copyable_v); + // GXUberPipelineUid is not trivially copyable because RasterizationState and BlendingState aren't + // either, but we can pretend it is for now. This will be improved after PR #10848 is finished. + memcpy(static_cast(&out), static_cast(&in), sizeof(out)); // Copy padding if (g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader) out.vertex_format = nullptr; diff --git a/Source/Core/VideoCommon/ShaderCache.h b/Source/Core/VideoCommon/ShaderCache.h index 809ebb23eb..c76f7dac16 100644 --- a/Source/Core/VideoCommon/ShaderCache.h +++ b/Source/Core/VideoCommon/ShaderCache.h @@ -176,8 +176,8 @@ private: template void ClearShaderCache(T& cache); template - void LoadPipelineCache(T& cache, LinearDiskCache& disk_cache, APIType api_type, - const char* type, bool include_gameid); + void LoadPipelineCache(T& cache, Common::LinearDiskCache& disk_cache, + APIType api_type, const char* type, bool include_gameid); template void ClearPipelineCache(T& cache, Y& disk_cache); @@ -216,7 +216,7 @@ private: bool pending = false; }; std::map shader_map; - LinearDiskCache disk_cache; + Common::LinearDiskCache disk_cache; }; ShaderModuleCache m_vs_cache; ShaderModuleCache m_gs_cache; @@ -229,8 +229,8 @@ private: std::map, bool>> m_gx_uber_pipeline_cache; File::IOFile m_gx_pipeline_uid_cache_file; - LinearDiskCache m_gx_pipeline_disk_cache; - LinearDiskCache m_gx_uber_pipeline_disk_cache; + Common::LinearDiskCache m_gx_pipeline_disk_cache; + Common::LinearDiskCache m_gx_uber_pipeline_disk_cache; // EFB copy to VRAM/RAM pipelines std::map> diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 6d138d5912..bcffe8e4ca 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -38,6 +38,7 @@ #include "VideoCommon/AbstractStagingTexture.h" #include "VideoCommon/BPMemory.h" #include "VideoCommon/FramebufferManager.h" +#include "VideoCommon/GraphicsModSystem/Runtime/CustomTextureData.h" #include "VideoCommon/GraphicsModSystem/Runtime/FBInfo.h" #include "VideoCommon/GraphicsModSystem/Runtime/GraphicsModActionData.h" #include "VideoCommon/GraphicsModSystem/Runtime/GraphicsModManager.h" @@ -656,8 +657,8 @@ void TextureCacheBase::DoSaveState(PointerWrap& p) } auto doList = [&p](auto list) { - u32 size = static_cast(list.size()); - p.Do(size); + u32 list_size = static_cast(list.size()); + p.Do(list_size); for (const auto& it : list) { p.Do(it.first); @@ -1327,12 +1328,6 @@ TCacheEntry* TextureCacheBase::Load(const TextureInfo& texture_info) RcTcacheEntry TextureCacheBase::GetTexture(const int textureCacheSafetyColorSampleSize, const TextureInfo& texture_info) { - u32 expanded_width = texture_info.GetExpandedWidth(); - u32 expanded_height = texture_info.GetExpandedHeight(); - - u32 width = texture_info.GetRawWidth(); - u32 height = texture_info.GetRawHeight(); - // Hash assigned to texcache entry (also used to generate filenames used for texture dumping and // custom texture lookup) u64 base_hash = TEXHASH_INVALID; @@ -1587,69 +1582,89 @@ RcTcacheEntry TextureCacheBase::GetTexture(const int textureCacheSafetyColorSamp InvalidateTexture(oldest_entry); } - std::shared_ptr hires_tex; + VideoCommon::CustomTextureData* data = nullptr; + bool has_arbitrary_mipmaps = false; + std::shared_ptr hires_texture; if (g_ActiveConfig.bHiresTextures) { - hires_tex = HiresTexture::Search(texture_info); - - if (hires_tex) + hires_texture = HiresTexture::Search(texture_info); + if (hires_texture) { - const auto& level = hires_tex->GetData().m_levels[0]; - if (level.width != width || level.height != height) - { - width = level.width; - height = level.height; - } - expanded_width = level.width; - expanded_height = level.height; + data = &hires_texture->GetData(); + has_arbitrary_mipmaps = hires_texture->HasArbitraryMipmaps(); } } + return CreateTextureEntry( + TextureCreationInfo{base_hash, full_hash, bytes_per_block, palette_size}, texture_info, + textureCacheSafetyColorSampleSize, data, has_arbitrary_mipmaps); +} + +RcTcacheEntry TextureCacheBase::CreateTextureEntry( + const TextureCreationInfo& creation_info, const TextureInfo& texture_info, + const int safety_color_sample_size, VideoCommon::CustomTextureData* custom_texture_data, + const bool custom_arbitrary_mipmaps) +{ #ifdef __APPLE__ const bool no_mips = g_ActiveConfig.bNoMipmapping; #else const bool no_mips = false; #endif - // how many levels the allocated texture shall have - const u32 texLevels = no_mips ? 1 : - hires_tex ? (u32)hires_tex->GetData().m_levels.size() : - texture_info.GetLevelCount(); - // We can decode on the GPU if it is a supported format and the flag is enabled. - // Currently we don't decode RGBA8 textures from TMEM, as that would require copying from both - // banks, and if we're doing an copy we may as well just do the whole thing on the CPU, since - // there's no conversion between formats. In the future this could be extended with a separate - // shader, however. - const bool decode_on_gpu = - !hires_tex && g_ActiveConfig.UseGPUTextureDecoding() && - !(texture_info.IsFromTmem() && texture_info.GetTextureFormat() == TextureFormat::RGBA8); - - // create the entry/texture - const TextureConfig config(width, height, texLevels, 1, 1, - hires_tex ? hires_tex->GetFormat() : AbstractTextureFormat::RGBA8, 0); - RcTcacheEntry entry = AllocateCacheEntry(config); - if (!entry) - return entry; - - ArbitraryMipmapDetector arbitrary_mip_detector; - if (hires_tex) + RcTcacheEntry entry; + if (custom_texture_data && custom_texture_data->m_levels.size() >= 1) { - const auto& level = hires_tex->GetData().m_levels[0]; - entry->texture->Load(0, level.width, level.height, level.row_length, level.data.data(), - level.data.size()); + const u32 texLevels = no_mips ? 1 : (u32)custom_texture_data->m_levels.size(); + const auto& first_level = custom_texture_data->m_levels[0]; + const TextureConfig config(first_level.width, first_level.height, texLevels, 1, 1, + first_level.format, 0); + entry = AllocateCacheEntry(config); + if (!entry) [[unlikely]] + return entry; + for (u32 level_index = 0; level_index != texLevels; ++level_index) + { + const auto& level = custom_texture_data->m_levels[level_index]; + entry->texture->Load(level_index, level.width, level.height, level.row_length, + level.data.data(), level.data.size()); + } + + entry->has_arbitrary_mips = custom_arbitrary_mipmaps; + entry->is_custom_tex = true; } - - // Initialized to null because only software loading uses this buffer - u8* dst_buffer = nullptr; - - if (!hires_tex) + else { + const u32 texLevels = no_mips ? 1 : texture_info.GetLevelCount(); + const u32 expanded_width = texture_info.GetExpandedWidth(); + const u32 expanded_height = texture_info.GetExpandedHeight(); + + const u32 width = texture_info.GetRawWidth(); + const u32 height = texture_info.GetRawHeight(); + + const TextureConfig config(width, height, texLevels, 1, 1, AbstractTextureFormat::RGBA8, 0); + entry = AllocateCacheEntry(config); + if (!entry) [[unlikely]] + return entry; + + // We can decode on the GPU if it is a supported format and the flag is enabled. + // Currently we don't decode RGBA8 textures from TMEM, as that would require copying from both + // banks, and if we're doing an copy we may as well just do the whole thing on the CPU, since + // there's no conversion between formats. In the future this could be extended with a separate + // shader, however. + const bool decode_on_gpu = + g_ActiveConfig.UseGPUTextureDecoding() && + !(texture_info.IsFromTmem() && texture_info.GetTextureFormat() == TextureFormat::RGBA8); + + ArbitraryMipmapDetector arbitrary_mip_detector; + + // Initialized to null because only software loading uses this buffer + u8* dst_buffer = nullptr; + if (!decode_on_gpu || - !DecodeTextureOnGPU(entry, 0, texture_info.GetData(), texture_info.GetTextureSize(), - texture_info.GetTextureFormat(), width, height, expanded_width, - expanded_height, - bytes_per_block * (expanded_width / texture_info.GetBlockWidth()), - texture_info.GetTlutAddress(), texture_info.GetTlutFormat())) + !DecodeTextureOnGPU( + entry, 0, texture_info.GetData(), texture_info.GetTextureSize(), + texture_info.GetTextureFormat(), width, height, expanded_width, expanded_height, + creation_info.bytes_per_block * (expanded_width / texture_info.GetBlockWidth()), + texture_info.GetTlutAddress(), texture_info.GetTlutFormat())) { size_t decoded_texture_size = expanded_width * sizeof(u32) * expanded_height; @@ -1690,42 +1705,7 @@ RcTcacheEntry TextureCacheBase::GetTexture(const int textureCacheSafetyColorSamp dst_buffer += decoded_texture_size; } - } - iter = textures_by_address.emplace(texture_info.GetRawAddress(), entry); - if (textureCacheSafetyColorSampleSize == 0 || - std::max(texture_info.GetTextureSize(), palette_size) <= - (u32)textureCacheSafetyColorSampleSize * 8) - { - entry->textures_by_hash_iter = textures_by_hash.emplace(full_hash, entry); - } - - entry->SetGeneralParameters(texture_info.GetRawAddress(), texture_info.GetTextureSize(), - full_format, false); - entry->SetDimensions(texture_info.GetRawWidth(), texture_info.GetRawHeight(), - texture_info.GetLevelCount()); - entry->SetHashes(base_hash, full_hash); - entry->is_custom_tex = hires_tex != nullptr; - entry->memory_stride = entry->BytesPerRow(); - entry->SetNotCopy(); - - std::string basename; - if (g_ActiveConfig.bDumpTextures && !hires_tex) - { - basename = HiresTexture::GenBaseName(texture_info, true); - } - - if (hires_tex) - { - for (u32 level_index = 1; level_index != texLevels; ++level_index) - { - const auto& level = hires_tex->GetData().m_levels[level_index]; - entry->texture->Load(level_index, level.width, level.height, level.row_length, - level.data.data(), level.data.size()); - } - } - else - { for (u32 level = 1; level != texLevels; ++level) { auto mip_level = texture_info.GetMipMapLevel(level - 1); @@ -1733,12 +1713,13 @@ RcTcacheEntry TextureCacheBase::GetTexture(const int textureCacheSafetyColorSamp continue; if (!decode_on_gpu || - !DecodeTextureOnGPU( - entry, level, mip_level->GetData(), mip_level->GetTextureSize(), - texture_info.GetTextureFormat(), mip_level->GetRawWidth(), mip_level->GetRawHeight(), - mip_level->GetExpandedWidth(), mip_level->GetExpandedHeight(), - bytes_per_block * (mip_level->GetExpandedWidth() / texture_info.GetBlockWidth()), - texture_info.GetTlutAddress(), texture_info.GetTlutFormat())) + !DecodeTextureOnGPU(entry, level, mip_level->GetData(), mip_level->GetTextureSize(), + texture_info.GetTextureFormat(), mip_level->GetRawWidth(), + mip_level->GetRawHeight(), mip_level->GetExpandedWidth(), + mip_level->GetExpandedHeight(), + creation_info.bytes_per_block * + (mip_level->GetExpandedWidth() / texture_info.GetBlockWidth()), + texture_info.GetTlutAddress(), texture_info.GetTlutFormat())) { // No need to call CheckTempSize here, as the whole buffer is preallocated at the beginning const u32 decoded_mip_size = @@ -1755,19 +1736,37 @@ RcTcacheEntry TextureCacheBase::GetTexture(const int textureCacheSafetyColorSamp dst_buffer += decoded_mip_size; } } - } - entry->has_arbitrary_mips = hires_tex ? hires_tex->HasArbitraryMipmaps() : - arbitrary_mip_detector.HasArbitraryMipmaps(dst_buffer); + entry->has_arbitrary_mips = arbitrary_mip_detector.HasArbitraryMipmaps(dst_buffer); - if (g_ActiveConfig.bDumpTextures && !hires_tex) - { - for (u32 level = 0; level < texLevels; ++level) + if (g_ActiveConfig.bDumpTextures) { - DumpTexture(entry, basename, level, entry->has_arbitrary_mips); + const std::string basename = HiresTexture::GenBaseName(texture_info, true); + for (u32 level = 0; level < texLevels; ++level) + { + DumpTexture(entry, basename, level, entry->has_arbitrary_mips); + } } } + const auto iter = textures_by_address.emplace(texture_info.GetRawAddress(), entry); + if (safety_color_sample_size == 0 || + std::max(texture_info.GetTextureSize(), creation_info.palette_size) <= + (u32)safety_color_sample_size * 8) + { + entry->textures_by_hash_iter = textures_by_hash.emplace(creation_info.full_hash, entry); + } + + const TextureAndTLUTFormat full_format(texture_info.GetTextureFormat(), + texture_info.GetTlutFormat()); + entry->SetGeneralParameters(texture_info.GetRawAddress(), texture_info.GetTextureSize(), + full_format, false); + entry->SetDimensions(texture_info.GetRawWidth(), texture_info.GetRawHeight(), + texture_info.GetLevelCount()); + entry->SetHashes(creation_info.base_hash, creation_info.full_hash); + entry->memory_stride = entry->BytesPerRow(); + entry->SetNotCopy(); + INCSTAT(g_stats.num_textures_uploaded); SETSTAT(g_stats.num_textures_alive, static_cast(textures_by_address.size())); @@ -1776,6 +1775,7 @@ RcTcacheEntry TextureCacheBase::GetTexture(const int textureCacheSafetyColorSamp // This should only be needed if the texture was updated, or used GPU decoding. entry->texture->FinishedRendering(); + return entry; } diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index ce001bb53c..10018732b1 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -32,6 +32,11 @@ class AbstractStagingTexture; class PointerWrap; struct VideoConfig; +namespace VideoCommon +{ +class CustomTextureData; +} + constexpr std::string_view EFB_DUMP_PREFIX = "efb1"; constexpr std::string_view XFB_DUMP_PREFIX = "xfb1"; @@ -242,6 +247,14 @@ public: TexPoolEntry(std::unique_ptr tex, std::unique_ptr fb); }; + struct TextureCreationInfo + { + u64 base_hash; + u64 full_hash; + u32 bytes_per_block; + u32 palette_size; + }; + TextureCacheBase(); virtual ~TextureCacheBase(); @@ -328,6 +341,11 @@ private: void SetBackupConfig(const VideoConfig& config); + RcTcacheEntry CreateTextureEntry(const TextureCreationInfo& creation_info, + const TextureInfo& texture_info, int safety_color_sample_size, + VideoCommon::CustomTextureData* custom_texture_data, + bool custom_arbitrary_mipmaps); + RcTcacheEntry GetXFBFromCache(u32 address, u32 width, u32 height, u32 stride); RcTcacheEntry ApplyPaletteToEntry(RcTcacheEntry& entry, const u8* palette, TLUTFormat tlutfmt); diff --git a/Source/Core/VideoCommon/TextureConversionShader.cpp b/Source/Core/VideoCommon/TextureConversionShader.cpp index c9242de6e5..6962daa29b 100644 --- a/Source/Core/VideoCommon/TextureConversionShader.cpp +++ b/Source/Core/VideoCommon/TextureConversionShader.cpp @@ -202,9 +202,9 @@ static void WriteSwizzler(ShaderCode& code, const EFBCopyParams& params, APIType const int blkH = TexDecoder_GetEFBCopyBlockHeightInTexels(params.copy_format); int samples = GetEncodedSampleCount(params.copy_format); - code.Write(" int x_block_position = (uv1.x >> {}) << {};\n", IntLog2(blkH * blkW / samples), - IntLog2(blkW)); - code.Write(" int y_block_position = uv1.y << {};\n", IntLog2(blkH)); + code.Write(" int x_block_position = (uv1.x >> {}) << {};\n", + MathUtil::IntLog2(blkH * blkW / samples), MathUtil::IntLog2(blkW)); + code.Write(" int y_block_position = uv1.y << {};\n", MathUtil::IntLog2(blkH)); if (samples == 1) { // With samples == 1, we write out pairs of blocks; one A8R8, one G8B8. @@ -212,9 +212,10 @@ static void WriteSwizzler(ShaderCode& code, const EFBCopyParams& params, APIType samples = 2; } code.Write(" int offset_in_block = uv1.x & {};\n", (blkH * blkW / samples) - 1); - code.Write(" int y_offset_in_block = offset_in_block >> {};\n", IntLog2(blkW / samples)); + code.Write(" int y_offset_in_block = offset_in_block >> {};\n", + MathUtil::IntLog2(blkW / samples)); code.Write(" int x_offset_in_block = (offset_in_block & {}) << {};\n", (blkW / samples) - 1, - IntLog2(samples)); + MathUtil::IntLog2(samples)); code.Write(" sampleUv.x = x_block_position + x_offset_in_block;\n" " sampleUv.y = y_block_position + y_offset_in_block;\n"); diff --git a/Source/Core/VideoCommon/TextureInfo.cpp b/Source/Core/VideoCommon/TextureInfo.cpp index 35441d4d36..b73461ba33 100644 --- a/Source/Core/VideoCommon/TextureInfo.cpp +++ b/Source/Core/VideoCommon/TextureInfo.cpp @@ -83,7 +83,7 @@ TextureInfo::TextureInfo(u32 stage, const u8* ptr, const u8* tlut_ptr, u32 addre // e.g. 64x64 with 7 LODs would have the mipmap chain 64x64,32x32,16x16,8x8,4x4,2x2,1x1,0x0, so // we limit the mipmap count to 6 there const u32 limited_mip_count = - std::min(IntLog2(std::max(width, height)) + 1, raw_mip_count + 1) - 1; + std::min(MathUtil::IntLog2(std::max(width, height)) + 1, raw_mip_count + 1) - 1; // load mips const u8* src_data = m_ptr + GetTextureSize(); diff --git a/Source/Core/VideoCommon/VertexLoaderManager.cpp b/Source/Core/VideoCommon/VertexLoaderManager.cpp index 0236201001..fb24803f1c 100644 --- a/Source/Core/VideoCommon/VertexLoaderManager.cpp +++ b/Source/Core/VideoCommon/VertexLoaderManager.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -153,14 +154,8 @@ NativeVertexFormat* GetUberVertexFormat(const PortableVertexDeclaration& decl) // The padding in the structs can cause the memcmp() in the map to create duplicates. // Avoid this by initializing the padding to zero. PortableVertexDeclaration new_decl; -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wclass-memaccess" -#endif - std::memset(&new_decl, 0, sizeof(new_decl)); -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif + static_assert(std::is_trivially_copyable_v); + std::memset(static_cast(&new_decl), 0, sizeof(new_decl)); new_decl.stride = decl.stride; auto MakeDummyAttribute = [](AttributeFormat& attr, ComponentFormat type, int components, diff --git a/Source/Core/WinUpdater/Main.cpp b/Source/Core/WinUpdater/Main.cpp index 6b7fd801ef..20aa398fd2 100644 --- a/Source/Core/WinUpdater/Main.cpp +++ b/Source/Core/WinUpdater/Main.cpp @@ -31,7 +31,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine // Test for write permissions bool need_admin = false; - auto path = GetModuleName(hInstance); + auto path = Common::GetModuleName(hInstance); if (!path) { UI::Error("Failed to get updater filename."); @@ -58,7 +58,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine } // Relaunch the updater as administrator - ShellExecuteW(nullptr, L"runas", path->c_str(), pCmdLine, NULL, SW_SHOW); + ShellExecuteW(nullptr, L"runas", path->c_str(), pCmdLine, nullptr, SW_SHOW); return 0; } diff --git a/Source/Core/WinUpdater/WinUI.cpp b/Source/Core/WinUpdater/WinUI.cpp index 418764813b..696ac55b0a 100644 --- a/Source/Core/WinUpdater/WinUI.cpp +++ b/Source/Core/WinUpdater/WinUI.cpp @@ -77,7 +77,7 @@ bool InitWindow() if (!window_handle) return false; - if (SUCCEEDED(CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, + if (SUCCEEDED(CoCreateInstance(CLSID_TaskbarList, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(taskbar_list.GetAddressOf())))) { if (FAILED(taskbar_list->HrInit())) @@ -88,8 +88,8 @@ bool InitWindow() int y = PADDING_HEIGHT; - label_handle = CreateWindow(L"STATIC", NULL, WS_VISIBLE | WS_CHILD, 5, y, 500, 25, window_handle, - nullptr, nullptr, 0); + label_handle = CreateWindow(L"STATIC", nullptr, WS_VISIBLE | WS_CHILD, 5, y, 500, 25, + window_handle, nullptr, nullptr, 0); if (!label_handle) return false; @@ -106,7 +106,7 @@ bool InitWindow() y += GetWindowHeight(label_handle) + PADDING_HEIGHT; - total_progressbar_handle = CreateWindow(PROGRESS_CLASS, NULL, PROGRESSBAR_FLAGS, 5, y, 470, 25, + total_progressbar_handle = CreateWindow(PROGRESS_CLASS, nullptr, PROGRESSBAR_FLAGS, 5, y, 470, 25, window_handle, nullptr, nullptr, 0); y += GetWindowHeight(total_progressbar_handle) + PADDING_HEIGHT; @@ -114,8 +114,8 @@ bool InitWindow() if (!total_progressbar_handle) return false; - current_progressbar_handle = CreateWindow(PROGRESS_CLASS, NULL, PROGRESSBAR_FLAGS, 5, y, 470, 25, - window_handle, nullptr, nullptr, 0); + current_progressbar_handle = CreateWindow(PROGRESS_CLASS, nullptr, PROGRESSBAR_FLAGS, 5, y, 470, + 25, window_handle, nullptr, nullptr, 0); y += GetWindowHeight(current_progressbar_handle) + PADDING_HEIGHT; diff --git a/Source/UnitTests/Common/MathUtilTest.cpp b/Source/UnitTests/Common/MathUtilTest.cpp index 229acac7fe..78416772a9 100644 --- a/Source/UnitTests/Common/MathUtilTest.cpp +++ b/Source/UnitTests/Common/MathUtilTest.cpp @@ -7,15 +7,15 @@ TEST(MathUtil, IntLog2) { - EXPECT_EQ(0, IntLog2(1)); - EXPECT_EQ(1, IntLog2(2)); - EXPECT_EQ(2, IntLog2(4)); - EXPECT_EQ(3, IntLog2(8)); - EXPECT_EQ(63, IntLog2(0x8000000000000000ull)); + EXPECT_EQ(0, MathUtil::IntLog2(1)); + EXPECT_EQ(1, MathUtil::IntLog2(2)); + EXPECT_EQ(2, MathUtil::IntLog2(4)); + EXPECT_EQ(3, MathUtil::IntLog2(8)); + EXPECT_EQ(63, MathUtil::IntLog2(0x8000000000000000ull)); // Rounding behavior. - EXPECT_EQ(3, IntLog2(15)); - EXPECT_EQ(63, IntLog2(0xFFFFFFFFFFFFFFFFull)); + EXPECT_EQ(3, MathUtil::IntLog2(15)); + EXPECT_EQ(63, MathUtil::IntLog2(0xFFFFFFFFFFFFFFFFull)); } TEST(MathUtil, NextPowerOf2) diff --git a/Source/UnitTests/Core/CoreTimingTest.cpp b/Source/UnitTests/Core/CoreTimingTest.cpp index 14731a10e7..8857ef8aba 100644 --- a/Source/UnitTests/Core/CoreTimingTest.cpp +++ b/Source/UnitTests/Core/CoreTimingTest.cpp @@ -38,7 +38,7 @@ void CallbackTemplate(Core::System& system, u64 userdata, s64 lateness) class ScopeInit final { public: - ScopeInit() : m_profile_path(File::CreateTempDir()) + explicit ScopeInit(Core::System& system) : m_system(system), m_profile_path(File::CreateTempDir()) { if (!UserDirectoryExists()) { @@ -48,8 +48,7 @@ public: UICommon::SetUserDirectory(m_profile_path); Config::Init(); SConfig::Init(); - PowerPC::Init(PowerPC::CPUCore::Interpreter); - auto& system = Core::System::GetInstance(); + system.GetPowerPC().Init(PowerPC::CPUCore::Interpreter); auto& core_timing = system.GetCoreTiming(); core_timing.Init(); } @@ -59,10 +58,9 @@ public: { return; } - auto& system = Core::System::GetInstance(); - auto& core_timing = system.GetCoreTiming(); + auto& core_timing = m_system.GetCoreTiming(); core_timing.Shutdown(); - PowerPC::Shutdown(); + m_system.GetPowerPC().Shutdown(); SConfig::Shutdown(); Config::Shutdown(); Core::UndeclareAsCPUThread(); @@ -71,32 +69,35 @@ public: bool UserDirectoryExists() const { return !m_profile_path.empty(); } private: + Core::System& m_system; std::string m_profile_path; }; -static void AdvanceAndCheck(u32 idx, int downcount, int expected_lateness = 0, +static void AdvanceAndCheck(Core::System& system, u32 idx, int downcount, int expected_lateness = 0, int cpu_downcount = 0) { s_callbacks_ran_flags = 0; s_expected_callback = CB_IDS[idx]; s_lateness = expected_lateness; - PowerPC::ppcState.downcount = cpu_downcount; // Pretend we executed X cycles of instructions. - auto& system = Core::System::GetInstance(); + auto& ppc_state = system.GetPPCState(); + ppc_state.downcount = cpu_downcount; // Pretend we executed X cycles of instructions. auto& core_timing = system.GetCoreTiming(); core_timing.Advance(); EXPECT_EQ(decltype(s_callbacks_ran_flags)().set(idx), s_callbacks_ran_flags); - EXPECT_EQ(downcount, PowerPC::ppcState.downcount); + EXPECT_EQ(downcount, ppc_state.downcount); } TEST(CoreTiming, BasicOrder) { - ScopeInit guard; + auto& system = Core::System::GetInstance(); + + ScopeInit guard(system); ASSERT_TRUE(guard.UserDirectoryExists()); - auto& system = Core::System::GetInstance(); auto& core_timing = system.GetCoreTiming(); + auto& ppc_state = system.GetPPCState(); CoreTiming::EventType* cb_a = core_timing.RegisterEvent("callbackA", CallbackTemplate<0>); CoreTiming::EventType* cb_b = core_timing.RegisterEvent("callbackB", CallbackTemplate<1>); @@ -109,21 +110,21 @@ TEST(CoreTiming, BasicOrder) // D -> B -> C -> A -> E core_timing.ScheduleEvent(1000, cb_a, CB_IDS[0]); - EXPECT_EQ(1000, PowerPC::ppcState.downcount); + EXPECT_EQ(1000, ppc_state.downcount); core_timing.ScheduleEvent(500, cb_b, CB_IDS[1]); - EXPECT_EQ(500, PowerPC::ppcState.downcount); + EXPECT_EQ(500, ppc_state.downcount); core_timing.ScheduleEvent(800, cb_c, CB_IDS[2]); - EXPECT_EQ(500, PowerPC::ppcState.downcount); + EXPECT_EQ(500, ppc_state.downcount); core_timing.ScheduleEvent(100, cb_d, CB_IDS[3]); - EXPECT_EQ(100, PowerPC::ppcState.downcount); + EXPECT_EQ(100, ppc_state.downcount); core_timing.ScheduleEvent(1200, cb_e, CB_IDS[4]); - EXPECT_EQ(100, PowerPC::ppcState.downcount); + EXPECT_EQ(100, ppc_state.downcount); - AdvanceAndCheck(3, 400); - AdvanceAndCheck(1, 300); - AdvanceAndCheck(2, 200); - AdvanceAndCheck(0, 200); - AdvanceAndCheck(4, MAX_SLICE_LENGTH); + AdvanceAndCheck(system, 3, 400); + AdvanceAndCheck(system, 1, 300); + AdvanceAndCheck(system, 2, 200); + AdvanceAndCheck(system, 0, 200); + AdvanceAndCheck(system, 4, MAX_SLICE_LENGTH); } namespace SharedSlotTest @@ -146,11 +147,13 @@ TEST(CoreTiming, SharedSlot) { using namespace SharedSlotTest; - ScopeInit guard; + auto& system = Core::System::GetInstance(); + + ScopeInit guard(system); ASSERT_TRUE(guard.UserDirectoryExists()); - auto& system = Core::System::GetInstance(); auto& core_timing = system.GetCoreTiming(); + auto& ppc_state = system.GetPPCState(); CoreTiming::EventType* cb_a = core_timing.RegisterEvent("callbackA", FifoCallback<0>); CoreTiming::EventType* cb_b = core_timing.RegisterEvent("callbackB", FifoCallback<1>); @@ -166,23 +169,24 @@ TEST(CoreTiming, SharedSlot) // Enter slice 0 core_timing.Advance(); - EXPECT_EQ(1000, PowerPC::ppcState.downcount); + EXPECT_EQ(1000, ppc_state.downcount); s_callbacks_ran_flags = 0; s_counter = 0; s_lateness = 0; - PowerPC::ppcState.downcount = 0; + ppc_state.downcount = 0; core_timing.Advance(); - EXPECT_EQ(MAX_SLICE_LENGTH, PowerPC::ppcState.downcount); + EXPECT_EQ(MAX_SLICE_LENGTH, ppc_state.downcount); EXPECT_EQ(0x1FULL, s_callbacks_ran_flags.to_ullong()); } TEST(CoreTiming, PredictableLateness) { - ScopeInit guard; + auto& system = Core::System::GetInstance(); + + ScopeInit guard(system); ASSERT_TRUE(guard.UserDirectoryExists()); - auto& system = Core::System::GetInstance(); auto& core_timing = system.GetCoreTiming(); CoreTiming::EventType* cb_a = core_timing.RegisterEvent("callbackA", CallbackTemplate<0>); @@ -194,8 +198,8 @@ TEST(CoreTiming, PredictableLateness) core_timing.ScheduleEvent(100, cb_a, CB_IDS[0]); core_timing.ScheduleEvent(200, cb_b, CB_IDS[1]); - AdvanceAndCheck(0, 90, 10, -10); // (100 - 10) - AdvanceAndCheck(1, MAX_SLICE_LENGTH, 50, -50); + AdvanceAndCheck(system, 0, 90, 10, -10); // (100 - 10) + AdvanceAndCheck(system, 1, MAX_SLICE_LENGTH, 50, -50); } namespace ChainSchedulingTest @@ -220,11 +224,13 @@ TEST(CoreTiming, ChainScheduling) { using namespace ChainSchedulingTest; - ScopeInit guard; + auto& system = Core::System::GetInstance(); + + ScopeInit guard(system); ASSERT_TRUE(guard.UserDirectoryExists()); - auto& system = Core::System::GetInstance(); auto& core_timing = system.GetCoreTiming(); + auto& ppc_state = system.GetPPCState(); CoreTiming::EventType* cb_a = core_timing.RegisterEvent("callbackA", CallbackTemplate<0>); CoreTiming::EventType* cb_b = core_timing.RegisterEvent("callbackB", CallbackTemplate<1>); @@ -239,24 +245,24 @@ TEST(CoreTiming, ChainScheduling) core_timing.ScheduleEvent(1000, cb_b, CB_IDS[1]); core_timing.ScheduleEvent(2200, cb_c, CB_IDS[2]); core_timing.ScheduleEvent(1000, cb_rs, reinterpret_cast(cb_rs)); - EXPECT_EQ(800, PowerPC::ppcState.downcount); + EXPECT_EQ(800, ppc_state.downcount); s_reschedules = 3; - AdvanceAndCheck(0, 200); // cb_a - AdvanceAndCheck(1, 1000); // cb_b, cb_rs + AdvanceAndCheck(system, 0, 200); // cb_a + AdvanceAndCheck(system, 1, 1000); // cb_b, cb_rs EXPECT_EQ(2, s_reschedules); - PowerPC::ppcState.downcount = 0; + ppc_state.downcount = 0; core_timing.Advance(); // cb_rs EXPECT_EQ(1, s_reschedules); - EXPECT_EQ(200, PowerPC::ppcState.downcount); + EXPECT_EQ(200, ppc_state.downcount); - AdvanceAndCheck(2, 800); // cb_c + AdvanceAndCheck(system, 2, 800); // cb_c - PowerPC::ppcState.downcount = 0; + ppc_state.downcount = 0; core_timing.Advance(); // cb_rs EXPECT_EQ(0, s_reschedules); - EXPECT_EQ(MAX_SLICE_LENGTH, PowerPC::ppcState.downcount); + EXPECT_EQ(MAX_SLICE_LENGTH, ppc_state.downcount); } namespace ScheduleIntoPastTest @@ -279,11 +285,13 @@ TEST(CoreTiming, ScheduleIntoPast) { using namespace ScheduleIntoPastTest; - ScopeInit guard; + auto& system = Core::System::GetInstance(); + + ScopeInit guard(system); ASSERT_TRUE(guard.UserDirectoryExists()); - auto& system = Core::System::GetInstance(); auto& core_timing = system.GetCoreTiming(); + auto& ppc_state = system.GetPPCState(); s_cb_next = core_timing.RegisterEvent("callbackA", CallbackTemplate<0>); CoreTiming::EventType* cb_b = core_timing.RegisterEvent("callbackB", CallbackTemplate<1>); @@ -293,9 +301,9 @@ TEST(CoreTiming, ScheduleIntoPast) core_timing.Advance(); core_timing.ScheduleEvent(1000, cb_chain, CB_IDS[0] + 1); - EXPECT_EQ(1000, PowerPC::ppcState.downcount); + EXPECT_EQ(1000, ppc_state.downcount); - AdvanceAndCheck(0, MAX_SLICE_LENGTH, 1000); // Run cb_chain into late cb_a + AdvanceAndCheck(system, 0, MAX_SLICE_LENGTH, 1000); // Run cb_chain into late cb_a // Schedule late from wrong thread // The problem with scheduling CPU events from outside the CPU Thread is that g_global_timer @@ -309,23 +317,25 @@ TEST(CoreTiming, ScheduleIntoPast) core_timing.ScheduleEvent(0, cb_b, CB_IDS[1], CoreTiming::FromThread::NON_CPU); core_timing_globals.global_timer += 1000; Core::DeclareAsCPUThread(); - AdvanceAndCheck(1, MAX_SLICE_LENGTH, MAX_SLICE_LENGTH + 1000); + AdvanceAndCheck(system, 1, MAX_SLICE_LENGTH, MAX_SLICE_LENGTH + 1000); // Schedule directly into the past from the CPU. // This shouldn't happen in practice, but it's best if we don't mess up the slice length and // downcount if we do. core_timing.ScheduleEvent(-1000, s_cb_next, CB_IDS[0]); - EXPECT_EQ(0, PowerPC::ppcState.downcount); - AdvanceAndCheck(0, MAX_SLICE_LENGTH, 1000); + EXPECT_EQ(0, ppc_state.downcount); + AdvanceAndCheck(system, 0, MAX_SLICE_LENGTH, 1000); } TEST(CoreTiming, Overclocking) { - ScopeInit guard; + auto& system = Core::System::GetInstance(); + + ScopeInit guard(system); ASSERT_TRUE(guard.UserDirectoryExists()); - auto& system = Core::System::GetInstance(); auto& core_timing = system.GetCoreTiming(); + auto& ppc_state = system.GetPPCState(); CoreTiming::EventType* cb_a = core_timing.RegisterEvent("callbackA", CallbackTemplate<0>); CoreTiming::EventType* cb_b = core_timing.RegisterEvent("callbackB", CallbackTemplate<1>); @@ -346,13 +356,13 @@ TEST(CoreTiming, Overclocking) core_timing.ScheduleEvent(400, cb_c, CB_IDS[2]); core_timing.ScheduleEvent(800, cb_d, CB_IDS[3]); core_timing.ScheduleEvent(1600, cb_e, CB_IDS[4]); - EXPECT_EQ(200, PowerPC::ppcState.downcount); + EXPECT_EQ(200, ppc_state.downcount); - AdvanceAndCheck(0, 200); // (200 - 100) * 2 - AdvanceAndCheck(1, 400); // (400 - 200) * 2 - AdvanceAndCheck(2, 800); // (800 - 400) * 2 - AdvanceAndCheck(3, 1600); // (1600 - 800) * 2 - AdvanceAndCheck(4, MAX_SLICE_LENGTH * 2); + AdvanceAndCheck(system, 0, 200); // (200 - 100) * 2 + AdvanceAndCheck(system, 1, 400); // (400 - 200) * 2 + AdvanceAndCheck(system, 2, 800); // (800 - 400) * 2 + AdvanceAndCheck(system, 3, 1600); // (1600 - 800) * 2 + AdvanceAndCheck(system, 4, MAX_SLICE_LENGTH * 2); // Underclock Config::SetCurrent(Config::MAIN_OVERCLOCK, 0.5f); @@ -363,13 +373,13 @@ TEST(CoreTiming, Overclocking) core_timing.ScheduleEvent(400, cb_c, CB_IDS[2]); core_timing.ScheduleEvent(800, cb_d, CB_IDS[3]); core_timing.ScheduleEvent(1600, cb_e, CB_IDS[4]); - EXPECT_EQ(50, PowerPC::ppcState.downcount); + EXPECT_EQ(50, ppc_state.downcount); - AdvanceAndCheck(0, 50); // (200 - 100) / 2 - AdvanceAndCheck(1, 100); // (400 - 200) / 2 - AdvanceAndCheck(2, 200); // (800 - 400) / 2 - AdvanceAndCheck(3, 400); // (1600 - 800) / 2 - AdvanceAndCheck(4, MAX_SLICE_LENGTH / 2); + AdvanceAndCheck(system, 0, 50); // (200 - 100) / 2 + AdvanceAndCheck(system, 1, 100); // (400 - 200) / 2 + AdvanceAndCheck(system, 2, 200); // (800 - 400) / 2 + AdvanceAndCheck(system, 3, 400); // (1600 - 800) / 2 + AdvanceAndCheck(system, 4, MAX_SLICE_LENGTH / 2); // Try switching the clock mid-emulation Config::SetCurrent(Config::MAIN_OVERCLOCK, 1.0f); @@ -380,14 +390,14 @@ TEST(CoreTiming, Overclocking) core_timing.ScheduleEvent(400, cb_c, CB_IDS[2]); core_timing.ScheduleEvent(800, cb_d, CB_IDS[3]); core_timing.ScheduleEvent(1600, cb_e, CB_IDS[4]); - EXPECT_EQ(100, PowerPC::ppcState.downcount); + EXPECT_EQ(100, ppc_state.downcount); - AdvanceAndCheck(0, 100); // (200 - 100) + AdvanceAndCheck(system, 0, 100); // (200 - 100) Config::SetCurrent(Config::MAIN_OVERCLOCK, 2.0f); - AdvanceAndCheck(1, 400); // (400 - 200) * 2 - AdvanceAndCheck(2, 800); // (800 - 400) * 2 + AdvanceAndCheck(system, 1, 400); // (400 - 200) * 2 + AdvanceAndCheck(system, 2, 800); // (800 - 400) * 2 Config::SetCurrent(Config::MAIN_OVERCLOCK, 0.1f); - AdvanceAndCheck(3, 80); // (1600 - 800) / 10 + AdvanceAndCheck(system, 3, 80); // (1600 - 800) / 10 Config::SetCurrent(Config::MAIN_OVERCLOCK, 1.0f); - AdvanceAndCheck(4, MAX_SLICE_LENGTH); + AdvanceAndCheck(system, 4, MAX_SLICE_LENGTH); } diff --git a/Source/UnitTests/Core/PowerPC/JitArm64/FPRF.cpp b/Source/UnitTests/Core/PowerPC/JitArm64/FPRF.cpp index 1bc22c3263..285469b90f 100644 --- a/Source/UnitTests/Core/PowerPC/JitArm64/FPRF.cpp +++ b/Source/UnitTests/Core/PowerPC/JitArm64/FPRF.cpp @@ -34,10 +34,12 @@ public: const u8* raw_fprf_double = GetCodePtr(); GenerateFPRF(false); + auto& ppc_state = system.GetPPCState(); + fprf_single = Common::BitCast(GetCodePtr()); MOV(ARM64Reg::X15, ARM64Reg::X30); MOV(ARM64Reg::X14, PPC_REG); - MOVP2R(PPC_REG, &PowerPC::ppcState); + MOVP2R(PPC_REG, &ppc_state); BL(raw_fprf_single); MOV(ARM64Reg::X30, ARM64Reg::X15); MOV(PPC_REG, ARM64Reg::X14); @@ -46,7 +48,7 @@ public: fprf_double = Common::BitCast(GetCodePtr()); MOV(ARM64Reg::X15, ARM64Reg::X30); MOV(ARM64Reg::X14, PPC_REG); - MOVP2R(PPC_REG, &PowerPC::ppcState); + MOVP2R(PPC_REG, &ppc_state); BL(raw_fprf_double); MOV(ARM64Reg::X30, ARM64Reg::X15); MOV(PPC_REG, ARM64Reg::X14); @@ -59,29 +61,31 @@ public: } // namespace -static u32 RunUpdateFPRF(const std::function& f) +static u32 RunUpdateFPRF(PowerPC::PowerPCState& ppc_state, const std::function& f) { - PowerPC::ppcState.fpscr.Hex = 0x12345678; + ppc_state.fpscr.Hex = 0x12345678; f(); - return PowerPC::ppcState.fpscr.Hex; + return ppc_state.fpscr.Hex; } TEST(JitArm64, FPRF) { - TestFPRF test(Core::System::GetInstance()); + auto& system = Core::System::GetInstance(); + auto& ppc_state = system.GetPPCState(); + TestFPRF test(system); for (const u64 double_input : double_test_values) { const u32 expected_double = RunUpdateFPRF( - [&] { PowerPC::ppcState.UpdateFPRFDouble(Common::BitCast(double_input)); }); - const u32 actual_double = RunUpdateFPRF([&] { test.fprf_double(double_input); }); + ppc_state, [&] { ppc_state.UpdateFPRFDouble(Common::BitCast(double_input)); }); + const u32 actual_double = RunUpdateFPRF(ppc_state, [&] { test.fprf_double(double_input); }); EXPECT_EQ(expected_double, actual_double); const u32 single_input = ConvertToSingle(double_input); const u32 expected_single = RunUpdateFPRF( - [&] { PowerPC::ppcState.UpdateFPRFSingle(Common::BitCast(single_input)); }); - const u32 actual_single = RunUpdateFPRF([&] { test.fprf_single(single_input); }); + ppc_state, [&] { ppc_state.UpdateFPRFSingle(Common::BitCast(single_input)); }); + const u32 actual_single = RunUpdateFPRF(ppc_state, [&] { test.fprf_single(single_input); }); EXPECT_EQ(expected_single, actual_single); } } diff --git a/Source/UnitTests/Core/PowerPC/JitArm64/Fres.cpp b/Source/UnitTests/Core/PowerPC/JitArm64/Fres.cpp index ea82ea9c98..d2624f117d 100644 --- a/Source/UnitTests/Core/PowerPC/JitArm64/Fres.cpp +++ b/Source/UnitTests/Core/PowerPC/JitArm64/Fres.cpp @@ -34,7 +34,7 @@ public: fres = Common::BitCast(GetCodePtr()); MOV(ARM64Reg::X15, ARM64Reg::X30); MOV(ARM64Reg::X14, PPC_REG); - MOVP2R(PPC_REG, &PowerPC::ppcState); + MOVP2R(PPC_REG, &system.GetPPCState()); MOV(ARM64Reg::X1, ARM64Reg::X0); m_float_emit.FMOV(ARM64Reg::D0, ARM64Reg::X0); m_float_emit.FRECPE(ARM64Reg::D0, ARM64Reg::D0); diff --git a/Source/UnitTests/Core/PowerPC/JitArm64/Frsqrte.cpp b/Source/UnitTests/Core/PowerPC/JitArm64/Frsqrte.cpp index af15857476..cf5bfd0df0 100644 --- a/Source/UnitTests/Core/PowerPC/JitArm64/Frsqrte.cpp +++ b/Source/UnitTests/Core/PowerPC/JitArm64/Frsqrte.cpp @@ -34,7 +34,7 @@ public: frsqrte = Common::BitCast(GetCodePtr()); MOV(ARM64Reg::X15, ARM64Reg::X30); MOV(ARM64Reg::X14, PPC_REG); - MOVP2R(PPC_REG, &PowerPC::ppcState); + MOVP2R(PPC_REG, &system.GetPPCState()); MOV(ARM64Reg::X1, ARM64Reg::X0); m_float_emit.FMOV(ARM64Reg::D0, ARM64Reg::X0); m_float_emit.FRSQRTE(ARM64Reg::D0, ARM64Reg::D0);