update Cheat files

This commit is contained in:
Nayla Hanegan 2023-04-20 20:32:13 -04:00
parent 9ab8c1e433
commit cbfd634a4b
No known key found for this signature in database
GPG key ID: BAFE9001DA16CFA2
217 changed files with 2263 additions and 1880 deletions

View file

@ -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 <ryan.pavlik@gmail.com> <abiryan@ryand.net>
#
# 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)

View file

@ -6,6 +6,10 @@ cmake_minimum_required(VERSION 3.13)
cmake_policy(SET CMP0079 NEW) # let target_link_libraries() link to a target defined in a different directory
cmake_policy(SET CMP0080 OLD) # allow using BundleUtilities at configure time
if (POLICY CMP0099)
cmake_policy(SET CMP0099 NEW) # Propagate INTERFACE_LINK_OPTIONS from private dependencies, used by MacOS framework builds of SDL
endif()
# Weird chicken-and-egg problem: We can't check the compiler before the project() call, but we have to set the policies before it.
# So we do this in two steps: Set the policies if they exist, then error out afterwards if we end up being MSVC and they don't exist.
if (POLICY CMP0117)
@ -693,7 +697,11 @@ endif()
add_subdirectory(Externals/imgui)
add_subdirectory(Externals/implot)
add_subdirectory(Externals/glslang)
# 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)

View file

@ -499,7 +499,6 @@ a9010014 39200002
04456F08 C0028008
0445650C 3BFF0004
E2000001 80008000
*Board animations happen faster.
$QOL - Increased Capsule Throwing Speed [gamemasterplc]
@ -523,7 +522,7 @@ $QOL - Instant Text Display [gamemasterplc]
0404a560 38000000
*Text is displayed instantly.
$QOL - Show Controller Port Number of Who Paused in Mini-Games [gamemasterplc]
$QOL - Show Controller Port Number of Who Paused [gamemasterplc]
C2040178 00000002
807F0050 906D0000
38600000 00000000
@ -710,30 +709,30 @@ C20C8FA0 0000001B
*Improves the RNG of what items are received.
*Null items can be retrieved. To Dispose of throw on any space.
$Mechanics - Last 5 Turns Happens on the First Turn [Nayla]
$Mechanics: "Last 5 Turns" Event - Happens on the First Turn [Nayla]
0480CB88 2C040001
0408CB8C 41800048
$Mechanics - Last 5 Turns is x3 Coins on Spaces [Nayla]
$Mechanics: "Last 5 Turns" Event - is x3 Coins on Spaces [Nayla]
040FB87C 38A00000
040FB8EC 3A600000
*Last 5 Turns Event is always x3 Coins on Spaces.
$Mechanics - Last 5 Turns is 5 Star Spaces [Nayla]
$Mechanics: "Last 5 Turns" Event - is 5 Star Spaces [Nayla]
040FB87C 38A00003
040FB8EC 3A600003
*Last 5 Turns Event is always 5 Star Spaces.
$Mechanics - Last 5 Turns is Capsule Spaces on Every Space [Nayla]
$Mechanics: "Last 5 Turns" Event - is All Capsule Spaces [Nayla]
040FB87C 38A00001
040FB8EC 3A600001
*Last 5 Turns Event forces all spaces to Have Capsule Events.
$Mechanics - Last 5 Turns is Disabled [Nayla]
$Mechanics: "Last 5 Turns" Event - is Disabled [Nayla]
0408D1F4 41800048
*Last 5 Turns Event never happens.
$Mechanics - Last 5 Turns is Red Spaces are Bowser Spaces [Nayla]
$Mechanics: "Last 5 Turns" Event - is Red Spaces are Bowser Spaces [Nayla]
040FB87C 38A00002
040FB8EC 3A6000012
*Last 5 Turns Event forces Red Spaces to turn into Bowser Spaces.
@ -785,7 +784,7 @@ B00D8CD4 AAAD8CD4
$Mechanics - Same Space Duels Always Happen [Nayla]
04094740 60000000
*Duels never happen if you are on the same space.
*Duels always happen if you are on the same space
$Mechanics - Same Space Duels Don't Happen [Nayla]
04094740 48000030

View file

@ -508,7 +508,7 @@ $QOL - Instant Text Display [Celerizer]
0404f51c 38000000
*Text is displayed instantly.
$QOL - Show Controller Port Number of Who Paused in Mini-Games [Celerizer]
$QOL - Show Controller Port Number of Who Paused [Celerizer]
C20456D4 00000002
807F0050 906D0000
38600000 00000000
@ -543,6 +543,12 @@ F6000001 80008180
80A405A0 38800001
14000000 38A0FFFF
E0000000 80008000
F6000002 80008180
5460D808 54640FFE
7C040050 5400283E
14000020 3C80FFFF
14000024 6084FFFF
E0000000 80008000
*Unlocks Everything in the game.
$Board - Faire Square: Free Whomps [gamemasterplc]
@ -791,7 +797,7 @@ $Mechanics - Gain 20 Coins on Blue Spaces
$Mechanics - Gain 40 Coins on Blue Spaces
0415F1E8 3BC00028
$Mechanics - Last 5 Turns Happens on the First Turn [Ralf]
$Mechanics: "Last 5 Turns" Event - Happens on the First Turn [Ralf]
06005170 0000001C
3C608026 88835B74
88035B75 7C040050
@ -800,7 +806,7 @@ $Mechanics - Last 5 Turns Happens on the First Turn [Ralf]
0414B6C8 60000000
0414B704 4BEB9A6D
$Mechanics - Last 5 Turns Happens after Turn 5 [Ralf]
$Mechanics: "Last 5 Turns" Event - Happens after Turn 5 [Ralf]
06005170 0000001C
3C608026 88835B74
88035B75 7C040050
@ -809,24 +815,24 @@ $Mechanics - Last 5 Turns Happens after Turn 5 [Ralf]
0414B6C8 60000000
0414B704 4BEB9A6D
$Mechanics - Last 5 Turns is x3 Coins on Spaces [gamemasterplc]
$Mechanics: "Last 5 Turns" Event - is x3 Coins on Spaces [gamemasterplc]
04202314 38000000
*Last 5 Turns Event is always x3 Coins on spaces.
$Mechanics - Last 5 Turns is 40 Coin Bonus [gamemasterplc]
$Mechanics: "Last 5 Turns" Event - is 40 Coin Bonus [gamemasterplc]
04202314 38000001
*Last 5 Turns Event is always a 40 coin bonus for last place.
$Mechanics - Last 5 Turns is 5 Character Spaces [gamemasterplc]
$Mechanics: "Last 5 Turns" Event - is 5 Character Spaces [gamemasterplc]
04202314 38000002 [gamemasterplc]
*Last 5 Turns Event is always 5 extra character spaces for last place.
$Mechanics - Last 5 Turns is Bowser Revolution [gamemasterplc]
$Mechanics: "Last 5 Turns" Event - is Bowser Revolution [gamemasterplc]
04202314 38000003
*Last 5 Turns Event is always a Bowser Revolution.
*This makes everyones coins equal.
$Mechanics - Last 5 Turns is Disabled [Ralf]
$Mechanics: "Last 5 Turns" Event - is Disabled [Ralf]
0414B6C8 4800007C
*Last 5 Turns event is disabled

View file

@ -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
@ -1039,10 +1039,6 @@ $Mechanics - Hammer Bro Orb Steals 20 Coins [Ralf]
*Hammer Bro steals 20 coins instead of 10 when landing on his space.
$Mechanics - Happening Star Becomes Star Star [Airsola]
204e4ae0 48000210
044e4a38 48000014
044e4a6c 38000000
e2000001 80008000
204e16ec 8903001f
044e16ec 8903003b
e2000001 80008000
@ -1050,7 +1046,6 @@ e2000001 80008000
044e1a0c 8903003b
e2000001 80008000
*The Happening Star will become a bonus star awarded to the player who held the highest amount of stars at any point of the game. Recommended only for Windmillville, or Pyramid Park.
*Incompatible with Fixed Bonus Star because it implements it.
$Mechanics - Improved Duel Results [Airsola]
c21d8ed0 00000007
@ -1071,38 +1066,38 @@ C21D8ED0 00000003
60000000 00000000
*(X) -> 1/2 Coins
$Mechanics - Last 5 Turns Event Happens on the First Turn [Ralf]
$Mechanics: "Last 5 Turns" Event - Happens on the First Turn [Ralf]
04152070 2C040001
04152074 4080011C
041521AC 2C040001
041521B0 41800044
$Mechanics - Last 5 Turns Event Happens after Turn 5 [Ralf]
$Mechanics: "Last 5 Turns" Event - Happens after Turn 5 [Ralf]
04152070 2C040006
04152074 4080011C
041521AC 2C040006
041521B0 41800044
$Mechanics - Last 5 Turns Event Is Always x3 Coins on Spaces [gamemasterplc]
$Mechanics: "Last 5 Turns" Event - is x3 Coins on Spaces [gamemasterplc]
042311A8 38000000
$Mechanics - Last 5 Turns Event Is Always 10 More Koopa Kid Spaces [gamemasterplc]
$Mechanics: "Last 5 Turns" Event - is Always 10 More Koopa Kid Spaces [gamemasterplc]
042311A8 38000001
$Mechanics - Last 5 Turns Event Is Always 40 Coin Bonus [gamemasterplc]
$Mechanics: "Last 5 Turns" Event - is Always 40 Coin Bonus [gamemasterplc]
042311A8 38000002
$Mechanics - Last 5 Turns Event Is Always Stars are 10 Coins [gamemasterplc]
$Mechanics: "Last 5 Turns" Event - is Always Stars are 10 Coins [gamemasterplc]
042311A8 38000003
$Mechanics - Last 5 Turns Event Is Always Red Spaces are Bowser Spaces [gamemasterplc]
$Mechanics: "Last 5 Turns" Event - is Always Red Spaces are Bowser Spaces [gamemasterplc]
042311A8 38000004
$Mechanics - Last 5 Turns Event Is Always Chain Chomp Ride for 5 Coins (Pyramid Park) [gamemasterplc]
$Mechanics: "Last 5 Turns" Event - is Always Chain Chomp Ride for 5 Coins (Pyramid Park) [gamemasterplc]
042311A8 38000005
*Only use on Pyramid Park
$Mechanics - Last 5 Turns Event Is Disabled [Ralf]
$Mechanics: "Last 5 Turns" Event - is Disabled [Ralf]
04152074 60000000
041521B0 48000044
@ -1137,10 +1132,6 @@ $Mechanics - Microphone Always Off [gamemasterplc]
*Microphone game setting stays off while playing Mario Party 7.
$Mechanics - Orb Star Becomes Coin Star [Airsola]
204e4ae0 48000210
044e4a38 48000014
044e4a6c 38000000
e2000001 80008000
204e16b0 a8ca003c
044e16b0 a8ca002c
e2000001 80008000
@ -1148,8 +1139,6 @@ e2000001 80008000
044e18d4 a8c3002c
e2000001 80008000
*The return of the classic Coin Star.
*Incompatible with Fixed Bonus Star because it implements it.
$Mechanics - Orbs Can Only Be Placed On Your Current Space [gamemasterplc]
041e7128 60000000
@ -1162,7 +1151,7 @@ $Mechanics - Piranha Plant Takes ALL Coins [gamemasterplc]
$Mechanics - Slow Shroom Orb Rolls 1-3 [gamemasterplc]
0418CCC8 38000003
0418D1AC 40820020
*Orb is morew balanced.
*Orb is more balanced.
$Mechanics - Slow Shroom Orb Rolls 1-5 [gamemasterplc]
0418ccc8 38000005
@ -1172,7 +1161,6 @@ $Mechanics - Slow Shroom Orb Rolls 1-5 [gamemasterplc]
$Mechanics - Stars Cost 40 coins [Ralf]
0418876c 3b800005
04188774 3b80000A
*Only works in Grand Canal and Bowser's Enchanted Inferno
$Mechanics - Use Multiple Orbs in the Same Turn [Ralf]
@ -1229,7 +1217,7 @@ $Minigame: La Bomba - Always 4 Bombs [Airsola, Rain]
044e8cf4 00000004
e2000001 80008000
$Minigame: Jump Man - Player is Slower
$Minigame: Jump Man - Player is Slower [gamemasterplc]
204EF0C0 40768000
044EF0B8 3C430C12
E2000001 80008000
@ -1263,7 +1251,7 @@ $Minigame: Target Tag - All Targets Worth 50 Points [gamemasterplc]
044EAC28 38800032
E2000001 80008000
$Minigame: Vine Country - DK is Faster
$Minigame: Vine Country - DK is Faster [gamemasterplc]
204E5EE8 901F0174
044E5EE4 3803FFFE
E2000001 80008000

