Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
cfdb10a7ba | ||
|
8012b28b92 | ||
|
531d280461 | ||
|
d702915624 | ||
|
943d5eeddf | ||
|
f3ac6f054f | ||
|
a94af8ea62 | ||
|
6da4853360 | ||
|
b738584832 | ||
|
1cb34ea0d3 | ||
|
662bb9ba77 | ||
|
26e3f96983 | ||
|
cd3244f139 | ||
|
e5310b25d4 | ||
|
80033b84cb | ||
|
cf9bb90ae3 |
8
.github/workflows/ci-merge.js
vendored
8
.github/workflows/ci-merge.js
vendored
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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>());
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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, ¶ms, &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, ¶ms, 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, ¶ms, 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);
|
||||
|
@@ -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;
|
||||
|
@@ -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()));
|
||||
|
@@ -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:
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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:
|
||||
|
@@ -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)};
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
};
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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 =
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -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:
|
||||
|
@@ -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());
|
||||
|
@@ -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;
|
||||
};
|
||||
|
@@ -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);
|
||||
|
@@ -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(
|
||||
|
@@ -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(
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -3,6 +3,7 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <QDialog>
|
||||
#include "core/dumping/ffmpeg_backend.h"
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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));
|
||||
|
@@ -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())));
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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__)
|
||||
|
@@ -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
|
@@ -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.
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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();
|
||||
|
@@ -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;
|
||||
|
@@ -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) \
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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));
|
||||
|
@@ -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: {
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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));
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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)) {
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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:
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -6,6 +6,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <span>
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/kernel/thread.h"
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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();
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
};
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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>
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -3,7 +3,7 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
#pragma optimize("", off)
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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_;
|
||||
|
@@ -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;
|
||||
|
@@ -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>();
|
||||
|
@@ -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:
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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>();
|
||||
|
@@ -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:
|
||||
|
@@ -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"},
|
||||
|
@@ -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"},
|
||||
|
@@ -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"},
|
||||
|
@@ -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;
|
||||
|
@@ -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(§ion_header, data, sizeof(section_header));
|
||||
std::memcpy(§ion_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(§ion_header, data, sizeof(section_header));
|
||||
std::memcpy(§ion_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;
|
||||
|
@@ -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____";
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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
Reference in New Issue
Block a user