Compare commits

..

1 Commits

Author SHA1 Message Date
Gaberboo 87b101588a
Merge e2aa224300 into b4a1967310 2024-12-15 16:47:34 -08:00
171 changed files with 3380 additions and 3087 deletions

View File

@ -1,24 +0,0 @@
function(dolphin_inject_version_info target)
set(INFO_PLIST_PATH "$<TARGET_BUNDLE_DIR:${target}>/Contents/Info.plist")
add_custom_command(TARGET ${target}
POST_BUILD
COMMAND /usr/libexec/PlistBuddy -c
"Delete :CFBundleShortVersionString"
"${INFO_PLIST_PATH}"
|| true
COMMAND /usr/libexec/PlistBuddy -c
"Delete :CFBundleLongVersionString"
"${INFO_PLIST_PATH}"
|| true
COMMAND /usr/libexec/PlistBuddy -c
"Delete :CFBundleVersion"
"${INFO_PLIST_PATH}"
|| true
COMMAND /usr/libexec/PlistBuddy -c
"Merge '${CMAKE_BINARY_DIR}/Source/Core/VersionInfo.plist'"
"${INFO_PLIST_PATH}")
endfunction()

View File

@ -19,27 +19,28 @@ function(dolphin_make_imported_target_if_missing target lib)
endif()
endfunction()
function(dolphin_optional_system_library out_use_system library)
function(dolphin_optional_system_library library)
string(TOUPPER ${library} upperlib)
set(USE_SYSTEM_${upperlib} "" CACHE STRING "Use system ${library} instead of bundled. ON - Always use system and fail if unavailable, OFF - Always use bundled, AUTO - Use system if available, otherwise use bundled, blank - Delegate to USE_SYSTEM_LIBS. Default is blank.")
if("${USE_SYSTEM_${upperlib}}" STREQUAL "")
if(APPROVED_VENDORED_DEPENDENCIES)
string(TOLOWER ${library} lowerlib)
if(lowerlib IN_LIST APPROVED_VENDORED_DEPENDENCIES)
set(${out_use_system} AUTO PARENT_SCOPE)
set(RESOLVED_USE_SYSTEM_${upperlib} AUTO PARENT_SCOPE)
else()
set(${out_use_system} ON PARENT_SCOPE)
set(RESOLVED_USE_SYSTEM_${upperlib} ON PARENT_SCOPE)
endif()
else()
set(${out_use_system} ${USE_SYSTEM_LIBS} PARENT_SCOPE)
set(RESOLVED_USE_SYSTEM_${upperlib} ${USE_SYSTEM_LIBS} PARENT_SCOPE)
endif()
else()
set(${out_use_system} ${USE_SYSTEM_${upperlib}} PARENT_SCOPE)
set(RESOLVED_USE_SYSTEM_${upperlib} ${USE_SYSTEM_${upperlib}} PARENT_SCOPE)
endif()
endfunction()
function(dolphin_add_bundled_library library use_system bundled_path)
if (${use_system} STREQUAL "AUTO")
function(dolphin_add_bundled_library library bundled_path)
string(TOUPPER ${library} upperlib)
if (${RESOLVED_USE_SYSTEM_${upperlib}} STREQUAL "AUTO")
message(STATUS "No system ${library} was found. Using static ${library} from Externals.")
else()
message(STATUS "Using static ${library} from Externals")
@ -51,9 +52,9 @@ function(dolphin_add_bundled_library library use_system bundled_path)
endfunction()
function(dolphin_find_optional_system_library library bundled_path)
dolphin_optional_system_library(use_system ${library})
dolphin_optional_system_library(${library})
string(TOUPPER ${library} upperlib)
if(use_system)
if(RESOLVED_USE_SYSTEM_${upperlib})
find_package(${library} ${ARGN})
# Yay for cmake packages being inconsistent
if(DEFINED ${library}_FOUND)
@ -61,7 +62,7 @@ function(dolphin_find_optional_system_library library bundled_path)
else()
set(prefix ${upperlib})
endif()
if((NOT ${prefix}_FOUND) AND (NOT ${use_system} STREQUAL "AUTO"))
if((NOT ${found}) AND (NOT ${RESOLVED_USE_SYSTEM_${upperlib}} STREQUAL "AUTO"))
message(FATAL_ERROR "No system ${library} was found. Please install it or set USE_SYSTEM_${upperlib} to AUTO or OFF.")
endif()
endif()
@ -69,17 +70,17 @@ function(dolphin_find_optional_system_library library bundled_path)
message(STATUS "Using system ${library}")
set(${prefix}_TYPE "System" PARENT_SCOPE)
else()
dolphin_add_bundled_library(${library} ${use_system} ${bundled_path})
dolphin_add_bundled_library(${library} ${bundled_path})
set(${prefix}_TYPE "Bundled" PARENT_SCOPE)
endif()
endfunction()
function(dolphin_find_optional_system_library_pkgconfig library search alias bundled_path)
dolphin_optional_system_library(use_system ${library})
dolphin_optional_system_library(${library})
string(TOUPPER ${library} upperlib)
if(use_system)
if(RESOLVED_USE_SYSTEM_${upperlib})
pkg_search_module(${library} ${search} ${ARGN} IMPORTED_TARGET)
if((NOT ${library}_FOUND) AND (NOT ${use_system} STREQUAL "AUTO"))
if((NOT ${library}_FOUND) AND (NOT ${RESOLVED_USE_SYSTEM_${upperlib}} STREQUAL "AUTO"))
message(FATAL_ERROR "No system ${library} was found. Please install it or set USE_SYSTEM_${upperlib} to AUTO or OFF.")
endif()
endif()
@ -88,7 +89,7 @@ function(dolphin_find_optional_system_library_pkgconfig library search alias bun
dolphin_alias_library(${alias} PkgConfig::${library})
set(${library}_TYPE "System" PARENT_SCOPE)
else()
dolphin_add_bundled_library(${library} ${use_system} ${bundled_path})
dolphin_add_bundled_library(${library} ${bundled_path})
set(${library}_TYPE "Bundled" PARENT_SCOPE)
endif()
endfunction()

View File

@ -65,5 +65,6 @@ endfunction()
configure_source_file("Source/Core/Common/scmrev.h")
if(APPLE)
configure_source_file("Source/Core/VersionInfo.plist")
configure_source_file("Source/Core/DolphinQt/Info.plist")
configure_source_file("Source/Core/MacUpdater/Info.plist")
endif()

View File

@ -783,9 +783,14 @@ if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/Source/Core/Common/scmrev.h)
endif()
if(APPLE)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Source/Core)
if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/Source/Core/VersionInfo.plist)
file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/Source/Core/VersionInfo.plist)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Source/Core/DolphinQt)
if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/Source/Core/DolphinQt/Info.plist)
file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/Source/Core/DolphinQt/Info.plist)
endif()
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Source/Core/MacUpdater)
if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/Source/Core/MacUpdater/Info.plist)
file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/Source/Core/MacUpdater/Info.plist)
endif()
endif()

View File

@ -1,41 +1,41 @@
# RZDK01 - The Legend of Zelda: Twilight Princess [Wii]
[OnFrame]
# Add memory patches to be applied every frame here.
$Hyrule Field Speed Hack
0x80047DEC:dword:0x60000000
0x80047E08:dword:0x60000000
0x80047E20:dword:0x60000000
0x80047E3C:dword:0x60000000
0x80047E40:dword:0x60000000
0x80047E44:dword:0x60000000
0x80047E48:dword:0x60000000
0x80047E4C:dword:0x60000000
0x80047E50:dword:0x60000000
0x80047E54:dword:0x60000000
0x80047E58:dword:0x60000000
0x80047E5C:dword:0x60000000
0x80047E60:dword:0x60000000
0x80047E64:dword:0x60000000
0x80047E68:dword:0x60000000
0x80047E6C:dword:0x60000000
0x80047E70:dword:0x60000000
0x80047E74:dword:0x60000000
0x80047E78:dword:0x60000000
0x80047E7C:dword:0x60000000
0x80047E80:dword:0x60000000
0x80047E84:dword:0x60000000
0x80047E88:dword:0x60000000
0x80047E8C:dword:0x60000000
0x80047E94:dword:0x60000000
0x80047EB0:dword:0x60000000
0x80047EC8:dword:0x60000000
0x80047EE4:dword:0x60000000
[Patches_RetroAchievements_Verified]
$Hyrule Field Speed Hack
[ActionReplay]
# Add action replay cheats here.
# RZDK01 - The Legend of Zelda: Twilight Princess [Wii]
[OnFrame]
# Add memory patches to be applied every frame here.
$Hyrule Field Speed Hack
0x80047DEC:dword:0x60000000
0x80047E08:dword:0x60000000
0x80047E20:dword:0x60000000
0x80047E3C:dword:0x60000000
0x80047E40:dword:0x60000000
0x80047E44:dword:0x60000000
0x80047E48:dword:0x60000000
0x80047E4C:dword:0x60000000
0x80047E50:dword:0x60000000
0x80047E54:dword:0x60000000
0x80047E58:dword:0x60000000
0x80047E5C:dword:0x60000000
0x80047E60:dword:0x60000000
0x80047E64:dword:0x60000000
0x80047E68:dword:0x60000000
0x80047E6C:dword:0x60000000
0x80047E70:dword:0x60000000
0x80047E74:dword:0x60000000
0x80047E78:dword:0x60000000
0x80047E7C:dword:0x60000000
0x80047E80:dword:0x60000000
0x80047E84:dword:0x60000000
0x80047E88:dword:0x60000000
0x80047E8C:dword:0x60000000
0x80047E94:dword:0x60000000
0x80047EB0:dword:0x60000000
0x80047EC8:dword:0x60000000
0x80047EE4:dword:0x60000000
[Patches_RetroAchievements_Verified]
$Hyrule Field Speed Hack
[ActionReplay]
# Add action replay cheats here.

View File

