Compare commits

..

6 Commits

Author SHA1 Message Date
617e8ef969 core: Run clang format 2023-12-28 22:47:19 +02:00
72463c8c8c core: Remove CASCADE_CODE
* R_TRY replaces completely
2023-12-28 22:39:20 +02:00
e9b149c99b Address review comments 2023-12-28 22:39:13 +02:00
475c01e053 code: Result constants are lower case 2023-12-28 22:39:02 +02:00
3ae8431aef code: Rename ResultCode to Result 2023-12-28 22:36:10 +02:00
0fd8892892 kernel: Switch to atmosphere style macros 2023-12-28 22:33:04 +02:00
171 changed files with 2359 additions and 1588 deletions

View File

@ -121,7 +121,7 @@ function(download_moltenvk)
set(MOLTENVK_TAR "${CMAKE_BINARY_DIR}/externals/MoltenVK.tar")
if (NOT EXISTS ${MOLTENVK_DIR})
if (NOT EXISTS ${MOLTENVK_TAR})
file(DOWNLOAD https://github.com/KhronosGroup/MoltenVK/releases/download/v1.2.7-rc1/MoltenVK-all.tar
file(DOWNLOAD https://github.com/KhronosGroup/MoltenVK/releases/latest/download/MoltenVK-all.tar
${MOLTENVK_TAR} SHOW_PROGRESS)
endif()

View File

@ -26,38 +26,6 @@
<!-- Fixed -->
<key>LSApplicationCategoryType</key>
<string>public.app-category.games</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>3ds</string>
<string>3dsx</string>
<string>cci</string>
<string>cxi</string>
<string>cia</string>
</array>
<key>CFBundleTypeName</key>
<string>Nintendo 3DS File</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Default</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>elf</string>
<string>axf</string>
</array>
<key>CFBundleTypeName</key>
<string>Unix Executable and Linkable Format</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
</dict>
</array>
<key>NSCameraUsageDescription</key>
<string>This app requires camera access to emulate the 3DS&apos;s cameras.</string>
<key>NSMicrophoneUsageDescription</key>

View File

@ -12,19 +12,18 @@ QPushButton#GraphicsAPIStatusBarButton:hover {
border: 1px solid #76797C;
}
QPushButton#TogglableStatusBarButton {
color: #959595;
QPushButton#3DOptionStatusBarButton {
color: #A5A5A5;
font-weight: bold;
border: 1px solid transparent;
background-color: transparent;
padding: 0px 3px 0px 3px;
text-align: center;
min-width: 60px;
min-height: 20px;
}
QPushButton#TogglableStatusBarButton:checked {
color: #00FF00;
}
QPushButton#TogglableStatusBarButton:hover {
QPushButton#3DOptionStatusBarButton:hover {
border: 1px solid #76797C;
}

View File

