Compare commits

..

1 Commits

Author SHA1 Message Date
5a38c5f190 cheats: Use global cheat engine 2023-07-31 23:39:21 +03:00
326 changed files with 6056 additions and 8208 deletions

View File

@ -11,7 +11,7 @@ async function checkBaseChanges(github, context) {
repository(name:$name, owner:$owner) { repository(name:$name, owner:$owner) {
ref(qualifiedName:$ref) { ref(qualifiedName:$ref) {
target { target {
... on Commit { id committedDate oid } ... on Commit { id pushedDate oid }
} }
} }
} }
@ -22,9 +22,9 @@ async function checkBaseChanges(github, context) {
ref: 'refs/heads/master', ref: 'refs/heads/master',
}; };
const result = await github.graphql(query, variables); const result = await github.graphql(query, variables);
const committedAt = result.repository.ref.target.committedDate; const pushedAt = result.repository.ref.target.pushedDate;
console.log(`Last commit committed at ${committedAt}.`); console.log(`Last commit pushed at ${pushedAt}.`);
const delta = new Date() - new Date(committedAt); const delta = new Date() - new Date(pushedAt);
if (delta <= DETECTION_TIME_FRAME) { if (delta <= DETECTION_TIME_FRAME) {
console.info('New changes detected, triggering a new build.'); console.info('New changes detected, triggering a new build.');
return true; return true;

View File

@ -57,7 +57,6 @@ CMAKE_DEPENDENT_OPTION(ENABLE_TESTS "Enable generating tests executable" ON "NOT
CMAKE_DEPENDENT_OPTION(ENABLE_DEDICATED_ROOM "Enable generating dedicated room executable" ON "NOT ANDROID AND NOT IOS" OFF) CMAKE_DEPENDENT_OPTION(ENABLE_DEDICATED_ROOM "Enable generating dedicated room executable" ON "NOT ANDROID AND NOT IOS" OFF)
option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON) option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
option(ENABLE_SCRIPTING "Enable RPC server for scripting" ON)
CMAKE_DEPENDENT_OPTION(ENABLE_CUBEB "Enables the cubeb audio backend" ON "NOT IOS" OFF) CMAKE_DEPENDENT_OPTION(ENABLE_CUBEB "Enables the cubeb audio backend" ON "NOT IOS" OFF)
option(ENABLE_OPENAL "Enables the OpenAL audio backend" ON) option(ENABLE_OPENAL "Enables the OpenAL audio backend" ON)
@ -342,6 +341,13 @@ function(get_timestamp _var)
set(${_var} "${timestamp}" PARENT_SCOPE) set(${_var} "${timestamp}" PARENT_SCOPE)
endfunction() endfunction()
# Prevent boost from linking against libs when building
add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY
-DBOOST_SYSTEM_NO_LIB
-DBOOST_DATE_TIME_NO_LIB
-DBOOST_REGEX_NO_LIB
)
# generate git/build information # generate git/build information
include(GetGitRevisionDescription) include(GetGitRevisionDescription)
get_git_head_revision(GIT_REF_SPEC GIT_REV) get_git_head_revision(GIT_REF_SPEC GIT_REV)
@ -349,23 +355,17 @@ git_describe(GIT_DESC --always --long --dirty)
git_branch_name(GIT_BRANCH) git_branch_name(GIT_BRANCH)
get_timestamp(BUILD_DATE) get_timestamp(BUILD_DATE)
# Boost if (NOT USE_SYSTEM_BOOST)
# Prevent boost from linking against libs when building add_definitions( -DBOOST_ALL_NO_LIB )
add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY
-DBOOST_SYSTEM_NO_LIB
-DBOOST_DATE_TIME_NO_LIB
-DBOOST_REGEX_NO_LIB
)
if (USE_SYSTEM_BOOST)
find_package(Boost 1.70.0 COMPONENTS container locale serialization iostreams REQUIRED)
endif() endif()
enable_testing() enable_testing()
add_subdirectory(externals) add_subdirectory(externals)
# Boost (bundled) # Boost
if (NOT USE_SYSTEM_BOOST) if (USE_SYSTEM_BOOST)
add_definitions( -DBOOST_ALL_NO_LIB ) find_package(Boost 1.70.0 COMPONENTS serialization iostreams REQUIRED)
else()
add_library(Boost::boost ALIAS boost) add_library(Boost::boost ALIAS boost)
add_library(Boost::serialization ALIAS boost_serialization) add_library(Boost::serialization ALIAS boost_serialization)
add_library(Boost::iostreams ALIAS boost_iostreams) add_library(Boost::iostreams ALIAS boost_iostreams)

View File

@ -57,7 +57,9 @@ if (DEFINED ENV{CI})
set(BUILD_VERSION ${CMAKE_MATCH_1}) set(BUILD_VERSION ${CMAKE_MATCH_1})
endif() endif()
if (BUILD_VERSION) if (BUILD_VERSION)
set(BUILD_FULLNAME "${REPO_NAME} ${BUILD_VERSION}") # This leaves a trailing space on the last word, but we actually want that
# because of how it's styled in the title bar.
set(BUILD_FULLNAME "${REPO_NAME} ${BUILD_VERSION} ")
else() else()
set(BUILD_FULLNAME "") set(BUILD_FULLNAME "")
endif() endif()

View File

@ -12,29 +12,27 @@ include(DownloadExternals)
include(ExternalProject) include(ExternalProject)
# Boost # Boost
if (NOT USE_SYSTEM_BOOST) set(BOOST_ROOT "${CMAKE_SOURCE_DIR}/externals/boost" CACHE STRING "")
message(STATUS "Including vendored Boost library") set(Boost_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/externals/boost" CACHE STRING "")
set(BOOST_ROOT "${CMAKE_SOURCE_DIR}/externals/boost" CACHE STRING "") set(Boost_NO_SYSTEM_PATHS ON CACHE BOOL "")
set(Boost_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/externals/boost" CACHE STRING "") add_library(boost INTERFACE)
set(Boost_NO_SYSTEM_PATHS ON CACHE BOOL "") target_include_directories(boost SYSTEM INTERFACE ${Boost_INCLUDE_DIR})
add_library(boost INTERFACE)
target_include_directories(boost SYSTEM INTERFACE ${Boost_INCLUDE_DIR})
# Boost::serialization # Boost::serialization
file(GLOB boost_serialization_SRC "${CMAKE_SOURCE_DIR}/externals/boost/libs/serialization/src/*.cpp") file(GLOB boost_serialization_SRC "${CMAKE_SOURCE_DIR}/externals/boost/libs/serialization/src/*.cpp")
add_library(boost_serialization STATIC ${boost_serialization_SRC}) add_library(boost_serialization STATIC ${boost_serialization_SRC})
target_link_libraries(boost_serialization PUBLIC boost) target_link_libraries(boost_serialization PUBLIC boost)
# Boost::iostreams
add_library(
boost_iostreams
STATIC
${CMAKE_SOURCE_DIR}/externals/boost/libs/iostreams/src/file_descriptor.cpp
${CMAKE_SOURCE_DIR}/externals/boost/libs/iostreams/src/mapped_file.cpp
)
target_link_libraries(boost_iostreams PUBLIC boost)
# Boost::iostreams
add_library(
boost_iostreams
STATIC
${CMAKE_SOURCE_DIR}/externals/boost/libs/iostreams/src/file_descriptor.cpp
${CMAKE_SOURCE_DIR}/externals/boost/libs/iostreams/src/mapped_file.cpp
)
target_link_libraries(boost_iostreams PUBLIC boost)
# Add additional boost libs here; remember to ALIAS them in the root CMakeLists! # Add additional boost libs here; remember to ALIAS them in the root CMakeLists!
endif()
# Catch2 # Catch2
set(CATCH_INSTALL_DOCS OFF CACHE BOOL "") set(CATCH_INSTALL_DOCS OFF CACHE BOOL "")
@ -173,38 +171,37 @@ endif()
add_library(json-headers INTERFACE) add_library(json-headers INTERFACE)
target_include_directories(json-headers INTERFACE ./json) target_include_directories(json-headers INTERFACE ./json)
# OpenSSL
if (USE_SYSTEM_OPENSSL)
find_package(OpenSSL 1.1)
if (OPENSSL_FOUND)
set(OPENSSL_LIBRARIES OpenSSL::SSL OpenSSL::Crypto)
endif()
endif()
if (NOT OPENSSL_FOUND)
# LibreSSL
set(LIBRESSL_SKIP_INSTALL ON CACHE BOOL "")
set(OPENSSLDIR "/etc/ssl/")
add_subdirectory(libressl EXCLUDE_FROM_ALL)
target_include_directories(ssl INTERFACE ./libressl/include)
target_compile_definitions(ssl PRIVATE -DHAVE_INET_NTOP)
get_directory_property(OPENSSL_LIBRARIES
DIRECTORY libressl
DEFINITION OPENSSL_LIBS)
endif()
# httplib
add_library(httplib INTERFACE)
target_include_directories(httplib INTERFACE ./httplib)
target_compile_options(httplib INTERFACE -DCPPHTTPLIB_OPENSSL_SUPPORT)
target_link_libraries(httplib INTERFACE ${OPENSSL_LIBRARIES})
if(ANDROID)
add_subdirectory(android-ifaddrs)
endif()
# cpp-jwt
if (ENABLE_WEB_SERVICE) if (ENABLE_WEB_SERVICE)
if (USE_SYSTEM_OPENSSL)
find_package(OpenSSL 1.1)
if (OPENSSL_FOUND)
set(OPENSSL_LIBRARIES OpenSSL::SSL OpenSSL::Crypto)
endif()
endif()
if (NOT OPENSSL_FOUND)
# LibreSSL
set(LIBRESSL_SKIP_INSTALL ON CACHE BOOL "")
set(OPENSSLDIR "/etc/ssl/")
add_subdirectory(libressl EXCLUDE_FROM_ALL)
target_include_directories(ssl INTERFACE ./libressl/include)
target_compile_definitions(ssl PRIVATE -DHAVE_INET_NTOP)
get_directory_property(OPENSSL_LIBRARIES
DIRECTORY libressl
DEFINITION OPENSSL_LIBS)
endif()
if(ANDROID)
add_subdirectory(android-ifaddrs)
endif()
# httplib
add_library(httplib INTERFACE)
target_include_directories(httplib INTERFACE ./httplib)
target_compile_options(httplib INTERFACE -DCPPHTTPLIB_OPENSSL_SUPPORT)
target_link_libraries(httplib INTERFACE ${OPENSSL_LIBRARIES})
# cpp-jwt
add_library(cpp-jwt INTERFACE) add_library(cpp-jwt INTERFACE)
target_include_directories(cpp-jwt INTERFACE ./cpp-jwt/include) target_include_directories(cpp-jwt INTERFACE ./cpp-jwt/include)
target_compile_definitions(cpp-jwt INTERFACE CPP_JWT_USE_VENDORED_NLOHMANN_JSON) target_compile_definitions(cpp-jwt INTERFACE CPP_JWT_USE_VENDORED_NLOHMANN_JSON)

View File

@ -29,7 +29,6 @@
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<application <application
android:name="org.citra.citra_emu.CitraApplication" android:name="org.citra.citra_emu.CitraApplication"

View File

@ -1,10 +1,7 @@
package org.citra.citra_emu.ui.main; package org.citra.citra_emu.ui.main;
import android.Manifest;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri; import android.net.Uri;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
@ -16,7 +13,6 @@ import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.core.splashscreen.SplashScreen; import androidx.core.splashscreen.SplashScreen;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.util.Collections; import java.util.Collections;
@ -128,9 +124,6 @@ public final class MainActivity extends AppCompatActivity implements MainView {
); );
}); });
private final ActivityResultLauncher<String> requestNotificationPermissionLauncher =
registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> { });
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
SplashScreen splashScreen = SplashScreen.installSplashScreen(this); SplashScreen splashScreen = SplashScreen.installSplashScreen(this);
@ -172,12 +165,6 @@ public final class MainActivity extends AppCompatActivity implements MainView {
EmulationActivity.tryDismissRunningNotification(this); EmulationActivity.tryDismissRunningNotification(this);
setInsets(); setInsets();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
requestNotificationPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS);
}
}
} }
@Override @Override

View File

