From 38b854705588ddc2d0cdd767645fcaf502d327b7 Mon Sep 17 00:00:00 2001 From: TellowKrinkle Date: Thu, 30 Mar 2023 21:03:16 -0500 Subject: [PATCH 01/72] CMake: Enable CMP0099 Allows INTERFACE_LINK_OPTIONS to propagate through private dependencies, required by MacOS framework builds of SDL2 --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4fd3972ad2..d24daa79e4 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) From 0d4a5274f115874dba612c9b477aa062e59675ea Mon Sep 17 00:00:00 2001 From: TellowKrinkle Date: Thu, 30 Mar 2023 21:05:14 -0500 Subject: [PATCH 02/72] CMake: Remove custom SDL2 find script It doesn't properly set the include paths for macos framework builds of SDL, and SDL has had its own find script since 2.0.10 --- CMake/FindSDL2.cmake | 250 ------------------------------------------- 1 file changed, 250 deletions(-) delete mode 100644 CMake/FindSDL2.cmake 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) - From 1bf593f65a512707f46603a7b022f36564a77e40 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 1 Apr 2023 14:34:30 +0200 Subject: [PATCH 03/72] Jit: Change argument order for InvalidateICacheLine(s)FromJIT --- Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp | 10 +++++----- .../Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp | 16 ++++++++-------- Source/Core/Core/PowerPC/JitInterface.cpp | 4 ++-- Source/Core/Core/PowerPC/JitInterface.h | 4 ++-- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp index ca287c80cc..445a68c0db 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp @@ -361,15 +361,15 @@ 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()))); + MOV(32, R(ABI_PARAM2), R(effective_address)); + MOV(32, R(ABI_PARAM3), R(loop_counter)); + MOV(64, R(ABI_PARAM1), Imm64(reinterpret_cast(&m_system.GetJitInterface()))); ABI_CallFunction(JitInterface::InvalidateICacheLinesFromJIT); } else { - MOV(32, R(ABI_PARAM1), R(effective_address)); - MOV(64, R(ABI_PARAM3), Imm64(reinterpret_cast(&m_system.GetJitInterface()))); + MOV(32, R(ABI_PARAM2), R(effective_address)); + MOV(64, R(ABI_PARAM1), Imm64(reinterpret_cast(&m_system.GetJitInterface()))); ABI_CallFunction(JitInterface::InvalidateICacheLineFromJIT); } ABI_PopRegistersAndAdjustStack(registersInUse, 0); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp index d3f920b588..a772946482 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp @@ -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/JitInterface.cpp b/Source/Core/Core/PowerPC/JitInterface.cpp index beec9559e6..fd6ea3ae40 100644 --- a/Source/Core/Core/PowerPC/JitInterface.cpp +++ b/Source/Core/Core/PowerPC/JitInterface.cpp @@ -257,12 +257,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); } 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 { From e24e52af3c0dd0be3bc21b0fe1531b2435436688 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Tue, 28 Mar 2023 03:57:56 +0200 Subject: [PATCH 04/72] Jit64: Use utility function for function calls in dcbx. We have these for a reason. I think this also fixes a theoretical problem when `ABI_PARAM1 == loop_counter` where the first MOV destroys the second's value; I'm not sure if this can actually happen in practice though. --- Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp index 445a68c0db..c56c4a4764 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_PARAM2), R(effective_address)); - MOV(32, R(ABI_PARAM3), R(loop_counter)); - MOV(64, R(ABI_PARAM1), 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_PARAM2), R(effective_address)); - MOV(64, R(ABI_PARAM1), 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); From 9e0755a5983d8d9a277cea284534fb32a545f270 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Sun, 2 Apr 2023 15:51:06 -0700 Subject: [PATCH 05/72] HookableEvent: Use std::recursive_mutex instead of std::mutex This fixes a crash when recording fifologs, as the mutex is acquired when BPWritten calls AfterFrameEvent::Trigger, but then acquired again when FifoRecorder::EndFrame calls m_end_of_frame_event.reset(). std::mutex does not allow calling lock() if the thread already owns the mutex, while std::recursive_mutex does allow this. This is a regression from #11522 (which introduced the HookableEvent system). --- Source/Core/Common/HookableEvent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; }; From 2ac7b5a523383d2125db1f8d6dc844425c4148e6 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Wed, 5 Apr 2023 20:00:37 +0200 Subject: [PATCH 06/72] Jit64: Fix possibly redundant MOV in ABI_CallFunctionPR(). --- Source/Core/Common/x64Emitter.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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); } From 18f8ae37ab1091f104114489a4a8371d94b9475c Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Tue, 28 Mar 2023 20:39:02 +0200 Subject: [PATCH 07/72] PowerPC/Expression: Pass System to EvaluateCondition(). --- Source/Core/Core/PowerPC/BreakPoints.cpp | 7 ++++--- Source/Core/Core/PowerPC/BreakPoints.h | 4 ++-- Source/Core/Core/PowerPC/Expression.cpp | 23 ++++++++++++----------- Source/Core/Core/PowerPC/Expression.h | 11 ++++++----- Source/Core/Core/PowerPC/MMU.cpp | 3 ++- Source/Core/Core/PowerPC/PowerPC.cpp | 2 +- 6 files changed, 27 insertions(+), 23 deletions(-) diff --git a/Source/Core/Core/PowerPC/BreakPoints.cpp b/Source/Core/Core/PowerPC/BreakPoints.cpp index fd30da2b91..473871e74f 100644 --- a/Source/Core/Core/PowerPC/BreakPoints.cpp +++ b/Source/Core/Core/PowerPC/BreakPoints.cpp @@ -16,6 +16,7 @@ #include "Core/PowerPC/Expression.h" #include "Core/PowerPC/JitInterface.h" #include "Core/PowerPC/MMU.h" +#include "Core/PowerPC/PowerPC.h" #include "Core/System.h" bool BreakPoints::IsAddressBreakPoint(u32 address) const @@ -352,14 +353,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..111e1bb365 100644 --- a/Source/Core/Core/PowerPC/BreakPoints.h +++ b/Source/Core/Core/PowerPC/BreakPoints.h @@ -45,8 +45,8 @@ 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. 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/MMU.cpp b/Source/Core/Core/PowerPC/MMU.cpp index 92786beec6..bfbc25c655 100644 --- a/Source/Core/Core/PowerPC/MMU.cpp +++ b/Source/Core/Core/PowerPC/MMU.cpp @@ -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, &debug_interface, var, address, write, size, m_ppc_state.pc); if (!pause) return; diff --git a/Source/Core/Core/PowerPC/PowerPC.cpp b/Source/Core/Core/PowerPC/PowerPC.cpp index fef24a482a..6f18fad090 100644 --- a/Source/Core/Core/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/PowerPC/PowerPC.cpp @@ -645,7 +645,7 @@ void CheckBreakPoints() { const TBreakPoint* bp = PowerPC::breakpoints.GetBreakpoint(PowerPC::ppcState.pc); - if (!bp || !bp->is_enabled || !EvaluateCondition(bp->condition)) + if (!bp || !bp->is_enabled || !EvaluateCondition(Core::System::GetInstance(), bp->condition)) return; if (bp->break_on_hit) From aec3a882d7a875e45f97279d4ced3d3140a7cc87 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Tue, 28 Mar 2023 21:47:38 +0200 Subject: [PATCH 08/72] PowerPC/JitInterface: Access PowerPCState through System. --- Source/Core/Core/PowerPC/JitInterface.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Source/Core/Core/PowerPC/JitInterface.cpp b/Source/Core/Core/PowerPC/JitInterface.cpp index 084064ceaf..750d3b6d65 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; } @@ -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))->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); } } From 6018daa3fa05542b0f97da43fb4b97722c03e224 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Tue, 28 Mar 2023 21:48:22 +0200 Subject: [PATCH 09/72] PowerPC/PPCCache: Access PowerPCState through System. --- Source/Core/Core/PowerPC/PPCCache.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) 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() From e5941428d138e96c6dfb2832bb14bf402debd18b Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Tue, 28 Mar 2023 21:59:39 +0200 Subject: [PATCH 10/72] PowerPC/PPCTables: Pass instruction address to GetOpInfo(). --- .../Core/PowerPC/Interpreter/Interpreter.cpp | 4 ++-- Source/Core/Core/PowerPC/JitCommon/JitBase.h | 2 +- Source/Core/Core/PowerPC/JitInterface.cpp | 2 +- Source/Core/Core/PowerPC/PPCAnalyst.cpp | 10 +++++----- Source/Core/Core/PowerPC/PPCTables.cpp | 20 +++++++++---------- Source/Core/Core/PowerPC/PPCTables.h | 8 ++++---- Source/Core/DolphinQt/MenuBar.cpp | 2 +- 7 files changed, 23 insertions(+), 25 deletions(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp index c41635c7e6..b4ba4e777d 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 && 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 750d3b6d65..7ca17cbffc 100644 --- a/Source/Core/Core/PowerPC/JitInterface.cpp +++ b/Source/Core/Core/PowerPC/JitInterface.cpp @@ -297,7 +297,7 @@ void JitInterface::CompileExceptionCheck(ExceptionType type) // 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, ppc_state.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; } diff --git a/Source/Core/Core/PowerPC/PPCAnalyst.cpp b/Source/Core/Core/PowerPC/PPCAnalyst.cpp index 1d4f5fab2f..029aecb87b 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 @@ -274,7 +274,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 +323,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 +357,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 +778,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/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/DolphinQt/MenuBar.cpp b/Source/Core/DolphinQt/MenuBar.cpp index 2677ac27d0..4d764f2fac 100644 --- a/Source/Core/DolphinQt/MenuBar.cpp +++ b/Source/Core/DolphinQt/MenuBar.cpp @@ -1699,7 +1699,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); From 192d8b6e40567338a84ef7a98a92561e53e198aa Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Tue, 28 Mar 2023 22:07:50 +0200 Subject: [PATCH 11/72] VideoCommon/CommandProcessor: Pass System to HandleUnknownOpcode(). --- Source/Core/VideoCommon/CommandProcessor.cpp | 8 +++++--- Source/Core/VideoCommon/CommandProcessor.h | 2 +- Source/Core/VideoCommon/OpcodeDecoding.cpp | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) 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; } } From 2d1f661118cda9b90318aef943afed086dbfc794 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Tue, 28 Mar 2023 23:52:36 +0200 Subject: [PATCH 12/72] DolphinQt: Avoid ppcState global. --- .../DolphinQt/Debugger/CodeViewWidget.cpp | 56 +++---- .../Core/DolphinQt/Debugger/CodeViewWidget.h | 5 +- Source/Core/DolphinQt/Debugger/CodeWidget.cpp | 60 ++++---- Source/Core/DolphinQt/Debugger/CodeWidget.h | 6 + .../DolphinQt/Debugger/RegisterWidget.cpp | 137 +++++++++--------- .../Core/DolphinQt/Debugger/RegisterWidget.h | 6 + 6 files changed, 143 insertions(+), 127 deletions(-) diff --git a/Source/Core/DolphinQt/Debugger/CodeViewWidget.cpp b/Source/Core/DolphinQt/Debugger/CodeViewWidget.cpp index f954f57ccc..8e8b535b7f 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(); }); @@ -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,8 @@ 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; + const std::optional pc = + guard ? std::make_optional(m_system.GetPPCState().pc) : std::nullopt; const bool dark_theme = qApp->palette().color(QPalette::Base).valueF() < 0.5; @@ -533,7 +534,7 @@ 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); @@ -595,10 +596,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 = PowerPC::debug_interface.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(), ','); @@ -651,7 +653,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,8 +743,8 @@ void CodeViewWidget::OnCopyTargetAddress() const u32 addr = GetContextAddress(); - const std::string code_line = [addr] { - Core::CPUThreadGuard guard(Core::System::GetInstance()); + const std::string code_line = [this, addr] { + Core::CPUThreadGuard guard(m_system); return PowerPC::debug_interface.Disassemble(&guard, addr); }(); @@ -771,8 +773,8 @@ void CodeViewWidget::OnShowTargetInMemory() const u32 addr = GetContextAddress(); - const std::string code_line = [addr] { - Core::CPUThreadGuard guard(Core::System::GetInstance()); + const std::string code_line = [this, addr] { + Core::CPUThreadGuard guard(m_system); return PowerPC::debug_interface.Disassemble(&guard, addr); }(); @@ -790,8 +792,8 @@ void CodeViewWidget::OnCopyCode() { const u32 addr = GetContextAddress(); - const std::string text = [addr] { - Core::CPUThreadGuard guard(Core::System::GetInstance()); + const std::string text = [this, addr] { + Core::CPUThreadGuard guard(m_system); return PowerPC::debug_interface.Disassemble(&guard, addr); }(); @@ -809,7 +811,7 @@ 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; @@ -828,8 +830,8 @@ void CodeViewWidget::OnCopyHex() { const u32 addr = GetContextAddress(); - const u32 instruction = [addr] { - Core::CPUThreadGuard guard(Core::System::GetInstance()); + const u32 instruction = [this, addr] { + Core::CPUThreadGuard guard(m_system); return PowerPC::debug_interface.ReadInstruction(guard, addr); }(); @@ -857,7 +859,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 +884,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 +919,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 +948,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 +976,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 +985,7 @@ void CodeViewWidget::OnSetSymbolEndAddress() void CodeViewWidget::OnReplaceInstruction() { - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); const u32 addr = GetContextAddress(); @@ -1006,7 +1008,7 @@ void CodeViewWidget::OnReplaceInstruction() void CodeViewWidget::OnRestoreInstruction() { - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); const u32 addr = GetContextAddress(); 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..02286fa8b1 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,8 +435,7 @@ 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; @@ -455,21 +454,20 @@ void CodeWidget::Step() 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); + PowerPC::breakpoints.Add(m_system.GetPPCState().pc + 4, true); cpu.EnableStepping(false); Core::DisplayMessage(tr("Step over in progress...").toStdString(), 2000); } @@ -480,23 +478,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,8 +501,9 @@ void CodeWidget::StepOut() using clock = std::chrono::steady_clock; clock::time_point timeout = clock::now() + std::chrono::seconds(5); + auto& ppc_state = m_system.GetPPCState(); { - Core::CPUThreadGuard guard(system); + Core::CPUThreadGuard guard(m_system); PowerPC::breakpoints.ClearAllTemporary(); @@ -516,10 +513,10 @@ void CodeWidget::StepOut() // 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(); break; @@ -528,28 +525,27 @@ void CodeWidget::StepOut() 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)); + } while (ppc_state.pc != next_pc && clock::now() < timeout && + !PowerPC::breakpoints.IsAddressBreakPoint(ppc_state.pc)); } else { PowerPC::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 && !PowerPC::breakpoints.IsAddressBreakPoint(ppc_state.pc)); PowerPC::SetMode(old_mode); } emit Host::GetInstance()->UpdateDisasmDialog(); - if (PowerPC::breakpoints.IsAddressBreakPoint(PowerPC::ppcState.pc)) + if (PowerPC::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 +555,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/RegisterWidget.cpp b/Source/Core/DolphinQt/Debugger/RegisterWidget.cpp index 9d7079e04a..f11df86444 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,29 +381,30 @@ 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 @@ -406,83 +413,79 @@ void RegisterWidget::PopulateTable() // 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; }; From 62de9c593bb5e402a9315777cb49917721e43799 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Wed, 29 Mar 2023 00:42:27 +0200 Subject: [PATCH 13/72] UnitTests: Avoid ppcState global. --- Source/UnitTests/Core/CoreTimingTest.cpp | 105 +++++++++--------- .../UnitTests/Core/PowerPC/JitArm64/FPRF.cpp | 24 ++-- .../UnitTests/Core/PowerPC/JitArm64/Fres.cpp | 2 +- .../Core/PowerPC/JitArm64/Frsqrte.cpp | 2 +- 4 files changed, 71 insertions(+), 62 deletions(-) diff --git a/Source/UnitTests/Core/CoreTimingTest.cpp b/Source/UnitTests/Core/CoreTimingTest.cpp index 14731a10e7..3a8012cdf0 100644 --- a/Source/UnitTests/Core/CoreTimingTest.cpp +++ b/Source/UnitTests/Core/CoreTimingTest.cpp @@ -74,20 +74,20 @@ private: 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) @@ -97,6 +97,7 @@ TEST(CoreTiming, BasicOrder) 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 @@ -151,6 +152,7 @@ TEST(CoreTiming, SharedSlot) 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,14 +168,14 @@ 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()); } @@ -194,8 +196,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 @@ -225,6 +227,7 @@ TEST(CoreTiming, ChainScheduling) 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 +242,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 @@ -284,6 +287,7 @@ TEST(CoreTiming, ScheduleIntoPast) 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 +297,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,14 +313,14 @@ 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) @@ -326,6 +330,7 @@ TEST(CoreTiming, Overclocking) 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 +351,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 +368,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 +385,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); From b08d259d5cc0ffe0eb88a45a486c28d2125e56f3 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Wed, 5 Apr 2023 19:01:11 -0700 Subject: [PATCH 14/72] Common: Relicense TypeUtils to CC0 I am the sole contributor (apart from e149ad4f0a9874f354221a7fc76d8f1841e47808 which only changed the license header). --- Source/Core/Common/TypeUtils.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 From cd79207853a5b8a8c564c99e1fe141214dac292f Mon Sep 17 00:00:00 2001 From: sowens99 Date: Thu, 6 Apr 2023 01:47:42 -0400 Subject: [PATCH 15/72] DolphinQt: StickWidget and IRWidget check for changed x/y before signaling change --- Source/Core/DolphinQt/TAS/IRWidget.cpp | 20 +++++++++++++++++--- Source/Core/DolphinQt/TAS/StickWidget.cpp | 20 +++++++++++++++++--- 2 files changed, 34 insertions(+), 6 deletions(-) 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(); } From 1312624e0510d135cbfccbd84d85a346dfc75195 Mon Sep 17 00:00:00 2001 From: Minty-Meeo <45425365+Minty-Meeo@users.noreply.github.com> Date: Thu, 23 Mar 2023 11:18:20 -0500 Subject: [PATCH 16/72] Resolve [-Wshadow] --- Source/Core/Core/FifoPlayer/FifoRecorder.cpp | 4 +--- Source/Core/VideoCommon/TextureCacheBase.cpp | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) 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/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 6d138d5912..fa01029ea5 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -656,8 +656,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); From 56fcc97f6dc91ca177c384803f4f9657dbd73ae4 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Thu, 6 Apr 2023 18:37:45 -0700 Subject: [PATCH 17/72] CMake: Check `WIN32` instead of `CMAKE_SYSTEM_NAME STREQUAL Windows` --- Source/Core/Common/CMakeLists.txt | 2 +- Source/Core/VideoBackends/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index 1177363ec3..8269290729 100644 --- a/Source/Core/Common/CMakeLists.txt +++ b/Source/Core/Common/CMakeLists.txt @@ -299,7 +299,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/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) From 969d5e0fbeef8cd2e1a6a3a59be53b4569912fd6 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Thu, 6 Apr 2023 16:30:34 -0700 Subject: [PATCH 18/72] CMake: Don't include SPIRV-Cross except on Windows and macOS Building it on Linux is unnecessary as Direct3D and Metal are unavailable. --- CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ae86d33b42..3904d059d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -693,7 +693,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) From 44e3993f2fa3a93181923a30f7a8610306c99959 Mon Sep 17 00:00:00 2001 From: sowens99 Date: Fri, 7 Apr 2023 11:20:05 -0400 Subject: [PATCH 19/72] DolphinQt: Prevent MemoryViewWidget updates when hidden --- Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp index 46db6477d4..e5983a5675 100644 --- a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp @@ -437,6 +437,9 @@ void MemoryViewWidget::Update() void MemoryViewWidget::UpdateColumns() { + if (!isVisible()) + return; + // Check if table is created if (m_table->item(1, 1) == nullptr) return; From ed177bdbd7c77df9c34c2670c329415c998faa59 Mon Sep 17 00:00:00 2001 From: TellowKrinkle Date: Thu, 30 Mar 2023 15:23:22 -0500 Subject: [PATCH 20/72] VideoBackends:Metal: Use max pixel samplers constant --- Source/Core/VideoBackends/Metal/MTLStateTracker.h | 13 ++++++++----- Source/Core/VideoBackends/Metal/MTLStateTracker.mm | 12 ++++++------ 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Source/Core/VideoBackends/Metal/MTLStateTracker.h b/Source/Core/VideoBackends/Metal/MTLStateTracker.h index f425cd2884..2357322e4c 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; diff --git a/Source/Core/VideoBackends/Metal/MTLStateTracker.mm b/Source/Core/VideoBackends/Metal/MTLStateTracker.mm index 53462b9bdf..2769910d88 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() @@ -801,13 +801,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); From 02cd8b63630bc6fae9b208531d5b31a44572412a Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Fri, 7 Apr 2023 22:33:40 -0700 Subject: [PATCH 21/72] DolphinQt: Fix mouse lock checkbox appearing when it shouldn't See https://bugs.dolphin-emu.org/issues/13232; this was introduced in 7dde0c3c319577fd913e4de72a6113a8998ada49. Apparently, providing a parent for a widget that is not visible makes your new widget visible when the parent is later made visible, in addition to managing the deletion of the widget; the documentation does not specify this (only that if the parent is visible you need to explicitly show it). --- Source/Core/DolphinQt/Settings/InterfacePane.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Core/DolphinQt/Settings/InterfacePane.cpp b/Source/Core/DolphinQt/Settings/InterfacePane.cpp index 9365795551..8cbcc62ee3 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 } From e101f7f6aeb941b54bed30af05d6c83bad8ee0aa Mon Sep 17 00:00:00 2001 From: iwubcode Date: Tue, 14 Mar 2023 00:10:40 -0500 Subject: [PATCH 22/72] VideoCommon: refactor GetTexture into a separate function for creation, separating the custom texture data path from the game's texture data path --- Source/Core/VideoCommon/TextureCacheBase.cpp | 202 +++++++++---------- Source/Core/VideoCommon/TextureCacheBase.h | 18 ++ 2 files changed, 119 insertions(+), 101 deletions(-) diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 6d138d5912..15f79f99bd 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" @@ -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); From 1596b13743b2d84683a979b328d2d19246753e05 Mon Sep 17 00:00:00 2001 From: Robin Kertels Date: Sat, 8 Apr 2023 14:54:49 +0200 Subject: [PATCH 23/72] Android: Give Debug and Benchmark builds unique names on the launcher and for the DocumentsProvider --- Source/Android/app/build.gradle | 5 +++-- Source/Android/app/src/main/AndroidManifest.xml | 4 ++-- .../org/dolphinemu/dolphinemu/features/DocumentProvider.kt | 4 ++-- .../java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java | 1 + 4 files changed, 8 insertions(+), 6 deletions(-) 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..85fee36a18 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 @@ -59,7 +59,7 @@ class DocumentProvider : DocumentsProvider() { 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, @@ -171,7 +171,7 @@ class DocumentProvider : DocumentsProvider() { } val name = if (file == rootDirectory) { - context!!.getString(R.string.app_name) + context!!.getString(R.string.app_name_suffixed) } else { file.name } 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. From d11c8075e76bffda9fec2cdd4cd9691d7a3a670c Mon Sep 17 00:00:00 2001 From: Sketch <75850871+noahpistilli@users.noreply.github.com> Date: Mon, 3 Apr 2023 11:02:06 -0400 Subject: [PATCH 24/72] Reload DLList on call to KDDownload --- Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp | 1 + 1 file changed, 1 insertion(+) 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); From fe4aadc575f4741bbb959fdf45e41696341276ca Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 9 Apr 2023 04:12:31 +0200 Subject: [PATCH 25/72] IOS/DI: Remove RegisterWrapper. --- Source/Core/Core/IOS/DI/DI.cpp | 169 +++++++++++++++------------------ 1 file changed, 78 insertions(+), 91 deletions(-) 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)); From 424d1367407bbade7d885bdc193ee8cbdd4eb073 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 9 Apr 2023 09:04:58 +0200 Subject: [PATCH 26/72] Readme: Update Transifex URL The old URL redirects to the new URL for now, but apparently it will stop doing that in a few months. Let's update it in the Readme. --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 23843583bf2fcc349bef18b37e1a8539be3db17d Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Tue, 28 Mar 2023 20:26:52 +0200 Subject: [PATCH 27/72] PowerPC: Refactor to class, move to System. --- Source/Core/Common/Debug/CodeTrace.cpp | 19 +- Source/Core/Core/Boot/Boot_BS2Emu.cpp | 5 +- Source/Core/Core/Core.cpp | 18 +- Source/Core/Core/CoreTiming.cpp | 8 +- .../Core/Core/Debugger/Debugger_SymbolMap.cpp | 2 +- .../Core/Core/Debugger/PPCDebugInterface.cpp | 28 +- Source/Core/Core/HLE/HLE.cpp | 2 +- Source/Core/Core/HW/CPU.cpp | 30 +- Source/Core/Core/HW/CPU.h | 9 +- .../Core/Core/HW/EXI/EXI_DeviceEthernet.cpp | 5 +- Source/Core/Core/HW/SystemTimers.cpp | 2 +- Source/Core/Core/IOS/IOS.cpp | 5 +- Source/Core/Core/IOS/MIOS.cpp | 16 +- Source/Core/Core/IOS/Network/SSL.cpp | 10 +- Source/Core/Core/IOS/Network/Socket.cpp | 14 +- Source/Core/Core/PatchEngine.cpp | 2 +- Source/Core/Core/PowerPC/BreakPoints.cpp | 34 +- Source/Core/Core/PowerPC/BreakPoints.h | 20 + .../CachedInterpreter/CachedInterpreter.cpp | 13 +- Source/Core/Core/PowerPC/GDBStub.cpp | 16 +- .../Core/PowerPC/Interpreter/Interpreter.cpp | 11 +- .../Interpreter/Interpreter_Branch.cpp | 2 +- .../Interpreter/Interpreter_Integer.cpp | 5 +- .../Interpreter_SystemRegisters.cpp | 6 +- Source/Core/Core/PowerPC/Jit64/Jit.cpp | 14 +- Source/Core/Core/PowerPC/JitArm64/Jit.cpp | 16 +- .../JitArm64/JitArm64_SystemRegisters.cpp | 1 + .../Core/Core/PowerPC/JitCommon/JitBase.cpp | 7 +- Source/Core/Core/PowerPC/MMU.cpp | 22 +- Source/Core/Core/PowerPC/MMU.h | 4 +- Source/Core/Core/PowerPC/PPCAnalyst.cpp | 7 +- Source/Core/Core/PowerPC/PPCSymbolDB.cpp | 2 +- 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 + .../DolphinQt/Debugger/BreakpointWidget.cpp | 54 ++- .../DolphinQt/Debugger/BreakpointWidget.h | 6 + .../DolphinQt/Debugger/CodeDiffDialog.cpp | 5 +- .../DolphinQt/Debugger/CodeViewWidget.cpp | 65 +-- Source/Core/DolphinQt/Debugger/CodeWidget.cpp | 38 +- .../DolphinQt/Debugger/MemoryViewWidget.cpp | 15 +- .../DolphinQt/Debugger/MemoryViewWidget.h | 5 +- .../DolphinQt/Debugger/RegisterWidget.cpp | 4 +- .../Core/DolphinQt/Debugger/ThreadWidget.cpp | 9 +- .../Core/DolphinQt/Debugger/WatchWidget.cpp | 80 ++-- Source/Core/DolphinQt/Debugger/WatchWidget.h | 5 +- Source/Core/DolphinQt/MenuBar.cpp | 3 +- Source/UnitTests/Core/CoreTimingTest.cpp | 41 +- 50 files changed, 705 insertions(+), 531 deletions(-) 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/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/Core.cpp b/Source/Core/Core/Core.cpp index fbc87d18fd..4294faaf45 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -435,7 +435,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 +444,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 +552,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 +590,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 +628,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 +901,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/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/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/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/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/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/PatchEngine.cpp b/Source/Core/Core/PatchEngine.cpp index b180991522..21187dd9b6 100644 --- a/Source/Core/Core/PatchEngine.cpp +++ b/Source/Core/Core/PatchEngine.cpp @@ -277,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/PowerPC/BreakPoints.cpp b/Source/Core/Core/PowerPC/BreakPoints.cpp index 473871e74f..c4555c7569 100644 --- a/Source/Core/Core/PowerPC/BreakPoints.cpp +++ b/Source/Core/Core/PowerPC/BreakPoints.cpp @@ -19,6 +19,12 @@ #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(), @@ -107,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)); } @@ -143,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) @@ -167,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(); @@ -187,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 @@ -197,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; @@ -280,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(); }); } @@ -309,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(); }); } @@ -318,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(); }); } diff --git a/Source/Core/Core/PowerPC/BreakPoints.h b/Source/Core/Core/PowerPC/BreakPoints.h index 111e1bb365..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 { @@ -53,6 +57,13 @@ struct TMemCheck 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/GDBStub.cpp b/Source/Core/Core/PowerPC/GDBStub.cpp index 7a702e7188..99cdae0ce0 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); } diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp index b4ba4e777d..168df8deaf 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp @@ -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/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index ce01d560e2..ef0dd426ab 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)); @@ -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; } @@ -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_SystemRegisters.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp index ceabebb3c9..f01a0f0cf9 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp @@ -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/MMU.cpp b/Source/Core/Core/PowerPC/MMU.cpp index bfbc25c655..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,8 +545,8 @@ void MMU::Memcheck(u32 address, u64 var, bool write, size_t size) mc->num_hits++; - const bool pause = - mc->Action(m_system, &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; @@ -892,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) @@ -1189,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) @@ -1212,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) @@ -1566,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). @@ -1586,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 029aecb87b..34501a5bbe 100644 --- a/Source/Core/Core/PowerPC/PPCAnalyst.cpp +++ b/Source/Core/Core/PowerPC/PPCAnalyst.cpp @@ -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. 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/PowerPC.cpp b/Source/Core/Core/PowerPC/PowerPC.cpp index 6f18fad090..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(Core::System::GetInstance(), 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/DolphinQt/Debugger/BreakpointWidget.cpp b/Source/Core/DolphinQt/Debugger/BreakpointWidget.cpp index 019494491b..c21ae91e6f 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(); } @@ -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(); @@ -360,8 +370,8 @@ void BreakpointWidget::OnSave() 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 8e8b535b7f..312cc1f190 100644 --- a/Source/Core/DolphinQt/Debugger/CodeViewWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/CodeViewWidget.cpp @@ -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) @@ -294,8 +294,11 @@ void CodeViewWidget::Update(const Core::CPUThreadGuard* guard) for (int i = 0; i < rows; i++) setRowHeight(i, rowh); + auto& power_pc = m_system.GetPowerPC(); + auto& debug_interface = power_pc.GetDebugInterface(); + const std::optional pc = - guard ? std::make_optional(m_system.GetPPCState().pc) : std::nullopt; + guard ? std::make_optional(power_pc.GetPPCState().pc) : std::nullopt; const bool dark_theme = qApp->palette().color(QPalette::Base).valueF() < 0.5; @@ -304,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. @@ -360,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); @@ -536,8 +539,8 @@ void CodeViewWidget::ReplaceAddress(u32 address, ReplaceWith replace) { 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); } @@ -598,7 +601,7 @@ void CodeViewWidget::OnContextMenu() { Core::CPUThreadGuard guard(m_system); const u32 pc = m_system.GetPPCState().pc; - const std::string disasm = PowerPC::debug_interface.Disassemble(&guard, pc); + const std::string disasm = m_system.GetPowerPC().GetDebugInterface().Disassemble(&guard, pc); if (addr == pc) { @@ -642,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(); @@ -745,14 +749,14 @@ void CodeViewWidget::OnCopyTargetAddress() const std::string code_line = [this, addr] { Core::CPUThreadGuard guard(m_system); - return PowerPC::debug_interface.Disassemble(&guard, addr); + 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) { @@ -775,14 +779,14 @@ void CodeViewWidget::OnShowTargetInMemory() const std::string code_line = [this, addr] { Core::CPUThreadGuard guard(m_system); - return PowerPC::debug_interface.Disassemble(&guard, addr); + 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); @@ -794,7 +798,7 @@ void CodeViewWidget::OnCopyCode() const std::string text = [this, addr] { Core::CPUThreadGuard guard(m_system); - return PowerPC::debug_interface.Disassemble(&guard, addr); + return m_system.GetPowerPC().GetDebugInterface().Disassemble(&guard, addr); }(); QApplication::clipboard()->setText(QString::fromStdString(text)); @@ -818,7 +822,8 @@ void CodeViewWidget::OnCopyFunction() 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); } } @@ -832,7 +837,7 @@ void CodeViewWidget::OnCopyHex() const u32 instruction = [this, addr] { Core::CPUThreadGuard guard(m_system); - return PowerPC::debug_interface.ReadInstruction(guard, addr); + return m_system.GetPowerPC().GetDebugInterface().ReadInstruction(guard, addr); }(); QApplication::clipboard()->setText( @@ -843,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(); } @@ -997,11 +1002,12 @@ 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); } } @@ -1012,7 +1018,7 @@ void CodeViewWidget::OnRestoreInstruction() const u32 addr = GetContextAddress(); - PowerPC::debug_interface.UnsetPatch(guard, addr); + m_system.GetPowerPC().GetDebugInterface().UnsetPatch(guard, addr); Update(&guard); } @@ -1091,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(); @@ -1102,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/CodeWidget.cpp b/Source/Core/DolphinQt/Debugger/CodeWidget.cpp index 02286fa8b1..1f82c969de 100644 --- a/Source/Core/DolphinQt/Debugger/CodeWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/CodeWidget.cpp @@ -442,12 +442,13 @@ void CodeWidget::Step() 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. } @@ -466,8 +467,9 @@ void CodeWidget::StepOver() if (inst.LK) { - PowerPC::breakpoints.ClearAllTemporary(); - PowerPC::breakpoints.Add(m_system.GetPPCState().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); } @@ -501,14 +503,16 @@ void CodeWidget::StepOut() using clock = std::chrono::steady_clock; clock::time_point timeout = clock::now() + std::chrono::seconds(5); - auto& ppc_state = m_system.GetPPCState(); + auto& power_pc = m_system.GetPowerPC(); + auto& ppc_state = power_pc.GetPPCState(); + auto& breakpoints = power_pc.GetBreakPoints(); { 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 @@ -518,7 +522,7 @@ void CodeWidget::StepOut() { if (WillInstructionReturn(m_system, inst)) { - PowerPC::SingleStep(); + power_pc.SingleStep(); break; } @@ -528,24 +532,24 @@ void CodeWidget::StepOut() u32 next_pc = ppc_state.pc + 4; do { - PowerPC::SingleStep(); + power_pc.SingleStep(); } while (ppc_state.pc != next_pc && clock::now() < timeout && - !PowerPC::breakpoints.IsAddressBreakPoint(ppc_state.pc)); + !breakpoints.IsAddressBreakPoint(ppc_state.pc)); } else { - PowerPC::SingleStep(); + power_pc.SingleStep(); } inst = PowerPC::MMU::HostRead_Instruction(guard, ppc_state.pc); - } while (clock::now() < timeout && !PowerPC::breakpoints.IsAddressBreakPoint(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(ppc_state.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); diff --git a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp index e5983a5675..d05e043da1 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); @@ -571,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); @@ -808,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) { @@ -829,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); } } 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 f11df86444..b41fffb39a 100644 --- a/Source/Core/DolphinQt/Debugger/RegisterWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/RegisterWidget.cpp @@ -409,7 +409,9 @@ void RegisterWidget::PopulateTable() // 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( 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..2be4a2a2f7 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(); } @@ -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(); @@ -317,7 +320,7 @@ void WatchWidget::OnSave() 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/MenuBar.cpp b/Source/Core/DolphinQt/MenuBar.cpp index 4d764f2fac..07391cb65b 100644 --- a/Source/Core/DolphinQt/MenuBar.cpp +++ b/Source/Core/DolphinQt/MenuBar.cpp @@ -800,7 +800,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(); diff --git a/Source/UnitTests/Core/CoreTimingTest.cpp b/Source/UnitTests/Core/CoreTimingTest.cpp index 3a8012cdf0..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,6 +69,7 @@ public: bool UserDirectoryExists() const { return !m_profile_path.empty(); } private: + Core::System& m_system; std::string m_profile_path; }; @@ -92,10 +91,11 @@ static void AdvanceAndCheck(Core::System& system, u32 idx, int downcount, int ex 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(); @@ -147,10 +147,11 @@ 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(); @@ -181,10 +182,11 @@ TEST(CoreTiming, SharedSlot) 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>); @@ -222,10 +224,11 @@ 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(); @@ -282,10 +285,11 @@ 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(); @@ -325,10 +329,11 @@ TEST(CoreTiming, ScheduleIntoPast) 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(); From 69d6be09f7084444bc90d5fb6174d8532d5bd51c Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Fri, 31 Mar 2023 19:50:00 +0200 Subject: [PATCH 28/72] IOS/FS: GetDirectoryStats() should return an error if the given path is not a directory. --- Source/Core/Core/IOS/FS/HostBackend/FS.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/IOS/FS/HostBackend/FS.cpp b/Source/Core/Core/IOS/FS/HostBackend/FS.cpp index 2b2cf16be1..cf9a50396e 100644 --- a/Source/Core/Core/IOS/FS/HostBackend/FS.cpp +++ b/Source/Core/Core/IOS/FS/HostBackend/FS.cpp @@ -771,7 +771,12 @@ 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); // add one for the folder itself @@ -783,7 +788,7 @@ Result HostFileSystem::GetDirectoryStats(const std::string& wii_ } else { - WARN_LOG_FMT(IOS_FS, "fsBlock failed, cannot find directory: {}", path); + return ResultCode::Invalid; } return stats; } From 8295d6d4154bef240f4b23d098c46afd9ea29752 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Fri, 31 Mar 2023 20:03:40 +0200 Subject: [PATCH 29/72] IOS/FS: More accurate cluster calculation in GetDirectoryStats(). --- Source/Core/Core/IOS/FS/HostBackend/FS.cpp | 53 ++++++++++++++-------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/Source/Core/Core/IOS/FS/HostBackend/FS.cpp b/Source/Core/Core/IOS/FS/HostBackend/FS.cpp index cf9a50396e..2f390e4d76 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 @@ -747,6 +749,19 @@ 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"); @@ -779,12 +794,12 @@ Result HostFileSystem::GetDirectoryStats(const std::string& wii_ if (info.IsDirectory()) { File::FSTEntry parent_dir = File::ScanDirectoryTree(path, true); + // 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 { From 5c05155828431262c983bb3c8d3ec437bef6864a Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Fri, 31 Mar 2023 20:07:04 +0200 Subject: [PATCH 30/72] IOS/FS: Implement GetNandStats(). --- Source/Core/Core/IOS/FS/HostBackend/FS.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Source/Core/Core/IOS/FS/HostBackend/FS.cpp b/Source/Core/Core/IOS/FS/HostBackend/FS.cpp index 2f390e4d76..7a2d2135c2 100644 --- a/Source/Core/Core/IOS/FS/HostBackend/FS.cpp +++ b/Source/Core/Core/IOS/FS/HostBackend/FS.cpp @@ -764,17 +764,18 @@ static u64 ComputeUsedClusters(const File::FSTEntry& parent_entry) 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; } From 5373fcc1e7351b80b64072b7edf625f5bae00c44 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Fri, 31 Mar 2023 20:50:56 +0200 Subject: [PATCH 31/72] IOS/FS: Filter files exposed to the emulated system in ReadDirectory() and GetDirectoryStats(). --- Source/Core/Core/IOS/FS/FileSystem.h | 3 ++ Source/Core/Core/IOS/FS/FileSystemCommon.cpp | 8 ++++ Source/Core/Core/IOS/FS/HostBackend/FS.cpp | 47 +++++++++++++++++--- 3 files changed, 52 insertions(+), 6 deletions(-) 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 7a2d2135c2..991f1353d2 100644 --- a/Source/Core/Core/IOS/FS/HostBackend/FS.cpp +++ b/Source/Core/Core/IOS/FS/HostBackend/FS.cpp @@ -104,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, @@ -647,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: @@ -795,6 +829,7 @@ Result HostFileSystem::GetDirectoryStats(const std::string& wii_ 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 = static_cast(std::min(1 + parent_dir.size, TOTAL_INODES)); From 1cf30055b26fa2966c411ae9e70510daaa21174a Mon Sep 17 00:00:00 2001 From: Minty-Meeo <45425365+Minty-Meeo@users.noreply.github.com> Date: Thu, 23 Mar 2023 12:28:44 -0500 Subject: [PATCH 32/72] Resolve [-Wsign-compare] --- Source/Core/Common/FileUtil.cpp | 2 +- Source/Core/Core/HW/EXI/BBA/BuiltIn.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/Core/Common/FileUtil.cpp b/Source/Core/Common/FileUtil.cpp index b97185e769..a9e7c35946 100644 --- a/Source/Core/Common/FileUtil.cpp +++ b/Source/Core/Common/FileUtil.cpp @@ -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(); 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; From d9a49c68d98a4a45eddd69007b2e15cdea6798f5 Mon Sep 17 00:00:00 2001 From: Minty-Meeo <45425365+Minty-Meeo@users.noreply.github.com> Date: Thu, 23 Mar 2023 12:00:41 -0500 Subject: [PATCH 33/72] Resolve [-Wunused-lambda-capture] --- Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp index 46db6477d4..eda208da00 100644 --- a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp @@ -885,7 +885,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); From 3282082599a36d4a7597751322bcec7349c4a7d8 Mon Sep 17 00:00:00 2001 From: Minty-Meeo <45425365+Minty-Meeo@users.noreply.github.com> Date: Thu, 23 Mar 2023 11:17:49 -0500 Subject: [PATCH 34/72] Resolve [-Wwrite-strings] --- Source/Core/DolphinQt/Main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/DolphinQt/Main.cpp b/Source/Core/DolphinQt/Main.cpp index 849a5b5550..317d12fefa 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 From 2bb619a508ecb3df24be709345fae7ef0dbd434d Mon Sep 17 00:00:00 2001 From: Minty-Meeo <45425365+Minty-Meeo@users.noreply.github.com> Date: Thu, 23 Mar 2023 10:42:37 -0500 Subject: [PATCH 35/72] Resolve [-Wstringop-overflow=] --- Source/Core/Common/Crypto/bn.cpp | 27 +++++++++++++++------------ Source/Core/Common/Crypto/bn.h | 14 ++++++++------ 2 files changed, 23 insertions(+), 18 deletions(-) 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); From 64ce2012e34bbe7ba031f70173531cf350f4282b Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 11 Apr 2023 09:12:01 -0400 Subject: [PATCH 36/72] Common/ENetUtil: Move interface into Common namespace Rather than just being under a separate ENetUtil namespace, we can unify this into the common namespace as Common::ENet. --- Source/Core/Common/ENetUtil.cpp | 4 ++-- Source/Core/Common/ENetUtil.h | 4 ++-- Source/Core/Core/NetPlayClient.cpp | 6 +++--- Source/Core/Core/NetPlayServer.cpp | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Source/Core/Common/ENetUtil.cpp b/Source/Core/Common/ENetUtil.cpp index 3cdfbf8829..3bf524ea8b 100644 --- a/Source/Core/Common/ENetUtil.cpp +++ b/Source/Core/Common/ENetUtil.cpp @@ -6,7 +6,7 @@ #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/ENetUtil.h index 5b06e5a007..a011e37057 100644 --- a/Source/Core/Common/ENetUtil.h +++ b/Source/Core/Common/ENetUtil.h @@ -9,9 +9,9 @@ #include "Common/CommonTypes.h" -namespace ENetUtil +namespace Common::ENet { 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/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp index db5027fd08..074e4faf54 100644 --- a/Source/Core/Core/NetPlayClient.cpp +++ b/Source/Core/Core/NetPlayClient.cpp @@ -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); } } @@ -1522,7 +1522,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 +1577,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 30a2ba894a..a5e716cd31 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -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(); @@ -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) @@ -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) From 81493ee91082c70af3426de5638cc1615efc209f Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 11 Apr 2023 09:17:00 -0400 Subject: [PATCH 37/72] NetPlayServer: Prevent unnecessary copies in GetInterfaceSet() This was previously copying each pair out of the vector returned by GetInterfaceListInternal() when we just need to emplace the first entry of each pair. --- Source/Core/Core/NetPlayServer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index 30a2ba894a..20c54a1adf 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -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; } From 09e11b80679c3c03796fa78b0f1894a38ea59566 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 11 Apr 2023 11:48:46 -0400 Subject: [PATCH 38/72] Common: Rename ENetUtil.cpp/.h to ENet.cpp/.h --- Source/Core/Common/CMakeLists.txt | 4 ++-- Source/Core/Common/{ENetUtil.cpp => ENet.cpp} | 2 +- Source/Core/Common/{ENetUtil.h => ENet.h} | 0 Source/Core/Core/NetPlayClient.cpp | 2 +- Source/Core/Core/NetPlayServer.cpp | 2 +- Source/Core/DolphinLib.props | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) rename Source/Core/Common/{ENetUtil.cpp => ENet.cpp} (98%) rename Source/Core/Common/{ENetUtil.h => ENet.h} (100%) diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index 8269290729..77f9c87a1a 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 diff --git a/Source/Core/Common/ENetUtil.cpp b/Source/Core/Common/ENet.cpp similarity index 98% rename from Source/Core/Common/ENetUtil.cpp rename to Source/Core/Common/ENet.cpp index 3bf524ea8b..b694eba042 100644 --- a/Source/Core/Common/ENetUtil.cpp +++ b/Source/Core/Common/ENet.cpp @@ -1,7 +1,7 @@ // 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" diff --git a/Source/Core/Common/ENetUtil.h b/Source/Core/Common/ENet.h similarity index 100% rename from Source/Core/Common/ENetUtil.h rename to Source/Core/Common/ENet.h diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp index 074e4faf54..0aa235afd2 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" diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index a5e716cd31..9453c97478 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" diff --git a/Source/Core/DolphinLib.props b/Source/Core/DolphinLib.props index 44048669a6..0a23ac5c8c 100644 --- a/Source/Core/DolphinLib.props +++ b/Source/Core/DolphinLib.props @@ -42,7 +42,7 @@ - + @@ -753,7 +753,7 @@ - + From 67ab4d24732f785612e87e94f67a44b4199a7989 Mon Sep 17 00:00:00 2001 From: LillyJadeKatrin Date: Sat, 8 Apr 2023 13:53:50 -0400 Subject: [PATCH 39/72] Added ResolveHash to AchievementManager Added the ResolveHash method to AchievementManager. This is a blocking function to send a hash string to the RetroAchievements server to verify it and get a game ID back. --- Source/Core/Core/AchievementManager.cpp | 21 +++++++++++++++++++++ Source/Core/Core/AchievementManager.h | 7 +++++++ 2 files changed, 28 insertions(+) diff --git a/Source/Core/Core/AchievementManager.cpp b/Source/Core/Core/AchievementManager.cpp index 7e0fa5a9d9..4cd3aad766 100644 --- a/Source/Core/Core/AchievementManager.cpp +++ b/Source/Core/Core/AchievementManager.cpp @@ -4,6 +4,10 @@ #ifdef USE_RETRO_ACHIEVEMENTS #include "Core/AchievementManager.h" + +#include +#include + #include "Common/HttpRequest.h" #include "Common/WorkQueueThread.h" #include "Config/AchievementSettings.h" @@ -71,6 +75,23 @@ AchievementManager::ResponseType AchievementManager::VerifyCredentials(const std 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; +} + // 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..4132db23af 100644 --- a/Source/Core/Core/AchievementManager.h +++ b/Source/Core/Core/AchievementManager.h @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -38,7 +39,10 @@ public: private: AchievementManager() = default; + static constexpr int HASH_LENGTH = 33; + ResponseType VerifyCredentials(const std::string& password); + ResponseType ResolveHash(std::array game_hash); template ResponseType Request(RcRequest rc_request, RcResponse* rc_response, @@ -47,7 +51,10 @@ private: rc_runtime_t m_runtime{}; bool m_is_runtime_initialized = false; + unsigned int m_game_id = 0; rc_api_login_response_t m_login_data{}; + + Common::WorkQueueThread> m_queue; }; // class AchievementManager From 7e8a770b309b61e87ca9cf133d2cec41552e90fc Mon Sep 17 00:00:00 2001 From: LillyJadeKatrin Date: Mon, 10 Apr 2023 23:56:15 -0400 Subject: [PATCH 40/72] Added StartRASession to AchievementManager Added a call to the RetroAchievements Start Session API to AchievementManager. This is primarily for client-side activation, so it doesn't return much of value, aside from its success/error information, but I'm storing the return structure in case this changes in the future. --- Source/Core/Core/AchievementManager.cpp | 14 ++++++++++++++ Source/Core/Core/AchievementManager.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/Source/Core/Core/AchievementManager.cpp b/Source/Core/Core/AchievementManager.cpp index 4cd3aad766..6239563167 100644 --- a/Source/Core/Core/AchievementManager.cpp +++ b/Source/Core/Core/AchievementManager.cpp @@ -92,6 +92,20 @@ AchievementManager::ResolveHash(std::array game_hash) 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; +} + // 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 4132db23af..c16c140670 100644 --- a/Source/Core/Core/AchievementManager.h +++ b/Source/Core/Core/AchievementManager.h @@ -43,6 +43,7 @@ private: ResponseType VerifyCredentials(const std::string& password); ResponseType ResolveHash(std::array game_hash); + ResponseType StartRASession(); template ResponseType Request(RcRequest rc_request, RcResponse* rc_response, @@ -55,6 +56,7 @@ private: rc_api_login_response_t m_login_data{}; + Common::WorkQueueThread> m_queue; }; // class AchievementManager From bd75ce6e6db1c3bc06daae951bddf9733c9783ad Mon Sep 17 00:00:00 2001 From: LillyJadeKatrin Date: Wed, 5 Apr 2023 20:19:58 -0400 Subject: [PATCH 41/72] Added FetchGameData to AchievementManager FetchGameData is the big one - this retrieves the logic for all the achievements, leaderboards, and rich presence, and all the relevant metadata for the game. --- Source/Core/Core/AchievementManager.cpp | 11 +++++++++++ Source/Core/Core/AchievementManager.h | 3 +++ 2 files changed, 14 insertions(+) diff --git a/Source/Core/Core/AchievementManager.cpp b/Source/Core/Core/AchievementManager.cpp index 6239563167..ff93120d7c 100644 --- a/Source/Core/Core/AchievementManager.cpp +++ b/Source/Core/Core/AchievementManager.cpp @@ -106,6 +106,17 @@ AchievementManager::ResponseType AchievementManager::StartRASession() 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); +} + // 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 c16c140670..7e39990fd3 100644 --- a/Source/Core/Core/AchievementManager.h +++ b/Source/Core/Core/AchievementManager.h @@ -44,6 +44,7 @@ private: ResponseType VerifyCredentials(const std::string& password); ResponseType ResolveHash(std::array game_hash); ResponseType StartRASession(); + ResponseType FetchGameData(); template ResponseType Request(RcRequest rc_request, RcResponse* rc_response, @@ -57,6 +58,8 @@ private: + rc_api_fetch_game_data_response_t m_game_data{}; + Common::WorkQueueThread> m_queue; }; // class AchievementManager From 8b57c4b239da92f76491792b2b67f9763c505e6a Mon Sep 17 00:00:00 2001 From: LillyJadeKatrin Date: Tue, 11 Apr 2023 00:04:08 -0400 Subject: [PATCH 42/72] Added LoadGameByFilenameAsync and CloseGame to AchievementManager LoadGameByFilenameAsync sets up a volume reader and hashes the volume, then uses that hash to make the three consecutive API requests to resolve hash, start session and load game data. CloseGame resets the m_is_game_loaded flag, wipes the queue, and destroys all the game data responses. --- Source/Core/Core/AchievementManager.cpp | 111 ++++++++++++++++++++++-- Source/Core/Core/AchievementManager.h | 13 +-- Source/Core/Core/BootManager.cpp | 11 +++ Source/Core/Core/Core.cpp | 5 ++ 4 files changed, 126 insertions(+), 14 deletions(-) diff --git a/Source/Core/Core/AchievementManager.cpp b/Source/Core/Core/AchievementManager.cpp index ff93120d7c..a566ae6a63 100644 --- a/Source/Core/Core/AchievementManager.cpp +++ b/Source/Core/Core/AchievementManager.cpp @@ -12,6 +12,7 @@ #include "Common/WorkQueueThread.h" #include "Config/AchievementSettings.h" #include "Core/Core.h" +#include "DiscIO/Volume.h" AchievementManager* AchievementManager::GetInstance() { @@ -32,46 +33,140 @@ 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) { + auto state = std::make_unique(); + state->volume = DiscIO::CreateVolume(path_utf8); + return reinterpret_cast(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; + rc_hash_generate_from_file(game_hash.data(), RC_CONSOLE_GAMECUBE, iso_path.c_str()); + 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; + callback(fetch_game_data_response); + }); +} + +void AchievementManager::CloseGame() +{ + m_is_game_loaded = false; + m_game_id = 0; + m_queue.Cancel(); } 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; } diff --git a/Source/Core/Core/AchievementManager.h b/Source/Core/Core/AchievementManager.h index 7e39990fd3..ecbf236d60 100644 --- a/Source/Core/Core/AchievementManager.h +++ b/Source/Core/Core/AchievementManager.h @@ -22,17 +22,21 @@ 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 CloseGame(); void Logout(); void Shutdown(); @@ -54,11 +58,8 @@ private: rc_runtime_t m_runtime{}; bool m_is_runtime_initialized = false; unsigned int m_game_id = 0; - rc_api_login_response_t m_login_data{}; - - - rc_api_fetch_game_data_response_t m_game_data{}; + bool m_is_game_loaded = false; Common::WorkQueueThread> m_queue; }; // class AchievementManager 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/Core.cpp b/Source/Core/Core/Core.cpp index 4294faaf45..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); From 6982f52f6edff1a9e7e4e3b02de4a88e5799a3b4 Mon Sep 17 00:00:00 2001 From: LillyJadeKatrin Date: Sun, 9 Apr 2023 08:12:22 -0400 Subject: [PATCH 43/72] Updated rcheevos submodule Update the rcheevos submodule to the most recent origin/develop, which contains a fix to the gamecube hash algorithm to politely exit if it is unable to open a file. --- Externals/rcheevos/rcheevos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 678c93589a642a72d8f2122fca681b886e442ccd Mon Sep 17 00:00:00 2001 From: Minty-Meeo <45425365+Minty-Meeo@users.noreply.github.com> Date: Thu, 23 Mar 2023 12:49:09 -0500 Subject: [PATCH 44/72] Resolve [-Wclass-memaccess] --- Source/Core/Core/FifoPlayer/FifoPlayer.cpp | 12 ++++------ Source/Core/Core/HW/MemoryInterface.cpp | 9 +------ .../HW/WiimoteEmu/DesiredWiimoteState.cpp | 10 ++------ Source/Core/VideoCommon/CPMemory.cpp | 12 ++++------ Source/Core/VideoCommon/ShaderCache.cpp | 24 +++++++------------ .../Core/VideoCommon/VertexLoaderManager.cpp | 11 +++------ 6 files changed, 22 insertions(+), 56 deletions(-) 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/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/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/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/ShaderCache.cpp b/Source/Core/VideoCommon/ShaderCache.cpp index 1c01356c99..150f38b307 100644 --- a/Source/Core/VideoCommon/ShaderCache.cpp +++ b/Source/Core/VideoCommon/ShaderCache.cpp @@ -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/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, From efd06a85d2af7da5968a5daba4d601776fd32360 Mon Sep 17 00:00:00 2001 From: Minty-Meeo <45425365+Minty-Meeo@users.noreply.github.com> Date: Thu, 23 Mar 2023 12:56:57 -0500 Subject: [PATCH 45/72] Resolve [-Wunused-but-set-variable] --- Source/Core/Common/SettingsHandler.cpp | 2 -- 1 file changed, 2 deletions(-) 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); } From 528f7c90e9c83b5ef1469a36a0c1035948548909 Mon Sep 17 00:00:00 2001 From: Minty-Meeo <45425365+Minty-Meeo@users.noreply.github.com> Date: Thu, 23 Mar 2023 13:26:34 -0500 Subject: [PATCH 46/72] Resolve [-Wtautological-constant-out-of-range-compare] --- Source/Core/Core/NetPlayClient.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp index db5027fd08..e21dbb393e 100644 --- a/Source/Core/Core/NetPlayClient.cpp +++ b/Source/Core/Core/NetPlayClient.cpp @@ -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 } From 244918acb8e0a9580f17b0c06de7583e95ea4fe6 Mon Sep 17 00:00:00 2001 From: Minty-Meeo <45425365+Minty-Meeo@users.noreply.github.com> Date: Thu, 23 Mar 2023 11:01:13 -0500 Subject: [PATCH 47/72] Resolve [-Wdeprecated-declarations] --- Source/Core/Common/HttpRequest.cpp | 13 +++++++------ Source/Core/Common/HttpRequest.h | 3 +-- Source/Core/UpdaterCommon/UpdaterCommon.cpp | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) 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/UpdaterCommon/UpdaterCommon.cpp b/Source/Core/UpdaterCommon/UpdaterCommon.cpp index 408c313c95..9dd40c679f 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; From 65edfb0eeda1710d11d1133501b6cd0a335869aa Mon Sep 17 00:00:00 2001 From: Minty-Meeo <45425365+Minty-Meeo@users.noreply.github.com> Date: Thu, 23 Mar 2023 13:17:29 -0500 Subject: [PATCH 48/72] Resolve [-Wunused-const-variable] --- Source/Core/Core/HW/DSPHLE/UCodes/AESnd.cpp | 16 ++++++++-------- Source/Core/Core/HW/ProcessorInterface.cpp | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) 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/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) From f29019180f12e8287661ebde19f0b1baed966bc9 Mon Sep 17 00:00:00 2001 From: Minty-Meeo <45425365+Minty-Meeo@users.noreply.github.com> Date: Thu, 23 Mar 2023 13:55:04 -0500 Subject: [PATCH 49/72] Pragma diagnostic ignore [-Wregister] is no longer needed --- Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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 From f5bdfdde1abe44121a6b2c7d895e63edb5b8f726 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 12 Apr 2023 14:15:56 -0400 Subject: [PATCH 50/72] Common/UPnP: Move interface into Common namespace Keeps these utilities consistent with the rest of most of the Common library. --- Source/Core/Common/UPnP.cpp | 4 ++-- Source/Core/Common/UPnP.h | 4 ++-- Source/Core/Core/NetPlayServer.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) 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/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index aa4d97be0e..cf5f5571b9 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -111,7 +111,7 @@ NetPlayServer::~NetPlayServer() } #ifdef USE_UPNP - UPnP::StopPortmapping(); + Common::UPnP::StopPortmapping(); #endif } @@ -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 } } From 33836d630ab24ca5f522f2d74ef40404153e7c32 Mon Sep 17 00:00:00 2001 From: OatmealDome Date: Wed, 12 Apr 2023 16:00:08 -0400 Subject: [PATCH 51/72] Externals: Update SDL to 2.26.5 --- Externals/SDL/SDL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 0753b3b6ed75b7e5668eade824eb444d29d7956d Mon Sep 17 00:00:00 2001 From: OatmealDome Date: Wed, 12 Apr 2023 16:42:44 -0400 Subject: [PATCH 52/72] Externals: Update MoltenVK to 1.2.3 --- Externals/MoltenVK/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From e4caace6bb6213851b979cdd76f9f44ef6d9cd09 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 13 Apr 2023 09:38:09 -0400 Subject: [PATCH 53/72] Common/IniFile: Move interface into Common namespace Gets this out of the global namespace and into the Common namespace --- 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/IniFile.cpp | 3 +++ Source/Core/Common/IniFile.h | 3 +++ Source/Core/Core/ActionReplay.cpp | 9 ++++----- Source/Core/Core/ActionReplay.h | 9 ++++++--- Source/Core/Core/CheatCodes.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/GeckoCodeConfig.cpp | 6 +++--- Source/Core/Core/GeckoCodeConfig.h | 7 +++++-- Source/Core/Core/HotkeyManager.cpp | 2 +- Source/Core/Core/IOS/USB/USB_KBD.cpp | 2 +- Source/Core/Core/NetPlayServer.cpp | 4 ++-- Source/Core/Core/PatchEngine.cpp | 17 ++++++++--------- Source/Core/Core/PatchEngine.h | 7 +++++-- Source/Core/DolphinQt/Config/ARCodeWidget.cpp | 7 ++++--- .../Core/DolphinQt/Config/GameConfigWidget.h | 4 ++-- .../Core/DolphinQt/Config/GeckoCodeWidget.cpp | 7 ++++--- .../DolphinQt/Config/Mapping/MappingWindow.cpp | 6 +++--- Source/Core/DolphinQt/Config/PatchesWidget.cpp | 7 ++++--- .../DolphinQt/Debugger/BreakpointWidget.cpp | 4 ++-- Source/Core/DolphinQt/Debugger/WatchWidget.cpp | 4 ++-- .../Core/DolphinQt/TAS/WiiTASInputWindow.cpp | 2 +- .../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 ++++---- .../Core/InputCommon/ControllerEmu/StickGate.h | 4 ++-- .../InputCommon/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/ResourcePack/Manager.cpp | 14 +++++++------- Source/Core/VideoCommon/PostProcessing.cpp | 6 +++--- 45 files changed, 172 insertions(+), 137 deletions(-) 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/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/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/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/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/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/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/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/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index cf5f5571b9..91f494f8df 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -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); diff --git a/Source/Core/Core/PatchEngine.cpp b/Source/Core/Core/PatchEngine.cpp index 21187dd9b6..069d8565c0 100644 --- a/Source/Core/Core/PatchEngine.cpp +++ b/Source/Core/Core/PatchEngine.cpp @@ -101,11 +101,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; @@ -151,7 +149,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; @@ -176,7 +174,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); @@ -210,9 +208,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); 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/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/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/Debugger/BreakpointWidget.cpp b/Source/Core/DolphinQt/Debugger/BreakpointWidget.cpp index c21ae91e6f..2412bef831 100644 --- a/Source/Core/DolphinQt/Debugger/BreakpointWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/BreakpointWidget.cpp @@ -337,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)) { @@ -367,7 +367,7 @@ 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", m_system.GetPowerPC().GetBreakPoints().GetStrings()); diff --git a/Source/Core/DolphinQt/Debugger/WatchWidget.cpp b/Source/Core/DolphinQt/Debugger/WatchWidget.cpp index 2be4a2a2f7..16d327835e 100644 --- a/Source/Core/DolphinQt/Debugger/WatchWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/WatchWidget.cpp @@ -289,7 +289,7 @@ void WatchWidget::OnNewWatch() void WatchWidget::OnLoad() { - IniFile ini; + Common::IniFile ini; std::vector watches; @@ -317,7 +317,7 @@ 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", m_system.GetPowerPC().GetDebugInterface().SaveWatchesToStrings()); 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/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/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/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/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"; From 09c80513cd82c05948620a5ade1668ca419ce0fc Mon Sep 17 00:00:00 2001 From: TellowKrinkle Date: Thu, 13 Apr 2023 22:33:40 -0500 Subject: [PATCH 54/72] VideoBackends:Metal: Fix perf queries Fixes an issue where perf queries could end up including counts from previous queries --- .../VideoBackends/Metal/MTLStateTracker.h | 1 + .../VideoBackends/Metal/MTLStateTracker.mm | 22 +++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/Source/Core/VideoBackends/Metal/MTLStateTracker.h b/Source/Core/VideoBackends/Metal/MTLStateTracker.h index f425cd2884..48b37873d8 100644 --- a/Source/Core/VideoBackends/Metal/MTLStateTracker.h +++ b/Source/Core/VideoBackends/Metal/MTLStateTracker.h @@ -267,6 +267,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..9cd7ea52d0 100644 --- a/Source/Core/VideoBackends/Metal/MTLStateTracker.mm +++ b/Source/Core/VideoBackends/Metal/MTLStateTracker.mm @@ -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(); + } } } From 505f40cf9d6df3a2f5985132505caacf4125d403 Mon Sep 17 00:00:00 2001 From: LillyJadeKatrin Date: Wed, 12 Apr 2023 21:46:27 -0400 Subject: [PATCH 55/72] Added ActivateDeactivateAchievement to AchievementManager ActivateDeactivateAchievement is passed an Achievement ID as returned from the FetchGameData API call and determines whether to activate it, deactivate it, or leave it where it is based on its current known state and what settings are enabled. Activating or deactivating an achievement entails calling a method provided by rcheevos that performs this on the rcheevos runtime. Activating an achievement loads its memory signature into the runtime; now the runtime will process the achievement each time the rc_runtime_do_frame function is called (this will be in a future PR) to determine when the achievement's requirements are met. Deactivating an achievement unloads it from the runtime. The specific logic to determine whether an achievement is active operates over many fields but is documented in detail inside the function. There are multiple settings flags for which achievements are enabled (one flag for all achievements, an "unofficial" flag for enabling achievements marked as unofficial i.e. those that have logic on the site but have not yet been officially approved, and an "encore" flag that enables achievements the player has already unlocked) and this function also evaluates whether the achievement has been unlocked in hardcore mode or softcore mode (though currently every reference to the current hardcore mode state is hardcoded as false). --- Source/Core/Core/AchievementManager.cpp | 49 +++++++++++++++++++ Source/Core/Core/AchievementManager.h | 18 +++++++ .../Core/Core/Config/AchievementSettings.cpp | 5 ++ Source/Core/Core/Config/AchievementSettings.h | 3 ++ 4 files changed, 75 insertions(+) diff --git a/Source/Core/Core/AchievementManager.cpp b/Source/Core/Core/AchievementManager.cpp index a566ae6a63..84329b1f10 100644 --- a/Source/Core/Core/AchievementManager.cpp +++ b/Source/Core/Core/AchievementManager.cpp @@ -14,6 +14,8 @@ #include "Core/Core.h" #include "DiscIO/Volume.h" +static constexpr bool hardcore_mode_enabled = false; + AchievementManager* AchievementManager::GetInstance() { static AchievementManager s_instance; @@ -138,6 +140,7 @@ void AchievementManager::CloseGame() m_is_game_loaded = false; m_game_id = 0; m_queue.Cancel(); + m_unlock_map.clear(); } void AchievementManager::Logout() @@ -212,6 +215,52 @@ AchievementManager::ResponseType AchievementManager::FetchGameData() rc_api_process_fetch_game_data_response); } +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 ecbf236d60..511a573d23 100644 --- a/Source/Core/Core/AchievementManager.h +++ b/Source/Core/Core/AchievementManager.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -16,6 +17,8 @@ #include "Common/Event.h" #include "Common/WorkQueueThread.h" +using AchievementId = u32; + class AchievementManager { public: @@ -50,6 +53,8 @@ private: ResponseType StartRASession(); ResponseType FetchGameData(); + void ActivateDeactivateAchievement(AchievementId id, bool enabled, bool unofficial, bool encore); + template ResponseType Request(RcRequest rc_request, RcResponse* rc_response, const std::function& init_request, @@ -61,6 +66,19 @@ private: 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; }; // class AchievementManager diff --git a/Source/Core/Core/Config/AchievementSettings.cpp b/Source/Core/Core/Config/AchievementSettings.cpp index f7ec642881..92a761f6a6 100644 --- a/Source/Core/Core/Config/AchievementSettings.cpp +++ b/Source/Core/Core/Config/AchievementSettings.cpp @@ -13,4 +13,9 @@ 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_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..13da23eafa 100644 --- a/Source/Core/Core/Config/AchievementSettings.h +++ b/Source/Core/Core/Config/AchievementSettings.h @@ -11,4 +11,7 @@ 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_UNOFFICIAL_ENABLED; +extern const Info RA_ENCORE_ENABLED; } // namespace Config From db44e10057893deb614fc67cd8c87515bae7d53f Mon Sep 17 00:00:00 2001 From: LillyJadeKatrin Date: Wed, 12 Apr 2023 21:43:07 -0400 Subject: [PATCH 56/72] Added FetchUnlockData to AchievementManager FetchUnlockData is an API call to RetroAchievements that downloads a list of achievement IDs for a game that the user has already unlocked and published to the site. It accepts a parameter for whether or not hardcore or softcore achievements are being requested, so that must be provided as well. Once it has the requested list on hand, it updates each achievement's status in the unlock map and will activate or deactivate achievements as necessary. --- Source/Core/Core/AchievementManager.cpp | 33 +++++++++++++++++++++++++ Source/Core/Core/AchievementManager.h | 2 ++ 2 files changed, 35 insertions(+) diff --git a/Source/Core/Core/AchievementManager.cpp b/Source/Core/Core/AchievementManager.cpp index 84329b1f10..e6b5df8bd9 100644 --- a/Source/Core/Core/AchievementManager.cpp +++ b/Source/Core/Core/AchievementManager.cpp @@ -215,6 +215,39 @@ AchievementManager::ResponseType AchievementManager::FetchGameData() 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) { diff --git a/Source/Core/Core/AchievementManager.h b/Source/Core/Core/AchievementManager.h index 511a573d23..0e0c2668d9 100644 --- a/Source/Core/Core/AchievementManager.h +++ b/Source/Core/Core/AchievementManager.h @@ -52,6 +52,7 @@ private: ResponseType ResolveHash(std::array game_hash); ResponseType StartRASession(); ResponseType FetchGameData(); + ResponseType FetchUnlockData(bool hardcore); void ActivateDeactivateAchievement(AchievementId id, bool enabled, bool unofficial, bool encore); @@ -80,6 +81,7 @@ private: std::unordered_map m_unlock_map; Common::WorkQueueThread> m_queue; + std::recursive_mutex m_lock; }; // class AchievementManager #endif // USE_RETRO_ACHIEVEMENTS From da1de36cb9b46a13cff4cd610516d19e3799923f Mon Sep 17 00:00:00 2001 From: LillyJadeKatrin Date: Wed, 12 Apr 2023 08:51:51 -0400 Subject: [PATCH 57/72] Added LoadUnlockData and ActivateDeactivateAchievements to AchievementManager LoadUnlockData and ActivateDeactivateAchievements are the public API components responding to the FetchUnlocks and A/DAchievement (singular) private methods. LoadUnlockData is asynchronous and performs both a hardcore and a softcore unlock call, updating the unlock map and the active status of any achievements returned from these calls. ActivateDeactivateAchievements calls ActivateDeactivateAchievement on every achievement ID found in m_game_data, initializing the unlock map for each ID if not already found. Both of these are currently called in LoadGameByFilenameAsync once the game has been loaded properly. There's a lock around this, to ensure that the unlock map is initialized properly by ActivateDeactivate Achievements before FetchUnlockData makes modifications to it without stalling the async portions of FetchUnlockData. --- Source/Core/Core/AchievementManager.cpp | 39 +++++++++++++++++++++++++ Source/Core/Core/AchievementManager.h | 2 ++ 2 files changed, 41 insertions(+) diff --git a/Source/Core/Core/AchievementManager.cpp b/Source/Core/Core/AchievementManager.cpp index e6b5df8bd9..11061073fe 100644 --- a/Source/Core/Core/AchievementManager.cpp +++ b/Source/Core/Core/AchievementManager.cpp @@ -131,16 +131,55 @@ void AchievementManager::LoadGameByFilenameAsync(const std::string& iso_path, 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(); + } + 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::CloseGame() { m_is_game_loaded = false; m_game_id = 0; m_queue.Cancel(); m_unlock_map.clear(); + ActivateDeactivateAchievements(); } void AchievementManager::Logout() diff --git a/Source/Core/Core/AchievementManager.h b/Source/Core/Core/AchievementManager.h index 0e0c2668d9..7eb6397e49 100644 --- a/Source/Core/Core/AchievementManager.h +++ b/Source/Core/Core/AchievementManager.h @@ -39,6 +39,8 @@ public: bool IsLoggedIn() const; void LoadGameByFilenameAsync(const std::string& iso_path, const ResponseCallback& callback); + void LoadUnlockData(const ResponseCallback& callback); + void ActivateDeactivateAchievements(); void CloseGame(); void Logout(); void Shutdown(); From 64e3a64c87d6a7880be47d14bf97174f791a2d58 Mon Sep 17 00:00:00 2001 From: LillyJadeKatrin Date: Thu, 13 Apr 2023 23:34:46 -0400 Subject: [PATCH 58/72] Added ActivateDeactivateLeaderboards to AchievementManager This activates or deactivates leaderboards in the rcheevos runtime similarly to achievements. The logic is much more straightforward - all leaderboards are active together; there is nothing requiring some leaderboards to be active while others are unactive, and even a leaderboard that has been submitted to in this session is still active to be submitted to again. The only criteria are that leaderboards must be enabled in the settings, and hardcore mode must be on, the latter of which is false until a future PR. --- Source/Core/Core/AchievementManager.cpp | 19 +++++++++++++++++++ Source/Core/Core/AchievementManager.h | 1 + .../Core/Core/Config/AchievementSettings.cpp | 2 ++ Source/Core/Core/Config/AchievementSettings.h | 1 + 4 files changed, 23 insertions(+) diff --git a/Source/Core/Core/AchievementManager.cpp b/Source/Core/Core/AchievementManager.cpp index 11061073fe..1b44ab8a4e 100644 --- a/Source/Core/Core/AchievementManager.cpp +++ b/Source/Core/Core/AchievementManager.cpp @@ -141,6 +141,7 @@ void AchievementManager::LoadGameByFilenameAsync(const std::string& iso_path, LoadUnlockData([](ResponseType r_type) {}); ActivateDeactivateAchievements(); } + ActivateDeactivateLeaderboards(); callback(fetch_game_data_response); }); @@ -173,6 +174,23 @@ void AchievementManager::ActivateDeactivateAchievements() } } +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::CloseGame() { m_is_game_loaded = false; @@ -180,6 +198,7 @@ void AchievementManager::CloseGame() m_queue.Cancel(); m_unlock_map.clear(); ActivateDeactivateAchievements(); + ActivateDeactivateLeaderboards(); } void AchievementManager::Logout() diff --git a/Source/Core/Core/AchievementManager.h b/Source/Core/Core/AchievementManager.h index 7eb6397e49..d2e37329f0 100644 --- a/Source/Core/Core/AchievementManager.h +++ b/Source/Core/Core/AchievementManager.h @@ -41,6 +41,7 @@ public: void LoadUnlockData(const ResponseCallback& callback); void ActivateDeactivateAchievements(); + void ActivateDeactivateLeaderboards(); void CloseGame(); void Logout(); void Shutdown(); diff --git a/Source/Core/Core/Config/AchievementSettings.cpp b/Source/Core/Core/Config/AchievementSettings.cpp index 92a761f6a6..6da342cbc4 100644 --- a/Source/Core/Core/Config/AchievementSettings.cpp +++ b/Source/Core/Core/Config/AchievementSettings.cpp @@ -15,6 +15,8 @@ const Info RA_USERNAME{{System::Achievements, "Achievements", "User 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_UNOFFICIAL_ENABLED{{System::Achievements, "Achievements", "UnofficialEnabled"}, false}; const Info RA_ENCORE_ENABLED{{System::Achievements, "Achievements", "EncoreEnabled"}, false}; diff --git a/Source/Core/Core/Config/AchievementSettings.h b/Source/Core/Core/Config/AchievementSettings.h index 13da23eafa..f49537ec39 100644 --- a/Source/Core/Core/Config/AchievementSettings.h +++ b/Source/Core/Core/Config/AchievementSettings.h @@ -12,6 +12,7 @@ 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_UNOFFICIAL_ENABLED; extern const Info RA_ENCORE_ENABLED; } // namespace Config From 31c3288fd52704f41dde9c7304b0233c53accb19 Mon Sep 17 00:00:00 2001 From: LillyJadeKatrin Date: Thu, 13 Apr 2023 23:35:49 -0400 Subject: [PATCH 59/72] Added ActivateDeactivateRichPresence to AchievementManager RetroAchievements Rich Presence is a script that is run periodically on a game's memory to provide a detailed text description of what the player is doing. Existing Discord presence on Dolphin would update a player's Discord status to say not just that they are using Dolphin but that they are playing, for example, Sonic Adventure 2 Battle; Rich Presence would detail that the player is in City Escape with 5 lives and 142 rings. Activating this in the runtime simply entails loading that text script, as returned by the FetchGameData API call, into the runtime, here only determined by whether rich presence is enabled in the achievement settings. Deactivating this is done via the same rcheevos method by setting the rich presence to an empty string. --- Source/Core/Core/AchievementManager.cpp | 12 ++++++++++++ Source/Core/Core/AchievementManager.h | 2 ++ Source/Core/Core/Config/AchievementSettings.cpp | 2 ++ Source/Core/Core/Config/AchievementSettings.h | 1 + 4 files changed, 17 insertions(+) diff --git a/Source/Core/Core/AchievementManager.cpp b/Source/Core/Core/AchievementManager.cpp index 1b44ab8a4e..a274ac11b7 100644 --- a/Source/Core/Core/AchievementManager.cpp +++ b/Source/Core/Core/AchievementManager.cpp @@ -142,6 +142,7 @@ void AchievementManager::LoadGameByFilenameAsync(const std::string& iso_path, ActivateDeactivateAchievements(); } ActivateDeactivateLeaderboards(); + ActivateDeactivateRichPresence(); callback(fetch_game_data_response); }); @@ -191,6 +192,16 @@ void AchievementManager::ActivateDeactivateLeaderboards() } } +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; @@ -199,6 +210,7 @@ void AchievementManager::CloseGame() m_unlock_map.clear(); ActivateDeactivateAchievements(); ActivateDeactivateLeaderboards(); + ActivateDeactivateRichPresence(); } void AchievementManager::Logout() diff --git a/Source/Core/Core/AchievementManager.h b/Source/Core/Core/AchievementManager.h index d2e37329f0..b759386721 100644 --- a/Source/Core/Core/AchievementManager.h +++ b/Source/Core/Core/AchievementManager.h @@ -42,6 +42,8 @@ public: void LoadUnlockData(const ResponseCallback& callback); void ActivateDeactivateAchievements(); void ActivateDeactivateLeaderboards(); + void ActivateDeactivateRichPresence(); + void CloseGame(); void Logout(); void Shutdown(); diff --git a/Source/Core/Core/Config/AchievementSettings.cpp b/Source/Core/Core/Config/AchievementSettings.cpp index 6da342cbc4..3499fcc791 100644 --- a/Source/Core/Core/Config/AchievementSettings.cpp +++ b/Source/Core/Core/Config/AchievementSettings.cpp @@ -17,6 +17,8 @@ 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}; diff --git a/Source/Core/Core/Config/AchievementSettings.h b/Source/Core/Core/Config/AchievementSettings.h index f49537ec39..33318f7400 100644 --- a/Source/Core/Core/Config/AchievementSettings.h +++ b/Source/Core/Core/Config/AchievementSettings.h @@ -13,6 +13,7 @@ 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 From 5e0c20f8a53d587e4fcacfd202627eadd3a12472 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 15 Apr 2023 03:25:15 -0400 Subject: [PATCH 60/72] Common/MathUtil: Remove MathFloatVectorSum() This isn't used anywhere and not really a generic utility, so we can get rid of it. This also lets us remove MathUtil.cpp, since this was the only thing within that file. --- Source/Core/Common/CMakeLists.txt | 1 - Source/Core/Common/MathUtil.cpp | 12 ------------ Source/Core/Common/MathUtil.h | 3 --- Source/Core/DolphinLib.props | 1 - 4 files changed, 17 deletions(-) delete mode 100644 Source/Core/Common/MathUtil.cpp diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index 77f9c87a1a..6d9636363d 100644 --- a/Source/Core/Common/CMakeLists.txt +++ b/Source/Core/Common/CMakeLists.txt @@ -80,7 +80,6 @@ add_library(common Logging/Log.h Logging/LogManager.cpp Logging/LogManager.h - MathUtil.cpp MathUtil.h Matrix.cpp Matrix.h 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..8656c4313a 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" @@ -188,8 +187,6 @@ private: } // namespace MathUtil -float MathFloatVectorSum(const std::vector&); - // Rounds down. 0 -> undefined constexpr int IntLog2(u64 val) { diff --git a/Source/Core/DolphinLib.props b/Source/Core/DolphinLib.props index 0a23ac5c8c..8a463f5a5e 100644 --- a/Source/Core/DolphinLib.props +++ b/Source/Core/DolphinLib.props @@ -773,7 +773,6 @@ - From 784a21692763296cbd93f59c4cf8a58c902b81e8 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 15 Apr 2023 03:27:35 -0400 Subject: [PATCH 61/72] Common/MathUtil: Move IntLog2 into MathUtil namespace Gets this out of the global namespace. --- Source/Core/Common/Arm64Emitter.cpp | 2 +- Source/Core/Common/MathUtil.h | 3 +-- Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp | 4 ++-- .../Core/PowerPC/Jit64/Jit_SystemRegisters.cpp | 4 ++-- .../Core/Core/PowerPC/Jit64Common/EmuCodeBlock.cpp | 2 +- Source/Core/Core/PowerPC/JitArm64/Jit.cpp | 6 +++--- .../Core/PowerPC/JitArm64/JitArm64_Integer.cpp | 12 ++++++------ .../Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp | 4 ++-- .../PowerPC/JitArm64/JitArm64_SystemRegisters.cpp | 4 ++-- Source/Core/UICommon/UICommon.cpp | 2 +- Source/Core/VideoBackends/OGL/OGLStreamBuffer.cpp | 2 +- .../Core/VideoCommon/TextureConversionShader.cpp | 11 ++++++----- Source/Core/VideoCommon/TextureInfo.cpp | 2 +- Source/UnitTests/Common/MathUtilTest.cpp | 14 +++++++------- 14 files changed, 36 insertions(+), 36 deletions(-) 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/MathUtil.h b/Source/Core/Common/MathUtil.h index 8656c4313a..1494a894d9 100644 --- a/Source/Core/Common/MathUtil.h +++ b/Source/Core/Common/MathUtil.h @@ -185,10 +185,9 @@ private: T m_variance{}; }; -} // namespace MathUtil - // Rounds down. 0 -> undefined constexpr int IntLog2(u64 val) { return 63 - std::countl_zero(val); } +} // namespace MathUtil 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_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 ef0dd426ab..4f1c81316f 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -544,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(); @@ -938,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(); @@ -974,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(); 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 5c4a1b1d56..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; diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp index f01a0f0cf9..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); } 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/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/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/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) From 57ed5320b59371fd0d3162e7611312cdc80e3b46 Mon Sep 17 00:00:00 2001 From: Robin Kertels Date: Sat, 8 Apr 2023 15:55:50 +0200 Subject: [PATCH 62/72] Android: Fix various issues with the DocumentProvider Fixes copying & deleting folders and copy conflict handling. --- .../dolphinemu/features/DocumentProvider.kt | 80 ++++++------------- 1 file changed, 25 insertions(+), 55 deletions(-) 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 85fee36a18..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,7 +54,6 @@ 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 { @@ -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,52 +124,36 @@ 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) { @@ -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 } } From a5d06fde4b597d93750ba29bc2db83401fe431f7 Mon Sep 17 00:00:00 2001 From: get <45425365+Minty-Meeo@users.noreply.github.com> Date: Fri, 14 Apr 2023 23:55:53 -0500 Subject: [PATCH 63/72] Embrace nullptr over NULL and 0 --- Source/Core/Common/GL/GLInterface/GLX.cpp | 6 ++++-- Source/Core/Common/MemoryUtil.cpp | 2 +- Source/Core/Core/IOS/USB/USB_HID/HIDv4.cpp | 2 +- Source/Core/Core/PowerPC/GDBStub.cpp | 2 +- Source/Core/DolphinNoGUI/PlatformWin32.cpp | 8 ++++---- Source/Core/DolphinQt/QtUtils/FlowLayout.cpp | 4 ++-- Source/Core/DolphinQt/QtUtils/WinIconHelper.cpp | 2 +- Source/Core/DolphinQt/Settings/GameCubePane.cpp | 4 ++-- Source/Core/DolphinQt/ToolBar.cpp | 4 ++-- Source/Core/UICommon/Disassembler.cpp | 3 ++- Source/Core/UICommon/ResourcePack/ResourcePack.cpp | 4 ++-- Source/Core/VideoBackends/D3D12/DX12Context.cpp | 2 +- Source/Core/VideoBackends/OGL/OGLTexture.cpp | 10 +++++----- Source/Core/VideoBackends/OGL/OGLTexture.h | 2 +- Source/Core/WinUpdater/Main.cpp | 2 +- Source/Core/WinUpdater/WinUI.cpp | 12 ++++++------ 16 files changed, 36 insertions(+), 33 deletions(-) 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/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/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/PowerPC/GDBStub.cpp b/Source/Core/Core/PowerPC/GDBStub.cpp index 99cdae0ce0..d88d6a06b0 100644 --- a/Source/Core/Core/PowerPC/GDBStub.cpp +++ b/Source/Core/Core/PowerPC/GDBStub.cpp @@ -1052,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/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/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/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/ToolBar.cpp b/Source/Core/DolphinQt/ToolBar.cpp index 49f384848d..b50e48bf9e 100644 --- a/Source/Core/DolphinQt/ToolBar.cpp +++ b/Source/Core/DolphinQt/ToolBar.cpp @@ -154,14 +154,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("Play")); m_pause_play_action->setIcon(Resources::GetScaledThemeIcon("play")); connect(m_pause_play_action, &QAction::triggered, this, &ToolBar::PlayPressed); 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/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/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/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/WinUpdater/Main.cpp b/Source/Core/WinUpdater/Main.cpp index 6b7fd801ef..66fc521671 100644 --- a/Source/Core/WinUpdater/Main.cpp +++ b/Source/Core/WinUpdater/Main.cpp @@ -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; From c0b6e9e69cd7a0f5519824b5f24ec232d43590a7 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Mon, 17 Apr 2023 23:11:26 -0700 Subject: [PATCH 64/72] Treat --debugger command line as a temporary setting Before, Settings::SetDebugModeEnabled was used; this calls SetBaseOrCurrent() which will usually permanently change the base configuration setting for the debugger to true. Thus, the debugger would remain active even if the --debugger command line option was removed. Now, it remains active only for the current run, like other command-line options. Note that SetBaseOrCurrent is also used by the "Show Debugging UI" option under Options -> Interface; this means that if the debugger is turned off (or off and then back on) by the user while --debugger is specified, this will be reset to whatever the base configuration had when Dolphin is closed and reopened. This behavior is consistent with the rest of the UI. To my understanding, the --debugger option is something from 5.0 stable/DolphinWx where there was no way to toggle the debug UI in the settings (and the command-line option was the only way of enabling it). It's less useful nowadays. --- Source/Core/DolphinQt/Main.cpp | 2 -- Source/Core/UICommon/CommandLineParse.cpp | 7 +++++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Source/Core/DolphinQt/Main.cpp b/Source/Core/DolphinQt/Main.cpp index 317d12fefa..4b01bdcc27 100644 --- a/Source/Core/DolphinQt/Main.cpp +++ b/Source/Core/DolphinQt/Main.cpp @@ -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/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) From 801fa8e905c9ff73c993c940e3e7966e55efc4cb Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Mon, 17 Apr 2023 23:18:42 -0700 Subject: [PATCH 65/72] Only force-show the code widget when first enabling the debugger Before, any call of Settings::SetDebugModeEnabled(true) would show it. This means that if the debugging UI is enabled, but the user manually closed the code widget, then toggling any option on the interface pane (such as "Pause on Focus Loss") would cause the code widget to reappear. Additionally, closing and reopening dolphin did not call SetDebugModeEnabled, so the code widget did not reappear in that case (it only appeared after touching the interface pane). This is a bit silly, so now only enabling the debugger does it. This also somewhat resolves an inconsistency introduced by the previous commit: prior to it, --debugger would call SetDebugModeEnabled(true) and thus show the code pane; after these commits, it does not, as it acts like a config change. This is a behavior difference, but not a particularly important one. --- Source/Core/DolphinQt/Settings.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From a4e1e23c344718fc1f42f820de1af3046fa2aa9e Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Tue, 18 Apr 2023 11:01:11 +0200 Subject: [PATCH 66/72] AchievementManager: Fix crash when launching non-disc game. --- Source/Core/Core/AchievementManager.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Source/Core/Core/AchievementManager.cpp b/Source/Core/Core/AchievementManager.cpp index a566ae6a63..49457e431a 100644 --- a/Source/Core/Core/AchievementManager.cpp +++ b/Source/Core/Core/AchievementManager.cpp @@ -67,12 +67,13 @@ void AchievementManager::LoadGameByFilenameAsync(const std::string& iso_path, std::unique_ptr volume; }; rc_hash_filereader volume_reader{ - .open = - [](const char* path_utf8) { - auto state = std::make_unique(); - state->volume = DiscIO::CreateVolume(path_utf8); - return reinterpret_cast(state.release()); - }, + .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) @@ -111,7 +112,8 @@ void AchievementManager::LoadGameByFilenameAsync(const std::string& iso_path, .close = [](void* file_handle) { delete reinterpret_cast(file_handle); }}; rc_hash_init_custom_filereader(&volume_reader); std::array game_hash; - rc_hash_generate_from_file(game_hash.data(), RC_CONSOLE_GAMECUBE, iso_path.c_str()); + 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) From b3fad3b41aff029421b5f000d83e6170e0267c62 Mon Sep 17 00:00:00 2001 From: Nayla Date: Thu, 6 Apr 2023 17:37:28 -0400 Subject: [PATCH 67/72] GMPE01, GP5E01, GP6E01, GP7E01, RM8E01: Code Updates --- Data/Sys/GameSettings/GMPE01.ini | 157 ++++++++++++++++++++++--- Data/Sys/GameSettings/GP5E01.ini | 194 ++++++++++++++++++++----------- Data/Sys/GameSettings/GP6E01.ini | 106 ++++++++++++++--- Data/Sys/GameSettings/GP7E01.ini | 159 ++++++++++++++++++------- Data/Sys/GameSettings/RM8E01.ini | 22 +++- 5 files changed, 495 insertions(+), 143 deletions(-) diff --git a/Data/Sys/GameSettings/GMPE01.ini b/Data/Sys/GameSettings/GMPE01.ini index b77cbb6231..cc780d9e26 100644 --- a/Data/Sys/GameSettings/GMPE01.ini +++ b/Data/Sys/GameSettings/GMPE01.ini @@ -167,7 +167,7 @@ $QOL - Rumble Always Off [gamemasterplc] 0018FDDC 00000000 *Rumble is always disabled -$QOL - Show Controller Port Number of Who Paused in Mini-Games [gamemasterplc] +$QOL - Show Controller Port Number of Who Paused [gamemasterplc] c203e9b4 00000002 807f0050 906d0000 38600000 00000000 @@ -184,6 +184,14 @@ c2031b88 0000000c 3ce08000 60e7aff4 7ce903a6 4e800421 57a0083c 00000000 +C20B1184 00000007 +88CD8488 38C60001 +C02281F0 38600138 +38800010 3CA08012 +60A5DB53 3CE08000 +60E7AFF4 7CE903A6 +4E800421 880D8488 +60000000 00000000 *Check which player is pausing during minigames. $QOL - Unlock Everything [gamemasterplc] @@ -266,7 +274,7 @@ $Extra - Disable Music 041d3d1c 00000001 *Disables all in-game music. -$Mechanics - Battle Games Always Worth 20 Coins [Nora] +$Mechanics - Battle Games Always Worth 20 Coins [Nayla] 001D5DE0 00040032 $Mechanics - Double the Amount of Turns [Airsola] @@ -310,6 +318,26 @@ $Mechanics - Free Stars [gamemasterplc] 04084720 38800000 *Stars cost nothing instead of the usual 20 coins. +$Mechanics - Gain 0 Coins on Blue Spaces +0407FD74 60000000 +0407FD78 3BC00000 + +$Mechanics - Gain 5 Coins on Blue Spaces +0407FD74 60000000 +0407FD78 3BC00005 + +$Mechanics - Gain 10 Coins on Blue Spaces +0407FD74 60000000 +0407FD78 3BC0000A + +$Mechanics - Gain 20 Coins on Blue Spaces +0407FD74 60000000 +0407FD78 3BC00014 + +$Mechanics - Gain 40 Coins on Blue Spaces +0407FD74 60000000 +0407FD78 3BC00028 + $Mechanics - Item Deletion [Rain] c208d424 00000002 987d0001 3c608000 @@ -349,25 +377,37 @@ c208a07c 0000001f *Item Deletion is now a thing. *Press B to view your items, then delete the item with R. -$Mechanics - Lose 0 Coins On Red Spaces [Nora] +$Mechanics - Lose 0 Coins On Red Spaces [Nayla] 0407FD74 60000000 0407FD78 3BC00000 -$Mechanics - Lose 20 Coins On Red Spaces [Nora] +$Mechanics - Lose 5 Coins On Red Spaces [Nayla] 0407FD74 60000000 -0407FD78 3BC00014 +0407FD78 3BC0FFFB -$Mechanics - Lottery 3rd Place Prize is Gaddlight or Warp Pipe [Nora] +$Mechanics - Lose 10 Coins On Red Spaces [Nayla] +0407FD74 60000000 +0407FD78 3BC0FFF6 + +$Mechanics - Lose 20 Coins On Red Spaces [Nayla] +0407FD74 60000000 +0407FD78 3BC0FFEC + +$Mechanics - Lose 40 Coins On Red Spaces [Nayla] +0407FD74 60000000 +0407FD78 3BC0FFD8 + +$Mechanics - Lottery 3rd Place Prize is Gaddlight or Warp Pipe [Nayla] 021D5678 00000805 -$Mechanics - Lottery 3rd Place Prize is Magic Lamp or Boo's Crystal Ball [Nora] +$Mechanics - Lottery 3rd Place Prize is Magic Lamp or Boo's Crystal Ball [Nayla] 021D5678 00000BOC -$Mechanics - Lottery Costs 0 Coins [Nora] +$Mechanics - Lottery Costs 0 Coins [Nayla] 0407BD20 2C1E0000 *Makes the lottery cost nothing instead of the usual 5 coins. -$Mechanics - Lottery Costs 10 Coins [Nora] +$Mechanics - Lottery Costs 10 Coins [Nayla] 0407BD20 2C1E000A *Makes the lottery cost nothing instead of the usual 5 coins. @@ -387,6 +427,90 @@ $Mechanics - Mini Status Rolls 1-10 [gamemasterplc] 04085d74 3800000a *Mini Mushroom rolls a 1-10 dice instead of a 1-5 dice. +$Mechanics - Random Items on Mushroom Spaces [Rain] +C2083878 00000010 +3C608005 6063FB90 +7C6903A6 4E800421 +4800000D 3FB55555 +55555553 7C6802A6 +C8430000 38600000 +38800000 C00287F4 +2C03000C 41820018 +FC010040 40800010 +EC21102A 38630001 +4BFFFFE8 3C80817F +6084FFF0 90640000 +2C030008 41800008 +38630001 3C800007 +6084006D 7C632214 +38800000 38A00000 +60000000 00000000 +C2083028 0000003D +48000195 0B596F75 +10676F74 1061101E +054D696E 69104D75 +7368726F 6F6D1E08 +85FF000B 596F7510 +676F7410 61101E05 +4D656761 104D7573 +68726F6F 6D1E0885 +FF000B59 6F751067 +6F741061 101E0553 +75706572 104D696E +69104D75 7368726F +6F6D1E08 85FF000B +596F7510 676F7410 +61101E05 53757065 +72104D65 6761104D +75736872 6F6F6D1E +0885FF00 0B596F75 +10676F74 1061101E +054D696E 69104D65 +67611048 616D6D65 +721E0885 FF000B59 +6F751067 6F741061 +101E0557 61727010 +50697065 1E0885FF +000B596F 7510676F +74106110 1E055377 +61701043 6172641E +0885FF00 0B596F75 +10676F74 1061101E +05537061 726B7910 +53746963 6B65721E +0885FF00 0B596F75 +10676F74 1061101E +05476164 646C6967 +68741E08 85FF000B +596F7510 676F7410 +61101E05 43686F6D +70104361 6C6C1E08 +85FF000B 596F7510 +676F7410 61101E05 +426F7773 65721053 +7569741E 0885FF00 +0B596F75 10676F74 +1061101E 04437279 +7374616C 1042616C +6C1E0885 FF000B59 +6F751067 6F741061 +101E074D 61676963 +104C616D 701E0885 +FF000000 7C6802A6 +3C80817F 6084FFF0 +80840000 38A00000 +38C00000 7CE518AE +2C070000 40A20020 +7C062000 41820020 +7C632A14 38630001 +38C60001 38A00000 +4BFFFFDC 38A50001 +4BFFFFD4 7C641B78 +38600000 00000000 +C2083CF0 00000002 +3C80817F 6084FFF0 +80840000 00000000 + $Minigame: Bowser's Bigger Blast - Infinite Time [gamemasterplc] 20431174 3803FFFF 04431174 38030000 @@ -428,6 +552,13 @@ A0A40000 7CA00734 38600000 00000000 *Increases the limit from 160 to 300 Thwomps per player in the minigame Dominiation +$Minigame: Three Throw - All Hoops Empty [gamemasterplc] +20434274 3800000A +04434260 38800000 +0443427C 38A00000 +0443425C 60000000 +E2000001 80008000 + $Minigame: Take a Breather - Mash Only L [gamemasterplc] 20420834 408209b8 04420818 38a00000 @@ -435,17 +566,17 @@ $Minigame: Take a Breather - Mash Only L [gamemasterplc] e2000001 80008000 *Mash just L in the minigame Take a Breather. -$Minigame Replacement - Bowser's Bigger Blast ➜ Chain Chomp Fever [Nora] +$Minigame Replacement - Bowser's Bigger Blast ➜ Chain Chomp Fever [Nayla] 2818fd2c 00000027 0218fd2c 00000025 e2000001 80008000 -$Minigame Replacement - Dungeon Duos ➜ The Great Deflate [Nora] +$Minigame Replacement - Dungeon Duos ➜ The Great Deflate [Nayla] 2818fd2c 0000001F 0218fd2c 00000018 e2000001 80008000 -$Minigame Replacement - Three Throw ➜ Mr. Blizzard's Brigade [Nora] +$Minigame Replacement - Three Throw ➜ Mr. Blizzard's Brigade [Nayla] 2818fd2c 00000009 0218fd2c 0000000B -e2000001 80008000 +e2000001 80008000 \ No newline at end of file diff --git a/Data/Sys/GameSettings/GP5E01.ini b/Data/Sys/GameSettings/GP5E01.ini index 256ae9d2b8..3cb00f0062 100644 --- a/Data/Sys/GameSettings/GP5E01.ini +++ b/Data/Sys/GameSettings/GP5E01.ini @@ -213,7 +213,7 @@ $P2 No Red Spaces [Datel] 0022A18D 00000000 $P2 Max Capsule Spaces [Datel] -044E335E 08000000 +044E335E 08000000 08224AF4 00000042 0022A18E 000000FF @@ -423,7 +423,7 @@ $Press L+X: Player Stops Moving [Datel] 044E338C 08000000 8A2885FA 00004440 0022A07A 00000001 -0022A182 00000001 +0022A182 00000001 0022A28A 00000001 0022A392 00000001 00000000 40000000 @@ -491,6 +491,14 @@ c2096910 00000002 a9010014 39200002 7d084fd6 00000000 0409696C 7D150E70 +204562EC 2C1F0082 +044562E8 3BFF0002 +04460AF0 40000000 +04456CE8 C0028008 +04456E30 C0028008 +04456F08 C0028008 +0445650C 3BFF0004 +E2000001 80008000 *Board animations happen faster. $QOL - Increased Capsule Throwing Speed [gamemasterplc] @@ -514,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 @@ -531,6 +539,13 @@ C20396A8 0000000C 3CE08000 60E7B468 7CE903A6 4E800421 57A0083C 00000000 +C20BCAA0 00000006 +38DF0001 C0228218 +38600138 38800010 +3CA0801B 60A5AED0 +3CE08000 60E7B468 +7CE903A6 4E800421 +57E0083C 00000000 *Check which player is pausing during minigames. $QOL - Unlock Everything @@ -544,12 +559,12 @@ $QOL - Unlock Everything 04472838 3880FFFF 0446BFCC 38C0FFFF E2000001 80008000 -F6000002 80008180 -5460D808 54640FFE -7C040050 5400283E -14000020 3C80FFFF -14000024 6084FFFF -E0000000 80008000 +F6000002 80008180 +5460D808 54640FFE +7C040050 5400283E +14000020 3C80FFFF +14000024 6084FFFF +E0000000 80008000 *Unlocks Everything in the game. $Board: Bowser Nightmare - Bowser does not Steal Coins [gamemasterplc] @@ -576,10 +591,10 @@ E2000001 80008000 $Board: Pirate Dream - Free Thwomps & Whomps [gamemasterplc] 0412811C 4800002C 04128210 38800000 -F6000001 80008180 -4080002C 386003A0 -14000000 4800002C -140000C0 38800000 +F6000001 80008180 +4080002C 386003A0 +14000000 4800002C +140000C0 38800000 E0000000 80008000 *Thwomp and Whomp are now free to pass in the board Pirate Dream. @@ -611,6 +626,9 @@ $Mechanics - Battle Minigames Don't Affect Mini-Game Star [gamemasterplc] e2000001 80008000 *Battle Minigames do not count towards the Mini-Game Star. +$Mechanics - Capsules Can Be Thrown Everywhere [gamemasterplc] +040C56C0 38A0007F + $Mechanics - Disable Capsules [gamemasterplc] F6000001 80008180 3BC50005 887E0000 @@ -644,6 +662,21 @@ f6000001 80008180 e0000000 80008000 *Stars cost nothing instead of the usual 20 coins. +$Mechanics - Gain 0 Coin on Blue Spaces [Nayla] +040A9F5C 38800000 + +$Mechanics - Gain 5 Coins on Blue Spaces [Nayla] +040A9F5C 38800005 + +$Mechanics - Gain 10 Coins on Blue Spaces [Nayla] +040A9F5C 3880000A + +$Mechanics - Gain 20 Coins on Blue Spaces [Nayla] +040A9F5C 38800014 + +$Mechanics - Gain 40 Coins on Blue Spaces [Nayla] +040A9F5C 38800028 + $Mechanics - Improved Item RNG [gamemasterplc] C20C8FA0 0000001B 9421FFF0 7C0802A6 @@ -676,68 +709,84 @@ 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 is x3 Coins on Spaces [gamemasterplc] -20288860 00000076 -045152BC 00000001 -E2100000 80008000 -20288860 00000078 -044FE3BC 00000001 -E2000001 80008000 +$Mechanics: "Last 5 Turns" Event - Happens on the First Turn [Nayla] +0480CB88 2C040001 +0408CB8C 41800048 + +$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 [gamemasterplc] -20288860 00000076 -045152BC 00000003 -E2100000 80008000 -20288860 00000078 -044FE3BC 00000003 -E2000001 80008000 +$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 [gamemasterplc] -20288860 00000076 -045152BC 00000001 -E2100000 80008000 -20288860 00000078 -044FE3BC 00000001 -E2000001 80008000 +$Mechanics: "Last 5 Turns" Event - is Capsule Spaces on Every Space [Nayla] +040FB87C 38A00001 +040FB8EC 3A600001 *Last 5 Turns Event forces all spaces to Have Capsule Events. -$Mechanics - Last 5 Turns is Disabled [gamemasterplc] -F6000002 80008180 -88030005 7C040050 -2C000005 4080000C -1400000C 4800000C -E0000000 80008000 +$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 [gamemasterplc] -20288860 00000076 -045152BC 00000002 -E2100000 80008000 -20288860 00000078 -044FE3BC 00000002 -E2000001 80008000 +$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. -$Mechanics - Lose 0 Coins On Red Spaces [Nora] +$Mechanics - Lose 0 Coins On Red Spaces [Nayla] 040AA160 38800000 -$Mechanics - Lose 20 Coins On Red Spaces [Nora] +$Mechanics - Lose 5 Coins On Red Spaces [Nayla] +040AA160 3880FFFB + +$Mechanics - Lose 10 Coins On Red Spaces [Nayla] +040AA160 3880FFF6 + +$Mechanics - Lose 20 Coins On Red Spaces [Nayla] 040AA160 3880FFEC +$Mechanics - Lose 40 Coins On Red Spaces [Nayla] +040AA160 3880FFD8 + $Mechanics – Obtain Capsules on Final Turn [gamemasterplc] -F6000001 80008180 -7C040040 40820024 -14000004 48000024 +F6000001 80008180 +7C040040 40820024 +14000004 48000024 E0000000 80008000 *Miracles can really happen -$Mechanics - Same Space Duels Always Happen [Nora] -04094740 60000000 -*Duels never happen if you are on the same space. +$Mechanics - P1 Picks Minigames [gamemasterplc] +C211D0E4 0000000F +ABED862C 73FA0008 +2C1A0008 4082001C +A86D8CD4 3863FFFF +7C03EBD6 7C00E9D6 +7C001850 B00D8CD4 +73FA0004 2C1A0004 +4082001C A86D8CD4 +38630001 7C03EBD6 +7C00E9D6 7C001850 +B00D8CD4 AAAD8CD4 +73FA0100 2C1A0000 +40820018 3C608000 +6063D400 7C6903A6 +4E800421 4BFFFF94 +60000000 00000000 +04005BFC 60000000 +04005C24 60000000 +0411D0E8 48000058 +0411D0E0 60000000 +*Use D-Pad -$Mechanics - Same Space Duels Don't Happen [Nora] +$Mechanics - Same Space Duels Always Happen [Nayla] +04094740 60000000 +*Duels always happen if you are on the same space + +$Mechanics - Same Space Duels Don't Happen [Nayla] 04094740 48000030 *Duels never happen if you are on the same space. @@ -767,17 +816,17 @@ $Minigame: Curvy Curves - 1 Player is Slower [Airsola] e2000001 00000000 *1 Player is slower in Curvy Curves. -$Minigame: Coney Island - No Slow Down -204763E4 3C608048 -044763E0 38000000 -0447663C 38000000 -E2000001 80008000 +$Minigame: Coney Island - No Slow Down +204763E4 3C608048 +044763E0 38000000 +0447663C 38000000 +E2000001 80008000 *You do not slow down when gathering ice cream. -$Minigame: Flower Shower - All Flowers are worth 3 Points [gamemasterplc] -20459BEC 801F003C -04459BEC 38000003 -E2000001 80008000 +$Minigame: Flower Shower - All Flowers are worth 3 Points [gamemasterplc] +20459BEC 801F003C +04459BEC 38000003 +E2000001 80008000 *This makes the golden flowers the same value as the normal flowers. $Minigame: Ground Pound Down - No Rocks Until End [gamemasterplc] @@ -793,13 +842,18 @@ E2000001 80008000 *Only one lap around in the minigame Later Skater. $Minigame: Leaf Leap - Allow score to go above 180 [gamemasterplc] -20474848 408000FC -04474848 60000000 -E2000001 80008000 +20474848 408000FC +04474848 60000000 +E2000001 80008000 $Minigame: Leaf Leap - Leaves Display Quicker [gamemasterplc] -20474A04 38030001 -04474A04 3800003C +20474A04 38030001 +04474A04 3800003C +E2000001 80008000 + +$Minigame: Heat Stroke - Disable Fake Swing [gamemasterplc] +2047A1DC A3E40000 +0447A200 38600002 E2000001 80008000 $Minigame: Pop Star Piranhas - Halved Time to Pick [Airsola] diff --git a/Data/Sys/GameSettings/GP6E01.ini b/Data/Sys/GameSettings/GP6E01.ini index 47eb810071..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 @@ -525,6 +525,13 @@ C203E1FC 0000000C 3CE08000 60E7C354 7CE903A6 4E800421 57A0083C 00000000 +C2192B1C 00000006 +38DD0001 C02280E0 +38600138 38800010 +3CA08022 60A5ABEF +3CE08000 60E7C354 +7CE903A6 4E800421 +57A0083C 00000000 *Check which player is pausing during minigames. $QOL - Unlock Everything [gamemasterplc] @@ -536,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] @@ -689,6 +702,25 @@ e2000001 00000000 e2000001 00000000 *The return of the classic Coin Star. +$Extra - Change Turn Count on the Fly +06005100 00000064 +3C60802C A083FFD0 +A0630008 3CA08026 +88C55B75 546005EF +41820044 54800673 +4182000C 38C6FFFF +48000010 548006B5 +4182002C 38C60001 +28060063 40810008 +38C00063 88055B74 +7C060040 40800008 +7C060378 98C55B75 +4818CE5C 806D9808 +4818CE38 00000000 +04191F94 4BE7316C +*Hold L and Press A = Decrease Amount of Turns +*Hold R and Press A = Increase Amount of Turns + $Mechanics - Disable Bonus Stars [gamemasterplc] 48000000 804CA084 DE000000 80008180 @@ -750,29 +782,75 @@ C2183590 00000002 E2000001 80008000 *Stars cost nothing instead of the usual 20 coins. -$Mechanics - Last 5 Turns is x3 Coins on Spaces [gamemasterplc] +$Mechanics - Gain 0 Coins on Blue Spaces +0415F1E8 3BC00000 + +$Mechanics - Gain 5 Coins on Blue Spaces +0415F1E8 3BC00005 + +$Mechanics - Gain 10 Coins on Blue Spaces +0415F1E8 3BC0000A + +$Mechanics - Gain 20 Coins on Blue Spaces +0415F1E8 3BC00014 + +$Mechanics - Gain 40 Coins on Blue Spaces +0415F1E8 3BC00028 + +$Mechanics: "Last 5 Turns" Event - Happens on the First Turn [Ralf] +06005170 0000001C +3C608026 88835B74 +88035B75 7C040050 +2C000005 4C800020 +481FEC24 00000000 +0414B6C8 60000000 +0414B704 4BEB9A6D + +$Mechanics: "Last 5 Turns" Event - Happens after Turn 5 [Ralf] +06005170 0000001C +3C608026 88835B74 +88035B75 7C040050 +2C000005 4C800020 +481FEC24 00000006 +0414B6C8 60000000 +0414B704 4BEB9A6D + +$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" Event - is Disabled [Ralf] +0414B6C8 4800007C +*Last 5 Turns event is disabled + $Mechanics - Lose 0 Coins On Red Spaces [Ralf] 0415F278 38800000 +$Mechanics - Lose 5 Coins On Red Spaces [Ralf] +0415F278 3880FFFB + +$Mechanics - Lose 10 Coins On Red Spaces [Ralf] +0415F278 3880FFF6 + $Mechanics - Lose 20 Coins On Red Spaces [Ralf] 0415F278 3880FFEC +$Mechanics - Lose 40 Coins On Red Spaces [Ralf] +0415F278 3880FFD8 + $Mechanics - Obtain Orbs on Last Turn [gamemasterplc] F6000001 80008180 7C040040 4080041C @@ -831,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] @@ -901,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 37ab3225a7..b403f65091 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 @@ -646,6 +646,13 @@ c20402fc 0000000c 3ce08000 60e7c8cc 7ce903a6 4e800421 57a0083c 00000000 +C219965C 00000006 +38DE0001 C02280E0 +38600138 38800010 +3CA08025 60A548EF +3CE08000 60E7C8CC +7CE903A6 4E800421 +57C0083C 00000000 *Check which player is pausing during minigames. $QOL - Unlock Everything [gamemasterplc] @@ -683,6 +690,11 @@ E2000001 80008000 044F0CFC 38600001 044F0D18 38600001 E2000001 80008000 +04235ABC 60000000 +04235B0C 60000000 +04235B90 60000000 +022922F8 0003FFFF +04235B74 60000000 *Unlocks everything in the game. *Permanent once saved! @@ -717,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] @@ -838,19 +850,13 @@ $Extra - Disables Music [Ralf] 0414aaf0 4e800020 *Disables all in-game music. -$Mechanics - Orb Star Becomes Coin Star [Airsola] -204e4ae0 48000210 -044e4a38 48000014 -044e4a6c 38000000 -e2000001 80008000 -204e16b0 a8ca003c -044e16b0 a8ca002c -e2000001 80008000 -204e18d4 a8c3003c -044e18d4 a8c3002c -e2000001 80008000 -*The return of the classic Coin Star. -*Incompatible with Fixed Bonus Star because it implements it. +$Extra - Random Music [gamemasterplc] +C214AB0C 00000004 +38600076 3C808004 +60841DD4 7C8903A6 +4E800421 7C7D1B78 +60000000 00000000 +0414A26C 38600000S $Mechanics - Able To Hold 5 Orbs [Ralf] 041675b8 38600005 @@ -911,7 +917,7 @@ c24e6288 00000006 e2000001 80008000 *Battle Minigames do not count towards the Mini-Game Star. -$Mechanics - Character Spaces Give 10 coins [Ralf] +$Mechanics - Character Spaces Give 10 Coins [Ralf] 041685BC 60000000 041685C0 38800005 @@ -992,6 +998,26 @@ e2000001 80008000 e2000001 80008000 *Stars cost nothing instead of the usual 20 coins. +$Mechanics - Gain 0 Coins on Blue Spaces +04168578 60000000 +0416857C 38800000 + +$Mechanics - Gain 5 Coins on Blue Spaces +04168578 60000000 +0416857C 38800005 + +$Mechanics - Gain 10 Coins on Blue Spaces +04168578 60000000 +0416857C 3880000A + +$Mechanics - Gain 20 Coins on Blue Spaces +04168578 60000000 +0416857C 38800014 + +$Mechanics - Gain 40 Coins on Blue Spaces +04168578 60000000 +0416857C 38800028 + $Mechanics - Gain 5 Coins On Flower Orb Spaces [Ralf] 041C4F30 38A00005 @@ -1013,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 @@ -1024,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 @@ -1045,33 +1066,61 @@ C21D8ED0 00000003 60000000 00000000 *(X) -> 1/2 Coins -$Mechanics - Last 5 Turns Event Is Always x3 Coins on Spaces [gamemasterplc] +$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] +04152070 2C040006 +04152074 4080011C +041521AC 2C040006 +041521B0 41800044 + +$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] +04152074 60000000 +041521B0 48000044 + $Mechanics - Lose 0 Coins On Red Spaces [Ralf] 04168600 60000000 04168604 38800000 +$Mechanics - Lose 5 Coins On Red Spaces [Ralf] +04168600 60000000 +04168604 3880FFFB + +$Mechanics - Lose 10 Coins On Red Spaces [Ralf] +04168600 60000000 +04168604 3880FFF6 + $Mechanics - Lose 20 Coins On Red Spaces [Ralf] 04168600 60000000 04168604 3880FFEC +$Mechanics - Lose 40 Coins On Red Spaces [Ralf] +04168600 60000000 +04168604 3880FFD8 + $Mechanics - Mic Minigames Have A 10% Chance Of Appearing Instead Of 20% [gamemasterplc] 042f7a04 41200000 *Less Mic Minigames and see more standard minigames. @@ -1082,6 +1131,15 @@ $Mechanics - Microphone Always Off [gamemasterplc] 04098fcc 38600000 *Microphone game setting stays off while playing Mario Party 7. +$Mechanics - Orb Star Becomes Coin Star [Airsola] +204e16b0 a8ca003c +044e16b0 a8ca002c +e2000001 80008000 +204e18d4 a8c3003c +044e18d4 a8c3002c +e2000001 80008000 +*The return of the classic Coin Star. + $Mechanics - Orbs Can Only Be Placed On Your Current Space [gamemasterplc] 041e7128 60000000 *Orbs are more aggressively balanced. @@ -1090,14 +1148,19 @@ $Mechanics - Piranha Plant Takes ALL Coins [gamemasterplc] 041AC0DC 38030000 041AC0E8 7C771B78 +$Mechanics - Slow Shroom Orb Rolls 1-3 [gamemasterplc] +0418CCC8 38000003 +0418D1AC 40820020 +*Orb is more balanced. + $Mechanics - Slow Shroom Orb Rolls 1-5 [gamemasterplc] 0418ccc8 38000005 0418d1ac 40820020 *Orb is more balanced. $Mechanics - Stars Cost 40 coins [Ralf] -0418876c 3b800014 -04188774 3b800028 +0418876c 3b800005 +04188774 3b80000A *Only works in Grand Canal and Bowser's Enchanted Inferno $Mechanics - Use Multiple Orbs in the Same Turn [Ralf] @@ -1154,6 +1217,11 @@ $Minigame: La Bomba - Always 4 Bombs [Airsola, Rain] 044e8cf4 00000004 e2000001 80008000 +$Minigame: Jump Man - Player is Slower [gamemasterplc] +204EF0C0 40768000 +044EF0B8 3C430C12 +E2000001 80008000 + $Minigame: Pogo-a-Go-Go - Spin Faster/Less Airtime [Airsola] 202f2f3c 00000026 044eae38 3fe00000 @@ -1172,17 +1240,22 @@ $Minigame: Spinner Cell - Faster Machines [Airsola, Rain] 044ef5d4 41100000 e2000001 80008000 -$Minigame: Target Tag - All Targets Worth 50 Points [gamemasterplc] -204EAC28 80840000 -044EAC28 38800032 -E2000001 80008000 - $Minigame: Spray Anything - Faster Bubbles/Less Cooldown [Airsola, gamemasterplc] 202f2f3c 0000001b 0450bc40 c10a872b 0450bc48 3fa00000 e2000001 80008000 +$Minigame: Target Tag - All Targets Worth 50 Points [gamemasterplc] +204EAC28 80840000 +044EAC28 38800032 +E2000001 80008000 + +$Minigame: Vine Country - DK is Faster [gamemasterplc] +204E5EE8 901F0174 +044E5EE4 3803FFFE +E2000001 80008000 + $Minigame Replacement - Bridge Work ➜ Mad Props 28291558 00000034 02291558 00000032 diff --git a/Data/Sys/GameSettings/RM8E01.ini b/Data/Sys/GameSettings/RM8E01.ini index dae60fb48c..24e0df1de9 100644 --- a/Data/Sys/GameSettings/RM8E01.ini +++ b/Data/Sys/GameSettings/RM8E01.ini @@ -201,7 +201,7 @@ e0000000 80008000 *Taunt during your turn. *Also removes the cap on how fast you can taunt. -$QOL - Increased Text Display [Nora] +$QOL - Increased Text Display [Nayla] 0405DED4 60000000 *Text is displayed instantly. @@ -230,6 +230,22 @@ $Board: Goomba's Booty Boardwalk - Remove Dolphin Shuttles [gamemasterplc] e2000001 80008000 *A long tedious path forms in the board Goomba's Booty Boardwalk. +$Board: Goomba's Booty Boardwalk - Stars Cost 20 Coins [gamepmasterplc] +48000000 800030C8 +DE000000 80008180 +30013078 9421F8B0 +D2013078 00000009 +8083000C 80840070 +38A00067 3CC08023 +1C840118 7CC62214 +38C682F8 A8E60026 +2C070014 40800014 +B0A60010 B0A60012 +B0A60014 4E800020 +38E7FFEC B0E60026 +9421F8B0 00000000 +E0000000 80008000 + $Board: King Boo's Haunted Hideaway - Make the Whomp Toll Free [gamemasterplc] 48000000 800030c8 de000000 80008180 @@ -311,7 +327,7 @@ d210987c 00000005 e0000000 80008000 *Cashzap Candy steals coins rather then destroying. -$Mechanics - Disable Duelo Candy [Nora, Rain, jdaster] +$Mechanics - Disable Duelo Candy [Nayla, Rain, jdaster] c0000000 00000010 3821ffdc 90610010 90810014 90a10018 @@ -365,7 +381,7 @@ e0000000 80008000 *Disables the overpowered Lucky Spaces. *Disables certain happening spaces due to the level of assembly needed for this patch. -$Mechanics - Disable Slogo Candy [Nora, Rain, jdaster] +$Mechanics - Disable Slogo Candy [Nayla, Rain, jdaster] c0000000 00000010 3821ffdc 90610010 90810014 90a10018 From f1ad43afafe72fcad67d5ff39469442a2740213f Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 18 Apr 2023 12:50:31 -0400 Subject: [PATCH 68/72] Common/CommonFuncs: Move interface into Common namespace Gets these functions out of the global namespace. --- Source/Core/Common/CommonFuncs.cpp | 3 +++ Source/Core/Common/CommonFuncs.h | 3 +++ Source/Core/Common/CompatPatches.cpp | 2 +- Source/Core/Common/FileUtil.cpp | 8 ++++---- Source/Core/Core/HW/EXI/BBA/TAPServer_Apple.cpp | 7 ++++--- Source/Core/UICommon/AutoUpdate.cpp | 4 ++-- Source/Core/UpdaterCommon/UpdaterCommon.cpp | 2 +- Source/Core/WinUpdater/Main.cpp | 2 +- 8 files changed, 19 insertions(+), 12 deletions(-) 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/FileUtil.cpp b/Source/Core/Common/FileUtil.cpp index a9e7c35946..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; } @@ -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/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/UICommon/AutoUpdate.cpp b/Source/Core/UICommon/AutoUpdate.cpp index a638ae33a6..e8de74c794 100644 --- a/Source/Core/UICommon/AutoUpdate.cpp +++ b/Source/Core/UICommon/AutoUpdate.cpp @@ -299,13 +299,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/UpdaterCommon/UpdaterCommon.cpp b/Source/Core/UpdaterCommon/UpdaterCommon.cpp index 9dd40c679f..bba12b8f48 100644 --- a/Source/Core/UpdaterCommon/UpdaterCommon.cpp +++ b/Source/Core/UpdaterCommon/UpdaterCommon.cpp @@ -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/WinUpdater/Main.cpp b/Source/Core/WinUpdater/Main.cpp index 6b7fd801ef..11997822e8 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."); From 07ed932a09c43ed02cece0b6e345c38ddb520aa7 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 19 Apr 2023 09:14:36 -0400 Subject: [PATCH 69/72] Common/LinearDiskCache: Move interface into Common namespace Gets the interface out of the global namespace. --- Source/Core/Common/LinearDiskCache.h | 3 +++ Source/Core/VideoBackends/Vulkan/ObjectCache.cpp | 8 ++++---- Source/Core/VideoCommon/ShaderCache.cpp | 10 +++++----- Source/Core/VideoCommon/ShaderCache.h | 10 +++++----- 4 files changed, 17 insertions(+), 14 deletions(-) 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/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/ShaderCache.cpp b/Source/Core/VideoCommon/ShaderCache.cpp index 150f38b307..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); 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> From b4cc1ade020665d0ba8f5c5e40c7f4f1ce90ec38 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 19 Apr 2023 12:25:21 -0400 Subject: [PATCH 70/72] Common/TraversalClient: Use correct deleter with g_MainNetHost Previously this was using the default deleter (which just calls delete on the pointer), which is incorrect, since the ENetHost instance is allocated through ENet's C API, so we need to use its functions to deallocate the host instead. --- Source/Core/Common/ENet.h | 9 ++++++++- Source/Core/Common/TraversalClient.cpp | 14 +++++++------- Source/Core/Common/TraversalClient.h | 3 ++- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Source/Core/Common/ENet.h b/Source/Core/Common/ENet.h index a011e37057..f1791ca41d 100644 --- a/Source/Core/Common/ENet.h +++ b/Source/Core/Common/ENet.h @@ -3,14 +3,21 @@ // #pragma once -#include +#include #include +#include #include "Common/CommonTypes.h" 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); 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(); From 7a78ace6081423c95fe761bbc605b5904e1fdd02 Mon Sep 17 00:00:00 2001 From: Dentomologist Date: Wed, 19 Apr 2023 16:36:04 -0700 Subject: [PATCH 71/72] Qt/Config: Move BalloonTip.h/cpp from Graphics to ToolTipControls BalloonTip.h/cpp are only used from the ToolTipControls folder, so move them there. --- Source/Core/DolphinQt/CMakeLists.txt | 4 ++-- Source/Core/DolphinQt/Config/Graphics/GraphicsBool.cpp | 1 - .../Config/{Graphics => ToolTipControls}/BalloonTip.cpp | 2 +- .../Config/{Graphics => ToolTipControls}/BalloonTip.h | 0 Source/Core/DolphinQt/Config/ToolTipControls/ToolTipWidget.h | 2 +- Source/Core/DolphinQt/DolphinQt.vcxproj | 4 ++-- 6 files changed, 6 insertions(+), 7 deletions(-) rename Source/Core/DolphinQt/Config/{Graphics => ToolTipControls}/BalloonTip.cpp (99%) rename Source/Core/DolphinQt/Config/{Graphics => ToolTipControls}/BalloonTip.h (100%) 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/Graphics/GraphicsBool.cpp b/Source/Core/DolphinQt/Config/Graphics/GraphicsBool.cpp index ceb459c57a..99099496a2 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) 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/DolphinQt.vcxproj b/Source/Core/DolphinQt/DolphinQt.vcxproj index 01280a46a9..596e661219 100644 --- a/Source/Core/DolphinQt/DolphinQt.vcxproj +++ b/Source/Core/DolphinQt/DolphinQt.vcxproj @@ -68,7 +68,6 @@ - @@ -118,6 +117,7 @@ + @@ -268,7 +268,6 @@ - @@ -314,6 +313,7 @@ + From 4174f0063e7ce05ae0eb2f49eed9de677bb46d28 Mon Sep 17 00:00:00 2001 From: Dentomologist Date: Fri, 14 Apr 2023 14:16:23 -0700 Subject: [PATCH 72/72] Qt: Remove unused class GraphicsBoolEx In older versions of Dolphin GraphicsBoolEx was used to create a pair of radio buttons selecting one of Virtual XFB and Real XFB, but this was removed with the introduction of Hybrid XFB in 65cd085f. In the meantime GraphicsRadioInt was introduced to allow for Graphics radio buttons with multiple options, so GraphicsBoolEx is now redundant. --- .../Config/Graphics/GraphicsBool.cpp | 20 ------------------- .../DolphinQt/Config/Graphics/GraphicsBool.h | 14 ------------- 2 files changed, 34 deletions(-) diff --git a/Source/Core/DolphinQt/Config/Graphics/GraphicsBool.cpp b/Source/Core/DolphinQt/Config/Graphics/GraphicsBool.cpp index ceb459c57a..7892714ec9 100644 --- a/Source/Core/DolphinQt/Config/Graphics/GraphicsBool.cpp +++ b/Source/Core/DolphinQt/Config/Graphics/GraphicsBool.cpp @@ -32,23 +32,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; -};