@ -1,3 +1,19 @@
QPushButton#TogglableStatusBarButton {
color: #959595;
border: 1px solid transparent;
background-color: transparent;
padding: 0px 3px 0px 3px;
text-align: center;
}
QPushButton#TogglableStatusBarButton:checked {
color: palette(text);
}
QPushButton#TogglableStatusBarButton:hover {
border: 1px solid #76797C;
}
QPushButton#GraphicsAPIStatusBarButton {
color: #656565;
border: 1px solid transparent;
@ -10,23 +26,6 @@ QPushButton#GraphicsAPIStatusBarButton:hover {
border: 1px solid #76797C;
}
QPushButton#TogglableStatusBarButton {
min-width: 0px;
color: #656565;
border: 1px solid transparent;
background-color: transparent;
padding: 0px 3px 0px 3px;
text-align: center;
}
QPushButton#TogglableStatusBarButton:checked {
color: #00FF00;
}
QPushButton#TogglableStatusBarButton:hover {
border: 1px solid #76797C;
}
QToolTip {
border: 1px solid #76797C;
background-color: #5A7566;

View File

@ -395,6 +395,9 @@ if(USE_SYSTEM_VULKAN_HEADERS)
else()
target_include_directories(vulkan-headers SYSTEM INTERFACE ./vulkan-headers/include)
endif()
if (APPLE)
target_include_directories(vulkan-headers SYSTEM INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK)
endif()
# adrenotools
if (ANDROID AND "arm64" IN_LIST ARCHITECTURE)

1071
externals/moltenvk/mvk_config.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -7,13 +7,25 @@ package org.citra.citra_emu.features.cheats.model
import androidx.annotation.Keep
@Keep
object CheatEngine {
external fun loadCheatFile(titleId: Long)
external fun saveCheatFile(titleId: Long)
class CheatEngine(titleId: Long) {
@Keep
private val mPointer: Long
init {
mPointer = initialize(titleId)
}
protected external fun finalize()
external fun getCheats(): Array<Cheat>
external fun addCheat(cheat: Cheat?)
external fun removeCheat(index: Int)
external fun updateCheat(index: Int, newCheat: Cheat?)
external fun saveCheatFile()
companion object {
@JvmStatic
private external fun initialize(titleId: Long): Long
}
}

View File

@ -47,19 +47,18 @@ class CheatsViewModel : ViewModel() {
val detailsViewFocusChange get() = _detailsViewFocusChange.asStateFlow()
private val _detailsViewFocusChange = MutableStateFlow(false)
private var titleId: Long = 0
private var cheatEngine: CheatEngine? = null
lateinit var cheats: Array<Cheat>
private var cheatsNeedSaving = false
private var selectedCheatPosition = -1
fun initialize(titleId_: Long) {
titleId = titleId_;
fun initialize(titleId: Long) {
cheatEngine = CheatEngine(titleId)
load()
}
private fun load() {
CheatEngine.loadCheatFile(titleId)
cheats = CheatEngine.getCheats()
cheats = cheatEngine!!.getCheats()
for (i in cheats.indices) {
cheats[i].setEnabledChangedCallback {
cheatsNeedSaving = true
@ -70,7 +69,7 @@ class CheatsViewModel : ViewModel() {
fun saveIfNeeded() {
if (cheatsNeedSaving) {
CheatEngine.saveCheatFile(titleId)
cheatEngine!!.saveCheatFile()
cheatsNeedSaving = false
}
}
@ -108,7 +107,7 @@ class CheatsViewModel : ViewModel() {
_isAdding.value = false
_isEditing.value = false
val position = cheats.size
CheatEngine.addCheat(cheat)
cheatEngine!!.addCheat(cheat)
cheatsNeedSaving = true
load()
notifyCheatAdded(position)
@ -124,7 +123,7 @@ class CheatsViewModel : ViewModel() {
}
fun updateSelectedCheat(newCheat: Cheat?) {
CheatEngine.updateCheat(selectedCheatPosition, newCheat)
cheatEngine!!.updateCheat(selectedCheatPosition, newCheat)
cheatsNeedSaving = true
load()
notifyCheatUpdated(selectedCheatPosition)
@ -142,7 +141,7 @@ class CheatsViewModel : ViewModel() {
fun deleteSelectedCheat() {
val position = selectedCheatPosition
setSelectedCheat(null, -1)
CheatEngine.removeCheat(position)
cheatEngine!!.removeCheat(position)
cheatsNeedSaving = true
load()
notifyCheatDeleted(position)

View File

@ -15,24 +15,24 @@
extern "C" {
static Cheats::CheatEngine& GetEngine() {
Core::System& system{Core::System::GetInstance()};
return system.CheatEngine();
static Cheats::CheatEngine* GetPointer(JNIEnv* env, jobject obj) {
return reinterpret_cast<Cheats::CheatEngine*>(
env->GetLongField(obj, IDCache::GetCheatEnginePointer()));
}
JNIEXPORT void JNICALL Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_loadCheatFile(
JNIEXPORT jlong JNICALL Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_initialize(
JNIEnv* env, jclass, jlong title_id) {
GetEngine().LoadCheatFile(title_id);
return reinterpret_cast<jlong>(new Cheats::CheatEngine(title_id, Core::System::GetInstance()));
}
JNIEXPORT void JNICALL Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_saveCheatFile(
JNIEnv* env, jclass, jlong title_id) {
GetEngine().SaveCheatFile(title_id);
JNIEXPORT void JNICALL
Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_finalize(JNIEnv* env, jobject obj) {
delete GetPointer(env, obj);
}
JNIEXPORT jobjectArray JNICALL
Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_getCheats(JNIEnv* env, jclass) {
auto cheats = GetEngine().GetCheats();
Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_getCheats(JNIEnv* env, jobject obj) {
auto cheats = GetPointer(env, obj)->GetCheats();
const jobjectArray array =
env->NewObjectArray(static_cast<jsize>(cheats.size()), IDCache::GetCheatClass(), nullptr);
@ -45,19 +45,22 @@ Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_getCheats(JNIEnv* en
}
JNIEXPORT void JNICALL Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_addCheat(
JNIEnv* env, jclass, jobject j_cheat) {
auto cheat = *CheatFromJava(env, j_cheat);
GetEngine().AddCheat(std::move(cheat));
JNIEnv* env, jobject obj, jobject j_cheat) {
GetPointer(env, obj)->AddCheat(*CheatFromJava(env, j_cheat));
}
JNIEXPORT void JNICALL Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_removeCheat(
JNIEnv* env, jclass, jint index) {
GetEngine().RemoveCheat(index);
JNIEnv* env, jobject obj, jint index) {
GetPointer(env, obj)->RemoveCheat(index);
}
JNIEXPORT void JNICALL Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_updateCheat(
JNIEnv* env, jclass, jint index, jobject j_new_cheat) {
auto cheat = *CheatFromJava(env, j_new_cheat);
GetEngine().UpdateCheat(index, std::move(cheat));
JNIEnv* env, jobject obj, jint index, jobject j_new_cheat) {
GetPointer(env, obj)->UpdateCheat(index, *CheatFromJava(env, j_new_cheat));
}
JNIEXPORT void JNICALL Java_org_citra_citra_1emu_features_cheats_model_CheatEngine_saveCheatFile(
JNIEnv* env, jobject obj) {
GetPointer(env, obj)->SaveCheatFile();
}
}

View File

@ -146,7 +146,6 @@ void Config::ReadValues() {
ReadSetting("Renderer", Settings::values.use_disk_shader_cache);
ReadSetting("Renderer", Settings::values.use_vsync_new);
ReadSetting("Renderer", Settings::values.texture_filter);
ReadSetting("Renderer", Settings::values.texture_sampling);
// Work around to map Android setting for enabling the frame limiter to the format Citra expects
if (sdl2_config->GetBoolean("Renderer", "use_frame_limit", true)) {
@ -215,8 +214,6 @@ void Config::ReadValues() {
} catch (...) {
}
}
ReadSetting("System", Settings::values.init_ticks_type);
ReadSetting("System", Settings::values.init_ticks_override);
ReadSetting("System", Settings::values.plugin_loader_enabled);
ReadSetting("System", Settings::values.allow_plugin_loader);

View File

@ -288,14 +288,6 @@ init_clock =
# Note: 3DS can only handle times later then Jan 1 2000
init_time =
# The system ticks count to use when citra starts
# 0: Random (default), 1: Fixed
init_ticks_type =
# Tick count to use when init_ticks_type is set to Fixed.
# Defaults to 0.
init_ticks_override =
# Plugin loader state, if enabled plugins will be loaded from the SD card.
# You can also set if homebrew apps are allowed to enable the plugin loader
plugin_loader =

View File

@ -81,8 +81,8 @@ jstring Java_org_citra_citra_1emu_model_GameInfo_getTitle(JNIEnv* env, jobject o
Loader::SMDH::TitleLanguage language = Loader::SMDH::TitleLanguage::English;
// Get the title from SMDH in UTF-16 format
std::u16string title{reinterpret_cast<char16_t*>(
smdh->titles[static_cast<std::size_t>(language)].long_title.data())};
std::u16string title{
reinterpret_cast<char16_t*>(smdh->titles[static_cast<size_t>(language)].long_title.data())};
return ToJString(env, Common::UTF16ToUTF8(title).data());
}
@ -93,8 +93,8 @@ jstring Java_org_citra_citra_1emu_model_GameInfo_getCompany(JNIEnv* env, jobject
// Get the Publisher's name from SMDH in UTF-16 format
char16_t* publisher;
publisher = reinterpret_cast<char16_t*>(
smdh->titles[static_cast<std::size_t>(language)].publisher.data());
publisher =
reinterpret_cast<char16_t*>(smdh->titles[static_cast<size_t>(language)].publisher.data());
return ToJString(env, Common::UTF16ToUTF8(publisher).data());
}

View File

@ -35,6 +35,8 @@ static jclass s_cheat_class;
static jfieldID s_cheat_pointer;
static jmethodID s_cheat_constructor;
static jfieldID s_cheat_engine_pointer;
static jfieldID s_game_info_pointer;
static jclass s_disk_cache_progress_class;
@ -114,6 +116,10 @@ jmethodID GetCheatConstructor() {
return s_cheat_constructor;
}
jfieldID GetCheatEnginePointer() {
return s_cheat_engine_pointer;
}
jfieldID GetGameInfoPointer() {
return s_game_info_pointer;
}
@ -189,6 +195,12 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
s_cheat_constructor = env->GetMethodID(cheat_class, "<init>", "(J)V");
env->DeleteLocalRef(cheat_class);
// Initialize CheatEngine
const jclass cheat_engine_class =
env->FindClass("org/citra/citra_emu/features/cheats/model/CheatEngine");
s_cheat_engine_pointer = env->GetFieldID(cheat_engine_class, "mPointer", "J");
env->DeleteLocalRef(cheat_engine_class);
// Initialize GameInfo
const jclass game_info_class = env->FindClass("org/citra/citra_emu/model/GameInfo");
s_game_info_pointer = env->GetFieldID(game_info_class, "pointer", "J");

View File

@ -35,6 +35,8 @@ jclass GetCheatClass();
jfieldID GetCheatPointer();
jmethodID GetCheatConstructor();
jfieldID GetCheatEnginePointer();
jfieldID GetGameInfoPointer();
jclass GetDiskCacheProgressClass();

View File

@ -661,8 +661,8 @@ void Java_org_citra_citra_1emu_NativeLibrary_removeAmiibo([[maybe_unused]] JNIEn
JNIEXPORT jobject JNICALL Java_org_citra_citra_1emu_utils_CiaInstallWorker_installCIA(
JNIEnv* env, jobject jobj, jstring jpath) {
std::string path = GetJString(env, jpath);
Service::AM::InstallStatus res = Service::AM::InstallCIA(
path, [env, jobj](std::size_t total_bytes_read, std::size_t file_size) {
Service::AM::InstallStatus res =
Service::AM::InstallCIA(path, [env, jobj](size_t total_bytes_read, size_t file_size) {
env->CallVoidMethod(jobj, IDCache::GetCiaInstallHelperSetProgress(),
static_cast<jint>(file_size), static_cast<jint>(total_bytes_read));
});

View File

@ -4,11 +4,11 @@ add_library(audio_core STATIC
codec.h
dsp_interface.cpp
dsp_interface.h
hle/aac_decoder.cpp
hle/aac_decoder.h
hle/common.h
hle/decoder.cpp
hle/decoder.h
hle/faad2_decoder.cpp
hle/faad2_decoder.h
hle/filter.cpp
hle/filter.h
hle/hle.cpp

View File

@ -1,26 +0,0 @@
// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "audio_core/hle/decoder.h"
namespace AudioCore::HLE {
using NeAACDecHandle = void*;
class AACDecoder final : public DecoderBase {
public:
explicit AACDecoder(Memory::MemorySystem& memory);
~AACDecoder() override;
BinaryMessage ProcessRequest(const BinaryMessage& request) override;
private:
BinaryMessage Decode(const BinaryMessage& request);
Memory::MemorySystem& memory;
NeAACDecHandle decoder = nullptr;
};
} // namespace AudioCore::HLE

View File

@ -32,4 +32,34 @@ DecoderSampleRate GetSampleRateEnum(u32 sample_rate) {
}
}
DecoderBase::~DecoderBase(){};
NullDecoder::NullDecoder() = default;
NullDecoder::~NullDecoder() = default;
std::optional<BinaryMessage> NullDecoder::ProcessRequest(const BinaryMessage& request) {
BinaryMessage response{};
switch (request.header.cmd) {
case DecoderCommand::Init:
case DecoderCommand::Shutdown:
case DecoderCommand::SaveState:
case DecoderCommand::LoadState:
response = request;
response.header.result = ResultStatus::Success;
return response;
case DecoderCommand::EncodeDecode:
response.header.codec = request.header.codec;
response.header.cmd = request.header.cmd;
response.header.result = ResultStatus::Success;
response.decode_aac_response.num_channels = 2; // Just assume stereo here
response.decode_aac_response.size = request.decode_aac_request.size;
response.decode_aac_response.num_samples = 1024; // Just assume 1024 here
return response;
default:
LOG_ERROR(Audio_DSP, "Got unknown binary request: {}",
static_cast<u16>(request.header.cmd));
return std::nullopt;
}
};
} // namespace AudioCore::HLE

View File

@ -135,8 +135,21 @@ enum_le<DecoderSampleRate> GetSampleRateEnum(u32 sample_rate);
class DecoderBase {
public:
virtual ~DecoderBase() = default;
virtual BinaryMessage ProcessRequest(const BinaryMessage& request) = 0;
virtual ~DecoderBase();
virtual std::optional<BinaryMessage> ProcessRequest(const BinaryMessage& request) = 0;
/// Return true if this Decoder can be loaded. Return false if the system cannot create the
/// decoder
virtual bool IsValid() const = 0;
};
class NullDecoder final : public DecoderBase {
public:
NullDecoder();
~NullDecoder() override;
std::optional<BinaryMessage> ProcessRequest(const BinaryMessage& request) override;
bool IsValid() const override {
return true;
}
};
} // namespace AudioCore::HLE

View File

@ -3,11 +3,30 @@
// Refer to the license.txt file included.
#include <neaacdec.h>
#include "audio_core/hle/aac_decoder.h"
#include "audio_core/hle/faad2_decoder.h"
namespace AudioCore::HLE {
AACDecoder::AACDecoder(Memory::MemorySystem& memory) : memory(memory) {
class FAAD2Decoder::Impl {
public:
explicit Impl(Memory::MemorySystem& memory);
~Impl();
std::optional<BinaryMessage> ProcessRequest(const BinaryMessage& request);
bool IsValid() const {
return decoder != nullptr;
}
private:
std::optional<BinaryMessage> Initalize(const BinaryMessage& request);
std::optional<BinaryMessage> Decode(const BinaryMessage& request);
Memory::MemorySystem& memory;
NeAACDecHandle decoder = nullptr;
};
FAAD2Decoder::Impl::Impl(Memory::MemorySystem& memory) : memory(memory) {
decoder = NeAACDecOpen();
if (decoder == nullptr) {
LOG_CRITICAL(Audio_DSP, "Could not open FAAD2 decoder.");
@ -27,7 +46,7 @@ AACDecoder::AACDecoder(Memory::MemorySystem& memory) : memory(memory) {
LOG_INFO(Audio_DSP, "Created FAAD2 AAC decoder.");
}
AACDecoder::~AACDecoder() {
FAAD2Decoder::Impl::~Impl() {
if (decoder) {
NeAACDecClose(decoder);
decoder = nullptr;
@ -36,23 +55,16 @@ AACDecoder::~AACDecoder() {
}
}
BinaryMessage AACDecoder::ProcessRequest(const BinaryMessage& request) {
std::optional<BinaryMessage> FAAD2Decoder::Impl::ProcessRequest(const BinaryMessage& request) {
if (request.header.codec != DecoderCodec::DecodeAAC) {
LOG_ERROR(Audio_DSP, "AAC decoder received unsupported codec: {}",
LOG_ERROR(Audio_DSP, "FAAD2 AAC Decoder cannot handle such codec: {}",
static_cast<u16>(request.header.codec));
return {
.header =
{
.result = ResultStatus::Error,
},
};
return {};
}
switch (request.header.cmd) {
case DecoderCommand::Init: {
BinaryMessage response = request;
response.header.result = ResultStatus::Success;
return response;
return Initalize(request);
}
case DecoderCommand::EncodeDecode: {
return Decode(request);
@ -60,25 +72,26 @@ BinaryMessage AACDecoder::ProcessRequest(const BinaryMessage& request) {
case DecoderCommand::Shutdown:
case DecoderCommand::SaveState:
case DecoderCommand::LoadState: {
LOG_WARNING(Audio_DSP, "Got unimplemented AAC binary request: {}",
LOG_WARNING(Audio_DSP, "Got unimplemented binary request: {}",
static_cast<u16>(request.header.cmd));
BinaryMessage response = request;
response.header.result = ResultStatus::Success;
return response;
}
default:
LOG_ERROR(Audio_DSP, "Got unknown AAC binary request: {}",
LOG_ERROR(Audio_DSP, "Got unknown binary request: {}",
static_cast<u16>(request.header.cmd));
return {
.header =
{
.result = ResultStatus::Error,
},
};
return {};
}
}
BinaryMessage AACDecoder::Decode(const BinaryMessage& request) {
std::optional<BinaryMessage> FAAD2Decoder::Impl::Initalize(const BinaryMessage& request) {
BinaryMessage response = request;
response.header.result = ResultStatus::Success;
return response;
}
std::optional<BinaryMessage> FAAD2Decoder::Impl::Decode(const BinaryMessage& request) {
BinaryMessage response{};
response.header.codec = request.header.codec;
response.header.cmd = request.header.cmd;
@ -88,10 +101,6 @@ BinaryMessage AACDecoder::Decode(const BinaryMessage& request) {
response.decode_aac_response.num_channels = 2;
response.decode_aac_response.num_samples = 1024;
if (decoder == nullptr) {
return response;
}
if (request.decode_aac_request.src_addr < Memory::FCRAM_PADDR ||
request.decode_aac_request.src_addr + request.decode_aac_request.size >
Memory::FCRAM_PADDR + Memory::FCRAM_SIZE) {
@ -162,4 +171,16 @@ BinaryMessage AACDecoder::Decode(const BinaryMessage& request) {
return response;
}
FAAD2Decoder::FAAD2Decoder(Memory::MemorySystem& memory) : impl(std::make_unique<Impl>(memory)) {}
FAAD2Decoder::~FAAD2Decoder() = default;
std::optional<BinaryMessage> FAAD2Decoder::ProcessRequest(const BinaryMessage& request) {
return impl->ProcessRequest(request);
}
bool FAAD2Decoder::IsValid() const {
return impl->IsValid();
}
} // namespace AudioCore::HLE

View File

@ -0,0 +1,23 @@
// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "audio_core/hle/decoder.h"
namespace AudioCore::HLE {
class FAAD2Decoder final : public DecoderBase {
public:
explicit FAAD2Decoder(Memory::MemorySystem& memory);
~FAAD2Decoder() override;
std::optional<BinaryMessage> ProcessRequest(const BinaryMessage& request) override;
bool IsValid() const override;
private:
class Impl;
std::unique_ptr<Impl> impl;
};
} // namespace AudioCore::HLE

View File

@ -8,9 +8,9 @@
#include <boost/serialization/vector.hpp>
#include <boost/serialization/weak_ptr.hpp>
#include "audio_core/audio_types.h"
#include "audio_core/hle/aac_decoder.h"
#include "audio_core/hle/common.h"
#include "audio_core/hle/decoder.h"
#include "audio_core/hle/faad2_decoder.h"
#include "audio_core/hle/hle.h"
#include "audio_core/hle/mixers.h"
#include "audio_core/hle/shared_memory.h"
@ -24,10 +24,16 @@
#include "core/core.h"
#include "core/core_timing.h"
SERIALIZE_EXPORT_IMPL(AudioCore::DspHle)
using InterruptType = Service::DSP::InterruptType;
namespace AudioCore {
DspHle::DspHle()
: DspHle(Core::System::GetInstance(), Core::System::GetInstance().Memory(),
Core::System::GetInstance().CoreTiming()) {}
DspHle::DspHle(Core::System& system) : DspHle(system, system.Memory(), system.CoreTiming()) {}
template <class Archive>
@ -92,7 +98,7 @@ private:
Core::Timing& core_timing;
Core::TimingEventType* tick_event{};
std::unique_ptr<HLE::DecoderBase> aac_decoder{};
std::unique_ptr<HLE::DecoderBase> decoder{};
std::function<void(Service::DSP::InterruptType type, DspPipe pipe)> interrupt_handler{};
@ -108,6 +114,13 @@ private:
friend class boost::serialization::access;
};
static std::vector<std::function<std::unique_ptr<HLE::DecoderBase>(Memory::MemorySystem&)>>
decoder_backends = {
[](Memory::MemorySystem& memory) -> std::unique_ptr<HLE::DecoderBase> {
return std::make_unique<HLE::FAAD2Decoder>(memory);
},
};
DspHle::Impl::Impl(DspHle& parent_, Memory::MemorySystem& memory, Core::Timing& timing)
: parent(parent_), core_timing(timing) {
dsp_memory.raw_memory.fill(0);
@ -116,7 +129,19 @@ DspHle::Impl::Impl(DspHle& parent_, Memory::MemorySystem& memory, Core::Timing&
source.SetMemory(memory);
}
aac_decoder = std::make_unique<HLE::AACDecoder>(memory);
for (auto& factory : decoder_backends) {
decoder = factory(memory);
if (decoder && decoder->IsValid()) {
break;
}
}
if (!decoder || !decoder->IsValid()) {
LOG_WARNING(Audio_DSP,
"Unable to load any decoders, this could cause missing audio in some games");
decoder = std::make_unique<HLE::NullDecoder>();
}
tick_event =
core_timing.RegisterEvent("AudioCore::DspHle::tick_event", [this](u64, s64 cycles_late) {
this->AudioTickCallback(cycles_late);
@ -266,9 +291,12 @@ void DspHle::Impl::PipeWrite(DspPipe pipe_number, std::span<const u8> buffer) {
UNIMPLEMENTED();
return;
}
const HLE::BinaryMessage response = aac_decoder->ProcessRequest(request);
pipe_data[static_cast<u32>(pipe_number)].resize(sizeof(response));
std::memcpy(pipe_data[static_cast<u32>(pipe_number)].data(), &response, sizeof(response));
std::optional<HLE::BinaryMessage> response = decoder->ProcessRequest(request);
if (response) {
const HLE::BinaryMessage& value = *response;
pipe_data[static_cast<u32>(pipe_number)].resize(sizeof(value));
std::memcpy(pipe_data[static_cast<u32>(pipe_number)].data(), &value, sizeof(value));
}
interrupt_handler(InterruptType::Pipe, DspPipe::Binary);
break;

View File

@ -50,9 +50,13 @@ private:
friend struct Impl;
std::unique_ptr<Impl> impl;
DspHle();
template <class Archive>
void serialize(Archive& ar, const unsigned int);
friend class boost::serialization::access;
};
} // namespace AudioCore
BOOST_CLASS_EXPORT_KEY(AudioCore::DspHle)

View File

View File

@ -24,8 +24,8 @@ namespace {
constexpr std::array input_details = {
#ifdef HAVE_CUBEB
InputDetails{InputType::Cubeb, "Real Device (Cubeb)", true,
[](Core::System& system, std::string_view device_id) -> std::unique_ptr<Input> {
if (!system.HasMicPermission()) {
[](std::string_view device_id) -> std::unique_ptr<Input> {
if (!Core::System::GetInstance().HasMicPermission()) {
LOG_WARNING(Audio,
"Microphone permission denied, falling back to null input.");
return std::make_unique<NullInput>();
@ -36,8 +36,8 @@ constexpr std::array input_details = {
#endif
#ifdef HAVE_OPENAL
InputDetails{InputType::OpenAL, "Real Device (OpenAL)", true,
[](Core::System& system, std::string_view device_id) -> std::unique_ptr<Input> {
if (!system.HasMicPermission()) {
[](std::string_view device_id) -> std::unique_ptr<Input> {
if (!Core::System::GetInstance().HasMicPermission()) {
LOG_WARNING(Audio,
"Microphone permission denied, falling back to null input.");
return std::make_unique<NullInput>();
@ -47,12 +47,12 @@ constexpr std::array input_details = {
&ListOpenALInputDevices},
#endif
InputDetails{InputType::Static, "Static Noise", false,
[](Core::System& system, std::string_view device_id) -> std::unique_ptr<Input> {
[](std::string_view device_id) -> std::unique_ptr<Input> {
return std::make_unique<StaticInput>();
},
[] { return std::vector<std::string>{"Static Noise"}; }},
InputDetails{InputType::Null, "None", false,
[](Core::System& system, std::string_view device_id) -> std::unique_ptr<Input> {
[](std::string_view device_id) -> std::unique_ptr<Input> {
return std::make_unique<NullInput>();
},
[] { return std::vector<std::string>{"None"}; }},

View File

@ -10,10 +10,6 @@
#include <vector>
#include "common/common_types.h"
namespace Core {
class System;
}
namespace AudioCore {
class Input;
@ -27,7 +23,7 @@ enum class InputType : u32 {
};
struct InputDetails {
using FactoryFn = std::unique_ptr<Input> (*)(Core::System& system, std::string_view device_id);
using FactoryFn = std::unique_ptr<Input> (*)(std::string_view device_id);
using ListDevicesFn = std::vector<std::string> (*)();
/// Type of this input.

View File

@ -148,7 +148,7 @@ ALsizei OpenALSink::Impl::Callback(void* impl_, void* buffer, ALsizei buffer_siz
return 0;
}
const std::size_t num_frames = buffer_size_in_bytes / (2 * sizeof(s16));
const size_t num_frames = buffer_size_in_bytes / (2 * sizeof(s16));
impl->cb(reinterpret_cast<s16*>(buffer), num_frames);
return buffer_size_in_bytes;

View File

@ -83,7 +83,7 @@ void SDL2Sink::Impl::Callback(void* impl_, u8* buffer, int buffer_size_in_bytes)
if (!impl || !impl->cb)
return;
const std::size_t num_frames = buffer_size_in_bytes / (2 * sizeof(s16));
const size_t num_frames = buffer_size_in_bytes / (2 * sizeof(s16));
impl->cb(reinterpret_cast<s16*>(buffer), num_frames);
}

View File

@ -146,7 +146,6 @@ void Config::ReadValues() {
ReadSetting("Renderer", Settings::values.frame_limit);
ReadSetting("Renderer", Settings::values.use_vsync_new);
ReadSetting("Renderer", Settings::values.texture_filter);
ReadSetting("Renderer", Settings::values.texture_sampling);
ReadSetting("Renderer", Settings::values.mono_render_option);
ReadSetting("Renderer", Settings::values.render_3d);
@ -225,8 +224,6 @@ void Config::ReadValues() {
std::chrono::system_clock::from_time_t(std::mktime(&t)).time_since_epoch())
.count();
}
ReadSetting("System", Settings::values.init_ticks_type);
ReadSetting("System", Settings::values.init_ticks_override);
ReadSetting("System", Settings::values.plugin_loader_enabled);
ReadSetting("System", Settings::values.allow_plugin_loader);
@ -236,7 +233,7 @@ void Config::ReadValues() {
std::string offset_string =
sdl2_config->GetString("System", "init_time_offset", default_init_time_offset);
std::size_t sep_index = offset_string.find(' ');
size_t sep_index = offset_string.find(' ');
if (sep_index == std::string::npos) {
LOG_ERROR(Config, "Failed to parse init_time_offset. Using 0 00:00:00");

View File

@ -307,14 +307,6 @@ init_clock =
# Note: 3DS can only handle times later then Jan 1 2000
init_time =
# The system ticks count to use when citra starts
# 0: Random (default), 1: Fixed
init_ticks_type =
# Tick count to use when init_ticks_type is set to Fixed.
# Defaults to 0.
init_ticks_override =
[Camera]
# Which camera engine to use for the right outer camera
# blank (default): a dummy camera that always returns black image

View File

@ -54,11 +54,8 @@ const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> Config:
// This must be in alphabetical order according to action name as it must have the same order as
// UISetting::values.shortcuts, which is alphabetically ordered.
// clang-format off
const std::array<UISettings::Shortcut, 30> Config::default_hotkeys {{
const std::array<UISettings::Shortcut, 28> Config::default_hotkeys {{
{QStringLiteral("Advance Frame"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::ApplicationShortcut}},
{QStringLiteral("Audio Mute/Unmute"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+M"), Qt::WindowShortcut}},
{QStringLiteral("Audio Volume Down"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::WindowShortcut}},
{QStringLiteral("Audio Volume Up"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::WindowShortcut}},
{QStringLiteral("Capture Screenshot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+P"), Qt::WidgetWithChildrenShortcut}},
{QStringLiteral("Continue/Pause Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F4"), Qt::WindowShortcut}},
{QStringLiteral("Decrease 3D Factor"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+-"), Qt::ApplicationShortcut}},
@ -71,6 +68,7 @@ const std::array<UISettings::Shortcut, 30> Config::default_hotkeys {{
{QStringLiteral("Load Amiibo"), QStringLiteral("Main Window"), {QStringLiteral("F2"), Qt::WidgetWithChildrenShortcut}},
{QStringLiteral("Load File"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+O"), Qt::WidgetWithChildrenShortcut}},
{QStringLiteral("Load from Newest Slot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+V"), Qt::WindowShortcut}},
{QStringLiteral("Mute Audio"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+M"), Qt::WindowShortcut}},
{QStringLiteral("Remove Amiibo"), QStringLiteral("Main Window"), {QStringLiteral("F3"), Qt::ApplicationShortcut}},
{QStringLiteral("Restart Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F6"), Qt::WindowShortcut}},
{QStringLiteral("Rotate Screens Upright"), QStringLiteral("Main Window"), {QStringLiteral("F8"), Qt::WindowShortcut}},
@ -647,7 +645,6 @@ void Config::ReadRendererValues() {
ReadGlobalSetting(Settings::values.bg_blue);
ReadGlobalSetting(Settings::values.texture_filter);
ReadGlobalSetting(Settings::values.texture_sampling);
if (global) {
ReadBasicSetting(Settings::values.use_shader_jit);
@ -687,8 +684,6 @@ void Config::ReadSystemValues() {
ReadBasicSetting(Settings::values.init_clock);
ReadBasicSetting(Settings::values.init_time);
ReadBasicSetting(Settings::values.init_time_offset);
ReadBasicSetting(Settings::values.init_ticks_type);
ReadBasicSetting(Settings::values.init_ticks_override);
ReadBasicSetting(Settings::values.plugin_loader_enabled);
ReadBasicSetting(Settings::values.allow_plugin_loader);
}
@ -768,7 +763,6 @@ void Config::ReadUIValues() {
ReadBasicSetting(UISettings::values.callout_flags);
ReadBasicSetting(UISettings::values.show_console);
ReadBasicSetting(UISettings::values.pause_when_in_background);
ReadBasicSetting(UISettings::values.mute_when_in_background);
ReadBasicSetting(UISettings::values.hide_mouse);
}
@ -1136,7 +1130,6 @@ void Config::SaveRendererValues() {
WriteGlobalSetting(Settings::values.bg_blue);
WriteGlobalSetting(Settings::values.texture_filter);
WriteGlobalSetting(Settings::values.texture_sampling);
if (global) {
WriteSetting(QStringLiteral("use_shader_jit"), Settings::values.use_shader_jit.GetValue(),
@ -1176,8 +1169,6 @@ void Config::SaveSystemValues() {
WriteBasicSetting(Settings::values.init_clock);
WriteBasicSetting(Settings::values.init_time);
WriteBasicSetting(Settings::values.init_time_offset);
WriteBasicSetting(Settings::values.init_ticks_type);
WriteBasicSetting(Settings::values.init_ticks_override);
WriteBasicSetting(Settings::values.plugin_loader_enabled);
WriteBasicSetting(Settings::values.allow_plugin_loader);
}
@ -1240,7 +1231,6 @@ void Config::SaveUIValues() {
WriteBasicSetting(UISettings::values.callout_flags);
WriteBasicSetting(UISettings::values.show_console);
WriteBasicSetting(UISettings::values.pause_when_in_background);
WriteBasicSetting(UISettings::values.mute_when_in_background);
WriteBasicSetting(UISettings::values.hide_mouse);
}

View File

@ -26,7 +26,7 @@ public:
static const std::array<int, Settings::NativeButton::NumButtons> default_buttons;
static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> default_analogs;
static const std::array<UISettings::Shortcut, 30> default_hotkeys;
static const std::array<UISettings::Shortcut, 28> default_hotkeys;
private:
void Initialize(const std::string& config_name);

View File

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

View File

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

View File

@ -74,8 +74,6 @@ void ConfigureGeneral::SetConfiguration() {
ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing.GetValue());
ui->toggle_background_pause->setChecked(
UISettings::values.pause_when_in_background.GetValue());
ui->toggle_background_mute->setChecked(
UISettings::values.mute_when_in_background.GetValue());
ui->toggle_hide_mouse->setChecked(UISettings::values.hide_mouse.GetValue());
ui->toggle_update_check->setChecked(
@ -176,7 +174,6 @@ void ConfigureGeneral::ApplyConfiguration() {
if (Settings::IsConfiguringGlobal()) {
UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked();
UISettings::values.pause_when_in_background = ui->toggle_background_pause->isChecked();
UISettings::values.mute_when_in_background = ui->toggle_background_mute->isChecked();
UISettings::values.hide_mouse = ui->toggle_hide_mouse->isChecked();
UISettings::values.check_for_update_on_start = ui->toggle_update_check->isChecked();

View File

@ -36,13 +36,6 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="toggle_background_mute">
<property name="text">
<string>Mute audio when in background</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="toggle_hide_mouse">
<property name="text">

View File

@ -38,7 +38,7 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const QString
graphics_tab = std::make_unique<ConfigureGraphics>(physical_devices, is_powered_on, this);
system_tab = std::make_unique<ConfigureSystem>(system, this);
debug_tab = std::make_unique<ConfigureDebug>(is_powered_on, this);
cheat_tab = std::make_unique<ConfigureCheats>(system.CheatEngine(), title_id, this);
cheat_tab = std::make_unique<ConfigureCheats>(system, title_id, this);
ui->setupUi(this);

View File

@ -230,8 +230,6 @@ ConfigureSystem::ConfigureSystem(Core::System& system_, QWidget* parent)
&ConfigureSystem::UpdateBirthdayComboBox);
connect(ui->combo_init_clock, qOverload<int>(&QComboBox::currentIndexChanged), this,
&ConfigureSystem::UpdateInitTime);
connect(ui->combo_init_ticks_type, qOverload<int>(&QComboBox::currentIndexChanged), this,
&ConfigureSystem::UpdateInitTicks);
connect(ui->button_regenerate_console_id, &QPushButton::clicked, this,
&ConfigureSystem::RefreshConsoleID);
connect(ui->button_start_download, &QPushButton::clicked, this,
@ -295,11 +293,6 @@ void ConfigureSystem::SetConfiguration() {
QTime time = QTime::fromMSecsSinceStartOfDay(static_cast<int>(time_offset * 1000));
ui->edit_init_time_offset_time->setTime(time);
ui->combo_init_ticks_type->setCurrentIndex(
static_cast<u8>(Settings::values.init_ticks_type.GetValue()));
ui->edit_init_ticks_value->setText(
QString::number(Settings::values.init_ticks_override.GetValue()));
cfg = Service::CFG::GetModule(system);
ReadSystemSettings();
@ -420,11 +413,6 @@ void ConfigureSystem::ApplyConfiguration() {
static_cast<Settings::InitClock>(ui->combo_init_clock->currentIndex());
Settings::values.init_time = ui->edit_init_time->dateTime().toSecsSinceEpoch();
Settings::values.init_ticks_type =
static_cast<Settings::InitTicks>(ui->combo_init_ticks_type->currentIndex());
Settings::values.init_ticks_override =
static_cast<s64>(ui->edit_init_ticks_value->text().toLongLong());
s64 time_offset_time = ui->edit_init_time_offset_time->time().msecsSinceStartOfDay() / 1000;
s64 time_offset_days = ui->edit_init_time_offset_days->value() * 86400;
@ -474,7 +462,6 @@ void ConfigureSystem::ConfigureTime() {
SetConfiguration();
UpdateInitTime(ui->combo_init_clock->currentIndex());
UpdateInitTicks(ui->combo_init_ticks_type->currentIndex());
}
void ConfigureSystem::UpdateInitTime(int init_clock) {
@ -490,15 +477,6 @@ void ConfigureSystem::UpdateInitTime(int init_clock) {
ui->edit_init_time_offset_time->setVisible(!is_fixed_time && is_global);
}
void ConfigureSystem::UpdateInitTicks(int init_ticks_type) {
const bool is_global = Settings::IsConfiguringGlobal();
const bool is_fixed =
static_cast<Settings::InitTicks>(init_ticks_type) == Settings::InitTicks::Fixed;
ui->label_init_ticks_value->setVisible(is_fixed && is_global);
ui->edit_init_ticks_value->setVisible(is_fixed && is_global);
}
void ConfigureSystem::RefreshConsoleID() {
QMessageBox::StandardButton reply;
QString warning_text = tr("This will replace your current virtual 3DS with a new one. "
@ -534,8 +512,6 @@ void ConfigureSystem::SetupPerGameUI() {
ui->label_birthday->setVisible(false);
ui->label_init_clock->setVisible(false);
ui->label_init_time->setVisible(false);
ui->label_init_ticks_type->setVisible(false);
ui->label_init_ticks_value->setVisible(false);
ui->label_console_id->setVisible(false);
ui->label_sound->setVisible(false);
ui->label_language->setVisible(false);
@ -546,14 +522,12 @@ void ConfigureSystem::SetupPerGameUI() {
ui->combo_birthday->setVisible(false);
ui->combo_birthmonth->setVisible(false);
ui->combo_init_clock->setVisible(false);
ui->combo_init_ticks_type->setVisible(false);
ui->combo_sound->setVisible(false);
ui->combo_language->setVisible(false);
ui->combo_country->setVisible(false);
ui->label_init_time_offset->setVisible(false);
ui->edit_init_time_offset_days->setVisible(false);
ui->edit_init_time_offset_time->setVisible(false);
ui->edit_init_ticks_value->setVisible(false);
ui->toggle_system_setup->setVisible(false);
ui->button_regenerate_console_id->setVisible(false);
// Apps can change the state of the plugin loader, so plugins load

View File

@ -43,7 +43,6 @@ private:
void UpdateBirthdayComboBox(int birthmonth_index);
void UpdateInitTime(int init_clock);
void UpdateInitTicks(int init_ticks_type);
void RefreshConsoleID();
void SetupPerGameUI();

View File

@ -304,75 +304,34 @@
</layout>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_init_ticks_type">
<property name="text">
<string>Initial System Ticks</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QComboBox" name="combo_init_ticks_type">
<item>
<property name="text">
<string>Random</string>
</property>
</item>
<item>
<property name="text">
<string>Fixed</string>
</property>
</item>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label_init_ticks_value">
<property name="text">
<string>Initial System Ticks Override</string>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QLineEdit" name="edit_init_ticks_value">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maxLength">
<number>20</number>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QLabel" name="label_play_coins">
<property name="text">
<string>Play Coins:</string>
</property>
</widget>
</item>
<item row="11" column="1">
<item row="9" column="1">
<widget class="QSpinBox" name="spinBox_play_coins">
<property name="maximum">
<number>300</number>
</property>
</widget>
</item>
<item row="12" column="1">
<item row="10" column="1">
<widget class="QCheckBox" name="toggle_system_setup">
<property name="text">
<string>Run System Setup when Home Menu is launched</string>
</property>
</widget>
</item>
<item row="13" column="0">
<item row="11" column="0">
<widget class="QLabel" name="label_console_id">
<property name="text">
<string>Console ID:</string>
</property>
</widget>
</item>
<item row="13" column="1">
<item row="11" column="1">
<widget class="QPushButton" name="button_regenerate_console_id">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
@ -388,35 +347,35 @@
</property>
</widget>
</item>
<item row="14" column="0">
<item row="12" column="0">
<widget class="QLabel" name="label_plugin_loader">
<property name="text">
<string>3GX Plugin Loader:</string>
</property>
</widget>
</item>
<item row="14" column="1">
<item row="12" column="1">
<widget class="QCheckBox" name="plugin_loader">
<property name="text">
<string>Enable 3GX plugin loader</string>
</property>
</widget>
</item>
<item row="15" column="1">
<item row="13" column="1">
<widget class="QCheckBox" name="allow_plugin_loader">
<property name="text">
<string>Allow games to change plugin loader state</string>
</property>
</widget>
</item>
<item row="16" column="0">
<item row="14" column="0">
<widget class="QLabel" name="label_nus_download">
<property name="text">
<string>Download System Files from Nitendo servers</string>
</property>
</widget>
</item>
<item row="16" column="1">
<item row="14" column="1">
<widget class="QWidget" name="body_nus_download">
<layout class="QHBoxLayout" name="horizontalLayout_nus_download">
<item>

View File

@ -229,7 +229,6 @@ GMainWindow::GMainWindow(Core::System& system_)
SetDefaultUIGeometry();
RestoreUIState();
ConnectAppEvents();
ConnectMenuEvents();
ConnectWidgetEvents();
@ -420,38 +419,6 @@ void GMainWindow::InitializeWidgets() {
statusBar()->insertPermanentWidget(0, graphics_api_button);
volume_popup = new QWidget(this);
volume_popup->setWindowFlags(Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint | Qt::Popup);
volume_popup->setLayout(new QVBoxLayout());
volume_popup->setMinimumWidth(200);
volume_slider = new QSlider(Qt::Horizontal);
volume_slider->setObjectName(QStringLiteral("volume_slider"));
volume_slider->setMaximum(100);
volume_slider->setPageStep(5);
connect(volume_slider, &QSlider::valueChanged, this, [this](int percentage) {
Settings::values.audio_muted = false;
const auto value = static_cast<float>(percentage) / volume_slider->maximum();
Settings::values.volume.SetValue(value);
UpdateVolumeUI();
});
volume_popup->layout()->addWidget(volume_slider);
volume_button = new QPushButton();
volume_button->setObjectName(QStringLiteral("TogglableStatusBarButton"));
volume_button->setFocusPolicy(Qt::NoFocus);
volume_button->setCheckable(true);
UpdateVolumeUI();
connect(volume_button, &QPushButton::clicked, this, [&] {
UpdateVolumeUI();
volume_popup->setVisible(!volume_popup->isVisible());
QRect rect = volume_button->geometry();
QPoint bottomLeft = statusBar()->mapToGlobal(rect.topLeft());
bottomLeft.setY(bottomLeft.y() - volume_popup->geometry().height());
volume_popup->setGeometry(QRect(bottomLeft, QSize(rect.width(), rect.height())));
});
statusBar()->insertPermanentWidget(1, volume_button);
statusBar()->addPermanentWidget(multiplayer_state->GetStatusText());
statusBar()->addPermanentWidget(multiplayer_state->GetStatusIcon());
@ -704,10 +671,8 @@ void GMainWindow::InitializeHotkeys() {
}
UpdateStatusBar();
});
connect_shortcut(QStringLiteral("Audio Mute/Unmute"), &GMainWindow::OnMute);
connect_shortcut(QStringLiteral("Audio Volume Down"), &GMainWindow::OnDecreaseVolume);
connect_shortcut(QStringLiteral("Audio Volume Up"), &GMainWindow::OnIncreaseVolume);
connect_shortcut(QStringLiteral("Mute Audio"),
[] { Settings::values.audio_muted = !Settings::values.audio_muted; });
// We use "static" here in order to avoid capturing by lambda due to a MSVC bug, which makes the
// variable hold a garbage value after this function exits
@ -778,50 +743,23 @@ void GMainWindow::RestoreUIState() {
}
void GMainWindow::OnAppFocusStateChanged(Qt::ApplicationState state) {
if (!UISettings::values.pause_when_in_background) {
return;
}
if (state != Qt::ApplicationHidden && state != Qt::ApplicationInactive &&
state != Qt::ApplicationActive) {
LOG_DEBUG(Frontend, "ApplicationState unusual flag: {} ", state);
}
if (!emulation_running) {
return;
}
if (UISettings::values.pause_when_in_background) {
if (emu_thread->IsRunning() &&
if (ui->action_Pause->isEnabled() &&
(state & (Qt::ApplicationHidden | Qt::ApplicationInactive))) {
auto_paused = true;
OnPauseGame();
} else if (!emu_thread->IsRunning() && auto_paused && state == Qt::ApplicationActive) {
} else if (emulation_running && !emu_thread->IsRunning() && auto_paused &&
state == Qt::ApplicationActive) {
auto_paused = false;
OnStartGame();
}
}
if (UISettings::values.mute_when_in_background) {
if (!Settings::values.audio_muted &&
(state & (Qt::ApplicationHidden | Qt::ApplicationInactive))) {
Settings::values.audio_muted = true;
auto_muted = true;
} else if (auto_muted && state == Qt::ApplicationActive) {
Settings::values.audio_muted = false;
auto_muted = false;
}
UpdateVolumeUI();
}
}
bool GApplicationEventFilter::eventFilter(QObject* object, QEvent* event) {
if (event->type() == QEvent::FileOpen) {
emit FileOpen(static_cast<QFileOpenEvent*>(event));
return true;
}
return false;
}
void GMainWindow::ConnectAppEvents() {
const auto filter = new GApplicationEventFilter();
QGuiApplication::instance()->installEventFilter(filter);
connect(filter, &GApplicationEventFilter::FileOpen, this, &GMainWindow::OnFileOpen);
}
void GMainWindow::ConnectWidgetEvents() {
connect(game_list, &GameList::GameChosen, this, &GMainWindow::OnGameListLoadFile);
@ -1920,7 +1858,7 @@ void GMainWindow::OnStartGame() {
#endif
UpdateSaveStates();
UpdateStatusButtons();
UpdateAPIIndicator();
}
void GMainWindow::OnRestartGame() {
@ -1957,7 +1895,7 @@ void GMainWindow::OnStopGame() {
ShutdownGame();
graphics_api_button->setEnabled(true);
Settings::RestoreGlobalState(false);
UpdateStatusButtons();
UpdateAPIIndicator();
}
void GMainWindow::OnLoadComplete() {
@ -2198,7 +2136,7 @@ void GMainWindow::OnConfigure() {
}
UpdateSecondaryWindowVisibility();
UpdateBootHomeMenuState();
UpdateStatusButtons();
UpdateAPIIndicator();
} else {
Settings::values.input_profiles = old_input_profiles;
Settings::values.touch_from_button_maps = old_touch_from_button_maps;
@ -2628,57 +2566,6 @@ void GMainWindow::ShowMouseCursor() {
}
}
void GMainWindow::OnMute() {
Settings::values.audio_muted = !Settings::values.audio_muted;
UpdateVolumeUI();
}
void GMainWindow::OnDecreaseVolume() {
Settings::values.audio_muted = false;
const auto current_volume =
static_cast<s32>(Settings::values.volume.GetValue() * volume_slider->maximum());
int step = 5;
if (current_volume <= 30) {
step = 2;
}
if (current_volume <= 6) {
step = 1;
}
const auto value =
static_cast<float>(std::max(current_volume - step, 0)) / volume_slider->maximum();
Settings::values.volume.SetValue(value);
UpdateVolumeUI();
}
void GMainWindow::OnIncreaseVolume() {
Settings::values.audio_muted = false;
const auto current_volume =
static_cast<s32>(Settings::values.volume.GetValue() * volume_slider->maximum());
int step = 5;
if (current_volume < 30) {
step = 2;
}
if (current_volume < 6) {
step = 1;
}
const auto value = static_cast<float>(current_volume + step) / volume_slider->maximum();
Settings::values.volume.SetValue(value);
UpdateVolumeUI();
}
void GMainWindow::UpdateVolumeUI() {
const auto volume_value =
static_cast<int>(Settings::values.volume.GetValue() * volume_slider->maximum());
volume_slider->setValue(volume_value);
if (Settings::values.audio_muted) {
volume_button->setChecked(false);
volume_button->setText(tr("VOLUME: MUTE"));
} else {
volume_button->setChecked(true);
volume_button->setText(tr("VOLUME: %1%", "Volume percentage (e.g. 50%)").arg(volume_value));
}
}
void GMainWindow::UpdateAPIIndicator(bool update) {
static std::array graphics_apis = {QStringLiteral("SOFTWARE"), QStringLiteral("OPENGL"),
QStringLiteral("VULKAN")};
@ -2699,11 +2586,6 @@ void GMainWindow::UpdateAPIIndicator(bool update) {
graphics_api_button->setStyleSheet(style_sheet);
}
void GMainWindow::UpdateStatusButtons() {
UpdateAPIIndicator();
UpdateVolumeUI();
}
void GMainWindow::OnMouseActivity() {
ShowMouseCursor();
}
@ -2870,10 +2752,6 @@ bool GMainWindow::DropAction(QDropEvent* event) {
return true;
}
void GMainWindow::OnFileOpen(const QFileOpenEvent* event) {
BootGame(event->file());
}
void GMainWindow::dropEvent(QDropEvent* event) {
DropAction(event);
}
@ -3005,8 +2883,6 @@ void GMainWindow::OpenPerGameConfiguration(u64 title_id, const QString& file_nam
if (!is_powered_on) {
config->Save();
}
UpdateStatusButtons();
}
void GMainWindow::OnMoviePlaybackCompleted() {

View File

@ -41,7 +41,6 @@ class LoadingScreen;
class MicroProfileDialog;
class MultiplayerState;
class ProfilerWidget;
class QFileOpenEvent;
template <typename>
class QFutureWatcher;
class QLabel;
@ -97,8 +96,6 @@ public:
bool DropAction(QDropEvent* event);
void AcceptDropEvent(QDropEvent* event);
void OnFileOpen(const QFileOpenEvent* event);
void UninstallTitles(
const std::vector<std::tuple<Service::FS::MediaType, u64, QString>>& titles);
@ -140,7 +137,6 @@ private:
void SyncMenuUISettings();
void RestoreUIState();
void ConnectAppEvents();
void ConnectWidgetEvents();
void ConnectMenuEvents();
void UpdateMenuState();
@ -267,10 +263,6 @@ private slots:
void OnLanguageChanged(const QString& locale);
void OnMouseActivity();
void OnDecreaseVolume();
void OnIncreaseVolume();
void OnMute();
private:
Q_INVOKABLE void OnMoviePlaybackCompleted();
void UpdateStatusBar();
@ -283,9 +275,7 @@ private:
void HideMouseCursor();
void ShowMouseCursor();
void OpenPerGameConfiguration(u64 title_id, const QString& file_name);
void UpdateVolumeUI();
void UpdateAPIIndicator(bool update = false);
void UpdateStatusButtons();
#ifdef __unix__
void SetGamemodeEnabled(bool state);
#endif
@ -307,9 +297,6 @@ private:
QLabel* game_fps_label = nullptr;
QLabel* emu_frametime_label = nullptr;
QPushButton* graphics_api_button = nullptr;
QPushButton* volume_button = nullptr;
QWidget* volume_popup = nullptr;
QSlider* volume_slider = nullptr;
QTimer status_bar_update_timer;
bool message_label_used_for_movie = false;
@ -325,7 +312,6 @@ private:
QString game_path;
bool auto_paused = false;
bool auto_muted = false;
QTimer mouse_hide_timer;
// Movie
@ -396,15 +382,5 @@ protected:
void mouseReleaseEvent(QMouseEvent* event) override;
};
class GApplicationEventFilter : public QObject {
Q_OBJECT
signals:
void FileOpen(const QFileOpenEvent* event);
protected:
bool eventFilter(QObject* object, QEvent* event) override;
};
Q_DECLARE_METATYPE(std::size_t);
Q_DECLARE_METATYPE(Service::AM::InstallStatus);

View File

@ -25,7 +25,7 @@ bool QtImageInterface::DecodePNG(std::vector<u8>& dst, u32& width, u32& height,
image = image.convertToFormat(QImage::Format_RGBA8888);
// Write RGBA8 to vector
const std::size_t image_size = width * height * 4;
const size_t image_size = width * height * 4;
dst.resize(image_size);
std::memcpy(dst.data(), image.constBits(), image_size);

View File

@ -80,7 +80,6 @@ struct Values {
Settings::Setting<bool> save_state_warning{true, "saveStateWarning"};
Settings::Setting<bool> first_start{true, "firstStart"};
Settings::Setting<bool> pause_when_in_background{false, "pauseWhenInBackground"};
Settings::Setting<bool> mute_when_in_background{false, "muteWhenInBackground"};
Settings::Setting<bool> hide_mouse{false, "hideInactiveMouse"};
bool updater_found;

View File

@ -30,7 +30,7 @@ namespace Common {
#ifdef __APPLE__
static std::string GetCPUString() {
char buf[128];
std::size_t buf_len = sizeof(buf);
size_t buf_len = sizeof(buf);
if (sysctlbyname("machdep.cpu.brand_string", &buf, &buf_len, NULL, 0) == -1) {
return "Unknown";
}

View File

@ -63,15 +63,15 @@ struct ABIFrameInfo {
};
inline ABIFrameInfo ABI_CalculateFrameSize(std::bitset<64> regs, std::size_t frame_size) {
const std::size_t gprs_count = (regs & ABI_ALL_GPRS).count();
const std::size_t fprs_count = (regs & ABI_ALL_FPRS).count();
const size_t gprs_count = (regs & ABI_ALL_GPRS).count();
const size_t fprs_count = (regs & ABI_ALL_FPRS).count();
const std::size_t gprs_size = (gprs_count + 1) / 2 * 16;
const std::size_t fprs_size = fprs_count * 16;
const size_t gprs_size = (gprs_count + 1) / 2 * 16;
const size_t fprs_size = fprs_count * 16;
std::size_t total_size = 0;
size_t total_size = 0;
total_size += gprs_size;
const std::size_t fprs_base_subtraction = total_size;
const size_t fprs_base_subtraction = total_size;
total_size += fprs_size;
total_size += frame_size;
@ -100,11 +100,11 @@ inline void ABI_PushRegisters(oaknut::CodeGenerator& code, std::bitset<64> regs,
}
if (!gprs.empty()) {
for (std::size_t i = 0; i < gprs.size() - 1; i += 2) {
for (size_t i = 0; i < gprs.size() - 1; i += 2) {
code.STP(gprs[i], gprs[i + 1], SP, i * sizeof(u64));
}
if (gprs.size() % 2 == 1) {
const std::size_t i = gprs.size() - 1;
const size_t i = gprs.size() - 1;
code.STR(gprs[i], SP, i * sizeof(u64));
}
}
@ -121,11 +121,11 @@ inline void ABI_PushRegisters(oaknut::CodeGenerator& code, std::bitset<64> regs,
}
if (!fprs.empty()) {
for (std::size_t i = 0; i < fprs.size() - 1; i += 2) {
for (size_t i = 0; i < fprs.size() - 1; i += 2) {
code.STP(fprs[i], fprs[i + 1], SP, frame_info.fprs_offset + i * (sizeof(u64) * 2));
}
if (fprs.size() % 2 == 1) {
const std::size_t i = fprs.size() - 1;
const size_t i = fprs.size() - 1;
code.STR(fprs[i], SP, frame_info.fprs_offset + i * (sizeof(u64) * 2));
}
}
@ -159,11 +159,11 @@ inline void ABI_PopRegisters(oaknut::CodeGenerator& code, std::bitset<64> regs,
}
if (!gprs.empty()) {
for (std::size_t i = 0; i < gprs.size() - 1; i += 2) {
for (size_t i = 0; i < gprs.size() - 1; i += 2) {
code.LDP(gprs[i], gprs[i + 1], SP, i * sizeof(u64));
}
if (gprs.size() % 2 == 1) {
const std::size_t i = gprs.size() - 1;
const size_t i = gprs.size() - 1;
code.LDR(gprs[i], SP, i * sizeof(u64));
}
}
@ -180,11 +180,11 @@ inline void ABI_PopRegisters(oaknut::CodeGenerator& code, std::bitset<64> regs,
}
if (!fprs.empty()) {
for (std::size_t i = 0; i < fprs.size() - 1; i += 2) {
for (size_t i = 0; i < fprs.size() - 1; i += 2) {
code.LDP(fprs[i], fprs[i + 1], SP, frame_info.fprs_offset + i * (sizeof(u64) * 2));
}
if (fprs.size() % 2 == 1) {
const std::size_t i = fprs.size() - 1;
const size_t i = fprs.size() - 1;
code.LDR(fprs[i], SP, frame_info.fprs_offset + i * (sizeof(u64) * 2));
}
}

View File

@ -16,10 +16,10 @@
namespace Common {
namespace detail {
constexpr std::size_t DefaultCapacity = 0x1000;
constexpr size_t DefaultCapacity = 0x1000;
} // namespace detail
template <typename T, std::size_t Capacity = detail::DefaultCapacity>
template <typename T, size_t Capacity = detail::DefaultCapacity>
class SPSCQueue {
static_assert((Capacity & (Capacity - 1)) == 0, "Capacity must be a power of two.");
@ -74,7 +74,7 @@ private:
template <PushMode Mode, typename... Args>
bool Emplace(Args&&... args) {
const std::size_t write_index = m_write_index.load(std::memory_order::relaxed);
const size_t write_index = m_write_index.load(std::memory_order::relaxed);
if constexpr (Mode == PushMode::Try) {
// Check if we have free slots to write to.
@ -92,7 +92,7 @@ private:
}
// Determine the position to write to.
const std::size_t pos = write_index % Capacity;
const size_t pos = write_index % Capacity;
// Emplace into the queue.
new (std::addressof(m_data[pos])) T(std::forward<Args>(args)...);
@ -109,7 +109,7 @@ private:
template <PopMode Mode>
bool Pop(T& t, [[maybe_unused]] std::stop_token stop_token = {}) {
const std::size_t read_index = m_read_index.load(std::memory_order::relaxed);
const size_t read_index = m_read_index.load(std::memory_order::relaxed);
if constexpr (Mode == PopMode::Try) {
// Check if the queue is empty.
@ -136,7 +136,7 @@ private:
}
// Determine the position to read from.
const std::size_t pos = read_index % Capacity;
const size_t pos = read_index % Capacity;
// Pop the data off the queue, moving it.
t = std::move(m_data[pos]);
@ -162,7 +162,7 @@ private:
std::mutex consumer_cv_mutex;
};
template <typename T, std::size_t Capacity = detail::DefaultCapacity>
template <typename T, size_t Capacity = detail::DefaultCapacity>
class MPSCQueue {
public:
template <typename... Args>
@ -202,7 +202,7 @@ private:
std::mutex write_mutex;
};
template <typename T, std::size_t Capacity = detail::DefaultCapacity>
template <typename T, size_t Capacity = detail::DefaultCapacity>
class MPMCQueue {
public:
template <typename... Args>

View File

@ -40,9 +40,11 @@
#define WORDS_BIGENDIAN 1
#endif
typedef std::uint8_t uint8;
typedef std::uint32_t uint32;
typedef std::uint64_t uint64;
using namespace std;
typedef uint8_t uint8;
typedef uint32_t uint32;
typedef uint64_t uint64;
namespace Common {
@ -150,19 +152,19 @@ static uint64 HashLen17to32(const char* s, std::size_t len) {
// Return a 16-byte hash for 48 bytes. Quick and dirty.
// Callers do best to use "random-looking" values for a and b.
static std::pair<uint64, uint64> WeakHashLen32WithSeeds(uint64 w, uint64 x, uint64 y, uint64 z,
uint64 a, uint64 b) {
static pair<uint64, uint64> WeakHashLen32WithSeeds(uint64 w, uint64 x, uint64 y, uint64 z, uint64 a,
uint64 b) {
a += w;
b = Rotate(b + a + z, 21);
uint64 c = a;
a += x;
a += y;
b += Rotate(a, 44);
return std::make_pair(a + z, b + c);
return make_pair(a + z, b + c);
}
// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty.
static std::pair<uint64, uint64> WeakHashLen32WithSeeds(const char* s, uint64 a, uint64 b) {
static pair<uint64, uint64> WeakHashLen32WithSeeds(const char* s, uint64 a, uint64 b) {
return WeakHashLen32WithSeeds(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16), Fetch64(s + 24), a,
b);
}
@ -205,8 +207,8 @@ uint64 CityHash64(const char* s, std::size_t len) {
uint64 x = Fetch64(s + len - 40);
uint64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
uint64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
std::pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
std::pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
x = x * k1 + Fetch64(s);
// Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
@ -274,7 +276,7 @@ uint128 CityHash128WithSeed(const char* s, std::size_t len, uint128 seed) {
// We expect len >= 128 to be the common case. Keep 56 bytes of state:
// v, w, x, y, and z.
std::pair<uint64, uint64> v, w;
pair<uint64, uint64> v, w;
uint64 x = Uint128Low64(seed);
uint64 y = Uint128High64(seed);
uint64 z = len * k1;

View File

@ -38,7 +38,7 @@ bool DynamicLibrary::Load(std::string_view filename) {
if (!handle) {
DWORD error_message_id = GetLastError();
LPSTR message_buffer = nullptr;
std::size_t size =
size_t size =
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, error_message_id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),

View File

@ -1159,7 +1159,7 @@ std::size_t IOFile::ReadImpl(void* data, std::size_t length, std::size_t data_si
}
#ifdef _WIN32
static std::size_t pread(int fd, void* buf, std::size_t count, uint64_t offset) {
static std::size_t pread(int fd, void* buf, size_t count, uint64_t offset) {
long unsigned int read_bytes = 0;
OVERLAPPED overlapped = {0};
HANDLE file = reinterpret_cast<HANDLE>(_get_osfhandle(fd));

View File

@ -37,7 +37,7 @@ static inline u64 ComputeStructHash64(const T& data) noexcept {
* Combines the seed parameter with the provided hash, producing a new unique hash
* Implementation from: http://boost.sourceforge.net/doc/html/boost/hash_combine.html
*/
[[nodiscard]] inline u64 HashCombine(const u64 seed, const u64 hash) {
inline u64 HashCombine(const u64 seed, const u64 hash) {
return seed ^ (hash + 0x9e3779b9 + (seed << 6) + (seed >> 2));
}

View File

@ -39,7 +39,7 @@ void CondvarWait(Condvar& cv, Lock& lock, std::stop_token token, Pred&& pred) {
namespace std {
namespace polyfill {
using stop_state_callback = std::size_t;
using stop_state_callback = size_t;
class stop_state {
public:

View File

@ -28,11 +28,6 @@ enum class InitClock : u32 {
FixedTime = 1,
};
enum class InitTicks : u32 {
Random = 0,
Fixed = 1,
};
enum class LayoutOption : u32 {
Default,
SingleScreen,
@ -442,8 +437,6 @@ struct Values {
Setting<InitClock> init_clock{InitClock::SystemTime, "init_clock"};
Setting<u64> init_time{946681277ULL, "init_time"};
Setting<s64> init_time_offset{0, "init_time_offset"};
Setting<InitTicks> init_ticks_type{InitTicks::Random, "init_ticks_type"};
Setting<s64> init_ticks_override{0, "init_ticks_override"};
Setting<bool> plugin_loader_enabled{false, "plugin_loader"};
Setting<bool> allow_plugin_loader{true, "allow_plugin_loader"};

View File

@ -31,9 +31,9 @@ template <class T>
class SlotVector {
public:
~SlotVector() noexcept {
std::size_t index = 0;
size_t index = 0;
for (u64 bits : stored_bitset) {
for (std::size_t bit = 0; bits; ++bit, bits >>= 1) {
for (size_t bit = 0; bits; ++bit, bits >>= 1) {
if ((bits & 1) != 0) {
values[index + bit].object.~T();
}
@ -81,7 +81,7 @@ public:
ResetStorageBit(id.index);
}
std::size_t size() const noexcept {
size_t size() const noexcept {
return values_capacity - free_list.size();
}
@ -126,12 +126,12 @@ private:
return free_index;
}
void Reserve(std::size_t new_capacity) noexcept {
void Reserve(size_t new_capacity) noexcept {
Entry* const new_values = new Entry[new_capacity];
std::size_t index = 0;
size_t index = 0;
for (u64 bits : stored_bitset) {
for (std::size_t bit = 0; bits; ++bit, bits >>= 1) {
const std::size_t i = index + bit;
for (size_t bit = 0; bits; ++bit, bits >>= 1) {
const size_t i = index + bit;
if ((bits & 1) == 0) {
continue;
}
@ -144,7 +144,7 @@ private:
stored_bitset.resize((new_capacity + 63) / 64);
const std::size_t old_free_size = free_list.size();
const size_t old_free_size = free_list.size();
free_list.resize(old_free_size + (new_capacity - values_capacity));
std::iota(free_list.begin() + old_free_size, free_list.end(),
static_cast<u32>(values_capacity));
@ -155,7 +155,7 @@ private:
}
Entry* values = nullptr;
std::size_t values_capacity = 0;
size_t values_capacity = 0;
std::vector<u64> stored_bitset;
std::vector<u32> free_list;
@ -165,7 +165,7 @@ private:
template <>
struct std::hash<Common::SlotId> {
std::size_t operator()(const Common::SlotId& id) const noexcept {
size_t operator()(const Common::SlotId& id) const noexcept {
return std::hash<u32>{}(id.index);
}
};

View File

@ -23,23 +23,23 @@ namespace Common {
// a cache which evicts the least recently used item when it is full
// the cache elements are statically allocated.
template <class Key, class Value, std::size_t Size>
template <class Key, class Value, size_t Size>
class StaticLRUCache {
public:
using key_type = Key;
using value_type = Value;
using list_type = std::list<std::pair<Key, std::size_t>>;
using list_type = std::list<std::pair<Key, size_t>>;
using array_type = std::array<Value, Size>;
StaticLRUCache() = default;
~StaticLRUCache() = default;
std::size_t size() const {
size_t size() const {
return m_list.size();
}
constexpr std::size_t capacity() const {
constexpr size_t capacity() const {
return m_array.size();
}
@ -59,7 +59,7 @@ public:
// lookup value in the cache
auto i = find(key);
if (i == m_list.cend()) {
std::size_t next_index = size();
size_t next_index = size();
// insert item into the cache, but first check if it is full
if (next_index >= capacity()) {
// cache is full, evict the least recently used item
@ -97,10 +97,10 @@ private:
[&key](const auto& el) { return el.first == key; });
}
std::size_t evict() {
size_t evict() {
// evict item from the end of most recently used list
typename list_type::iterator i = --m_list.end();
std::size_t evicted_index = i->second;
size_t evicted_index = i->second;
m_list.erase(i);
return evicted_index;
}

View File

@ -9,7 +9,7 @@
namespace Common {
template <std::size_t N>
template <size_t N>
struct StringLiteral {
constexpr StringLiteral(const char (&str)[N]) {
std::copy_n(str, N, value);

View File

@ -101,7 +101,7 @@ void SetCurrentThreadName(const char* name) {
#elif defined(__linux__)
// Linux limits thread names to 15 characters and will outright reject any
// attempt to set a longer name with ERANGE.
std::string truncated(name, std::min(strlen(name), static_cast<std::size_t>(15)));
std::string truncated(name, std::min(strlen(name), static_cast<size_t>(15)));
if (int e = pthread_setname_np(pthread_self(), truncated.c_str())) {
errno = e;
LOG_ERROR(Common, "Failed to set thread name to '{}': {}", truncated, GetLastErrorMsg());

View File

@ -25,7 +25,7 @@ class StatefulThreadWorker {
static constexpr bool with_state = !std::is_same_v<StateType, void>;
struct DummyCallable {
int operator()(std::size_t) const noexcept {
int operator()(size_t) const noexcept {
return 0;
}
};
@ -33,13 +33,12 @@ class StatefulThreadWorker {
using Task =
std::conditional_t<with_state, UniqueFunction<void, StateType*>, UniqueFunction<void>>;
using StateMaker =
std::conditional_t<with_state, std::function<StateType(std::size_t)>, DummyCallable>;
std::conditional_t<with_state, std::function<StateType(size_t)>, DummyCallable>;
public:
explicit StatefulThreadWorker(std::size_t num_workers, std::string_view name,
StateMaker func = {})
explicit StatefulThreadWorker(size_t num_workers, std::string_view name, StateMaker func = {})
: workers_queued{num_workers}, thread_name{name} {
const auto lambda = [this, func](std::stop_token stop_token, std::size_t index) {
const auto lambda = [this, func](std::stop_token stop_token, size_t index) {
Common::SetCurrentThreadName(thread_name.data());
{
[[maybe_unused]] std::conditional_t<with_state, StateType, int> state{func(index)};
@ -70,7 +69,7 @@ public:
wait_condition.notify_all();
};
threads.reserve(num_workers);
for (std::size_t i = 0; i < num_workers; ++i) {
for (size_t i = 0; i < num_workers; ++i) {
threads.emplace_back(lambda, i);
}
}
@ -111,10 +110,10 @@ private:
std::mutex queue_mutex;
std::condition_variable_any condition;
std::condition_variable wait_condition;
std::atomic<std::size_t> work_scheduled{};
std::atomic<std::size_t> work_done{};
std::atomic<std::size_t> workers_stopped{};
std::atomic<std::size_t> workers_queued{};
std::atomic<size_t> work_scheduled{};
std::atomic<size_t> work_done{};
std::atomic<size_t> workers_stopped{};
std::atomic<size_t> workers_queued{};
std::string_view thread_name;
std::vector<std::jthread> threads;
};

View File

@ -13,8 +13,8 @@ namespace {
template <Common::StringLiteral haystack, Common::StringLiteral needle>
constexpr u32 GetMatchingBitsFromStringLiteral() {
u32 result = 0;
for (std::size_t i = 0; i < haystack.strlen; i++) {
for (std::size_t a = 0; a < needle.strlen; a++) {
for (size_t i = 0; i < haystack.strlen; i++) {
for (size_t a = 0; a < needle.strlen; a++) {
if (haystack.value[i] == needle.value[a]) {
result |= 1 << (haystack.strlen - 1 - i);
}

View File

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

View File

@ -5,9 +5,7 @@
#pragma once
#include <memory>
#include <optional>
#include <shared_mutex>
#include <span>
#include <vector>
#include "common/common_types.h"
@ -26,39 +24,22 @@ class CheatBase;
class CheatEngine {
public:
explicit CheatEngine(Core::System& system);
explicit CheatEngine(u64 title_id_, Core::System& system);
~CheatEngine();
/// Registers the cheat execution callback.
void Connect();
/// 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.
std::vector<std::shared_ptr<CheatBase>> GetCheats() const;
void AddCheat(const std::shared_ptr<CheatBase>& cheat);
void RemoveCheat(std::size_t index);
/// 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;
void UpdateCheat(std::size_t index, const std::shared_ptr<CheatBase>& new_cheat);
void SaveCheatFile() const;
private:
/// The cheat execution callback.
void LoadCheatFile();
void RunCallback(std::uintptr_t user_data, s64 cycles_late);
private:
Core::System& system;
Core::TimingEventType* event;
std::optional<u64> loaded_title_id;
std::vector<std::shared_ptr<CheatBase>> cheats_list;
mutable std::shared_mutex cheats_list_mutex;
Core::TimingEventType* event;
Core::System& system;
u64 title_id;
};
} // namespace Cheats

View File

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

View File

@ -77,7 +77,7 @@ public:
/// (there might be multiple lines of those hex numbers)
/// Comment lines start with a '*'
/// This function will pares the file for such structures
static std::vector<std::shared_ptr<CheatBase>> LoadFile(const std::string& filepath);
static std::vector<std::unique_ptr<CheatBase>> LoadFile(const std::string& filepath);
private:
std::atomic<bool> enabled = false;

View File

@ -72,7 +72,7 @@ Core::Timing& Global() {
return System::GetInstance().CoreTiming();
}
System::System() : movie{*this}, cheat_engine{*this} {}
System::System() : movie{*this} {}
System::~System() = default;
@ -296,20 +296,6 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st
return init_result;
}
// Restore any parameters that should be carried through a reset.
if (restore_deliver_arg.has_value()) {
if (auto apt = Service::APT::GetModule(*this)) {
apt->GetAppletManager()->SetDeliverArg(restore_deliver_arg);
}
restore_deliver_arg.reset();
}
if (restore_plugin_context.has_value()) {
if (auto plg_ldr = Service::PLGLDR::GetService(*this)) {
plg_ldr->SetPluginLoaderContext(restore_plugin_context.value());
}
restore_plugin_context.reset();
}
telemetry_session->AddInitialInfo(*app_loader);
std::shared_ptr<Kernel::Process> process;
const Loader::ResultStatus load_result{app_loader->Load(process)};
@ -334,10 +320,7 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st
LOG_ERROR(Core, "Failed to find title id for ROM (Error {})",
static_cast<u32>(load_result));
}
cheat_engine.LoadCheatFile(title_id);
cheat_engine.Connect();
cheat_engine = std::make_unique<Cheats::CheatEngine>(title_id, *this);
perf_stats = std::make_unique<PerfStats>(title_id);
if (Settings::values.dump_textures) {
@ -393,8 +376,7 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window,
memory = std::make_unique<Memory::MemorySystem>(*this);
timing = std::make_unique<Timing>(num_cores, Settings::values.cpu_clock_percentage.GetValue(),
movie.GetOverrideBaseTicks());
timing = std::make_unique<Timing>(num_cores, Settings::values.cpu_clock_percentage.GetValue());
kernel = std::make_unique<Kernel::KernelSystem>(
*memory, *timing, [this] { PrepareReschedule(); }, memory_mode, num_cores, n3ds_hw_caps,
@ -464,12 +446,6 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window,
gpu->SetInterruptHandler(
[gsp](Service::GSP::InterruptId interrupt_id) { gsp->SignalInterrupt(interrupt_id); });
auto plg_ldr = Service::PLGLDR::GetService(*this);
if (plg_ldr) {
plg_ldr->SetEnabled(Settings::values.plugin_loader_enabled.GetValue());
plg_ldr->SetAllowGameChangeState(Settings::values.allow_plugin_loader.GetValue());
}
LOG_DEBUG(Core, "Initialized OK");
is_powered_on = true;
@ -526,11 +502,11 @@ const Memory::MemorySystem& System::Memory() const {
}
Cheats::CheatEngine& System::CheatEngine() {
return cheat_engine;
return *cheat_engine;
}
const Cheats::CheatEngine& System::CheatEngine() const {
return cheat_engine;
return *cheat_engine;
}
void System::RegisterVideoDumper(std::shared_ptr<VideoDumper::Backend> dumper) {
@ -584,6 +560,7 @@ void System::Shutdown(bool is_deserializing) {
if (!is_deserializing) {
GDBStub::Shutdown();
perf_stats.reset();
cheat_engine.reset();
app_loader.reset();
}
custom_tex_manager.reset();
@ -622,13 +599,10 @@ void System::Reset() {
// reloading.
// TODO: Properly implement the reset
// Save the APT deliver arg and plugin loader context across resets.
// This is needed as we don't currently support proper app jumping.
// Since the system is completely reinitialized, we'll have to store the deliver arg manually.
boost::optional<Service::APT::DeliverArg> deliver_arg;
if (auto apt = Service::APT::GetModule(*this)) {
restore_deliver_arg = apt->GetAppletManager()->ReceiveDeliverArg();
}
if (auto plg_ldr = Service::PLGLDR::GetService(*this)) {
restore_plugin_context = plg_ldr->GetPluginLoaderContext();
deliver_arg = apt->GetAppletManager()->ReceiveDeliverArg();
}
Shutdown();
@ -641,6 +615,11 @@ void System::Reset() {
// Reload the system with the same setting
[[maybe_unused]] const System::ResultStatus result =
Load(*m_emu_window, m_filepath, m_secondary_window);
// Restore the deliver arg.
if (auto apt = Service::APT::GetModule(*this)) {
apt->GetAppletManager()->SetDeliverArg(std::move(deliver_arg));
}
}
void System::ApplySettings() {
@ -685,11 +664,9 @@ void System::ApplySettings() {
Service::MIC::ReloadMic(*this);
}
auto plg_ldr = Service::PLGLDR::GetService(*this);
if (plg_ldr) {
plg_ldr->SetEnabled(Settings::values.plugin_loader_enabled.GetValue());
plg_ldr->SetAllowGameChangeState(Settings::values.allow_plugin_loader.GetValue());
}
Service::PLGLDR::PLG_LDR::SetEnabled(Settings::values.plugin_loader_enabled.GetValue());
Service::PLGLDR::PLG_LDR::SetAllowGameChangeState(
Settings::values.allow_plugin_loader.GetValue());
}
template <class Archive>
@ -741,7 +718,7 @@ void System::serialize(Archive& ar, const unsigned int file_version) {
if (Archive::is_loading::value) {
timing->UnlockEventQueue();
memory->SetDSP(*dsp_core);
cheat_engine.Connect();
cheat_engine->Connect();
gpu->Sync();
// Re-register gpu callback, because gsp service changed after service_manager got

View File

@ -8,13 +8,9 @@
#include <memory>
#include <mutex>
#include <string>
#include <boost/optional.hpp>
#include <boost/serialization/version.hpp>
#include "common/common_types.h"
#include "core/arm/arm_interface.h"
#include "core/cheats/cheats.h"
#include "core/hle/service/apt/applet_manager.h"
#include "core/hle/service/plgldr/plgldr.h"
#include "core/movie.h"
#include "core/perf_stats.h"
@ -52,6 +48,10 @@ struct New3dsHwCapabilities;
enum class MemoryMode : u8;
} // namespace Kernel
namespace Cheats {
class CheatEngine;
}
namespace VideoDumper {
class Backend;
}
@ -401,7 +401,7 @@ private:
Core::Movie movie;
/// Cheats manager
Cheats::CheatEngine cheat_engine;
std::unique_ptr<Cheats::CheatEngine> cheat_engine;
/// Video dumper backend
std::shared_ptr<VideoDumper::Backend> video_dumper;
@ -447,9 +447,6 @@ private:
std::function<bool()> mic_permission_func;
bool mic_permission_granted = false;
boost::optional<Service::APT::DeliverArg> restore_deliver_arg;
boost::optional<Service::PLGLDR::PLG_LDR::PluginLoaderContext> restore_plugin_context;
friend class boost::serialization::access;
template <typename Archive>
void serialize(Archive& ar, const unsigned int file_version);

View File

@ -3,11 +3,9 @@
// Refer to the license.txt file included.
#include <algorithm>
#include <random>
#include <tuple>
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/settings.h"
#include "core/core_timing.h"
namespace Core {
@ -21,28 +19,15 @@ bool Timing::Event::operator<(const Timing::Event& right) const {
return std::tie(time, fifo_order) < std::tie(right.time, right.fifo_order);
}
Timing::Timing(std::size_t num_cores, u32 cpu_clock_percentage, s64 override_base_ticks) {
// Generate non-zero base tick count to simulate time the system ran before launching the game.
// This accounts for games that rely on the system tick to seed randomness.
const auto base_ticks = override_base_ticks >= 0 ? override_base_ticks : GenerateBaseTicks();
Timing::Timing(std::size_t num_cores, u32 cpu_clock_percentage) {
timers.resize(num_cores);
for (std::size_t i = 0; i < num_cores; ++i) {
timers[i] = std::make_shared<Timer>(base_ticks);
timers[i] = std::make_shared<Timer>();
}
UpdateClockSpeed(cpu_clock_percentage);
current_timer = timers[0].get();
}
s64 Timing::GenerateBaseTicks() {
if (Settings::values.init_ticks_type.GetValue() == Settings::InitTicks::Fixed) {
return Settings::values.init_ticks_override.GetValue();
}
// Bounded to 32 bits to make sure we don't generate too high of a counter and risk overflowing.
std::mt19937 random_gen(std::random_device{}());
return random_gen();
}
void Timing::UpdateClockSpeed(u32 cpu_clock_percentage) {
for (auto& timer : timers) {
timer->cpu_clock_scale = 100.0 / cpu_clock_percentage;
@ -161,7 +146,7 @@ std::shared_ptr<Timing::Timer> Timing::GetTimer(std::size_t cpu_id) {
return timers[cpu_id];
}
Timing::Timer::Timer(s64 base_ticks) : executed_ticks(base_ticks) {}
Timing::Timer::Timer() = default;
Timing::Timer::~Timer() {
MoveEvents();

View File

@ -185,7 +185,7 @@ public:
class Timer {
public:
Timer(s64 base_ticks = 0);
Timer();
~Timer();
s64 GetMaxSliceLength() const;
@ -249,7 +249,7 @@ public:
friend class boost::serialization::access;
};
explicit Timing(std::size_t num_cores, u32 cpu_clock_percentage, s64 override_base_ticks = -1);
explicit Timing(std::size_t num_cores, u32 cpu_clock_percentage);
~Timing(){};
@ -290,9 +290,6 @@ public:
event_queue_locked = false;
}
/// Generates a random tick count to seed the system tick timer with.
static s64 GenerateBaseTicks();
private:
// unordered_map stores each element separately as a linked list node so pointers to
// elements remain stable regardless of rehashes/resizing.

View File

@ -1073,7 +1073,7 @@ std::vector<FormatInfo> ListFormats() {
continue;
}
out.push_back({current->name, ToStdString(current->long_name), extensions,
out.push_back({current->name, ToStdString(current->long_name), std::move(extensions),
std::move(supported_video_codecs), std::move(supported_audio_codecs),
GetOptionList(current->priv_class, true)});
}

View File

@ -57,9 +57,9 @@ static bool LZSS_Decompress(std::span<const u8> compressed, std::span<u8> decomp
u32 buffer_top_and_bottom;
std::memcpy(&buffer_top_and_bottom, footer, sizeof(u32));
std::size_t out = decompressed.size();
std::size_t index = compressed.size() - ((buffer_top_and_bottom >> 24) & 0xFF);
std::size_t stop_index = compressed.size() - (buffer_top_and_bottom & 0xFFFFFF);
size_t out = decompressed.size();
size_t index = compressed.size() - ((buffer_top_and_bottom >> 24) & 0xFF);
size_t stop_index = compressed.size() - (buffer_top_and_bottom & 0xFFFFFF);
std::memset(decompressed.data(), 0, decompressed.size());
std::memcpy(decompressed.data(), compressed.data(), compressed.size());

View File

@ -131,7 +131,7 @@ public:
return m_offset;
}
bool Seek(std::size_t offset) {
bool Seek(size_t offset) {
if (offset > m_size)
return false;
m_offset = offset;
@ -242,7 +242,7 @@ private:
if (m_target_relative_offset + length > m_target.size())
return false;
// Byte by byte copy.
for (std::size_t i = 0; i < length; ++i)
for (size_t i = 0; i < length; ++i)
m_target.data()[m_target.Tell() + i] = m_target.data()[m_target_relative_offset++];
m_target.Seek(m_target.Tell() + length);
return true;

View File

@ -65,7 +65,7 @@ static bool ReadSection(std::vector<u8>& data_out, FileUtil::IOFile& file, std::
Loader::ResultStatus FileSys::Plugin3GXLoader::Load(
Service::PLGLDR::PLG_LDR::PluginLoaderContext& plg_context, Kernel::Process& process,
Kernel::KernelSystem& kernel, Service::PLGLDR::PLG_LDR& plg_ldr) {
Kernel::KernelSystem& kernel) {
FileUtil::IOFile file(plg_context.plugin_path, "rb");
if (!file.IsOpen()) {
LOG_ERROR(Service_PLGLDR, "Failed to load 3GX plugin. Not found: {}",
@ -158,12 +158,12 @@ Loader::ResultStatus FileSys::Plugin3GXLoader::Load(
return Loader::ResultStatus::Error;
}
return Map(plg_context, process, kernel, plg_ldr);
return Map(plg_context, process, kernel);
}
Loader::ResultStatus FileSys::Plugin3GXLoader::Map(
Service::PLGLDR::PLG_LDR::PluginLoaderContext& plg_context, Kernel::Process& process,
Kernel::KernelSystem& kernel, Service::PLGLDR::PLG_LDR& plg_ldr) {
Kernel::KernelSystem& kernel) {
// Verify exe load checksum function is available
if (exe_load_func.empty() && plg_context.load_exe_func.empty()) {
@ -195,7 +195,7 @@ Loader::ResultStatus FileSys::Plugin3GXLoader::Map(
return Loader::ResultStatus::ErrorMemoryAllocationFailed;
}
auto backing_memory_fb = kernel.memory.GetFCRAMRef(*offset_fb);
plg_ldr.SetPluginFBAddr(Memory::FCRAM_PADDR + *offset_fb);
Service::PLGLDR::PLG_LDR::SetPluginFBAddr(Memory::FCRAM_PADDR + *offset_fb);
std::fill(backing_memory_fb.GetPtr(), backing_memory_fb.GetPtr() + _3GX_fb_size, 0);
auto vma_heap_fb = process.vm_manager.MapBackingMemory(
@ -357,7 +357,7 @@ void FileSys::Plugin3GXLoader::MapBootloader(Kernel::Process& process, Kernel::K
// Write bootloader
kernel.memory.WriteBlock(
process, _3GX_exe_load_addr - bootloader_memory_size, bootloader.data(),
std::min<std::size_t>(bootloader.size() * sizeof(u32), bootloader_memory_size));
std::min<size_t>(bootloader.size() * sizeof(u32), bootloader_memory_size));
game_instructions[0] = 0xE51FF004; // ldr pc, [pc, #-4]
game_instructions[1] = _3GX_exe_load_addr - bootloader_memory_size;

View File

@ -43,8 +43,7 @@ class FileBackend;
class Plugin3GXLoader {
public:
Loader::ResultStatus Load(Service::PLGLDR::PLG_LDR::PluginLoaderContext& plg_context,
Kernel::Process& process, Kernel::KernelSystem& kernel,
Service::PLGLDR::PLG_LDR& plg_ldr);
Kernel::Process& process, Kernel::KernelSystem& kernel);
struct PluginHeader {
u32_le magic;
@ -69,10 +68,9 @@ public:
private:
Loader::ResultStatus Map(Service::PLGLDR::PLG_LDR::PluginLoaderContext& plg_context,
Kernel::Process& process, Kernel::KernelSystem& kernel,
Service::PLGLDR::PLG_LDR& plg_ldr);
Kernel::Process& process, Kernel::KernelSystem& kernel);
static constexpr std::size_t bootloader_memory_size = 0x1000;
static constexpr size_t bootloader_memory_size = 0x1000;
static void MapBootloader(Kernel::Process& process, Kernel::KernelSystem& kernel,
u32 memory_offset, std::span<const u32> exe_load_func,
const u32_le* exe_load_args, u32 checksum_size, u32 exe_checksum,

View File

@ -16,7 +16,7 @@ std::size_t DirectRomFSReader::ReadFile(std::size_t offset, std::size_t length,
return 0; // Crypto++ does not like zero size buffer
const auto segments = BreakupRead(offset, length);
std::size_t read_progress = 0;
size_t read_progress = 0;
// Skip cache if the read is too big
if (segments.size() == 1 && segments[0].second > cache_line_size) {
@ -33,8 +33,8 @@ std::size_t DirectRomFSReader::ReadFile(std::size_t offset, std::size_t length,
// TODO(PabloMK7): Make cache thread safe, read the comment in CacheReady function.
// std::unique_lock<std::shared_mutex> read_guard(cache_mutex);
for (const auto& seg : segments) {
std::size_t read_size = cache_line_size;
std::size_t page = OffsetToPage(seg.first);
size_t read_size = cache_line_size;
size_t page = OffsetToPage(seg.first);
// Check if segment is in cache
auto cache_entry = cache.request(page);
if (!cache_entry.first) {
@ -51,7 +51,7 @@ std::size_t DirectRomFSReader::ReadFile(std::size_t offset, std::size_t length,
LOG_TRACE(Service_FS, "RomFS Cache HIT: page={}, length={}, into={}", page, seg.second,
(seg.first - page));
}
std::size_t copy_amount =
size_t copy_amount =
(read_size > (seg.first - page))
? std::min((seg.first - page) + seg.second, read_size) - (seg.first - page)
: 0;
@ -98,10 +98,10 @@ std::vector<std::pair<std::size_t, std::size_t>> DirectRomFSReader::BreakupRead(
return ret;
}
std::size_t curr_offset = offset;
size_t curr_offset = offset;
while (length) {
std::size_t next_page = OffsetToPage(curr_offset + cache_line_size);
std::size_t curr_page_len = std::min(length, next_page - curr_offset);
size_t next_page = OffsetToPage(curr_offset + cache_line_size);
size_t curr_page_len = std::min(length, next_page - curr_offset);
ret.push_back(std::make_pair(curr_offset, curr_page_len));
curr_offset = next_page;
length -= curr_page_len;

View File

@ -67,8 +67,8 @@ private:
u64 data_size;
// Total cache size: 128KB
static constexpr std::size_t cache_line_size = (1 << 13); // About 8KB
static constexpr std::size_t cache_line_count = 16;
static constexpr size_t cache_line_size = (1 << 13); // About 8KB
static constexpr size_t cache_line_count = 16;
Common::StaticLRUCache<std::size_t, std::array<u8, cache_line_size>, cache_line_count> cache;
// TODO(PabloMK7): Make cache thread safe, read the comment in CacheReady function.

View File

@ -9,7 +9,7 @@
namespace Frontend {
void RegisterDefaultApplets(Core::System& system) {
system.RegisterSoftwareKeyboard(std::make_shared<DefaultKeyboard>(system));
system.RegisterSoftwareKeyboard(std::make_shared<DefaultKeyboard>());
system.RegisterMiiSelector(std::make_shared<DefaultMiiSelector>());
}
} // namespace Frontend

View File

@ -144,12 +144,10 @@ const KeyboardData& SoftwareKeyboard::ReceiveData() {
return data;
}
DefaultKeyboard::DefaultKeyboard(Core::System& system_) : system(system_) {}
void DefaultKeyboard::Execute(const Frontend::KeyboardConfig& config_) {
SoftwareKeyboard::Execute(config_);
auto cfg = Service::CFG::GetModule(system);
auto cfg = Service::CFG::GetModule(Core::System::GetInstance());
std::string username = Common::UTF16ToUTF8(cfg->GetUsername());
switch (this->config.button_config) {
case ButtonConfig::None:

View File

@ -8,10 +8,6 @@
#include <vector>
#include "common/assert.h"
namespace Core {
class System;
}
namespace Frontend {
enum class AcceptedInput {
@ -141,12 +137,8 @@ protected:
class DefaultKeyboard final : public SoftwareKeyboard {
public:
explicit DefaultKeyboard(Core::System& system_);
void Execute(const KeyboardConfig& config) override;
void ShowError(const std::string& error) override;
private:
Core::System& system;
};
} // namespace Frontend

View File

@ -173,7 +173,8 @@ void EmuWindow::TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y) {
TouchPressed(framebuffer_x, framebuffer_y);
}
void EmuWindow::UpdateCurrentFramebufferLayout(u32 width, u32 height, bool is_portrait_mode) {
void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height,
bool is_portrait_mode) {
Layout::FramebufferLayout layout;
// If in portrait mode, only the MobilePortrait option really makes sense
@ -199,8 +200,7 @@ void EmuWindow::UpdateCurrentFramebufferLayout(u32 width, u32 height, bool is_po
layout =
Layout::LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
Settings::values.upright_screen.GetValue(),
Settings::values.large_screen_proportion.GetValue(),
Layout::VerticalAlignment::Bottom);
Settings::values.large_screen_proportion.GetValue());
break;
case Settings::LayoutOption::HybridScreen:
layout =
@ -208,10 +208,8 @@ void EmuWindow::UpdateCurrentFramebufferLayout(u32 width, u32 height, bool is_po
Settings::values.upright_screen.GetValue());
break;
case Settings::LayoutOption::SideScreen:
layout =
Layout::LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
Settings::values.upright_screen.GetValue(), 1.0f,
Layout::VerticalAlignment::Bottom);
layout = Layout::SideFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
Settings::values.upright_screen.GetValue());
break;
#ifndef ANDROID
case Settings::LayoutOption::SeparateWindows:
@ -224,9 +222,8 @@ void EmuWindow::UpdateCurrentFramebufferLayout(u32 width, u32 height, bool is_po
Settings::values.swap_screen.GetValue());
break;
case Settings::LayoutOption::MobileLandscape:
layout =
Layout::LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
false, 2.25f, Layout::VerticalAlignment::Top);
layout = Layout::MobileLandscapeFrameLayout(
width, height, Settings::values.swap_screen.GetValue(), 2.25f, false);
break;
case Settings::LayoutOption::Default:
default:

View File

@ -30,7 +30,7 @@ u32 FramebufferLayout::GetScalingRatio() const {
// Finds the largest size subrectangle contained in window area that is confined to the aspect ratio
template <class T>
static Common::Rectangle<T> MaxRectangle(Common::Rectangle<T> window_area,
static Common::Rectangle<T> maxRectangle(Common::Rectangle<T> window_area,
float screen_aspect_ratio) {
float scale = std::min(static_cast<float>(window_area.GetWidth()),
window_area.GetHeight() / screen_aspect_ratio);
@ -50,15 +50,15 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height, bool swapped, bool u
if (upright) {
// Default layout gives equal screen sizes to the top and bottom screen
screen_window_area = {0, 0, width / 2, height};
top_screen = MaxRectangle(screen_window_area, TOP_SCREEN_UPRIGHT_ASPECT_RATIO);
bot_screen = MaxRectangle(screen_window_area, BOT_SCREEN_UPRIGHT_ASPECT_RATIO);
top_screen = maxRectangle(screen_window_area, TOP_SCREEN_UPRIGHT_ASPECT_RATIO);
bot_screen = maxRectangle(screen_window_area, BOT_SCREEN_UPRIGHT_ASPECT_RATIO);
// both screens width are taken into account by dividing by 2
emulation_aspect_ratio = TOP_SCREEN_UPRIGHT_ASPECT_RATIO / 2;
} else {
// Default layout gives equal screen sizes to the top and bottom screen
screen_window_area = {0, 0, width, height / 2};
top_screen = MaxRectangle(screen_window_area, TOP_SCREEN_ASPECT_RATIO);
bot_screen = MaxRectangle(screen_window_area, BOT_SCREEN_ASPECT_RATIO);
top_screen = maxRectangle(screen_window_area, TOP_SCREEN_ASPECT_RATIO);
bot_screen = maxRectangle(screen_window_area, BOT_SCREEN_ASPECT_RATIO);
// both screens height are taken into account by multiplying by 2
emulation_aspect_ratio = TOP_SCREEN_ASPECT_RATIO * 2;
}
@ -71,7 +71,7 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height, bool swapped, bool u
// Recalculate the bottom screen to account for the height difference between right and
// left
screen_window_area = {0, 0, top_screen.GetWidth(), height};
bot_screen = MaxRectangle(screen_window_area, BOT_SCREEN_UPRIGHT_ASPECT_RATIO);
bot_screen = maxRectangle(screen_window_area, BOT_SCREEN_UPRIGHT_ASPECT_RATIO);
bot_screen =
bot_screen.TranslateY((top_screen.GetHeight() - bot_screen.GetHeight()) / 2);
if (swapped) {
@ -96,7 +96,7 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height, bool swapped, bool u
// Recalculate the bottom screen to account for the width difference between top and
// bottom
screen_window_area = {0, 0, width, top_screen.GetHeight()};
bot_screen = MaxRectangle(screen_window_area, BOT_SCREEN_ASPECT_RATIO);
bot_screen = maxRectangle(screen_window_area, BOT_SCREEN_ASPECT_RATIO);
bot_screen = bot_screen.TranslateX((top_screen.GetWidth() - bot_screen.GetWidth()) / 2);
if (swapped) {
bot_screen = bot_screen.TranslateY(height / 2 - bot_screen.GetHeight());
@ -124,8 +124,8 @@ FramebufferLayout MobilePortraitFrameLayout(u32 width, u32 height, bool swapped)
FramebufferLayout res{width, height, true, true, {}, {}};
// Default layout gives equal screen sizes to the top and bottom screen
Common::Rectangle<u32> screen_window_area{0, 0, width, height / 2};
Common::Rectangle<u32> top_screen = MaxRectangle(screen_window_area, TOP_SCREEN_ASPECT_RATIO);
Common::Rectangle<u32> bot_screen = MaxRectangle(screen_window_area, BOT_SCREEN_ASPECT_RATIO);
Common::Rectangle<u32> top_screen = maxRectangle(screen_window_area, TOP_SCREEN_ASPECT_RATIO);
Common::Rectangle<u32> bot_screen = maxRectangle(screen_window_area, BOT_SCREEN_ASPECT_RATIO);
float window_aspect_ratio = static_cast<float>(height) / width;
// both screens height are taken into account by multiplying by 2
@ -151,6 +151,48 @@ FramebufferLayout MobilePortraitFrameLayout(u32 width, u32 height, bool swapped)
return res;
}
FramebufferLayout MobileLandscapeFrameLayout(u32 width, u32 height, bool swapped,
float scale_factor, bool center_vertical) {
ASSERT(width > 0);
ASSERT(height > 0);
FramebufferLayout res{width, height, true, true, {}, {}};
// Split the window into two parts. Give 4x width to the main screen and 1x width to the small
// To do that, find the total emulation box and maximize that based on window size
float window_aspect_ratio = static_cast<float>(height) / width;
float emulation_aspect_ratio =
swapped ? Core::kScreenBottomHeight * scale_factor /
(Core::kScreenBottomWidth * scale_factor + Core::kScreenTopWidth)
: Core::kScreenTopHeight * scale_factor /
(Core::kScreenTopWidth * scale_factor + Core::kScreenBottomWidth);
float large_screen_aspect_ratio = swapped ? BOT_SCREEN_ASPECT_RATIO : TOP_SCREEN_ASPECT_RATIO;
float small_screen_aspect_ratio = swapped ? TOP_SCREEN_ASPECT_RATIO : BOT_SCREEN_ASPECT_RATIO;
Common::Rectangle<u32> screen_window_area{0, 0, width, height};
Common::Rectangle<u32> total_rect = maxRectangle(screen_window_area, emulation_aspect_ratio);
Common::Rectangle<u32> large_screen = maxRectangle(total_rect, large_screen_aspect_ratio);
Common::Rectangle<u32> fourth_size_rect = total_rect.Scale(1.f / scale_factor);
Common::Rectangle<u32> small_screen = maxRectangle(fourth_size_rect, small_screen_aspect_ratio);
if (window_aspect_ratio < emulation_aspect_ratio) {
large_screen =
large_screen.TranslateX((screen_window_area.GetWidth() - total_rect.GetWidth()) / 2);
} else if (center_vertical) {
large_screen = large_screen.TranslateY((height - total_rect.GetHeight()) / 2);
}
// Shift the small screen to the bottom right corner
small_screen = small_screen.TranslateX(large_screen.right);
if (center_vertical) {
small_screen = small_screen.TranslateY(large_screen.GetHeight() + large_screen.top -
small_screen.GetHeight());
}
res.top_screen = swapped ? small_screen : large_screen;
res.bottom_screen = swapped ? large_screen : small_screen;
return res;
}
FramebufferLayout SingleFrameLayout(u32 width, u32 height, bool swapped, bool upright) {
ASSERT(width > 0);
ASSERT(height > 0);
@ -163,13 +205,13 @@ FramebufferLayout SingleFrameLayout(u32 width, u32 height, bool swapped, bool up
Common::Rectangle<u32> bot_screen;
float emulation_aspect_ratio;
if (upright) {
top_screen = MaxRectangle(screen_window_area, TOP_SCREEN_UPRIGHT_ASPECT_RATIO);
bot_screen = MaxRectangle(screen_window_area, BOT_SCREEN_UPRIGHT_ASPECT_RATIO);
top_screen = maxRectangle(screen_window_area, TOP_SCREEN_UPRIGHT_ASPECT_RATIO);
bot_screen = maxRectangle(screen_window_area, BOT_SCREEN_UPRIGHT_ASPECT_RATIO);
emulation_aspect_ratio =
(swapped) ? BOT_SCREEN_UPRIGHT_ASPECT_RATIO : TOP_SCREEN_UPRIGHT_ASPECT_RATIO;
} else {
top_screen = MaxRectangle(screen_window_area, TOP_SCREEN_ASPECT_RATIO);
bot_screen = MaxRectangle(screen_window_area, BOT_SCREEN_ASPECT_RATIO);
top_screen = maxRectangle(screen_window_area, TOP_SCREEN_ASPECT_RATIO);
bot_screen = maxRectangle(screen_window_area, BOT_SCREEN_ASPECT_RATIO);
emulation_aspect_ratio = (swapped) ? BOT_SCREEN_ASPECT_RATIO : TOP_SCREEN_ASPECT_RATIO;
}
@ -190,7 +232,7 @@ FramebufferLayout SingleFrameLayout(u32 width, u32 height, bool swapped, bool up
}
FramebufferLayout LargeFrameLayout(u32 width, u32 height, bool swapped, bool upright,
float scale_factor, VerticalAlignment vertical_alignment) {
float scale_factor) {
ASSERT(width > 0);
ASSERT(height > 0);
@ -232,10 +274,10 @@ FramebufferLayout LargeFrameLayout(u32 width, u32 height, bool swapped, bool upr
}
Common::Rectangle<u32> screen_window_area{0, 0, width, height};
Common::Rectangle<u32> total_rect = MaxRectangle(screen_window_area, emulation_aspect_ratio);
Common::Rectangle<u32> large_screen = MaxRectangle(total_rect, large_screen_aspect_ratio);
Common::Rectangle<u32> scaled_rect = total_rect.Scale(1.f / scale_factor);
Common::Rectangle<u32> small_screen = MaxRectangle(scaled_rect, small_screen_aspect_ratio);
Common::Rectangle<u32> total_rect = maxRectangle(screen_window_area, emulation_aspect_ratio);
Common::Rectangle<u32> large_screen = maxRectangle(total_rect, large_screen_aspect_ratio);
Common::Rectangle<u32> fourth_size_rect = total_rect.Scale(1.f / scale_factor);
Common::Rectangle<u32> small_screen = maxRectangle(fourth_size_rect, small_screen_aspect_ratio);
if (window_aspect_ratio < emulation_aspect_ratio) {
large_screen = large_screen.TranslateX((width - total_rect.GetWidth()) / 2);
@ -244,46 +286,13 @@ FramebufferLayout LargeFrameLayout(u32 width, u32 height, bool swapped, bool upr
}
if (upright) {
large_screen = large_screen.TranslateY(small_screen.GetHeight());
small_screen = small_screen.TranslateY(large_screen.top - small_screen.GetHeight());
switch (vertical_alignment) {
case VerticalAlignment::Top:
// Shift the small screen to the top right corner
small_screen = small_screen.TranslateX(large_screen.left);
break;
case VerticalAlignment::Middle:
// Shift the small screen to the center right
small_screen = small_screen.TranslateX(
((large_screen.GetWidth() - small_screen.GetWidth()) / 2) + large_screen.left);
break;
case VerticalAlignment::Bottom:
// Shift the small screen to the bottom right corner
small_screen = small_screen.TranslateX(large_screen.right - small_screen.GetWidth());
break;
default:
UNREACHABLE();
break;
}
small_screen = small_screen.TranslateX(large_screen.right - small_screen.GetWidth())
.TranslateY(large_screen.top - small_screen.GetHeight());
} else {
small_screen = small_screen.TranslateX(large_screen.right);
switch (vertical_alignment) {
case VerticalAlignment::Top:
// Shift the small screen to the top right corner
small_screen = small_screen.TranslateY(large_screen.top);
break;
case VerticalAlignment::Middle:
// Shift the small screen to the center right
small_screen = small_screen.TranslateY(
((large_screen.GetHeight() - small_screen.GetHeight()) / 2) + large_screen.top);
break;
case VerticalAlignment::Bottom:
// Shift the small screen to the bottom right corner
small_screen = small_screen.TranslateY(large_screen.bottom - small_screen.GetHeight());
break;
default:
UNREACHABLE();
break;
}
small_screen =
small_screen.TranslateX(large_screen.right)
.TranslateY(large_screen.GetHeight() + large_screen.top - small_screen.GetHeight());
}
res.top_screen = swapped ? small_screen : large_screen;
res.bottom_screen = swapped ? large_screen : small_screen;
@ -322,11 +331,11 @@ FramebufferLayout HybridScreenLayout(u32 width, u32 height, bool swapped, bool u
}
Common::Rectangle<u32> screen_window_area{0, 0, width, height};
Common::Rectangle<u32> total_rect = MaxRectangle(screen_window_area, hybrid_area_aspect_ratio);
Common::Rectangle<u32> large_main_screen = MaxRectangle(total_rect, main_screen_aspect_ratio);
Common::Rectangle<u32> total_rect = maxRectangle(screen_window_area, hybrid_area_aspect_ratio);
Common::Rectangle<u32> large_main_screen = maxRectangle(total_rect, main_screen_aspect_ratio);
Common::Rectangle<u32> side_rect = total_rect.Scale(1.f / scale_factor);
Common::Rectangle<u32> small_top_screen = MaxRectangle(side_rect, top_screen_aspect_ratio);
Common::Rectangle<u32> small_bottom_screen = MaxRectangle(side_rect, bot_screen_aspect_ratio);
Common::Rectangle<u32> small_top_screen = maxRectangle(side_rect, top_screen_aspect_ratio);
Common::Rectangle<u32> small_bottom_screen = maxRectangle(side_rect, bot_screen_aspect_ratio);
if (window_aspect_ratio < hybrid_area_aspect_ratio) {
large_main_screen = large_main_screen.TranslateX((width - total_rect.GetWidth()) / 2);
@ -364,6 +373,54 @@ FramebufferLayout HybridScreenLayout(u32 width, u32 height, bool swapped, bool u
return res;
}
FramebufferLayout SideFrameLayout(u32 width, u32 height, bool swapped, bool upright) {
ASSERT(width > 0);
ASSERT(height > 0);
FramebufferLayout res{width, height, true, true, {}, {}, !upright};
// Aspect ratio of both screens side by side
float emulation_aspect_ratio =
upright ? static_cast<float>(Core::kScreenTopWidth + Core::kScreenBottomWidth) /
Core::kScreenTopHeight
: static_cast<float>(Core::kScreenTopHeight) /
(Core::kScreenTopWidth + Core::kScreenBottomWidth);
float window_aspect_ratio = static_cast<float>(height) / width;
Common::Rectangle<u32> screen_window_area{0, 0, width, height};
// Find largest Rectangle that can fit in the window size with the given aspect ratio
Common::Rectangle<u32> screen_rect = maxRectangle(screen_window_area, emulation_aspect_ratio);
// Find sizes of top and bottom screen
Common::Rectangle<u32> top_screen =
upright ? maxRectangle(screen_rect, TOP_SCREEN_UPRIGHT_ASPECT_RATIO)
: maxRectangle(screen_rect, TOP_SCREEN_ASPECT_RATIO);
Common::Rectangle<u32> bot_screen =
upright ? maxRectangle(screen_rect, BOT_SCREEN_UPRIGHT_ASPECT_RATIO)
: maxRectangle(screen_rect, BOT_SCREEN_ASPECT_RATIO);
if (window_aspect_ratio < emulation_aspect_ratio) {
// Apply borders to the left and right sides of the window.
u32 shift_horizontal = (screen_window_area.GetWidth() - screen_rect.GetWidth()) / 2;
top_screen = top_screen.TranslateX(shift_horizontal);
bot_screen = bot_screen.TranslateX(shift_horizontal);
} else {
// Window is narrower than the emulation content => apply borders to the top and bottom
u32 shift_vertical = (screen_window_area.GetHeight() - screen_rect.GetHeight()) / 2;
top_screen = top_screen.TranslateY(shift_vertical);
bot_screen = bot_screen.TranslateY(shift_vertical);
}
if (upright) {
// Leave the top screen at the top if we are swapped.
res.top_screen = swapped ? top_screen : top_screen.TranslateY(bot_screen.GetHeight());
res.bottom_screen = swapped ? bot_screen.TranslateY(top_screen.GetHeight()) : bot_screen;
} else {
// Move the top screen to the right if we are swapped.
res.top_screen = swapped ? top_screen.TranslateX(bot_screen.GetWidth()) : top_screen;
res.bottom_screen = swapped ? bot_screen : bot_screen.TranslateX(top_screen.GetWidth());
}
return res;
}
FramebufferLayout SeparateWindowsLayout(u32 width, u32 height, bool is_secondary, bool upright) {
// When is_secondary is true, we disable the top screen, and enable the bottom screen.
// The same logic is found in the SingleFrameLayout using the is_swapped bool.
@ -397,14 +454,14 @@ FramebufferLayout CustomFrameLayout(u32 width, u32 height, bool is_swapped) {
}
FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondary) {
FramebufferLayout layout;
if (Settings::values.custom_layout.GetValue() == true) {
return CustomFrameLayout(std::max(Settings::values.custom_top_right.GetValue(),
layout = CustomFrameLayout(std::max(Settings::values.custom_top_right.GetValue(),
Settings::values.custom_bottom_right.GetValue()),
std::max(Settings::values.custom_top_bottom.GetValue(),
Settings::values.custom_bottom_bottom.GetValue()),
Settings::values.swap_screen.GetValue());
}
} else {
int width, height;
switch (Settings::values.layout_option.GetValue()) {
case Settings::LayoutOption::SingleScreen:
@ -413,6 +470,15 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar
#endif
{
const bool swap_screens = is_secondary || Settings::values.swap_screen.GetValue();
if (Settings::values.upright_screen.GetValue()) {
if (swap_screens) {
width = Core::kScreenBottomHeight * res_scale;
height = Core::kScreenBottomWidth * res_scale;
} else {
width = Core::kScreenTopHeight * res_scale;
height = Core::kScreenTopWidth * res_scale;
}
} else {
if (swap_screens) {
width = Core::kScreenBottomWidth * res_scale;
height = Core::kScreenBottomHeight * res_scale;
@ -420,80 +486,99 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar
width = Core::kScreenTopWidth * res_scale;
height = Core::kScreenTopHeight * res_scale;
}
if (Settings::values.upright_screen.GetValue()) {
std::swap(width, height);
}
return SingleFrameLayout(width, height, swap_screens,
layout = SingleFrameLayout(width, height, swap_screens,
Settings::values.upright_screen.GetValue());
break;
}
case Settings::LayoutOption::LargeScreen:
if (Settings::values.upright_screen.GetValue()) {
if (Settings::values.swap_screen.GetValue()) {
width = Core::kScreenBottomHeight * res_scale;
height =
(Core::kScreenBottomWidth +
static_cast<int>(Core::kScreenTopWidth /
Settings::values.large_screen_proportion.GetValue())) *
res_scale;
} else {
width = Core::kScreenTopHeight * res_scale;
height =
(Core::kScreenTopWidth +
static_cast<int>(Core::kScreenBottomWidth /
Settings::values.large_screen_proportion.GetValue())) *
res_scale;
}
} else {
if (Settings::values.swap_screen.GetValue()) {
width = (Core::kScreenBottomWidth +
Core::kScreenTopWidth /
static_cast<int>(Settings::values.large_screen_proportion.GetValue())) *
static_cast<int>(
Settings::values.large_screen_proportion.GetValue())) *
res_scale;
height = Core::kScreenBottomHeight * res_scale;
} else {
width = (Core::kScreenTopWidth +
Core::kScreenBottomWidth /
static_cast<int>(Settings::values.large_screen_proportion.GetValue())) *
static_cast<int>(
Settings::values.large_screen_proportion.GetValue())) *
res_scale;
height = Core::kScreenTopHeight * res_scale;
}
if (Settings::values.upright_screen.GetValue()) {
std::swap(width, height);
}
return LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
layout = LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
Settings::values.upright_screen.GetValue(),
Settings::values.large_screen_proportion.GetValue(),
VerticalAlignment::Bottom);
Settings::values.large_screen_proportion.GetValue());
break;
case Settings::LayoutOption::SideScreen:
if (Settings::values.upright_screen.GetValue()) {
width = Core::kScreenTopHeight * res_scale;
height = (Core::kScreenTopWidth + Core::kScreenBottomWidth) * res_scale;
} else {
width = (Core::kScreenTopWidth + Core::kScreenBottomWidth) * res_scale;
height = Core::kScreenTopHeight * res_scale;
if (Settings::values.upright_screen.GetValue()) {
std::swap(width, height);
}
return LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
Settings::values.upright_screen.GetValue(), 1,
VerticalAlignment::Middle);
layout = SideFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
Settings::values.upright_screen.GetValue());
break;
case Settings::LayoutOption::MobilePortrait:
width = Core::kScreenTopWidth * res_scale;
height = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale;
return MobilePortraitFrameLayout(width, height, Settings::values.swap_screen.GetValue());
case Settings::LayoutOption::MobileLandscape: {
constexpr float large_screen_proportion = 2.25f;
layout =
MobilePortraitFrameLayout(width, height, Settings::values.swap_screen.GetValue());
break;
case Settings::LayoutOption::MobileLandscape:
if (Settings::values.swap_screen.GetValue()) {
width = (Core::kScreenBottomWidth +
static_cast<int>(Core::kScreenTopWidth / large_screen_proportion)) *
width =
(Core::kScreenBottomWidth + static_cast<int>(Core::kScreenTopWidth / 2.25f)) *
res_scale;
height = Core::kScreenBottomHeight * res_scale;
} else {
width = (Core::kScreenTopWidth +
static_cast<int>(Core::kScreenBottomWidth / large_screen_proportion)) *
width =
(Core::kScreenTopWidth + static_cast<int>(Core::kScreenBottomWidth / 2.25f)) *
res_scale;
height = Core::kScreenTopHeight * res_scale;
}
return LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(), false,
large_screen_proportion, VerticalAlignment::Top);
}
layout = MobileLandscapeFrameLayout(
width, height, Settings::values.swap_screen.GetValue(), 2.25f, false);
break;
case Settings::LayoutOption::Default:
default:
if (Settings::values.upright_screen.GetValue()) {
width = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale;
height = Core::kScreenTopWidth * res_scale;
} else {
width = Core::kScreenTopWidth * res_scale;
height = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale;
if (Settings::values.upright_screen.GetValue()) {
std::swap(width, height);
}
return DefaultFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
layout = DefaultFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
Settings::values.upright_screen.GetValue());
break;
}
UNREACHABLE();
}
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::CardboardVR) {
layout = Layout::GetCardboardSettings(layout);
}
return layout;
}
FramebufferLayout GetCardboardSettings(const FramebufferLayout& layout) {

View File

@ -20,31 +20,6 @@ enum class DisplayOrientation {
PortraitFlipped, // 3DS rotated 270 degrees counter-clockwise
};
/// Describes the vertical alignment of the top and bottom screens in LargeFrameLayout
/// Top
/// +-------------+-----+
/// | | |
/// | +-----+
/// | |
/// +-------------+
/// Middle
/// +-------------+
/// | +-----+
/// | | |
/// | +-----+
/// +-------------+
/// Bottom
/// +-------------+
/// | |
/// | +-----+
/// | | |
/// +-------------+-----+
enum class VerticalAlignment {
Top,
Middle,
Bottom,
};
/// Describes the horizontal coordinates for the right eye screen when using Cardboard VR
struct CardboardSettings {
u32 top_screen_right_eye;
@ -68,7 +43,7 @@ struct FramebufferLayout {
CardboardSettings cardboard;
/**
* Returns the ratio of pixel size of the top screen, compared to the native size of the 3DS
* Returns the ration of pixel size of the top screen, compared to the native size of the 3DS
* screen.
*/
u32 GetScalingRatio() const;
@ -79,7 +54,6 @@ struct FramebufferLayout {
* @param width Window framebuffer width in pixels
* @param height Window framebuffer height in pixels
* @param is_swapped if true, the bottom screen will be displayed above the top screen
* @param upright if true, the screens will be rotated 90 degrees anti-clockwise
* @return Newly created FramebufferLayout object with default screen regions initialized
*/
FramebufferLayout DefaultFrameLayout(u32 width, u32 height, bool is_swapped, bool upright);
@ -93,12 +67,25 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height, bool is_swapped, boo
*/
FramebufferLayout MobilePortraitFrameLayout(u32 width, u32 height, bool is_swapped);
/**
* Factory method for constructing a Frame with the a 4x size Top screen with a 1x size bottom
* screen on the right
* This is useful in particular because it matches well with a 1920x1080 resolution monitor
* @param width Window framebuffer width in pixels
* @param height Window framebuffer height in pixels
* @param is_swapped if true, the bottom screen will be the large display
* @param scale_factor Scale factor to use for bottom screen with respect to top screen
* @param center_vertical When true, centers the top and bottom screens vertically
* @return Newly created FramebufferLayout object with default screen regions initialized
*/
FramebufferLayout MobileLandscapeFrameLayout(u32 width, u32 height, bool is_swapped,
float scale_factor, bool center_vertical);
/**
* Factory method for constructing a FramebufferLayout with only the top or bottom screen
* @param width Window framebuffer width in pixels
* @param height Window framebuffer height in pixels
* @param is_swapped if true, the bottom screen will be displayed (and the top won't be displayed)
* @param upright if true, the screens will be rotated 90 degrees anti-clockwise
* @return Newly created FramebufferLayout object with default screen regions initialized
*/
FramebufferLayout SingleFrameLayout(u32 width, u32 height, bool is_swapped, bool upright);
@ -110,25 +97,32 @@ FramebufferLayout SingleFrameLayout(u32 width, u32 height, bool is_swapped, bool
* @param width Window framebuffer width in pixels
* @param height Window framebuffer height in pixels
* @param is_swapped if true, the bottom screen will be the large display
* @param upright if true, the screens will be rotated 90 degrees anti-clockwise
* @param scale_factor The ratio between the large screen with respect to the smaller screen
* @param vertical_alignment The vertical alignment of the smaller screen relative to the larger
* screen
* @return Newly created FramebufferLayout object with default screen regions initialized
*/
FramebufferLayout LargeFrameLayout(u32 width, u32 height, bool is_swapped, bool upright,
float scale_factor, VerticalAlignment vertical_alignment);
float scale_factor);
/**
* Factory method for constructing a frame with 2.5 times bigger top screen on the right,
* and 1x top and bottom screen on the left
* @param width Window framebuffer width in pixels
* @param height Window framebuffer height in pixels
* @param is_swapped if true, the bottom screen will be the large display
* @param upright if true, the screens will be rotated 90 degrees anti-clockwise
* @return Newly created FramebufferLayout object with default screen regions initialized
*/
FramebufferLayout HybridScreenLayout(u32 width, u32 height, bool swapped, bool upright);
/**
* Factory method for constructing a Frame with the Top screen and bottom
* screen side by side
* This is useful for devices with small screens, like the GPDWin
* @param width Window framebuffer width in pixels
* @param height Window framebuffer height in pixels
* @param is_swapped if true, the bottom screen will be the left display
* @return Newly created FramebufferLayout object with default screen regions initialized
*/
FramebufferLayout SideFrameLayout(u32 width, u32 height, bool is_swapped, bool upright);
/**
* Factory method for constructing a Frame with the Top screen and bottom
* screen on separate windows

View File

@ -5,16 +5,97 @@
#include <cstddef>
#include <memory>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include "common/assert.h"
#include "common/common_types.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/applets/applet.h"
#include "core/hle/applets/erreula.h"
#include "core/hle/applets/mii_selector.h"
#include "core/hle/applets/mint.h"
#include "core/hle/applets/swkbd.h"
#include "core/hle/result.h"
namespace HLE::Applets {
static std::unordered_map<Service::APT::AppletId, std::shared_ptr<Applet>> applets;
/// The CoreTiming event identifier for the Applet update callback.
static Core::TimingEventType* applet_update_event = nullptr;
/// The interval at which the Applet update callback will be called, 16.6ms
static const u64 applet_update_interval_us = 16666;
Result Applet::Create(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload,
const std::shared_ptr<Service::APT::AppletManager>& manager) {
switch (id) {
case Service::APT::AppletId::SoftwareKeyboard1:
case Service::APT::AppletId::SoftwareKeyboard2:
applets[id] = std::make_shared<SoftwareKeyboard>(id, parent, preload, manager);
break;
case Service::APT::AppletId::Ed1:
case Service::APT::AppletId::Ed2:
applets[id] = std::make_shared<MiiSelector>(id, parent, preload, manager);
break;
case Service::APT::AppletId::Error:
case Service::APT::AppletId::Error2:
applets[id] = std::make_shared<ErrEula>(id, parent, preload, manager);
break;
case Service::APT::AppletId::Mint:
case Service::APT::AppletId::Mint2:
applets[id] = std::make_shared<Mint>(id, parent, preload, manager);
break;
default:
LOG_ERROR(Service_APT, "Could not create applet {}", id);
// TODO(Subv): Find the right error code
return Result(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotSupported,
ErrorLevel::Permanent);
}
Service::APT::AppletAttributes attributes;
attributes.applet_pos.Assign(Service::APT::AppletPos::AutoLibrary);
attributes.is_home_menu.Assign(false);
const auto lock_handle_data = manager->GetLockHandle(attributes);
manager->Initialize(id, lock_handle_data->corrected_attributes);
manager->Enable(lock_handle_data->corrected_attributes);
if (preload) {
manager->FinishPreloadingLibraryApplet(id);
}
// Schedule the update event
Core::System::GetInstance().CoreTiming().ScheduleEvent(
usToCycles(applet_update_interval_us), applet_update_event, static_cast<u64>(id));
return ResultSuccess;
}
std::shared_ptr<Applet> Applet::Get(Service::APT::AppletId id) {
auto itr = applets.find(id);
if (itr != applets.end())
return itr->second;
return nullptr;
}
/// Handles updating the current Applet every time it's called.
static void AppletUpdateEvent(u64 applet_id, s64 cycles_late) {
const auto id = static_cast<Service::APT::AppletId>(applet_id);
const auto applet = Applet::Get(id);
ASSERT_MSG(applet != nullptr, "Applet doesn't exist! applet_id={:08X}", id);
if (applet->IsActive()) {
applet->Update();
}
// If the applet is still running after the last update, reschedule the event
if (applet->IsRunning()) {
Core::System::GetInstance().CoreTiming().ScheduleEvent(
usToCycles(applet_update_interval_us) - cycles_late, applet_update_event, applet_id);
} else {
// Otherwise the applet has terminated, in which case we should clean it up
applets[id] = nullptr;
}
}
bool Applet::IsRunning() const {
return is_running;
}
@ -59,4 +140,13 @@ void Applet::CloseApplet(std::shared_ptr<Kernel::Object> object, const std::vect
is_running = false;
}
void Init() {
// Register the applet update callback
applet_update_event = Core::System::GetInstance().CoreTiming().RegisterEvent(
"HLE Applet Update Event", AppletUpdateEvent);
}
void Shutdown() {
Core::System::GetInstance().CoreTiming().RemoveEvent(applet_update_event);
}
} // namespace HLE::Applets

View File

@ -14,6 +14,24 @@ class Applet {
public:
virtual ~Applet() = default;
/**
* Creates an instance of the Applet subclass identified by the parameter.
* and stores it in a global map.
* @param id Id of the applet to create.
* @param parent Id of the applet's parent.
* @param preload Whether the applet is being preloaded.
* @returns Result Whether the operation was successful or not.
*/
static Result Create(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload,
const std::shared_ptr<Service::APT::AppletManager>& manager);
/**
* Retrieves the Applet instance identified by the specified id.
* @param id Id of the Applet to retrieve.
* @returns Requested Applet or nullptr if not found.
*/
static std::shared_ptr<Applet> Get(Service::APT::AppletId id);
/**
* Handles a parameter from the application.
* @param parameter Parameter data to handle.
@ -37,9 +55,9 @@ public:
virtual void Update() = 0;
protected:
Applet(Core::System& system, Service::APT::AppletId id, Service::APT::AppletId parent,
bool preload, std::weak_ptr<Service::APT::AppletManager> manager)
: system(system), id(id), parent(parent), preload(preload), manager(std::move(manager)) {}
Applet(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload,
std::weak_ptr<Service::APT::AppletManager> manager)
: id(id), parent(parent), preload(preload), manager(std::move(manager)) {}
/**
* Handles a parameter from the application.
@ -61,8 +79,6 @@ protected:
*/
virtual Result Finalize() = 0;
Core::System& system;
Service::APT::AppletId id; ///< Id of this Applet
Service::APT::AppletId parent; ///< Id of this Applet's parent
bool preload; ///< Whether the Applet is being preloaded.
@ -81,4 +97,9 @@ private:
std::weak_ptr<Service::APT::AppletManager> manager;
};
/// Initializes the HLE applets
void Init();
/// Shuts down the HLE applets
void Shutdown();
} // namespace HLE::Applets

View File

@ -28,7 +28,7 @@ Result ErrEula::ReceiveParameterImpl(const Service::APT::MessageParameter& param
// TODO: allocated memory never released
using Kernel::MemoryPermission;
// Create a SharedMemory that directly points to this heap block.
framebuffer_memory = system.Kernel().CreateSharedMemoryForApplet(
framebuffer_memory = Core::System::GetInstance().Kernel().CreateSharedMemoryForApplet(
0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite,
"ErrEula Memory");

View File

@ -11,9 +11,9 @@ namespace HLE::Applets {
class ErrEula final : public Applet {
public:
explicit ErrEula(Core::System& system, Service::APT::AppletId id, Service::APT::AppletId parent,
bool preload, std::weak_ptr<Service::APT::AppletManager> manager)
: Applet(system, id, parent, preload, std::move(manager)) {}
explicit ErrEula(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload,
std::weak_ptr<Service::APT::AppletManager> manager)
: Applet(id, parent, preload, std::move(manager)) {}
Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override;
Result Start(const Service::APT::MessageParameter& parameter) override;

View File

@ -35,7 +35,7 @@ Result MiiSelector::ReceiveParameterImpl(const Service::APT::MessageParameter& p
using Kernel::MemoryPermission;
// Create a SharedMemory that directly points to this heap block.
framebuffer_memory = system.Kernel().CreateSharedMemoryForApplet(
framebuffer_memory = Core::System::GetInstance().Kernel().CreateSharedMemoryForApplet(
0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite,
"MiiSelector Memory");
@ -57,7 +57,7 @@ Result MiiSelector::Start(const Service::APT::MessageParameter& parameter) {
std::memcpy(&config, parameter.buffer.data(), parameter.buffer.size());
using namespace Frontend;
frontend_applet = system.GetMiiSelector();
frontend_applet = Core::System::GetInstance().GetMiiSelector();
ASSERT(frontend_applet);
MiiSelectorConfig frontend_config = ToFrontendConfig(config);

View File

@ -62,9 +62,9 @@ ASSERT_REG_POSITION(guest_mii_name, 0x6C);
class MiiSelector final : public Applet {
public:
MiiSelector(Core::System& system, Service::APT::AppletId id, Service::APT::AppletId parent,
bool preload, std::weak_ptr<Service::APT::AppletManager> manager)
: Applet(system, id, parent, preload, std::move(manager)) {}
MiiSelector(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload,
std::weak_ptr<Service::APT::AppletManager> manager)
: Applet(id, parent, preload, std::move(manager)) {}
Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override;
Result Start(const Service::APT::MessageParameter& parameter) override;

View File

@ -28,7 +28,7 @@ Result Mint::ReceiveParameterImpl(const Service::APT::MessageParameter& paramete
// TODO: allocated memory never released
using Kernel::MemoryPermission;
// Create a SharedMemory that directly points to this heap block.
framebuffer_memory = system.Kernel().CreateSharedMemoryForApplet(
framebuffer_memory = Core::System::GetInstance().Kernel().CreateSharedMemoryForApplet(
0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite,
"Mint Memory");

View File

@ -11,9 +11,9 @@ namespace HLE::Applets {
class Mint final : public Applet {
public:
explicit Mint(Core::System& system, Service::APT::AppletId id, Service::APT::AppletId parent,
bool preload, std::weak_ptr<Service::APT::AppletManager> manager)
: Applet(system, id, parent, preload, std::move(manager)) {}
explicit Mint(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload,
std::weak_ptr<Service::APT::AppletManager> manager)
: Applet(id, parent, preload, std::move(manager)) {}
Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override;
Result Start(const Service::APT::MessageParameter& parameter) override;

View File

@ -32,7 +32,7 @@ Result SoftwareKeyboard::ReceiveParameterImpl(Service::APT::MessageParameter con
using Kernel::MemoryPermission;
// Create a SharedMemory that directly points to this heap block.
framebuffer_memory = system.Kernel().CreateSharedMemoryForApplet(
framebuffer_memory = Core::System::GetInstance().Kernel().CreateSharedMemoryForApplet(
0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite,
"SoftwareKeyboard Memory");
@ -99,7 +99,7 @@ Result SoftwareKeyboard::Start(Service::APT::MessageParameter const& parameter)
DrawScreenKeyboard();
using namespace Frontend;
frontend_applet = system.GetSoftwareKeyboard();
frontend_applet = Core::System::GetInstance().GetSoftwareKeyboard();
ASSERT(frontend_applet);
frontend_applet->Execute(ToFrontendConfig(config));

View File

@ -175,9 +175,9 @@ static_assert(sizeof(SoftwareKeyboardConfig) == 0x400, "Software Keyboard Config
class SoftwareKeyboard final : public Applet {
public:
SoftwareKeyboard(Core::System& system, Service::APT::AppletId id, Service::APT::AppletId parent,
bool preload, std::weak_ptr<Service::APT::AppletManager> manager)
: Applet(system, id, parent, preload, std::move(manager)) {}
SoftwareKeyboard(Service::APT::AppletId id, Service::APT::AppletId parent, bool preload,
std::weak_ptr<Service::APT::AppletManager> manager)
: Applet(id, parent, preload, std::move(manager)) {}
Result ReceiveParameterImpl(const Service::APT::MessageParameter& parameter) override;
Result Start(const Service::APT::MessageParameter& parameter) override;

View File

@ -22,22 +22,22 @@ std::shared_ptr<ResourceLimit> ResourceLimit::Create(KernelSystem& kernel, std::
}
s32 ResourceLimit::GetCurrentValue(ResourceLimitType type) const {
const auto index = static_cast<std::size_t>(type);
const auto index = static_cast<size_t>(type);
return m_current_values[index];
}
s32 ResourceLimit::GetLimitValue(ResourceLimitType type) const {
const auto index = static_cast<std::size_t>(type);
const auto index = static_cast<size_t>(type);
return m_limit_values[index];
}
void ResourceLimit::SetLimitValue(ResourceLimitType type, s32 value) {
const auto index = static_cast<std::size_t>(type);
const auto index = static_cast<size_t>(type);
m_limit_values[index] = value;
}
bool ResourceLimit::Reserve(ResourceLimitType type, s32 amount) {
const auto index = static_cast<std::size_t>(type);
const auto index = static_cast<size_t>(type);
const s32 limit = m_limit_values[index];
const s32 new_value = m_current_values[index] + amount;
if (new_value > limit) {
@ -50,7 +50,7 @@ bool ResourceLimit::Reserve(ResourceLimitType type, s32 amount) {
}
bool ResourceLimit::Release(ResourceLimitType type, s32 amount) {
const auto index = static_cast<std::size_t>(type);
const auto index = static_cast<size_t>(type);
const s32 value = m_current_values[index];
if (amount > value) {
LOG_ERROR(Kernel, "Amount {} exceeds current value {} for resource type {}", amount, value,

View File

@ -68,7 +68,7 @@ public:
bool Release(ResourceLimitType type, s32 amount);
private:
using ResourceArray = std::array<s32, static_cast<std::size_t>(ResourceLimitType::Max)>;
using ResourceArray = std::array<s32, static_cast<size_t>(ResourceLimitType::Max)>;
ResourceArray m_limit_values{};
ResourceArray m_current_values{};
std::string m_name;

View File

@ -18,7 +18,8 @@ SharedMemory::SharedMemory(KernelSystem& kernel) : Object(kernel), kernel(kernel
SharedMemory::~SharedMemory() {
for (const auto& interval : holding_memory) {
memory_region->Free(interval.lower(), interval.upper() - interval.lower());
kernel.GetMemoryRegion(MemoryRegion::SYSTEM)
->Free(interval.lower(), interval.upper() - interval.lower());
}
auto process = owner_process.lock();
@ -38,18 +39,17 @@ ResultVal<std::shared_ptr<SharedMemory>> KernelSystem::CreateSharedMemory(
std::shared_ptr<Process> owner_process, u32 size, MemoryPermission permissions,
MemoryPermission other_permissions, VAddr address, MemoryRegion region, std::string name) {
auto memory_region = GetMemoryRegion(region);
auto shared_memory = std::make_shared<SharedMemory>(*this);
shared_memory->owner_process = owner_process;
shared_memory->name = std::move(name);
shared_memory->size = size;
shared_memory->memory_region = memory_region;
shared_memory->permissions = permissions;
shared_memory->other_permissions = other_permissions;
if (address == 0) {
// We need to allocate a block from the Linear Heap ourselves.
// We'll manually allocate some memory from the linear heap in the specified region.
auto memory_region = GetMemoryRegion(region);
auto offset = memory_region->LinearAllocate(size);
ASSERT_MSG(offset, "Not enough space in region to allocate shared memory!");
@ -93,7 +93,6 @@ std::shared_ptr<SharedMemory> KernelSystem::CreateSharedMemoryForApplet(
shared_memory->owner_process = std::weak_ptr<Process>();
shared_memory->name = std::move(name);
shared_memory->size = size;
shared_memory->memory_region = memory_region;
shared_memory->permissions = permissions;
shared_memory->other_permissions = other_permissions;
for (const auto& interval : backing_blocks) {
@ -127,7 +126,7 @@ Result SharedMemory::Map(Process& target_process, VAddr address, MemoryPermissio
// Heap-backed memory blocks can not be mapped with other_permissions = DontCare
if (base_address != 0 && other_permissions == MemoryPermission::DontCare) {
LOG_ERROR(Kernel, "cannot map id={}, address=0x{:08X} name={}, permissions don't match",
LOG_ERROR(Kernel, "cannot map id={}, address=0x{08X} name={}, permissions don't match",
GetObjectId(), address, name);
return ResultInvalidCombination;
}

View File

@ -94,8 +94,6 @@ private:
std::vector<std::pair<MemoryRef, u32>> backing_blocks;
/// Size of the memory block. Page-aligned.
u32 size = 0;
/// Region of memory this block exists in.
std::shared_ptr<MemoryRegionInfo> memory_region = nullptr;
/// Permission restrictions applied to the process which created the block.
MemoryPermission permissions{};
/// Permission restrictions applied to other processes mapping the block.
@ -118,7 +116,6 @@ private:
ar& linear_heap_phys_offset;
ar& backing_blocks;
ar& size;
ar& memory_region;
ar& permissions;
ar& other_permissions;
ar& owner_process;

View File

@ -1686,8 +1686,8 @@ Result SVC::AcceptSession(Handle* out_server_session, Handle server_port_handle)
return current_process->handle_table.Create(out_server_session, std::move(session));
}
static void CopyStringPart(char* out, const char* in, std::size_t offset, std::size_t max_length) {
std::size_t str_size = strlen(in);
static void CopyStringPart(char* out, const char* in, size_t offset, size_t max_length) {
size_t str_size = strlen(in);
if (offset < str_size) {
strncpy(out, in + offset, max_length - 1);
out[max_length - 1] = '\0';

View File

@ -60,7 +60,12 @@ void Thread::Acquire(Thread* thread) {
Thread::Thread(KernelSystem& kernel, u32 core_id)
: WaitObject(kernel), core_id(core_id), thread_manager(kernel.GetThreadManager(core_id)) {}
Thread::~Thread() = default;
Thread::~Thread() {
auto process = owner_process.lock();
if (process) {
process->resource_limit->Release(ResourceLimitType::Thread, 1);
}
}
Thread* ThreadManager::GetCurrentThread() const {
return current_thread.get();
@ -96,7 +101,6 @@ void Thread::Stop() {
((tls_address - Memory::TLS_AREA_VADDR) % Memory::CITRA_PAGE_SIZE) / Memory::TLS_ENTRY_SIZE;
if (auto process = owner_process.lock()) {
process->tls_slots[tls_page].reset(tls_slot);
process->resource_limit->Release(ResourceLimitType::Thread, 1);
}
}
@ -244,7 +248,7 @@ void Thread::WakeAfterDelay(s64 nanoseconds, bool thread_safe_mode) {
// Don't schedule a wakeup if the thread wants to wait forever
if (nanoseconds == -1)
return;
std::size_t core = thread_safe_mode ? core_id : std::numeric_limits<std::size_t>::max();
size_t core = thread_safe_mode ? core_id : std::numeric_limits<std::size_t>::max();
thread_manager.kernel.timing.ScheduleEvent(nsToCycles(nanoseconds),
thread_manager.ThreadWakeupEventType, thread_id,

View File

@ -20,9 +20,6 @@
#include "core/hle/service/soc/soc_u.h"
#include "core/memory.h"
SERIALIZE_EXPORT_IMPL(Service::AC::Module)
SERVICE_CONSTRUCT_IMPL(Service::AC::Module)
namespace Service::AC {
void Module::Interface::CreateDefaultConfig(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
@ -99,7 +96,7 @@ void Module::Interface::GetWifiStatus(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
bool can_reach_internet = false;
std::shared_ptr<SOC::SOC_U> socu_module = SOC::GetService(ac->system);
std::shared_ptr<SOC::SOC_U> socu_module = SOC::GetService(Core::System::GetInstance());
if (socu_module) {
can_reach_internet = socu_module->GetDefaultInterfaceInfo().has_value();
}
@ -197,13 +194,11 @@ Module::Interface::Interface(std::shared_ptr<Module> ac, const char* name, u32 m
void InstallInterfaces(Core::System& system) {
auto& service_manager = system.ServiceManager();
auto ac = std::make_shared<Module>(system);
auto ac = std::make_shared<Module>();
std::make_shared<AC_I>(ac)->InstallAsService(service_manager);
std::make_shared<AC_U>(ac)->InstallAsService(service_manager);
}
Module::Module(Core::System& system_) : system(system_) {}
template <class Archive>
void Module::serialize(Archive& ar, const unsigned int) {
ar& ac_connected;
@ -212,6 +207,7 @@ void Module::serialize(Archive& ar, const unsigned int) {
ar& disconnect_event;
// default_config is never written to
}
SERIALIZE_IMPL(Module)
} // namespace Service::AC
SERIALIZE_IMPL(Service::AC::Module)

View File

@ -19,9 +19,6 @@ class Event;
namespace Service::AC {
class Module final {
public:
explicit Module(Core::System& system_);
~Module() = default;
class Interface : public ServiceFramework<Interface> {
public:
Interface(std::shared_ptr<Module> ac, const char* name, u32 max_session);
@ -172,16 +169,11 @@ protected:
std::shared_ptr<Kernel::Event> disconnect_event;
private:
Core::System& system;
template <class Archive>
void serialize(Archive& ar, const unsigned int);
void serialize(Archive& ar, const unsigned int file_version);
friend class boost::serialization::access;
};
void InstallInterfaces(Core::System& system);
} // namespace Service::AC
BOOST_CLASS_EXPORT_KEY(Service::AC::Module)
SERVICE_CONSTRUCT(Service::AC::Module)

View File

@ -9,7 +9,6 @@
#include <cryptopp/modes.h>
#include <fmt/format.h>
#include "common/alignment.h"
#include "common/archives.h"
#include "common/common_paths.h"
#include "common/file_util.h"
#include "common/logging/log.h"
@ -34,9 +33,6 @@
#include "core/loader/smdh.h"
#include "core/nus_download.h"
SERIALIZE_EXPORT_IMPL(Service::AM::Module)
SERVICE_CONSTRUCT_IMPL(Service::AM::Module)
namespace Service::AM {
constexpr u16 PLATFORM_CTR = 0x0004;
@ -85,9 +81,8 @@ public:
std::vector<CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption> content;
};
CIAFile::CIAFile(Core::System& system_, Service::FS::MediaType media_type)
: system(system_), media_type(media_type),
decryption_state(std::make_unique<DecryptionState>()) {}
CIAFile::CIAFile(Service::FS::MediaType media_type)
: media_type(media_type), decryption_state(std::make_unique<DecryptionState>()) {}
CIAFile::~CIAFile() {
Close();
@ -366,7 +361,8 @@ bool CIAFile::Close() const {
// are closed.
std::string to_delete =
GetTitleContentPath(media_type, old_tmd.GetTitleID(), old_index);
if (!system.IsPoweredOn() || !system.SetSelfDelete(to_delete)) {
if (!(Core::System::GetInstance().IsPoweredOn() &&
Core::System::GetInstance().SetSelfDelete(to_delete))) {
FileUtil::Delete(to_delete);
}
}
@ -429,7 +425,6 @@ InstallStatus InstallCIA(const std::string& path,
FileSys::CIAContainer container;
if (container.Load(path) == Loader::ResultStatus::Success) {
Service::AM::CIAFile installFile(
Core::System::GetInstance(),
Service::AM::GetTitleMediaType(container.GetTitleMetadata().GetTitleID()));
bool title_key_available = container.GetTicket().GetTitleKey().has_value();
@ -507,7 +502,7 @@ InstallStatus InstallCIA(const std::string& path,
InstallStatus InstallFromNus(u64 title_id, int version) {
LOG_DEBUG(Service_AM, "Downloading {:X}", title_id);
CIAFile install_file{Core::System::GetInstance(), GetTitleMediaType(title_id)};
CIAFile install_file{GetTitleMediaType(title_id)};
std::string path = fmt::format("/ccs/download/{:016X}/tmd", title_id);
if (version != -1) {
@ -1332,7 +1327,7 @@ void Module::Interface::BeginImportProgram(Kernel::HLERequestContext& ctx) {
// Citra will store contents out to sdmc/nand
const FileSys::Path cia_path = {};
auto file = std::make_shared<Service::FS::File>(
am->system.Kernel(), std::make_unique<CIAFile>(am->system, media_type), cia_path);
am->kernel, std::make_unique<CIAFile>(media_type), cia_path);
am->cia_installing = true;
@ -1359,7 +1354,7 @@ void Module::Interface::BeginImportProgramTemporarily(Kernel::HLERequestContext&
// contents out to sdmc/nand
const FileSys::Path cia_path = {};
auto file = std::make_shared<Service::FS::File>(
am->system.Kernel(), std::make_unique<CIAFile>(am->system, FS::MediaType::NAND), cia_path);
am->kernel, std::make_unique<CIAFile>(FS::MediaType::NAND), cia_path);
am->cia_installing = true;
@ -1774,8 +1769,8 @@ void Module::Interface::BeginImportTicket(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
// Create our TicketFile handle for the app to write to
auto file = std::make_shared<Service::FS::File>(
am->system.Kernel(), std::make_unique<TicketFile>(), FileSys::Path{});
auto file = std::make_shared<Service::FS::File>(am->kernel, std::make_unique<TicketFile>(),
FileSys::Path{});
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
rb.Push(ResultSuccess); // No error
@ -1794,19 +1789,13 @@ void Module::Interface::EndImportTicket(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
}
template <class Archive>
void Module::serialize(Archive& ar, const unsigned int) {
ar& cia_installing;
ar& am_title_list;
ar& system_updater_mutex;
}
SERIALIZE_IMPL(Module)
Module::Module(Core::System& system) : system(system) {
Module::Module(Core::System& system) : kernel(system.Kernel()) {
ScanForAllTitles();
system_updater_mutex = system.Kernel().CreateMutex(false, "AM::SystemUpdaterMutex");
}
Module::Module(Kernel::KernelSystem& kernel) : kernel(kernel) {}
Module::~Module() = default;
void InstallInterfaces(Core::System& system) {

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