Compare commits

...

57 Commits

Author SHA1 Message Date
arades79
98631b45b6 remove constexpr from virtual function
Signed-off-by: arades79 <scravers@protonmail.com>
2023-02-14 19:14:29 -05:00
arades79
880b6e9795 use a string view to skip allocation
Signed-off-by: arades79 <scravers@protonmail.com>
2023-02-14 12:35:40 -05:00
arades79
683019878f remove static from pointer sized or smaller types for aesthetics, change constexpr static to static constexpr for consistency
Signed-off-by: arades79 <scravers@protonmail.com>
2023-02-14 12:35:39 -05:00
arades79
26e44a3be4 apply clang-format
Signed-off-by: arades79 <scravers@protonmail.com>
2023-02-14 12:35:39 -05:00
arades79
392a029ef4 don't use static inside constexpr function
Signed-off-by: arades79 <scravers@protonmail.com>
2023-02-14 12:33:11 -05:00
arades79
45e13b03f3 add static lifetime to constexpr values to force compile time evaluation where possible
Signed-off-by: arades79 <scravers@protonmail.com>
2023-02-14 12:33:11 -05:00
liamwhite
5f5a6e4b2e Merge pull request #9795 from Kelebek1/biquad_fix
[audio_core] Use different state offset for each biquad filter channel
2023-02-14 09:11:26 -05:00
liamwhite
d87db919f9 Merge pull request #9793 from Morph1984/borderless-hidpi
main: Fix borderless fullscreen for high dpi scaled displays
2023-02-14 09:11:15 -05:00
Kelebek1
3a90ed99be Fix biquad filter command's state buffer offset 2023-02-13 16:21:29 +00:00
bunnei
770a49616d Merge pull request #9784 from m-HD/master
settings: added missing graphical settings to RestoreGlobalState()
2023-02-12 21:49:45 -08:00
Morph
d6677b50f6 main: Fix borderless fullscreen for high dpi scaled displays
On Windows, a borderless window will be treated the same as exclusive fullscreen
when the window geometry matches the physical dimensions of the screen.
However, with High DPI scaling, when the devicePixelRatioF() is > 1, the borderless
window apparently is not treated as exclusive fullscreen and functions correctly.
One can verify and replicate this behavior by using a high resolution (4K) display,
and switching between 100% and 200% scaling in Windows' display settings.
At 100%, without the addition of 1, it is treated as exclusive fullscreen.
At 200%, with or without the addition of 1, it is treated as borderless windowed.
Therefore, we can use (read: abuse) this difference in behavior to fix this issue for
those with higher resolution displays when the Qt scaling ratio is > 1.
Should this behavior be changed in the future, please revisit this workaround.
2023-02-12 21:58:49 -05:00
bunnei
8b74047b1b Merge pull request #9757 from german77/gyro
core: hid: Use gyro thresholds modes set by the game
2023-02-12 00:19:22 -08:00
bunnei
f70fcdb873 Merge pull request #9746 from ameerj/ogl-msaa-texcache
texture_cache: OpenGL: Implement MSAA uploads and copies
2023-02-12 00:18:52 -08:00
m-HD
9df92bad2a Update settings.cpp
added missing graphical settings to RestoreGlobalState()
2023-02-12 02:58:39 +01:00
liamwhite
fbba6e10bc Merge pull request #9781 from ColinKinloch/info_id_typo
kernel/svc: Fix undefined info_id
2023-02-11 20:13:54 -05:00
ameerj
93cf2b3ca8 texture_cache: OpenGL: Implement MSAA uploads and copies 2023-02-11 15:43:07 -05:00
Colin Kinloch
868ab0d3b4 kernel/svc: Fix undefined info_id 2023-02-11 18:00:34 +00:00
liamwhite
c97b5c9ff9 Merge pull request #9777 from vonchenplus/speed_up_video_copy
video_core: Speed up video frame data copy
2023-02-11 12:35:16 -05:00
liamwhite
709879cfc1 Merge pull request #9773 from bunnei/fix-process-resource
core: kernel: k_process: Use application system resource.
2023-02-11 10:28:50 -05:00
liamwhite
89c09d639a Merge pull request #9768 from merryhime/biquad-rounding
biquad_filter: Fix rounding in ApplyBiquadFilterInt
2023-02-11 10:28:42 -05:00
liamwhite
1040f1f503 Merge pull request #9744 from behunin/quick-release
gpu_thread: Remove OnCommandListEndCommand
2023-02-11 10:28:30 -05:00
FengChen
4adf39edf2 video_core: Speed up video frame data copy 2023-02-11 22:18:54 +08:00
bunnei
abd826ba87 Merge pull request #9742 from liamwhite/svc-wrap-only
kernel/svc: switch to generated wrappers
2023-02-10 21:41:22 -08:00
bunnei
023ac943aa Merge pull request #9759 from german77/pro_controller
input_common: Reintroduce custom pro controller support
2023-02-10 21:14:40 -08:00
bunnei
e79270507b core: kernel: k_process: Use application system resource. 2023-02-10 21:03:39 -08:00
Merry
3c60bc36a1 biquad_filter: Clamp f64 in ApplyBiquadFilterFloat 2023-02-10 20:43:34 +00:00
Merry
9bdcb1070f biquad_filter: Fix rounding in ApplyBiquadFilterInt 2023-02-10 20:34:52 +00:00
liamwhite
b3a8c0dc49 Merge pull request #9761 from Morph1984/oops
main: Re-add QtWebEngine zoom factor
2023-02-10 10:54:10 -05:00
bunnei
84743fd6ce Merge pull request #9765 from liamwhite/ffs-apple
kernel: avoid usage of bit_cast
2023-02-10 07:53:40 -08:00
Liam
36b70dec05 kernel: avoid usage of bit_cast 2023-02-10 09:13:58 -05:00
Morph
3fbb93e5c9 main: Re-add QtWebEngine zoom factor
For some reason, I had removed this in ad6cec71ec

This should fix any improperly scaled web applets.
2023-02-09 22:57:37 -05:00
liamwhite
c5743d5499 Merge pull request #9736 from Kelebek1/dynamic_vertex_attribs
Remove fake vertex bindings when dynamic state is enabled
2023-02-09 22:14:55 -05:00
liamwhite
cbb289fbee Merge pull request #9750 from ameerj/glsl-sample-id-mask
glsl_emit_context: Remove redeclarations of gl_SampleID and gl_SampleMask
2023-02-09 22:14:47 -05:00
liamwhite
c0b36c2d26 Merge pull request #9758 from german77/multi_audio
audio: cubeb: Fix yuzu crashing when it test for latency
2023-02-09 22:14:33 -05:00
Narr the Reg
acba9a6b76 input_common: Reintroduce custom pro controller support 2023-02-09 20:08:54 -06:00
Narr the Reg
7c0dcea96c audio: cubeb: Fix yuzu crashing when it test for latency 2023-02-09 19:38:03 -06:00
Narr the Reg
5e9fa5def5 core: hid: Use gyro thresholds modes set by the game 2023-02-09 19:07:50 -06:00
Matías Locatti
7bad3a7e5e Merge pull request #9749 from ameerj/pr9559-partial-revert
buffer_base: Partially revert changes from #9559
2023-02-09 17:53:45 -03:00
ameerj
eb9f16dce4 buffer_base: Partially revert changes from #9559
This fixes a regression where Yoshi's Crafted World (and potentially other titles) would enter an infinite loop when GPU Accuracy was set to "Normal"
2023-02-08 19:37:23 -05:00
ameerj
04139cb3ed glsl_emit_context: Remove redeclarations of gl_SampleID and gl_SampleMask
These built-ins seem to be available without needing to be declared for fragment shaders, similar i.e. to gl_FragDepth
2023-02-08 19:34:39 -05:00
liamwhite
f6477b91f9 Merge pull request #9747 from german77/SetSupportedNpadIdTypes
service: hid: Return error if arguments of SetSupportedNpadIdType is invalid
2023-02-08 10:09:26 -05:00
Narr the Reg
c27006e99d service: hid: Return error if arguments of SetSupportedNpadIdType is invalid 2023-02-07 21:11:39 -06:00
Mai
f3b532d091 Merge pull request #9739 from liamwhite/old-gcc-fix
kernel: fix compilation with older gcc
2023-02-07 22:10:35 -05:00
Behunin
8551ac6008 Remove OnCommandListEndCommand
Call rasterizer->ReleaseFences() directly
2023-02-07 17:21:17 -07:00
Liam
2415d37ea2 kernel/svc: switch to generated wrappers 2023-02-06 23:57:44 -05:00
liamwhite
1f3e8d633a Merge pull request #4949 from Morph1984/hidpi-temp-fix
main: Enable High DPI fixes for Qt >= 5.14
2023-02-06 23:20:49 -05:00
bunnei
ecbf74b87a Merge pull request #9644 from SaiKai/volume_quicksetting
add volume quicksetting with volume slider
2023-02-06 17:10:44 -08:00
bunnei
01cb49973a Merge pull request #9735 from merryhime/dynarmic-6.4.5
dynarmic: Update to 6.4.5
2023-02-06 17:09:17 -08:00
Liam
82c2a3da9f kernel: fix compilation with older gcc 2023-02-06 13:14:27 -05:00
liamwhite
72f78a48e3 Merge pull request #9737 from goldenx86/yuzu_cmd
Update yuzu_cmd's default_ini.h
2023-02-06 09:08:27 -05:00
Kelebek1
8ae2a664d2 Remove fake vertex bindings when dynamic state is enabled 2023-02-05 22:28:03 +00:00
Merry
3f852c61d1 dynarmic: Update to 6.4.5 2023-02-05 21:49:32 +00:00
Jonas Gutenschwager
2a491f7aaa remove disambiguation argument from mute text
Co-authored-by: Morph <39850852+Morph1984@users.noreply.github.com>
2023-02-04 00:00:20 +01:00
Morph
ad6cec71ec main: Convert to device independent coordinates for scaling
devicePixelRatioF() returns the scaling ratio when high dpi scaling is enabled.
When high dpi scaling is enabled, the raw screen coordinate system is scaled to device independent coordinates.
2023-01-25 21:16:05 -05:00
Morph
5be85c556e main: Use passthrough scaling for non-windows OSes
They should be better than windows when handling fractional scaling ratios.
2023-01-25 21:16:04 -05:00
Morph
6a1b089a50 main: Enable High DPI fixes for Qt >= 5.14
This uses Qt's new high DPI application attributes for scaling the current window.
However, these aren't perfect as scaling with non integer scales will cause artifacts in UI, icons and other elements.
Therefore, we use a heuristic to select an appropriate integer scale value depending on the current screen resolution and applies this to the application.
2023-01-25 21:16:04 -05:00
Jonas Gutenschwager
4653effad8 add volume quicksetting with volume slider 2023-01-19 15:13:23 +01:00
120 changed files with 8087 additions and 1809 deletions

View File

