Compare commits

..

16 Commits

Author SHA1 Message Date
GPUCode
cfdb10a7ba renderer_software: Add jit compiler for tev stages 2023-07-17 18:12:02 +03:00
GPUCode
8012b28b92 renderer_software: Move memory access out of the raster loop
* Profiling shows this has a significant impact
2023-07-16 03:45:57 +03:00
GPUCode
531d280461 renderer_software: Multi-thread processing
* Doubles the performance in most cases
2023-07-16 03:02:55 +03:00
Narr the Reg
d702915624 Remove some global usages of system (#6688) 2023-07-11 21:43:28 -07:00
GPUCode
943d5eeddf citra_qt: Remove image allocation limit (#6682) 2023-07-11 21:43:19 -07:00
Steveice10
f3ac6f054f audio_core: Clean up cubeb backend. (#6677) 2023-07-11 21:43:07 -07:00
Wunk
a94af8ea62 shader_jit: Add optimizations up to x86-64-v4 (#6668) 2023-07-11 09:21:37 -07:00
Ikko Eltociear Ashimine
6da4853360 kernel: fix typo in recorder.cpp (#6686) 2023-07-11 02:56:36 +02:00
GPUCode
b738584832 android: Update layout indexes (#6673) 2023-07-10 03:05:18 +03:00
SachinVin
1cb34ea0d3 core/memory.*:constify GetPhysicalPointer;
audio_core\hle\source.h: constify `memory_system`
2023-07-09 16:37:28 +05:30
Steveice10
662bb9ba77 hle: Stub some service calls used by the home menu. (#6675) 2023-07-07 22:05:38 -07:00
Narr the Reg
26e3f96983 service: nfc: Start adapter communication on scan (#6671) 2023-07-07 19:02:39 -07:00
Steveice10
cd3244f139 mic_u: Fix up logic for populating shared memory sample buffer. (#6669) 2023-07-07 19:02:31 -07:00
Vitor K
e5310b25d4 ci-merge: remove use of deprecated pushedDate (#6676) 2023-07-07 22:30:15 +02:00
GPUCode
80033b84cb renderer_software: Fix screen rendering (#6664) 2023-07-06 17:15:59 -07:00
GPUCode
cf9bb90ae3 code: Use std::span where appropriate (#6658)
* code: Use std::span when possible

* code: Prefix memcpy and memcmp with std::
2023-07-07 01:52:40 +03:00
178 changed files with 2224 additions and 2441 deletions

View File

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

View File

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

View File

@@ -67,7 +67,7 @@ JNIEXPORT jlong JNICALL Java_org_citra_citra_1emu_model_GameInfo_initialize(JNIE
Loader::SMDH* smdh = nullptr;
if (Loader::IsValidSMDH(smdh_data)) {
smdh = new Loader::SMDH;
memcpy(smdh, smdh_data.data(), sizeof(Loader::SMDH));
std::memcpy(smdh, smdh_data.data(), sizeof(Loader::SMDH));
}
return reinterpret_cast<jlong>(smdh);
}

View File

@@ -151,7 +151,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
Camera::RegisterFactory("ndk", std::move(ndk_factory));
// Register frontend applets
Frontend::RegisterDefaultApplets();
Frontend::RegisterDefaultApplets(system);
system.RegisterMiiSelector(std::make_shared<MiiSelector::AndroidMiiSelector>());
system.RegisterSoftwareKeyboard(std::make_shared<SoftwareKeyboard::AndroidKeyboard>());

View File

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

View File

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

View File

@@ -5,7 +5,7 @@
#pragma once
#include <memory>
#include <vector>
#include <span>
#include <boost/serialization/access.hpp>
#include "audio_core/audio_types.h"
#include "audio_core/time_stretch.h"
@@ -80,7 +80,7 @@ public:
* @param pipe_number The Pipe ID
* @param buffer The data to write to the pipe.
*/
virtual void PipeWrite(DspPipe pipe_number, const std::vector<u8>& buffer) = 0;
virtual void PipeWrite(DspPipe pipe_number, std::span<const u8> buffer) = 0;
/// Returns a reference to the array backing DSP memory
virtual std::array<u8, Memory::DSP_RAM_SIZE>& GetDspMemory() = 0;
@@ -89,7 +89,7 @@ public:
virtual void SetServiceToInterrupt(std::weak_ptr<Service::DSP::DSP_DSP> dsp) = 0;
/// Loads the DSP program
virtual void LoadComponent(const std::vector<u8>& buffer) = 0;
virtual void LoadComponent(std::span<const u8> buffer) = 0;
/// Unloads the DSP program
virtual void UnloadComponent() = 0;

View File

@@ -66,7 +66,7 @@ public:
bool RecvDataIsReady(u32 register_number) const;
std::vector<u8> PipeRead(DspPipe pipe_number, std::size_t length);
std::size_t GetPipeReadableSize(DspPipe pipe_number) const;
void PipeWrite(DspPipe pipe_number, const std::vector<u8>& buffer);
void PipeWrite(DspPipe pipe_number, std::span<const u8> buffer);
std::array<u8, Memory::DSP_RAM_SIZE>& GetDspMemory();
@@ -244,7 +244,7 @@ size_t DspHle::Impl::GetPipeReadableSize(DspPipe pipe_number) const {
return pipe_data[pipe_index].size();
}
void DspHle::Impl::PipeWrite(DspPipe pipe_number, const std::vector<u8>& buffer) {
void DspHle::Impl::PipeWrite(DspPipe pipe_number, std::span<const u8> buffer) {
switch (pipe_number) {
case DspPipe::Audio: {
if (buffer.size() != 4) {
@@ -494,7 +494,7 @@ size_t DspHle::GetPipeReadableSize(DspPipe pipe_number) const {
return impl->GetPipeReadableSize(pipe_number);
}
void DspHle::PipeWrite(DspPipe pipe_number, const std::vector<u8>& buffer) {
void DspHle::PipeWrite(DspPipe pipe_number, std::span<const u8> buffer) {
impl->PipeWrite(pipe_number, buffer);
}
@@ -506,7 +506,7 @@ void DspHle::SetServiceToInterrupt(std::weak_ptr<DSP_DSP> dsp) {
impl->SetServiceToInterrupt(std::move(dsp));
}
void DspHle::LoadComponent(const std::vector<u8>& component_data) {
void DspHle::LoadComponent(std::span<const u8> component_data) {
// HLE doesn't need DSP program. Only log some info here
LOG_INFO(Service_DSP, "Firmware hash: {:#018x}",
Common::ComputeHash64(component_data.data(), component_data.size()));

View File

@@ -30,13 +30,13 @@ public:
void SetSemaphore(u16 semaphore_value) override;
std::vector<u8> PipeRead(DspPipe pipe_number, std::size_t length) override;
std::size_t GetPipeReadableSize(DspPipe pipe_number) const override;
void PipeWrite(DspPipe pipe_number, const std::vector<u8>& buffer) override;
void PipeWrite(DspPipe pipe_number, std::span<const u8> buffer) override;
std::array<u8, Memory::DSP_RAM_SIZE>& GetDspMemory() override;
void SetServiceToInterrupt(std::weak_ptr<Service::DSP::DSP_DSP> dsp) override;
void LoadComponent(const std::vector<u8>& buffer) override;
void LoadComponent(std::span<const u8> buffer) override;
void UnloadComponent() override;
private:

View File

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

View File

@@ -26,7 +26,7 @@ enum class SegmentType : u8 {
class Dsp1 {
public:
explicit Dsp1(const std::vector<u8>& raw);
explicit Dsp1(std::span<const u8> raw);
struct Header {
std::array<u8, 0x100> signature;
@@ -65,7 +65,7 @@ public:
bool recv_data_on_start;
};
Dsp1::Dsp1(const std::vector<u8>& raw) {
Dsp1::Dsp1(std::span<const u8> raw) {
Header header;
std::memcpy(&header, raw.data(), sizeof(header));
recv_data_on_start = header.recv_data_on_start != 0;
@@ -220,7 +220,7 @@ struct DspLle::Impl final {
}
}
void WritePipe(u8 pipe_index, const std::vector<u8>& data) {
void WritePipe(u8 pipe_index, std::span<const u8> data) {
PipeStatus pipe_status = GetPipeStatus(pipe_index, PipeDirection::CPUtoDSP);
bool need_update = false;
const u8* buffer_ptr = data.data();
@@ -304,7 +304,7 @@ struct DspLle::Impl final {
return size & PipeStatus::PtrMask;
}
void LoadComponent(const std::vector<u8>& buffer) {
void LoadComponent(std::span<const u8> buffer) {
if (loaded) {
LOG_ERROR(Audio_DSP, "Component already loaded!");
return;
@@ -400,7 +400,7 @@ std::size_t DspLle::GetPipeReadableSize(DspPipe pipe_number) const {
return impl->GetPipeReadableSize(static_cast<u8>(pipe_number));
}
void DspLle::PipeWrite(DspPipe pipe_number, const std::vector<u8>& buffer) {
void DspLle::PipeWrite(DspPipe pipe_number, std::span<const u8> buffer) {
impl->WritePipe(static_cast<u8>(pipe_number), buffer);
}
@@ -476,7 +476,7 @@ void DspLle::SetRecvDataHandler(u8 index, std::function<void()> handler) {
impl->teakra.SetRecvDataHandler(index, handler);
}
void DspLle::LoadComponent(const std::vector<u8>& buffer) {
void DspLle::LoadComponent(std::span<const u8> buffer) {
impl->LoadComponent(buffer);
}

View File

@@ -4,6 +4,7 @@
#pragma once
#include <span>
#include "audio_core/dsp_interface.h"
namespace Core {
@@ -22,7 +23,7 @@ public:
void SetSemaphore(u16 semaphore_value) override;
std::vector<u8> PipeRead(DspPipe pipe_number, std::size_t length) override;
std::size_t GetPipeReadableSize(DspPipe pipe_number) const override;
void PipeWrite(DspPipe pipe_number, const std::vector<u8>& buffer) override;
void PipeWrite(DspPipe pipe_number, std::span<const u8> buffer) override;
std::array<u8, Memory::DSP_RAM_SIZE>& GetDspMemory() override;
@@ -31,7 +32,7 @@ public:
void SetSemaphoreHandler(std::function<void()> handler);
void SetRecvDataHandler(u8 index, std::function<void()> handler);
void LoadComponent(const std::vector<u8>& buffer) override;
void LoadComponent(const std::span<const u8> buffer) override;
void UnloadComponent() override;
private:

View File

@@ -346,7 +346,7 @@ int main(int argc, char** argv) {
system.ApplySettings();
// Register frontend applets
Frontend::RegisterDefaultApplets();
Frontend::RegisterDefaultApplets(system);
EmuWindow_SDL2::InitializeSDL2();
@@ -354,12 +354,12 @@ int main(int argc, char** argv) {
bool is_secondary) -> std::unique_ptr<EmuWindow_SDL2> {
switch (Settings::values.graphics_api.GetValue()) {
case Settings::GraphicsAPI::OpenGL:
return std::make_unique<EmuWindow_SDL2_GL>(fullscreen, is_secondary);
return std::make_unique<EmuWindow_SDL2_GL>(system, fullscreen, is_secondary);
case Settings::GraphicsAPI::Software:
return std::make_unique<EmuWindow_SDL2_SW>(system, fullscreen, is_secondary);
}
LOG_ERROR(Frontend, "Invalid Graphics API, using OpenGL");
return std::make_unique<EmuWindow_SDL2_GL>(fullscreen, is_secondary);
return std::make_unique<EmuWindow_SDL2_GL>(system, fullscreen, is_secondary);
};
const auto emu_window{create_emu_window(fullscreen, false)};

View File

@@ -109,7 +109,8 @@ void EmuWindow_SDL2::Fullscreen() {
SDL_MaximizeWindow(render_window);
}
EmuWindow_SDL2::EmuWindow_SDL2(bool is_secondary) : EmuWindow(is_secondary) {}
EmuWindow_SDL2::EmuWindow_SDL2(Core::System& system_, bool is_secondary)
: EmuWindow(is_secondary), system(system_) {}
EmuWindow_SDL2::~EmuWindow_SDL2() {
SDL_Quit();
@@ -202,7 +203,7 @@ void EmuWindow_SDL2::OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minima
void EmuWindow_SDL2::UpdateFramerateCounter() {
const u32 current_time = SDL_GetTicks();
if (current_time > last_time + 2000) {
const auto results = Core::System::GetInstance().GetAndResetPerfStats();
const auto results = system.GetAndResetPerfStats();
const auto title =
fmt::format("Citra {} | {}-{} | FPS: {:.0f} ({:.0f}%)", Common::g_build_fullname,
Common::g_scm_branch, Common::g_scm_desc, results.game_fps,

View File

@@ -10,9 +10,13 @@
struct SDL_Window;
namespace Core {
class System;
}
class EmuWindow_SDL2 : public Frontend::EmuWindow {
public:
explicit EmuWindow_SDL2(bool is_secondary);
explicit EmuWindow_SDL2(Core::System& system_, bool is_secondary);
~EmuWindow_SDL2();
/// Initializes SDL2
@@ -78,4 +82,6 @@ protected:
/// Keeps track of how often to update the title bar during gameplay
u32 last_time = 0;
Core::System& system;
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -129,7 +129,7 @@ void ConfigurePerGame::HandleApplyButtonClicked() {
static QPixmap GetQPixmapFromSMDH(std::vector<u8>& smdh_data) {
Loader::SMDH smdh;
memcpy(&smdh, smdh_data.data(), sizeof(Loader::SMDH));
std::memcpy(&smdh, smdh_data.data(), sizeof(Loader::SMDH));
bool large = true;
std::vector<u16> icon_data = smdh.GetIcon(large);

View File

@@ -487,7 +487,7 @@ void GraphicsVertexShaderWidget::Reload(bool replace_vertex_data, void* vertex_d
if (replace_vertex_data) {
if (vertex_data) {
memcpy(&input_vertex, vertex_data, sizeof(input_vertex));
std::memcpy(&input_vertex, vertex_data, sizeof(input_vertex));
for (unsigned attr = 0; attr < 16; ++attr) {
for (unsigned comp = 0; comp < 4; ++comp) {
input_data[4 * attr + comp]->setText(

View File

@@ -18,7 +18,7 @@ QString RecordDialog::FormatObject(const IPCDebugger::ObjectInfo& object) const
.arg(object.id, 8, 16, QLatin1Char('0'));
}
QString RecordDialog::FormatCmdbuf(const std::vector<u32>& cmdbuf) const {
QString RecordDialog::FormatCmdbuf(std::span<const u32> cmdbuf) const {
QString result;
for (std::size_t i = 0; i < cmdbuf.size(); ++i) {
result.append(

View File

@@ -4,6 +4,7 @@
#include <array>
#include <memory>
#include <span>
#include <string>
#include <vector>
#include <QDialog>
@@ -28,7 +29,7 @@ public:
private:
QString FormatObject(const IPCDebugger::ObjectInfo& object) const;
QString FormatCmdbuf(const std::vector<u32>& cmdbuf) const;
QString FormatCmdbuf(std::span<const u32> cmdbuf) const;
void UpdateCmdbufDisplay();
std::unique_ptr<Ui::RecordDialog> ui;

View File

@@ -64,7 +64,7 @@ WaitTreeItem* WaitTreeItem::Parent() const {
return parent;
}
const std::vector<std::unique_ptr<WaitTreeItem>>& WaitTreeItem::Children() const {
std::span<const std::unique_ptr<WaitTreeItem>> WaitTreeItem::Children() const {
return children;
}

View File

@@ -4,6 +4,7 @@
#pragma once
#include <span>
#include <QAbstractItemModel>
#include <QDockWidget>
#include <QTreeView>
@@ -36,7 +37,7 @@ public:
void Expand();
WaitTreeItem* Parent() const;
const std::vector<std::unique_ptr<WaitTreeItem>>& Children() const;
std::span<const std::unique_ptr<WaitTreeItem>> Children() const;
std::size_t Row() const;
static std::vector<std::unique_ptr<WaitTreeThread>> MakeThreadItemList();

View File

@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include <memory>
#include <vector>
#include <QDialog>
#include "core/dumping/ffmpeg_backend.h"

View File

@@ -6,8 +6,10 @@
#include <algorithm>
#include <map>
#include <span>
#include <unordered_map>
#include <utility>
#include <vector>
#include <QCoreApplication>
#include <QFileInfo>
#include <QImage>
@@ -153,7 +155,7 @@ public:
static constexpr int LongTitleRole = SortRole + 5;
GameListItemPath() = default;
GameListItemPath(const QString& game_path, const std::vector<u8>& smdh_data, u64 program_id,
GameListItemPath(const QString& game_path, std::span<const u8> smdh_data, u64 program_id,
u64 extdata_id) {
setData(type(), TypeRole);
setData(game_path, FullPathRole);
@@ -178,7 +180,7 @@ public:
}
Loader::SMDH smdh;
memcpy(&smdh, smdh_data.data(), sizeof(Loader::SMDH));
std::memcpy(&smdh, smdh_data.data(), sizeof(Loader::SMDH));
// Get icon from SMDH
if (UISettings::values.game_list_icon_size.GetValue() !=
@@ -286,7 +288,7 @@ public:
class GameListItemRegion : public GameListItem {
public:
GameListItemRegion() = default;
explicit GameListItemRegion(const std::vector<u8>& smdh_data) {
explicit GameListItemRegion(std::span<const u8> smdh_data) {
setData(type(), TypeRole);
if (!Loader::IsValidSMDH(smdh_data)) {
@@ -295,7 +297,7 @@ public:
}
Loader::SMDH smdh;
memcpy(&smdh, smdh_data.data(), sizeof(Loader::SMDH));
std::memcpy(&smdh, smdh_data.data(), sizeof(Loader::SMDH));
setText(GetRegionFromSMDH(smdh));
setData(GetRegionFromSMDH(smdh), SortRole);

View File

@@ -80,7 +80,7 @@ const static std::unordered_map<VideoCore::LoadCallbackStage, const char*> progr
static QPixmap GetQPixmapFromSMDH(std::vector<u8>& smdh_data) {
Loader::SMDH smdh;
memcpy(&smdh, smdh_data.data(), sizeof(Loader::SMDH));
std::memcpy(&smdh, smdh_data.data(), sizeof(Loader::SMDH));
bool large = true;
std::vector<u16> icon_data = smdh.GetIcon(large);

View File

@@ -1223,7 +1223,7 @@ void GMainWindow::BootGame(const QString& filename) {
}
// Create and start the emulation thread
emu_thread = std::make_unique<EmuThread>(*render_window);
emu_thread = std::make_unique<EmuThread>(system, *render_window);
emit EmulationStarting(emu_thread.get());
emu_thread->start();
@@ -1814,7 +1814,7 @@ void GMainWindow::OnLoadComplete() {
void GMainWindow::OnMenuReportCompatibility() {
if (!NetSettings::values.citra_token.empty() && !NetSettings::values.citra_username.empty()) {
CompatDB compatdb{this};
CompatDB compatdb{system.TelemetrySession(), this};
compatdb.exec();
} else {
QMessageBox::critical(this, tr("Missing Citra Account"),
@@ -2931,7 +2931,7 @@ int main(int argc, char* argv[]) {
GMainWindow main_window(system);
// Register frontend applets
Frontend::RegisterDefaultApplets();
Frontend::RegisterDefaultApplets(system);
system.RegisterMiiSelector(std::make_shared<QtMiiSelector>(main_window));
system.RegisterSoftwareKeyboard(std::make_shared<QtKeyboard>(main_window));

View File

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

View File

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

View File

@@ -53,7 +53,8 @@ add_library(citra_common STATIC
archives.h
assert.h
atomic_ops.h
bit_cast.h
detached_tasks.cpp
detached_tasks.h
bit_field.h
bit_set.h
bounded_threadsafe_queue.h
@@ -65,8 +66,6 @@ add_library(citra_common STATIC
common_precompiled_headers.h
common_types.h
construct.h
detached_tasks.cpp
detached_tasks.h
dynamic_library/dynamic_library.cpp
dynamic_library/dynamic_library.h
dynamic_library/fdk-aac.cpp
@@ -112,7 +111,6 @@ add_library(citra_common STATIC
settings.cpp
settings.h
slot_vector.h
socket_types.h
serialization/atomic.h
serialization/boost_discrete_interval.hpp
serialization/boost_flat_set.h

View File

@@ -13,20 +13,26 @@
// lambda and force the compiler to not inline it.
#define ASSERT(_a_) \
([&]() CITRA_NO_INLINE { \
do \
if (!(_a_)) [[unlikely]] { \
LOG_CRITICAL(Debug, "Assertion Failed!"); \
Crash(); \
} \
}())
[]() CITRA_NO_INLINE CITRA_NO_RETURN { \
LOG_CRITICAL(Debug, "Assertion Failed!"); \
Crash(); \
exit(1); \
}(); \
} \
while (0)
#define ASSERT_MSG(_a_, ...) \
([&]() CITRA_NO_INLINE { \
if (!(_a_)) [[unlikely]] { \
LOG_CRITICAL(Debug, "Assertion Failed!\n" __VA_ARGS__); \
Crash(); \
do \
if (!(_a_)) [[unlikely]] { \
[&]() CITRA_NO_INLINE CITRA_NO_RETURN { \
LOG_CRITICAL(Debug, "Assertion Failed!\n" __VA_ARGS__); \
Crash(); \
exit(1); \
}(); \
} \
}())
while (0)
#define UNREACHABLE() \
([]() CITRA_NO_INLINE CITRA_NO_RETURN { \
@@ -52,6 +58,3 @@
#define UNIMPLEMENTED() LOG_CRITICAL(Debug, "Unimplemented code!")
#define UNIMPLEMENTED_MSG(_a_, ...) LOG_CRITICAL(Debug, _a_, __VA_ARGS__)
#define UNIMPLEMENTED_IF(cond) ASSERT_MSG(!(cond), "Unimplemented code!")
#define UNIMPLEMENTED_IF_MSG(cond, ...) ASSERT_MSG(!(cond), __VA_ARGS__)

View File

@@ -1,23 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <version>
#ifdef __cpp_lib_bit_cast
#include <bit>
#endif
namespace Common {
template <typename To, typename From>
constexpr inline To BitCast(const From& from) {
#ifdef __cpp_lib_bit_cast
return std::bit_cast<To>(from);
#else
return __builtin_bit_cast(To, from);
#endif
}
} // namespace Common

View File

@@ -110,15 +110,6 @@ __declspec(dllimport) void __stdcall DebugBreak(void);
return static_cast<T>(key) == 0; \
}
#define CITRA_NON_COPYABLE(cls) \
cls(const cls&) = delete; \
cls& operator=(const cls&) = delete
#define CITRA_NON_MOVEABLE(cls) \
cls(cls&&) = delete; \
cls& operator=(cls&&) = delete
// Generic function to get last error message.
// Call directly after the command or use the error num.
// This function might change the error code.

View File

@@ -855,7 +855,7 @@ const std::string& GetDefaultUserPath(UserPath path) {
return g_default_paths[path];
}
const void UpdateUserPath(UserPath path, const std::string& filename) {
void UpdateUserPath(UserPath path, const std::string& filename) {
if (filename.empty()) {
return;
}

View File

@@ -191,7 +191,7 @@ void SetCurrentRomPath(const std::string& path);
[[nodiscard]] const std::string& GetDefaultUserPath(UserPath path);
// Update the Global Path with the new value
const void UpdateUserPath(UserPath path, const std::string& filename);
void UpdateUserPath(UserPath path, const std::string& filename);
// Returns the path to where the sys file are
[[nodiscard]] std::string GetSysDirectory();

View File

@@ -154,7 +154,7 @@ private:
struct Header {
Header() : id(*(u32*)"DCAC"), key_t_size(sizeof(K)), value_t_size(sizeof(V)) {
memcpy(ver, scm_rev_git_str, 40);
std::memcpy(ver, scm_rev_git_str, 40);
}
const u32 id;

View File

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

View File

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

View File

@@ -11,6 +11,7 @@
#include <cstring>
#include <limits>
#include <new>
#include <span>
#include <type_traits>
#include <vector>
#include "common/common_types.h"
@@ -57,7 +58,7 @@ public:
return push_count;
}
std::size_t Push(const std::vector<T>& input) {
std::size_t Push(std::span<const T> input) {
return Push(input.data(), input.size() / granularity);
}

View File

@@ -505,9 +505,6 @@ struct Values {
// Miscellaneous
Setting<std::string> log_filter{"*:Info", "log_filter"};
// Network
Setting<std::string> network_interface{std::string(), "network_interface"};
// Video Dumping
std::string output_format;
std::string format_options;

View File

@@ -1,143 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_types.h"
#include "common/swap.h"
namespace Network {
/// Address families
enum class Domain : u32 {
UNSPEC = 0,
INET = 2, ///< Address family for IPv4
INET6 = 23,
};
/// Socket types
enum class Type : u32 {
STREAM = 1,
DGRAM = 2,
};
/// Shutdown mode
enum class ShutdownHow {
RD,
WR,
RDWR,
};
enum class FcntlCmd : u32 {
GETFL = 3,
SETFL = 4,
};
enum class SendFlags : u32 {
OOB = 1,
PEEK = 2,
DONTWAIT = 4,
};
DECLARE_ENUM_FLAG_OPERATORS(SendFlags)
/// Array of IPv4 address
using IPv4Address = std::array<u8, 4>;
/// Union to represent the 3DS sockaddr structure
union CTRSockAddr {
/// Structure to represent a raw sockaddr
struct {
u8 len; ///< The length of the entire structure, only the set fields count
u8 sa_family; ///< The address family of the sockaddr
u8 sa_data[0x1A]; ///< The extra data, this varies, depending on the address family
} raw;
/// Structure to represent the 3ds' sockaddr_in structure
struct CTRSockAddrIn {
u8 len; ///< The length of the entire structure
u8 sin_family; ///< The address family of the sockaddr_in
u16 sin_port; ///< The port associated with this sockaddr_in
u32 sin_addr; ///< The actual address of the sockaddr_in
} in;
static_assert(sizeof(CTRSockAddrIn) == 8, "Invalid CTRSockAddrIn size");
};
struct CTRAddrInfo {
s32_le ai_flags;
s32_le ai_family;
s32_le ai_socktype;
s32_le ai_protocol;
s32_le ai_addrlen;
char ai_canonname[256];
CTRSockAddr ai_addr;
static u32 AddressInfoFlagsToPlatform(u32 flags) {
u32 ret = 0;
if (flags & 1) {
ret |= AI_PASSIVE;
}
if (flags & 2) {
ret |= AI_CANONNAME;
}
if (flags & 4) {
ret |= AI_NUMERICHOST;
}
if (flags & 8) {
ret |= AI_NUMERICSERV;
}
return ret;
}
static u32 AddressInfoFlagsFromPlatform(u32 flags) {
u32 ret = 0;
if (flags & AI_PASSIVE) {
ret |= 1;
}
if (flags & AI_CANONNAME) {
ret |= 2;
}
if (flags & AI_NUMERICHOST) {
ret |= 4;
}
if (flags & AI_NUMERICSERV) {
ret |= 8;
}
return ret;
}
/// Converts a platform-specific addrinfo to a 3ds addrinfo.
static CTRAddrInfo FromPlatform(const addrinfo& addr) {
CTRAddrInfo ctr_addr{
.ai_flags = static_cast<s32_le>(AddressInfoFlagsFromPlatform(addr.ai_flags)),
.ai_family = static_cast<s32_le>(SocketDomainFromPlatform(addr.ai_family)),
.ai_socktype = static_cast<s32_le>(SocketTypeFromPlatform(addr.ai_socktype)),
.ai_protocol = static_cast<s32_le>(SocketProtocolFromPlatform(addr.ai_protocol)),
.ai_addr = CTRSockAddr::FromPlatform(*addr.ai_addr),
};
ctr_addr.ai_addrlen = static_cast<s32_le>(ctr_addr.ai_addr.raw.len);
if (addr.ai_canonname)
std::strncpy(ctr_addr.ai_canonname, addr.ai_canonname,
sizeof(ctr_addr.ai_canonname) - 1);
return ctr_addr;
}
/// Converts a platform-specific addrinfo to a 3ds addrinfo.
static addrinfo ToPlatform(const CTRAddrInfo& ctr_addr) {
// Only certain fields are meaningful in hints, copy them manually
addrinfo addr = {
.ai_flags = static_cast<int>(AddressInfoFlagsToPlatform(ctr_addr.ai_flags)),
.ai_family = static_cast<int>(SocketDomainToPlatform(ctr_addr.ai_family)),
.ai_socktype = static_cast<int>(SocketTypeToPlatform(ctr_addr.ai_socktype)),
.ai_protocol = static_cast<int>(SocketProtocolToPlatform(ctr_addr.ai_protocol)),
};
return addr;
}
};
static_assert(sizeof(CTRAddrInfo) == 0x130, "Size of CTRAddrInfo is not correct");
constexpr u32 FLAG_MSG_PEEK = 0x2;
constexpr u32 FLAG_MSG_DONTWAIT = 0x80;
constexpr u32 FLAG_O_NONBLOCK = 0x800;
} // namespace Network

View File

@@ -56,7 +56,7 @@ static CPUCaps Detect() {
// Citra at all anyway
int cpu_id[4];
memset(caps.brand_string, 0, sizeof(caps.brand_string));
std::memset(caps.brand_string, 0, sizeof(caps.brand_string));
// Detect CPU's CPUID capabilities and grab CPU string
__cpuid(cpu_id, 0x00000000);

View File

@@ -5,19 +5,18 @@
#include <algorithm>
#include <zstd.h>
#include "common/assert.h"
#include "common/zstd_compression.h"
namespace Common::Compression {
std::vector<u8> CompressDataZSTD(const u8* source, std::size_t source_size, s32 compression_level) {
std::vector<u8> CompressDataZSTD(std::span<const u8> source, s32 compression_level) {
compression_level = std::clamp(compression_level, ZSTD_minCLevel(), ZSTD_maxCLevel());
const std::size_t max_compressed_size = ZSTD_compressBound(source_size);
const std::size_t max_compressed_size = ZSTD_compressBound(source.size());
std::vector<u8> compressed(max_compressed_size);
const std::size_t compressed_size =
ZSTD_compress(compressed.data(), compressed.size(), source, source_size, compression_level);
const std::size_t compressed_size = ZSTD_compress(
compressed.data(), compressed.size(), source.data(), source.size(), compression_level);
if (ZSTD_isError(compressed_size)) {
// Compression failed
@@ -29,11 +28,11 @@ std::vector<u8> CompressDataZSTD(const u8* source, std::size_t source_size, s32
return compressed;
}
std::vector<u8> CompressDataZSTDDefault(const u8* source, std::size_t source_size) {
return CompressDataZSTD(source, source_size, ZSTD_CLEVEL_DEFAULT);
std::vector<u8> CompressDataZSTDDefault(std::span<const u8> source) {
return CompressDataZSTD(source, ZSTD_CLEVEL_DEFAULT);
}
std::vector<u8> DecompressDataZSTD(const std::vector<u8>& compressed) {
std::vector<u8> DecompressDataZSTD(std::span<const u8> compressed) {
const std::size_t decompressed_size =
ZSTD_getFrameContentSize(compressed.data(), compressed.size());
std::vector<u8> decompressed(decompressed_size);

View File

@@ -4,6 +4,7 @@
#pragma once
#include <span>
#include <vector>
#include "common/common_types.h"
@@ -14,24 +15,21 @@ namespace Common::Compression {
* Compresses a source memory region with Zstandard and returns the compressed data in a vector.
*
* @param source the uncompressed source memory region.
* @param source_size the size in bytes of the uncompressed source memory region.
* @param compression_level the used compression level. Should be between 1 and 22.
*
* @return the compressed data.
*/
[[nodiscard]] std::vector<u8> CompressDataZSTD(const u8* source, std::size_t source_size,
s32 compression_level);
[[nodiscard]] std::vector<u8> CompressDataZSTD(std::span<const u8> source, s32 compression_level);
/**
* Compresses a source memory region with Zstandard with the default compression level and returns
* the compressed data in a vector.
*
* @param source the uncompressed source memory region.
* @param source_size the size in bytes of the uncompressed source memory region.
*
* @return the compressed data.
*/
[[nodiscard]] std::vector<u8> CompressDataZSTDDefault(const u8* source, std::size_t source_size);
[[nodiscard]] std::vector<u8> CompressDataZSTDDefault(std::span<const u8> source);
/**
* Decompresses a source memory region with Zstandard and returns the uncompressed data in a vector.
@@ -40,6 +38,6 @@ namespace Common::Compression {
*
* @return the decompressed data.
*/
[[nodiscard]] std::vector<u8> DecompressDataZSTD(const std::vector<u8>& compressed);
[[nodiscard]] std::vector<u8> DecompressDataZSTD(std::span<const u8> compressed);
} // namespace Common::Compression

View File

@@ -439,11 +439,6 @@ add_library(citra_core STATIC
hw/rsa/rsa.h
hw/y2r.cpp
hw/y2r.h
network/network.cpp
network/network.h
network/network_interface.cpp
network/network_interface.h
network/sockets.h
loader/3dsx.cpp
loader/3dsx.h
loader/elf.cpp

View File

@@ -6,6 +6,7 @@
#include <cmath>
#include <fstream>
#include <functional>
#include <span>
#include <string>
#include <vector>
#include <boost/iostreams/device/file_descriptor.hpp>
@@ -144,7 +145,7 @@ static inline void JokerOp(const GatewayCheat::CheatLine& line, State& state,
}
static inline void PatchOp(const GatewayCheat::CheatLine& line, State& state, Core::System& system,
const std::vector<GatewayCheat::CheatLine>& cheat_lines) {
std::span<const GatewayCheat::CheatLine> cheat_lines) {
if (state.if_flag > 0) {
// Skip over the additional patch lines
state.current_line_nr += static_cast<int>(std::ceil(line.value / 8.0));

View File

@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <span>
#include <unordered_map>
#include "common/assert.h"
#include "common/file_util.h"
@@ -892,7 +893,7 @@ std::string FormatDuration(s64 duration) {
}
std::string FormatDefaultValue(const AVOption* option,
const std::vector<OptionInfo::NamedConstant>& named_constants) {
std::span<const OptionInfo::NamedConstant> named_constants) {
// The following is taken and modified from libavutil code (opt.c)
switch (option->type) {
case AV_OPT_TYPE_BOOL: {

View File

@@ -296,11 +296,10 @@ ResultVal<ArchiveFormatInfo> ArchiveFactory_ExtSaveData::GetFormatInfo(const Pat
return info;
}
void ArchiveFactory_ExtSaveData::WriteIcon(const Path& path, const u8* icon_data,
std::size_t icon_size) {
void ArchiveFactory_ExtSaveData::WriteIcon(const Path& path, std::span<const u8> icon) {
std::string game_path = FileSys::GetExtSaveDataPath(GetMountPoint(), path);
FileUtil::IOFile icon_file(game_path + "icon", "wb");
icon_file.WriteBytes(icon_data, icon_size);
icon_file.WriteBytes(icon.data(), icon.size());
}
} // namespace FileSys

View File

@@ -5,6 +5,7 @@
#pragma once
#include <memory>
#include <span>
#include <string>
#include <boost/serialization/export.hpp>
#include <boost/serialization/string.hpp>
@@ -38,7 +39,7 @@ public:
* @param icon_data Binary data of the icon
* @param icon_size Size of the icon data
*/
void WriteIcon(const Path& path, const u8* icon_data, std::size_t icon_size);
void WriteIcon(const Path& path, std::span<const u8> icon);
private:
bool shared; ///< Whether this archive represents an ExtSaveData archive or a SharedExtSaveData

View File

@@ -249,7 +249,7 @@ ResultVal<std::size_t> NCCHFile::Read(const u64 offset, const std::size_t length
std::size_t available_size = static_cast<std::size_t>(file_buffer.size() - offset);
std::size_t copy_size = std::min(length, available_size);
memcpy(buffer, file_buffer.data() + offset, copy_size);
std::memcpy(buffer, file_buffer.data() + offset, copy_size);
return copy_size;
}

View File

@@ -108,7 +108,7 @@ Loader::ResultStatus CIAContainer::Load(const std::string& filepath) {
return Loader::ResultStatus::Success;
}
Loader::ResultStatus CIAContainer::Load(const std::vector<u8>& file_data) {
Loader::ResultStatus CIAContainer::Load(std::span<const u8> file_data) {
Loader::ResultStatus result = LoadHeader(file_data);
if (result != Loader::ResultStatus::Success)
return result;
@@ -133,30 +133,29 @@ Loader::ResultStatus CIAContainer::Load(const std::vector<u8>& file_data) {
return Loader::ResultStatus::Success;
}
Loader::ResultStatus CIAContainer::LoadHeader(const std::vector<u8>& header_data,
std::size_t offset) {
if (header_data.size() - offset < sizeof(Header))
Loader::ResultStatus CIAContainer::LoadHeader(std::span<const u8> header_data, std::size_t offset) {
if (header_data.size() - offset < sizeof(Header)) {
return Loader::ResultStatus::Error;
}
std::memcpy(&cia_header, header_data.data(), sizeof(Header));
return Loader::ResultStatus::Success;
}
Loader::ResultStatus CIAContainer::LoadTicket(const std::vector<u8>& ticket_data,
std::size_t offset) {
Loader::ResultStatus CIAContainer::LoadTicket(std::span<const u8> ticket_data, std::size_t offset) {
return cia_ticket.Load(ticket_data, offset);
}
Loader::ResultStatus CIAContainer::LoadTitleMetadata(const std::vector<u8>& tmd_data,
Loader::ResultStatus CIAContainer::LoadTitleMetadata(std::span<const u8> tmd_data,
std::size_t offset) {
return cia_tmd.Load(tmd_data, offset);
}
Loader::ResultStatus CIAContainer::LoadMetadata(const std::vector<u8>& meta_data,
std::size_t offset) {
if (meta_data.size() - offset < sizeof(Metadata))
Loader::ResultStatus CIAContainer::LoadMetadata(std::span<const u8> meta_data, std::size_t offset) {
if (meta_data.size() - offset < sizeof(Metadata)) {
return Loader::ResultStatus::Error;
}
std::memcpy(&cia_metadata, meta_data.data(), sizeof(Metadata));

View File

@@ -6,8 +6,8 @@
#include <array>
#include <memory>
#include <span>
#include <string>
#include <vector>
#include "common/common_types.h"
#include "common/swap.h"
#include "core/file_sys/ticket.h"
@@ -39,13 +39,13 @@ public:
// Load whole CIAs outright
Loader::ResultStatus Load(const FileBackend& backend);
Loader::ResultStatus Load(const std::string& filepath);
Loader::ResultStatus Load(const std::vector<u8>& header_data);
Loader::ResultStatus Load(std::span<const u8> header_data);
// Load parts of CIAs (for CIAs streamed in)
Loader::ResultStatus LoadHeader(const std::vector<u8>& header_data, std::size_t offset = 0);
Loader::ResultStatus LoadTicket(const std::vector<u8>& ticket_data, std::size_t offset = 0);
Loader::ResultStatus LoadTitleMetadata(const std::vector<u8>& tmd_data, std::size_t offset = 0);
Loader::ResultStatus LoadMetadata(const std::vector<u8>& meta_data, std::size_t offset = 0);
Loader::ResultStatus LoadHeader(std::span<const u8> header_data, std::size_t offset = 0);
Loader::ResultStatus LoadTicket(std::span<const u8> ticket_data, std::size_t offset = 0);
Loader::ResultStatus LoadTitleMetadata(std::span<const u8> tmd_data, std::size_t offset = 0);
Loader::ResultStatus LoadMetadata(std::span<const u8> meta_data, std::size_t offset = 0);
const Ticket& GetTicket() const;
const TitleMetadata& GetTitleMetadata() const;

View File

@@ -4,6 +4,7 @@
#include <cstring>
#include <memory>
#include <span>
#include <cryptopp/aes.h>
#include <cryptopp/modes.h>
#include <cryptopp/sha.h>
@@ -36,10 +37,10 @@ u64 GetModId(u64 program_id) {
* @param size Size of compressed buffer
* @return Size of decompressed buffer
*/
static u32 LZSS_GetDecompressedSize(const u8* buffer, u32 size) {
static std::size_t LZSS_GetDecompressedSize(std::span<const u8> buffer) {
u32 offset_size;
std::memcpy(&offset_size, buffer + size - sizeof(u32), sizeof(u32));
return offset_size + size;
std::memcpy(&offset_size, buffer.data() + buffer.size() - sizeof(u32), sizeof(u32));
return offset_size + buffer.size();
}
/**
@@ -50,19 +51,18 @@ static u32 LZSS_GetDecompressedSize(const u8* buffer, u32 size) {
* @param decompressed_size Size of decompressed buffer
* @return True on success, otherwise false
*/
static bool LZSS_Decompress(const u8* compressed, u32 compressed_size, u8* decompressed,
u32 decompressed_size) {
const u8* footer = compressed + compressed_size - 8;
static bool LZSS_Decompress(std::span<const u8> compressed, std::span<u8> decompressed) {
const u8* footer = compressed.data() + compressed.size() - 8;
u32 buffer_top_and_bottom;
std::memcpy(&buffer_top_and_bottom, footer, sizeof(u32));
u32 out = decompressed_size;
u32 index = compressed_size - ((buffer_top_and_bottom >> 24) & 0xFF);
u32 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);
memset(decompressed, 0, decompressed_size);
memcpy(decompressed, compressed, compressed_size);
std::memset(decompressed.data(), 0, decompressed.size());
std::memcpy(decompressed.data(), compressed.data(), compressed.size());
while (index > stop_index) {
u8 control = compressed[--index];
@@ -92,7 +92,7 @@ static bool LZSS_Decompress(const u8* compressed, u32 compressed_size, u8* decom
for (unsigned j = 0; j < segment_size; j++) {
// Check if compression is out of bounds
if (out + segment_offset >= decompressed_size)
if (out + segment_offset >= decompressed.size())
return false;
u8 data = decompressed[out + segment_offset];
@@ -538,14 +538,9 @@ Loader::ResultStatus NCCHContainer::LoadSectionExeFS(const char* name, std::vect
if (strcmp(section.name, ".code") == 0 && is_compressed) {
// Section is compressed, read compressed .code section...
std::unique_ptr<u8[]> temp_buffer;
try {
temp_buffer.reset(new u8[section.size]);
} catch (std::bad_alloc&) {
return Loader::ResultStatus::ErrorMemoryAllocationFailed;
}
if (exefs_file.ReadBytes(&temp_buffer[0], section.size) != section.size)
std::vector<u8> temp_buffer(section.size);
if (exefs_file.ReadBytes(temp_buffer.data(), temp_buffer.size()) !=
temp_buffer.size())
return Loader::ResultStatus::Error;
if (is_encrypted) {
@@ -553,11 +548,10 @@ Loader::ResultStatus NCCHContainer::LoadSectionExeFS(const char* name, std::vect
}
// Decompress .code section...
u32 decompressed_size = LZSS_GetDecompressedSize(&temp_buffer[0], section.size);
buffer.resize(decompressed_size);
if (!LZSS_Decompress(&temp_buffer[0], section.size, buffer.data(),
decompressed_size))
buffer.resize(LZSS_GetDecompressedSize(temp_buffer));
if (!LZSS_Decompress(temp_buffer, buffer)) {
return Loader::ResultStatus::ErrorInvalidFormat;
}
} else {
// Section is uncompressed...
buffer.resize(section.size);

View File

@@ -142,8 +142,8 @@ Loader::ResultStatus FileSys::Plugin3GXLoader::Load(
}
exe_load_func.push_back(instruction);
}
memcpy(exe_load_args, header.infos.builtin_load_exe_args,
sizeof(_3gx_Infos::builtin_load_exe_args));
std::memcpy(exe_load_args, header.infos.builtin_load_exe_args,
sizeof(_3gx_Infos::builtin_load_exe_args));
}
// Load code sections
@@ -245,8 +245,8 @@ Loader::ResultStatus FileSys::Plugin3GXLoader::Map(
plugin_header.plgldr_reply = plg_context.plg_reply;
plugin_header.is_default_plugin = plg_context.is_default_path;
if (plg_context.use_user_load_parameters) {
memcpy(plugin_header.config, plg_context.user_load_parameters.config,
sizeof(PluginHeader::config));
std::memcpy(plugin_header.config, plg_context.user_load_parameters.config,
sizeof(PluginHeader::config));
}
kernel.memory.WriteBlock(process, _3GX_exe_load_addr, &plugin_header, sizeof(PluginHeader));
@@ -286,8 +286,7 @@ Loader::ResultStatus FileSys::Plugin3GXLoader::Map(
}
void FileSys::Plugin3GXLoader::MapBootloader(Kernel::Process& process, Kernel::KernelSystem& kernel,
u32 memory_offset,
const std::vector<u32>& exe_load_func,
u32 memory_offset, std::span<const u32> exe_load_func,
const u32_le* exe_load_args, u32 checksum_size,
u32 exe_checksum, bool no_flash) {
@@ -296,7 +295,8 @@ void FileSys::Plugin3GXLoader::MapBootloader(Kernel::Process& process, Kernel::K
sizeof(u32) * 2);
std::array<u32_le, g_plugin_loader_bootloader.size() / sizeof(u32)> bootloader;
memcpy(bootloader.data(), g_plugin_loader_bootloader.data(), g_plugin_loader_bootloader.size());
std::memcpy(bootloader.data(), g_plugin_loader_bootloader.data(),
g_plugin_loader_bootloader.size());
for (auto it = bootloader.begin(); it < bootloader.end(); it++) {
switch (static_cast<u32>(*it)) {

View File

@@ -21,9 +21,10 @@
#pragma once
#include <core/file_sys/archive_backend.h>
#include <span>
#include "common/common_types.h"
#include "common/swap.h"
#include "core/file_sys/archive_backend.h"
#include "core/hle/kernel/process.h"
#include "core/hle/service/plgldr/plgldr.h"
@@ -71,7 +72,7 @@ private:
static constexpr size_t bootloader_memory_size = 0x1000;
static void MapBootloader(Kernel::Process& process, Kernel::KernelSystem& kernel,
u32 memory_offset, const std::vector<u32>& exe_load_func,
u32 memory_offset, std::span<const u32> exe_load_func,
const u32_le* exe_load_args, u32 checksum_size, u32 exe_checksum,
bool no_flash);

View File

@@ -13,7 +13,7 @@
namespace FileSys {
Loader::ResultStatus Ticket::Load(const std::vector<u8> file_data, std::size_t offset) {
Loader::ResultStatus Ticket::Load(std::span<const u8> file_data, std::size_t offset) {
std::size_t total_size = static_cast<std::size_t>(file_data.size() - offset);
if (total_size < sizeof(u32))
return Loader::ResultStatus::Error;
@@ -35,8 +35,8 @@ Loader::ResultStatus Ticket::Load(const std::vector<u8> file_data, std::size_t o
// Read signature + ticket body
ticket_signature.resize(signature_size);
memcpy(ticket_signature.data(), &file_data[offset + sizeof(u32)], signature_size);
memcpy(&ticket_body, &file_data[offset + body_start], sizeof(Body));
std::memcpy(ticket_signature.data(), &file_data[offset + sizeof(u32)], signature_size);
std::memcpy(&ticket_body, &file_data[offset + body_start], sizeof(Body));
return Loader::ResultStatus::Success;
}

View File

@@ -6,6 +6,7 @@
#include <array>
#include <optional>
#include <span>
#include <string>
#include <vector>
#include "common/common_funcs.h"
@@ -47,7 +48,7 @@ public:
static_assert(sizeof(Body) == 0x210, "Ticket body structure size is wrong");
#pragma pack(pop)
Loader::ResultStatus Load(const std::vector<u8> file_data, std::size_t offset = 0);
Loader::ResultStatus Load(std::span<const u8> file_data, std::size_t offset = 0);
std::optional<std::array<u8, 16>> GetTitleKey() const;
private:

View File

@@ -29,12 +29,13 @@ Loader::ResultStatus TitleMetadata::Load(const std::string& file_path) {
return result;
}
Loader::ResultStatus TitleMetadata::Load(const std::vector<u8>& file_data, std::size_t offset) {
Loader::ResultStatus TitleMetadata::Load(std::span<const u8> file_data, std::size_t offset) {
std::size_t total_size = static_cast<std::size_t>(file_data.size() - offset);
if (total_size < sizeof(u32_be))
if (total_size < sizeof(u32_be)) {
return Loader::ResultStatus::Error;
}
memcpy(&signature_type, &file_data[offset], sizeof(u32_be));
std::memcpy(&signature_type, &file_data[offset], sizeof(u32_be));
// Signature lengths are variable, and the body follows the signature
u32 signature_size = GetSignatureSize(signature_type);
@@ -46,13 +47,14 @@ Loader::ResultStatus TitleMetadata::Load(const std::vector<u8>& file_data, std::
std::size_t body_start = Common::AlignUp(signature_size + sizeof(u32), 0x40);
std::size_t body_end = body_start + sizeof(Body);
if (total_size < body_end)
if (total_size < body_end) {
return Loader::ResultStatus::Error;
}
// Read signature + TMD body, then load the amount of ContentChunks specified
tmd_signature.resize(signature_size);
memcpy(tmd_signature.data(), &file_data[offset + sizeof(u32_be)], signature_size);
memcpy(&tmd_body, &file_data[offset + body_start], sizeof(TitleMetadata::Body));
std::memcpy(tmd_signature.data(), &file_data[offset + sizeof(u32_be)], signature_size);
std::memcpy(&tmd_body, &file_data[offset + body_start], sizeof(TitleMetadata::Body));
std::size_t expected_size =
body_start + sizeof(Body) + static_cast<u16>(tmd_body.content_count) * sizeof(ContentChunk);
@@ -65,8 +67,8 @@ Loader::ResultStatus TitleMetadata::Load(const std::vector<u8>& file_data, std::
for (u16 i = 0; i < tmd_body.content_count; i++) {
ContentChunk chunk;
memcpy(&chunk, &file_data[offset + body_end + (i * sizeof(ContentChunk))],
sizeof(ContentChunk));
std::memcpy(&chunk, &file_data[offset + body_end + (i * sizeof(ContentChunk))],
sizeof(ContentChunk));
tmd_chunks.push_back(chunk);
}

View File

@@ -5,6 +5,7 @@
#pragma once
#include <array>
#include <span>
#include <string>
#include <vector>
#include "common/common_types.h"
@@ -82,7 +83,7 @@ public:
#pragma pack(pop)
Loader::ResultStatus Load(const std::string& file_path);
Loader::ResultStatus Load(const std::vector<u8>& file_data, std::size_t offset = 0);
Loader::ResultStatus Load(std::span<const u8> file_data, std::size_t offset = 0);
Loader::ResultStatus Save(const std::string& file_path);
u64 GetTitleID() const;

View File

@@ -8,8 +8,8 @@
#include "core/frontend/applets/swkbd.h"
namespace Frontend {
void RegisterDefaultApplets() {
Core::System::GetInstance().RegisterSoftwareKeyboard(std::make_shared<DefaultKeyboard>());
Core::System::GetInstance().RegisterMiiSelector(std::make_shared<DefaultMiiSelector>());
void RegisterDefaultApplets(Core::System& system) {
system.RegisterSoftwareKeyboard(std::make_shared<DefaultKeyboard>());
system.RegisterMiiSelector(std::make_shared<DefaultMiiSelector>());
}
} // namespace Frontend

View File

@@ -9,5 +9,5 @@ namespace Frontend {
* Registers default, frontend-independent applet implementations.
* Will be replaced later if any frontend-specific implementation is available.
*/
void RegisterDefaultApplets();
void RegisterDefaultApplets(Core::System& system);
} // namespace Frontend

View File

@@ -491,7 +491,7 @@ void SendReply(const char* reply) {
return;
}
memset(command_buffer, 0, sizeof(command_buffer));
std::memset(command_buffer, 0, sizeof(command_buffer));
command_length = static_cast<u32>(strlen(reply));
if (command_length + 4 > sizeof(command_buffer)) {
@@ -499,7 +499,7 @@ void SendReply(const char* reply) {
return;
}
memcpy(command_buffer + 1, reply, command_length);
std::memcpy(command_buffer + 1, reply, command_length);
u8 checksum = CalculateChecksum(command_buffer, command_length + 1);
command_buffer[0] = GDB_STUB_START;
@@ -639,7 +639,7 @@ static void SendSignal(Kernel::Thread* thread, u32 signal, bool full = true) {
/// Read command from gdb client.
static void ReadCommand() {
command_length = 0;
memset(command_buffer, 0, sizeof(command_buffer));
std::memset(command_buffer, 0, sizeof(command_buffer));
u8 c = ReadByte();
if (c == GDB_STUB_ACK) {
@@ -711,7 +711,7 @@ static bool IsDataAvailable() {
/// Send requested register to gdb client.
static void ReadRegister() {
static u8 reply[64];
memset(reply, 0, sizeof(reply));
std::memset(reply, 0, sizeof(reply));
u32 id = HexCharToValue(command_buffer[1]);
if (command_buffer[2] != '\0') {
@@ -737,7 +737,7 @@ static void ReadRegister() {
/// Send all registers to the gdb client.
static void ReadRegisters() {
static u8 buffer[GDB_BUFFER_SIZE - 4];
memset(buffer, 0, sizeof(buffer));
std::memset(buffer, 0, sizeof(buffer));
u8* bufptr = buffer;

View File

@@ -6,6 +6,7 @@
#pragma once
#include <span>
#include "common/common_types.h"
#include "core/hle/kernel/thread.h"

View File

@@ -115,7 +115,7 @@ void HandleHioReply(const u8* const command_buffer, const u32 command_length) {
}
// Skip 'F' header
auto* command_pos = command_buffer + 1;
const u8* command_pos = command_buffer + 1;
if (*command_pos == 0 || *command_pos == ',') {
LOG_WARNING(Debug_GDBStub, "bad HIO packet format position 0: {}", *command_pos);

View File

@@ -23,7 +23,7 @@ ResultCode ErrEula::ReceiveParameterImpl(const Service::APT::MessageParameter& p
Service::APT::CaptureBufferInfo capture_info;
ASSERT(sizeof(capture_info) == parameter.buffer.size());
memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info));
std::memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info));
// TODO: allocated memory never released
using Kernel::MemoryPermission;

View File

@@ -31,7 +31,7 @@ ResultCode MiiSelector::ReceiveParameterImpl(const Service::APT::MessageParamete
Service::APT::CaptureBufferInfo capture_info;
ASSERT(sizeof(capture_info) == parameter.buffer.size());
memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info));
std::memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info));
using Kernel::MemoryPermission;
// Create a SharedMemory that directly points to this heap block.
@@ -54,7 +54,7 @@ ResultCode MiiSelector::Start(const Service::APT::MessageParameter& parameter) {
ASSERT_MSG(parameter.buffer.size() == sizeof(config),
"The size of the parameter (MiiConfig) is wrong");
memcpy(&config, parameter.buffer.data(), parameter.buffer.size());
std::memcpy(&config, parameter.buffer.data(), parameter.buffer.size());
using namespace Frontend;
frontend_applet = Core::System::GetInstance().GetMiiSelector();

View File

@@ -23,7 +23,7 @@ ResultCode Mint::ReceiveParameterImpl(const Service::APT::MessageParameter& para
Service::APT::CaptureBufferInfo capture_info;
ASSERT(sizeof(capture_info) == parameter.buffer.size());
memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info));
std::memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info));
// TODO: allocated memory never released
using Kernel::MemoryPermission;

View File

@@ -93,7 +93,7 @@ ResultCode SoftwareKeyboard::Start(Service::APT::MessageParameter const& paramet
ASSERT_MSG(parameter.buffer.size() == sizeof(config),
"The size of the parameter (SoftwareKeyboardConfig) is wrong");
memcpy(&config, parameter.buffer.data(), parameter.buffer.size());
std::memcpy(&config, parameter.buffer.data(), parameter.buffer.size());
text_memory = std::static_pointer_cast<Kernel::SharedMemory, Kernel::Object>(parameter.object);
DrawScreenKeyboard();
@@ -115,7 +115,7 @@ void SoftwareKeyboard::Update() {
const KeyboardData& data = frontend_applet->ReceiveData();
std::u16string text = Common::UTF8ToUTF16(data.text);
// Include a null terminator
memcpy(text_memory->GetPointer(), text.c_str(), (text.length() + 1) * sizeof(char16_t));
std::memcpy(text_memory->GetPointer(), text.c_str(), (text.length() + 1) * sizeof(char16_t));
switch (config.num_buttons_m1) {
case SoftwareKeyboardButtonConfig::SingleButton:
config.return_code = SoftwareKeyboardResult::D0Click;

View File

@@ -38,7 +38,7 @@ public:
void Skip(unsigned size_in_words, bool set_to_null) {
if (set_to_null)
memset(cmdbuf + index, 0, size_in_words * sizeof(u32));
std::memset(cmdbuf + index, 0, size_in_words * sizeof(u32));
index += size_in_words;
}
};

View File

@@ -304,13 +304,13 @@ MappedBuffer::MappedBuffer(Memory::MemorySystem& memory, std::shared_ptr<Process
perms = desc.perms;
}
void MappedBuffer::Read(void* dest_buffer, std::size_t offset, std::size_t size) const {
void MappedBuffer::Read(void* dest_buffer, std::size_t offset, std::size_t size) {
ASSERT(perms & IPC::R);
ASSERT(offset + size <= this->size);
memory->ReadBlock(*process, address + static_cast<VAddr>(offset), dest_buffer, size);
}
void MappedBuffer::Write(const void* src_buffer, std::size_t offset, std::size_t size) const {
void MappedBuffer::Write(const void* src_buffer, std::size_t offset, std::size_t size) {
ASSERT(perms & IPC::W);
ASSERT(offset + size <= this->size);
memory->WriteBlock(*process, address + static_cast<VAddr>(offset), src_buffer, size);

View File

@@ -129,16 +129,14 @@ public:
MappedBuffer(Memory::MemorySystem& memory, std::shared_ptr<Process> process, u32 descriptor,
VAddr address, u32 id);
// Interface for service
void Read(void* dest_buffer, std::size_t offset, std::size_t size) const;
void Write(const void* src_buffer, std::size_t offset, std::size_t size) const;
// interface for service
void Read(void* dest_buffer, std::size_t offset, std::size_t size);
void Write(const void* src_buffer, std::size_t offset, std::size_t size);
std::size_t GetSize() const {
return size;
}
// Interface for ipc helper
// interface for ipc helper
u32 GenerateDescriptor() const {
return IPC::MappedBufferDesc(size, perms);
}

View File

@@ -74,7 +74,7 @@ void Recorder::SetRequestInfo(const std::shared_ptr<Kernel::Thread>& client_thre
const u32 thread_id = client_thread->GetThreadId();
if (!record_map.count(thread_id)) {
// This is possible when the recorder is enabled after application started
LOG_ERROR(Kernel, "No request is assoicated with the thread");
LOG_ERROR(Kernel, "No request is associated with the thread");
return;
}
@@ -113,7 +113,7 @@ void Recorder::SetReplyInfo(const std::shared_ptr<Kernel::Thread>& client_thread
const u32 thread_id = client_thread->GetThreadId();
if (!record_map.count(thread_id)) {
// This is possible when the recorder is enabled after application started
LOG_ERROR(Kernel, "No request is assoicated with the thread");
LOG_ERROR(Kernel, "No request is associated with the thread");
return;
}
@@ -133,7 +133,7 @@ void Recorder::SetHLEUnimplemented(const std::shared_ptr<Kernel::Thread>& client
const u32 thread_id = client_thread->GetThreadId();
if (!record_map.count(thread_id)) {
// This is possible when the recorder is enabled after application started
LOG_ERROR(Kernel, "No request is assoicated with the thread");
LOG_ERROR(Kernel, "No request is associated with the thread");
return;
}

View File

@@ -8,6 +8,7 @@
#include <atomic>
#include <functional>
#include <memory>
#include <span>
#include <string>
#include <unordered_map>
#include <vector>
@@ -230,7 +231,7 @@ public:
/// Retrieves a process from the current list of processes.
std::shared_ptr<Process> GetProcessById(u32 process_id) const;
const std::vector<std::shared_ptr<Process>>& GetProcessList() const {
std::span<const std::shared_ptr<Process>> GetProcessList() const {
return process_list;
}

View File

@@ -1,7 +1,7 @@
// Copyright 2015 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma optimize("", off)
#include <algorithm>
#include <memory>
#include <boost/serialization/array.hpp>

View File

@@ -87,8 +87,7 @@ Handler::Handler(Core::Timing& timing) : timing(timing) {
shared_page.sliderstate_3d = static_cast<float_le>(slidestate);
}
/// Gets system time in 3DS format. The epoch is Jan 1900, and the unit is millisecond.
u64 Handler::GetSystemTime() const {
u64 Handler::GetSystemTimeSince2000() const {
std::chrono::milliseconds now =
init_time + std::chrono::duration_cast<std::chrono::milliseconds>(timing.GetGlobalTimeUs());
@@ -104,23 +103,25 @@ u64 Handler::GetSystemTime() const {
epoch_tm.tm_isdst = 0;
s64 epoch = std::mktime(&epoch_tm) * 1000;
// 3DS console time uses Jan 1 1900 as internal epoch,
// so we use the milliseconds between 1900 and 2000 as base console time
u64 console_time = 3155673600000ULL;
// Only when system time is after 2000, we set it as 3DS system time
if (now.count() > epoch) {
console_time += (now.count() - epoch);
return now.count() - epoch;
} else {
return 0;
}
}
return console_time;
u64 Handler::GetSystemTimeSince1900() const {
// 3DS console time uses Jan 1 1900 as internal epoch,
// so we use the milliseconds between 1900 and 2000 as base console time
return 3155673600000ULL + GetSystemTimeSince2000();
}
void Handler::UpdateTimeCallback(std::uintptr_t user_data, int cycles_late) {
DateTime& date_time =
shared_page.date_time_counter % 2 ? shared_page.date_time_0 : shared_page.date_time_1;
date_time.date_time = GetSystemTime();
date_time.date_time = GetSystemTimeSince1900();
date_time.update_tick = timing.GetTicks();
date_time.tick_to_second_coefficient = BASE_CLOCK_RATE_ARM11;
date_time.tick_offset = 0;

View File

@@ -110,8 +110,13 @@ public:
return sizeof(shared_page);
}
/// Gets the system time in milliseconds since the year 2000.
u64 GetSystemTimeSince2000() const;
/// Gets the system time in milliseconds since the year 1900.
u64 GetSystemTimeSince1900() const;
private:
u64 GetSystemTime() const;
void UpdateTimeCallback(std::uintptr_t user_data, int cycles_late);
Core::Timing& timing;
Core::TimingEventType* update_time_event;

View File

@@ -543,13 +543,15 @@ void SVC::ExitProcess() {
current_process->status = ProcessStatus::Exited;
// Stop all the process threads that are currently waiting for objects.
auto& thread_list = kernel.GetCurrentThreadManager().GetThreadList();
const auto thread_list = kernel.GetCurrentThreadManager().GetThreadList();
for (auto& thread : thread_list) {
if (thread->owner_process.lock() != current_process)
if (thread->owner_process.lock() != current_process) {
continue;
}
if (thread.get() == kernel.GetCurrentThreadManager().GetCurrentThread())
if (thread.get() == kernel.GetCurrentThreadManager().GetCurrentThread()) {
continue;
}
// TODO(Subv): When are the other running/ready threads terminated?
ASSERT_MSG(thread->status == ThreadStatus::WaitSynchAny ||
@@ -695,7 +697,7 @@ ResultCode SVC::OpenThread(Handle* out_handle, Handle process_handle, u32 thread
}
for (u32 core_id = 0; core_id < system.GetNumCores(); core_id++) {
auto& thread_list = kernel.GetThreadManager(core_id).GetThreadList();
const auto thread_list = kernel.GetThreadManager(core_id).GetThreadList();
for (auto& thread : thread_list) {
if (thread->owner_process.lock() == process && thread.get()->thread_id == thread_id) {
auto result_handle = kernel.GetCurrentProcess()->handle_table.Create(thread);
@@ -2092,7 +2094,7 @@ ResultCode SVC::ControlProcess(Handle process_handle, u32 process_OP, u32 varg2,
}
case ControlProcessOP::PROCESSOP_SCHEDULE_THREADS_WITHOUT_TLS_MAGIC: {
for (u32 core_id = 0; core_id < system.GetNumCores(); core_id++) {
auto& thread_list = kernel.GetThreadManager(core_id).GetThreadList();
const auto thread_list = kernel.GetThreadManager(core_id).GetThreadList();
for (auto& thread : thread_list) {
if (thread->owner_process.lock() != process) {
continue;

View File

@@ -3,7 +3,7 @@
// Refer to the license.txt file included.
#pragma once
#pragma optimize("", off)
#include <array>
#include <cstring>
#include <type_traits>

View File

@@ -304,7 +304,7 @@ void ThreadManager::DebugThreadQueue() {
* alloc_needed: Whether there's a need to allocate a new TLS page (All pages are full).
*/
static std::tuple<std::size_t, std::size_t, bool> GetFreeThreadLocalSlot(
const std::vector<std::bitset<8>>& tls_slots) {
std::span<const std::bitset<8>> tls_slots) {
// Iterate over all the allocated pages, and try to find one where not all slots are used.
for (std::size_t page = 0; page < tls_slots.size(); ++page) {
const auto& page_tls_slots = tls_slots[page];
@@ -527,7 +527,7 @@ ThreadManager::~ThreadManager() {
}
}
const std::vector<std::shared_ptr<Thread>>& ThreadManager::GetThreadList() {
std::span<const std::shared_ptr<Thread>> ThreadManager::GetThreadList() {
return thread_list;
}

View File

@@ -5,6 +5,7 @@
#pragma once
#include <memory>
#include <span>
#include <string>
#include <unordered_map>
#include <vector>
@@ -113,7 +114,7 @@ public:
/**
* Get a const reference to the thread list for debug use
*/
const std::vector<std::shared_ptr<Thread>>& GetThreadList();
std::span<const std::shared_ptr<Thread>> GetThreadList();
void SetCPU(ARM_Interface& cpu_) {
cpu = &cpu_;

View File

@@ -2,7 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <core/hle/lock.h>
#include "core/hle/lock.h"
namespace HLE {
std::recursive_mutex g_hle_lock;

View File

@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/service/act/act.h"
#include "core/hle/service/act/act_a.h"
#include "core/hle/service/act/act_u.h"
@@ -14,6 +15,35 @@ Module::Interface::Interface(std::shared_ptr<Module> act, const char* name)
Module::Interface::~Interface() = default;
void Module::Interface::Initialize(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx, 0x1, 2, 4); // 0x10084
const auto sdk_version = rp.Pop<u32>();
const auto shared_memory_size = rp.Pop<u32>();
const auto caller_pid = rp.PopPID();
[[maybe_unused]] const auto shared_memory = rp.PopObject<Kernel::SharedMemory>();
LOG_DEBUG(Service_ACT,
"(STUBBED) called sdk_version={:08X}, shared_memory_size={:08X}, caller_pid={}",
sdk_version, shared_memory_size, caller_pid);
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(RESULT_SUCCESS);
}
void Module::Interface::GetAccountDataBlock(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx, 0x6, 3, 2); // 0x600C2
const auto unknown = rp.Pop<u8>();
const auto size = rp.Pop<u32>();
const auto block_id = rp.Pop<u32>();
[[maybe_unused]] auto output_buffer = rp.PopMappedBuffer();
LOG_DEBUG(Service_ACT, "(STUBBED) called unknown={:02X}, size={:08X}, block_id={:08X}", unknown,
size, block_id);
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(RESULT_SUCCESS);
}
void InstallInterfaces(Core::System& system) {
auto& service_manager = system.ServiceManager();
auto act = std::make_shared<Module>();

View File

@@ -22,6 +22,33 @@ public:
protected:
std::shared_ptr<Module> act;
/**
* ACT::Initialize service function.
* Inputs:
* 1 : SDK version
* 2 : Shared Memory Size
* 3 : PID Translation Header (0x20)
* 4 : Caller PID
* 5 : Handle Translation Header (0x0)
* 6 : Shared Memory Handle
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void Initialize(Kernel::HLERequestContext& ctx);
/**
* ACT::GetAccountDataBlock service function.
* Inputs:
* 1 : u8 Unknown
* 2 : Size
* 3 : Block ID
* 4 : Output Buffer Mapping Translation Header ((Size << 4) | 0xC)
* 5 : Output Buffer Pointer
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void GetAccountDataBlock(Kernel::HLERequestContext& ctx);
};
private:

View File

@@ -11,9 +11,9 @@ ACT_A::ACT_A(std::shared_ptr<Module> act) : Module::Interface(std::move(act), "a
const FunctionInfo functions[] = {
// act:u shared commands
// clang-format off
{IPC::MakeHeader(0x0001, 2, 4), nullptr, "Initialize"},
{IPC::MakeHeader(0x0001, 2, 4), &ACT_A::Initialize, "Initialize"},
{IPC::MakeHeader(0x0002, 1, 0), nullptr, "GetErrorCode"},
{IPC::MakeHeader(0x0006, 3, 2), nullptr, "GetAccountDataBlock"},
{IPC::MakeHeader(0x0006, 3, 2), &ACT_A::GetAccountDataBlock, "GetAccountDataBlock"},
{IPC::MakeHeader(0x000B, 1, 2), nullptr, "AcquireEulaList"},
{IPC::MakeHeader(0x000D, 1, 0), nullptr, "GenerateUuid"},
// act:a

View File

@@ -10,9 +10,9 @@ namespace Service::ACT {
ACT_U::ACT_U(std::shared_ptr<Module> act) : Module::Interface(std::move(act), "act:u") {
static const FunctionInfo functions[] = {
// clang-format off
{IPC::MakeHeader(0x0001, 2, 4), nullptr, "Initialize"},
{IPC::MakeHeader(0x0001, 2, 4), &ACT_U::Initialize, "Initialize"},
{IPC::MakeHeader(0x0002, 1, 0), nullptr, "GetErrorCode"},
{IPC::MakeHeader(0x0006, 3, 2), nullptr, "GetAccountDataBlock"},
{IPC::MakeHeader(0x0006, 3, 2), &ACT_U::GetAccountDataBlock, "GetAccountDataBlock"},
{IPC::MakeHeader(0x000B, 1, 2), nullptr, "AcquireEulaList"},
{IPC::MakeHeader(0x000D, 1, 0), nullptr, "GenerateUuid"},
// clang-format on

View File

@@ -223,7 +223,7 @@ ResultVal<std::size_t> CIAFile::Write(u64 offset, std::size_t length, bool flush
std::size_t buf_max_size =
std::min(static_cast<std::size_t>(offset + length), FileSys::CIA_HEADER_SIZE);
data.resize(buf_max_size);
memcpy(data.data() + offset, buffer, buf_copy_size);
std::memcpy(data.data() + offset, buffer, buf_copy_size);
// We have enough data to load a CIA header and parse it.
if (written >= FileSys::CIA_HEADER_SIZE) {
@@ -248,7 +248,7 @@ ResultVal<std::size_t> CIAFile::Write(u64 offset, std::size_t length, bool flush
buf_offset;
std::size_t buf_max_size = std::min(offset + length, container.GetContentOffset());
data.resize(buf_max_size);
memcpy(data.data() + copy_offset, buffer + buf_offset, buf_copy_size);
std::memcpy(data.data() + copy_offset, buffer + buf_offset, buf_copy_size);
}
// TODO(shinyquagsire23): Write out .tik files to nand?
@@ -850,7 +850,7 @@ void Module::Interface::GetProgramList(Kernel::HLERequestContext& ctx) {
rb.PushMappedBuffer(title_ids_output);
}
ResultCode GetTitleInfoFromList(const std::vector<u64>& title_id_list,
ResultCode GetTitleInfoFromList(std::span<const u64> title_id_list,
Service::FS::MediaType media_type,
Kernel::MappedBuffer& title_info_out) {
std::size_t write_offset = 0;
@@ -1121,6 +1121,17 @@ void Module::Interface::GetTicketList(Kernel::HLERequestContext& ctx) {
ticket_list_count, ticket_index);
}
void Module::Interface::NeedsCleanup(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx, 0x0013, 1, 0); // 0x00130040
const auto media_type = rp.Pop<u8>();
LOG_DEBUG(Service_AM, "(STUBBED) media_type=0x{:02x}", media_type);
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
rb.Push(RESULT_SUCCESS);
rb.Push<bool>(false);
}
void Module::Interface::QueryAvailableTitleDatabase(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx, 0x0019, 1, 0); // 0x190040
u8 media_type = rp.Pop<u8>();

View File

@@ -357,6 +357,16 @@ public:
*/
void GetTicketList(Kernel::HLERequestContext& ctx);
/**
* AM::NeedsCleanup service function
* Inputs:
* 1 : Media Type
* Outputs:
* 1 : Result, 0 on success, otherwise error code
* 2 : bool, Needs Cleanup
*/
void NeedsCleanup(Kernel::HLERequestContext& ctx);
/**
* AM::QueryAvailableTitleDatabase service function
* Inputs:

View File

@@ -28,7 +28,7 @@ AM_NET::AM_NET(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "a
{IPC::MakeHeader(0x0010, 4, 2), nullptr, "GetImportContentContextList"},
{IPC::MakeHeader(0x0011, 4, 4), nullptr, "GetImportContentContexts"},
{IPC::MakeHeader(0x0012, 4, 2), nullptr, "DeleteImportContentContexts"},
{IPC::MakeHeader(0x0013, 1, 0), nullptr, "NeedsCleanup"},
{IPC::MakeHeader(0x0013, 1, 0), &AM_NET::NeedsCleanup, "NeedsCleanup"},
{IPC::MakeHeader(0x0014, 1, 0), nullptr, "DoCleanup"},
{IPC::MakeHeader(0x0015, 1, 0), nullptr, "DeleteAllImportContexts"},
{IPC::MakeHeader(0x0016, 0, 0), nullptr, "DeleteAllTemporaryPrograms"},

View File

@@ -28,7 +28,7 @@ AM_SYS::AM_SYS(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "a
{IPC::MakeHeader(0x0010, 4, 2), nullptr, "GetImportContentContextList"},
{IPC::MakeHeader(0x0011, 4, 4), nullptr, "GetImportContentContexts"},
{IPC::MakeHeader(0x0012, 4, 2), nullptr, "DeleteImportContentContexts"},
{IPC::MakeHeader(0x0013, 1, 0), nullptr, "NeedsCleanup"},
{IPC::MakeHeader(0x0013, 1, 0), &AM_SYS::NeedsCleanup, "NeedsCleanup"},
{IPC::MakeHeader(0x0014, 1, 0), nullptr, "DoCleanup"},
{IPC::MakeHeader(0x0015, 1, 0), nullptr, "DeleteAllImportContexts"},
{IPC::MakeHeader(0x0016, 0, 0), nullptr, "DeleteAllTemporaryPrograms"},

View File

@@ -28,7 +28,7 @@ AM_U::AM_U(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "am:u"
{IPC::MakeHeader(0x0010, 4, 2), nullptr, "GetImportContentContextList"},
{IPC::MakeHeader(0x0011, 4, 4), nullptr, "GetImportContentContexts"},
{IPC::MakeHeader(0x0012, 4, 2), nullptr, "DeleteImportContentContexts"},
{IPC::MakeHeader(0x0013, 1, 0), nullptr, "NeedsCleanup"},
{IPC::MakeHeader(0x0013, 1, 0), &AM_U::NeedsCleanup, "NeedsCleanup"},
{IPC::MakeHeader(0x0014, 1, 0), nullptr, "DoCleanup"},
{IPC::MakeHeader(0x0015, 1, 0), nullptr, "DeleteAllImportContexts"},
{IPC::MakeHeader(0x0016, 0, 0), nullptr, "DeleteAllTemporaryPrograms"},

View File

@@ -134,7 +134,7 @@ void Module::APTInterface::Initialize(Kernel::HLERequestContext& ctx) {
static u32 DecompressLZ11(const u8* in, u8* out) {
u32_le decompressed_size;
memcpy(&decompressed_size, in, sizeof(u32));
std::memcpy(&decompressed_size, in, sizeof(u32));
in += 4;
u8 type = decompressed_size & 0xFF;

View File

@@ -12,7 +12,7 @@ void RelocateSharedFont(std::shared_ptr<Kernel::SharedMemory> shared_font, VAddr
const u8* cfnt_ptr = shared_font->GetPointer(SharedFontStartOffset);
CFNT cfnt;
memcpy(&cfnt, cfnt_ptr, sizeof(cfnt));
std::memcpy(&cfnt, cfnt_ptr, sizeof(cfnt));
u32 assumed_cmap_offset = 0;
u32 assumed_cwdh_offset = 0;
@@ -27,17 +27,17 @@ void RelocateSharedFont(std::shared_ptr<Kernel::SharedMemory> shared_font, VAddr
const u8* data = shared_font->GetPointer(current_offset);
SectionHeader section_header;
memcpy(&section_header, data, sizeof(section_header));
std::memcpy(&section_header, data, sizeof(section_header));
if (first_cmap_offset == 0 && memcmp(section_header.magic, "CMAP", 4) == 0) {
if (first_cmap_offset == 0 && std::memcmp(section_header.magic, "CMAP", 4) == 0) {
first_cmap_offset = current_offset;
} else if (first_cwdh_offset == 0 && memcmp(section_header.magic, "CWDH", 4) == 0) {
} else if (first_cwdh_offset == 0 && std::memcmp(section_header.magic, "CWDH", 4) == 0) {
first_cwdh_offset = current_offset;
} else if (first_tglp_offset == 0 && memcmp(section_header.magic, "TGLP", 4) == 0) {
} else if (first_tglp_offset == 0 && std::memcmp(section_header.magic, "TGLP", 4) == 0) {
first_tglp_offset = current_offset;
} else if (memcmp(section_header.magic, "FINF", 4) == 0) {
} else if (std::memcmp(section_header.magic, "FINF", 4) == 0) {
BCFNT::FINF finf;
memcpy(&finf, data, sizeof(finf));
std::memcpy(&finf, data, sizeof(finf));
assumed_cmap_offset = finf.cmap_offset - sizeof(SectionHeader);
assumed_cwdh_offset = finf.cwdh_offset - sizeof(SectionHeader);
@@ -59,44 +59,44 @@ void RelocateSharedFont(std::shared_ptr<Kernel::SharedMemory> shared_font, VAddr
u8* data = shared_font->GetPointer(current_offset);
SectionHeader section_header;
memcpy(&section_header, data, sizeof(section_header));
std::memcpy(&section_header, data, sizeof(section_header));
if (memcmp(section_header.magic, "FINF", 4) == 0) {
if (std::memcmp(section_header.magic, "FINF", 4) == 0) {
BCFNT::FINF finf;
memcpy(&finf, data, sizeof(finf));
std::memcpy(&finf, data, sizeof(finf));
// Relocate the offsets in the FINF section
finf.cmap_offset += offset;
finf.cwdh_offset += offset;
finf.tglp_offset += offset;
memcpy(data, &finf, sizeof(finf));
} else if (memcmp(section_header.magic, "CMAP", 4) == 0) {
std::memcpy(data, &finf, sizeof(finf));
} else if (std::memcmp(section_header.magic, "CMAP", 4) == 0) {
BCFNT::CMAP cmap;
memcpy(&cmap, data, sizeof(cmap));
std::memcpy(&cmap, data, sizeof(cmap));
// Relocate the offsets in the CMAP section
if (cmap.next_cmap_offset != 0)
cmap.next_cmap_offset += offset;
memcpy(data, &cmap, sizeof(cmap));
} else if (memcmp(section_header.magic, "CWDH", 4) == 0) {
std::memcpy(data, &cmap, sizeof(cmap));
} else if (std::memcmp(section_header.magic, "CWDH", 4) == 0) {
BCFNT::CWDH cwdh;
memcpy(&cwdh, data, sizeof(cwdh));
std::memcpy(&cwdh, data, sizeof(cwdh));
// Relocate the offsets in the CWDH section
if (cwdh.next_cwdh_offset != 0)
cwdh.next_cwdh_offset += offset;
memcpy(data, &cwdh, sizeof(cwdh));
} else if (memcmp(section_header.magic, "TGLP", 4) == 0) {
std::memcpy(data, &cwdh, sizeof(cwdh));
} else if (std::memcmp(section_header.magic, "TGLP", 4) == 0) {
BCFNT::TGLP tglp;
memcpy(&tglp, data, sizeof(tglp));
std::memcpy(&tglp, data, sizeof(tglp));
// Relocate the offsets in the TGLP section
tglp.sheet_data_offset += offset;
memcpy(data, &tglp, sizeof(tglp));
std::memcpy(data, &tglp, sizeof(tglp));
}
current_offset += section_header.section_size;

View File

@@ -834,7 +834,7 @@ void Module::Interface::OpenAndRead(Kernel::HLERequestContext& ctx) {
open_mode.check);
}
std::string Module::EncodeBase64(const std::vector<u8>& in) const {
std::string Module::EncodeBase64(std::span<const u8> in) const {
using namespace CryptoPP;
using Name::EncodingLookupArray;
using Name::InsertLineBreaks;
@@ -855,7 +855,7 @@ std::string Module::EncodeBase64(const std::vector<u8>& in) const {
}
std::string Module::GetCecDataPathTypeAsString(const CecDataPathType type, const u32 program_id,
const std::vector<u8>& msg_id) const {
std::span<const u8> msg_id) const {
switch (type) {
case CecDataPathType::MboxList:
return "/CEC/MBoxList____";

View File

@@ -5,6 +5,7 @@
#pragma once
#include <memory>
#include <span>
#include "common/bit_field.h"
#include "common/common_funcs.h"
#include "core/hle/kernel/event.h"
@@ -610,10 +611,11 @@ private:
0x26, 0x00, 0x01, 0x00};
/// Encoding function used for the message id
std::string EncodeBase64(const std::vector<u8>& in) const;
std::string EncodeBase64(std::span<const u8> in) const;
std::string GetCecDataPathTypeAsString(const CecDataPathType type, const u32 program_id,
const std::vector<u8>& msg_id = std::vector<u8>()) const;
std::string GetCecDataPathTypeAsString(
const CecDataPathType type, const u32 program_id,
std::span<const u8> msg_id = std::span<const u8>{}) const;
std::string GetCecCommandAsString(const CecCommand command) const;

View File

@@ -271,6 +271,17 @@ void Module::Interface::SecureInfoGetRegion(Kernel::HLERequestContext& ctx, u16
rb.Push<u8>(static_cast<u8>(cfg->GetRegionValue()));
}
void Module::Interface::SecureInfoGetByte101(Kernel::HLERequestContext& ctx, u16 id) {
IPC::RequestParser rp(ctx, id, 0, 0);
LOG_DEBUG(Service_CFG, "(STUBBED) called");
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
rb.Push(RESULT_SUCCESS);
// According to 3dbrew this is normally 0.
rb.Push<u8>(0);
}
void Module::Interface::GenHashConsoleUnique(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx, 0x03, 1, 0);
const u32 app_id_salt = rp.Pop<u32>() & 0x000FFFFF;
@@ -285,8 +296,8 @@ void Module::Interface::GenHashConsoleUnique(Kernel::HLERequestContext& ctx) {
std::array<u8, CryptoPP::SHA256::DIGESTSIZE> hash;
CryptoPP::SHA256().CalculateDigest(hash.data(), buffer.data(), sizeof(buffer));
u32 low, high;
memcpy(&low, &hash[hash.size() - 8], sizeof(u32));
memcpy(&high, &hash[hash.size() - 4], sizeof(u32));
std::memcpy(&low, &hash[hash.size() - 8], sizeof(u32));
std::memcpy(&high, &hash[hash.size() - 4], sizeof(u32));
rb.Push(low);
rb.Push(high);
} else {
@@ -439,7 +450,7 @@ ResultVal<void*> Module::GetConfigInfoBlockPointer(u32 block_id, u32 size, u32 f
ResultCode Module::GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* output) {
void* pointer = nullptr;
CASCADE_RESULT(pointer, GetConfigInfoBlockPointer(block_id, size, flag));
memcpy(output, pointer, size);
std::memcpy(output, pointer, size);
return RESULT_SUCCESS;
}
@@ -447,7 +458,7 @@ ResultCode Module::GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* ou
ResultCode Module::SetConfigInfoBlock(u32 block_id, u32 size, u32 flag, const void* input) {
void* pointer = nullptr;
CASCADE_RESULT(pointer, GetConfigInfoBlockPointer(block_id, size, flag));
memcpy(pointer, input, size);
std::memcpy(pointer, input, size);
return RESULT_SUCCESS;
}
@@ -473,10 +484,10 @@ ResultCode Module::CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const
config->block_entries[config->total_entries].offset_or_data = offset;
// Write the data at the new offset
memcpy(&cfg_config_file_buffer[offset], data, size);
std::memcpy(&cfg_config_file_buffer[offset], data, size);
} else {
// The offset_or_data field in the header contains the data itself if it's 4 bytes or less
memcpy(&config->block_entries[config->total_entries].offset_or_data, data, size);
std::memcpy(&config->block_entries[config->total_entries].offset_or_data, data, size);
}
++config->total_entries;
@@ -721,7 +732,7 @@ Module::~Module() = default;
/// Checks if the language is available in the chosen region, and returns a proper one
static std::tuple<u32 /*region*/, SystemLanguage> AdjustLanguageInfoBlock(
const std::vector<u32>& region_code, SystemLanguage language) {
std::span<const u32> region_code, SystemLanguage language) {
static const std::array<std::vector<SystemLanguage>, 7> region_languages{{
// JPN
{LANGUAGE_JP},
@@ -750,13 +761,14 @@ static std::tuple<u32 /*region*/, SystemLanguage> AdjustLanguageInfoBlock(
}
// The language is not available in any available region, so default to the first region and
// language
u32 default_region = region_code[0];
const u32 default_region = region_code[0];
return {default_region, region_languages[default_region][0]};
}
void Module::SetPreferredRegionCodes(const std::vector<u32>& region_codes) {
void Module::SetPreferredRegionCodes(std::span<const u32> region_codes) {
const SystemLanguage current_language = GetSystemLanguage();
auto [region, adjusted_language] = AdjustLanguageInfoBlock(region_codes, current_language);
const auto [region, adjusted_language] =
AdjustLanguageInfoBlock(region_codes, current_language);
preferred_region_code = region;
LOG_INFO(Service_CFG, "Preferred region code set to {}", preferred_region_code);

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