@ -1,53 +1,62 @@
set(BUILD_CURL_EXE OFF)
set(BUILD_EXAMPLES OFF)
set(BUILD_LIBCURL_DOCS OFF)
set(BUILD_MISC_DOCS OFF)
set(BUILD_SHARED_LIBS OFF)
set(BUILD_STATIC_LIBS ON)
set(BUILD_TESTING OFF)
set(CURL_ENABLE_EXPORT_TARGET OFF)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/curl/include)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/curl/lib)
set(HTTP_ONLY ON)
set(CURL_LIBS MbedTLS::mbedtls zlibstatic)
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
set(use_core_foundation ON)
set(CURL_USE_LIBPSL OFF)
set(CURL_USE_LIBSSH2 OFF)
set(CURL_ZLIB OFF CACHE BOOL "" FORCE)
set(CURL_ZSTD OFF)
set(USE_LIBIDN2 OFF)
set(USE_NGHTTP2 OFF)
find_library(SYSTEMCONFIGURATION_FRAMEWORK "SystemConfiguration")
if(NOT SYSTEMCONFIGURATION_FRAMEWORK)
message(FATAL_ERROR "SystemConfiguration framework not found")
endif()
if(UNIX)
# We use mbedtls on Unix(-like) systems and Android.
set(CURL_USE_OPENSSL OFF)
# This is set if the dolphin_find_optional_system_library call from the main CMakeLists.txt
# is able to find mbedtls on the system.
if(MBEDTLS_FOUND)
# We can just enable CURL_USE_MBEDTLS.
set(CURL_USE_MBEDTLS ON)
else()
# HACK: Set some internal variables to pretend like mbedtls was found on the system.
# We can't use CURL_USE_MBEDTLS with our copy from Externals, as that flag expects
# mbedtls to be installed (the CMakeLists attempts to search for it with find_package).
set(_ssl_enabled ON)
set(USE_MBEDTLS ON)
set(_curl_ca_bundle_supported TRUE)
endif()
list(APPEND CURL_LIBS "-framework SystemConfiguration")
endif()
if(WIN32)
set(CURL_USE_SCHANNEL ON)
file(GLOB SRCS curl/lib/*.c curl/lib/vauth/*.c curl/lib/vquic/*.c curl/lib/vssh/*.c curl/lib/vtls/*.c)
add_library(
curl
STATIC
curl/include/curl/curl.h
${SRCS}
)
set(SEARCH_CA_BUNDLE_PATHS
/etc/ssl/certs/ca-certificates.crt
/etc/pki/tls/certs/ca-bundle.crt
/usr/share/ssl/certs/ca-bundle.crt
/usr/local/share/certs/ca-root-nss.crt
/etc/ssl/cert.pem)
foreach(SEARCH_CA_BUNDLE_PATH ${SEARCH_CA_BUNDLE_PATHS})
if(EXISTS "${SEARCH_CA_BUNDLE_PATH}")
message(STATUS "Found CA bundle: ${SEARCH_CA_BUNDLE_PATH}")
set(CURL_CA_BUNDLE "${SEARCH_CA_BUNDLE_PATH}")
set(CURL_CA_BUNDLE_SET TRUE)
break()
endif()
endforeach()
if(NOT CURL_CA_PATH_SET)
if(EXISTS "/etc/ssl/certs")
set(CURL_CA_PATH "/etc/ssl/certs")
set(CURL_CA_PATH_SET TRUE)
endif()
endif()
if(ANDROID)
set(CURL_CA_PATH "/system/etc/security/cacerts" CACHE STRING "")
dolphin_disable_warnings(curl)
target_link_libraries(curl ${CURL_LIBS})
target_include_directories(curl PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/curl/include")
target_compile_definitions(curl PRIVATE "BUILDING_LIBCURL=1")
if (WIN32)
target_compile_definitions(curl PUBLIC "CURL_STATICLIB=1" "CURL_DISABLE_LDAP" "USE_WINDOWS_SSPI" "USE_SCHANNEL")
target_link_libraries(curl Crypt32.lib)
else()
target_compile_definitions(curl PUBLIC "CURL_STATICLIB=1" "USE_MBEDTLS=1" "HAVE_CONFIG_H=1" "CURL_DISABLE_LDAP")
if (CURL_CA_PATH_SET)
target_compile_definitions(curl PUBLIC CURL_CA_PATH="${CURL_CA_PATH}")
endif()
endif()
add_subdirectory(curl)
if(UNIX AND NOT MBEDTLS_FOUND)
# HACK: Manually link with the mbedtls libraries.
target_link_libraries(libcurl_static PRIVATE
MbedTLS::mbedtls
MbedTLS::mbedx509)
endif()
add_library(CURL::libcurl ALIAS curl)

22
Externals/curl/COPYING vendored Normal file
View File

@ -0,0 +1,22 @@
COPYRIGHT AND PERMISSION NOTICE
Copyright (c) 1996 - 2016, Daniel Stenberg, <daniel@haxx.se>, and many
contributors, see the THANKS file.
All rights reserved.
Permission to use, copy, modify, and distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright
notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of a copyright holder shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization of the copyright holder.

2
Externals/curl/curl vendored

@ -1 +1 @@
Subproject commit 75a2079d5c28debb2eaa848ca9430f1fe0d7844c
Subproject commit d755a5f7c009dd63a61b2c745180d8ba937cbfeb

View File

@ -50,14 +50,14 @@
<ClCompile Include="curl\lib\curl_memrchr.c" />
<ClCompile Include="curl\lib\curl_multibyte.c" />
<ClCompile Include="curl\lib\curl_ntlm_core.c" />
<ClCompile Include="curl\lib\curl_ntlm_wb.c" />
<ClCompile Include="curl\lib\curl_path.c" />
<ClCompile Include="curl\lib\curl_range.c" />
<ClCompile Include="curl\lib\curl_rtmp.c" />
<ClCompile Include="curl\lib\curl_sasl.c" />
<ClCompile Include="curl\lib\curl_sha512_256.c" />
<ClCompile Include="curl\lib\curl_sspi.c" />
<ClCompile Include="curl\lib\curl_threads.c" />
<ClCompile Include="curl\lib\curl_trc.c" />
<ClCompile Include="curl\lib\cw-out.c" />
<ClCompile Include="curl\lib\dict.c" />
<ClCompile Include="curl\lib\doh.c" />
<ClCompile Include="curl\lib\dynbuf.c" />
@ -120,7 +120,6 @@
<ClCompile Include="curl\lib\psl.c" />
<ClCompile Include="curl\lib\rand.c" />
<ClCompile Include="curl\lib\rename.c" />
<ClCompile Include="curl\lib\request.c" />
<ClCompile Include="curl\lib\rtsp.c" />
<ClCompile Include="curl\lib\select.c" />
<ClCompile Include="curl\lib\sendf.c" />
@ -168,16 +167,12 @@
<ClCompile Include="curl\lib\vauth\vauth.c" />
<ClCompile Include="curl\lib\vquic\curl_msh3.c" />
<ClCompile Include="curl\lib\vquic\curl_ngtcp2.c" />
<ClCompile Include="curl\lib\vquic\curl_osslq.c" />
<ClCompile Include="curl\lib\vquic\curl_quiche.c" />
<ClCompile Include="curl\lib\vquic\vquic.c" />
<ClCompile Include="curl\lib\vquic\vquic-tls.c" />
<ClCompile Include="curl\lib\vssh\curl_path.c" />
<ClCompile Include="curl\lib\vssh\libssh.c" />
<ClCompile Include="curl\lib\vssh\libssh2.c" />
<ClCompile Include="curl\lib\vssh\wolfssh.c" />
<ClCompile Include="curl\lib\vtls\bearssl.c" />
<ClCompile Include="curl\lib\vtls\cipher_suite.c" />
<ClCompile Include="curl\lib\vtls\gtls.c" />
<ClCompile Include="curl\lib\vtls\hostcheck.c" />
<ClCompile Include="curl\lib\vtls\keylog.c" />
@ -249,6 +244,8 @@
<ClInclude Include="curl\lib\curl_memrchr.h" />
<ClInclude Include="curl\lib\curl_multibyte.h" />
<ClInclude Include="curl\lib\curl_ntlm_core.h" />
<ClInclude Include="curl\lib\curl_ntlm_wb.h" />
<ClInclude Include="curl\lib\curl_path.h" />
<ClInclude Include="curl\lib\curl_printf.h" />
<ClInclude Include="curl\lib\curl_range.h" />
<ClInclude Include="curl\lib\curl_rtmp.h" />
@ -256,11 +253,9 @@
<ClInclude Include="curl\lib\curl_setup.h" />
<ClInclude Include="curl\lib\curl_setup_once.h" />
<ClInclude Include="curl\lib\curl_sha256.h" />
<ClInclude Include="curl\lib\curl_sha512_256.h" />
<ClInclude Include="curl\lib\curl_sspi.h" />
<ClInclude Include="curl\lib\curl_threads.h" />
<ClInclude Include="curl\lib\curl_trc.h" />
<ClInclude Include="curl\lib\cw_out.h" />
<ClInclude Include="curl\lib\dict.h" />
<ClInclude Include="curl\lib\doh.h" />
<ClInclude Include="curl\lib\dynbuf.h" />
@ -313,7 +308,6 @@
<ClInclude Include="curl\lib\psl.h" />
<ClInclude Include="curl\lib\rand.h" />
<ClInclude Include="curl\lib\rename.h" />
<ClInclude Include="curl\lib\request.h" />
<ClInclude Include="curl\lib\rtsp.h" />
<ClInclude Include="curl\lib\select.h" />
<ClInclude Include="curl\lib\sendf.h" />
@ -353,15 +347,11 @@
<ClInclude Include="curl\lib\vauth\vauth.h" />
<ClInclude Include="curl\lib\vquic\curl_msh3.h" />
<ClInclude Include="curl\lib\vquic\curl_ngtcp2.h" />
<ClInclude Include="curl\lib\vquic\curl_osslq.h" />
<ClInclude Include="curl\lib\vquic\curl_quiche.h" />
<ClInclude Include="curl\lib\vquic\vquic.h" />
<ClInclude Include="curl\lib\vquic\vquic-tls.h" />
<ClInclude Include="curl\lib\vquic\vquic_int.h" />
<ClInclude Include="curl\lib\vssh\curl_path.h" />
<ClInclude Include="curl\lib\vssh\ssh.h" />
<ClInclude Include="curl\lib\vtls\bearssl.h" />
<ClInclude Include="curl\lib\vtls\cipher_suites.h" />
<ClInclude Include="curl\lib\vtls\gtls.h" />
<ClInclude Include="curl\lib\vtls\hostcheck.h" />
<ClInclude Include="curl\lib\vtls\keylog.h" />

1049
Externals/curl/curl_config.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -19,9 +19,7 @@ import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.PopupMenu
import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager
@ -328,11 +326,12 @@ class EmulationActivity : AppCompatActivity(), ThemeProvider {
}
private fun enableFullscreenImmersive() {
WindowCompat.setDecorFitsSystemWindows(window, false)
WindowInsetsControllerCompat(window, window.decorView).let { controller ->
controller.hide(WindowInsetsCompat.Type.systemBars())
controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
}
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
View.SYSTEM_UI_FLAG_FULLSCREEN or
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
}
private fun updateDisplaySettings() {

View File

@ -124,7 +124,7 @@ class Settings : Closeable {
const val SECTION_INI_DSP = "DSP"
const val SECTION_LOGGER_LOGS = "Logs"
const val SECTION_LOGGER_OPTIONS = "Options"
const val SECTION_GFX_HARDWARE = "Hardware"
const val SECTION_GFX_HARDWARE = "Settings"
const val SECTION_GFX_SETTINGS = "Settings"
const val SECTION_GFX_ENHANCEMENTS = "Enhancements"
const val SECTION_GFX_COLOR_CORRECTION = "ColorCorrection"

View File

@ -1,132 +1,132 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.skylanders.ui
import android.app.AlertDialog
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.AdapterView.OnItemClickListener
import android.widget.ArrayAdapter
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.dolphinemu.dolphinemu.R
import org.dolphinemu.dolphinemu.activities.EmulationActivity
import org.dolphinemu.dolphinemu.databinding.DialogCreateSkylanderBinding
import org.dolphinemu.dolphinemu.databinding.ListItemNfcFigureSlotBinding
import org.dolphinemu.dolphinemu.features.skylanders.SkylanderConfig
import org.dolphinemu.dolphinemu.features.skylanders.SkylanderConfig.removeSkylander
import org.dolphinemu.dolphinemu.features.skylanders.model.SkylanderPair
class SkylanderSlotAdapter(
private val slots: List<SkylanderSlot>,
private val activity: EmulationActivity
) : RecyclerView.Adapter<SkylanderSlotAdapter.ViewHolder>(), OnItemClickListener {
class ViewHolder(var binding: ListItemNfcFigureSlotBinding) :
RecyclerView.ViewHolder(binding.getRoot())
private lateinit var binding: DialogCreateSkylanderBinding
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val binding = ListItemNfcFigureSlotBinding.inflate(inflater, parent, false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val slot = slots[position]
holder.binding.textFigureName.text = slot.label
holder.binding.buttonClearFigure.setOnClickListener {
removeSkylander(slot.portalSlot)
activity.clearSkylander(slot.slotNum)
}
holder.binding.buttonLoadFigure.setOnClickListener {
val loadSkylander = Intent(Intent.ACTION_OPEN_DOCUMENT)
loadSkylander.addCategory(Intent.CATEGORY_OPENABLE)
loadSkylander.type = "*/*"
activity.setSkylanderData(0, 0, "", position)
activity.startActivityForResult(
loadSkylander,
EmulationActivity.REQUEST_SKYLANDER_FILE
)
}
val inflater = LayoutInflater.from(activity)
binding = DialogCreateSkylanderBinding.inflate(inflater)
val nameList = SkylanderConfig.REVERSE_LIST_SKYLANDERS.keys.toMutableList()
nameList.sort()
val skylanderNames: ArrayList<String> = ArrayList(nameList)
binding.skylanderDropdown.setAdapter(
ArrayAdapter(
activity, R.layout.support_simple_spinner_dropdown_item,
skylanderNames
)
)
binding.skylanderDropdown.onItemClickListener = this
holder.binding.buttonCreateFigure.setOnClickListener {
if (binding.getRoot().parent != null) {
(binding.getRoot().parent as ViewGroup).removeAllViews()
}
val createDialog = MaterialAlertDialogBuilder(activity)
.setTitle(R.string.create_skylander_title)
.setView(binding.getRoot())
.setPositiveButton(R.string.create_figure, null)
.setNegativeButton(R.string.cancel, null)
.show()
createDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
if (binding.skylanderId.text.toString().isNotBlank() &&
binding.skylanderVar.text.toString().isNotBlank()
) {
val createSkylander = Intent(Intent.ACTION_CREATE_DOCUMENT)
createSkylander.addCategory(Intent.CATEGORY_OPENABLE)
createSkylander.type = "*/*"
val id = binding.skylanderId.text.toString().toInt()
val variant = binding.skylanderVar.text.toString().toInt()
val name = SkylanderConfig.LIST_SKYLANDERS[SkylanderPair(id, variant)]
if (name != null) {
createSkylander.putExtra(
Intent.EXTRA_TITLE,
"$name.sky"
)
activity.setSkylanderData(id, variant, name, position)
} else {
createSkylander.putExtra(
Intent.EXTRA_TITLE,
"Unknown(ID: " + id + "Variant: " + variant + ").sky"
)
activity.setSkylanderData(id, variant, "Unknown", position)
}
activity.startActivityForResult(
createSkylander,
EmulationActivity.REQUEST_CREATE_SKYLANDER
)
createDialog.dismiss()
} else {
Toast.makeText(
activity, R.string.invalid_skylander,
Toast.LENGTH_SHORT
).show()
}
}
}
}
override fun getItemCount(): Int {
return slots.size
}
override fun onItemClick(parent: AdapterView<*>, view: View, position: Int, id: Long) {
val skylanderIdVar =
SkylanderConfig.REVERSE_LIST_SKYLANDERS[parent.getItemAtPosition(position)]
binding.skylanderId.setText(skylanderIdVar!!.id.toString())
binding.skylanderVar.setText(skylanderIdVar.variant.toString())
}
}
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.skylanders.ui
import android.app.AlertDialog
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.AdapterView.OnItemClickListener
import android.widget.ArrayAdapter
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.dolphinemu.dolphinemu.R
import org.dolphinemu.dolphinemu.activities.EmulationActivity
import org.dolphinemu.dolphinemu.databinding.DialogCreateSkylanderBinding
import org.dolphinemu.dolphinemu.databinding.ListItemNfcFigureSlotBinding
import org.dolphinemu.dolphinemu.features.skylanders.SkylanderConfig
import org.dolphinemu.dolphinemu.features.skylanders.SkylanderConfig.removeSkylander
import org.dolphinemu.dolphinemu.features.skylanders.model.SkylanderPair
class SkylanderSlotAdapter(
private val slots: List<SkylanderSlot>,
private val activity: EmulationActivity
) : RecyclerView.Adapter<SkylanderSlotAdapter.ViewHolder>(), OnItemClickListener {
class ViewHolder(var binding: ListItemNfcFigureSlotBinding) :
RecyclerView.ViewHolder(binding.getRoot())
private lateinit var binding: DialogCreateSkylanderBinding
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val binding = ListItemNfcFigureSlotBinding.inflate(inflater, parent, false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val slot = slots[position]
holder.binding.textFigureName.text = slot.label
holder.binding.buttonClearFigure.setOnClickListener {
removeSkylander(slot.portalSlot)
activity.clearSkylander(slot.slotNum)
}
holder.binding.buttonLoadFigure.setOnClickListener {
val loadSkylander = Intent(Intent.ACTION_OPEN_DOCUMENT)
loadSkylander.addCategory(Intent.CATEGORY_OPENABLE)
loadSkylander.type = "*/*"
activity.setSkylanderData(0, 0, "", position)
activity.startActivityForResult(
loadSkylander,
EmulationActivity.REQUEST_SKYLANDER_FILE
)
}
val inflater = LayoutInflater.from(activity)
binding = DialogCreateSkylanderBinding.inflate(inflater)
val nameList = SkylanderConfig.REVERSE_LIST_SKYLANDERS.keys.toMutableList()
nameList.sort()
val skylanderNames: ArrayList<String> = ArrayList(nameList)
binding.skylanderDropdown.setAdapter(
ArrayAdapter(
activity, R.layout.support_simple_spinner_dropdown_item,
skylanderNames
)
)
binding.skylanderDropdown.onItemClickListener = this
holder.binding.buttonCreateFigure.setOnClickListener {
if (binding.getRoot().parent != null) {
(binding.getRoot().parent as ViewGroup).removeAllViews()
}
val createDialog = MaterialAlertDialogBuilder(activity)
.setTitle(R.string.create_skylander_title)
.setView(binding.getRoot())
.setPositiveButton(R.string.create_figure, null)
.setNegativeButton(R.string.cancel, null)
.show()
createDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
if (binding.skylanderId.text.toString().isNotBlank() &&
binding.skylanderVar.text.toString().isNotBlank()
) {
val createSkylander = Intent(Intent.ACTION_CREATE_DOCUMENT)
createSkylander.addCategory(Intent.CATEGORY_OPENABLE)
createSkylander.type = "*/*"
val id = binding.skylanderId.text.toString().toInt()
val variant = binding.skylanderVar.text.toString().toInt()
val name = SkylanderConfig.LIST_SKYLANDERS[SkylanderPair(id, variant)]
if (name != null) {
createSkylander.putExtra(
Intent.EXTRA_TITLE,
"$name.sky"
)
activity.setSkylanderData(id, variant, name, position)
} else {
createSkylander.putExtra(
Intent.EXTRA_TITLE,
"Unknown(ID: " + id + "Variant: " + variant + ").sky"
)
activity.setSkylanderData(id, variant, "Unknown", position)
}
activity.startActivityForResult(
createSkylander,
EmulationActivity.REQUEST_CREATE_SKYLANDER
)
createDialog.dismiss()
} else {
Toast.makeText(
activity, R.string.invalid_skylander,
Toast.LENGTH_SHORT
).show()
}
}
}
}
override fun getItemCount(): Int {
return slots.size
}
override fun onItemClick(parent: AdapterView<*>, view: View, position: Int, id: Long) {
val skylanderIdVar =
SkylanderConfig.REVERSE_LIST_SKYLANDERS[parent.getItemAtPosition(position)]
binding.skylanderId.setText(skylanderIdVar!!.id.toString())
binding.skylanderVar.setText(skylanderIdVar.variant.toString())
}
}

View File