@@ -132,7 +132,7 @@ void AudioRenderer::CreateSinkStreams() {
}
void AudioRenderer::ThreadFunc() {
constexpr char name[]{"AudioRenderer"};
static constexpr char name[]{"AudioRenderer"};
MicroProfileOnThreadCreate(name);
Common::SetCurrentThreadName(name);
Common::SetCurrentThreadPriority(Common::ThreadPriority::Critical);

View File

@@ -251,8 +251,8 @@ void CommandBuffer::GenerateBiquadFilterCommand(const s32 node_id, EffectInfoBas
const auto& parameter{
*reinterpret_cast<BiquadFilterInfo::ParameterVersion1*>(effect_info.GetParameter())};
const auto state{
reinterpret_cast<VoiceState::BiquadFilterState*>(effect_info.GetStateBuffer())};
const auto state{reinterpret_cast<VoiceState::BiquadFilterState*>(
effect_info.GetStateBuffer() + channel * sizeof(VoiceState::BiquadFilterState))};
cmd.input = buffer_offset + parameter.inputs[channel];
cmd.output = buffer_offset + parameter.outputs[channel];

View File

@@ -4,6 +4,7 @@
#include "audio_core/renderer/adsp/command_list_processor.h"
#include "audio_core/renderer/command/effect/biquad_filter.h"
#include "audio_core/renderer/voice/voice_state.h"
#include "common/bit_cast.h"
namespace AudioCore::AudioRenderer {
/**
@@ -19,21 +20,21 @@ namespace AudioCore::AudioRenderer {
void ApplyBiquadFilterFloat(std::span<s32> output, std::span<const s32> input,
std::array<s16, 3>& b_, std::array<s16, 2>& a_,
VoiceState::BiquadFilterState& state, const u32 sample_count) {
constexpr s64 min{std::numeric_limits<s32>::min()};
constexpr s64 max{std::numeric_limits<s32>::max()};
constexpr f64 min{std::numeric_limits<s32>::min()};
constexpr f64 max{std::numeric_limits<s32>::max()};
std::array<f64, 3> b{Common::FixedPoint<50, 14>::from_base(b_[0]).to_double(),
Common::FixedPoint<50, 14>::from_base(b_[1]).to_double(),
Common::FixedPoint<50, 14>::from_base(b_[2]).to_double()};
std::array<f64, 2> a{Common::FixedPoint<50, 14>::from_base(a_[0]).to_double(),
Common::FixedPoint<50, 14>::from_base(a_[1]).to_double()};
std::array<f64, 4> s{state.s0.to_double(), state.s1.to_double(), state.s2.to_double(),
state.s3.to_double()};
std::array<f64, 4> s{Common::BitCast<f64>(state.s0), Common::BitCast<f64>(state.s1),
Common::BitCast<f64>(state.s2), Common::BitCast<f64>(state.s3)};
for (u32 i = 0; i < sample_count; i++) {
f64 in_sample{static_cast<f64>(input[i])};
auto sample{in_sample * b[0] + s[0] * b[1] + s[1] * b[2] + s[2] * a[0] + s[3] * a[1]};
output[i] = static_cast<s32>(std::clamp(static_cast<s64>(sample), min, max));
output[i] = static_cast<s32>(std::clamp(sample, min, max));
s[1] = s[0];
s[0] = in_sample;
@@ -41,10 +42,10 @@ void ApplyBiquadFilterFloat(std::span<s32> output, std::span<const s32> input,
s[2] = sample;
}
state.s0 = s[0];
state.s1 = s[1];
state.s2 = s[2];
state.s3 = s[3];
state.s0 = Common::BitCast<s64>(s[0]);
state.s1 = Common::BitCast<s64>(s[1]);
state.s2 = Common::BitCast<s64>(s[2]);
state.s3 = Common::BitCast<s64>(s[3]);
}
/**
@@ -58,29 +59,20 @@ void ApplyBiquadFilterFloat(std::span<s32> output, std::span<const s32> input,
* @param sample_count - Number of samples to process.
*/
static void ApplyBiquadFilterInt(std::span<s32> output, std::span<const s32> input,
std::array<s16, 3>& b_, std::array<s16, 2>& a_,
std::array<s16, 3>& b, std::array<s16, 2>& a,
VoiceState::BiquadFilterState& state, const u32 sample_count) {
constexpr s64 min{std::numeric_limits<s32>::min()};
constexpr s64 max{std::numeric_limits<s32>::max()};
std::array<Common::FixedPoint<50, 14>, 3> b{
Common::FixedPoint<50, 14>::from_base(b_[0]),
Common::FixedPoint<50, 14>::from_base(b_[1]),
Common::FixedPoint<50, 14>::from_base(b_[2]),
};
std::array<Common::FixedPoint<50, 14>, 3> a{
Common::FixedPoint<50, 14>::from_base(a_[0]),
Common::FixedPoint<50, 14>::from_base(a_[1]),
};
for (u32 i = 0; i < sample_count; i++) {
s64 in_sample{input[i]};
auto sample{in_sample * b[0] + state.s0};
const auto out_sample{std::clamp(sample.to_long(), min, max)};
const s64 in_sample{input[i]};
const s64 sample{in_sample * b[0] + state.s0};
const s64 out_sample{std::clamp<s64>((sample + (1 << 13)) >> 14, min, max)};
output[i] = static_cast<s32>(out_sample);
state.s0 = state.s1 + b[1] * in_sample + a[0] * out_sample;
state.s1 = 0 + b[2] * in_sample + a[1] * out_sample;
state.s1 = b[2] * in_sample + a[1] * out_sample;
}
}

View File

@@ -244,16 +244,16 @@ template <size_t NumChannels>
static void ApplyI3dl2ReverbEffect(I3dl2ReverbInfo::State& state,
std::span<std::span<const s32>> inputs,
std::span<std::span<s32>> outputs, const u32 sample_count) {
constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes1Ch{
static constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes1Ch{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes2Ch{
static constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes2Ch{
0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1,
};
constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes4Ch{
static constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes4Ch{
0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 3, 3, 3,
};
constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes6Ch{
static constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes6Ch{
2, 0, 0, 1, 1, 1, 1, 4, 4, 4, 1, 1, 1, 0, 0, 0, 0, 5, 5, 5,
};

View File

@@ -252,16 +252,16 @@ template <size_t NumChannels>
static void ApplyReverbEffect(const ReverbInfo::ParameterVersion2& params, ReverbInfo::State& state,
std::vector<std::span<const s32>>& inputs,
std::vector<std::span<s32>>& outputs, const u32 sample_count) {
constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes1Ch{
static constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes1Ch{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes2Ch{
static constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes2Ch{
0, 0, 1, 1, 0, 1, 0, 0, 1, 1,
};
constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes4Ch{
static constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes4Ch{
0, 0, 1, 1, 0, 1, 2, 2, 3, 3,
};
constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes6Ch{
static constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes6Ch{
0, 0, 1, 1, 2, 2, 4, 4, 5, 5,
};

View File

@@ -19,24 +19,24 @@ namespace AudioCore::AudioRenderer {
static void SrcProcessFrame(std::span<s32> output, std::span<const s32> input,
const u32 target_sample_count, const u32 source_sample_count,
UpsamplerState* state) {
constexpr u32 WindowSize = 10;
constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc1{
static constexpr u32 WindowSize = 10;
static constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc1{
0.95376587f, -0.12872314f, 0.060028076f, -0.032470703f, 0.017669678f,
-0.009124756f, 0.004272461f, -0.001739502f, 0.000579834f, -0.000091552734f,
};
constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc2{
static constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc2{
0.8230896f, -0.19161987f, 0.093444824f, -0.05090332f, 0.027557373f,
-0.014038086f, 0.0064697266f, -0.002532959f, 0.00079345703f, -0.00012207031f,
};
constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc3{
static constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc3{
0.6298828f, -0.19274902f, 0.09725952f, -0.05319214f, 0.028625488f,
-0.014373779f, 0.006500244f, -0.0024719238f, 0.0007324219f, -0.000091552734f,
};
constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc4{
static constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc4{
0.4057312f, -0.1468811f, 0.07601929f, -0.041656494f, 0.022216797f,
-0.011016846f, 0.004852295f, -0.0017700195f, 0.00048828125f, -0.000030517578f,
};
constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc5{
static constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc5{
0.1854248f, -0.075164795f, 0.03967285f, -0.021728516f, 0.011474609f,
-0.005584717f, 0.0024108887f, -0.0008239746f, 0.00021362305f, 0.0f,
};

View File

@@ -94,7 +94,7 @@ bool SystemManager::Remove(System& system_) {
}
void SystemManager::ThreadFunc() {
constexpr char name[]{"AudioRenderSystemManager"};
static constexpr char name[]{"AudioRenderSystemManager"};
MicroProfileOnThreadCreate(name);
Common::SetCurrentThreadName(name);
Common::SetCurrentThreadPriority(Common::ThreadPriority::High);

View File

@@ -19,10 +19,10 @@ struct VoiceState {
* State of the voice's biquad filter.
*/
struct BiquadFilterState {
Common::FixedPoint<50, 14> s0;
Common::FixedPoint<50, 14> s1;
Common::FixedPoint<50, 14> s2;
Common::FixedPoint<50, 14> s3;
s64 s0;
s64 s1;
s64 s2;
s64 s3;
};
/**

View File

@@ -302,11 +302,21 @@ std::vector<std::string> ListCubebSinkDevices(bool capture) {
std::vector<std::string> device_list;
cubeb* ctx;
#ifdef _WIN32
auto com_init_result = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
#endif
if (cubeb_init(&ctx, "yuzu Device Enumerator", nullptr) != CUBEB_OK) {
LOG_CRITICAL(Audio_Sink, "cubeb_init failed");
return {};
}
#ifdef _WIN32
if (SUCCEEDED(com_init_result)) {
CoUninitialize();
}
#endif
auto type{capture ? CUBEB_DEVICE_TYPE_INPUT : CUBEB_DEVICE_TYPE_OUTPUT};
cubeb_device_collection collection;
if (cubeb_enumerate_devices(ctx, type, &collection) != CUBEB_OK) {
@@ -329,12 +339,22 @@ std::vector<std::string> ListCubebSinkDevices(bool capture) {
u32 GetCubebLatency() {
cubeb* ctx;
#ifdef _WIN32
auto com_init_result = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
#endif
if (cubeb_init(&ctx, "yuzu Latency Getter", nullptr) != CUBEB_OK) {
LOG_CRITICAL(Audio_Sink, "cubeb_init failed");
// Return a large latency so we choose SDL instead.
return 10000u;
}
#ifdef _WIN32
if (SUCCEEDED(com_init_result)) {
CoUninitialize();
}
#endif
cubeb_stream_params params{};
params.rate = TargetSampleRate;
params.channels = 2;

View File

@@ -35,7 +35,7 @@ void SinkStream::AppendBuffer(SinkBuffer& buffer, std::vector<s16>& samples) {
if (system_channels == 6 && device_channels == 2) {
// We're given 6 channels, but our device only outputs 2, so downmix.
constexpr std::array<f32, 4> down_mix_coeff{1.0f, 0.707f, 0.251f, 0.707f};
static constexpr std::array<f32, 4> down_mix_coeff{1.0f, 0.707f, 0.251f, 0.707f};
for (u32 read_index = 0, write_index = 0; read_index < samples.size();
read_index += system_channels, write_index += device_channels) {
@@ -202,7 +202,7 @@ void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::siz
// If we're paused or going to shut down, we don't want to consume buffers as coretiming is
// paused and we'll desync, so just play silence.
if (system.IsPaused() || system.IsShuttingDown()) {
constexpr std::array<s16, 6> silence{};
static constexpr std::array<s16, 6> silence{};
for (size_t i = frames_written; i < num_frames; i++) {
std::memcpy(&output_buffer[i * frame_size], &silence[0], frame_size_bytes);
}

View File

@@ -199,7 +199,11 @@ void RestoreGlobalState(bool is_powered_on) {
values.renderer_backend.SetGlobal(true);
values.renderer_force_max_clock.SetGlobal(true);
values.vulkan_device.SetGlobal(true);
values.fullscreen_mode.SetGlobal(true);
values.aspect_ratio.SetGlobal(true);
values.resolution_setup.SetGlobal(true);
values.scaling_filter.SetGlobal(true);
values.anti_aliasing.SetGlobal(true);
values.max_anisotropy.SetGlobal(true);
values.use_speed_limit.SetGlobal(true);
values.speed_limit.SetGlobal(true);

View File

@@ -488,6 +488,7 @@ struct Values {
Setting<bool> enable_raw_input{false, "enable_raw_input"};
Setting<bool> controller_navigation{true, "controller_navigation"};
Setting<bool> enable_joycon_driver{true, "enable_joycon_driver"};
Setting<bool> enable_procon_driver{false, "enable_procon_driver"};
SwitchableSetting<bool> vibration_enabled{true, "vibration_enabled"};
SwitchableSetting<bool> enable_accurate_vibrations{false, "enable_accurate_vibrations"};

View File

@@ -310,6 +310,7 @@ add_library(core STATIC
hle/kernel/svc/svc_event.cpp
hle/kernel/svc/svc_exception.cpp
hle/kernel/svc/svc_info.cpp
hle/kernel/svc/svc_insecure_memory.cpp
hle/kernel/svc/svc_interrupt_event.cpp
hle/kernel/svc/svc_io_pool.cpp
hle/kernel/svc/svc_ipc.cpp

View File

@@ -5,6 +5,7 @@
#include <array>
#include <span>
#include <string>
#include <vector>
#include <dynarmic/interface/halt_reason.h>

View File

@@ -45,7 +45,7 @@ CoreTiming::~CoreTiming() {
}
void CoreTiming::ThreadEntry(CoreTiming& instance) {
constexpr char name[] = "HostTiming";
static constexpr char name[] = "HostTiming";
MicroProfileOnThreadCreate(name);
Common::SetCurrentThreadName(name);
Common::SetCurrentThreadPriority(Common::ThreadPriority::Critical);

View File

@@ -41,9 +41,8 @@ static void PutSIMDRegister(std::array<u32, 64>& simd_regs, size_t offset, const
// For sample XML files see the GDB source /gdb/features
// This XML defines what the registers are for this specific ARM device
std::string GDBStubA64::GetTargetXML() const {
constexpr const char* target_xml =
R"(<?xml version="1.0"?>
std::string_view GDBStubA64::GetTargetXML() const {
return R"(<?xml version="1.0"?>
<!DOCTYPE target SYSTEM "gdb-target.dtd">
<target version="1.0">
<architecture>aarch64</architecture>
@@ -178,8 +177,6 @@ std::string GDBStubA64::GetTargetXML() const {
<reg name="fpcr" bitsize="32"/>
</feature>
</target>)";
return target_xml;
}
std::string GDBStubA64::RegRead(const Kernel::KThread* thread, size_t id) const {
@@ -270,9 +267,8 @@ u32 GDBStubA64::BreakpointInstruction() const {
return 0xd4200000;
}
std::string GDBStubA32::GetTargetXML() const {
constexpr const char* target_xml =
R"(<?xml version="1.0"?>
std::string_view GDBStubA32::GetTargetXML() const {
return R"(<?xml version="1.0"?>
<!DOCTYPE target SYSTEM "gdb-target.dtd">
<target version="1.0">
<architecture>arm</architecture>
@@ -378,8 +374,6 @@ std::string GDBStubA32::GetTargetXML() const {
<reg name="fpscr" bitsize="32" type="int" group="float" regnum="80"/>
</feature>
</target>)";
return target_xml;
}
std::string GDBStubA32::RegRead(const Kernel::KThread* thread, size_t id) const {

View File

@@ -16,7 +16,7 @@ namespace Core {
class GDBStubArch {
public:
virtual ~GDBStubArch() = default;
virtual std::string GetTargetXML() const = 0;
virtual std::string_view GetTargetXML() const = 0;
virtual std::string RegRead(const Kernel::KThread* thread, size_t id) const = 0;
virtual void RegWrite(Kernel::KThread* thread, size_t id, std::string_view value) const = 0;
virtual std::string ReadRegisters(const Kernel::KThread* thread) const = 0;
@@ -27,7 +27,7 @@ public:
class GDBStubA64 final : public GDBStubArch {
public:
std::string GetTargetXML() const override;
std::string_view GetTargetXML() const override;
std::string RegRead(const Kernel::KThread* thread, size_t id) const override;
void RegWrite(Kernel::KThread* thread, size_t id, std::string_view value) const override;
std::string ReadRegisters(const Kernel::KThread* thread) const override;
@@ -47,7 +47,7 @@ private:
class GDBStubA32 final : public GDBStubArch {
public:
std::string GetTargetXML() const override;
std::string_view GetTargetXML() const override;
std::string RegRead(const Kernel::KThread* thread, size_t id) const override;
void RegWrite(Kernel::KThread* thread, size_t id, std::string_view value) const override;
std::string ReadRegisters(const Kernel::KThread* thread) const override;

View File

@@ -41,12 +41,12 @@ static IPSFileType IdentifyMagic(const std::vector<u8>& magic) {
return IPSFileType::Error;
}
constexpr std::array<u8, 5> patch_magic{{'P', 'A', 'T', 'C', 'H'}};
static constexpr std::array<u8, 5> patch_magic{{'P', 'A', 'T', 'C', 'H'}};
if (std::equal(magic.begin(), magic.end(), patch_magic.begin())) {
return IPSFileType::IPS;
}
constexpr std::array<u8, 5> ips32_magic{{'I', 'P', 'S', '3', '2'}};
static constexpr std::array<u8, 5> ips32_magic{{'I', 'P', 'S', '3', '2'}};
if (std::equal(magic.begin(), magic.end(), ips32_magic.begin())) {
return IPSFileType::IPS32;
}
@@ -55,12 +55,12 @@ static IPSFileType IdentifyMagic(const std::vector<u8>& magic) {
}
static bool IsEOF(IPSFileType type, const std::vector<u8>& data) {
constexpr std::array<u8, 3> eof{{'E', 'O', 'F'}};
static constexpr std::array<u8, 3> eof{{'E', 'O', 'F'}};
if (type == IPSFileType::IPS && std::equal(data.begin(), data.end(), eof.begin())) {
return true;
}
constexpr std::array<u8, 4> eeof{{'E', 'E', 'O', 'F'}};
static constexpr std::array<u8, 4> eeof{{'E', 'E', 'O', 'F'}};
return type == IPSFileType::IPS32 && std::equal(data.begin(), data.end(), eeof.begin());
}

View File

@@ -71,7 +71,7 @@ static std::string GetRelativePathFromNcaID(const std::array<u8, 16>& nca_id, bo
}
static std::string GetCNMTName(TitleType type, u64 title_id) {
constexpr std::array<const char*, 9> TITLE_TYPE_NAMES{
static constexpr std::array<const char*, 9> TITLE_TYPE_NAMES{
"SystemProgram",
"SystemData",
"SystemUpdate",

View File

@@ -957,7 +957,7 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback
raw_status.gyro.y.value,
raw_status.gyro.z.value,
});
emulated.SetGyroThreshold(raw_status.gyro.x.properties.threshold);
emulated.SetUserGyroThreshold(raw_status.gyro.x.properties.threshold);
emulated.UpdateRotation(raw_status.delta_timestamp);
emulated.UpdateOrientation(raw_status.delta_timestamp);
force_update_motion = raw_status.force_update;
@@ -1284,6 +1284,26 @@ void EmulatedController::SetLedPattern() {
}
}
void EmulatedController::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode mode) {
for (auto& motion : controller.motion_values) {
switch (mode) {
case GyroscopeZeroDriftMode::Loose:
motion_sensitivity = motion.emulated.IsAtRestLoose;
motion.emulated.SetGyroThreshold(motion.emulated.ThresholdLoose);
break;
case GyroscopeZeroDriftMode::Tight:
motion_sensitivity = motion.emulated.IsAtRestThight;
motion.emulated.SetGyroThreshold(motion.emulated.ThresholdThight);
break;
case GyroscopeZeroDriftMode::Standard:
default:
motion_sensitivity = motion.emulated.IsAtRestStandard;
motion.emulated.SetGyroThreshold(motion.emulated.ThresholdStandard);
break;
}
}
}
void EmulatedController::SetSupportedNpadStyleTag(NpadStyleTag supported_styles) {
supported_style_tag = supported_styles;
if (!is_connected) {

View File

@@ -398,6 +398,9 @@ public:
/// Asks the output device to change the player led pattern
void SetLedPattern();
/// Changes sensitivity of the motion sensor
void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode mode);
/**
* Adds a callback to the list of events
* @param update_callback A ConsoleUpdateCallback that will be triggered
@@ -523,7 +526,7 @@ private:
bool is_connected{false};
bool is_configuring{false};
bool system_buttons_enabled{true};
f32 motion_sensitivity{0.01f};
f32 motion_sensitivity{Core::HID::MotionInput::IsAtRestStandard};
bool force_update_motion{false};
u32 turbo_button_state{0};

View File

@@ -282,6 +282,13 @@ enum class VibrationGcErmCommand : u64 {
StopHard = 2,
};
// This is nn::hid::GyroscopeZeroDriftMode
enum class GyroscopeZeroDriftMode : u32 {
Loose = 0,
Standard = 1,
Tight = 2,
};
// This is nn::hid::NpadStyleTag
struct NpadStyleTag {
union {

View File

@@ -9,7 +9,7 @@ namespace Core::HID {
MotionInput::MotionInput() {
// Initialize PID constants with default values
SetPID(0.3f, 0.005f, 0.0f);
SetGyroThreshold(0.007f);
SetGyroThreshold(ThresholdStandard);
}
void MotionInput::SetPID(f32 new_kp, f32 new_ki, f32 new_kd) {
@@ -26,11 +26,11 @@ void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) {
gyro = gyroscope - gyro_bias;
// Auto adjust drift to minimize drift
if (!IsMoving(0.1f)) {
if (!IsMoving(IsAtRestRelaxed)) {
gyro_bias = (gyro_bias * 0.9999f) + (gyroscope * 0.0001f);
}
if (gyro.Length() < gyro_threshold) {
if (gyro.Length() < gyro_threshold * user_gyro_threshold) {
gyro = {};
} else {
only_accelerometer = false;
@@ -49,6 +49,10 @@ void MotionInput::SetGyroThreshold(f32 threshold) {
gyro_threshold = threshold;
}
void MotionInput::SetUserGyroThreshold(f32 threshold) {
user_gyro_threshold = threshold / ThresholdStandard;
}
void MotionInput::EnableReset(bool reset) {
reset_enabled = reset;
}
@@ -208,7 +212,7 @@ void MotionInput::ResetOrientation() {
if (!reset_enabled || only_accelerometer) {
return;
}
if (!IsMoving(0.5f) && accel.z <= -0.9f) {
if (!IsMoving(IsAtRestRelaxed) && accel.z <= -0.9f) {
++reset_counter;
if (reset_counter > 900) {
quat.w = 0;

View File

@@ -11,6 +11,15 @@ namespace Core::HID {
class MotionInput {
public:
static constexpr float ThresholdLoose = 0.01f;
static constexpr float ThresholdStandard = 0.007f;
static constexpr float ThresholdThight = 0.002f;
static constexpr float IsAtRestRelaxed = 0.05f;
static constexpr float IsAtRestLoose = 0.02f;
static constexpr float IsAtRestStandard = 0.01f;
static constexpr float IsAtRestThight = 0.005f;
explicit MotionInput();
MotionInput(const MotionInput&) = default;
@@ -26,6 +35,9 @@ public:
void SetGyroBias(const Common::Vec3f& bias);
void SetGyroThreshold(f32 threshold);
/// Applies a modifier on top of the normal gyro threshold
void SetUserGyroThreshold(f32 threshold);
void EnableReset(bool reset);
void ResetRotations();
@@ -74,6 +86,9 @@ private:
// Minimum gyro amplitude to detect if the device is moving
f32 gyro_threshold = 0.0f;
// Multiplies gyro_threshold by this value
f32 user_gyro_threshold = 0.0f;
// Number of invalid sequential data
u32 reset_counter = 0;

View File

@@ -203,23 +203,23 @@ Result KCapabilities::ProcessMapRegionCapability(const u32 cap, F f) {
Result KCapabilities::MapRegion_(const u32 cap, KPageTable* page_table) {
// Map each region into the process's page table.
R_RETURN(ProcessMapRegionCapability(
return ProcessMapRegionCapability(
cap, [](KMemoryRegionType region_type, KMemoryPermission perm) -> Result {
// R_RETURN(page_table->MapRegion(region_type, perm));
UNIMPLEMENTED();
R_SUCCEED();
}));
});
}
Result KCapabilities::CheckMapRegion(KernelCore& kernel, const u32 cap) {
// Check that each region has a physical backing store.
R_RETURN(ProcessMapRegionCapability(
return ProcessMapRegionCapability(
cap, [&](KMemoryRegionType region_type, KMemoryPermission perm) -> Result {
R_UNLESS(kernel.MemoryLayout().GetPhysicalMemoryRegionTree().FindFirstDerived(
region_type) != nullptr,
ResultOutOfRange);
R_SUCCEED();
}));
});
}
Result KCapabilities::SetInterruptPairCapability(const u32 cap) {

View File

@@ -370,7 +370,7 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:
// Initialize proces address space
if (const Result result{page_table.InitializeForProcess(
metadata.GetAddressSpaceType(), false, false, false, KMemoryManager::Pool::Application,
0x8000000, code_size, &kernel.GetSystemSystemResource(), resource_limit)};
0x8000000, code_size, &kernel.GetAppSystemResource(), resource_limit)};
result.IsError()) {
R_RETURN(result);
}

View File

@@ -1146,6 +1146,14 @@ const KMemoryManager& KernelCore::MemoryManager() const {
return *impl->memory_manager;
}
KSystemResource& KernelCore::GetAppSystemResource() {
return *impl->app_system_resource;
}
const KSystemResource& KernelCore::GetAppSystemResource() const {
return *impl->app_system_resource;
}
KSystemResource& KernelCore::GetSystemSystemResource() {
return *impl->sys_system_resource;
}

View File

@@ -246,6 +246,12 @@ public:
/// Gets the virtual memory manager for the kernel.
const KMemoryManager& MemoryManager() const;
/// Gets the application resource manager.
KSystemResource& GetAppSystemResource();
/// Gets the application resource manager.
const KSystemResource& GetAppSystemResource() const;
/// Gets the system resource manager.
KSystemResource& GetSystemSystemResource();

View File

@@ -3,6 +3,7 @@
#pragma once
#include <condition_variable>
#include <cstddef>
#include <memory>
#include <mutex>

File diff suppressed because it is too large Load Diff

View File

@@ -1,172 +1,536 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
// This file is automatically generated using svc_generator.py.
#include "common/common_types.h"
#include "core/hle/kernel/svc_types.h"
#include "core/hle/result.h"
#pragma once
namespace Core {
class System;
}
#include "common/common_types.h"
#include "core/hle/kernel/svc_types.h"
#include "core/hle/result.h"
namespace Kernel::Svc {
void Call(Core::System& system, u32 immediate);
Result SetHeapSize(Core::System& system, VAddr* out_address, u64 size);
Result SetMemoryPermission(Core::System& system, VAddr address, u64 size, MemoryPermission perm);
Result SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask, u32 attr);
Result MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size);
Result UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size);
Result QueryMemory(Core::System& system, VAddr memory_info_address, VAddr page_info_address,
VAddr query_address);
// clang-format off
Result SetHeapSize(Core::System& system, uintptr_t* out_address, uint64_t size);
Result SetMemoryPermission(Core::System& system, uint64_t address, uint64_t size, MemoryPermission perm);
Result SetMemoryAttribute(Core::System& system, uint64_t address, uint64_t size, uint32_t mask, uint32_t attr);
Result MapMemory(Core::System& system, uint64_t dst_address, uint64_t src_address, uint64_t size);
Result UnmapMemory(Core::System& system, uint64_t dst_address, uint64_t src_address, uint64_t size);
Result QueryMemory(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info, uint64_t address);
void ExitProcess(Core::System& system);
Result CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point, u64 arg,
VAddr stack_bottom, u32 priority, s32 core_id);
Result CreateThread(Core::System& system, Handle* out_handle, uint64_t func, uint64_t arg, uint64_t stack_bottom, int32_t priority, int32_t core_id);
Result StartThread(Core::System& system, Handle thread_handle);
void ExitThread(Core::System& system);
void SleepThread(Core::System& system, s64 nanoseconds);
Result GetThreadPriority(Core::System& system, u32* out_priority, Handle handle);
Result SetThreadPriority(Core::System& system, Handle thread_handle, u32 priority);
Result GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id,
u64* out_affinity_mask);
Result SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id,
u64 affinity_mask);
u32 GetCurrentProcessorNumber(Core::System& system);
void SleepThread(Core::System& system, int64_t ns);
Result GetThreadPriority(Core::System& system, int32_t* out_priority, Handle thread_handle);
Result SetThreadPriority(Core::System& system, Handle thread_handle, int32_t priority);
Result GetThreadCoreMask(Core::System& system, int32_t* out_core_id, uint64_t* out_affinity_mask, Handle thread_handle);
Result SetThreadCoreMask(Core::System& system, Handle thread_handle, int32_t core_id, uint64_t affinity_mask);
int32_t GetCurrentProcessorNumber(Core::System& system);
Result SignalEvent(Core::System& system, Handle event_handle);
Result ClearEvent(Core::System& system, Handle event_handle);
Result MapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, u64 size,
MemoryPermission map_perm);
Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, u64 size);
Result CreateTransferMemory(Core::System& system, Handle* out, VAddr address, u64 size,
MemoryPermission map_perm);
Result MapSharedMemory(Core::System& system, Handle shmem_handle, uint64_t address, uint64_t size, MemoryPermission map_perm);
Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, uint64_t address, uint64_t size);
Result CreateTransferMemory(Core::System& system, Handle* out_handle, uint64_t address, uint64_t size, MemoryPermission map_perm);
Result CloseHandle(Core::System& system, Handle handle);
Result ResetSignal(Core::System& system, Handle handle);
Result WaitSynchronization(Core::System& system, s32* index, VAddr handles_address, s32 num_handles,
s64 nano_seconds);
Result WaitSynchronization(Core::System& system, int32_t* out_index, uint64_t handles, int32_t num_handles, int64_t timeout_ns);
Result CancelSynchronization(Core::System& system, Handle handle);
Result ArbitrateLock(Core::System& system, Handle thread_handle, VAddr address, u32 tag);
Result ArbitrateUnlock(Core::System& system, VAddr address);
Result WaitProcessWideKeyAtomic(Core::System& system, VAddr address, VAddr cv_key, u32 tag,
s64 timeout_ns);
void SignalProcessWideKey(Core::System& system, VAddr cv_key, s32 count);
u64 GetSystemTick(Core::System& system);
Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr port_name_address);
Result SendSyncRequest(Core::System& system, Handle handle);
Result GetProcessId(Core::System& system, u64* out_process_id, Handle handle);
Result GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle);
void Break(Core::System& system, u32 reason, u64 info1, u64 info2);
void OutputDebugString(Core::System& system, VAddr address, u64 len);
Result GetInfo(Core::System& system, u64* result, u64 info_id, Handle handle, u64 info_sub_id);
Result MapPhysicalMemory(Core::System& system, VAddr addr, u64 size);
Result UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size);
Result GetResourceLimitLimitValue(Core::System& system, u64* out_limit_value,
Handle resource_limit_handle, LimitableResource which);
Result GetResourceLimitCurrentValue(Core::System& system, u64* out_current_value,
Handle resource_limit_handle, LimitableResource which);
Result SetThreadActivity(Core::System& system, Handle thread_handle,
ThreadActivity thread_activity);
Result GetThreadContext(Core::System& system, VAddr out_context, Handle thread_handle);
Result WaitForAddress(Core::System& system, VAddr address, ArbitrationType arb_type, s32 value,
s64 timeout_ns);
Result SignalToAddress(Core::System& system, VAddr address, SignalType signal_type, s32 value,
s32 count);
Result ArbitrateLock(Core::System& system, Handle thread_handle, uint64_t address, uint32_t tag);
Result ArbitrateUnlock(Core::System& system, uint64_t address);
Result WaitProcessWideKeyAtomic(Core::System& system, uint64_t address, uint64_t cv_key, uint32_t tag, int64_t timeout_ns);
void SignalProcessWideKey(Core::System& system, uint64_t cv_key, int32_t count);
int64_t GetSystemTick(Core::System& system);
Result ConnectToNamedPort(Core::System& system, Handle* out_handle, uint64_t name);
Result SendSyncRequest(Core::System& system, Handle session_handle);
Result SendSyncRequestWithUserBuffer(Core::System& system, uint64_t message_buffer, uint64_t message_buffer_size, Handle session_handle);
Result SendAsyncRequestWithUserBuffer(Core::System& system, Handle* out_event_handle, uint64_t message_buffer, uint64_t message_buffer_size, Handle session_handle);
Result GetProcessId(Core::System& system, uint64_t* out_process_id, Handle process_handle);
Result GetThreadId(Core::System& system, uint64_t* out_thread_id, Handle thread_handle);
void Break(Core::System& system, BreakReason break_reason, uint64_t arg, uint64_t size);
Result OutputDebugString(Core::System& system, uint64_t debug_str, uint64_t len);
void ReturnFromException(Core::System& system, Result result);
Result GetInfo(Core::System& system, uint64_t* out, InfoType info_type, Handle handle, uint64_t info_subtype);
void FlushEntireDataCache(Core::System& system);
Result FlushDataCache(Core::System& system, uint64_t address, uint64_t size);
Result MapPhysicalMemory(Core::System& system, uint64_t address, uint64_t size);
Result UnmapPhysicalMemory(Core::System& system, uint64_t address, uint64_t size);
Result GetDebugFutureThreadInfo(Core::System& system, lp64::LastThreadContext* out_context, uint64_t* out_thread_id, Handle debug_handle, int64_t ns);
Result GetLastThreadInfo(Core::System& system, lp64::LastThreadContext* out_context, uintptr_t* out_tls_address, uint32_t* out_flags);
Result GetResourceLimitLimitValue(Core::System& system, int64_t* out_limit_value, Handle resource_limit_handle, LimitableResource which);
Result GetResourceLimitCurrentValue(Core::System& system, int64_t* out_current_value, Handle resource_limit_handle, LimitableResource which);
Result SetThreadActivity(Core::System& system, Handle thread_handle, ThreadActivity thread_activity);
Result GetThreadContext3(Core::System& system, uint64_t out_context, Handle thread_handle);
Result WaitForAddress(Core::System& system, uint64_t address, ArbitrationType arb_type, int32_t value, int64_t timeout_ns);
Result SignalToAddress(Core::System& system, uint64_t address, SignalType signal_type, int32_t value, int32_t count);
void SynchronizePreemptionState(Core::System& system);
void KernelDebug(Core::System& system, u32 kernel_debug_type, u64 param1, u64 param2, u64 param3);
void ChangeKernelTraceState(Core::System& system, u32 trace_state);
Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, u32 is_light,
u64 name);
Result ReplyAndReceive(Core::System& system, s32* out_index, Handle* handles, s32 num_handles,
Handle reply_target, s64 timeout_ns);
Result CreateEvent(Core::System& system, Handle* out_write, Handle* out_read);
Result CreateCodeMemory(Core::System& system, Handle* out, VAddr address, size_t size);
Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, u32 operation,
VAddr address, size_t size, MemoryPermission perm);
Result GetProcessList(Core::System& system, u32* out_num_processes, VAddr out_process_ids,
u32 out_process_ids_size);
Result GetThreadList(Core::System& system, u32* out_num_threads, VAddr out_thread_ids,
u32 out_thread_ids_size, Handle debug_handle);
Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, VAddr address,
u64 size, MemoryPermission perm);
Result MapProcessMemory(Core::System& system, VAddr dst_address, Handle process_handle,
VAddr src_address, u64 size);
Result UnmapProcessMemory(Core::System& system, VAddr dst_address, Handle process_handle,
VAddr src_address, u64 size);
Result QueryProcessMemory(Core::System& system, VAddr memory_info_address, VAddr page_info_address,
Handle process_handle, VAddr address);
Result MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,
u64 src_address, u64 size);
Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,
u64 src_address, u64 size);
Result GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type);
Result GetResourceLimitPeakValue(Core::System& system, int64_t* out_peak_value, Handle resource_limit_handle, LimitableResource which);
Result CreateIoPool(Core::System& system, Handle* out_handle, IoPoolType which);
Result CreateIoRegion(Core::System& system, Handle* out_handle, Handle io_pool, uint64_t physical_address, uint64_t size, MemoryMapping mapping, MemoryPermission perm);
void KernelDebug(Core::System& system, KernelDebugType kern_debug_type, uint64_t arg0, uint64_t arg1, uint64_t arg2);
void ChangeKernelTraceState(Core::System& system, KernelTraceState kern_trace_state);
Result CreateSession(Core::System& system, Handle* out_server_session_handle, Handle* out_client_session_handle, bool is_light, uint64_t name);
Result AcceptSession(Core::System& system, Handle* out_handle, Handle port);
Result ReplyAndReceive(Core::System& system, int32_t* out_index, uint64_t handles, int32_t num_handles, Handle reply_target, int64_t timeout_ns);
Result ReplyAndReceiveWithUserBuffer(Core::System& system, int32_t* out_index, uint64_t message_buffer, uint64_t message_buffer_size, uint64_t handles, int32_t num_handles, Handle reply_target, int64_t timeout_ns);
Result CreateEvent(Core::System& system, Handle* out_write_handle, Handle* out_read_handle);
Result MapIoRegion(Core::System& system, Handle io_region, uint64_t address, uint64_t size, MemoryPermission perm);
Result UnmapIoRegion(Core::System& system, Handle io_region, uint64_t address, uint64_t size);
Result MapPhysicalMemoryUnsafe(Core::System& system, uint64_t address, uint64_t size);
Result UnmapPhysicalMemoryUnsafe(Core::System& system, uint64_t address, uint64_t size);
Result SetUnsafeLimit(Core::System& system, uint64_t limit);
Result CreateCodeMemory(Core::System& system, Handle* out_handle, uint64_t address, uint64_t size);
Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, CodeMemoryOperation operation, uint64_t address, uint64_t size, MemoryPermission perm);
void SleepSystem(Core::System& system);
Result ReadWriteRegister(Core::System& system, uint32_t* out_value, uint64_t address, uint32_t mask, uint32_t value);
Result SetProcessActivity(Core::System& system, Handle process_handle, ProcessActivity process_activity);
Result CreateSharedMemory(Core::System& system, Handle* out_handle, uint64_t size, MemoryPermission owner_perm, MemoryPermission remote_perm);
Result MapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t address, uint64_t size, MemoryPermission owner_perm);
Result UnmapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t address, uint64_t size);
Result CreateInterruptEvent(Core::System& system, Handle* out_read_handle, int32_t interrupt_id, InterruptType interrupt_type);
Result QueryPhysicalAddress(Core::System& system, lp64::PhysicalMemoryInfo* out_info, uint64_t address);
Result QueryIoMapping(Core::System& system, uintptr_t* out_address, uintptr_t* out_size, uint64_t physical_address, uint64_t size);
Result CreateDeviceAddressSpace(Core::System& system, Handle* out_handle, uint64_t das_address, uint64_t das_size);
Result AttachDeviceAddressSpace(Core::System& system, DeviceName device_name, Handle das_handle);
Result DetachDeviceAddressSpace(Core::System& system, DeviceName device_name, Handle das_handle);
Result MapDeviceAddressSpaceByForce(Core::System& system, Handle das_handle, Handle process_handle, uint64_t process_address, uint64_t size, uint64_t device_address, uint32_t option);
Result MapDeviceAddressSpaceAligned(Core::System& system, Handle das_handle, Handle process_handle, uint64_t process_address, uint64_t size, uint64_t device_address, uint32_t option);
Result UnmapDeviceAddressSpace(Core::System& system, Handle das_handle, Handle process_handle, uint64_t process_address, uint64_t size, uint64_t device_address);
Result InvalidateProcessDataCache(Core::System& system, Handle process_handle, uint64_t address, uint64_t size);
Result StoreProcessDataCache(Core::System& system, Handle process_handle, uint64_t address, uint64_t size);
Result FlushProcessDataCache(Core::System& system, Handle process_handle, uint64_t address, uint64_t size);
Result DebugActiveProcess(Core::System& system, Handle* out_handle, uint64_t process_id);
Result BreakDebugProcess(Core::System& system, Handle debug_handle);
Result TerminateDebugProcess(Core::System& system, Handle debug_handle);
Result GetDebugEvent(Core::System& system, uint64_t out_info, Handle debug_handle);
Result ContinueDebugEvent(Core::System& system, Handle debug_handle, uint32_t flags, uint64_t thread_ids, int32_t num_thread_ids);
Result GetProcessList(Core::System& system, int32_t* out_num_processes, uint64_t out_process_ids, int32_t max_out_count);
Result GetThreadList(Core::System& system, int32_t* out_num_threads, uint64_t out_thread_ids, int32_t max_out_count, Handle debug_handle);
Result GetDebugThreadContext(Core::System& system, uint64_t out_context, Handle debug_handle, uint64_t thread_id, uint32_t context_flags);
Result SetDebugThreadContext(Core::System& system, Handle debug_handle, uint64_t thread_id, uint64_t context, uint32_t context_flags);
Result QueryDebugProcessMemory(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info, Handle process_handle, uint64_t address);
Result ReadDebugProcessMemory(Core::System& system, uint64_t buffer, Handle debug_handle, uint64_t address, uint64_t size);
Result WriteDebugProcessMemory(Core::System& system, Handle debug_handle, uint64_t buffer, uint64_t address, uint64_t size);
Result SetHardwareBreakPoint(Core::System& system, HardwareBreakPointRegisterName name, uint64_t flags, uint64_t value);
Result GetDebugThreadParam(Core::System& system, uint64_t* out_64, uint32_t* out_32, Handle debug_handle, uint64_t thread_id, DebugThreadParam param);
Result GetSystemInfo(Core::System& system, uint64_t* out, SystemInfoType info_type, Handle handle, uint64_t info_subtype);
Result CreatePort(Core::System& system, Handle* out_server_handle, Handle* out_client_handle, int32_t max_sessions, bool is_light, uint64_t name);
Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t name, int32_t max_sessions);
Result ConnectToPort(Core::System& system, Handle* out_handle, Handle port);
Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, uint64_t address, uint64_t size, MemoryPermission perm);
Result MapProcessMemory(Core::System& system, uint64_t dst_address, Handle process_handle, uint64_t src_address, uint64_t size);
Result UnmapProcessMemory(Core::System& system, uint64_t dst_address, Handle process_handle, uint64_t src_address, uint64_t size);
Result QueryProcessMemory(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info, Handle process_handle, uint64_t address);
Result MapProcessCodeMemory(Core::System& system, Handle process_handle, uint64_t dst_address, uint64_t src_address, uint64_t size);
Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, uint64_t dst_address, uint64_t src_address, uint64_t size);
Result CreateProcess(Core::System& system, Handle* out_handle, uint64_t parameters, uint64_t caps, int32_t num_caps);
Result StartProcess(Core::System& system, Handle process_handle, int32_t priority, int32_t core_id, uint64_t main_thread_stack_size);
Result TerminateProcess(Core::System& system, Handle process_handle);
Result GetProcessInfo(Core::System& system, int64_t* out_info, Handle process_handle, ProcessInfoType info_type);
Result CreateResourceLimit(Core::System& system, Handle* out_handle);
Result SetResourceLimitLimitValue(Core::System& system, Handle resource_limit_handle,
LimitableResource which, u64 limit_value);
Result SetResourceLimitLimitValue(Core::System& system, Handle resource_limit_handle, LimitableResource which, int64_t limit_value);
Result MapInsecureMemory(Core::System& system, uint64_t address, uint64_t size);
Result UnmapInsecureMemory(Core::System& system, uint64_t address, uint64_t size);
//
Result SetHeapSize64From32(Core::System& system, uintptr_t* out_address, uint32_t size);
Result SetMemoryPermission64From32(Core::System& system, uint32_t address, uint32_t size, MemoryPermission perm);
Result SetMemoryAttribute64From32(Core::System& system, uint32_t address, uint32_t size, uint32_t mask, uint32_t attr);
Result MapMemory64From32(Core::System& system, uint32_t dst_address, uint32_t src_address, uint32_t size);
Result UnmapMemory64From32(Core::System& system, uint32_t dst_address, uint32_t src_address, uint32_t size);
Result QueryMemory64From32(Core::System& system, uint32_t out_memory_info, PageInfo* out_page_info, uint32_t address);
void ExitProcess64From32(Core::System& system);
Result CreateThread64From32(Core::System& system, Handle* out_handle, uint32_t func, uint32_t arg, uint32_t stack_bottom, int32_t priority, int32_t core_id);
Result StartThread64From32(Core::System& system, Handle thread_handle);
void ExitThread64From32(Core::System& system);
void SleepThread64From32(Core::System& system, int64_t ns);
Result GetThreadPriority64From32(Core::System& system, int32_t* out_priority, Handle thread_handle);
Result SetThreadPriority64From32(Core::System& system, Handle thread_handle, int32_t priority);
Result GetThreadCoreMask64From32(Core::System& system, int32_t* out_core_id, uint64_t* out_affinity_mask, Handle thread_handle);
Result SetThreadCoreMask64From32(Core::System& system, Handle thread_handle, int32_t core_id, uint64_t affinity_mask);
int32_t GetCurrentProcessorNumber64From32(Core::System& system);
Result SignalEvent64From32(Core::System& system, Handle event_handle);
Result ClearEvent64From32(Core::System& system, Handle event_handle);
Result MapSharedMemory64From32(Core::System& system, Handle shmem_handle, uint32_t address, uint32_t size, MemoryPermission map_perm);
Result UnmapSharedMemory64From32(Core::System& system, Handle shmem_handle, uint32_t address, uint32_t size);
Result CreateTransferMemory64From32(Core::System& system, Handle* out_handle, uint32_t address, uint32_t size, MemoryPermission map_perm);
Result CloseHandle64From32(Core::System& system, Handle handle);
Result ResetSignal64From32(Core::System& system, Handle handle);
Result WaitSynchronization64From32(Core::System& system, int32_t* out_index, uint32_t handles, int32_t num_handles, int64_t timeout_ns);
Result CancelSynchronization64From32(Core::System& system, Handle handle);
Result ArbitrateLock64From32(Core::System& system, Handle thread_handle, uint32_t address, uint32_t tag);
Result ArbitrateUnlock64From32(Core::System& system, uint32_t address);
Result WaitProcessWideKeyAtomic64From32(Core::System& system, uint32_t address, uint32_t cv_key, uint32_t tag, int64_t timeout_ns);
void SignalProcessWideKey64From32(Core::System& system, uint32_t cv_key, int32_t count);
int64_t GetSystemTick64From32(Core::System& system);
Result ConnectToNamedPort64From32(Core::System& system, Handle* out_handle, uint32_t name);
Result SendSyncRequest64From32(Core::System& system, Handle session_handle);
Result SendSyncRequestWithUserBuffer64From32(Core::System& system, uint32_t message_buffer, uint32_t message_buffer_size, Handle session_handle);
Result SendAsyncRequestWithUserBuffer64From32(Core::System& system, Handle* out_event_handle, uint32_t message_buffer, uint32_t message_buffer_size, Handle session_handle);
Result GetProcessId64From32(Core::System& system, uint64_t* out_process_id, Handle process_handle);
Result GetThreadId64From32(Core::System& system, uint64_t* out_thread_id, Handle thread_handle);
void Break64From32(Core::System& system, BreakReason break_reason, uint32_t arg, uint32_t size);
Result OutputDebugString64From32(Core::System& system, uint32_t debug_str, uint32_t len);
void ReturnFromException64From32(Core::System& system, Result result);
Result GetInfo64From32(Core::System& system, uint64_t* out, InfoType info_type, Handle handle, uint64_t info_subtype);
void FlushEntireDataCache64From32(Core::System& system);
Result FlushDataCache64From32(Core::System& system, uint32_t address, uint32_t size);
Result MapPhysicalMemory64From32(Core::System& system, uint32_t address, uint32_t size);
Result UnmapPhysicalMemory64From32(Core::System& system, uint32_t address, uint32_t size);
Result GetDebugFutureThreadInfo64From32(Core::System& system, ilp32::LastThreadContext* out_context, uint64_t* out_thread_id, Handle debug_handle, int64_t ns);
Result GetLastThreadInfo64From32(Core::System& system, ilp32::LastThreadContext* out_context, uintptr_t* out_tls_address, uint32_t* out_flags);
Result GetResourceLimitLimitValue64From32(Core::System& system, int64_t* out_limit_value, Handle resource_limit_handle, LimitableResource which);
Result GetResourceLimitCurrentValue64From32(Core::System& system, int64_t* out_current_value, Handle resource_limit_handle, LimitableResource which);
Result SetThreadActivity64From32(Core::System& system, Handle thread_handle, ThreadActivity thread_activity);
Result GetThreadContext364From32(Core::System& system, uint32_t out_context, Handle thread_handle);
Result WaitForAddress64From32(Core::System& system, uint32_t address, ArbitrationType arb_type, int32_t value, int64_t timeout_ns);
Result SignalToAddress64From32(Core::System& system, uint32_t address, SignalType signal_type, int32_t value, int32_t count);
void SynchronizePreemptionState64From32(Core::System& system);
Result GetResourceLimitPeakValue64From32(Core::System& system, int64_t* out_peak_value, Handle resource_limit_handle, LimitableResource which);
Result CreateIoPool64From32(Core::System& system, Handle* out_handle, IoPoolType which);
Result CreateIoRegion64From32(Core::System& system, Handle* out_handle, Handle io_pool, uint64_t physical_address, uint32_t size, MemoryMapping mapping, MemoryPermission perm);
void KernelDebug64From32(Core::System& system, KernelDebugType kern_debug_type, uint64_t arg0, uint64_t arg1, uint64_t arg2);
void ChangeKernelTraceState64From32(Core::System& system, KernelTraceState kern_trace_state);
Result CreateSession64From32(Core::System& system, Handle* out_server_session_handle, Handle* out_client_session_handle, bool is_light, uint32_t name);
Result AcceptSession64From32(Core::System& system, Handle* out_handle, Handle port);
Result ReplyAndReceive64From32(Core::System& system, int32_t* out_index, uint32_t handles, int32_t num_handles, Handle reply_target, int64_t timeout_ns);
Result ReplyAndReceiveWithUserBuffer64From32(Core::System& system, int32_t* out_index, uint32_t message_buffer, uint32_t message_buffer_size, uint32_t handles, int32_t num_handles, Handle reply_target, int64_t timeout_ns);
Result CreateEvent64From32(Core::System& system, Handle* out_write_handle, Handle* out_read_handle);
Result MapIoRegion64From32(Core::System& system, Handle io_region, uint32_t address, uint32_t size, MemoryPermission perm);
Result UnmapIoRegion64From32(Core::System& system, Handle io_region, uint32_t address, uint32_t size);
Result MapPhysicalMemoryUnsafe64From32(Core::System& system, uint32_t address, uint32_t size);
Result UnmapPhysicalMemoryUnsafe64From32(Core::System& system, uint32_t address, uint32_t size);
Result SetUnsafeLimit64From32(Core::System& system, uint32_t limit);
Result CreateCodeMemory64From32(Core::System& system, Handle* out_handle, uint32_t address, uint32_t size);
Result ControlCodeMemory64From32(Core::System& system, Handle code_memory_handle, CodeMemoryOperation operation, uint64_t address, uint64_t size, MemoryPermission perm);
void SleepSystem64From32(Core::System& system);
Result ReadWriteRegister64From32(Core::System& system, uint32_t* out_value, uint64_t address, uint32_t mask, uint32_t value);
Result SetProcessActivity64From32(Core::System& system, Handle process_handle, ProcessActivity process_activity);
Result CreateSharedMemory64From32(Core::System& system, Handle* out_handle, uint32_t size, MemoryPermission owner_perm, MemoryPermission remote_perm);
Result MapTransferMemory64From32(Core::System& system, Handle trmem_handle, uint32_t address, uint32_t size, MemoryPermission owner_perm);
Result UnmapTransferMemory64From32(Core::System& system, Handle trmem_handle, uint32_t address, uint32_t size);
Result CreateInterruptEvent64From32(Core::System& system, Handle* out_read_handle, int32_t interrupt_id, InterruptType interrupt_type);
Result QueryPhysicalAddress64From32(Core::System& system, ilp32::PhysicalMemoryInfo* out_info, uint32_t address);
Result QueryIoMapping64From32(Core::System& system, uintptr_t* out_address, uintptr_t* out_size, uint64_t physical_address, uint32_t size);
Result CreateDeviceAddressSpace64From32(Core::System& system, Handle* out_handle, uint64_t das_address, uint64_t das_size);
Result AttachDeviceAddressSpace64From32(Core::System& system, DeviceName device_name, Handle das_handle);
Result DetachDeviceAddressSpace64From32(Core::System& system, DeviceName device_name, Handle das_handle);
Result MapDeviceAddressSpaceByForce64From32(Core::System& system, Handle das_handle, Handle process_handle, uint64_t process_address, uint32_t size, uint64_t device_address, uint32_t option);
Result MapDeviceAddressSpaceAligned64From32(Core::System& system, Handle das_handle, Handle process_handle, uint64_t process_address, uint32_t size, uint64_t device_address, uint32_t option);
Result UnmapDeviceAddressSpace64From32(Core::System& system, Handle das_handle, Handle process_handle, uint64_t process_address, uint32_t size, uint64_t device_address);
Result InvalidateProcessDataCache64From32(Core::System& system, Handle process_handle, uint64_t address, uint64_t size);
Result StoreProcessDataCache64From32(Core::System& system, Handle process_handle, uint64_t address, uint64_t size);
Result FlushProcessDataCache64From32(Core::System& system, Handle process_handle, uint64_t address, uint64_t size);
Result DebugActiveProcess64From32(Core::System& system, Handle* out_handle, uint64_t process_id);
Result BreakDebugProcess64From32(Core::System& system, Handle debug_handle);
Result TerminateDebugProcess64From32(Core::System& system, Handle debug_handle);
Result GetDebugEvent64From32(Core::System& system, uint32_t out_info, Handle debug_handle);
Result ContinueDebugEvent64From32(Core::System& system, Handle debug_handle, uint32_t flags, uint32_t thread_ids, int32_t num_thread_ids);
Result GetProcessList64From32(Core::System& system, int32_t* out_num_processes, uint32_t out_process_ids, int32_t max_out_count);
Result GetThreadList64From32(Core::System& system, int32_t* out_num_threads, uint32_t out_thread_ids, int32_t max_out_count, Handle debug_handle);
Result GetDebugThreadContext64From32(Core::System& system, uint32_t out_context, Handle debug_handle, uint64_t thread_id, uint32_t context_flags);
Result SetDebugThreadContext64From32(Core::System& system, Handle debug_handle, uint64_t thread_id, uint32_t context, uint32_t context_flags);
Result QueryDebugProcessMemory64From32(Core::System& system, uint32_t out_memory_info, PageInfo* out_page_info, Handle process_handle, uint32_t address);
Result ReadDebugProcessMemory64From32(Core::System& system, uint32_t buffer, Handle debug_handle, uint32_t address, uint32_t size);
Result WriteDebugProcessMemory64From32(Core::System& system, Handle debug_handle, uint32_t buffer, uint32_t address, uint32_t size);
Result SetHardwareBreakPoint64From32(Core::System& system, HardwareBreakPointRegisterName name, uint64_t flags, uint64_t value);
Result GetDebugThreadParam64From32(Core::System& system, uint64_t* out_64, uint32_t* out_32, Handle debug_handle, uint64_t thread_id, DebugThreadParam param);
Result GetSystemInfo64From32(Core::System& system, uint64_t* out, SystemInfoType info_type, Handle handle, uint64_t info_subtype);
Result CreatePort64From32(Core::System& system, Handle* out_server_handle, Handle* out_client_handle, int32_t max_sessions, bool is_light, uint32_t name);
Result ManageNamedPort64From32(Core::System& system, Handle* out_server_handle, uint32_t name, int32_t max_sessions);
Result ConnectToPort64From32(Core::System& system, Handle* out_handle, Handle port);
Result SetProcessMemoryPermission64From32(Core::System& system, Handle process_handle, uint64_t address, uint64_t size, MemoryPermission perm);
Result MapProcessMemory64From32(Core::System& system, uint32_t dst_address, Handle process_handle, uint64_t src_address, uint32_t size);
Result UnmapProcessMemory64From32(Core::System& system, uint32_t dst_address, Handle process_handle, uint64_t src_address, uint32_t size);
Result QueryProcessMemory64From32(Core::System& system, uint32_t out_memory_info, PageInfo* out_page_info, Handle process_handle, uint64_t address);
Result MapProcessCodeMemory64From32(Core::System& system, Handle process_handle, uint64_t dst_address, uint64_t src_address, uint64_t size);
Result UnmapProcessCodeMemory64From32(Core::System& system, Handle process_handle, uint64_t dst_address, uint64_t src_address, uint64_t size);
Result CreateProcess64From32(Core::System& system, Handle* out_handle, uint32_t parameters, uint32_t caps, int32_t num_caps);
Result StartProcess64From32(Core::System& system, Handle process_handle, int32_t priority, int32_t core_id, uint64_t main_thread_stack_size);
Result TerminateProcess64From32(Core::System& system, Handle process_handle);
Result GetProcessInfo64From32(Core::System& system, int64_t* out_info, Handle process_handle, ProcessInfoType info_type);
Result CreateResourceLimit64From32(Core::System& system, Handle* out_handle);
Result SetResourceLimitLimitValue64From32(Core::System& system, Handle resource_limit_handle, LimitableResource which, int64_t limit_value);
Result MapInsecureMemory64From32(Core::System& system, uint32_t address, uint32_t size);
Result UnmapInsecureMemory64From32(Core::System& system, uint32_t address, uint32_t size);
Result SetHeapSize32(Core::System& system, u32* heap_addr, u32 heap_size);
Result SetMemoryAttribute32(Core::System& system, u32 address, u32 size, u32 mask, u32 attr);
Result MapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size);
Result UnmapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size);
Result QueryMemory32(Core::System& system, u32 memory_info_address, u32 page_info_address,
u32 query_address);
void ExitProcess32(Core::System& system);
Result CreateThread32(Core::System& system, Handle* out_handle, u32 priority, u32 entry_point,
u32 arg, u32 stack_top, s32 processor_id);
Result StartThread32(Core::System& system, Handle thread_handle);
void ExitThread32(Core::System& system);
void SleepThread32(Core::System& system, u32 nanoseconds_low, u32 nanoseconds_high);
Result GetThreadPriority32(Core::System& system, u32* out_priority, Handle handle);
Result SetThreadPriority32(Core::System& system, Handle thread_handle, u32 priority);
Result GetThreadCoreMask32(Core::System& system, Handle thread_handle, s32* out_core_id,
u32* out_affinity_mask_low, u32* out_affinity_mask_high);
Result SetThreadCoreMask32(Core::System& system, Handle thread_handle, s32 core_id,
u32 affinity_mask_low, u32 affinity_mask_high);
u32 GetCurrentProcessorNumber32(Core::System& system);
Result SignalEvent32(Core::System& system, Handle event_handle);
Result ClearEvent32(Core::System& system, Handle event_handle);
Result MapSharedMemory32(Core::System& system, Handle shmem_handle, u32 address, u32 size,
MemoryPermission map_perm);
Result UnmapSharedMemory32(Core::System& system, Handle shmem_handle, u32 address, u32 size);
Result CreateTransferMemory32(Core::System& system, Handle* out, u32 address, u32 size,
MemoryPermission map_perm);
Result CloseHandle32(Core::System& system, Handle handle);
Result ResetSignal32(Core::System& system, Handle handle);
Result WaitSynchronization32(Core::System& system, u32 timeout_low, u32 handles_address,
s32 num_handles, u32 timeout_high, s32* index);
Result CancelSynchronization32(Core::System& system, Handle handle);
Result ArbitrateLock32(Core::System& system, Handle thread_handle, u32 address, u32 tag);
Result ArbitrateUnlock32(Core::System& system, u32 address);
Result WaitProcessWideKeyAtomic32(Core::System& system, u32 address, u32 cv_key, u32 tag,
u32 timeout_ns_low, u32 timeout_ns_high);
void SignalProcessWideKey32(Core::System& system, u32 cv_key, s32 count);
void GetSystemTick32(Core::System& system, u32* time_low, u32* time_high);
Result ConnectToNamedPort32(Core::System& system, Handle* out_handle, u32 port_name_address);
Result SendSyncRequest32(Core::System& system, Handle handle);
Result GetProcessId32(Core::System& system, u32* out_process_id_low, u32* out_process_id_high,
Handle handle);
Result GetThreadId32(Core::System& system, u32* out_thread_id_low, u32* out_thread_id_high,
Handle thread_handle);
void Break32(Core::System& system, u32 reason, u32 info1, u32 info2);
void OutputDebugString32(Core::System& system, u32 address, u32 len);
Result GetInfo32(Core::System& system, u32* result_low, u32* result_high, u32 sub_id_low,
u32 info_id, u32 handle, u32 sub_id_high);
Result MapPhysicalMemory32(Core::System& system, u32 addr, u32 size);
Result UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size);
Result SetThreadActivity32(Core::System& system, Handle thread_handle,
ThreadActivity thread_activity);
Result GetThreadContext32(Core::System& system, u32 out_context, Handle thread_handle);
Result WaitForAddress32(Core::System& system, u32 address, ArbitrationType arb_type, s32 value,
u32 timeout_ns_low, u32 timeout_ns_high);
Result SignalToAddress32(Core::System& system, u32 address, SignalType signal_type, s32 value,
s32 count);
Result CreateEvent32(Core::System& system, Handle* out_write, Handle* out_read);
Result CreateCodeMemory32(Core::System& system, Handle* out, u32 address, u32 size);
Result ControlCodeMemory32(Core::System& system, Handle code_memory_handle, u32 operation,
u64 address, u64 size, MemoryPermission perm);
Result FlushProcessDataCache32(Core::System& system, Handle process_handle, u64 address, u64 size);
Result SetHeapSize64(Core::System& system, uintptr_t* out_address, uint64_t size);
Result SetMemoryPermission64(Core::System& system, uint64_t address, uint64_t size, MemoryPermission perm);
Result SetMemoryAttribute64(Core::System& system, uint64_t address, uint64_t size, uint32_t mask, uint32_t attr);
Result MapMemory64(Core::System& system, uint64_t dst_address, uint64_t src_address, uint64_t size);
Result UnmapMemory64(Core::System& system, uint64_t dst_address, uint64_t src_address, uint64_t size);
Result QueryMemory64(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info, uint64_t address);
void ExitProcess64(Core::System& system);
Result CreateThread64(Core::System& system, Handle* out_handle, uint64_t func, uint64_t arg, uint64_t stack_bottom, int32_t priority, int32_t core_id);
Result StartThread64(Core::System& system, Handle thread_handle);
void ExitThread64(Core::System& system);
void SleepThread64(Core::System& system, int64_t ns);
Result GetThreadPriority64(Core::System& system, int32_t* out_priority, Handle thread_handle);
Result SetThreadPriority64(Core::System& system, Handle thread_handle, int32_t priority);
Result GetThreadCoreMask64(Core::System& system, int32_t* out_core_id, uint64_t* out_affinity_mask, Handle thread_handle);
Result SetThreadCoreMask64(Core::System& system, Handle thread_handle, int32_t core_id, uint64_t affinity_mask);
int32_t GetCurrentProcessorNumber64(Core::System& system);
Result SignalEvent64(Core::System& system, Handle event_handle);
Result ClearEvent64(Core::System& system, Handle event_handle);
Result MapSharedMemory64(Core::System& system, Handle shmem_handle, uint64_t address, uint64_t size, MemoryPermission map_perm);
Result UnmapSharedMemory64(Core::System& system, Handle shmem_handle, uint64_t address, uint64_t size);
Result CreateTransferMemory64(Core::System& system, Handle* out_handle, uint64_t address, uint64_t size, MemoryPermission map_perm);
Result CloseHandle64(Core::System& system, Handle handle);
Result ResetSignal64(Core::System& system, Handle handle);
Result WaitSynchronization64(Core::System& system, int32_t* out_index, uint64_t handles, int32_t num_handles, int64_t timeout_ns);
Result CancelSynchronization64(Core::System& system, Handle handle);
Result ArbitrateLock64(Core::System& system, Handle thread_handle, uint64_t address, uint32_t tag);
Result ArbitrateUnlock64(Core::System& system, uint64_t address);
Result WaitProcessWideKeyAtomic64(Core::System& system, uint64_t address, uint64_t cv_key, uint32_t tag, int64_t timeout_ns);
void SignalProcessWideKey64(Core::System& system, uint64_t cv_key, int32_t count);
int64_t GetSystemTick64(Core::System& system);
Result ConnectToNamedPort64(Core::System& system, Handle* out_handle, uint64_t name);
Result SendSyncRequest64(Core::System& system, Handle session_handle);
Result SendSyncRequestWithUserBuffer64(Core::System& system, uint64_t message_buffer, uint64_t message_buffer_size, Handle session_handle);
Result SendAsyncRequestWithUserBuffer64(Core::System& system, Handle* out_event_handle, uint64_t message_buffer, uint64_t message_buffer_size, Handle session_handle);
Result GetProcessId64(Core::System& system, uint64_t* out_process_id, Handle process_handle);
Result GetThreadId64(Core::System& system, uint64_t* out_thread_id, Handle thread_handle);
void Break64(Core::System& system, BreakReason break_reason, uint64_t arg, uint64_t size);
Result OutputDebugString64(Core::System& system, uint64_t debug_str, uint64_t len);
void ReturnFromException64(Core::System& system, Result result);
Result GetInfo64(Core::System& system, uint64_t* out, InfoType info_type, Handle handle, uint64_t info_subtype);
void FlushEntireDataCache64(Core::System& system);
Result FlushDataCache64(Core::System& system, uint64_t address, uint64_t size);
Result MapPhysicalMemory64(Core::System& system, uint64_t address, uint64_t size);
Result UnmapPhysicalMemory64(Core::System& system, uint64_t address, uint64_t size);
Result GetDebugFutureThreadInfo64(Core::System& system, lp64::LastThreadContext* out_context, uint64_t* out_thread_id, Handle debug_handle, int64_t ns);
Result GetLastThreadInfo64(Core::System& system, lp64::LastThreadContext* out_context, uintptr_t* out_tls_address, uint32_t* out_flags);
Result GetResourceLimitLimitValue64(Core::System& system, int64_t* out_limit_value, Handle resource_limit_handle, LimitableResource which);
Result GetResourceLimitCurrentValue64(Core::System& system, int64_t* out_current_value, Handle resource_limit_handle, LimitableResource which);
Result SetThreadActivity64(Core::System& system, Handle thread_handle, ThreadActivity thread_activity);
Result GetThreadContext364(Core::System& system, uint64_t out_context, Handle thread_handle);
Result WaitForAddress64(Core::System& system, uint64_t address, ArbitrationType arb_type, int32_t value, int64_t timeout_ns);
Result SignalToAddress64(Core::System& system, uint64_t address, SignalType signal_type, int32_t value, int32_t count);
void SynchronizePreemptionState64(Core::System& system);
Result GetResourceLimitPeakValue64(Core::System& system, int64_t* out_peak_value, Handle resource_limit_handle, LimitableResource which);
Result CreateIoPool64(Core::System& system, Handle* out_handle, IoPoolType which);
Result CreateIoRegion64(Core::System& system, Handle* out_handle, Handle io_pool, uint64_t physical_address, uint64_t size, MemoryMapping mapping, MemoryPermission perm);
void KernelDebug64(Core::System& system, KernelDebugType kern_debug_type, uint64_t arg0, uint64_t arg1, uint64_t arg2);
void ChangeKernelTraceState64(Core::System& system, KernelTraceState kern_trace_state);
Result CreateSession64(Core::System& system, Handle* out_server_session_handle, Handle* out_client_session_handle, bool is_light, uint64_t name);
Result AcceptSession64(Core::System& system, Handle* out_handle, Handle port);
Result ReplyAndReceive64(Core::System& system, int32_t* out_index, uint64_t handles, int32_t num_handles, Handle reply_target, int64_t timeout_ns);
Result ReplyAndReceiveWithUserBuffer64(Core::System& system, int32_t* out_index, uint64_t message_buffer, uint64_t message_buffer_size, uint64_t handles, int32_t num_handles, Handle reply_target, int64_t timeout_ns);
Result CreateEvent64(Core::System& system, Handle* out_write_handle, Handle* out_read_handle);
Result MapIoRegion64(Core::System& system, Handle io_region, uint64_t address, uint64_t size, MemoryPermission perm);
Result UnmapIoRegion64(Core::System& system, Handle io_region, uint64_t address, uint64_t size);
Result MapPhysicalMemoryUnsafe64(Core::System& system, uint64_t address, uint64_t size);
Result UnmapPhysicalMemoryUnsafe64(Core::System& system, uint64_t address, uint64_t size);
Result SetUnsafeLimit64(Core::System& system, uint64_t limit);
Result CreateCodeMemory64(Core::System& system, Handle* out_handle, uint64_t address, uint64_t size);
Result ControlCodeMemory64(Core::System& system, Handle code_memory_handle, CodeMemoryOperation operation, uint64_t address, uint64_t size, MemoryPermission perm);
void SleepSystem64(Core::System& system);
Result ReadWriteRegister64(Core::System& system, uint32_t* out_value, uint64_t address, uint32_t mask, uint32_t value);
Result SetProcessActivity64(Core::System& system, Handle process_handle, ProcessActivity process_activity);
Result CreateSharedMemory64(Core::System& system, Handle* out_handle, uint64_t size, MemoryPermission owner_perm, MemoryPermission remote_perm);
Result MapTransferMemory64(Core::System& system, Handle trmem_handle, uint64_t address, uint64_t size, MemoryPermission owner_perm);
Result UnmapTransferMemory64(Core::System& system, Handle trmem_handle, uint64_t address, uint64_t size);
Result CreateInterruptEvent64(Core::System& system, Handle* out_read_handle, int32_t interrupt_id, InterruptType interrupt_type);
Result QueryPhysicalAddress64(Core::System& system, lp64::PhysicalMemoryInfo* out_info, uint64_t address);
Result QueryIoMapping64(Core::System& system, uintptr_t* out_address, uintptr_t* out_size, uint64_t physical_address, uint64_t size);
Result CreateDeviceAddressSpace64(Core::System& system, Handle* out_handle, uint64_t das_address, uint64_t das_size);
Result AttachDeviceAddressSpace64(Core::System& system, DeviceName device_name, Handle das_handle);
Result DetachDeviceAddressSpace64(Core::System& system, DeviceName device_name, Handle das_handle);
Result MapDeviceAddressSpaceByForce64(Core::System& system, Handle das_handle, Handle process_handle, uint64_t process_address, uint64_t size, uint64_t device_address, uint32_t option);
Result MapDeviceAddressSpaceAligned64(Core::System& system, Handle das_handle, Handle process_handle, uint64_t process_address, uint64_t size, uint64_t device_address, uint32_t option);
Result UnmapDeviceAddressSpace64(Core::System& system, Handle das_handle, Handle process_handle, uint64_t process_address, uint64_t size, uint64_t device_address);
Result InvalidateProcessDataCache64(Core::System& system, Handle process_handle, uint64_t address, uint64_t size);
Result StoreProcessDataCache64(Core::System& system, Handle process_handle, uint64_t address, uint64_t size);
Result FlushProcessDataCache64(Core::System& system, Handle process_handle, uint64_t address, uint64_t size);
Result DebugActiveProcess64(Core::System& system, Handle* out_handle, uint64_t process_id);
Result BreakDebugProcess64(Core::System& system, Handle debug_handle);
Result TerminateDebugProcess64(Core::System& system, Handle debug_handle);
Result GetDebugEvent64(Core::System& system, uint64_t out_info, Handle debug_handle);
Result ContinueDebugEvent64(Core::System& system, Handle debug_handle, uint32_t flags, uint64_t thread_ids, int32_t num_thread_ids);
Result GetProcessList64(Core::System& system, int32_t* out_num_processes, uint64_t out_process_ids, int32_t max_out_count);
Result GetThreadList64(Core::System& system, int32_t* out_num_threads, uint64_t out_thread_ids, int32_t max_out_count, Handle debug_handle);
Result GetDebugThreadContext64(Core::System& system, uint64_t out_context, Handle debug_handle, uint64_t thread_id, uint32_t context_flags);
Result SetDebugThreadContext64(Core::System& system, Handle debug_handle, uint64_t thread_id, uint64_t context, uint32_t context_flags);
Result QueryDebugProcessMemory64(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info, Handle process_handle, uint64_t address);
Result ReadDebugProcessMemory64(Core::System& system, uint64_t buffer, Handle debug_handle, uint64_t address, uint64_t size);
Result WriteDebugProcessMemory64(Core::System& system, Handle debug_handle, uint64_t buffer, uint64_t address, uint64_t size);
Result SetHardwareBreakPoint64(Core::System& system, HardwareBreakPointRegisterName name, uint64_t flags, uint64_t value);
Result GetDebugThreadParam64(Core::System& system, uint64_t* out_64, uint32_t* out_32, Handle debug_handle, uint64_t thread_id, DebugThreadParam param);
Result GetSystemInfo64(Core::System& system, uint64_t* out, SystemInfoType info_type, Handle handle, uint64_t info_subtype);
Result CreatePort64(Core::System& system, Handle* out_server_handle, Handle* out_client_handle, int32_t max_sessions, bool is_light, uint64_t name);
Result ManageNamedPort64(Core::System& system, Handle* out_server_handle, uint64_t name, int32_t max_sessions);
Result ConnectToPort64(Core::System& system, Handle* out_handle, Handle port);
Result SetProcessMemoryPermission64(Core::System& system, Handle process_handle, uint64_t address, uint64_t size, MemoryPermission perm);
Result MapProcessMemory64(Core::System& system, uint64_t dst_address, Handle process_handle, uint64_t src_address, uint64_t size);
Result UnmapProcessMemory64(Core::System& system, uint64_t dst_address, Handle process_handle, uint64_t src_address, uint64_t size);
Result QueryProcessMemory64(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info, Handle process_handle, uint64_t address);
Result MapProcessCodeMemory64(Core::System& system, Handle process_handle, uint64_t dst_address, uint64_t src_address, uint64_t size);
Result UnmapProcessCodeMemory64(Core::System& system, Handle process_handle, uint64_t dst_address, uint64_t src_address, uint64_t size);
Result CreateProcess64(Core::System& system, Handle* out_handle, uint64_t parameters, uint64_t caps, int32_t num_caps);
Result StartProcess64(Core::System& system, Handle process_handle, int32_t priority, int32_t core_id, uint64_t main_thread_stack_size);
Result TerminateProcess64(Core::System& system, Handle process_handle);
Result GetProcessInfo64(Core::System& system, int64_t* out_info, Handle process_handle, ProcessInfoType info_type);
Result CreateResourceLimit64(Core::System& system, Handle* out_handle);
Result SetResourceLimitLimitValue64(Core::System& system, Handle resource_limit_handle, LimitableResource which, int64_t limit_value);
Result MapInsecureMemory64(Core::System& system, uint64_t address, uint64_t size);
Result UnmapInsecureMemory64(Core::System& system, uint64_t address, uint64_t size);
enum class SvcId : u32 {
SetHeapSize = 0x1,
SetMemoryPermission = 0x2,
SetMemoryAttribute = 0x3,
MapMemory = 0x4,
UnmapMemory = 0x5,
QueryMemory = 0x6,
ExitProcess = 0x7,
CreateThread = 0x8,
StartThread = 0x9,
ExitThread = 0xa,
SleepThread = 0xb,
GetThreadPriority = 0xc,
SetThreadPriority = 0xd,
GetThreadCoreMask = 0xe,
SetThreadCoreMask = 0xf,
GetCurrentProcessorNumber = 0x10,
SignalEvent = 0x11,
ClearEvent = 0x12,
MapSharedMemory = 0x13,
UnmapSharedMemory = 0x14,
CreateTransferMemory = 0x15,
CloseHandle = 0x16,
ResetSignal = 0x17,
WaitSynchronization = 0x18,
CancelSynchronization = 0x19,
ArbitrateLock = 0x1a,
ArbitrateUnlock = 0x1b,
WaitProcessWideKeyAtomic = 0x1c,
SignalProcessWideKey = 0x1d,
GetSystemTick = 0x1e,
ConnectToNamedPort = 0x1f,
SendSyncRequestLight = 0x20,
SendSyncRequest = 0x21,
SendSyncRequestWithUserBuffer = 0x22,
SendAsyncRequestWithUserBuffer = 0x23,
GetProcessId = 0x24,
GetThreadId = 0x25,
Break = 0x26,
OutputDebugString = 0x27,
ReturnFromException = 0x28,
GetInfo = 0x29,
FlushEntireDataCache = 0x2a,
FlushDataCache = 0x2b,
MapPhysicalMemory = 0x2c,
UnmapPhysicalMemory = 0x2d,
GetDebugFutureThreadInfo = 0x2e,
GetLastThreadInfo = 0x2f,
GetResourceLimitLimitValue = 0x30,
GetResourceLimitCurrentValue = 0x31,
SetThreadActivity = 0x32,
GetThreadContext3 = 0x33,
WaitForAddress = 0x34,
SignalToAddress = 0x35,
SynchronizePreemptionState = 0x36,
GetResourceLimitPeakValue = 0x37,
CreateIoPool = 0x39,
CreateIoRegion = 0x3a,
KernelDebug = 0x3c,
ChangeKernelTraceState = 0x3d,
CreateSession = 0x40,
AcceptSession = 0x41,
ReplyAndReceiveLight = 0x42,
ReplyAndReceive = 0x43,
ReplyAndReceiveWithUserBuffer = 0x44,
CreateEvent = 0x45,
MapIoRegion = 0x46,
UnmapIoRegion = 0x47,
MapPhysicalMemoryUnsafe = 0x48,
UnmapPhysicalMemoryUnsafe = 0x49,
SetUnsafeLimit = 0x4a,
CreateCodeMemory = 0x4b,
ControlCodeMemory = 0x4c,
SleepSystem = 0x4d,
ReadWriteRegister = 0x4e,
SetProcessActivity = 0x4f,
CreateSharedMemory = 0x50,
MapTransferMemory = 0x51,
UnmapTransferMemory = 0x52,
CreateInterruptEvent = 0x53,
QueryPhysicalAddress = 0x54,
QueryIoMapping = 0x55,
CreateDeviceAddressSpace = 0x56,
AttachDeviceAddressSpace = 0x57,
DetachDeviceAddressSpace = 0x58,
MapDeviceAddressSpaceByForce = 0x59,
MapDeviceAddressSpaceAligned = 0x5a,
UnmapDeviceAddressSpace = 0x5c,
InvalidateProcessDataCache = 0x5d,
StoreProcessDataCache = 0x5e,
FlushProcessDataCache = 0x5f,
DebugActiveProcess = 0x60,
BreakDebugProcess = 0x61,
TerminateDebugProcess = 0x62,
GetDebugEvent = 0x63,
ContinueDebugEvent = 0x64,
GetProcessList = 0x65,
GetThreadList = 0x66,
GetDebugThreadContext = 0x67,
SetDebugThreadContext = 0x68,
QueryDebugProcessMemory = 0x69,
ReadDebugProcessMemory = 0x6a,
WriteDebugProcessMemory = 0x6b,
SetHardwareBreakPoint = 0x6c,
GetDebugThreadParam = 0x6d,
GetSystemInfo = 0x6f,
CreatePort = 0x70,
ManageNamedPort = 0x71,
ConnectToPort = 0x72,
SetProcessMemoryPermission = 0x73,
MapProcessMemory = 0x74,
UnmapProcessMemory = 0x75,
QueryProcessMemory = 0x76,
MapProcessCodeMemory = 0x77,
UnmapProcessCodeMemory = 0x78,
CreateProcess = 0x79,
StartProcess = 0x7a,
TerminateProcess = 0x7b,
GetProcessInfo = 0x7c,
CreateResourceLimit = 0x7d,
SetResourceLimitLimitValue = 0x7e,
CallSecureMonitor = 0x7f,
MapInsecureMemory = 0x90,
UnmapInsecureMemory = 0x91,
};
// clang-format on
// Custom ABI.
Result ReplyAndReceiveLight(Core::System& system, Handle handle, uint32_t* args);
Result ReplyAndReceiveLight64From32(Core::System& system, Handle handle, uint32_t* args);
Result ReplyAndReceiveLight64(Core::System& system, Handle handle, uint32_t* args);
Result SendSyncRequestLight(Core::System& system, Handle session_handle, uint32_t* args);
Result SendSyncRequestLight64From32(Core::System& system, Handle session_handle, uint32_t* args);
Result SendSyncRequestLight64(Core::System& system, Handle session_handle, uint32_t* args);
void CallSecureMonitor(Core::System& system, lp64::SecureMonitorArguments* args);
void CallSecureMonitor64From32(Core::System& system, ilp32::SecureMonitorArguments* args);
void CallSecureMonitor64(Core::System& system, lp64::SecureMonitorArguments* args);
// Defined in svc_light_ipc.cpp.
void SvcWrap_ReplyAndReceiveLight64From32(Core::System& system);
void SvcWrap_ReplyAndReceiveLight64(Core::System& system);
void SvcWrap_SendSyncRequestLight64From32(Core::System& system);
void SvcWrap_SendSyncRequestLight64(Core::System& system);
// Defined in svc_secure_monitor_call.cpp.
void SvcWrap_CallSecureMonitor64From32(Core::System& system);
void SvcWrap_CallSecureMonitor64(Core::System& system);
// Perform a supervisor call by index.
void Call(Core::System& system, u32 imm);
} // namespace Kernel::Svc

View File

@@ -16,7 +16,7 @@ Result SetThreadActivity(Core::System& system, Handle thread_handle,
thread_activity);
// Validate the activity.
constexpr auto IsValidThreadActivity = [](ThreadActivity activity) {
static constexpr auto IsValidThreadActivity = [](ThreadActivity activity) {
return activity == ThreadActivity::Runnable || activity == ThreadActivity::Paused;
};
R_UNLESS(IsValidThreadActivity(thread_activity), ResultInvalidEnumValue);
@@ -36,9 +36,30 @@ Result SetThreadActivity(Core::System& system, Handle thread_handle,
return ResultSuccess;
}
Result SetThreadActivity32(Core::System& system, Handle thread_handle,
Result SetProcessActivity(Core::System& system, Handle process_handle,
ProcessActivity process_activity) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result SetThreadActivity64(Core::System& system, Handle thread_handle,
ThreadActivity thread_activity) {
return SetThreadActivity(system, thread_handle, thread_activity);
}
Result SetProcessActivity64(Core::System& system, Handle process_handle,
ProcessActivity process_activity) {
return SetProcessActivity(system, process_handle, process_activity);
}
Result SetThreadActivity64From32(Core::System& system, Handle thread_handle,
ThreadActivity thread_activity) {
return SetThreadActivity(system, thread_handle, thread_activity);
}
Result SetProcessActivity64From32(Core::System& system, Handle process_handle,
ProcessActivity process_activity) {
return SetProcessActivity(system, process_handle, process_activity);
}
} // namespace Kernel::Svc

View File

@@ -75,12 +75,6 @@ Result WaitForAddress(Core::System& system, VAddr address, ArbitrationType arb_t
return system.Kernel().CurrentProcess()->WaitAddressArbiter(address, arb_type, value, timeout);
}
Result WaitForAddress32(Core::System& system, u32 address, ArbitrationType arb_type, s32 value,
u32 timeout_ns_low, u32 timeout_ns_high) {
const auto timeout = static_cast<s64>(timeout_ns_low | (u64{timeout_ns_high} << 32));
return WaitForAddress(system, address, arb_type, value, timeout);
}
// Signals to an address (via Address Arbiter)
Result SignalToAddress(Core::System& system, VAddr address, SignalType signal_type, s32 value,
s32 count) {
@@ -105,9 +99,24 @@ Result SignalToAddress(Core::System& system, VAddr address, SignalType signal_ty
count);
}
Result SignalToAddress32(Core::System& system, u32 address, SignalType signal_type, s32 value,
Result WaitForAddress64(Core::System& system, VAddr address, ArbitrationType arb_type, s32 value,
s64 timeout_ns) {
return WaitForAddress(system, address, arb_type, value, timeout_ns);
}
Result SignalToAddress64(Core::System& system, VAddr address, SignalType signal_type, s32 value,
s32 count) {
return SignalToAddress(system, address, signal_type, value, count);
}
Result WaitForAddress64From32(Core::System& system, u32 address, ArbitrationType arb_type,
s32 value, s64 timeout_ns) {
return WaitForAddress(system, address, arb_type, value, timeout_ns);
}
Result SignalToAddress64From32(Core::System& system, u32 address, SignalType signal_type, s32 value,
s32 count) {
return SignalToAddress(system, address, signal_type, value, count);
}
} // namespace Kernel::Svc

View File

@@ -2,5 +2,49 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel::Svc {} // namespace Kernel::Svc
namespace Kernel::Svc {
Result QueryPhysicalAddress(Core::System& system, lp64::PhysicalMemoryInfo* out_info,
uint64_t address) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result QueryIoMapping(Core::System& system, uintptr_t* out_address, uintptr_t* out_size,
uint64_t physical_address, uint64_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result QueryPhysicalAddress64(Core::System& system, lp64::PhysicalMemoryInfo* out_info,
uint64_t address) {
R_RETURN(QueryPhysicalAddress(system, out_info, address));
}
Result QueryIoMapping64(Core::System& system, uintptr_t* out_address, uintptr_t* out_size,
uint64_t physical_address, uint64_t size) {
R_RETURN(QueryIoMapping(system, out_address, out_size, physical_address, size));
}
Result QueryPhysicalAddress64From32(Core::System& system, ilp32::PhysicalMemoryInfo* out_info,
uint32_t address) {
lp64::PhysicalMemoryInfo info{};
R_TRY(QueryPhysicalAddress(system, std::addressof(info), address));
*out_info = {
.physical_address = info.physical_address,
.virtual_address = static_cast<u32>(info.virtual_address),
.size = static_cast<u32>(info.size),
};
R_SUCCEED();
}
Result QueryIoMapping64From32(Core::System& system, uintptr_t* out_address, uintptr_t* out_size,
uint64_t physical_address, uint32_t size) {
R_RETURN(QueryIoMapping(system, reinterpret_cast<uintptr_t*>(out_address),
reinterpret_cast<uintptr_t*>(out_size), physical_address, size));
}
} // namespace Kernel::Svc

View File

@@ -9,7 +9,28 @@
namespace Kernel::Svc {
Result FlushProcessDataCache32(Core::System& system, Handle process_handle, u64 address, u64 size) {
void FlushEntireDataCache(Core::System& system) {
UNIMPLEMENTED();
}
Result FlushDataCache(Core::System& system, VAddr address, size_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result InvalidateProcessDataCache(Core::System& system, Handle process_handle, uint64_t address,
uint64_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result StoreProcessDataCache(Core::System& system, Handle process_handle, uint64_t address,
uint64_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result FlushProcessDataCache(Core::System& system, Handle process_handle, u64 address, u64 size) {
// Validate address/size.
R_UNLESS(size > 0, ResultInvalidSize);
R_UNLESS(address == static_cast<uintptr_t>(address), ResultInvalidCurrentMemory);
@@ -28,4 +49,50 @@ Result FlushProcessDataCache32(Core::System& system, Handle process_handle, u64
R_RETURN(system.Memory().FlushDataCache(*process, address, size));
}
void FlushEntireDataCache64(Core::System& system) {
FlushEntireDataCache(system);
}
Result FlushDataCache64(Core::System& system, VAddr address, size_t size) {
R_RETURN(FlushDataCache(system, address, size));
}
Result InvalidateProcessDataCache64(Core::System& system, Handle process_handle, uint64_t address,
uint64_t size) {
R_RETURN(InvalidateProcessDataCache(system, process_handle, address, size));
}
Result StoreProcessDataCache64(Core::System& system, Handle process_handle, uint64_t address,
uint64_t size) {
R_RETURN(StoreProcessDataCache(system, process_handle, address, size));
}
Result FlushProcessDataCache64(Core::System& system, Handle process_handle, uint64_t address,
uint64_t size) {
R_RETURN(FlushProcessDataCache(system, process_handle, address, size));
}
void FlushEntireDataCache64From32(Core::System& system) {
return FlushEntireDataCache(system);
}
Result FlushDataCache64From32(Core::System& system, uint32_t address, uint32_t size) {
R_RETURN(FlushDataCache(system, address, size));
}
Result InvalidateProcessDataCache64From32(Core::System& system, Handle process_handle,
uint64_t address, uint64_t size) {
R_RETURN(InvalidateProcessDataCache(system, process_handle, address, size));
}
Result StoreProcessDataCache64From32(Core::System& system, Handle process_handle, uint64_t address,
uint64_t size) {
R_RETURN(StoreProcessDataCache(system, process_handle, address, size));
}
Result FlushProcessDataCache64From32(Core::System& system, Handle process_handle, uint64_t address,
uint64_t size) {
R_RETURN(FlushProcessDataCache(system, process_handle, address, size));
}
} // namespace Kernel::Svc

View File

@@ -63,12 +63,9 @@ Result CreateCodeMemory(Core::System& system, Handle* out, VAddr address, size_t
return ResultSuccess;
}
Result CreateCodeMemory32(Core::System& system, Handle* out, u32 address, u32 size) {
return CreateCodeMemory(system, out, address, size);
}
Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, u32 operation,
VAddr address, size_t size, MemoryPermission perm) {
Result ControlCodeMemory(Core::System& system, Handle code_memory_handle,
CodeMemoryOperation operation, VAddr address, size_t size,
MemoryPermission perm) {
LOG_TRACE(Kernel_SVC,
"called, code_memory_handle=0x{:X}, operation=0x{:X}, address=0x{:X}, size=0x{:X}, "
@@ -90,7 +87,7 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, u32 op
// This enables homebrew usage of these SVCs for JIT.
// Perform the operation.
switch (static_cast<CodeMemoryOperation>(operation)) {
switch (operation) {
case CodeMemoryOperation::Map: {
// Check that the region is in range.
R_UNLESS(
@@ -146,9 +143,26 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, u32 op
return ResultSuccess;
}
Result ControlCodeMemory32(Core::System& system, Handle code_memory_handle, u32 operation,
u64 address, u64 size, MemoryPermission perm) {
return ControlCodeMemory(system, code_memory_handle, operation, address, size, perm);
Result CreateCodeMemory64(Core::System& system, Handle* out_handle, uint64_t address,
uint64_t size) {
R_RETURN(CreateCodeMemory(system, out_handle, address, size));
}
Result ControlCodeMemory64(Core::System& system, Handle code_memory_handle,
CodeMemoryOperation operation, uint64_t address, uint64_t size,
MemoryPermission perm) {
R_RETURN(ControlCodeMemory(system, code_memory_handle, operation, address, size, perm));
}
Result CreateCodeMemory64From32(Core::System& system, Handle* out_handle, uint32_t address,
uint32_t size) {
R_RETURN(CreateCodeMemory(system, out_handle, address, size));
}
Result ControlCodeMemory64From32(Core::System& system, Handle code_memory_handle,
CodeMemoryOperation operation, uint64_t address, uint64_t size,
MemoryPermission perm) {
R_RETURN(ControlCodeMemory(system, code_memory_handle, operation, address, size, perm));
}
} // namespace Kernel::Svc

View File

@@ -47,12 +47,6 @@ Result WaitProcessWideKeyAtomic(Core::System& system, VAddr address, VAddr cv_ke
address, Common::AlignDown(cv_key, sizeof(u32)), tag, timeout);
}
Result WaitProcessWideKeyAtomic32(Core::System& system, u32 address, u32 cv_key, u32 tag,
u32 timeout_ns_low, u32 timeout_ns_high) {
const auto timeout_ns = static_cast<s64>(timeout_ns_low | (u64{timeout_ns_high} << 32));
return WaitProcessWideKeyAtomic(system, address, cv_key, tag, timeout_ns);
}
/// Signal process wide key
void SignalProcessWideKey(Core::System& system, VAddr cv_key, s32 count) {
LOG_TRACE(Kernel_SVC, "called, cv_key=0x{:X}, count=0x{:08X}", cv_key, count);
@@ -62,7 +56,21 @@ void SignalProcessWideKey(Core::System& system, VAddr cv_key, s32 count) {
Common::AlignDown(cv_key, sizeof(u32)), count);
}
void SignalProcessWideKey32(Core::System& system, u32 cv_key, s32 count) {
Result WaitProcessWideKeyAtomic64(Core::System& system, uint64_t address, uint64_t cv_key,
uint32_t tag, int64_t timeout_ns) {
R_RETURN(WaitProcessWideKeyAtomic(system, address, cv_key, tag, timeout_ns));
}
void SignalProcessWideKey64(Core::System& system, uint64_t cv_key, int32_t count) {
SignalProcessWideKey(system, cv_key, count);
}
Result WaitProcessWideKeyAtomic64From32(Core::System& system, uint32_t address, uint32_t cv_key,
uint32_t tag, int64_t timeout_ns) {
R_RETURN(WaitProcessWideKeyAtomic(system, address, cv_key, tag, timeout_ns));
}
void SignalProcessWideKey64From32(Core::System& system, uint32_t cv_key, int32_t count) {
SignalProcessWideKey(system, cv_key, count);
}

View File

@@ -2,5 +2,193 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel::Svc {} // namespace Kernel::Svc
namespace Kernel::Svc {
Result DebugActiveProcess(Core::System& system, Handle* out_handle, uint64_t process_id) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result BreakDebugProcess(Core::System& system, Handle debug_handle) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result TerminateDebugProcess(Core::System& system, Handle debug_handle) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result GetDebugEvent(Core::System& system, uint64_t out_info, Handle debug_handle) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result ContinueDebugEvent(Core::System& system, Handle debug_handle, uint32_t flags,
uint64_t user_thread_ids, int32_t num_thread_ids) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result GetDebugThreadContext(Core::System& system, uint64_t out_context, Handle debug_handle,
uint64_t thread_id, uint32_t context_flags) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result SetDebugThreadContext(Core::System& system, Handle debug_handle, uint64_t thread_id,
uint64_t user_context, uint32_t context_flags) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result QueryDebugProcessMemory(Core::System& system, uint64_t out_memory_info,
PageInfo* out_page_info, Handle debug_handle, uintptr_t address) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result ReadDebugProcessMemory(Core::System& system, uintptr_t buffer, Handle debug_handle,
uintptr_t address, size_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result WriteDebugProcessMemory(Core::System& system, Handle debug_handle, uintptr_t buffer,
uintptr_t address, size_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result SetHardwareBreakPoint(Core::System& system, HardwareBreakPointRegisterName name,
uint64_t flags, uint64_t value) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result GetDebugThreadParam(Core::System& system, uint64_t* out_64, uint32_t* out_32,
Handle debug_handle, uint64_t thread_id, DebugThreadParam param) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result DebugActiveProcess64(Core::System& system, Handle* out_handle, uint64_t process_id) {
R_RETURN(DebugActiveProcess(system, out_handle, process_id));
}
Result BreakDebugProcess64(Core::System& system, Handle debug_handle) {
R_RETURN(BreakDebugProcess(system, debug_handle));
}
Result TerminateDebugProcess64(Core::System& system, Handle debug_handle) {
R_RETURN(TerminateDebugProcess(system, debug_handle));
}
Result GetDebugEvent64(Core::System& system, uint64_t out_info, Handle debug_handle) {
R_RETURN(GetDebugEvent(system, out_info, debug_handle));
}
Result ContinueDebugEvent64(Core::System& system, Handle debug_handle, uint32_t flags,
uint64_t thread_ids, int32_t num_thread_ids) {
R_RETURN(ContinueDebugEvent(system, debug_handle, flags, thread_ids, num_thread_ids));
}
Result GetDebugThreadContext64(Core::System& system, uint64_t out_context, Handle debug_handle,
uint64_t thread_id, uint32_t context_flags) {
R_RETURN(GetDebugThreadContext(system, out_context, debug_handle, thread_id, context_flags));
}
Result SetDebugThreadContext64(Core::System& system, Handle debug_handle, uint64_t thread_id,
uint64_t context, uint32_t context_flags) {
R_RETURN(SetDebugThreadContext(system, debug_handle, thread_id, context, context_flags));
}
Result QueryDebugProcessMemory64(Core::System& system, uint64_t out_memory_info,
PageInfo* out_page_info, Handle debug_handle, uint64_t address) {
R_RETURN(
QueryDebugProcessMemory(system, out_memory_info, out_page_info, debug_handle, address));
}
Result ReadDebugProcessMemory64(Core::System& system, uint64_t buffer, Handle debug_handle,
uint64_t address, uint64_t size) {
R_RETURN(ReadDebugProcessMemory(system, buffer, debug_handle, address, size));
}
Result WriteDebugProcessMemory64(Core::System& system, Handle debug_handle, uint64_t buffer,
uint64_t address, uint64_t size) {
R_RETURN(WriteDebugProcessMemory(system, debug_handle, buffer, address, size));
}
Result SetHardwareBreakPoint64(Core::System& system, HardwareBreakPointRegisterName name,
uint64_t flags, uint64_t value) {
R_RETURN(SetHardwareBreakPoint(system, name, flags, value));
}
Result GetDebugThreadParam64(Core::System& system, uint64_t* out_64, uint32_t* out_32,
Handle debug_handle, uint64_t thread_id, DebugThreadParam param) {
R_RETURN(GetDebugThreadParam(system, out_64, out_32, debug_handle, thread_id, param));
}
Result DebugActiveProcess64From32(Core::System& system, Handle* out_handle, uint64_t process_id) {
R_RETURN(DebugActiveProcess(system, out_handle, process_id));
}
Result BreakDebugProcess64From32(Core::System& system, Handle debug_handle) {
R_RETURN(BreakDebugProcess(system, debug_handle));
}
Result TerminateDebugProcess64From32(Core::System& system, Handle debug_handle) {
R_RETURN(TerminateDebugProcess(system, debug_handle));
}
Result GetDebugEvent64From32(Core::System& system, uint32_t out_info, Handle debug_handle) {
R_RETURN(GetDebugEvent(system, out_info, debug_handle));
}
Result ContinueDebugEvent64From32(Core::System& system, Handle debug_handle, uint32_t flags,
uint32_t thread_ids, int32_t num_thread_ids) {
R_RETURN(ContinueDebugEvent(system, debug_handle, flags, thread_ids, num_thread_ids));
}
Result GetDebugThreadContext64From32(Core::System& system, uint32_t out_context,
Handle debug_handle, uint64_t thread_id,
uint32_t context_flags) {
R_RETURN(GetDebugThreadContext(system, out_context, debug_handle, thread_id, context_flags));
}
Result SetDebugThreadContext64From32(Core::System& system, Handle debug_handle, uint64_t thread_id,
uint32_t context, uint32_t context_flags) {
R_RETURN(SetDebugThreadContext(system, debug_handle, thread_id, context, context_flags));
}
Result QueryDebugProcessMemory64From32(Core::System& system, uint32_t out_memory_info,
PageInfo* out_page_info, Handle debug_handle,
uint32_t address) {
R_RETURN(
QueryDebugProcessMemory(system, out_memory_info, out_page_info, debug_handle, address));
}
Result ReadDebugProcessMemory64From32(Core::System& system, uint32_t buffer, Handle debug_handle,
uint32_t address, uint32_t size) {
R_RETURN(ReadDebugProcessMemory(system, buffer, debug_handle, address, size));
}
Result WriteDebugProcessMemory64From32(Core::System& system, Handle debug_handle, uint32_t buffer,
uint32_t address, uint32_t size) {
R_RETURN(WriteDebugProcessMemory(system, debug_handle, buffer, address, size));
}
Result SetHardwareBreakPoint64From32(Core::System& system, HardwareBreakPointRegisterName name,
uint64_t flags, uint64_t value) {
R_RETURN(SetHardwareBreakPoint(system, name, flags, value));
}
Result GetDebugThreadParam64From32(Core::System& system, uint64_t* out_64, uint32_t* out_32,
Handle debug_handle, uint64_t thread_id,
DebugThreadParam param) {
R_RETURN(GetDebugThreadParam(system, out_64, out_32, debug_handle, thread_id, param));
}
} // namespace Kernel::Svc

View File

@@ -8,18 +8,22 @@
namespace Kernel::Svc {
/// Used to output a message on a debug hardware unit - does nothing on a retail unit
void OutputDebugString(Core::System& system, VAddr address, u64 len) {
if (len == 0) {
return;
}
Result OutputDebugString(Core::System& system, VAddr address, u64 len) {
R_SUCCEED_IF(len == 0);
std::string str(len, '\0');
system.Memory().ReadBlock(address, str.data(), str.size());
LOG_DEBUG(Debug_Emulated, "{}", str);
R_SUCCEED();
}
void OutputDebugString32(Core::System& system, u32 address, u32 len) {
OutputDebugString(system, address, len);
Result OutputDebugString64(Core::System& system, uint64_t debug_str, uint64_t len) {
R_RETURN(OutputDebugString(system, debug_str, len));
}
Result OutputDebugString64From32(Core::System& system, uint32_t debug_str, uint32_t len) {
R_RETURN(OutputDebugString(system, debug_str, len));
}
} // namespace Kernel::Svc

View File

@@ -1,6 +1,253 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/alignment.h"
#include "common/scope_exit.h"
#include "core/core.h"
#include "core/hle/kernel/k_device_address_space.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc.h"
namespace Kernel::Svc {} // namespace Kernel::Svc
namespace Kernel::Svc {
constexpr inline u64 DeviceAddressSpaceAlignMask = (1ULL << 22) - 1;
constexpr bool IsProcessAndDeviceAligned(uint64_t process_address, uint64_t device_address) {
return (process_address & DeviceAddressSpaceAlignMask) ==
(device_address & DeviceAddressSpaceAlignMask);
}
Result CreateDeviceAddressSpace(Core::System& system, Handle* out, uint64_t das_address,
uint64_t das_size) {
// Validate input.
R_UNLESS(Common::IsAligned(das_address, PageSize), ResultInvalidMemoryRegion);
R_UNLESS(Common::IsAligned(das_size, PageSize), ResultInvalidMemoryRegion);
R_UNLESS(das_size > 0, ResultInvalidMemoryRegion);
R_UNLESS((das_address < das_address + das_size), ResultInvalidMemoryRegion);
// Create the device address space.
KDeviceAddressSpace* das = KDeviceAddressSpace::Create(system.Kernel());
R_UNLESS(das != nullptr, ResultOutOfResource);
SCOPE_EXIT({ das->Close(); });
// Initialize the device address space.
R_TRY(das->Initialize(das_address, das_size));
// Register the device address space.
KDeviceAddressSpace::Register(system.Kernel(), das);
// Add to the handle table.
R_TRY(system.CurrentProcess()->GetHandleTable().Add(out, das));
R_SUCCEED();
}
Result AttachDeviceAddressSpace(Core::System& system, DeviceName device_name, Handle das_handle) {
// Get the device address space.
KScopedAutoObject das =
system.CurrentProcess()->GetHandleTable().GetObject<KDeviceAddressSpace>(das_handle);
R_UNLESS(das.IsNotNull(), ResultInvalidHandle);
// Attach.
R_RETURN(das->Attach(device_name));
}
Result DetachDeviceAddressSpace(Core::System& system, DeviceName device_name, Handle das_handle) {
// Get the device address space.
KScopedAutoObject das =
system.CurrentProcess()->GetHandleTable().GetObject<KDeviceAddressSpace>(das_handle);
R_UNLESS(das.IsNotNull(), ResultInvalidHandle);
// Detach.
R_RETURN(das->Detach(device_name));
}
constexpr bool IsValidDeviceMemoryPermission(MemoryPermission device_perm) {
switch (device_perm) {
case MemoryPermission::Read:
case MemoryPermission::Write:
case MemoryPermission::ReadWrite:
return true;
default:
return false;
}
}
Result MapDeviceAddressSpaceByForce(Core::System& system, Handle das_handle, Handle process_handle,
uint64_t process_address, size_t size, uint64_t device_address,
u32 option) {
// Decode the option.
const MapDeviceAddressSpaceOption option_pack{option};
const auto device_perm = option_pack.permission;
const auto reserved = option_pack.reserved;
// Validate input.
R_UNLESS(Common::IsAligned(process_address, PageSize), ResultInvalidAddress);
R_UNLESS(Common::IsAligned(device_address, PageSize), ResultInvalidAddress);
R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
R_UNLESS(size > 0, ResultInvalidSize);
R_UNLESS((process_address < process_address + size), ResultInvalidCurrentMemory);
R_UNLESS((device_address < device_address + size), ResultInvalidMemoryRegion);
R_UNLESS((process_address == static_cast<uintptr_t>(process_address)),
ResultInvalidCurrentMemory);
R_UNLESS(IsValidDeviceMemoryPermission(device_perm), ResultInvalidNewMemoryPermission);
R_UNLESS(reserved == 0, ResultInvalidEnumValue);
// Get the device address space.
KScopedAutoObject das =
system.CurrentProcess()->GetHandleTable().GetObject<KDeviceAddressSpace>(das_handle);
R_UNLESS(das.IsNotNull(), ResultInvalidHandle);
// Get the process.
KScopedAutoObject process =
system.CurrentProcess()->GetHandleTable().GetObject<KProcess>(process_handle);
R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
// Validate that the process address is within range.
auto& page_table = process->PageTable();
R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory);
// Map.
R_RETURN(
das->MapByForce(std::addressof(page_table), process_address, size, device_address, option));
}
Result MapDeviceAddressSpaceAligned(Core::System& system, Handle das_handle, Handle process_handle,
uint64_t process_address, size_t size, uint64_t device_address,
u32 option) {
// Decode the option.
const MapDeviceAddressSpaceOption option_pack{option};
const auto device_perm = option_pack.permission;
const auto reserved = option_pack.reserved;
// Validate input.
R_UNLESS(Common::IsAligned(process_address, PageSize), ResultInvalidAddress);
R_UNLESS(Common::IsAligned(device_address, PageSize), ResultInvalidAddress);
R_UNLESS(IsProcessAndDeviceAligned(process_address, device_address), ResultInvalidAddress);
R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
R_UNLESS(size > 0, ResultInvalidSize);
R_UNLESS((process_address < process_address + size), ResultInvalidCurrentMemory);
R_UNLESS((device_address < device_address + size), ResultInvalidMemoryRegion);
R_UNLESS((process_address == static_cast<uintptr_t>(process_address)),
ResultInvalidCurrentMemory);
R_UNLESS(IsValidDeviceMemoryPermission(device_perm), ResultInvalidNewMemoryPermission);
R_UNLESS(reserved == 0, ResultInvalidEnumValue);
// Get the device address space.
KScopedAutoObject das =
system.CurrentProcess()->GetHandleTable().GetObject<KDeviceAddressSpace>(das_handle);
R_UNLESS(das.IsNotNull(), ResultInvalidHandle);
// Get the process.
KScopedAutoObject process =
system.CurrentProcess()->GetHandleTable().GetObject<KProcess>(process_handle);
R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
// Validate that the process address is within range.
auto& page_table = process->PageTable();
R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory);
// Map.
R_RETURN(
das->MapAligned(std::addressof(page_table), process_address, size, device_address, option));
}
Result UnmapDeviceAddressSpace(Core::System& system, Handle das_handle, Handle process_handle,
uint64_t process_address, size_t size, uint64_t device_address) {
// Validate input.
R_UNLESS(Common::IsAligned(process_address, PageSize), ResultInvalidAddress);
R_UNLESS(Common::IsAligned(device_address, PageSize), ResultInvalidAddress);
R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
R_UNLESS(size > 0, ResultInvalidSize);
R_UNLESS((process_address < process_address + size), ResultInvalidCurrentMemory);
R_UNLESS((device_address < device_address + size), ResultInvalidMemoryRegion);
R_UNLESS((process_address == static_cast<uintptr_t>(process_address)),
ResultInvalidCurrentMemory);
// Get the device address space.
KScopedAutoObject das =
system.CurrentProcess()->GetHandleTable().GetObject<KDeviceAddressSpace>(das_handle);
R_UNLESS(das.IsNotNull(), ResultInvalidHandle);
// Get the process.
KScopedAutoObject process =
system.CurrentProcess()->GetHandleTable().GetObject<KProcess>(process_handle);
R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
// Validate that the process address is within range.
auto& page_table = process->PageTable();
R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory);
R_RETURN(das->Unmap(std::addressof(page_table), process_address, size, device_address));
}
Result CreateDeviceAddressSpace64(Core::System& system, Handle* out_handle, uint64_t das_address,
uint64_t das_size) {
R_RETURN(CreateDeviceAddressSpace(system, out_handle, das_address, das_size));
}
Result AttachDeviceAddressSpace64(Core::System& system, DeviceName device_name, Handle das_handle) {
R_RETURN(AttachDeviceAddressSpace(system, device_name, das_handle));
}
Result DetachDeviceAddressSpace64(Core::System& system, DeviceName device_name, Handle das_handle) {
R_RETURN(DetachDeviceAddressSpace(system, device_name, das_handle));
}
Result MapDeviceAddressSpaceByForce64(Core::System& system, Handle das_handle,
Handle process_handle, uint64_t process_address,
uint64_t size, uint64_t device_address, u32 option) {
R_RETURN(MapDeviceAddressSpaceByForce(system, das_handle, process_handle, process_address, size,
device_address, option));
}
Result MapDeviceAddressSpaceAligned64(Core::System& system, Handle das_handle,
Handle process_handle, uint64_t process_address,
uint64_t size, uint64_t device_address, u32 option) {
R_RETURN(MapDeviceAddressSpaceAligned(system, das_handle, process_handle, process_address, size,
device_address, option));
}
Result UnmapDeviceAddressSpace64(Core::System& system, Handle das_handle, Handle process_handle,
uint64_t process_address, uint64_t size, uint64_t device_address) {
R_RETURN(UnmapDeviceAddressSpace(system, das_handle, process_handle, process_address, size,
device_address));
}
Result CreateDeviceAddressSpace64From32(Core::System& system, Handle* out_handle,
uint64_t das_address, uint64_t das_size) {
R_RETURN(CreateDeviceAddressSpace(system, out_handle, das_address, das_size));
}
Result AttachDeviceAddressSpace64From32(Core::System& system, DeviceName device_name,
Handle das_handle) {
R_RETURN(AttachDeviceAddressSpace(system, device_name, das_handle));
}
Result DetachDeviceAddressSpace64From32(Core::System& system, DeviceName device_name,
Handle das_handle) {
R_RETURN(DetachDeviceAddressSpace(system, device_name, das_handle));
}
Result MapDeviceAddressSpaceByForce64From32(Core::System& system, Handle das_handle,
Handle process_handle, uint64_t process_address,
uint32_t size, uint64_t device_address, u32 option) {
R_RETURN(MapDeviceAddressSpaceByForce(system, das_handle, process_handle, process_address, size,
device_address, option));
}
Result MapDeviceAddressSpaceAligned64From32(Core::System& system, Handle das_handle,
Handle process_handle, uint64_t process_address,
uint32_t size, uint64_t device_address, u32 option) {
R_RETURN(MapDeviceAddressSpaceAligned(system, das_handle, process_handle, process_address, size,
device_address, option));
}
Result UnmapDeviceAddressSpace64From32(Core::System& system, Handle das_handle,
Handle process_handle, uint64_t process_address,
uint32_t size, uint64_t device_address) {
R_RETURN(UnmapDeviceAddressSpace(system, das_handle, process_handle, process_address, size,
device_address));
}
} // namespace Kernel::Svc

View File

@@ -24,10 +24,6 @@ Result SignalEvent(Core::System& system, Handle event_handle) {
return event->Signal();
}
Result SignalEvent32(Core::System& system, Handle event_handle) {
return SignalEvent(system, event_handle);
}
Result ClearEvent(Core::System& system, Handle event_handle) {
LOG_TRACE(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
@@ -55,10 +51,6 @@ Result ClearEvent(Core::System& system, Handle event_handle) {
return ResultInvalidHandle;
}
Result ClearEvent32(Core::System& system, Handle event_handle) {
return ClearEvent(system, event_handle);
}
Result CreateEvent(Core::System& system, Handle* out_write, Handle* out_read) {
LOG_DEBUG(Kernel_SVC, "called");
@@ -104,8 +96,29 @@ Result CreateEvent(Core::System& system, Handle* out_write, Handle* out_read) {
return ResultSuccess;
}
Result CreateEvent32(Core::System& system, Handle* out_write, Handle* out_read) {
return CreateEvent(system, out_write, out_read);
Result SignalEvent64(Core::System& system, Handle event_handle) {
R_RETURN(SignalEvent(system, event_handle));
}
Result ClearEvent64(Core::System& system, Handle event_handle) {
R_RETURN(ClearEvent(system, event_handle));
}
Result CreateEvent64(Core::System& system, Handle* out_write_handle, Handle* out_read_handle) {
R_RETURN(CreateEvent(system, out_write_handle, out_read_handle));
}
Result SignalEvent64From32(Core::System& system, Handle event_handle) {
R_RETURN(SignalEvent(system, event_handle));
}
Result ClearEvent64From32(Core::System& system, Handle event_handle) {
R_RETURN(ClearEvent(system, event_handle));
}
Result CreateEvent64From32(Core::System& system, Handle* out_write_handle,
Handle* out_read_handle) {
R_RETURN(CreateEvent(system, out_write_handle, out_read_handle));
}
} // namespace Kernel::Svc

View File

@@ -12,10 +12,10 @@
namespace Kernel::Svc {
/// Break program execution
void Break(Core::System& system, u32 reason, u64 info1, u64 info2) {
void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) {
BreakReason break_reason =
static_cast<BreakReason>(reason & ~static_cast<u32>(BreakReason::NotificationOnlyFlag));
bool notification_only = (reason & static_cast<u32>(BreakReason::NotificationOnlyFlag)) != 0;
reason & static_cast<BreakReason>(~BreakReason::NotificationOnlyFlag);
bool notification_only = True(reason & BreakReason::NotificationOnlyFlag);
bool has_dumped_buffer{};
std::vector<u8> debug_buffer;
@@ -90,9 +90,9 @@ void Break(Core::System& system, u32 reason, u64 info1, u64 info2) {
break;
}
system.GetReporter().SaveSvcBreakReport(reason, notification_only, info1, info2,
has_dumped_buffer ? std::make_optional(debug_buffer)
: std::nullopt);
system.GetReporter().SaveSvcBreakReport(
static_cast<u32>(reason), notification_only, info1, info2,
has_dumped_buffer ? std::make_optional(debug_buffer) : std::nullopt);
if (!notification_only) {
LOG_CRITICAL(
@@ -114,8 +114,24 @@ void Break(Core::System& system, u32 reason, u64 info1, u64 info2) {
}
}
void Break32(Core::System& system, u32 reason, u32 info1, u32 info2) {
Break(system, reason, info1, info2);
void ReturnFromException(Core::System& system, Result result) {
UNIMPLEMENTED();
}
void Break64(Core::System& system, BreakReason break_reason, uint64_t arg, uint64_t size) {
Break(system, break_reason, arg, size);
}
void Break64From32(Core::System& system, BreakReason break_reason, uint32_t arg, uint32_t size) {
Break(system, break_reason, arg, size);
}
void ReturnFromException64(Core::System& system, Result result) {
ReturnFromException(system, result);
}
void ReturnFromException64From32(Core::System& system, Result result) {
ReturnFromException(system, result);
}
} // namespace Kernel::Svc

View File

@@ -10,11 +10,12 @@
namespace Kernel::Svc {
/// Gets system/memory information for the current process
Result GetInfo(Core::System& system, u64* result, u64 info_id, Handle handle, u64 info_sub_id) {
LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id,
info_sub_id, handle);
Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle handle,
u64 info_sub_id) {
LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}",
info_id_type, info_sub_id, handle);
const auto info_id_type = static_cast<InfoType>(info_id);
u32 info_id = static_cast<u32>(info_id_type);
switch (info_id_type) {
case InfoType::CoreMask:
@@ -267,16 +268,30 @@ Result GetInfo(Core::System& system, u64* result, u64 info_id, Handle handle, u6
}
}
Result GetInfo32(Core::System& system, u32* result_low, u32* result_high, u32 sub_id_low,
u32 info_id, u32 handle, u32 sub_id_high) {
const u64 sub_id{u64{sub_id_low} | (u64{sub_id_high} << 32)};
u64 res_value{};
Result GetSystemInfo(Core::System& system, uint64_t* out, SystemInfoType info_type, Handle handle,
uint64_t info_subtype) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
const Result result{GetInfo(system, &res_value, info_id, handle, sub_id)};
*result_high = static_cast<u32>(res_value >> 32);
*result_low = static_cast<u32>(res_value & std::numeric_limits<u32>::max());
Result GetInfo64(Core::System& system, uint64_t* out, InfoType info_type, Handle handle,
uint64_t info_subtype) {
R_RETURN(GetInfo(system, out, info_type, handle, info_subtype));
}
return result;
Result GetSystemInfo64(Core::System& system, uint64_t* out, SystemInfoType info_type, Handle handle,
uint64_t info_subtype) {
R_RETURN(GetSystemInfo(system, out, info_type, handle, info_subtype));
}
Result GetInfo64From32(Core::System& system, uint64_t* out, InfoType info_type, Handle handle,
uint64_t info_subtype) {
R_RETURN(GetInfo(system, out, info_type, handle, info_subtype));
}
Result GetSystemInfo64From32(Core::System& system, uint64_t* out, SystemInfoType info_type,
Handle handle, uint64_t info_subtype) {
R_RETURN(GetSystemInfo(system, out, info_type, handle, info_subtype));
}
} // namespace Kernel::Svc

View File

@@ -0,0 +1,35 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel::Svc {
Result MapInsecureMemory(Core::System& system, uintptr_t address, size_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result UnmapInsecureMemory(Core::System& system, uintptr_t address, size_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result MapInsecureMemory64(Core::System& system, uint64_t address, uint64_t size) {
R_RETURN(MapInsecureMemory(system, address, size));
}
Result UnmapInsecureMemory64(Core::System& system, uint64_t address, uint64_t size) {
R_RETURN(UnmapInsecureMemory(system, address, size));
}
Result MapInsecureMemory64From32(Core::System& system, uint32_t address, uint32_t size) {
R_RETURN(MapInsecureMemory(system, address, size));
}
Result UnmapInsecureMemory64From32(Core::System& system, uint32_t address, uint32_t size) {
R_RETURN(UnmapInsecureMemory(system, address, size));
}
} // namespace Kernel::Svc

View File

@@ -2,5 +2,24 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel::Svc {} // namespace Kernel::Svc
namespace Kernel::Svc {
Result CreateInterruptEvent(Core::System& system, Handle* out, int32_t interrupt_id,
InterruptType type) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result CreateInterruptEvent64(Core::System& system, Handle* out_read_handle, int32_t interrupt_id,
InterruptType interrupt_type) {
R_RETURN(CreateInterruptEvent(system, out_read_handle, interrupt_id, interrupt_type));
}
Result CreateInterruptEvent64From32(Core::System& system, Handle* out_read_handle,
int32_t interrupt_id, InterruptType interrupt_type) {
R_RETURN(CreateInterruptEvent(system, out_read_handle, interrupt_id, interrupt_type));
}
} // namespace Kernel::Svc

View File

@@ -2,5 +2,70 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel::Svc {} // namespace Kernel::Svc
namespace Kernel::Svc {
Result CreateIoPool(Core::System& system, Handle* out, IoPoolType pool_type) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result CreateIoRegion(Core::System& system, Handle* out, Handle io_pool_handle, uint64_t phys_addr,
size_t size, MemoryMapping mapping, MemoryPermission perm) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result MapIoRegion(Core::System& system, Handle io_region_handle, uintptr_t address, size_t size,
MemoryPermission map_perm) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result UnmapIoRegion(Core::System& system, Handle io_region_handle, uintptr_t address,
size_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result CreateIoPool64(Core::System& system, Handle* out_handle, IoPoolType pool_type) {
R_RETURN(CreateIoPool(system, out_handle, pool_type));
}
Result CreateIoRegion64(Core::System& system, Handle* out_handle, Handle io_pool,
uint64_t physical_address, uint64_t size, MemoryMapping mapping,
MemoryPermission perm) {
R_RETURN(CreateIoRegion(system, out_handle, io_pool, physical_address, size, mapping, perm));
}
Result MapIoRegion64(Core::System& system, Handle io_region, uint64_t address, uint64_t size,
MemoryPermission perm) {
R_RETURN(MapIoRegion(system, io_region, address, size, perm));
}
Result UnmapIoRegion64(Core::System& system, Handle io_region, uint64_t address, uint64_t size) {
R_RETURN(UnmapIoRegion(system, io_region, address, size));
}
Result CreateIoPool64From32(Core::System& system, Handle* out_handle, IoPoolType pool_type) {
R_RETURN(CreateIoPool(system, out_handle, pool_type));
}
Result CreateIoRegion64From32(Core::System& system, Handle* out_handle, Handle io_pool,
uint64_t physical_address, uint32_t size, MemoryMapping mapping,
MemoryPermission perm) {
R_RETURN(CreateIoRegion(system, out_handle, io_pool, physical_address, size, mapping, perm));
}
Result MapIoRegion64From32(Core::System& system, Handle io_region, uint32_t address, uint32_t size,
MemoryPermission perm) {
R_RETURN(MapIoRegion(system, io_region, address, size, perm));
}
Result UnmapIoRegion64From32(Core::System& system, Handle io_region, uint32_t address,
uint32_t size) {
R_RETURN(UnmapIoRegion(system, io_region, address, size));
}
} // namespace Kernel::Svc

View File

@@ -24,20 +24,37 @@ Result SendSyncRequest(Core::System& system, Handle handle) {
return session->SendSyncRequest();
}
Result SendSyncRequest32(Core::System& system, Handle handle) {
return SendSyncRequest(system, handle);
Result SendSyncRequestWithUserBuffer(Core::System& system, uint64_t message_buffer,
uint64_t message_buffer_size, Handle session_handle) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result ReplyAndReceive(Core::System& system, s32* out_index, Handle* handles, s32 num_handles,
Result SendAsyncRequestWithUserBuffer(Core::System& system, Handle* out_event_handle,
uint64_t message_buffer, uint64_t message_buffer_size,
Handle session_handle) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_addr, s32 num_handles,
Handle reply_target, s64 timeout_ns) {
auto& kernel = system.Kernel();
auto& handle_table = GetCurrentThread(kernel).GetOwnerProcess()->GetHandleTable();
R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange);
R_UNLESS(system.Memory().IsValidVirtualAddressRange(
handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)),
ResultInvalidPointer);
std::vector<Handle> handles(num_handles);
system.Memory().ReadBlock(handles_addr, handles.data(), sizeof(Handle) * num_handles);
// Convert handle list to object table.
std::vector<KSynchronizationObject*> objs(num_handles);
R_UNLESS(
handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles, num_handles),
ResultInvalidHandle);
R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles.data(),
num_handles),
ResultInvalidHandle);
// Ensure handles are closed when we're done.
SCOPE_EXIT({
@@ -86,4 +103,72 @@ Result ReplyAndReceive(Core::System& system, s32* out_index, Handle* handles, s3
}
}
Result ReplyAndReceiveWithUserBuffer(Core::System& system, int32_t* out_index,
uint64_t message_buffer, uint64_t message_buffer_size,
uint64_t handles, int32_t num_handles, Handle reply_target,
int64_t timeout_ns) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result SendSyncRequest64(Core::System& system, Handle session_handle) {
R_RETURN(SendSyncRequest(system, session_handle));
}
Result SendSyncRequestWithUserBuffer64(Core::System& system, uint64_t message_buffer,
uint64_t message_buffer_size, Handle session_handle) {
R_RETURN(
SendSyncRequestWithUserBuffer(system, message_buffer, message_buffer_size, session_handle));
}
Result SendAsyncRequestWithUserBuffer64(Core::System& system, Handle* out_event_handle,
uint64_t message_buffer, uint64_t message_buffer_size,
Handle session_handle) {
R_RETURN(SendAsyncRequestWithUserBuffer(system, out_event_handle, message_buffer,
message_buffer_size, session_handle));
}
Result ReplyAndReceive64(Core::System& system, int32_t* out_index, uint64_t handles,
int32_t num_handles, Handle reply_target, int64_t timeout_ns) {
R_RETURN(ReplyAndReceive(system, out_index, handles, num_handles, reply_target, timeout_ns));
}
Result ReplyAndReceiveWithUserBuffer64(Core::System& system, int32_t* out_index,
uint64_t message_buffer, uint64_t message_buffer_size,
uint64_t handles, int32_t num_handles, Handle reply_target,
int64_t timeout_ns) {
R_RETURN(ReplyAndReceiveWithUserBuffer(system, out_index, message_buffer, message_buffer_size,
handles, num_handles, reply_target, timeout_ns));
}
Result SendSyncRequest64From32(Core::System& system, Handle session_handle) {
R_RETURN(SendSyncRequest(system, session_handle));
}
Result SendSyncRequestWithUserBuffer64From32(Core::System& system, uint32_t message_buffer,
uint32_t message_buffer_size, Handle session_handle) {
R_RETURN(
SendSyncRequestWithUserBuffer(system, message_buffer, message_buffer_size, session_handle));
}
Result SendAsyncRequestWithUserBuffer64From32(Core::System& system, Handle* out_event_handle,
uint32_t message_buffer, uint32_t message_buffer_size,
Handle session_handle) {
R_RETURN(SendAsyncRequestWithUserBuffer(system, out_event_handle, message_buffer,
message_buffer_size, session_handle));
}
Result ReplyAndReceive64From32(Core::System& system, int32_t* out_index, uint32_t handles,
int32_t num_handles, Handle reply_target, int64_t timeout_ns) {
R_RETURN(ReplyAndReceive(system, out_index, handles, num_handles, reply_target, timeout_ns));
}
Result ReplyAndReceiveWithUserBuffer64From32(Core::System& system, int32_t* out_index,
uint32_t message_buffer, uint32_t message_buffer_size,
uint32_t handles, int32_t num_handles,
Handle reply_target, int64_t timeout_ns) {
R_RETURN(ReplyAndReceiveWithUserBuffer(system, out_index, message_buffer, message_buffer_size,
handles, num_handles, reply_target, timeout_ns));
}
} // namespace Kernel::Svc

View File

@@ -5,15 +5,31 @@
namespace Kernel::Svc {
void KernelDebug([[maybe_unused]] Core::System& system, [[maybe_unused]] u32 kernel_debug_type,
[[maybe_unused]] u64 param1, [[maybe_unused]] u64 param2,
[[maybe_unused]] u64 param3) {
void KernelDebug(Core::System& system, KernelDebugType kernel_debug_type, u64 arg0, u64 arg1,
u64 arg2) {
// Intentionally do nothing, as this does nothing in released kernel binaries.
}
void ChangeKernelTraceState([[maybe_unused]] Core::System& system,
[[maybe_unused]] u32 trace_state) {
void ChangeKernelTraceState(Core::System& system, KernelTraceState trace_state) {
// Intentionally do nothing, as this does nothing in released kernel binaries.
}
void KernelDebug64(Core::System& system, KernelDebugType kern_debug_type, uint64_t arg0,
uint64_t arg1, uint64_t arg2) {
KernelDebug(system, kern_debug_type, arg0, arg1, arg2);
}
void ChangeKernelTraceState64(Core::System& system, KernelTraceState kern_trace_state) {
ChangeKernelTraceState(system, kern_trace_state);
}
void KernelDebug64From32(Core::System& system, KernelDebugType kern_debug_type, uint64_t arg0,
uint64_t arg1, uint64_t arg2) {
KernelDebug(system, kern_debug_type, arg0, arg1, arg2);
}
void ChangeKernelTraceState64From32(Core::System& system, KernelTraceState kern_trace_state) {
ChangeKernelTraceState(system, kern_trace_state);
}
} // namespace Kernel::Svc

View File

@@ -1,6 +1,73 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/arm/arm_interface.h"
#include "core/core.h"
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel::Svc {} // namespace Kernel::Svc
namespace Kernel::Svc {
Result SendSyncRequestLight(Core::System& system, Handle session_handle, u32* args) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result ReplyAndReceiveLight(Core::System& system, Handle session_handle, u32* args) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result SendSyncRequestLight64(Core::System& system, Handle session_handle, u32* args) {
R_RETURN(SendSyncRequestLight(system, session_handle, args));
}
Result ReplyAndReceiveLight64(Core::System& system, Handle session_handle, u32* args) {
R_RETURN(ReplyAndReceiveLight(system, session_handle, args));
}
Result SendSyncRequestLight64From32(Core::System& system, Handle session_handle, u32* args) {
R_RETURN(SendSyncRequestLight(system, session_handle, args));
}
Result ReplyAndReceiveLight64From32(Core::System& system, Handle session_handle, u32* args) {
R_RETURN(ReplyAndReceiveLight(system, session_handle, args));
}
// Custom ABI implementation for light IPC.
template <typename F>
static void SvcWrap_LightIpc(Core::System& system, F&& cb) {
auto& core = system.CurrentArmInterface();
std::array<u32, 7> arguments{};
Handle session_handle = static_cast<Handle>(core.GetReg(0));
for (int i = 0; i < 7; i++) {
arguments[i] = static_cast<u32>(core.GetReg(i + 1));
}
Result ret = cb(system, session_handle, arguments.data());
core.SetReg(0, ret.raw);
for (int i = 0; i < 7; i++) {
core.SetReg(i + 1, arguments[i]);
}
}
void SvcWrap_SendSyncRequestLight64(Core::System& system) {
SvcWrap_LightIpc(system, SendSyncRequestLight64);
}
void SvcWrap_ReplyAndReceiveLight64(Core::System& system) {
SvcWrap_LightIpc(system, ReplyAndReceiveLight64);
}
void SvcWrap_SendSyncRequestLight64From32(Core::System& system) {
SvcWrap_LightIpc(system, SendSyncRequestLight64From32);
}
void SvcWrap_ReplyAndReceiveLight64From32(Core::System& system) {
SvcWrap_LightIpc(system, ReplyAndReceiveLight64From32);
}
} // namespace Kernel::Svc

View File

@@ -27,10 +27,6 @@ Result ArbitrateLock(Core::System& system, Handle thread_handle, VAddr address,
return system.Kernel().CurrentProcess()->WaitForAddress(thread_handle, address, tag);
}
Result ArbitrateLock32(Core::System& system, Handle thread_handle, u32 address, u32 tag) {
return ArbitrateLock(system, thread_handle, address, tag);
}
/// Unlock a mutex
Result ArbitrateUnlock(Core::System& system, VAddr address) {
LOG_TRACE(Kernel_SVC, "called address=0x{:X}", address);
@@ -50,8 +46,21 @@ Result ArbitrateUnlock(Core::System& system, VAddr address) {
return system.Kernel().CurrentProcess()->SignalToAddress(address);
}
Result ArbitrateUnlock32(Core::System& system, u32 address) {
return ArbitrateUnlock(system, address);
Result ArbitrateLock64(Core::System& system, Handle thread_handle, uint64_t address, uint32_t tag) {
R_RETURN(ArbitrateLock(system, thread_handle, address, tag));
}
Result ArbitrateUnlock64(Core::System& system, uint64_t address) {
R_RETURN(ArbitrateUnlock(system, address));
}
Result ArbitrateLock64From32(Core::System& system, Handle thread_handle, uint32_t address,
uint32_t tag) {
R_RETURN(ArbitrateLock(system, thread_handle, address, tag));
}
Result ArbitrateUnlock64From32(Core::System& system, uint32_t address) {
R_RETURN(ArbitrateUnlock(system, address));
}
} // namespace Kernel::Svc

View File

@@ -144,10 +144,6 @@ Result SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mas
return page_table.SetMemoryAttribute(address, size, mask, attr);
}
Result SetMemoryAttribute32(Core::System& system, u32 address, u32 size, u32 mask, u32 attr) {
return SetMemoryAttribute(system, address, size, mask, attr);
}
/// Maps a memory range into a different range.
Result MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) {
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
@@ -163,10 +159,6 @@ Result MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size)
return page_table.MapMemory(dst_addr, src_addr, size);
}
Result MapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size) {
return MapMemory(system, dst_addr, src_addr, size);
}
/// Unmaps a region that was previously mapped with svcMapMemory
Result UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) {
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
@@ -182,8 +174,44 @@ Result UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 siz
return page_table.UnmapMemory(dst_addr, src_addr, size);
}
Result UnmapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size) {
return UnmapMemory(system, dst_addr, src_addr, size);
Result SetMemoryPermission64(Core::System& system, uint64_t address, uint64_t size,
MemoryPermission perm) {
R_RETURN(SetMemoryPermission(system, address, size, perm));
}
Result SetMemoryAttribute64(Core::System& system, uint64_t address, uint64_t size, uint32_t mask,
uint32_t attr) {
R_RETURN(SetMemoryAttribute(system, address, size, mask, attr));
}
Result MapMemory64(Core::System& system, uint64_t dst_address, uint64_t src_address,
uint64_t size) {
R_RETURN(MapMemory(system, dst_address, src_address, size));
}
Result UnmapMemory64(Core::System& system, uint64_t dst_address, uint64_t src_address,
uint64_t size) {
R_RETURN(UnmapMemory(system, dst_address, src_address, size));
}
Result SetMemoryPermission64From32(Core::System& system, uint32_t address, uint32_t size,
MemoryPermission perm) {
R_RETURN(SetMemoryPermission(system, address, size, perm));
}
Result SetMemoryAttribute64From32(Core::System& system, uint32_t address, uint32_t size,
uint32_t mask, uint32_t attr) {
R_RETURN(SetMemoryAttribute(system, address, size, mask, attr));
}
Result MapMemory64From32(Core::System& system, uint32_t dst_address, uint32_t src_address,
uint32_t size) {
R_RETURN(MapMemory(system, dst_address, src_address, size));
}
Result UnmapMemory64From32(Core::System& system, uint32_t dst_address, uint32_t src_address,
uint32_t size) {
R_RETURN(UnmapMemory(system, dst_address, src_address, size));
}
} // namespace Kernel::Svc

View File

@@ -21,13 +21,6 @@ Result SetHeapSize(Core::System& system, VAddr* out_address, u64 size) {
return ResultSuccess;
}
Result SetHeapSize32(Core::System& system, u32* heap_addr, u32 heap_size) {
VAddr temp_heap_addr{};
const Result result{SetHeapSize(system, &temp_heap_addr, heap_size)};
*heap_addr = static_cast<u32>(temp_heap_addr);
return result;
}
/// Maps memory at a desired address
Result MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size);
@@ -77,10 +70,6 @@ Result MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
return page_table.MapPhysicalMemory(addr, size);
}
Result MapPhysicalMemory32(Core::System& system, u32 addr, u32 size) {
return MapPhysicalMemory(system, addr, size);
}
/// Unmaps memory previously mapped via MapPhysicalMemory
Result UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size);
@@ -130,8 +119,67 @@ Result UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
return page_table.UnmapPhysicalMemory(addr, size);
}
Result UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size) {
return UnmapPhysicalMemory(system, addr, size);
Result MapPhysicalMemoryUnsafe(Core::System& system, uint64_t address, uint64_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result UnmapPhysicalMemoryUnsafe(Core::System& system, uint64_t address, uint64_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result SetUnsafeLimit(Core::System& system, uint64_t limit) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result SetHeapSize64(Core::System& system, uint64_t* out_address, uint64_t size) {
R_RETURN(SetHeapSize(system, out_address, size));
}
Result MapPhysicalMemory64(Core::System& system, uint64_t address, uint64_t size) {
R_RETURN(MapPhysicalMemory(system, address, size));
}
Result UnmapPhysicalMemory64(Core::System& system, uint64_t address, uint64_t size) {
R_RETURN(UnmapPhysicalMemory(system, address, size));
}
Result MapPhysicalMemoryUnsafe64(Core::System& system, uint64_t address, uint64_t size) {
R_RETURN(MapPhysicalMemoryUnsafe(system, address, size));
}
Result UnmapPhysicalMemoryUnsafe64(Core::System& system, uint64_t address, uint64_t size) {
R_RETURN(UnmapPhysicalMemoryUnsafe(system, address, size));
}
Result SetUnsafeLimit64(Core::System& system, uint64_t limit) {
R_RETURN(SetUnsafeLimit(system, limit));
}
Result SetHeapSize64From32(Core::System& system, uintptr_t* out_address, uint32_t size) {
R_RETURN(SetHeapSize(system, out_address, size));
}
Result MapPhysicalMemory64From32(Core::System& system, uint32_t address, uint32_t size) {
R_RETURN(MapPhysicalMemory(system, address, size));
}
Result UnmapPhysicalMemory64From32(Core::System& system, uint32_t address, uint32_t size) {
R_RETURN(UnmapPhysicalMemory(system, address, size));
}
Result MapPhysicalMemoryUnsafe64From32(Core::System& system, uint32_t address, uint32_t size) {
R_RETURN(MapPhysicalMemoryUnsafe(system, address, size));
}
Result UnmapPhysicalMemoryUnsafe64From32(Core::System& system, uint32_t address, uint32_t size) {
R_RETURN(UnmapPhysicalMemoryUnsafe(system, address, size));
}
Result SetUnsafeLimit64From32(Core::System& system, uint32_t limit) {
R_RETURN(SetUnsafeLimit(system, limit));
}
} // namespace Kernel::Svc

View File

@@ -63,9 +63,60 @@ Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr port_name_add
return ResultSuccess;
}
Result ConnectToNamedPort32(Core::System& system, Handle* out_handle, u32 port_name_address) {
Result CreatePort(Core::System& system, Handle* out_server, Handle* out_client,
int32_t max_sessions, bool is_light, uintptr_t name) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
return ConnectToNamedPort(system, out_handle, port_name_address);
Result ConnectToPort(Core::System& system, Handle* out_handle, Handle port) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t name,
int32_t max_sessions) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result ConnectToNamedPort64(Core::System& system, Handle* out_handle, uint64_t name) {
R_RETURN(ConnectToNamedPort(system, out_handle, name));
}
Result CreatePort64(Core::System& system, Handle* out_server_handle, Handle* out_client_handle,
int32_t max_sessions, bool is_light, uint64_t name) {
R_RETURN(
CreatePort(system, out_server_handle, out_client_handle, max_sessions, is_light, name));
}
Result ManageNamedPort64(Core::System& system, Handle* out_server_handle, uint64_t name,
int32_t max_sessions) {
R_RETURN(ManageNamedPort(system, out_server_handle, name, max_sessions));
}
Result ConnectToPort64(Core::System& system, Handle* out_handle, Handle port) {
R_RETURN(ConnectToPort(system, out_handle, port));
}
Result ConnectToNamedPort64From32(Core::System& system, Handle* out_handle, uint32_t name) {
R_RETURN(ConnectToNamedPort(system, out_handle, name));
}
Result CreatePort64From32(Core::System& system, Handle* out_server_handle,
Handle* out_client_handle, int32_t max_sessions, bool is_light,
uint32_t name) {
R_RETURN(
CreatePort(system, out_server_handle, out_client_handle, max_sessions, is_light, name));
}
Result ManageNamedPort64From32(Core::System& system, Handle* out_server_handle, uint32_t name,
int32_t max_sessions) {
R_RETURN(ManageNamedPort(system, out_server_handle, name, max_sessions));
}
Result ConnectToPort64From32(Core::System& system, Handle* out_handle, Handle port) {
R_RETURN(ConnectToPort(system, out_handle, port));
}
} // namespace Kernel::Svc

View File

@@ -2,5 +2,20 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel::Svc {} // namespace Kernel::Svc
namespace Kernel::Svc {
void SleepSystem(Core::System& system) {
UNIMPLEMENTED();
}
void SleepSystem64(Core::System& system) {
return SleepSystem(system);
}
void SleepSystem64From32(Core::System& system) {
return SleepSystem(system);
}
} // namespace Kernel::Svc

View File

@@ -18,10 +18,6 @@ void ExitProcess(Core::System& system) {
system.Exit();
}
void ExitProcess32(Core::System& system) {
ExitProcess(system);
}
/// Gets the ID of the specified process or a specified thread's owning process.
Result GetProcessId(Core::System& system, u64* out_process_id, Handle handle) {
LOG_DEBUG(Kernel_SVC, "called handle=0x{:08X}", handle);
@@ -54,17 +50,8 @@ Result GetProcessId(Core::System& system, u64* out_process_id, Handle handle) {
return ResultSuccess;
}
Result GetProcessId32(Core::System& system, u32* out_process_id_low, u32* out_process_id_high,
Handle handle) {
u64 out_process_id{};
const auto result = GetProcessId(system, &out_process_id, handle);
*out_process_id_low = static_cast<u32>(out_process_id);
*out_process_id_high = static_cast<u32>(out_process_id >> 32);
return result;
}
Result GetProcessList(Core::System& system, u32* out_num_processes, VAddr out_process_ids,
u32 out_process_ids_size) {
Result GetProcessList(Core::System& system, s32* out_num_processes, VAddr out_process_ids,
int32_t out_process_ids_size) {
LOG_DEBUG(Kernel_SVC, "called. out_process_ids=0x{:016X}, out_process_ids_size={}",
out_process_ids, out_process_ids_size);
@@ -89,7 +76,8 @@ Result GetProcessList(Core::System& system, u32* out_num_processes, VAddr out_pr
auto& memory = system.Memory();
const auto& process_list = kernel.GetProcessList();
const auto num_processes = process_list.size();
const auto copy_amount = std::min(std::size_t{out_process_ids_size}, num_processes);
const auto copy_amount =
std::min(static_cast<std::size_t>(out_process_ids_size), num_processes);
for (std::size_t i = 0; i < copy_amount; ++i) {
memory.Write64(out_process_ids, process_list[i]->GetProcessID());
@@ -100,8 +88,9 @@ Result GetProcessList(Core::System& system, u32* out_num_processes, VAddr out_pr
return ResultSuccess;
}
Result GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type) {
LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type=0x{:X}", process_handle, type);
Result GetProcessInfo(Core::System& system, s64* out, Handle process_handle,
ProcessInfoType info_type) {
LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type=0x{:X}", process_handle, info_type);
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle);
@@ -111,14 +100,95 @@ Result GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32
return ResultInvalidHandle;
}
const auto info_type = static_cast<ProcessInfoType>(type);
if (info_type != ProcessInfoType::ProcessState) {
LOG_ERROR(Kernel_SVC, "Expected info_type to be ProcessState but got {} instead", type);
LOG_ERROR(Kernel_SVC, "Expected info_type to be ProcessState but got {} instead",
info_type);
return ResultInvalidEnumValue;
}
*out = static_cast<u64>(process->GetState());
*out = static_cast<s64>(process->GetState());
return ResultSuccess;
}
Result CreateProcess(Core::System& system, Handle* out_handle, uint64_t parameters, uint64_t caps,
int32_t num_caps) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result StartProcess(Core::System& system, Handle process_handle, int32_t priority, int32_t core_id,
uint64_t main_thread_stack_size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result TerminateProcess(Core::System& system, Handle process_handle) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
void ExitProcess64(Core::System& system) {
ExitProcess(system);
}
Result GetProcessId64(Core::System& system, uint64_t* out_process_id, Handle process_handle) {
R_RETURN(GetProcessId(system, out_process_id, process_handle));
}
Result GetProcessList64(Core::System& system, int32_t* out_num_processes, uint64_t out_process_ids,
int32_t max_out_count) {
R_RETURN(GetProcessList(system, out_num_processes, out_process_ids, max_out_count));
}
Result CreateProcess64(Core::System& system, Handle* out_handle, uint64_t parameters, uint64_t caps,
int32_t num_caps) {
R_RETURN(CreateProcess(system, out_handle, parameters, caps, num_caps));
}
Result StartProcess64(Core::System& system, Handle process_handle, int32_t priority,
int32_t core_id, uint64_t main_thread_stack_size) {
R_RETURN(StartProcess(system, process_handle, priority, core_id, main_thread_stack_size));
}
Result TerminateProcess64(Core::System& system, Handle process_handle) {
R_RETURN(TerminateProcess(system, process_handle));
}
Result GetProcessInfo64(Core::System& system, int64_t* out_info, Handle process_handle,
ProcessInfoType info_type) {
R_RETURN(GetProcessInfo(system, out_info, process_handle, info_type));
}
void ExitProcess64From32(Core::System& system) {
ExitProcess(system);
}
Result GetProcessId64From32(Core::System& system, uint64_t* out_process_id, Handle process_handle) {
R_RETURN(GetProcessId(system, out_process_id, process_handle));
}
Result GetProcessList64From32(Core::System& system, int32_t* out_num_processes,
uint32_t out_process_ids, int32_t max_out_count) {
R_RETURN(GetProcessList(system, out_num_processes, out_process_ids, max_out_count));
}
Result CreateProcess64From32(Core::System& system, Handle* out_handle, uint32_t parameters,
uint32_t caps, int32_t num_caps) {
R_RETURN(CreateProcess(system, out_handle, parameters, caps, num_caps));
}
Result StartProcess64From32(Core::System& system, Handle process_handle, int32_t priority,
int32_t core_id, uint64_t main_thread_stack_size) {
R_RETURN(StartProcess(system, process_handle, priority, core_id, main_thread_stack_size));
}
Result TerminateProcess64From32(Core::System& system, Handle process_handle) {
R_RETURN(TerminateProcess(system, process_handle));
}
Result GetProcessInfo64From32(Core::System& system, int64_t* out_info, Handle process_handle,
ProcessInfoType info_type) {
R_RETURN(GetProcessInfo(system, out_info, process_handle, info_type));
}
} // namespace Kernel::Svc

View File

@@ -271,4 +271,54 @@ Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 d
KPageTable::ICacheInvalidationStrategy::InvalidateAll);
}
Result SetProcessMemoryPermission64(Core::System& system, Handle process_handle, uint64_t address,
uint64_t size, MemoryPermission perm) {
R_RETURN(SetProcessMemoryPermission(system, process_handle, address, size, perm));
}
Result MapProcessMemory64(Core::System& system, uint64_t dst_address, Handle process_handle,
uint64_t src_address, uint64_t size) {
R_RETURN(MapProcessMemory(system, dst_address, process_handle, src_address, size));
}
Result UnmapProcessMemory64(Core::System& system, uint64_t dst_address, Handle process_handle,
uint64_t src_address, uint64_t size) {
R_RETURN(UnmapProcessMemory(system, dst_address, process_handle, src_address, size));
}
Result MapProcessCodeMemory64(Core::System& system, Handle process_handle, uint64_t dst_address,
uint64_t src_address, uint64_t size) {
R_RETURN(MapProcessCodeMemory(system, process_handle, dst_address, src_address, size));
}
Result UnmapProcessCodeMemory64(Core::System& system, Handle process_handle, uint64_t dst_address,
uint64_t src_address, uint64_t size) {
R_RETURN(UnmapProcessCodeMemory(system, process_handle, dst_address, src_address, size));
}
Result SetProcessMemoryPermission64From32(Core::System& system, Handle process_handle,
uint64_t address, uint64_t size, MemoryPermission perm) {
R_RETURN(SetProcessMemoryPermission(system, process_handle, address, size, perm));
}
Result MapProcessMemory64From32(Core::System& system, uint32_t dst_address, Handle process_handle,
uint64_t src_address, uint32_t size) {
R_RETURN(MapProcessMemory(system, dst_address, process_handle, src_address, size));
}
Result UnmapProcessMemory64From32(Core::System& system, uint32_t dst_address, Handle process_handle,
uint64_t src_address, uint32_t size) {
R_RETURN(UnmapProcessMemory(system, dst_address, process_handle, src_address, size));
}
Result MapProcessCodeMemory64From32(Core::System& system, Handle process_handle,
uint64_t dst_address, uint64_t src_address, uint64_t size) {
R_RETURN(MapProcessCodeMemory(system, process_handle, dst_address, src_address, size));
}
Result UnmapProcessCodeMemory64From32(Core::System& system, Handle process_handle,
uint64_t dst_address, uint64_t src_address, uint64_t size) {
R_RETURN(UnmapProcessCodeMemory(system, process_handle, dst_address, src_address, size));
}
} // namespace Kernel::Svc

View File

@@ -9,12 +9,16 @@
namespace Kernel::Svc {
/// Get which CPU core is executing the current thread
u32 GetCurrentProcessorNumber(Core::System& system) {
int32_t GetCurrentProcessorNumber(Core::System& system) {
LOG_TRACE(Kernel_SVC, "called");
return static_cast<u32>(system.CurrentPhysicalCore().CoreIndex());
return static_cast<int32_t>(system.CurrentPhysicalCore().CoreIndex());
}
u32 GetCurrentProcessorNumber32(Core::System& system) {
int32_t GetCurrentProcessorNumber64(Core::System& system) {
return GetCurrentProcessorNumber(system);
}
int32_t GetCurrentProcessorNumber64From32(Core::System& system) {
return GetCurrentProcessorNumber(system);
}

View File

@@ -7,24 +7,20 @@
namespace Kernel::Svc {
Result QueryMemory(Core::System& system, VAddr memory_info_address, VAddr page_info_address,
Result QueryMemory(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info,
VAddr query_address) {
LOG_TRACE(Kernel_SVC,
"called, memory_info_address=0x{:016X}, page_info_address=0x{:016X}, "
"called, out_memory_info=0x{:016X}, "
"query_address=0x{:016X}",
memory_info_address, page_info_address, query_address);
out_memory_info, query_address);
return QueryProcessMemory(system, memory_info_address, page_info_address, CurrentProcess,
// Query memory is just QueryProcessMemory on the current process.
return QueryProcessMemory(system, out_memory_info, out_page_info, CurrentProcess,
query_address);
}
Result QueryMemory32(Core::System& system, u32 memory_info_address, u32 page_info_address,
u32 query_address) {
return QueryMemory(system, memory_info_address, page_info_address, query_address);
}
Result QueryProcessMemory(Core::System& system, VAddr memory_info_address, VAddr page_info_address,
Handle process_handle, VAddr address) {
Result QueryProcessMemory(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info,
Handle process_handle, uint64_t address) {
LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address);
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle);
@@ -37,19 +33,33 @@ Result QueryProcessMemory(Core::System& system, VAddr memory_info_address, VAddr
auto& memory{system.Memory()};
const auto memory_info{process->PageTable().QueryInfo(address).GetSvcMemoryInfo()};
memory.Write64(memory_info_address + 0x00, memory_info.base_address);
memory.Write64(memory_info_address + 0x08, memory_info.size);
memory.Write32(memory_info_address + 0x10, static_cast<u32>(memory_info.state) & 0xff);
memory.Write32(memory_info_address + 0x14, static_cast<u32>(memory_info.attribute));
memory.Write32(memory_info_address + 0x18, static_cast<u32>(memory_info.permission));
memory.Write32(memory_info_address + 0x1c, memory_info.ipc_count);
memory.Write32(memory_info_address + 0x20, memory_info.device_count);
memory.Write32(memory_info_address + 0x24, 0);
memory.WriteBlock(out_memory_info, &memory_info, sizeof(memory_info));
// Page info appears to be currently unused by the kernel and is always set to zero.
memory.Write32(page_info_address, 0);
//! This is supposed to be part of the QueryInfo call.
*out_page_info = {};
return ResultSuccess;
R_SUCCEED();
}
Result QueryMemory64(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info,
uint64_t address) {
R_RETURN(QueryMemory(system, out_memory_info, out_page_info, address));
}
Result QueryProcessMemory64(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info,
Handle process_handle, uint64_t address) {
R_RETURN(QueryProcessMemory(system, out_memory_info, out_page_info, process_handle, address));
}
Result QueryMemory64From32(Core::System& system, uint32_t out_memory_info, PageInfo* out_page_info,
uint32_t address) {
R_RETURN(QueryMemory(system, out_memory_info, out_page_info, address));
}
Result QueryProcessMemory64From32(Core::System& system, uint32_t out_memory_info,
PageInfo* out_page_info, Handle process_handle,
uint64_t address) {
R_RETURN(QueryProcessMemory(system, out_memory_info, out_page_info, process_handle, address));
}
} // namespace Kernel::Svc

View File

@@ -2,5 +2,26 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel::Svc {} // namespace Kernel::Svc
namespace Kernel::Svc {
Result ReadWriteRegister(Core::System& system, uint32_t* out, uint64_t address, uint32_t mask,
uint32_t value) {
*out = 0;
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result ReadWriteRegister64(Core::System& system, uint32_t* out_value, uint64_t address,
uint32_t mask, uint32_t value) {
R_RETURN(ReadWriteRegister(system, out_value, address, mask, value));
}
Result ReadWriteRegister64From32(Core::System& system, uint32_t* out_value, uint64_t address,
uint32_t mask, uint32_t value) {
R_RETURN(ReadWriteRegister(system, out_value, address, mask, value));
}
} // namespace Kernel::Svc

View File

@@ -32,7 +32,7 @@ Result CreateResourceLimit(Core::System& system, Handle* out_handle) {
return ResultSuccess;
}
Result GetResourceLimitLimitValue(Core::System& system, u64* out_limit_value,
Result GetResourceLimitLimitValue(Core::System& system, s64* out_limit_value,
Handle resource_limit_handle, LimitableResource which) {
LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}", resource_limit_handle,
which);
@@ -52,7 +52,7 @@ Result GetResourceLimitLimitValue(Core::System& system, u64* out_limit_value,
return ResultSuccess;
}
Result GetResourceLimitCurrentValue(Core::System& system, u64* out_current_value,
Result GetResourceLimitCurrentValue(Core::System& system, s64* out_current_value,
Handle resource_limit_handle, LimitableResource which) {
LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}", resource_limit_handle,
which);
@@ -73,7 +73,7 @@ Result GetResourceLimitCurrentValue(Core::System& system, u64* out_current_value
}
Result SetResourceLimitLimitValue(Core::System& system, Handle resource_limit_handle,
LimitableResource which, u64 limit_value) {
LimitableResource which, s64 limit_value) {
LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}, limit_value={}",
resource_limit_handle, which, limit_value);
@@ -92,4 +92,58 @@ Result SetResourceLimitLimitValue(Core::System& system, Handle resource_limit_ha
return ResultSuccess;
}
Result GetResourceLimitPeakValue(Core::System& system, int64_t* out_peak_value,
Handle resource_limit_handle, LimitableResource which) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result GetResourceLimitLimitValue64(Core::System& system, int64_t* out_limit_value,
Handle resource_limit_handle, LimitableResource which) {
R_RETURN(GetResourceLimitLimitValue(system, out_limit_value, resource_limit_handle, which));
}
Result GetResourceLimitCurrentValue64(Core::System& system, int64_t* out_current_value,
Handle resource_limit_handle, LimitableResource which) {
R_RETURN(GetResourceLimitCurrentValue(system, out_current_value, resource_limit_handle, which));
}
Result GetResourceLimitPeakValue64(Core::System& system, int64_t* out_peak_value,
Handle resource_limit_handle, LimitableResource which) {
R_RETURN(GetResourceLimitPeakValue(system, out_peak_value, resource_limit_handle, which));
}
Result CreateResourceLimit64(Core::System& system, Handle* out_handle) {
R_RETURN(CreateResourceLimit(system, out_handle));
}
Result SetResourceLimitLimitValue64(Core::System& system, Handle resource_limit_handle,
LimitableResource which, int64_t limit_value) {
R_RETURN(SetResourceLimitLimitValue(system, resource_limit_handle, which, limit_value));
}
Result GetResourceLimitLimitValue64From32(Core::System& system, int64_t* out_limit_value,
Handle resource_limit_handle, LimitableResource which) {
R_RETURN(GetResourceLimitLimitValue(system, out_limit_value, resource_limit_handle, which));
}
Result GetResourceLimitCurrentValue64From32(Core::System& system, int64_t* out_current_value,
Handle resource_limit_handle, LimitableResource which) {
R_RETURN(GetResourceLimitCurrentValue(system, out_current_value, resource_limit_handle, which));
}
Result GetResourceLimitPeakValue64From32(Core::System& system, int64_t* out_peak_value,
Handle resource_limit_handle, LimitableResource which) {
R_RETURN(GetResourceLimitPeakValue(system, out_peak_value, resource_limit_handle, which));
}
Result CreateResourceLimit64From32(Core::System& system, Handle* out_handle) {
R_RETURN(CreateResourceLimit(system, out_handle));
}
Result SetResourceLimitLimitValue64From32(Core::System& system, Handle resource_limit_handle,
LimitableResource which, int64_t limit_value) {
R_RETURN(SetResourceLimitLimitValue(system, resource_limit_handle, which, limit_value));
}
} // namespace Kernel::Svc

View File

@@ -1,6 +1,53 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h"
#include "core/hle/kernel/physical_core.h"
#include "core/hle/kernel/svc.h"
namespace Kernel::Svc {} // namespace Kernel::Svc
namespace Kernel::Svc {
void CallSecureMonitor(Core::System& system, lp64::SecureMonitorArguments* args) {
UNIMPLEMENTED();
}
void CallSecureMonitor64(Core::System& system, lp64::SecureMonitorArguments* args) {
CallSecureMonitor(system, args);
}
void CallSecureMonitor64From32(Core::System& system, ilp32::SecureMonitorArguments* args) {
// CallSecureMonitor64From32 is not supported.
UNIMPLEMENTED_MSG("CallSecureMonitor64From32");
}
// Custom ABI for CallSecureMonitor.
void SvcWrap_CallSecureMonitor64(Core::System& system) {
auto& core = system.CurrentPhysicalCore().ArmInterface();
lp64::SecureMonitorArguments args{};
for (int i = 0; i < 8; i++) {
args.r[i] = core.GetReg(i);
}
CallSecureMonitor64(system, &args);
for (int i = 0; i < 8; i++) {
core.SetReg(i, args.r[i]);
}
}
void SvcWrap_CallSecureMonitor64From32(Core::System& system) {
auto& core = system.CurrentPhysicalCore().ArmInterface();
ilp32::SecureMonitorArguments args{};
for (int i = 0; i < 8; i++) {
args.r[i] = static_cast<u32>(core.GetReg(i));
}
CallSecureMonitor64From32(system, &args);
for (int i = 0; i < 8; i++) {
core.SetReg(i, args.r[i]);
}
}
} // namespace Kernel::Svc

View File

@@ -90,14 +90,39 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien
} // namespace
Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, u32 is_light,
Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, bool is_light,
u64 name) {
if (is_light) {
// return CreateSession<KLightSession>(system, out_server, out_client, name);
return ResultUnknown;
return ResultNotImplemented;
} else {
return CreateSession<KSession>(system, out_server, out_client, name);
}
}
Result AcceptSession(Core::System& system, Handle* out_handle, Handle port_handle) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result CreateSession64(Core::System& system, Handle* out_server_session_handle,
Handle* out_client_session_handle, bool is_light, uint64_t name) {
R_RETURN(CreateSession(system, out_server_session_handle, out_client_session_handle, is_light,
name));
}
Result AcceptSession64(Core::System& system, Handle* out_handle, Handle port) {
R_RETURN(AcceptSession(system, out_handle, port));
}
Result CreateSession64From32(Core::System& system, Handle* out_server_session_handle,
Handle* out_client_session_handle, bool is_light, uint32_t name) {
R_RETURN(CreateSession(system, out_server_session_handle, out_client_session_handle, is_light,
name));
}
Result AcceptSession64From32(Core::System& system, Handle* out_handle, Handle port) {
R_RETURN(AcceptSession(system, out_handle, port));
}
} // namespace Kernel::Svc

View File

@@ -67,11 +67,6 @@ Result MapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address,
return ResultSuccess;
}
Result MapSharedMemory32(Core::System& system, Handle shmem_handle, u32 address, u32 size,
Svc::MemoryPermission map_perm) {
return MapSharedMemory(system, shmem_handle, address, size, map_perm);
}
Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, u64 size) {
// Validate the address/size.
R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress);
@@ -99,8 +94,40 @@ Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, VAddr addres
return ResultSuccess;
}
Result UnmapSharedMemory32(Core::System& system, Handle shmem_handle, u32 address, u32 size) {
return UnmapSharedMemory(system, shmem_handle, address, size);
Result CreateSharedMemory(Core::System& system, Handle* out_handle, uint64_t size,
MemoryPermission owner_perm, MemoryPermission remote_perm) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result MapSharedMemory64(Core::System& system, Handle shmem_handle, uint64_t address, uint64_t size,
MemoryPermission map_perm) {
R_RETURN(MapSharedMemory(system, shmem_handle, address, size, map_perm));
}
Result UnmapSharedMemory64(Core::System& system, Handle shmem_handle, uint64_t address,
uint64_t size) {
R_RETURN(UnmapSharedMemory(system, shmem_handle, address, size));
}
Result CreateSharedMemory64(Core::System& system, Handle* out_handle, uint64_t size,
MemoryPermission owner_perm, MemoryPermission remote_perm) {
R_RETURN(CreateSharedMemory(system, out_handle, size, owner_perm, remote_perm));
}
Result MapSharedMemory64From32(Core::System& system, Handle shmem_handle, uint32_t address,
uint32_t size, MemoryPermission map_perm) {
R_RETURN(MapSharedMemory(system, shmem_handle, address, size, map_perm));
}
Result UnmapSharedMemory64From32(Core::System& system, Handle shmem_handle, uint32_t address,
uint32_t size) {
R_RETURN(UnmapSharedMemory(system, shmem_handle, address, size));
}
Result CreateSharedMemory64From32(Core::System& system, Handle* out_handle, uint32_t size,
MemoryPermission owner_perm, MemoryPermission remote_perm) {
R_RETURN(CreateSharedMemory(system, out_handle, size, owner_perm, remote_perm));
}
} // namespace Kernel::Svc

View File

@@ -20,10 +20,6 @@ Result CloseHandle(Core::System& system, Handle handle) {
return ResultSuccess;
}
Result CloseHandle32(Core::System& system, Handle handle) {
return CloseHandle(system, handle);
}
/// Clears the signaled state of an event or process.
Result ResetSignal(Core::System& system, Handle handle) {
LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle);
@@ -52,10 +48,6 @@ Result ResetSignal(Core::System& system, Handle handle) {
return ResultInvalidHandle;
}
Result ResetSignal32(Core::System& system, Handle handle) {
return ResetSignal(system, handle);
}
/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
Result WaitSynchronization(Core::System& system, s32* index, VAddr handles_address, s32 num_handles,
s64 nano_seconds) {
@@ -93,12 +85,6 @@ Result WaitSynchronization(Core::System& system, s32* index, VAddr handles_addre
nano_seconds);
}
Result WaitSynchronization32(Core::System& system, u32 timeout_low, u32 handles_address,
s32 num_handles, u32 timeout_high, s32* index) {
const s64 nano_seconds{(static_cast<s64>(timeout_high) << 32) | static_cast<s64>(timeout_low)};
return WaitSynchronization(system, index, handles_address, num_handles, nano_seconds);
}
/// Resumes a thread waiting on WaitSynchronization
Result CancelSynchronization(Core::System& system, Handle handle) {
LOG_TRACE(Kernel_SVC, "called handle=0x{:X}", handle);
@@ -113,10 +99,6 @@ Result CancelSynchronization(Core::System& system, Handle handle) {
return ResultSuccess;
}
Result CancelSynchronization32(Core::System& system, Handle handle) {
return CancelSynchronization(system, handle);
}
void SynchronizePreemptionState(Core::System& system) {
auto& kernel = system.Kernel();
@@ -136,4 +118,46 @@ void SynchronizePreemptionState(Core::System& system) {
}
}
Result CloseHandle64(Core::System& system, Handle handle) {
R_RETURN(CloseHandle(system, handle));
}
Result ResetSignal64(Core::System& system, Handle handle) {
R_RETURN(ResetSignal(system, handle));
}
Result WaitSynchronization64(Core::System& system, int32_t* out_index, uint64_t handles,
int32_t num_handles, int64_t timeout_ns) {
R_RETURN(WaitSynchronization(system, out_index, handles, num_handles, timeout_ns));
}
Result CancelSynchronization64(Core::System& system, Handle handle) {
R_RETURN(CancelSynchronization(system, handle));
}
void SynchronizePreemptionState64(Core::System& system) {
SynchronizePreemptionState(system);
}
Result CloseHandle64From32(Core::System& system, Handle handle) {
R_RETURN(CloseHandle(system, handle));
}
Result ResetSignal64From32(Core::System& system, Handle handle) {
R_RETURN(ResetSignal(system, handle));
}
Result WaitSynchronization64From32(Core::System& system, int32_t* out_index, uint32_t handles,
int32_t num_handles, int64_t timeout_ns) {
R_RETURN(WaitSynchronization(system, out_index, handles, num_handles, timeout_ns));
}
Result CancelSynchronization64From32(Core::System& system, Handle handle) {
R_RETURN(CancelSynchronization(system, handle));
}
void SynchronizePreemptionState64From32(Core::System& system) {
SynchronizePreemptionState(system);
}
} // namespace Kernel::Svc

View File

@@ -20,7 +20,7 @@ constexpr bool IsValidVirtualCoreId(int32_t core_id) {
/// Creates a new thread
Result CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point, u64 arg,
VAddr stack_bottom, u32 priority, s32 core_id) {
VAddr stack_bottom, s32 priority, s32 core_id) {
LOG_DEBUG(Kernel_SVC,
"called entry_point=0x{:08X}, arg=0x{:08X}, stack_bottom=0x{:08X}, "
"priority=0x{:08X}, core_id=0x{:08X}",
@@ -91,11 +91,6 @@ Result CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point,
return ResultSuccess;
}
Result CreateThread32(Core::System& system, Handle* out_handle, u32 priority, u32 entry_point,
u32 arg, u32 stack_top, s32 processor_id) {
return CreateThread(system, out_handle, entry_point, arg, stack_top, priority, processor_id);
}
/// Starts the thread for the provided handle
Result StartThread(Core::System& system, Handle thread_handle) {
LOG_DEBUG(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
@@ -115,10 +110,6 @@ Result StartThread(Core::System& system, Handle thread_handle) {
return ResultSuccess;
}
Result StartThread32(Core::System& system, Handle thread_handle) {
return StartThread(system, thread_handle);
}
/// Called when a thread exits
void ExitThread(Core::System& system) {
LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC());
@@ -129,10 +120,6 @@ void ExitThread(Core::System& system) {
system.Kernel().UnregisterInUseObject(current_thread);
}
void ExitThread32(Core::System& system) {
ExitThread(system);
}
/// Sleep the current thread
void SleepThread(Core::System& system, s64 nanoseconds) {
auto& kernel = system.Kernel();
@@ -160,13 +147,8 @@ void SleepThread(Core::System& system, s64 nanoseconds) {
}
}
void SleepThread32(Core::System& system, u32 nanoseconds_low, u32 nanoseconds_high) {
const auto nanoseconds = static_cast<s64>(u64{nanoseconds_low} | (u64{nanoseconds_high} << 32));
SleepThread(system, nanoseconds);
}
/// Gets the thread context
Result GetThreadContext(Core::System& system, VAddr out_context, Handle thread_handle) {
Result GetThreadContext3(Core::System& system, VAddr out_context, Handle thread_handle) {
LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle=0x{:X}", out_context,
thread_handle);
@@ -223,12 +205,8 @@ Result GetThreadContext(Core::System& system, VAddr out_context, Handle thread_h
return ResultSuccess;
}
Result GetThreadContext32(Core::System& system, u32 out_context, Handle thread_handle) {
return GetThreadContext(system, out_context, thread_handle);
}
/// Gets the priority for the specified thread
Result GetThreadPriority(Core::System& system, u32* out_priority, Handle handle) {
Result GetThreadPriority(Core::System& system, s32* out_priority, Handle handle) {
LOG_TRACE(Kernel_SVC, "called");
// Get the thread from its handle.
@@ -241,12 +219,8 @@ Result GetThreadPriority(Core::System& system, u32* out_priority, Handle handle)
return ResultSuccess;
}
Result GetThreadPriority32(Core::System& system, u32* out_priority, Handle handle) {
return GetThreadPriority(system, out_priority, handle);
}
/// Sets the priority for the specified thread
Result SetThreadPriority(Core::System& system, Handle thread_handle, u32 priority) {
Result SetThreadPriority(Core::System& system, Handle thread_handle, s32 priority) {
// Get the current process.
KProcess& process = *system.Kernel().CurrentProcess();
@@ -264,12 +238,8 @@ Result SetThreadPriority(Core::System& system, Handle thread_handle, u32 priorit
return ResultSuccess;
}
Result SetThreadPriority32(Core::System& system, Handle thread_handle, u32 priority) {
return SetThreadPriority(system, thread_handle, priority);
}
Result GetThreadList(Core::System& system, u32* out_num_threads, VAddr out_thread_ids,
u32 out_thread_ids_size, Handle debug_handle) {
Result GetThreadList(Core::System& system, s32* out_num_threads, VAddr out_thread_ids,
s32 out_thread_ids_size, Handle debug_handle) {
// TODO: Handle this case when debug events are supported.
UNIMPLEMENTED_IF(debug_handle != InvalidHandle);
@@ -296,7 +266,7 @@ Result GetThreadList(Core::System& system, u32* out_num_threads, VAddr out_threa
auto& memory = system.Memory();
const auto& thread_list = current_process->GetThreadList();
const auto num_threads = thread_list.size();
const auto copy_amount = std::min(std::size_t{out_thread_ids_size}, num_threads);
const auto copy_amount = std::min(static_cast<std::size_t>(out_thread_ids_size), num_threads);
auto list_iter = thread_list.cbegin();
for (std::size_t i = 0; i < copy_amount; ++i, ++list_iter) {
@@ -308,8 +278,8 @@ Result GetThreadList(Core::System& system, u32* out_num_threads, VAddr out_threa
return ResultSuccess;
}
Result GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id,
u64* out_affinity_mask) {
Result GetThreadCoreMask(Core::System& system, s32* out_core_id, u64* out_affinity_mask,
Handle thread_handle) {
LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle);
// Get the thread from its handle.
@@ -323,15 +293,6 @@ Result GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_co
return ResultSuccess;
}
Result GetThreadCoreMask32(Core::System& system, Handle thread_handle, s32* out_core_id,
u32* out_affinity_mask_low, u32* out_affinity_mask_high) {
u64 out_affinity_mask{};
const auto result = GetThreadCoreMask(system, thread_handle, out_core_id, &out_affinity_mask);
*out_affinity_mask_high = static_cast<u32>(out_affinity_mask >> 32);
*out_affinity_mask_low = static_cast<u32>(out_affinity_mask);
return result;
}
Result SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id,
u64 affinity_mask) {
// Determine the core id/affinity mask.
@@ -364,12 +325,6 @@ Result SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id
return ResultSuccess;
}
Result SetThreadCoreMask32(Core::System& system, Handle thread_handle, s32 core_id,
u32 affinity_mask_low, u32 affinity_mask_high) {
const auto affinity_mask = u64{affinity_mask_low} | (u64{affinity_mask_high} << 32);
return SetThreadCoreMask(system, thread_handle, core_id, affinity_mask);
}
/// Get the ID for the specified thread.
Result GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle) {
// Get the thread from its handle.
@@ -382,15 +337,101 @@ Result GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handl
return ResultSuccess;
}
Result GetThreadId32(Core::System& system, u32* out_thread_id_low, u32* out_thread_id_high,
Handle thread_handle) {
u64 out_thread_id{};
const Result result{GetThreadId(system, &out_thread_id, thread_handle)};
Result CreateThread64(Core::System& system, Handle* out_handle, uint64_t func, uint64_t arg,
uint64_t stack_bottom, int32_t priority, int32_t core_id) {
R_RETURN(CreateThread(system, out_handle, func, arg, stack_bottom, priority, core_id));
}
*out_thread_id_low = static_cast<u32>(out_thread_id >> 32);
*out_thread_id_high = static_cast<u32>(out_thread_id & std::numeric_limits<u32>::max());
Result StartThread64(Core::System& system, Handle thread_handle) {
R_RETURN(StartThread(system, thread_handle));
}
return result;
void ExitThread64(Core::System& system) {
return ExitThread(system);
}
void SleepThread64(Core::System& system, int64_t ns) {
return SleepThread(system, ns);
}
Result GetThreadPriority64(Core::System& system, int32_t* out_priority, Handle thread_handle) {
R_RETURN(GetThreadPriority(system, out_priority, thread_handle));
}
Result SetThreadPriority64(Core::System& system, Handle thread_handle, int32_t priority) {
R_RETURN(SetThreadPriority(system, thread_handle, priority));
}
Result GetThreadCoreMask64(Core::System& system, int32_t* out_core_id, uint64_t* out_affinity_mask,
Handle thread_handle) {
R_RETURN(GetThreadCoreMask(system, out_core_id, out_affinity_mask, thread_handle));
}
Result SetThreadCoreMask64(Core::System& system, Handle thread_handle, int32_t core_id,
uint64_t affinity_mask) {
R_RETURN(SetThreadCoreMask(system, thread_handle, core_id, affinity_mask));
}
Result GetThreadId64(Core::System& system, uint64_t* out_thread_id, Handle thread_handle) {
R_RETURN(GetThreadId(system, out_thread_id, thread_handle));
}
Result GetThreadContext364(Core::System& system, uint64_t out_context, Handle thread_handle) {
R_RETURN(GetThreadContext3(system, out_context, thread_handle));
}
Result GetThreadList64(Core::System& system, int32_t* out_num_threads, uint64_t out_thread_ids,
int32_t max_out_count, Handle debug_handle) {
R_RETURN(GetThreadList(system, out_num_threads, out_thread_ids, max_out_count, debug_handle));
}
Result CreateThread64From32(Core::System& system, Handle* out_handle, uint32_t func, uint32_t arg,
uint32_t stack_bottom, int32_t priority, int32_t core_id) {
R_RETURN(CreateThread(system, out_handle, func, arg, stack_bottom, priority, core_id));
}
Result StartThread64From32(Core::System& system, Handle thread_handle) {
R_RETURN(StartThread(system, thread_handle));
}
void ExitThread64From32(Core::System& system) {
return ExitThread(system);
}
void SleepThread64From32(Core::System& system, int64_t ns) {
return SleepThread(system, ns);
}
Result GetThreadPriority64From32(Core::System& system, int32_t* out_priority,
Handle thread_handle) {
R_RETURN(GetThreadPriority(system, out_priority, thread_handle));
}
Result SetThreadPriority64From32(Core::System& system, Handle thread_handle, int32_t priority) {
R_RETURN(SetThreadPriority(system, thread_handle, priority));
}
Result GetThreadCoreMask64From32(Core::System& system, int32_t* out_core_id,
uint64_t* out_affinity_mask, Handle thread_handle) {
R_RETURN(GetThreadCoreMask(system, out_core_id, out_affinity_mask, thread_handle));
}
Result SetThreadCoreMask64From32(Core::System& system, Handle thread_handle, int32_t core_id,
uint64_t affinity_mask) {
R_RETURN(SetThreadCoreMask(system, thread_handle, core_id, affinity_mask));
}
Result GetThreadId64From32(Core::System& system, uint64_t* out_thread_id, Handle thread_handle) {
R_RETURN(GetThreadId(system, out_thread_id, thread_handle));
}
Result GetThreadContext364From32(Core::System& system, uint32_t out_context, Handle thread_handle) {
R_RETURN(GetThreadContext3(system, out_context, thread_handle));
}
Result GetThreadList64From32(Core::System& system, int32_t* out_num_threads,
uint32_t out_thread_ids, int32_t max_out_count, Handle debug_handle) {
R_RETURN(GetThreadList(system, out_num_threads, out_thread_ids, max_out_count, debug_handle));
}
} // namespace Kernel::Svc

View File

@@ -2,5 +2,59 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel::Svc {} // namespace Kernel::Svc
namespace Kernel::Svc {
Result GetDebugFutureThreadInfo(Core::System& system, lp64::LastThreadContext* out_context,
uint64_t* out_thread_id, Handle debug_handle, int64_t ns) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result GetLastThreadInfo(Core::System& system, lp64::LastThreadContext* out_context,
uint64_t* out_tls_address, uint32_t* out_flags) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result GetDebugFutureThreadInfo64(Core::System& system, lp64::LastThreadContext* out_context,
uint64_t* out_thread_id, Handle debug_handle, int64_t ns) {
R_RETURN(GetDebugFutureThreadInfo(system, out_context, out_thread_id, debug_handle, ns));
}
Result GetLastThreadInfo64(Core::System& system, lp64::LastThreadContext* out_context,
uint64_t* out_tls_address, uint32_t* out_flags) {
R_RETURN(GetLastThreadInfo(system, out_context, out_tls_address, out_flags));
}
Result GetDebugFutureThreadInfo64From32(Core::System& system, ilp32::LastThreadContext* out_context,
uint64_t* out_thread_id, Handle debug_handle, int64_t ns) {
lp64::LastThreadContext context{};
R_TRY(
GetDebugFutureThreadInfo(system, std::addressof(context), out_thread_id, debug_handle, ns));
*out_context = {
.fp = static_cast<u32>(context.fp),
.sp = static_cast<u32>(context.sp),
.lr = static_cast<u32>(context.lr),
.pc = static_cast<u32>(context.pc),
};
R_SUCCEED();
}
Result GetLastThreadInfo64From32(Core::System& system, ilp32::LastThreadContext* out_context,
uint64_t* out_tls_address, uint32_t* out_flags) {
lp64::LastThreadContext context{};
R_TRY(GetLastThreadInfo(system, std::addressof(context), out_tls_address, out_flags));
*out_context = {
.fp = static_cast<u32>(context.fp),
.sp = static_cast<u32>(context.sp),
.lr = static_cast<u32>(context.lr),
.pc = static_cast<u32>(context.pc),
};
R_SUCCEED();
}
} // namespace Kernel::Svc

View File

@@ -9,7 +9,7 @@
namespace Kernel::Svc {
/// This returns the total CPU ticks elapsed since the CPU was powered-on
u64 GetSystemTick(Core::System& system) {
int64_t GetSystemTick(Core::System& system) {
LOG_TRACE(Kernel_SVC, "called");
auto& core_timing = system.CoreTiming();
@@ -21,13 +21,15 @@ u64 GetSystemTick(Core::System& system) {
core_timing.AddTicks(400U);
}
return result;
return static_cast<int64_t>(result);
}
void GetSystemTick32(Core::System& system, u32* time_low, u32* time_high) {
const auto time = GetSystemTick(system);
*time_low = static_cast<u32>(time);
*time_high = static_cast<u32>(time >> 32);
int64_t GetSystemTick64(Core::System& system) {
return GetSystemTick(system);
}
int64_t GetSystemTick64From32(Core::System& system) {
return GetSystemTick(system);
}
} // namespace Kernel::Svc

View File

@@ -72,8 +72,46 @@ Result CreateTransferMemory(Core::System& system, Handle* out, VAddr address, u6
return ResultSuccess;
}
Result CreateTransferMemory32(Core::System& system, Handle* out, u32 address, u32 size,
MemoryPermission map_perm) {
return CreateTransferMemory(system, out, address, size, map_perm);
Result MapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t address, uint64_t size,
MemoryPermission owner_perm) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result UnmapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t address,
uint64_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result MapTransferMemory64(Core::System& system, Handle trmem_handle, uint64_t address,
uint64_t size, MemoryPermission owner_perm) {
R_RETURN(MapTransferMemory(system, trmem_handle, address, size, owner_perm));
}
Result UnmapTransferMemory64(Core::System& system, Handle trmem_handle, uint64_t address,
uint64_t size) {
R_RETURN(UnmapTransferMemory(system, trmem_handle, address, size));
}
Result CreateTransferMemory64(Core::System& system, Handle* out_handle, uint64_t address,
uint64_t size, MemoryPermission map_perm) {
R_RETURN(CreateTransferMemory(system, out_handle, address, size, map_perm));
}
Result MapTransferMemory64From32(Core::System& system, Handle trmem_handle, uint32_t address,
uint32_t size, MemoryPermission owner_perm) {
R_RETURN(MapTransferMemory(system, trmem_handle, address, size, owner_perm));
}
Result UnmapTransferMemory64From32(Core::System& system, Handle trmem_handle, uint32_t address,
uint32_t size) {
R_RETURN(UnmapTransferMemory(system, trmem_handle, address, size));
}
Result CreateTransferMemory64From32(Core::System& system, Handle* out_handle, uint32_t address,
uint32_t size, MemoryPermission map_perm) {
R_RETURN(CreateTransferMemory(system, out_handle, address, size, map_perm));
}
} // namespace Kernel::Svc

View File

@@ -0,0 +1,716 @@
# SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
# Raw SVC definitions from the kernel.
#
# Avoid modifying the prototypes; see below for how to customize generation
# for a given typename.
SVCS = [
[0x01, "Result SetHeapSize(Address* out_address, Size size);"],
[0x02, "Result SetMemoryPermission(Address address, Size size, MemoryPermission perm);"],
[0x03, "Result SetMemoryAttribute(Address address, Size size, uint32_t mask, uint32_t attr);"],
[0x04, "Result MapMemory(Address dst_address, Address src_address, Size size);"],
[0x05, "Result UnmapMemory(Address dst_address, Address src_address, Size size);"],
[0x06, "Result QueryMemory(Address out_memory_info, PageInfo* out_page_info, Address address);"],
[0x07, "void ExitProcess();"],
[0x08, "Result CreateThread(Handle* out_handle, ThreadFunc func, Address arg, Address stack_bottom, int32_t priority, int32_t core_id);"],
[0x09, "Result StartThread(Handle thread_handle);"],
[0x0A, "void ExitThread();"],
[0x0B, "void SleepThread(int64_t ns);"],
[0x0C, "Result GetThreadPriority(int32_t* out_priority, Handle thread_handle);"],
[0x0D, "Result SetThreadPriority(Handle thread_handle, int32_t priority);"],
[0x0E, "Result GetThreadCoreMask(int32_t* out_core_id, uint64_t* out_affinity_mask, Handle thread_handle);"],
[0x0F, "Result SetThreadCoreMask(Handle thread_handle, int32_t core_id, uint64_t affinity_mask);"],
[0x10, "int32_t GetCurrentProcessorNumber();"],
[0x11, "Result SignalEvent(Handle event_handle);"],
[0x12, "Result ClearEvent(Handle event_handle);"],
[0x13, "Result MapSharedMemory(Handle shmem_handle, Address address, Size size, MemoryPermission map_perm);"],
[0x14, "Result UnmapSharedMemory(Handle shmem_handle, Address address, Size size);"],
[0x15, "Result CreateTransferMemory(Handle* out_handle, Address address, Size size, MemoryPermission map_perm);"],
[0x16, "Result CloseHandle(Handle handle);"],
[0x17, "Result ResetSignal(Handle handle);"],
[0x18, "Result WaitSynchronization(int32_t* out_index, Address handles, int32_t num_handles, int64_t timeout_ns);"],
[0x19, "Result CancelSynchronization(Handle handle);"],
[0x1A, "Result ArbitrateLock(Handle thread_handle, Address address, uint32_t tag);"],
[0x1B, "Result ArbitrateUnlock(Address address);"],
[0x1C, "Result WaitProcessWideKeyAtomic(Address address, Address cv_key, uint32_t tag, int64_t timeout_ns);"],
[0x1D, "void SignalProcessWideKey(Address cv_key, int32_t count);"],
[0x1E, "int64_t GetSystemTick();"],
[0x1F, "Result ConnectToNamedPort(Handle* out_handle, Address name);"],
[0x20, "Result SendSyncRequestLight(Handle session_handle);"],
[0x21, "Result SendSyncRequest(Handle session_handle);"],
[0x22, "Result SendSyncRequestWithUserBuffer(Address message_buffer, Size message_buffer_size, Handle session_handle);"],
[0x23, "Result SendAsyncRequestWithUserBuffer(Handle* out_event_handle, Address message_buffer, Size message_buffer_size, Handle session_handle);"],
[0x24, "Result GetProcessId(uint64_t* out_process_id, Handle process_handle);"],
[0x25, "Result GetThreadId(uint64_t* out_thread_id, Handle thread_handle);"],
[0x26, "void Break(BreakReason break_reason, Address arg, Size size);"],
[0x27, "Result OutputDebugString(Address debug_str, Size len);"],
[0x28, "void ReturnFromException(Result result);"],
[0x29, "Result GetInfo(uint64_t* out, InfoType info_type, Handle handle, uint64_t info_subtype);"],
[0x2A, "void FlushEntireDataCache();"],
[0x2B, "Result FlushDataCache(Address address, Size size);"],
[0x2C, "Result MapPhysicalMemory(Address address, Size size);"],
[0x2D, "Result UnmapPhysicalMemory(Address address, Size size);"],
[0x2E, "Result GetDebugFutureThreadInfo(LastThreadContext* out_context, uint64_t* out_thread_id, Handle debug_handle, int64_t ns);"],
[0x2F, "Result GetLastThreadInfo(LastThreadContext* out_context, Address* out_tls_address, uint32_t* out_flags);"],
[0x30, "Result GetResourceLimitLimitValue(int64_t* out_limit_value, Handle resource_limit_handle, LimitableResource which);"],
[0x31, "Result GetResourceLimitCurrentValue(int64_t* out_current_value, Handle resource_limit_handle, LimitableResource which);"],
[0x32, "Result SetThreadActivity(Handle thread_handle, ThreadActivity thread_activity);"],
[0x33, "Result GetThreadContext3(Address out_context, Handle thread_handle);"],
[0x34, "Result WaitForAddress(Address address, ArbitrationType arb_type, int32_t value, int64_t timeout_ns);"],
[0x35, "Result SignalToAddress(Address address, SignalType signal_type, int32_t value, int32_t count);"],
[0x36, "void SynchronizePreemptionState();"],
[0x37, "Result GetResourceLimitPeakValue(int64_t* out_peak_value, Handle resource_limit_handle, LimitableResource which);"],
[0x39, "Result CreateIoPool(Handle* out_handle, IoPoolType which);"],
[0x3A, "Result CreateIoRegion(Handle* out_handle, Handle io_pool, PhysicalAddress physical_address, Size size, MemoryMapping mapping, MemoryPermission perm);"],
[0x3C, "void KernelDebug(KernelDebugType kern_debug_type, uint64_t arg0, uint64_t arg1, uint64_t arg2);"],
[0x3D, "void ChangeKernelTraceState(KernelTraceState kern_trace_state);"],
[0x40, "Result CreateSession(Handle* out_server_session_handle, Handle* out_client_session_handle, bool is_light, Address name);"],
[0x41, "Result AcceptSession(Handle* out_handle, Handle port);"],
[0x42, "Result ReplyAndReceiveLight(Handle handle);"],
[0x43, "Result ReplyAndReceive(int32_t* out_index, Address handles, int32_t num_handles, Handle reply_target, int64_t timeout_ns);"],
[0x44, "Result ReplyAndReceiveWithUserBuffer(int32_t* out_index, Address message_buffer, Size message_buffer_size, Address handles, int32_t num_handles, Handle reply_target, int64_t timeout_ns);"],
[0x45, "Result CreateEvent(Handle* out_write_handle, Handle* out_read_handle);"],
[0x46, "Result MapIoRegion(Handle io_region, Address address, Size size, MemoryPermission perm);"],
[0x47, "Result UnmapIoRegion(Handle io_region, Address address, Size size);"],
[0x48, "Result MapPhysicalMemoryUnsafe(Address address, Size size);"],
[0x49, "Result UnmapPhysicalMemoryUnsafe(Address address, Size size);"],
[0x4A, "Result SetUnsafeLimit(Size limit);"],
[0x4B, "Result CreateCodeMemory(Handle* out_handle, Address address, Size size);"],
[0x4C, "Result ControlCodeMemory(Handle code_memory_handle, CodeMemoryOperation operation, uint64_t address, uint64_t size, MemoryPermission perm);"],
[0x4D, "void SleepSystem();"],
[0x4E, "Result ReadWriteRegister(uint32_t* out_value, PhysicalAddress address, uint32_t mask, uint32_t value);"],
[0x4F, "Result SetProcessActivity(Handle process_handle, ProcessActivity process_activity);"],
[0x50, "Result CreateSharedMemory(Handle* out_handle, Size size, MemoryPermission owner_perm, MemoryPermission remote_perm);"],
[0x51, "Result MapTransferMemory(Handle trmem_handle, Address address, Size size, MemoryPermission owner_perm);"],
[0x52, "Result UnmapTransferMemory(Handle trmem_handle, Address address, Size size);"],
[0x53, "Result CreateInterruptEvent(Handle* out_read_handle, int32_t interrupt_id, InterruptType interrupt_type);"],
[0x54, "Result QueryPhysicalAddress(PhysicalMemoryInfo* out_info, Address address);"],
[0x55, "Result QueryIoMapping(Address* out_address, Size* out_size, PhysicalAddress physical_address, Size size);"],
[0x56, "Result CreateDeviceAddressSpace(Handle* out_handle, uint64_t das_address, uint64_t das_size);"],
[0x57, "Result AttachDeviceAddressSpace(DeviceName device_name, Handle das_handle);"],
[0x58, "Result DetachDeviceAddressSpace(DeviceName device_name, Handle das_handle);"],
[0x59, "Result MapDeviceAddressSpaceByForce(Handle das_handle, Handle process_handle, uint64_t process_address, Size size, uint64_t device_address, uint32_t option);"],
[0x5A, "Result MapDeviceAddressSpaceAligned(Handle das_handle, Handle process_handle, uint64_t process_address, Size size, uint64_t device_address, uint32_t option);"],
[0x5C, "Result UnmapDeviceAddressSpace(Handle das_handle, Handle process_handle, uint64_t process_address, Size size, uint64_t device_address);"],
[0x5D, "Result InvalidateProcessDataCache(Handle process_handle, uint64_t address, uint64_t size);"],
[0x5E, "Result StoreProcessDataCache(Handle process_handle, uint64_t address, uint64_t size);"],
[0x5F, "Result FlushProcessDataCache(Handle process_handle, uint64_t address, uint64_t size);"],
[0x60, "Result DebugActiveProcess(Handle* out_handle, uint64_t process_id);"],
[0x61, "Result BreakDebugProcess(Handle debug_handle);"],
[0x62, "Result TerminateDebugProcess(Handle debug_handle);"],
[0x63, "Result GetDebugEvent(Address out_info, Handle debug_handle);"],
[0x64, "Result ContinueDebugEvent(Handle debug_handle, uint32_t flags, Address thread_ids, int32_t num_thread_ids);"],
[0x65, "Result GetProcessList(int32_t* out_num_processes, Address out_process_ids, int32_t max_out_count);"],
[0x66, "Result GetThreadList(int32_t* out_num_threads, Address out_thread_ids, int32_t max_out_count, Handle debug_handle);"],
[0x67, "Result GetDebugThreadContext(Address out_context, Handle debug_handle, uint64_t thread_id, uint32_t context_flags);"],
[0x68, "Result SetDebugThreadContext(Handle debug_handle, uint64_t thread_id, Address context, uint32_t context_flags);"],
[0x69, "Result QueryDebugProcessMemory(Address out_memory_info, PageInfo* out_page_info, Handle process_handle, Address address);"],
[0x6A, "Result ReadDebugProcessMemory(Address buffer, Handle debug_handle, Address address, Size size);"],
[0x6B, "Result WriteDebugProcessMemory(Handle debug_handle, Address buffer, Address address, Size size);"],
[0x6C, "Result SetHardwareBreakPoint(HardwareBreakPointRegisterName name, uint64_t flags, uint64_t value);"],
[0x6D, "Result GetDebugThreadParam(uint64_t* out_64, uint32_t* out_32, Handle debug_handle, uint64_t thread_id, DebugThreadParam param);"],
[0x6F, "Result GetSystemInfo(uint64_t* out, SystemInfoType info_type, Handle handle, uint64_t info_subtype);"],
[0x70, "Result CreatePort(Handle* out_server_handle, Handle* out_client_handle, int32_t max_sessions, bool is_light, Address name);"],
[0x71, "Result ManageNamedPort(Handle* out_server_handle, Address name, int32_t max_sessions);"],
[0x72, "Result ConnectToPort(Handle* out_handle, Handle port);"],
[0x73, "Result SetProcessMemoryPermission(Handle process_handle, uint64_t address, uint64_t size, MemoryPermission perm);"],
[0x74, "Result MapProcessMemory(Address dst_address, Handle process_handle, uint64_t src_address, Size size);"],
[0x75, "Result UnmapProcessMemory(Address dst_address, Handle process_handle, uint64_t src_address, Size size);"],
[0x76, "Result QueryProcessMemory(Address out_memory_info, PageInfo* out_page_info, Handle process_handle, uint64_t address);"],
[0x77, "Result MapProcessCodeMemory(Handle process_handle, uint64_t dst_address, uint64_t src_address, uint64_t size);"],
[0x78, "Result UnmapProcessCodeMemory(Handle process_handle, uint64_t dst_address, uint64_t src_address, uint64_t size);"],
[0x79, "Result CreateProcess(Handle* out_handle, Address parameters, Address caps, int32_t num_caps);"],
[0x7A, "Result StartProcess(Handle process_handle, int32_t priority, int32_t core_id, uint64_t main_thread_stack_size);"],
[0x7B, "Result TerminateProcess(Handle process_handle);"],
[0x7C, "Result GetProcessInfo(int64_t* out_info, Handle process_handle, ProcessInfoType info_type);"],
[0x7D, "Result CreateResourceLimit(Handle* out_handle);"],
[0x7E, "Result SetResourceLimitLimitValue(Handle resource_limit_handle, LimitableResource which, int64_t limit_value);"],
[0x7F, "void CallSecureMonitor(SecureMonitorArguments args);"],
[0x90, "Result MapInsecureMemory(Address address, Size size);"],
[0x91, "Result UnmapInsecureMemory(Address address, Size size);"],
]
# These use a custom ABI, and therefore require custom wrappers
SKIP_WRAPPERS = {
0x20: "SendSyncRequestLight",
0x42: "ReplyAndReceiveLight",
0x7F: "CallSecureMonitor",
}
BIT_32 = 0
BIT_64 = 1
REG_SIZES = [4, 8]
SUFFIX_NAMES = ["64From32", "64"]
TYPE_SIZES = {
# SVC types
"ArbitrationType": 4,
"BreakReason": 4,
"CodeMemoryOperation": 4,
"DebugThreadParam": 4,
"DeviceName": 4,
"HardwareBreakPointRegisterName": 4,
"Handle": 4,
"InfoType": 4,
"InterruptType": 4,
"IoPoolType": 4,
"KernelDebugType": 4,
"KernelTraceState": 4,
"LimitableResource": 4,
"MemoryMapping": 4,
"MemoryPermission": 4,
"PageInfo": 4,
"ProcessActivity": 4,
"ProcessInfoType": 4,
"Result": 4,
"SignalType": 4,
"SystemInfoType": 4,
"ThreadActivity": 4,
# Arch-specific types
"ilp32::LastThreadContext": 16,
"ilp32::PhysicalMemoryInfo": 16,
"ilp32::SecureMonitorArguments": 32,
"lp64::LastThreadContext": 32,
"lp64::PhysicalMemoryInfo": 24,
"lp64::SecureMonitorArguments": 64,
# Generic types
"bool": 1,
"int32_t": 4,
"int64_t": 8,
"uint32_t": 4,
"uint64_t": 8,
"void": 0,
}
TYPE_REPLACEMENTS = {
"Address": ["uint32_t", "uint64_t"],
"LastThreadContext": ["ilp32::LastThreadContext", "lp64::LastThreadContext"],
"PhysicalAddress": ["uint64_t", "uint64_t"],
"PhysicalMemoryInfo": ["ilp32::PhysicalMemoryInfo", "lp64::PhysicalMemoryInfo"],
"SecureMonitorArguments": ["ilp32::SecureMonitorArguments", "lp64::SecureMonitorArguments"],
"Size": ["uint32_t", "uint64_t"],
"ThreadFunc": ["uint32_t", "uint64_t"],
}
# Statically verify that the hardcoded sizes match the intended
# sizes in C++.
def emit_size_check():
lines = []
for type, size in TYPE_SIZES.items():
if type != "void":
lines.append(f"static_assert(sizeof({type}) == {size});")
return "\n".join(lines)
# Replaces a type with an arch-specific one, if it exists.
def substitute_type(name, bitness):
if name in TYPE_REPLACEMENTS:
return TYPE_REPLACEMENTS[name][bitness]
else:
return name
class Argument:
def __init__(self, type_name, var_name, is_output, is_outptr, is_address):
self.type_name = type_name
self.var_name = var_name
self.is_output = is_output
self.is_outptr = is_outptr
self.is_address = is_address
# Parses C-style string declarations for SVCs.
def parse_declaration(declaration, bitness):
return_type, rest = declaration.split(" ", 1)
func_name, rest = rest.split("(", 1)
arg_names, rest = rest.split(")", 1)
argument_types = []
return_type = substitute_type(return_type, bitness)
assert return_type in TYPE_SIZES, f"Unknown type '{return_type}'"
if arg_names:
for arg_name in arg_names.split(", "):
type_name, var_name = arg_name.replace("*", "").split(" ", 1)
# All outputs must contain out_ in the name.
is_output = var_name == "out" or var_name.find("out_") != -1
# User-pointer outputs are not written to registers.
is_outptr = is_output and arg_name.find("*") == -1
# Special handling is performed for output addresses to avoid awkwardness
# in conversion for the 32-bit equivalents.
is_address = is_output and not is_outptr and \
type_name in ["Address", "Size"]
type_name = substitute_type(type_name, bitness)
assert type_name in TYPE_SIZES, f"Unknown type '{type_name}'"
argument_types.append(
Argument(type_name, var_name, is_output, is_outptr, is_address))
return (return_type, func_name, argument_types)
class RegisterAllocator:
def __init__(self, num_regs, byte_size, parameter_count):
self.registers = {}
self.num_regs = num_regs
self.byte_size = byte_size
self.parameter_count = parameter_count
# Mark the given register as allocated, for use in layout
# calculation if the NGRN exceeds the ABI parameter count.
def allocate(self, i):
assert i not in self.registers, f"Register R{i} already allocated"
self.registers[i] = True
return i
# Calculate the next available location for a register;
# the NGRN has exceeded the ABI parameter count.
def allocate_first_free(self):
for i in range(0, self.num_regs):
if i in self.registers:
continue
self.allocate(i)
return i
assert False, "No registers available"
# Add a single register at the given NGRN.
# If the index exceeds the ABI parameter count, try to find a
# location to add it. Returns the output location and increment.
def add_single(self, ngrn):
if ngrn >= self.parameter_count:
return (self.allocate_first_free(), 0)
else:
return (self.allocate(ngrn), 1)
# Add registers at the given NGRN for a data type of
# the given size. Returns the output locations and increment.
def add(self, ngrn, data_size, align=True):
if data_size <= self.byte_size:
r, i = self.add_single(ngrn)
return ([r], i)
regs = []
inc = ngrn % 2 if align else 0
remaining_size = data_size
while remaining_size > 0:
r, i = self.add_single(ngrn + inc)
regs.append(r)
inc += i
remaining_size -= self.byte_size
return (regs, inc)
def reg_alloc(bitness):
if bitness == 0:
# aapcs32: 4 4-byte registers
return RegisterAllocator(8, 4, 4)
elif bitness == 1:
# aapcs64: 8 8-byte registers
return RegisterAllocator(8, 8, 8)
# Converts a parsed SVC declaration into register lists for
# the return value, outputs, and inputs.
def get_registers(parse_result, bitness):
output_alloc = reg_alloc(bitness)
input_alloc = reg_alloc(bitness)
return_type, _, arguments = parse_result
return_write = []
output_writes = []
input_reads = []
input_ngrn = 0
output_ngrn = 0
# Run the input calculation.
for arg in arguments:
if arg.is_output and not arg.is_outptr:
input_ngrn += 1
continue
regs, increment = input_alloc.add(
input_ngrn, TYPE_SIZES[arg.type_name], align=True)
input_reads.append([arg.type_name, arg.var_name, regs])
input_ngrn += increment
# Include the return value if this SVC returns a value.
if return_type != "void":
regs, increment = output_alloc.add(
output_ngrn, TYPE_SIZES[return_type], align=False)
return_write.append([return_type, regs])
output_ngrn += increment
# Run the output calculation.
for arg in arguments:
if not arg.is_output or arg.is_outptr:
continue
regs, increment = output_alloc.add(
output_ngrn, TYPE_SIZES[arg.type_name], align=False)
output_writes.append(
[arg.type_name, arg.var_name, regs, arg.is_address])
output_ngrn += increment
return (return_write, output_writes, input_reads)
# Collects possibly multiple source registers into the named C++ value.
def emit_gather(sources, name, type_name, reg_size):
get_fn = f"GetReg{reg_size*8}"
if len(sources) == 1:
s, = sources
line = f"{name} = Convert<{type_name}>({get_fn}(system, {s}));"
return [line]
var_type = f"std::array<uint{reg_size*8}_t, {len(sources)}>"
lines = [
f"{var_type} {name}_gather{{}};"
]
for i in range(0, len(sources)):
lines.append(
f"{name}_gather[{i}] = {get_fn}(system, {sources[i]});")
lines.append(f"{name} = Convert<{type_name}>({name}_gather);")
return lines
# Produces one or more statements which assign the named C++ value
# into possibly multiple registers.
def emit_scatter(destinations, name, reg_size):
set_fn = f"SetReg{reg_size*8}"
reg_type = f"uint{reg_size*8}_t"
if len(destinations) == 1:
d, = destinations
line = f"{set_fn}(system, {d}, Convert<{reg_type}>({name}));"
return [line]
var_type = f"std::array<{reg_type}, {len(destinations)}>"
lines = [
f"auto {name}_scatter = Convert<{var_type}>({name});"
]
for i in range(0, len(destinations)):
lines.append(
f"{set_fn}(system, {destinations[i]}, {name}_scatter[{i}]);")
return lines
def emit_lines(lines, indent=' '):
output_lines = []
first = True
for line in lines:
if line and not first:
output_lines.append(indent + line)
else:
output_lines.append(line)
first = False
return "\n".join(output_lines)
# Emit a C++ function to wrap a guest SVC.
def emit_wrapper(wrapped_fn, suffix, register_info, arguments, byte_size):
return_write, output_writes, input_reads = register_info
lines = [
f"static void SvcWrap_{wrapped_fn}{suffix}(Core::System& system) {{"
]
# Get everything ready.
for return_type, _ in return_write:
lines.append(f"{return_type} ret{{}};")
if return_write:
lines.append("")
for output_type, var_name, _, is_address in output_writes:
output_type = "uintptr_t" if is_address else output_type
lines.append(f"{output_type} {var_name}{{}};")
for input_type, var_name, _ in input_reads:
lines.append(f"{input_type} {var_name}{{}};")
if output_writes or input_reads:
lines.append("")
for input_type, var_name, sources in input_reads:
lines += emit_gather(sources, var_name, input_type, byte_size)
if input_reads:
lines.append("")
# Build the call.
call_arguments = ["system"]
for arg in arguments:
if arg.is_output and not arg.is_outptr:
call_arguments.append(f"&{arg.var_name}")
else:
call_arguments.append(arg.var_name)
line = ""
if return_write:
line += "ret = "
line += f"{wrapped_fn}{suffix}({', '.join(call_arguments)});"
lines.append(line)
if return_write or output_writes:
lines.append("")
# Write back the return value and outputs.
for _, destinations in return_write:
lines += emit_scatter(destinations, "ret", byte_size)
for _, var_name, destinations, _ in output_writes:
lines += emit_scatter(destinations, var_name, byte_size)
# Finish.
return emit_lines(lines) + "\n}"
COPYRIGHT = """\
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
// This file is automatically generated using svc_generator.py.
"""
PROLOGUE_H = """
#pragma once
namespace Core {
class System;
}
#include "common/common_types.h"
#include "core/hle/kernel/svc_types.h"
#include "core/hle/result.h"
namespace Kernel::Svc {
// clang-format off
"""
EPILOGUE_H = """
// clang-format on
// Custom ABI.
Result ReplyAndReceiveLight(Core::System& system, Handle handle, uint32_t* args);
Result ReplyAndReceiveLight64From32(Core::System& system, Handle handle, uint32_t* args);
Result ReplyAndReceiveLight64(Core::System& system, Handle handle, uint32_t* args);
Result SendSyncRequestLight(Core::System& system, Handle session_handle, uint32_t* args);
Result SendSyncRequestLight64From32(Core::System& system, Handle session_handle, uint32_t* args);
Result SendSyncRequestLight64(Core::System& system, Handle session_handle, uint32_t* args);
void CallSecureMonitor(Core::System& system, lp64::SecureMonitorArguments* args);
void CallSecureMonitor64From32(Core::System& system, ilp32::SecureMonitorArguments* args);
void CallSecureMonitor64(Core::System& system, lp64::SecureMonitorArguments* args);
// Defined in svc_light_ipc.cpp.
void SvcWrap_ReplyAndReceiveLight64From32(Core::System& system);
void SvcWrap_ReplyAndReceiveLight64(Core::System& system);
void SvcWrap_SendSyncRequestLight64From32(Core::System& system);
void SvcWrap_SendSyncRequestLight64(Core::System& system);
// Defined in svc_secure_monitor_call.cpp.
void SvcWrap_CallSecureMonitor64From32(Core::System& system);
void SvcWrap_CallSecureMonitor64(Core::System& system);
// Perform a supervisor call by index.
void Call(Core::System& system, u32 imm);
} // namespace Kernel::Svc
"""
PROLOGUE_CPP = """
#include <type_traits>
#include "core/arm/arm_interface.h"
#include "core/core.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc.h"
namespace Kernel::Svc {
static uint32_t GetReg32(Core::System& system, int n) {
return static_cast<uint32_t>(system.CurrentArmInterface().GetReg(n));
}
static void SetReg32(Core::System& system, int n, uint32_t result) {
system.CurrentArmInterface().SetReg(n, static_cast<uint64_t>(result));
}
static uint64_t GetReg64(Core::System& system, int n) {
return system.CurrentArmInterface().GetReg(n);
}
static void SetReg64(Core::System& system, int n, uint64_t result) {
system.CurrentArmInterface().SetReg(n, result);
}
// Like bit_cast, but handles the case when the source and dest
// are differently-sized.
template <typename To, typename From>
requires(std::is_trivial_v<To> && std::is_trivially_copyable_v<From>)
static To Convert(const From& from) {
To to{};
if constexpr (sizeof(To) >= sizeof(From)) {
std::memcpy(&to, &from, sizeof(From));
} else {
std::memcpy(&to, &from, sizeof(To));
}
return to;
}
// clang-format off
"""
EPILOGUE_CPP = """
// clang-format on
void Call(Core::System& system, u32 imm) {
auto& kernel = system.Kernel();
kernel.EnterSVCProfile();
if (system.CurrentProcess()->Is64BitProcess()) {
Call64(system, imm);
} else {
Call32(system, imm);
}
kernel.ExitSVCProfile();
}
} // namespace Kernel::Svc
"""
def emit_call(bitness, names, suffix):
bit_size = REG_SIZES[bitness]*8
indent = " "
lines = [
f"static void Call{bit_size}(Core::System& system, u32 imm) {{",
f"{indent}switch (static_cast<SvcId>(imm)) {{"
]
for _, name in names:
lines.append(f"{indent}case SvcId::{name}:")
lines.append(f"{indent*2}return SvcWrap_{name}{suffix}(system);")
lines.append(f"{indent}default:")
lines.append(
f"{indent*2}LOG_CRITICAL(Kernel_SVC, \"Unknown SVC {{:x}}!\", imm);")
lines.append(f"{indent*2}break;")
lines.append(f"{indent}}}")
lines.append("}")
return "\n".join(lines)
def build_fn_declaration(return_type, name, arguments):
arg_list = ["Core::System& system"]
for arg in arguments:
type_name = "uintptr_t" if arg.is_address else arg.type_name
pointer = "*" if arg.is_output and not arg.is_outptr else ""
arg_list.append(f"{type_name}{pointer} {arg.var_name}")
return f"{return_type} {name}({', '.join(arg_list)});"
def build_enum_declarations():
lines = ["enum class SvcId : u32 {"]
indent = " "
for imm, decl in SVCS:
_, name, _ = parse_declaration(decl, BIT_64)
lines.append(f"{indent}{name} = {hex(imm)},")
lines.append("};")
return "\n".join(lines)
def main():
arch_fw_declarations = [[], []]
svc_fw_declarations = []
wrapper_fns = []
names = []
for imm, decl in SVCS:
return_type, name, arguments = parse_declaration(decl, BIT_64)
if imm not in SKIP_WRAPPERS:
svc_fw_declarations.append(
build_fn_declaration(return_type, name, arguments))
names.append([imm, name])
for bitness in range(2):
byte_size = REG_SIZES[bitness]
suffix = SUFFIX_NAMES[bitness]
for imm, decl in SVCS:
if imm in SKIP_WRAPPERS:
continue
parse_result = parse_declaration(decl, bitness)
return_type, name, arguments = parse_result
register_info = get_registers(parse_result, bitness)
wrapper_fns.append(
emit_wrapper(name, suffix, register_info, arguments, byte_size))
arch_fw_declarations[bitness].append(
build_fn_declaration(return_type, name + suffix, arguments))
call_32 = emit_call(BIT_32, names, SUFFIX_NAMES[BIT_32])
call_64 = emit_call(BIT_64, names, SUFFIX_NAMES[BIT_64])
enum_decls = build_enum_declarations()
with open("svc.h", "w") as f:
f.write(COPYRIGHT)
f.write(PROLOGUE_H)
f.write("\n".join(svc_fw_declarations))
f.write("\n\n")
f.write("\n".join(arch_fw_declarations[BIT_32]))
f.write("\n\n")
f.write("\n".join(arch_fw_declarations[BIT_64]))
f.write("\n\n")
f.write(enum_decls)
f.write(EPILOGUE_H)
with open("svc.cpp", "w") as f:
f.write(COPYRIGHT)
f.write(PROLOGUE_CPP)
f.write(emit_size_check())
f.write("\n\n")
f.write("\n\n".join(wrapper_fns))
f.write("\n\n")
f.write(call_32)
f.write("\n\n")
f.write(call_64)
f.write(EPILOGUE_CPP)
print(f"Done (emitted {len(names)} definitions)")
if __name__ == "__main__":
main()

View File

@@ -11,6 +11,7 @@ namespace Kernel {
constexpr Result ResultOutOfSessions{ErrorModule::Kernel, 7};
constexpr Result ResultInvalidArgument{ErrorModule::Kernel, 14};
constexpr Result ResultNotImplemented{ErrorModule::Kernel, 33};
constexpr Result ResultNoSynchronizationObject{ErrorModule::Kernel, 57};
constexpr Result ResultTerminationRequested{ErrorModule::Kernel, 59};
constexpr Result ResultInvalidSize{ErrorModule::Kernel, 101};

View File

@@ -168,6 +168,7 @@ enum class BreakReason : u32 {
NotificationOnlyFlag = 0x80000000,
};
DECLARE_ENUM_FLAG_OPERATORS(BreakReason);
enum class DebugEvent : u32 {
CreateProcess = 0,
@@ -596,6 +597,11 @@ enum class ProcessInfoType : u32 {
ProcessState = 0,
};
enum class ProcessActivity : u32 {
Runnable,
Paused,
};
struct CreateProcessParameter {
std::array<char, 12> name;
u32 version;
@@ -611,4 +617,9 @@ static_assert(sizeof(CreateProcessParameter) == 0x30);
constexpr size_t NumSupervisorCalls = 0xC0;
using SvcAccessFlagSet = std::bitset<NumSupervisorCalls>;
enum class InitialProcessIdRangeInfo : u64 {
Minimum = 0,
Maximum = 1,
};
} // namespace Kernel::Svc

View File

@@ -35,11 +35,11 @@ constexpr inline u32 EncodeKernelVersion(u32 major, u32 minor) {
}
constexpr inline u32 GetKernelMajorVersion(u32 encoded) {
return std::bit_cast<decltype(KernelVersion::major_version)>(encoded).Value();
return decltype(KernelVersion::major_version)::ExtractValue(encoded);
}
constexpr inline u32 GetKernelMinorVersion(u32 encoded) {
return std::bit_cast<decltype(KernelVersion::minor_version)>(encoded).Value();
return decltype(KernelVersion::minor_version)::ExtractValue(encoded);
}
// Nintendo doesn't support programs targeting SVC versions < 3.0.

View File

@@ -1,733 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_types.h"
#include "core/arm/arm_interface.h"
#include "core/core.h"
#include "core/hle/kernel/svc_types.h"
#include "core/hle/result.h"
#include "core/memory.h"
namespace Kernel {
static inline u64 Param(const Core::System& system, int n) {
return system.CurrentArmInterface().GetReg(n);
}
static inline u32 Param32(const Core::System& system, int n) {
return static_cast<u32>(system.CurrentArmInterface().GetReg(n));
}
/**
* HLE a function return from the current ARM userland process
* @param system System context
* @param result Result to return
*/
static inline void FuncReturn(Core::System& system, u64 result) {
system.CurrentArmInterface().SetReg(0, result);
}
static inline void FuncReturn32(Core::System& system, u32 result) {
system.CurrentArmInterface().SetReg(0, (u64)result);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Function wrappers that return type Result
template <Result func(Core::System&, u64)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, Param(system, 0)).raw);
}
template <Result func(Core::System&, u64, u64)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, Param(system, 0), Param(system, 1)).raw);
}
template <Result func(Core::System&, u32)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, static_cast<u32>(Param(system, 0))).raw);
}
template <Result func(Core::System&, u32, u32)>
void SvcWrap64(Core::System& system) {
FuncReturn(
system,
func(system, static_cast<u32>(Param(system, 0)), static_cast<u32>(Param(system, 1))).raw);
}
// Used by SetThreadActivity
template <Result func(Core::System&, Handle, Svc::ThreadActivity)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)),
static_cast<Svc::ThreadActivity>(Param(system, 1)))
.raw);
}
template <Result func(Core::System&, u32, u64, u64, u64)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1),
Param(system, 2), Param(system, 3))
.raw);
}
// Used by MapProcessMemory and UnmapProcessMemory
template <Result func(Core::System&, u64, u32, u64, u64)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1)),
Param(system, 2), Param(system, 3))
.raw);
}
// Used by ControlCodeMemory
template <Result func(Core::System&, Handle, u32, VAddr, size_t, Svc::MemoryPermission)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, static_cast<Handle>(Param(system, 0)),
static_cast<u32>(Param(system, 1)), Param(system, 2), Param(system, 3),
static_cast<Svc::MemoryPermission>(Param(system, 4)))
.raw);
}
template <Result func(Core::System&, u32*)>
void SvcWrap64(Core::System& system) {
u32 param = 0;
const u32 retval = func(system, &param).raw;
system.CurrentArmInterface().SetReg(1, param);
FuncReturn(system, retval);
}
template <Result func(Core::System&, u32*, u32)>
void SvcWrap64(Core::System& system) {
u32 param_1 = 0;
const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1))).raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
template <Result func(Core::System&, u32*, u32*)>
void SvcWrap64(Core::System& system) {
u32 param_1 = 0;
u32 param_2 = 0;
const u32 retval = func(system, &param_1, &param_2).raw;
auto& arm_interface = system.CurrentArmInterface();
arm_interface.SetReg(1, param_1);
arm_interface.SetReg(2, param_2);
FuncReturn(system, retval);
}
template <Result func(Core::System&, u32*, u64)>
void SvcWrap64(Core::System& system) {
u32 param_1 = 0;
const u32 retval = func(system, &param_1, Param(system, 1)).raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
template <Result func(Core::System&, u32*, u64, u32)>
void SvcWrap64(Core::System& system) {
u32 param_1 = 0;
const u32 retval =
func(system, &param_1, Param(system, 1), static_cast<u32>(Param(system, 2))).raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
template <Result func(Core::System&, u64*, u32)>
void SvcWrap64(Core::System& system) {
u64 param_1 = 0;
const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1))).raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
template <Result func(Core::System&, u64, u32)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1))).raw);
}
template <Result func(Core::System&, u64*, u64)>
void SvcWrap64(Core::System& system) {
u64 param_1 = 0;
const u32 retval = func(system, &param_1, Param(system, 1)).raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
template <Result func(Core::System&, u64*, u32, u32)>
void SvcWrap64(Core::System& system) {
u64 param_1 = 0;
const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1)),
static_cast<u32>(Param(system, 2)))
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
// Used by GetResourceLimitLimitValue.
template <Result func(Core::System&, u64*, Handle, Svc::LimitableResource)>
void SvcWrap64(Core::System& system) {
u64 param_1 = 0;
const u32 retval = func(system, &param_1, static_cast<Handle>(Param(system, 1)),
static_cast<Svc::LimitableResource>(Param(system, 2)))
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
template <Result func(Core::System&, u32, u64)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1)).raw);
}
// Used by SetResourceLimitLimitValue
template <Result func(Core::System&, Handle, Svc::LimitableResource, u64)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, static_cast<Handle>(Param(system, 0)),
static_cast<Svc::LimitableResource>(Param(system, 1)), Param(system, 2))
.raw);
}
// Used by SetThreadCoreMask
template <Result func(Core::System&, Handle, s32, u64)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)),
static_cast<s32>(Param(system, 1)), Param(system, 2))
.raw);
}
// Used by GetThreadCoreMask
template <Result func(Core::System&, Handle, s32*, u64*)>
void SvcWrap64(Core::System& system) {
s32 param_1 = 0;
u64 param_2 = 0;
const Result retval = func(system, static_cast<u32>(Param(system, 2)), &param_1, &param_2);
system.CurrentArmInterface().SetReg(1, param_1);
system.CurrentArmInterface().SetReg(2, param_2);
FuncReturn(system, retval.raw);
}
template <Result func(Core::System&, u64, u64, u32, u32)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
static_cast<u32>(Param(system, 2)), static_cast<u32>(Param(system, 3)))
.raw);
}
template <Result func(Core::System&, u64, u64, u32, u64)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
static_cast<u32>(Param(system, 2)), Param(system, 3))
.raw);
}
template <Result func(Core::System&, u32, u64, u32)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1),
static_cast<u32>(Param(system, 2)))
.raw);
}
template <Result func(Core::System&, u64, u64, u64)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, Param(system, 0), Param(system, 1), Param(system, 2)).raw);
}
template <Result func(Core::System&, u64, u64, u32)>
void SvcWrap64(Core::System& system) {
FuncReturn(
system,
func(system, Param(system, 0), Param(system, 1), static_cast<u32>(Param(system, 2))).raw);
}
// Used by SetMemoryPermission
template <Result func(Core::System&, u64, u64, Svc::MemoryPermission)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
static_cast<Svc::MemoryPermission>(Param(system, 2)))
.raw);
}
// Used by MapSharedMemory
template <Result func(Core::System&, Handle, u64, u64, Svc::MemoryPermission)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, static_cast<Handle>(Param(system, 0)), Param(system, 1),
Param(system, 2), static_cast<Svc::MemoryPermission>(Param(system, 3)))
.raw);
}
template <Result func(Core::System&, u32, u64, u64)>
void SvcWrap64(Core::System& system) {
FuncReturn(
system,
func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), Param(system, 2)).raw);
}
// Used by WaitSynchronization
template <Result func(Core::System&, s32*, u64, s32, s64)>
void SvcWrap64(Core::System& system) {
s32 param_1 = 0;
const u32 retval = func(system, &param_1, Param(system, 1), static_cast<s32>(Param(system, 2)),
static_cast<s64>(Param(system, 3)))
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
template <Result func(Core::System&, u64, u64, u32, s64)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
static_cast<u32>(Param(system, 2)), static_cast<s64>(Param(system, 3)))
.raw);
}
// Used by GetInfo
template <Result func(Core::System&, u64*, u64, Handle, u64)>
void SvcWrap64(Core::System& system) {
u64 param_1 = 0;
const u32 retval = func(system, &param_1, Param(system, 1),
static_cast<Handle>(Param(system, 2)), Param(system, 3))
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
template <Result func(Core::System&, u32*, u64, u64, u64, u32, s32)>
void SvcWrap64(Core::System& system) {
u32 param_1 = 0;
const u32 retval = func(system, &param_1, Param(system, 1), Param(system, 2), Param(system, 3),
static_cast<u32>(Param(system, 4)), static_cast<s32>(Param(system, 5)))
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
// Used by CreateTransferMemory
template <Result func(Core::System&, Handle*, u64, u64, Svc::MemoryPermission)>
void SvcWrap64(Core::System& system) {
u32 param_1 = 0;
const u32 retval = func(system, &param_1, Param(system, 1), Param(system, 2),
static_cast<Svc::MemoryPermission>(Param(system, 3)))
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
// Used by CreateCodeMemory
template <Result func(Core::System&, Handle*, VAddr, size_t)>
void SvcWrap64(Core::System& system) {
u32 param_1 = 0;
const u32 retval = func(system, &param_1, Param(system, 1), Param(system, 2)).raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
template <Result func(Core::System&, Handle*, u64, u32, u32)>
void SvcWrap64(Core::System& system) {
u32 param_1 = 0;
const u32 retval = func(system, &param_1, Param(system, 1), static_cast<u32>(Param(system, 2)),
static_cast<u32>(Param(system, 3)))
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
// Used by CreateSession
template <Result func(Core::System&, Handle*, Handle*, u32, u64)>
void SvcWrap64(Core::System& system) {
Handle param_1 = 0;
Handle param_2 = 0;
const u32 retval = func(system, &param_1, &param_2, static_cast<u32>(Param(system, 2)),
static_cast<u32>(Param(system, 3)))
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
system.CurrentArmInterface().SetReg(2, param_2);
FuncReturn(system, retval);
}
// Used by ReplyAndReceive
template <Result func(Core::System&, s32*, Handle*, s32, Handle, s64)>
void SvcWrap64(Core::System& system) {
s32 param_1 = 0;
s32 num_handles = static_cast<s32>(Param(system, 2));
std::vector<Handle> handles(num_handles);
system.Memory().ReadBlock(Param(system, 1), handles.data(), num_handles * sizeof(Handle));
const u32 retval = func(system, &param_1, handles.data(), num_handles,
static_cast<s32>(Param(system, 3)), static_cast<s64>(Param(system, 4)))
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
// Used by WaitForAddress
template <Result func(Core::System&, u64, Svc::ArbitrationType, s32, s64)>
void SvcWrap64(Core::System& system) {
FuncReturn(system,
func(system, Param(system, 0), static_cast<Svc::ArbitrationType>(Param(system, 1)),
static_cast<s32>(Param(system, 2)), static_cast<s64>(Param(system, 3)))
.raw);
}
// Used by SignalToAddress
template <Result func(Core::System&, u64, Svc::SignalType, s32, s32)>
void SvcWrap64(Core::System& system) {
FuncReturn(system,
func(system, Param(system, 0), static_cast<Svc::SignalType>(Param(system, 1)),
static_cast<s32>(Param(system, 2)), static_cast<s32>(Param(system, 3)))
.raw);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Function wrappers that return type u32
template <u32 func(Core::System&)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Function wrappers that return type u64
template <u64 func(Core::System&)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Function wrappers that return type void
template <void func(Core::System&)>
void SvcWrap64(Core::System& system) {
func(system);
}
template <void func(Core::System&, u32)>
void SvcWrap64(Core::System& system) {
func(system, static_cast<u32>(Param(system, 0)));
}
template <void func(Core::System&, u32, u64, u64, u64)>
void SvcWrap64(Core::System& system) {
func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), Param(system, 2),
Param(system, 3));
}
template <void func(Core::System&, s64)>
void SvcWrap64(Core::System& system) {
func(system, static_cast<s64>(Param(system, 0)));
}
template <void func(Core::System&, u64, s32)>
void SvcWrap64(Core::System& system) {
func(system, Param(system, 0), static_cast<s32>(Param(system, 1)));
}
template <void func(Core::System&, u64, u64)>
void SvcWrap64(Core::System& system) {
func(system, Param(system, 0), Param(system, 1));
}
template <void func(Core::System&, u64, u64, u64)>
void SvcWrap64(Core::System& system) {
func(system, Param(system, 0), Param(system, 1), Param(system, 2));
}
template <void func(Core::System&, u32, u64, u64)>
void SvcWrap64(Core::System& system) {
func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), Param(system, 2));
}
// Used by QueryMemory32, ArbitrateLock32
template <Result func(Core::System&, u32, u32, u32)>
void SvcWrap32(Core::System& system) {
FuncReturn32(system,
func(system, Param32(system, 0), Param32(system, 1), Param32(system, 2)).raw);
}
// Used by Break32
template <void func(Core::System&, u32, u32, u32)>
void SvcWrap32(Core::System& system) {
func(system, Param32(system, 0), Param32(system, 1), Param32(system, 2));
}
// Used by ExitProcess32, ExitThread32
template <void func(Core::System&)>
void SvcWrap32(Core::System& system) {
func(system);
}
// Used by GetCurrentProcessorNumber32
template <u32 func(Core::System&)>
void SvcWrap32(Core::System& system) {
FuncReturn32(system, func(system));
}
// Used by SleepThread32
template <void func(Core::System&, u32, u32)>
void SvcWrap32(Core::System& system) {
func(system, Param32(system, 0), Param32(system, 1));
}
// Used by CreateThread32
template <Result func(Core::System&, Handle*, u32, u32, u32, u32, s32)>
void SvcWrap32(Core::System& system) {
Handle param_1 = 0;
const u32 retval = func(system, &param_1, Param32(system, 0), Param32(system, 1),
Param32(system, 2), Param32(system, 3), Param32(system, 4))
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
// Used by GetInfo32
template <Result func(Core::System&, u32*, u32*, u32, u32, u32, u32)>
void SvcWrap32(Core::System& system) {
u32 param_1 = 0;
u32 param_2 = 0;
const u32 retval = func(system, &param_1, &param_2, Param32(system, 0), Param32(system, 1),
Param32(system, 2), Param32(system, 3))
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
system.CurrentArmInterface().SetReg(2, param_2);
FuncReturn(system, retval);
}
// Used by GetThreadPriority32, ConnectToNamedPort32
template <Result func(Core::System&, u32*, u32)>
void SvcWrap32(Core::System& system) {
u32 param_1 = 0;
const u32 retval = func(system, &param_1, Param32(system, 1)).raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
// Used by GetThreadId32
template <Result func(Core::System&, u32*, u32*, u32)>
void SvcWrap32(Core::System& system) {
u32 param_1 = 0;
u32 param_2 = 0;
const u32 retval = func(system, &param_1, &param_2, Param32(system, 1)).raw;
system.CurrentArmInterface().SetReg(1, param_1);
system.CurrentArmInterface().SetReg(2, param_2);
FuncReturn(system, retval);
}
// Used by GetSystemTick32
template <void func(Core::System&, u32*, u32*)>
void SvcWrap32(Core::System& system) {
u32 param_1 = 0;
u32 param_2 = 0;
func(system, &param_1, &param_2);
system.CurrentArmInterface().SetReg(0, param_1);
system.CurrentArmInterface().SetReg(1, param_2);
}
// Used by CreateEvent32
template <Result func(Core::System&, Handle*, Handle*)>
void SvcWrap32(Core::System& system) {
Handle param_1 = 0;
Handle param_2 = 0;
const u32 retval = func(system, &param_1, &param_2).raw;
system.CurrentArmInterface().SetReg(1, param_1);
system.CurrentArmInterface().SetReg(2, param_2);
FuncReturn(system, retval);
}
// Used by GetThreadId32
template <Result func(Core::System&, Handle, u32*, u32*, u32*)>
void SvcWrap32(Core::System& system) {
u32 param_1 = 0;
u32 param_2 = 0;
u32 param_3 = 0;
const u32 retval = func(system, Param32(system, 2), &param_1, &param_2, &param_3).raw;
system.CurrentArmInterface().SetReg(1, param_1);
system.CurrentArmInterface().SetReg(2, param_2);
system.CurrentArmInterface().SetReg(3, param_3);
FuncReturn(system, retval);
}
// Used by GetThreadCoreMask32
template <Result func(Core::System&, Handle, s32*, u32*, u32*)>
void SvcWrap32(Core::System& system) {
s32 param_1 = 0;
u32 param_2 = 0;
u32 param_3 = 0;
const u32 retval = func(system, Param32(system, 2), &param_1, &param_2, &param_3).raw;
system.CurrentArmInterface().SetReg(1, param_1);
system.CurrentArmInterface().SetReg(2, param_2);
system.CurrentArmInterface().SetReg(3, param_3);
FuncReturn(system, retval);
}
// Used by SignalProcessWideKey32
template <void func(Core::System&, u32, s32)>
void SvcWrap32(Core::System& system) {
func(system, static_cast<u32>(Param(system, 0)), static_cast<s32>(Param(system, 1)));
}
// Used by SetThreadActivity32
template <Result func(Core::System&, Handle, Svc::ThreadActivity)>
void SvcWrap32(Core::System& system) {
const u32 retval = func(system, static_cast<Handle>(Param(system, 0)),
static_cast<Svc::ThreadActivity>(Param(system, 1)))
.raw;
FuncReturn(system, retval);
}
// Used by SetThreadPriority32
template <Result func(Core::System&, Handle, u32)>
void SvcWrap32(Core::System& system) {
const u32 retval =
func(system, static_cast<Handle>(Param(system, 0)), static_cast<u32>(Param(system, 1))).raw;
FuncReturn(system, retval);
}
// Used by SetMemoryAttribute32
template <Result func(Core::System&, Handle, u32, u32, u32)>
void SvcWrap32(Core::System& system) {
const u32 retval =
func(system, static_cast<Handle>(Param(system, 0)), static_cast<u32>(Param(system, 1)),
static_cast<u32>(Param(system, 2)), static_cast<u32>(Param(system, 3)))
.raw;
FuncReturn(system, retval);
}
// Used by MapSharedMemory32
template <Result func(Core::System&, Handle, u32, u32, Svc::MemoryPermission)>
void SvcWrap32(Core::System& system) {
const u32 retval = func(system, static_cast<Handle>(Param(system, 0)),
static_cast<u32>(Param(system, 1)), static_cast<u32>(Param(system, 2)),
static_cast<Svc::MemoryPermission>(Param(system, 3)))
.raw;
FuncReturn(system, retval);
}
// Used by SetThreadCoreMask32
template <Result func(Core::System&, Handle, s32, u32, u32)>
void SvcWrap32(Core::System& system) {
const u32 retval =
func(system, static_cast<Handle>(Param(system, 0)), static_cast<s32>(Param(system, 1)),
static_cast<u32>(Param(system, 2)), static_cast<u32>(Param(system, 3)))
.raw;
FuncReturn(system, retval);
}
// Used by WaitProcessWideKeyAtomic32
template <Result func(Core::System&, u32, u32, Handle, u32, u32)>
void SvcWrap32(Core::System& system) {
const u32 retval =
func(system, static_cast<u32>(Param(system, 0)), static_cast<u32>(Param(system, 1)),
static_cast<Handle>(Param(system, 2)), static_cast<u32>(Param(system, 3)),
static_cast<u32>(Param(system, 4)))
.raw;
FuncReturn(system, retval);
}
// Used by WaitForAddress32
template <Result func(Core::System&, u32, Svc::ArbitrationType, s32, u32, u32)>
void SvcWrap32(Core::System& system) {
const u32 retval = func(system, static_cast<u32>(Param(system, 0)),
static_cast<Svc::ArbitrationType>(Param(system, 1)),
static_cast<s32>(Param(system, 2)), static_cast<u32>(Param(system, 3)),
static_cast<u32>(Param(system, 4)))
.raw;
FuncReturn(system, retval);
}
// Used by SignalToAddress32
template <Result func(Core::System&, u32, Svc::SignalType, s32, s32)>
void SvcWrap32(Core::System& system) {
const u32 retval = func(system, static_cast<u32>(Param(system, 0)),
static_cast<Svc::SignalType>(Param(system, 1)),
static_cast<s32>(Param(system, 2)), static_cast<s32>(Param(system, 3)))
.raw;
FuncReturn(system, retval);
}
// Used by SendSyncRequest32, ArbitrateUnlock32
template <Result func(Core::System&, u32)>
void SvcWrap32(Core::System& system) {
FuncReturn(system, func(system, static_cast<u32>(Param(system, 0))).raw);
}
// Used by CreateTransferMemory32
template <Result func(Core::System&, Handle*, u32, u32, Svc::MemoryPermission)>
void SvcWrap32(Core::System& system) {
Handle handle = 0;
const u32 retval = func(system, &handle, Param32(system, 1), Param32(system, 2),
static_cast<Svc::MemoryPermission>(Param32(system, 3)))
.raw;
system.CurrentArmInterface().SetReg(1, handle);
FuncReturn(system, retval);
}
// Used by WaitSynchronization32
template <Result func(Core::System&, u32, u32, s32, u32, s32*)>
void SvcWrap32(Core::System& system) {
s32 param_1 = 0;
const u32 retval = func(system, Param32(system, 0), Param32(system, 1), Param32(system, 2),
Param32(system, 3), &param_1)
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
// Used by CreateCodeMemory32
template <Result func(Core::System&, Handle*, u32, u32)>
void SvcWrap32(Core::System& system) {
Handle handle = 0;
const u32 retval = func(system, &handle, Param32(system, 1), Param32(system, 2)).raw;
system.CurrentArmInterface().SetReg(1, handle);
FuncReturn(system, retval);
}
// Used by ControlCodeMemory32
template <Result func(Core::System&, Handle, u32, u64, u64, Svc::MemoryPermission)>
void SvcWrap32(Core::System& system) {
const u32 retval =
func(system, Param32(system, 0), Param32(system, 1), Param(system, 2), Param(system, 4),
static_cast<Svc::MemoryPermission>(Param32(system, 6)))
.raw;
FuncReturn(system, retval);
}
// Used by Invalidate/Store/FlushProcessDataCache32
template <Result func(Core::System&, Handle, u64, u64)>
void SvcWrap32(Core::System& system) {
const u64 address = (Param(system, 3) << 32) | Param(system, 2);
const u64 size = (Param(system, 4) << 32) | Param(system, 1);
FuncReturn32(system, func(system, Param32(system, 0), address, size).raw);
}
} // namespace Kernel

View File

@@ -1570,7 +1570,7 @@ void IApplicationFunctions::GetDisplayVersion(Kernel::HLERequestContext& ctx) {
const auto& version = res.first->GetVersionString();
std::copy(version.begin(), version.end(), version_string.begin());
} else {
constexpr char default_version[]{"1.0.0"};
static constexpr char default_version[]{"1.0.0"};
std::memcpy(version_string.data(), default_version, sizeof(default_version));
}

View File

@@ -56,7 +56,7 @@ void Controller::SetPerformanceConfiguration(PerformanceMode mode,
}
void Controller::SetFromCpuBoostMode(CpuBoostMode mode) {
constexpr std::array<PerformanceConfiguration, 3> BOOST_MODE_TO_CONFIG_MAP{{
static constexpr std::array<PerformanceConfiguration, 3> BOOST_MODE_TO_CONFIG_MAP{{
PerformanceConfiguration::Config7,
PerformanceConfiguration::Config13,
PerformanceConfiguration::Config15,

View File

@@ -758,12 +758,20 @@ Core::HID::NpadStyleTag Controller_NPad::GetSupportedStyleSet() const {
return hid_core.GetSupportedStyleTag();
}
void Controller_NPad::SetSupportedNpadIdTypes(std::span<const u8> data) {
Result Controller_NPad::SetSupportedNpadIdTypes(std::span<const u8> data) {
constexpr std::size_t max_number_npad_ids = 0xa;
const auto length = data.size();
ASSERT(length > 0 && (length % sizeof(u32)) == 0);
const std::size_t elements = length / sizeof(u32);
if (elements > max_number_npad_ids) {
return InvalidArraySize;
}
supported_npad_id_types.clear();
supported_npad_id_types.resize(length / sizeof(u32));
supported_npad_id_types.resize(elements);
std::memcpy(supported_npad_id_types.data(), data.data(), length);
return ResultSuccess;
}
void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {
@@ -1124,7 +1132,8 @@ Result Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
return ResultSuccess;
}
Result Controller_NPad::SetGyroscopeZeroDriftMode(
const Core::HID::SixAxisSensorHandle& sixaxis_handle, GyroscopeZeroDriftMode drift_mode) {
const Core::HID::SixAxisSensorHandle& sixaxis_handle,
Core::HID::GyroscopeZeroDriftMode drift_mode) {
const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
@@ -1132,14 +1141,16 @@ Result Controller_NPad::SetGyroscopeZeroDriftMode(
}
auto& sixaxis = GetSixaxisState(sixaxis_handle);
auto& controller = GetControllerFromHandle(sixaxis_handle);
sixaxis.gyroscope_zero_drift_mode = drift_mode;
controller.device->SetGyroscopeZeroDriftMode(drift_mode);
return ResultSuccess;
}
Result Controller_NPad::GetGyroscopeZeroDriftMode(
const Core::HID::SixAxisSensorHandle& sixaxis_handle,
GyroscopeZeroDriftMode& drift_mode) const {
Core::HID::GyroscopeZeroDriftMode& drift_mode) const {
const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
if (is_valid.IsError()) {
LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);

View File

@@ -52,13 +52,6 @@ public:
// When the controller is requesting a motion update for the shared memory
void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) override;
// This is nn::hid::GyroscopeZeroDriftMode
enum class GyroscopeZeroDriftMode : u32 {
Loose = 0,
Standard = 1,
Tight = 2,
};
// This is nn::hid::NpadJoyHoldType
enum class NpadJoyHoldType : u64 {
Vertical = 0,
@@ -96,7 +89,7 @@ public:
void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
Core::HID::NpadStyleTag GetSupportedStyleSet() const;
void SetSupportedNpadIdTypes(std::span<const u8> data);
Result SetSupportedNpadIdTypes(std::span<const u8> data);
void GetSupportedNpadIdTypes(u32* data, std::size_t max_length);
std::size_t GetSupportedNpadIdTypesSize() const;
@@ -146,9 +139,9 @@ public:
Result DisconnectNpad(Core::HID::NpadIdType npad_id);
Result SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
GyroscopeZeroDriftMode drift_mode);
Core::HID::GyroscopeZeroDriftMode drift_mode);
Result GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
GyroscopeZeroDriftMode& drift_mode) const;
Core::HID::GyroscopeZeroDriftMode& drift_mode) const;
Result IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
bool& is_at_rest) const;
Result IsFirmwareUpdateAvailableForSixAxisSensor(
@@ -489,7 +482,8 @@ private:
Core::HID::SixAxisSensorFusionParameters fusion{};
Core::HID::SixAxisSensorCalibrationParameter calibration{};
Core::HID::SixAxisSensorIcInformation ic_information{};
GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard};
Core::HID::GyroscopeZeroDriftMode gyroscope_zero_drift_mode{
Core::HID::GyroscopeZeroDriftMode::Standard};
};
struct NpadControllerData {

View File

@@ -18,6 +18,7 @@ constexpr Result NpadIsDualJoycon{ErrorModule::HID, 601};
constexpr Result NpadIsSameType{ErrorModule::HID, 602};
constexpr Result InvalidNpadId{ErrorModule::HID, 709};
constexpr Result NpadNotConnected{ErrorModule::HID, 710};
constexpr Result InvalidArraySize{ErrorModule::HID, 715};
constexpr Result InvalidPalmaHandle{ErrorModule::HID, 3302};
} // namespace Service::HID

View File

@@ -712,7 +712,7 @@ void Hid::ResetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto sixaxis_handle{rp.PopRaw<Core::HID::SixAxisSensorHandle>()};
const auto drift_mode{rp.PopEnum<Controller_NPad::GyroscopeZeroDriftMode>()};
const auto drift_mode{rp.PopEnum<Core::HID::GyroscopeZeroDriftMode>()};
const auto applet_resource_user_id{rp.Pop<u64>()};
auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
@@ -739,7 +739,7 @@ void Hid::GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
auto drift_mode{Controller_NPad::GyroscopeZeroDriftMode::Standard};
auto drift_mode{Core::HID::GyroscopeZeroDriftMode::Standard};
auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
const auto result = controller.GetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode);
@@ -764,7 +764,7 @@ void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
const auto drift_mode{Controller_NPad::GyroscopeZeroDriftMode::Standard};
const auto drift_mode{Core::HID::GyroscopeZeroDriftMode::Standard};
auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
const auto result = controller.SetGyroscopeZeroDriftMode(parameters.sixaxis_handle, drift_mode);
@@ -1025,13 +1025,13 @@ void Hid::SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto applet_resource_user_id{rp.Pop<u64>()};
applet_resource->GetController<Controller_NPad>(HidController::NPad)
.SetSupportedNpadIdTypes(ctx.ReadBuffer());
const auto result = applet_resource->GetController<Controller_NPad>(HidController::NPad)
.SetSupportedNpadIdTypes(ctx.ReadBuffer());
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
rb.Push(result);
}
void Hid::ActivateNpad(Kernel::HLERequestContext& ctx) {

View File

@@ -124,7 +124,7 @@ private:
//!< value
};
constexpr static std::size_t SyncpointCount{192};
static constexpr std::size_t SyncpointCount{192};
std::array<SyncpointInfo, SyncpointCount> syncpoints{};
std::mutex reservation_lock;

View File

@@ -286,7 +286,7 @@ static constexpr int TransitionTime(int year, Rule rule, int offset) {
}
static bool ParsePosixName(const char* name, TimeZoneRule& rule) {
constexpr char default_rule[]{",M4.1.0,M10.5.0"};
static constexpr char default_rule[]{",M4.1.0,M10.5.0"};
const char* std_name{name};
int std_len{};
int offset{};

View File

@@ -34,7 +34,7 @@ static u64 GenerateTelemetryId() {
mbedtls_entropy_context entropy;
mbedtls_entropy_init(&entropy);
mbedtls_ctr_drbg_context ctr_drbg;
constexpr std::array<char, 18> personalization{{"yuzu Telemetry ID"}};
static constexpr std::array<char, 18> personalization{{"yuzu Telemetry ID"}};
mbedtls_ctr_drbg_init(&ctr_drbg);
ASSERT(mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,

View File

@@ -16,7 +16,7 @@ namespace InputCommon {
Joycons::Joycons(const std::string& input_engine_) : InputEngine(input_engine_) {
// Avoid conflicting with SDL driver
if (!Settings::values.enable_joycon_driver) {
if (!Settings::values.enable_joycon_driver && !Settings::values.enable_procon_driver) {
return;
}
LOG_INFO(Input, "Joycon driver Initialization started");
@@ -46,6 +46,12 @@ void Joycons::Reset() {
}
device->Stop();
}
for (const auto& device : pro_controller) {
if (!device) {
continue;
}
device->Stop();
}
SDL_hid_exit();
}
@@ -61,6 +67,11 @@ void Joycons::Setup() {
PreSetController(GetIdentifier(port, Joycon::ControllerType::Right));
device = std::make_shared<Joycon::JoyconDriver>(port++);
}
port = 0;
for (auto& device : pro_controller) {
PreSetController(GetIdentifier(port, Joycon::ControllerType::Pro));
device = std::make_shared<Joycon::JoyconDriver>(port++);
}
scan_thread = std::jthread([this](std::stop_token stop_token) { ScanThread(stop_token); });
}
@@ -116,6 +127,9 @@ bool Joycons::IsDeviceNew(SDL_hid_device_info* device_info) const {
// Check if device already exist
switch (type) {
case Joycon::ControllerType::Left:
if (!Settings::values.enable_joycon_driver) {
return false;
}
for (const auto& device : left_joycons) {
if (is_handle_identical(device)) {
return false;
@@ -123,12 +137,25 @@ bool Joycons::IsDeviceNew(SDL_hid_device_info* device_info) const {
}
break;
case Joycon::ControllerType::Right:
if (!Settings::values.enable_joycon_driver) {
return false;
}
for (const auto& device : right_joycons) {
if (is_handle_identical(device)) {
return false;
}
}
break;
case Joycon::ControllerType::Pro:
if (!Settings::values.enable_procon_driver) {
return false;
}
for (const auto& device : pro_controller) {
if (is_handle_identical(device)) {
return false;
}
}
break;
default:
return false;
}
@@ -199,6 +226,14 @@ std::shared_ptr<Joycon::JoyconDriver> Joycons::GetNextFreeHandle(
return *unconnected_device;
}
}
if (type == Joycon::ControllerType::Pro) {
const auto unconnected_device = std::ranges::find_if(
pro_controller, [](auto& device) { return !device->IsConnected(); });
if (unconnected_device != pro_controller.end()) {
return *unconnected_device;
}
}
return nullptr;
}
@@ -355,7 +390,7 @@ void Joycons::OnMotionUpdate(std::size_t port, Joycon::ControllerType type, int
void Joycons::OnRingConUpdate(f32 ring_data) {
// To simplify ring detection it will always be mapped to an empty identifier for all
// controllers
constexpr PadIdentifier identifier = {
static constexpr PadIdentifier identifier = {
.guid = Common::UUID{},
.port = 0,
.pad = 0,
@@ -409,6 +444,15 @@ std::shared_ptr<Joycon::JoyconDriver> Joycons::GetHandle(PadIdentifier identifie
}
}
if (type == Joycon::ControllerType::Pro) {
const auto matching_device = std::ranges::find_if(
pro_controller, [is_handle_active](auto& device) { return is_handle_active(device); });
if (matching_device != pro_controller.end()) {
return *matching_device;
}
}
return nullptr;
}
@@ -455,6 +499,9 @@ std::vector<Common::ParamPackage> Joycons::GetInputDevices() const {
for (const auto& controller : right_joycons) {
add_entry(controller);
}
for (const auto& controller : pro_controller) {
add_entry(controller);
}
// List dual joycon pairs
for (std::size_t i = 0; i < MaxSupportedControllers; i++) {

View File

@@ -106,6 +106,7 @@ private:
// Joycon types are split by type to ease supporting dualjoycon configurations
std::array<std::shared_ptr<Joycon::JoyconDriver>, MaxSupportedControllers> left_joycons{};
std::array<std::shared_ptr<Joycon::JoyconDriver>, MaxSupportedControllers> right_joycons{};
std::array<std::shared_ptr<Joycon::JoyconDriver>, MaxSupportedControllers> pro_controller{};
};
} // namespace InputCommon

View File

@@ -343,6 +343,14 @@ void SDLDriver::InitJoystick(int joystick_index) {
}
}
if (Settings::values.enable_procon_driver) {
if (guid.uuid[5] == 0x05 && guid.uuid[4] == 0x7e && guid.uuid[8] == 0x09) {
LOG_WARNING(Input, "Preferring joycon driver for device index {}", joystick_index);
SDL_JoystickClose(sdl_joystick);
return;
}
}
std::scoped_lock lock{joystick_map_mutex};
if (joystick_map.find(guid) == joystick_map.end()) {
auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_gamecontroller);
@@ -465,13 +473,19 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1");
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
// Disable hidapi drivers for switch controllers when the custom joycon driver is enabled
// Disable hidapi drivers for joycon controllers when the custom joycon driver is enabled
if (Settings::values.enable_joycon_driver) {
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "0");
} else {
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "1");
}
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "1");
// Disable hidapi drivers for pro controllers when the custom joycon driver is enabled
if (Settings::values.enable_procon_driver) {
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "0");
} else {
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "1");
}
// Disable hidapi driver for xbox. Already default on Windows, this causes conflict with native
// driver on Linux.
@@ -602,7 +616,7 @@ bool SDLDriver::IsVibrationEnabled(const PadIdentifier& identifier) {
const auto joystick =
GetSDLJoystickByGUID(identifier.guid.RawString(), static_cast<int>(identifier.port));
constexpr Common::Input::VibrationStatus test_vibration{
static constexpr Common::Input::VibrationStatus test_vibration{
.low_amplitude = 1,
.low_frequency = 160.0f,
.high_amplitude = 1,
@@ -610,7 +624,7 @@ bool SDLDriver::IsVibrationEnabled(const PadIdentifier& identifier) {
.type = Common::Input::VibrationAmplificationType::Exponential,
};
constexpr Common::Input::VibrationStatus zero_vibration{
static constexpr Common::Input::VibrationStatus zero_vibration{
.low_amplitude = 0,
.low_frequency = 160.0f,
.high_amplitude = 0,

View File

@@ -543,9 +543,10 @@ void JoyconDriver::SetCallbacks(const JoyconCallbacks& callbacks) {
DriverResult JoyconDriver::GetDeviceType(SDL_hid_device_info* device_info,
ControllerType& controller_type) {
static constexpr std::array<std::pair<u32, ControllerType>, 2> supported_devices{
static constexpr std::array<std::pair<u32, ControllerType>, 6> supported_devices{
std::pair<u32, ControllerType>{0x2006, ControllerType::Left},
{0x2007, ControllerType::Right},
{0x2009, ControllerType::Pro},
};
constexpr u16 nintendo_vendor_id = 0x057e;

View File

@@ -310,12 +310,6 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
if (runtime_info.force_early_z) {
header += "layout(early_fragment_tests)in;";
}
if (info.uses_sample_id) {
header += "in int gl_SampleID;";
}
if (info.stores_sample_mask) {
header += "out int gl_SampleMask[];";
}
break;
case Stage::Compute:
stage_name = "cs";

View File

@@ -538,7 +538,7 @@ TEST_CASE("BufferBase: Cached write downloads") {
int num = 0;
buffer.ForEachDownloadRangeAndClear(c, WORD, [&](u64 offset, u64 size) { ++num; });
buffer.ForEachUploadRange(c, WORD, [&](u64 offset, u64 size) { ++num; });
REQUIRE(num == 1);
REQUIRE(num == 0);
REQUIRE(!buffer.IsRegionCpuModified(c + PAGE, PAGE));
REQUIRE(!buffer.IsRegionGpuModified(c + PAGE, PAGE));
buffer.FlushCachedWrites();

View File

@@ -430,7 +430,7 @@ private:
if (query_begin >= SizeBytes() || size < 0) {
return;
}
[[maybe_unused]] u64* const untracked_words = Array<Type::Untracked>();
u64* const untracked_words = Array<Type::Untracked>();
u64* const state_words = Array<type>();
const u64 query_end = query_begin + std::min(static_cast<u64>(size), SizeBytes());
u64* const words_begin = state_words + query_begin / BYTES_PER_WORD;
@@ -483,7 +483,7 @@ private:
NotifyRasterizer<true>(word_index, current_bits, ~u64{0});
}
// Exclude CPU modified pages when visiting GPU pages
const u64 word = current_word;
const u64 word = current_word & ~(type == Type::GPU ? untracked_words[word_index] : 0);
u64 page = page_begin;
page_begin = 0;
@@ -531,7 +531,7 @@ private:
[[nodiscard]] bool IsRegionModified(u64 offset, u64 size) const noexcept {
static_assert(type != Type::Untracked);
[[maybe_unused]] const u64* const untracked_words = Array<Type::Untracked>();
const u64* const untracked_words = Array<Type::Untracked>();
const u64* const state_words = Array<type>();
const u64 num_query_words = size / BYTES_PER_WORD + 1;
const u64 word_begin = offset / BYTES_PER_WORD;
@@ -539,7 +539,8 @@ private:
const u64 page_limit = Common::DivCeil(offset + size, BYTES_PER_PAGE);
u64 page_index = (offset / BYTES_PER_PAGE) % PAGES_PER_WORD;
for (u64 word_index = word_begin; word_index < word_end; ++word_index, page_index = 0) {
const u64 word = state_words[word_index];
const u64 off_word = type == Type::GPU ? untracked_words[word_index] : 0;
const u64 word = state_words[word_index] & ~off_word;
if (word == 0) {
continue;
}
@@ -563,7 +564,7 @@ private:
[[nodiscard]] std::pair<u64, u64> ModifiedRegion(u64 offset, u64 size) const noexcept {
static_assert(type != Type::Untracked);
[[maybe_unused]] const u64* const untracked_words = Array<Type::Untracked>();
const u64* const untracked_words = Array<Type::Untracked>();
const u64* const state_words = Array<type>();
const u64 num_query_words = size / BYTES_PER_WORD + 1;
const u64 word_begin = offset / BYTES_PER_WORD;
@@ -573,7 +574,8 @@ private:
u64 begin = std::numeric_limits<u64>::max();
u64 end = 0;
for (u64 word_index = word_begin; word_index < word_end; ++word_index) {
const u64 word = state_words[word_index];
const u64 off_word = type == Type::GPU ? untracked_words[word_index] : 0;
const u64 word = state_words[word_index] & ~off_word;
if (word == 0) {
continue;
}

View File

@@ -258,7 +258,7 @@ u32 Maxwell3D::GetMaxCurrentVertices() {
size_t Maxwell3D::EstimateIndexBufferSize() {
GPUVAddr start_address = regs.index_buffer.StartAddress();
GPUVAddr end_address = regs.index_buffer.EndAddress();
constexpr std::array<size_t, 4> max_sizes = {
static constexpr std::array<size_t, 4> max_sizes = {
std::numeric_limits<u8>::max(), std::numeric_limits<u16>::max(),
std::numeric_limits<u32>::max(), std::numeric_limits<u32>::max()};
const size_t byte_size = regs.index_buffer.FormatSizeInBytes();

View File

@@ -99,7 +99,7 @@ struct GPU::Impl {
/// Signal the ending of command list.
void OnCommandListEnd() {
gpu_thread.OnCommandListEnd();
rasterizer->ReleaseFences();
}
/// Request a host GPU memory flush from the CPU.

View File

@@ -40,8 +40,6 @@ static void RunThread(std::stop_token stop_token, Core::System& system,
scheduler.Push(submit_list->channel, std::move(submit_list->entries));
} else if (const auto* data = std::get_if<SwapBuffersCommand>(&next.data)) {
renderer.SwapBuffers(data->framebuffer ? &*data->framebuffer : nullptr);
} else if (std::holds_alternative<OnCommandListEndCommand>(next.data)) {
rasterizer->ReleaseFences();
} else if (std::holds_alternative<GPUTickCommand>(next.data)) {
system.GPU().TickWork();
} else if (const auto* flush = std::get_if<FlushRegionCommand>(&next.data)) {
@@ -110,10 +108,6 @@ void ThreadManager::FlushAndInvalidateRegion(VAddr addr, u64 size) {
rasterizer->OnCPUWrite(addr, size);
}
void ThreadManager::OnCommandListEnd() {
PushCommand(OnCommandListEndCommand());
}
u64 ThreadManager::PushCommand(CommandData&& command_data, bool block) {
if (!is_async) {
// In synchronous GPU mode, block the caller until the command has executed

View File

@@ -77,16 +77,12 @@ struct FlushAndInvalidateRegionCommand final {
u64 size;
};
/// Command called within the gpu, to schedule actions after a command list end
struct OnCommandListEndCommand final {};
/// Command to make the gpu look into pending requests
struct GPUTickCommand final {};
using CommandData =
std::variant<std::monostate, SubmitListCommand, SwapBuffersCommand, FlushRegionCommand,
InvalidateRegionCommand, FlushAndInvalidateRegionCommand, OnCommandListEndCommand,
GPUTickCommand>;
InvalidateRegionCommand, FlushAndInvalidateRegionCommand, GPUTickCommand>;
struct CommandDataContainer {
CommandDataContainer() = default;
@@ -134,8 +130,6 @@ public:
/// Notify rasterizer that any caches of the specified region should be flushed and invalidated
void FlushAndInvalidateRegion(VAddr addr, u64 size);
void OnCommandListEnd();
void TickGPU();
private:

View File

@@ -189,9 +189,7 @@ void Vic::WriteYUVFrame(const AVFrame* frame, const VicConfig& config) {
for (std::size_t y = 0; y < frame_height; ++y) {
const std::size_t src = y * stride;
const std::size_t dst = y * aligned_width;
for (std::size_t x = 0; x < frame_width; ++x) {
luma_buffer[dst + x] = luma_src[src + x];
}
std::memcpy(luma_buffer.data() + dst, luma_src + src, frame_width);
}
host1x.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(),
luma_buffer.size());
@@ -205,15 +203,15 @@ void Vic::WriteYUVFrame(const AVFrame* frame, const VicConfig& config) {
// Frame from FFmpeg software
// Populate chroma buffer from both channels with interleaving.
const std::size_t half_width = frame_width / 2;
u8* chroma_buffer_data = chroma_buffer.data();
const u8* chroma_b_src = frame->data[1];
const u8* chroma_r_src = frame->data[2];
for (std::size_t y = 0; y < half_height; ++y) {
const std::size_t src = y * half_stride;
const std::size_t dst = y * aligned_width;
for (std::size_t x = 0; x < half_width; ++x) {
chroma_buffer[dst + x * 2] = chroma_b_src[src + x];
chroma_buffer[dst + x * 2 + 1] = chroma_r_src[src + x];
chroma_buffer_data[dst + x * 2] = chroma_b_src[src + x];
chroma_buffer_data[dst + x * 2 + 1] = chroma_r_src[src + x];
}
}
break;
@@ -225,9 +223,7 @@ void Vic::WriteYUVFrame(const AVFrame* frame, const VicConfig& config) {
for (std::size_t y = 0; y < half_height; ++y) {
const std::size_t src = y * stride;
const std::size_t dst = y * aligned_width;
for (std::size_t x = 0; x < frame_width; ++x) {
chroma_buffer[dst + x] = chroma_src[src + x];
}
std::memcpy(chroma_buffer.data() + dst, chroma_src + src, frame_width);
}
break;
}

View File

@@ -22,6 +22,8 @@ set(SHADER_FILES
convert_d24s8_to_abgr8.frag
convert_depth_to_float.frag
convert_float_to_depth.frag
convert_msaa_to_non_msaa.comp
convert_non_msaa_to_msaa.comp
convert_s8d24_to_abgr8.frag
full_screen_triangle.vert
fxaa.frag

View File

@@ -0,0 +1,30 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#version 450 core
layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
layout (binding = 0, rgba8) uniform readonly restrict image2DMSArray msaa_in;
layout (binding = 1, rgba8) uniform writeonly restrict image2DArray output_img;
void main() {
const ivec3 coords = ivec3(gl_GlobalInvocationID);
if (any(greaterThanEqual(coords, imageSize(msaa_in)))) {
return;
}
// TODO: Specialization constants for num_samples?
const int num_samples = imageSamples(msaa_in);
for (int curr_sample = 0; curr_sample < num_samples; ++curr_sample) {
const vec4 pixel = imageLoad(msaa_in, coords, curr_sample);
const int single_sample_x = 2 * coords.x + (curr_sample & 1);
const int single_sample_y = 2 * coords.y + ((curr_sample / 2) & 1);
const ivec3 dest_coords = ivec3(single_sample_x, single_sample_y, coords.z);
if (any(greaterThanEqual(dest_coords, imageSize(output_img)))) {
continue;
}
imageStore(output_img, dest_coords, pixel);
}
}

View File

@@ -0,0 +1,29 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#version 450 core
layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
layout (binding = 0, rgba8) uniform readonly restrict image2DArray img_in;
layout (binding = 1, rgba8) uniform writeonly restrict image2DMSArray output_msaa;
void main() {
const ivec3 coords = ivec3(gl_GlobalInvocationID);
if (any(greaterThanEqual(coords, imageSize(output_msaa)))) {
return;
}
// TODO: Specialization constants for num_samples?
const int num_samples = imageSamples(output_msaa);
for (int curr_sample = 0; curr_sample < num_samples; ++curr_sample) {
const int single_sample_x = 2 * coords.x + (curr_sample & 1);
const int single_sample_y = 2 * coords.y + ((curr_sample / 2) & 1);
const ivec3 single_coords = ivec3(single_sample_x, single_sample_y, coords.z);
if (any(greaterThanEqual(single_coords, imageSize(img_in)))) {
continue;
}
const vec4 pixel = imageLoad(img_in, single_coords);
imageStore(output_msaa, coords, curr_sample, pixel);
}
}

View File

@@ -216,7 +216,7 @@ private:
std::vector<u64> big_page_continous;
std::vector<std::pair<VAddr, std::size_t>> page_stash{};
constexpr static size_t continous_bits = 64;
static constexpr size_t continous_bits = 64;
const size_t unique_identifier;
std::unique_ptr<VideoCommon::InvalidationAccumulator> accumulator;

View File

@@ -557,6 +557,14 @@ void TextureCacheRuntime::CopyImage(Image& dst_image, Image& src_image,
}
}
void TextureCacheRuntime::CopyImageMSAA(Image& dst_image, Image& src_image,
std::span<const VideoCommon::ImageCopy> copies) {
LOG_DEBUG(Render_OpenGL, "Copying from {} samples to {} samples", src_image.info.num_samples,
dst_image.info.num_samples);
// TODO: Leverage the format conversion pass if possible/accurate.
util_shaders.CopyMSAA(dst_image, src_image, copies);
}
void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src,
std::span<const VideoCommon::ImageCopy> copies) {
LOG_DEBUG(Render_OpenGL, "Converting {} to {}", src.info.format, dst.info.format);

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