@ -13,8 +13,8 @@ public class EmulationMenuSettings {
public static final int LayoutOption_SingleScreen = 1; public static final int LayoutOption_SingleScreen = 1;
public static final int LayoutOption_LargeScreen = 2; public static final int LayoutOption_LargeScreen = 2;
public static final int LayoutOption_SideScreen = 3; public static final int LayoutOption_SideScreen = 3;
public static final int LayoutOption_MobilePortrait = 5; public static final int LayoutOption_MobilePortrait = 4;
public static final int LayoutOption_MobileLandscape = 6; public static final int LayoutOption_MobileLandscape = 5;
public static boolean getJoystickRelCenter() { public static boolean getJoystickRelCenter() {
return mPreferences.getBoolean("EmulationMenuSettings_JoystickRelCenter", true); return mPreferences.getBoolean("EmulationMenuSettings_JoystickRelCenter", true);

View File

@ -53,7 +53,7 @@ void AndroidMiiSelector::Setup(const Frontend::MiiSelectorConfig& config) {
const u32 return_code = static_cast<u32>( const u32 return_code = static_cast<u32>(
env->GetLongField(data, env->GetFieldID(s_mii_selector_data_class, "return_code", "J"))); env->GetLongField(data, env->GetFieldID(s_mii_selector_data_class, "return_code", "J")));
if (return_code == 1) { if (return_code == 1) {
Finalize(return_code, Mii::MiiData{}); Finalize(return_code, HLE::Applets::MiiData{});
return; return;
} }

View File

@ -26,7 +26,6 @@
#include "core/hle/service/nfc/nfc.h" #include "core/hle/service/nfc/nfc.h"
#include "core/loader/loader.h" #include "core/loader/loader.h"
#include "core/savestate.h" #include "core/savestate.h"
#include "core/telemetry_session.h"
#include "jni/android_common/android_common.h" #include "jni/android_common/android_common.h"
#include "jni/applets/mii_selector.h" #include "jni/applets/mii_selector.h"
#include "jni/applets/swkbd.h" #include "jni/applets/swkbd.h"
@ -152,12 +151,12 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
Camera::RegisterFactory("ndk", std::move(ndk_factory)); Camera::RegisterFactory("ndk", std::move(ndk_factory));
// Register frontend applets // Register frontend applets
Frontend::RegisterDefaultApplets(system); Frontend::RegisterDefaultApplets();
system.RegisterMiiSelector(std::make_shared<MiiSelector::AndroidMiiSelector>()); system.RegisterMiiSelector(std::make_shared<MiiSelector::AndroidMiiSelector>());
system.RegisterSoftwareKeyboard(std::make_shared<SoftwareKeyboard::AndroidKeyboard>()); system.RegisterSoftwareKeyboard(std::make_shared<SoftwareKeyboard::AndroidKeyboard>());
// Register microphone permission check // Register microphone permission check
system.RegisterMicPermissionCheck(&CheckMicPermission); Core::System::GetInstance().RegisterMicPermissionCheck(&CheckMicPermission);
InputManager::Init(); InputManager::Init();
@ -167,7 +166,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
return load_result; return load_result;
} }
auto& telemetry_session = system.TelemetrySession(); auto& telemetry_session = Core::System::GetInstance().TelemetrySession();
telemetry_session.AddField(Common::Telemetry::FieldType::App, "Frontend", "Android"); telemetry_session.AddField(Common::Telemetry::FieldType::App, "Frontend", "Android");
stop_run = false; stop_run = false;
@ -188,7 +187,8 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
audio_stretching_event = audio_stretching_event =
system.CoreTiming().RegisterEvent("AudioStretchingEvent", [&](u64, s64 cycles_late) { system.CoreTiming().RegisterEvent("AudioStretchingEvent", [&](u64, s64 cycles_late) {
if (Settings::values.enable_audio_stretching) { if (Settings::values.enable_audio_stretching) {
system.DSP().EnableStretching(system.GetAndResetPerfStats().emulation_speed < 0.95); Core::DSP().EnableStretching(
Core::System::GetInstance().GetAndResetPerfStats().emulation_speed < 0.95);
} }
system.CoreTiming().ScheduleEvent(audio_stretching_ticks - cycles_late, system.CoreTiming().ScheduleEvent(audio_stretching_ticks - cycles_late,
@ -219,7 +219,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
SCOPE_EXIT({ Settings::values.volume = volume; }); SCOPE_EXIT({ Settings::values.volume = volume; });
Settings::values.volume = 0; Settings::values.volume = 0;
std::unique_lock pause_lock{paused_mutex}; std::unique_lock<std::mutex> pause_lock(paused_mutex);
running_cv.wait(pause_lock, [] { return !pause_emulation || stop_run; }); running_cv.wait(pause_lock, [] { return !pause_emulation || stop_run; });
window->PollEvents(); window->PollEvents();
} }
@ -621,7 +621,7 @@ jobjectArray Java_org_citra_citra_1emu_NativeLibrary_GetSavestateInfo(
return nullptr; return nullptr;
} }
const auto savestates = Core::ListSaveStates(title_id, system.Movie().GetCurrentMovieID()); const auto savestates = Core::ListSaveStates(title_id);
const jobjectArray array = const jobjectArray array =
env->NewObjectArray(static_cast<jsize>(savestates.size()), savestate_info_class, nullptr); env->NewObjectArray(static_cast<jsize>(savestates.size()), savestate_info_class, nullptr);
for (std::size_t i = 0; i < savestates.size(); ++i) { for (std::size_t i = 0; i < savestates.size(); ++i) {

View File

@ -37,33 +37,39 @@ CubebInput::CubebInput(std::string device_id)
} }
CubebInput::~CubebInput() { CubebInput::~CubebInput() {
if (!impl->ctx)
return;
if (impl->stream) { if (impl->stream) {
if (cubeb_stream_stop(impl->stream) != CUBEB_OK) { if (cubeb_stream_stop(impl->stream) != CUBEB_OK) {
LOG_ERROR(Audio, "Error stopping cubeb input stream."); LOG_ERROR(Audio, "Error stopping cubeb input stream.");
} }
cubeb_stream_destroy(impl->stream); cubeb_stream_destroy(impl->stream);
} }
if (impl->ctx) { cubeb_destroy(impl->ctx);
cubeb_destroy(impl->ctx);
}
} }
void CubebInput::StartSampling(const InputParameters& params) { void CubebInput::StartSampling(const InputParameters& params) {
// Cubeb apparently only supports signed 16 bit PCM (and float32 which the 3ds doesn't support) // Cubeb apparently only supports signed 16 bit PCM (and float32 which the 3ds doesn't support)
// TODO: Resample the input stream. // TODO resample the input stream
if (params.sign == Signedness::Unsigned) { if (params.sign == Signedness::Unsigned) {
LOG_ERROR(Audio, LOG_ERROR(Audio,
"Application requested unsupported unsigned pcm format. Falling back to signed."); "Application requested unsupported unsigned pcm format. Falling back to signed");
} }
parameters = params;
impl->sample_size_in_bytes = params.sample_size / 8; impl->sample_size_in_bytes = params.sample_size / 8;
parameters = params;
is_sampling = true;
cubeb_devid input_device = nullptr; cubeb_devid input_device = nullptr;
if (device_id != auto_device_name && !device_id.empty()) { if (device_id != auto_device_name && !device_id.empty()) {
cubeb_device_collection collection; cubeb_device_collection collection;
if (cubeb_enumerate_devices(impl->ctx, CUBEB_DEVICE_TYPE_INPUT, &collection) == CUBEB_OK) { if (cubeb_enumerate_devices(impl->ctx, CUBEB_DEVICE_TYPE_INPUT, &collection) != CUBEB_OK) {
LOG_WARNING(Audio, "Audio input device enumeration not supported");
} else {
const auto collection_end = collection.device + collection.count; const auto collection_end = collection.device + collection.count;
const auto device = std::find_if( const auto device = std::find_if(
collection.device, collection_end, [this](const cubeb_device_info& info) { collection.device, collection_end, [this](const cubeb_device_info& info) {
@ -73,42 +79,39 @@ void CubebInput::StartSampling(const InputParameters& params) {
input_device = device->devid; input_device = device->devid;
} }
cubeb_device_collection_destroy(impl->ctx, &collection); cubeb_device_collection_destroy(impl->ctx, &collection);
} else {
LOG_WARNING(Audio_Sink,
"Audio input device enumeration not supported, using default device.");
} }
} }
cubeb_stream_params input_params = { cubeb_stream_params input_params;
.format = CUBEB_SAMPLE_S16LE, input_params.channels = 1;
.rate = params.sample_rate, input_params.layout = CUBEB_LAYOUT_UNDEFINED;
.channels = 1, input_params.prefs = CUBEB_STREAM_PREF_NONE;
.layout = CUBEB_LAYOUT_UNDEFINED, input_params.format = CUBEB_SAMPLE_S16LE;
}; input_params.rate = params.sample_rate;
u32 latency_frames = 512; // Firefox default u32 latency_frames = 512; // Firefox default
if (cubeb_get_min_latency(impl->ctx, &input_params, &latency_frames) != CUBEB_OK) { if (cubeb_get_min_latency(impl->ctx, &input_params, &latency_frames) != CUBEB_OK) {
LOG_WARNING(Audio, "Error getting minimum input latency, falling back to default latency."); LOG_ERROR(Audio, "Could not get minimum latency");
} }
if (cubeb_stream_init(impl->ctx, &impl->stream, "Citra Microphone", input_device, &input_params, if (cubeb_stream_init(impl->ctx, &impl->stream, "Citra Microphone", input_device, &input_params,
nullptr, nullptr, latency_frames, Impl::DataCallback, Impl::StateCallback, nullptr, nullptr, latency_frames, Impl::DataCallback, Impl::StateCallback,
impl.get()) != CUBEB_OK) { impl.get()) != CUBEB_OK) {
LOG_CRITICAL(Audio, "Error creating cubeb input stream."); LOG_CRITICAL(Audio, "Error creating cubeb input stream");
is_sampling = false;
return; return;
} }
if (cubeb_stream_start(impl->stream) != CUBEB_OK) { if (cubeb_stream_start(impl->stream) != CUBEB_OK) {
LOG_CRITICAL(Audio, "Error starting cubeb input stream."); LOG_CRITICAL(Audio, "Error starting cubeb input stream");
cubeb_stream_destroy(impl->stream); is_sampling = false;
impl->stream = nullptr;
return; return;
} }
is_sampling = true;
} }
void CubebInput::StopSampling() { void CubebInput::StopSampling() {
// TODO(xperia64): Destroy the stream for now to avoid a leak because StartSampling
// reinitializes the stream every time
if (impl->stream) { if (impl->stream) {
cubeb_stream_stop(impl->stream); cubeb_stream_stop(impl->stream);
cubeb_stream_destroy(impl->stream); cubeb_stream_destroy(impl->stream);
@ -118,14 +121,8 @@ void CubebInput::StopSampling() {
} }
void CubebInput::AdjustSampleRate(u32 sample_rate) { void CubebInput::AdjustSampleRate(u32 sample_rate) {
if (!is_sampling) { // TODO This should restart the stream with the new sample rate
return; LOG_ERROR(Audio, "AdjustSampleRate unimplemented!");
}
auto new_parameters = parameters;
new_parameters.sample_rate = sample_rate;
StopSampling();
StartSampling(new_parameters);
} }
Samples CubebInput::Read() { Samples CubebInput::Read() {
@ -139,7 +136,7 @@ Samples CubebInput::Read() {
long CubebInput::Impl::DataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer, long CubebInput::Impl::DataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer,
void* output_buffer, long num_frames) { void* output_buffer, long num_frames) {
auto impl = static_cast<Impl*>(user_data); Impl* impl = static_cast<Impl*>(user_data);
if (!impl) { if (!impl) {
return 0; return 0;
} }
@ -180,7 +177,9 @@ std::vector<std::string> ListCubebInputDevices() {
} }
cubeb_device_collection collection; cubeb_device_collection collection;
if (cubeb_enumerate_devices(ctx, CUBEB_DEVICE_TYPE_INPUT, &collection) == CUBEB_OK) { if (cubeb_enumerate_devices(ctx, CUBEB_DEVICE_TYPE_INPUT, &collection) != CUBEB_OK) {
LOG_WARNING(Audio_Sink, "Audio input device enumeration not supported");
} else {
for (std::size_t i = 0; i < collection.count; i++) { for (std::size_t i = 0; i < collection.count; i++) {
const cubeb_device_info& device = collection.device[i]; const cubeb_device_info& device = collection.device[i];
if (device.state == CUBEB_DEVICE_STATE_ENABLED && device.friendly_name) { if (device.state == CUBEB_DEVICE_STATE_ENABLED && device.friendly_name) {
@ -188,8 +187,6 @@ std::vector<std::string> ListCubebInputDevices() {
} }
} }
cubeb_device_collection_destroy(ctx, &collection); cubeb_device_collection_destroy(ctx, &collection);
} else {
LOG_WARNING(Audio_Sink, "Audio input device enumeration not supported.");
} }
cubeb_destroy(ctx); cubeb_destroy(ctx);

View File

@ -13,6 +13,8 @@
namespace AudioCore { namespace AudioCore {
struct CubebSink::Impl { struct CubebSink::Impl {
unsigned int sample_rate = 0;
cubeb* ctx = nullptr; cubeb* ctx = nullptr;
cubeb_stream* stream = nullptr; cubeb_stream* stream = nullptr;
@ -29,29 +31,28 @@ CubebSink::CubebSink(std::string_view target_device_name) : impl(std::make_uniqu
LOG_CRITICAL(Audio_Sink, "cubeb_init failed"); LOG_CRITICAL(Audio_Sink, "cubeb_init failed");
return; return;
} }
cubeb_set_log_callback(CUBEB_LOG_NORMAL, &Impl::LogCallback);
if (cubeb_set_log_callback(CUBEB_LOG_NORMAL, &Impl::LogCallback) != CUBEB_OK) { impl->sample_rate = native_sample_rate;
LOG_CRITICAL(Audio_Sink, "cubeb_set_log_callback failed");
return;
}
cubeb_stream_params params = { cubeb_stream_params params;
.format = CUBEB_SAMPLE_S16LE, params.rate = impl->sample_rate;
.rate = native_sample_rate, params.channels = 2;
.channels = 2, params.layout = CUBEB_LAYOUT_STEREO;
.layout = CUBEB_LAYOUT_STEREO, params.format = CUBEB_SAMPLE_S16NE;
}; params.prefs = CUBEB_STREAM_PREF_PERSIST;
u32 minimum_latency = 100 * native_sample_rate / 1000; // Firefox default u32 minimum_latency = 100 * impl->sample_rate / 1000; // Firefox default
if (cubeb_get_min_latency(impl->ctx, &params, &minimum_latency) != CUBEB_OK) { if (cubeb_get_min_latency(impl->ctx, &params, &minimum_latency) != CUBEB_OK) {
LOG_WARNING(Audio_Sink, LOG_CRITICAL(Audio_Sink, "Error getting minimum latency");
"Error getting minimum output latency, falling back to default latency.");
} }
cubeb_devid output_device = nullptr; cubeb_devid output_device = nullptr;
if (target_device_name != auto_device_name && !target_device_name.empty()) { if (target_device_name != auto_device_name && !target_device_name.empty()) {
cubeb_device_collection collection; cubeb_device_collection collection;
if (cubeb_enumerate_devices(impl->ctx, CUBEB_DEVICE_TYPE_OUTPUT, &collection) == CUBEB_OK) { if (cubeb_enumerate_devices(impl->ctx, CUBEB_DEVICE_TYPE_OUTPUT, &collection) != CUBEB_OK) {
LOG_WARNING(Audio_Sink, "Audio output device enumeration not supported");
} else {
const auto collection_end{collection.device + collection.count}; const auto collection_end{collection.device + collection.count};
const auto device{ const auto device{
std::find_if(collection.device, collection_end, [&](const cubeb_device_info& info) { std::find_if(collection.device, collection_end, [&](const cubeb_device_info& info) {
@ -62,15 +63,12 @@ CubebSink::CubebSink(std::string_view target_device_name) : impl(std::make_uniqu
output_device = device->devid; output_device = device->devid;
} }
cubeb_device_collection_destroy(impl->ctx, &collection); cubeb_device_collection_destroy(impl->ctx, &collection);
} else {
LOG_WARNING(Audio_Sink,
"Audio output device enumeration not supported, using default device.");
} }
} }
auto stream_err = cubeb_stream_init(impl->ctx, &impl->stream, "CitraAudio", nullptr, nullptr, int stream_err = cubeb_stream_init(impl->ctx, &impl->stream, "CitraAudio", nullptr, nullptr,
output_device, &params, std::max(512u, minimum_latency), output_device, &params, std::max(512u, minimum_latency),
&Impl::DataCallback, &Impl::StateCallback, impl.get()); &Impl::DataCallback, &Impl::StateCallback, impl.get());
if (stream_err != CUBEB_OK) { if (stream_err != CUBEB_OK) {
switch (stream_err) { switch (stream_err) {
case CUBEB_ERROR: case CUBEB_ERROR:
@ -94,20 +92,23 @@ CubebSink::CubebSink(std::string_view target_device_name) : impl(std::make_uniqu
} }
CubebSink::~CubebSink() { CubebSink::~CubebSink() {
if (impl->stream) { if (!impl->ctx) {
if (cubeb_stream_stop(impl->stream) != CUBEB_OK) { return;
LOG_ERROR(Audio_Sink, "Error stopping cubeb stream.");
}
cubeb_stream_destroy(impl->stream);
} }
if (impl->ctx) { if (cubeb_stream_stop(impl->stream) != CUBEB_OK) {
cubeb_destroy(impl->ctx); LOG_CRITICAL(Audio_Sink, "Error stopping cubeb stream");
} }
cubeb_stream_destroy(impl->stream);
cubeb_destroy(impl->ctx);
} }
unsigned int CubebSink::GetNativeSampleRate() const { unsigned int CubebSink::GetNativeSampleRate() const {
return native_sample_rate; if (!impl->ctx)
return native_sample_rate;
return impl->sample_rate;
} }
void CubebSink::SetCallback(std::function<void(s16*, std::size_t)> cb) { void CubebSink::SetCallback(std::function<void(s16*, std::size_t)> cb) {
@ -120,12 +121,13 @@ long CubebSink::Impl::DataCallback(cubeb_stream* stream, void* user_data, const
auto* buffer = static_cast<s16*>(output_buffer); auto* buffer = static_cast<s16*>(output_buffer);
if (!impl || !impl->cb) { if (!impl || !impl->cb) {
LOG_DEBUG(Audio_Sink, "Missing internal data and/or audio callback, emitting zeroes."); LOG_DEBUG(Audio_Sink, "Emitting zeros");
std::memset(output_buffer, 0, num_frames * 2 * sizeof(s16)); std::memset(output_buffer, 0, num_frames * 2 * sizeof(s16));
} else { return num_frames;
impl->cb(buffer, num_frames);
} }
impl->cb(buffer, num_frames);
return num_frames; return num_frames;
} }
@ -147,7 +149,7 @@ void CubebSink::Impl::StateCallback(cubeb_stream* stream, void* user_data, cubeb
} }
void CubebSink::Impl::LogCallback(char const* format, ...) { void CubebSink::Impl::LogCallback(char const* format, ...) {
std::array<char, 512> buffer{}; std::array<char, 512> buffer;
std::va_list args; std::va_list args;
va_start(args, format); va_start(args, format);
#ifdef _MSC_VER #ifdef _MSC_VER
@ -164,13 +166,15 @@ std::vector<std::string> ListCubebSinkDevices() {
std::vector<std::string> device_list; std::vector<std::string> device_list;
cubeb* ctx; cubeb* ctx;
if (cubeb_init(&ctx, "Citra Output Device Enumerator", nullptr) != CUBEB_OK) { if (cubeb_init(&ctx, "CitraEnumerator", nullptr) != CUBEB_OK) {
LOG_CRITICAL(Audio_Sink, "cubeb_init failed"); LOG_CRITICAL(Audio_Sink, "cubeb_init failed");
return {}; return {};
} }
cubeb_device_collection collection; cubeb_device_collection collection;
if (cubeb_enumerate_devices(ctx, CUBEB_DEVICE_TYPE_OUTPUT, &collection) == CUBEB_OK) { if (cubeb_enumerate_devices(ctx, CUBEB_DEVICE_TYPE_OUTPUT, &collection) != CUBEB_OK) {
LOG_WARNING(Audio_Sink, "Audio output device enumeration not supported");
} else {
for (std::size_t i = 0; i < collection.count; i++) { for (std::size_t i = 0; i < collection.count; i++) {
const cubeb_device_info& device = collection.device[i]; const cubeb_device_info& device = collection.device[i];
if (device.state == CUBEB_DEVICE_STATE_ENABLED && device.friendly_name) { if (device.state == CUBEB_DEVICE_STATE_ENABLED && device.friendly_name) {
@ -178,8 +182,6 @@ std::vector<std::string> ListCubebSinkDevices() {
} }
} }
cubeb_device_collection_destroy(ctx, &collection); cubeb_device_collection_destroy(ctx, &collection);
} else {
LOG_WARNING(Audio_Sink, "Audio output device enumeration not supported.");
} }
cubeb_destroy(ctx); cubeb_destroy(ctx);

View File

@ -5,24 +5,20 @@
#include "common/common_types.h" #include "common/common_types.h"
namespace AudioCore {
struct ADTSData { struct ADTSData {
u8 header_length = 0; u8 header_length;
bool mpeg2 = false; bool MPEG2;
u8 profile = 0; u8 profile;
u8 channels = 0; u8 channels;
u8 channel_idx = 0; u8 channel_idx;
u8 framecount = 0; u8 framecount;
u8 samplerate_idx = 0; u8 samplerate_idx;
u32 length = 0; u32 length;
u32 samplerate = 0; u32 samplerate;
}; };
ADTSData ParseADTS(const u8* buffer); ADTSData ParseADTS(const char* buffer);
// last two bytes of MF AAC decoder user data // last two bytes of MF AAC decoder user data
// see https://docs.microsoft.com/en-us/windows/desktop/medfound/aac-decoder#example-media-types // see https://docs.microsoft.com/en-us/windows/desktop/medfound/aac-decoder#example-media-types
u16 MFGetAACTag(const ADTSData& input); u16 MFGetAACTag(const ADTSData& input);
} // namespace AudioCore

View File

@ -3,59 +3,44 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <array> #include <array>
#include "adts.h" #include "adts.h"
#include "common/bit_field.h"
namespace AudioCore {
constexpr std::array<u32, 16> freq_table = {96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, constexpr std::array<u32, 16> freq_table = {96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
16000, 12000, 11025, 8000, 7350, 0, 0, 0}; 16000, 12000, 11025, 8000, 7350, 0, 0, 0};
constexpr std::array<u8, 8> channel_table = {0, 1, 2, 3, 4, 5, 6, 8}; constexpr std::array<u8, 8> channel_table = {0, 1, 2, 3, 4, 5, 6, 8};
struct ADTSHeader { ADTSData ParseADTS(const char* buffer) {
union { u32 tmp = 0;
std::array<u8, 7> raw{}; ADTSData out;
BitFieldBE<52, 12, u64> sync_word;
BitFieldBE<51, 1, u64> mpeg2;
BitFieldBE<49, 2, u64> layer;
BitFieldBE<48, 1, u64> protection_absent;
BitFieldBE<46, 2, u64> profile;
BitFieldBE<42, 4, u64> samplerate_idx;
BitFieldBE<41, 1, u64> private_bit;
BitFieldBE<38, 3, u64> channel_idx;
BitFieldBE<37, 1, u64> originality;
BitFieldBE<36, 1, u64> home;
BitFieldBE<35, 1, u64> copyright_id;
BitFieldBE<34, 1, u64> copyright_id_start;
BitFieldBE<21, 13, u64> frame_length;
BitFieldBE<10, 11, u64> buffer_fullness;
BitFieldBE<8, 2, u64> frame_count;
};
};
ADTSData ParseADTS(const u8* buffer) {
ADTSHeader header;
memcpy(header.raw.data(), buffer, sizeof(header.raw));
// sync word 0xfff // sync word 0xfff
if (header.sync_word != 0xfff) { tmp = (buffer[0] << 8) | (buffer[1] & 0xf0);
return {}; if ((tmp & 0xffff) != 0xfff0) {
out.length = 0;
return out;
} }
ADTSData out{};
// bit 16 = no CRC // bit 16 = no CRC
out.header_length = header.protection_absent ? 7 : 9; out.header_length = (buffer[1] & 0x1) ? 7 : 9;
out.mpeg2 = static_cast<bool>(header.mpeg2); out.MPEG2 = (buffer[1] >> 3) & 0x1;
// bit 17 to 18 // bit 17 to 18
out.profile = static_cast<u8>(header.profile) + 1; out.profile = (buffer[2] >> 6) + 1;
// bit 19 to 22 // bit 19 to 22
out.samplerate_idx = static_cast<u8>(header.samplerate_idx); tmp = (buffer[2] >> 2) & 0xf;
out.samplerate = header.samplerate_idx > 15 ? 0 : freq_table[header.samplerate_idx]; out.samplerate_idx = tmp;
out.samplerate = (tmp > 15) ? 0 : freq_table[tmp];
// bit 24 to 26 // bit 24 to 26
out.channel_idx = static_cast<u8>(header.channel_idx); tmp = ((buffer[2] & 0x1) << 2) | ((buffer[3] >> 6) & 0x3);
out.channels = (header.channel_idx > 7) ? 0 : channel_table[header.channel_idx]; out.channel_idx = tmp;
out.channels = (tmp > 7) ? 0 : channel_table[tmp];
// bit 55 to 56 // bit 55 to 56
out.framecount = static_cast<u8>(header.frame_count + 1); out.framecount = (buffer[6] & 0x3) + 1;
// bit 31 to 43 // bit 31 to 43
out.length = static_cast<u32>(header.frame_length); tmp = (buffer[3] & 0x3) << 11;
tmp |= (buffer[4] << 3) & 0x7f8;
tmp |= (buffer[5] >> 5) & 0x7;
out.length = tmp;
return out; return out;
} }
@ -76,4 +61,3 @@ u16 MFGetAACTag(const ADTSData& input) {
return tag; return tag;
} }
} // namespace AudioCore

View File

@ -24,7 +24,7 @@ private:
std::optional<BinaryMessage> Decode(const BinaryMessage& request); std::optional<BinaryMessage> Decode(const BinaryMessage& request);
void Clear(); void Clear();
bool InitializeDecoder(AudioCore::ADTSData& adts_header); bool InitializeDecoder(ADTSData& adts_header);
static OSStatus DataFunc(AudioConverterRef in_audio_converter, u32* io_number_data_packets, static OSStatus DataFunc(AudioConverterRef in_audio_converter, u32* io_number_data_packets,
AudioBufferList* io_data, AudioBufferList* io_data,
@ -33,7 +33,7 @@ private:
Memory::MemorySystem& memory; Memory::MemorySystem& memory;
AudioCore::ADTSData adts_config; ADTSData adts_config;
AudioStreamBasicDescription output_format = {}; AudioStreamBasicDescription output_format = {};
AudioConverterRef converter = nullptr; AudioConverterRef converter = nullptr;
@ -85,11 +85,7 @@ std::optional<BinaryMessage> AudioToolboxDecoder::Impl::ProcessRequest(
case DecoderCommand::EncodeDecode: { case DecoderCommand::EncodeDecode: {
return Decode(request); return Decode(request);
} }
case DecoderCommand::Shutdown: case DecoderCommand::Unknown: {
case DecoderCommand::SaveState:
case DecoderCommand::LoadState: {
LOG_WARNING(Audio_DSP, "Got unimplemented binary request: {}",
static_cast<u16>(request.header.cmd));
BinaryMessage response = request; BinaryMessage response = request;
response.header.result = ResultStatus::Success; response.header.result = ResultStatus::Success;
return response; return response;
@ -101,7 +97,7 @@ std::optional<BinaryMessage> AudioToolboxDecoder::Impl::ProcessRequest(
} }
} }
bool AudioToolboxDecoder::Impl::InitializeDecoder(AudioCore::ADTSData& adts_header) { bool AudioToolboxDecoder::Impl::InitializeDecoder(ADTSData& adts_header) {
if (converter) { if (converter) {
if (adts_config.channels == adts_header.channels && if (adts_config.channels == adts_header.channels &&
adts_config.samplerate == adts_header.samplerate) { adts_config.samplerate == adts_header.samplerate) {
@ -183,9 +179,8 @@ std::optional<BinaryMessage> AudioToolboxDecoder::Impl::Decode(const BinaryMessa
return {}; return {};
} }
const auto data = auto data = memory.GetFCRAMPointer(request.decode_aac_request.src_addr - Memory::FCRAM_PADDR);
memory.GetFCRAMPointer(request.decode_aac_request.src_addr - Memory::FCRAM_PADDR); auto adts_header = ParseADTS(reinterpret_cast<const char*>(data));
auto adts_header = AudioCore::ParseADTS(data);
curr_data = data + adts_header.header_length; curr_data = data + adts_header.header_length;
curr_data_len = request.decode_aac_request.size - adts_header.header_length; curr_data_len = request.decode_aac_request.size - adts_header.header_length;

View File

@ -42,9 +42,7 @@ std::optional<BinaryMessage> NullDecoder::ProcessRequest(const BinaryMessage& re
BinaryMessage response{}; BinaryMessage response{};
switch (request.header.cmd) { switch (request.header.cmd) {
case DecoderCommand::Init: case DecoderCommand::Init:
case DecoderCommand::Shutdown: case DecoderCommand::Unknown:
case DecoderCommand::SaveState:
case DecoderCommand::LoadState:
response = request; response = request;
response.header.result = ResultStatus::Success; response.header.result = ResultStatus::Success;
return response; return response;

View File

@ -14,16 +14,9 @@
namespace AudioCore::HLE { namespace AudioCore::HLE {
enum class DecoderCommand : u16 { enum class DecoderCommand : u16 {
/// Initializes the decoder.
Init = 0, Init = 0,
/// Decodes/encodes a data frame.
EncodeDecode = 1, EncodeDecode = 1,
/// Shuts down the decoder. Unknown = 2, // Probably UnInit
Shutdown = 2,
/// Loads the saved decoder state. Used for DSP wake.
LoadState = 3,
/// Saves the decoder state. Used for DSP sleep.
SaveState = 4,
}; };
enum class DecoderCodec : u16 { enum class DecoderCodec : u16 {

View File

@ -111,11 +111,7 @@ std::optional<BinaryMessage> FDKDecoder::Impl::ProcessRequest(const BinaryMessag
case DecoderCommand::EncodeDecode: { case DecoderCommand::EncodeDecode: {
return Decode(request); return Decode(request);
} }
case DecoderCommand::Shutdown: case DecoderCommand::Unknown: {
case DecoderCommand::SaveState:
case DecoderCommand::LoadState: {
LOG_WARNING(Audio_DSP, "Got unimplemented binary request: {}",
static_cast<u16>(request.header.cmd));
BinaryMessage response = request; BinaryMessage response = request;
response.header.result = ResultStatus::Success; response.header.result = ResultStatus::Success;
return response; return response;

View File

@ -80,11 +80,7 @@ std::optional<BinaryMessage> FFMPEGDecoder::Impl::ProcessRequest(const BinaryMes
case DecoderCommand::EncodeDecode: { case DecoderCommand::EncodeDecode: {
return Decode(request); return Decode(request);
} }
case DecoderCommand::Shutdown: case DecoderCommand::Unknown: {
case DecoderCommand::SaveState:
case DecoderCommand::LoadState: {
LOG_WARNING(Audio_DSP, "Got unimplemented binary request: {}",
static_cast<u16>(request.header.cmd));
BinaryMessage response = request; BinaryMessage response = request;
response.header.result = ResultStatus::Success; response.header.result = ResultStatus::Success;
return response; return response;

View File

@ -8,7 +8,6 @@
#include <boost/serialization/vector.hpp> #include <boost/serialization/vector.hpp>
#include <boost/serialization/weak_ptr.hpp> #include <boost/serialization/weak_ptr.hpp>
#include "audio_core/audio_types.h" #include "audio_core/audio_types.h"
#include "common/archives.h"
#ifdef HAVE_MF #ifdef HAVE_MF
#include "audio_core/hle/wmf_decoder.h" #include "audio_core/hle/wmf_decoder.h"
#elif HAVE_AUDIOTOOLBOX #elif HAVE_AUDIOTOOLBOX
@ -320,10 +319,6 @@ void DspHle::Impl::PipeWrite(DspPipe pipe_number, std::span<const u8> buffer) {
pipe_data[static_cast<u32>(pipe_number)].resize(sizeof(value)); pipe_data[static_cast<u32>(pipe_number)].resize(sizeof(value));
std::memcpy(pipe_data[static_cast<u32>(pipe_number)].data(), &value, sizeof(value)); std::memcpy(pipe_data[static_cast<u32>(pipe_number)].data(), &value, sizeof(value));
} }
auto dsp = dsp_dsp.lock();
if (dsp) {
dsp->SignalInterrupt(InterruptType::Pipe, DspPipe::Binary);
}
break; break;
} }
default: default:
@ -466,6 +461,8 @@ void DspHle::Impl::AudioTickCallback(s64 cycles_late) {
// TODO(merry): Signal all the other interrupts as appropriate. // TODO(merry): Signal all the other interrupts as appropriate.
if (auto service = dsp_dsp.lock()) { if (auto service = dsp_dsp.lock()) {
service->SignalInterrupt(InterruptType::Pipe, DspPipe::Audio); service->SignalInterrupt(InterruptType::Pipe, DspPipe::Audio);
// HACK(merry): Added to prevent regressions. Will remove soon.
service->SignalInterrupt(InterruptType::Pipe, DspPipe::Binary);
} }
} }

View File

@ -27,7 +27,7 @@ public:
~Impl(); ~Impl();
std::optional<BinaryMessage> ProcessRequest(const BinaryMessage& request); std::optional<BinaryMessage> ProcessRequest(const BinaryMessage& request);
bool SetMediaType(const AudioCore::ADTSData& adts_data); bool SetMediaType(const ADTSData& adts_data);
private: private:
std::optional<BinaryMessage> Initalize(const BinaryMessage& request); std::optional<BinaryMessage> Initalize(const BinaryMessage& request);
@ -36,8 +36,8 @@ private:
Memory::MemorySystem& memory; Memory::MemorySystem& memory;
std::unique_ptr<AMediaCodec, AMediaCodecRelease> decoder; std::unique_ptr<AMediaCodec, AMediaCodecRelease> decoder;
// default: 2 channles, 48000 samplerate // default: 2 channles, 48000 samplerate
AudioCore::ADTSData mADTSData{ ADTSData mADTSData{
/*header_length*/ 7, /*mpeg2*/ false, /*profile*/ 2, /*header_length*/ 7, /*MPEG2*/ false, /*profile*/ 2,
/*channels*/ 2, /*channel_idx*/ 2, /*framecount*/ 0, /*channels*/ 2, /*channel_idx*/ 2, /*framecount*/ 0,
/*samplerate_idx*/ 3, /*length*/ 0, /*samplerate*/ 48000}; /*samplerate_idx*/ 3, /*length*/ 0, /*samplerate*/ 48000};
}; };
@ -54,7 +54,7 @@ std::optional<BinaryMessage> MediaNDKDecoder::Impl::Initalize(const BinaryMessag
return response; return response;
} }
bool MediaNDKDecoder::Impl::SetMediaType(const AudioCore::ADTSData& adts_data) { bool MediaNDKDecoder::Impl::SetMediaType(const ADTSData& adts_data) {
const char* mime = "audio/mp4a-latm"; const char* mime = "audio/mp4a-latm";
if (decoder && mADTSData.profile == adts_data.profile && if (decoder && mADTSData.profile == adts_data.profile &&
mADTSData.channel_idx == adts_data.channel_idx && mADTSData.channel_idx == adts_data.channel_idx &&
@ -110,11 +110,7 @@ std::optional<BinaryMessage> MediaNDKDecoder::Impl::ProcessRequest(const BinaryM
case DecoderCommand::EncodeDecode: { case DecoderCommand::EncodeDecode: {
return Decode(request); return Decode(request);
} }
case DecoderCommand::Shutdown: case DecoderCommand::Unknown: {
case DecoderCommand::SaveState:
case DecoderCommand::LoadState: {
LOG_WARNING(Audio_DSP, "Got unimplemented binary request: {}",
static_cast<u16>(request.header.cmd));
BinaryMessage response = request; BinaryMessage response = request;
response.header.result = ResultStatus::Success; response.header.result = ResultStatus::Success;
return response; return response;
@ -141,9 +137,8 @@ std::optional<BinaryMessage> MediaNDKDecoder::Impl::Decode(const BinaryMessage&
return response; return response;
} }
const u8* data = u8* data = memory.GetFCRAMPointer(request.decode_aac_request.src_addr - Memory::FCRAM_PADDR);
memory.GetFCRAMPointer(request.decode_aac_request.src_addr - Memory::FCRAM_PADDR); ADTSData adts_data = ParseADTS(reinterpret_cast<const char*>(data));
ADTSData adts_data = AudioCore::ParseADTS(data);
SetMediaType(adts_data); SetMediaType(adts_data);
response.decode_aac_response.sample_rate = GetSampleRateEnum(adts_data.samplerate); response.decode_aac_response.sample_rate = GetSampleRateEnum(adts_data.samplerate);
response.decode_aac_response.num_channels = adts_data.channels; response.decode_aac_response.num_channels = adts_data.channels;

View File

@ -66,7 +66,7 @@ public:
private: private:
const std::size_t source_id; const std::size_t source_id;
const Memory::MemorySystem* memory_system{}; Memory::MemorySystem* memory_system;
StereoFrame16 current_frame; StereoFrame16 current_frame;
using Format = SourceConfiguration::Configuration::Format; using Format = SourceConfiguration::Configuration::Format;

View File

@ -23,8 +23,7 @@ private:
std::optional<BinaryMessage> Decode(const BinaryMessage& request); std::optional<BinaryMessage> Decode(const BinaryMessage& request);
MFOutputState DecodingLoop(AudioCore::ADTSData adts_header, MFOutputState DecodingLoop(ADTSData adts_header, std::array<std::vector<u8>, 2>& out_streams);
std::array<std::vector<u8>, 2>& out_streams);
bool transform_initialized = false; bool transform_initialized = false;
bool format_selected = false; bool format_selected = false;
@ -116,11 +115,7 @@ std::optional<BinaryMessage> WMFDecoder::Impl::ProcessRequest(const BinaryMessag
case DecoderCommand::EncodeDecode: { case DecoderCommand::EncodeDecode: {
return Decode(request); return Decode(request);
} }
case DecoderCommand::Shutdown: case DecoderCommand::Unknown: {
case DecoderCommand::SaveState:
case DecoderCommand::LoadState: {
LOG_WARNING(Audio_DSP, "Got unimplemented binary request: {}",
static_cast<u16>(request.header.cmd));
BinaryMessage response = request; BinaryMessage response = request;
response.header.result = ResultStatus::Success; response.header.result = ResultStatus::Success;
return response; return response;
@ -140,7 +135,7 @@ std::optional<BinaryMessage> WMFDecoder::Impl::Initalize(const BinaryMessage& re
return response; return response;
} }
MFOutputState WMFDecoder::Impl::DecodingLoop(AudioCore::ADTSData adts_header, MFOutputState WMFDecoder::Impl::DecodingLoop(ADTSData adts_header,
std::array<std::vector<u8>, 2>& out_streams) { std::array<std::vector<u8>, 2>& out_streams) {
std::optional<std::vector<f32>> output_buffer; std::optional<std::vector<f32>> output_buffer;
@ -211,14 +206,14 @@ std::optional<BinaryMessage> WMFDecoder::Impl::Decode(const BinaryMessage& reque
request.decode_aac_request.src_addr); request.decode_aac_request.src_addr);
return std::nullopt; return std::nullopt;
} }
const u8* data = u8* data = memory.GetFCRAMPointer(request.decode_aac_request.src_addr - Memory::FCRAM_PADDR);
memory.GetFCRAMPointer(request.decode_aac_request.src_addr - Memory::FCRAM_PADDR);
std::array<std::vector<u8>, 2> out_streams; std::array<std::vector<u8>, 2> out_streams;
unique_mfptr<IMFSample> sample; unique_mfptr<IMFSample> sample;
MFInputState input_status = MFInputState::OK; MFInputState input_status = MFInputState::OK;
MFOutputState output_status = MFOutputState::OK; MFOutputState output_status = MFOutputState::OK;
std::optional<ADTSMeta> adts_meta = DetectMediaType(data, request.decode_aac_request.size); std::optional<ADTSMeta> adts_meta =
DetectMediaType((char*)data, request.decode_aac_request.size);
if (!adts_meta) { if (!adts_meta) {
LOG_ERROR(Audio_DSP, "Unable to deduce decoding parameters from ADTS stream"); LOG_ERROR(Audio_DSP, "Unable to deduce decoding parameters from ADTS stream");

View File

@ -110,9 +110,8 @@ unique_mfptr<IMFSample> CreateSample(const void* data, DWORD len, DWORD alignmen
return sample; return sample;
} }
bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, const ADTSData& adts,
const AudioCore::ADTSData& adts, const UINT8* user_data, const UINT8* user_data, UINT32 user_data_len, GUID audio_format) {
UINT32 user_data_len, GUID audio_format) {
HRESULT hr = S_OK; HRESULT hr = S_OK;
unique_mfptr<IMFMediaType> t; unique_mfptr<IMFMediaType> t;
@ -191,12 +190,12 @@ bool SelectOutputMediaType(IMFTransform* transform, int out_stream_id, GUID audi
return false; return false;
} }
std::optional<ADTSMeta> DetectMediaType(const u8* buffer, std::size_t len) { std::optional<ADTSMeta> DetectMediaType(char* buffer, std::size_t len) {
if (len < 7) { if (len < 7) {
return std::nullopt; return std::nullopt;
} }
AudioCore::ADTSData tmp; ADTSData tmp;
ADTSMeta result; ADTSMeta result;
// see https://docs.microsoft.com/en-us/windows/desktop/api/mmreg/ns-mmreg-heaacwaveinfo_tag // see https://docs.microsoft.com/en-us/windows/desktop/api/mmreg/ns-mmreg-heaacwaveinfo_tag
// for the meaning of the byte array below // for the meaning of the byte array below
@ -208,7 +207,7 @@ std::optional<ADTSMeta> DetectMediaType(const u8* buffer, std::size_t len) {
UINT8 aac_tmp[] = {0x01, 0x00, 0xfe, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0x00, 0x00}; UINT8 aac_tmp[] = {0x01, 0x00, 0xfe, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0x00, 0x00};
uint16_t tag = 0; uint16_t tag = 0;
tmp = AudioCore::ParseADTS(buffer); tmp = ParseADTS(buffer);
if (tmp.length == 0) { if (tmp.length == 0) {
return std::nullopt; return std::nullopt;
} }
@ -216,7 +215,7 @@ std::optional<ADTSMeta> DetectMediaType(const u8* buffer, std::size_t len) {
tag = MFGetAACTag(tmp); tag = MFGetAACTag(tmp);
aac_tmp[12] |= (tag & 0xff00) >> 8; aac_tmp[12] |= (tag & 0xff00) >> 8;
aac_tmp[13] |= (tag & 0x00ff); aac_tmp[13] |= (tag & 0x00ff);
std::memcpy(&(result.ADTSHeader), &tmp, sizeof(AudioCore::ADTSData)); std::memcpy(&(result.ADTSHeader), &tmp, sizeof(ADTSData));
std::memcpy(&(result.AACTag), aac_tmp, 14); std::memcpy(&(result.AACTag), aac_tmp, 14);
return result; return result;
} }

View File

@ -99,7 +99,7 @@ void ReportError(std::string msg, HRESULT hr);
// data type for transferring ADTS metadata between functions // data type for transferring ADTS metadata between functions
struct ADTSMeta { struct ADTSMeta {
AudioCore::ADTSData ADTSHeader; ADTSData ADTSHeader;
u8 AACTag[14]; u8 AACTag[14];
}; };
@ -110,10 +110,10 @@ bool InitMFDLL();
unique_mfptr<IMFTransform> MFDecoderInit(GUID audio_format = MFAudioFormat_AAC); unique_mfptr<IMFTransform> MFDecoderInit(GUID audio_format = MFAudioFormat_AAC);
unique_mfptr<IMFSample> CreateSample(const void* data, DWORD len, DWORD alignment = 1, unique_mfptr<IMFSample> CreateSample(const void* data, DWORD len, DWORD alignment = 1,
LONGLONG duration = 0); LONGLONG duration = 0);
bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, const ADTSData& adts,
const AudioCore::ADTSData& adts, const UINT8* user_data, const UINT8* user_data, UINT32 user_data_len,
UINT32 user_data_len, GUID audio_format = MFAudioFormat_AAC); GUID audio_format = MFAudioFormat_AAC);
std::optional<ADTSMeta> DetectMediaType(const u8* buffer, std::size_t len); std::optional<ADTSMeta> DetectMediaType(char* buffer, std::size_t len);
bool SelectOutputMediaType(IMFTransform* transform, int out_stream_id, bool SelectOutputMediaType(IMFTransform* transform, int out_stream_id,
GUID audio_format = MFAudioFormat_PCM); GUID audio_format = MFAudioFormat_PCM);
void MFFlush(IMFTransform* transform); void MFFlush(IMFTransform* transform);

View File

@ -19,6 +19,7 @@
#include "common/detached_tasks.h" #include "common/detached_tasks.h"
#include "common/file_util.h" #include "common/file_util.h"
#include "common/logging/backend.h" #include "common/logging/backend.h"
#include "common/logging/filter.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/scm_rev.h" #include "common/scm_rev.h"
#include "common/scope_exit.h" #include "common/scope_exit.h"
@ -27,15 +28,18 @@
#include "core/core.h" #include "core/core.h"
#include "core/dumping/backend.h" #include "core/dumping/backend.h"
#include "core/dumping/ffmpeg_backend.h" #include "core/dumping/ffmpeg_backend.h"
#include "core/file_sys/cia_container.h"
#include "core/frontend/applets/default_applets.h" #include "core/frontend/applets/default_applets.h"
#include "core/frontend/framebuffer_layout.h" #include "core/frontend/framebuffer_layout.h"
#include "core/gdbstub/gdbstub.h"
#include "core/hle/service/am/am.h" #include "core/hle/service/am/am.h"
#include "core/hle/service/cfg/cfg.h" #include "core/hle/service/cfg/cfg.h"
#include "core/loader/loader.h"
#include "core/movie.h" #include "core/movie.h"
#include "core/telemetry_session.h"
#include "input_common/main.h" #include "input_common/main.h"
#include "network/network.h" #include "network/network.h"
#include "video_core/renderer_base.h" #include "video_core/renderer_base.h"
#include "video_core/video_core.h"
#undef _UNICODE #undef _UNICODE
#include <getopt.h> #include <getopt.h>
@ -327,7 +331,7 @@ int main(int argc, char** argv) {
} }
auto& system = Core::System::GetInstance(); auto& system = Core::System::GetInstance();
auto& movie = system.Movie(); auto& movie = Core::Movie::GetInstance();
if (!movie_record.empty()) { if (!movie_record.empty()) {
movie.PrepareForRecording(); movie.PrepareForRecording();
@ -342,7 +346,7 @@ int main(int argc, char** argv) {
system.ApplySettings(); system.ApplySettings();
// Register frontend applets // Register frontend applets
Frontend::RegisterDefaultApplets(system); Frontend::RegisterDefaultApplets();
EmuWindow_SDL2::InitializeSDL2(); EmuWindow_SDL2::InitializeSDL2();
@ -350,12 +354,12 @@ int main(int argc, char** argv) {
bool is_secondary) -> std::unique_ptr<EmuWindow_SDL2> { bool is_secondary) -> std::unique_ptr<EmuWindow_SDL2> {
switch (Settings::values.graphics_api.GetValue()) { switch (Settings::values.graphics_api.GetValue()) {
case Settings::GraphicsAPI::OpenGL: case Settings::GraphicsAPI::OpenGL:
return std::make_unique<EmuWindow_SDL2_GL>(system, fullscreen, is_secondary); return std::make_unique<EmuWindow_SDL2_GL>(fullscreen, is_secondary);
case Settings::GraphicsAPI::Software: case Settings::GraphicsAPI::Software:
return std::make_unique<EmuWindow_SDL2_SW>(system, fullscreen, is_secondary); return std::make_unique<EmuWindow_SDL2_SW>(system, fullscreen, is_secondary);
} }
LOG_ERROR(Frontend, "Invalid Graphics API, using OpenGL"); LOG_ERROR(Frontend, "Invalid Graphics API, using OpenGL");
return std::make_unique<EmuWindow_SDL2_GL>(system, fullscreen, is_secondary); return std::make_unique<EmuWindow_SDL2_GL>(fullscreen, is_secondary);
}; };
const auto emu_window{create_emu_window(fullscreen, false)}; const auto emu_window{create_emu_window(fullscreen, false)};

View File

@ -109,8 +109,7 @@ void EmuWindow_SDL2::Fullscreen() {
SDL_MaximizeWindow(render_window); SDL_MaximizeWindow(render_window);
} }
EmuWindow_SDL2::EmuWindow_SDL2(Core::System& system_, bool is_secondary) EmuWindow_SDL2::EmuWindow_SDL2(bool is_secondary) : EmuWindow(is_secondary) {}
: EmuWindow(is_secondary), system(system_) {}
EmuWindow_SDL2::~EmuWindow_SDL2() { EmuWindow_SDL2::~EmuWindow_SDL2() {
SDL_Quit(); SDL_Quit();
@ -128,54 +127,16 @@ void EmuWindow_SDL2::InitializeSDL2() {
SDL_SetMainReady(); SDL_SetMainReady();
} }
u32 EmuWindow_SDL2::GetEventWindowId(const SDL_Event& event) const {
switch (event.type) {
case SDL_WINDOWEVENT:
return event.window.windowID;
case SDL_KEYDOWN:
case SDL_KEYUP:
return event.key.windowID;
case SDL_MOUSEMOTION:
return event.motion.windowID;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
return event.button.windowID;
case SDL_MOUSEWHEEL:
return event.wheel.windowID;
case SDL_FINGERDOWN:
case SDL_FINGERMOTION:
case SDL_FINGERUP:
return event.tfinger.windowID;
case SDL_TEXTEDITING:
return event.edit.windowID;
case SDL_TEXTEDITING_EXT:
return event.editExt.windowID;
case SDL_TEXTINPUT:
return event.text.windowID;
case SDL_DROPBEGIN:
case SDL_DROPFILE:
case SDL_DROPTEXT:
case SDL_DROPCOMPLETE:
return event.drop.windowID;
case SDL_USEREVENT:
return event.user.windowID;
default:
// Event is not for any particular window, so we can just pretend it's for this one.
return render_window_id;
}
}
void EmuWindow_SDL2::PollEvents() { void EmuWindow_SDL2::PollEvents() {
SDL_Event event; SDL_Event event;
std::vector<SDL_Event> other_window_events; std::vector<SDL_Event> other_window_events;
// SDL_PollEvent returns 0 when there are no more events in the event queue // SDL_PollEvent returns 0 when there are no more events in the event queue
while (SDL_PollEvent(&event)) { while (SDL_PollEvent(&event)) {
if (GetEventWindowId(event) != render_window_id) { if (event.window.windowID != render_window_id) {
other_window_events.push_back(event); other_window_events.push_back(event);
continue; continue;
} }
switch (event.type) { switch (event.type) {
case SDL_WINDOWEVENT: case SDL_WINDOWEVENT:
switch (event.window.event) { switch (event.window.event) {
@ -241,7 +202,7 @@ void EmuWindow_SDL2::OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minima
void EmuWindow_SDL2::UpdateFramerateCounter() { void EmuWindow_SDL2::UpdateFramerateCounter() {
const u32 current_time = SDL_GetTicks(); const u32 current_time = SDL_GetTicks();
if (current_time > last_time + 2000) { if (current_time > last_time + 2000) {
const auto results = system.GetAndResetPerfStats(); const auto results = Core::System::GetInstance().GetAndResetPerfStats();
const auto title = const auto title =
fmt::format("Citra {} | {}-{} | FPS: {:.0f} ({:.0f}%)", Common::g_build_fullname, fmt::format("Citra {} | {}-{} | FPS: {:.0f} ({:.0f}%)", Common::g_build_fullname,
Common::g_scm_branch, Common::g_scm_desc, results.game_fps, Common::g_scm_branch, Common::g_scm_desc, results.game_fps,

View File

@ -8,16 +8,11 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "core/frontend/emu_window.h" #include "core/frontend/emu_window.h"
union SDL_Event;
struct SDL_Window; struct SDL_Window;
namespace Core {
class System;
}
class EmuWindow_SDL2 : public Frontend::EmuWindow { class EmuWindow_SDL2 : public Frontend::EmuWindow {
public: public:
explicit EmuWindow_SDL2(Core::System& system_, bool is_secondary); explicit EmuWindow_SDL2(bool is_secondary);
~EmuWindow_SDL2(); ~EmuWindow_SDL2();
/// Initializes SDL2 /// Initializes SDL2
@ -36,9 +31,6 @@ public:
void RequestClose(); void RequestClose();
protected: protected:
/// Gets the ID of the window an event originated from.
u32 GetEventWindowId(const SDL_Event& event) const;
/// Called by PollEvents when a key is pressed or released. /// Called by PollEvents when a key is pressed or released.
void OnKeyEvent(int key, u8 state); void OnKeyEvent(int key, u8 state);
@ -86,6 +78,4 @@ protected:
/// Keeps track of how often to update the title bar during gameplay /// Keeps track of how often to update the title bar during gameplay
u32 last_time = 0; u32 last_time = 0;
Core::System& system;
}; };

View File

@ -42,8 +42,8 @@ private:
SDL_GLContext context; SDL_GLContext context;
}; };
EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(Core::System& system_, bool fullscreen, bool is_secondary) EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(bool fullscreen, bool is_secondary)
: EmuWindow_SDL2{system_, is_secondary} { : EmuWindow_SDL2{is_secondary} {
// Initialize the window // Initialize the window
if (Settings::values.use_gles) { if (Settings::values.use_gles) {
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);

View File

@ -9,13 +9,9 @@
struct SDL_Window; struct SDL_Window;
namespace Core {
class System;
}
class EmuWindow_SDL2_GL : public EmuWindow_SDL2 { class EmuWindow_SDL2_GL : public EmuWindow_SDL2 {
public: public:
explicit EmuWindow_SDL2_GL(Core::System& system_, bool fullscreen, bool is_secondary); explicit EmuWindow_SDL2_GL(bool fullscreen, bool is_secondary);
~EmuWindow_SDL2_GL(); ~EmuWindow_SDL2_GL();
void Present() override; void Present() override;

View File

@ -18,7 +18,7 @@
class DummyContext : public Frontend::GraphicsContext {}; class DummyContext : public Frontend::GraphicsContext {};
EmuWindow_SDL2_SW::EmuWindow_SDL2_SW(Core::System& system_, bool fullscreen, bool is_secondary) EmuWindow_SDL2_SW::EmuWindow_SDL2_SW(Core::System& system_, bool fullscreen, bool is_secondary)
: EmuWindow_SDL2{system_, is_secondary}, system{system_} { : EmuWindow_SDL2{is_secondary}, system{system_} {
std::string window_title = fmt::format("Citra {} | {}-{}", Common::g_build_fullname, std::string window_title = fmt::format("Citra {} | {}-{}", Common::g_build_fullname,
Common::g_scm_branch, Common::g_scm_desc); Common::g_scm_branch, Common::g_scm_desc);
render_window = render_window =

View File

@ -67,5 +67,6 @@ void QtMiiSelector::OpenDialog() {
dialog.return_code, index); dialog.return_code, index);
const auto mii_data = dialog.miis.at(index); const auto mii_data = dialog.miis.at(index);
Finalize(dialog.return_code, dialog.return_code == 0 ? std::move(mii_data) : Mii::MiiData{}); Finalize(dialog.return_code,
dialog.return_code == 0 ? std::move(mii_data) : HLE::Applets::MiiData{});
} }

View File

@ -24,7 +24,7 @@ private:
QVBoxLayout* layout; QVBoxLayout* layout;
QtMiiSelector* mii_selector; QtMiiSelector* mii_selector;
u32 return_code = 0; u32 return_code = 0;
std::vector<Mii::MiiData> miis; std::vector<HLE::Applets::MiiData> miis;
friend class QtMiiSelector; friend class QtMiiSelector;
}; };

View File

@ -44,8 +44,7 @@
static Frontend::WindowSystemType GetWindowSystemType(); static Frontend::WindowSystemType GetWindowSystemType();
EmuThread::EmuThread(Core::System& system_, Frontend::GraphicsContext& core_context) EmuThread::EmuThread(Frontend::GraphicsContext& core_context) : core_context(core_context) {}
: system{system_}, core_context(core_context) {}
EmuThread::~EmuThread() = default; EmuThread::~EmuThread() = default;
@ -63,6 +62,7 @@ static GMainWindow* GetMainWindow() {
void EmuThread::run() { void EmuThread::run() {
MicroProfileOnThreadCreate("EmuThread"); MicroProfileOnThreadCreate("EmuThread");
const auto scope = core_context.Acquire(); const auto scope = core_context.Acquire();
Core::System& system = Core::System::GetInstance();
if (Settings::values.preload_textures) { if (Settings::values.preload_textures) {
emit LoadProgress(VideoCore::LoadCallbackStage::Preload, 0, 0); emit LoadProgress(VideoCore::LoadCallbackStage::Preload, 0, 0);
@ -107,7 +107,7 @@ void EmuThread::run() {
} }
if (result != Core::System::ResultStatus::Success) { if (result != Core::System::ResultStatus::Success) {
this->SetRunning(false); this->SetRunning(false);
emit ErrorThrown(result, system.GetStatusDetails()); emit ErrorThrown(result, Core::System::GetInstance().GetStatusDetails());
} }
was_active = running || exec_step; was_active = running || exec_step;
@ -248,8 +248,8 @@ public:
#ifdef HAS_OPENGL #ifdef HAS_OPENGL
class OpenGLRenderWidget : public RenderWidget { class OpenGLRenderWidget : public RenderWidget {
public: public:
explicit OpenGLRenderWidget(GRenderWindow* parent, Core::System& system_, bool is_secondary) explicit OpenGLRenderWidget(GRenderWindow* parent, bool is_secondary)
: RenderWidget(parent), system(system_), is_secondary(is_secondary) { : RenderWidget(parent), is_secondary(is_secondary) {
setAttribute(Qt::WA_NativeWindow); setAttribute(Qt::WA_NativeWindow);
setAttribute(Qt::WA_PaintOnScreen); setAttribute(Qt::WA_PaintOnScreen);
if (GetWindowSystemType() == Frontend::WindowSystemType::Wayland) { if (GetWindowSystemType() == Frontend::WindowSystemType::Wayland) {
@ -266,7 +266,7 @@ public:
if (!isVisible()) { if (!isVisible()) {
return; return;
} }
if (!system.IsPoweredOn()) { if (!Core::System::GetInstance().IsPoweredOn()) {
return; return;
} }
context->MakeCurrent(); context->MakeCurrent();
@ -284,7 +284,6 @@ public:
private: private:
std::unique_ptr<Frontend::GraphicsContext> context{}; std::unique_ptr<Frontend::GraphicsContext> context{};
Core::System& system;
bool is_secondary; bool is_secondary;
}; };
#endif #endif
@ -297,7 +296,7 @@ struct SoftwareRenderWidget : public RenderWidget {
if (!isVisible()) { if (!isVisible()) {
return; return;
} }
if (!system.IsPoweredOn()) { if (!Core::System::GetInstance().IsPoweredOn()) {
return; return;
} }
@ -387,6 +386,10 @@ GRenderWindow::GRenderWindow(QWidget* parent_, EmuThread* emu_thread_, Core::Sys
bool is_secondary_) bool is_secondary_)
: QWidget(parent_), EmuWindow(is_secondary_), emu_thread(emu_thread_), system{system_} { : QWidget(parent_), EmuWindow(is_secondary_), emu_thread(emu_thread_), system{system_} {
setWindowTitle(QStringLiteral("Citra %1 | %2-%3")
.arg(QString::fromUtf8(Common::g_build_name),
QString::fromUtf8(Common::g_scm_branch),
QString::fromUtf8(Common::g_scm_desc)));
setAttribute(Qt::WA_AcceptTouchEvents); setAttribute(Qt::WA_AcceptTouchEvents);
auto layout = new QHBoxLayout(this); auto layout = new QHBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0); layout->setContentsMargins(0, 0, 0, 0);
@ -663,7 +666,7 @@ bool GRenderWindow::InitializeOpenGL() {
// TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground, // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground,
// WA_DontShowOnScreen, WA_DeleteOnClose // WA_DontShowOnScreen, WA_DeleteOnClose
auto child = new OpenGLRenderWidget(this, system, is_secondary); auto child = new OpenGLRenderWidget(this, is_secondary);
child_widget = child; child_widget = child;
child_widget->windowHandle()->create(); child_widget->windowHandle()->create();

View File

@ -18,10 +18,6 @@ class QTouchEvent;
class GRenderWindow; class GRenderWindow;
namespace Core {
class System;
}
namespace VideoCore { namespace VideoCore {
enum class LoadCallbackStage; enum class LoadCallbackStage;
} }
@ -30,7 +26,7 @@ class EmuThread final : public QThread {
Q_OBJECT Q_OBJECT
public: public:
explicit EmuThread(Core::System& system_, Frontend::GraphicsContext& context); explicit EmuThread(Frontend::GraphicsContext& context);
~EmuThread() override; ~EmuThread() override;
/** /**
@ -84,7 +80,6 @@ private:
std::mutex running_mutex; std::mutex running_mutex;
std::condition_variable running_cv; std::condition_variable running_cv;
Core::System& system;
Frontend::GraphicsContext& core_context; Frontend::GraphicsContext& core_context;
signals: signals:

View File

@ -9,12 +9,11 @@
#include "citra_qt/compatdb.h" #include "citra_qt/compatdb.h"
#include "common/telemetry.h" #include "common/telemetry.h"
#include "core/core.h" #include "core/core.h"
#include "core/telemetry_session.h"
#include "ui_compatdb.h" #include "ui_compatdb.h"
CompatDB::CompatDB(Core::TelemetrySession& telemetry_session_, QWidget* parent) CompatDB::CompatDB(QWidget* parent)
: QWizard(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), : QWizard(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
ui{std::make_unique<Ui::CompatDB>()}, telemetry_session{telemetry_session_} { ui{std::make_unique<Ui::CompatDB>()} {
ui->setupUi(this); ui->setupUi(this);
connect(ui->radioButton_Perfect, &QRadioButton::clicked, this, &CompatDB::EnableNext); connect(ui->radioButton_Perfect, &QRadioButton::clicked, this, &CompatDB::EnableNext);
connect(ui->radioButton_Great, &QRadioButton::clicked, this, &CompatDB::EnableNext); connect(ui->radioButton_Great, &QRadioButton::clicked, this, &CompatDB::EnableNext);
@ -52,15 +51,16 @@ void CompatDB::Submit() {
case CompatDBPage::Final: case CompatDBPage::Final:
back(); back();
LOG_DEBUG(Frontend, "Compatibility Rating: {}", compatibility->checkedId()); LOG_DEBUG(Frontend, "Compatibility Rating: {}", compatibility->checkedId());
telemetry_session.AddField(Common::Telemetry::FieldType::UserFeedback, "Compatibility", Core::System::GetInstance().TelemetrySession().AddField(
compatibility->checkedId()); Common::Telemetry::FieldType::UserFeedback, "Compatibility",
compatibility->checkedId());
button(NextButton)->setEnabled(false); button(NextButton)->setEnabled(false);
button(NextButton)->setText(tr("Submitting")); button(NextButton)->setText(tr("Submitting"));
button(CancelButton)->setVisible(false); button(CancelButton)->setVisible(false);
testcase_watcher.setFuture( testcase_watcher.setFuture(QtConcurrent::run(
QtConcurrent::run([this] { return telemetry_session.SubmitTestcase(); })); [] { return Core::System::GetInstance().TelemetrySession().SubmitTestcase(); }));
break; break;
default: default:
LOG_ERROR(Frontend, "Unexpected page: {}", currentId()); LOG_ERROR(Frontend, "Unexpected page: {}", currentId());

View File

@ -8,10 +8,6 @@
#include <QFutureWatcher> #include <QFutureWatcher>
#include <QWizard> #include <QWizard>
namespace Core {
class TelemetrySession;
}
namespace Ui { namespace Ui {
class CompatDB; class CompatDB;
} }
@ -20,7 +16,7 @@ class CompatDB : public QWizard {
Q_OBJECT Q_OBJECT
public: public:
explicit CompatDB(Core::TelemetrySession& telemetry_session_, QWidget* parent = nullptr); explicit CompatDB(QWidget* parent = nullptr);
~CompatDB(); ~CompatDB();
private: private:
@ -31,6 +27,4 @@ private:
void Submit(); void Submit();
void OnTestcaseSubmitted(); void OnTestcaseSubmitted();
void EnableNext(); void EnableNext();
Core::TelemetrySession& telemetry_session;
}; };

View File

@ -29,7 +29,7 @@ Config::~Config() {
const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = { const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = {
Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_T, Qt::Key_G, Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_T, Qt::Key_G,
Qt::Key_F, Qt::Key_H, Qt::Key_Q, Qt::Key_W, Qt::Key_M, Qt::Key_N, Qt::Key_F, Qt::Key_H, Qt::Key_Q, Qt::Key_W, Qt::Key_M, Qt::Key_N,
Qt::Key_O, Qt::Key_P, Qt::Key_1, Qt::Key_2, Qt::Key_B, Qt::Key_V, Qt::Key_O, Qt::Key_P, Qt::Key_1, Qt::Key_2, Qt::Key_B,
}; };
const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> Config::default_analogs{{ const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> Config::default_analogs{{
@ -772,11 +772,6 @@ void Config::ReadUIGameListValues() {
ReadBasicSetting(UISettings::values.game_list_hide_no_icon); ReadBasicSetting(UISettings::values.game_list_hide_no_icon);
ReadBasicSetting(UISettings::values.game_list_single_line_mode); ReadBasicSetting(UISettings::values.game_list_single_line_mode);
ReadBasicSetting(UISettings::values.show_compat_column);
ReadBasicSetting(UISettings::values.show_region_column);
ReadBasicSetting(UISettings::values.show_type_column);
ReadBasicSetting(UISettings::values.show_size_column);
qt_config->endGroup(); qt_config->endGroup();
} }
@ -1235,11 +1230,6 @@ void Config::SaveUIGameListValues() {
WriteBasicSetting(UISettings::values.game_list_hide_no_icon); WriteBasicSetting(UISettings::values.game_list_hide_no_icon);
WriteBasicSetting(UISettings::values.game_list_single_line_mode); WriteBasicSetting(UISettings::values.game_list_single_line_mode);
WriteBasicSetting(UISettings::values.show_compat_column);
WriteBasicSetting(UISettings::values.show_region_column);
WriteBasicSetting(UISettings::values.show_type_column);
WriteBasicSetting(UISettings::values.show_size_column);
qt_config->endGroup(); qt_config->endGroup();
} }

View File

@ -21,8 +21,68 @@
<item> <item>
<widget class="QTabWidget" name="tabWidget"> <widget class="QTabWidget" name="tabWidget">
<property name="currentIndex"> <property name="currentIndex">
<number>-1</number> <number>0</number>
</property> </property>
<widget class="ConfigureGeneral" name="generalTab">
<attribute name="title">
<string>General</string>
</attribute>
</widget>
<widget class="ConfigureSystem" name="systemTab">
<attribute name="title">
<string>System</string>
</attribute>
</widget>
<widget class="ConfigureInput" name="inputTab">
<attribute name="title">
<string>Input</string>
</attribute>
</widget>
<widget class="ConfigureHotkeys" name="hotkeysTab">
<attribute name="title">
<string>Hotkeys</string>
</attribute>
</widget>
<widget class="ConfigureGraphics" name="graphicsTab">
<attribute name="title">
<string>Graphics</string>
</attribute>
</widget>
<widget class="ConfigureEnhancements" name="enhancementsTab">
<attribute name="title">
<string>Enhancements</string>
</attribute>
</widget>
<widget class="ConfigureAudio" name="audioTab">
<attribute name="title">
<string>Audio</string>
</attribute>
</widget>
<widget class="ConfigureCamera" name="cameraTab">
<attribute name="title">
<string>Camera</string>
</attribute>
</widget>
<widget class="ConfigureDebug" name="debugTab">
<attribute name="title">
<string>Debug</string>
</attribute>
</widget>
<widget class="ConfigureStorage" name="storageTab">
<attribute name="title">
<string>Storage</string>
</attribute>
</widget>
<widget class="ConfigureWeb" name="webTab">
<attribute name="title">
<string>Web</string>
</attribute>
</widget>
<widget class="ConfigureUi" name="uiTab">
<attribute name="title">
<string>UI</string>
</attribute>
</widget>
</widget> </widget>
</item> </item>
</layout> </layout>

View File

@ -10,13 +10,14 @@
#include "citra_qt/configuration/configuration_shared.h" #include "citra_qt/configuration/configuration_shared.h"
#include "citra_qt/configuration/configure_audio.h" #include "citra_qt/configuration/configure_audio.h"
#include "common/settings.h" #include "common/settings.h"
#include "core/core.h"
#include "ui_configure_audio.h" #include "ui_configure_audio.h"
#if defined(__APPLE__) #if defined(__APPLE__)
#include "common/apple_authorization.h" #include "common/apple_authorization.h"
#endif #endif
ConfigureAudio::ConfigureAudio(bool is_powered_on, QWidget* parent) ConfigureAudio::ConfigureAudio(QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureAudio>()) { : QWidget(parent), ui(std::make_unique<Ui::ConfigureAudio>()) {
ui->setupUi(this); ui->setupUi(this);
@ -26,7 +27,8 @@ ConfigureAudio::ConfigureAudio(bool is_powered_on, QWidget* parent)
AudioCore::GetSinkName(static_cast<AudioCore::SinkType>(type)).data())); AudioCore::GetSinkName(static_cast<AudioCore::SinkType>(type)).data()));
} }
ui->emulation_combo_box->setEnabled(!is_powered_on); const bool is_running = Core::System::GetInstance().IsPoweredOn();
ui->emulation_combo_box->setEnabled(!is_running);
connect(ui->volume_slider, &QSlider::valueChanged, this, connect(ui->volume_slider, &QSlider::valueChanged, this,
&ConfigureAudio::SetVolumeIndicatorText); &ConfigureAudio::SetVolumeIndicatorText);

View File

@ -19,7 +19,7 @@ class ConfigureAudio : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit ConfigureAudio(bool is_powered_on, QWidget* parent = nullptr); explicit ConfigureAudio(QWidget* parent = nullptr);
~ConfigureAudio() override; ~ConfigureAudio() override;
void ApplyConfiguration(); void ApplyConfiguration();

View File

@ -47,7 +47,8 @@ ConfigureCamera::~ConfigureCamera() {
} }
void ConfigureCamera::ConnectEvents() { void ConfigureCamera::ConnectEvents() {
connect(ui->image_source, qOverload<int>(&QComboBox::currentIndexChanged), this, connect(ui->image_source,
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
[this](int index) { [this](int index) {
StopPreviewing(); StopPreviewing();
UpdateImageSourceUI(); UpdateImageSourceUI();
@ -57,33 +58,36 @@ void ConfigureCamera::ConnectEvents() {
} }
#endif #endif
}); });
connect(ui->camera_selection, qOverload<int>(&QComboBox::currentIndexChanged), this, [this] { connect(ui->camera_selection,
StopPreviewing(); static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, [this] {
if (GetCameraSelection() != current_selected) { StopPreviewing();
RecordConfig(); if (GetCameraSelection() != current_selected) {
} RecordConfig();
if (ui->camera_selection->currentIndex() == 1) { }
ui->camera_mode->setCurrentIndex(1); // Double if (ui->camera_selection->currentIndex() == 1) {
if (camera_name[0] == camera_name[2] && camera_config[0] == camera_config[2]) { ui->camera_mode->setCurrentIndex(1); // Double
ui->camera_mode->setCurrentIndex(0); // Single if (camera_name[0] == camera_name[2] && camera_config[0] == camera_config[2]) {
} ui->camera_mode->setCurrentIndex(0); // Single
} }
UpdateCameraMode(); }
SetConfiguration(); UpdateCameraMode();
}); SetConfiguration();
connect(ui->camera_mode, qOverload<int>(&QComboBox::currentIndexChanged), this, [this] { });
StopPreviewing(); connect(ui->camera_mode, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
ui->camera_position_label->setVisible(ui->camera_mode->currentIndex() == 1); this, [this] {
ui->camera_position->setVisible(ui->camera_mode->currentIndex() == 1); StopPreviewing();
current_selected = GetCameraSelection(); ui->camera_position_label->setVisible(ui->camera_mode->currentIndex() == 1);
}); ui->camera_position->setVisible(ui->camera_mode->currentIndex() == 1);
connect(ui->camera_position, qOverload<int>(&QComboBox::currentIndexChanged), this, [this] { current_selected = GetCameraSelection();
StopPreviewing(); });
if (GetCameraSelection() != current_selected) { connect(ui->camera_position,
RecordConfig(); static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, [this] {
} StopPreviewing();
SetConfiguration(); if (GetCameraSelection() != current_selected) {
}); RecordConfig();
}
SetConfiguration();
});
connect(ui->toolButton, &QToolButton::clicked, this, &ConfigureCamera::OnToolButtonClicked); connect(ui->toolButton, &QToolButton::clicked, this, &ConfigureCamera::OnToolButtonClicked);
connect(ui->preview_button, &QPushButton::clicked, this, [this] { StartPreviewing(); }); connect(ui->preview_button, &QPushButton::clicked, this, [this] { StartPreviewing(); });
connect(ui->prompt_before_load, &QCheckBox::stateChanged, this, [this](int state) { connect(ui->prompt_before_load, &QCheckBox::stateChanged, this, [this](int state) {

View File

@ -11,8 +11,10 @@
#include "core/cheats/gateway_cheat.h" #include "core/cheats/gateway_cheat.h"
#include "ui_configure_cheats.h" #include "ui_configure_cheats.h"
ConfigureCheats::ConfigureCheats(Core::System& system, u64 title_id_, QWidget* parent) ConfigureCheats::ConfigureCheats(Cheats::CheatEngine& cheat_engine_, u64 title_id_, QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureCheats>()), title_id{title_id_} { : QWidget(parent),
ui(std::make_unique<Ui::ConfigureCheats>()), cheat_engine{cheat_engine_}, title_id{
title_id_} {
// Setup gui control settings // Setup gui control settings
ui->setupUi(this); ui->setupUi(this);
ui->tableCheats->setColumnWidth(0, 30); ui->tableCheats->setColumnWidth(0, 30);
@ -34,15 +36,14 @@ ConfigureCheats::ConfigureCheats(Core::System& system, u64 title_id_, QWidget* p
[this] { SaveCheat(ui->tableCheats->currentRow()); }); [this] { SaveCheat(ui->tableCheats->currentRow()); });
connect(ui->buttonDelete, &QPushButton::clicked, this, &ConfigureCheats::OnDeleteCheat); connect(ui->buttonDelete, &QPushButton::clicked, this, &ConfigureCheats::OnDeleteCheat);
cheat_engine = std::make_unique<Cheats::CheatEngine>(title_id, system); cheat_engine.LoadCheatFile(title_id);
LoadCheats(); LoadCheats();
} }
ConfigureCheats::~ConfigureCheats() = default; ConfigureCheats::~ConfigureCheats() = default;
void ConfigureCheats::LoadCheats() { void ConfigureCheats::LoadCheats() {
cheats = cheat_engine->GetCheats(); cheats = cheat_engine.GetCheats();
const int cheats_count = static_cast<int>(cheats.size()); const int cheats_count = static_cast<int>(cheats.size());
ui->tableCheats->setRowCount(cheats_count); ui->tableCheats->setRowCount(cheats_count);
@ -106,12 +107,12 @@ bool ConfigureCheats::SaveCheat(int row) {
ui->textNotes->toPlainText().toStdString()); ui->textNotes->toPlainText().toStdString());
if (newly_created) { if (newly_created) {
cheat_engine->AddCheat(cheat); cheat_engine.AddCheat(std::move(cheat));
newly_created = false; newly_created = false;
} else { } else {
cheat_engine->UpdateCheat(row, cheat); cheat_engine.UpdateCheat(row, std::move(cheat));
} }
cheat_engine->SaveCheatFile(); cheat_engine.SaveCheatFile(title_id);
int previous_row = ui->tableCheats->currentRow(); int previous_row = ui->tableCheats->currentRow();
int previous_col = ui->tableCheats->currentColumn(); int previous_col = ui->tableCheats->currentColumn();
@ -161,7 +162,7 @@ void ConfigureCheats::OnCheckChanged(int state) {
const QCheckBox* checkbox = qobject_cast<QCheckBox*>(sender()); const QCheckBox* checkbox = qobject_cast<QCheckBox*>(sender());
int row = static_cast<int>(checkbox->property("row").toInt()); int row = static_cast<int>(checkbox->property("row").toInt());
cheats[row]->SetEnabled(state); cheats[row]->SetEnabled(state);
cheat_engine->SaveCheatFile(); cheat_engine.SaveCheatFile(title_id);
} }
void ConfigureCheats::OnTextEdited() { void ConfigureCheats::OnTextEdited() {
@ -173,8 +174,8 @@ void ConfigureCheats::OnDeleteCheat() {
if (newly_created) { if (newly_created) {
newly_created = false; newly_created = false;
} else { } else {
cheat_engine->RemoveCheat(ui->tableCheats->currentRow()); cheat_engine.RemoveCheat(ui->tableCheats->currentRow());
cheat_engine->SaveCheatFile(); cheat_engine.SaveCheatFile(title_id);
} }
LoadCheats(); LoadCheats();

View File

@ -5,6 +5,7 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include <span>
#include <QWidget> #include <QWidget>
#include "common/common_types.h" #include "common/common_types.h"
@ -13,10 +14,6 @@ class CheatBase;
class CheatEngine; class CheatEngine;
} // namespace Cheats } // namespace Cheats
namespace Core {
class System;
}
namespace Ui { namespace Ui {
class ConfigureCheats; class ConfigureCheats;
} // namespace Ui } // namespace Ui
@ -25,7 +22,8 @@ class ConfigureCheats : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit ConfigureCheats(Core::System& system, u64 title_id, QWidget* parent = nullptr); explicit ConfigureCheats(Cheats::CheatEngine& cheat_engine, u64 title_id_,
QWidget* parent = nullptr);
~ConfigureCheats(); ~ConfigureCheats();
bool ApplyConfiguration(); bool ApplyConfiguration();
@ -58,9 +56,9 @@ private slots:
private: private:
std::unique_ptr<Ui::ConfigureCheats> ui; std::unique_ptr<Ui::ConfigureCheats> ui;
std::vector<std::shared_ptr<Cheats::CheatBase>> cheats; Cheats::CheatEngine& cheat_engine;
std::span<const std::shared_ptr<Cheats::CheatBase>> cheats;
bool edited = false, newly_created = false; bool edited = false, newly_created = false;
int last_row = -1, last_col = -1; int last_row = -1, last_col = -1;
u64 title_id; u64 title_id;
std::unique_ptr<Cheats::CheatEngine> cheat_engine;
}; };

View File

@ -11,6 +11,7 @@
#include "common/file_util.h" #include "common/file_util.h"
#include "common/logging/backend.h" #include "common/logging/backend.h"
#include "common/settings.h" #include "common/settings.h"
#include "core/core.h"
#include "ui_configure_debug.h" #include "ui_configure_debug.h"
// The QSlider doesn't have an easy way to set a custom step amount, // The QSlider doesn't have an easy way to set a custom step amount,
@ -24,8 +25,8 @@ static constexpr int SettingsToSlider(int value) {
return (value - 5) / 5; return (value - 5) / 5;
} }
ConfigureDebug::ConfigureDebug(bool is_powered_on_, QWidget* parent) ConfigureDebug::ConfigureDebug(QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureDebug>()), is_powered_on{is_powered_on_} { : QWidget(parent), ui(std::make_unique<Ui::ConfigureDebug>()) {
ui->setupUi(this); ui->setupUi(this);
SetConfiguration(); SetConfiguration();
@ -34,6 +35,7 @@ ConfigureDebug::ConfigureDebug(bool is_powered_on_, QWidget* parent)
QDesktopServices::openUrl(QUrl::fromLocalFile(path)); QDesktopServices::openUrl(QUrl::fromLocalFile(path));
}); });
const bool is_powered_on = Core::System::GetInstance().IsPoweredOn();
ui->toggle_cpu_jit->setEnabled(!is_powered_on); ui->toggle_cpu_jit->setEnabled(!is_powered_on);
ui->toggle_renderer_debug->setEnabled(!is_powered_on); ui->toggle_renderer_debug->setEnabled(!is_powered_on);
@ -57,7 +59,7 @@ void ConfigureDebug::SetConfiguration() {
ui->toggle_gdbstub->setChecked(Settings::values.use_gdbstub.GetValue()); ui->toggle_gdbstub->setChecked(Settings::values.use_gdbstub.GetValue());
ui->gdbport_spinbox->setEnabled(Settings::values.use_gdbstub.GetValue()); ui->gdbport_spinbox->setEnabled(Settings::values.use_gdbstub.GetValue());
ui->gdbport_spinbox->setValue(Settings::values.gdbstub_port.GetValue()); ui->gdbport_spinbox->setValue(Settings::values.gdbstub_port.GetValue());
ui->toggle_console->setEnabled(!is_powered_on); ui->toggle_console->setEnabled(!Core::System::GetInstance().IsPoweredOn());
ui->toggle_console->setChecked(UISettings::values.show_console.GetValue()); ui->toggle_console->setChecked(UISettings::values.show_console.GetValue());
ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter.GetValue())); ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter.GetValue()));
ui->toggle_cpu_jit->setChecked(Settings::values.use_cpu_jit.GetValue()); ui->toggle_cpu_jit->setChecked(Settings::values.use_cpu_jit.GetValue());

View File

@ -15,7 +15,7 @@ class ConfigureDebug : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit ConfigureDebug(bool is_powered_on, QWidget* parent = nullptr); explicit ConfigureDebug(QWidget* parent = nullptr);
~ConfigureDebug() override; ~ConfigureDebug() override;
void ApplyConfiguration(); void ApplyConfiguration();
@ -25,5 +25,4 @@ public:
private: private:
std::unique_ptr<Ui::ConfigureDebug> ui; std::unique_ptr<Ui::ConfigureDebug> ui;
bool is_powered_on;
}; };

View File

@ -4,19 +4,8 @@
#include <map> #include <map>
#include <QListWidgetItem> #include <QListWidgetItem>
#include "citra_qt/configuration/configure_audio.h" #include "citra_qt/configuration/config.h"
#include "citra_qt/configuration/configure_camera.h"
#include "citra_qt/configuration/configure_debug.h"
#include "citra_qt/configuration/configure_dialog.h" #include "citra_qt/configuration/configure_dialog.h"
#include "citra_qt/configuration/configure_enhancements.h"
#include "citra_qt/configuration/configure_general.h"
#include "citra_qt/configuration/configure_graphics.h"
#include "citra_qt/configuration/configure_hotkeys.h"
#include "citra_qt/configuration/configure_input.h"
#include "citra_qt/configuration/configure_storage.h"
#include "citra_qt/configuration/configure_system.h"
#include "citra_qt/configuration/configure_ui.h"
#include "citra_qt/configuration/configure_web.h"
#include "citra_qt/hotkeys.h" #include "citra_qt/hotkeys.h"
#include "common/settings.h" #include "common/settings.h"
#include "core/core.h" #include "core/core.h"
@ -25,41 +14,16 @@
ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, Core::System& system_, ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, Core::System& system_,
bool enable_web_config) bool enable_web_config)
: QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()}, registry{registry_}, : QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()}, registry{registry_},
system{system_}, is_powered_on{system.IsPoweredOn()}, system{system_} {
general_tab{std::make_unique<ConfigureGeneral>(this)},
system_tab{std::make_unique<ConfigureSystem>(system, this)},
input_tab{std::make_unique<ConfigureInput>(this)},
hotkeys_tab{std::make_unique<ConfigureHotkeys>(this)},
graphics_tab{std::make_unique<ConfigureGraphics>(is_powered_on, this)},
enhancements_tab{std::make_unique<ConfigureEnhancements>(this)},
audio_tab{std::make_unique<ConfigureAudio>(is_powered_on, this)},
camera_tab{std::make_unique<ConfigureCamera>(this)},
debug_tab{std::make_unique<ConfigureDebug>(is_powered_on, this)},
storage_tab{std::make_unique<ConfigureStorage>(is_powered_on, this)},
web_tab{std::make_unique<ConfigureWeb>(this)}, ui_tab{std::make_unique<ConfigureUi>(this)} {
Settings::SetConfiguringGlobal(true); Settings::SetConfiguringGlobal(true);
ui->setupUi(this); ui->setupUi(this);
ui->hotkeysTab->Populate(registry);
ui->tabWidget->addTab(general_tab.get(), tr("General")); ui->webTab->SetWebServiceConfigEnabled(enable_web_config);
ui->tabWidget->addTab(system_tab.get(), tr("System"));
ui->tabWidget->addTab(input_tab.get(), tr("Input"));
ui->tabWidget->addTab(hotkeys_tab.get(), tr("Hotkeys"));
ui->tabWidget->addTab(graphics_tab.get(), tr("Graphics"));
ui->tabWidget->addTab(enhancements_tab.get(), tr("Enhancements"));
ui->tabWidget->addTab(audio_tab.get(), tr("Audio"));
ui->tabWidget->addTab(camera_tab.get(), tr("Camera"));
ui->tabWidget->addTab(debug_tab.get(), tr("Debug"));
ui->tabWidget->addTab(storage_tab.get(), tr("Storage"));
ui->tabWidget->addTab(web_tab.get(), tr("Web"));
ui->tabWidget->addTab(ui_tab.get(), tr("UI"));
hotkeys_tab->Populate(registry);
web_tab->SetWebServiceConfigEnabled(enable_web_config);
PopulateSelectionList(); PopulateSelectionList();
connect(ui_tab.get(), &ConfigureUi::LanguageChanged, this, &ConfigureDialog::OnLanguageChanged); connect(ui->uiTab, &ConfigureUi::LanguageChanged, this, &ConfigureDialog::OnLanguageChanged);
connect(ui->selectorList, &QListWidget::itemSelectionChanged, this, connect(ui->selectorList, &QListWidget::itemSelectionChanged, this,
&ConfigureDialog::UpdateVisibleTabs); &ConfigureDialog::UpdateVisibleTabs);
@ -67,46 +31,46 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, Cor
ui->selectorList->setCurrentRow(0); ui->selectorList->setCurrentRow(0);
// Set up used key list synchronisation // Set up used key list synchronisation
connect(input_tab.get(), &ConfigureInput::InputKeysChanged, hotkeys_tab.get(), connect(ui->inputTab, &ConfigureInput::InputKeysChanged, ui->hotkeysTab,
&ConfigureHotkeys::OnInputKeysChanged); &ConfigureHotkeys::OnInputKeysChanged);
connect(hotkeys_tab.get(), &ConfigureHotkeys::HotkeysChanged, input_tab.get(), connect(ui->hotkeysTab, &ConfigureHotkeys::HotkeysChanged, ui->inputTab,
&ConfigureInput::OnHotkeysChanged); &ConfigureInput::OnHotkeysChanged);
// Synchronise lists upon initialisation // Synchronise lists upon initialisation
input_tab->EmitInputKeysChanged(); ui->inputTab->EmitInputKeysChanged();
hotkeys_tab->EmitHotkeysChanged(); ui->hotkeysTab->EmitHotkeysChanged();
} }
ConfigureDialog::~ConfigureDialog() = default; ConfigureDialog::~ConfigureDialog() = default;
void ConfigureDialog::SetConfiguration() { void ConfigureDialog::SetConfiguration() {
general_tab->SetConfiguration(); ui->generalTab->SetConfiguration();
system_tab->SetConfiguration(); ui->systemTab->SetConfiguration();
input_tab->LoadConfiguration(); ui->inputTab->LoadConfiguration();
graphics_tab->SetConfiguration(); ui->graphicsTab->SetConfiguration();
enhancements_tab->SetConfiguration(); ui->enhancementsTab->SetConfiguration();
audio_tab->SetConfiguration(); ui->audioTab->SetConfiguration();
camera_tab->SetConfiguration(); ui->cameraTab->SetConfiguration();
debug_tab->SetConfiguration(); ui->debugTab->SetConfiguration();
web_tab->SetConfiguration(); ui->webTab->SetConfiguration();
ui_tab->SetConfiguration(); ui->uiTab->SetConfiguration();
storage_tab->SetConfiguration(); ui->storageTab->SetConfiguration();
} }
void ConfigureDialog::ApplyConfiguration() { void ConfigureDialog::ApplyConfiguration() {
general_tab->ApplyConfiguration(); ui->generalTab->ApplyConfiguration();
system_tab->ApplyConfiguration(); ui->systemTab->ApplyConfiguration();
input_tab->ApplyConfiguration(); ui->inputTab->ApplyConfiguration();
input_tab->ApplyProfile(); ui->inputTab->ApplyProfile();
hotkeys_tab->ApplyConfiguration(registry); ui->hotkeysTab->ApplyConfiguration(registry);
graphics_tab->ApplyConfiguration(); ui->graphicsTab->ApplyConfiguration();
enhancements_tab->ApplyConfiguration(); ui->enhancementsTab->ApplyConfiguration();
audio_tab->ApplyConfiguration(); ui->audioTab->ApplyConfiguration();
camera_tab->ApplyConfiguration(); ui->cameraTab->ApplyConfiguration();
debug_tab->ApplyConfiguration(); ui->debugTab->ApplyConfiguration();
web_tab->ApplyConfiguration(); ui->webTab->ApplyConfiguration();
ui_tab->ApplyConfiguration(); ui->uiTab->ApplyConfiguration();
storage_tab->ApplyConfiguration(); ui->storageTab->ApplyConfiguration();
system.ApplySettings(); system.ApplySettings();
Settings::LogSettings(); Settings::LogSettings();
} }
@ -117,11 +81,11 @@ void ConfigureDialog::PopulateSelectionList() {
ui->selectorList->clear(); ui->selectorList->clear();
const std::array<std::pair<QString, QList<QWidget*>>, 5> items{ const std::array<std::pair<QString, QList<QWidget*>>, 5> items{
{{tr("General"), {general_tab.get(), web_tab.get(), debug_tab.get(), ui_tab.get()}}, {{tr("General"), {ui->generalTab, ui->webTab, ui->debugTab, ui->uiTab}},
{tr("System"), {system_tab.get(), camera_tab.get(), storage_tab.get()}}, {tr("System"), {ui->systemTab, ui->cameraTab, ui->storageTab}},
{tr("Graphics"), {enhancements_tab.get(), graphics_tab.get()}}, {tr("Graphics"), {ui->enhancementsTab, ui->graphicsTab}},
{tr("Audio"), {audio_tab.get()}}, {tr("Audio"), {ui->audioTab}},
{tr("Controls"), {input_tab.get(), hotkeys_tab.get()}}}}; {tr("Controls"), {ui->inputTab, ui->hotkeysTab}}}};
for (const auto& entry : items) { for (const auto& entry : items) {
auto* const item = new QListWidgetItem(entry.first); auto* const item = new QListWidgetItem(entry.first);
@ -148,18 +112,18 @@ void ConfigureDialog::RetranslateUI() {
ui->selectorList->setCurrentRow(old_row); ui->selectorList->setCurrentRow(old_row);
ui->tabWidget->setCurrentIndex(old_index); ui->tabWidget->setCurrentIndex(old_index);
general_tab->RetranslateUI(); ui->generalTab->RetranslateUI();
system_tab->RetranslateUI(); ui->systemTab->RetranslateUI();
input_tab->RetranslateUI(); ui->inputTab->RetranslateUI();
hotkeys_tab->RetranslateUI(); ui->hotkeysTab->RetranslateUI();
graphics_tab->RetranslateUI(); ui->graphicsTab->RetranslateUI();
enhancements_tab->RetranslateUI(); ui->enhancementsTab->RetranslateUI();
audio_tab->RetranslateUI(); ui->audioTab->RetranslateUI();
camera_tab->RetranslateUI(); ui->cameraTab->RetranslateUI();
debug_tab->RetranslateUI(); ui->debugTab->RetranslateUI();
web_tab->RetranslateUI(); ui->webTab->RetranslateUI();
ui_tab->RetranslateUI(); ui->uiTab->RetranslateUI();
storage_tab->RetranslateUI(); ui->storageTab->RetranslateUI();
} }
void ConfigureDialog::UpdateVisibleTabs() { void ConfigureDialog::UpdateVisibleTabs() {
@ -167,18 +131,18 @@ void ConfigureDialog::UpdateVisibleTabs() {
if (items.isEmpty()) if (items.isEmpty())
return; return;
const std::map<QWidget*, QString> widgets = {{general_tab.get(), tr("General")}, const std::map<QWidget*, QString> widgets = {{ui->generalTab, tr("General")},
{system_tab.get(), tr("System")}, {ui->systemTab, tr("System")},
{input_tab.get(), tr("Input")}, {ui->inputTab, tr("Input")},
{hotkeys_tab.get(), tr("Hotkeys")}, {ui->hotkeysTab, tr("Hotkeys")},
{enhancements_tab.get(), tr("Enhancements")}, {ui->enhancementsTab, tr("Enhancements")},
{graphics_tab.get(), tr("Advanced")}, {ui->graphicsTab, tr("Advanced")},
{audio_tab.get(), tr("Audio")}, {ui->audioTab, tr("Audio")},
{camera_tab.get(), tr("Camera")}, {ui->cameraTab, tr("Camera")},
{debug_tab.get(), tr("Debug")}, {ui->debugTab, tr("Debug")},
{storage_tab.get(), tr("Storage")}, {ui->storageTab, tr("Storage")},
{web_tab.get(), tr("Web")}, {ui->webTab, tr("Web")},
{ui_tab.get(), tr("UI")}}; {ui->uiTab, tr("UI")}};
ui->tabWidget->clear(); ui->tabWidget->clear();

View File

@ -17,19 +17,6 @@ namespace Core {
class System; class System;
} }
class ConfigureGeneral;
class ConfigureSystem;
class ConfigureInput;
class ConfigureHotkeys;
class ConfigureGraphics;
class ConfigureEnhancements;
class ConfigureAudio;
class ConfigureCamera;
class ConfigureDebug;
class ConfigureStorage;
class ConfigureWeb;
class ConfigureUi;
class ConfigureDialog : public QDialog { class ConfigureDialog : public QDialog {
Q_OBJECT Q_OBJECT
@ -55,18 +42,4 @@ private:
std::unique_ptr<Ui::ConfigureDialog> ui; std::unique_ptr<Ui::ConfigureDialog> ui;
HotkeyRegistry& registry; HotkeyRegistry& registry;
Core::System& system; Core::System& system;
bool is_powered_on;
std::unique_ptr<ConfigureGeneral> general_tab;
std::unique_ptr<ConfigureSystem> system_tab;
std::unique_ptr<ConfigureInput> input_tab;
std::unique_ptr<ConfigureHotkeys> hotkeys_tab;
std::unique_ptr<ConfigureGraphics> graphics_tab;
std::unique_ptr<ConfigureEnhancements> enhancements_tab;
std::unique_ptr<ConfigureAudio> audio_tab;
std::unique_ptr<ConfigureCamera> camera_tab;
std::unique_ptr<ConfigureDebug> debug_tab;
std::unique_ptr<ConfigureStorage> storage_tab;
std::unique_ptr<ConfigureWeb> web_tab;
std::unique_ptr<ConfigureUi> ui_tab;
}; };

View File

@ -22,7 +22,8 @@ ConfigureEnhancements::ConfigureEnhancements(QWidget* parent)
const bool res_scale_enabled = graphics_api != Settings::GraphicsAPI::Software; const bool res_scale_enabled = graphics_api != Settings::GraphicsAPI::Software;
ui->resolution_factor_combobox->setEnabled(res_scale_enabled); ui->resolution_factor_combobox->setEnabled(res_scale_enabled);
connect(ui->render_3d_combobox, qOverload<int>(&QComboBox::currentIndexChanged), this, connect(ui->render_3d_combobox,
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
[this](int currentIndex) { [this](int currentIndex) {
updateShaders(static_cast<Settings::StereoRenderOption>(currentIndex)); updateShaders(static_cast<Settings::StereoRenderOption>(currentIndex));
}); });

View File

@ -6,14 +6,14 @@
#include "citra_qt/configuration/configuration_shared.h" #include "citra_qt/configuration/configuration_shared.h"
#include "citra_qt/configuration/configure_graphics.h" #include "citra_qt/configuration/configure_graphics.h"
#include "common/settings.h" #include "common/settings.h"
#include "core/core.h"
#include "ui_configure_graphics.h" #include "ui_configure_graphics.h"
ConfigureGraphics::ConfigureGraphics(bool is_powered_on, QWidget* parent) ConfigureGraphics::ConfigureGraphics(QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureGraphics>()) { : QWidget(parent), ui(std::make_unique<Ui::ConfigureGraphics>()) {
ui->setupUi(this); ui->setupUi(this);
ui->toggle_vsync_new->setEnabled(!is_powered_on); ui->toggle_vsync_new->setEnabled(!Core::System::GetInstance().IsPoweredOn());
ui->graphics_api_combo->setEnabled(!is_powered_on);
// Set the index to -1 to ensure the below lambda is called with setCurrentIndex // Set the index to -1 to ensure the below lambda is called with setCurrentIndex
ui->graphics_api_combo->setCurrentIndex(-1); ui->graphics_api_combo->setCurrentIndex(-1);
@ -29,10 +29,9 @@ ConfigureGraphics::ConfigureGraphics(bool is_powered_on, QWidget* parent)
}); });
connect(ui->toggle_hw_shader, &QCheckBox::toggled, this, [this] { connect(ui->toggle_hw_shader, &QCheckBox::toggled, this, [this] {
const bool enabled = ui->toggle_hw_shader->isEnabled();
const bool checked = ui->toggle_hw_shader->isChecked(); const bool checked = ui->toggle_hw_shader->isChecked();
ui->hw_shader_group->setEnabled(checked && enabled); ui->hw_shader_group->setEnabled(checked);
ui->toggle_disk_shader_cache->setEnabled(checked && enabled); ui->toggle_disk_shader_cache->setEnabled(checked);
}); });
SetupPerGameUI(); SetupPerGameUI();

View File

@ -19,7 +19,7 @@ class ConfigureGraphics : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit ConfigureGraphics(bool is_powered_on, QWidget* parent = nullptr); explicit ConfigureGraphics(QWidget* parent = nullptr);
~ConfigureGraphics() override; ~ConfigureGraphics() override;
void ApplyConfiguration(); void ApplyConfiguration();

View File

@ -19,9 +19,6 @@
<property name="windowTitle"> <property name="windowTitle">
<string>Form</string> <string>Form</string>
</property> </property>
<property name="accessibleName">
<string>Graphics</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<widget class="QGroupBox" name="apiBox"> <widget class="QGroupBox" name="apiBox">

View File

@ -9,6 +9,7 @@
#include "citra_qt/configuration/configure_hotkeys.h" #include "citra_qt/configuration/configure_hotkeys.h"
#include "citra_qt/hotkeys.h" #include "citra_qt/hotkeys.h"
#include "citra_qt/util/sequence_dialog/sequence_dialog.h" #include "citra_qt/util/sequence_dialog/sequence_dialog.h"
#include "common/settings.h"
#include "ui_configure_hotkeys.h" #include "ui_configure_hotkeys.h"
constexpr int name_column = 0; constexpr int name_column = 0;
@ -188,9 +189,9 @@ void ConfigureHotkeys::PopupContextMenu(const QPoint& menu_location) {
QAction* clear = context_menu.addAction(tr("Clear")); QAction* clear = context_menu.addAction(tr("Clear"));
const auto hotkey_index = index.sibling(index.row(), hotkey_column); const auto hotkey_index = index.sibling(index.row(), hotkey_column);
connect(restore_default, &QAction::triggered, this, connect(restore_default, &QAction::triggered,
[this, hotkey_index] { RestoreHotkey(hotkey_index); }); [this, hotkey_index] { RestoreHotkey(hotkey_index); });
connect(clear, &QAction::triggered, this, connect(clear, &QAction::triggered,
[this, hotkey_index] { model->setData(hotkey_index, QString{}); }); [this, hotkey_index] { model->setData(hotkey_index, QString{}); });
context_menu.exec(ui->hotkey_list->viewport()->mapToGlobal(menu_location)); context_menu.exec(ui->hotkey_list->viewport()->mapToGlobal(menu_location));

View File

@ -162,7 +162,7 @@ ConfigureInput::ConfigureInput(QWidget* parent)
ui->buttonDpadUp, ui->buttonDpadDown, ui->buttonDpadLeft, ui->buttonDpadRight, ui->buttonDpadUp, ui->buttonDpadDown, ui->buttonDpadLeft, ui->buttonDpadRight,
ui->buttonL, ui->buttonR, ui->buttonStart, ui->buttonSelect, ui->buttonL, ui->buttonR, ui->buttonStart, ui->buttonSelect,
ui->buttonDebug, ui->buttonGpio14, ui->buttonZL, ui->buttonZR, ui->buttonDebug, ui->buttonGpio14, ui->buttonZL, ui->buttonZR,
ui->buttonHome, ui->buttonPower, ui->buttonHome,
}; };
analog_map_buttons = {{ analog_map_buttons = {{

View File

@ -305,24 +305,6 @@
</layout> </layout>
</item> </item>
<item row="1" column="1"> <item row="1" column="1">
<layout class="QVBoxLayout" name="verticalLayout_34">
<item>
<widget class="QLabel" name="label_37">
<property name="text">
<string>Power:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonPower">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<layout class="QVBoxLayout" name="verticalLayout_28"> <layout class="QVBoxLayout" name="verticalLayout_28">
<item> <item>
<widget class="QLabel" name="label_36"> <widget class="QLabel" name="label_36">
@ -358,7 +340,7 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="3" column="0"> <item row="2" column="0">
<layout class="QVBoxLayout" name="verticalLayout_32"> <layout class="QVBoxLayout" name="verticalLayout_32">
<item> <item>
<widget class="QLabel" name="label_40"> <widget class="QLabel" name="label_40">

View File

@ -27,18 +27,16 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const QString
Core::System& system_) Core::System& system_)
: QDialog(parent), ui(std::make_unique<Ui::ConfigurePerGame>()), : QDialog(parent), ui(std::make_unique<Ui::ConfigurePerGame>()),
filename{file_name.toStdString()}, title_id{title_id_}, system{system_} { filename{file_name.toStdString()}, title_id{title_id_}, system{system_} {
const auto config_file_name = title_id == 0 ? std::string(FileUtil::GetFilename(filename)) const auto config_file_name = title_id == 0 ? filename : fmt::format("{:016X}", title_id);
: fmt::format("{:016X}", title_id);
game_config = std::make_unique<Config>(config_file_name, Config::ConfigType::PerGameConfig); game_config = std::make_unique<Config>(config_file_name, Config::ConfigType::PerGameConfig);
const bool is_powered_on = system.IsPoweredOn(); audio_tab = std::make_unique<ConfigureAudio>(this);
audio_tab = std::make_unique<ConfigureAudio>(is_powered_on, this);
general_tab = std::make_unique<ConfigureGeneral>(this); general_tab = std::make_unique<ConfigureGeneral>(this);
enhancements_tab = std::make_unique<ConfigureEnhancements>(this); enhancements_tab = std::make_unique<ConfigureEnhancements>(this);
graphics_tab = std::make_unique<ConfigureGraphics>(is_powered_on, this); graphics_tab = std::make_unique<ConfigureGraphics>(this);
system_tab = std::make_unique<ConfigureSystem>(system, this); system_tab = std::make_unique<ConfigureSystem>(this);
debug_tab = std::make_unique<ConfigureDebug>(is_powered_on, this); debug_tab = std::make_unique<ConfigureDebug>(this);
cheat_tab = std::make_unique<ConfigureCheats>(system, title_id, this); cheat_tab = std::make_unique<ConfigureCheats>(system.CheatEngine(), title_id, this);
ui->setupUi(this); ui->setupUi(this);

View File

@ -6,12 +6,12 @@
#include <QFileDialog> #include <QFileDialog>
#include <QUrl> #include <QUrl>
#include "citra_qt/configuration/configure_storage.h" #include "citra_qt/configuration/configure_storage.h"
#include "common/file_util.h"
#include "common/settings.h" #include "common/settings.h"
#include "core/core.h"
#include "ui_configure_storage.h" #include "ui_configure_storage.h"
ConfigureStorage::ConfigureStorage(bool is_powered_on_, QWidget* parent) ConfigureStorage::ConfigureStorage(QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureStorage>()), is_powered_on{is_powered_on_} { : QWidget(parent), ui(std::make_unique<Ui::ConfigureStorage>()) {
ui->setupUi(this); ui->setupUi(this);
SetConfiguration(); SetConfiguration();
@ -74,7 +74,7 @@ void ConfigureStorage::SetConfiguration() {
ui->toggle_virtual_sd->setChecked(Settings::values.use_virtual_sd.GetValue()); ui->toggle_virtual_sd->setChecked(Settings::values.use_virtual_sd.GetValue());
ui->toggle_custom_storage->setChecked(Settings::values.use_custom_storage.GetValue()); ui->toggle_custom_storage->setChecked(Settings::values.use_custom_storage.GetValue());
ui->storage_group->setEnabled(!is_powered_on); ui->storage_group->setEnabled(!Core::System::GetInstance().IsPoweredOn());
} }
void ConfigureStorage::ApplyConfiguration() { void ConfigureStorage::ApplyConfiguration() {

View File

@ -15,7 +15,7 @@ class ConfigureStorage : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit ConfigureStorage(bool is_powered_on, QWidget* parent = nullptr); explicit ConfigureStorage(QWidget* parent = nullptr);
~ConfigureStorage() override; ~ConfigureStorage() override;
void ApplyConfiguration(); void ApplyConfiguration();
@ -23,5 +23,4 @@ public:
void SetConfiguration(); void SetConfiguration();
std::unique_ptr<Ui::ConfigureStorage> ui; std::unique_ptr<Ui::ConfigureStorage> ui;
bool is_powered_on;
}; };

View File

@ -223,12 +223,14 @@ static const std::array<const char*, 187> country_names = {
QT_TRANSLATE_NOOP("ConfigureSystem", "Bermuda"), // 180-186 QT_TRANSLATE_NOOP("ConfigureSystem", "Bermuda"), // 180-186
}; };
ConfigureSystem::ConfigureSystem(Core::System& system_, QWidget* parent) ConfigureSystem::ConfigureSystem(QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureSystem>()), system{system_} { : QWidget(parent), ui(std::make_unique<Ui::ConfigureSystem>()) {
ui->setupUi(this); ui->setupUi(this);
connect(ui->combo_birthmonth, qOverload<int>(&QComboBox::currentIndexChanged), this, connect(ui->combo_birthmonth,
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
&ConfigureSystem::UpdateBirthdayComboBox); &ConfigureSystem::UpdateBirthdayComboBox);
connect(ui->combo_init_clock, qOverload<int>(&QComboBox::currentIndexChanged), this, connect(ui->combo_init_clock,
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
&ConfigureSystem::UpdateInitTime); &ConfigureSystem::UpdateInitTime);
connect(ui->button_regenerate_console_id, &QPushButton::clicked, this, connect(ui->button_regenerate_console_id, &QPushButton::clicked, this,
&ConfigureSystem::RefreshConsoleID); &ConfigureSystem::RefreshConsoleID);
@ -278,7 +280,7 @@ ConfigureSystem::ConfigureSystem(Core::System& system_, QWidget* parent)
ConfigureSystem::~ConfigureSystem() = default; ConfigureSystem::~ConfigureSystem() = default;
void ConfigureSystem::SetConfiguration() { void ConfigureSystem::SetConfiguration() {
enabled = !system.IsPoweredOn(); enabled = !Core::System::GetInstance().IsPoweredOn();
ui->combo_init_clock->setCurrentIndex(static_cast<u8>(Settings::values.init_clock.GetValue())); ui->combo_init_clock->setCurrentIndex(static_cast<u8>(Settings::values.init_clock.GetValue()));
QDateTime date_time; QDateTime date_time;
@ -294,7 +296,7 @@ void ConfigureSystem::SetConfiguration() {
ui->edit_init_time_offset_time->setTime(time); ui->edit_init_time_offset_time->setTime(time);
if (!enabled) { if (!enabled) {
cfg = Service::CFG::GetModule(system); cfg = Service::CFG::GetModule(Core::System::GetInstance());
ASSERT_MSG(cfg, "CFG Module missing!"); ASSERT_MSG(cfg, "CFG Module missing!");
ReadSystemSettings(); ReadSystemSettings();
ui->group_system_settings->setEnabled(false); ui->group_system_settings->setEnabled(false);

View File

@ -16,10 +16,6 @@ namespace ConfigurationShared {
enum class CheckState; enum class CheckState;
} }
namespace Core {
class System;
}
namespace Service { namespace Service {
namespace CFG { namespace CFG {
class Module; class Module;
@ -30,7 +26,7 @@ class ConfigureSystem : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit ConfigureSystem(Core::System& system, QWidget* parent = nullptr); explicit ConfigureSystem(QWidget* parent = nullptr);
~ConfigureSystem() override; ~ConfigureSystem() override;
void ApplyConfiguration(); void ApplyConfiguration();
@ -49,10 +45,8 @@ private:
void DownloadFromNUS(); void DownloadFromNUS();
private:
std::unique_ptr<Ui::ConfigureSystem> ui;
Core::System& system;
ConfigurationShared::CheckState is_new_3ds; ConfigurationShared::CheckState is_new_3ds;
std::unique_ptr<Ui::ConfigureSystem> ui;
bool enabled = false; bool enabled = false;
std::shared_ptr<Service::CFG::Module> cfg; std::shared_ptr<Service::CFG::Module> cfg;

View File

@ -16,6 +16,7 @@
#include "citra_qt/debugger/graphics/graphics_cmdlists.h" #include "citra_qt/debugger/graphics/graphics_cmdlists.h"
#include "citra_qt/util/util.h" #include "citra_qt/util/util.h"
#include "common/vector_math.h" #include "common/vector_math.h"
#include "core/core.h"
#include "core/memory.h" #include "core/memory.h"
#include "video_core/debug_utils/debug_utils.h" #include "video_core/debug_utils/debug_utils.h"
#include "video_core/pica_state.h" #include "video_core/pica_state.h"
@ -166,7 +167,8 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) {
const auto format = texture.format; const auto format = texture.format;
const auto info = Pica::Texture::TextureInfo::FromPicaRegister(config, format); const auto info = Pica::Texture::TextureInfo::FromPicaRegister(config, format);
const u8* src = memory.GetPhysicalPointer(config.GetPhysicalAddress()); const u8* src =
Core::System::GetInstance().Memory().GetPhysicalPointer(config.GetPhysicalAddress());
new_info_widget = new TextureInfoWidget(src, info); new_info_widget = new TextureInfoWidget(src, info);
} }
if (command_info_widget) { if (command_info_widget) {
@ -180,8 +182,8 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) {
} }
#undef COMMAND_IN_RANGE #undef COMMAND_IN_RANGE
GPUCommandListWidget::GPUCommandListWidget(Memory::MemorySystem& memory_, QWidget* parent) GPUCommandListWidget::GPUCommandListWidget(QWidget* parent)
: QDockWidget(tr("Pica Command List"), parent), memory{memory_} { : QDockWidget(tr("Pica Command List"), parent) {
setObjectName(QStringLiteral("Pica Command List")); setObjectName(QStringLiteral("Pica Command List"));
GPUCommandListModel* model = new GPUCommandListModel(this); GPUCommandListModel* model = new GPUCommandListModel(this);

View File

@ -7,14 +7,11 @@
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QDockWidget> #include <QDockWidget>
#include "video_core/debug_utils/debug_utils.h" #include "video_core/debug_utils/debug_utils.h"
#include "video_core/gpu_debugger.h"
class QPushButton; class QPushButton;
class QTreeView; class QTreeView;
namespace Memory {
class MemorySystem;
}
class GPUCommandListModel : public QAbstractListModel { class GPUCommandListModel : public QAbstractListModel {
Q_OBJECT Q_OBJECT
@ -42,7 +39,7 @@ class GPUCommandListWidget : public QDockWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit GPUCommandListWidget(Memory::MemorySystem& memory, QWidget* parent = nullptr); explicit GPUCommandListWidget(QWidget* parent = nullptr);
public slots: public slots:
void OnToggleTracing(); void OnToggleTracing();
@ -57,7 +54,7 @@ signals:
private: private:
std::unique_ptr<Pica::DebugUtils::PicaTrace> pica_trace; std::unique_ptr<Pica::DebugUtils::PicaTrace> pica_trace;
Memory::MemorySystem& memory;
QTreeView* list_widget; QTreeView* list_widget;
QWidget* command_info_widget; QWidget* command_info_widget;
QPushButton* toggle_tracing; QPushButton* toggle_tracing;

View File

@ -15,6 +15,8 @@
#include "citra_qt/debugger/graphics/graphics_surface.h" #include "citra_qt/debugger/graphics/graphics_surface.h"
#include "citra_qt/util/spinbox.h" #include "citra_qt/util/spinbox.h"
#include "common/color.h" #include "common/color.h"
#include "core/core.h"
#include "core/hw/gpu.h"
#include "core/memory.h" #include "core/memory.h"
#include "video_core/pica_state.h" #include "video_core/pica_state.h"
#include "video_core/regs_framebuffer.h" #include "video_core/regs_framebuffer.h"
@ -49,10 +51,9 @@ void SurfacePicture::mouseMoveEvent(QMouseEvent* event) {
mousePressEvent(event); mousePressEvent(event);
} }
GraphicsSurfaceWidget::GraphicsSurfaceWidget(Memory::MemorySystem& memory_, GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> debug_context,
std::shared_ptr<Pica::DebugContext> debug_context,
QWidget* parent) QWidget* parent)
: BreakPointObserverDock(debug_context, tr("Pica Surface Viewer"), parent), memory{memory_}, : BreakPointObserverDock(debug_context, tr("Pica Surface Viewer"), parent),
surface_source(Source::ColorBuffer) { surface_source(Source::ColorBuffer) {
setObjectName(QStringLiteral("PicaSurface")); setObjectName(QStringLiteral("PicaSurface"));
@ -289,57 +290,57 @@ void GraphicsSurfaceWidget::Pick(int x, int y) {
return; return;
} }
const u8* buffer = memory.GetPhysicalPointer(surface_address); u8* buffer = Core::System::GetInstance().Memory().GetPhysicalPointer(surface_address);
if (!buffer) { if (buffer == nullptr) {
surface_info_label->setText(tr("(unable to access pixel data)")); surface_info_label->setText(tr("(unable to access pixel data)"));
surface_info_label->setAlignment(Qt::AlignCenter); surface_info_label->setAlignment(Qt::AlignCenter);
return; return;
} }
const u32 nibbles_per_pixel = GraphicsSurfaceWidget::NibblesPerPixel(surface_format); unsigned nibbles_per_pixel = GraphicsSurfaceWidget::NibblesPerPixel(surface_format);
const u32 stride = nibbles_per_pixel * surface_width / 2; unsigned stride = nibbles_per_pixel * surface_width / 2;
const bool nibble_mode = (nibbles_per_pixel == 1);
const u32 bytes_per_pixel = [&] { unsigned bytes_per_pixel;
if (nibble_mode) { bool nibble_mode = (nibbles_per_pixel == 1);
// As nibbles are contained in a byte we still need to access one byte per nibble if (nibble_mode) {
return 1u; // As nibbles are contained in a byte we still need to access one byte per nibble
} else { bytes_per_pixel = 1;
return nibbles_per_pixel / 2; } else {
} bytes_per_pixel = nibbles_per_pixel / 2;
}(); }
const u32 coarse_y = y & ~7; const u32 coarse_y = y & ~7;
const u32 offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; u32 offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride;
const u8* pixel = buffer + (nibble_mode ? (offset / 2) : offset); const u8* pixel = buffer + (nibble_mode ? (offset / 2) : offset);
const auto get_text = [offset](Format format, const u8* pixel) { auto GetText = [offset](Format format, const u8* pixel) {
switch (format) { switch (format) {
case Format::RGBA8: { case Format::RGBA8: {
const auto value = Common::Color::DecodeRGBA8(pixel) / 255.0f; auto value = Common::Color::DecodeRGBA8(pixel) / 255.0f;
return QStringLiteral("Red: %1, Green: %2, Blue: %3, Alpha: %4") return QStringLiteral("Red: %1, Green: %2, Blue: %3, Alpha: %4")
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2), .arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2),
QString::number(value.b(), 'f', 2), QString::number(value.a(), 'f', 2)); QString::number(value.b(), 'f', 2), QString::number(value.a(), 'f', 2));
} }
case Format::RGB8: { case Format::RGB8: {
const auto value = Common::Color::DecodeRGB8(pixel) / 255.0f; auto value = Common::Color::DecodeRGB8(pixel) / 255.0f;
return QStringLiteral("Red: %1, Green: %2, Blue: %3") return QStringLiteral("Red: %1, Green: %2, Blue: %3")
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2), .arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2),
QString::number(value.b(), 'f', 2)); QString::number(value.b(), 'f', 2));
} }
case Format::RGB5A1: { case Format::RGB5A1: {
const auto value = Common::Color::DecodeRGB5A1(pixel) / 255.0f; auto value = Common::Color::DecodeRGB5A1(pixel) / 255.0f;
return QStringLiteral("Red: %1, Green: %2, Blue: %3, Alpha: %4") return QStringLiteral("Red: %1, Green: %2, Blue: %3, Alpha: %4")
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2), .arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2),
QString::number(value.b(), 'f', 2), QString::number(value.a(), 'f', 2)); QString::number(value.b(), 'f', 2), QString::number(value.a(), 'f', 2));
} }
case Format::RGB565: { case Format::RGB565: {
const auto value = Common::Color::DecodeRGB565(pixel) / 255.0f; auto value = Common::Color::DecodeRGB565(pixel) / 255.0f;
return QStringLiteral("Red: %1, Green: %2, Blue: %3") return QStringLiteral("Red: %1, Green: %2, Blue: %3")
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2), .arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2),
QString::number(value.b(), 'f', 2)); QString::number(value.b(), 'f', 2));
} }
case Format::RGBA4: { case Format::RGBA4: {
const auto value = Common::Color::DecodeRGBA4(pixel) / 255.0f; auto value = Common::Color::DecodeRGBA4(pixel) / 255.0f;
return QStringLiteral("Red: %1, Green: %2, Blue: %3, Alpha: %4") return QStringLiteral("Red: %1, Green: %2, Blue: %3, Alpha: %4")
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2), .arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2),
QString::number(value.b(), 'f', 2), QString::number(value.a(), 'f', 2)); QString::number(value.b(), 'f', 2), QString::number(value.a(), 'f', 2));
@ -347,7 +348,7 @@ void GraphicsSurfaceWidget::Pick(int x, int y) {
case Format::IA8: case Format::IA8:
return QStringLiteral("Index: %1, Alpha: %2").arg(pixel[0], pixel[1]); return QStringLiteral("Index: %1, Alpha: %2").arg(pixel[0], pixel[1]);
case Format::RG8: { case Format::RG8: {
const auto value = Common::Color::DecodeRG8(pixel) / 255.0f; auto value = Common::Color::DecodeRG8(pixel) / 255.0f;
return QStringLiteral("Red: %1, Green: %2") return QStringLiteral("Red: %1, Green: %2")
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2)); .arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2));
} }
@ -358,11 +359,11 @@ void GraphicsSurfaceWidget::Pick(int x, int y) {
case Format::IA4: case Format::IA4:
return QStringLiteral("Index: %1, Alpha: %2").arg(*pixel & 0xF, (*pixel & 0xF0) >> 4); return QStringLiteral("Index: %1, Alpha: %2").arg(*pixel & 0xF, (*pixel & 0xF0) >> 4);
case Format::I4: { case Format::I4: {
const u8 i = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF; u8 i = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF;
return QStringLiteral("Index: %1").arg(i); return QStringLiteral("Index: %1").arg(i);
} }
case Format::A4: { case Format::A4: {
const u8 a = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF; u8 a = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF;
return QStringLiteral("Alpha: %1").arg(QString::number(a / 15.0f, 'f', 2)); return QStringLiteral("Alpha: %1").arg(QString::number(a / 15.0f, 'f', 2));
} }
case Format::ETC1: case Format::ETC1:
@ -370,17 +371,17 @@ void GraphicsSurfaceWidget::Pick(int x, int y) {
// TODO: Display block information or channel values? // TODO: Display block information or channel values?
return QStringLiteral("Compressed data"); return QStringLiteral("Compressed data");
case Format::D16: { case Format::D16: {
const auto value = Common::Color::DecodeD16(pixel); auto value = Common::Color::DecodeD16(pixel);
return QStringLiteral("Depth: %1").arg(QString::number(value / (float)0xFFFF, 'f', 4)); return QStringLiteral("Depth: %1").arg(QString::number(value / (float)0xFFFF, 'f', 4));
} }
case Format::D24: { case Format::D24: {
const auto value = Common::Color::DecodeD24(pixel); auto value = Common::Color::DecodeD24(pixel);
return QStringLiteral("Depth: %1") return QStringLiteral("Depth: %1")
.arg(QString::number(value / (float)0xFFFFFF, 'f', 4)); .arg(QString::number(value / (float)0xFFFFFF, 'f', 4));
} }
case Format::D24X8: case Format::D24X8:
case Format::X24S8: { case Format::X24S8: {
const auto values = Common::Color::DecodeD24S8(pixel); auto values = Common::Color::DecodeD24S8(pixel);
return QStringLiteral("Depth: %1, Stencil: %2") return QStringLiteral("Depth: %1, Stencil: %2")
.arg(QString::number(values[0] / (float)0xFFFFFF, 'f', 4), values[1]); .arg(QString::number(values[0] / (float)0xFFFFFF, 'f', 4), values[1]);
} }
@ -397,13 +398,13 @@ void GraphicsSurfaceWidget::Pick(int x, int y) {
if (nibble_mode) { if (nibble_mode) {
nibble_index += (offset % 2) ? 0 : 1; nibble_index += (offset % 2) ? 0 : 1;
} }
const u8 byte = pixel[nibble_index / 2]; u8 byte = pixel[nibble_index / 2];
const u8 nibble = (byte >> ((nibble_index % 2) ? 0 : 4)) & 0xF; u8 nibble = (byte >> ((nibble_index % 2) ? 0 : 4)) & 0xF;
nibbles.append(QString::number(nibble, 16).toUpper()); nibbles.append(QString::number(nibble, 16).toUpper());
} }
surface_info_label->setText( surface_info_label->setText(
QStringLiteral("Raw: 0x%3\n(%4)").arg(nibbles, get_text(surface_format, pixel))); QStringLiteral("Raw: 0x%3\n(%4)").arg(nibbles, GetText(surface_format, pixel)));
surface_info_label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); surface_info_label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
} }
@ -545,9 +546,9 @@ void GraphicsSurfaceWidget::OnUpdate() {
// TODO: Implement a good way to visualize alpha components! // TODO: Implement a good way to visualize alpha components!
QImage decoded_image(surface_width, surface_height, QImage::Format_ARGB32); QImage decoded_image(surface_width, surface_height, QImage::Format_ARGB32);
const u8* buffer = memory.GetPhysicalPointer(surface_address); u8* buffer = Core::System::GetInstance().Memory().GetPhysicalPointer(surface_address);
if (!buffer) { if (buffer == nullptr) {
surface_picture_label->hide(); surface_picture_label->hide();
surface_info_label->setText(tr("(invalid surface address)")); surface_info_label->setText(tr("(invalid surface address)"));
surface_info_label->setAlignment(Qt::AlignCenter); surface_info_label->setAlignment(Qt::AlignCenter);
@ -681,8 +682,9 @@ void GraphicsSurfaceWidget::SaveSurface() {
tr("Failed to save surface data to file '%1'").arg(filename)); tr("Failed to save surface data to file '%1'").arg(filename));
} }
} else if (selected_filter == bin_filter) { } else if (selected_filter == bin_filter) {
const u8* const buffer = memory.GetPhysicalPointer(surface_address); const u8* const buffer =
ASSERT_MSG(buffer, "Memory not accessible"); Core::System::GetInstance().Memory().GetPhysicalPointer(surface_address);
ASSERT_MSG(buffer != nullptr, "Memory not accessible");
QFile file{filename}; QFile file{filename};
if (!file.open(QIODevice::WriteOnly)) { if (!file.open(QIODevice::WriteOnly)) {

View File

@ -14,10 +14,6 @@ class CSpinBox;
class GraphicsSurfaceWidget; class GraphicsSurfaceWidget;
namespace Memory {
class MemorySystem;
}
class SurfacePicture : public QLabel { class SurfacePicture : public QLabel {
Q_OBJECT Q_OBJECT
@ -76,8 +72,7 @@ class GraphicsSurfaceWidget : public BreakPointObserverDock {
static unsigned int NibblesPerPixel(Format format); static unsigned int NibblesPerPixel(Format format);
public: public:
explicit GraphicsSurfaceWidget(Memory::MemorySystem& memory, explicit GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> debug_context,
std::shared_ptr<Pica::DebugContext> debug_context,
QWidget* parent = nullptr); QWidget* parent = nullptr);
void Pick(int x, int y); void Pick(int x, int y);
@ -100,7 +95,6 @@ private:
void SaveSurface(); void SaveSurface();
Memory::MemorySystem& memory;
QComboBox* surface_source_list; QComboBox* surface_source_list;
CSpinBox* surface_address_control; CSpinBox* surface_address_control;
QSpinBox* surface_width_control; QSpinBox* surface_width_control;

View File

@ -16,13 +16,13 @@
#include "core/hle/service/sm/sm.h" #include "core/hle/service/sm/sm.h"
#include "ui_recorder.h" #include "ui_recorder.h"
IPCRecorderWidget::IPCRecorderWidget(Core::System& system_, QWidget* parent) IPCRecorderWidget::IPCRecorderWidget(QWidget* parent)
: QDockWidget(parent), ui(std::make_unique<Ui::IPCRecorder>()), system{system_} { : QDockWidget(parent), ui(std::make_unique<Ui::IPCRecorder>()) {
ui->setupUi(this); ui->setupUi(this);
qRegisterMetaType<IPCDebugger::RequestRecord>(); qRegisterMetaType<IPCDebugger::RequestRecord>();
connect(ui->enabled, &QCheckBox::stateChanged, this, connect(ui->enabled, &QCheckBox::stateChanged,
[this](int new_state) { SetEnabled(new_state == Qt::Checked); }); [this](int new_state) { SetEnabled(new_state == Qt::Checked); });
connect(ui->clearButton, &QPushButton::clicked, this, &IPCRecorderWidget::Clear); connect(ui->clearButton, &QPushButton::clicked, this, &IPCRecorderWidget::Clear);
connect(ui->filter, &QLineEdit::textChanged, this, &IPCRecorderWidget::ApplyFilterToAll); connect(ui->filter, &QLineEdit::textChanged, this, &IPCRecorderWidget::ApplyFilterToAll);
@ -90,7 +90,7 @@ void IPCRecorderWidget::OnEntryUpdated(IPCDebugger::RequestRecord record) {
(record.status == IPCDebugger::RequestStatus::Handled && (record.status == IPCDebugger::RequestStatus::Handled &&
record.translated_reply_cmdbuf[1] != RESULT_SUCCESS.raw)) { // Unimplemented / Error record.translated_reply_cmdbuf[1] != RESULT_SUCCESS.raw)) { // Unimplemented / Error
auto item = ui->main->invisibleRootItem()->child(row_id); auto* item = ui->main->invisibleRootItem()->child(row_id);
for (int column = 0; column < item->columnCount(); ++column) { for (int column = 0; column < item->columnCount(); ++column) {
item->setBackground(column, QBrush(QColor::fromRgb(255, 0, 0))); item->setBackground(column, QBrush(QColor::fromRgb(255, 0, 0)));
} }
@ -100,11 +100,11 @@ void IPCRecorderWidget::OnEntryUpdated(IPCDebugger::RequestRecord record) {
} }
void IPCRecorderWidget::SetEnabled(bool enabled) { void IPCRecorderWidget::SetEnabled(bool enabled) {
if (!system.IsPoweredOn()) { if (!Core::System::GetInstance().IsPoweredOn()) {
return; return;
} }
auto& ipc_recorder = system.Kernel().GetIPCRecorder(); auto& ipc_recorder = Core::System::GetInstance().Kernel().GetIPCRecorder();
ipc_recorder.SetEnabled(enabled); ipc_recorder.SetEnabled(enabled);
if (enabled) { if (enabled) {
@ -123,10 +123,10 @@ void IPCRecorderWidget::Clear() {
} }
QString IPCRecorderWidget::GetServiceName(const IPCDebugger::RequestRecord& record) const { QString IPCRecorderWidget::GetServiceName(const IPCDebugger::RequestRecord& record) const {
if (system.IsPoweredOn() && record.client_port.id != -1) { if (Core::System::GetInstance().IsPoweredOn() && record.client_port.id != -1) {
const Service::SM::ServiceManager& sm = system.ServiceManager(); const auto service_name =
const u32 port_id = static_cast<u32>(record.client_port.id); Core::System::GetInstance().ServiceManager().GetServiceNameByPortId(
const auto service_name = sm.GetServiceNameByPortId(port_id); static_cast<u32>(record.client_port.id));
if (!service_name.empty()) { if (!service_name.empty()) {
return QString::fromStdString(service_name); return QString::fromStdString(service_name);

View File

@ -14,15 +14,11 @@ namespace Ui {
class IPCRecorder; class IPCRecorder;
} }
namespace Core {
class System;
}
class IPCRecorderWidget : public QDockWidget { class IPCRecorderWidget : public QDockWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit IPCRecorderWidget(Core::System& system, QWidget* parent = nullptr); explicit IPCRecorderWidget(QWidget* parent = nullptr);
~IPCRecorderWidget(); ~IPCRecorderWidget();
void OnEmulationStarting(); void OnEmulationStarting();
@ -41,10 +37,9 @@ private:
QString GetFunctionName(const IPCDebugger::RequestRecord& record) const; QString GetFunctionName(const IPCDebugger::RequestRecord& record) const;
void OpenRecordDialog(QTreeWidgetItem* item, int column); void OpenRecordDialog(QTreeWidgetItem* item, int column);
private:
std::unique_ptr<Ui::IPCRecorder> ui; std::unique_ptr<Ui::IPCRecorder> ui;
IPCDebugger::CallbackHandle handle; IPCDebugger::CallbackHandle handle;
Core::System& system;
// The offset between record id and row id, assuming record ids are assigned // The offset between record id and row id, assuming record ids are assigned
// continuously and only the 'Clear' action can be performed, this is enough. // continuously and only the 'Clear' action can be performed, this is enough.
// The initial value is 1, which means record 1 = row 0. // The initial value is 1, which means record 1 = row 0.

View File

@ -9,8 +9,8 @@
#include "core/core.h" #include "core/core.h"
#include "ui_registers.h" #include "ui_registers.h"
RegistersWidget::RegistersWidget(const Core::System& system_, QWidget* parent) RegistersWidget::RegistersWidget(QWidget* parent)
: QDockWidget(parent), cpu_regs_ui(std::make_unique<Ui::ARMRegisters>()), system{system_} { : QDockWidget(parent), cpu_regs_ui(std::make_unique<Ui::ARMRegisters>()) {
cpu_regs_ui->setupUi(this); cpu_regs_ui->setupUi(this);
tree = cpu_regs_ui->treeWidget; tree = cpu_regs_ui->treeWidget;
@ -62,21 +62,17 @@ RegistersWidget::RegistersWidget(const Core::System& system_, QWidget* parent)
RegistersWidget::~RegistersWidget() = default; RegistersWidget::~RegistersWidget() = default;
void RegistersWidget::OnDebugModeEntered() { void RegistersWidget::OnDebugModeEntered() {
if (!system.IsPoweredOn()) { if (!Core::System::GetInstance().IsPoweredOn())
return; return;
}
// TODO: Handle all cores // Todo: Handle all cores
const ARM_Interface& core = system.GetCore(0); for (int i = 0; i < core_registers->childCount(); ++i)
for (int i = 0; i < core_registers->childCount(); ++i) {
core_registers->child(i)->setText( core_registers->child(i)->setText(
1, QStringLiteral("0x%1").arg(core.GetReg(i), 8, 16, QLatin1Char('0'))); 1, QStringLiteral("0x%1").arg(Core::GetCore(0).GetReg(i), 8, 16, QLatin1Char('0')));
}
for (int i = 0; i < vfp_registers->childCount(); ++i) { for (int i = 0; i < vfp_registers->childCount(); ++i)
vfp_registers->child(i)->setText( vfp_registers->child(i)->setText(
1, QStringLiteral("0x%1").arg(core.GetVFPReg(i), 8, 16, QLatin1Char('0'))); 1, QStringLiteral("0x%1").arg(Core::GetCore(0).GetVFPReg(i), 8, 16, QLatin1Char('0')));
}
UpdateCPSRValues(); UpdateCPSRValues();
UpdateVFPSystemRegisterValues(); UpdateVFPSystemRegisterValues();
@ -90,29 +86,24 @@ void RegistersWidget::OnEmulationStarting(EmuThread* emu_thread) {
void RegistersWidget::OnEmulationStopping() { void RegistersWidget::OnEmulationStopping() {
// Reset widget text // Reset widget text
for (int i = 0; i < core_registers->childCount(); ++i) { for (int i = 0; i < core_registers->childCount(); ++i)
core_registers->child(i)->setText(1, QString{}); core_registers->child(i)->setText(1, QString{});
}
for (int i = 0; i < vfp_registers->childCount(); ++i) { for (int i = 0; i < vfp_registers->childCount(); ++i)
vfp_registers->child(i)->setText(1, QString{}); vfp_registers->child(i)->setText(1, QString{});
}
for (int i = 0; i < cpsr->childCount(); ++i) { for (int i = 0; i < cpsr->childCount(); ++i)
cpsr->child(i)->setText(1, QString{}); cpsr->child(i)->setText(1, QString{});
}
cpsr->setText(1, QString{}); cpsr->setText(1, QString{});
// FPSCR // FPSCR
for (int i = 0; i < vfp_system_registers->child(0)->childCount(); ++i) { for (int i = 0; i < vfp_system_registers->child(0)->childCount(); ++i)
vfp_system_registers->child(0)->child(i)->setText(1, QString{}); vfp_system_registers->child(0)->child(i)->setText(1, QString{});
}
// FPEXC // FPEXC
for (int i = 0; i < vfp_system_registers->child(1)->childCount(); ++i) { for (int i = 0; i < vfp_system_registers->child(1)->childCount(); ++i)
vfp_system_registers->child(1)->child(i)->setText(1, QString{}); vfp_system_registers->child(1)->child(i)->setText(1, QString{});
}
vfp_system_registers->child(0)->setText(1, QString{}); vfp_system_registers->child(0)->setText(1, QString{});
vfp_system_registers->child(1)->setText(1, QString{}); vfp_system_registers->child(1)->setText(1, QString{});
@ -139,8 +130,8 @@ void RegistersWidget::CreateCPSRChildren() {
} }
void RegistersWidget::UpdateCPSRValues() { void RegistersWidget::UpdateCPSRValues() {
// TODO: Handle all cores // Todo: Handle all cores
const u32 cpsr_val = system.GetCore(0).GetCPSR(); const u32 cpsr_val = Core::GetCore(0).GetCPSR();
cpsr->setText(1, QStringLiteral("0x%1").arg(cpsr_val, 8, 16, QLatin1Char('0'))); cpsr->setText(1, QStringLiteral("0x%1").arg(cpsr_val, 8, 16, QLatin1Char('0')));
cpsr->child(0)->setText( cpsr->child(0)->setText(
@ -202,10 +193,9 @@ void RegistersWidget::CreateVFPSystemRegisterChildren() {
} }
void RegistersWidget::UpdateVFPSystemRegisterValues() { void RegistersWidget::UpdateVFPSystemRegisterValues() {
// TODO: handle all cores // Todo: handle all cores
const ARM_Interface& core = system.GetCore(0); const u32 fpscr_val = Core::GetCore(0).GetVFPSystemReg(VFP_FPSCR);
const u32 fpscr_val = core.GetVFPSystemReg(VFP_FPSCR); const u32 fpexc_val = Core::GetCore(0).GetVFPSystemReg(VFP_FPEXC);
const u32 fpexc_val = core.GetVFPSystemReg(VFP_FPEXC);
QTreeWidgetItem* const fpscr = vfp_system_registers->child(0); QTreeWidgetItem* const fpscr = vfp_system_registers->child(0);
fpscr->setText(1, QStringLiteral("0x%1").arg(fpscr_val, 8, 16, QLatin1Char('0'))); fpscr->setText(1, QStringLiteral("0x%1").arg(fpscr_val, 8, 16, QLatin1Char('0')));

View File

@ -15,15 +15,11 @@ namespace Ui {
class ARMRegisters; class ARMRegisters;
} }
namespace Core {
class System;
}
class RegistersWidget : public QDockWidget { class RegistersWidget : public QDockWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit RegistersWidget(const Core::System& system, QWidget* parent = nullptr); explicit RegistersWidget(QWidget* parent = nullptr);
~RegistersWidget(); ~RegistersWidget();
public slots: public slots:
@ -41,7 +37,7 @@ private:
void UpdateVFPSystemRegisterValues(); void UpdateVFPSystemRegisterValues();
std::unique_ptr<Ui::ARMRegisters> cpu_regs_ui; std::unique_ptr<Ui::ARMRegisters> cpu_regs_ui;
const Core::System& system;
QTreeWidget* tree; QTreeWidget* tree;
QTreeWidgetItem* core_registers; QTreeWidgetItem* core_registers;

View File

@ -5,10 +5,11 @@
#include <array> #include <array>
#include "citra_qt/debugger/wait_tree.h" #include "citra_qt/debugger/wait_tree.h"
#include "citra_qt/uisettings.h" #include "citra_qt/uisettings.h"
#include "citra_qt/util/util.h"
#include "common/assert.h" #include "common/assert.h"
#include "common/settings.h"
#include "core/hle/kernel/event.h" #include "core/hle/kernel/event.h"
#include "core/hle/kernel/mutex.h" #include "core/hle/kernel/mutex.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/semaphore.h" #include "core/hle/kernel/semaphore.h"
#include "core/hle/kernel/thread.h" #include "core/hle/kernel/thread.h"
#include "core/hle/kernel/timer.h" #include "core/hle/kernel/timer.h"
@ -75,13 +76,13 @@ std::size_t WaitTreeItem::Row() const {
return row; return row;
} }
std::vector<std::unique_ptr<WaitTreeThread>> WaitTreeItem::MakeThreadItemList( std::vector<std::unique_ptr<WaitTreeThread>> WaitTreeItem::MakeThreadItemList() {
Core::System& system) { const u32 num_cores = Core::GetNumCores();
const u32 num_cores = system.GetNumCores();
std::vector<std::unique_ptr<WaitTreeThread>> item_list; std::vector<std::unique_ptr<WaitTreeThread>> item_list;
item_list.reserve(num_cores); item_list.reserve(num_cores);
for (u32 i = 0; i < num_cores; ++i) { for (u32 i = 0; i < num_cores; ++i) {
const auto threads = system.Kernel().GetThreadManager(i).GetThreadList(); const auto& threads =
Core::System::GetInstance().Kernel().GetThreadManager(i).GetThreadList();
item_list.reserve(item_list.size() + threads.size()); item_list.reserve(item_list.size() + threads.size());
for (std::size_t j = 0; j < threads.size(); ++j) { for (std::size_t j = 0; j < threads.size(); ++j) {
item_list.push_back(std::make_unique<WaitTreeThread>(*threads[j])); item_list.push_back(std::make_unique<WaitTreeThread>(*threads[j]));
@ -435,12 +436,11 @@ void WaitTreeModel::ClearItems() {
thread_items.clear(); thread_items.clear();
} }
void WaitTreeModel::InitItems(Core::System& system) { void WaitTreeModel::InitItems() {
thread_items = WaitTreeItem::MakeThreadItemList(system); thread_items = WaitTreeItem::MakeThreadItemList();
} }
WaitTreeWidget::WaitTreeWidget(Core::System& system_, QWidget* parent) WaitTreeWidget::WaitTreeWidget(QWidget* parent) : QDockWidget(tr("Wait Tree"), parent) {
: QDockWidget(tr("Wait Tree"), parent), system{system_} {
setObjectName(QStringLiteral("WaitTreeWidget")); setObjectName(QStringLiteral("WaitTreeWidget"));
view = new QTreeView(this); view = new QTreeView(this);
view->setHeaderHidden(true); view->setHeaderHidden(true);
@ -449,10 +449,9 @@ WaitTreeWidget::WaitTreeWidget(Core::System& system_, QWidget* parent)
} }
void WaitTreeWidget::OnDebugModeEntered() { void WaitTreeWidget::OnDebugModeEntered() {
if (!system.IsPoweredOn()) { if (!Core::System::GetInstance().IsPoweredOn())
return; return;
} model->InitItems();
model->InitItems(system);
view->setModel(model); view->setModel(model);
setEnabled(true); setEnabled(true);
} }

View File

@ -23,10 +23,6 @@ class Thread;
class Timer; class Timer;
} // namespace Kernel } // namespace Kernel
namespace Core {
class System;
}
class WaitTreeThread; class WaitTreeThread;
class WaitTreeItem : public QObject { class WaitTreeItem : public QObject {
@ -43,7 +39,7 @@ public:
WaitTreeItem* Parent() const; WaitTreeItem* Parent() const;
std::span<const std::unique_ptr<WaitTreeItem>> Children() const; std::span<const std::unique_ptr<WaitTreeItem>> Children() const;
std::size_t Row() const; std::size_t Row() const;
static std::vector<std::unique_ptr<WaitTreeThread>> MakeThreadItemList(Core::System& system); static std::vector<std::unique_ptr<WaitTreeThread>> MakeThreadItemList();
private: private:
std::size_t row; std::size_t row;
@ -170,7 +166,7 @@ public:
int columnCount(const QModelIndex& parent) const override; int columnCount(const QModelIndex& parent) const override;
void ClearItems(); void ClearItems();
void InitItems(Core::System& system); void InitItems();
private: private:
std::vector<std::unique_ptr<WaitTreeThread>> thread_items; std::vector<std::unique_ptr<WaitTreeThread>> thread_items;
@ -180,7 +176,7 @@ class WaitTreeWidget : public QDockWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit WaitTreeWidget(Core::System& system, QWidget* parent = nullptr); explicit WaitTreeWidget(QWidget* parent = nullptr);
public slots: public slots:
void OnDebugModeEntered(); void OnDebugModeEntered();
@ -192,5 +188,4 @@ public slots:
private: private:
QTreeView* view; QTreeView* view;
WaitTreeModel* model; WaitTreeModel* model;
Core::System& system;
}; };

View File

@ -9,11 +9,10 @@
#include "citra_qt/uisettings.h" #include "citra_qt/uisettings.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "core/core.h" #include "core/core.h"
#include "core/loader/loader.h"
namespace DiscordRPC { namespace DiscordRPC {
DiscordImpl::DiscordImpl(const Core::System& system_) : system{system_} { DiscordImpl::DiscordImpl() {
DiscordEventHandlers handlers{}; DiscordEventHandlers handlers{};
// The number is the client ID for Citra, it's used for images and the // The number is the client ID for Citra, it's used for images and the
@ -35,15 +34,12 @@ void DiscordImpl::Update() {
std::chrono::system_clock::now().time_since_epoch()) std::chrono::system_clock::now().time_since_epoch())
.count(); .count();
std::string title; std::string title;
const bool is_powered_on = system.IsPoweredOn(); if (Core::System::GetInstance().IsPoweredOn())
if (is_powered_on) { Core::System::GetInstance().GetAppLoader().ReadTitle(title);
system.GetAppLoader().ReadTitle(title);
}
DiscordRichPresence presence{}; DiscordRichPresence presence{};
presence.largeImageKey = "citra"; presence.largeImageKey = "citra";
presence.largeImageText = "Citra is an emulator for the Nintendo 3DS"; presence.largeImageText = "Citra is an emulator for the Nintendo 3DS";
if (is_powered_on) { if (Core::System::GetInstance().IsPoweredOn()) {
presence.state = title.c_str(); presence.state = title.c_str();
presence.details = "Currently in game"; presence.details = "Currently in game";
} else { } else {

View File

@ -6,22 +6,15 @@
#include "citra_qt/discord.h" #include "citra_qt/discord.h"
namespace Core {
class System;
}
namespace DiscordRPC { namespace DiscordRPC {
class DiscordImpl : public DiscordInterface { class DiscordImpl : public DiscordInterface {
public: public:
DiscordImpl(const Core::System& system); DiscordImpl();
~DiscordImpl() override; ~DiscordImpl() override;
void Pause() override; void Pause() override;
void Update() override; void Update() override;
private:
const Core::System& system;
}; };
} // namespace DiscordRPC } // namespace DiscordRPC

View File

@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <QActionGroup>
#include <QApplication> #include <QApplication>
#include <QDir> #include <QDir>
#include <QFileInfo> #include <QFileInfo>
@ -308,9 +307,6 @@ GameList::GameList(GMainWindow* parent) : QWidget{parent} {
tree_view->setEditTriggers(QHeaderView::NoEditTriggers); tree_view->setEditTriggers(QHeaderView::NoEditTriggers);
tree_view->setContextMenuPolicy(Qt::CustomContextMenu); tree_view->setContextMenuPolicy(Qt::CustomContextMenu);
tree_view->setStyleSheet(QStringLiteral("QTreeView{ border: none; }")); tree_view->setStyleSheet(QStringLiteral("QTreeView{ border: none; }"));
tree_view->header()->setContextMenuPolicy(Qt::CustomContextMenu);
UpdateColumnVisibility();
item_model->insertColumns(0, COLUMN_COUNT); item_model->insertColumns(0, COLUMN_COUNT);
RetranslateUI(); RetranslateUI();
@ -321,8 +317,6 @@ GameList::GameList(GMainWindow* parent) : QWidget{parent} {
connect(tree_view, &QTreeView::customContextMenuRequested, this, &GameList::PopupContextMenu); connect(tree_view, &QTreeView::customContextMenuRequested, this, &GameList::PopupContextMenu);
connect(tree_view, &QTreeView::expanded, this, &GameList::OnItemExpanded); connect(tree_view, &QTreeView::expanded, this, &GameList::OnItemExpanded);
connect(tree_view, &QTreeView::collapsed, this, &GameList::OnItemExpanded); connect(tree_view, &QTreeView::collapsed, this, &GameList::OnItemExpanded);
connect(tree_view->header(), &QHeaderView::customContextMenuRequested, this,
&GameList::PopupHeaderContextMenu);
// We must register all custom types with the Qt Automoc system so that we are able to use // We must register all custom types with the Qt Automoc system so that we are able to use
// it with signals/slots. In this case, QList falls under the umbrells of custom types. // it with signals/slots. In this case, QList falls under the umbrells of custom types.
@ -477,41 +471,6 @@ void GameList::PopupContextMenu(const QPoint& menu_location) {
context_menu.exec(tree_view->viewport()->mapToGlobal(menu_location)); context_menu.exec(tree_view->viewport()->mapToGlobal(menu_location));
} }
void GameList::PopupHeaderContextMenu(const QPoint& menu_location) {
const QModelIndex item = tree_view->indexAt(menu_location);
if (!item.isValid()) {
return;
}
QMenu context_menu;
static const QMap<QString, Settings::Setting<bool>*> columns{
{tr("Compatibility"), &UISettings::values.show_compat_column},
{tr("Region"), &UISettings::values.show_region_column},
{tr("File type"), &UISettings::values.show_type_column},
{tr("Size"), &UISettings::values.show_size_column}};
QActionGroup* column_group = new QActionGroup(this);
column_group->setExclusive(false);
for (const auto& key : columns.keys()) {
QAction* action = column_group->addAction(context_menu.addAction(key));
action->setCheckable(true);
action->setChecked(columns[key]->GetValue());
connect(action, &QAction::toggled, [this, key](bool value) {
*columns[key] = !columns[key]->GetValue();
UpdateColumnVisibility();
});
}
context_menu.exec(tree_view->viewport()->mapToGlobal(menu_location));
}
void GameList::UpdateColumnVisibility() {
tree_view->setColumnHidden(COLUMN_COMPATIBILITY, !UISettings::values.show_compat_column);
tree_view->setColumnHidden(COLUMN_REGION, !UISettings::values.show_region_column);
tree_view->setColumnHidden(COLUMN_FILE_TYPE, !UISettings::values.show_type_column);
tree_view->setColumnHidden(COLUMN_SIZE, !UISettings::values.show_size_column);
}
void ForEachOpenGLCacheFile(u64 program_id, auto func) { void ForEachOpenGLCacheFile(u64 program_id, auto func) {
for (const std::string_view cache_type : {"separable", "conventional"}) { for (const std::string_view cache_type : {"separable", "conventional"}) {
const std::string path = fmt::format("{}opengl/precompiled/{}/{:016X}.bin", const std::string path = fmt::format("{}opengl/precompiled/{}/{:016X}.bin",
@ -791,10 +750,6 @@ QStandardItemModel* GameList::GetModel() const {
void GameList::PopulateAsync(QVector<UISettings::GameDir>& game_dirs) { void GameList::PopulateAsync(QVector<UISettings::GameDir>& game_dirs) {
tree_view->setEnabled(false); tree_view->setEnabled(false);
// Update the columns in case UISettings has changed
UpdateColumnVisibility();
// Delete any rows that might already exist if we're repopulating // Delete any rows that might already exist if we're repopulating
item_model->removeRows(0, item_model->rowCount()); item_model->removeRows(0, item_model->rowCount());
search_field->clear(); search_field->clear();

View File

@ -104,11 +104,9 @@ private:
void DonePopulating(const QStringList& watch_list); void DonePopulating(const QStringList& watch_list);
void PopupContextMenu(const QPoint& menu_location); void PopupContextMenu(const QPoint& menu_location);
void PopupHeaderContextMenu(const QPoint& menu_location);
void AddGamePopup(QMenu& context_menu, const QString& path, u64 program_id, u64 extdata_id); void AddGamePopup(QMenu& context_menu, const QString& path, u64 program_id, u64 extdata_id);
void AddCustomDirPopup(QMenu& context_menu, QModelIndex selected); void AddCustomDirPopup(QMenu& context_menu, QModelIndex selected);
void AddPermDirPopup(QMenu& context_menu, QModelIndex selected); void AddPermDirPopup(QMenu& context_menu, QModelIndex selected);
void UpdateColumnVisibility();
QString FindGameByProgramID(QStandardItem* current_item, u64 program_id, int role); QString FindGameByProgramID(QStandardItem* current_item, u64 program_id, int role);

View File

@ -14,7 +14,6 @@
#include <QtGui> #include <QtGui>
#include <QtWidgets> #include <QtWidgets>
#include <fmt/format.h> #include <fmt/format.h>
#include "core/telemetry_session.h"
#ifdef __APPLE__ #ifdef __APPLE__
#include <unistd.h> // for chdir #include <unistd.h> // for chdir
#endif #endif
@ -74,6 +73,7 @@
#include "common/microprofile.h" #include "common/microprofile.h"
#include "common/scm_rev.h" #include "common/scm_rev.h"
#include "common/scope_exit.h" #include "common/scope_exit.h"
#include "common/string_util.h"
#if CITRA_ARCH(x86_64) #if CITRA_ARCH(x86_64)
#include "common/x64/cpu_detect.h" #include "common/x64/cpu_detect.h"
#endif #endif
@ -173,7 +173,7 @@ static QString PrettyProductName() {
} }
GMainWindow::GMainWindow(Core::System& system_) GMainWindow::GMainWindow(Core::System& system_)
: ui{std::make_unique<Ui::MainWindow>()}, system{system_}, movie{system.Movie()}, : ui{std::make_unique<Ui::MainWindow>()}, system{system_}, movie{Core::Movie::GetInstance()},
config{std::make_unique<Config>()}, emu_thread{nullptr} { config{std::make_unique<Config>()}, emu_thread{nullptr} {
Common::Log::Initialize(); Common::Log::Initialize();
Common::Log::Start(); Common::Log::Start();
@ -353,8 +353,8 @@ void GMainWindow::InitializeWidgets() {
}); });
InputCommon::Init(); InputCommon::Init();
multiplayer_state = new MultiplayerState(system, this, game_list->GetModel(), multiplayer_state = new MultiplayerState(this, game_list->GetModel(), ui->action_Leave_Room,
ui->action_Leave_Room, ui->action_Show_Room); ui->action_Show_Room);
multiplayer_state->setVisible(false); multiplayer_state->setVisible(false);
#if ENABLE_QT_UPDATER #if ENABLE_QT_UPDATER
@ -434,7 +434,7 @@ void GMainWindow::InitializeDebugWidgets() {
debug_menu->addAction(microProfileDialog->toggleViewAction()); debug_menu->addAction(microProfileDialog->toggleViewAction());
#endif #endif
registersWidget = new RegistersWidget(system, this); registersWidget = new RegistersWidget(this);
addDockWidget(Qt::RightDockWidgetArea, registersWidget); addDockWidget(Qt::RightDockWidgetArea, registersWidget);
registersWidget->hide(); registersWidget->hide();
debug_menu->addAction(registersWidget->toggleViewAction()); debug_menu->addAction(registersWidget->toggleViewAction());
@ -448,7 +448,7 @@ void GMainWindow::InitializeDebugWidgets() {
graphicsWidget->hide(); graphicsWidget->hide();
debug_menu->addAction(graphicsWidget->toggleViewAction()); debug_menu->addAction(graphicsWidget->toggleViewAction());
graphicsCommandsWidget = new GPUCommandListWidget(system.Memory(), this); graphicsCommandsWidget = new GPUCommandListWidget(this);
addDockWidget(Qt::RightDockWidgetArea, graphicsCommandsWidget); addDockWidget(Qt::RightDockWidgetArea, graphicsCommandsWidget);
graphicsCommandsWidget->hide(); graphicsCommandsWidget->hide();
debug_menu->addAction(graphicsCommandsWidget->toggleViewAction()); debug_menu->addAction(graphicsCommandsWidget->toggleViewAction());
@ -472,7 +472,7 @@ void GMainWindow::InitializeDebugWidgets() {
connect(this, &GMainWindow::EmulationStopping, graphicsTracingWidget, connect(this, &GMainWindow::EmulationStopping, graphicsTracingWidget,
&GraphicsTracingWidget::OnEmulationStopping); &GraphicsTracingWidget::OnEmulationStopping);
waitTreeWidget = new WaitTreeWidget(system, this); waitTreeWidget = new WaitTreeWidget(this);
addDockWidget(Qt::LeftDockWidgetArea, waitTreeWidget); addDockWidget(Qt::LeftDockWidgetArea, waitTreeWidget);
waitTreeWidget->hide(); waitTreeWidget->hide();
debug_menu->addAction(waitTreeWidget->toggleViewAction()); debug_menu->addAction(waitTreeWidget->toggleViewAction());
@ -490,7 +490,7 @@ void GMainWindow::InitializeDebugWidgets() {
connect(this, &GMainWindow::EmulationStopping, waitTreeWidget, connect(this, &GMainWindow::EmulationStopping, waitTreeWidget,
[this] { lleServiceModulesWidget->setDisabled(false); }); [this] { lleServiceModulesWidget->setDisabled(false); });
ipcRecorderWidget = new IPCRecorderWidget(system, this); ipcRecorderWidget = new IPCRecorderWidget(this);
addDockWidget(Qt::RightDockWidgetArea, ipcRecorderWidget); addDockWidget(Qt::RightDockWidgetArea, ipcRecorderWidget);
ipcRecorderWidget->hide(); ipcRecorderWidget->hide();
debug_menu->addAction(ipcRecorderWidget->toggleViewAction()); debug_menu->addAction(ipcRecorderWidget->toggleViewAction());
@ -1171,18 +1171,20 @@ void GMainWindow::BootGame(const QString& filename) {
movie.PrepareForPlayback(movie_playback_path.toStdString()); movie.PrepareForPlayback(movie_playback_path.toStdString());
} }
u64 title_id{0};
const std::string path = filename.toStdString(); const std::string path = filename.toStdString();
const auto loader = Loader::GetLoader(path); const auto loader = Loader::GetLoader(path);
u64 title_id{0}; if (loader && loader->ReadProgramId(title_id) == Loader::ResultStatus::Success) {
loader->ReadProgramId(title_id); // Load per game settings
const std::string name{FileUtil::GetFilename(filename.toStdString())};
const std::string config_file_name =
title_id == 0 ? name : fmt::format("{:016X}", title_id);
Config per_game_config(config_file_name, Config::ConfigType::PerGameConfig);
system.ApplySettings();
// Load per game settings LOG_INFO(Frontend, "Using per game config file for title id {}", config_file_name);
const std::string name{FileUtil::GetFilename(filename.toStdString())}; }
const std::string config_file_name = title_id == 0 ? name : fmt::format("{:016X}", title_id);
LOG_INFO(Frontend, "Loading per game config file for title {}", config_file_name);
Config per_game_config(config_file_name, Config::ConfigType::PerGameConfig);
system.ApplySettings();
Settings::LogSettings(); Settings::LogSettings();
@ -1221,7 +1223,7 @@ void GMainWindow::BootGame(const QString& filename) {
} }
// Create and start the emulation thread // Create and start the emulation thread
emu_thread = std::make_unique<EmuThread>(system, *render_window); emu_thread = std::make_unique<EmuThread>(*render_window);
emit EmulationStarting(emu_thread.get()); emit EmulationStarting(emu_thread.get());
emu_thread->start(); emu_thread->start();
@ -1413,7 +1415,7 @@ void GMainWindow::UpdateSaveStates() {
if (system.GetAppLoader().ReadProgramId(title_id) != Loader::ResultStatus::Success) { if (system.GetAppLoader().ReadProgramId(title_id) != Loader::ResultStatus::Success) {
return; return;
} }
auto savestates = Core::ListSaveStates(title_id, movie.GetCurrentMovieID()); auto savestates = Core::ListSaveStates(title_id);
for (u32 i = 0; i < Core::SaveStateSlotCount; ++i) { for (u32 i = 0; i < Core::SaveStateSlotCount; ++i) {
actions_load_state[i]->setEnabled(false); actions_load_state[i]->setEnabled(false);
actions_load_state[i]->setText(tr("Slot %1").arg(i + 1)); actions_load_state[i]->setText(tr("Slot %1").arg(i + 1));
@ -1812,7 +1814,7 @@ void GMainWindow::OnLoadComplete() {
void GMainWindow::OnMenuReportCompatibility() { void GMainWindow::OnMenuReportCompatibility() {
if (!NetSettings::values.citra_token.empty() && !NetSettings::values.citra_username.empty()) { if (!NetSettings::values.citra_token.empty() && !NetSettings::values.citra_username.empty()) {
CompatDB compatdb{system.TelemetrySession(), this}; CompatDB compatdb{this};
compatdb.exec(); compatdb.exec();
} else { } else {
QMessageBox::critical(this, tr("Missing Citra Account"), QMessageBox::critical(this, tr("Missing Citra Account"),
@ -2046,6 +2048,7 @@ void GMainWindow::OnLoadAmiibo() {
return; return;
} }
Core::System& system{Core::System::GetInstance()};
Service::SM::ServiceManager& sm = system.ServiceManager(); Service::SM::ServiceManager& sm = system.ServiceManager();
auto nfc = sm.GetService<Service::NFC::Module::Interface>("nfc:u"); auto nfc = sm.GetService<Service::NFC::Module::Interface>("nfc:u");
if (nfc == nullptr) { if (nfc == nullptr) {
@ -2117,15 +2120,14 @@ void GMainWindow::OnToggleFilterBar() {
} }
void GMainWindow::OnCreateGraphicsSurfaceViewer() { void GMainWindow::OnCreateGraphicsSurfaceViewer() {
auto graphicsSurfaceViewerWidget = auto graphicsSurfaceViewerWidget = new GraphicsSurfaceWidget(Pica::g_debug_context, this);
new GraphicsSurfaceWidget(system.Memory(), Pica::g_debug_context, this);
addDockWidget(Qt::RightDockWidgetArea, graphicsSurfaceViewerWidget); addDockWidget(Qt::RightDockWidgetArea, graphicsSurfaceViewerWidget);
// TODO: Maybe graphicsSurfaceViewerWidget->setFloating(true); // TODO: Maybe graphicsSurfaceViewerWidget->setFloating(true);
graphicsSurfaceViewerWidget->show(); graphicsSurfaceViewerWidget->show();
} }
void GMainWindow::OnRecordMovie() { void GMainWindow::OnRecordMovie() {
MovieRecordDialog dialog(this, system); MovieRecordDialog dialog(this);
if (dialog.exec() != QDialog::Accepted) { if (dialog.exec() != QDialog::Accepted) {
return; return;
} }
@ -2142,7 +2144,7 @@ void GMainWindow::OnRecordMovie() {
} }
void GMainWindow::OnPlayMovie() { void GMainWindow::OnPlayMovie() {
MoviePlayDialog dialog(this, game_list, system); MoviePlayDialog dialog(this, game_list);
if (dialog.exec() != QDialog::Accepted) { if (dialog.exec() != QDialog::Accepted) {
return; return;
} }
@ -2783,13 +2785,9 @@ void GMainWindow::UpdateWindowTitle() {
const QString full_name = QString::fromUtf8(Common::g_build_fullname); const QString full_name = QString::fromUtf8(Common::g_build_fullname);
if (game_title.isEmpty()) { if (game_title.isEmpty()) {
setWindowTitle(QStringLiteral("Citra %1").arg(full_name)); setWindowTitle(tr("Citra %1").arg(full_name));
} else { } else {
setWindowTitle(QStringLiteral("Citra %1 | %2").arg(full_name, game_title)); setWindowTitle(tr("Citra %1| %2").arg(full_name, game_title));
render_window->setWindowTitle(
QStringLiteral("Citra %1 | %2 | %3").arg(full_name, game_title, tr("Primary Window")));
secondary_window->setWindowTitle(QStringLiteral("Citra %1 | %2 | %3")
.arg(full_name, game_title, tr("Secondary Window")));
} }
} }
@ -2847,7 +2845,7 @@ void GMainWindow::RetranslateStatusBar() {
void GMainWindow::SetDiscordEnabled([[maybe_unused]] bool state) { void GMainWindow::SetDiscordEnabled([[maybe_unused]] bool state) {
#ifdef USE_DISCORD_PRESENCE #ifdef USE_DISCORD_PRESENCE
if (state) { if (state) {
discord_rpc = std::make_unique<DiscordRPC::DiscordImpl>(system); discord_rpc = std::make_unique<DiscordRPC::DiscordImpl>();
} else { } else {
discord_rpc = std::make_unique<DiscordRPC::NullImpl>(); discord_rpc = std::make_unique<DiscordRPC::NullImpl>();
} }
@ -2933,7 +2931,7 @@ int main(int argc, char* argv[]) {
GMainWindow main_window(system); GMainWindow main_window(system);
// Register frontend applets // Register frontend applets
Frontend::RegisterDefaultApplets(system); Frontend::RegisterDefaultApplets();
system.RegisterMiiSelector(std::make_shared<QtMiiSelector>(main_window)); system.RegisterMiiSelector(std::make_shared<QtMiiSelector>(main_window));
system.RegisterSoftwareKeyboard(std::make_shared<QtKeyboard>(main_window)); system.RegisterSoftwareKeyboard(std::make_shared<QtKeyboard>(main_window));

View File

@ -15,9 +15,8 @@
#include "core/movie.h" #include "core/movie.h"
#include "ui_movie_play_dialog.h" #include "ui_movie_play_dialog.h"
MoviePlayDialog::MoviePlayDialog(QWidget* parent, GameList* game_list_, const Core::System& system_) MoviePlayDialog::MoviePlayDialog(QWidget* parent, GameList* game_list_)
: QDialog(parent), : QDialog(parent), ui(std::make_unique<Ui::MoviePlayDialog>()), game_list(game_list_) {
ui(std::make_unique<Ui::MoviePlayDialog>()), game_list{game_list_}, system{system_} {
ui->setupUi(this); ui->setupUi(this);
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
@ -27,10 +26,10 @@ MoviePlayDialog::MoviePlayDialog(QWidget* parent, GameList* game_list_, const Co
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &MoviePlayDialog::accept); connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &MoviePlayDialog::accept);
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &MoviePlayDialog::reject); connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &MoviePlayDialog::reject);
if (system.IsPoweredOn()) { if (Core::System::GetInstance().IsPoweredOn()) {
QString note_text; QString note_text;
note_text = tr("Current running game will be stopped."); note_text = tr("Current running game will be stopped.");
if (system.Movie().GetPlayMode() == Core::Movie::PlayMode::Recording) { if (Core::Movie::GetInstance().GetPlayMode() == Core::Movie::PlayMode::Recording) {
note_text.append(tr("<br>Current recording will be discarded.")); note_text.append(tr("<br>Current recording will be discarded."));
} }
ui->note2Label->setText(note_text); ui->note2Label->setText(note_text);
@ -44,7 +43,7 @@ QString MoviePlayDialog::GetMoviePath() const {
} }
QString MoviePlayDialog::GetGamePath() const { QString MoviePlayDialog::GetGamePath() const {
const auto metadata = system.Movie().GetMovieMetadata(GetMoviePath().toStdString()); const auto metadata = Core::Movie::GetInstance().GetMovieMetadata(GetMoviePath().toStdString());
return game_list->FindGameByProgramID(metadata.program_id, GameListItemPath::FullPathRole); return game_list->FindGameByProgramID(metadata.program_id, GameListItemPath::FullPathRole);
} }
@ -68,10 +67,9 @@ void MoviePlayDialog::UpdateUIDisplay() {
ui->lengthLineEdit->clear(); ui->lengthLineEdit->clear();
ui->note1Label->setVisible(true); ui->note1Label->setVisible(true);
const auto& movie = system.Movie();
const auto path = GetMoviePath().toStdString(); const auto path = GetMoviePath().toStdString();
const auto validation_result = movie.ValidateMovie(path); const auto validation_result = Core::Movie::GetInstance().ValidateMovie(path);
if (validation_result == Core::Movie::ValidationResult::Invalid) { if (validation_result == Core::Movie::ValidationResult::Invalid) {
ui->note1Label->setText(tr("Invalid movie file.")); ui->note1Label->setText(tr("Invalid movie file."));
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
@ -96,7 +94,7 @@ void MoviePlayDialog::UpdateUIDisplay() {
UNREACHABLE(); UNREACHABLE();
} }
const auto metadata = movie.GetMovieMetadata(path); const auto metadata = Core::Movie::GetInstance().GetMovieMetadata(path);
// Format game title // Format game title
const auto title = const auto title =

View File

@ -11,15 +11,11 @@ namespace Ui {
class MoviePlayDialog; class MoviePlayDialog;
} }
namespace Core {
class System;
}
class MoviePlayDialog : public QDialog { class MoviePlayDialog : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
explicit MoviePlayDialog(QWidget* parent, GameList* game_list, const Core::System& system); explicit MoviePlayDialog(QWidget* parent, GameList* game_list);
~MoviePlayDialog() override; ~MoviePlayDialog() override;
QString GetMoviePath() const; QString GetMoviePath() const;
@ -31,5 +27,4 @@ private:
std::unique_ptr<Ui::MoviePlayDialog> ui; std::unique_ptr<Ui::MoviePlayDialog> ui;
GameList* game_list; GameList* game_list;
const Core::System& system;
}; };

View File

@ -10,8 +10,8 @@
#include "core/movie.h" #include "core/movie.h"
#include "ui_movie_record_dialog.h" #include "ui_movie_record_dialog.h"
MovieRecordDialog::MovieRecordDialog(QWidget* parent, const Core::System& system_) MovieRecordDialog::MovieRecordDialog(QWidget* parent)
: QDialog(parent), ui(std::make_unique<Ui::MovieRecordDialog>()), system{system_} { : QDialog(parent), ui(std::make_unique<Ui::MovieRecordDialog>()) {
ui->setupUi(this); ui->setupUi(this);
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
@ -23,9 +23,9 @@ MovieRecordDialog::MovieRecordDialog(QWidget* parent, const Core::System& system
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &MovieRecordDialog::reject); connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &MovieRecordDialog::reject);
QString note_text; QString note_text;
if (system.IsPoweredOn()) { if (Core::System::GetInstance().IsPoweredOn()) {
note_text = tr("Current running game will be restarted."); note_text = tr("Current running game will be restarted.");
if (system.Movie().GetPlayMode() == Core::Movie::PlayMode::Recording) { if (Core::Movie::GetInstance().GetPlayMode() == Core::Movie::PlayMode::Recording) {
note_text.append(tr("<br>Current recording will be discarded.")); note_text.append(tr("<br>Current recording will be discarded."));
} }
} else { } else {

View File

@ -9,15 +9,11 @@ namespace Ui {
class MovieRecordDialog; class MovieRecordDialog;
} }
namespace Core {
class System;
}
class MovieRecordDialog : public QDialog { class MovieRecordDialog : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
explicit MovieRecordDialog(QWidget* parent, const Core::System& system); explicit MovieRecordDialog(QWidget* parent);
~MovieRecordDialog() override; ~MovieRecordDialog() override;
QString GetPath() const; QString GetPath() const;
@ -28,5 +24,4 @@ private:
void UpdateUIDisplay(); void UpdateUIDisplay();
std::unique_ptr<Ui::MovieRecordDialog> ui; std::unique_ptr<Ui::MovieRecordDialog> ui;
const Core::System& system;
}; };

View File

@ -9,8 +9,10 @@
#include <QString> #include <QString>
#include <QtConcurrent/QtConcurrentRun> #include <QtConcurrent/QtConcurrentRun>
#include "citra_qt/main.h" #include "citra_qt/main.h"
#include "citra_qt/multiplayer/client_room.h"
#include "citra_qt/multiplayer/direct_connect.h" #include "citra_qt/multiplayer/direct_connect.h"
#include "citra_qt/multiplayer/message.h" #include "citra_qt/multiplayer/message.h"
#include "citra_qt/multiplayer/state.h"
#include "citra_qt/multiplayer/validation.h" #include "citra_qt/multiplayer/validation.h"
#include "citra_qt/uisettings.h" #include "citra_qt/uisettings.h"
#include "core/hle/service/cfg/cfg.h" #include "core/hle/service/cfg/cfg.h"
@ -20,9 +22,9 @@
enum class ConnectionType : u8 { TraversalServer, IP }; enum class ConnectionType : u8 { TraversalServer, IP };
DirectConnectWindow::DirectConnectWindow(Core::System& system_, QWidget* parent) DirectConnectWindow::DirectConnectWindow(QWidget* parent)
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
ui(std::make_unique<Ui::DirectConnect>()), system{system_} { ui(std::make_unique<Ui::DirectConnect>()) {
ui->setupUi(this); ui->setupUi(this);
@ -89,7 +91,7 @@ void DirectConnectWindow::Connect() {
if (auto room_member = Network::GetRoomMember().lock()) { if (auto room_member = Network::GetRoomMember().lock()) {
auto port = UISettings::values.port.toUInt(); auto port = UISettings::values.port.toUInt();
room_member->Join(ui->nickname->text().toStdString(), room_member->Join(ui->nickname->text().toStdString(),
Service::CFG::GetConsoleIdHash(system), Service::CFG::GetConsoleIdHash(Core::System::GetInstance()),
ui->ip->text().toStdString().c_str(), port, 0, ui->ip->text().toStdString().c_str(), port, 0,
Network::NoPreferredMac, ui->password->text().toStdString().c_str()); Network::NoPreferredMac, ui->password->text().toStdString().c_str());
} }

View File

@ -13,15 +13,11 @@ namespace Ui {
class DirectConnect; class DirectConnect;
} }
namespace Core {
class System;
}
class DirectConnectWindow : public QDialog { class DirectConnectWindow : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
explicit DirectConnectWindow(Core::System& system, QWidget* parent = nullptr); explicit DirectConnectWindow(QWidget* parent = nullptr);
~DirectConnectWindow(); ~DirectConnectWindow();
void RetranslateUi(); void RetranslateUi();
@ -43,6 +39,5 @@ private:
QFutureWatcher<void>* watcher; QFutureWatcher<void>* watcher;
std::unique_ptr<Ui::DirectConnect> ui; std::unique_ptr<Ui::DirectConnect> ui;
Core::System& system;
Validation validation; Validation validation;
}; };

View File

@ -12,6 +12,7 @@
#include <QTime> #include <QTime>
#include <QtConcurrent/QtConcurrentRun> #include <QtConcurrent/QtConcurrentRun>
#include "citra_qt/game_list_p.h" #include "citra_qt/game_list_p.h"
#include "citra_qt/main.h"
#include "citra_qt/multiplayer/host_room.h" #include "citra_qt/multiplayer/host_room.h"
#include "citra_qt/multiplayer/message.h" #include "citra_qt/multiplayer/message.h"
#include "citra_qt/multiplayer/state.h" #include "citra_qt/multiplayer/state.h"
@ -26,10 +27,10 @@
#include "web_service/verify_user_jwt.h" #include "web_service/verify_user_jwt.h"
#endif #endif
HostRoomWindow::HostRoomWindow(Core::System& system_, QWidget* parent, QStandardItemModel* list, HostRoomWindow::HostRoomWindow(QWidget* parent, QStandardItemModel* list,
std::shared_ptr<Network::AnnounceMultiplayerSession> session) std::shared_ptr<Network::AnnounceMultiplayerSession> session)
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
ui(std::make_unique<Ui::HostRoom>()), system{system_}, announce_multiplayer_session(session) { ui(std::make_unique<Ui::HostRoom>()), announce_multiplayer_session(session) {
ui->setupUi(this); ui->setupUi(this);
// set up validation for all of the fields // set up validation for all of the fields
@ -195,8 +196,9 @@ void HostRoomWindow::Host() {
} }
} }
#endif #endif
member->Join(ui->username->text().toStdString(), Service::CFG::GetConsoleIdHash(system), member->Join(ui->username->text().toStdString(),
"127.0.0.1", port, 0, Network::NoPreferredMac, password, token); Service::CFG::GetConsoleIdHash(Core::System::GetInstance()), "127.0.0.1", port,
0, Network::NoPreferredMac, password, token);
// Store settings // Store settings
UISettings::values.room_nickname = ui->username->text(); UISettings::values.room_nickname = ui->username->text();

View File

@ -9,16 +9,14 @@
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
#include <QStandardItemModel> #include <QStandardItemModel>
#include <QVariant> #include <QVariant>
#include "citra_qt/multiplayer/chat_room.h"
#include "citra_qt/multiplayer/validation.h" #include "citra_qt/multiplayer/validation.h"
#include "network/network.h"
namespace Ui { namespace Ui {
class HostRoom; class HostRoom;
} }
namespace Core {
class System;
}
namespace Network { namespace Network {
class AnnounceMultiplayerSession; class AnnounceMultiplayerSession;
} }
@ -36,7 +34,7 @@ class HostRoomWindow : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
explicit HostRoomWindow(Core::System& system, QWidget* parent, QStandardItemModel* list, explicit HostRoomWindow(QWidget* parent, QStandardItemModel* list,
std::shared_ptr<Network::AnnounceMultiplayerSession> session); std::shared_ptr<Network::AnnounceMultiplayerSession> session);
~HostRoomWindow(); ~HostRoomWindow();
@ -52,7 +50,6 @@ private:
std::unique_ptr<Network::VerifyUser::Backend> CreateVerifyBackend(bool use_validation) const; std::unique_ptr<Network::VerifyUser::Backend> CreateVerifyBackend(bool use_validation) const;
std::unique_ptr<Ui::HostRoom> ui; std::unique_ptr<Ui::HostRoom> ui;
Core::System& system;
std::weak_ptr<Network::AnnounceMultiplayerSession> announce_multiplayer_session; std::weak_ptr<Network::AnnounceMultiplayerSession> announce_multiplayer_session;
QStandardItemModel* game_list; QStandardItemModel* game_list;
ComboBoxProxyModel* proxy; ComboBoxProxyModel* proxy;

View File

@ -7,9 +7,11 @@
#include <QtConcurrent/QtConcurrentRun> #include <QtConcurrent/QtConcurrentRun>
#include "citra_qt/game_list_p.h" #include "citra_qt/game_list_p.h"
#include "citra_qt/main.h" #include "citra_qt/main.h"
#include "citra_qt/multiplayer/client_room.h"
#include "citra_qt/multiplayer/lobby.h" #include "citra_qt/multiplayer/lobby.h"
#include "citra_qt/multiplayer/lobby_p.h" #include "citra_qt/multiplayer/lobby_p.h"
#include "citra_qt/multiplayer/message.h" #include "citra_qt/multiplayer/message.h"
#include "citra_qt/multiplayer/state.h"
#include "citra_qt/multiplayer/validation.h" #include "citra_qt/multiplayer/validation.h"
#include "citra_qt/uisettings.h" #include "citra_qt/uisettings.h"
#include "common/logging/log.h" #include "common/logging/log.h"
@ -21,10 +23,10 @@
#include "web_service/web_backend.h" #include "web_service/web_backend.h"
#endif #endif
Lobby::Lobby(Core::System& system_, QWidget* parent, QStandardItemModel* list, Lobby::Lobby(QWidget* parent, QStandardItemModel* list,
std::shared_ptr<Network::AnnounceMultiplayerSession> session) std::shared_ptr<Network::AnnounceMultiplayerSession> session)
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
ui(std::make_unique<Ui::Lobby>()), system{system_}, announce_multiplayer_session(session) { ui(std::make_unique<Ui::Lobby>()), announce_multiplayer_session(session) {
ui->setupUi(this); ui->setupUi(this);
// setup the watcher for background connections // setup the watcher for background connections
@ -150,8 +152,8 @@ void Lobby::OnJoinRoom(const QModelIndex& source) {
const std::string verify_UID = const std::string verify_UID =
proxy->data(connection_index, LobbyItemHost::HostVerifyUIDRole).toString().toStdString(); proxy->data(connection_index, LobbyItemHost::HostVerifyUIDRole).toString().toStdString();
// Attempt to connect in a different thread // attempt to connect in a different thread
QFuture<void> f = QtConcurrent::run([this, nickname, ip, port, password, verify_UID] { QFuture<void> f = QtConcurrent::run([nickname, ip, port, password, verify_UID] {
std::string token; std::string token;
#ifdef ENABLE_WEB_SERVICE #ifdef ENABLE_WEB_SERVICE
if (!NetSettings::values.citra_username.empty() && if (!NetSettings::values.citra_username.empty() &&
@ -168,8 +170,8 @@ void Lobby::OnJoinRoom(const QModelIndex& source) {
} }
#endif #endif
if (auto room_member = Network::GetRoomMember().lock()) { if (auto room_member = Network::GetRoomMember().lock()) {
room_member->Join(nickname, Service::CFG::GetConsoleIdHash(system), ip.c_str(), port, 0, room_member->Join(nickname, Service::CFG::GetConsoleIdHash(Core::System::GetInstance()),
Network::NoPreferredMac, password, token); ip.c_str(), port, 0, Network::NoPreferredMac, password, token);
} }
}); });
watcher->setFuture(f); watcher->setFuture(f);

View File

@ -12,16 +12,12 @@
#include "citra_qt/multiplayer/validation.h" #include "citra_qt/multiplayer/validation.h"
#include "common/announce_multiplayer_room.h" #include "common/announce_multiplayer_room.h"
#include "network/announce_multiplayer_session.h" #include "network/announce_multiplayer_session.h"
#include "network/room_member.h" #include "network/network.h"
namespace Ui { namespace Ui {
class Lobby; class Lobby;
} }
namespace Core {
class System;
}
class LobbyModel; class LobbyModel;
class LobbyFilterProxyModel; class LobbyFilterProxyModel;
@ -33,7 +29,7 @@ class Lobby : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
explicit Lobby(Core::System& system, QWidget* parent, QStandardItemModel* list, explicit Lobby(QWidget* parent, QStandardItemModel* list,
std::shared_ptr<Network::AnnounceMultiplayerSession> session); std::shared_ptr<Network::AnnounceMultiplayerSession> session);
~Lobby() override; ~Lobby() override;
@ -88,9 +84,7 @@ private:
*/ */
QString PasswordPrompt(); QString PasswordPrompt();
private:
std::unique_ptr<Ui::Lobby> ui; std::unique_ptr<Ui::Lobby> ui;
Core::System& system;
QStandardItemModel* model{}; QStandardItemModel* model{};
QStandardItemModel* game_list{}; QStandardItemModel* game_list{};

View File

@ -17,10 +17,9 @@
#include "citra_qt/util/clickable_label.h" #include "citra_qt/util/clickable_label.h"
#include "common/logging/log.h" #include "common/logging/log.h"
MultiplayerState::MultiplayerState(Core::System& system_, QWidget* parent, MultiplayerState::MultiplayerState(QWidget* parent, QStandardItemModel* game_list_model,
QStandardItemModel* game_list_model, QAction* leave_room, QAction* leave_room, QAction* show_room)
QAction* show_room) : QWidget(parent), game_list_model(game_list_model), leave_room(leave_room),
: QWidget(parent), system{system_}, game_list_model(game_list_model), leave_room(leave_room),
show_room(show_room) { show_room(show_room) {
if (auto member = Network::GetRoomMember().lock()) { if (auto member = Network::GetRoomMember().lock()) {
// register the network structs to use in slots and signals // register the network structs to use in slots and signals
@ -204,14 +203,14 @@ static void BringWidgetToFront(QWidget* widget) {
void MultiplayerState::OnViewLobby() { void MultiplayerState::OnViewLobby() {
if (lobby == nullptr) { if (lobby == nullptr) {
lobby = new Lobby(system, this, game_list_model, announce_multiplayer_session); lobby = new Lobby(this, game_list_model, announce_multiplayer_session);
} }
BringWidgetToFront(lobby); BringWidgetToFront(lobby);
} }
void MultiplayerState::OnCreateRoom() { void MultiplayerState::OnCreateRoom() {
if (host_room == nullptr) { if (host_room == nullptr) {
host_room = new HostRoomWindow(system, this, game_list_model, announce_multiplayer_session); host_room = new HostRoomWindow(this, game_list_model, announce_multiplayer_session);
} }
BringWidgetToFront(host_room); BringWidgetToFront(host_room);
} }
@ -275,7 +274,7 @@ void MultiplayerState::OnOpenNetworkRoom() {
void MultiplayerState::OnDirectConnectToRoom() { void MultiplayerState::OnDirectConnectToRoom() {
if (direct_connect == nullptr) { if (direct_connect == nullptr) {
direct_connect = new DirectConnectWindow(system, this); direct_connect = new DirectConnectWindow(this);
} }
BringWidgetToFront(direct_connect); BringWidgetToFront(direct_connect);
} }

View File

@ -15,16 +15,12 @@ class ClientRoomWindow;
class DirectConnectWindow; class DirectConnectWindow;
class ClickableLabel; class ClickableLabel;
namespace Core {
class System;
}
class MultiplayerState : public QWidget { class MultiplayerState : public QWidget {
Q_OBJECT; Q_OBJECT;
public: public:
explicit MultiplayerState(Core::System& system, QWidget* parent, QStandardItemModel* game_list, explicit MultiplayerState(QWidget* parent, QStandardItemModel* game_list, QAction* leave_room,
QAction* leave_room, QAction* show_room); QAction* show_room);
~MultiplayerState(); ~MultiplayerState();
/** /**
@ -75,7 +71,6 @@ signals:
void AnnounceFailed(const Common::WebResult&); void AnnounceFailed(const Common::WebResult&);
private: private:
Core::System& system;
Lobby* lobby = nullptr; Lobby* lobby = nullptr;
HostRoomWindow* host_room = nullptr; HostRoomWindow* host_room = nullptr;
ClientRoomWindow* client_room = nullptr; ClientRoomWindow* client_room = nullptr;

View File

@ -3,15 +3,10 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <QImage> #include <QImage>
#include <QImageReader>
#include <QString> #include <QString>
#include "citra_qt/qt_image_interface.h" #include "citra_qt/qt_image_interface.h"
#include "common/logging/log.h" #include "common/logging/log.h"
QtImageInterface::QtImageInterface() {
QImageReader::setAllocationLimit(0);
}
bool QtImageInterface::DecodePNG(std::vector<u8>& dst, u32& width, u32& height, bool QtImageInterface::DecodePNG(std::vector<u8>& dst, u32& width, u32& height,
std::span<const u8> src) { std::span<const u8> src) {
QImage image(QImage::fromData(src.data(), static_cast<int>(src.size()))); QImage image(QImage::fromData(src.data(), static_cast<int>(src.size())));

View File

@ -8,7 +8,6 @@
class QtImageInterface final : public Frontend::ImageInterface { class QtImageInterface final : public Frontend::ImageInterface {
public: public:
QtImageInterface();
bool DecodePNG(std::vector<u8>& dst, u32& width, u32& height, std::span<const u8> src) override; bool DecodePNG(std::vector<u8>& dst, u32& width, u32& height, std::span<const u8> src) override;
bool EncodePNG(const std::string& path, u32 width, u32 height, bool EncodePNG(const std::string& path, u32 width, u32 height,
std::span<const u8> src) override; std::span<const u8> src) override;

View File

@ -97,12 +97,6 @@ struct Values {
Settings::Setting<bool> game_list_hide_no_icon{false, "hideNoIcon"}; Settings::Setting<bool> game_list_hide_no_icon{false, "hideNoIcon"};
Settings::Setting<bool> game_list_single_line_mode{false, "singleLineMode"}; Settings::Setting<bool> game_list_single_line_mode{false, "singleLineMode"};
// Compatibility List
Settings::Setting<bool> show_compat_column{true, "show_compat_column"};
Settings::Setting<bool> show_region_column{true, "show_region_column"};
Settings::Setting<bool> show_type_column{true, "show_type_column"};
Settings::Setting<bool> show_size_column{true, "show_size_column"};
Settings::Setting<u16> screenshot_resolution_factor{0, "screenshot_resolution_factor"}; Settings::Setting<u16> screenshot_resolution_factor{0, "screenshot_resolution_factor"};
Settings::SwitchableSetting<std::string> screenshot_path{"", "screenshotPath"}; Settings::SwitchableSetting<std::string> screenshot_path{"", "screenshotPath"};

View File

@ -130,9 +130,11 @@ bool UpdaterPrivate::StartUpdateCheck() {
main_process->setProgram(tool_info.absoluteFilePath()); main_process->setProgram(tool_info.absoluteFilePath());
main_process->setArguments({QStringLiteral("--checkupdates"), QStringLiteral("-v")}); main_process->setArguments({QStringLiteral("--checkupdates"), QStringLiteral("-v")});
connect(main_process, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this, connect(main_process,
static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), this,
&UpdaterPrivate::UpdaterReady, Qt::QueuedConnection); &UpdaterPrivate::UpdaterReady, Qt::QueuedConnection);
connect(main_process, qOverload<QProcess::ProcessError>(&QProcess::errorOccurred), this, connect(main_process,
static_cast<void (QProcess::*)(QProcess::ProcessError)>(&QProcess::errorOccurred), this,
&UpdaterPrivate::UpdaterError, Qt::QueuedConnection); &UpdaterPrivate::UpdaterError, Qt::QueuedConnection);
main_process->start(QIODevice::ReadOnly); main_process->start(QIODevice::ReadOnly);
@ -154,7 +156,7 @@ void UpdaterPrivate::StopUpdateCheck(int delay, bool async) {
QTimer* timer = new QTimer(this); QTimer* timer = new QTimer(this);
timer->setSingleShot(true); timer->setSingleShot(true);
connect(timer, &QTimer::timeout, this, [this, timer]() { connect(timer, &QTimer::timeout, [this, timer]() {
StopUpdateCheck(0, false); StopUpdateCheck(0, false);
timer->deleteLater(); timer->deleteLater();
}); });

View File

@ -176,9 +176,6 @@ endif()
if (CITRA_USE_PRECOMPILED_HEADERS) if (CITRA_USE_PRECOMPILED_HEADERS)
target_precompile_headers(citra_common PRIVATE precompiled_headers.h) target_precompile_headers(citra_common PRIVATE precompiled_headers.h)
endif() endif()
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND CMAKE_CXX_COMPILER_ID STREQUAL GNU)
find_library(BACKTRACE_LIBRARY backtrace) target_link_libraries(citra_common PRIVATE backtrace dl)
if (BACKTRACE_LIBRARY AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND CMAKE_CXX_COMPILER_ID STREQUAL GNU)
target_link_libraries(citra_common PRIVATE ${BACKTRACE_LIBRARY} dl)
target_compile_definitions(citra_common PRIVATE CITRA_LINUX_GCC_BACKTRACE)
endif() endif()

View File

@ -13,11 +13,12 @@
#define _SH_DENYWR 0 #define _SH_DENYWR 0
#endif #endif
#ifdef CITRA_LINUX_GCC_BACKTRACE #if defined(__linux__) && defined(__GNUG__) && !defined(__clang__)
#define BOOST_STACKTRACE_USE_BACKTRACE #define BOOST_STACKTRACE_USE_BACKTRACE
#include <boost/stacktrace.hpp> #include <boost/stacktrace.hpp>
#undef BOOST_STACKTRACE_USE_BACKTRACE #undef BOOST_STACKTRACE_USE_BACKTRACE
#include <signal.h> #include <signal.h>
#define CITRA_LINUX_GCC_BACKTRACE
#endif #endif
#include "common/bounded_threadsafe_queue.h" #include "common/bounded_threadsafe_queue.h"

View File

@ -88,7 +88,6 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
SUB(Service, FRD) \ SUB(Service, FRD) \
SUB(Service, FS) \ SUB(Service, FS) \
SUB(Service, ERR) \ SUB(Service, ERR) \
SUB(Service, ACT) \
SUB(Service, APT) \ SUB(Service, APT) \
SUB(Service, BOSS) \ SUB(Service, BOSS) \
SUB(Service, GSP) \ SUB(Service, GSP) \

View File

@ -55,7 +55,6 @@ enum class Class : u8 {
Service_FRD, ///< The FRD (Friends) service Service_FRD, ///< The FRD (Friends) service
Service_FS, ///< The FS (Filesystem) service implementation Service_FS, ///< The FS (Filesystem) service implementation
Service_ERR, ///< The ERR (Error) port implementation Service_ERR, ///< The ERR (Error) port implementation
Service_ACT, ///< The ACT (Account) service
Service_APT, ///< The APT (Applets) service Service_APT, ///< The APT (Applets) service
Service_BOSS, ///< The BOSS (SpotPass) service Service_BOSS, ///< The BOSS (SpotPass) service
Service_GSP, ///< The GSP (GPU control) service Service_GSP, ///< The GSP (GPU control) service

View File

@ -100,14 +100,13 @@ enum Values {
ZR, ZR,
Home, Home,
Power,
NumButtons, NumButtons,
}; };
constexpr int BUTTON_HID_BEGIN = A; constexpr int BUTTON_HID_BEGIN = A;
constexpr int BUTTON_IR_BEGIN = ZL; constexpr int BUTTON_IR_BEGIN = ZL;
constexpr int BUTTON_NS_BEGIN = Power; constexpr int BUTTON_NS_BEGIN = Home;
constexpr int BUTTON_HID_END = BUTTON_IR_BEGIN; constexpr int BUTTON_HID_END = BUTTON_IR_BEGIN;
constexpr int BUTTON_IR_END = BUTTON_NS_BEGIN; constexpr int BUTTON_IR_END = BUTTON_NS_BEGIN;
@ -135,7 +134,6 @@ static const std::array<const char*, NumButtons> mapping = {{
"button_zl", "button_zl",
"button_zr", "button_zr",
"button_home", "button_home",
"button_power",
}}; }};
} // namespace NativeButton } // namespace NativeButton

View File

@ -62,29 +62,12 @@ public:
return SlotId{index}; return SlotId{index};
} }
template <typename... Args>
[[nodiscard]] SlotId swap_and_insert(SlotId existing_id, Args&&... args) noexcept {
const u32 index = FreeValueIndex();
T& existing_value = values[existing_id.index].object;
new (&values[index].object) T(std::move(existing_value));
existing_value.~T();
new (&values[existing_id.index].object) T(std::forward<Args>(args)...);
SetStorageBit(index);
return SlotId{index};
}
void erase(SlotId id) noexcept { void erase(SlotId id) noexcept {
values[id.index].object.~T(); values[id.index].object.~T();
free_list.push_back(id.index); free_list.push_back(id.index);
ResetStorageBit(id.index); ResetStorageBit(id.index);
} }
size_t size() const noexcept {
return values_capacity - free_list.size();
}
private: private:
struct NonTrivialDummy { struct NonTrivialDummy {
NonTrivialDummy() noexcept {} NonTrivialDummy() noexcept {}
@ -110,7 +93,7 @@ private:
return ((stored_bitset[index / 64] >> (index % 64)) & 1) != 0; return ((stored_bitset[index / 64] >> (index % 64)) & 1) != 0;
} }
void ValidateIndex([[maybe_unused]] SlotId id) const noexcept { void ValidateIndex(SlotId id) const noexcept {
DEBUG_ASSERT(id); DEBUG_ASSERT(id);
DEBUG_ASSERT(id.index / 64 < stored_bitset.size()); DEBUG_ASSERT(id.index / 64 < stored_bitset.size());
DEBUG_ASSERT(((stored_bitset[id.index / 64] >> (id.index % 64)) & 1) != 0); DEBUG_ASSERT(((stored_bitset[id.index / 64] >> (id.index % 64)) & 1) != 0);

View File

@ -184,8 +184,6 @@ add_library(citra_core STATIC
hle/kernel/wait_object.h hle/kernel/wait_object.h
hle/lock.cpp hle/lock.cpp
hle/lock.h hle/lock.h
hle/mii.h
hle/mii.cpp
hle/result.h hle/result.h
hle/romfs.cpp hle/romfs.cpp
hle/romfs.h hle/romfs.h
@ -247,8 +245,6 @@ add_library(citra_core STATIC
hle/service/cam/cam_s.h hle/service/cam/cam_s.h
hle/service/cam/cam_u.cpp hle/service/cam/cam_u.cpp
hle/service/cam/cam_u.h hle/service/cam/cam_u.h
hle/service/cam/y2r_u.cpp
hle/service/cam/y2r_u.h
hle/service/cecd/cecd.cpp hle/service/cecd/cecd.cpp
hle/service/cecd/cecd.h hle/service/cecd/cecd.h
hle/service/cecd/cecd_ndm.cpp hle/service/cecd/cecd_ndm.cpp
@ -259,8 +255,6 @@ add_library(citra_core STATIC
hle/service/cecd/cecd_u.h hle/service/cecd/cecd_u.h
hle/service/cfg/cfg.cpp hle/service/cfg/cfg.cpp
hle/service/cfg/cfg.h hle/service/cfg/cfg.h
hle/service/cfg/cfg_defaults.cpp
hle/service/cfg/cfg_defaults.h
hle/service/cfg/cfg_i.cpp hle/service/cfg/cfg_i.cpp
hle/service/cfg/cfg_i.h hle/service/cfg/cfg_i.h
hle/service/cfg/cfg_nor.cpp hle/service/cfg/cfg_nor.cpp
@ -281,8 +275,8 @@ add_library(citra_core STATIC
hle/service/dlp/dlp_srvr.h hle/service/dlp/dlp_srvr.h
hle/service/dsp/dsp_dsp.cpp hle/service/dsp/dsp_dsp.cpp
hle/service/dsp/dsp_dsp.h hle/service/dsp/dsp_dsp.h
hle/service/err/err_f.cpp hle/service/err_f.cpp
hle/service/err/err_f.h hle/service/err_f.h
hle/service/frd/frd.cpp hle/service/frd/frd.cpp
hle/service/frd/frd.h hle/service/frd/frd.h
hle/service/frd/frd_a.cpp hle/service/frd/frd_a.cpp
@ -309,8 +303,8 @@ add_library(citra_core STATIC
hle/service/hid/hid_spvr.h hle/service/hid/hid_spvr.h
hle/service/hid/hid_user.cpp hle/service/hid/hid_user.cpp
hle/service/hid/hid_user.h hle/service/hid/hid_user.h
hle/service/http/http_c.cpp hle/service/http_c.cpp
hle/service/http/http_c.h hle/service/http_c.h
hle/service/ir/extra_hid.cpp hle/service/ir/extra_hid.cpp
hle/service/ir/extra_hid.h hle/service/ir/extra_hid.h
hle/service/ir/ir.cpp hle/service/ir/ir.cpp
@ -325,8 +319,8 @@ add_library(citra_core STATIC
hle/service/ldr_ro/cro_helper.h hle/service/ldr_ro/cro_helper.h
hle/service/ldr_ro/ldr_ro.cpp hle/service/ldr_ro/ldr_ro.cpp
hle/service/ldr_ro/ldr_ro.h hle/service/ldr_ro/ldr_ro.h
hle/service/mic/mic_u.cpp hle/service/mic_u.cpp
hle/service/mic/mic_u.h hle/service/mic_u.h
hle/service/mvd/mvd.cpp hle/service/mvd/mvd.cpp
hle/service/mvd/mvd.h hle/service/mvd/mvd.h
hle/service/mvd/mvd_std.cpp hle/service/mvd/mvd_std.cpp
@ -423,10 +417,12 @@ add_library(citra_core STATIC
hle/service/sm/sm.h hle/service/sm/sm.h
hle/service/sm/srv.cpp hle/service/sm/srv.cpp
hle/service/sm/srv.h hle/service/sm/srv.h
hle/service/soc/soc_u.cpp hle/service/soc_u.cpp
hle/service/soc/soc_u.h hle/service/soc_u.h
hle/service/ssl/ssl_c.cpp hle/service/ssl_c.cpp
hle/service/ssl/ssl_c.h hle/service/ssl_c.h
hle/service/y2r_u.cpp
hle/service/y2r_u.h
hw/aes/arithmetic128.cpp hw/aes/arithmetic128.cpp
hw/aes/arithmetic128.h hw/aes/arithmetic128.h
hw/aes/ccm.cpp hw/aes/ccm.cpp
@ -461,6 +457,14 @@ add_library(citra_core STATIC
perf_stats.cpp perf_stats.cpp
perf_stats.h perf_stats.h
precompiled_headers.h precompiled_headers.h
rpc/packet.cpp
rpc/packet.h
rpc/rpc_server.cpp
rpc/rpc_server.h
rpc/server.cpp
rpc/server.h
rpc/udp_server.cpp
rpc/udp_server.h
savestate.cpp savestate.cpp
savestate.h savestate.h
system_titles.cpp system_titles.cpp
@ -475,32 +479,18 @@ add_library(citra_core STATIC
create_target_directory_groups(citra_core) create_target_directory_groups(citra_core)
target_link_libraries(citra_core PUBLIC citra_common PRIVATE audio_core network video_core) target_link_libraries(citra_core PUBLIC citra_common PRIVATE audio_core network video_core)
target_link_libraries(citra_core PRIVATE Boost::boost Boost::serialization Boost::iostreams httplib) target_link_libraries(citra_core PRIVATE Boost::boost Boost::serialization Boost::iostreams)
target_link_libraries(citra_core PUBLIC dds-ktx PRIVATE cryptopp fmt::fmt lodepng open_source_archives) target_link_libraries(citra_core PUBLIC dds-ktx PRIVATE cryptopp fmt::fmt lodepng open_source_archives)
set_target_properties(citra_core PROPERTIES INTERPROCEDURAL_OPTIMIZATION ${ENABLE_LTO}) set_target_properties(citra_core PROPERTIES INTERPROCEDURAL_OPTIMIZATION ${ENABLE_LTO})
if (ENABLE_WEB_SERVICE) if (ENABLE_WEB_SERVICE)
target_compile_definitions(citra_core PRIVATE -DENABLE_WEB_SERVICE) target_compile_definitions(citra_core PRIVATE -DENABLE_WEB_SERVICE -DCPPHTTPLIB_OPENSSL_SUPPORT)
target_link_libraries(citra_core PRIVATE web_service) target_link_libraries(citra_core PRIVATE web_service ${OPENSSL_LIBS} httplib)
if (ANDROID) if (ANDROID)
target_link_libraries(citra_core PRIVATE ifaddrs) target_link_libraries(citra_core PRIVATE ifaddrs)
endif() endif()
endif() endif()
if (ENABLE_SCRIPTING)
target_compile_definitions(citra_core PRIVATE -DENABLE_SCRIPTING)
target_sources(citra_core PRIVATE
rpc/packet.cpp
rpc/packet.h
rpc/rpc_server.cpp
rpc/rpc_server.h
rpc/server.cpp
rpc/server.h
rpc/udp_server.cpp
rpc/udp_server.h
)
endif()
if ("x86_64" IN_LIST ARCHITECTURE OR "arm64" IN_LIST ARCHITECTURE) if ("x86_64" IN_LIST ARCHITECTURE OR "arm64" IN_LIST ARCHITECTURE)
target_sources(citra_core PRIVATE target_sources(citra_core PRIVATE
arm/dynarmic/arm_dynarmic.cpp arm/dynarmic/arm_dynarmic.cpp

View File

@ -10,8 +10,6 @@
#include "core/cheats/gateway_cheat.h" #include "core/cheats/gateway_cheat.h"
#include "core/core.h" #include "core/core.h"
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/hle/kernel/process.h"
#include "core/hw/gpu.h"
namespace Cheats { namespace Cheats {
@ -19,11 +17,11 @@ namespace Cheats {
// we use the same value // we use the same value
constexpr u64 run_interval_ticks = 50'000'000; constexpr u64 run_interval_ticks = 50'000'000;
CheatEngine::CheatEngine(u64 title_id_, Core::System& system_) CheatEngine::CheatEngine(Core::System& system_) : system{system_} {}
: system(system_), title_id{title_id_} {
LoadCheatFile(); CheatEngine::~CheatEngine() {
if (system.IsPoweredOn()) { if (system.IsPoweredOn()) {
Connect(); system.CoreTiming().UnscheduleEvent(event, 0);
} }
} }
@ -34,24 +32,18 @@ void CheatEngine::Connect() {
system.CoreTiming().ScheduleEvent(run_interval_ticks, event); system.CoreTiming().ScheduleEvent(run_interval_ticks, event);
} }
CheatEngine::~CheatEngine() { std::span<const std::shared_ptr<CheatBase>> CheatEngine::GetCheats() const {
if (system.IsPoweredOn()) { std::shared_lock lock{cheats_list_mutex};
system.CoreTiming().UnscheduleEvent(event, 0);
}
}
std::vector<std::shared_ptr<CheatBase>> CheatEngine::GetCheats() const {
std::shared_lock<std::shared_mutex> lock(cheats_list_mutex);
return cheats_list; return cheats_list;
} }
void CheatEngine::AddCheat(const std::shared_ptr<CheatBase>& cheat) { void CheatEngine::AddCheat(std::shared_ptr<CheatBase>&& cheat) {
std::unique_lock<std::shared_mutex> lock(cheats_list_mutex); std::unique_lock lock{cheats_list_mutex};
cheats_list.push_back(cheat); cheats_list.push_back(std::move(cheat));
} }
void CheatEngine::RemoveCheat(std::size_t index) { void CheatEngine::RemoveCheat(std::size_t index) {
std::unique_lock<std::shared_mutex> lock(cheats_list_mutex); std::unique_lock lock{cheats_list_mutex};
if (index < 0 || index >= cheats_list.size()) { if (index < 0 || index >= cheats_list.size()) {
LOG_ERROR(Core_Cheats, "Invalid index {}", index); LOG_ERROR(Core_Cheats, "Invalid index {}", index);
return; return;
@ -59,16 +51,16 @@ void CheatEngine::RemoveCheat(std::size_t index) {
cheats_list.erase(cheats_list.begin() + index); cheats_list.erase(cheats_list.begin() + index);
} }
void CheatEngine::UpdateCheat(std::size_t index, const std::shared_ptr<CheatBase>& new_cheat) { void CheatEngine::UpdateCheat(std::size_t index, std::shared_ptr<CheatBase>&& new_cheat) {
std::unique_lock<std::shared_mutex> lock(cheats_list_mutex); std::unique_lock lock{cheats_list_mutex};
if (index < 0 || index >= cheats_list.size()) { if (index < 0 || index >= cheats_list.size()) {
LOG_ERROR(Core_Cheats, "Invalid index {}", index); LOG_ERROR(Core_Cheats, "Invalid index {}", index);
return; return;
} }
cheats_list[index] = new_cheat; cheats_list[index] = std::move(new_cheat);
} }
void CheatEngine::SaveCheatFile() const { void CheatEngine::SaveCheatFile(u64 title_id) const {
const std::string cheat_dir = FileUtil::GetUserPath(FileUtil::UserPath::CheatsDir); const std::string cheat_dir = FileUtil::GetUserPath(FileUtil::UserPath::CheatsDir);
const std::string filepath = fmt::format("{}{:016X}.txt", cheat_dir, title_id); const std::string filepath = fmt::format("{}{:016X}.txt", cheat_dir, title_id);
@ -83,7 +75,7 @@ void CheatEngine::SaveCheatFile() const {
} }
} }
void CheatEngine::LoadCheatFile() { void CheatEngine::LoadCheatFile(u64 title_id) {
const std::string cheat_dir = FileUtil::GetUserPath(FileUtil::UserPath::CheatsDir); const std::string cheat_dir = FileUtil::GetUserPath(FileUtil::UserPath::CheatsDir);
const std::string filepath = fmt::format("{}{:016X}.txt", cheat_dir, title_id); const std::string filepath = fmt::format("{}{:016X}.txt", cheat_dir, title_id);
@ -96,15 +88,15 @@ void CheatEngine::LoadCheatFile() {
auto gateway_cheats = GatewayCheat::LoadFile(filepath); auto gateway_cheats = GatewayCheat::LoadFile(filepath);
{ {
std::unique_lock<std::shared_mutex> lock(cheats_list_mutex); std::unique_lock lock{cheats_list_mutex};
std::move(gateway_cheats.begin(), gateway_cheats.end(), std::back_inserter(cheats_list)); cheats_list = std::move(gateway_cheats);
} }
} }
void CheatEngine::RunCallback([[maybe_unused]] std::uintptr_t user_data, s64 cycles_late) { void CheatEngine::RunCallback([[maybe_unused]] std::uintptr_t user_data, s64 cycles_late) {
{ {
std::shared_lock<std::shared_mutex> lock(cheats_list_mutex); std::shared_lock lock{cheats_list_mutex};
for (auto& cheat : cheats_list) { for (const auto& cheat : cheats_list) {
if (cheat->IsEnabled()) { if (cheat->IsEnabled()) {
cheat->Execute(system); cheat->Execute(system);
} }

View File

@ -6,6 +6,7 @@
#include <memory> #include <memory>
#include <shared_mutex> #include <shared_mutex>
#include <span>
#include <vector> #include <vector>
#include "common/common_types.h" #include "common/common_types.h"
@ -24,22 +25,38 @@ class CheatBase;
class CheatEngine { class CheatEngine {
public: public:
explicit CheatEngine(u64 title_id_, Core::System& system); explicit CheatEngine(Core::System& system);
~CheatEngine(); ~CheatEngine();
/// Registers the cheat execution callback.
void Connect(); void Connect();
std::vector<std::shared_ptr<CheatBase>> GetCheats() const;
void AddCheat(const std::shared_ptr<CheatBase>& cheat); /// Returns a span of the currently active cheats.
std::span<const std::shared_ptr<CheatBase>> GetCheats() const;
/// Adds a cheat to the cheat engine.
void AddCheat(std::shared_ptr<CheatBase>&& cheat);
/// Removes a cheat at the specified index in the cheats list.
void RemoveCheat(std::size_t index); void RemoveCheat(std::size_t index);
void UpdateCheat(std::size_t index, const std::shared_ptr<CheatBase>& new_cheat);
void SaveCheatFile() const; /// Updates a cheat at the specified index in the cheats list.
void UpdateCheat(std::size_t index, std::shared_ptr<CheatBase>&& new_cheat);
/// Loads the cheat file from disk for the specified title id.
void LoadCheatFile(u64 title_id);
/// Saves currently active cheats to file for the specified title id.
void SaveCheatFile(u64 title_id) const;
private: private:
void LoadCheatFile(); /// The cheat execution callback.
void RunCallback(std::uintptr_t user_data, s64 cycles_late); void RunCallback(std::uintptr_t user_data, s64 cycles_late);
private:
Core::System& system;
Core::TimingEventType* event;
std::vector<std::shared_ptr<CheatBase>> cheats_list; std::vector<std::shared_ptr<CheatBase>> cheats_list;
mutable std::shared_mutex cheats_list_mutex; mutable std::shared_mutex cheats_list_mutex;
Core::TimingEventType* event;
Core::System& system;
u64 title_id;
}; };
} // namespace Cheats } // namespace Cheats

View File

@ -472,8 +472,8 @@ std::string GatewayCheat::ToString() const {
return result; return result;
} }
std::vector<std::unique_ptr<CheatBase>> GatewayCheat::LoadFile(const std::string& filepath) { std::vector<std::shared_ptr<CheatBase>> GatewayCheat::LoadFile(const std::string& filepath) {
std::vector<std::unique_ptr<CheatBase>> cheats; std::vector<std::shared_ptr<CheatBase>> cheats;
boost::iostreams::stream<boost::iostreams::file_descriptor_source> file; boost::iostreams::stream<boost::iostreams::file_descriptor_source> file;
FileUtil::OpenFStream<std::ios_base::in>(file, filepath); FileUtil::OpenFStream<std::ios_base::in>(file, filepath);
@ -493,7 +493,7 @@ std::vector<std::unique_ptr<CheatBase>> GatewayCheat::LoadFile(const std::string
line = Common::StripSpaces(line); // remove spaces at front and end line = Common::StripSpaces(line); // remove spaces at front and end
if (line.length() >= 2 && line.front() == '[') { if (line.length() >= 2 && line.front() == '[') {
if (!cheat_lines.empty()) { if (!cheat_lines.empty()) {
cheats.push_back(std::make_unique<GatewayCheat>(name, cheat_lines, comments)); cheats.push_back(std::make_shared<GatewayCheat>(name, cheat_lines, comments));
cheats.back()->SetEnabled(enabled); cheats.back()->SetEnabled(enabled);
enabled = false; enabled = false;
} }
@ -511,7 +511,7 @@ std::vector<std::unique_ptr<CheatBase>> GatewayCheat::LoadFile(const std::string
} }
} }
if (!cheat_lines.empty()) { if (!cheat_lines.empty()) {
cheats.push_back(std::make_unique<GatewayCheat>(name, cheat_lines, comments)); cheats.push_back(std::make_shared<GatewayCheat>(name, cheat_lines, comments));
cheats.back()->SetEnabled(enabled); cheats.back()->SetEnabled(enabled);
} }
return cheats; return cheats;

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