@ -1,72 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/root"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/spacing_medlarge">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/layout_skylander_dropdown"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/spacing_medlarge"
android:paddingHorizontal="@dimen/spacing_medlarge"
android:hint="@string/skylander_label"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textfield.MaterialAutoCompleteTextView
android:id="@+id/skylander_dropdown"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:spinnerMode="dialog"
android:imeOptions="actionDone" />
</com.google.android.material.textfield.TextInputLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintTop_toBottomOf="@+id/layout_skylander_dropdown"
android:gravity="center_vertical"
android:baselineAligned="false">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/layout_skylander_id"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="@string/skylander_id"
android:paddingHorizontal="@dimen/spacing_medlarge">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/skylander_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/layout_skylander_var"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="@string/skylander_variant"
android:paddingHorizontal="@dimen/spacing_medlarge">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/skylander_var"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/root"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/spacing_medlarge">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/layout_skylander_dropdown"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/spacing_medlarge"
android:paddingHorizontal="@dimen/spacing_medlarge"
android:hint="@string/skylander_label"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textfield.MaterialAutoCompleteTextView
android:id="@+id/skylander_dropdown"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:spinnerMode="dialog"
android:imeOptions="actionDone" />
</com.google.android.material.textfield.TextInputLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintTop_toBottomOf="@+id/layout_skylander_dropdown"
android:gravity="center_vertical"
android:baselineAligned="false">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/layout_skylander_id"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="@string/skylander_id"
android:paddingHorizontal="@dimen/spacing_medlarge">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/skylander_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/layout_skylander_var"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="@string/skylander_variant"
android:paddingHorizontal="@dimen/spacing_medlarge">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/skylander_var"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -62,7 +62,7 @@ bool IsPathAndroidContent(std::string_view uri)
std::string OpenModeToAndroid(std::string mode)
{
// The 'b' specifier is not supported by Android. Since we're on POSIX, it's fine to just skip it.
std::erase(mode, 'b');
mode.erase(std::remove(mode.begin(), mode.end(), 'b'));
if (mode == "r")
return "r";

View File

@ -191,7 +191,7 @@ Java_org_dolphinemu_dolphinemu_features_cheats_model_GeckoCheat_downloadCodes(JN
const std::string gametdb_id = GetJString(env, jGameTdbId);
bool success = true;
const std::vector<Gecko::GeckoCode> codes = Gecko::DownloadCodes(gametdb_id, &success);
const std::vector<Gecko::GeckoCode> codes = Gecko::DownloadCodes(gametdb_id, &success, false);
if (!success)
return nullptr;

View File

@ -51,9 +51,10 @@ Java_org_dolphinemu_dolphinemu_features_cheats_model_GraphicsModGroup_getMods(JN
for (GraphicsModConfig& mod : mod_group->GetMods())
{
// If no group matches the mod's features, or if the mod has no features, skip it
if (std::ranges::none_of(mod.m_features, [&groups](const GraphicsModFeatureConfig& feature) {
return groups.contains(feature.m_group);
}))
if (std::none_of(mod.m_features.begin(), mod.m_features.end(),
[&groups](const GraphicsModFeatureConfig& feature) {
return groups.contains(feature.m_group);
}))
{
continue;
}

View File

@ -1,9 +1,13 @@
// Copyright 2003 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <condition_variable>
#include <EGL/egl.h>
#include <android/log.h>
#include <android/native_window_jni.h>
#include <cstdio>
#include <cstdlib>
#include <fmt/format.h>
#include <jni.h>
#include <memory>
#include <mutex>
#include <optional>
@ -11,12 +15,6 @@
#include <thread>
#include <utility>
#include <EGL/egl.h>
#include <android/log.h>
#include <android/native_window_jni.h>
#include <fmt/format.h>
#include <jni.h>
#include "Common/AndroidAnalytics.h"
#include "Common/Assert.h"
#include "Common/CPUDetect.h"
@ -79,8 +77,6 @@ Common::Event s_update_main_frame_event;
// This exists to prevent surfaces from being destroyed during the boot process,
// as that can lead to the boot process dereferencing nullptr.
std::mutex s_surface_lock;
std::condition_variable s_surface_cv;
bool s_need_nonblocking_alert_msg;
Common::Flag s_is_booting;
@ -486,8 +482,6 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceChang
if (g_presenter)
g_presenter->ChangeSurface(s_surf);
s_surface_cv.notify_all();
}
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceDestroyed(JNIEnv*,
@ -521,8 +515,6 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceDestr
ANativeWindow_release(s_surf);
s_surf = nullptr;
}
s_surface_cv.notify_all();
}
JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_HasSurface(JNIEnv*, jclass)
@ -614,14 +606,12 @@ static void Run(JNIEnv* env, std::unique_ptr<BootParameters>&& boot, bool riivol
volume.GetDiscNumber()));
}
s_need_nonblocking_alert_msg = true;
std::unique_lock<std::mutex> surface_guard(s_surface_lock);
s_surface_cv.wait(surface_guard, []() { return s_surf != nullptr; });
WindowSystemInfo wsi(WindowSystemType::Android, nullptr, s_surf, s_surf);
wsi.render_surface_scale = GetRenderSurfaceScale(env);
s_need_nonblocking_alert_msg = true;
std::unique_lock<std::mutex> surface_guard(s_surface_lock);
if (BootManager::BootCore(Core::System::GetInstance(), std::move(boot), wsi))
{
static constexpr int WAIT_STEP = 25;

View File

@ -34,7 +34,6 @@ add_library(common
Config/Enums.h
Config/Layer.cpp
Config/Layer.h
Contains.h
CPUDetect.h
Crypto/AES.cpp
Crypto/AES.h

View File

@ -1,61 +0,0 @@
// Copyright 2025 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <algorithm>
#include <iterator>
namespace Common
{
struct ContainsFn
{
template <std::input_iterator I, std::sentinel_for<I> S, class T, class Proj = std::identity>
requires std::indirect_binary_predicate < std::ranges::equal_to, std::projected<I, Proj>,
const T* > constexpr bool operator()(I first, S last, const T& value, Proj proj = {}) const
{
return std::ranges::find(std::move(first), last, value, std::move(proj)) != last;
}
template <std::ranges::input_range R, class T, class Proj = std::identity>
requires std::indirect_binary_predicate < std::ranges::equal_to,
std::projected<std::ranges::iterator_t<R>, Proj>,
const T* > constexpr bool operator()(R&& r, const T& value, Proj proj = {}) const
{
return (*this)(std::ranges::begin(r), std::ranges::end(r), value, std::move(proj));
}
};
struct ContainsSubrangeFn
{
template <std::forward_iterator I1, std::sentinel_for<I1> S1, std::forward_iterator I2,
std::sentinel_for<I2> S2, class Pred = std::ranges::equal_to,
class Proj1 = std::identity, class Proj2 = std::identity>
requires std::indirectly_comparable<I1, I2, Pred, Proj1, Proj2>
constexpr bool operator()(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {},
Proj1 proj1 = {}, Proj2 proj2 = {}) const
{
return !std::ranges::search(std::move(first1), std::move(last1), std::move(first2),
std::move(last2), std::move(pred), std::move(proj1),
std::move(proj2))
.empty();
}
template <std::ranges::forward_range R1, std::ranges::forward_range R2,
class Pred = std::ranges::equal_to, class Proj1 = std::identity,
class Proj2 = std::identity>
requires std::indirectly_comparable<std::ranges::iterator_t<R1>, std::ranges::iterator_t<R2>,
Pred, Proj1, Proj2>
constexpr bool operator()(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {},
Proj2 proj2 = {}) const
{
return (*this)(std::ranges::begin(r1), std::ranges::end(r1), std::ranges::begin(r2),
std::ranges::end(r2), std::move(pred), std::move(proj1), std::move(proj2));
}
};
// TODO C++23: Replace with std::ranges::contains.
inline constexpr ContainsFn Contains{};
// TODO C++23: Replace with std::ranges::contains_subrange.
inline constexpr ContainsSubrangeFn ContainsSubrange{};
} // namespace Common

View File

@ -24,7 +24,7 @@ struct Elt
{
bool IsZero() const
{
return std::ranges::all_of(data, [](u8 b) { return b == 0; });
return std::all_of(data.begin(), data.end(), [](u8 b) { return b == 0; });
}
void MulX()

View File

@ -91,7 +91,7 @@ void MemoryPatches::DisablePatch(const Core::CPUThreadGuard& guard, std::size_t
bool MemoryPatches::HasEnabledPatch(u32 address) const
{
return std::ranges::any_of(m_patches, [address](const MemoryPatch& patch) {
return std::any_of(m_patches.begin(), m_patches.end(), [address](const MemoryPatch& patch) {
return patch.address == address && patch.is_enabled == MemoryPatch::State::Enabled;
});
}

View File

@ -79,7 +79,7 @@ void Watches::DisableWatch(std::size_t index)
bool Watches::HasEnabledWatch(u32 address) const
{
return std::ranges::any_of(m_watches, [address](const auto& watch) {
return std::any_of(m_watches.begin(), m_watches.end(), [address](const auto& watch) {
return watch.address == address && watch.is_enabled == Watch::State::Enabled;
});
}

View File

@ -729,7 +729,7 @@ static bool Unpack(const std::function<bool()>& cancelled, const std::string pat
const bool is_path_traversal_attack =
(childname.find("\\") != std::string_view::npos) ||
(childname.find('/') != std::string_view::npos) ||
std::ranges::all_of(childname, [](char c) { return c == '.'; });
std::all_of(childname.begin(), childname.end(), [](char c) { return c == '.'; });
if (is_path_traversal_attack)
{
ERROR_LOG_FMT(

View File

@ -41,7 +41,7 @@ std::vector<std::string> DoFileSearch(const std::vector<std::string>& directorie
// N.B. This avoids doing any copies
auto ext_matches = [&native_exts](const fs::path& path) {
const std::basic_string_view<fs::path::value_type> native_path = path.native();
return std::ranges::any_of(native_exts, [&native_path](const auto& ext) {
return std::any_of(native_exts.cbegin(), native_exts.cend(), [&native_path](const auto& ext) {
const auto compare_len = ext.native().length();
if (native_path.length() < compare_len)
return false;
@ -98,8 +98,7 @@ std::vector<std::string> DoFileSearch(const std::vector<std::string>& directorie
// not because std::filesystem returns duplicates). Also note that this pathname-based uniqueness
// isn't as thorough as std::filesystem::equivalent.
std::ranges::sort(result);
const auto unique_result = std::ranges::unique(result);
result.erase(unique_result.begin(), unique_result.end());
result.erase(std::unique(result.begin(), result.end()), result.end());
// Dolphin expects to be able to use "/" (DIR_SEP) everywhere.
// std::filesystem uses the OS separator.

View File

@ -85,8 +85,7 @@ bool IniFile::Section::Delete(std::string_view key)
return false;
values.erase(it);
keys_order.erase(std::ranges::find_if(
keys_order, [&](std::string_view v) { return CaseInsensitiveEquals(key, v); }));
keys_order.erase(std::ranges::find(keys_order, key));
return true;
}

View File

@ -99,13 +99,7 @@ void GenericLogFmt(LogLevel level, LogType type, const char* file, int line, con
static_assert(NumFields == sizeof...(args),
"Unexpected number of replacement fields in format string; did you pass too few or "
"too many arguments?");
#if FMT_VERSION >= 110000
auto&& format_str = fmt::format_string<Args...>(format);
#else
auto&& format_str = format;
#endif
GenericLogFmtImpl(level, type, file, line, format_str, fmt::make_format_args(args...));
GenericLogFmtImpl(level, type, file, line, format, fmt::make_format_args(args...));
}
} // namespace Common::Log

View File

@ -1,48 +1,48 @@
// Copyright 2019 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <algorithm>
#include <mz_compat.h>
#include "Common/CommonTypes.h"
#include "Common/ScopeGuard.h"
namespace Common
{
// Reads all of the current file. destination must be big enough to fit the whole file.
inline bool ReadFileFromZip(unzFile file, u8* destination, u64 len)
{
const u64 MAX_BUFFER_SIZE = 65535;
if (unzOpenCurrentFile(file) != UNZ_OK)
return false;
Common::ScopeGuard guard{[&] { unzCloseCurrentFile(file); }};
u64 bytes_to_go = len;
while (bytes_to_go > 0)
{
// NOTE: multiples of 4G can't cause read_len == 0 && bytes_to_go > 0, as MAX_BUFFER_SIZE is
// small.
const u32 read_len = static_cast<u32>(std::min(bytes_to_go, MAX_BUFFER_SIZE));
const int rv = unzReadCurrentFile(file, destination, read_len);
if (rv < 0)
return false;
const u32 bytes_read = static_cast<u32>(rv);
bytes_to_go -= bytes_read;
destination += bytes_read;
}
return unzEndOfFile(file) == 1;
}
template <typename ContiguousContainer>
bool ReadFileFromZip(unzFile file, ContiguousContainer* destination)
{
return ReadFileFromZip(file, reinterpret_cast<u8*>(destination->data()), destination->size());
}
} // namespace Common
// Copyright 2019 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <algorithm>
#include <mz_compat.h>
#include "Common/CommonTypes.h"
#include "Common/ScopeGuard.h"
namespace Common
{
// Reads all of the current file. destination must be big enough to fit the whole file.
inline bool ReadFileFromZip(unzFile file, u8* destination, u64 len)
{
const u64 MAX_BUFFER_SIZE = 65535;
if (unzOpenCurrentFile(file) != UNZ_OK)
return false;
Common::ScopeGuard guard{[&] { unzCloseCurrentFile(file); }};
u64 bytes_to_go = len;
while (bytes_to_go > 0)
{
// NOTE: multiples of 4G can't cause read_len == 0 && bytes_to_go > 0, as MAX_BUFFER_SIZE is
// small.
const u32 read_len = static_cast<u32>(std::min(bytes_to_go, MAX_BUFFER_SIZE));
const int rv = unzReadCurrentFile(file, destination, read_len);
if (rv < 0)
return false;
const u32 bytes_read = static_cast<u32>(rv);
bytes_to_go -= bytes_read;
destination += bytes_read;
}
return unzEndOfFile(file) == 1;
}
template <typename ContiguousContainer>
bool ReadFileFromZip(unzFile file, ContiguousContainer* destination)
{
return ReadFileFromZip(file, reinterpret_cast<u8*>(destination->data()), destination->size());
}
} // namespace Common

View File

@ -41,17 +41,12 @@ bool MsgAlertFmt(bool yes_no, MsgType style, Common::Log::LogType log_type, cons
static_assert(NumFields == sizeof...(args),
"Unexpected number of replacement fields in format string; did you pass too few or "
"too many arguments?");
#if FMT_VERSION >= 110000
static_assert(std::is_base_of_v<fmt::detail::compile_string, S>);
auto&& format_str = fmt::format_string<Args...>(format);
#elif FMT_VERSION >= 90000
#if FMT_VERSION >= 90000
static_assert(fmt::detail::is_compile_string<S>::value);
auto&& format_str = format;
#else
static_assert(fmt::is_compile_string<S>::value);
auto&& format_str = format;
#endif
return MsgAlertFmtImpl(yes_no, style, log_type, file, line, format_str,
return MsgAlertFmtImpl(yes_no, style, log_type, file, line, format,
fmt::make_format_args(args...));
}
@ -65,9 +60,7 @@ bool MsgAlertFmtT(bool yes_no, MsgType style, Common::Log::LogType log_type, con
static_assert(NumFields == sizeof...(args),
"Unexpected number of replacement fields in format string; did you pass too few or "
"too many arguments?");
#if FMT_VERSION >= 110000
static_assert(std::is_base_of_v<fmt::detail::compile_string, S>);
#elif FMT_VERSION >= 90000
#if FMT_VERSION >= 90000
static_assert(fmt::detail::is_compile_string<S>::value);
#else
static_assert(fmt::is_compile_string<S>::value);

View File

@ -11,7 +11,6 @@
#include <fmt/ranges.h>
#include "Common/CommonTypes.h"
#include "Common/Contains.h"
#include "Common/FileUtil.h"
#include "Common/StringUtil.h"
@ -106,14 +105,15 @@ bool IsTitlePath(const std::string& path, std::optional<FromWhichRoot> from, u64
static bool IsIllegalCharacter(char c)
{
static constexpr char illegal_chars[] = {'\"', '*', '/', ':', '<', '>', '?', '\\', '|', '\x7f'};
return static_cast<unsigned char>(c) <= 0x1F || Common::Contains(illegal_chars, c);
static constexpr auto illegal_chars = {'\"', '*', '/', ':', '<', '>', '?', '\\', '|', '\x7f'};
return static_cast<unsigned char>(c) <= 0x1F ||
std::find(illegal_chars.begin(), illegal_chars.end(), c) != illegal_chars.end();
}
std::string EscapeFileName(const std::string& filename)
{
// Prevent paths from containing special names like ., .., ..., ...., and so on
if (std::ranges::all_of(filename, [](char c) { return c == '.'; }))
if (std::all_of(filename.begin(), filename.end(), [](char c) { return c == '.'; }))
return ReplaceAll(filename, ".", "__2e__");
// Escape all double underscores since we will use double underscores for our escape sequences
@ -170,7 +170,8 @@ std::string UnescapeFileName(const std::string& filename)
bool IsFileNameSafe(const std::string_view filename)
{
return !filename.empty() && !std::ranges::all_of(filename, [](char c) { return c == '.'; }) &&
std::ranges::none_of(filename, IsIllegalCharacter);
return !filename.empty() &&
!std::all_of(filename.begin(), filename.end(), [](char c) { return c == '.'; }) &&
std::none_of(filename.begin(), filename.end(), IsIllegalCharacter);
}
} // namespace Common

View File

@ -275,21 +275,6 @@ inline bool IsAlpha(char c)
return std::isalpha(c, std::locale::classic());
}
inline bool IsAlnum(char c)
{
return std::isalnum(c, std::locale::classic());
}
inline bool IsUpper(char c)
{
return std::isupper(c, std::locale::classic());
}
inline bool IsXDigit(char c)
{
return std::isxdigit(c /* no locale needed */) != 0;
}
inline char ToLower(char ch)
{
return std::tolower(ch, std::locale::classic());

View File

@ -132,6 +132,7 @@ public:
void DoIdle();
std::recursive_mutex& GetLock();
void SetHardcoreMode();
bool IsHardcoreModeActive() const;
void SetGameIniId(const std::string& game_ini_id) { m_game_ini_id = game_ini_id; }
@ -198,8 +199,6 @@ private:
void* userdata);
void DisplayWelcomeMessage();
void SetHardcoreMode();
template <typename T>
void FilterApprovedIni(std::vector<T>& codes, const std::string& game_ini_id) const;
template <typename T>

View File

@ -17,7 +17,6 @@
#include "Common/Assert.h"
#include "Common/CommonTypes.h"
#include "Common/Contains.h"
#include "Common/StringUtil.h"
#include "Core/Host.h"
#include "DiscIO/Enums.h"
@ -39,13 +38,17 @@ static std::optional<DiscIO::Language> TryParseLanguage(const std::string& local
// Special handling of Chinese due to its two writing systems
if (split_locale[0] == "zh")
{
if (Common::Contains(split_locale, "Hans"))
const auto locale_contains = [&split_locale](std::string_view str) {
return std::find(split_locale.cbegin(), split_locale.cend(), str) != split_locale.cend();
};
if (locale_contains("Hans"))
return DiscIO::Language::SimplifiedChinese;
if (Common::Contains(split_locale, "Hant"))
if (locale_contains("Hant"))
return DiscIO::Language::TraditionalChinese;
// Mainland China and Singapore use simplified characters
if (Common::Contains(split_locale, "CN") || Common::Contains(split_locale, "SG"))
if (locale_contains("CN") || locale_contains("SG"))
return DiscIO::Language::SimplifiedChinese;
else
return DiscIO::Language::TraditionalChinese;
@ -76,9 +79,11 @@ static DiscIO::Language ComputeDefaultLanguage()
static std::optional<std::string> TryParseCountryCode(const std::string& locale)
{
const auto is_upper = [](char c) { return std::isupper(c, std::locale::classic()); };
for (const std::string& part : SplitString(locale, '-'))
{
if (part.size() == 2 && Common::IsUpper(part[0]) && Common::IsUpper(part[1]))
if (part.size() == 2 && is_upper(part[0]) && is_upper(part[1]))
return part;
}

View File

@ -63,7 +63,7 @@ const Info<bool> GFX_CACHE_HIRES_TEXTURES{{System::GFX, "Settings", "CacheHiresT
const Info<bool> GFX_DUMP_EFB_TARGET{{System::GFX, "Settings", "DumpEFBTarget"}, false};
const Info<bool> GFX_DUMP_XFB_TARGET{{System::GFX, "Settings", "DumpXFBTarget"}, false};
const Info<bool> GFX_DUMP_FRAMES_AS_IMAGES{{System::GFX, "Settings", "DumpFramesAsImages"}, false};
const Info<bool> GFX_USE_LOSSLESS{{System::GFX, "Settings", "UseLossless"}, false};
const Info<bool> GFX_USE_FFV1{{System::GFX, "Settings", "UseFFV1"}, false};
const Info<std::string> GFX_DUMP_FORMAT{{System::GFX, "Settings", "DumpFormat"}, "avi"};
const Info<std::string> GFX_DUMP_CODEC{{System::GFX, "Settings", "DumpCodec"}, ""};
const Info<std::string> GFX_DUMP_PIXEL_FORMAT{{System::GFX, "Settings", "DumpPixelFormat"}, ""};

View File

@ -62,7 +62,7 @@ extern const Info<bool> GFX_CACHE_HIRES_TEXTURES;
extern const Info<bool> GFX_DUMP_EFB_TARGET;
extern const Info<bool> GFX_DUMP_XFB_TARGET;
extern const Info<bool> GFX_DUMP_FRAMES_AS_IMAGES;
extern const Info<bool> GFX_USE_LOSSLESS;
extern const Info<bool> GFX_USE_FFV1;
extern const Info<std::string> GFX_DUMP_FORMAT;
extern const Info<std::string> GFX_DUMP_CODEC;
extern const Info<std::string> GFX_DUMP_PIXEL_FORMAT;

View File

@ -114,8 +114,9 @@ public:
for (const auto& value : section_map)
{
const Config::Location location{system.first, section_name, value.first};
const bool load_disallowed = std::ranges::any_of(
s_setting_disallowed, [&location](const auto* l) { return *l == location; });
const bool load_disallowed =
std::any_of(begin(s_setting_disallowed), end(s_setting_disallowed),
[&location](const Config::Location* l) { return *l == location; });
if (load_disallowed)
continue;

View File

@ -6,7 +6,6 @@
#include <algorithm>
#include <array>
#include "Common/Contains.h"
#include "Core/Config/WiimoteSettings.h"
namespace ConfigLoaders
@ -16,7 +15,8 @@ bool IsSettingSaveable(const Config::Location& config_location)
static constexpr std::array systems_not_saveable = {Config::System::GCPad, Config::System::WiiPad,
Config::System::GCKeyboard};
if (!Common::Contains(systems_not_saveable, config_location.system))
if (std::find(begin(systems_not_saveable), end(systems_not_saveable), config_location.system) ==
end(systems_not_saveable))
{
return true;
}
@ -27,8 +27,9 @@ bool IsSettingSaveable(const Config::Location& config_location)
&Config::WIIMOTE_BB_SOURCE.GetLocation(),
};
return std::ranges::any_of(s_setting_saveable, [&config_location](const auto* location) {
return *location == config_location;
});
return std::any_of(begin(s_setting_saveable), end(s_setting_saveable),
[&config_location](const Config::Location* location) {
return *location == config_location;
});
}
} // namespace ConfigLoaders

View File

@ -41,7 +41,6 @@ static void LoadFromDTM(Config::Layer* config_layer, Movie::DTMHeader* dtm)
else
config_layer->Set(Config::MAIN_GC_LANGUAGE, static_cast<int>(dtm->language));
config_layer->Set(Config::SYSCONF_WIDESCREEN, dtm->bWidescreen);
config_layer->Set(Config::SYSCONF_COUNTRY, dtm->countryCode);
config_layer->Set(Config::GFX_HACK_EFB_ACCESS_ENABLE, dtm->bEFBAccessEnable);
config_layer->Set(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM, dtm->bSkipEFBCopyToRam);
@ -70,7 +69,6 @@ void SaveToDTM(Movie::DTMHeader* dtm)
else
dtm->language = Config::Get(Config::MAIN_GC_LANGUAGE);
dtm->bWidescreen = Config::Get(Config::SYSCONF_WIDESCREEN);
dtm->countryCode = Config::Get(Config::SYSCONF_COUNTRY);
dtm->bEFBAccessEnable = Config::Get(Config::GFX_HACK_EFB_ACCESS_ENABLE);
dtm->bSkipEFBCopyToRam = Config::Get(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM);

View File

@ -194,7 +194,7 @@ void DisplayMessage(std::string message, int time_in_ms)
return;
// Actually displaying non-ASCII could cause things to go pear-shaped
if (!std::ranges::all_of(message, Common::IsPrintableCharacter))
if (!std::all_of(message.begin(), message.end(), Common::IsPrintableCharacter))
return;
OSD::AddMessage(std::move(message), time_in_ms);

View File

@ -776,11 +776,14 @@ bool DSPAssembler::AssemblePass(const std::string& text, int pass)
m_location.line_num = 0;
m_cur_pass = pass;
constexpr int LINEBUF_SIZE = 1024;
char line[LINEBUF_SIZE] = {};
while (!m_failed && fsrc.getline(line, LINEBUF_SIZE))
#define LINEBUF_SIZE 1024
char line[LINEBUF_SIZE] = {0};
while (!m_failed && !fsrc.fail() && !fsrc.eof())
{
int opcode_size = 0;
fsrc.getline(line, LINEBUF_SIZE);
if (fsrc.fail())
break;
m_location.line_text = line;
m_location.line_num++;

View File

@ -7,7 +7,6 @@
#include <chrono>
#include <regex>
#include "Common/Contains.h"
#include "Common/Event.h"
#include "Core/Core.h"
#include "Core/Debugger/PPCDebugInterface.h"
@ -255,9 +254,12 @@ HitType CodeTrace::TraceLogic(const TraceOutput& current_instr, bool first_hit)
// The reg_itr will be used later for erasing.
auto reg_itr = std::ranges::find(m_reg_autotrack, instr.reg0);
const bool match_reg123 =
(!instr.reg1.empty() && Common::Contains(m_reg_autotrack, instr.reg1)) ||
(!instr.reg2.empty() && Common::Contains(m_reg_autotrack, instr.reg2)) ||
(!instr.reg3.empty() && Common::Contains(m_reg_autotrack, instr.reg3));
(!instr.reg1.empty() && std::find(m_reg_autotrack.begin(), m_reg_autotrack.end(),
instr.reg1) != m_reg_autotrack.end()) ||
(!instr.reg2.empty() && std::find(m_reg_autotrack.begin(), m_reg_autotrack.end(),
instr.reg2) != m_reg_autotrack.end()) ||
(!instr.reg3.empty() && std::find(m_reg_autotrack.begin(), m_reg_autotrack.end(),
instr.reg3) != m_reg_autotrack.end());
const bool match_reg0 = reg_itr != m_reg_autotrack.end();
if (!match_reg0 && !match_reg123 && !mem_hit)
@ -265,8 +267,8 @@ HitType CodeTrace::TraceLogic(const TraceOutput& current_instr, bool first_hit)
// Checks if the intstruction is a type that needs special handling.
const auto CompareInstruction = [](std::string_view instruction, const auto& type_compare) {
return std::ranges::any_of(
type_compare, [&instruction](std::string_view s) { return instruction.starts_with(s); });
return std::any_of(type_compare.begin(), type_compare.end(),
[&instruction](std::string_view s) { return instruction.starts_with(s); });
};
// Exclusions from updating tracking logic. mt operations are too complex and specialized.

View File

@ -13,7 +13,6 @@
#include <fmt/format.h>
#include "Common/Align.h"
#include "Common/Contains.h"
#include "Common/GekkoDisassembler.h"
#include "Common/StringUtil.h"
@ -254,7 +253,7 @@ Common::Debug::Threads PPCDebugInterface::GetThreads(const Core::CPUThreadGuard&
const auto insert_threads = [&guard, &threads, &visited_addrs](u32 addr, auto get_next_addr) {
while (addr != 0 && PowerPC::MMU::HostIsRAMAddress(guard, addr))
{
if (Common::Contains(visited_addrs, addr))
if (std::find(visited_addrs.begin(), visited_addrs.end(), addr) != visited_addrs.end())
break;
visited_addrs.push_back(addr);
auto thread = std::make_unique<Core::Debug::OSThreadView>(guard, addr);

View File

@ -17,10 +17,13 @@
namespace Gecko
{
std::vector<GeckoCode> DownloadCodes(std::string gametdb_id, bool* succeeded)
std::vector<GeckoCode> DownloadCodes(std::string gametdb_id, bool* succeeded, bool use_https)
{
// TODO: Fix https://bugs.dolphin-emu.org/issues/11772 so we don't need this workaround
const std::string protocol = use_https ? "https://" : "http://";
// codes.rc24.xyz is a mirror of the now defunct geckocodes.org.
std::string endpoint{"https://codes.rc24.xyz/txt.php?txt=" + gametdb_id};
std::string endpoint{protocol + "codes.rc24.xyz/txt.php?txt=" + gametdb_id};
Common::HttpRequest http;
// The server always redirects once to the same location.

View File

@ -17,7 +17,8 @@ class IniFile;
namespace Gecko
{
std::vector<GeckoCode> LoadCodes(const Common::IniFile& globalIni, const Common::IniFile& localIni);
std::vector<GeckoCode> DownloadCodes(std::string gametdb_id, bool* succeeded);
std::vector<GeckoCode> DownloadCodes(std::string gametdb_id, bool* succeeded,
bool use_https = true);
void SaveCodes(Common::IniFile& inifile, const std::vector<GeckoCode>& gcodes);
std::optional<GeckoCode::Code> DeserializeLine(const std::string& line);

View File

@ -686,7 +686,7 @@ bool CEXIETHERNET::BuiltInBBAInterface::SendFrame(const u8* frame, u32 size)
}
default:
ERROR_LOG_FMT(SP1, "Unsupported EtherType {:#06x}", *ethertype);
ERROR_LOG_FMT(SP1, "Unsupported EtherType {#06x}", *ethertype);
return false;
}

View File

@ -101,8 +101,8 @@ std::pair<GCMemcardErrorCode, std::optional<GCMemcard>> GCMemcard::Open(std::str
MBIT_SIZE_MEMORY_CARD_2043,
}};
if (!std::ranges::any_of(valid_megabits,
[filesize_megabits](u64 mbits) { return mbits == filesize_megabits; }))
if (!std::any_of(valid_megabits.begin(), valid_megabits.end(),
[filesize_megabits](u64 mbits) { return mbits == filesize_megabits; }))
{
error_code.Set(GCMemcardValidityIssues::INVALID_CARD_SIZE);
return std::make_pair(error_code, std::nullopt);
@ -1296,8 +1296,8 @@ GCMemcardErrorCode Header::CheckForErrors(u16 card_size_mbits) const
error_code.Set(GCMemcardValidityIssues::MISMATCHED_CARD_SIZE);
// unused areas, should always be filled with 0xFF
if (std::ranges::any_of(m_unused_1, [](u8 val) { return val != 0xFF; }) ||
std::ranges::any_of(m_unused_2, [](u8 val) { return val != 0xFF; }))
if (std::any_of(m_unused_1.begin(), m_unused_1.end(), [](u8 val) { return val != 0xFF; }) ||
std::any_of(m_unused_2.begin(), m_unused_2.end(), [](u8 val) { return val != 0xFF; }))
{
error_code.Set(GCMemcardValidityIssues::DATA_IN_UNUSED_AREA);
}
@ -1361,7 +1361,7 @@ GCMemcardErrorCode Directory::CheckForErrors() const
error_code.Set(GCMemcardValidityIssues::INVALID_CHECKSUM);
// unused area, should always be filled with 0xFF
if (std::ranges::any_of(m_padding, [](u8 val) { return val != 0xFF; }))
if (std::any_of(m_padding.begin(), m_padding.end(), [](u8 val) { return val != 0xFF; }))
error_code.Set(GCMemcardValidityIssues::DATA_IN_UNUSED_AREA);
return error_code;

View File

@ -613,7 +613,8 @@ void WiimoteScanner::SetScanMode(WiimoteScanMode scan_mode)
bool WiimoteScanner::IsReady() const
{
std::lock_guard lg(m_backends_mutex);
return std::ranges::any_of(m_backends, &WiimoteScannerBackend::IsReady);
return std::any_of(m_backends.begin(), m_backends.end(),
[](const auto& backend) { return backend->IsReady(); });
}
static void CheckForDisconnectedWiimotes()

View File

@ -98,8 +98,8 @@ bool IOCtlVRequest::HasNumberOfValidVectors(const size_t in_count, const size_t
return false;
auto IsValidVector = [](const auto& vector) { return vector.size == 0 || vector.address != 0; };
return std::ranges::all_of(in_vectors, IsValidVector) &&
std::ranges::all_of(io_vectors, IsValidVector);
return std::all_of(in_vectors.begin(), in_vectors.end(), IsValidVector) &&
std::all_of(io_vectors.begin(), io_vectors.end(), IsValidVector);
}
void IOCtlRequest::Log(std::string_view device_name, Common::Log::LogType type,

View File

@ -298,7 +298,7 @@ std::string TMDReader::GetGameID() const
std::memcpy(game_id, m_bytes.data() + offsetof(TMDHeader, title_id) + 4, 4);
std::memcpy(game_id + 4, m_bytes.data() + offsetof(TMDHeader, group_id), 2);
if (std::ranges::all_of(game_id, Common::IsPrintableCharacter))
if (std::all_of(std::begin(game_id), std::end(game_id), Common::IsPrintableCharacter))
return std::string(game_id, sizeof(game_id));
return fmt::format("{:016x}", GetTitleId());

View File

@ -79,7 +79,8 @@ static bool IsValidPartOfTitleID(const std::string& string)
{
if (string.length() != 8)
return false;
return std::ranges::all_of(string, Common::IsXDigit);
return std::all_of(string.begin(), string.end(),
[](const auto character) { return std::isxdigit(character) != 0; });
}
static std::vector<u64> GetTitlesInTitleOrImport(FS::FileSystem* fs, const std::string& titles_dir)

View File

@ -464,7 +464,7 @@ static bool HasAllRequiredContents(Kernel& ios, const ES::TMDReader& tmd)
const u64 title_id = tmd.GetTitleId();
const std::vector<ES::Content> contents = tmd.GetContents();
const ES::SharedContentMap shared_content_map{ios.GetFSCore()};
return std::ranges::all_of(contents, [&](const ES::Content& content) {
return std::all_of(contents.cbegin(), contents.cend(), [&](const ES::Content& content) {
if (content.IsOptional())
return true;
@ -878,7 +878,7 @@ ReturnCode ESCore::DeleteSharedContent(const std::array<u8, 20>& sha1) const
// Check whether the shared content is used by a system title.
const std::vector<u64> titles = GetInstalledTitles();
const bool is_used_by_system_title = std::ranges::any_of(titles, [&](u64 id) {
const bool is_used_by_system_title = std::any_of(titles.begin(), titles.end(), [&](u64 id) {
if (!ES::IsTitleType(id, ES::TitleType::System))
return false;
@ -887,8 +887,8 @@ ReturnCode ESCore::DeleteSharedContent(const std::array<u8, 20>& sha1) const
return true;
const auto contents = tmd.GetContents();
return std::ranges::any_of(contents,
[&sha1](const auto& content) { return content.sha1 == sha1; });
return std::any_of(contents.begin(), contents.end(),
[&sha1](const auto& content) { return content.sha1 == sha1; });
});
// Any shared content used by a system title cannot be deleted.

View File

@ -26,7 +26,7 @@ bool IsValidNonRootPath(std::string_view path)
bool IsValidFilename(std::string_view filename)
{
return filename.length() <= MaxFilenameLength &&
!std::ranges::any_of(filename, [](char c) { return c == '/'; });
!std::any_of(filename.begin(), filename.end(), [](char c) { return c == '/'; });
}
SplitPathResult SplitPathAndBasename(std::string_view path)

View File

@ -461,7 +461,8 @@ ResultCode HostFileSystem::Format(Uid uid)
ResultCode HostFileSystem::CreateFileOrDirectory(Uid uid, Gid gid, const std::string& path,
FileAttribute attr, Modes modes, bool is_file)
{
if (!IsValidNonRootPath(path) || !std::ranges::all_of(path, Common::IsPrintableCharacter))
if (!IsValidNonRootPath(path) ||
!std::all_of(path.begin(), path.end(), Common::IsPrintableCharacter))
{
return ResultCode::Invalid;
}
@ -515,14 +516,14 @@ ResultCode HostFileSystem::CreateDirectory(Uid uid, Gid gid, const std::string&
bool HostFileSystem::IsFileOpened(const std::string& path) const
{
return std::ranges::any_of(m_handles, [&path](const Handle& handle) {
return std::any_of(m_handles.begin(), m_handles.end(), [&path](const Handle& handle) {
return handle.opened && handle.wii_path == path;
});
}
bool HostFileSystem::IsDirectoryInUse(const std::string& path) const
{
return std::ranges::any_of(m_handles, [&path](const Handle& handle) {
return std::any_of(m_handles.begin(), m_handles.end(), [&path](const Handle& handle) {
return handle.opened && handle.wii_path.starts_with(path);
});
}

View File

@ -58,8 +58,8 @@ bool WC24FriendList::CheckFriendList() const
bool WC24FriendList::DoesFriendExist(u64 friend_id) const
{
return std::ranges::any_of(m_data.friend_codes,
[&friend_id](const u64 v) { return v == friend_id; });
return std::any_of(m_data.friend_codes.cbegin(), m_data.friend_codes.cend(),
[&friend_id](const u64 v) { return v == friend_id; });
}
std::vector<u64> WC24FriendList::GetUnconfirmedFriends() const

View File

@ -1085,10 +1085,10 @@ void WiiSockMan::UpdatePollCommands()
std::vector<int> original_order(pfds.size());
std::iota(original_order.begin(), original_order.end(), 0);
// Select indices with valid fds
const auto partition_result = std::ranges::partition(original_order, [&](auto i) {
auto mid = std::partition(original_order.begin(), original_order.end(), [&](auto i) {
return GetHostSocket(memory.Read_U32(pcmd.buffer_out + 0xc * i)) >= 0;
});
const auto n_valid = std::distance(original_order.begin(), partition_result.begin());
const auto n_valid = std::distance(original_order.begin(), mid);
// Move all the valid pollfds to the front of the vector
for (auto i = 0; i < n_valid; ++i)

View File

@ -74,7 +74,7 @@ bool Device::HasClass(const u8 device_class) const
if (GetDeviceDescriptor().bDeviceClass == device_class)
return true;
const auto interfaces = GetInterfaces(0);
return std::ranges::any_of(interfaces, [device_class](const auto& interface) {
return std::any_of(interfaces.begin(), interfaces.end(), [device_class](const auto& interface) {
return interface.bInterfaceClass == device_class;
});
}

View File

@ -234,7 +234,7 @@ std::optional<IPCReply> OH0::RegisterClassChangeHook(const IOCtlVRequest& reques
bool OH0::HasDeviceWithVidPid(const u16 vid, const u16 pid) const
{
return std::ranges::any_of(m_devices, [=](const auto& device) {
return std::any_of(m_devices.begin(), m_devices.end(), [=](const auto& device) {
return device.second->GetVid() == vid && device.second->GetPid() == pid;
});
}

View File

@ -380,9 +380,9 @@ bool IsEmulated(u32 major_version)
if (major_version == static_cast<u32>(Titles::BC & 0xffffffff))
return true;
return std::ranges::any_of(ios_memory_values, [major_version](const MemoryValues& values) {
return values.ios_number == major_version;
});
return std::any_of(
ios_memory_values.begin(), ios_memory_values.end(),
[major_version](const MemoryValues& values) { return values.ios_number == major_version; });
}
bool IsEmulated(u64 title_id)

View File

@ -375,8 +375,8 @@ s32 WFSSRVDevice::Rename(std::string source, std::string dest) const
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFS_RENAME: {} to {}", source, dest);
const bool opened =
std::ranges::any_of(m_fds, [&](const auto& fd) { return fd.in_use && fd.path == source; });
const bool opened = std::any_of(m_fds.begin(), m_fds.end(),
[&](const auto& fd) { return fd.in_use && fd.path == source; });
if (opened)
return WFS_FILE_IS_OPENED;

View File

@ -93,7 +93,7 @@ static std::array<u8, 20> ConvertGitRevisionToBytes(const std::string& revision)
{
std::array<u8, 20> revision_bytes{};
if (revision.size() % 2 == 0 && std::ranges::all_of(revision, Common::IsXDigit))
if (revision.size() % 2 == 0 && std::all_of(revision.begin(), revision.end(), ::isxdigit))
{
// The revision string normally contains a git commit hash,
// which is 40 hexadecimal digits long. In DTM files, each pair of
@ -1081,11 +1081,11 @@ void MovieManager::LoadInput(const std::string& movie_path)
std::vector<u8> movInput(m_current_byte);
t_record.ReadArray(movInput.data(), movInput.size());
const auto mismatch_result = std::ranges::mismatch(movInput, m_temp_input);
const auto result = std::mismatch(movInput.begin(), movInput.end(), m_temp_input.begin());
if (mismatch_result.in1 != movInput.end())
if (result.first != movInput.end())
{
const ptrdiff_t mismatch_index = std::distance(movInput.begin(), mismatch_result.in1);
const ptrdiff_t mismatch_index = std::distance(movInput.begin(), result.first);
// this is a "you did something wrong" alert for the user's benefit.
// we'll try to say what's going on in excruciating detail, otherwise the user might not

View File

@ -132,8 +132,7 @@ struct DTMHeader
bool bUseFMA;
u8 GBAControllers; // GBA Controllers plugged in (the bits are ports 1-4)
bool bWidescreen; // true indicates SYSCONF aspect ratio is 16:9, false for 4:3
u8 countryCode; // SYSCONF country code
std::array<u8, 5> reserved; // Padding for any new config options
std::array<u8, 6> reserved; // Padding for any new config options
std::array<char, 40> discChange; // Name of iso file to switch to, for two disc games.
std::array<u8, 20> revision; // Git hash
u32 DSPiromHash;

View File

@ -2486,8 +2486,8 @@ bool NetPlayClient::PlayerHasControllerMapped(const PlayerId pid) const
{
const auto mapping_matches_player_id = [pid](const PlayerId& mapping) { return mapping == pid; };
return std::ranges::any_of(m_pad_map, mapping_matches_player_id) ||
std::ranges::any_of(m_wiimote_map, mapping_matches_player_id);
return std::any_of(m_pad_map.begin(), m_pad_map.end(), mapping_matches_player_id) ||
std::any_of(m_wiimote_map.begin(), m_wiimote_map.end(), mapping_matches_player_id);
}
bool NetPlayClient::IsLocalPlayer(const PlayerId pid) const
@ -2543,7 +2543,7 @@ bool NetPlayClient::DoAllPlayersHaveGame()
{
std::lock_guard lkp(m_crit.players);
return std::ranges::all_of(m_players, [](const auto& entry) {
return std::all_of(std::begin(m_players), std::end(m_players), [](auto entry) {
return entry.second.game_status == SyncIdentifierComparison::SameGame;
});
}

View File

@ -237,7 +237,7 @@ static bool DecompressPacketIntoFolderInternal(sf::Packet& packet, const std::st
if (name.find('\\') != std::string::npos)
return false;
#endif
if (std::ranges::all_of(name, [](char c) { return c == '.'; }))
if (std::all_of(name.begin(), name.end(), [](char c) { return c == '.'; }))
return false;
bool is_folder;

View File

@ -1060,14 +1060,14 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, Client& player)
{
// we have all records for this frame
if (!std::ranges::all_of(timebases, [&](std::pair<PlayerId, u64> pair) {
if (!std::all_of(timebases.begin(), timebases.end(), [&](std::pair<PlayerId, u64> pair) {
return pair.second == timebases[0].second;
}))
{
int pid_to_blame = 0;
for (auto pair : timebases)
{
if (std::ranges::all_of(timebases, [&](std::pair<PlayerId, u64> other) {
if (std::all_of(timebases.begin(), timebases.end(), [&](std::pair<PlayerId, u64> other) {
return other.first == pair.first || other.second != pair.second;
}))
{
@ -1467,12 +1467,14 @@ bool NetPlayServer::SetupNetSettings()
bool NetPlayServer::DoAllPlayersHaveIPLDump() const
{
return std::ranges::all_of(m_players, [](const auto& p) { return p.second.has_ipl_dump; });
return std::all_of(m_players.begin(), m_players.end(),
[](const auto& p) { return p.second.has_ipl_dump; });
}
bool NetPlayServer::DoAllPlayersHaveHardwareFMA() const
{
return std::ranges::all_of(m_players, [](const auto& p) { return p.second.has_hardware_fma; });
return std::all_of(m_players.begin(), m_players.end(),
[](const auto& p) { return p.second.has_hardware_fma; });
}
struct SaveSyncInfo
@ -2232,8 +2234,8 @@ bool NetPlayServer::PlayerHasControllerMapped(const PlayerId pid) const
{
const auto mapping_matches_player_id = [pid](const PlayerId& mapping) { return mapping == pid; };
return std::ranges::any_of(m_pad_map, mapping_matches_player_id) ||
std::ranges::any_of(m_wiimote_map, mapping_matches_player_id);
return std::any_of(m_pad_map.begin(), m_pad_map.end(), mapping_matches_player_id) ||
std::any_of(m_wiimote_map.begin(), m_wiimote_map.end(), mapping_matches_player_id);
}
void NetPlayServer::AssignNewUserAPad(const Client& player)

View File

@ -371,7 +371,7 @@ bool MemChecks::OverlapsMemcheck(u32 address, u32 length) const
const u32 page_end_suffix = length - 1;
const u32 page_end_address = address | page_end_suffix;
return std::ranges::any_of(m_mem_checks, [&](const auto& mc) {
return std::any_of(m_mem_checks.cbegin(), m_mem_checks.cend(), [&](const auto& mc) {
return ((mc.start_address | page_end_suffix) == page_end_address ||
(mc.end_address | page_end_suffix) == page_end_address) ||
((mc.start_address | page_end_suffix) < page_end_address &&

View File

@ -136,14 +136,15 @@ static double CallstackFunc(expr_func* f, vec_expr_t* args, void* c)
if (!std::isnan(num))
{
u32 address = static_cast<u32>(num);
return std::ranges::any_of(stack, [address](const auto& s) { return s.vAddress == address; });
return std::any_of(stack.begin(), stack.end(),
[address](const auto& s) { return s.vAddress == address; });
}
const char* cstr = expr_get_str(&vec_nth(args, 0));
if (cstr != nullptr)
{
return std::ranges::any_of(
stack, [cstr](const auto& s) { return s.Name.find(cstr) != std::string::npos; });
return std::any_of(stack.begin(), stack.end(),
[cstr](const auto& s) { return s.Name.find(cstr) != std::string::npos; });
}
return 0;

View File

@ -644,20 +644,6 @@ void Jit64::fselx(UGeckoInstruction inst)
if (cpu_info.bAVX)
{
// Prefer BLENDVPD over VBLENDVPD if the latter doesn't save any
// instructions.
//
// VBLENDVPD allows separate source and destination registers, which can
// eliminate a MOVAPD/MOVSD. However, on Intel since Skylake, VBLENDVPD
// takes additional uops to execute compared to BLENDVPD (according to
// https://uops.info). On AMD and older Intel microarchitectures there is no
// difference.
if (d == c)
{
BLENDVPD(Rd, Rb);
return;
}
X64Reg src1 = XMM1;
if (Rc.IsSimpleReg())
{
@ -668,7 +654,7 @@ void Jit64::fselx(UGeckoInstruction inst)
MOVAPD(XMM1, Rc);
}
if (packed)
if (d == c || packed)
{
VBLENDVPD(Rd, src1, Rb, XMM0);
return;

View File

@ -369,8 +369,10 @@ RCForkGuard RegCache::Fork()
void RegCache::Discard(BitSet32 pregs)
{
ASSERT_MSG(DYNA_REC, std::ranges::none_of(m_xregs, &X64CachedReg::IsLocked),
"Someone forgot to unlock a X64 reg");
ASSERT_MSG(
DYNA_REC,
std::none_of(m_xregs.begin(), m_xregs.end(), [](const auto& x) { return x.IsLocked(); }),
"Someone forgot to unlock a X64 reg");
for (preg_t i : pregs)
{
@ -391,8 +393,10 @@ void RegCache::Discard(BitSet32 pregs)
void RegCache::Flush(BitSet32 pregs, IgnoreDiscardedRegisters ignore_discarded_registers)
{
ASSERT_MSG(DYNA_REC, std::ranges::none_of(m_xregs, &X64CachedReg::IsLocked),
"Someone forgot to unlock a X64 reg");
ASSERT_MSG(
DYNA_REC,
std::none_of(m_xregs.begin(), m_xregs.end(), [](const auto& x) { return x.IsLocked(); }),
"Someone forgot to unlock a X64 reg");
for (preg_t i : pregs)
{
@ -455,8 +459,9 @@ void RegCache::Commit()
bool RegCache::IsAllUnlocked() const
{
return std::ranges::none_of(m_regs, &PPCCachedReg::IsLocked) &&
std::ranges::none_of(m_xregs, &X64CachedReg::IsLocked) && !IsAnyConstraintActive();
return std::none_of(m_regs.begin(), m_regs.end(), [](const auto& r) { return r.IsLocked(); }) &&
std::none_of(m_xregs.begin(), m_xregs.end(), [](const auto& x) { return x.IsLocked(); }) &&
!IsAnyConstraintActive();
}
void RegCache::PreloadRegisters(BitSet32 to_preload)
@ -749,5 +754,6 @@ void RegCache::Realize(preg_t preg)
bool RegCache::IsAnyConstraintActive() const
{
return std::ranges::any_of(m_constraints, &RCConstraint::IsActive);
return std::any_of(m_constraints.begin(), m_constraints.end(),
[](const auto& c) { return c.IsActive(); });
}

View File

@ -355,13 +355,8 @@ protected:
Arm64Gen::ARM64Reg exit_address_after_return_reg = Arm64Gen::ARM64Reg::INVALID_REG);
void WriteBLRExit(Arm64Gen::ARM64Reg dest);
void GetCRFieldBit(int field, int bit, Arm64Gen::ARM64Reg out);
void SetCRFieldBit(int field, int bit, Arm64Gen::ARM64Reg in, bool negate = false);
void ClearCRFieldBit(int field, int bit);
void SetCRFieldBit(int field, int bit);
void FixGTBeforeSettingCRFieldBit(Arm64Gen::ARM64Reg reg);
Arm64Gen::FixupBranch JumpIfCRFieldBit(int field, int bit, bool jump_if_set);
void FixGTBeforeSettingCRFieldBit(Arm64Gen::ARM64Reg reg);
void UpdateFPExceptionSummary(Arm64Gen::ARM64Reg fpscr);
void UpdateRoundingMode();

View File

@ -765,14 +765,6 @@ void JitArm64::rlwinmx_internal(UGeckoInstruction inst, u32 sh)
return;
}
if (mask == 0)
{
gpr.SetImmediate(a, 0);
if (inst.Rc)
ComputeRC0(0);
return;
}
gpr.BindToRegister(a, a == s);
if (sh == 0 && mask == 0xFFFFFFFF)
@ -1136,85 +1128,47 @@ void JitArm64::addzex(UGeckoInstruction inst)
int a = inst.RA, d = inst.RD;
if (gpr.IsImm(a) && (gpr.GetImm(a) == 0 || HasConstantCarry()))
switch (js.carryFlag)
{
const u32 imm = gpr.GetImm(a);
const bool is_all_ones = imm == 0xFFFFFFFF;
case CarryFlag::InPPCState:
{
const bool allocate_reg = d == a;
gpr.BindToRegister(d, allocate_reg);
switch (js.carryFlag)
{
case CarryFlag::InPPCState:
{
gpr.BindToRegister(d, false);
LDRB(IndexType::Unsigned, gpr.R(d), PPC_REG, PPCSTATE_OFF(xer_ca));
ComputeCarry(false);
break;
}
case CarryFlag::InHostCarry:
{
gpr.BindToRegister(d, false);
CSET(gpr.R(d), CCFlags::CC_CS);
ComputeCarry(false);
break;
}
case CarryFlag::ConstantTrue:
{
gpr.SetImmediate(d, imm + 1);
ComputeCarry(is_all_ones);
break;
}
case CarryFlag::ConstantFalse:
{
gpr.SetImmediate(d, imm);
ComputeCarry(false);
break;
}
auto WA = allocate_reg ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(gpr.R(d));
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(a), WA);
}
ComputeCarry();
break;
}
else
case CarryFlag::InHostCarry:
{
switch (js.carryFlag)
gpr.BindToRegister(d, d == a);
CARRY_IF_NEEDED(ADC, ADCS, gpr.R(d), gpr.R(a), ARM64Reg::WZR);
ComputeCarry();
break;
}
case CarryFlag::ConstantTrue:
{
gpr.BindToRegister(d, d == a);
CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(a), 1);
ComputeCarry();
break;
}
case CarryFlag::ConstantFalse:
{
if (d != a)
{
case CarryFlag::InPPCState:
{
const bool allocate_reg = d == a;
gpr.BindToRegister(d, allocate_reg);
gpr.BindToRegister(d, false);
MOV(gpr.R(d), gpr.R(a));
}
{
auto WA = allocate_reg ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(gpr.R(d));
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(a), WA);
}
ComputeCarry();
break;
}
case CarryFlag::InHostCarry:
{
gpr.BindToRegister(d, d == a);
CARRY_IF_NEEDED(ADC, ADCS, gpr.R(d), gpr.R(a), ARM64Reg::WZR);
ComputeCarry();
break;
}
case CarryFlag::ConstantTrue:
{
gpr.BindToRegister(d, d == a);
CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(a), 1);
ComputeCarry();
break;
}
case CarryFlag::ConstantFalse:
{
if (d != a)
{
gpr.BindToRegister(d, false);
MOV(gpr.R(d), gpr.R(a));
}
ComputeCarry(false);
break;
}
}
ComputeCarry(false);
break;
}
}
if (inst.Rc)
@ -1262,62 +1216,40 @@ void JitArm64::subfex(UGeckoInstruction inst)
if (gpr.IsImm(a) && (mex || gpr.IsImm(b)))
{
const u32 i = gpr.GetImm(a);
const u32 j = mex ? -1 : gpr.GetImm(b);
const u32 imm = ~i + j;
const bool is_zero = imm == 0;
const bool is_all_ones = imm == 0xFFFFFFFF;
u32 i = gpr.GetImm(a), j = mex ? -1 : gpr.GetImm(b);
gpr.BindToRegister(d, false);
switch (js.carryFlag)
{
case CarryFlag::InPPCState:
{
gpr.BindToRegister(d, false);
ARM64Reg RD = gpr.R(d);
if (is_zero)
{
LDRB(IndexType::Unsigned, RD, PPC_REG, PPCSTATE_OFF(xer_ca));
}
else
{
auto WA = gpr.GetScopedReg();
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
ADDI2R(RD, WA, imm, RD);
}
auto WA = gpr.GetScopedReg();
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
ADDI2R(gpr.R(d), WA, ~i + j, gpr.R(d));
break;
}
case CarryFlag::InHostCarry:
{
gpr.BindToRegister(d, false);
ARM64Reg RD = gpr.R(d);
if (is_all_ones)
{
// RD = -1 + carry = carry ? 0 : -1
// CSETM sets the destination to -1 if the condition is true, 0
// otherwise. Hence, the condition must be carry clear.
CSETM(RD, CC_CC);
}
else
{
MOVI2R(RD, imm);
ADC(RD, RD, ARM64Reg::WZR);
}
auto WA = gpr.GetScopedReg();
MOVI2R(WA, ~i + j);
ADC(gpr.R(d), WA, ARM64Reg::WZR);
break;
}
case CarryFlag::ConstantTrue:
{
gpr.SetImmediate(d, imm + 1);
gpr.SetImmediate(d, ~i + j + 1);
break;
}
case CarryFlag::ConstantFalse:
{
gpr.SetImmediate(d, imm);
gpr.SetImmediate(d, ~i + j);
break;
}
}
const bool must_have_carry = Interpreter::Helper_Carry(~i, j);
const bool might_have_carry = is_all_ones;
const bool might_have_carry = (~i + j) == 0xFFFFFFFF;
if (must_have_carry)
{
@ -1405,49 +1337,39 @@ void JitArm64::subfzex(UGeckoInstruction inst)
int a = inst.RA, d = inst.RD;
if (gpr.IsImm(a) && HasConstantCarry())
{
const u32 imm = ~gpr.GetImm(a);
const u32 carry = js.carryFlag == CarryFlag::ConstantTrue;
gpr.SetImmediate(d, imm + carry);
ComputeCarry(Interpreter::Helper_Carry(imm, carry));
}
else
{
gpr.BindToRegister(d, d == a);
gpr.BindToRegister(d, d == a);
switch (js.carryFlag)
{
case CarryFlag::InPPCState:
{
{
auto WA = gpr.GetScopedReg();
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
MVN(gpr.R(d), gpr.R(a));
CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(d), WA);
}
ComputeCarry();
break;
}
case CarryFlag::InHostCarry:
{
CARRY_IF_NEEDED(SBC, SBCS, gpr.R(d), ARM64Reg::WZR, gpr.R(a));
ComputeCarry();
break;
}
case CarryFlag::ConstantTrue:
{
CARRY_IF_NEEDED(NEG, NEGS, gpr.R(d), gpr.R(a));
ComputeCarry();
break;
}
case CarryFlag::ConstantFalse:
switch (js.carryFlag)
{
case CarryFlag::InPPCState:
{
{
auto WA = gpr.GetScopedReg();
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
MVN(gpr.R(d), gpr.R(a));
ComputeCarry(false);
break;
}
CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(d), WA);
}
ComputeCarry();
break;
}
case CarryFlag::InHostCarry:
{
CARRY_IF_NEEDED(SBC, SBCS, gpr.R(d), ARM64Reg::WZR, gpr.R(a));
ComputeCarry();
break;
}
case CarryFlag::ConstantTrue:
{
CARRY_IF_NEEDED(NEG, NEGS, gpr.R(d), gpr.R(a));
ComputeCarry();
break;
}
case CarryFlag::ConstantFalse:
{
MVN(gpr.R(d), gpr.R(a));
ComputeCarry(false);
break;
}
}
if (inst.Rc)
@ -1472,34 +1394,23 @@ void JitArm64::subfic(UGeckoInstruction inst)
else
{
const bool will_read = d == a;
const bool is_zero = imm == 0;
gpr.BindToRegister(d, will_read);
// d = imm - a
ARM64Reg RD = gpr.R(d);
if (imm == -1)
{
// d = -1 - a = ~a
MVN(RD, gpr.R(a));
// CA is always set in this case
ComputeCarry(true);
}
else
{
const bool is_zero = imm == 0;
// d = imm - a
Arm64GPRCache::ScopedARM64Reg WA(ARM64Reg::WZR);
if (!is_zero)
{
Arm64GPRCache::ScopedARM64Reg WA(ARM64Reg::WZR);
if (!is_zero)
{
WA = will_read ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(RD);
MOVI2R(WA, imm);
}
CARRY_IF_NEEDED(SUB, SUBS, RD, WA, gpr.R(a));
WA = will_read ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(RD);
MOVI2R(WA, imm);
}
ComputeCarry();
CARRY_IF_NEEDED(SUB, SUBS, RD, WA, gpr.R(a));
}
ComputeCarry();
}
}
@ -1514,66 +1425,40 @@ void JitArm64::addex(UGeckoInstruction inst)
if (gpr.IsImm(a) && (mex || gpr.IsImm(b)))
{
const u32 i = gpr.GetImm(a), j = mex ? -1 : gpr.GetImm(b);
const u32 imm = i + j;
const bool is_zero = imm == 0;
const bool is_all_ones = imm == 0xFFFFFFFF;
u32 i = gpr.GetImm(a), j = mex ? -1 : gpr.GetImm(b);
gpr.BindToRegister(d, false);
switch (js.carryFlag)
{
case CarryFlag::InPPCState:
{
gpr.BindToRegister(d, false);
ARM64Reg RD = gpr.R(d);
if (is_zero)
{
LDRB(IndexType::Unsigned, RD, PPC_REG, PPCSTATE_OFF(xer_ca));
}
else
{
auto WA = gpr.GetScopedReg();
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
ADDI2R(RD, WA, imm, RD);
}
auto WA = gpr.GetScopedReg();
LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca));
ADDI2R(gpr.R(d), WA, i + j, gpr.R(d));
break;
}
case CarryFlag::InHostCarry:
{
gpr.BindToRegister(d, false);
ARM64Reg RD = gpr.R(d);
if (is_zero)
{
// RD = 0 + carry = carry ? 1 : 0
CSET(RD, CC_CS);
}
else if (is_all_ones)
{
// RD = -1 + carry = carry ? 0 : -1
// Note that CSETM sets the destination to -1 if the condition is true,
// and 0 otherwise. Hence, the condition must be carry clear.
CSETM(RD, CC_CC);
}
else
{
MOVI2R(RD, imm);
ADC(RD, RD, ARM64Reg::WZR);
}
MOVI2R(RD, i + j);
ADC(RD, RD, ARM64Reg::WZR);
break;
}
case CarryFlag::ConstantTrue:
{
gpr.SetImmediate(d, imm + 1);
gpr.SetImmediate(d, i + j + 1);
break;
}
case CarryFlag::ConstantFalse:
{
gpr.SetImmediate(d, imm);
gpr.SetImmediate(d, i + j);
break;
}
}
const bool must_have_carry = Interpreter::Helper_Carry(i, j);
const bool might_have_carry = is_all_ones;
const bool might_have_carry = (i + j) == 0xFFFFFFFF;
if (must_have_carry)
{

View File

@ -817,8 +817,9 @@ void JitArm64::dcbx(UGeckoInstruction inst)
STR(IndexType::Unsigned, loop_counter, PPC_REG, PPCSTATE_OFF_SPR(SPR_CTR));
// downcount -= (WA * reg_cycle_count)
MSUB(reg_downcount, WA, reg_cycle_count, reg_downcount);
MUL(WB, WA, reg_cycle_count);
// ^ Note that this cannot overflow because it's limited by (downcount/cycle_count).
SUB(reg_downcount, reg_downcount, WB);
STR(IndexType::Unsigned, reg_downcount, PPC_REG, PPCSTATE_OFF(downcount));
SetJumpTarget(downcount_is_zero_or_negative);

View File

@ -7,7 +7,6 @@
#include "Common/CommonTypes.h"
#include "Common/Config/Config.h"
#include "Common/StringUtil.h"
#include "Common/Unreachable.h"
#include "Core/Config/SessionSettings.h"
#include "Core/ConfigManager.h"
@ -338,12 +337,8 @@ void JitArm64::ps_sel(UGeckoInstruction inst)
const auto V0Q = fpr.GetScopedReg();
const ARM64Reg V0 = reg_encoder(V0Q);
m_float_emit.FCMGE(size, V0, VA);
if (d == b)
m_float_emit.BIT(VD, VC, V0);
else if (d == c)
m_float_emit.BIF(VD, VB, V0);
else
Common::Unreachable();
m_float_emit.BSL(V0, VC, VB);
m_float_emit.MOV(VD, V0);
}
ASSERT_MSG(DYNA_REC, singles == (fpr.IsSingle(a) && fpr.IsSingle(b) && fpr.IsSingle(c)),

View File

@ -20,144 +20,6 @@
using namespace Arm64Gen;
void JitArm64::GetCRFieldBit(int field, int bit, ARM64Reg out)
{
ARM64Reg CR = gpr.CR(field);
ARM64Reg WCR = EncodeRegTo32(CR);
switch (bit)
{
case PowerPC::CR_SO_BIT: // check bit 59 set
UBFX(out, CR, PowerPC::CR_EMU_SO_BIT, 1);
break;
case PowerPC::CR_EQ_BIT: // check bits 31-0 == 0
CMP(WCR, ARM64Reg::WZR);
CSET(out, CC_EQ);
break;
case PowerPC::CR_GT_BIT: // check val > 0
CMP(CR, ARM64Reg::ZR);
CSET(out, CC_GT);
break;
case PowerPC::CR_LT_BIT: // check bit 62 set
UBFX(out, CR, PowerPC::CR_EMU_LT_BIT, 1);
break;
default:
ASSERT_MSG(DYNA_REC, false, "Invalid CR bit");
}
}
void JitArm64::SetCRFieldBit(int field, int bit, ARM64Reg in, bool negate)
{
gpr.BindCRToRegister(field, true);
ARM64Reg CR = gpr.CR(field);
if (bit != PowerPC::CR_GT_BIT)
FixGTBeforeSettingCRFieldBit(CR);
switch (bit)
{
case PowerPC::CR_SO_BIT: // set bit 59 to input
BFI(CR, in, PowerPC::CR_EMU_SO_BIT, 1);
if (negate)
EOR(CR, CR, LogicalImm(1ULL << PowerPC::CR_EMU_SO_BIT, GPRSize::B64));
break;
case PowerPC::CR_EQ_BIT: // clear low 32 bits, set bit 0 to !input
AND(CR, CR, LogicalImm(0xFFFF'FFFF'0000'0000, GPRSize::B64));
ORR(CR, CR, in);
if (!negate)
EOR(CR, CR, LogicalImm(1ULL << 0, GPRSize::B64));
break;
case PowerPC::CR_GT_BIT: // set bit 63 to !input
BFI(CR, in, 63, 1);
if (!negate)
EOR(CR, CR, LogicalImm(1ULL << 63, GPRSize::B64));
break;
case PowerPC::CR_LT_BIT: // set bit 62 to input
BFI(CR, in, PowerPC::CR_EMU_LT_BIT, 1);
if (negate)
EOR(CR, CR, LogicalImm(1ULL << PowerPC::CR_EMU_LT_BIT, GPRSize::B64));
break;
}
ORR(CR, CR, LogicalImm(1ULL << 32, GPRSize::B64));
}
void JitArm64::ClearCRFieldBit(int field, int bit)
{
gpr.BindCRToRegister(field, true);
ARM64Reg XA = gpr.CR(field);
switch (bit)
{
case PowerPC::CR_SO_BIT:
AND(XA, XA, LogicalImm(~(u64(1) << PowerPC::CR_EMU_SO_BIT), GPRSize::B64));
break;
case PowerPC::CR_EQ_BIT:
FixGTBeforeSettingCRFieldBit(XA);
ORR(XA, XA, LogicalImm(1, GPRSize::B64));
break;
case PowerPC::CR_GT_BIT:
ORR(XA, XA, LogicalImm(u64(1) << 63, GPRSize::B64));
break;
case PowerPC::CR_LT_BIT:
AND(XA, XA, LogicalImm(~(u64(1) << PowerPC::CR_EMU_LT_BIT), GPRSize::B64));
break;
}
}
void JitArm64::SetCRFieldBit(int field, int bit)
{
gpr.BindCRToRegister(field, true);
ARM64Reg XA = gpr.CR(field);
if (bit != PowerPC::CR_GT_BIT)
FixGTBeforeSettingCRFieldBit(XA);
switch (bit)
{
case PowerPC::CR_SO_BIT:
ORR(XA, XA, LogicalImm(u64(1) << PowerPC::CR_EMU_SO_BIT, GPRSize::B64));
break;
case PowerPC::CR_EQ_BIT:
AND(XA, XA, LogicalImm(0xFFFF'FFFF'0000'0000, GPRSize::B64));
break;
case PowerPC::CR_GT_BIT:
AND(XA, XA, LogicalImm(~(u64(1) << 63), GPRSize::B64));
break;
case PowerPC::CR_LT_BIT:
ORR(XA, XA, LogicalImm(u64(1) << PowerPC::CR_EMU_LT_BIT, GPRSize::B64));
break;
}
ORR(XA, XA, LogicalImm(u64(1) << 32, GPRSize::B64));
}
void JitArm64::FixGTBeforeSettingCRFieldBit(ARM64Reg reg)
{
// GT is considered unset if the internal representation is <= 0, or in other words,
// if the internal representation either has bit 63 set or has all bits set to zero.
// If all bits are zero and we set some bit that's unrelated to GT, we need to set bit 63 so GT
// doesn't accidentally become considered set. Gross but necessary; this can break actual games.
auto WA = gpr.GetScopedReg();
ARM64Reg XA = EncodeRegTo64(WA);
ORR(XA, reg, LogicalImm(1ULL << 63, GPRSize::B64));
CMP(reg, ARM64Reg::ZR);
CSEL(reg, reg, XA, CC_NEQ);
}
FixupBranch JitArm64::JumpIfCRFieldBit(int field, int bit, bool jump_if_set)
{
ARM64Reg XA = gpr.CR(field);
@ -180,6 +42,19 @@ FixupBranch JitArm64::JumpIfCRFieldBit(int field, int bit, bool jump_if_set)
}
}
void JitArm64::FixGTBeforeSettingCRFieldBit(Arm64Gen::ARM64Reg reg)
{
// GT is considered unset if the internal representation is <= 0, or in other words,
// if the internal representation either has bit 63 set or has all bits set to zero.
// If all bits are zero and we set some bit that's unrelated to GT, we need to set bit 63 so GT
// doesn't accidentally become considered set. Gross but necessary; this can break actual games.
auto WA = gpr.GetScopedReg();
ARM64Reg XA = EncodeRegTo64(WA);
ORR(XA, reg, LogicalImm(1ULL << 63, GPRSize::B64));
CMP(reg, ARM64Reg::ZR);
CSEL(reg, reg, XA, CC_NEQ);
}
void JitArm64::UpdateFPExceptionSummary(ARM64Reg fpscr)
{
auto WA = gpr.GetScopedReg();
@ -593,47 +468,72 @@ void JitArm64::crXXX(UGeckoInstruction inst)
INSTRUCTION_START
JITDISABLE(bJITSystemRegistersOff);
if (inst.CRBA == inst.CRBB)
// Special case: crclr
if (inst.CRBA == inst.CRBB && inst.CRBA == inst.CRBD && inst.SUBOP10 == 193)
{
switch (inst.SUBOP10)
// Clear CR field bit
int field = inst.CRBD >> 2;
int bit = 3 - (inst.CRBD & 3);
gpr.BindCRToRegister(field, true);
ARM64Reg XA = gpr.CR(field);
switch (bit)
{
// crclr
case 129: // crandc: A && ~B => 0
case 193: // crxor: A ^ B => 0
{
ClearCRFieldBit(inst.CRBD >> 2, 3 - (inst.CRBD & 3));
return;
}
// crset
case 289: // creqv: ~(A ^ B) => 1
case 417: // crorc: A || ~B => 1
{
SetCRFieldBit(inst.CRBD >> 2, 3 - (inst.CRBD & 3));
return;
}
case 257: // crand: A && B => A
case 449: // cror: A || B => A
{
auto WA = gpr.GetScopedReg();
ARM64Reg XA = EncodeRegTo64(WA);
GetCRFieldBit(inst.CRBA >> 2, 3 - (inst.CRBA & 3), XA);
SetCRFieldBit(inst.CRBD >> 2, 3 - (inst.CRBD & 3), XA, false);
return;
}
case 33: // crnor: ~(A || B) => ~A
case 225: // crnand: ~(A && B) => ~A
{
auto WA = gpr.GetScopedReg();
ARM64Reg XA = EncodeRegTo64(WA);
GetCRFieldBit(inst.CRBA >> 2, 3 - (inst.CRBA & 3), XA);
SetCRFieldBit(inst.CRBD >> 2, 3 - (inst.CRBD & 3), XA, true);
return;
}
case PowerPC::CR_SO_BIT:
AND(XA, XA, LogicalImm(~(u64(1) << PowerPC::CR_EMU_SO_BIT), GPRSize::B64));
break;
case PowerPC::CR_EQ_BIT:
FixGTBeforeSettingCRFieldBit(XA);
ORR(XA, XA, LogicalImm(1, GPRSize::B64));
break;
case PowerPC::CR_GT_BIT:
ORR(XA, XA, LogicalImm(u64(1) << 63, GPRSize::B64));
break;
case PowerPC::CR_LT_BIT:
AND(XA, XA, LogicalImm(~(u64(1) << PowerPC::CR_EMU_LT_BIT), GPRSize::B64));
break;
}
return;
}
// crnor or crnand
const bool negate_result = inst.SUBOP10 == 33 || inst.SUBOP10 == 225;
// Special case: crset
if (inst.CRBA == inst.CRBB && inst.CRBA == inst.CRBD && inst.SUBOP10 == 289)
{
// SetCRFieldBit
int field = inst.CRBD >> 2;
int bit = 3 - (inst.CRBD & 3);
gpr.BindCRToRegister(field, true);
ARM64Reg XA = gpr.CR(field);
if (bit != PowerPC::CR_GT_BIT)
FixGTBeforeSettingCRFieldBit(XA);
switch (bit)
{
case PowerPC::CR_SO_BIT:
ORR(XA, XA, LogicalImm(u64(1) << PowerPC::CR_EMU_SO_BIT, GPRSize::B64));
break;
case PowerPC::CR_EQ_BIT:
AND(XA, XA, LogicalImm(0xFFFF'FFFF'0000'0000, GPRSize::B64));
break;
case PowerPC::CR_GT_BIT:
AND(XA, XA, LogicalImm(~(u64(1) << 63), GPRSize::B64));
break;
case PowerPC::CR_LT_BIT:
ORR(XA, XA, LogicalImm(u64(1) << PowerPC::CR_EMU_LT_BIT, GPRSize::B64));
break;
}
ORR(XA, XA, LogicalImm(u64(1) << 32, GPRSize::B64));
return;
}
auto WA = gpr.GetScopedReg();
ARM64Reg XA = EncodeRegTo64(WA);
@ -641,42 +541,106 @@ void JitArm64::crXXX(UGeckoInstruction inst)
auto WB = gpr.GetScopedReg();
ARM64Reg XB = EncodeRegTo64(WB);
GetCRFieldBit(inst.CRBA >> 2, 3 - (inst.CRBA & 3), XA);
GetCRFieldBit(inst.CRBB >> 2, 3 - (inst.CRBB & 3), XB);
// creqv or crnand or crnor
bool negateA = inst.SUBOP10 == 289 || inst.SUBOP10 == 225 || inst.SUBOP10 == 33;
// crandc or crorc or crnand or crnor
bool negateB =
inst.SUBOP10 == 129 || inst.SUBOP10 == 417 || inst.SUBOP10 == 225 || inst.SUBOP10 == 33;
// GetCRFieldBit
for (int i = 0; i < 2; i++)
{
int field = i ? inst.CRBB >> 2 : inst.CRBA >> 2;
int bit = i ? 3 - (inst.CRBB & 3) : 3 - (inst.CRBA & 3);
ARM64Reg out = i ? XB : XA;
bool negate = i ? negateB : negateA;
ARM64Reg XC = gpr.CR(field);
ARM64Reg WC = EncodeRegTo32(XC);
switch (bit)
{
case PowerPC::CR_SO_BIT: // check bit 59 set
UBFX(out, XC, PowerPC::CR_EMU_SO_BIT, 1);
if (negate)
EOR(out, out, LogicalImm(1, GPRSize::B64));
break;
case PowerPC::CR_EQ_BIT: // check bits 31-0 == 0
CMP(WC, ARM64Reg::WZR);
CSET(out, negate ? CC_NEQ : CC_EQ);
break;
case PowerPC::CR_GT_BIT: // check val > 0
CMP(XC, ARM64Reg::ZR);
CSET(out, negate ? CC_LE : CC_GT);
break;
case PowerPC::CR_LT_BIT: // check bit 62 set
UBFX(out, XC, PowerPC::CR_EMU_LT_BIT, 1);
if (negate)
EOR(out, out, LogicalImm(1, GPRSize::B64));
break;
default:
ASSERT_MSG(DYNA_REC, false, "Invalid CR bit");
}
}
// Compute combined bit
switch (inst.SUBOP10)
{
case 225: // crnand: ~(A && B)
case 33: // crnor: ~(A || B) == (~A && ~B)
case 129: // crandc: A && ~B
case 257: // crand: A && B
AND(XA, XA, XB);
break;
case 129: // crandc: A && ~B
BIC(XA, XA, XB);
break;
case 193: // crxor: A ^ B
case 289: // creqv: ~(A ^ B) = ~A ^ B
EOR(XA, XA, XB);
break;
case 289: // creqv: ~(A ^ B) = A ^ ~B
EON(XA, XA, XB);
break;
case 33: // crnor: ~(A || B)
case 225: // crnand: ~(A && B) == (~A || ~B)
case 417: // crorc: A || ~B
case 449: // cror: A || B
ORR(XA, XA, XB);
break;
case 417: // crorc: A || ~B
ORN(XA, XA, XB);
break;
}
}
// Store result bit in CRBD
SetCRFieldBit(inst.CRBD >> 2, 3 - (inst.CRBD & 3), XA, negate_result);
int field = inst.CRBD >> 2;
int bit = 3 - (inst.CRBD & 3);
gpr.BindCRToRegister(field, true);
ARM64Reg CR = gpr.CR(field);
if (bit != PowerPC::CR_GT_BIT)
FixGTBeforeSettingCRFieldBit(CR);
switch (bit)
{
case PowerPC::CR_SO_BIT: // set bit 59 to input
BFI(CR, XA, PowerPC::CR_EMU_SO_BIT, 1);
break;
case PowerPC::CR_EQ_BIT: // clear low 32 bits, set bit 0 to !input
AND(CR, CR, LogicalImm(0xFFFF'FFFF'0000'0000, GPRSize::B64));
EOR(XA, XA, LogicalImm(1, GPRSize::B64));
ORR(CR, CR, XA);
break;
case PowerPC::CR_GT_BIT: // set bit 63 to !input
EOR(XA, XA, LogicalImm(1, GPRSize::B64));
BFI(CR, XA, 63, 1);
break;
case PowerPC::CR_LT_BIT: // set bit 62 to input
BFI(CR, XA, PowerPC::CR_EMU_LT_BIT, 1);
break;
}
ORR(CR, CR, LogicalImm(1ULL << 32, GPRSize::B64));
}
void JitArm64::mfcr(UGeckoInstruction inst)

View File

@ -110,9 +110,9 @@ JitBase::~JitBase()
CPUThreadConfigCallback::RemoveConfigChangedCallback(m_registered_config_callback_id);
}
bool JitBase::DoesConfigNeedRefresh() const
bool JitBase::DoesConfigNeedRefresh()
{
return std::ranges::any_of(JIT_SETTINGS, [this](const auto& pair) {
return std::any_of(JIT_SETTINGS.begin(), JIT_SETTINGS.end(), [this](const auto& pair) {
return this->*pair.first != Config::Get(*pair.second);
});
}
@ -276,7 +276,7 @@ bool JitBase::CanMergeNextInstructions(int count) const
return true;
}
bool JitBase::ShouldHandleFPExceptionForInstruction(const PPCAnalyst::CodeOp* op) const
bool JitBase::ShouldHandleFPExceptionForInstruction(const PPCAnalyst::CodeOp* op)
{
if (jo.fp_exceptions)
return (op->opinfo->flags & FL_FLOAT_EXCEPTION) != 0;

View File

@ -167,7 +167,7 @@ protected:
static const std::array<std::pair<bool JitBase::*, const Config::Info<bool>*>, 23> JIT_SETTINGS;
bool DoesConfigNeedRefresh() const;
bool DoesConfigNeedRefresh();
void RefreshConfig();
void InitFastmemArena();
@ -178,16 +178,8 @@ protected:
void CleanUpAfterStackFault();
bool CanMergeNextInstructions(int count) const;
bool HasConstantCarry() const
{
#ifdef _M_ARM_64
return js.carryFlag == CarryFlag::ConstantTrue || js.carryFlag == CarryFlag::ConstantFalse;
#else
return false;
#endif
}
bool ShouldHandleFPExceptionForInstruction(const PPCAnalyst::CodeOp* op) const;
bool ShouldHandleFPExceptionForInstruction(const PPCAnalyst::CodeOp* op);
public:
explicit JitBase(Core::System& system);

View File

@ -191,7 +191,7 @@ static void AnalyzeFunction2(PPCSymbolDB* func_db, Common::Symbol* func)
{
u32 flags = func->flags;
bool nonleafcall = std::ranges::any_of(func->calls, [&](const auto& call) {
bool nonleafcall = std::any_of(func->calls.begin(), func->calls.end(), [&](const auto& call) {
const Common::Symbol* const called_func = func_db->GetSymbolFromAddr(call.function);
return called_func && (called_func->flags & Common::FFLAG_LEAF) == 0;
});

View File

@ -6,11 +6,11 @@
#include <algorithm>
#include <cstring>
#include <map>
#include <ranges>
#include <sstream>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include <fmt/format.h>
@ -18,7 +18,6 @@
#include "Common/IOFile.h"
#include "Common/Logging/Log.h"
#include "Common/StringUtil.h"
#include "Common/Unreachable.h"
#include "Core/Core.h"
#include "Core/Debugger/DebugInterface.h"
#include "Core/PowerPC/MMU.h"
@ -252,7 +251,7 @@ bool PPCSymbolDB::LoadMap(const Core::CPUThreadGuard& guard, const std::string&
continue;
// Support CodeWarrior and Dolphin map
if (StripWhitespace(line).ends_with(" section layout") || strcmp(temp, ".text") == 0 ||
if (std::string_view{line}.ends_with(" section layout\n") || strcmp(temp, ".text") == 0 ||
strcmp(temp, ".init") == 0)
{
section_name = temp;
@ -311,7 +310,7 @@ bool PPCSymbolDB::LoadMap(const Core::CPUThreadGuard& guard, const std::string&
continue;
column_count = 2;
// Three columns format (with optional alignment):
// Three columns format:
// Starting Virtual
// address Size address
// -----------------------
@ -320,7 +319,7 @@ bool PPCSymbolDB::LoadMap(const Core::CPUThreadGuard& guard, const std::string&
else
iss.str("");
// Four columns format (with optional alignment):
// Four columns format:
// Starting Virtual File
// address Size address offset
// ---------------------------------
@ -328,77 +327,85 @@ bool PPCSymbolDB::LoadMap(const Core::CPUThreadGuard& guard, const std::string&
column_count = 4;
}
u32 address;
u32 vaddress;
u32 size = 0;
u32 offset = 0;
u32 alignment = 0;
char name[512]{};
static constexpr char ENTRY_OF_STRING[] = " (entry of ";
static constexpr std::string_view ENTRY_OF_VIEW(ENTRY_OF_STRING);
auto parse_entry_of = [](char* name) {
if (char* s1 = strstr(name, ENTRY_OF_STRING); s1 != nullptr)
{
char container[512];
char* ptr = s1 + ENTRY_OF_VIEW.size();
sscanf(ptr, "%511s", container);
// Skip sections, those start with a dot, e.g. (entry of .text)
if (char* s2 = strchr(container, ')'); s2 != nullptr && *container != '.')
{
ptr += strlen(container);
// Preserve data after the entry part, usually it contains object names
strcpy(s1, ptr);
*s2 = '\0';
strcat(container, "::");
strcat(container, name);
strcpy(name, container);
}
}
};
auto was_alignment = [](const char* name) {
return *name == ' ' || (*name >= '0' && *name <= '9');
};
auto parse_alignment = [](char* name, u32* alignment) {
const std::string buffer(StripWhitespace(name));
return sscanf(buffer.c_str(), "%i %511[^\r\n]", alignment, name);
};
switch (column_count)
u32 address, vaddress, size, offset, alignment;
char name[512], container[512];
if (column_count == 4)
{
case 4:
// sometimes there is no alignment value, and sometimes it is because it is an entry of
// something else
sscanf(line, "%08x %08x %08x %08x %511[^\r\n]", &address, &size, &vaddress, &offset, name);
if (was_alignment(name))
parse_alignment(name, &alignment);
// The `else` statement was omitted to handle symbol already saved in Dolphin symbol map
// since it doesn't omit the alignment on save for such case.
parse_entry_of(name);
break;
case 3:
if (length > 37 && line[37] == ' ')
{
alignment = 0;
sscanf(line, "%08x %08x %08x %08x %511s", &address, &size, &vaddress, &offset, name);
char* s = strstr(line, "(entry of ");
if (s)
{
sscanf(s + 10, "%511s", container);
char* s2 = (strchr(container, ')'));
if (s2 && container[0] != '.')
{
s2[0] = '\0';
strcat(container, "::");
strcat(container, name);
strcpy(name, container);
}
}
}
else
{
sscanf(line, "%08x %08x %08x %08x %i %511s", &address, &size, &vaddress, &offset,
&alignment, name);
}
}
else if (column_count == 3)
{
// some entries in the table have a function name followed by " (entry of " followed by a
// container name, followed by ")"
// instead of a space followed by a number followed by a space followed by a name
sscanf(line, "%08x %08x %08x %511[^\r\n]", &address, &size, &vaddress, name);
if (was_alignment(name))
parse_alignment(name, &alignment);
// The `else` statement was omitted to handle symbol already saved in Dolphin symbol map
// since it doesn't omit the alignment on save for such case.
parse_entry_of(name);
break;
case 2:
sscanf(line, "%08x %511[^\r\n]", &address, name);
if (length > 27 && line[27] != ' ' && strstr(line, "(entry of "))
{
alignment = 0;
sscanf(line, "%08x %08x %08x %511s", &address, &size, &vaddress, name);
char* s = strstr(line, "(entry of ");
if (s)
{
sscanf(s + 10, "%511s", container);
char* s2 = (strchr(container, ')'));
if (s2 && container[0] != '.')
{
s2[0] = '\0';
strcat(container, "::");
strcat(container, name);
strcpy(name, container);
}
}
}
else
{
sscanf(line, "%08x %08x %08x %i %511s", &address, &size, &vaddress, &alignment, name);
}
}
else if (column_count == 2)
{
sscanf(line, "%08x %511s", &address, name);
vaddress = address;
break;
default:
// Should never happen
Common::Unreachable();
size = 0;
}
else
{
break;
}
const char* namepos = strstr(line, name);
if (namepos != nullptr) // would be odd if not :P
strcpy(name, namepos);
name[strlen(name) - 1] = 0;
if (name[strlen(name) - 1] == '\r')
name[strlen(name) - 1] = 0;
// Split the current name string into separate parts, and get the object name
// if it exists.
const std::vector<std::string> parts = SplitString(name, '\t');
const std::string name_string(StripWhitespace(parts.size() > 0 ? parts[0] : name));
const std::string name_string(StripWhitespace(parts[0]));
const std::string object_filename_string =
parts.size() > 1 ? std::string(StripWhitespace(parts[1])) : "";
@ -459,38 +466,42 @@ bool PPCSymbolDB::SaveSymbolMap(const std::string& filename) const
if (!f)
return false;
std::vector<const Common::Symbol*> function_symbols;
std::vector<const Common::Symbol*> data_symbols;
for (const auto& function : m_functions)
{
const Common::Symbol& symbol = function.second;
if (symbol.type == Common::Symbol::Type::Function)
function_symbols.push_back(&symbol);
else
data_symbols.push_back(&symbol);
}
// Write .text section
auto function_symbols =
m_functions |
std::views::filter([](auto f) { return f.second.type == Common::Symbol::Type::Function; }) |
std::views::transform([](auto f) { return f.second; });
f.WriteString(".text section layout\n");
for (const auto& symbol : function_symbols)
{
// Write symbol address, size, virtual address, alignment, name
std::string line = fmt::format("{:08x} {:06x} {:08x} {} {}", symbol.address, symbol.size,
symbol.address, 0, symbol.name);
std::string line = fmt::format("{0:08x} {1:06x} {2:08x} {3} {4}", symbol->address, symbol->size,
symbol->address, 0, symbol->name);
// Also write the object name if it exists
if (!symbol.object_name.empty())
line += fmt::format(" \t{0}", symbol.object_name);
if (!symbol->object_name.empty())
line += fmt::format(" \t{0}", symbol->object_name);
line += "\n";
f.WriteString(line);
}
// Write .data section
auto data_symbols =
m_functions |
std::views::filter([](auto f) { return f.second.type == Common::Symbol::Type::Data; }) |
std::views::transform([](auto f) { return f.second; });
f.WriteString("\n.data section layout\n");
for (const auto& symbol : data_symbols)
{
// Write symbol address, size, virtual address, alignment, name
std::string line = fmt::format("{:08x} {:06x} {:08x} {} {}", symbol.address, symbol.size,
symbol.address, 0, symbol.name);
std::string line = fmt::format("{0:08x} {1:06x} {2:08x} {3} {4}", symbol->address, symbol->size,
symbol->address, 0, symbol->name);
// Also write the object name if it exists
if (!symbol.object_name.empty())
line += fmt::format(" \t{0}", symbol.object_name);
if (!symbol->object_name.empty())
line += fmt::format(" \t{0}", symbol->object_name);
line += "\n";
f.WriteString(line);
}

View File

@ -24,7 +24,6 @@
#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/Contains.h"
#include "Common/Event.h"
#include "Common/FileUtil.h"
#include "Common/IOFile.h"
@ -262,7 +261,9 @@ static int GetEmptySlot(const std::vector<SlotWithTimestamp>& used_slots)
{
for (int i = 1; i <= (int)NUM_STATES; i++)
{
if (!Common::Contains(used_slots, i, &SlotWithTimestamp::slot))
const auto it = std::find_if(used_slots.begin(), used_slots.end(),
[i](const SlotWithTimestamp& slot) { return slot.slot == i; });
if (it == used_slots.end())
return i;
}
return -1;

View File

@ -10,7 +10,6 @@
#include <array>
#include <fmt/format.h>
#include "Common/Contains.h"
#include "Common/IniFile.h"
#include "Common/StringUtil.h"
@ -87,7 +86,10 @@ static void LoadPatchSection(const Common::IniFile& ini)
static bool IsWC24Channel()
{
const auto& sconfig = SConfig::GetInstance();
return Common::Contains(s_wc24_channels, sconfig.GetTitleID());
const auto found =
std::find(s_wc24_channels.begin(), s_wc24_channels.end(), sconfig.GetTitleID());
return found != s_wc24_channels.end();
}
static void LoadPatches()

View File

@ -21,7 +21,6 @@
#include "Common/Align.h"
#include "Common/Assert.h"
#include "Common/CommonTypes.h"
#include "Common/Contains.h"
#include "Common/EnumUtils.h"
#include "Common/FileUtil.h"
#include "Common/HttpRequest.h"
@ -224,14 +223,15 @@ bool IsTitleInstalled(u64 title_id)
// Since this isn't IOS and we only need a simple way to figure out if a title is installed,
// we make the (reasonable) assumption that having more than just the TMD in the content
// directory means that the title is installed.
return std::ranges::any_of(*entries, [](const std::string& file) { return file != "title.tmd"; });
return std::any_of(entries->begin(), entries->end(),
[](const std::string& file) { return file != "title.tmd"; });
}
bool IsTMDImported(IOS::HLE::FS::FileSystem& fs, u64 title_id)
{
const auto entries = fs.ReadDirectory(0, 0, Common::GetTitleContentPath(title_id));
return entries &&
std::ranges::any_of(*entries, [](const std::string& file) { return file == "title.tmd"; });
return entries && std::any_of(entries->begin(), entries->end(),
[](const std::string& file) { return file == "title.tmd"; });
}
IOS::ES::TMDReader FindBackupTMD(IOS::HLE::FS::FileSystem& fs, u64 title_id)
@ -467,7 +467,12 @@ OnlineSystemUpdater::Response OnlineSystemUpdater::GetSystemTitles()
// but the backing data CDN is still active and accessible from other URLs. We take advantage
// of this by hosting our own NetUpdateSOAP endpoint which serves the correct list of titles to
// install along with URLs for the Wii U CDN.
#ifdef ANDROID
// HTTPS is unsupported on Android (https://bugs.dolphin-emu.org/issues/11772).
base_url = "http://fakenus.dolphin-emu.org";
#else
base_url = "https://fakenus.dolphin-emu.org";
#endif
}
const std::string url = fmt::format("{}/nus/services/NetUpdateSOAP", base_url);
@ -586,8 +591,10 @@ UpdateResult OnlineSystemUpdater::InstallTitleFromNUS(const std::string& prefix_
const UpdateResult import_result = [&]() {
for (const IOS::ES::Content& content : tmd.first.GetContents())
{
const bool is_already_installed =
Common::Contains(stored_contents, content.id, &IOS::ES::Content::id);
const bool is_already_installed = std::find_if(stored_contents.begin(), stored_contents.end(),
[&content](const auto& stored_content) {
return stored_content.id == content.id;
}) != stored_contents.end();
// Do skip what is already installed on the NAND.
if (is_already_installed)
@ -940,8 +947,8 @@ static NANDCheckResult CheckNAND(IOS::HLE::Kernel& ios, bool repair)
}
const auto installed_contents = es.GetStoredContentsFromTMD(tmd);
const bool is_installed = std::ranges::any_of(
installed_contents, [](const auto& content) { return !content.IsShared(); });
const bool is_installed = std::any_of(installed_contents.begin(), installed_contents.end(),
[](const auto& content) { return !content.IsShared(); });
if (is_installed && installed_contents != tmd.GetContents() &&
(tmd.GetTitleFlags() & IOS::ES::TitleFlags::TITLE_TYPE_DATA) == 0)

View File

@ -13,7 +13,6 @@
#include "Common/CommonTypes.h"
#include "Common/MathUtil.h"
#include "Common/StringUtil.h"
#include "DiscIO/Blob.h"
#include "DiscIO/Filesystem.h"
#include "DiscIO/Volume.h"
@ -40,7 +39,8 @@ std::string NameForPartitionType(u32 partition_type, bool include_prefix)
static_cast<char>((partition_type >> 16) & 0xFF),
static_cast<char>((partition_type >> 8) & 0xFF),
static_cast<char>(partition_type & 0xFF)};
if (std::ranges::all_of(type_as_game_id, Common::IsAlnum))
if (std::all_of(type_as_game_id.cbegin(), type_as_game_id.cend(),
[](char c) { return std::isalnum(c, std::locale::classic()); }))
{
return include_prefix ? "P-" + type_as_game_id : type_as_game_id;
}

View File

@ -240,9 +240,11 @@ bool NANDImporter::ExtractCertificates()
for (const PEMCertificate& certificate : certificates)
{
const auto search_result = std::ranges::search(content_bytes, certificate.search_bytes);
const auto search_result =
std::search(content_bytes.begin(), content_bytes.end(), certificate.search_bytes.begin(),
certificate.search_bytes.end());
if (search_result.empty())
if (search_result == content_bytes.end())
{
ERROR_LOG_FMT(DISCIO, "ExtractCertificates: Could not find offset for certficate '{}'",
certificate.filename);
@ -250,8 +252,7 @@ bool NANDImporter::ExtractCertificates()
}
const std::string pem_file_path = m_nand_root + std::string(certificate.filename);
const ptrdiff_t certificate_offset =
std::distance(content_bytes.begin(), search_result.begin());
const ptrdiff_t certificate_offset = std::distance(content_bytes.begin(), search_result);
constexpr int min_offset = 2;
if (certificate_offset < min_offset)
{

View File

@ -104,7 +104,7 @@ FileDataLoaderHostFS::MakeAbsoluteFromRelative(std::string_view external_relativ
result.pop_back();
result.pop_back();
}
else if (std::ranges::all_of(element, [](char c) { return c == '.'; }))
else if (std::all_of(element.begin(), element.end(), [](char c) { return c == '.'; }))
{
// This is a triple, quadruple, etc. dot.
// Some file systems treat this as several 'up' path traversals, but Riivolution does not.

View File

@ -21,7 +21,6 @@
#include "Common/CPUDetect.h"
#include "Common/CommonPaths.h"
#include "Common/CommonTypes.h"
#include "Common/Contains.h"
#include "Common/Crypto/SHA1.h"
#include "Common/FileUtil.h"
#include "Common/Hash.h"
@ -144,8 +143,11 @@ RedumpVerifier::DownloadStatus RedumpVerifier::DownloadDatfile(const std::string
if (File::Exists(output_path))
return DownloadStatus::FailButOldCacheAvailable;
const std::string system_not_available_message = "System \"" + system + "\" doesn't exist.";
const bool system_not_available_match =
Common::ContainsSubrange(*result, "System \"" + system + "\" doesn't exist.");
result->end() != std::search(result->begin(), result->end(),
system_not_available_message.begin(),
system_not_available_message.end());
return system_not_available_match ? DownloadStatus::SystemNotAvailable : DownloadStatus::Fail;
}
@ -451,18 +453,21 @@ std::vector<Partition> VolumeVerifier::CheckPartitions()
types.emplace_back(*type);
}
if (!Common::Contains(types, PARTITION_UPDATE))
if (std::find(types.cbegin(), types.cend(), PARTITION_UPDATE) == types.cend())
AddProblem(Severity::Low, Common::GetStringT("The update partition is missing."));
const bool has_data_partition = Common::Contains(types, PARTITION_DATA);
const bool has_data_partition =
std::find(types.cbegin(), types.cend(), PARTITION_DATA) != types.cend();
if (!m_is_datel && !has_data_partition)
AddProblem(Severity::High, Common::GetStringT("The data partition is missing."));
const bool has_channel_partition = Common::Contains(types, PARTITION_CHANNEL);
const bool has_channel_partition =
std::find(types.cbegin(), types.cend(), PARTITION_CHANNEL) != types.cend();
if (ShouldHaveChannelPartition() && !has_channel_partition)
AddProblem(Severity::Medium, Common::GetStringT("The channel partition is missing."));
const bool has_install_partition = Common::Contains(types, PARTITION_INSTALL);
const bool has_install_partition =
std::find(types.cbegin(), types.cend(), PARTITION_INSTALL) != types.cend();
if (ShouldHaveInstallPartition() && !has_install_partition)
AddProblem(Severity::High, Common::GetStringT("The install partition is missing."));
@ -724,15 +729,16 @@ bool VolumeVerifier::ShouldHaveInstallPartition() const
static constexpr std::array<std::string_view, 4> dragon_quest_x = {"S4MJGD", "S4SJGD", "S6TJGD",
"SDQJGD"};
const std::string& game_id = m_volume.GetGameID();
return std::ranges::any_of(dragon_quest_x,
[&game_id](std::string_view x) { return x == game_id; });
return std::any_of(dragon_quest_x.cbegin(), dragon_quest_x.cend(),
[&game_id](std::string_view x) { return x == game_id; });
}
bool VolumeVerifier::ShouldHaveMasterpiecePartitions() const
{
static constexpr std::array<std::string_view, 4> ssbb = {"RSBE01", "RSBJ01", "RSBK01", "RSBP01"};
const std::string& game_id = m_volume.GetGameID();
return std::ranges::any_of(ssbb, [&game_id](std::string_view x) { return x == game_id; });
return std::any_of(ssbb.cbegin(), ssbb.cend(),
[&game_id](std::string_view x) { return x == game_id; });
}
bool VolumeVerifier::ShouldBeDualLayer() const
@ -1033,7 +1039,7 @@ void VolumeVerifier::CheckSuperPaperMario()
if (!m_volume.Read(offset, length, data.data(), partition))
return;
if (std::ranges::any_of(data, [](u8 x) { return x != 0; }))
if (std::any_of(data.cbegin(), data.cend(), [](u8 x) { return x != 0; }))
{
AddProblem(Severity::High,
Common::GetStringT("Some padding data that should be zero is not zero. "

View File

@ -176,7 +176,7 @@ IOS::ES::TicketReader VolumeWAD::GetTicketWithFixedCommonKey() const
return m_ticket;
const std::vector<u8> sig = m_ticket.GetSignatureData();
if (!std::ranges::all_of(sig, [](u8 a) { return a == 0; }))
if (!std::all_of(sig.cbegin(), sig.cend(), [](u8 a) { return a == 0; }))
{
// This does not look like a typical "invalid common key index" ticket, so let's assume
// the index is correct. This saves some time when reading properly signed titles.

View File

@ -1126,7 +1126,7 @@ bool WIARVZFileReader<RVZ>::TryReuse(std::map<ReuseID, GroupEntry>* reusable_gro
static bool AllAre(const std::vector<u8>& data, u8 x)
{
return std::ranges::all_of(data, [x](u8 y) { return x == y; });
return std::all_of(data.begin(), data.end(), [x](u8 y) { return x == y; });
}
static bool AllAre(const u8* begin, const u8* end, u8 x)
@ -1379,8 +1379,8 @@ WIARVZFileReader<RVZ>::ProcessAndCompress(CompressThreadState* state, CompressPa
}
}
if (!std::ranges::all_of(output_entries,
[](const auto& entry) { return entry.reused_group.has_value(); }))
if (!std::all_of(output_entries.begin(), output_entries.end(),
[](const OutputParametersEntry& entry) { return entry.reused_group; }))
{
const u64 number_of_exception_lists =
chunks_per_wii_group == 1 ? exception_lists_per_chunk : chunks;

View File

@ -38,7 +38,6 @@
<ClInclude Include="Common\Config\ConfigInfo.h" />
<ClInclude Include="Common\Config\Enums.h" />
<ClInclude Include="Common\Config\Layer.h" />
<ClInclude Include="Common\Contains.h" />
<ClInclude Include="Common\CPUDetect.h" />
<ClInclude Include="Common\Crypto\AES.h" />
<ClInclude Include="Common\Crypto\bn.h" />

View File

@ -52,7 +52,6 @@ add_executable(dolphin-emu
Config/ConfigControls/ConfigBool.h
Config/ConfigControls/ConfigChoice.cpp
Config/ConfigControls/ConfigChoice.h
Config/ConfigControls/ConfigControl.h
Config/ConfigControls/ConfigInteger.cpp
Config/ConfigControls/ConfigInteger.h
Config/ConfigControls/ConfigRadio.cpp
@ -573,11 +572,12 @@ endif()
if(APPLE)
include(BundleUtilities)
set(BUNDLE_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/DolphinQt.app)
# Ask for an application bundle.
set_target_properties(dolphin-emu PROPERTIES
MACOSX_BUNDLE true
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in"
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_BINARY_DIR}/Info.plist"
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ""
OUTPUT_NAME DolphinQt
)
@ -614,9 +614,6 @@ if(APPLE)
source_group("Resources" FILES "${CMAKE_SOURCE_DIR}/Data/${res}")
endforeach()
include(DolphinInjectVersionInfo)
dolphin_inject_version_info(dolphin-emu)
# Copy MoltenVK into the bundle
if(ENABLE_VULKAN)
if(USE_BUNDLED_MOLTENVK)
@ -651,7 +648,7 @@ if(APPLE)
COMMAND "${CMAKE_SOURCE_DIR}/Tools/mac-codesign.sh"
"-e" "${CMAKE_CURRENT_SOURCE_DIR}/DolphinEmu$<$<CONFIG:Debug>:Debug>.entitlements"
"${MACOS_CODE_SIGNING_IDENTITY}"
"$<TARGET_BUNDLE_DIR:dolphin-emu>"
"${BUNDLE_PATH}"
)
endif()
else()

View File

@ -3,28 +3,31 @@
#include "DolphinQt/Config/ConfigControls/ConfigBool.h"
#include <QEvent>
#include <QFont>
#include <QSignalBlocker>
#include "Common/Config/Config.h"
#include "DolphinQt/Settings.h"
ConfigBool::ConfigBool(const QString& label, const Config::Info<bool>& setting, bool reverse)
: ConfigBool(label, setting, nullptr, reverse)
: ToolTipCheckBox(label), m_setting(setting), m_reverse(reverse)
{
}
ConfigBool::ConfigBool(const QString& label, const Config::Info<bool>& setting,
Config::Layer* layer, bool reverse)
: ConfigControl(label, setting.GetLocation(), layer), m_setting(setting), m_reverse(reverse)
{
setChecked(ReadValue(setting) ^ reverse);
connect(this, &QCheckBox::toggled, this, &ConfigBool::Update);
setChecked(Config::Get(m_setting) ^ reverse);
connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] {
QFont bf = font();
bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base);
setFont(bf);
const QSignalBlocker blocker(this);
setChecked(Config::Get(m_setting) ^ m_reverse);
});
}
void ConfigBool::Update()
{
const bool value = static_cast<bool>(isChecked() ^ m_reverse);
SaveValue(m_setting, value);
}
void ConfigBool::OnConfigChanged()
{
setChecked(ReadValue(m_setting) ^ m_reverse);
Config::SetBaseOrCurrent(m_setting, static_cast<bool>(isChecked() ^ m_reverse));
}

View File

@ -3,25 +3,23 @@
#pragma once
#include "DolphinQt/Config/ConfigControls/ConfigControl.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipCheckBox.h"
#include "Common/Config/ConfigInfo.h"
namespace Config
{
template <typename T>
class Info;
}
class ConfigBool final : public ConfigControl<ToolTipCheckBox>
class ConfigBool : public ToolTipCheckBox
{
Q_OBJECT
public:
ConfigBool(const QString& label, const Config::Info<bool>& setting, bool reverse = false);
ConfigBool(const QString& label, const Config::Info<bool>& setting, Config::Layer* layer,
bool reverse = false);
protected:
void OnConfigChanged() override;
private:
void Update();
const Config::Info<bool> m_setting;
const Config::Info<bool>& m_setting;
bool m_reverse;
};

View File

@ -5,168 +5,85 @@
#include <QSignalBlocker>
ConfigChoice::ConfigChoice(const QStringList& options, const Config::Info<int>& setting,
Config::Layer* layer)
: ConfigControl(setting.GetLocation(), layer), m_setting(setting)
#include "Common/Config/Config.h"
#include "DolphinQt/Settings.h"
ConfigChoice::ConfigChoice(const QStringList& options, const Config::Info<int>& setting)
: m_setting(setting)
{
addItems(options);
setCurrentIndex(ReadValue(setting));
connect(this, &QComboBox::currentIndexChanged, this, &ConfigChoice::Update);
setCurrentIndex(Config::Get(m_setting));
connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] {
QFont bf = font();
bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base);
setFont(bf);
const QSignalBlocker blocker(this);
setCurrentIndex(Config::Get(m_setting));
});
}
void ConfigChoice::Update(int choice)
{
SaveValue(m_setting, choice);
}
void ConfigChoice::OnConfigChanged()
{
setCurrentIndex(ReadValue(m_setting));
Config::SetBaseOrCurrent(m_setting, choice);
}
ConfigStringChoice::ConfigStringChoice(const std::vector<std::string>& options,
const Config::Info<std::string>& setting,
Config::Layer* layer)
: ConfigControl(setting.GetLocation(), layer), m_setting(setting), m_text_is_data(true)
const Config::Info<std::string>& setting)
: m_setting(setting), m_text_is_data(true)
{
for (const auto& op : options)
addItem(QString::fromStdString(op));
Connect();
Load();
connect(this, &QComboBox::currentIndexChanged, this, &ConfigStringChoice::Update);
}
ConfigStringChoice::ConfigStringChoice(const std::vector<std::pair<QString, QString>>& options,
const Config::Info<std::string>& setting,
Config::Layer* layer)
: ConfigControl(setting.GetLocation(), layer), m_setting(setting), m_text_is_data(false)
const Config::Info<std::string>& setting)
: m_setting(setting), m_text_is_data(false)
{
for (const auto& [option_text, option_data] : options)
addItem(option_text, option_data);
connect(this, &QComboBox::currentIndexChanged, this, &ConfigStringChoice::Update);
Connect();
Load();
}
void ConfigStringChoice::Connect()
{
const auto on_config_changed = [this]() {
QFont bf = font();
bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base);
setFont(bf);
Load();
};
connect(&Settings::Instance(), &Settings::ConfigChanged, this, on_config_changed);
connect(this, &QComboBox::currentIndexChanged, this, &ConfigStringChoice::Update);
}
void ConfigStringChoice::Update(int index)
{
if (m_text_is_data)
SaveValue(m_setting, itemText(index).toStdString());
{
Config::SetBaseOrCurrent(m_setting, itemText(index).toStdString());
}
else
SaveValue(m_setting, itemData(index).toString().toStdString());
{
Config::SetBaseOrCurrent(m_setting, itemData(index).toString().toStdString());
}
}
void ConfigStringChoice::Load()
{
const QString setting_value = QString::fromStdString(ReadValue(m_setting));
const QString setting_value = QString::fromStdString(Config::Get(m_setting));
const int index = m_text_is_data ? findText(setting_value) : findData(setting_value);
// This can be called publicly.
const QSignalBlocker block(this);
setCurrentIndex(index);
}
void ConfigStringChoice::OnConfigChanged()
{
Load();
}
ConfigComplexChoice::ConfigComplexChoice(const InfoVariant setting1, const InfoVariant setting2,
Config::Layer* layer)
: m_layer(layer), m_setting1(setting1), m_setting2(setting2)
{
connect(&Settings::Instance(), &Settings::ConfigChanged, this, &ConfigComplexChoice::Refresh);
connect(this, &QComboBox::currentIndexChanged, this, &ConfigComplexChoice::SaveValue);
}
void ConfigComplexChoice::Refresh()
{
auto& location = GetLocation();
QFont bf = font();
if (m_layer != nullptr)
{
bf.setBold(m_layer->Exists(location.first) || m_layer->Exists(location.second));
}
else
{
bf.setBold(Config::GetActiveLayerForConfig(location.first) != Config::LayerType::Base ||
Config::GetActiveLayerForConfig(location.second) != Config::LayerType::Base);
}
setFont(bf);
UpdateComboIndex();
}
void ConfigComplexChoice::Add(const QString& name, const OptionVariant option1,
const OptionVariant option2)
{
const QSignalBlocker blocker(this);
addItem(name);
m_options.push_back(std::make_pair(option1, option2));
}
void ConfigComplexChoice::Reset()
{
clear();
m_options.clear();
}
void ConfigComplexChoice::SaveValue(int choice)
{
auto Set = [this](auto& setting, auto& value) {
if (m_layer != nullptr)
{
m_layer->Set(setting.GetLocation(), value);
Config::OnConfigChanged();
return;
}
Config::SetBaseOrCurrent(setting, value);
};
std::visit(Set, m_setting1, m_options[choice].first);
std::visit(Set, m_setting2, m_options[choice].second);
}
void ConfigComplexChoice::UpdateComboIndex()
{
auto Get = [this](auto& setting) {
if (m_layer != nullptr)
return static_cast<OptionVariant>(m_layer->Get(setting));
return static_cast<OptionVariant>(Config::Get(setting));
};
std::pair<OptionVariant, OptionVariant> values =
std::make_pair(std::visit(Get, m_setting1), std::visit(Get, m_setting2));
auto it = std::find(m_options.begin(), m_options.end(), values);
int index = static_cast<int>(std::distance(m_options.begin(), it));
const QSignalBlocker blocker(this);
setCurrentIndex(index);
}
const std::pair<Config::Location, Config::Location> ConfigComplexChoice::GetLocation() const
{
auto visit = [](auto& v) { return v.GetLocation(); };
return {std::visit(visit, m_setting1), std::visit(visit, m_setting2)};
}
void ConfigComplexChoice::mousePressEvent(QMouseEvent* event)
{
if (event->button() == Qt::RightButton && m_layer != nullptr)
{
auto& location = GetLocation();
m_layer->DeleteKey(location.first);
m_layer->DeleteKey(location.second);
Config::OnConfigChanged();
}
else
{
QComboBox::mousePressEvent(event);
}
};

View File

@ -7,20 +7,15 @@
#include <utility>
#include <vector>
#include "DolphinQt/Config/ConfigControls/ConfigControl.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipComboBox.h"
#include "Common/Config/ConfigInfo.h"
#include "Common/Config/Config.h"
class ConfigChoice final : public ConfigControl<ToolTipComboBox>
class ConfigChoice : public ToolTipComboBox
{
Q_OBJECT
public:
ConfigChoice(const QStringList& options, const Config::Info<int>& setting,
Config::Layer* layer = nullptr);
protected:
void OnConfigChanged() override;
ConfigChoice(const QStringList& options, const Config::Info<int>& setting);
private:
void Update(int choice);
@ -28,49 +23,20 @@ private:
Config::Info<int> m_setting;
};
class ConfigStringChoice final : public ConfigControl<ToolTipComboBox>
class ConfigStringChoice : public ToolTipComboBox
{
Q_OBJECT
public:
ConfigStringChoice(const std::vector<std::string>& options,
const Config::Info<std::string>& setting, Config::Layer* layer = nullptr);
const Config::Info<std::string>& setting);
ConfigStringChoice(const std::vector<std::pair<QString, QString>>& options,
const Config::Info<std::string>& setting, Config::Layer* layer = nullptr);
const Config::Info<std::string>& setting);
private:
void Connect();
void Update(int index);
void Load();
protected:
void OnConfigChanged() override;
private:
void Update(int index);
const Config::Info<std::string> m_setting;
Config::Info<std::string> m_setting;
bool m_text_is_data = false;
};
class ConfigComplexChoice final : public ToolTipComboBox
{
Q_OBJECT
using InfoVariant = std::variant<Config::Info<u32>, Config::Info<int>, Config::Info<bool>>;
using OptionVariant = std::variant<u32, int, bool>;
public:
ConfigComplexChoice(const InfoVariant setting1, const InfoVariant setting2,
Config::Layer* layer = nullptr);
void Add(const QString& name, const OptionVariant option1, const OptionVariant option2);
void Refresh();
void Reset();
const std::pair<Config::Location, Config::Location> GetLocation() const;
private:
void SaveValue(int choice);
void UpdateComboIndex();
void mousePressEvent(QMouseEvent* event) override;
Config::Layer* m_layer;
const InfoVariant m_setting1;
const InfoVariant m_setting2;
std::vector<std::pair<OptionVariant, OptionVariant>> m_options;
};

View File

@ -1,105 +0,0 @@
// Copyright 2024 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <QFont>
#include <QMouseEvent>
#include <QSignalBlocker>
#include "Common/Config/Enums.h"
#include "Common/Config/Layer.h"
#include "DolphinQt/Settings.h"
namespace Config
{
template <typename T>
class Info;
struct Location;
} // namespace Config
template <class Derived>
class ConfigControl : public Derived
{
public:
ConfigControl(const Config::Location& location, Config::Layer* layer)
: m_location(location), m_layer(layer)
{
ConnectConfig();
}
ConfigControl(const QString& label, const Config::Location& location, Config::Layer* layer)
: Derived(label), m_location(location), m_layer(layer)
{
ConnectConfig();
}
ConfigControl(const Qt::Orientation& orient, const Config::Location& location,
Config::Layer* layer)
: Derived(orient), m_location(location), m_layer(layer)
{
ConnectConfig();
}
const Config::Location GetLocation() const { return m_location; }
protected:
void ConnectConfig()
{
Derived::connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] {
QFont bf = Derived::font();
bf.setBold(IsConfigLocal());
Derived::setFont(bf);
const QSignalBlocker blocker(this);
OnConfigChanged();
});
}
template <typename T>
void SaveValue(const Config::Info<T>& setting, const T& value)
{
if (m_layer != nullptr)
{
m_layer->Set(m_location, value);
Config::OnConfigChanged();
return;
}
Config::SetBaseOrCurrent(setting, value);
}
template <typename T>
const T ReadValue(const Config::Info<T>& setting) const
{
if (m_layer != nullptr)
return m_layer->Get(setting);
return Config::Get(setting);
}
virtual void OnConfigChanged(){};
private:
bool IsConfigLocal() const
{
if (m_layer != nullptr)
return m_layer->Exists(m_location);
else
return Config::GetActiveLayerForConfig(m_location) != Config::LayerType::Base;
}
void mousePressEvent(QMouseEvent* event) override
{
if (m_layer != nullptr && event->button() == Qt::RightButton)
{
m_layer->DeleteKey(m_location);
Config::OnConfigChanged();
}
else
{
Derived::mousePressEvent(event);
}
}
const Config::Location m_location;
Config::Layer* m_layer;
};

View File

@ -3,16 +3,20 @@
#include "DolphinQt/Config/ConfigControls/ConfigFloatSlider.h"
#include <QSignalBlocker>
#include "Common/Config/Config.h"
#include "DolphinQt/Settings.h"
ConfigFloatSlider::ConfigFloatSlider(float minimum, float maximum,
const Config::Info<float>& setting, float step,
Config::Layer* layer)
: ConfigControl(Qt::Horizontal, setting.GetLocation(), layer), m_minimum(minimum), m_step(step),
m_setting(setting)
const Config::Info<float>& setting, float step)
: ToolTipSlider(Qt::Horizontal), m_minimum(minimum), m_step(step), m_setting(setting)
{
const float range = maximum - minimum;
const int steps = std::round(range / step);
const int interval = std::round(range / steps);
const int current_value = std::round((ReadValue(setting) - minimum) / step);
const int current_value = std::round((Config::Get(m_setting) - minimum) / step);
setMinimum(0);
setMaximum(steps);
@ -20,21 +24,25 @@ ConfigFloatSlider::ConfigFloatSlider(float minimum, float maximum,
setValue(current_value);
connect(this, &ConfigFloatSlider::valueChanged, this, &ConfigFloatSlider::Update);
connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] {
QFont bf = font();
bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base);
setFont(bf);
const QSignalBlocker blocker(this);
const int value = std::round((Config::Get(m_setting) - m_minimum) / m_step);
setValue(value);
});
}
void ConfigFloatSlider::Update(int value)
{
const float current_value = (m_step * value) + m_minimum;
SaveValue(m_setting, current_value);
Config::SetBaseOrCurrent(m_setting, current_value);
}
float ConfigFloatSlider::GetValue() const
{
return (m_step * value()) + m_minimum;
}
void ConfigFloatSlider::OnConfigChanged()
{
setValue(std::round((ReadValue(m_setting) - m_minimum) / m_step));
}

View File

@ -3,29 +3,28 @@
#pragma once
#include "DolphinQt/Config/ConfigControls/ConfigControl.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipSlider.h"
#include "Common/Config/ConfigInfo.h"
namespace Config
{
template <typename T>
class Info;
}
// Automatically converts an int slider into a float one.
// Do not read the int values or ranges directly from it.
class ConfigFloatSlider final : public ConfigControl<ToolTipSlider>
class ConfigFloatSlider : public ToolTipSlider
{
Q_OBJECT
public:
ConfigFloatSlider(float minimum, float maximum, const Config::Info<float>& setting, float step,
Config::Layer* layer = nullptr);
ConfigFloatSlider(float minimum, float maximum, const Config::Info<float>& setting, float step);
void Update(int value);
// Returns the adjusted float value
float GetValue() const;
protected:
void OnConfigChanged() override;
private:
float m_minimum;
float m_step;
const Config::Info<float> m_setting;
const Config::Info<float>& m_setting;
};

View File

@ -3,39 +3,33 @@
#include "DolphinQt/Config/ConfigControls/ConfigInteger.h"
ConfigInteger::ConfigInteger(int minimum, int maximum, const Config::Info<int>& setting, int step)
: ConfigInteger(minimum, maximum, setting, nullptr, step)
{
}
#include <QSignalBlocker>
ConfigInteger::ConfigInteger(int minimum, int maximum, const Config::Info<int>& setting,
Config::Layer* layer, int step)
: ConfigControl(setting.GetLocation(), layer), m_setting(setting)
#include "Common/Config/Config.h"
#include "DolphinQt/Settings.h"
ConfigInteger::ConfigInteger(int minimum, int maximum, const Config::Info<int>& setting, int step)
: ToolTipSpinBox(), m_setting(setting)
{
setMinimum(minimum);
setMaximum(maximum);
setSingleStep(step);
setValue(ReadValue(setting));
setValue(Config::Get(setting));
connect(this, &ConfigInteger::valueChanged, this, &ConfigInteger::Update);
connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] {
QFont bf = font();
bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base);
setFont(bf);
const QSignalBlocker blocker(this);
setValue(Config::Get(m_setting));
});
}
void ConfigInteger::Update(int value)
{
SaveValue(m_setting, value);
}
void ConfigInteger::OnConfigChanged()
{
setValue(ReadValue(m_setting));
}
ConfigIntegerLabel::ConfigIntegerLabel(const QString& text, ConfigInteger* widget)
: QLabel(text), m_widget(QPointer<ConfigInteger>(widget))
{
connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this]() {
// Label shares font changes with ConfigInteger to mark game ini settings.
if (m_widget)
setFont(m_widget->font());
});
Config::SetBaseOrCurrent(m_setting, value);
}

View File

@ -3,38 +3,21 @@
#pragma once
#include <QLabel>
#include <QPointer>
#include "DolphinQt/Config/ConfigControls/ConfigControl.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipSpinBox.h"
#include "Common/Config/ConfigInfo.h"
namespace Config
{
template <typename T>
class Info;
}
class ConfigInteger final : public ConfigControl<ToolTipSpinBox>
class ConfigInteger : public ToolTipSpinBox
{
Q_OBJECT
public:
ConfigInteger(int minimum, int maximum, const Config::Info<int>& setting, int step = 1);
ConfigInteger(int minimum, int maximum, const Config::Info<int>& setting, Config::Layer* layer,
int step = 1);
void Update(int value);
protected:
void OnConfigChanged() override;
private:
const Config::Info<int> m_setting;
};
class ConfigIntegerLabel final : public QLabel
{
Q_OBJECT
public:
ConfigIntegerLabel(const QString& text, ConfigInteger* widget);
private:
QPointer<ConfigInteger> m_widget;
const Config::Info<int>& m_setting;
};

View File

@ -3,21 +3,33 @@
#include "DolphinQt/Config/ConfigControls/ConfigRadio.h"
ConfigRadioInt::ConfigRadioInt(const QString& label, const Config::Info<int>& setting, int value,
Config::Layer* layer)
: ConfigControl(label, setting.GetLocation(), layer), m_setting(setting), m_value(value)
{
setChecked(ReadValue(setting) == value);
#include <QSignalBlocker>
#include "Common/Config/Config.h"
#include "DolphinQt/Settings.h"
ConfigRadioInt::ConfigRadioInt(const QString& label, const Config::Info<int>& setting, int value)
: ToolTipRadioButton(label), m_setting(setting), m_value(value)
{
setChecked(Config::Get(m_setting) == m_value);
connect(this, &QRadioButton::toggled, this, &ConfigRadioInt::Update);
connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] {
QFont bf = font();
bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base);
setFont(bf);
const QSignalBlocker blocker(this);
setChecked(Config::Get(m_setting) == m_value);
});
}
void ConfigRadioInt::Update()
{
if (isChecked())
{
SaveValue(m_setting, m_value);
Config::SetBaseOrCurrent(m_setting, m_value);
emit OnSelected(m_value);
}
else
@ -25,8 +37,3 @@ void ConfigRadioInt::Update()
emit OnDeselected(m_value);
}
}
void ConfigRadioInt::OnConfigChanged()
{
setChecked(ReadValue(m_setting) == m_value);
}

View File

@ -3,17 +3,15 @@
#pragma once
#include "DolphinQt/Config/ConfigControls/ConfigControl.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipRadioButton.h"
#include "Common/Config/ConfigInfo.h"
#include "Common/Config/Config.h"
class ConfigRadioInt final : public ConfigControl<ToolTipRadioButton>
class ConfigRadioInt : public ToolTipRadioButton
{
Q_OBJECT
public:
ConfigRadioInt(const QString& label, const Config::Info<int>& setting, int value,
Config::Layer* layer = nullptr);
ConfigRadioInt(const QString& label, const Config::Info<int>& setting, int value);
signals:
// Since selecting a new radio button deselects the old one, ::toggled will generate two signals.
@ -21,12 +19,9 @@ signals:
void OnSelected(int new_value);
void OnDeselected(int old_value);
protected:
void OnConfigChanged() override;
private:
void Update();
const Config::Info<int> m_setting;
Config::Info<int> m_setting;
int m_value;
};

View File

@ -1,91 +1,36 @@
// Copyright 2017 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <cassert>
#include <QFont>
#include "DolphinQt/Config/ConfigControls/ConfigSlider.h"
#include <QSignalBlocker>
#include "Common/Config/Config.h"
#include "DolphinQt/Settings.h"
ConfigSlider::ConfigSlider(int minimum, int maximum, const Config::Info<int>& setting, int tick)
: ConfigSlider(minimum, maximum, setting, nullptr, tick)
{
}
ConfigSlider::ConfigSlider(int minimum, int maximum, const Config::Info<int>& setting,
Config::Layer* layer, int tick)
: ConfigControl(Qt::Horizontal, setting.GetLocation(), layer), m_setting(setting)
: ToolTipSlider(Qt::Horizontal), m_setting(setting)
{
setMinimum(minimum);
setMaximum(maximum);
setTickInterval(tick);
setValue(ReadValue(setting));
setValue(Config::Get(setting));
connect(this, &ConfigSlider::valueChanged, this, &ConfigSlider::Update);
}
ConfigSlider::ConfigSlider(std::vector<int> tick_values, const Config::Info<int>& setting,
Config::Layer* layer)
: ConfigControl(Qt::Horizontal, setting.GetLocation(), layer), m_setting(setting),
m_tick_values(std::move(tick_values))
{
assert(!m_tick_values.empty());
setMinimum(0);
setMaximum(static_cast<int>(m_tick_values.size() - 1));
setPageStep(1);
setTickPosition(QSlider::TicksBelow);
OnConfigChanged();
connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] {
QFont bf = font();
bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base);
setFont(bf);
connect(this, &ConfigSlider::valueChanged, this, &ConfigSlider::Update);
const QSignalBlocker blocker(this);
setValue(Config::Get(m_setting));
});
}
void ConfigSlider::Update(int value)
{
if (!m_tick_values.empty())
{
if (value >= 0 && static_cast<size_t>(value) < m_tick_values.size())
SaveValue(m_setting, m_tick_values[static_cast<size_t>(value)]);
}
else
{
SaveValue(m_setting, value);
}
}
void ConfigSlider::OnConfigChanged()
{
if (!m_tick_values.empty())
{
// re-enable in case it was disabled
setEnabled(true);
const int config_value = ReadValue(m_setting);
for (size_t i = 0; i < m_tick_values.size(); ++i)
{
if (m_tick_values[i] == config_value)
{
setValue(static_cast<int>(i));
return;
}
}
// if we reach here than none of the options matched, disable the slider
setEnabled(false);
}
else
{
setValue(ReadValue(m_setting));
}
}
ConfigSliderLabel::ConfigSliderLabel(const QString& text, ConfigSlider* slider)
: QLabel(text), m_slider(QPointer<ConfigSlider>(slider))
{
connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this]() {
// Label shares font changes with slider to mark game ini settings.
if (m_slider)
setFont(m_slider->font());
});
Config::SetBaseOrCurrent(m_setting, value);
}

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