Compare commits
104 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
046c0c91a3 | ||
|
|
ca416a0fb8 | ||
|
|
9f9b64d280 | ||
|
|
c5b3c8d06b | ||
|
|
39c8d18feb | ||
|
|
d291fc1a51 | ||
|
|
4c348f4069 | ||
|
|
419a59a7b1 | ||
|
|
f250011ba0 | ||
|
|
e1600b0962 | ||
|
|
61b246a3a9 | ||
|
|
06e65de93c | ||
|
|
7a99226785 | ||
|
|
dffaffaac1 | ||
|
|
3446eb79b5 | ||
|
|
92adb69fa7 | ||
|
|
cd3e959f23 | ||
|
|
cc0dc3280d | ||
|
|
32b4627a9c | ||
|
|
e9b81e9f01 | ||
|
|
614bd0ee8c | ||
|
|
a54aee290f | ||
|
|
de4cadca1f | ||
|
|
a220d8799e | ||
|
|
2a24b1c973 | ||
|
|
182cf7d631 | ||
|
|
2f47b27654 | ||
|
|
283616dbd8 | ||
|
|
4d0ae1a17a | ||
|
|
f7808f5658 | ||
|
|
91bd2281bf | ||
|
|
7d287a6fb0 | ||
|
|
9a251339dc | ||
|
|
6380731486 | ||
|
|
1ba0b077fc | ||
|
|
cb56eaee41 | ||
|
|
3665a05488 | ||
|
|
392c1b96bc | ||
|
|
6ee1a784b8 | ||
|
|
d7843b8ef2 | ||
|
|
771a9c21cc | ||
|
|
385b5602e4 | ||
|
|
a1e3f6e27b | ||
|
|
09609dd50e | ||
|
|
2a82f1b08b | ||
|
|
02ea62568f | ||
|
|
ae6df703f5 | ||
|
|
ab88c2f611 | ||
|
|
2cbce77b92 | ||
|
|
9d665cb8db | ||
|
|
a8be822e8e | ||
|
|
e5a1e0a76d | ||
|
|
442096298e | ||
|
|
86e4aa81e9 | ||
|
|
fbb5ca2633 | ||
|
|
891090799c | ||
|
|
ad76b00f1e | ||
|
|
5c4e237902 | ||
|
|
3e4a0a13cb | ||
|
|
2978232390 | ||
|
|
03b574ae22 | ||
|
|
90c6141164 | ||
|
|
ca26fd0f42 | ||
|
|
dc83ca8914 | ||
|
|
4073931305 | ||
|
|
7c0908f301 | ||
|
|
966966dc02 | ||
|
|
8b4ecf22d4 | ||
|
|
111852a983 | ||
|
|
940d85241b | ||
|
|
4ed4bba305 | ||
|
|
e0f2db4376 | ||
|
|
4d4afc1502 | ||
|
|
f3a1bf53f9 | ||
|
|
2634e3c6eb | ||
|
|
3602df7f1f | ||
|
|
fa4294cc6f | ||
|
|
e3a615a616 | ||
|
|
d66b897a6d | ||
|
|
ddff03cff5 | ||
|
|
10e8acc451 | ||
|
|
77532ebde3 | ||
|
|
cd6f4f7eed | ||
|
|
8b0f334e0c | ||
|
|
c307ae2402 | ||
|
|
6d9661939f | ||
|
|
ffeb4ef83e | ||
|
|
b14d344dfc | ||
|
|
aa35e51fcd | ||
|
|
e107870bc8 | ||
|
|
f43a1da808 | ||
|
|
d264b7375c | ||
|
|
b8219ec838 | ||
|
|
0dc6967ff1 | ||
|
|
fcd0145eb5 | ||
|
|
2b863c9aa3 | ||
|
|
7a504a9365 | ||
|
|
4f5bbe56ba | ||
|
|
58b0ae84b5 | ||
|
|
c5e257017f | ||
|
|
b5784e9af2 | ||
|
|
4d4bbe756f | ||
|
|
1adf640d37 | ||
|
|
34635a42c0 |
@@ -9,6 +9,7 @@ stages:
|
||||
displayName: 'build'
|
||||
jobs:
|
||||
- job: build
|
||||
timeoutInMinutes: 120
|
||||
displayName: 'windows-msvc'
|
||||
pool:
|
||||
vmImage: windows-2019
|
||||
|
||||
4749
dist/languages/de.ts
vendored
Normal file
4749
dist/languages/de.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4757
dist/languages/es.ts
vendored
Normal file
4757
dist/languages/es.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4732
dist/languages/fr.ts
vendored
Normal file
4732
dist/languages/fr.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4724
dist/languages/it.ts
vendored
Normal file
4724
dist/languages/it.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4752
dist/languages/ja_JP.ts
vendored
Normal file
4752
dist/languages/ja_JP.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4719
dist/languages/nl.ts
vendored
Normal file
4719
dist/languages/nl.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4713
dist/languages/pl.ts
vendored
Normal file
4713
dist/languages/pl.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4757
dist/languages/pt_BR.ts
vendored
Normal file
4757
dist/languages/pt_BR.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4725
dist/languages/pt_PT.ts
vendored
Normal file
4725
dist/languages/pt_PT.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4720
dist/languages/ru_RU.ts
vendored
Normal file
4720
dist/languages/ru_RU.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4747
dist/languages/zh_CN.ts
vendored
Normal file
4747
dist/languages/zh_CN.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3
externals/CMakeLists.txt
vendored
3
externals/CMakeLists.txt
vendored
@@ -90,6 +90,9 @@ if (ENABLE_WEB_SERVICE)
|
||||
target_include_directories(httplib INTERFACE ./httplib)
|
||||
target_compile_definitions(httplib INTERFACE -DCPPHTTPLIB_OPENSSL_SUPPORT)
|
||||
target_link_libraries(httplib INTERFACE ${OPENSSL_LIBRARIES})
|
||||
if (WIN32)
|
||||
target_link_libraries(httplib INTERFACE crypt32 cryptui ws2_32)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Opus
|
||||
|
||||
4489
externals/httplib/httplib.h
vendored
4489
externals/httplib/httplib.h
vendored
File diff suppressed because it is too large
Load Diff
@@ -44,6 +44,19 @@ add_library(audio_core STATIC
|
||||
|
||||
create_target_directory_groups(audio_core)
|
||||
|
||||
if (NOT MSVC)
|
||||
target_compile_options(audio_core PRIVATE
|
||||
-Werror=conversion
|
||||
-Werror=ignored-qualifiers
|
||||
-Werror=implicit-fallthrough
|
||||
-Werror=reorder
|
||||
-Werror=sign-compare
|
||||
-Werror=unused-but-set-parameter
|
||||
-Werror=unused-but-set-variable
|
||||
-Werror=unused-variable
|
||||
)
|
||||
endif()
|
||||
|
||||
target_link_libraries(audio_core PUBLIC common core)
|
||||
target_link_libraries(audio_core PRIVATE SoundTouch)
|
||||
|
||||
|
||||
@@ -55,7 +55,8 @@ void Filter::Process(std::vector<s16>& signal) {
|
||||
/// @param total_count The total number of biquads to be cascaded.
|
||||
/// @param index 0-index of the biquad to calculate the Q value for.
|
||||
static double CascadingBiquadQ(std::size_t total_count, std::size_t index) {
|
||||
const double pole = M_PI * (2 * index + 1) / (4.0 * total_count);
|
||||
const auto pole =
|
||||
M_PI * static_cast<double>(2 * index + 1) / (4.0 * static_cast<double>(total_count));
|
||||
return 1.0 / (2.0 * std::cos(pole));
|
||||
}
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ std::vector<s16> Interpolate(InterpolationState& state, std::vector<s16> input,
|
||||
return {};
|
||||
|
||||
if (ratio <= 0) {
|
||||
LOG_CRITICAL(Audio, "Nonsensical interpolation ratio {}", ratio);
|
||||
LOG_ERROR(Audio, "Nonsensical interpolation ratio {}", ratio);
|
||||
return input;
|
||||
}
|
||||
|
||||
@@ -164,7 +164,8 @@ std::vector<s16> Interpolate(InterpolationState& state, std::vector<s16> input,
|
||||
const std::size_t num_frames{input.size() / 2};
|
||||
|
||||
std::vector<s16> output;
|
||||
output.reserve(static_cast<std::size_t>(input.size() / ratio + InterpolationState::taps));
|
||||
output.reserve(static_cast<std::size_t>(static_cast<double>(input.size()) / ratio +
|
||||
InterpolationState::taps));
|
||||
|
||||
for (std::size_t frame{}; frame < num_frames; ++frame) {
|
||||
const std::size_t lut_index{(state.fraction >> 8) * InterpolationState::taps};
|
||||
|
||||
@@ -3,16 +3,13 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <vector>
|
||||
#include "audio_core/algorithm/interpolate.h"
|
||||
|
||||
#include "audio_core/audio_out.h"
|
||||
#include "audio_core/audio_renderer.h"
|
||||
#include "audio_core/codec.h"
|
||||
#include "audio_core/common.h"
|
||||
#include "audio_core/info_updater.h"
|
||||
#include "audio_core/voice_context.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/writable_event.h"
|
||||
#include "core/memory.h"
|
||||
#include "core/settings.h"
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/swap.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
#include "core/hle/result.h"
|
||||
|
||||
namespace Core::Timing {
|
||||
|
||||
@@ -57,15 +57,15 @@ bool BehaviorInfo::IsLongSizePreDelaySupported() const {
|
||||
return AudioCommon::IsRevisionSupported(3, user_revision);
|
||||
}
|
||||
|
||||
bool BehaviorInfo::IsAudioRenererProcessingTimeLimit80PercentSupported() const {
|
||||
bool BehaviorInfo::IsAudioRendererProcessingTimeLimit80PercentSupported() const {
|
||||
return AudioCommon::IsRevisionSupported(5, user_revision);
|
||||
}
|
||||
|
||||
bool BehaviorInfo::IsAudioRenererProcessingTimeLimit75PercentSupported() const {
|
||||
bool BehaviorInfo::IsAudioRendererProcessingTimeLimit75PercentSupported() const {
|
||||
return AudioCommon::IsRevisionSupported(4, user_revision);
|
||||
}
|
||||
|
||||
bool BehaviorInfo::IsAudioRenererProcessingTimeLimit70PercentSupported() const {
|
||||
bool BehaviorInfo::IsAudioRendererProcessingTimeLimit70PercentSupported() const {
|
||||
return AudioCommon::IsRevisionSupported(1, user_revision);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,9 +49,9 @@ public:
|
||||
bool IsAdpcmLoopContextBugFixed() const;
|
||||
bool IsSplitterSupported() const;
|
||||
bool IsLongSizePreDelaySupported() const;
|
||||
bool IsAudioRenererProcessingTimeLimit80PercentSupported() const;
|
||||
bool IsAudioRenererProcessingTimeLimit75PercentSupported() const;
|
||||
bool IsAudioRenererProcessingTimeLimit70PercentSupported() const;
|
||||
bool IsAudioRendererProcessingTimeLimit80PercentSupported() const;
|
||||
bool IsAudioRendererProcessingTimeLimit75PercentSupported() const;
|
||||
bool IsAudioRendererProcessingTimeLimit70PercentSupported() const;
|
||||
bool IsElapsedFrameCountSupported() const;
|
||||
bool IsMemoryPoolForceMappingEnabled() const;
|
||||
bool IsFlushVoiceWaveBuffersSupported() const;
|
||||
|
||||
@@ -16,8 +16,9 @@ std::vector<s16> DecodeADPCM(const u8* const data, std::size_t size, const ADPCM
|
||||
|
||||
constexpr std::size_t FRAME_LEN = 8;
|
||||
constexpr std::size_t SAMPLES_PER_FRAME = 14;
|
||||
constexpr std::array<int, 16> SIGNED_NIBBLES = {
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1}};
|
||||
static constexpr std::array<int, 16> SIGNED_NIBBLES{
|
||||
0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1,
|
||||
};
|
||||
|
||||
const std::size_t sample_count = (size / FRAME_LEN) * SAMPLES_PER_FRAME;
|
||||
const std::size_t ret_size =
|
||||
|
||||
@@ -38,7 +38,7 @@ using ADPCM_Coeff = std::array<s16, 16>;
|
||||
* @param state ADPCM state, this is updated with new state
|
||||
* @return Decoded stereo signed PCM16 data, sample_count in length
|
||||
*/
|
||||
std::vector<s16> DecodeADPCM(const u8* const data, std::size_t size, const ADPCM_Coeff& coeff,
|
||||
std::vector<s16> DecodeADPCM(const u8* data, std::size_t size, const ADPCM_Coeff& coeff,
|
||||
ADPCMState& state);
|
||||
|
||||
}; // namespace AudioCore::Codec
|
||||
|
||||
@@ -152,7 +152,7 @@ void CommandGenerator::GenerateVoiceCommand(ServerVoiceInfo& voice_info) {
|
||||
if (!destination_data->IsConfigured()) {
|
||||
continue;
|
||||
}
|
||||
if (destination_data->GetMixId() >= mix_context.GetCount()) {
|
||||
if (destination_data->GetMixId() >= static_cast<int>(mix_context.GetCount())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -435,7 +435,7 @@ void CommandGenerator::GenerateAuxCommand(s32 mix_buffer_offset, EffectBase* inf
|
||||
GetMixBuffer(output_index), worker_params.sample_count, offset, write_count);
|
||||
memory.WriteBlock(aux->GetRecvInfo(), &recv_info, sizeof(AuxInfoDSP));
|
||||
|
||||
if (samples_read != worker_params.sample_count &&
|
||||
if (samples_read != static_cast<int>(worker_params.sample_count) &&
|
||||
samples_read <= params.sample_count) {
|
||||
std::memset(GetMixBuffer(output_index), 0, params.sample_count - samples_read);
|
||||
}
|
||||
@@ -611,7 +611,8 @@ void CommandGenerator::GenerateMixCommands(ServerMixInfo& mix_info) {
|
||||
const auto& dest_mix = mix_context.GetInfo(destination_data->GetMixId());
|
||||
const auto& dest_in_params = dest_mix.GetInParams();
|
||||
const auto mix_index = (base - 1) % in_params.buffer_count + in_params.buffer_offset;
|
||||
for (std::size_t i = 0; i < dest_in_params.buffer_count; i++) {
|
||||
for (std::size_t i = 0; i < static_cast<std::size_t>(dest_in_params.buffer_count);
|
||||
i++) {
|
||||
const auto mixed_volume = in_params.volume * destination_data->GetMixVolume(i);
|
||||
if (mixed_volume != 0.0f) {
|
||||
GenerateMixCommand(dest_in_params.buffer_offset + i, mix_index, mixed_volume,
|
||||
@@ -704,7 +705,7 @@ s32 CommandGenerator::DecodePcm16(ServerVoiceInfo& voice_info, VoiceState& dsp_s
|
||||
std::vector<s16> buffer(samples_processed * channel_count);
|
||||
memory.ReadBlock(buffer_pos, buffer.data(), buffer.size() * sizeof(s16));
|
||||
|
||||
for (std::size_t i = 0; i < samples_processed; i++) {
|
||||
for (std::size_t i = 0; i < static_cast<std::size_t>(samples_processed); i++) {
|
||||
sample_buffer[mix_offset + i] = buffer[i * channel_count + channel];
|
||||
}
|
||||
}
|
||||
@@ -726,8 +727,9 @@ s32 CommandGenerator::DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_s
|
||||
return 0;
|
||||
}
|
||||
|
||||
constexpr std::array<int, 16> SIGNED_NIBBLES = {
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1}};
|
||||
static constexpr std::array<int, 16> SIGNED_NIBBLES{
|
||||
0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1,
|
||||
};
|
||||
|
||||
constexpr std::size_t FRAME_LEN = 8;
|
||||
constexpr std::size_t NIBBLES_PER_SAMPLE = 16;
|
||||
@@ -789,9 +791,8 @@ s32 CommandGenerator::DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_s
|
||||
position_in_frame += 2;
|
||||
|
||||
// Decode entire frame
|
||||
if (remaining_samples >= SAMPLES_PER_FRAME) {
|
||||
if (remaining_samples >= static_cast<int>(SAMPLES_PER_FRAME)) {
|
||||
for (std::size_t i = 0; i < SAMPLES_PER_FRAME / 2; i++) {
|
||||
|
||||
// Sample 1
|
||||
const s32 s0 = SIGNED_NIBBLES[buffer[buffer_offset] >> 4];
|
||||
const s32 s1 = SIGNED_NIBBLES[buffer[buffer_offset++] & 0xf];
|
||||
@@ -800,7 +801,7 @@ s32 CommandGenerator::DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_s
|
||||
sample_buffer[cur_mix_offset++] = sample_1;
|
||||
sample_buffer[cur_mix_offset++] = sample_2;
|
||||
}
|
||||
remaining_samples -= SAMPLES_PER_FRAME;
|
||||
remaining_samples -= static_cast<int>(SAMPLES_PER_FRAME);
|
||||
position_in_frame += SAMPLES_PER_FRAME;
|
||||
continue;
|
||||
}
|
||||
@@ -866,7 +867,6 @@ void CommandGenerator::DecodeFromWaveBuffers(ServerVoiceInfo& voice_info, s32* o
|
||||
const auto resample_rate = static_cast<s32>(
|
||||
static_cast<float>(in_params.sample_rate) / static_cast<float>(target_sample_rate) *
|
||||
static_cast<float>(static_cast<s32>(in_params.pitch * 32768.0f)));
|
||||
auto* output_base = output;
|
||||
if (dsp_state.fraction + sample_count * resample_rate >
|
||||
static_cast<s32>(SCALED_MIX_BUFFER_SIZE - 4ULL)) {
|
||||
return;
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include <array>
|
||||
#include "audio_core/common.h"
|
||||
#include "audio_core/voice_context.h"
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Core::Memory {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/swap.h"
|
||||
|
||||
@@ -93,8 +93,10 @@ public:
|
||||
constexpr s32 clev{707}; // center mixing level coefficient
|
||||
constexpr s32 slev{707}; // surround mixing level coefficient
|
||||
|
||||
buf.push_back(left + (clev * center / 1000) + (slev * surround_left / 1000));
|
||||
buf.push_back(right + (clev * center / 1000) + (slev * surround_right / 1000));
|
||||
buf.push_back(static_cast<s16>(left + (clev * center / 1000) +
|
||||
(slev * surround_left / 1000)));
|
||||
buf.push_back(static_cast<s16>(right + (clev * center / 1000) +
|
||||
(slev * surround_right / 1000)));
|
||||
}
|
||||
queue.Push(buf);
|
||||
return;
|
||||
@@ -192,8 +194,8 @@ SinkStream& CubebSink::AcquireSinkStream(u32 sample_rate, u32 num_channels,
|
||||
|
||||
long CubebSinkStream::DataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer,
|
||||
void* output_buffer, long num_frames) {
|
||||
CubebSinkStream* impl = static_cast<CubebSinkStream*>(user_data);
|
||||
u8* buffer = reinterpret_cast<u8*>(output_buffer);
|
||||
auto* impl = static_cast<CubebSinkStream*>(user_data);
|
||||
auto* buffer = static_cast<u8*>(output_buffer);
|
||||
|
||||
if (!impl) {
|
||||
return {};
|
||||
|
||||
@@ -184,19 +184,19 @@ void EffectAuxInfo::UpdateForCommandGeneration() {
|
||||
}
|
||||
}
|
||||
|
||||
const VAddr EffectAuxInfo::GetSendInfo() const {
|
||||
VAddr EffectAuxInfo::GetSendInfo() const {
|
||||
return send_info;
|
||||
}
|
||||
|
||||
const VAddr EffectAuxInfo::GetSendBuffer() const {
|
||||
VAddr EffectAuxInfo::GetSendBuffer() const {
|
||||
return send_buffer;
|
||||
}
|
||||
|
||||
const VAddr EffectAuxInfo::GetRecvInfo() const {
|
||||
VAddr EffectAuxInfo::GetRecvInfo() const {
|
||||
return recv_info;
|
||||
}
|
||||
|
||||
const VAddr EffectAuxInfo::GetRecvBuffer() const {
|
||||
VAddr EffectAuxInfo::GetRecvBuffer() const {
|
||||
return recv_buffer;
|
||||
}
|
||||
|
||||
|
||||
@@ -166,13 +166,13 @@ public:
|
||||
std::array<u8, 0xa0> raw;
|
||||
};
|
||||
};
|
||||
static_assert(sizeof(EffectInfo::InParams) == 0xc0, "InParams is an invalid size");
|
||||
static_assert(sizeof(InParams) == 0xc0, "InParams is an invalid size");
|
||||
|
||||
struct OutParams {
|
||||
UsageStatus status{};
|
||||
INSERT_PADDING_BYTES(15);
|
||||
};
|
||||
static_assert(sizeof(EffectInfo::OutParams) == 0x10, "OutParams is an invalid size");
|
||||
static_assert(sizeof(OutParams) == 0x10, "OutParams is an invalid size");
|
||||
};
|
||||
|
||||
struct AuxAddress {
|
||||
@@ -184,8 +184,8 @@ struct AuxAddress {
|
||||
|
||||
class EffectBase {
|
||||
public:
|
||||
EffectBase(EffectType effect_type);
|
||||
~EffectBase();
|
||||
explicit EffectBase(EffectType effect_type);
|
||||
virtual ~EffectBase();
|
||||
|
||||
virtual void Update(EffectInfo::InParams& in_params) = 0;
|
||||
virtual void UpdateForCommandGeneration() = 0;
|
||||
@@ -206,8 +206,7 @@ protected:
|
||||
template <typename T>
|
||||
class EffectGeneric : public EffectBase {
|
||||
public:
|
||||
EffectGeneric(EffectType effect_type) : EffectBase::EffectBase(effect_type) {}
|
||||
~EffectGeneric() = default;
|
||||
explicit EffectGeneric(EffectType effect_type) : EffectBase(effect_type) {}
|
||||
|
||||
T& GetParams() {
|
||||
return internal_params;
|
||||
@@ -224,7 +223,7 @@ private:
|
||||
class EffectStubbed : public EffectBase {
|
||||
public:
|
||||
explicit EffectStubbed();
|
||||
~EffectStubbed();
|
||||
~EffectStubbed() override;
|
||||
|
||||
void Update(EffectInfo::InParams& in_params) override;
|
||||
void UpdateForCommandGeneration() override;
|
||||
@@ -233,7 +232,7 @@ public:
|
||||
class EffectI3dl2Reverb : public EffectGeneric<I3dl2ReverbParams> {
|
||||
public:
|
||||
explicit EffectI3dl2Reverb();
|
||||
~EffectI3dl2Reverb();
|
||||
~EffectI3dl2Reverb() override;
|
||||
|
||||
void Update(EffectInfo::InParams& in_params) override;
|
||||
void UpdateForCommandGeneration() override;
|
||||
@@ -245,7 +244,7 @@ private:
|
||||
class EffectBiquadFilter : public EffectGeneric<BiquadFilterParams> {
|
||||
public:
|
||||
explicit EffectBiquadFilter();
|
||||
~EffectBiquadFilter();
|
||||
~EffectBiquadFilter() override;
|
||||
|
||||
void Update(EffectInfo::InParams& in_params) override;
|
||||
void UpdateForCommandGeneration() override;
|
||||
@@ -254,14 +253,14 @@ public:
|
||||
class EffectAuxInfo : public EffectGeneric<AuxInfo> {
|
||||
public:
|
||||
explicit EffectAuxInfo();
|
||||
~EffectAuxInfo();
|
||||
~EffectAuxInfo() override;
|
||||
|
||||
void Update(EffectInfo::InParams& in_params) override;
|
||||
void UpdateForCommandGeneration() override;
|
||||
const VAddr GetSendInfo() const;
|
||||
const VAddr GetSendBuffer() const;
|
||||
const VAddr GetRecvInfo() const;
|
||||
const VAddr GetRecvBuffer() const;
|
||||
VAddr GetSendInfo() const;
|
||||
VAddr GetSendBuffer() const;
|
||||
VAddr GetRecvInfo() const;
|
||||
VAddr GetRecvBuffer() const;
|
||||
|
||||
private:
|
||||
VAddr send_info{};
|
||||
@@ -275,7 +274,7 @@ private:
|
||||
class EffectDelay : public EffectGeneric<DelayParams> {
|
||||
public:
|
||||
explicit EffectDelay();
|
||||
~EffectDelay();
|
||||
~EffectDelay() override;
|
||||
|
||||
void Update(EffectInfo::InParams& in_params) override;
|
||||
void UpdateForCommandGeneration() override;
|
||||
@@ -287,7 +286,7 @@ private:
|
||||
class EffectBufferMixer : public EffectGeneric<BufferMixerParams> {
|
||||
public:
|
||||
explicit EffectBufferMixer();
|
||||
~EffectBufferMixer();
|
||||
~EffectBufferMixer() override;
|
||||
|
||||
void Update(EffectInfo::InParams& in_params) override;
|
||||
void UpdateForCommandGeneration() override;
|
||||
@@ -296,7 +295,7 @@ public:
|
||||
class EffectReverb : public EffectGeneric<ReverbParams> {
|
||||
public:
|
||||
explicit EffectReverb();
|
||||
~EffectReverb();
|
||||
~EffectReverb() override;
|
||||
|
||||
void Update(EffectInfo::InParams& in_params) override;
|
||||
void UpdateForCommandGeneration() override;
|
||||
|
||||
@@ -64,7 +64,6 @@ bool InfoUpdater::UpdateBehaviorInfo(BehaviorInfo& in_behavior_info) {
|
||||
}
|
||||
|
||||
bool InfoUpdater::UpdateMemoryPools(std::vector<ServerMemoryPoolInfo>& memory_pool_info) {
|
||||
const auto force_mapping = behavior_info.IsMemoryPoolForceMappingEnabled();
|
||||
const auto memory_pool_count = memory_pool_info.size();
|
||||
const auto total_memory_pool_in = sizeof(ServerMemoryPoolInfo::InParams) * memory_pool_count;
|
||||
const auto total_memory_pool_out = sizeof(ServerMemoryPoolInfo::OutParams) * memory_pool_count;
|
||||
@@ -174,7 +173,7 @@ bool InfoUpdater::UpdateVoices(VoiceContext& voice_context,
|
||||
}
|
||||
// Voice states for each channel
|
||||
std::array<VoiceState*, AudioCommon::MAX_CHANNEL_COUNT> voice_states{};
|
||||
ASSERT(in_params.id < voice_count);
|
||||
ASSERT(static_cast<std::size_t>(in_params.id) < voice_count);
|
||||
|
||||
// Grab our current voice info
|
||||
auto& voice_info = voice_context.GetInfo(static_cast<std::size_t>(in_params.id));
|
||||
@@ -352,8 +351,8 @@ ResultCode InfoUpdater::UpdateMixes(MixContext& mix_context, std::size_t mix_buf
|
||||
for (std::size_t i = 0; i < mix_count; i++) {
|
||||
const auto& in = mix_in_params[i];
|
||||
total_buffer_count += in.buffer_count;
|
||||
if (in.dest_mix_id > mix_count && in.dest_mix_id != AudioCommon::NO_MIX &&
|
||||
in.mix_id != AudioCommon::FINAL_MIX) {
|
||||
if (static_cast<std::size_t>(in.dest_mix_id) > mix_count &&
|
||||
in.dest_mix_id != AudioCommon::NO_MIX && in.mix_id != AudioCommon::FINAL_MIX) {
|
||||
LOG_ERROR(
|
||||
Audio,
|
||||
"Invalid mix destination, mix_id={:X}, dest_mix_id={:X}, mix_buffer_count={:X}",
|
||||
|
||||
@@ -53,7 +53,7 @@ void MixContext::UpdateDistancesFromFinalMix() {
|
||||
auto mix_id = in_params.mix_id;
|
||||
// Needs to be referenced out of scope
|
||||
s32 distance_to_final_mix{AudioCommon::FINAL_MIX};
|
||||
for (; distance_to_final_mix < info_count; distance_to_final_mix++) {
|
||||
for (; distance_to_final_mix < static_cast<s32>(info_count); distance_to_final_mix++) {
|
||||
if (mix_id == AudioCommon::FINAL_MIX) {
|
||||
// If we're at the final mix, we're done
|
||||
break;
|
||||
@@ -77,7 +77,7 @@ void MixContext::UpdateDistancesFromFinalMix() {
|
||||
}
|
||||
|
||||
// If we're out of range for our distance, mark it as no final mix
|
||||
if (distance_to_final_mix >= info_count) {
|
||||
if (distance_to_final_mix >= static_cast<s32>(info_count)) {
|
||||
distance_to_final_mix = AudioCommon::NO_FINAL_MIX;
|
||||
}
|
||||
|
||||
|
||||
@@ -306,7 +306,7 @@ bool SplitterContext::UpdateInfo(const std::vector<u8>& input, std::size_t& inpu
|
||||
break;
|
||||
}
|
||||
|
||||
if (header.send_id < 0 || header.send_id > info_count) {
|
||||
if (header.send_id < 0 || static_cast<std::size_t>(header.send_id) > info_count) {
|
||||
LOG_ERROR(Audio, "Bad splitter data id");
|
||||
break;
|
||||
}
|
||||
@@ -348,7 +348,7 @@ bool SplitterContext::UpdateData(const std::vector<u8>& input, std::size_t& inpu
|
||||
break;
|
||||
}
|
||||
|
||||
if (header.splitter_id < 0 || header.splitter_id > data_count) {
|
||||
if (header.splitter_id < 0 || static_cast<std::size_t>(header.splitter_id) > data_count) {
|
||||
LOG_ERROR(Audio, "Bad splitter data id");
|
||||
break;
|
||||
}
|
||||
@@ -434,7 +434,7 @@ const std::vector<s32>& NodeStates::GetIndexList() const {
|
||||
}
|
||||
|
||||
void NodeStates::PushTsortResult(s32 index) {
|
||||
ASSERT(index < node_count);
|
||||
ASSERT(index < static_cast<s32>(node_count));
|
||||
index_list[index_pos++] = index;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core_timing_util.h"
|
||||
#include "core/settings.h"
|
||||
|
||||
namespace AudioCore {
|
||||
|
||||
@@ -128,7 +128,10 @@ void ServerVoiceInfo::UpdateParameters(const VoiceInfo::InParams& voice_in,
|
||||
in_params.wave_buffer_count = voice_in.wave_buffer_count;
|
||||
in_params.wave_bufffer_head = voice_in.wave_buffer_head;
|
||||
if (behavior_info.IsFlushVoiceWaveBuffersSupported()) {
|
||||
in_params.wave_buffer_flush_request_count += voice_in.wave_buffer_flush_request_count;
|
||||
const auto in_request_count = in_params.wave_buffer_flush_request_count;
|
||||
const auto voice_request_count = voice_in.wave_buffer_flush_request_count;
|
||||
in_params.wave_buffer_flush_request_count =
|
||||
static_cast<u8>(in_request_count + voice_request_count);
|
||||
}
|
||||
in_params.mix_id = voice_in.mix_id;
|
||||
if (behavior_info.IsSplitterSupported()) {
|
||||
@@ -488,11 +491,11 @@ s32 VoiceContext::DecodePcm16(s32* output_buffer, ServerWaveBuffer* wave_buffer,
|
||||
|
||||
// Fast path
|
||||
if (channel_count == 1) {
|
||||
for (std::size_t i = 0; i < samples_processed; i++) {
|
||||
for (std::ptrdiff_t i = 0; i < samples_processed; i++) {
|
||||
output_buffer[i] = buffer_data[i];
|
||||
}
|
||||
} else {
|
||||
for (std::size_t i = 0; i < samples_processed; i++) {
|
||||
for (std::ptrdiff_t i = 0; i < samples_processed; i++) {
|
||||
output_buffer[i] = buffer_data[i * channel_count + channel];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,4 +192,9 @@ create_target_directory_groups(common)
|
||||
find_package(Boost 1.71 COMPONENTS context headers REQUIRED)
|
||||
|
||||
target_link_libraries(common PUBLIC ${Boost_LIBRARIES} fmt::fmt microprofile)
|
||||
target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd xbyak)
|
||||
target_link_libraries(common PRIVATE lz4::lz4 xbyak)
|
||||
if (MSVC)
|
||||
target_link_libraries(common PRIVATE zstd::zstd)
|
||||
else()
|
||||
target_link_libraries(common PRIVATE zstd)
|
||||
endif()
|
||||
|
||||
@@ -16,14 +16,14 @@ namespace Common {
|
||||
|
||||
[[nodiscard]] constexpr u8 ToHexNibble(char c) {
|
||||
if (c >= 65 && c <= 70) {
|
||||
return c - 55;
|
||||
return static_cast<u8>(c - 55);
|
||||
}
|
||||
|
||||
if (c >= 97 && c <= 102) {
|
||||
return c - 87;
|
||||
return static_cast<u8>(c - 87);
|
||||
}
|
||||
|
||||
return c - 48;
|
||||
return static_cast<u8>(c - 48);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::vector<u8> HexStringToVector(std::string_view str, bool little_endian);
|
||||
@@ -33,11 +33,11 @@ template <std::size_t Size, bool le = false>
|
||||
std::array<u8, Size> out{};
|
||||
if constexpr (le) {
|
||||
for (std::size_t i = 2 * Size - 2; i <= 2 * Size; i -= 2) {
|
||||
out[i / 2] = (ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]);
|
||||
out[i / 2] = static_cast<u8>((ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]));
|
||||
}
|
||||
} else {
|
||||
for (std::size_t i = 0; i < 2 * Size; i += 2) {
|
||||
out[i / 2] = (ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]);
|
||||
out[i / 2] = static_cast<u8>((ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]));
|
||||
}
|
||||
}
|
||||
return out;
|
||||
|
||||
@@ -20,8 +20,8 @@ struct Rectangle {
|
||||
|
||||
constexpr Rectangle() = default;
|
||||
|
||||
constexpr Rectangle(T left, T top, T right, T bottom)
|
||||
: left(left), top(top), right(right), bottom(bottom) {}
|
||||
constexpr Rectangle(T left_, T top_, T right_, T bottom_)
|
||||
: left(left_), top(top_), right(right_), bottom(bottom_) {}
|
||||
|
||||
[[nodiscard]] T GetWidth() const {
|
||||
if constexpr (std::is_floating_point_v<T>) {
|
||||
|
||||
@@ -87,7 +87,13 @@ public:
|
||||
|
||||
template <typename V>
|
||||
[[nodiscard]] constexpr Vec2<decltype(T{} * V{})> operator*(const V& f) const {
|
||||
return {x * f, y * f};
|
||||
using TV = decltype(T{} * V{});
|
||||
using C = std::common_type_t<T, V>;
|
||||
|
||||
return {
|
||||
static_cast<TV>(static_cast<C>(x) * static_cast<C>(f)),
|
||||
static_cast<TV>(static_cast<C>(y) * static_cast<C>(f)),
|
||||
};
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
@@ -98,7 +104,13 @@ public:
|
||||
|
||||
template <typename V>
|
||||
[[nodiscard]] constexpr Vec2<decltype(T{} / V{})> operator/(const V& f) const {
|
||||
return {x / f, y / f};
|
||||
using TV = decltype(T{} / V{});
|
||||
using C = std::common_type_t<T, V>;
|
||||
|
||||
return {
|
||||
static_cast<TV>(static_cast<C>(x) / static_cast<C>(f)),
|
||||
static_cast<TV>(static_cast<C>(y) / static_cast<C>(f)),
|
||||
};
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
@@ -168,7 +180,10 @@ public:
|
||||
|
||||
template <typename T, typename V>
|
||||
[[nodiscard]] constexpr Vec2<T> operator*(const V& f, const Vec2<T>& vec) {
|
||||
return Vec2<T>(f * vec.x, f * vec.y);
|
||||
using C = std::common_type_t<T, V>;
|
||||
|
||||
return Vec2<T>(static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.x)),
|
||||
static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.y)));
|
||||
}
|
||||
|
||||
using Vec2f = Vec2<float>;
|
||||
@@ -237,7 +252,14 @@ public:
|
||||
|
||||
template <typename V>
|
||||
[[nodiscard]] constexpr Vec3<decltype(T{} * V{})> operator*(const V& f) const {
|
||||
return {x * f, y * f, z * f};
|
||||
using TV = decltype(T{} * V{});
|
||||
using C = std::common_type_t<T, V>;
|
||||
|
||||
return {
|
||||
static_cast<TV>(static_cast<C>(x) * static_cast<C>(f)),
|
||||
static_cast<TV>(static_cast<C>(y) * static_cast<C>(f)),
|
||||
static_cast<TV>(static_cast<C>(z) * static_cast<C>(f)),
|
||||
};
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
@@ -247,7 +269,14 @@ public:
|
||||
}
|
||||
template <typename V>
|
||||
[[nodiscard]] constexpr Vec3<decltype(T{} / V{})> operator/(const V& f) const {
|
||||
return {x / f, y / f, z / f};
|
||||
using TV = decltype(T{} / V{});
|
||||
using C = std::common_type_t<T, V>;
|
||||
|
||||
return {
|
||||
static_cast<TV>(static_cast<C>(x) / static_cast<C>(f)),
|
||||
static_cast<TV>(static_cast<C>(y) / static_cast<C>(f)),
|
||||
static_cast<TV>(static_cast<C>(z) / static_cast<C>(f)),
|
||||
};
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
@@ -367,7 +396,11 @@ public:
|
||||
|
||||
template <typename T, typename V>
|
||||
[[nodiscard]] constexpr Vec3<T> operator*(const V& f, const Vec3<T>& vec) {
|
||||
return Vec3<T>(f * vec.x, f * vec.y, f * vec.z);
|
||||
using C = std::common_type_t<T, V>;
|
||||
|
||||
return Vec3<T>(static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.x)),
|
||||
static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.y)),
|
||||
static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.z)));
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -446,7 +479,15 @@ public:
|
||||
|
||||
template <typename V>
|
||||
[[nodiscard]] constexpr Vec4<decltype(T{} * V{})> operator*(const V& f) const {
|
||||
return {x * f, y * f, z * f, w * f};
|
||||
using TV = decltype(T{} * V{});
|
||||
using C = std::common_type_t<T, V>;
|
||||
|
||||
return {
|
||||
static_cast<TV>(static_cast<C>(x) * static_cast<C>(f)),
|
||||
static_cast<TV>(static_cast<C>(y) * static_cast<C>(f)),
|
||||
static_cast<TV>(static_cast<C>(z) * static_cast<C>(f)),
|
||||
static_cast<TV>(static_cast<C>(w) * static_cast<C>(f)),
|
||||
};
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
@@ -457,7 +498,15 @@ public:
|
||||
|
||||
template <typename V>
|
||||
[[nodiscard]] constexpr Vec4<decltype(T{} / V{})> operator/(const V& f) const {
|
||||
return {x / f, y / f, z / f, w / f};
|
||||
using TV = decltype(T{} / V{});
|
||||
using C = std::common_type_t<T, V>;
|
||||
|
||||
return {
|
||||
static_cast<TV>(static_cast<C>(x) / static_cast<C>(f)),
|
||||
static_cast<TV>(static_cast<C>(y) / static_cast<C>(f)),
|
||||
static_cast<TV>(static_cast<C>(z) / static_cast<C>(f)),
|
||||
static_cast<TV>(static_cast<C>(w) / static_cast<C>(f)),
|
||||
};
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
@@ -582,7 +631,15 @@ public:
|
||||
|
||||
template <typename T, typename V>
|
||||
[[nodiscard]] constexpr Vec4<decltype(V{} * T{})> operator*(const V& f, const Vec4<T>& vec) {
|
||||
return {f * vec.x, f * vec.y, f * vec.z, f * vec.w};
|
||||
using TV = decltype(V{} * T{});
|
||||
using C = std::common_type_t<T, V>;
|
||||
|
||||
return {
|
||||
static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.x)),
|
||||
static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.y)),
|
||||
static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.z)),
|
||||
static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.w)),
|
||||
};
|
||||
}
|
||||
|
||||
using Vec4f = Vec4<float>;
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Common {
|
||||
using base_timer = std::chrono::steady_clock;
|
||||
using base_time_point = std::chrono::time_point<base_timer>;
|
||||
|
||||
class StandardWallClock : public WallClock {
|
||||
class StandardWallClock final : public WallClock {
|
||||
public:
|
||||
StandardWallClock(u64 emulated_cpu_frequency, u64 emulated_clock_frequency)
|
||||
: WallClock(emulated_cpu_frequency, emulated_clock_frequency, false) {
|
||||
|
||||
@@ -13,6 +13,8 @@ namespace Common {
|
||||
|
||||
class WallClock {
|
||||
public:
|
||||
virtual ~WallClock() = default;
|
||||
|
||||
/// Returns current wall time in nanoseconds
|
||||
[[nodiscard]] virtual std::chrono::nanoseconds GetTimeNS() = 0;
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
namespace Common {
|
||||
|
||||
namespace X64 {
|
||||
class NativeClock : public WallClock {
|
||||
class NativeClock final : public WallClock {
|
||||
public:
|
||||
NativeClock(u64 emulated_cpu_frequency, u64 emulated_clock_frequency, u64 rtsc_frequency);
|
||||
|
||||
|
||||
@@ -623,6 +623,17 @@ if (MSVC)
|
||||
# 'context' : truncation from 'type1' to 'type2'
|
||||
/we4305
|
||||
)
|
||||
else()
|
||||
target_compile_options(core PRIVATE
|
||||
-Werror=conversion
|
||||
-Werror=ignored-qualifiers
|
||||
-Werror=implicit-fallthrough
|
||||
-Werror=reorder
|
||||
-Werror=sign-compare
|
||||
-Werror=unused-but-set-parameter
|
||||
-Werror=unused-but-set-variable
|
||||
-Werror=unused-variable
|
||||
)
|
||||
endif()
|
||||
|
||||
create_target_directory_groups(core)
|
||||
|
||||
@@ -120,7 +120,7 @@ public:
|
||||
* Gets the instance of the System singleton class.
|
||||
* @returns Reference to the instance of the System singleton class.
|
||||
*/
|
||||
static System& GetInstance() {
|
||||
[[deprecated("Use of the global system instance is deprecated")]] static System& GetInstance() {
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
|
||||
@@ -411,7 +411,7 @@ Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& ke
|
||||
// Combine sources and seed
|
||||
for (auto& source : sd_key_sources) {
|
||||
for (std::size_t i = 0; i < source.size(); ++i) {
|
||||
source[i] ^= sd_seed[i & 0xF];
|
||||
source[i] = static_cast<u8>(source[i] ^ sd_seed[i & 0xF]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -266,8 +266,9 @@ std::multimap<u64, VirtualFile> RomFSBuildContext::Build() {
|
||||
cur_file->offset = file_partition_size;
|
||||
file_partition_size += cur_file->size;
|
||||
cur_file->entry_offset = entry_offset;
|
||||
entry_offset += sizeof(RomFSFileEntry) +
|
||||
Common::AlignUp(cur_file->path_len - cur_file->cur_path_ofs, 4);
|
||||
entry_offset +=
|
||||
static_cast<u32>(sizeof(RomFSFileEntry) +
|
||||
Common::AlignUp(cur_file->path_len - cur_file->cur_path_ofs, 4));
|
||||
prev_file = cur_file;
|
||||
}
|
||||
// Assign deferred parent/sibling ownership.
|
||||
@@ -284,8 +285,9 @@ std::multimap<u64, VirtualFile> RomFSBuildContext::Build() {
|
||||
for (const auto& it : directories) {
|
||||
cur_dir = it.second;
|
||||
cur_dir->entry_offset = entry_offset;
|
||||
entry_offset += sizeof(RomFSDirectoryEntry) +
|
||||
Common::AlignUp(cur_dir->path_len - cur_dir->cur_path_ofs, 4);
|
||||
entry_offset +=
|
||||
static_cast<u32>(sizeof(RomFSDirectoryEntry) +
|
||||
Common::AlignUp(cur_dir->path_len - cur_dir->cur_path_ofs, 4));
|
||||
}
|
||||
// Assign deferred parent/sibling ownership.
|
||||
for (auto it = directories.rbegin(); it->second != root; ++it) {
|
||||
|
||||
@@ -299,7 +299,7 @@ void IPSwitchCompiler::Parse() {
|
||||
patch_text->GetName(), offset, Common::HexToString(replace));
|
||||
}
|
||||
|
||||
patch.records.insert_or_assign(offset, std::move(replace));
|
||||
patch.records.insert_or_assign(static_cast<u32>(offset), std::move(replace));
|
||||
}
|
||||
|
||||
patches.push_back(std::move(patch));
|
||||
|
||||
@@ -108,7 +108,7 @@ std::vector<u8> CNMT::Serialize() const {
|
||||
memcpy(out.data() + sizeof(CNMTHeader), &opt_header, sizeof(OptionalHeader));
|
||||
}
|
||||
|
||||
auto offset = header.table_offset;
|
||||
u64_le offset = header.table_offset;
|
||||
|
||||
for (const auto& rec : content_records) {
|
||||
memcpy(out.data() + offset + sizeof(CNMTHeader), &rec, sizeof(ContentRecord));
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
namespace FileSys {
|
||||
namespace {
|
||||
|
||||
constexpr u64 SINGLE_BYTE_MODULUS = 0x100;
|
||||
constexpr u32 SINGLE_BYTE_MODULUS = 0x100;
|
||||
constexpr u64 DLC_BASE_TITLE_ID_MASK = 0xFFFFFFFFFFFFE000;
|
||||
|
||||
constexpr std::array<const char*, 14> EXEFS_FILE_NAMES{
|
||||
|
||||
@@ -19,38 +19,6 @@
|
||||
#include "core/loader/loader.h"
|
||||
|
||||
namespace FileSys {
|
||||
namespace {
|
||||
void SetTicketKeys(const std::vector<VirtualFile>& files) {
|
||||
auto& keys = Core::Crypto::KeyManager::Instance();
|
||||
|
||||
for (const auto& ticket_file : files) {
|
||||
if (ticket_file == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ticket_file->GetExtension() != "tik") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ticket_file->GetSize() <
|
||||
Core::Crypto::TICKET_FILE_TITLEKEY_OFFSET + sizeof(Core::Crypto::Key128)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Core::Crypto::Key128 key{};
|
||||
ticket_file->Read(key.data(), key.size(), Core::Crypto::TICKET_FILE_TITLEKEY_OFFSET);
|
||||
|
||||
// We get the name without the extension in order to create the rights ID.
|
||||
std::string name_only(ticket_file->GetName());
|
||||
name_only.erase(name_only.size() - 4);
|
||||
|
||||
const auto rights_id_raw = Common::HexStringToArray<16>(name_only);
|
||||
u128 rights_id;
|
||||
std::memcpy(rights_id.data(), rights_id_raw.data(), sizeof(u128));
|
||||
keys.SetKey(Core::Crypto::S128KeyType::Titlekey, key, rights_id[1], rights_id[0]);
|
||||
}
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
NSP::NSP(VirtualFile file_)
|
||||
: file(std::move(file_)), status{Loader::ResultStatus::Success},
|
||||
@@ -232,6 +200,35 @@ VirtualDir NSP::GetParentDirectory() const {
|
||||
return file->GetContainingDirectory();
|
||||
}
|
||||
|
||||
void NSP::SetTicketKeys(const std::vector<VirtualFile>& files) {
|
||||
for (const auto& ticket_file : files) {
|
||||
if (ticket_file == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ticket_file->GetExtension() != "tik") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ticket_file->GetSize() <
|
||||
Core::Crypto::TICKET_FILE_TITLEKEY_OFFSET + sizeof(Core::Crypto::Key128)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Core::Crypto::Key128 key{};
|
||||
ticket_file->Read(key.data(), key.size(), Core::Crypto::TICKET_FILE_TITLEKEY_OFFSET);
|
||||
|
||||
// We get the name without the extension in order to create the rights ID.
|
||||
std::string name_only(ticket_file->GetName());
|
||||
name_only.erase(name_only.size() - 4);
|
||||
|
||||
const auto rights_id_raw = Common::HexStringToArray<16>(name_only);
|
||||
u128 rights_id;
|
||||
std::memcpy(rights_id.data(), rights_id_raw.data(), sizeof(u128));
|
||||
keys.SetKey(Core::Crypto::S128KeyType::Titlekey, key, rights_id[1], rights_id[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void NSP::InitializeExeFSAndRomFS(const std::vector<VirtualFile>& files) {
|
||||
exefs = pfs;
|
||||
|
||||
@@ -286,12 +283,31 @@ void NSP::ReadNCAs(const std::vector<VirtualFile>& files) {
|
||||
}
|
||||
|
||||
auto next_nca = std::make_shared<NCA>(std::move(next_file), nullptr, 0);
|
||||
|
||||
if (next_nca->GetType() == NCAContentType::Program) {
|
||||
program_status[next_nca->GetTitleId()] = next_nca->GetStatus();
|
||||
}
|
||||
if (next_nca->GetStatus() == Loader::ResultStatus::Success ||
|
||||
(next_nca->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS &&
|
||||
(next_nca->GetTitleId() & 0x800) != 0)) {
|
||||
|
||||
if (next_nca->GetStatus() != Loader::ResultStatus::Success &&
|
||||
next_nca->GetStatus() != Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the last 3 hexadecimal digits of the CNMT TitleID is 0x800 or is missing the
|
||||
// BKTRBaseRomFS, this is an update NCA. Otherwise, this is a base NCA.
|
||||
if ((cnmt.GetTitleID() & 0x800) != 0 ||
|
||||
next_nca->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) {
|
||||
// If the last 3 hexadecimal digits of the NCA's TitleID is between 0x1 and
|
||||
// 0x7FF, this is a multi-program update NCA. Otherwise, this is a regular
|
||||
// update NCA.
|
||||
if ((next_nca->GetTitleId() & 0x7FF) != 0 &&
|
||||
(next_nca->GetTitleId() & 0x800) == 0) {
|
||||
ncas[next_nca->GetTitleId()][{cnmt.GetType(), rec.type}] =
|
||||
std::move(next_nca);
|
||||
} else {
|
||||
ncas[cnmt.GetTitleID()][{cnmt.GetType(), rec.type}] = std::move(next_nca);
|
||||
}
|
||||
} else {
|
||||
ncas[next_nca->GetTitleId()][{cnmt.GetType(), rec.type}] = std::move(next_nca);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ public:
|
||||
VirtualDir GetParentDirectory() const override;
|
||||
|
||||
private:
|
||||
void SetTicketKeys(const std::vector<VirtualFile>& files);
|
||||
void InitializeExeFSAndRomFS(const std::vector<VirtualFile>& files);
|
||||
void ReadNCAs(const std::vector<VirtualFile>& files);
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core.h"
|
||||
#include "core/frontend/applets/controller.h"
|
||||
#include "core/hle/service/hid/controllers/npad.h"
|
||||
#include "core/hle/service/hid/hid.h"
|
||||
@@ -14,6 +13,9 @@ namespace Core::Frontend {
|
||||
|
||||
ControllerApplet::~ControllerApplet() = default;
|
||||
|
||||
DefaultControllerApplet::DefaultControllerApplet(Service::SM::ServiceManager& service_manager_)
|
||||
: service_manager{service_manager_} {}
|
||||
|
||||
DefaultControllerApplet::~DefaultControllerApplet() = default;
|
||||
|
||||
void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callback,
|
||||
@@ -21,9 +23,7 @@ void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callb
|
||||
LOG_INFO(Service_HID, "called, deducing the best configuration based on the given parameters!");
|
||||
|
||||
auto& npad =
|
||||
Core::System::GetInstance()
|
||||
.ServiceManager()
|
||||
.GetService<Service::HID::Hid>("hid")
|
||||
service_manager.GetService<Service::HID::Hid>("hid")
|
||||
->GetAppletResource()
|
||||
->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad);
|
||||
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Service::SM {
|
||||
class ServiceManager;
|
||||
}
|
||||
|
||||
namespace Core::Frontend {
|
||||
|
||||
using BorderColor = std::array<u8, 4>;
|
||||
@@ -39,10 +43,14 @@ public:
|
||||
|
||||
class DefaultControllerApplet final : public ControllerApplet {
|
||||
public:
|
||||
explicit DefaultControllerApplet(Service::SM::ServiceManager& service_manager_);
|
||||
~DefaultControllerApplet() override;
|
||||
|
||||
void ReconfigureControllers(std::function<void()> callback,
|
||||
ControllerParameters parameters) const override;
|
||||
|
||||
private:
|
||||
Service::SM::ServiceManager& service_manager;
|
||||
};
|
||||
|
||||
} // namespace Core::Frontend
|
||||
|
||||
@@ -84,10 +84,12 @@ void EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) {
|
||||
return;
|
||||
|
||||
std::lock_guard guard{touch_state->mutex};
|
||||
touch_state->touch_x = static_cast<float>(framebuffer_x - framebuffer_layout.screen.left) /
|
||||
(framebuffer_layout.screen.right - framebuffer_layout.screen.left);
|
||||
touch_state->touch_y = static_cast<float>(framebuffer_y - framebuffer_layout.screen.top) /
|
||||
(framebuffer_layout.screen.bottom - framebuffer_layout.screen.top);
|
||||
touch_state->touch_x =
|
||||
static_cast<float>(framebuffer_x - framebuffer_layout.screen.left) /
|
||||
static_cast<float>(framebuffer_layout.screen.right - framebuffer_layout.screen.left);
|
||||
touch_state->touch_y =
|
||||
static_cast<float>(framebuffer_y - framebuffer_layout.screen.top) /
|
||||
static_cast<float>(framebuffer_layout.screen.bottom - framebuffer_layout.screen.top);
|
||||
|
||||
touch_state->touch_pressed = true;
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@ namespace Layout {
|
||||
template <class T>
|
||||
static Common::Rectangle<T> MaxRectangle(Common::Rectangle<T> window_area,
|
||||
float screen_aspect_ratio) {
|
||||
float scale = std::min(static_cast<float>(window_area.GetWidth()),
|
||||
window_area.GetHeight() / screen_aspect_ratio);
|
||||
const float scale = std::min(static_cast<float>(window_area.GetWidth()),
|
||||
static_cast<float>(window_area.GetHeight()) / screen_aspect_ratio);
|
||||
return Common::Rectangle<T>{0, 0, static_cast<T>(std::round(scale)),
|
||||
static_cast<T>(std::round(scale * screen_aspect_ratio))};
|
||||
}
|
||||
@@ -27,7 +27,7 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height) {
|
||||
// so just calculate them both even if the other isn't showing.
|
||||
FramebufferLayout res{width, height, false, {}};
|
||||
|
||||
const float window_aspect_ratio = static_cast<float>(height) / width;
|
||||
const float window_aspect_ratio = static_cast<float>(height) / static_cast<float>(width);
|
||||
const float emulation_aspect_ratio = EmulationAspectRatio(
|
||||
static_cast<AspectRatio>(Settings::values.aspect_ratio.GetValue()), window_aspect_ratio);
|
||||
|
||||
|
||||
@@ -33,6 +33,9 @@ public:
|
||||
virtual bool GetAnalogDirectionStatus(AnalogDirection direction) const {
|
||||
return {};
|
||||
}
|
||||
virtual bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
/// An abstract class template for a factory that can create input devices.
|
||||
|
||||
@@ -291,11 +291,11 @@ static void FpuWrite(std::size_t id, u128 val, Kernel::Thread* thread = nullptr)
|
||||
*/
|
||||
static u8 HexCharToValue(u8 hex) {
|
||||
if (hex >= '0' && hex <= '9') {
|
||||
return hex - '0';
|
||||
return static_cast<u8>(hex - '0');
|
||||
} else if (hex >= 'a' && hex <= 'f') {
|
||||
return hex - 'a' + 0xA;
|
||||
return static_cast<u8>(hex - 'a' + 0xA);
|
||||
} else if (hex >= 'A' && hex <= 'F') {
|
||||
return hex - 'A' + 0xA;
|
||||
return static_cast<u8>(hex - 'A' + 0xA);
|
||||
}
|
||||
|
||||
LOG_ERROR(Debug_GDBStub, "Invalid nibble: {} ({:02X})", hex, hex);
|
||||
@@ -310,9 +310,9 @@ static u8 HexCharToValue(u8 hex) {
|
||||
static u8 NibbleToHex(u8 n) {
|
||||
n &= 0xF;
|
||||
if (n < 0xA) {
|
||||
return '0' + n;
|
||||
return static_cast<u8>('0' + n);
|
||||
} else {
|
||||
return 'a' + n - 0xA;
|
||||
return static_cast<u8>('a' + n - 0xA);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,8 +355,8 @@ static u64 HexToLong(const u8* src, std::size_t len) {
|
||||
*/
|
||||
static void MemToGdbHex(u8* dest, const u8* src, std::size_t len) {
|
||||
while (len-- > 0) {
|
||||
u8 tmp = *src++;
|
||||
*dest++ = NibbleToHex(tmp >> 4);
|
||||
const u8 tmp = *src++;
|
||||
*dest++ = NibbleToHex(static_cast<u8>(tmp >> 4));
|
||||
*dest++ = NibbleToHex(tmp);
|
||||
}
|
||||
}
|
||||
@@ -370,7 +370,7 @@ static void MemToGdbHex(u8* dest, const u8* src, std::size_t len) {
|
||||
*/
|
||||
static void GdbHexToMem(u8* dest, const u8* src, std::size_t len) {
|
||||
while (len-- > 0) {
|
||||
*dest++ = (HexCharToValue(src[0]) << 4) | HexCharToValue(src[1]);
|
||||
*dest++ = static_cast<u8>((HexCharToValue(src[0]) << 4) | HexCharToValue(src[1]));
|
||||
src += 2;
|
||||
}
|
||||
}
|
||||
@@ -602,22 +602,22 @@ static void SendReply(const char* reply) {
|
||||
|
||||
memcpy(command_buffer + 1, reply, command_length);
|
||||
|
||||
u8 checksum = CalculateChecksum(command_buffer, command_length + 1);
|
||||
const u8 checksum = CalculateChecksum(command_buffer, command_length + 1);
|
||||
command_buffer[0] = GDB_STUB_START;
|
||||
command_buffer[command_length + 1] = GDB_STUB_END;
|
||||
command_buffer[command_length + 2] = NibbleToHex(checksum >> 4);
|
||||
command_buffer[command_length + 2] = NibbleToHex(static_cast<u8>(checksum >> 4));
|
||||
command_buffer[command_length + 3] = NibbleToHex(checksum);
|
||||
|
||||
u8* ptr = command_buffer;
|
||||
u32 left = command_length + 4;
|
||||
while (left > 0) {
|
||||
int sent_size = send(gdbserver_socket, reinterpret_cast<char*>(ptr), left, 0);
|
||||
const auto sent_size = send(gdbserver_socket, reinterpret_cast<char*>(ptr), left, 0);
|
||||
if (sent_size < 0) {
|
||||
LOG_ERROR(Debug_GDBStub, "gdb: send failed");
|
||||
return Shutdown();
|
||||
}
|
||||
|
||||
left -= sent_size;
|
||||
left -= static_cast<u32>(sent_size);
|
||||
ptr += sent_size;
|
||||
}
|
||||
}
|
||||
@@ -777,10 +777,10 @@ static void ReadCommand() {
|
||||
command_buffer[command_length++] = c;
|
||||
}
|
||||
|
||||
u8 checksum_received = HexCharToValue(ReadByte()) << 4;
|
||||
checksum_received |= HexCharToValue(ReadByte());
|
||||
auto checksum_received = static_cast<u32>(HexCharToValue(ReadByte()) << 4);
|
||||
checksum_received |= static_cast<u32>(HexCharToValue(ReadByte()));
|
||||
|
||||
u8 checksum_calculated = CalculateChecksum(command_buffer, command_length);
|
||||
const u32 checksum_calculated = CalculateChecksum(command_buffer, command_length);
|
||||
|
||||
if (checksum_received != checksum_calculated) {
|
||||
LOG_ERROR(Debug_GDBStub,
|
||||
|
||||
@@ -38,10 +38,11 @@ public:
|
||||
explicit RequestHelperBase(Kernel::HLERequestContext& context)
|
||||
: context(&context), cmdbuf(context.CommandBuffer()) {}
|
||||
|
||||
void Skip(unsigned size_in_words, bool set_to_null) {
|
||||
if (set_to_null)
|
||||
void Skip(u32 size_in_words, bool set_to_null) {
|
||||
if (set_to_null) {
|
||||
memset(cmdbuf + index, 0, size_in_words * sizeof(u32));
|
||||
index += size_in_words;
|
||||
}
|
||||
index += static_cast<ptrdiff_t>(size_in_words);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,15 +50,15 @@ public:
|
||||
*/
|
||||
void AlignWithPadding() {
|
||||
if (index & 3) {
|
||||
Skip(4 - (index & 3), true);
|
||||
Skip(static_cast<u32>(4 - (index & 3)), true);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned GetCurrentOffset() const {
|
||||
return static_cast<unsigned>(index);
|
||||
u32 GetCurrentOffset() const {
|
||||
return static_cast<u32>(index);
|
||||
}
|
||||
|
||||
void SetCurrentOffset(unsigned offset) {
|
||||
void SetCurrentOffset(u32 offset) {
|
||||
index = static_cast<ptrdiff_t>(offset);
|
||||
}
|
||||
};
|
||||
@@ -89,7 +90,7 @@ public:
|
||||
|
||||
// The entire size of the raw data section in u32 units, including the 16 bytes of mandatory
|
||||
// padding.
|
||||
u32 raw_data_size = sizeof(IPC::DataPayloadHeader) / 4 + 4 + normal_params_size;
|
||||
u64 raw_data_size = sizeof(IPC::DataPayloadHeader) / 4 + 4 + normal_params_size;
|
||||
|
||||
u32 num_handles_to_move{};
|
||||
u32 num_domain_objects{};
|
||||
@@ -105,7 +106,7 @@ public:
|
||||
raw_data_size += sizeof(DomainMessageHeader) / 4 + num_domain_objects;
|
||||
}
|
||||
|
||||
header.data_size.Assign(raw_data_size);
|
||||
header.data_size.Assign(static_cast<u32>(raw_data_size));
|
||||
if (num_handles_to_copy || num_handles_to_move) {
|
||||
header.enable_handle_descriptor.Assign(1);
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ std::shared_ptr<Object> HandleTable::GetGeneric(Handle handle) const {
|
||||
|
||||
void HandleTable::Clear() {
|
||||
for (u16 i = 0; i < table_size; ++i) {
|
||||
generations[i] = i + 1;
|
||||
generations[i] = static_cast<u16>(i + 1);
|
||||
objects[i] = nullptr;
|
||||
}
|
||||
next_free_slot = 0;
|
||||
|
||||
@@ -72,7 +72,7 @@ u32 GlobalScheduler::SelectThreads() {
|
||||
if (top_thread != nullptr) {
|
||||
// TODO(Blinkhawk): Implement Thread Pinning
|
||||
} else {
|
||||
idle_cores |= (1ul << core);
|
||||
idle_cores |= (1U << core);
|
||||
}
|
||||
top_threads[core] = top_thread;
|
||||
}
|
||||
@@ -126,7 +126,7 @@ u32 GlobalScheduler::SelectThreads() {
|
||||
top_threads[core_id] = suggested;
|
||||
}
|
||||
|
||||
idle_cores &= ~(1ul << core_id);
|
||||
idle_cores &= ~(1U << core_id);
|
||||
}
|
||||
u32 cores_needing_context_switch{};
|
||||
for (u32 core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) {
|
||||
@@ -134,7 +134,7 @@ u32 GlobalScheduler::SelectThreads() {
|
||||
ASSERT(top_threads[core] == nullptr ||
|
||||
static_cast<u32>(top_threads[core]->GetProcessorID()) == core);
|
||||
if (update_thread(top_threads[core], sched)) {
|
||||
cores_needing_context_switch |= (1ul << core);
|
||||
cores_needing_context_switch |= (1U << core);
|
||||
}
|
||||
}
|
||||
return cores_needing_context_switch;
|
||||
@@ -364,7 +364,7 @@ void GlobalScheduler::EnableInterruptAndSchedule(u32 cores_pending_reschedule,
|
||||
} else {
|
||||
must_context_switch = true;
|
||||
}
|
||||
cores_pending_reschedule &= ~(1ul << core);
|
||||
cores_pending_reschedule &= ~(1U << core);
|
||||
}
|
||||
if (must_context_switch) {
|
||||
auto& core_scheduler = kernel.CurrentScheduler();
|
||||
@@ -767,7 +767,7 @@ void Scheduler::SwitchToCurrent() {
|
||||
current_thread->context_guard.unlock();
|
||||
break;
|
||||
}
|
||||
if (current_thread->GetProcessorID() != core_id) {
|
||||
if (static_cast<u32>(current_thread->GetProcessorID()) != core_id) {
|
||||
current_thread->context_guard.unlock();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -774,6 +774,17 @@ void Module::Interface::ListQualifiedUsers(Kernel::HLERequestContext& ctx) {
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void Module::Interface::LoadOpenContext(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_ACC, "(STUBBED) called");
|
||||
|
||||
// This is similar to GetBaasAccountManagerForApplication
|
||||
// This command is used concurrently with ListOpenContextStoredUsers
|
||||
// TODO: Find the differences between this and GetBaasAccountManagerForApplication
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<IManagerForApplication>(profile_manager->GetLastOpenedUser());
|
||||
}
|
||||
|
||||
void Module::Interface::ListOpenContextStoredUsers(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_ACC, "(STUBBED) called");
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ public:
|
||||
void IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx);
|
||||
void GetProfileEditor(Kernel::HLERequestContext& ctx);
|
||||
void ListQualifiedUsers(Kernel::HLERequestContext& ctx);
|
||||
void LoadOpenContext(Kernel::HLERequestContext& ctx);
|
||||
void ListOpenContextStoredUsers(Kernel::HLERequestContext& ctx);
|
||||
|
||||
private:
|
||||
|
||||
@@ -29,7 +29,7 @@ ACC_U0::ACC_U0(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
|
||||
{110, nullptr, "StoreSaveDataThumbnail"},
|
||||
{111, nullptr, "ClearSaveDataThumbnail"},
|
||||
{120, nullptr, "CreateGuestLoginRequest"},
|
||||
{130, nullptr, "LoadOpenContext"}, // 5.0.0+
|
||||
{130, &ACC_U0::LoadOpenContext, "LoadOpenContext"}, // 5.0.0+
|
||||
{131, &ACC_U0::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"}, // 6.0.0+
|
||||
{140, &ACC_U0::InitializeApplicationInfoRestricted, "InitializeApplicationInfoRestricted"}, // 6.0.0+
|
||||
{141, &ACC_U0::ListQualifiedUsers, "ListQualifiedUsers"}, // 6.0.0+
|
||||
|
||||
@@ -206,7 +206,8 @@ void AppletManager::SetDefaultAppletFrontendSet() {
|
||||
|
||||
void AppletManager::SetDefaultAppletsIfMissing() {
|
||||
if (frontend.controller == nullptr) {
|
||||
frontend.controller = std::make_unique<Core::Frontend::DefaultControllerApplet>();
|
||||
frontend.controller =
|
||||
std::make_unique<Core::Frontend::DefaultControllerApplet>(system.ServiceManager());
|
||||
}
|
||||
|
||||
if (frontend.e_commerce == nullptr) {
|
||||
|
||||
@@ -196,7 +196,9 @@ private:
|
||||
const std::string& content_type_name) {
|
||||
if (client == nullptr) {
|
||||
client = std::make_unique<httplib::SSLClient>(BOXCAT_HOSTNAME, PORT);
|
||||
client->set_timeout_sec(timeout_seconds);
|
||||
client->set_connection_timeout(timeout_seconds);
|
||||
client->set_read_timeout(timeout_seconds);
|
||||
client->set_write_timeout(timeout_seconds);
|
||||
}
|
||||
|
||||
httplib::Headers headers{
|
||||
@@ -255,7 +257,7 @@ private:
|
||||
return out;
|
||||
}
|
||||
|
||||
std::unique_ptr<httplib::Client> client;
|
||||
std::unique_ptr<httplib::SSLClient> client;
|
||||
std::string path;
|
||||
u64 title_id;
|
||||
u64 build_id;
|
||||
@@ -443,7 +445,9 @@ std::optional<std::vector<u8>> Boxcat::GetLaunchParameter(TitleIDVersion title)
|
||||
Boxcat::StatusResult Boxcat::GetStatus(std::optional<std::string>& global,
|
||||
std::map<std::string, EventStatus>& games) {
|
||||
httplib::SSLClient client{BOXCAT_HOSTNAME, static_cast<int>(PORT)};
|
||||
client.set_timeout_sec(static_cast<int>(TIMEOUT_SECONDS));
|
||||
client.set_connection_timeout(static_cast<int>(TIMEOUT_SECONDS));
|
||||
client.set_read_timeout(static_cast<int>(TIMEOUT_SECONDS));
|
||||
client.set_write_timeout(static_cast<int>(TIMEOUT_SECONDS));
|
||||
|
||||
httplib::Headers headers{
|
||||
{std::string("Game-Assets-API-Version"), std::string(BOXCAT_API_VERSION)},
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/service/caps/caps_c.h"
|
||||
|
||||
namespace Service::Capture {
|
||||
@@ -47,7 +49,7 @@ CAPS_C::CAPS_C() : ServiceFramework("caps:c") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{1, nullptr, "CaptureRawImage"},
|
||||
{2, nullptr, "CaptureRawImageWithTimeout"},
|
||||
{33, nullptr, "Unknown33"},
|
||||
{33, &CAPS_C::SetShimLibraryVersion, "SetShimLibraryVersion"},
|
||||
{1001, nullptr, "RequestTakingScreenShot"},
|
||||
{1002, nullptr, "RequestTakingScreenShotWithTimeout"},
|
||||
{1011, nullptr, "NotifyTakingScreenShotRefused"},
|
||||
@@ -72,4 +74,16 @@ CAPS_C::CAPS_C() : ServiceFramework("caps:c") {
|
||||
|
||||
CAPS_C::~CAPS_C() = default;
|
||||
|
||||
void CAPS_C::SetShimLibraryVersion(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto library_version{rp.Pop<u64>()};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
|
||||
LOG_WARNING(Service_Capture, "(STUBBED) called. library_version={}, applet_resource_user_id={}",
|
||||
library_version, applet_resource_user_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
} // namespace Service::Capture
|
||||
|
||||
@@ -16,6 +16,9 @@ class CAPS_C final : public ServiceFramework<CAPS_C> {
|
||||
public:
|
||||
explicit CAPS_C();
|
||||
~CAPS_C() override;
|
||||
|
||||
private:
|
||||
void SetShimLibraryVersion(Kernel::HLERequestContext& ctx);
|
||||
};
|
||||
|
||||
} // namespace Service::Capture
|
||||
|
||||
@@ -25,7 +25,12 @@ CAPS_SU::CAPS_SU() : ServiceFramework("caps:su") {
|
||||
CAPS_SU::~CAPS_SU() = default;
|
||||
|
||||
void CAPS_SU::SetShimLibraryVersion(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_Capture, "(STUBBED) called");
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto library_version{rp.Pop<u64>()};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
|
||||
LOG_WARNING(Service_Capture, "(STUBBED) called. library_version={}, applet_resource_user_id={}",
|
||||
library_version, applet_resource_user_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
@@ -31,8 +31,7 @@ public:
|
||||
CAPS_U::CAPS_U() : ServiceFramework("caps:u") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{31, nullptr, "GetShimLibraryVersion"},
|
||||
{32, nullptr, "SetShimLibraryVersion"},
|
||||
{32, &CAPS_U::SetShimLibraryVersion, "SetShimLibraryVersion"},
|
||||
{102, &CAPS_U::GetAlbumContentsFileListForApplication, "GetAlbumContentsFileListForApplication"},
|
||||
{103, nullptr, "DeleteAlbumContentsFileForApplication"},
|
||||
{104, nullptr, "GetAlbumContentsFileSizeForApplication"},
|
||||
@@ -53,6 +52,18 @@ CAPS_U::CAPS_U() : ServiceFramework("caps:u") {
|
||||
|
||||
CAPS_U::~CAPS_U() = default;
|
||||
|
||||
void CAPS_U::SetShimLibraryVersion(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto library_version{rp.Pop<u64>()};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
|
||||
LOG_WARNING(Service_Capture, "(STUBBED) called. library_version={}, applet_resource_user_id={}",
|
||||
library_version, applet_resource_user_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void CAPS_U::GetAlbumContentsFileListForApplication(Kernel::HLERequestContext& ctx) {
|
||||
// Takes a type-0x6 output buffer containing an array of ApplicationAlbumFileEntry, a PID, an
|
||||
// u8 ContentType, two s64s, and an u64 AppletResourceUserId. Returns an output u64 for total
|
||||
|
||||
@@ -18,6 +18,7 @@ public:
|
||||
~CAPS_U() override;
|
||||
|
||||
private:
|
||||
void SetShimLibraryVersion(Kernel::HLERequestContext& ctx);
|
||||
void GetAlbumContentsFileListForApplication(Kernel::HLERequestContext& ctx);
|
||||
};
|
||||
|
||||
|
||||
@@ -31,6 +31,10 @@ public:
|
||||
virtual void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
|
||||
std::size_t size) = 0;
|
||||
|
||||
// When the controller is requesting a motion update for the shared memory
|
||||
virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
|
||||
std::size_t size) {}
|
||||
|
||||
// Called when input devices should be loaded
|
||||
virtual void OnLoadInputDevices() = 0;
|
||||
|
||||
|
||||
@@ -42,8 +42,8 @@ void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing,
|
||||
cur_entry.modifier = 0;
|
||||
if (Settings::values.keyboard_enabled) {
|
||||
for (std::size_t i = 0; i < keyboard_keys.size(); ++i) {
|
||||
cur_entry.key[i / KEYS_PER_BYTE] |=
|
||||
(keyboard_keys[i]->GetStatus() << (i % KEYS_PER_BYTE));
|
||||
auto& entry = cur_entry.key[i / KEYS_PER_BYTE];
|
||||
entry = static_cast<u8>(entry | (keyboard_keys[i]->GetStatus() << (i % KEYS_PER_BYTE)));
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < keyboard_mods.size(); ++i) {
|
||||
|
||||
@@ -260,7 +260,7 @@ void Controller_NPad::OnRelease() {}
|
||||
|
||||
void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
|
||||
const auto controller_idx = NPadIdToIndex(npad_id);
|
||||
[[maybe_unused]] const auto controller_type = connected_controllers[controller_idx].type;
|
||||
const auto controller_type = connected_controllers[controller_idx].type;
|
||||
if (!connected_controllers[controller_idx].is_connected) {
|
||||
return;
|
||||
}
|
||||
@@ -269,61 +269,69 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
|
||||
auto& rstick_entry = npad_pad_states[controller_idx].r_stick;
|
||||
const auto& button_state = buttons[controller_idx];
|
||||
const auto& analog_state = sticks[controller_idx];
|
||||
const auto& motion_state = motions[controller_idx];
|
||||
const auto [stick_l_x_f, stick_l_y_f] =
|
||||
analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetStatus();
|
||||
const auto [stick_r_x_f, stick_r_y_f] =
|
||||
analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]->GetStatus();
|
||||
|
||||
using namespace Settings::NativeButton;
|
||||
pad_state.a.Assign(button_state[A - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.b.Assign(button_state[B - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.x.Assign(button_state[X - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.y.Assign(button_state[Y - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.l_stick.Assign(button_state[LStick - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.r_stick.Assign(button_state[RStick - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.l.Assign(button_state[L - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.r.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.zl.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.zr.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.plus.Assign(button_state[Plus - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.minus.Assign(button_state[Minus - BUTTON_HID_BEGIN]->GetStatus());
|
||||
if (controller_type != NPadControllerType::JoyLeft) {
|
||||
pad_state.a.Assign(button_state[A - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.b.Assign(button_state[B - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.x.Assign(button_state[X - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.y.Assign(button_state[Y - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.r_stick.Assign(button_state[RStick - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.r.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.zr.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.plus.Assign(button_state[Plus - BUTTON_HID_BEGIN]->GetStatus());
|
||||
|
||||
pad_state.d_left.Assign(button_state[DLeft - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.d_up.Assign(button_state[DUp - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.d_right.Assign(button_state[DRight - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.d_down.Assign(button_state[DDown - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.r_stick_right.Assign(
|
||||
analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
|
||||
->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT));
|
||||
pad_state.r_stick_left.Assign(
|
||||
analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
|
||||
->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT));
|
||||
pad_state.r_stick_up.Assign(
|
||||
analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
|
||||
->GetAnalogDirectionStatus(Input::AnalogDirection::UP));
|
||||
pad_state.r_stick_down.Assign(
|
||||
analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
|
||||
->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN));
|
||||
rstick_entry.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX);
|
||||
rstick_entry.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX);
|
||||
}
|
||||
|
||||
pad_state.l_stick_right.Assign(
|
||||
analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus(
|
||||
Input::AnalogDirection::RIGHT));
|
||||
pad_state.l_stick_left.Assign(
|
||||
analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus(
|
||||
Input::AnalogDirection::LEFT));
|
||||
pad_state.l_stick_up.Assign(
|
||||
analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus(
|
||||
Input::AnalogDirection::UP));
|
||||
pad_state.l_stick_down.Assign(
|
||||
analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus(
|
||||
Input::AnalogDirection::DOWN));
|
||||
if (controller_type != NPadControllerType::JoyRight) {
|
||||
pad_state.d_left.Assign(button_state[DLeft - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.d_up.Assign(button_state[DUp - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.d_right.Assign(button_state[DRight - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.d_down.Assign(button_state[DDown - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.l_stick.Assign(button_state[LStick - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.l.Assign(button_state[L - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.zl.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.minus.Assign(button_state[Minus - BUTTON_HID_BEGIN]->GetStatus());
|
||||
|
||||
pad_state.r_stick_right.Assign(
|
||||
analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
|
||||
->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT));
|
||||
pad_state.r_stick_left.Assign(analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
|
||||
->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT));
|
||||
pad_state.r_stick_up.Assign(analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
|
||||
->GetAnalogDirectionStatus(Input::AnalogDirection::UP));
|
||||
pad_state.r_stick_down.Assign(analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
|
||||
->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN));
|
||||
pad_state.l_stick_right.Assign(
|
||||
analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
|
||||
->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT));
|
||||
pad_state.l_stick_left.Assign(
|
||||
analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
|
||||
->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT));
|
||||
pad_state.l_stick_up.Assign(
|
||||
analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
|
||||
->GetAnalogDirectionStatus(Input::AnalogDirection::UP));
|
||||
pad_state.l_stick_down.Assign(
|
||||
analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
|
||||
->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN));
|
||||
lstick_entry.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX);
|
||||
lstick_entry.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX);
|
||||
}
|
||||
|
||||
pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus());
|
||||
|
||||
lstick_entry.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX);
|
||||
lstick_entry.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX);
|
||||
rstick_entry.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX);
|
||||
rstick_entry.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX);
|
||||
if (controller_type == NPadControllerType::JoyLeft ||
|
||||
controller_type == NPadControllerType::JoyRight) {
|
||||
pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus());
|
||||
pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus());
|
||||
}
|
||||
}
|
||||
|
||||
void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
|
||||
@@ -365,6 +373,123 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
}
|
||||
const u32 npad_index = static_cast<u32>(i);
|
||||
|
||||
RequestPadStateUpdate(npad_index);
|
||||
auto& pad_state = npad_pad_states[npad_index];
|
||||
|
||||
auto& main_controller =
|
||||
npad.main_controller_states.npad[npad.main_controller_states.common.last_entry_index];
|
||||
auto& handheld_entry =
|
||||
npad.handheld_states.npad[npad.handheld_states.common.last_entry_index];
|
||||
auto& dual_entry = npad.dual_states.npad[npad.dual_states.common.last_entry_index];
|
||||
auto& left_entry = npad.left_joy_states.npad[npad.left_joy_states.common.last_entry_index];
|
||||
auto& right_entry =
|
||||
npad.right_joy_states.npad[npad.right_joy_states.common.last_entry_index];
|
||||
auto& pokeball_entry =
|
||||
npad.pokeball_states.npad[npad.pokeball_states.common.last_entry_index];
|
||||
auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index];
|
||||
|
||||
libnx_entry.connection_status.raw = 0;
|
||||
libnx_entry.connection_status.IsConnected.Assign(1);
|
||||
|
||||
switch (controller_type) {
|
||||
case NPadControllerType::None:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
case NPadControllerType::ProController:
|
||||
main_controller.connection_status.raw = 0;
|
||||
main_controller.connection_status.IsConnected.Assign(1);
|
||||
main_controller.connection_status.IsWired.Assign(1);
|
||||
main_controller.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
main_controller.pad.l_stick = pad_state.l_stick;
|
||||
main_controller.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
libnx_entry.connection_status.IsWired.Assign(1);
|
||||
break;
|
||||
case NPadControllerType::Handheld:
|
||||
handheld_entry.connection_status.raw = 0;
|
||||
handheld_entry.connection_status.IsConnected.Assign(1);
|
||||
handheld_entry.connection_status.IsWired.Assign(1);
|
||||
handheld_entry.connection_status.IsLeftJoyConnected.Assign(1);
|
||||
handheld_entry.connection_status.IsRightJoyConnected.Assign(1);
|
||||
handheld_entry.connection_status.IsLeftJoyWired.Assign(1);
|
||||
handheld_entry.connection_status.IsRightJoyWired.Assign(1);
|
||||
handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
handheld_entry.pad.l_stick = pad_state.l_stick;
|
||||
handheld_entry.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
libnx_entry.connection_status.IsWired.Assign(1);
|
||||
libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
|
||||
libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
|
||||
libnx_entry.connection_status.IsLeftJoyWired.Assign(1);
|
||||
libnx_entry.connection_status.IsRightJoyWired.Assign(1);
|
||||
break;
|
||||
case NPadControllerType::JoyDual:
|
||||
dual_entry.connection_status.raw = 0;
|
||||
dual_entry.connection_status.IsConnected.Assign(1);
|
||||
dual_entry.connection_status.IsLeftJoyConnected.Assign(1);
|
||||
dual_entry.connection_status.IsRightJoyConnected.Assign(1);
|
||||
dual_entry.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
dual_entry.pad.l_stick = pad_state.l_stick;
|
||||
dual_entry.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
|
||||
libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
|
||||
break;
|
||||
case NPadControllerType::JoyLeft:
|
||||
left_entry.connection_status.raw = 0;
|
||||
left_entry.connection_status.IsConnected.Assign(1);
|
||||
left_entry.connection_status.IsLeftJoyConnected.Assign(1);
|
||||
left_entry.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
left_entry.pad.l_stick = pad_state.l_stick;
|
||||
left_entry.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
|
||||
break;
|
||||
case NPadControllerType::JoyRight:
|
||||
right_entry.connection_status.raw = 0;
|
||||
right_entry.connection_status.IsConnected.Assign(1);
|
||||
right_entry.connection_status.IsRightJoyConnected.Assign(1);
|
||||
right_entry.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
right_entry.pad.l_stick = pad_state.l_stick;
|
||||
right_entry.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
|
||||
break;
|
||||
case NPadControllerType::Pokeball:
|
||||
pokeball_entry.connection_status.raw = 0;
|
||||
pokeball_entry.connection_status.IsConnected.Assign(1);
|
||||
pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
pokeball_entry.pad.l_stick = pad_state.l_stick;
|
||||
pokeball_entry.pad.r_stick = pad_state.r_stick;
|
||||
break;
|
||||
}
|
||||
|
||||
// LibNX exclusively uses this section, so we always update it since LibNX doesn't activate
|
||||
// any controllers.
|
||||
libnx_entry.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
libnx_entry.pad.l_stick = pad_state.l_stick;
|
||||
libnx_entry.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
press_state |= static_cast<u32>(pad_state.pad_states.raw);
|
||||
}
|
||||
std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(),
|
||||
shared_memory_entries.size() * sizeof(NPadEntry));
|
||||
}
|
||||
|
||||
void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
|
||||
std::size_t data_len) {
|
||||
if (!IsControllerActivated()) {
|
||||
return;
|
||||
}
|
||||
for (std::size_t i = 0; i < shared_memory_entries.size(); i++) {
|
||||
auto& npad = shared_memory_entries[i];
|
||||
|
||||
const auto& controller_type = connected_controllers[i].type;
|
||||
|
||||
if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::array<SixAxisGeneric*, 6> controller_sixaxes{
|
||||
&npad.sixaxis_full, &npad.sixaxis_handheld, &npad.sixaxis_dual_left,
|
||||
&npad.sixaxis_dual_right, &npad.sixaxis_left, &npad.sixaxis_right,
|
||||
@@ -403,23 +528,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
}
|
||||
}
|
||||
|
||||
RequestPadStateUpdate(npad_index);
|
||||
auto& pad_state = npad_pad_states[npad_index];
|
||||
|
||||
auto& main_controller =
|
||||
npad.main_controller_states.npad[npad.main_controller_states.common.last_entry_index];
|
||||
auto& handheld_entry =
|
||||
npad.handheld_states.npad[npad.handheld_states.common.last_entry_index];
|
||||
auto& dual_entry = npad.dual_states.npad[npad.dual_states.common.last_entry_index];
|
||||
auto& left_entry = npad.left_joy_states.npad[npad.left_joy_states.common.last_entry_index];
|
||||
auto& right_entry =
|
||||
npad.right_joy_states.npad[npad.right_joy_states.common.last_entry_index];
|
||||
auto& pokeball_entry =
|
||||
npad.pokeball_states.npad[npad.pokeball_states.common.last_entry_index];
|
||||
auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index];
|
||||
|
||||
libnx_entry.connection_status.raw = 0;
|
||||
libnx_entry.connection_status.IsConnected.Assign(1);
|
||||
auto& full_sixaxis_entry =
|
||||
npad.sixaxis_full.sixaxis[npad.sixaxis_full.common.last_entry_index];
|
||||
auto& handheld_sixaxis_entry =
|
||||
@@ -438,15 +546,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
UNREACHABLE();
|
||||
break;
|
||||
case NPadControllerType::ProController:
|
||||
main_controller.connection_status.raw = 0;
|
||||
main_controller.connection_status.IsConnected.Assign(1);
|
||||
main_controller.connection_status.IsWired.Assign(1);
|
||||
main_controller.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
main_controller.pad.l_stick = pad_state.l_stick;
|
||||
main_controller.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
libnx_entry.connection_status.IsWired.Assign(1);
|
||||
|
||||
if (sixaxis_sensors_enabled && motions[i][0]) {
|
||||
full_sixaxis_entry.accel = motion_devices[0].accel;
|
||||
full_sixaxis_entry.gyro = motion_devices[0].gyro;
|
||||
@@ -455,23 +554,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
}
|
||||
break;
|
||||
case NPadControllerType::Handheld:
|
||||
handheld_entry.connection_status.raw = 0;
|
||||
handheld_entry.connection_status.IsConnected.Assign(1);
|
||||
handheld_entry.connection_status.IsWired.Assign(1);
|
||||
handheld_entry.connection_status.IsLeftJoyConnected.Assign(1);
|
||||
handheld_entry.connection_status.IsRightJoyConnected.Assign(1);
|
||||
handheld_entry.connection_status.IsLeftJoyWired.Assign(1);
|
||||
handheld_entry.connection_status.IsRightJoyWired.Assign(1);
|
||||
handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
handheld_entry.pad.l_stick = pad_state.l_stick;
|
||||
handheld_entry.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
libnx_entry.connection_status.IsWired.Assign(1);
|
||||
libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
|
||||
libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
|
||||
libnx_entry.connection_status.IsLeftJoyWired.Assign(1);
|
||||
libnx_entry.connection_status.IsRightJoyWired.Assign(1);
|
||||
|
||||
if (sixaxis_sensors_enabled && motions[i][0]) {
|
||||
handheld_sixaxis_entry.accel = motion_devices[0].accel;
|
||||
handheld_sixaxis_entry.gyro = motion_devices[0].gyro;
|
||||
@@ -480,17 +562,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
}
|
||||
break;
|
||||
case NPadControllerType::JoyDual:
|
||||
dual_entry.connection_status.raw = 0;
|
||||
dual_entry.connection_status.IsConnected.Assign(1);
|
||||
dual_entry.connection_status.IsLeftJoyConnected.Assign(1);
|
||||
dual_entry.connection_status.IsRightJoyConnected.Assign(1);
|
||||
dual_entry.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
dual_entry.pad.l_stick = pad_state.l_stick;
|
||||
dual_entry.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
|
||||
libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
|
||||
|
||||
if (sixaxis_sensors_enabled && motions[i][0]) {
|
||||
// Set motion for the left joycon
|
||||
dual_left_sixaxis_entry.accel = motion_devices[0].accel;
|
||||
@@ -507,15 +578,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
}
|
||||
break;
|
||||
case NPadControllerType::JoyLeft:
|
||||
left_entry.connection_status.raw = 0;
|
||||
left_entry.connection_status.IsConnected.Assign(1);
|
||||
left_entry.connection_status.IsLeftJoyConnected.Assign(1);
|
||||
left_entry.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
left_entry.pad.l_stick = pad_state.l_stick;
|
||||
left_entry.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
|
||||
|
||||
if (sixaxis_sensors_enabled && motions[i][0]) {
|
||||
left_sixaxis_entry.accel = motion_devices[0].accel;
|
||||
left_sixaxis_entry.gyro = motion_devices[0].gyro;
|
||||
@@ -524,15 +586,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
}
|
||||
break;
|
||||
case NPadControllerType::JoyRight:
|
||||
right_entry.connection_status.raw = 0;
|
||||
right_entry.connection_status.IsConnected.Assign(1);
|
||||
right_entry.connection_status.IsRightJoyConnected.Assign(1);
|
||||
right_entry.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
right_entry.pad.l_stick = pad_state.l_stick;
|
||||
right_entry.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
|
||||
|
||||
if (sixaxis_sensors_enabled && motions[i][1]) {
|
||||
right_sixaxis_entry.accel = motion_devices[1].accel;
|
||||
right_sixaxis_entry.gyro = motion_devices[1].gyro;
|
||||
@@ -541,21 +594,8 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
}
|
||||
break;
|
||||
case NPadControllerType::Pokeball:
|
||||
pokeball_entry.connection_status.raw = 0;
|
||||
pokeball_entry.connection_status.IsConnected.Assign(1);
|
||||
pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
pokeball_entry.pad.l_stick = pad_state.l_stick;
|
||||
pokeball_entry.pad.r_stick = pad_state.r_stick;
|
||||
break;
|
||||
}
|
||||
|
||||
// LibNX exclusively uses this section, so we always update it since LibNX doesn't activate
|
||||
// any controllers.
|
||||
libnx_entry.pad.pad_states.raw = pad_state.pad_states.raw;
|
||||
libnx_entry.pad.l_stick = pad_state.l_stick;
|
||||
libnx_entry.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
press_state |= static_cast<u32>(pad_state.pad_states.raw);
|
||||
}
|
||||
std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(),
|
||||
shared_memory_entries.size() * sizeof(NPadEntry));
|
||||
@@ -609,20 +649,31 @@ void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode)
|
||||
}
|
||||
}
|
||||
|
||||
void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids,
|
||||
void Controller_NPad::VibrateController(const std::vector<u32>& controllers,
|
||||
const std::vector<Vibration>& vibrations) {
|
||||
LOG_DEBUG(Service_HID, "(STUBBED) called");
|
||||
LOG_TRACE(Service_HID, "called");
|
||||
|
||||
if (!Settings::values.vibration_enabled || !can_controllers_vibrate) {
|
||||
return;
|
||||
}
|
||||
for (std::size_t i = 0; i < controller_ids.size(); i++) {
|
||||
std::size_t controller_pos = NPadIdToIndex(static_cast<u32>(i));
|
||||
if (connected_controllers[controller_pos].is_connected) {
|
||||
// TODO(ogniK): Vibrate the physical controller
|
||||
bool success = true;
|
||||
for (std::size_t i = 0; i < controllers.size(); ++i) {
|
||||
if (!connected_controllers[i].is_connected) {
|
||||
continue;
|
||||
}
|
||||
using namespace Settings::NativeButton;
|
||||
const auto& button_state = buttons[i];
|
||||
if (button_state[A - BUTTON_HID_BEGIN]) {
|
||||
if (button_state[A - BUTTON_HID_BEGIN]->SetRumblePlay(
|
||||
vibrations[0].amp_high, vibrations[0].amp_low, vibrations[0].freq_high,
|
||||
vibrations[0].freq_low)) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
last_processed_vibration = vibrations.back();
|
||||
if (success) {
|
||||
last_processed_vibration = vibrations.back();
|
||||
}
|
||||
}
|
||||
|
||||
Controller_NPad::Vibration Controller_NPad::GetLastVibration() const {
|
||||
@@ -770,6 +821,15 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const {
|
||||
return unintended_home_button_input_protection[NPadIdToIndex(npad_id)];
|
||||
}
|
||||
|
||||
void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled,
|
||||
u32 npad_id) {
|
||||
unintended_home_button_input_protection[NPadIdToIndex(npad_id)] = is_protection_enabled;
|
||||
}
|
||||
|
||||
void Controller_NPad::SetVibrationEnabled(bool can_vibrate) {
|
||||
can_controllers_vibrate = can_vibrate;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,10 @@ public:
|
||||
// When the controller is requesting an update for the shared memory
|
||||
void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
|
||||
|
||||
// When the controller is requesting a motion update for the shared memory
|
||||
void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
|
||||
std::size_t size) override;
|
||||
|
||||
// Called when input devices should be loaded
|
||||
void OnLoadInputDevices() override;
|
||||
|
||||
@@ -121,7 +125,7 @@ public:
|
||||
|
||||
void SetNpadMode(u32 npad_id, NPadAssignments assignment_mode);
|
||||
|
||||
void VibrateController(const std::vector<u32>& controller_ids,
|
||||
void VibrateController(const std::vector<u32>& controllers,
|
||||
const std::vector<Vibration>& vibrations);
|
||||
|
||||
Vibration GetLastVibration() const;
|
||||
@@ -142,6 +146,8 @@ public:
|
||||
bool IsSixAxisSensorAtRest() const;
|
||||
void SetSixAxisEnabled(bool six_axis_status);
|
||||
LedPattern GetLedPattern(u32 npad_id);
|
||||
bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const;
|
||||
void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id);
|
||||
void SetVibrationEnabled(bool can_vibrate);
|
||||
bool IsVibrationEnabled() const;
|
||||
void ClearAllConnectedControllers();
|
||||
@@ -383,6 +389,7 @@ private:
|
||||
std::array<Kernel::EventPair, 10> styleset_changed_events;
|
||||
Vibration last_processed_vibration{};
|
||||
std::array<ControllerHolder, 10> connected_controllers{};
|
||||
std::array<bool, 10> unintended_home_button_input_protection{};
|
||||
GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard};
|
||||
bool can_controllers_vibrate{true};
|
||||
bool sixaxis_sensors_enabled{true};
|
||||
|
||||
@@ -40,7 +40,8 @@ namespace Service::HID {
|
||||
// Updating period for each HID device.
|
||||
// HID is polled every 15ms, this value was derived from
|
||||
// https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering#joy-con-status-data-packet
|
||||
constexpr auto pad_update_ns = std::chrono::nanoseconds{1000 * 1000}; // (1ms, 1000Hz)
|
||||
constexpr auto pad_update_ns = std::chrono::nanoseconds{1000 * 1000}; // (1ms, 1000Hz)
|
||||
constexpr auto motion_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000}; // (15ms, 66.666Hz)
|
||||
constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000;
|
||||
|
||||
IAppletResource::IAppletResource(Core::System& system)
|
||||
@@ -79,10 +80,14 @@ IAppletResource::IAppletResource(Core::System& system)
|
||||
[this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
|
||||
UpdateControllers(user_data, ns_late);
|
||||
});
|
||||
|
||||
// TODO(shinyquagsire23): Other update callbacks? (accel, gyro?)
|
||||
motion_update_event = Core::Timing::CreateEvent(
|
||||
"HID::MotionPadCallback",
|
||||
[this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
|
||||
UpdateMotion(user_data, ns_late);
|
||||
});
|
||||
|
||||
system.CoreTiming().ScheduleEvent(pad_update_ns, pad_update_event);
|
||||
system.CoreTiming().ScheduleEvent(motion_update_ns, motion_update_event);
|
||||
|
||||
ReloadInputDevices();
|
||||
}
|
||||
@@ -122,6 +127,16 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data,
|
||||
core_timing.ScheduleEvent(pad_update_ns - ns_late, pad_update_event);
|
||||
}
|
||||
|
||||
void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
|
||||
auto& core_timing = system.CoreTiming();
|
||||
|
||||
for (const auto& controller : controllers) {
|
||||
controller->OnMotionUpdate(core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE);
|
||||
}
|
||||
|
||||
core_timing.ScheduleEvent(motion_update_ns - ns_late, motion_update_event);
|
||||
}
|
||||
|
||||
class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> {
|
||||
public:
|
||||
IActiveVibrationDeviceList() : ServiceFramework("IActiveVibrationDeviceList") {
|
||||
@@ -173,7 +188,7 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) {
|
||||
{66, &Hid::StartSixAxisSensor, "StartSixAxisSensor"},
|
||||
{67, &Hid::StopSixAxisSensor, "StopSixAxisSensor"},
|
||||
{68, nullptr, "IsSixAxisSensorFusionEnabled"},
|
||||
{69, nullptr, "EnableSixAxisSensorFusion"},
|
||||
{69, &Hid::EnableSixAxisSensorFusion, "EnableSixAxisSensorFusion"},
|
||||
{70, nullptr, "SetSixAxisSensorFusionParameters"},
|
||||
{71, nullptr, "GetSixAxisSensorFusionParameters"},
|
||||
{72, nullptr, "ResetSixAxisSensorFusionParameters"},
|
||||
@@ -209,8 +224,8 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) {
|
||||
{128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"},
|
||||
{129, &Hid::GetNpadHandheldActivationMode, "GetNpadHandheldActivationMode"},
|
||||
{130, &Hid::SwapNpadAssignment, "SwapNpadAssignment"},
|
||||
{131, nullptr, "IsUnintendedHomeButtonInputProtectionEnabled"},
|
||||
{132, nullptr, "EnableUnintendedHomeButtonInputProtection"},
|
||||
{131, &Hid::IsUnintendedHomeButtonInputProtectionEnabled, "IsUnintendedHomeButtonInputProtectionEnabled"},
|
||||
{132, &Hid::EnableUnintendedHomeButtonInputProtection, "EnableUnintendedHomeButtonInputProtection"},
|
||||
{133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"},
|
||||
{134, nullptr, "SetNpadAnalogStickUseCenterClamp"},
|
||||
{135, nullptr, "SetNpadCaptureButtonAssignment"},
|
||||
@@ -458,6 +473,19 @@ void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) {
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void Hid::EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
[[maybe_unused]] const auto enable{rp.Pop<bool>()};
|
||||
const auto handle{rp.Pop<u32>()};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
|
||||
LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle,
|
||||
applet_resource_user_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto handle{rp.Pop<u32>()};
|
||||
@@ -781,6 +809,40 @@ void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto npad_id{rp.Pop<u32>()};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
|
||||
LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", npad_id,
|
||||
applet_resource_user_id);
|
||||
|
||||
auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<bool>(controller.IsUnintendedHomeButtonInputProtectionEnabled(npad_id));
|
||||
}
|
||||
|
||||
void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto unintended_home_button_input_protection{rp.Pop<bool>()};
|
||||
const auto npad_id{rp.Pop<u32>()};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
|
||||
LOG_WARNING(Service_HID,
|
||||
"(STUBBED) called, unintended_home_button_input_protection={}, npad_id={},"
|
||||
"applet_resource_user_id={}",
|
||||
npad_id, unintended_home_button_input_protection, applet_resource_user_id);
|
||||
|
||||
auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
|
||||
controller.SetUnintendedHomeButtonInputProtectionEnabled(
|
||||
unintended_home_button_input_protection, npad_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
@@ -802,18 +864,18 @@ void Hid::EndPermitVibrationSession(Kernel::HLERequestContext& ctx) {
|
||||
|
||||
void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto controller_id{rp.Pop<u32>()};
|
||||
const auto controller{rp.Pop<u32>()};
|
||||
const auto vibration_values{rp.PopRaw<Controller_NPad::Vibration>()};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
|
||||
LOG_DEBUG(Service_HID, "called, controller_id={}, applet_resource_user_id={}", controller_id,
|
||||
LOG_DEBUG(Service_HID, "called, controller={}, applet_resource_user_id={}", controller,
|
||||
applet_resource_user_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
applet_resource->GetController<Controller_NPad>(HidController::NPad)
|
||||
.VibrateController({controller_id}, {vibration_values});
|
||||
.VibrateController({controller}, {vibration_values});
|
||||
}
|
||||
|
||||
void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) {
|
||||
@@ -831,8 +893,6 @@ void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) {
|
||||
|
||||
std::memcpy(controller_list.data(), controllers.data(), controllers.size());
|
||||
std::memcpy(vibration_list.data(), vibrations.data(), vibrations.size());
|
||||
std::transform(controller_list.begin(), controller_list.end(), controller_list.begin(),
|
||||
[](u32 controller_id) { return controller_id - 3; });
|
||||
|
||||
applet_resource->GetController<Controller_NPad>(HidController::NPad)
|
||||
.VibrateController(controller_list, vibration_list);
|
||||
|
||||
@@ -65,10 +65,12 @@ private:
|
||||
|
||||
void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx);
|
||||
void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
|
||||
void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
|
||||
|
||||
std::shared_ptr<Kernel::SharedMemory> shared_mem;
|
||||
|
||||
std::shared_ptr<Core::Timing::EventType> pad_update_event;
|
||||
std::shared_ptr<Core::Timing::EventType> motion_update_event;
|
||||
Core::System& system;
|
||||
|
||||
std::array<std::unique_ptr<ControllerBase>, static_cast<size_t>(HidController::MaxControllers)>
|
||||
@@ -97,6 +99,7 @@ private:
|
||||
void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx);
|
||||
void StartSixAxisSensor(Kernel::HLERequestContext& ctx);
|
||||
void StopSixAxisSensor(Kernel::HLERequestContext& ctx);
|
||||
void EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx);
|
||||
void SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx);
|
||||
void GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx);
|
||||
void ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx);
|
||||
@@ -120,6 +123,8 @@ private:
|
||||
void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx);
|
||||
void GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx);
|
||||
void SwapNpadAssignment(Kernel::HLERequestContext& ctx);
|
||||
void IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx);
|
||||
void EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx);
|
||||
void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx);
|
||||
void EndPermitVibrationSession(Kernel::HLERequestContext& ctx);
|
||||
void SendVibrationValue(Kernel::HLERequestContext& ctx);
|
||||
|
||||
@@ -428,7 +428,7 @@ bool MiiManager::IsFullDatabase() const {
|
||||
}
|
||||
|
||||
u32 MiiManager::GetCount(SourceFlag source_flag) const {
|
||||
u32 count{};
|
||||
std::size_t count{};
|
||||
if ((source_flag & SourceFlag::Database) != SourceFlag::None) {
|
||||
// TODO(bunnei): We don't implement the Mii database, but when we do, update this
|
||||
count += 0;
|
||||
@@ -436,7 +436,7 @@ u32 MiiManager::GetCount(SourceFlag source_flag) const {
|
||||
if ((source_flag & SourceFlag::Default) != SourceFlag::None) {
|
||||
count += DefaultMiiCount;
|
||||
}
|
||||
return count;
|
||||
return static_cast<u32>(count);
|
||||
}
|
||||
|
||||
ResultVal<MiiInfo> MiiManager::UpdateLatest([[maybe_unused]] const MiiInfo& info,
|
||||
|
||||
@@ -22,6 +22,18 @@ u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector<u8>& input, const std::
|
||||
switch (static_cast<IoctlCommand>(command.raw)) {
|
||||
case IoctlCommand::IocSetNVMAPfdCommand:
|
||||
return SetNVMAPfd(input, output);
|
||||
case IoctlCommand::IocSubmit:
|
||||
return Submit(input, output);
|
||||
case IoctlCommand::IocGetSyncpoint:
|
||||
return GetSyncpoint(input, output);
|
||||
case IoctlCommand::IocGetWaitbase:
|
||||
return GetWaitbase(input, output);
|
||||
case IoctlCommand::IocMapBuffer:
|
||||
return MapBuffer(input, output);
|
||||
case IoctlCommand::IocMapBufferEx:
|
||||
return MapBufferEx(input, output);
|
||||
case IoctlCommand::IocUnmapBufferEx:
|
||||
return UnmapBufferEx(input, output);
|
||||
}
|
||||
|
||||
UNIMPLEMENTED_MSG("Unimplemented ioctl");
|
||||
@@ -30,11 +42,67 @@ u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector<u8>& input, const std::
|
||||
|
||||
u32 nvhost_nvdec::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||
IoctlSetNvmapFD params{};
|
||||
std::memcpy(¶ms, input.data(), input.size());
|
||||
std::memcpy(¶ms, input.data(), sizeof(IoctlSetNvmapFD));
|
||||
LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
|
||||
|
||||
nvmap_fd = params.nvmap_fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 nvhost_nvdec::Submit(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||
IoctlSubmit params{};
|
||||
std::memcpy(¶ms, input.data(), sizeof(IoctlSubmit));
|
||||
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
|
||||
std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmit));
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 nvhost_nvdec::GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||
IoctlGetSyncpoint params{};
|
||||
std::memcpy(¶ms, input.data(), sizeof(IoctlGetSyncpoint));
|
||||
LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown);
|
||||
params.value = 0; // Seems to be hard coded at 0
|
||||
std::memcpy(output.data(), ¶ms, sizeof(IoctlGetSyncpoint));
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 nvhost_nvdec::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||
IoctlGetWaitbase params{};
|
||||
std::memcpy(¶ms, input.data(), sizeof(IoctlGetWaitbase));
|
||||
LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown);
|
||||
params.value = 0; // Seems to be hard coded at 0
|
||||
std::memcpy(output.data(), ¶ms, sizeof(IoctlGetWaitbase));
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 nvhost_nvdec::MapBuffer(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||
IoctlMapBuffer params{};
|
||||
std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer));
|
||||
LOG_WARNING(Service_NVDRV, "(STUBBED) called with address={:08X}{:08X}", params.address_2,
|
||||
params.address_1);
|
||||
params.address_1 = 0;
|
||||
params.address_2 = 0;
|
||||
std::memcpy(output.data(), ¶ms, sizeof(IoctlMapBuffer));
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 nvhost_nvdec::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||
IoctlMapBufferEx params{};
|
||||
std::memcpy(¶ms, input.data(), sizeof(IoctlMapBufferEx));
|
||||
LOG_WARNING(Service_NVDRV, "(STUBBED) called with address={:08X}{:08X}", params.address_2,
|
||||
params.address_1);
|
||||
params.address_1 = 0;
|
||||
params.address_2 = 0;
|
||||
std::memcpy(output.data(), ¶ms, sizeof(IoctlMapBufferEx));
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 nvhost_nvdec::UnmapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||
IoctlUnmapBufferEx params{};
|
||||
std::memcpy(¶ms, input.data(), sizeof(IoctlUnmapBufferEx));
|
||||
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
|
||||
std::memcpy(output.data(), ¶ms, sizeof(IoctlUnmapBufferEx));
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace Service::Nvidia::Devices
|
||||
|
||||
@@ -23,16 +23,66 @@ public:
|
||||
private:
|
||||
enum class IoctlCommand : u32_le {
|
||||
IocSetNVMAPfdCommand = 0x40044801,
|
||||
IocSubmit = 0xC0400001,
|
||||
IocGetSyncpoint = 0xC0080002,
|
||||
IocGetWaitbase = 0xC0080003,
|
||||
IocMapBuffer = 0xC01C0009,
|
||||
IocMapBufferEx = 0xC0A40009,
|
||||
IocUnmapBufferEx = 0xC0A4000A,
|
||||
};
|
||||
|
||||
struct IoctlSetNvmapFD {
|
||||
u32_le nvmap_fd;
|
||||
};
|
||||
static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size");
|
||||
static_assert(sizeof(IoctlSetNvmapFD) == 0x4, "IoctlSetNvmapFD is incorrect size");
|
||||
|
||||
struct IoctlSubmit {
|
||||
INSERT_PADDING_BYTES(0x40); // TODO(DarkLordZach): RE this structure
|
||||
};
|
||||
static_assert(sizeof(IoctlSubmit) == 0x40, "IoctlSubmit has incorrect size");
|
||||
|
||||
struct IoctlGetSyncpoint {
|
||||
u32 unknown; // seems to be ignored? Nintendo added this
|
||||
u32 value;
|
||||
};
|
||||
static_assert(sizeof(IoctlGetSyncpoint) == 0x08, "IoctlGetSyncpoint has incorrect size");
|
||||
|
||||
struct IoctlGetWaitbase {
|
||||
u32 unknown; // seems to be ignored? Nintendo added this
|
||||
u32 value;
|
||||
};
|
||||
static_assert(sizeof(IoctlGetWaitbase) == 0x08, "IoctlGetWaitbase has incorrect size");
|
||||
|
||||
struct IoctlMapBuffer {
|
||||
u32 unknown;
|
||||
u32 address_1;
|
||||
u32 address_2;
|
||||
INSERT_PADDING_BYTES(0x10); // TODO(DarkLordZach): RE this structure
|
||||
};
|
||||
static_assert(sizeof(IoctlMapBuffer) == 0x1C, "IoctlMapBuffer is incorrect size");
|
||||
|
||||
struct IoctlMapBufferEx {
|
||||
u32 unknown;
|
||||
u32 address_1;
|
||||
u32 address_2;
|
||||
INSERT_PADDING_BYTES(0x98); // TODO(DarkLordZach): RE this structure
|
||||
};
|
||||
static_assert(sizeof(IoctlMapBufferEx) == 0xA4, "IoctlMapBufferEx has incorrect size");
|
||||
|
||||
struct IoctlUnmapBufferEx {
|
||||
INSERT_PADDING_BYTES(0xA4); // TODO(DarkLordZach): RE this structure
|
||||
};
|
||||
static_assert(sizeof(IoctlUnmapBufferEx) == 0xA4, "IoctlUnmapBufferEx has incorrect size");
|
||||
|
||||
u32_le nvmap_fd{};
|
||||
|
||||
u32 SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output);
|
||||
u32 Submit(const std::vector<u8>& input, std::vector<u8>& output);
|
||||
u32 GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output);
|
||||
u32 GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output);
|
||||
u32 MapBuffer(const std::vector<u8>& input, std::vector<u8>& output);
|
||||
u32 MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output);
|
||||
u32 UnmapBufferEx(const std::vector<u8>& input, std::vector<u8>& output);
|
||||
};
|
||||
|
||||
} // namespace Service::Nvidia::Devices
|
||||
|
||||
@@ -22,6 +22,18 @@ u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, const std::ve
|
||||
switch (static_cast<IoctlCommand>(command.raw)) {
|
||||
case IoctlCommand::IocSetNVMAPfdCommand:
|
||||
return SetNVMAPfd(input, output);
|
||||
case IoctlCommand::IocSubmit:
|
||||
return Submit(input, output);
|
||||
case IoctlCommand::IocGetSyncpoint:
|
||||
return GetSyncpoint(input, output);
|
||||
case IoctlCommand::IocGetWaitbase:
|
||||
return GetWaitbase(input, output);
|
||||
case IoctlCommand::IocMapBuffer:
|
||||
return MapBuffer(input, output);
|
||||
case IoctlCommand::IocMapBufferEx:
|
||||
return MapBuffer(input, output);
|
||||
case IoctlCommand::IocUnmapBufferEx:
|
||||
return UnmapBufferEx(input, output);
|
||||
}
|
||||
|
||||
UNIMPLEMENTED_MSG("Unimplemented ioctl");
|
||||
@@ -30,11 +42,71 @@ u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, const std::ve
|
||||
|
||||
u32 nvhost_vic::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||
IoctlSetNvmapFD params{};
|
||||
std::memcpy(¶ms, input.data(), input.size());
|
||||
std::memcpy(¶ms, input.data(), sizeof(IoctlSetNvmapFD));
|
||||
LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
|
||||
|
||||
nvmap_fd = params.nvmap_fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 nvhost_vic::Submit(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||
IoctlSubmit params{};
|
||||
std::memcpy(¶ms, input.data(), sizeof(IoctlSubmit));
|
||||
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
|
||||
|
||||
// Workaround for Luigi's Mansion 3, as nvhost_vic is not implemented for asynch GPU
|
||||
params.command_buffer = {};
|
||||
|
||||
std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmit));
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 nvhost_vic::GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||
IoctlGetSyncpoint params{};
|
||||
std::memcpy(¶ms, input.data(), sizeof(IoctlGetSyncpoint));
|
||||
LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown);
|
||||
params.value = 0; // Seems to be hard coded at 0
|
||||
std::memcpy(output.data(), ¶ms, sizeof(IoctlGetSyncpoint));
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 nvhost_vic::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||
IoctlGetWaitbase params{};
|
||||
std::memcpy(¶ms, input.data(), sizeof(IoctlGetWaitbase));
|
||||
LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown);
|
||||
params.value = 0; // Seems to be hard coded at 0
|
||||
std::memcpy(output.data(), ¶ms, sizeof(IoctlGetWaitbase));
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 nvhost_vic::MapBuffer(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||
IoctlMapBuffer params{};
|
||||
std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer));
|
||||
LOG_WARNING(Service_NVDRV, "(STUBBED) called with address={:08X}{:08X}", params.address_2,
|
||||
params.address_1);
|
||||
params.address_1 = 0;
|
||||
params.address_2 = 0;
|
||||
std::memcpy(output.data(), ¶ms, sizeof(IoctlMapBuffer));
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 nvhost_vic::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||
IoctlMapBufferEx params{};
|
||||
std::memcpy(¶ms, input.data(), sizeof(IoctlMapBufferEx));
|
||||
LOG_WARNING(Service_NVDRV, "(STUBBED) called with address={:08X}{:08X}", params.address_2,
|
||||
params.address_1);
|
||||
params.address_1 = 0;
|
||||
params.address_2 = 0;
|
||||
std::memcpy(output.data(), ¶ms, sizeof(IoctlMapBufferEx));
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 nvhost_vic::UnmapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||
IoctlUnmapBufferEx params{};
|
||||
std::memcpy(¶ms, input.data(), sizeof(IoctlUnmapBufferEx));
|
||||
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
|
||||
std::memcpy(output.data(), ¶ms, sizeof(IoctlUnmapBufferEx));
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace Service::Nvidia::Devices
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include "common/common_types.h"
|
||||
#include "common/swap.h"
|
||||
@@ -23,6 +24,12 @@ public:
|
||||
private:
|
||||
enum class IoctlCommand : u32_le {
|
||||
IocSetNVMAPfdCommand = 0x40044801,
|
||||
IocSubmit = 0xC0400001,
|
||||
IocGetSyncpoint = 0xC0080002,
|
||||
IocGetWaitbase = 0xC0080003,
|
||||
IocMapBuffer = 0xC01C0009,
|
||||
IocMapBufferEx = 0xC03C0009,
|
||||
IocUnmapBufferEx = 0xC03C000A,
|
||||
};
|
||||
|
||||
struct IoctlSetNvmapFD {
|
||||
@@ -30,9 +37,65 @@ private:
|
||||
};
|
||||
static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size");
|
||||
|
||||
struct IoctlSubmitCommandBuffer {
|
||||
u32 id;
|
||||
u32 offset;
|
||||
u32 count;
|
||||
};
|
||||
static_assert(sizeof(IoctlSubmitCommandBuffer) == 0xC,
|
||||
"IoctlSubmitCommandBuffer is incorrect size");
|
||||
|
||||
struct IoctlSubmit {
|
||||
u32 command_buffer_count;
|
||||
u32 relocations_count;
|
||||
u32 syncpt_count;
|
||||
u32 wait_count;
|
||||
std::array<IoctlSubmitCommandBuffer, 4> command_buffer;
|
||||
};
|
||||
static_assert(sizeof(IoctlSubmit) == 0x40, "IoctlSubmit is incorrect size");
|
||||
|
||||
struct IoctlGetSyncpoint {
|
||||
u32 unknown; // seems to be ignored? Nintendo added this
|
||||
u32 value;
|
||||
};
|
||||
static_assert(sizeof(IoctlGetSyncpoint) == 0x8, "IoctlGetSyncpoint is incorrect size");
|
||||
|
||||
struct IoctlGetWaitbase {
|
||||
u32 unknown; // seems to be ignored? Nintendo added this
|
||||
u32 value;
|
||||
};
|
||||
static_assert(sizeof(IoctlGetWaitbase) == 0x8, "IoctlGetWaitbase is incorrect size");
|
||||
|
||||
struct IoctlMapBuffer {
|
||||
u32 unknown;
|
||||
u32 address_1;
|
||||
u32 address_2;
|
||||
INSERT_PADDING_BYTES(0x10); // TODO(DarkLordZach): RE this structure
|
||||
};
|
||||
static_assert(sizeof(IoctlMapBuffer) == 0x1C, "IoctlMapBuffer is incorrect size");
|
||||
|
||||
struct IoctlMapBufferEx {
|
||||
u32 unknown;
|
||||
u32 address_1;
|
||||
u32 address_2;
|
||||
INSERT_PADDING_BYTES(0x30); // TODO(DarkLordZach): RE this structure
|
||||
};
|
||||
static_assert(sizeof(IoctlMapBufferEx) == 0x3C, "IoctlMapBufferEx is incorrect size");
|
||||
|
||||
struct IoctlUnmapBufferEx {
|
||||
INSERT_PADDING_BYTES(0x3C); // TODO(DarkLordZach): RE this structure
|
||||
};
|
||||
static_assert(sizeof(IoctlUnmapBufferEx) == 0x3C, "IoctlUnmapBufferEx is incorrect size");
|
||||
|
||||
u32_le nvmap_fd{};
|
||||
|
||||
u32 SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output);
|
||||
u32 Submit(const std::vector<u8>& input, std::vector<u8>& output);
|
||||
u32 GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output);
|
||||
u32 GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output);
|
||||
u32 MapBuffer(const std::vector<u8>& input, std::vector<u8>& output);
|
||||
u32 MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output);
|
||||
u32 UnmapBufferEx(const std::vector<u8>& input, std::vector<u8>& output);
|
||||
};
|
||||
|
||||
} // namespace Service::Nvidia::Devices
|
||||
|
||||
@@ -72,6 +72,23 @@
|
||||
|
||||
namespace Service {
|
||||
|
||||
/**
|
||||
* Creates a function string for logging, complete with the name (or header code, depending
|
||||
* on what's passed in) the port name, and all the cmd_buff arguments.
|
||||
*/
|
||||
[[maybe_unused]] static std::string MakeFunctionString(std::string_view name,
|
||||
std::string_view port_name,
|
||||
const u32* cmd_buff) {
|
||||
// Number of params == bits 0-5 + bits 6-11
|
||||
int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F);
|
||||
|
||||
std::string function_string = fmt::format("function '{}': port={}", name, port_name);
|
||||
for (int i = 1; i <= num_params; ++i) {
|
||||
function_string += fmt::format(", cmd_buff[{}]=0x{:X}", i, cmd_buff[i]);
|
||||
}
|
||||
return function_string;
|
||||
}
|
||||
|
||||
ServiceFrameworkBase::ServiceFrameworkBase(const char* service_name, u32 max_sessions,
|
||||
InvokerFn* handler_invoker)
|
||||
: service_name(service_name), max_sessions(max_sessions), handler_invoker(handler_invoker) {}
|
||||
|
||||
@@ -89,9 +89,9 @@ Network::Protocol Translate(Type type, Protocol protocol) {
|
||||
}
|
||||
}
|
||||
|
||||
u16 TranslatePollEventsToHost(u16 flags) {
|
||||
u16 result = 0;
|
||||
const auto translate = [&result, &flags](u16 from, u16 to) {
|
||||
u16 TranslatePollEventsToHost(u32 flags) {
|
||||
u32 result = 0;
|
||||
const auto translate = [&result, &flags](u32 from, u32 to) {
|
||||
if ((flags & from) != 0) {
|
||||
flags &= ~from;
|
||||
result |= to;
|
||||
@@ -105,12 +105,12 @@ u16 TranslatePollEventsToHost(u16 flags) {
|
||||
translate(POLL_NVAL, Network::POLL_NVAL);
|
||||
|
||||
UNIMPLEMENTED_IF_MSG(flags != 0, "Unimplemented flags={}", flags);
|
||||
return result;
|
||||
return static_cast<u16>(result);
|
||||
}
|
||||
|
||||
u16 TranslatePollEventsToGuest(u16 flags) {
|
||||
u16 result = 0;
|
||||
const auto translate = [&result, &flags](u16 from, u16 to) {
|
||||
u16 TranslatePollEventsToGuest(u32 flags) {
|
||||
u32 result = 0;
|
||||
const auto translate = [&result, &flags](u32 from, u32 to) {
|
||||
if ((flags & from) != 0) {
|
||||
flags &= ~from;
|
||||
result |= to;
|
||||
@@ -125,7 +125,7 @@ u16 TranslatePollEventsToGuest(u16 flags) {
|
||||
translate(Network::POLL_NVAL, POLL_NVAL);
|
||||
|
||||
UNIMPLEMENTED_IF_MSG(flags != 0, "Unimplemented flags={}", flags);
|
||||
return result;
|
||||
return static_cast<u16>(result);
|
||||
}
|
||||
|
||||
Network::SockAddrIn Translate(SockAddrIn value) {
|
||||
|
||||
@@ -31,10 +31,10 @@ Network::Type Translate(Type type);
|
||||
Network::Protocol Translate(Type type, Protocol protocol);
|
||||
|
||||
/// Translate abstract poll event flags to guest poll event flags
|
||||
u16 TranslatePollEventsToHost(u16 flags);
|
||||
u16 TranslatePollEventsToHost(u32 flags);
|
||||
|
||||
/// Translate guest poll event flags to abstract poll event flags
|
||||
u16 TranslatePollEventsToGuest(u16 flags);
|
||||
u16 TranslatePollEventsToGuest(u32 flags);
|
||||
|
||||
/// Translate guest socket address structure to abstract socket address structure
|
||||
Network::SockAddrIn Translate(SockAddrIn value);
|
||||
|
||||
@@ -820,7 +820,10 @@ static ResultCode ToCalendarTimeImpl(const TimeZoneRule& rules, s64 time, Calend
|
||||
const ResultCode result{
|
||||
ToCalendarTimeInternal(rules, time, calendar_time, calendar.additiona_info)};
|
||||
calendar.time.year = static_cast<s16>(calendar_time.year);
|
||||
calendar.time.month = calendar_time.month + 1; // Internal impl. uses 0-indexed month
|
||||
|
||||
// Internal impl. uses 0-indexed month
|
||||
calendar.time.month = static_cast<s8>(calendar_time.month + 1);
|
||||
|
||||
calendar.time.day = calendar_time.day;
|
||||
calendar.time.hour = calendar_time.hour;
|
||||
calendar.time.minute = calendar_time.minute;
|
||||
@@ -872,13 +875,15 @@ ResultCode TimeZoneManager::ToPosixTime(const TimeZoneRule& rules,
|
||||
const CalendarTime& calendar_time, s64& posix_time) const {
|
||||
posix_time = 0;
|
||||
|
||||
CalendarTimeInternal internal_time{};
|
||||
internal_time.year = calendar_time.year;
|
||||
internal_time.month = calendar_time.month - 1; // Internal impl. uses 0-indexed month
|
||||
internal_time.day = calendar_time.day;
|
||||
internal_time.hour = calendar_time.hour;
|
||||
internal_time.minute = calendar_time.minute;
|
||||
internal_time.second = calendar_time.second;
|
||||
CalendarTimeInternal internal_time{
|
||||
.year = calendar_time.year,
|
||||
// Internal impl. uses 0-indexed month
|
||||
.month = static_cast<s8>(calendar_time.month - 1),
|
||||
.day = calendar_time.day,
|
||||
.hour = calendar_time.hour,
|
||||
.minute = calendar_time.minute,
|
||||
.second = calendar_time.second,
|
||||
};
|
||||
|
||||
s32 hour{internal_time.hour};
|
||||
s32 minute{internal_time.minute};
|
||||
|
||||
@@ -159,7 +159,7 @@ public:
|
||||
header.data_size = static_cast<u32_le>(write_index - sizeof(Header));
|
||||
header.data_offset = sizeof(Header);
|
||||
header.objects_size = 4;
|
||||
header.objects_offset = sizeof(Header) + header.data_size;
|
||||
header.objects_offset = static_cast<u32>(sizeof(Header) + header.data_size);
|
||||
std::memcpy(buffer.data(), &header, sizeof(Header));
|
||||
|
||||
return buffer;
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Loader {
|
||||
|
||||
namespace {
|
||||
constexpr u32 PageAlignSize(u32 size) {
|
||||
return (size + Core::Memory::PAGE_MASK) & ~Core::Memory::PAGE_MASK;
|
||||
return static_cast<u32>((size + Core::Memory::PAGE_MASK) & ~Core::Memory::PAGE_MASK);
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ FileType AppLoader_NRO::IdentifyType(const FileSys::VirtualFile& file) {
|
||||
}
|
||||
|
||||
static constexpr u32 PageAlignSize(u32 size) {
|
||||
return (size + Core::Memory::PAGE_MASK) & ~Core::Memory::PAGE_MASK;
|
||||
return static_cast<u32>((size + Core::Memory::PAGE_MASK) & ~Core::Memory::PAGE_MASK);
|
||||
}
|
||||
|
||||
static bool LoadNroImpl(Kernel::Process& process, const std::vector<u8>& data,
|
||||
|
||||
@@ -47,7 +47,7 @@ std::vector<u8> DecompressSegment(const std::vector<u8>& compressed_data,
|
||||
}
|
||||
|
||||
constexpr u32 PageAlignSize(u32 size) {
|
||||
return (size + Core::Memory::PAGE_MASK) & ~Core::Memory::PAGE_MASK;
|
||||
return static_cast<u32>((size + Core::Memory::PAGE_MASK) & ~Core::Memory::PAGE_MASK);
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ struct NSOHeader {
|
||||
static_assert(sizeof(NSOHeader) == 0x100, "NSOHeader has incorrect size.");
|
||||
static_assert(std::is_trivially_copyable_v<NSOHeader>, "NSOHeader must be trivially copyable.");
|
||||
|
||||
constexpr u64 NSO_ARGUMENT_DATA_ALLOCATION_SIZE = 0x9000;
|
||||
constexpr u32 NSO_ARGUMENT_DATA_ALLOCATION_SIZE = 0x9000;
|
||||
|
||||
struct NSOArgumentHeader {
|
||||
u32_le allocated_size;
|
||||
|
||||
@@ -120,9 +120,9 @@ struct Memory::Impl {
|
||||
if ((addr & 1) == 0) {
|
||||
return Read<u16_le>(addr);
|
||||
} else {
|
||||
const u8 a{Read<u8>(addr)};
|
||||
const u8 b{Read<u8>(addr + sizeof(u8))};
|
||||
return (static_cast<u16>(b) << 8) | a;
|
||||
const u32 a{Read<u8>(addr)};
|
||||
const u32 b{Read<u8>(addr + sizeof(u8))};
|
||||
return static_cast<u16>((b << 8) | a);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,9 +130,9 @@ struct Memory::Impl {
|
||||
if ((addr & 3) == 0) {
|
||||
return Read<u32_le>(addr);
|
||||
} else {
|
||||
const u16 a{Read16(addr)};
|
||||
const u16 b{Read16(addr + sizeof(u16))};
|
||||
return (static_cast<u32>(b) << 16) | a;
|
||||
const u32 a{Read16(addr)};
|
||||
const u32 b{Read16(addr + sizeof(u16))};
|
||||
return (b << 16) | a;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -567,7 +567,7 @@ struct Memory::Impl {
|
||||
* @param page_table The page table to use to perform the mapping.
|
||||
* @param base The base address to begin mapping at.
|
||||
* @param size The total size of the range in bytes.
|
||||
* @param memory The memory to map.
|
||||
* @param target The target address to begin mapping from.
|
||||
* @param type The page type to map the memory as.
|
||||
*/
|
||||
void MapPages(Common::PageTable& page_table, VAddr base, u64 size, PAddr target,
|
||||
|
||||
@@ -153,8 +153,9 @@ std::vector<CheatEntry> TextCheatParser::Parse(std::string_view data) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto value = static_cast<u32>(std::stoul(hex, nullptr, 0x10));
|
||||
out[*current_entry].definition.opcodes[out[*current_entry].definition.num_opcodes++] =
|
||||
std::stoul(hex, nullptr, 0x10);
|
||||
value;
|
||||
|
||||
i += 8;
|
||||
} else {
|
||||
|
||||
@@ -238,14 +238,14 @@ SockAddrIn TranslateToSockAddrIn(sockaddr input_) {
|
||||
return result;
|
||||
}
|
||||
|
||||
u16 TranslatePollEvents(u16 events) {
|
||||
u16 result = 0;
|
||||
u16 TranslatePollEvents(u32 events) {
|
||||
u32 result = 0;
|
||||
|
||||
if (events & POLL_IN) {
|
||||
if ((events & POLL_IN) != 0) {
|
||||
events &= ~POLL_IN;
|
||||
result |= POLLIN;
|
||||
}
|
||||
if (events & POLL_PRI) {
|
||||
if ((events & POLL_PRI) != 0) {
|
||||
events &= ~POLL_PRI;
|
||||
#ifdef _WIN32
|
||||
LOG_WARNING(Service, "Winsock doesn't support POLLPRI");
|
||||
@@ -253,20 +253,20 @@ u16 TranslatePollEvents(u16 events) {
|
||||
result |= POLL_PRI;
|
||||
#endif
|
||||
}
|
||||
if (events & POLL_OUT) {
|
||||
if ((events & POLL_OUT) != 0) {
|
||||
events &= ~POLL_OUT;
|
||||
result |= POLLOUT;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED_IF_MSG(events != 0, "Unhandled guest events=0x{:x}", events);
|
||||
|
||||
return result;
|
||||
return static_cast<u16>(result);
|
||||
}
|
||||
|
||||
u16 TranslatePollRevents(u16 revents) {
|
||||
u16 result = 0;
|
||||
const auto translate = [&result, &revents](int host, unsigned guest) {
|
||||
if (revents & host) {
|
||||
u16 TranslatePollRevents(u32 revents) {
|
||||
u32 result = 0;
|
||||
const auto translate = [&result, &revents](u32 host, u32 guest) {
|
||||
if ((revents & host) != 0) {
|
||||
revents &= ~host;
|
||||
result |= guest;
|
||||
}
|
||||
@@ -280,7 +280,7 @@ u16 TranslatePollRevents(u16 revents) {
|
||||
|
||||
UNIMPLEMENTED_IF_MSG(revents != 0, "Unhandled host revents=0x{:x}", revents);
|
||||
|
||||
return result;
|
||||
return static_cast<u16>(result);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -350,7 +350,7 @@ std::pair<s32, Errno> Poll(std::vector<PollFD>& pollfds, s32 timeout) {
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < num; ++i) {
|
||||
pollfds[i].revents = TranslatePollRevents(host_pollfds[i].revents);
|
||||
pollfds[i].revents = TranslatePollRevents(static_cast<u32>(host_pollfds[i].revents));
|
||||
}
|
||||
|
||||
if (result > 0) {
|
||||
@@ -408,7 +408,7 @@ std::pair<Socket::AcceptResult, Errno> Socket::Accept() {
|
||||
|
||||
Errno Socket::Connect(SockAddrIn addr_in) {
|
||||
const sockaddr host_addr_in = TranslateFromSockAddrIn(addr_in);
|
||||
if (connect(fd, &host_addr_in, sizeof(host_addr_in)) != INVALID_SOCKET) {
|
||||
if (connect(fd, &host_addr_in, sizeof(host_addr_in)) != SOCKET_ERROR) {
|
||||
return Errno::SUCCESS;
|
||||
}
|
||||
|
||||
@@ -503,10 +503,10 @@ std::pair<s32, Errno> Socket::Recv(int flags, std::vector<u8>& message) {
|
||||
ASSERT(flags == 0);
|
||||
ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max()));
|
||||
|
||||
const int result =
|
||||
const auto result =
|
||||
recv(fd, reinterpret_cast<char*>(message.data()), static_cast<int>(message.size()), 0);
|
||||
if (result != SOCKET_ERROR) {
|
||||
return {result, Errno::SUCCESS};
|
||||
return {static_cast<s32>(result), Errno::SUCCESS};
|
||||
}
|
||||
|
||||
switch (const int ec = LastError()) {
|
||||
@@ -531,14 +531,14 @@ std::pair<s32, Errno> Socket::RecvFrom(int flags, std::vector<u8>& message, Sock
|
||||
socklen_t* const p_addrlen = addr ? &addrlen : nullptr;
|
||||
sockaddr* const p_addr_in = addr ? &addr_in : nullptr;
|
||||
|
||||
const int result = recvfrom(fd, reinterpret_cast<char*>(message.data()),
|
||||
static_cast<int>(message.size()), 0, p_addr_in, p_addrlen);
|
||||
const auto result = recvfrom(fd, reinterpret_cast<char*>(message.data()),
|
||||
static_cast<int>(message.size()), 0, p_addr_in, p_addrlen);
|
||||
if (result != SOCKET_ERROR) {
|
||||
if (addr) {
|
||||
ASSERT(addrlen == sizeof(addr_in));
|
||||
*addr = TranslateToSockAddrIn(addr_in);
|
||||
}
|
||||
return {result, Errno::SUCCESS};
|
||||
return {static_cast<s32>(result), Errno::SUCCESS};
|
||||
}
|
||||
|
||||
switch (const int ec = LastError()) {
|
||||
@@ -558,10 +558,10 @@ std::pair<s32, Errno> Socket::Send(const std::vector<u8>& message, int flags) {
|
||||
ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max()));
|
||||
ASSERT(flags == 0);
|
||||
|
||||
const int result = send(fd, reinterpret_cast<const char*>(message.data()),
|
||||
static_cast<int>(message.size()), 0);
|
||||
const auto result = send(fd, reinterpret_cast<const char*>(message.data()),
|
||||
static_cast<int>(message.size()), 0);
|
||||
if (result != SOCKET_ERROR) {
|
||||
return {result, Errno::SUCCESS};
|
||||
return {static_cast<s32>(result), Errno::SUCCESS};
|
||||
}
|
||||
|
||||
const int ec = LastError();
|
||||
@@ -591,10 +591,10 @@ std::pair<s32, Errno> Socket::SendTo(u32 flags, const std::vector<u8>& message,
|
||||
to = &host_addr_in;
|
||||
}
|
||||
|
||||
const int result = sendto(fd, reinterpret_cast<const char*>(message.data()),
|
||||
static_cast<int>(message.size()), 0, to, tolen);
|
||||
const auto result = sendto(fd, reinterpret_cast<const char*>(message.data()),
|
||||
static_cast<int>(message.size()), 0, to, tolen);
|
||||
if (result != SOCKET_ERROR) {
|
||||
return {result, Errno::SUCCESS};
|
||||
return {static_cast<s32>(result), Errno::SUCCESS};
|
||||
}
|
||||
|
||||
const int ec = LastError();
|
||||
|
||||
@@ -7,6 +7,8 @@ add_library(input_common STATIC
|
||||
main.h
|
||||
motion_emu.cpp
|
||||
motion_emu.h
|
||||
motion_from_button.cpp
|
||||
motion_from_button.h
|
||||
motion_input.cpp
|
||||
motion_input.h
|
||||
settings.cpp
|
||||
@@ -27,6 +29,35 @@ add_library(input_common STATIC
|
||||
udp/udp.h
|
||||
)
|
||||
|
||||
if (MSVC)
|
||||
target_compile_options(input_common PRIVATE
|
||||
# 'expression' : signed/unsigned mismatch
|
||||
/we4018
|
||||
# 'argument' : conversion from 'type1' to 'type2', possible loss of data (floating-point)
|
||||
/we4244
|
||||
# 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch
|
||||
/we4245
|
||||
# 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
|
||||
/we4254
|
||||
# 'var' : conversion from 'size_t' to 'type', possible loss of data
|
||||
/we4267
|
||||
# 'context' : truncation from 'type1' to 'type2'
|
||||
/we4305
|
||||
)
|
||||
else()
|
||||
target_compile_options(input_common PRIVATE
|
||||
-Werror=conversion
|
||||
-Werror=ignored-qualifiers
|
||||
-Werror=implicit-fallthrough
|
||||
-Werror=reorder
|
||||
-Werror=shadow
|
||||
-Werror=sign-compare
|
||||
-Werror=unused-but-set-parameter
|
||||
-Werror=unused-but-set-variable
|
||||
-Werror=unused-variable
|
||||
)
|
||||
endif()
|
||||
|
||||
if(SDL2_FOUND)
|
||||
target_sources(input_common PRIVATE
|
||||
sdl/sdl_impl.cpp
|
||||
|
||||
@@ -20,18 +20,22 @@ public:
|
||||
constexpr float SQRT_HALF = 0.707106781f;
|
||||
int x = 0, y = 0;
|
||||
|
||||
if (right->GetStatus())
|
||||
if (right->GetStatus()) {
|
||||
++x;
|
||||
if (left->GetStatus())
|
||||
}
|
||||
if (left->GetStatus()) {
|
||||
--x;
|
||||
if (up->GetStatus())
|
||||
}
|
||||
if (up->GetStatus()) {
|
||||
++y;
|
||||
if (down->GetStatus())
|
||||
}
|
||||
if (down->GetStatus()) {
|
||||
--y;
|
||||
}
|
||||
|
||||
float coef = modifier->GetStatus() ? modifier_scale : 1.0f;
|
||||
return std::make_tuple(x * coef * (y == 0 ? 1.0f : SQRT_HALF),
|
||||
y * coef * (x == 0 ? 1.0f : SQRT_HALF));
|
||||
const float coef = modifier->GetStatus() ? modifier_scale : 1.0f;
|
||||
return std::make_tuple(static_cast<float>(x) * coef * (y == 0 ? 1.0f : SQRT_HALF),
|
||||
static_cast<float>(y) * coef * (x == 0 ? 1.0f : SQRT_HALF));
|
||||
}
|
||||
|
||||
bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
|
||||
|
||||
@@ -15,11 +15,13 @@
|
||||
#endif
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "common/param_package.h"
|
||||
#include "input_common/gcadapter/gc_adapter.h"
|
||||
#include "input_common/settings.h"
|
||||
|
||||
namespace GCAdapter {
|
||||
|
||||
/// Used to loop through and assign button in poller
|
||||
// Used to loop through and assign button in poller
|
||||
constexpr std::array<PadButton, 12> PadButtonArray{
|
||||
PadButton::PAD_BUTTON_LEFT, PadButton::PAD_BUTTON_RIGHT, PadButton::PAD_BUTTON_DOWN,
|
||||
PadButton::PAD_BUTTON_UP, PadButton::PAD_TRIGGER_Z, PadButton::PAD_TRIGGER_R,
|
||||
@@ -27,6 +29,18 @@ constexpr std::array<PadButton, 12> PadButtonArray{
|
||||
PadButton::PAD_BUTTON_X, PadButton::PAD_BUTTON_Y, PadButton::PAD_BUTTON_START,
|
||||
};
|
||||
|
||||
static void PadToState(const GCPadStatus& pad, GCState& out_state) {
|
||||
for (const auto& button : PadButtonArray) {
|
||||
const auto button_key = static_cast<u16>(button);
|
||||
const auto button_value = (pad.button & button_key) != 0;
|
||||
out_state.buttons.insert_or_assign(static_cast<s32>(button_key), button_value);
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < pad.axis_values.size(); ++i) {
|
||||
out_state.axes.insert_or_assign(static_cast<u32>(i), pad.axis_values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Adapter::Adapter() {
|
||||
if (usb_adapter_handle != nullptr) {
|
||||
return;
|
||||
@@ -76,17 +90,17 @@ GCPadStatus Adapter::GetPadStatus(std::size_t port, const std::array<u8, 37>& ad
|
||||
|
||||
for (std::size_t i = 0; i < b1_buttons.size(); ++i) {
|
||||
if ((b1 & (1U << i)) != 0) {
|
||||
pad.button |= static_cast<u16>(b1_buttons[i]);
|
||||
pad.button = static_cast<u16>(pad.button | static_cast<u16>(b1_buttons[i]));
|
||||
}
|
||||
}
|
||||
|
||||
for (std::size_t j = 0; j < b2_buttons.size(); ++j) {
|
||||
if ((b2 & (1U << j)) != 0) {
|
||||
pad.button |= static_cast<u16>(b2_buttons[j]);
|
||||
pad.button = static_cast<u16>(pad.button | static_cast<u16>(b2_buttons[j]));
|
||||
}
|
||||
}
|
||||
for (PadAxes axis : axes) {
|
||||
const std::size_t index = static_cast<std::size_t>(axis);
|
||||
const auto index = static_cast<std::size_t>(axis);
|
||||
pad.axis_values[index] = adapter_payload[offset + 3 + index];
|
||||
}
|
||||
|
||||
@@ -98,17 +112,6 @@ GCPadStatus Adapter::GetPadStatus(std::size_t port, const std::array<u8, 37>& ad
|
||||
return pad;
|
||||
}
|
||||
|
||||
void Adapter::PadToState(const GCPadStatus& pad, GCState& state) {
|
||||
for (const auto& button : PadButtonArray) {
|
||||
const u16 button_value = static_cast<u16>(button);
|
||||
state.buttons.insert_or_assign(button_value, pad.button & button_value);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < pad.axis_values.size(); ++i) {
|
||||
state.axes.insert_or_assign(static_cast<u8>(i), pad.axis_values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void Adapter::Read() {
|
||||
LOG_DEBUG(Input, "GC Adapter Read() thread started");
|
||||
|
||||
@@ -248,7 +251,7 @@ void Adapter::GetGCEndpoint(libusb_device* device) {
|
||||
const libusb_interface_descriptor* interface = &interfaceContainer->altsetting[i];
|
||||
for (u8 e = 0; e < interface->bNumEndpoints; e++) {
|
||||
const libusb_endpoint_descriptor* endpoint = &interface->endpoint[e];
|
||||
if (endpoint->bEndpointAddress & LIBUSB_ENDPOINT_IN) {
|
||||
if ((endpoint->bEndpointAddress & LIBUSB_ENDPOINT_IN) != 0) {
|
||||
input_endpoint = endpoint->bEndpointAddress;
|
||||
} else {
|
||||
output_endpoint = endpoint->bEndpointAddress;
|
||||
@@ -292,6 +295,92 @@ void Adapter::Reset() {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Common::ParamPackage> Adapter::GetInputDevices() const {
|
||||
std::vector<Common::ParamPackage> devices;
|
||||
for (std::size_t port = 0; port < state.size(); ++port) {
|
||||
if (!DeviceConnected(port)) {
|
||||
continue;
|
||||
}
|
||||
std::string name = fmt::format("Gamecube Controller {}", port);
|
||||
devices.emplace_back(Common::ParamPackage{
|
||||
{"class", "gcpad"},
|
||||
{"display", std::move(name)},
|
||||
{"port", std::to_string(port)},
|
||||
});
|
||||
}
|
||||
return devices;
|
||||
}
|
||||
|
||||
InputCommon::ButtonMapping Adapter::GetButtonMappingForDevice(
|
||||
const Common::ParamPackage& params) const {
|
||||
// This list is missing ZL/ZR since those are not considered buttons.
|
||||
// We will add those afterwards
|
||||
// This list also excludes any button that can't be really mapped
|
||||
static constexpr std::array<std::pair<Settings::NativeButton::Values, PadButton>, 12>
|
||||
switch_to_gcadapter_button = {
|
||||
std::pair{Settings::NativeButton::A, PadButton::PAD_BUTTON_A},
|
||||
{Settings::NativeButton::B, PadButton::PAD_BUTTON_B},
|
||||
{Settings::NativeButton::X, PadButton::PAD_BUTTON_X},
|
||||
{Settings::NativeButton::Y, PadButton::PAD_BUTTON_Y},
|
||||
{Settings::NativeButton::Plus, PadButton::PAD_BUTTON_START},
|
||||
{Settings::NativeButton::DLeft, PadButton::PAD_BUTTON_LEFT},
|
||||
{Settings::NativeButton::DUp, PadButton::PAD_BUTTON_UP},
|
||||
{Settings::NativeButton::DRight, PadButton::PAD_BUTTON_RIGHT},
|
||||
{Settings::NativeButton::DDown, PadButton::PAD_BUTTON_DOWN},
|
||||
{Settings::NativeButton::SL, PadButton::PAD_TRIGGER_L},
|
||||
{Settings::NativeButton::SR, PadButton::PAD_TRIGGER_R},
|
||||
{Settings::NativeButton::R, PadButton::PAD_TRIGGER_Z},
|
||||
};
|
||||
if (!params.Has("port")) {
|
||||
return {};
|
||||
}
|
||||
|
||||
InputCommon::ButtonMapping mapping{};
|
||||
for (const auto& [switch_button, gcadapter_button] : switch_to_gcadapter_button) {
|
||||
Common::ParamPackage button_params({{"engine", "gcpad"}});
|
||||
button_params.Set("port", params.Get("port", 0));
|
||||
button_params.Set("button", static_cast<int>(gcadapter_button));
|
||||
mapping.insert_or_assign(switch_button, std::move(button_params));
|
||||
}
|
||||
|
||||
// Add the missing bindings for ZL/ZR
|
||||
static constexpr std::array<std::pair<Settings::NativeButton::Values, PadAxes>, 2>
|
||||
switch_to_gcadapter_axis = {
|
||||
std::pair{Settings::NativeButton::ZL, PadAxes::TriggerLeft},
|
||||
{Settings::NativeButton::ZR, PadAxes::TriggerRight},
|
||||
};
|
||||
for (const auto& [switch_button, gcadapter_axis] : switch_to_gcadapter_axis) {
|
||||
Common::ParamPackage button_params({{"engine", "gcpad"}});
|
||||
button_params.Set("port", params.Get("port", 0));
|
||||
button_params.Set("button", static_cast<int>(PadButton::PAD_STICK));
|
||||
button_params.Set("axis", static_cast<int>(gcadapter_axis));
|
||||
mapping.insert_or_assign(switch_button, std::move(button_params));
|
||||
}
|
||||
return mapping;
|
||||
}
|
||||
|
||||
InputCommon::AnalogMapping Adapter::GetAnalogMappingForDevice(
|
||||
const Common::ParamPackage& params) const {
|
||||
if (!params.Has("port")) {
|
||||
return {};
|
||||
}
|
||||
|
||||
InputCommon::AnalogMapping mapping = {};
|
||||
Common::ParamPackage left_analog_params;
|
||||
left_analog_params.Set("engine", "gcpad");
|
||||
left_analog_params.Set("port", params.Get("port", 0));
|
||||
left_analog_params.Set("axis_x", static_cast<int>(PadAxes::StickX));
|
||||
left_analog_params.Set("axis_y", static_cast<int>(PadAxes::StickY));
|
||||
mapping.insert_or_assign(Settings::NativeAnalog::LStick, std::move(left_analog_params));
|
||||
Common::ParamPackage right_analog_params;
|
||||
right_analog_params.Set("engine", "gcpad");
|
||||
right_analog_params.Set("port", params.Get("port", 0));
|
||||
right_analog_params.Set("axis_x", static_cast<int>(PadAxes::SubstickX));
|
||||
right_analog_params.Set("axis_y", static_cast<int>(PadAxes::SubstickY));
|
||||
mapping.insert_or_assign(Settings::NativeAnalog::RStick, std::move(right_analog_params));
|
||||
return mapping;
|
||||
}
|
||||
|
||||
bool Adapter::DeviceConnected(std::size_t port) const {
|
||||
return adapter_controllers_status[port] != ControllerTypes::None;
|
||||
}
|
||||
@@ -331,7 +420,7 @@ const std::array<GCState, 4>& Adapter::GetPadState() const {
|
||||
return state;
|
||||
}
|
||||
|
||||
int Adapter::GetOriginValue(int port, int axis) const {
|
||||
int Adapter::GetOriginValue(u32 port, u32 axis) const {
|
||||
return origin_status[port].axis_values[axis];
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <unordered_map>
|
||||
#include "common/common_types.h"
|
||||
#include "common/threadsafe_queue.h"
|
||||
#include "input_common/main.h"
|
||||
|
||||
struct libusb_context;
|
||||
struct libusb_device;
|
||||
@@ -59,7 +60,7 @@ struct GCPadStatus {
|
||||
|
||||
struct GCState {
|
||||
std::unordered_map<int, bool> buttons;
|
||||
std::unordered_map<int, u16> axes;
|
||||
std::unordered_map<u32, u16> axes;
|
||||
};
|
||||
|
||||
enum class ControllerTypes { None, Wired, Wireless };
|
||||
@@ -75,6 +76,10 @@ public:
|
||||
void BeginConfiguration();
|
||||
void EndConfiguration();
|
||||
|
||||
std::vector<Common::ParamPackage> GetInputDevices() const;
|
||||
InputCommon::ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) const;
|
||||
InputCommon::AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) const;
|
||||
|
||||
/// Returns true if there is a device connected to port
|
||||
bool DeviceConnected(std::size_t port) const;
|
||||
|
||||
@@ -84,13 +89,11 @@ public:
|
||||
std::array<GCState, 4>& GetPadState();
|
||||
const std::array<GCState, 4>& GetPadState() const;
|
||||
|
||||
int GetOriginValue(int port, int axis) const;
|
||||
int GetOriginValue(u32 port, u32 axis) const;
|
||||
|
||||
private:
|
||||
GCPadStatus GetPadStatus(std::size_t port, const std::array<u8, 37>& adapter_payload);
|
||||
|
||||
void PadToState(const GCPadStatus& pad, GCState& state);
|
||||
|
||||
void Read();
|
||||
|
||||
/// Resets status of device connected to port
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace InputCommon {
|
||||
|
||||
class GCButton final : public Input::ButtonDevice {
|
||||
public:
|
||||
explicit GCButton(int port_, int button_, const GCAdapter::Adapter* adapter)
|
||||
explicit GCButton(u32 port_, int button_, const GCAdapter::Adapter* adapter)
|
||||
: port(port_), button(button_), gcadapter(adapter) {}
|
||||
|
||||
~GCButton() override;
|
||||
@@ -28,14 +28,14 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
const int port;
|
||||
const u32 port;
|
||||
const int button;
|
||||
const GCAdapter::Adapter* gcadapter;
|
||||
};
|
||||
|
||||
class GCAxisButton final : public Input::ButtonDevice {
|
||||
public:
|
||||
explicit GCAxisButton(int port_, int axis_, float threshold_, bool trigger_if_greater_,
|
||||
explicit GCAxisButton(u32 port_, u32 axis_, float threshold_, bool trigger_if_greater_,
|
||||
const GCAdapter::Adapter* adapter)
|
||||
: port(port_), axis(axis_), threshold(threshold_), trigger_if_greater(trigger_if_greater_),
|
||||
gcadapter(adapter),
|
||||
@@ -56,8 +56,8 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
const int port;
|
||||
const int axis;
|
||||
const u32 port;
|
||||
const u32 axis;
|
||||
float threshold;
|
||||
bool trigger_if_greater;
|
||||
const GCAdapter::Adapter* gcadapter;
|
||||
@@ -70,8 +70,8 @@ GCButtonFactory::GCButtonFactory(std::shared_ptr<GCAdapter::Adapter> adapter_)
|
||||
GCButton::~GCButton() = default;
|
||||
|
||||
std::unique_ptr<Input::ButtonDevice> GCButtonFactory::Create(const Common::ParamPackage& params) {
|
||||
const int button_id = params.Get("button", 0);
|
||||
const int port = params.Get("port", 0);
|
||||
const auto button_id = params.Get("button", 0);
|
||||
const auto port = static_cast<u32>(params.Get("port", 0));
|
||||
|
||||
constexpr int PAD_STICK_ID = static_cast<u16>(GCAdapter::PadButton::PAD_STICK);
|
||||
|
||||
@@ -149,25 +149,27 @@ void GCButtonFactory::EndConfiguration() {
|
||||
|
||||
class GCAnalog final : public Input::AnalogDevice {
|
||||
public:
|
||||
GCAnalog(int port_, int axis_x_, int axis_y_, float deadzone_,
|
||||
const GCAdapter::Adapter* adapter, float range_)
|
||||
explicit GCAnalog(u32 port_, u32 axis_x_, u32 axis_y_, float deadzone_,
|
||||
const GCAdapter::Adapter* adapter, float range_)
|
||||
: port(port_), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_), gcadapter(adapter),
|
||||
origin_value_x(static_cast<float>(adapter->GetOriginValue(port_, axis_x_))),
|
||||
origin_value_y(static_cast<float>(adapter->GetOriginValue(port_, axis_y_))),
|
||||
range(range_) {}
|
||||
|
||||
float GetAxis(int axis) const {
|
||||
float GetAxis(u32 axis) const {
|
||||
if (gcadapter->DeviceConnected(port)) {
|
||||
std::lock_guard lock{mutex};
|
||||
const auto origin_value = axis % 2 == 0 ? origin_value_x : origin_value_y;
|
||||
return (gcadapter->GetPadState()[port].axes.at(axis) - origin_value) / (100.0f * range);
|
||||
const auto axis_value =
|
||||
static_cast<float>(gcadapter->GetPadState()[port].axes.at(axis));
|
||||
return (axis_value - origin_value) / (100.0f * range);
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
std::pair<float, float> GetAnalog(int axis_x, int axis_y) const {
|
||||
float x = GetAxis(axis_x);
|
||||
float y = GetAxis(axis_y);
|
||||
std::pair<float, float> GetAnalog(u32 analog_axis_x, u32 analog_axis_y) const {
|
||||
float x = GetAxis(analog_axis_x);
|
||||
float y = GetAxis(analog_axis_y);
|
||||
|
||||
// Make sure the coordinates are in the unit circle,
|
||||
// otherwise normalize it.
|
||||
@@ -208,9 +210,9 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
const int port;
|
||||
const int axis_x;
|
||||
const int axis_y;
|
||||
const u32 port;
|
||||
const u32 axis_x;
|
||||
const u32 axis_y;
|
||||
const float deadzone;
|
||||
const GCAdapter::Adapter* gcadapter;
|
||||
const float origin_value_x;
|
||||
@@ -231,11 +233,11 @@ GCAnalogFactory::GCAnalogFactory(std::shared_ptr<GCAdapter::Adapter> adapter_)
|
||||
* - "axis_y": the index of the axis to be bind as y-axis
|
||||
*/
|
||||
std::unique_ptr<Input::AnalogDevice> GCAnalogFactory::Create(const Common::ParamPackage& params) {
|
||||
const int port = params.Get("port", 0);
|
||||
const int axis_x = params.Get("axis_x", 0);
|
||||
const int axis_y = params.Get("axis_y", 1);
|
||||
const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f);
|
||||
const float range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f);
|
||||
const auto port = static_cast<u32>(params.Get("port", 0));
|
||||
const auto axis_x = static_cast<u32>(params.Get("axis_x", 0));
|
||||
const auto axis_y = static_cast<u32>(params.Get("axis_y", 1));
|
||||
const auto deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f);
|
||||
const auto range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f);
|
||||
|
||||
return std::make_unique<GCAnalog>(port, axis_x, axis_y, deadzone, adapter.get(), range);
|
||||
}
|
||||
@@ -256,7 +258,7 @@ Common::ParamPackage GCAnalogFactory::GetNextInput() {
|
||||
for (std::size_t port = 0; port < queue.size(); ++port) {
|
||||
while (queue[port].Pop(pad)) {
|
||||
if (pad.axis == GCAdapter::PadAxes::Undefined ||
|
||||
std::abs((pad.axis_value - 128.0f) / 128.0f) < 0.1) {
|
||||
std::abs((static_cast<float>(pad.axis_value) - 128.0f) / 128.0f) < 0.1f) {
|
||||
continue;
|
||||
}
|
||||
// An analog device needs two axes, so we need to store the axis for later and wait for
|
||||
|
||||
@@ -49,8 +49,9 @@ public:
|
||||
void ChangeKeyStatus(int key_code, bool pressed) {
|
||||
std::lock_guard guard{mutex};
|
||||
for (const KeyButtonPair& pair : list) {
|
||||
if (pair.key_code == key_code)
|
||||
if (pair.key_code == key_code) {
|
||||
pair.key_button->status.store(pressed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +74,7 @@ KeyButton::~KeyButton() {
|
||||
}
|
||||
|
||||
std::unique_ptr<Input::ButtonDevice> Keyboard::Create(const Common::ParamPackage& params) {
|
||||
int key_code = params.Get("code", 0);
|
||||
const int key_code = params.Get("code", 0);
|
||||
std::unique_ptr<KeyButton> button = std::make_unique<KeyButton>(key_button_list);
|
||||
key_button_list->AddKeyButton(key_code, button.get());
|
||||
return button;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "input_common/keyboard.h"
|
||||
#include "input_common/main.h"
|
||||
#include "input_common/motion_emu.h"
|
||||
#include "input_common/motion_from_button.h"
|
||||
#include "input_common/touch_from_button.h"
|
||||
#include "input_common/udp/client.h"
|
||||
#include "input_common/udp/udp.h"
|
||||
@@ -22,7 +23,7 @@ namespace InputCommon {
|
||||
|
||||
struct InputSubsystem::Impl {
|
||||
void Initialize() {
|
||||
auto gcadapter = std::make_shared<GCAdapter::Adapter>();
|
||||
gcadapter = std::make_shared<GCAdapter::Adapter>();
|
||||
gcbuttons = std::make_shared<GCButtonFactory>(gcadapter);
|
||||
Input::RegisterFactory<Input::ButtonDevice>("gcpad", gcbuttons);
|
||||
gcanalog = std::make_shared<GCAnalogFactory>(gcadapter);
|
||||
@@ -32,6 +33,8 @@ struct InputSubsystem::Impl {
|
||||
Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard);
|
||||
Input::RegisterFactory<Input::AnalogDevice>("analog_from_button",
|
||||
std::make_shared<AnalogFromButton>());
|
||||
Input::RegisterFactory<Input::MotionDevice>("keyboard",
|
||||
std::make_shared<MotionFromButton>());
|
||||
motion_emu = std::make_shared<MotionEmu>();
|
||||
Input::RegisterFactory<Input::MotionDevice>("motion_emu", motion_emu);
|
||||
Input::RegisterFactory<Input::TouchDevice>("touch_from_button",
|
||||
@@ -50,6 +53,7 @@ struct InputSubsystem::Impl {
|
||||
|
||||
void Shutdown() {
|
||||
Input::UnregisterFactory<Input::ButtonDevice>("keyboard");
|
||||
Input::UnregisterFactory<Input::MotionDevice>("keyboard");
|
||||
keyboard.reset();
|
||||
Input::UnregisterFactory<Input::AnalogDevice>("analog_from_button");
|
||||
Input::UnregisterFactory<Input::MotionDevice>("motion_emu");
|
||||
@@ -82,6 +86,8 @@ struct InputSubsystem::Impl {
|
||||
#endif
|
||||
auto udp_devices = udp->GetInputDevices();
|
||||
devices.insert(devices.end(), udp_devices.begin(), udp_devices.end());
|
||||
auto gcpad_devices = gcadapter->GetInputDevices();
|
||||
devices.insert(devices.end(), gcpad_devices.begin(), gcpad_devices.end());
|
||||
return devices;
|
||||
}
|
||||
|
||||
@@ -94,6 +100,9 @@ struct InputSubsystem::Impl {
|
||||
// TODO consider returning the SDL key codes for the default keybindings
|
||||
return {};
|
||||
}
|
||||
if (params.Get("class", "") == "gcpad") {
|
||||
return gcadapter->GetAnalogMappingForDevice(params);
|
||||
}
|
||||
#ifdef HAVE_SDL2
|
||||
if (params.Get("class", "") == "sdl") {
|
||||
return sdl->GetAnalogMappingForDevice(params);
|
||||
@@ -111,6 +120,9 @@ struct InputSubsystem::Impl {
|
||||
// TODO consider returning the SDL key codes for the default keybindings
|
||||
return {};
|
||||
}
|
||||
if (params.Get("class", "") == "gcpad") {
|
||||
return gcadapter->GetButtonMappingForDevice(params);
|
||||
}
|
||||
#ifdef HAVE_SDL2
|
||||
if (params.Get("class", "") == "sdl") {
|
||||
return sdl->GetButtonMappingForDevice(params);
|
||||
@@ -141,6 +153,7 @@ struct InputSubsystem::Impl {
|
||||
std::shared_ptr<UDPMotionFactory> udpmotion;
|
||||
std::shared_ptr<UDPTouchFactory> udptouch;
|
||||
std::shared_ptr<CemuhookUDP::Client> udp;
|
||||
std::shared_ptr<GCAdapter::Adapter> gcadapter;
|
||||
};
|
||||
|
||||
InputSubsystem::InputSubsystem() : impl{std::make_unique<Impl>()} {}
|
||||
@@ -183,6 +196,10 @@ ButtonMapping InputSubsystem::GetButtonMappingForDevice(const Common::ParamPacka
|
||||
return impl->GetButtonMappingForDevice(device);
|
||||
}
|
||||
|
||||
MotionMapping InputSubsystem::GetMotionMappingForDevice(const Common::ParamPackage& device) const {
|
||||
return impl->GetMotionMappingForDevice(device);
|
||||
}
|
||||
|
||||
GCAnalogFactory* InputSubsystem::GetGCAnalogs() {
|
||||
return impl->gcanalog.get();
|
||||
}
|
||||
|
||||
@@ -18,11 +18,11 @@ namespace InputCommon {
|
||||
// Implementation class of the motion emulation device
|
||||
class MotionEmuDevice {
|
||||
public:
|
||||
MotionEmuDevice(int update_millisecond, float sensitivity)
|
||||
: update_millisecond(update_millisecond),
|
||||
explicit MotionEmuDevice(int update_millisecond_, float sensitivity_)
|
||||
: update_millisecond(update_millisecond_),
|
||||
update_duration(std::chrono::duration_cast<std::chrono::steady_clock::duration>(
|
||||
std::chrono::milliseconds(update_millisecond))),
|
||||
sensitivity(sensitivity), motion_emu_thread(&MotionEmuDevice::MotionEmuThread, this) {}
|
||||
sensitivity(sensitivity_), motion_emu_thread(&MotionEmuDevice::MotionEmuThread, this) {}
|
||||
|
||||
~MotionEmuDevice() {
|
||||
if (motion_emu_thread.joinable()) {
|
||||
@@ -37,16 +37,18 @@ public:
|
||||
}
|
||||
|
||||
void Tilt(int x, int y) {
|
||||
auto mouse_move = Common::MakeVec(x, y) - mouse_origin;
|
||||
if (is_tilting) {
|
||||
std::lock_guard guard{tilt_mutex};
|
||||
if (mouse_move.x == 0 && mouse_move.y == 0) {
|
||||
tilt_angle = 0;
|
||||
} else {
|
||||
tilt_direction = mouse_move.Cast<float>();
|
||||
tilt_angle =
|
||||
std::clamp(tilt_direction.Normalize() * sensitivity, 0.0f, Common::PI * 0.5f);
|
||||
}
|
||||
if (!is_tilting) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard guard{tilt_mutex};
|
||||
const auto mouse_move = Common::MakeVec(x, y) - mouse_origin;
|
||||
if (mouse_move.x == 0 && mouse_move.y == 0) {
|
||||
tilt_angle = 0;
|
||||
} else {
|
||||
tilt_direction = mouse_move.Cast<float>();
|
||||
tilt_angle =
|
||||
std::clamp(tilt_direction.Normalize() * sensitivity, 0.0f, Common::PI * 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,11 +88,10 @@ private:
|
||||
void MotionEmuThread() {
|
||||
auto update_time = std::chrono::steady_clock::now();
|
||||
Common::Quaternion<float> q = Common::MakeQuaternion(Common::Vec3<float>(), 0);
|
||||
Common::Quaternion<float> old_q;
|
||||
|
||||
while (!shutdown_event.WaitUntil(update_time)) {
|
||||
update_time += update_duration;
|
||||
old_q = q;
|
||||
const Common::Quaternion<float> old_q = q;
|
||||
|
||||
{
|
||||
std::lock_guard guard{tilt_mutex};
|
||||
@@ -100,14 +101,14 @@ private:
|
||||
Common::MakeVec(-tilt_direction.y, 0.0f, tilt_direction.x), tilt_angle);
|
||||
}
|
||||
|
||||
auto inv_q = q.Inverse();
|
||||
const auto inv_q = q.Inverse();
|
||||
|
||||
// Set the gravity vector in world space
|
||||
auto gravity = Common::MakeVec(0.0f, -1.0f, 0.0f);
|
||||
|
||||
// Find the angular rate vector in world space
|
||||
auto angular_rate = ((q - old_q) * inv_q).xyz * 2;
|
||||
angular_rate *= 1000 / update_millisecond / Common::PI * 180;
|
||||
angular_rate *= static_cast<float>(1000 / update_millisecond) / Common::PI * 180.0f;
|
||||
|
||||
// Transform the two vectors from world space to 3DS space
|
||||
gravity = QuaternionRotate(inv_q, gravity);
|
||||
@@ -136,7 +137,7 @@ private:
|
||||
// can forward all the inputs to the implementation only when it is valid.
|
||||
class MotionEmuDeviceWrapper : public Input::MotionDevice {
|
||||
public:
|
||||
MotionEmuDeviceWrapper(int update_millisecond, float sensitivity) {
|
||||
explicit MotionEmuDeviceWrapper(int update_millisecond, float sensitivity) {
|
||||
device = std::make_shared<MotionEmuDevice>(update_millisecond, sensitivity);
|
||||
}
|
||||
|
||||
@@ -148,8 +149,8 @@ public:
|
||||
};
|
||||
|
||||
std::unique_ptr<Input::MotionDevice> MotionEmu::Create(const Common::ParamPackage& params) {
|
||||
int update_period = params.Get("update_period", 100);
|
||||
float sensitivity = params.Get("sensitivity", 0.01f);
|
||||
const int update_period = params.Get("update_period", 100);
|
||||
const float sensitivity = params.Get("sensitivity", 0.01f);
|
||||
auto device_wrapper = std::make_unique<MotionEmuDeviceWrapper>(update_period, sensitivity);
|
||||
// Previously created device is disconnected here. Having two motion devices for 3DS is not
|
||||
// expected.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user