View file

@ -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

2
Externals/SDL/SDL vendored

@ -1 +1 @@
Subproject commit f741adc86c8f5e7fc5c1863cf0d5e08b899d6209
Subproject commit ac13ca9ab691e13e8eebe9684740ddcb0d716203

@ -1 +1 @@
Subproject commit c5304a61bcf256ae80fcd1c8f64ad9646aaea757
Subproject commit d9e990e6d13527532b7e2bb23164a1f3b7f33bb5

View file

@ -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

View file

@ -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

View file

@ -31,7 +31,7 @@
<application
android:name=".DolphinApplication"
android:label="@string/app_name"
android:label="@string/app_name_suffixed"
android:icon="@mipmap/ic_launcher"
android:requestLegacyExternalStorage="true"
android:preserveLegacyExternalStorage="true"
@ -97,7 +97,7 @@
<activity
android:name=".activities.CustomFilePickerActivity"
android:exported="false"
android:label="@string/app_name"
android:label="@string/app_name_suffixed"
android:theme="@style/Theme.Dolphin.FilePicker">
<intent-filter>

View file

@ -54,12 +54,11 @@ class DocumentProvider : DocumentsProvider() {
override fun queryRoots(projection: Array<String>?): Cursor {
val result = MatrixCursor(projection ?: DEFAULT_ROOT_PROJECTION)
rootDirectory = rootDirectory ?: DirectoryInitialization.getUserDirectoryPath(context)
rootDirectory ?: return result
result.newRow().apply {
add(DocumentsContract.Root.COLUMN_ROOT_ID, ROOT_ID)
add(DocumentsContract.Root.COLUMN_TITLE, context!!.getString(R.string.app_name))
add(DocumentsContract.Root.COLUMN_TITLE, context!!.getString(R.string.app_name_suffixed))
add(DocumentsContract.Root.COLUMN_ICON, R.drawable.ic_dolphin)
add(
DocumentsContract.Root.COLUMN_FLAGS,
@ -73,7 +72,6 @@ class DocumentProvider : DocumentsProvider() {
override fun queryDocument(documentId: String, projection: Array<String>?): Cursor {
val result = MatrixCursor(projection ?: DEFAULT_DOCUMENT_PROJECTION)
rootDirectory = rootDirectory ?: DirectoryInitialization.getUserDirectoryPath(context)
rootDirectory ?: return result
val file = documentIdToPath(documentId)
appendDocument(file, result)
@ -102,7 +100,9 @@ class DocumentProvider : DocumentsProvider() {
documentId: String,
mode: String,
signal: CancellationSignal?
): ParcelFileDescriptor {
): ParcelFileDescriptor? {
rootDirectory ?: return null
val file = documentIdToPath(documentId)
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.parseMode(mode))
}
@ -111,7 +111,9 @@ class DocumentProvider : DocumentsProvider() {
parentDocumentId: String,
mimeType: String,
displayName: String
): String {
): String? {
rootDirectory ?: return null
val folder = documentIdToPath(parentDocumentId)
val file = findFileNameForNewFile(File(folder, displayName))
if (mimeType == DocumentsContract.Document.MIME_TYPE_DIR) {
@ -122,56 +124,40 @@ class DocumentProvider : DocumentsProvider() {
return pathToDocumentId(file)
}
override fun copyDocument(sourceDocumentId: String, targetParentDocumentId: String): String {
val file = documentIdToPath(sourceDocumentId)
val target = documentIdToPath(targetParentDocumentId)
val copy = copyRecursively(file, File(target, file.name))
return pathToDocumentId(copy)
}
override fun deleteDocument(documentId: String) {
rootDirectory ?: return
override fun removeDocument(documentId: String, parentDocumentId: String) {
val file = documentIdToPath(documentId)
file.deleteRecursively()
}
override fun moveDocument(
sourceDocumentId: String,
sourceParentDocumentId: String,
targetParentDocumentId: String
): String {
val copy = copyDocument(sourceDocumentId, targetParentDocumentId)
val file = documentIdToPath(sourceDocumentId)
file.delete()
return copy
override fun renameDocument(documentId: String, displayName: String): String? {
rootDirectory ?: return null
val file = documentIdToPath(documentId)
val dest = findFileNameForNewFile(File(file.parentFile, displayName))
file.renameTo(dest)
return pathToDocumentId(dest)
}
override fun renameDocument(documentId: String, displayName: String): String {
val file = documentIdToPath(documentId)
file.renameTo(findFileNameForNewFile(File(file.parentFile, displayName)))
return pathToDocumentId(file)
}
override fun isChildDocument(parentDocumentId: String, documentId: String): Boolean {
val file = documentIdToPath(documentId)
val folder = documentIdToPath(parentDocumentId)
return file.relativeToOrNull(folder) != null
}
override fun isChildDocument(parentDocumentId: String, documentId: String): Boolean
= documentId.startsWith(parentDocumentId)
private fun appendDocument(file: File, cursor: MatrixCursor) {
var flags = 0
if (file.isDirectory && file.canWrite()) {
flags = DocumentsContract.Document.FLAG_DIR_SUPPORTS_CREATE
} else if (file.canWrite()) {
flags = DocumentsContract.Document.FLAG_SUPPORTS_WRITE
if (file.canWrite()) {
flags = if (file.isDirectory) {
DocumentsContract.Document.FLAG_DIR_SUPPORTS_CREATE
} else {
DocumentsContract.Document.FLAG_SUPPORTS_WRITE
}
flags = flags or DocumentsContract.Document.FLAG_SUPPORTS_DELETE
flags = flags or DocumentsContract.Document.FLAG_SUPPORTS_REMOVE
flags = flags or DocumentsContract.Document.FLAG_SUPPORTS_MOVE
flags = flags or DocumentsContract.Document.FLAG_SUPPORTS_COPY
flags = flags or DocumentsContract.Document.FLAG_SUPPORTS_RENAME
// The system will handle copy + move for us
}
val name = if (file == rootDirectory) {
context!!.getString(R.string.app_name)
context!!.getString(R.string.app_name_suffixed)
} else {
file.name
}
@ -217,22 +203,6 @@ class DocumentProvider : DocumentsProvider() {
unusedFile = File("$pathWithoutExtension.$i.$extension")
i++
}
return file
}
private fun copyRecursively(src: File, dst: File): File {
val actualDst = findFileNameForNewFile(dst)
if (src.isDirectory) {
actualDst.mkdirs()
val children = src.listFiles()
if (children !== null) {
for (file in children) {
copyRecursively(file, File(actualDst, file.name))
}
}
} else {
src.copyTo(actualDst)
}
return actualDst
return unusedFile
}
}

View file

@ -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.

View file

@ -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<ActionReplay::ARCode> 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);

View file

@ -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<Gecko::GeckoCode> 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);

View file

@ -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<PatchEngine::Patch> 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);

View file

@ -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<IniFile::Section*>(

View file

@ -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(&section);
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);

View file

@ -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)
{

View file

@ -41,8 +41,8 @@ add_library(common
DebugInterface.h
DynamicLibrary.cpp
DynamicLibrary.h
ENetUtil.cpp
ENetUtil.h
ENet.cpp
ENet.h
EnumFormatter.h
EnumMap.h
Event.h
@ -80,7 +80,6 @@ add_library(common
Logging/Log.h
Logging/LogManager.cpp
Logging/LogManager.h
MathUtil.cpp
MathUtil.h
Matrix.cpp
Matrix.h
@ -299,7 +298,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
target_link_libraries(common PUBLIC dl rt)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
if(WIN32)
target_sources(common PRIVATE HRWrap.h HRWrap.cpp)
endif()

View file

@ -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<std::wstring> GetModuleName(void* hInstance)
return name;
}
#endif
} // namespace Common

View file

@ -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<std::wstring> GetModuleName(void* hInstance);
#endif
} // namespace Common

View file

@ -170,7 +170,7 @@ static std::optional<std::wstring> 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)

View file

@ -3,42 +3,45 @@
#include "Common/Crypto/bn.h"
#include <cstddef>
#include <cstdio>
#include <cstring>
#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];

View file

@ -3,13 +3,15 @@
#pragma once
#include <cstddef>
#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);

View file

@ -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;

View file

@ -1,12 +1,12 @@
// Copyright 2015 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "Common/ENetUtil.h"
#include "Common/ENet.h"
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
namespace ENetUtil
namespace Common::ENet
{
void WakeupThread(ENetHost* host)
{
@ -62,4 +62,4 @@ bool SendPacket(ENetPeer* socket, const sf::Packet& packet, u8 channel_id)
return true;
}
} // namespace ENetUtil
} // namespace Common::ENet

View file

@ -3,15 +3,22 @@
//
#pragma once
#include <enet/enet.h>
#include <memory>
#include <SFML/Network/Packet.hpp>
#include <enet/enet.h>
#include "Common/CommonTypes.h"
namespace ENetUtil
namespace Common::ENet
{
struct ENetHostDeleter
{
void operator()(ENetHost* host) const noexcept { enet_host_destroy(host); }
};
using ENetHostPtr = std::unique_ptr<ENetHost, ENetHostDeleter>;
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

View file

@ -358,14 +358,14 @@ u64 GetSize(FILE* f)
const u64 pos = ftello(f);
if (fseeko(f, 0, SEEK_END) != 0)
{
ERROR_LOG_FMT(COMMON, "GetSize: seek failed {}: {}", fmt::ptr(f), LastStrerrorString());
ERROR_LOG_FMT(COMMON, "GetSize: seek failed {}: {}", fmt::ptr(f), Common::LastStrerrorString());
return 0;
}
const u64 size = ftello(f);
if ((size != pos) && (fseeko(f, pos, SEEK_SET) != 0))
{
ERROR_LOG_FMT(COMMON, "GetSize: seek failed {}: {}", fmt::ptr(f), LastStrerrorString());
ERROR_LOG_FMT(COMMON, "GetSize: seek failed {}: {}", fmt::ptr(f), Common::LastStrerrorString());
return 0;
}
@ -379,7 +379,7 @@ bool CreateEmptyFile(const std::string& filename)
if (!File::IOFile(filename, "wb"))
{
ERROR_LOG_FMT(COMMON, "CreateEmptyFile: failed {}: {}", filename, LastStrerrorString());
ERROR_LOG_FMT(COMMON, "CreateEmptyFile: failed {}: {}", filename, Common::LastStrerrorString());
return false;
}
@ -486,7 +486,7 @@ FSTEntry ScanDirectoryTree(std::string directory, bool recursive)
}
else if (cur_depth < prev_depth)
{
while (dir_fsts.size() - 1 != cur_depth)
while (dir_fsts.size() != static_cast<size_t>(cur_depth) + 1u)
{
calc_dir_size(dir_fsts.top());
dir_fsts.pop();
@ -726,7 +726,7 @@ std::string GetBundleDirectory()
std::string GetExePath()
{
#ifdef _WIN32
auto exe_path = GetModuleName(nullptr);
auto exe_path = Common::GetModuleName(nullptr);
if (!exe_path)
return {};
std::error_code error;

View file

@ -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<int, 5> 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());

View file

@ -69,7 +69,7 @@ private:
struct Storage
{
std::mutex m_mutex;
std::recursive_mutex m_mutex;
std::vector<HookImpl*> m_listeners;
};

View file

@ -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<const u8*>(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<s64>(dltotal), static_cast<s64>(dlnow),
static_cast<s64>(ultotal), static_cast<s64>(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

View file

@ -25,8 +25,7 @@ public:
};
// Return false to abort the request
using ProgressCallback =
std::function<bool(double dlnow, double dltotal, double ulnow, double ultotal)>;
using ProgressCallback = std::function<bool(s64 dltotal, s64 dlnow, s64 ultotal, s64 ulnow)>;
explicit HttpRequest(std::chrono::milliseconds timeout_ms = std::chrono::milliseconds{3000},
ProgressCallback callback = nullptr);

View file

@ -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

View file

@ -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

View file

@ -27,6 +27,8 @@
// value_type[value_size] value;
//}
namespace Common
{
template <typename K, typename V>
class LinearDiskCacheReader
{
@ -163,3 +165,4 @@ private:
File::IOFile m_file;
u32 m_num_entries = 0;
};
} // namespace Common

View file

@ -1,12 +0,0 @@
// Copyright 2008 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "Common/MathUtil.h"
#include <numeric>
// Calculate sum of a float list
float MathFloatVectorSum(const std::vector<float>& Vec)
{
return std::accumulate(Vec.begin(), Vec.end(), 0.0f);
}

View file

@ -8,7 +8,6 @@
#include <cmath>
#include <limits>
#include <type_traits>
#include <vector>
#include "Common/CommonTypes.h"
@ -186,12 +185,9 @@ private:
T m_variance{};
};
} // namespace MathUtil
float MathFloatVectorSum(const std::vector<float>&);
// Rounds down. 0 -> undefined
constexpr int IntLog2(u64 val)
{
return 63 - std::countl_zero(val);
}
} // namespace MathUtil

View file

@ -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;

View file

@ -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);
}

View file

@ -304,7 +304,7 @@ int ENET_CALLBACK TraversalClient::InterceptCallback(ENetHost* host, ENetEvent*
}
std::unique_ptr<TraversalClient> g_TraversalClient;
std::unique_ptr<ENetHost> 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
auto host = Common::ENet::ENetHostPtr{enet_host_create(&addr, // address
50, // peerCount
NetPlay::CHANNEL_COUNT, // channelLimit
0, // incomingBandwidth
0); // outgoingBandwidth
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;

View file

@ -11,6 +11,7 @@
#include <enet/enet.h>
#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<TraversalClient> g_TraversalClient;
// the NetHost connected to the TraversalClient.
extern std::unique_ptr<ENetHost> 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();

View file

@ -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

View file

@ -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();

View file

@ -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

View file

@ -1106,6 +1106,7 @@ public:
template <typename FunctionPointer>
void ABI_CallFunctionPR(FunctionPointer func, const void* ptr, X64Reg reg1)
{
if (reg1 != ABI_PARAM2)
MOV(64, R(ABI_PARAM2), R(reg1));
MOV(64, R(ABI_PARAM1), Imm64(reinterpret_cast<u64>(ptr)));
ABI_CallFunction(func);

View file

@ -4,10 +4,17 @@
#ifdef USE_RETRO_ACHIEVEMENTS
#include "Core/AchievementManager.h"
#include <array>
#include <rcheevos/include/rc_hash.h>
#include "Common/HttpRequest.h"
#include "Common/WorkQueueThread.h"
#include "Config/AchievementSettings.h"
#include "Core/Core.h"
#include "DiscIO/Volume.h"
static constexpr bool hardcore_mode_enabled = false;
AchievementManager* AchievementManager::GetInstance()
{
@ -28,49 +35,337 @@ void AchievementManager::Init()
AchievementManager::ResponseType AchievementManager::Login(const std::string& password)
{
if (!m_is_runtime_initialized)
return AchievementManager::ResponseType::MANAGER_NOT_INITIALIZED;
return VerifyCredentials(password);
}
void AchievementManager::LoginAsync(const std::string& password, const LoginCallback& callback)
void AchievementManager::LoginAsync(const std::string& password, const ResponseCallback& callback)
{
if (!m_is_runtime_initialized)
{
callback(AchievementManager::ResponseType::MANAGER_NOT_INITIALIZED);
return;
}
m_queue.EmplaceItem([this, password, callback] { callback(VerifyCredentials(password)); });
}
bool AchievementManager::IsLoggedIn() const
{
return m_login_data.response.succeeded;
return !Config::Get(Config::RA_API_TOKEN).empty();
}
void AchievementManager::LoadGameByFilenameAsync(const std::string& iso_path,
const ResponseCallback& callback)
{
if (!m_is_runtime_initialized)
{
callback(AchievementManager::ResponseType::MANAGER_NOT_INITIALIZED);
return;
}
struct FilereaderState
{
int64_t position = 0;
std::unique_ptr<DiscIO::Volume> volume;
};
rc_hash_filereader volume_reader{
.open = [](const char* path_utf8) -> void* {
auto state = std::make_unique<FilereaderState>();
state->volume = DiscIO::CreateVolume(path_utf8);
if (!state->volume)
return nullptr;
return state.release();
},
.seek =
[](void* file_handle, int64_t offset, int origin) {
switch (origin)
{
case SEEK_SET:
reinterpret_cast<FilereaderState*>(file_handle)->position = offset;
break;
case SEEK_CUR:
reinterpret_cast<FilereaderState*>(file_handle)->position += offset;
break;
case SEEK_END:
// Unused
break;
}
},
.tell =
[](void* file_handle) {
return reinterpret_cast<FilereaderState*>(file_handle)->position;
},
.read =
[](void* file_handle, void* buffer, size_t requested_bytes) {
FilereaderState* filereader_state = reinterpret_cast<FilereaderState*>(file_handle);
bool success = (filereader_state->volume->Read(
filereader_state->position, requested_bytes, reinterpret_cast<u8*>(buffer),
DiscIO::PARTITION_NONE));
if (success)
{
filereader_state->position += requested_bytes;
return requested_bytes;
}
else
{
return static_cast<size_t>(0);
}
},
.close = [](void* file_handle) { delete reinterpret_cast<FilereaderState*>(file_handle); }};
rc_hash_init_custom_filereader(&volume_reader);
std::array<char, HASH_LENGTH> game_hash;
if (!rc_hash_generate_from_file(game_hash.data(), RC_CONSOLE_GAMECUBE, iso_path.c_str()))
return;
m_queue.EmplaceItem([this, callback, game_hash] {
const auto resolve_hash_response = ResolveHash(game_hash);
if (resolve_hash_response != ResponseType::SUCCESS || m_game_id == 0)
{
callback(resolve_hash_response);
return;
}
const auto start_session_response = StartRASession();
if (start_session_response != ResponseType::SUCCESS)
{
callback(start_session_response);
return;
}
const auto fetch_game_data_response = FetchGameData();
m_is_game_loaded = fetch_game_data_response == ResponseType::SUCCESS;
// Claim the lock, then queue the fetch unlock data calls, then initialize the unlock map in
// ActivateDeactiveAchievements. This allows the calls to process while initializing the
// unlock map but then forces them to wait until it's initialized before making modifications to
// it.
{
std::lock_guard lg{m_lock};
LoadUnlockData([](ResponseType r_type) {});
ActivateDeactivateAchievements();
}
ActivateDeactivateLeaderboards();
ActivateDeactivateRichPresence();
callback(fetch_game_data_response);
});
}
void AchievementManager::LoadUnlockData(const ResponseCallback& callback)
{
m_queue.EmplaceItem([this, callback] {
const auto hardcore_unlock_response = FetchUnlockData(true);
if (hardcore_unlock_response != ResponseType::SUCCESS)
{
callback(hardcore_unlock_response);
return;
}
callback(FetchUnlockData(false));
});
}
void AchievementManager::ActivateDeactivateAchievements()
{
bool enabled = Config::Get(Config::RA_ACHIEVEMENTS_ENABLED);
bool unofficial = Config::Get(Config::RA_UNOFFICIAL_ENABLED);
bool encore = Config::Get(Config::RA_ENCORE_ENABLED);
for (u32 ix = 0; ix < m_game_data.num_achievements; ix++)
{
auto iter =
m_unlock_map.insert({m_game_data.achievements[ix].id, UnlockStatus{.game_data_index = ix}});
ActivateDeactivateAchievement(iter.first->first, enabled, unofficial, encore);
}
}
void AchievementManager::ActivateDeactivateLeaderboards()
{
bool leaderboards_enabled = Config::Get(Config::RA_LEADERBOARDS_ENABLED);
for (u32 ix = 0; ix < m_game_data.num_leaderboards; ix++)
{
auto leaderboard = m_game_data.leaderboards[ix];
if (m_is_game_loaded && leaderboards_enabled && hardcore_mode_enabled)
{
rc_runtime_activate_lboard(&m_runtime, leaderboard.id, leaderboard.definition, nullptr, 0);
}
else
{
rc_runtime_deactivate_lboard(&m_runtime, m_game_data.leaderboards[ix].id);
}
}
}
void AchievementManager::ActivateDeactivateRichPresence()
{
rc_runtime_activate_richpresence(
&m_runtime,
(m_is_game_loaded && Config::Get(Config::RA_RICH_PRESENCE_ENABLED)) ?
m_game_data.rich_presence_script :
"",
nullptr, 0);
}
void AchievementManager::CloseGame()
{
m_is_game_loaded = false;
m_game_id = 0;
m_queue.Cancel();
m_unlock_map.clear();
ActivateDeactivateAchievements();
ActivateDeactivateLeaderboards();
ActivateDeactivateRichPresence();
}
void AchievementManager::Logout()
{
CloseGame();
Config::SetBaseOrCurrent(Config::RA_API_TOKEN, "");
rc_api_destroy_login_response(&m_login_data);
m_login_data.response.succeeded = 0;
}
void AchievementManager::Shutdown()
{
CloseGame();
m_is_runtime_initialized = false;
m_queue.Shutdown();
// DON'T log out - keep those credentials for next run.
rc_api_destroy_login_response(&m_login_data);
m_login_data.response.succeeded = 0;
rc_runtime_destroy(&m_runtime);
}
AchievementManager::ResponseType AchievementManager::VerifyCredentials(const std::string& password)
{
rc_api_login_response_t login_data{};
std::string username = Config::Get(Config::RA_USERNAME);
std::string api_token = Config::Get(Config::RA_API_TOKEN);
rc_api_login_request_t login_request = {
.username = username.c_str(), .api_token = api_token.c_str(), .password = password.c_str()};
ResponseType r_type = Request<rc_api_login_request_t, rc_api_login_response_t>(
login_request, &m_login_data, rc_api_init_login_request, rc_api_process_login_response);
login_request, &login_data, rc_api_init_login_request, rc_api_process_login_response);
if (r_type == ResponseType::SUCCESS)
Config::SetBaseOrCurrent(Config::RA_API_TOKEN, m_login_data.api_token);
Config::SetBaseOrCurrent(Config::RA_API_TOKEN, login_data.api_token);
rc_api_destroy_login_response(&login_data);
return r_type;
}
AchievementManager::ResponseType
AchievementManager::ResolveHash(std::array<char, HASH_LENGTH> 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<rc_api_resolve_hash_request_t, rc_api_resolve_hash_response_t>(
resolve_hash_request, &hash_data, rc_api_init_resolve_hash_request,
rc_api_process_resolve_hash_response);
if (r_type == ResponseType::SUCCESS)
m_game_id = hash_data.game_id;
rc_api_destroy_resolve_hash_response(&hash_data);
return r_type;
}
AchievementManager::ResponseType AchievementManager::StartRASession()
{
rc_api_start_session_response_t session_data{};
std::string username = Config::Get(Config::RA_USERNAME);
std::string api_token = Config::Get(Config::RA_API_TOKEN);
rc_api_start_session_request_t start_session_request = {
.username = username.c_str(), .api_token = api_token.c_str(), .game_id = m_game_id};
ResponseType r_type = Request<rc_api_start_session_request_t, rc_api_start_session_response_t>(
start_session_request, &session_data, rc_api_init_start_session_request,
rc_api_process_start_session_response);
rc_api_destroy_start_session_response(&session_data);
return r_type;
}
AchievementManager::ResponseType AchievementManager::FetchGameData()
{
std::string username = Config::Get(Config::RA_USERNAME);
std::string api_token = Config::Get(Config::RA_API_TOKEN);
rc_api_fetch_game_data_request_t fetch_data_request = {
.username = username.c_str(), .api_token = api_token.c_str(), .game_id = m_game_id};
return Request<rc_api_fetch_game_data_request_t, rc_api_fetch_game_data_response_t>(
fetch_data_request, &m_game_data, rc_api_init_fetch_game_data_request,
rc_api_process_fetch_game_data_response);
}
AchievementManager::ResponseType AchievementManager::FetchUnlockData(bool hardcore)
{
rc_api_fetch_user_unlocks_response_t unlock_data{};
std::string username = Config::Get(Config::RA_USERNAME);
std::string api_token = Config::Get(Config::RA_API_TOKEN);
rc_api_fetch_user_unlocks_request_t fetch_unlocks_request = {.username = username.c_str(),
.api_token = api_token.c_str(),
.game_id = m_game_id,
.hardcore = hardcore};
ResponseType r_type =
Request<rc_api_fetch_user_unlocks_request_t, rc_api_fetch_user_unlocks_response_t>(
fetch_unlocks_request, &unlock_data, rc_api_init_fetch_user_unlocks_request,
rc_api_process_fetch_user_unlocks_response);
if (r_type == ResponseType::SUCCESS)
{
std::lock_guard lg{m_lock};
bool enabled = Config::Get(Config::RA_ACHIEVEMENTS_ENABLED);
bool unofficial = Config::Get(Config::RA_UNOFFICIAL_ENABLED);
bool encore = Config::Get(Config::RA_ENCORE_ENABLED);
for (AchievementId ix = 0; ix < unlock_data.num_achievement_ids; ix++)
{
auto it = m_unlock_map.find(unlock_data.achievement_ids[ix]);
if (it == m_unlock_map.end())
continue;
it->second.remote_unlock_status =
hardcore ? UnlockStatus::UnlockType::HARDCORE : UnlockStatus::UnlockType::SOFTCORE;
ActivateDeactivateAchievement(unlock_data.achievement_ids[ix], enabled, unofficial, encore);
}
}
rc_api_destroy_fetch_user_unlocks_response(&unlock_data);
return r_type;
}
void AchievementManager::ActivateDeactivateAchievement(AchievementId id, bool enabled,
bool unofficial, bool encore)
{
auto it = m_unlock_map.find(id);
if (it == m_unlock_map.end())
return;
const UnlockStatus& status = it->second;
u32 index = status.game_data_index;
bool active = (rc_runtime_get_achievement(&m_runtime, id) != nullptr);
// Deactivate achievements if game is not loaded
bool activate = m_is_game_loaded;
// Activate achievements only if achievements are enabled
if (activate && !enabled)
activate = false;
// Deactivate if achievement is unofficial, unless unofficial achievements are enabled
if (activate && !unofficial &&
m_game_data.achievements[index].category == RC_ACHIEVEMENT_CATEGORY_UNOFFICIAL)
{
activate = false;
}
// If encore mode is on, activate/deactivate regardless of current unlock status
if (activate && !encore)
{
// Encore is off, achievement has been unlocked in this session, deactivate
activate = (status.session_unlock_count == 0);
// Encore is off, achievement has been hardcore unlocked on site, deactivate
if (activate && status.remote_unlock_status == UnlockStatus::UnlockType::HARDCORE)
activate = false;
// Encore is off, hardcore is off, achievement has been softcore unlocked on site, deactivate
if (activate && !hardcore_mode_enabled &&
status.remote_unlock_status == UnlockStatus::UnlockType::SOFTCORE)
{
activate = false;
}
}
if (!active && activate)
{
rc_runtime_activate_achievement(&m_runtime, id, m_game_data.achievements[index].definition,
nullptr, 0);
}
if (active && !activate)
rc_runtime_deactivate_achievement(&m_runtime, id);
}
// Every RetroAchievements API call, with only a partial exception for fetch_image, follows
// the same design pattern (here, X is the name of the call):
// Create a specific rc_api_X_request_t struct and populate with the necessary values

View file

@ -8,37 +8,58 @@
#include <mutex>
#include <string>
#include <thread>
#include <unordered_map>
#include <rcheevos/include/rc_api_runtime.h>
#include <rcheevos/include/rc_api_user.h>
#include <rcheevos/include/rc_runtime.h>
#include "Common/Event.h"
#include "Common/WorkQueueThread.h"
using AchievementId = u32;
class AchievementManager
{
public:
enum class ResponseType
{
SUCCESS,
MANAGER_NOT_INITIALIZED,
INVALID_CREDENTIALS,
CONNECTION_FAILED,
UNKNOWN_FAILURE
};
using LoginCallback = std::function<void(ResponseType)>;
using ResponseCallback = std::function<void(ResponseType)>;
static AchievementManager* GetInstance();
void Init();
ResponseType Login(const std::string& password);
void LoginAsync(const std::string& password, const LoginCallback& callback);
void LoginAsync(const std::string& password, const ResponseCallback& callback);
bool IsLoggedIn() const;
void LoadGameByFilenameAsync(const std::string& iso_path, const ResponseCallback& callback);
void LoadUnlockData(const ResponseCallback& callback);
void ActivateDeactivateAchievements();
void ActivateDeactivateLeaderboards();
void ActivateDeactivateRichPresence();
void CloseGame();
void Logout();
void Shutdown();
private:
AchievementManager() = default;
static constexpr int HASH_LENGTH = 33;
ResponseType VerifyCredentials(const std::string& password);
ResponseType ResolveHash(std::array<char, HASH_LENGTH> game_hash);
ResponseType StartRASession();
ResponseType FetchGameData();
ResponseType FetchUnlockData(bool hardcore);
void ActivateDeactivateAchievement(AchievementId id, bool enabled, bool unofficial, bool encore);
template <typename RcRequest, typename RcResponse>
ResponseType Request(RcRequest rc_request, RcResponse* rc_response,
@ -47,8 +68,25 @@ private:
rc_runtime_t m_runtime{};
bool m_is_runtime_initialized = false;
rc_api_login_response_t m_login_data{};
unsigned int m_game_id = 0;
rc_api_fetch_game_data_response_t m_game_data{};
bool m_is_game_loaded = false;
struct UnlockStatus
{
AchievementId game_data_index = 0;
enum class UnlockType
{
LOCKED,
SOFTCORE,
HARDCORE
} remote_unlock_status = UnlockType::LOCKED;
int session_unlock_count = 0;
};
std::unordered_map<AchievementId, UnlockStatus> m_unlock_map;
Common::WorkQueueThread<std::function<void()>> m_queue;
std::recursive_mutex m_lock;
}; // class AchievementManager
#endif // USE_RETRO_ACHIEVEMENTS

View file

@ -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<ARCode> LoadCodes(const IniFile& global_ini, const IniFile& local_ini)
std::vector<ARCode> LoadCodes(const Common::IniFile& global_ini, const Common::IniFile& local_ini)
{
std::vector<ARCode> codes;
const IniFile* inis[2] = {&global_ini, &local_ini};
for (const IniFile* ini : inis)
for (const auto* ini : {&global_ini, &local_ini})
{
std::vector<std::string> lines;
std::vector<std::string> encrypted_lines;
@ -250,7 +249,7 @@ std::vector<ARCode> LoadCodes(const IniFile& global_ini, const IniFile& local_in
return codes;
}
void SaveCodes(IniFile* local_ini, std::span<const ARCode> codes)
void SaveCodes(Common::IniFile* local_ini, std::span<const ARCode> codes)
{
std::vector<std::string> lines;
std::vector<std::string> enabled_lines;

View file

@ -10,7 +10,10 @@
#include "Common/CommonTypes.h"
namespace Common
{
class IniFile;
}
namespace Core
{
@ -47,10 +50,10 @@ void SetSyncedCodesAsActive();
void UpdateSyncedCodes(std::span<const ARCode> codes);
std::vector<ARCode> ApplyAndReturnCodes(std::span<const ARCode> 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<ARCode> LoadCodes(const IniFile& global_ini, const IniFile& local_ini);
void SaveCodes(IniFile* local_ini, std::span<const ARCode> codes);
std::vector<ARCode> LoadCodes(const Common::IniFile& global_ini, const Common::IniFile& local_ini);
void SaveCodes(Common::IniFile* local_ini, std::span<const ARCode> codes);
using EncryptedLine = std::string;
std::variant<std::monostate, AREntry, EncryptedLine> DeserializeLine(const std::string& line);

View file

@ -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)

View file

@ -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<BootParameters> boot, const WindowSystemInfo& wsi)
}
}
#ifdef USE_RETRO_ACHIEVEMENTS
std::string path = "";
if (std::holds_alternative<BootParameters::Disc>(boot->parameters))
{
path = std::get<BootParameters::Disc>(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<BootParameters::Disc>(boot->parameters);
if (load_ipl)

View file

@ -9,7 +9,7 @@
#include "Common/IniFile.h"
template <typename T>
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<T>* codes)
{
std::vector<std::string> lines;
@ -30,7 +30,8 @@ void ReadEnabledOrDisabled(const IniFile& ini, const std::string& section, bool
}
template <typename T>
void ReadEnabledAndDisabled(const IniFile& ini, const std::string& section, std::vector<T>* codes)
void ReadEnabledAndDisabled(const Common::IniFile& ini, const std::string& section,
std::vector<T>* codes)
{
ReadEnabledOrDisabled(ini, section + "_Enabled", true, codes);
ReadEnabledOrDisabled(ini, section + "_Disabled", false, codes);

View file

@ -13,4 +13,13 @@ namespace Config
const Info<bool> RA_ENABLED{{System::Achievements, "Achievements", "Enabled"}, false};
const Info<std::string> RA_USERNAME{{System::Achievements, "Achievements", "Username"}, ""};
const Info<std::string> RA_API_TOKEN{{System::Achievements, "Achievements", "ApiToken"}, ""};
const Info<bool> RA_ACHIEVEMENTS_ENABLED{
{System::Achievements, "Achievements", "AchievementsEnabled"}, false};
const Info<bool> RA_LEADERBOARDS_ENABLED{
{System::Achievements, "Achievements", "LeaderboardsEnabled"}, false};
const Info<bool> RA_RICH_PRESENCE_ENABLED{
{System::Achievements, "Achievements", "RichPresenceEnabled"}, false};
const Info<bool> RA_UNOFFICIAL_ENABLED{{System::Achievements, "Achievements", "UnofficialEnabled"},
false};
const Info<bool> RA_ENCORE_ENABLED{{System::Achievements, "Achievements", "EncoreEnabled"}, false};
} // namespace Config

View file

@ -11,4 +11,9 @@ namespace Config
extern const Info<bool> RA_ENABLED;
extern const Info<std::string> RA_USERNAME;
extern const Info<std::string> RA_API_TOKEN;
extern const Info<bool> RA_ACHIEVEMENTS_ENABLED;
extern const Info<bool> RA_LEADERBOARDS_ENABLED;
extern const Info<bool> RA_RICH_PRESENCE_ENABLED;
extern const Info<bool> RA_UNOFFICIAL_ENABLED;
extern const Info<bool> RA_ENCORE_ENABLED;
} // namespace Config

View file

@ -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<IniFile::Section>& 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<Config::System, IniFile> inis;
std::map<Config::System, Common::IniFile> 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

View file

@ -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<IniFile::Section>& 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

View file

@ -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<u16> revision)
Common::IniFile SConfig::LoadDefaultGameIni(const std::string& id, std::optional<u16> 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<u16> revision)
Common::IniFile SConfig::LoadLocalGameIni(const std::string& id, std::optional<u16> 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<u16> revision)
Common::IniFile SConfig::LoadGameIni(const std::string& id, std::optional<u16> 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))

View file

@ -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<u16> revision);
static IniFile LoadLocalGameIni(const std::string& id, std::optional<u16> revision);
static IniFile LoadGameIni(const std::string& id, std::optional<u16> revision);
static Common::IniFile LoadDefaultGameIni(const std::string& id, std::optional<u16> revision);
static Common::IniFile LoadLocalGameIni(const std::string& id, std::optional<u16> revision);
static Common::IniFile LoadGameIni(const std::string& id, std::optional<u16> revision);
SConfig(const SConfig&) = delete;
SConfig& operator=(const SConfig&) = delete;

View file

@ -38,6 +38,7 @@
#include "Common/Timer.h"
#include "Common/Version.h"
#include "Core/AchievementManager.h"
#include "Core/Boot/Boot.h"
#include "Core/BootManager.h"
#include "Core/Config/MainSettings.h"
@ -283,6 +284,10 @@ void Stop() // - Hammertime!
if (GetState() == State::Stopping || GetState() == State::Uninitialized)
return;
#ifdef USE_RETRO_ACHIEVEMENTS
AchievementManager::GetInstance()->CloseGame();
#endif // USE_RETRO_ACHIEVEMENTS
s_is_stopping = true;
CallOnStateChangedCallbacks(State::Stopping);
@ -435,7 +440,8 @@ static void FifoPlayerThread(const std::optional<std::string>& savestate_path,
{
DeclareAsCPUThread();
if (Core::System::GetInstance().IsDualCoreMode())
auto& system = Core::System::GetInstance();
if (system.IsDualCoreMode())
Common::SetCurrentThreadName("FIFO player thread");
else
Common::SetCurrentThreadName("FIFO-GPU thread");
@ -443,15 +449,14 @@ static void FifoPlayerThread(const std::optional<std::string>& savestate_path,
// Enter CPU run loop. When we leave it - we are done.
if (auto cpu_core = FifoPlayer::GetInstance().GetCPUCore())
{
PowerPC::InjectExternalCPUCore(cpu_core.get());
system.GetPowerPC().InjectExternalCPUCore(cpu_core.get());
s_is_started = true;
CPUSetInitialExecutionState();
auto& system = Core::System::GetInstance();
system.GetCPU().Run();
s_is_started = false;
PowerPC::InjectExternalCPUCore(nullptr);
system.GetPowerPC().InjectExternalCPUCore(nullptr);
FifoPlayer::GetInstance().Close();
}
else
@ -552,7 +557,7 @@ static void EmuThread(std::unique_ptr<BootParameters> boot, WindowSystemInfo wsi
HLE::Clear();
CPUThreadGuard guard(system);
PowerPC::debug_interface.Clear(guard);
system.GetPowerPC().GetDebugInterface().Clear(guard);
}};
VideoBackendBase::PopulateBackendInfo();
@ -590,7 +595,7 @@ static void EmuThread(std::unique_ptr<BootParameters> 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<std::string>& savestate_path, bool delete_savestate);
@ -628,11 +633,11 @@ static void EmuThread(std::unique_ptr<BootParameters> boot, WindowSystemInfo wsi
// Setup our core
if (Config::Get(Config::MAIN_CPU_CORE) != PowerPC::CPUCore::Interpreter)
{
PowerPC::SetMode(PowerPC::CoreMode::JIT);
system.GetPowerPC().SetMode(PowerPC::CoreMode::JIT);
}
else
{
PowerPC::SetMode(PowerPC::CoreMode::Interpreter);
system.GetPowerPC().SetMode(PowerPC::CoreMode::Interpreter);
}
UpdateTitle();
@ -901,7 +906,7 @@ void UpdateTitle()
{
// Settings are shown the same for both extended and summary info
const std::string SSettings = fmt::format(
"{} {} | {} | {}", PowerPC::GetCPUName(),
"{} {} | {} | {}", Core::System::GetInstance().GetPowerPC().GetCPUName(),
Core::System::GetInstance().IsDualCoreMode() ? "DC" : "SC", g_video_backend->GetDisplayName(),
Config::Get(Config::MAIN_DSP_HLE) ? "HLE" : "LLE");

View file

@ -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)

View file

@ -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

View file

@ -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<u32>(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);
}
}

View file

@ -6,6 +6,7 @@
#include <algorithm>
#include <cstring>
#include <mutex>
#include <type_traits>
#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<CPState>);
std::memcpy(static_cast<void*>(&cpmem), static_cast<const void*>(&analyzer.m_cpmem),
sizeof(CPState));
}
if (analyzer.m_end_of_primitives)
{

View file

@ -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));
},

View file

@ -127,11 +127,11 @@ std::vector<GeckoCode> DownloadCodes(std::string gametdb_id, bool* succeeded, bo
return gcodes;
}
std::vector<GeckoCode> LoadCodes(const IniFile& globalIni, const IniFile& localIni)
std::vector<GeckoCode> LoadCodes(const Common::IniFile& globalIni, const Common::IniFile& localIni)
{
std::vector<GeckoCode> gcodes;
for (const IniFile* ini : {&globalIni, &localIni})
for (const auto* ini : {&globalIni, &localIni})
{
std::vector<std::string> lines;
ini->GetLines("Gecko", &lines, false);
@ -239,7 +239,7 @@ static void SaveGeckoCode(std::vector<std::string>& lines, const GeckoCode& gcod
lines.push_back('*' + note);
}
void SaveCodes(IniFile& inifile, const std::vector<GeckoCode>& gcodes)
void SaveCodes(Common::IniFile& inifile, const std::vector<GeckoCode>& gcodes)
{
std::vector<std::string> lines;
std::vector<std::string> enabled_lines;

View file

@ -9,14 +9,17 @@
#include "Core/GeckoCode.h"
namespace Common
{
class IniFile;
}
namespace Gecko
{
std::vector<GeckoCode> LoadCodes(const IniFile& globalIni, const IniFile& localIni);
std::vector<GeckoCode> LoadCodes(const Common::IniFile& globalIni, const Common::IniFile& localIni);
std::vector<GeckoCode> DownloadCodes(std::string gametdb_id, bool* succeeded,
bool use_https = true);
void SaveCodes(IniFile& inifile, const std::vector<GeckoCode>& gcodes);
void SaveCodes(Common::IniFile& inifile, const std::vector<GeckoCode>& gcodes);
std::optional<GeckoCode::Code> DeserializeLine(const std::string& line);
} // namespace Gecko

View file

@ -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)

View file

@ -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<std::mutex>& 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;

View file

@ -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<std::function<void()>> m_pending_jobs;
Core::System& m_system;
};
} // namespace CPU

View file

@ -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;

View file

@ -384,7 +384,8 @@ void CEXIETHERNET::BuiltInBBAInterface::HandleTCPFrame(const Common::TCPPacket&
if (size > 0)
{
// only if contain data
if (static_cast<int>(this_seq - ref->ack_num) >= 0 && data.size() >= size)
if (static_cast<int>(this_seq - ref->ack_num) >= 0 &&
data.size() >= static_cast<size_t>(size))
{
ref->tcp_socket.send(data.data(), size);
ref->ack_num += size;

View file

@ -45,7 +45,8 @@ bool CEXIETHERNET::TAPServerNetworkInterface::Activate()
if (connect(fd, reinterpret_cast<sockaddr*>(&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())
{

View file

@ -448,7 +448,7 @@ void CEXIETHERNET::SendFromDirectFIFO()
const u8* frame = tx_fifo.get();
const u16 size = Common::BitCastPtr<u16>(&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;

View file

@ -61,14 +61,7 @@ MemoryInterfaceManager::~MemoryInterfaceManager() = default;
void MemoryInterfaceManager::Init()
{
static_assert(std::is_trivially_copyable_v<MIMemStruct>);
#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<void*>(&m_mi_mem), 0, sizeof(MIMemStruct));
}
void MemoryInterfaceManager::Shutdown()

View file

@ -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)

View file

@ -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()

View file

@ -136,14 +136,8 @@ static bool DeserializeExtensionState(DesiredWiimoteState* state,
return false;
auto& e = state->extension.data.emplace<T>();
static_assert(std::is_trivially_copyable_v<T>);
#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<void*>(&e), static_cast<const void*>(&serialized.data[offset]),
sizeof(T));
return true;
}

View file

@ -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"))

View file

@ -24,35 +24,18 @@
#include "Core/System.h"
#include "DiscIO/Volume.h"
template <u32 addr>
class RegisterWrapper
{
public:
operator u32() const
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
return memory.GetMMIOMapping()->Read<u32>(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::DIResult> 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::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
{
case DIIoctl::DVDLowInquiry:
INFO_LOG_FMT(IOS_DI, "DVDLowInquiry");
DICMDBUF0 = 0x12000000;
DICMDBUF1 = 0;
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0x12000000);
mmio->Write<u32>(ADDRESS_DICMDBUF1, 0);
return StartDMATransfer(0x20, request);
case DIIoctl::DVDLowReadDiskID:
INFO_LOG_FMT(IOS_DI, "DVDLowReadDiskID");
DICMDBUF0 = 0xA8000040;
DICMDBUF1 = 0;
DICMDBUF2 = 0x20;
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xA8000040);
mmio->Write<u32>(ADDRESS_DICMDBUF1, 0);
mmio->Write<u32>(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::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
return DIResult::CoverClosed;
case DIIoctl::DVDLowGetCoverRegister:
{
const u32 dicvr = DICVR;
const u32 dicvr = mmio->Read<u32>(ADDRESS_DICVR);
DEBUG_LOG_FMT(IOS_DI, "DVDLowGetCoverRegister {:#010x}", dicvr);
return WriteIfFits(request, dicvr);
}
@ -240,27 +224,27 @@ std::optional<DIDevice::DIResult> 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<u32>(ADDRESS_DICMDBUF0, 0xAD000000 | (position << 8));
mmio->Write<u32>(ADDRESS_DICMDBUF1, 0);
mmio->Write<u32>(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<u32>(ADDRESS_DICMDBUF0, 0xAD010000 | (position << 8));
mmio->Write<u32>(ADDRESS_DICMDBUF1, 0);
mmio->Write<u32>(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<u32>(ADDRESS_DICMDBUF0, 0xAD020000 | (position << 8));
mmio->Write<u32>(ADDRESS_DICMDBUF1, 0);
mmio->Write<u32>(ADDRESS_DICMDBUF2, 0);
return StartDMATransfer(0x800, request);
}
case DIIoctl::DVDLowGetLength:
@ -268,7 +252,7 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
return WriteIfFits(request, m_last_length);
case DIIoctl::DVDLowGetImmBuf:
{
const u32 diimmbuf = DIIMMBUF;
const u32 diimmbuf = mmio->Read<u32>(ADDRESS_DIIMMBUF);
INFO_LOG_FMT(IOS_DI, "DVDLowGetImmBuf {:#010x}", diimmbuf);
return WriteIfFits(request, diimmbuf);
}
@ -303,27 +287,27 @@ std::optional<DIDevice::DIResult> 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<u32>(ADDRESS_HW_GPIO_OUT);
if (spinup)
HW_GPIO_OUT = old_gpio & ~static_cast<u32>(GPIO::DI_SPIN);
mmio->Write<u32>(ADDRESS_HW_GPIO_OUT, old_gpio & ~static_cast<u32>(GPIO::DI_SPIN));
else
HW_GPIO_OUT = old_gpio | static_cast<u32>(GPIO::DI_SPIN);
mmio->Write<u32>(ADDRESS_HW_GPIO_OUT, old_gpio | static_cast<u32>(GPIO::DI_SPIN));
// Syscall 0x46 check_di_reset
const bool was_resetting = (HW_RESETS & (1 << 10)) == 0;
const bool was_resetting = (mmio->Read<u32>(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<u32>(ADDRESS_HW_RESETS, mmio->Read<u32>(ADDRESS_HW_RESETS) | (1 << 10));
}
else
{
// Syscall 0x44 assert_di_reset
HW_RESETS = HW_RESETS & ~(1 << 10);
mmio->Write<u32>(ADDRESS_HW_RESETS, mmio->Read<u32>(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<u32>(ADDRESS_HW_RESETS, mmio->Read<u32>(ADDRESS_HW_RESETS) | (1 << 10));
}
ResetDIRegisters();
return DIResult::Success;
@ -356,14 +340,14 @@ std::optional<DIDevice::DIResult> 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<u32>(ADDRESS_DICMDBUF0, 0xA8000000);
mmio->Write<u32>(ADDRESS_DICMDBUF1, position);
mmio->Write<u32>(ADDRESS_DICMDBUF2, length);
if (range.is_error_001_range && Config::Get(Config::SESSION_SHOULD_FAKE_ERROR_001))
{
DIMAR = request.buffer_out;
mmio->Write<u32>(ADDRESS_DIMAR, request.buffer_out);
m_last_length = length;
DILENGTH = length;
mmio->Write<u32>(ADDRESS_DILENGTH, length);
system.GetDVDInterface().ForceOutOfBoundsRead(DVD::ReplyType::IOS);
return {};
}
@ -403,13 +387,13 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
return DIResult::SecurityError;
case DIIoctl::DVDLowGetStatusRegister:
{
const u32 disr = DISR;
const u32 disr = mmio->Read<u32>(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<u32>(ADDRESS_DICR);
INFO_LOG_FMT(IOS_DI, "DVDLowGetControlRegister: {:#010x}", dicr);
return WriteIfFits(request, dicr);
}
@ -418,9 +402,9 @@ std::optional<DIDevice::DIResult> 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<u32>(ADDRESS_DICMDBUF0, 0xA4000000 | (param1 << 16));
mmio->Write<u32>(ADDRESS_DICMDBUF1, param2 & 0xFFFFFF);
mmio->Write<u32>(ADDRESS_DICMDBUF2, 0);
return StartDMATransfer(0x20, request);
}
case DIIoctl::DVDLowSeek:
@ -428,8 +412,8 @@ std::optional<DIDevice::DIResult> 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<u32>(ADDRESS_DICMDBUF0, 0xAB000000);
mmio->Write<u32>(ADDRESS_DICMDBUF1, position);
return StartImmediateTransfer(request, false);
}
case DIIoctl::DVDLowReadDvd:
@ -440,9 +424,9 @@ std::optional<DIDevice::DIResult> 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<u32>(ADDRESS_DICMDBUF0, 0xD0000000 | ((flag1 & 1) << 7) | ((flag2 & 1) << 6));
mmio->Write<u32>(ADDRESS_DICMDBUF1, position & 0xFFFFFF);
mmio->Write<u32>(ADDRESS_DICMDBUF2, length & 0xFFFFFF);
return StartDMATransfer(0x800 * length, request);
}
case DIIoctl::DVDLowReadDvdConfig:
@ -451,41 +435,41 @@ std::optional<DIDevice::DIResult> 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<u32>(ADDRESS_DICMDBUF0, 0xD1000000 | ((flag1 & 1) << 16) | param2);
mmio->Write<u32>(ADDRESS_DICMDBUF1, position & 0xFFFFFF);
mmio->Write<u32>(ADDRESS_DICMDBUF2, 0);
return StartImmediateTransfer(request);
}
case DIIoctl::DVDLowStopLaser:
INFO_LOG_FMT(IOS_DI, "DVDLowStopLaser");
DICMDBUF0 = 0xD2000000;
mmio->Write<u32>(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<u32>(ADDRESS_DICMDBUF0, 0xD9000000 | ((flag & 1) << 16));
mmio->Write<u32>(ADDRESS_DICMDBUF1, offset);
return StartImmediateTransfer(request);
}
case DIIoctl::DVDLowReadDiskBca:
INFO_LOG_FMT(IOS_DI, "DVDLowReadDiskBca");
DICMDBUF0 = 0xDA000000;
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xDA000000);
return StartDMATransfer(0x40, request);
case DIIoctl::DVDLowRequestDiscStatus:
INFO_LOG_FMT(IOS_DI, "DVDLowRequestDiscStatus");
DICMDBUF0 = 0xDB000000;
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xDB000000);
return StartImmediateTransfer(request);
case DIIoctl::DVDLowRequestRetryNumber:
INFO_LOG_FMT(IOS_DI, "DVDLowRequestRetryNumber");
DICMDBUF0 = 0xDC000000;
mmio->Write<u32>(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<u32>(ADDRESS_DICMDBUF0, 0xDD000000 | ((speed & 3) << 16));
return StartImmediateTransfer(request, false);
}
case DIIoctl::DVDLowSerMeasControl:
@ -493,12 +477,12 @@ std::optional<DIDevice::DIResult> 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<u32>(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<u32>(ADDRESS_DICMDBUF0, 0xE0000000);
return StartImmediateTransfer(request);
case DIIoctl::DVDLowAudioStream:
{
@ -507,17 +491,17 @@ std::optional<DIDevice::DIResult> 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<u64>(position) << 2, length);
DICMDBUF0 = 0xE1000000 | ((mode & 3) << 16);
DICMDBUF1 = position;
DICMDBUF2 = length;
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xE1000000 | ((mode & 3) << 16));
mmio->Write<u32>(ADDRESS_DICMDBUF1, position);
mmio->Write<u32>(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<u32>(ADDRESS_DICMDBUF0, 0xE2000000 | ((mode & 3) << 16));
mmio->Write<u32>(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::DIResult> 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<u32>(ADDRESS_DICMDBUF0, 0xE3000000 | ((eject & 1) << 17) | ((kill & 1) << 20));
mmio->Write<u32>(ADDRESS_DICMDBUF1, 0);
return StartImmediateTransfer(request);
}
case DIIoctl::DVDLowAudioBufferConfig:
@ -537,8 +521,8 @@ std::optional<DIDevice::DIResult> 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<u32>(ADDRESS_DICMDBUF0, 0xE4000000 | ((enable & 1) << 16) | (buffer_size & 0xf));
mmio->Write<u32>(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::DIResult> DIDevice::StartDMATransfer(u32 command_length,
return DIResult::BadArgument;
}
DIMAR = request.buffer_out;
auto& system = Core::System::GetInstance();
auto* mmio = system.GetMemory().GetMMIOMapping();
mmio->Write<u32>(ADDRESS_DIMAR, request.buffer_out);
m_last_length = command_length;
DILENGTH = command_length;
mmio->Write<u32>(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<u32>(ADDRESS_DIIMMBUF), request.buffer_out);
m_ios.EnqueueIPCReply(request, static_cast<s32>(result));

View file

@ -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
{

View file

@ -3,6 +3,8 @@
#include "Core/IOS/FS/FileSystem.h"
#include <algorithm>
#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('/');

View file

@ -4,6 +4,7 @@
#include "Core/IOS/FS/HostBackend/FS.h"
#include <algorithm>
#include <cmath>
#include <optional>
#include <string_view>
#include <type_traits>
@ -11,6 +12,7 @@
#include <fmt/format.h>
#include "Common/Align.h"
#include "Common/Assert.h"
#include "Common/ChunkFile.h"
#include "Common/FileUtil.h"
@ -27,6 +29,21 @@ namespace IOS::HLE::FS
{
constexpr u32 BUFFER_CHUNK_SIZE = 65536;
// size of a single cluster in the NAND
constexpr u16 CLUSTER_SIZE = 16384;
// total number of clusters available in the NAND
constexpr u16 TOTAL_CLUSTERS = 0x7ec0;
// number of clusters reserved for bad blocks and similar, not accessible to normal writes
constexpr u16 RESERVED_CLUSTERS = 0x0300;
// number of clusters actually usable by the file system
constexpr u16 USABLE_CLUSTERS = TOTAL_CLUSTERS - RESERVED_CLUSTERS;
// total number of inodes available in the NAND
constexpr u16 TOTAL_INODES = 0x17ff;
HostFileSystem::HostFilename HostFileSystem::BuildFilename(const std::string& wii_path) const
{
for (const auto& redirect : m_nand_redirects)
@ -47,21 +64,6 @@ HostFileSystem::HostFilename HostFileSystem::BuildFilename(const std::string& wi
return HostFilename{m_root_path, false};
}
// Get total filesize of contents of a directory (recursive)
// Only used for ES_GetUsage atm, could be useful elsewhere?
static u64 ComputeTotalFileSize(const File::FSTEntry& parent_entry)
{
u64 sizeOfFiles = 0;
for (const File::FSTEntry& entry : parent_entry.children)
{
if (entry.isDirectory)
sizeOfFiles += ComputeTotalFileSize(entry);
else
sizeOfFiles += entry.size;
}
return sizeOfFiles;
}
namespace
{
struct SerializedFstEntry
@ -102,6 +104,45 @@ auto GetNamePredicate(const std::string& name)
{
return [&name](const auto& entry) { return entry.name == name; };
}
// Convert the host directory entries into ones that can be exposed to the emulated system.
static u64 FixupDirectoryEntries(File::FSTEntry* dir, bool is_root)
{
u64 removed_entries = 0;
for (auto it = dir->children.begin(); it != dir->children.end();)
{
// Drop files in the root of the Wii NAND folder, since we store extra files there that the
// emulated system shouldn't know about.
if (is_root && !it->isDirectory)
{
++removed_entries;
it = dir->children.erase(it);
continue;
}
// Decode escaped invalid file system characters so that games (such as Harry Potter and the
// Half-Blood Prince) can find what they expect.
if (it->virtualName.find("__") != std::string::npos)
it->virtualName = Common::UnescapeFileName(it->virtualName);
// Drop files that have too long filenames.
if (!IsValidFilename(it->virtualName))
{
if (it->isDirectory)
removed_entries += it->size;
++removed_entries;
it = dir->children.erase(it);
continue;
}
if (dir->isDirectory)
removed_entries += FixupDirectoryEntries(&*it, false);
++it;
}
dir->size -= removed_entries;
return removed_entries;
}
} // namespace
bool HostFileSystem::FstEntry::CheckPermission(Uid caller_uid, Gid caller_gid,
@ -645,12 +686,7 @@ Result<std::vector<std::string>> HostFileSystem::ReadDirectory(Uid uid, Gid gid,
const std::string host_path = BuildFilename(path).host_path;
File::FSTEntry host_entry = File::ScanDirectoryTree(host_path, false);
for (File::FSTEntry& child : host_entry.children)
{
// Decode escaped invalid file system characters so that games (such as
// Harry Potter and the Half-Blood Prince) can find what they expect.
child.virtualName = Common::UnescapeFileName(child.virtualName);
}
FixupDirectoryEntries(&host_entry, path == "/");
// Sort files according to their order in the FST tree (issue 10234).
// The result should look like this:
@ -747,19 +783,33 @@ ResultCode HostFileSystem::SetMetadata(Uid caller_uid, const std::string& path,
return ResultCode::Success;
}
static u64 ComputeUsedClusters(const File::FSTEntry& parent_entry)
{
u64 clusters = 0;
for (const File::FSTEntry& entry : parent_entry.children)
{
if (entry.isDirectory)
clusters += ComputeUsedClusters(entry);
else
clusters += Common::AlignUp(entry.size, CLUSTER_SIZE) / CLUSTER_SIZE;
}
return clusters;
}
Result<NandStats> HostFileSystem::GetNandStats()
{
WARN_LOG_FMT(IOS_FS, "GET STATS - returning static values for now");
const auto root_stats = GetDirectoryStats("/");
if (!root_stats)
return root_stats.Error(); // TODO: is this right? can this fail on hardware?
// TODO: scrape the real amounts from somewhere...
NandStats stats{};
stats.cluster_size = 0x4000;
stats.free_clusters = 0x5DEC;
stats.used_clusters = 0x1DD4;
stats.bad_clusters = 0x10;
stats.reserved_clusters = 0x02F0;
stats.free_inodes = 0x146B;
stats.used_inodes = 0x0394;
stats.cluster_size = CLUSTER_SIZE;
stats.free_clusters = USABLE_CLUSTERS - root_stats->used_clusters;
stats.used_clusters = root_stats->used_clusters;
stats.bad_clusters = 0;
stats.reserved_clusters = RESERVED_CLUSTERS;
stats.free_inodes = TOTAL_INODES - root_stats->used_inodes;
stats.used_inodes = root_stats->used_inodes;
return stats;
}
@ -771,19 +821,25 @@ Result<DirectoryStats> HostFileSystem::GetDirectoryStats(const std::string& wii_
DirectoryStats stats{};
std::string path(BuildFilename(wii_path).host_path);
if (File::IsDirectory(path))
File::FileInfo info(path);
if (!info.Exists())
{
return ResultCode::NotFound;
}
if (info.IsDirectory())
{
File::FSTEntry parent_dir = File::ScanDirectoryTree(path, true);
FixupDirectoryEntries(&parent_dir, wii_path == "/");
// add one for the folder itself
stats.used_inodes = 1 + (u32)parent_dir.size;
stats.used_inodes = static_cast<u32>(std::min<u64>(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<u32>(std::min<u64>(clusters, USABLE_CLUSTERS));
}
else
{
WARN_LOG_FMT(IOS_FS, "fsBlock failed, cannot find directory: {}", path);
return ResultCode::Invalid;
}
return stats;
}

View file

@ -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()

View file

@ -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.");

View file

@ -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);

View file

@ -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;
}

View file

@ -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;

View file

@ -103,7 +103,7 @@ std::optional<IPCReply> 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();

View file

@ -191,7 +191,7 @@ USB_KBD::USB_KBD(Kernel& ios, const std::string& device_name) : Device(ios, devi
std::optional<IPCReply> 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);

View file

@ -23,7 +23,7 @@
#include "Common/CommonPaths.h"
#include "Common/CommonTypes.h"
#include "Common/Crypto/SHA1.h"
#include "Common/ENetUtil.h"
#include "Common/ENet.h"
#include "Common/FileUtil.h"
#include "Common/Logging/Log.h"
#include "Common/MsgHandler.h"
@ -168,7 +168,7 @@ NetPlayClient::NetPlayClient(const std::string& address, const u16 port, NetPlay
{
if (Connect())
{
m_client->intercept = ENetUtil::InterceptCallback;
m_client->intercept = Common::ENet::InterceptCallback;
m_thread = std::thread(&NetPlayClient::ThreadFunc, this);
}
}
@ -254,7 +254,8 @@ bool NetPlayClient::Connect()
// TODO: make this not hang
ENetEvent netEvent;
int net;
while ((net = enet_host_service(m_client, &netEvent, 5000)) > 0 && netEvent.type == 42)
while ((net = enet_host_service(m_client, &netEvent, 5000)) > 0 &&
netEvent.type == ENetEventType(42)) // See PR #11381 and ENetUtil::InterceptCallback
{
// ignore packets from traversal server
}
@ -1522,7 +1523,7 @@ void NetPlayClient::OnGameDigestAbort()
void NetPlayClient::Send(const sf::Packet& packet, const u8 channel_id)
{
ENetUtil::SendPacket(m_server, packet, channel_id);
Common::ENet::SendPacket(m_server, packet, channel_id);
}
void NetPlayClient::DisplayPlayersPing()
@ -1577,7 +1578,7 @@ void NetPlayClient::SendAsync(sf::Packet&& packet, const u8 channel_id)
std::lock_guard lkq(m_crit.async_queue_write);
m_async_queue.Push(AsyncQueueEntry{std::move(packet), channel_id});
}
ENetUtil::WakeupThread(m_client);
Common::ENet::WakeupThread(m_client);
}
// called from ---NETPLAY--- thread

View file

@ -20,7 +20,7 @@
#include <fmt/format.h>
#include "Common/CommonPaths.h"
#include "Common/ENetUtil.h"
#include "Common/ENet.h"
#include "Common/FileUtil.h"
#include "Common/HttpRequest.h"
#include "Common/Logging/Log.h"
@ -111,7 +111,7 @@ NetPlayServer::~NetPlayServer()
}
#ifdef USE_UPNP
UPnP::StopPortmapping();
Common::UPnP::StopPortmapping();
#endif
}
@ -153,7 +153,7 @@ NetPlayServer::NetPlayServer(const u16 port, const bool forward_port, NetPlayUI*
if (m_server != nullptr)
{
m_server->mtu = std::min(m_server->mtu, NetPlay::MAX_ENET_MTU);
m_server->intercept = ENetUtil::InterceptCallback;
m_server->intercept = Common::ENet::InterceptCallback;
}
SetupIndex();
@ -168,7 +168,7 @@ NetPlayServer::NetPlayServer(const u16 port, const bool forward_port, NetPlayUI*
#ifdef USE_UPNP
if (forward_port)
UPnP::TryPortmapping(port);
Common::UPnP::TryPortmapping(port);
#endif
}
}
@ -701,7 +701,7 @@ void NetPlayServer::SendAsync(sf::Packet&& packet, const PlayerId pid, const u8
std::lock_guard lkq(m_crit.async_queue_write);
m_async_queue.Push(AsyncQueueEntry{std::move(packet), pid, TargetMode::Only, channel_id});
}
ENetUtil::WakeupThread(m_server);
Common::ENet::WakeupThread(m_server);
}
void NetPlayServer::SendAsyncToClients(sf::Packet&& packet, const PlayerId skip_pid,
@ -712,7 +712,7 @@ void NetPlayServer::SendAsyncToClients(sf::Packet&& packet, const PlayerId skip_
m_async_queue.Push(
AsyncQueueEntry{std::move(packet), skip_pid, TargetMode::AllExcept, channel_id});
}
ENetUtil::WakeupThread(m_server);
Common::ENet::WakeupThread(m_server);
}
void NetPlayServer::SendChunked(sf::Packet&& packet, const PlayerId pid, const std::string& title)
@ -2027,10 +2027,10 @@ bool NetPlayServer::SyncCodes()
// Find all INI files
const auto game_id = game->GetGameID();
const auto revision = game->GetRevision();
IniFile globalIni;
Common::IniFile globalIni;
for (const std::string& filename : ConfigLoaders::GetGameIniFilenames(game_id, revision))
globalIni.Load(File::GetSysDirectory() + GAMESETTINGS_DIR DIR_SEP + filename, true);
IniFile localIni;
Common::IniFile localIni;
for (const std::string& filename : ConfigLoaders::GetGameIniFilenames(game_id, revision))
localIni.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + filename, true);
@ -2183,7 +2183,7 @@ void NetPlayServer::SendToClients(const sf::Packet& packet, const PlayerId skip_
void NetPlayServer::Send(ENetPeer* socket, const sf::Packet& packet, const u8 channel_id)
{
ENetUtil::SendPacket(socket, packet, channel_id);
Common::ENet::SendPacket(socket, packet, channel_id);
}
void NetPlayServer::KickPlayer(PlayerId player)
@ -2266,8 +2266,7 @@ u16 NetPlayServer::GetPort() const
std::unordered_set<std::string> NetPlayServer::GetInterfaceSet() const
{
std::unordered_set<std::string> result;
auto lst = GetInterfaceListInternal();
for (auto list_entry : lst)
for (const auto& list_entry : GetInterfaceListInternal())
result.emplace(list_entry.first);
return result;
}

View file

@ -102,11 +102,9 @@ std::string SerializeLine(const PatchEntry& entry)
}
void LoadPatchSection(const std::string& section, std::vector<Patch>* 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<std::string> lines;
Patch currentPatch;
@ -152,7 +150,7 @@ void LoadPatchSection(const std::string& section, std::vector<Patch>* patches,
}
}
void SavePatchSection(IniFile* local_ini, const std::vector<Patch>& patches)
void SavePatchSection(Common::IniFile* local_ini, const std::vector<Patch>& patches)
{
std::vector<std::string> lines;
std::vector<std::string> lines_enabled;
@ -177,7 +175,7 @@ void SavePatchSection(IniFile* local_ini, const std::vector<Patch>& 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<std::string> keys;
ini.GetKeys(section, &keys);
@ -211,9 +209,10 @@ int GetSpeedhackCycles(const u32 addr)
void LoadPatches()
{
IniFile merged = SConfig::GetInstance().LoadGameIni();
IniFile globalIni = SConfig::GetInstance().LoadDefaultGameIni();
IniFile localIni = SConfig::GetInstance().LoadLocalGameIni();
const auto& sconfig = SConfig::GetInstance();
Common::IniFile merged = sconfig.LoadGameIni();
Common::IniFile globalIni = sconfig.LoadDefaultGameIni();
Common::IniFile localIni = sconfig.LoadLocalGameIni();
LoadPatchSection("OnFrame", &s_on_frame, globalIni, localIni);
@ -278,7 +277,7 @@ static void ApplyMemoryPatches(const Core::CPUThreadGuard& guard,
std::lock_guard lock(s_on_frame_memory_mutex);
for (std::size_t index : memory_patch_indices)
{
PowerPC::debug_interface.ApplyExistingPatch(guard, index);
guard.GetSystem().GetPowerPC().GetDebugInterface().ApplyExistingPatch(guard, index);
}
}

View file

@ -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<PatchEntry> DeserializeLine(std::string line);
std::string SerializeLine(const PatchEntry& entry);
void LoadPatchSection(const std::string& section, std::vector<Patch>* patches,
const IniFile& globalIni, const IniFile& localIni);
void SavePatchSection(IniFile* local_ini, const std::vector<Patch>& patches);
const Common::IniFile& globalIni, const Common::IniFile& localIni);
void SavePatchSection(Common::IniFile* local_ini, const std::vector<Patch>& patches);
void LoadPatches();
void AddMemoryPatch(std::size_t index);

View file

@ -16,8 +16,15 @@
#include "Core/PowerPC/Expression.h"
#include "Core/PowerPC/JitInterface.h"
#include "Core/PowerPC/MMU.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
BreakPoints::BreakPoints(Core::System& system) : m_system(system)
{
}
BreakPoints::~BreakPoints() = default;
bool BreakPoints::IsAddressBreakPoint(u32 address) const
{
return std::any_of(m_breakpoints.begin(), m_breakpoints.end(),
@ -106,7 +113,7 @@ void BreakPoints::Add(TBreakPoint bp)
if (IsAddressBreakPoint(bp.address))
return;
Core::System::GetInstance().GetJitInterface().InvalidateICache(bp.address, 4, true);
m_system.GetJitInterface().InvalidateICache(bp.address, 4, true);
m_breakpoints.emplace_back(std::move(bp));
}
@ -142,7 +149,7 @@ void BreakPoints::Add(u32 address, bool temp, bool break_on_hit, bool log_on_hit
m_breakpoints.emplace_back(std::move(bp));
}
Core::System::GetInstance().GetJitInterface().InvalidateICache(address, 4, true);
m_system.GetJitInterface().InvalidateICache(address, 4, true);
}
bool BreakPoints::ToggleBreakPoint(u32 address)
@ -166,14 +173,14 @@ void BreakPoints::Remove(u32 address)
return;
m_breakpoints.erase(iter);
Core::System::GetInstance().GetJitInterface().InvalidateICache(address, 4, true);
m_system.GetJitInterface().InvalidateICache(address, 4, true);
}
void BreakPoints::Clear()
{
for (const TBreakPoint& bp : m_breakpoints)
{
Core::System::GetInstance().GetJitInterface().InvalidateICache(bp.address, 4, true);
m_system.GetJitInterface().InvalidateICache(bp.address, 4, true);
}
m_breakpoints.clear();
@ -186,7 +193,7 @@ void BreakPoints::ClearAllTemporary()
{
if (bp->is_temporary)
{
Core::System::GetInstance().GetJitInterface().InvalidateICache(bp->address, 4, true);
m_system.GetJitInterface().InvalidateICache(bp->address, 4, true);
bp = m_breakpoints.erase(bp);
}
else
@ -196,6 +203,12 @@ void BreakPoints::ClearAllTemporary()
}
}
MemChecks::MemChecks(Core::System& system) : m_system(system)
{
}
MemChecks::~MemChecks() = default;
MemChecks::TMemChecksStr MemChecks::GetStrings() const
{
TMemChecksStr mc_strings;
@ -279,8 +292,8 @@ void MemChecks::Add(TMemCheck memory_check)
// If this is the first one, clear the JIT cache so it can switch to
// watchpoint-compatible code.
if (!had_any)
Core::System::GetInstance().GetJitInterface().ClearCache();
Core::System::GetInstance().GetMMU().DBATUpdated();
m_system.GetJitInterface().ClearCache();
m_system.GetMMU().DBATUpdated();
});
}
@ -308,8 +321,8 @@ void MemChecks::Remove(u32 address)
Core::RunAsCPUThread([&] {
m_mem_checks.erase(iter);
if (!HasAny())
Core::System::GetInstance().GetJitInterface().ClearCache();
Core::System::GetInstance().GetMMU().DBATUpdated();
m_system.GetJitInterface().ClearCache();
m_system.GetMMU().DBATUpdated();
});
}
@ -317,8 +330,8 @@ void MemChecks::Clear()
{
Core::RunAsCPUThread([&] {
m_mem_checks.clear();
Core::System::GetInstance().GetJitInterface().ClearCache();
Core::System::GetInstance().GetMMU().DBATUpdated();
m_system.GetJitInterface().ClearCache();
m_system.GetMMU().DBATUpdated();
});
}
@ -352,14 +365,14 @@ bool MemChecks::OverlapsMemcheck(u32 address, u32 length) const
});
}
bool TMemCheck::Action(Common::DebugInterface* debug_interface, u64 value, u32 addr, bool write,
size_t size, u32 pc)
bool TMemCheck::Action(Core::System& system, Common::DebugInterface* debug_interface, u64 value,
u32 addr, bool write, size_t size, u32 pc)
{
if (!is_enabled)
return false;
if (((write && is_break_on_write) || (!write && is_break_on_read)) &&
EvaluateCondition(this->condition))
EvaluateCondition(system, this->condition))
{
if (log_on_hit)
{

View file

@ -15,6 +15,10 @@ namespace Common
{
class DebugInterface;
}
namespace Core
{
class System;
}
struct TBreakPoint
{
@ -45,14 +49,21 @@ struct TMemCheck
std::optional<Expression> condition;
// returns whether to break
bool Action(Common::DebugInterface* debug_interface, u64 value, u32 addr, bool write, size_t size,
u32 pc);
bool Action(Core::System& system, Common::DebugInterface* debug_interface, u64 value, u32 addr,
bool write, size_t size, u32 pc);
};
// Code breakpoints.
class BreakPoints
{
public:
explicit BreakPoints(Core::System& system);
BreakPoints(const BreakPoints& other) = delete;
BreakPoints(BreakPoints&& other) = delete;
BreakPoints& operator=(const BreakPoints& other) = delete;
BreakPoints& operator=(BreakPoints&& other) = delete;
~BreakPoints();
using TBreakPoints = std::vector<TBreakPoint>;
using TBreakPointsStr = std::vector<std::string>;
@ -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<TMemCheck>;
using TMemChecksStr = std::vector<std::string>;
@ -109,4 +128,5 @@ public:
private:
TMemChecks m_mem_checks;
Core::System& m_system;
};

View file

@ -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;

View file

@ -267,21 +267,22 @@ std::optional<Expression> 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<double>(PowerPC::ppcState.gpr[bind->index]);
v->value = static_cast<double>(ppc_state.gpr[bind->index]);
else
PowerPC::ppcState.gpr[bind->index] = static_cast<u32>(static_cast<s64>(v->value));
ppc_state.gpr[bind->index] = static_cast<u32>(static_cast<s64>(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<double>(PowerPC::ppcState.spr[bind->index]);
v->value = static_cast<double>(ppc_state.spr[bind->index]);
else
PowerPC::ppcState.spr[bind->index] = static_cast<u32>(static_cast<s64>(v->value));
ppc_state.spr[bind->index] = static_cast<u32>(static_cast<s64>(v->value));
break;
case VarBindingType::PCtr:
if (dir == SynchronizeDirection::From)
v->value = static_cast<double>(PowerPC::ppcState.pc);
v->value = static_cast<double>(ppc_state.pc);
break;
}
}

View file

@ -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<Expression> 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<VarBinding> m_binds;
};
inline bool EvaluateCondition(const std::optional<Expression>& condition)
inline bool EvaluateCondition(Core::System& system, const std::optional<Expression>& condition)
{
return !condition || condition->Evaluate() != 0.0;
return !condition || condition->Evaluate(system) != 0.0;
}

View file

@ -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<int>(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<int>(type),
len, addr);
}
@ -1048,7 +1052,7 @@ void InitLocal(const char* socket)
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, socket);
InitGeneric(PF_LOCAL, (const sockaddr*)&addr, sizeof(addr), NULL, NULL);
InitGeneric(PF_LOCAL, (const sockaddr*)&addr, sizeof(addr), nullptr, nullptr);
}
#endif

Some files were not shown because too many files have changed in this diff Show more