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)
add_subdirectory(Externals/spirv_cross)
# SPIRV-Cross is used on Windows for GLSL to HLSL conversion for the Direct3D 11 and Direct3D 12
# video backends, and on Apple devices for the Metal video backend.
if(WIN32 OR APPLE)
add_subdirectory(Externals/spirv_cross)
endif()
if(ENABLE_VULKAN)
add_definitions(-DHAS_VULKAN)

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
@ -903,10 +909,10 @@ e2000002 80008000
e2000002 80008000
*Harder to time the wheel in the minigame Body Builder.
$Minigame: Catch You Letter - All Letters Give 3 Points
204CBD6C 80010028
044CBD6C 38000003
E2000001 80008000
$Minigame: Catch You Letter - All Letters Give 3 Points
204CBD6C 80010028
044CBD6C 38000003
E2000001 80008000
*This essentially nullifies love letters.
$Minigame: Crate & Peril - 3 Players can Jump [Airsola, gamemasterplc]
@ -973,14 +979,14 @@ $Minigame: Mole It All Moles are Worth 3 Points [gamemasterplc]
E2000001 80008000
$Minigame: Snow Whirled Just Mash A [gamemasterplc]
204CB568 38650001
044CB568 38650004
204CB568 38650001
044CB568 38650004
E2000001 80008000
$Minigame: Snow Whirled Displayed Score Equals Rotations [gamemasterplc]
204CB66C 1C84005A
044CB66C 1C840001
E2000001 80008000
204CB66C 1C84005A
044CB66C 1C840001
E2000001 80008000
$Minigame: Odd Card Out - Spam Prevention [Airsola]
202c0254 00000007

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

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
50, // peerCount
NetPlay::CHANNEL_COUNT, // channelLimit
0, // incomingBandwidth
0); // outgoingBandwidth
auto host = Common::ENet::ENetHostPtr{enet_host_create(&addr, // address
50, // peerCount
NetPlay::CHANNEL_COUNT, // channelLimit
0, // incomingBandwidth
0)}; // outgoingBandwidth
if (!host)
{
g_MainNetHost.reset();
return false;
}
host->mtu = std::min(host->mtu, NetPlay::MAX_ENET_MTU);
g_MainNetHost.reset(host);
g_MainNetHost = std::move(host);
g_TraversalClient.reset(new TraversalClient(g_MainNetHost.get(), server, server_port));
}
return true;

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