Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05f722727b | ||
|
|
9f6852f93e |
No files matched your search
@@ -9,7 +9,6 @@ stages:
|
||||
displayName: 'build'
|
||||
jobs:
|
||||
- job: build
|
||||
timeoutInMinutes: 120
|
||||
displayName: 'windows-msvc'
|
||||
pool:
|
||||
vmImage: windows-2019
|
||||
|
||||
@@ -44,16 +44,6 @@ add_library(audio_core STATIC
|
||||
|
||||
create_target_directory_groups(audio_core)
|
||||
|
||||
if (NOT MSVC)
|
||||
target_compile_options(audio_core PRIVATE
|
||||
-Werror=ignored-qualifiers
|
||||
-Werror=implicit-fallthrough
|
||||
-Werror=reorder
|
||||
-Werror=sign-compare
|
||||
-Werror=unused-variable
|
||||
)
|
||||
endif()
|
||||
|
||||
target_link_libraries(audio_core PUBLIC common core)
|
||||
target_link_libraries(audio_core PRIVATE SoundTouch)
|
||||
|
||||
|
||||
@@ -3,13 +3,16 @@
|
||||
// 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,6 +21,7 @@
|
||||
#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::IsAudioRendererProcessingTimeLimit80PercentSupported() const {
|
||||
bool BehaviorInfo::IsAudioRenererProcessingTimeLimit80PercentSupported() const {
|
||||
return AudioCommon::IsRevisionSupported(5, user_revision);
|
||||
}
|
||||
|
||||
bool BehaviorInfo::IsAudioRendererProcessingTimeLimit75PercentSupported() const {
|
||||
bool BehaviorInfo::IsAudioRenererProcessingTimeLimit75PercentSupported() const {
|
||||
return AudioCommon::IsRevisionSupported(4, user_revision);
|
||||
}
|
||||
|
||||
bool BehaviorInfo::IsAudioRendererProcessingTimeLimit70PercentSupported() const {
|
||||
bool BehaviorInfo::IsAudioRenererProcessingTimeLimit70PercentSupported() const {
|
||||
return AudioCommon::IsRevisionSupported(1, user_revision);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,9 +49,9 @@ public:
|
||||
bool IsAdpcmLoopContextBugFixed() const;
|
||||
bool IsSplitterSupported() const;
|
||||
bool IsLongSizePreDelaySupported() const;
|
||||
bool IsAudioRendererProcessingTimeLimit80PercentSupported() const;
|
||||
bool IsAudioRendererProcessingTimeLimit75PercentSupported() const;
|
||||
bool IsAudioRendererProcessingTimeLimit70PercentSupported() const;
|
||||
bool IsAudioRenererProcessingTimeLimit80PercentSupported() const;
|
||||
bool IsAudioRenererProcessingTimeLimit75PercentSupported() const;
|
||||
bool IsAudioRenererProcessingTimeLimit70PercentSupported() const;
|
||||
bool IsElapsedFrameCountSupported() const;
|
||||
bool IsMemoryPoolForceMappingEnabled() const;
|
||||
bool IsFlushVoiceWaveBuffersSupported() const;
|
||||
|
||||
@@ -16,9 +16,8 @@ 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;
|
||||
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::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* data, std::size_t size, const ADPCM_Coeff& coeff,
|
||||
std::vector<s16> DecodeADPCM(const u8* const 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() >= static_cast<int>(mix_context.GetCount())) {
|
||||
if (destination_data->GetMixId() >= mix_context.GetCount()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ void CommandGenerator::PreCommand() {
|
||||
for (std::size_t i = 0; i < splitter_context.GetInfoCount(); i++) {
|
||||
const auto& base = splitter_context.GetInfo(i);
|
||||
std::string graph = fmt::format("b[{}]", i);
|
||||
const auto* head = base.GetHead();
|
||||
auto* head = base.GetHead();
|
||||
while (head != nullptr) {
|
||||
graph += fmt::format("->{}", head->GetMixId());
|
||||
head = head->GetNextDestination();
|
||||
@@ -214,7 +214,7 @@ void CommandGenerator::PostCommand() {
|
||||
|
||||
void CommandGenerator::GenerateDataSourceCommand(ServerVoiceInfo& voice_info, VoiceState& dsp_state,
|
||||
s32 channel) {
|
||||
const auto& in_params = voice_info.GetInParams();
|
||||
auto& in_params = voice_info.GetInParams();
|
||||
const auto depop = in_params.should_depop;
|
||||
|
||||
if (depop) {
|
||||
@@ -405,7 +405,7 @@ void CommandGenerator::GenerateBiquadFilterEffectCommand(s32 mix_buffer_offset,
|
||||
}
|
||||
|
||||
void CommandGenerator::GenerateAuxCommand(s32 mix_buffer_offset, EffectBase* info, bool enabled) {
|
||||
auto* aux = dynamic_cast<EffectAuxInfo*>(info);
|
||||
auto aux = dynamic_cast<EffectAuxInfo*>(info);
|
||||
const auto& params = aux->GetParams();
|
||||
if (aux->GetSendBuffer() != 0 && aux->GetRecvBuffer() != 0) {
|
||||
const auto max_channels = params.count;
|
||||
@@ -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 != static_cast<int>(worker_params.sample_count) &&
|
||||
if (samples_read != worker_params.sample_count &&
|
||||
samples_read <= params.sample_count) {
|
||||
std::memset(GetMixBuffer(output_index), 0, params.sample_count - samples_read);
|
||||
}
|
||||
@@ -571,7 +571,7 @@ void CommandGenerator::GenerateSubMixCommand(ServerMixInfo& mix_info) {
|
||||
if (dumping_frame) {
|
||||
LOG_DEBUG(Audio, "(DSP_TRACE) GenerateSubMixCommand");
|
||||
}
|
||||
const auto& in_params = mix_info.GetInParams();
|
||||
auto& in_params = mix_info.GetInParams();
|
||||
GenerateDepopForMixBuffersCommand(in_params.buffer_count, in_params.buffer_offset,
|
||||
in_params.sample_rate);
|
||||
|
||||
@@ -611,8 +611,7 @@ 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 < static_cast<std::size_t>(dest_in_params.buffer_count);
|
||||
i++) {
|
||||
for (std::size_t i = 0; i < 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,
|
||||
@@ -651,7 +650,7 @@ void CommandGenerator::GenerateFinalMixCommand() {
|
||||
LOG_DEBUG(Audio, "(DSP_TRACE) GenerateFinalMixCommand");
|
||||
}
|
||||
auto& mix_info = mix_context.GetFinalMixInfo();
|
||||
const auto& in_params = mix_info.GetInParams();
|
||||
const auto in_params = mix_info.GetInParams();
|
||||
|
||||
GenerateDepopForMixBuffersCommand(in_params.buffer_count, in_params.buffer_offset,
|
||||
in_params.sample_rate);
|
||||
@@ -675,7 +674,7 @@ void CommandGenerator::GenerateFinalMixCommand() {
|
||||
|
||||
s32 CommandGenerator::DecodePcm16(ServerVoiceInfo& voice_info, VoiceState& dsp_state,
|
||||
s32 sample_count, s32 channel, std::size_t mix_offset) {
|
||||
const auto& in_params = voice_info.GetInParams();
|
||||
auto& in_params = voice_info.GetInParams();
|
||||
const auto& wave_buffer = in_params.wave_buffer[dsp_state.wave_buffer_index];
|
||||
if (wave_buffer.buffer_address == 0) {
|
||||
return 0;
|
||||
@@ -705,7 +704,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 < static_cast<std::size_t>(samples_processed); i++) {
|
||||
for (std::size_t i = 0; i < samples_processed; i++) {
|
||||
sample_buffer[mix_offset + i] = buffer[i * channel_count + channel];
|
||||
}
|
||||
}
|
||||
@@ -715,7 +714,7 @@ s32 CommandGenerator::DecodePcm16(ServerVoiceInfo& voice_info, VoiceState& dsp_s
|
||||
|
||||
s32 CommandGenerator::DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_state,
|
||||
s32 sample_count, s32 channel, std::size_t mix_offset) {
|
||||
const auto& in_params = voice_info.GetInParams();
|
||||
auto& in_params = voice_info.GetInParams();
|
||||
const auto& wave_buffer = in_params.wave_buffer[dsp_state.wave_buffer_index];
|
||||
if (wave_buffer.buffer_address == 0) {
|
||||
return 0;
|
||||
@@ -727,9 +726,8 @@ s32 CommandGenerator::DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_s
|
||||
return 0;
|
||||
}
|
||||
|
||||
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::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;
|
||||
@@ -768,8 +766,8 @@ s32 CommandGenerator::DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_s
|
||||
val = std::clamp<s32>(val, -32768, 32767);
|
||||
// Advance output feedback.
|
||||
yn2 = yn1;
|
||||
yn1 = static_cast<s16>(val);
|
||||
return yn1;
|
||||
yn1 = val;
|
||||
return static_cast<s16>(val);
|
||||
};
|
||||
|
||||
std::size_t buffer_offset{};
|
||||
@@ -791,7 +789,7 @@ s32 CommandGenerator::DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_s
|
||||
position_in_frame += 2;
|
||||
|
||||
// Decode entire frame
|
||||
if (remaining_samples >= static_cast<int>(SAMPLES_PER_FRAME)) {
|
||||
if (remaining_samples >= SAMPLES_PER_FRAME) {
|
||||
for (std::size_t i = 0; i < SAMPLES_PER_FRAME / 2; i++) {
|
||||
|
||||
// Sample 1
|
||||
@@ -855,7 +853,7 @@ void CommandGenerator::DecodeFromWaveBuffers(ServerVoiceInfo& voice_info, s32* o
|
||||
VoiceState& dsp_state, s32 channel,
|
||||
s32 target_sample_rate, s32 sample_count,
|
||||
s32 node_id) {
|
||||
const auto& in_params = voice_info.GetInParams();
|
||||
auto& in_params = voice_info.GetInParams();
|
||||
if (dumping_frame) {
|
||||
LOG_DEBUG(Audio,
|
||||
"(DSP_TRACE) DecodeFromWaveBuffers, node_id={}, channel={}, "
|
||||
@@ -868,8 +866,8 @@ 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)));
|
||||
if (dsp_state.fraction + sample_count * resample_rate >
|
||||
static_cast<s32>(SCALED_MIX_BUFFER_SIZE - 4ULL)) {
|
||||
auto* output_base = output;
|
||||
if ((dsp_state.fraction + sample_count * resample_rate) > (SCALED_MIX_BUFFER_SIZE - 4ULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#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,7 +3,6 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/swap.h"
|
||||
|
||||
@@ -192,8 +192,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) {
|
||||
auto* impl = static_cast<CubebSinkStream*>(user_data);
|
||||
auto* buffer = static_cast<u8*>(output_buffer);
|
||||
CubebSinkStream* impl = static_cast<CubebSinkStream*>(user_data);
|
||||
u8* buffer = reinterpret_cast<u8*>(output_buffer);
|
||||
|
||||
if (!impl) {
|
||||
return {};
|
||||
|
||||
@@ -184,19 +184,19 @@ void EffectAuxInfo::UpdateForCommandGeneration() {
|
||||
}
|
||||
}
|
||||
|
||||
VAddr EffectAuxInfo::GetSendInfo() const {
|
||||
const VAddr EffectAuxInfo::GetSendInfo() const {
|
||||
return send_info;
|
||||
}
|
||||
|
||||
VAddr EffectAuxInfo::GetSendBuffer() const {
|
||||
const VAddr EffectAuxInfo::GetSendBuffer() const {
|
||||
return send_buffer;
|
||||
}
|
||||
|
||||
VAddr EffectAuxInfo::GetRecvInfo() const {
|
||||
const VAddr EffectAuxInfo::GetRecvInfo() const {
|
||||
return recv_info;
|
||||
}
|
||||
|
||||
VAddr EffectAuxInfo::GetRecvBuffer() const {
|
||||
const VAddr EffectAuxInfo::GetRecvBuffer() const {
|
||||
return recv_buffer;
|
||||
}
|
||||
|
||||
|
||||
@@ -166,13 +166,13 @@ public:
|
||||
std::array<u8, 0xa0> raw;
|
||||
};
|
||||
};
|
||||
static_assert(sizeof(InParams) == 0xc0, "InParams is an invalid size");
|
||||
static_assert(sizeof(EffectInfo::InParams) == 0xc0, "InParams is an invalid size");
|
||||
|
||||
struct OutParams {
|
||||
UsageStatus status{};
|
||||
INSERT_PADDING_BYTES(15);
|
||||
};
|
||||
static_assert(sizeof(OutParams) == 0x10, "OutParams is an invalid size");
|
||||
static_assert(sizeof(EffectInfo::OutParams) == 0x10, "OutParams is an invalid size");
|
||||
};
|
||||
|
||||
struct AuxAddress {
|
||||
@@ -184,8 +184,8 @@ struct AuxAddress {
|
||||
|
||||
class EffectBase {
|
||||
public:
|
||||
explicit EffectBase(EffectType effect_type);
|
||||
virtual ~EffectBase();
|
||||
EffectBase(EffectType effect_type);
|
||||
~EffectBase();
|
||||
|
||||
virtual void Update(EffectInfo::InParams& in_params) = 0;
|
||||
virtual void UpdateForCommandGeneration() = 0;
|
||||
@@ -206,7 +206,8 @@ protected:
|
||||
template <typename T>
|
||||
class EffectGeneric : public EffectBase {
|
||||
public:
|
||||
explicit EffectGeneric(EffectType effect_type) : EffectBase(effect_type) {}
|
||||
EffectGeneric(EffectType effect_type) : EffectBase::EffectBase(effect_type) {}
|
||||
~EffectGeneric() = default;
|
||||
|
||||
T& GetParams() {
|
||||
return internal_params;
|
||||
@@ -223,7 +224,7 @@ private:
|
||||
class EffectStubbed : public EffectBase {
|
||||
public:
|
||||
explicit EffectStubbed();
|
||||
~EffectStubbed() override;
|
||||
~EffectStubbed();
|
||||
|
||||
void Update(EffectInfo::InParams& in_params) override;
|
||||
void UpdateForCommandGeneration() override;
|
||||
@@ -232,7 +233,7 @@ public:
|
||||
class EffectI3dl2Reverb : public EffectGeneric<I3dl2ReverbParams> {
|
||||
public:
|
||||
explicit EffectI3dl2Reverb();
|
||||
~EffectI3dl2Reverb() override;
|
||||
~EffectI3dl2Reverb();
|
||||
|
||||
void Update(EffectInfo::InParams& in_params) override;
|
||||
void UpdateForCommandGeneration() override;
|
||||
@@ -244,7 +245,7 @@ private:
|
||||
class EffectBiquadFilter : public EffectGeneric<BiquadFilterParams> {
|
||||
public:
|
||||
explicit EffectBiquadFilter();
|
||||
~EffectBiquadFilter() override;
|
||||
~EffectBiquadFilter();
|
||||
|
||||
void Update(EffectInfo::InParams& in_params) override;
|
||||
void UpdateForCommandGeneration() override;
|
||||
@@ -253,14 +254,14 @@ public:
|
||||
class EffectAuxInfo : public EffectGeneric<AuxInfo> {
|
||||
public:
|
||||
explicit EffectAuxInfo();
|
||||
~EffectAuxInfo() override;
|
||||
~EffectAuxInfo();
|
||||
|
||||
void Update(EffectInfo::InParams& in_params) override;
|
||||
void UpdateForCommandGeneration() override;
|
||||
VAddr GetSendInfo() const;
|
||||
VAddr GetSendBuffer() const;
|
||||
VAddr GetRecvInfo() const;
|
||||
VAddr GetRecvBuffer() const;
|
||||
const VAddr GetSendInfo() const;
|
||||
const VAddr GetSendBuffer() const;
|
||||
const VAddr GetRecvInfo() const;
|
||||
const VAddr GetRecvBuffer() const;
|
||||
|
||||
private:
|
||||
VAddr send_info{};
|
||||
@@ -274,7 +275,7 @@ private:
|
||||
class EffectDelay : public EffectGeneric<DelayParams> {
|
||||
public:
|
||||
explicit EffectDelay();
|
||||
~EffectDelay() override;
|
||||
~EffectDelay();
|
||||
|
||||
void Update(EffectInfo::InParams& in_params) override;
|
||||
void UpdateForCommandGeneration() override;
|
||||
@@ -286,7 +287,7 @@ private:
|
||||
class EffectBufferMixer : public EffectGeneric<BufferMixerParams> {
|
||||
public:
|
||||
explicit EffectBufferMixer();
|
||||
~EffectBufferMixer() override;
|
||||
~EffectBufferMixer();
|
||||
|
||||
void Update(EffectInfo::InParams& in_params) override;
|
||||
void UpdateForCommandGeneration() override;
|
||||
@@ -295,7 +296,7 @@ public:
|
||||
class EffectReverb : public EffectGeneric<ReverbParams> {
|
||||
public:
|
||||
explicit EffectReverb();
|
||||
~EffectReverb() override;
|
||||
~EffectReverb();
|
||||
|
||||
void Update(EffectInfo::InParams& in_params) override;
|
||||
void UpdateForCommandGeneration() override;
|
||||
|
||||
@@ -64,6 +64,7 @@ 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;
|
||||
@@ -173,7 +174,7 @@ bool InfoUpdater::UpdateVoices(VoiceContext& voice_context,
|
||||
}
|
||||
// Voice states for each channel
|
||||
std::array<VoiceState*, AudioCommon::MAX_CHANNEL_COUNT> voice_states{};
|
||||
ASSERT(static_cast<std::size_t>(in_params.id) < voice_count);
|
||||
ASSERT(in_params.id < voice_count);
|
||||
|
||||
// Grab our current voice info
|
||||
auto& voice_info = voice_context.GetInfo(static_cast<std::size_t>(in_params.id));
|
||||
@@ -351,8 +352,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 (static_cast<std::size_t>(in.dest_mix_id) > mix_count &&
|
||||
in.dest_mix_id != AudioCommon::NO_MIX && in.mix_id != AudioCommon::FINAL_MIX) {
|
||||
if (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 < static_cast<s32>(info_count); distance_to_final_mix++) {
|
||||
for (; distance_to_final_mix < 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 >= static_cast<s32>(info_count)) {
|
||||
if (distance_to_final_mix >= 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 || static_cast<std::size_t>(header.send_id) > info_count) {
|
||||
if (header.send_id < 0 || 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 || static_cast<std::size_t>(header.splitter_id) > data_count) {
|
||||
if (header.splitter_id < 0 || 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 < static_cast<s32>(node_count));
|
||||
ASSERT(index < node_count);
|
||||
index_list[index_pos++] = index;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#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 {
|
||||
|
||||
@@ -488,11 +488,11 @@ s32 VoiceContext::DecodePcm16(s32* output_buffer, ServerWaveBuffer* wave_buffer,
|
||||
|
||||
// Fast path
|
||||
if (channel_count == 1) {
|
||||
for (std::ptrdiff_t i = 0; i < samples_processed; i++) {
|
||||
for (std::size_t i = 0; i < samples_processed; i++) {
|
||||
output_buffer[i] = buffer_data[i];
|
||||
}
|
||||
} else {
|
||||
for (std::ptrdiff_t i = 0; i < samples_processed; i++) {
|
||||
for (std::size_t i = 0; i < samples_processed; i++) {
|
||||
output_buffer[i] = buffer_data[i * channel_count + channel];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 final : public WallClock {
|
||||
class StandardWallClock : public WallClock {
|
||||
public:
|
||||
StandardWallClock(u64 emulated_cpu_frequency, u64 emulated_clock_frequency)
|
||||
: WallClock(emulated_cpu_frequency, emulated_clock_frequency, false) {
|
||||
|
||||
@@ -13,8 +13,6 @@ 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 final : public WallClock {
|
||||
class NativeClock : public WallClock {
|
||||
public:
|
||||
NativeClock(u64 emulated_cpu_frequency, u64 emulated_clock_frequency, u64 rtsc_frequency);
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ std::optional<Callback> DynarmicCP15::CompileInternalOperation(bool two, unsigne
|
||||
CoprocReg CRm, unsigned opc2) {
|
||||
LOG_CRITICAL(Core_ARM, "CP15: cdp{} p15, {}, {}, {}, {}, {}", two ? "2" : "", opc1, CRd, CRn,
|
||||
CRm, opc2);
|
||||
return std::nullopt;
|
||||
return {};
|
||||
}
|
||||
|
||||
CallbackOrAccessOneWord DynarmicCP15::CompileSendOneWord(bool two, unsigned opc1, CoprocReg CRn,
|
||||
@@ -115,7 +115,7 @@ std::optional<Callback> DynarmicCP15::CompileLoadWords(bool two, bool long_trans
|
||||
LOG_CRITICAL(Core_ARM, "CP15: mrrc{}{} p15, {}, [...]", two ? "2" : "",
|
||||
long_transfer ? "l" : "", CRd);
|
||||
}
|
||||
return std::nullopt;
|
||||
return {};
|
||||
}
|
||||
|
||||
std::optional<Callback> DynarmicCP15::CompileStoreWords(bool two, bool long_transfer, CoprocReg CRd,
|
||||
@@ -127,7 +127,7 @@ std::optional<Callback> DynarmicCP15::CompileStoreWords(bool two, bool long_tran
|
||||
LOG_CRITICAL(Core_ARM, "CP15: mrrc{}{} p15, {}, [...]", two ? "2" : "",
|
||||
long_transfer ? "l" : "", CRd);
|
||||
}
|
||||
return std::nullopt;
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
@@ -35,8 +35,8 @@ public:
|
||||
std::optional<u8> option) override;
|
||||
|
||||
ARM_Dynarmic_32& parent;
|
||||
u32 uprw = 0;
|
||||
u32 uro = 0;
|
||||
u32 uprw;
|
||||
u32 uro;
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
+4
-4
@@ -178,7 +178,7 @@ struct System::Impl {
|
||||
arp_manager.ResetAll();
|
||||
|
||||
telemetry_session = std::make_unique<Core::TelemetrySession>();
|
||||
service_manager = std::make_shared<Service::SM::ServiceManager>(kernel);
|
||||
service_manager = std::make_shared<Service::SM::ServiceManager>();
|
||||
|
||||
Service::Init(service_manager, system);
|
||||
GDBStub::DeferStart();
|
||||
@@ -221,7 +221,7 @@ struct System::Impl {
|
||||
telemetry_session->AddInitialInfo(*app_loader);
|
||||
auto main_process =
|
||||
Kernel::Process::Create(system, "main", Kernel::Process::ProcessType::Userland);
|
||||
const auto [load_result, load_parameters] = app_loader->Load(*main_process, system);
|
||||
const auto [load_result, load_parameters] = app_loader->Load(*main_process);
|
||||
if (load_result != Loader::ResultStatus::Success) {
|
||||
LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", static_cast<int>(load_result));
|
||||
Shutdown();
|
||||
@@ -629,11 +629,11 @@ Loader::AppLoader& System::GetAppLoader() const {
|
||||
return *impl->app_loader;
|
||||
}
|
||||
|
||||
void System::SetFilesystem(FileSys::VirtualFilesystem vfs) {
|
||||
void System::SetFilesystem(std::shared_ptr<FileSys::VfsFilesystem> vfs) {
|
||||
impl->virtual_filesystem = std::move(vfs);
|
||||
}
|
||||
|
||||
FileSys::VirtualFilesystem System::GetFilesystem() const {
|
||||
std::shared_ptr<FileSys::VfsFilesystem> System::GetFilesystem() const {
|
||||
return impl->virtual_filesystem;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -120,7 +120,7 @@ public:
|
||||
* Gets the instance of the System singleton class.
|
||||
* @returns Reference to the instance of the System singleton class.
|
||||
*/
|
||||
[[deprecated("Use of the global system instance is deprecated")]] static System& GetInstance() {
|
||||
static System& GetInstance() {
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
@@ -316,9 +316,9 @@ public:
|
||||
Service::SM::ServiceManager& ServiceManager();
|
||||
const Service::SM::ServiceManager& ServiceManager() const;
|
||||
|
||||
void SetFilesystem(FileSys::VirtualFilesystem vfs);
|
||||
void SetFilesystem(std::shared_ptr<FileSys::VfsFilesystem> vfs);
|
||||
|
||||
FileSys::VirtualFilesystem GetFilesystem() const;
|
||||
std::shared_ptr<FileSys::VfsFilesystem> GetFilesystem() const;
|
||||
|
||||
void RegisterCheatList(const std::vector<Memory::CheatEntry>& list,
|
||||
const std::array<u8, 0x20>& build_id, VAddr main_region_begin,
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include "common/file_util.h"
|
||||
#include "core/core.h"
|
||||
#include "core/file_sys/bis_factory.h"
|
||||
#include "core/file_sys/mode.h"
|
||||
#include "core/file_sys/registered_cache.h"
|
||||
#include "core/file_sys/vfs.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
@@ -81,11 +81,11 @@ VirtualDir BISFactory::OpenPartition(BisPartitionId id) const {
|
||||
}
|
||||
}
|
||||
|
||||
VirtualFile BISFactory::OpenPartitionStorage(BisPartitionId id,
|
||||
VirtualFilesystem file_system) const {
|
||||
VirtualFile BISFactory::OpenPartitionStorage(BisPartitionId id) const {
|
||||
auto& keys = Core::Crypto::KeyManager::Instance();
|
||||
Core::Crypto::PartitionDataManager pdm{file_system->OpenDirectory(
|
||||
Common::FS::GetUserPath(Common::FS::UserPath::SysDataDir), Mode::Read)};
|
||||
Core::Crypto::PartitionDataManager pdm{
|
||||
Core::System::GetInstance().GetFilesystem()->OpenDirectory(
|
||||
Common::FS::GetUserPath(Common::FS::UserPath::SysDataDir), Mode::Read)};
|
||||
keys.PopulateFromPartitionData(pdm);
|
||||
|
||||
switch (id) {
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
VirtualDir GetModificationDumpRoot(u64 title_id) const;
|
||||
|
||||
VirtualDir OpenPartition(BisPartitionId id) const;
|
||||
VirtualFile OpenPartitionStorage(BisPartitionId id, VirtualFilesystem file_system) const;
|
||||
VirtualFile OpenPartitionStorage(BisPartitionId id) const;
|
||||
|
||||
VirtualDir GetImageDirectory() const;
|
||||
|
||||
|
||||
@@ -323,7 +323,7 @@ bool NCA::ReadRomFSSection(const NCASectionHeader& section, const NCASectionTabl
|
||||
subsection_buckets.back().entries.push_back({section.bktr.relocation.offset, {0}, ctr_low});
|
||||
subsection_buckets.back().entries.push_back({size, {0}, 0});
|
||||
|
||||
std::optional<Core::Crypto::Key128> key;
|
||||
std::optional<Core::Crypto::Key128> key = {};
|
||||
if (encrypted) {
|
||||
if (has_rights_id) {
|
||||
status = Loader::ResultStatus::Success;
|
||||
@@ -442,18 +442,18 @@ std::optional<Core::Crypto::Key128> NCA::GetTitlekey() {
|
||||
memcpy(rights_id.data(), header.rights_id.data(), 16);
|
||||
if (rights_id == u128{}) {
|
||||
status = Loader::ResultStatus::ErrorInvalidRightsID;
|
||||
return std::nullopt;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto titlekey = keys.GetKey(Core::Crypto::S128KeyType::Titlekey, rights_id[1], rights_id[0]);
|
||||
if (titlekey == Core::Crypto::Key128{}) {
|
||||
status = Loader::ResultStatus::ErrorMissingTitlekey;
|
||||
return std::nullopt;
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!keys.HasKey(Core::Crypto::S128KeyType::Titlekek, master_key_id)) {
|
||||
status = Loader::ResultStatus::ErrorMissingTitlekek;
|
||||
return std::nullopt;
|
||||
return {};
|
||||
}
|
||||
|
||||
Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(
|
||||
@@ -477,7 +477,7 @@ VirtualFile NCA::Decrypt(const NCASectionHeader& s_header, VirtualFile in, u64 s
|
||||
case NCASectionCryptoType::BKTR:
|
||||
LOG_TRACE(Crypto, "called with mode=CTR, starting_offset={:016X}", starting_offset);
|
||||
{
|
||||
std::optional<Core::Crypto::Key128> key;
|
||||
std::optional<Core::Crypto::Key128> key = {};
|
||||
if (has_rights_id) {
|
||||
status = Loader::ResultStatus::Success;
|
||||
key = GetTitlekey();
|
||||
|
||||
@@ -83,7 +83,7 @@ enum class Language : u8 {
|
||||
Italian = 7,
|
||||
Dutch = 8,
|
||||
CanadianFrench = 9,
|
||||
Portuguese = 10,
|
||||
Portugese = 10,
|
||||
Russian = 11,
|
||||
Korean = 12,
|
||||
Taiwanese = 13,
|
||||
|
||||
@@ -245,11 +245,9 @@ void IPSwitchCompiler::Parse() {
|
||||
|
||||
// Read rest of patch
|
||||
while (true) {
|
||||
if (i + 1 >= lines.size()) {
|
||||
if (i + 1 >= lines.size())
|
||||
break;
|
||||
}
|
||||
|
||||
const auto& patch_line = lines[++i];
|
||||
const auto patch_line = lines[++i];
|
||||
|
||||
// Start of new patch
|
||||
if (StartsWith(patch_line, "@enabled") || StartsWith(patch_line, "@disabled")) {
|
||||
|
||||
@@ -12,49 +12,6 @@
|
||||
#include "core/file_sys/nca_patch.h"
|
||||
|
||||
namespace FileSys {
|
||||
namespace {
|
||||
template <bool Subsection, typename BlockType, typename BucketType>
|
||||
std::pair<std::size_t, std::size_t> SearchBucketEntry(u64 offset, const BlockType& block,
|
||||
const BucketType& buckets) {
|
||||
if constexpr (Subsection) {
|
||||
const auto& last_bucket = buckets[block.number_buckets - 1];
|
||||
if (offset >= last_bucket.entries[last_bucket.number_entries].address_patch) {
|
||||
return {block.number_buckets - 1, last_bucket.number_entries};
|
||||
}
|
||||
} else {
|
||||
ASSERT_MSG(offset <= block.size, "Offset is out of bounds in BKTR relocation block.");
|
||||
}
|
||||
|
||||
std::size_t bucket_id = std::count_if(
|
||||
block.base_offsets.begin() + 1, block.base_offsets.begin() + block.number_buckets,
|
||||
[&offset](u64 base_offset) { return base_offset <= offset; });
|
||||
|
||||
const auto& bucket = buckets[bucket_id];
|
||||
|
||||
if (bucket.number_entries == 1) {
|
||||
return {bucket_id, 0};
|
||||
}
|
||||
|
||||
std::size_t low = 0;
|
||||
std::size_t mid = 0;
|
||||
std::size_t high = bucket.number_entries - 1;
|
||||
while (low <= high) {
|
||||
mid = (low + high) / 2;
|
||||
if (bucket.entries[mid].address_patch > offset) {
|
||||
high = mid - 1;
|
||||
} else {
|
||||
if (mid == bucket.number_entries - 1 ||
|
||||
bucket.entries[mid + 1].address_patch > offset) {
|
||||
return {bucket_id, mid};
|
||||
}
|
||||
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
|
||||
UNREACHABLE_MSG("Offset could not be found in BKTR block.");
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
BKTR::BKTR(VirtualFile base_romfs_, VirtualFile bktr_romfs_, RelocationBlock relocation_,
|
||||
std::vector<RelocationBucket> relocation_buckets_, SubsectionBlock subsection_,
|
||||
@@ -153,6 +110,46 @@ std::size_t BKTR::Read(u8* data, std::size_t length, std::size_t offset) const {
|
||||
return raw_read;
|
||||
}
|
||||
|
||||
template <bool Subsection, typename BlockType, typename BucketType>
|
||||
std::pair<std::size_t, std::size_t> BKTR::SearchBucketEntry(u64 offset, BlockType block,
|
||||
BucketType buckets) const {
|
||||
if constexpr (Subsection) {
|
||||
const auto last_bucket = buckets[block.number_buckets - 1];
|
||||
if (offset >= last_bucket.entries[last_bucket.number_entries].address_patch)
|
||||
return {block.number_buckets - 1, last_bucket.number_entries};
|
||||
} else {
|
||||
ASSERT_MSG(offset <= block.size, "Offset is out of bounds in BKTR relocation block.");
|
||||
}
|
||||
|
||||
std::size_t bucket_id = std::count_if(
|
||||
block.base_offsets.begin() + 1, block.base_offsets.begin() + block.number_buckets,
|
||||
[&offset](u64 base_offset) { return base_offset <= offset; });
|
||||
|
||||
const auto bucket = buckets[bucket_id];
|
||||
|
||||
if (bucket.number_entries == 1)
|
||||
return {bucket_id, 0};
|
||||
|
||||
std::size_t low = 0;
|
||||
std::size_t mid = 0;
|
||||
std::size_t high = bucket.number_entries - 1;
|
||||
while (low <= high) {
|
||||
mid = (low + high) / 2;
|
||||
if (bucket.entries[mid].address_patch > offset) {
|
||||
high = mid - 1;
|
||||
} else {
|
||||
if (mid == bucket.number_entries - 1 ||
|
||||
bucket.entries[mid + 1].address_patch > offset) {
|
||||
return {bucket_id, mid};
|
||||
}
|
||||
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
|
||||
UNREACHABLE_MSG("Offset could not be found in BKTR block.");
|
||||
}
|
||||
|
||||
RelocationEntry BKTR::GetRelocationEntry(u64 offset) const {
|
||||
const auto res = SearchBucketEntry<false>(offset, relocation, relocation_buckets);
|
||||
return relocation_buckets[res.first].entries[res.second];
|
||||
|
||||
@@ -117,6 +117,10 @@ public:
|
||||
bool Rename(std::string_view name) override;
|
||||
|
||||
private:
|
||||
template <bool Subsection, typename BlockType, typename BucketType>
|
||||
std::pair<std::size_t, std::size_t> SearchBucketEntry(u64 offset, BlockType block,
|
||||
BucketType buckets) const;
|
||||
|
||||
RelocationEntry GetRelocationEntry(u64 offset) const;
|
||||
RelocationEntry GetNextRelocationEntry(u64 offset) const;
|
||||
|
||||
|
||||
@@ -76,7 +76,8 @@ VirtualDir FindSubdirectoryCaseless(const VirtualDir dir, std::string_view name)
|
||||
}
|
||||
|
||||
std::optional<std::vector<Core::Memory::CheatEntry>> ReadCheatFileFromFolder(
|
||||
u64 title_id, const PatchManager::BuildID& build_id_, const VirtualDir& base_path, bool upper) {
|
||||
const Core::System& system, u64 title_id, const PatchManager::BuildID& build_id_,
|
||||
const VirtualDir& base_path, bool upper) {
|
||||
const auto build_id_raw = Common::HexToString(build_id_, upper);
|
||||
const auto build_id = build_id_raw.substr(0, sizeof(u64) * 2);
|
||||
const auto file = base_path->GetFile(fmt::format("{}.txt", build_id));
|
||||
@@ -94,8 +95,9 @@ std::optional<std::vector<Core::Memory::CheatEntry>> ReadCheatFileFromFolder(
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const Core::Memory::TextCheatParser parser;
|
||||
return parser.Parse(std::string_view(reinterpret_cast<const char*>(data.data()), data.size()));
|
||||
Core::Memory::TextCheatParser parser;
|
||||
return parser.Parse(system,
|
||||
std::string_view(reinterpret_cast<const char*>(data.data()), data.size()));
|
||||
}
|
||||
|
||||
void AppendCommaIfNotEmpty(std::string& to, std::string_view with) {
|
||||
@@ -333,12 +335,14 @@ std::vector<Core::Memory::CheatEntry> PatchManager::CreateCheatList(
|
||||
|
||||
auto cheats_dir = FindSubdirectoryCaseless(subdir, "cheats");
|
||||
if (cheats_dir != nullptr) {
|
||||
if (const auto res = ReadCheatFileFromFolder(title_id, build_id_, cheats_dir, true)) {
|
||||
auto res = ReadCheatFileFromFolder(system, title_id, build_id_, cheats_dir, true);
|
||||
if (res.has_value()) {
|
||||
std::copy(res->begin(), res->end(), std::back_inserter(out));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (const auto res = ReadCheatFileFromFolder(title_id, build_id_, cheats_dir, false)) {
|
||||
res = ReadCheatFileFromFolder(system, title_id, build_id_, cheats_dir, false);
|
||||
if (res.has_value()) {
|
||||
std::copy(res->begin(), res->end(), std::back_inserter(out));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core.h"
|
||||
#include "core/file_sys/card_image.h"
|
||||
#include "core/file_sys/content_archive.h"
|
||||
#include "core/file_sys/nca_metadata.h"
|
||||
@@ -18,9 +19,7 @@
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
RomFSFactory::RomFSFactory(Loader::AppLoader& app_loader, ContentProvider& provider,
|
||||
Service::FileSystem::FileSystemController& controller)
|
||||
: content_provider{provider}, filesystem_controller{controller} {
|
||||
RomFSFactory::RomFSFactory(Loader::AppLoader& app_loader) {
|
||||
// Load the RomFS from the app
|
||||
if (app_loader.ReadRomFS(file) != Loader::ResultStatus::Success) {
|
||||
LOG_ERROR(Service_FS, "Unable to read RomFS!");
|
||||
@@ -47,38 +46,39 @@ ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess(u64 current_process_titl
|
||||
|
||||
ResultVal<VirtualFile> RomFSFactory::Open(u64 title_id, StorageId storage,
|
||||
ContentRecordType type) const {
|
||||
const std::shared_ptr<NCA> res = GetEntry(title_id, storage, type);
|
||||
std::shared_ptr<NCA> res;
|
||||
|
||||
switch (storage) {
|
||||
case StorageId::None:
|
||||
res = Core::System::GetInstance().GetContentProvider().GetEntry(title_id, type);
|
||||
break;
|
||||
case StorageId::NandSystem:
|
||||
res =
|
||||
Core::System::GetInstance().GetFileSystemController().GetSystemNANDContents()->GetEntry(
|
||||
title_id, type);
|
||||
break;
|
||||
case StorageId::NandUser:
|
||||
res = Core::System::GetInstance().GetFileSystemController().GetUserNANDContents()->GetEntry(
|
||||
title_id, type);
|
||||
break;
|
||||
case StorageId::SdCard:
|
||||
res = Core::System::GetInstance().GetFileSystemController().GetSDMCContents()->GetEntry(
|
||||
title_id, type);
|
||||
break;
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Unimplemented storage_id={:02X}", static_cast<u8>(storage));
|
||||
}
|
||||
|
||||
if (res == nullptr) {
|
||||
// TODO(DarkLordZach): Find the right error code to use here
|
||||
return RESULT_UNKNOWN;
|
||||
}
|
||||
|
||||
const auto romfs = res->GetRomFS();
|
||||
if (romfs == nullptr) {
|
||||
// TODO(DarkLordZach): Find the right error code to use here
|
||||
return RESULT_UNKNOWN;
|
||||
}
|
||||
|
||||
return MakeResult<VirtualFile>(romfs);
|
||||
}
|
||||
|
||||
std::shared_ptr<NCA> RomFSFactory::GetEntry(u64 title_id, StorageId storage,
|
||||
ContentRecordType type) const {
|
||||
switch (storage) {
|
||||
case StorageId::None:
|
||||
return content_provider.GetEntry(title_id, type);
|
||||
case StorageId::NandSystem:
|
||||
return filesystem_controller.GetSystemNANDContents()->GetEntry(title_id, type);
|
||||
case StorageId::NandUser:
|
||||
return filesystem_controller.GetUserNANDContents()->GetEntry(title_id, type);
|
||||
case StorageId::SdCard:
|
||||
return filesystem_controller.GetSDMCContents()->GetEntry(title_id, type);
|
||||
case StorageId::Host:
|
||||
case StorageId::GameCard:
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Unimplemented storage_id={:02X}", static_cast<u8>(storage));
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace FileSys
|
||||
@@ -13,15 +13,8 @@ namespace Loader {
|
||||
class AppLoader;
|
||||
} // namespace Loader
|
||||
|
||||
namespace Service::FileSystem {
|
||||
class FileSystemController;
|
||||
}
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
class ContentProvider;
|
||||
class NCA;
|
||||
|
||||
enum class ContentRecordType : u8;
|
||||
|
||||
enum class StorageId : u8 {
|
||||
@@ -36,26 +29,18 @@ enum class StorageId : u8 {
|
||||
/// File system interface to the RomFS archive
|
||||
class RomFSFactory {
|
||||
public:
|
||||
explicit RomFSFactory(Loader::AppLoader& app_loader, ContentProvider& provider,
|
||||
Service::FileSystem::FileSystemController& controller);
|
||||
explicit RomFSFactory(Loader::AppLoader& app_loader);
|
||||
~RomFSFactory();
|
||||
|
||||
void SetPackedUpdate(VirtualFile update_raw);
|
||||
[[nodiscard]] ResultVal<VirtualFile> OpenCurrentProcess(u64 current_process_title_id) const;
|
||||
[[nodiscard]] ResultVal<VirtualFile> Open(u64 title_id, StorageId storage,
|
||||
ContentRecordType type) const;
|
||||
ResultVal<VirtualFile> OpenCurrentProcess(u64 current_process_title_id) const;
|
||||
ResultVal<VirtualFile> Open(u64 title_id, StorageId storage, ContentRecordType type) const;
|
||||
|
||||
private:
|
||||
[[nodiscard]] std::shared_ptr<NCA> GetEntry(u64 title_id, StorageId storage,
|
||||
ContentRecordType type) const;
|
||||
|
||||
VirtualFile file;
|
||||
VirtualFile update_raw;
|
||||
bool updatable;
|
||||
u64 ivfc_offset;
|
||||
|
||||
ContentProvider& content_provider;
|
||||
Service::FileSystem::FileSystemController& filesystem_controller;
|
||||
};
|
||||
|
||||
} // namespace FileSys
|
||||
@@ -267,9 +267,9 @@ void NSP::ReadNCAs(const std::vector<VirtualFile>& files) {
|
||||
}
|
||||
|
||||
const CNMT cnmt(inner_file);
|
||||
auto& ncas_title = ncas[cnmt.GetTitleID()];
|
||||
|
||||
ncas[cnmt.GetTitleID()][{cnmt.GetType(), ContentRecordType::Meta}] = nca;
|
||||
|
||||
ncas_title[{cnmt.GetType(), ContentRecordType::Meta}] = nca;
|
||||
for (const auto& rec : cnmt.GetContentRecords()) {
|
||||
const auto id_string = Common::HexToString(rec.nca_id, false);
|
||||
auto next_file = pfs->GetFile(fmt::format("{}.nca", id_string));
|
||||
@@ -287,12 +287,12 @@ 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();
|
||||
program_status[cnmt.GetTitleID()] = next_nca->GetStatus();
|
||||
}
|
||||
if (next_nca->GetStatus() == Loader::ResultStatus::Success ||
|
||||
(next_nca->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS &&
|
||||
(next_nca->GetTitleId() & 0x800) != 0)) {
|
||||
ncas[next_nca->GetTitleId()][{cnmt.GetType(), rec.type}] = std::move(next_nca);
|
||||
(cnmt.GetTitleID() & 0x800) != 0)) {
|
||||
ncas_title[{cnmt.GetType(), rec.type}] = std::move(next_nca);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -169,12 +169,11 @@ VfsDirectory::~VfsDirectory() = default;
|
||||
|
||||
std::optional<u8> VfsFile::ReadByte(std::size_t offset) const {
|
||||
u8 out{};
|
||||
const std::size_t size = Read(&out, sizeof(u8), offset);
|
||||
if (size == 1) {
|
||||
std::size_t size = Read(&out, 1, offset);
|
||||
if (size == 1)
|
||||
return out;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<u8> VfsFile::ReadBytes(std::size_t size, std::size_t offset) const {
|
||||
|
||||
@@ -58,11 +58,10 @@ std::size_t OffsetVfsFile::Write(const u8* data, std::size_t length, std::size_t
|
||||
}
|
||||
|
||||
std::optional<u8> OffsetVfsFile::ReadByte(std::size_t r_offset) const {
|
||||
if (r_offset >= size) {
|
||||
return std::nullopt;
|
||||
}
|
||||
if (r_offset < size)
|
||||
return file->ReadByte(offset + r_offset);
|
||||
|
||||
return file->ReadByte(offset + r_offset);
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<u8> OffsetVfsFile::ReadBytes(std::size_t r_size, std::size_t r_offset) const {
|
||||
|
||||
@@ -54,11 +54,9 @@ public:
|
||||
}
|
||||
|
||||
std::optional<u8> ReadByte(std::size_t offset) const override {
|
||||
if (offset >= size) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return value;
|
||||
if (offset < size)
|
||||
return value;
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<u8> ReadBytes(std::size_t length, std::size_t offset) const override {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#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"
|
||||
@@ -13,9 +14,6 @@ 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,
|
||||
@@ -23,7 +21,9 @@ void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callb
|
||||
LOG_INFO(Service_HID, "called, deducing the best configuration based on the given parameters!");
|
||||
|
||||
auto& npad =
|
||||
service_manager.GetService<Service::HID::Hid>("hid")
|
||||
Core::System::GetInstance()
|
||||
.ServiceManager()
|
||||
.GetService<Service::HID::Hid>("hid")
|
||||
->GetAppletResource()
|
||||
->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad);
|
||||
|
||||
|
||||
@@ -8,10 +8,6 @@
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Service::SM {
|
||||
class ServiceManager;
|
||||
}
|
||||
|
||||
namespace Core::Frontend {
|
||||
|
||||
using BorderColor = std::array<u8, 4>;
|
||||
@@ -43,14 +39,10 @@ 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
|
||||
@@ -33,9 +33,6 @@ 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.
|
||||
@@ -122,11 +119,11 @@ using ButtonDevice = InputDevice<bool>;
|
||||
using AnalogDevice = InputDevice<std::tuple<float, float>>;
|
||||
|
||||
/**
|
||||
* A motion status is an object that returns a tuple of accelerometer state vector,
|
||||
* gyroscope state vector, rotation state vector and orientation state matrix.
|
||||
* A motion device is an input device that returns a tuple of accelerometer state vector and
|
||||
* gyroscope state vector.
|
||||
*
|
||||
* For both vectors:
|
||||
* x+ is the same direction as RIGHT on D-pad.
|
||||
* x+ is the same direction as LEFT on D-pad.
|
||||
* y+ is normal to the touch screen, pointing outward.
|
||||
* z+ is the same direction as UP on D-pad.
|
||||
*
|
||||
@@ -136,22 +133,8 @@ using AnalogDevice = InputDevice<std::tuple<float, float>>;
|
||||
* For gyroscope state vector:
|
||||
* Orientation is determined by right-hand rule.
|
||||
* Units: deg/sec
|
||||
*
|
||||
* For rotation state vector
|
||||
* Units: rotations
|
||||
*
|
||||
* For orientation state matrix
|
||||
* x vector
|
||||
* y vector
|
||||
* z vector
|
||||
*/
|
||||
using MotionStatus = std::tuple<Common::Vec3<float>, Common::Vec3<float>, Common::Vec3<float>,
|
||||
std::array<Common::Vec3f, 3>>;
|
||||
|
||||
/**
|
||||
* A motion device is an input device that returns a motion status object
|
||||
*/
|
||||
using MotionDevice = InputDevice<MotionStatus>;
|
||||
using MotionDevice = InputDevice<std::tuple<Common::Vec3<float>, Common::Vec3<float>>>;
|
||||
|
||||
/**
|
||||
* A touch device is an input device that returns a tuple of two floats and a bool. The floats are
|
||||
|
||||
@@ -774,17 +774,6 @@ 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,7 +34,6 @@ 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, &ACC_U0::LoadOpenContext, "LoadOpenContext"}, // 5.0.0+
|
||||
{130, nullptr, "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+
|
||||
|
||||
@@ -1192,7 +1192,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
|
||||
{120, nullptr, "ExecuteProgram"},
|
||||
{121, nullptr, "ClearUserChannel"},
|
||||
{122, nullptr, "UnpopToUserChannel"},
|
||||
{123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"},
|
||||
{123, nullptr, "GetPreviousProgramIndex"},
|
||||
{124, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
|
||||
{130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"},
|
||||
{140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"},
|
||||
@@ -1554,14 +1554,6 @@ void IApplicationFunctions::QueryApplicationPlayStatisticsByUid(Kernel::HLEReque
|
||||
rb.Push<u32>(0);
|
||||
}
|
||||
|
||||
void IApplicationFunctions::GetPreviousProgramIndex(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<s32>(previous_program_index);
|
||||
}
|
||||
|
||||
void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
|
||||
|
||||
@@ -288,13 +288,11 @@ private:
|
||||
void SetApplicationCopyrightVisibility(Kernel::HLERequestContext& ctx);
|
||||
void QueryApplicationPlayStatistics(Kernel::HLERequestContext& ctx);
|
||||
void QueryApplicationPlayStatisticsByUid(Kernel::HLERequestContext& ctx);
|
||||
void GetPreviousProgramIndex(Kernel::HLERequestContext& ctx);
|
||||
void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx);
|
||||
void GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx);
|
||||
|
||||
bool launch_popped_application_specific = false;
|
||||
bool launch_popped_account_preselect = false;
|
||||
s32 previous_program_index{-1};
|
||||
Kernel::EventPair gpu_error_detected_event;
|
||||
Kernel::EventPair friend_invitation_storage_channel_event;
|
||||
Core::System& system;
|
||||
|
||||
@@ -206,8 +206,7 @@ void AppletManager::SetDefaultAppletFrontendSet() {
|
||||
|
||||
void AppletManager::SetDefaultAppletsIfMissing() {
|
||||
if (frontend.controller == nullptr) {
|
||||
frontend.controller =
|
||||
std::make_unique<Core::Frontend::DefaultControllerApplet>(system.ServiceManager());
|
||||
frontend.controller = std::make_unique<Core::Frontend::DefaultControllerApplet>();
|
||||
}
|
||||
|
||||
if (frontend.e_commerce == nullptr) {
|
||||
|
||||
@@ -379,7 +379,7 @@ ResultVal<FileSys::VirtualFile> FileSystemController::OpenBISPartitionStorage(
|
||||
return FileSys::ERROR_ENTITY_NOT_FOUND;
|
||||
}
|
||||
|
||||
auto part = bis_factory->OpenPartitionStorage(id, system.GetFilesystem());
|
||||
auto part = bis_factory->OpenPartitionStorage(id);
|
||||
if (part == nullptr) {
|
||||
return FileSys::ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
@@ -31,10 +31,6 @@ 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;
|
||||
|
||||
|
||||
@@ -250,9 +250,6 @@ void Controller_NPad::OnLoadInputDevices() {
|
||||
std::transform(players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
|
||||
players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_END,
|
||||
sticks[i].begin(), Input::CreateDevice<Input::AnalogDevice>);
|
||||
std::transform(players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_BEGIN,
|
||||
players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_END,
|
||||
motions[i].begin(), Input::CreateDevice<Input::MotionDevice>);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,7 +266,6 @@ 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] =
|
||||
@@ -364,7 +360,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
continue;
|
||||
}
|
||||
const u32 npad_index = static_cast<u32>(i);
|
||||
|
||||
RequestPadStateUpdate(npad_index);
|
||||
auto& pad_state = npad_pad_states[npad_index];
|
||||
|
||||
@@ -382,18 +377,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
|
||||
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 =
|
||||
npad.sixaxis_handheld.sixaxis[npad.sixaxis_handheld.common.last_entry_index];
|
||||
auto& dual_left_sixaxis_entry =
|
||||
npad.sixaxis_dual_left.sixaxis[npad.sixaxis_dual_left.common.last_entry_index];
|
||||
auto& dual_right_sixaxis_entry =
|
||||
npad.sixaxis_dual_right.sixaxis[npad.sixaxis_dual_right.common.last_entry_index];
|
||||
auto& left_sixaxis_entry =
|
||||
npad.sixaxis_left.sixaxis[npad.sixaxis_left.common.last_entry_index];
|
||||
auto& right_sixaxis_entry =
|
||||
npad.sixaxis_right.sixaxis[npad.sixaxis_right.common.last_entry_index];
|
||||
|
||||
switch (controller_type) {
|
||||
case NPadControllerType::None:
|
||||
@@ -480,143 +463,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
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,
|
||||
};
|
||||
|
||||
for (auto* sixaxis_sensor : controller_sixaxes) {
|
||||
sixaxis_sensor->common.entry_count = 16;
|
||||
sixaxis_sensor->common.total_entry_count = 17;
|
||||
|
||||
const auto& last_entry =
|
||||
sixaxis_sensor->sixaxis[sixaxis_sensor->common.last_entry_index];
|
||||
|
||||
sixaxis_sensor->common.timestamp = core_timing.GetCPUTicks();
|
||||
sixaxis_sensor->common.last_entry_index =
|
||||
(sixaxis_sensor->common.last_entry_index + 1) % 17;
|
||||
|
||||
auto& cur_entry = sixaxis_sensor->sixaxis[sixaxis_sensor->common.last_entry_index];
|
||||
|
||||
cur_entry.timestamp = last_entry.timestamp + 1;
|
||||
cur_entry.timestamp2 = cur_entry.timestamp;
|
||||
}
|
||||
|
||||
// Try to read sixaxis sensor states
|
||||
std::array<MotionDevice, 2> motion_devices;
|
||||
|
||||
if (sixaxis_sensors_enabled && Settings::values.motion_enabled) {
|
||||
sixaxis_at_rest = true;
|
||||
for (std::size_t e = 0; e < motion_devices.size(); ++e) {
|
||||
const auto& device = motions[i][e];
|
||||
if (device) {
|
||||
std::tie(motion_devices[e].accel, motion_devices[e].gyro,
|
||||
motion_devices[e].rotation, motion_devices[e].orientation) =
|
||||
device->GetStatus();
|
||||
sixaxis_at_rest = sixaxis_at_rest && motion_devices[e].gyro.Length2() < 0.0001f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
auto& full_sixaxis_entry =
|
||||
npad.sixaxis_full.sixaxis[npad.sixaxis_full.common.last_entry_index];
|
||||
auto& handheld_sixaxis_entry =
|
||||
npad.sixaxis_handheld.sixaxis[npad.sixaxis_handheld.common.last_entry_index];
|
||||
auto& dual_left_sixaxis_entry =
|
||||
npad.sixaxis_dual_left.sixaxis[npad.sixaxis_dual_left.common.last_entry_index];
|
||||
auto& dual_right_sixaxis_entry =
|
||||
npad.sixaxis_dual_right.sixaxis[npad.sixaxis_dual_right.common.last_entry_index];
|
||||
auto& left_sixaxis_entry =
|
||||
npad.sixaxis_left.sixaxis[npad.sixaxis_left.common.last_entry_index];
|
||||
auto& right_sixaxis_entry =
|
||||
npad.sixaxis_right.sixaxis[npad.sixaxis_right.common.last_entry_index];
|
||||
|
||||
switch (controller_type) {
|
||||
case NPadControllerType::None:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
case NPadControllerType::ProController:
|
||||
if (sixaxis_sensors_enabled && motions[i][0]) {
|
||||
full_sixaxis_entry.accel = motion_devices[0].accel;
|
||||
full_sixaxis_entry.gyro = motion_devices[0].gyro;
|
||||
full_sixaxis_entry.rotation = motion_devices[0].rotation;
|
||||
full_sixaxis_entry.orientation = motion_devices[0].orientation;
|
||||
}
|
||||
break;
|
||||
case NPadControllerType::Handheld:
|
||||
if (sixaxis_sensors_enabled && motions[i][0]) {
|
||||
handheld_sixaxis_entry.accel = motion_devices[0].accel;
|
||||
handheld_sixaxis_entry.gyro = motion_devices[0].gyro;
|
||||
handheld_sixaxis_entry.rotation = motion_devices[0].rotation;
|
||||
handheld_sixaxis_entry.orientation = motion_devices[0].orientation;
|
||||
}
|
||||
break;
|
||||
case NPadControllerType::JoyDual:
|
||||
if (sixaxis_sensors_enabled && motions[i][0]) {
|
||||
// Set motion for the left joycon
|
||||
dual_left_sixaxis_entry.accel = motion_devices[0].accel;
|
||||
dual_left_sixaxis_entry.gyro = motion_devices[0].gyro;
|
||||
dual_left_sixaxis_entry.rotation = motion_devices[0].rotation;
|
||||
dual_left_sixaxis_entry.orientation = motion_devices[0].orientation;
|
||||
}
|
||||
if (sixaxis_sensors_enabled && motions[i][1]) {
|
||||
// Set motion for the right joycon
|
||||
dual_right_sixaxis_entry.accel = motion_devices[1].accel;
|
||||
dual_right_sixaxis_entry.gyro = motion_devices[1].gyro;
|
||||
dual_right_sixaxis_entry.rotation = motion_devices[1].rotation;
|
||||
dual_right_sixaxis_entry.orientation = motion_devices[1].orientation;
|
||||
}
|
||||
break;
|
||||
case NPadControllerType::JoyLeft:
|
||||
if (sixaxis_sensors_enabled && motions[i][0]) {
|
||||
left_sixaxis_entry.accel = motion_devices[0].accel;
|
||||
left_sixaxis_entry.gyro = motion_devices[0].gyro;
|
||||
left_sixaxis_entry.rotation = motion_devices[0].rotation;
|
||||
left_sixaxis_entry.orientation = motion_devices[0].orientation;
|
||||
}
|
||||
break;
|
||||
case NPadControllerType::JoyRight:
|
||||
if (sixaxis_sensors_enabled && motions[i][1]) {
|
||||
right_sixaxis_entry.accel = motion_devices[1].accel;
|
||||
right_sixaxis_entry.gyro = motion_devices[1].gyro;
|
||||
right_sixaxis_entry.rotation = motion_devices[1].rotation;
|
||||
right_sixaxis_entry.orientation = motion_devices[1].orientation;
|
||||
}
|
||||
break;
|
||||
case NPadControllerType::Pokeball:
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(),
|
||||
shared_memory_entries.size() * sizeof(NPadEntry));
|
||||
}
|
||||
|
||||
void Controller_NPad::SetSupportedStyleSet(NPadType style_set) {
|
||||
style.raw = style_set.raw;
|
||||
}
|
||||
@@ -649,14 +495,6 @@ Controller_NPad::NpadHoldType Controller_NPad::GetHoldType() const {
|
||||
return hold_type;
|
||||
}
|
||||
|
||||
void Controller_NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode) {
|
||||
handheld_activation_mode = activation_mode;
|
||||
}
|
||||
|
||||
Controller_NPad::NpadHandheldActivationMode Controller_NPad::GetNpadHandheldActivationMode() const {
|
||||
return handheld_activation_mode;
|
||||
}
|
||||
|
||||
void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) {
|
||||
const std::size_t npad_index = NPadIdToIndex(npad_id);
|
||||
ASSERT(npad_index < shared_memory_entries.size());
|
||||
@@ -665,31 +503,20 @@ void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode)
|
||||
}
|
||||
}
|
||||
|
||||
void Controller_NPad::VibrateController(const std::vector<u32>& controllers,
|
||||
void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids,
|
||||
const std::vector<Vibration>& vibrations) {
|
||||
LOG_TRACE(Service_HID, "called");
|
||||
LOG_DEBUG(Service_HID, "(STUBBED) called");
|
||||
|
||||
if (!Settings::values.vibration_enabled || !can_controllers_vibrate) {
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
if (success) {
|
||||
last_processed_vibration = vibrations.back();
|
||||
}
|
||||
last_processed_vibration = vibrations.back();
|
||||
}
|
||||
|
||||
Controller_NPad::Vibration Controller_NPad::GetLastVibration() const {
|
||||
@@ -755,14 +582,6 @@ Controller_NPad::GyroscopeZeroDriftMode Controller_NPad::GetGyroscopeZeroDriftMo
|
||||
return gyroscope_zero_drift_mode;
|
||||
}
|
||||
|
||||
bool Controller_NPad::IsSixAxisSensorAtRest() const {
|
||||
return sixaxis_at_rest;
|
||||
}
|
||||
|
||||
void Controller_NPad::SetSixAxisEnabled(bool six_axis_status) {
|
||||
sixaxis_sensors_enabled = six_axis_status;
|
||||
}
|
||||
|
||||
void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) {
|
||||
const auto npad_index_1 = NPadIdToIndex(npad_id_1);
|
||||
const auto npad_index_2 = NPadIdToIndex(npad_id_2);
|
||||
|
||||
@@ -32,10 +32,6 @@ 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;
|
||||
|
||||
@@ -78,12 +74,6 @@ public:
|
||||
Single = 1,
|
||||
};
|
||||
|
||||
enum class NpadHandheldActivationMode : u64 {
|
||||
Dual = 0,
|
||||
Single = 1,
|
||||
None = 2,
|
||||
};
|
||||
|
||||
enum class NPadControllerType {
|
||||
None,
|
||||
ProController,
|
||||
@@ -120,12 +110,9 @@ public:
|
||||
void SetHoldType(NpadHoldType joy_hold_type);
|
||||
NpadHoldType GetHoldType() const;
|
||||
|
||||
void SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode);
|
||||
NpadHandheldActivationMode GetNpadHandheldActivationMode() const;
|
||||
|
||||
void SetNpadMode(u32 npad_id, NPadAssignments assignment_mode);
|
||||
|
||||
void VibrateController(const std::vector<u32>& controllers,
|
||||
void VibrateController(const std::vector<u32>& controller_ids,
|
||||
const std::vector<Vibration>& vibrations);
|
||||
|
||||
Vibration GetLastVibration() const;
|
||||
@@ -143,8 +130,6 @@ public:
|
||||
|
||||
void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode);
|
||||
GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const;
|
||||
bool IsSixAxisSensorAtRest() const;
|
||||
void SetSixAxisEnabled(bool six_axis_status);
|
||||
LedPattern GetLedPattern(u32 npad_id);
|
||||
void SetVibrationEnabled(bool can_vibrate);
|
||||
bool IsVibrationEnabled() const;
|
||||
@@ -267,24 +252,6 @@ private:
|
||||
};
|
||||
static_assert(sizeof(NPadGeneric) == 0x350, "NPadGeneric is an invalid size");
|
||||
|
||||
struct SixAxisStates {
|
||||
s64_le timestamp{};
|
||||
INSERT_PADDING_WORDS(2);
|
||||
s64_le timestamp2{};
|
||||
Common::Vec3f accel{};
|
||||
Common::Vec3f gyro{};
|
||||
Common::Vec3f rotation{};
|
||||
std::array<Common::Vec3f, 3> orientation{};
|
||||
s64_le always_one{1};
|
||||
};
|
||||
static_assert(sizeof(SixAxisStates) == 0x68, "SixAxisStates is an invalid size");
|
||||
|
||||
struct SixAxisGeneric {
|
||||
CommonHeader common{};
|
||||
std::array<SixAxisStates, 17> sixaxis{};
|
||||
};
|
||||
static_assert(sizeof(SixAxisGeneric) == 0x708, "SixAxisGeneric is an invalid size");
|
||||
|
||||
enum class ColorReadError : u32_le {
|
||||
ReadOk = 0,
|
||||
ColorDoesntExist = 1,
|
||||
@@ -314,13 +281,6 @@ private:
|
||||
};
|
||||
};
|
||||
|
||||
struct MotionDevice {
|
||||
Common::Vec3f accel;
|
||||
Common::Vec3f gyro;
|
||||
Common::Vec3f rotation;
|
||||
std::array<Common::Vec3f, 3> orientation;
|
||||
};
|
||||
|
||||
struct NPadEntry {
|
||||
NPadType joy_styles;
|
||||
NPadAssignments pad_assignment;
|
||||
@@ -340,12 +300,9 @@ private:
|
||||
NPadGeneric pokeball_states;
|
||||
NPadGeneric libnx; // TODO(ogniK): Find out what this actually is, libnx seems to only be
|
||||
// relying on this for the time being
|
||||
SixAxisGeneric sixaxis_full;
|
||||
SixAxisGeneric sixaxis_handheld;
|
||||
SixAxisGeneric sixaxis_dual_left;
|
||||
SixAxisGeneric sixaxis_dual_right;
|
||||
SixAxisGeneric sixaxis_left;
|
||||
SixAxisGeneric sixaxis_right;
|
||||
INSERT_PADDING_BYTES(
|
||||
0x708 *
|
||||
6); // TODO(ogniK): SixAxis states, require more information before implementation
|
||||
NPadDevice device_type;
|
||||
NPadProperties properties;
|
||||
INSERT_PADDING_WORDS(1);
|
||||
@@ -368,29 +325,22 @@ private:
|
||||
|
||||
NPadType style{};
|
||||
std::array<NPadEntry, 10> shared_memory_entries{};
|
||||
using ButtonArray = std::array<
|
||||
std::array<
|
||||
std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>,
|
||||
10>;
|
||||
using StickArray = std::array<
|
||||
10>
|
||||
buttons;
|
||||
std::array<
|
||||
std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>,
|
||||
10>;
|
||||
using MotionArray = std::array<
|
||||
std::array<std::unique_ptr<Input::MotionDevice>, Settings::NativeMotion::NUM_MOTION_HID>,
|
||||
10>;
|
||||
ButtonArray buttons;
|
||||
StickArray sticks;
|
||||
MotionArray motions;
|
||||
10>
|
||||
sticks;
|
||||
std::vector<u32> supported_npad_id_types{};
|
||||
NpadHoldType hold_type{NpadHoldType::Vertical};
|
||||
NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual};
|
||||
// Each controller should have their own styleset changed event
|
||||
std::array<Kernel::EventPair, 10> styleset_changed_events;
|
||||
Vibration last_processed_vibration{};
|
||||
std::array<ControllerHolder, 10> connected_controllers{};
|
||||
GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard};
|
||||
bool can_controllers_vibrate{true};
|
||||
bool sixaxis_sensors_enabled{true};
|
||||
bool sixaxis_at_rest{true};
|
||||
std::array<ControllerPad, 10> npad_pad_states{};
|
||||
bool is_in_lr_assignment_mode{false};
|
||||
Core::System& system;
|
||||
|
||||
@@ -40,8 +40,7 @@ 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 motion_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000}; // (15ms, 66.666Hz)
|
||||
constexpr auto pad_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000}; // (15ms, 66.6Hz)
|
||||
constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000;
|
||||
|
||||
IAppletResource::IAppletResource(Core::System& system)
|
||||
@@ -80,14 +79,10 @@ IAppletResource::IAppletResource(Core::System& system)
|
||||
[this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
|
||||
UpdateControllers(user_data, ns_late);
|
||||
});
|
||||
motion_update_event = Core::Timing::CreateEvent(
|
||||
"HID::MotionPadCallback",
|
||||
[this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
|
||||
UpdateMotion(user_data, ns_late);
|
||||
});
|
||||
|
||||
// TODO(shinyquagsire23): Other update callbacks? (accel, gyro?)
|
||||
|
||||
system.CoreTiming().ScheduleEvent(pad_update_ns, pad_update_event);
|
||||
system.CoreTiming().ScheduleEvent(motion_update_ns, motion_update_event);
|
||||
|
||||
ReloadInputDevices();
|
||||
}
|
||||
@@ -127,16 +122,6 @@ 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") {
|
||||
@@ -179,8 +164,8 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) {
|
||||
{56, nullptr, "ActivateJoyXpad"},
|
||||
{58, nullptr, "GetJoyXpadLifoHandle"},
|
||||
{59, nullptr, "GetJoyXpadIds"},
|
||||
{60, &Hid::ActivateSixAxisSensor, "ActivateSixAxisSensor"},
|
||||
{61, &Hid::DeactivateSixAxisSensor, "DeactivateSixAxisSensor"},
|
||||
{60, nullptr, "ActivateSixAxisSensor"},
|
||||
{61, nullptr, "DeactivateSixAxisSensor"},
|
||||
{62, nullptr, "GetSixAxisSensorLifoHandle"},
|
||||
{63, nullptr, "ActivateJoySixAxisSensor"},
|
||||
{64, nullptr, "DeactivateJoySixAxisSensor"},
|
||||
@@ -188,7 +173,7 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) {
|
||||
{66, &Hid::StartSixAxisSensor, "StartSixAxisSensor"},
|
||||
{67, &Hid::StopSixAxisSensor, "StopSixAxisSensor"},
|
||||
{68, nullptr, "IsSixAxisSensorFusionEnabled"},
|
||||
{69, &Hid::EnableSixAxisSensorFusion, "EnableSixAxisSensorFusion"},
|
||||
{69, nullptr, "EnableSixAxisSensorFusion"},
|
||||
{70, nullptr, "SetSixAxisSensorFusionParameters"},
|
||||
{71, nullptr, "GetSixAxisSensorFusionParameters"},
|
||||
{72, nullptr, "ResetSixAxisSensorFusionParameters"},
|
||||
@@ -344,31 +329,6 @@ void Hid::GetXpadIDs(Kernel::HLERequestContext& ctx) {
|
||||
rb.Push(0);
|
||||
}
|
||||
|
||||
void Hid::ActivateSixAxisSensor(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto handle{rp.Pop<u32>()};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(true);
|
||||
LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle,
|
||||
applet_resource_user_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void Hid::DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto handle{rp.Pop<u32>()};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(false);
|
||||
|
||||
LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle,
|
||||
applet_resource_user_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void Hid::ActivateDebugPad(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
@@ -473,19 +433,6 @@ void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) {
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void Hid::EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
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>()};
|
||||
@@ -537,13 +484,13 @@ void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) {
|
||||
const auto handle{rp.Pop<u32>()};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
|
||||
LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle,
|
||||
applet_resource_user_id);
|
||||
LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle,
|
||||
applet_resource_user_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad)
|
||||
.IsSixAxisSensorAtRest());
|
||||
// TODO (Hexagon12): Properly implement reading gyroscope values from controllers.
|
||||
rb.Push(true);
|
||||
}
|
||||
|
||||
void Hid::SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
|
||||
@@ -767,11 +714,8 @@ void Hid::SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
const auto mode{rp.Pop<u64>()};
|
||||
|
||||
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, mode={}", applet_resource_user_id,
|
||||
mode);
|
||||
|
||||
applet_resource->GetController<Controller_NPad>(HidController::NPad)
|
||||
.SetNpadHandheldActivationMode(Controller_NPad::NpadHandheldActivationMode{mode});
|
||||
LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, mode={}",
|
||||
applet_resource_user_id, mode);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
@@ -781,13 +725,11 @@ void Hid::GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
|
||||
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
|
||||
LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
|
||||
applet_resource_user_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u64>(
|
||||
static_cast<u64>(applet_resource->GetController<Controller_NPad>(HidController::NPad)
|
||||
.GetNpadHandheldActivationMode()));
|
||||
}
|
||||
|
||||
void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) {
|
||||
@@ -830,18 +772,18 @@ void Hid::EndPermitVibrationSession(Kernel::HLERequestContext& ctx) {
|
||||
|
||||
void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto controller{rp.Pop<u32>()};
|
||||
const auto controller_id{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={}, applet_resource_user_id={}", controller,
|
||||
LOG_DEBUG(Service_HID, "called, controller_id={}, applet_resource_user_id={}", controller_id,
|
||||
applet_resource_user_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
applet_resource->GetController<Controller_NPad>(HidController::NPad)
|
||||
.VibrateController({controller}, {vibration_values});
|
||||
.VibrateController({controller_id}, {vibration_values});
|
||||
}
|
||||
|
||||
void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) {
|
||||
@@ -859,6 +801,8 @@ 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,12 +65,10 @@ 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)>
|
||||
@@ -88,8 +86,6 @@ private:
|
||||
void CreateAppletResource(Kernel::HLERequestContext& ctx);
|
||||
void ActivateXpad(Kernel::HLERequestContext& ctx);
|
||||
void GetXpadIDs(Kernel::HLERequestContext& ctx);
|
||||
void ActivateSixAxisSensor(Kernel::HLERequestContext& ctx);
|
||||
void DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx);
|
||||
void ActivateDebugPad(Kernel::HLERequestContext& ctx);
|
||||
void ActivateTouchScreen(Kernel::HLERequestContext& ctx);
|
||||
void ActivateMouse(Kernel::HLERequestContext& ctx);
|
||||
@@ -99,7 +95,6 @@ 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);
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
@@ -73,10 +72,10 @@ private:
|
||||
std::array<u8, 10> uuid;
|
||||
u8 uuid_length; // TODO(ogniK): Figure out if this is actual the uuid length or does it
|
||||
// mean something else
|
||||
std::array<u8, 0x15> padding_1;
|
||||
INSERT_PADDING_BYTES(0x15);
|
||||
u32_le protocol;
|
||||
u32_le tag_type;
|
||||
std::array<u8, 0x2c> padding_2;
|
||||
INSERT_PADDING_BYTES(0x2c);
|
||||
};
|
||||
static_assert(sizeof(TagInfo) == 0x54, "TagInfo is an invalid size");
|
||||
|
||||
@@ -214,15 +213,13 @@ private:
|
||||
LOG_DEBUG(Service_NFP, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
const auto& amiibo = nfp_interface.GetAmiiboBuffer();
|
||||
const TagInfo tag_info{
|
||||
.uuid = amiibo.uuid,
|
||||
.uuid_length = static_cast<u8>(tag_info.uuid.size()),
|
||||
.padding_1 = {},
|
||||
.protocol = 1, // TODO(ogniK): Figure out actual values
|
||||
.tag_type = 2,
|
||||
.padding_2 = {},
|
||||
};
|
||||
auto amiibo = nfp_interface.GetAmiiboBuffer();
|
||||
TagInfo tag_info{};
|
||||
tag_info.uuid = amiibo.uuid;
|
||||
tag_info.uuid_length = static_cast<u8>(tag_info.uuid.size());
|
||||
|
||||
tag_info.protocol = 1; // TODO(ogniK): Figure out actual values
|
||||
tag_info.tag_type = 2;
|
||||
ctx.WriteBuffer(tag_info);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
@@ -239,7 +236,7 @@ private:
|
||||
LOG_DEBUG(Service_NFP, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
const auto& amiibo = nfp_interface.GetAmiiboBuffer();
|
||||
auto amiibo = nfp_interface.GetAmiiboBuffer();
|
||||
ctx.WriteBuffer(amiibo.model_info);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -265,7 +265,7 @@ std::optional<nvhost_as_gpu::BufferMap> nvhost_as_gpu::FindBufferMap(GPUVAddr gp
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
return {};
|
||||
}
|
||||
|
||||
void nvhost_as_gpu::AddBufferMap(GPUVAddr gpu_addr, std::size_t size, VAddr cpu_addr,
|
||||
@@ -286,7 +286,7 @@ std::optional<std::size_t> nvhost_as_gpu::RemoveBufferMap(GPUVAddr gpu_addr) {
|
||||
return size;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace Service::Nvidia::Devices
|
||||
@@ -54,7 +54,7 @@ struct EventInterface {
|
||||
}
|
||||
mask = mask >> 1;
|
||||
}
|
||||
return std::nullopt;
|
||||
return {};
|
||||
}
|
||||
void SetEventStatus(const u32 event_id, EventState new_status) {
|
||||
EventState old_status = status[event_id];
|
||||
|
||||
@@ -114,7 +114,7 @@ std::optional<u64> NVFlinger::OpenDisplay(std::string_view name) {
|
||||
[&](const VI::Display& display) { return display.GetName() == name; });
|
||||
|
||||
if (itr == displays.end()) {
|
||||
return std::nullopt;
|
||||
return {};
|
||||
}
|
||||
|
||||
return itr->GetID();
|
||||
@@ -124,7 +124,7 @@ std::optional<u64> NVFlinger::CreateLayer(u64 display_id) {
|
||||
auto* const display = FindDisplay(display_id);
|
||||
|
||||
if (display == nullptr) {
|
||||
return std::nullopt;
|
||||
return {};
|
||||
}
|
||||
|
||||
const u64 layer_id = next_layer_id++;
|
||||
@@ -144,7 +144,7 @@ std::optional<u32> NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) co
|
||||
const auto* const layer = FindLayer(display_id, layer_id);
|
||||
|
||||
if (layer == nullptr) {
|
||||
return std::nullopt;
|
||||
return {};
|
||||
}
|
||||
|
||||
return layer->GetBufferQueue().GetId();
|
||||
|
||||
@@ -89,6 +89,8 @@ namespace Service {
|
||||
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) {}
|
||||
@@ -187,6 +189,9 @@ ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& co
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Module interface
|
||||
|
||||
/// Initialize ServiceManager
|
||||
void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system) {
|
||||
// NVFlinger needs to be accessed by several services like Vi and AppletOE so we instantiate it
|
||||
|
||||
@@ -19,7 +19,7 @@ constexpr ResultCode ERR_ALREADY_REGISTERED(ErrorModule::SM, 4);
|
||||
constexpr ResultCode ERR_INVALID_NAME(ErrorModule::SM, 6);
|
||||
constexpr ResultCode ERR_SERVICE_NOT_REGISTERED(ErrorModule::SM, 7);
|
||||
|
||||
ServiceManager::ServiceManager(Kernel::KernelCore& kernel_) : kernel{kernel_} {}
|
||||
ServiceManager::ServiceManager() = default;
|
||||
ServiceManager::~ServiceManager() = default;
|
||||
|
||||
void ServiceManager::InvokeControlRequest(Kernel::HLERequestContext& context) {
|
||||
@@ -27,11 +27,11 @@ void ServiceManager::InvokeControlRequest(Kernel::HLERequestContext& context) {
|
||||
}
|
||||
|
||||
static ResultCode ValidateServiceName(const std::string& name) {
|
||||
if (name.empty() || name.size() > 8) {
|
||||
if (name.size() <= 0 || name.size() > 8) {
|
||||
LOG_ERROR(Service_SM, "Invalid service name! service={}", name);
|
||||
return ERR_INVALID_NAME;
|
||||
}
|
||||
if (name.rfind('\0') != std::string::npos) {
|
||||
if (name.find('\0') != std::string::npos) {
|
||||
LOG_ERROR(Service_SM, "A non null terminated service was passed");
|
||||
return ERR_INVALID_NAME;
|
||||
}
|
||||
@@ -48,8 +48,8 @@ void ServiceManager::InstallInterfaces(std::shared_ptr<ServiceManager> self,
|
||||
self->controller_interface = std::make_unique<Controller>();
|
||||
}
|
||||
|
||||
ResultVal<std::shared_ptr<Kernel::ServerPort>> ServiceManager::RegisterService(std::string name,
|
||||
u32 max_sessions) {
|
||||
ResultVal<std::shared_ptr<Kernel::ServerPort>> ServiceManager::RegisterService(
|
||||
std::string name, unsigned int max_sessions) {
|
||||
|
||||
CASCADE_CODE(ValidateServiceName(name));
|
||||
|
||||
@@ -58,6 +58,7 @@ ResultVal<std::shared_ptr<Kernel::ServerPort>> ServiceManager::RegisterService(s
|
||||
return ERR_ALREADY_REGISTERED;
|
||||
}
|
||||
|
||||
auto& kernel = Core::System::GetInstance().Kernel();
|
||||
auto [server_port, client_port] =
|
||||
Kernel::ServerPort::CreatePortPair(kernel, max_sessions, name);
|
||||
|
||||
|
||||
@@ -48,11 +48,11 @@ class ServiceManager {
|
||||
public:
|
||||
static void InstallInterfaces(std::shared_ptr<ServiceManager> self, Kernel::KernelCore& kernel);
|
||||
|
||||
explicit ServiceManager(Kernel::KernelCore& kernel_);
|
||||
ServiceManager();
|
||||
~ServiceManager();
|
||||
|
||||
ResultVal<std::shared_ptr<Kernel::ServerPort>> RegisterService(std::string name,
|
||||
u32 max_sessions);
|
||||
unsigned int max_sessions);
|
||||
ResultCode UnregisterService(const std::string& name);
|
||||
ResultVal<std::shared_ptr<Kernel::ClientPort>> GetServicePort(const std::string& name);
|
||||
ResultVal<std::shared_ptr<Kernel::ClientSession>> ConnectToService(const std::string& name);
|
||||
@@ -79,9 +79,6 @@ private:
|
||||
|
||||
/// Map of registered services, retrieved using GetServicePort or ConnectToService.
|
||||
std::unordered_map<std::string, std::shared_ptr<Kernel::ClientPort>> registered_services;
|
||||
|
||||
/// Kernel context
|
||||
Kernel::KernelCore& kernel;
|
||||
};
|
||||
|
||||
} // namespace Service::SM
|
||||
@@ -497,7 +497,7 @@ std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::vector<u
|
||||
return {0, Errno::SUCCESS};
|
||||
}
|
||||
|
||||
const std::optional<FileDescriptor>& descriptor = file_descriptors[pollfd.fd];
|
||||
std::optional<FileDescriptor>& descriptor = file_descriptors[pollfd.fd];
|
||||
if (!descriptor) {
|
||||
LOG_ERROR(Service, "File descriptor handle={} is not allocated", pollfd.fd);
|
||||
pollfd.revents = POLL_NVAL;
|
||||
|
||||
@@ -89,7 +89,7 @@ FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::Virtua
|
||||
}
|
||||
|
||||
AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirectory::Load(
|
||||
Kernel::Process& process, Core::System& system) {
|
||||
Kernel::Process& process) {
|
||||
if (is_loaded) {
|
||||
return {ResultStatus::ErrorAlreadyLoaded, {}};
|
||||
}
|
||||
@@ -141,9 +141,9 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool should_pass_arguments = std::strcmp(module, "rtld") == 0;
|
||||
const auto tentative_next_load_addr = AppLoader_NSO::LoadModule(
|
||||
process, system, *module_file, code_size, should_pass_arguments, false);
|
||||
const bool should_pass_arguments{std::strcmp(module, "rtld") == 0};
|
||||
const auto tentative_next_load_addr{AppLoader_NSO::LoadModule(
|
||||
process, *module_file, code_size, should_pass_arguments, false)};
|
||||
if (!tentative_next_load_addr) {
|
||||
return {ResultStatus::ErrorLoadingNSO, {}};
|
||||
}
|
||||
@@ -168,9 +168,9 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
|
||||
}
|
||||
|
||||
const VAddr load_addr{next_load_addr};
|
||||
const bool should_pass_arguments = std::strcmp(module, "rtld") == 0;
|
||||
const auto tentative_next_load_addr = AppLoader_NSO::LoadModule(
|
||||
process, system, *module_file, load_addr, should_pass_arguments, true, pm);
|
||||
const bool should_pass_arguments{std::strcmp(module, "rtld") == 0};
|
||||
const auto tentative_next_load_addr{AppLoader_NSO::LoadModule(
|
||||
process, *module_file, load_addr, should_pass_arguments, true, pm)};
|
||||
if (!tentative_next_load_addr) {
|
||||
return {ResultStatus::ErrorLoadingNSO, {}};
|
||||
}
|
||||
@@ -192,8 +192,8 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
|
||||
// Register the RomFS if a ".romfs" file was found
|
||||
if (romfs_iter != files.end() && *romfs_iter != nullptr) {
|
||||
romfs = *romfs_iter;
|
||||
system.GetFileSystemController().RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(
|
||||
*this, system.GetContentProvider(), system.GetFileSystemController()));
|
||||
Core::System::GetInstance().GetFileSystemController().RegisterRomFS(
|
||||
std::make_unique<FileSys::RomFSFactory>(*this));
|
||||
}
|
||||
|
||||
is_loaded = true;
|
||||
|
||||
@@ -9,10 +9,6 @@
|
||||
#include "core/file_sys/program_metadata.h"
|
||||
#include "core/loader/loader.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Loader {
|
||||
|
||||
/**
|
||||
@@ -41,7 +37,7 @@ public:
|
||||
return IdentifyType(file);
|
||||
}
|
||||
|
||||
LoadResult Load(Kernel::Process& process, Core::System& system) override;
|
||||
LoadResult Load(Kernel::Process& process) override;
|
||||
|
||||
ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
|
||||
ResultStatus ReadIcon(std::vector<u8>& buffer) override;
|
||||
|
||||
@@ -383,8 +383,7 @@ FileType AppLoader_ELF::IdentifyType(const FileSys::VirtualFile& file) {
|
||||
return FileType::Error;
|
||||
}
|
||||
|
||||
AppLoader_ELF::LoadResult AppLoader_ELF::Load(Kernel::Process& process,
|
||||
[[maybe_unused]] Core::System& system) {
|
||||
AppLoader_ELF::LoadResult AppLoader_ELF::Load(Kernel::Process& process) {
|
||||
if (is_loaded) {
|
||||
return {ResultStatus::ErrorAlreadyLoaded, {}};
|
||||
}
|
||||
|
||||
@@ -8,10 +8,6 @@
|
||||
#include "common/common_types.h"
|
||||
#include "core/loader/loader.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Loader {
|
||||
|
||||
/// Loads an ELF/AXF file
|
||||
@@ -30,7 +26,7 @@ public:
|
||||
return IdentifyType(file);
|
||||
}
|
||||
|
||||
LoadResult Load(Kernel::Process& process, Core::System& system) override;
|
||||
LoadResult Load(Kernel::Process& process) override;
|
||||
};
|
||||
|
||||
} // namespace Loader
|
||||
@@ -43,8 +43,7 @@ FileType AppLoader_KIP::GetFileType() const {
|
||||
: FileType::Error;
|
||||
}
|
||||
|
||||
AppLoader::LoadResult AppLoader_KIP::Load(Kernel::Process& process,
|
||||
[[maybe_unused]] Core::System& system) {
|
||||
AppLoader::LoadResult AppLoader_KIP::Load(Kernel::Process& process) {
|
||||
if (is_loaded) {
|
||||
return {ResultStatus::ErrorAlreadyLoaded, {}};
|
||||
}
|
||||
|
||||
@@ -6,10 +6,6 @@
|
||||
|
||||
#include "core/loader/loader.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace FileSys {
|
||||
class KIP;
|
||||
}
|
||||
@@ -30,7 +26,7 @@ public:
|
||||
|
||||
FileType GetFileType() const override;
|
||||
|
||||
LoadResult Load(Kernel::Process& process, Core::System& system) override;
|
||||
LoadResult Load(Kernel::Process& process) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<FileSys::KIP> kip;
|
||||
|
||||
@@ -15,10 +15,6 @@
|
||||
#include "core/file_sys/control_metadata.h"
|
||||
#include "core/file_sys/vfs.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace FileSys {
|
||||
class NACP;
|
||||
} // namespace FileSys
|
||||
@@ -158,10 +154,9 @@ public:
|
||||
/**
|
||||
* Load the application and return the created Process instance
|
||||
* @param process The newly created process.
|
||||
* @param system The system that this process is being loaded under.
|
||||
* @return The status result of the operation.
|
||||
*/
|
||||
virtual LoadResult Load(Kernel::Process& process, Core::System& system) = 0;
|
||||
virtual LoadResult Load(Kernel::Process& process) = 0;
|
||||
|
||||
/**
|
||||
* Get the code (typically .code section) of the application
|
||||
|
||||
@@ -41,8 +41,7 @@ FileType AppLoader_NAX::GetFileType() const {
|
||||
return IdentifyTypeImpl(*nax);
|
||||
}
|
||||
|
||||
AppLoader_NAX::LoadResult AppLoader_NAX::Load(Kernel::Process& process,
|
||||
[[maybe_unused]] Core::System& system) {
|
||||
AppLoader_NAX::LoadResult AppLoader_NAX::Load(Kernel::Process& process) {
|
||||
if (is_loaded) {
|
||||
return {ResultStatus::ErrorAlreadyLoaded, {}};
|
||||
}
|
||||
@@ -66,7 +65,7 @@ AppLoader_NAX::LoadResult AppLoader_NAX::Load(Kernel::Process& process,
|
||||
return {nca_status, {}};
|
||||
}
|
||||
|
||||
const auto result = nca_loader->Load(process, system);
|
||||
const auto result = nca_loader->Load(process);
|
||||
if (result.first != ResultStatus::Success) {
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -8,12 +8,10 @@
|
||||
#include "common/common_types.h"
|
||||
#include "core/loader/loader.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
class NAX;
|
||||
|
||||
} // namespace FileSys
|
||||
|
||||
namespace Loader {
|
||||
@@ -35,7 +33,7 @@ public:
|
||||
|
||||
FileType GetFileType() const override;
|
||||
|
||||
LoadResult Load(Kernel::Process& process, Core::System& system) override;
|
||||
LoadResult Load(Kernel::Process& process) override;
|
||||
|
||||
ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
|
||||
u64 ReadRomFSIVFCOffset() const override;
|
||||
|
||||
@@ -31,7 +31,7 @@ FileType AppLoader_NCA::IdentifyType(const FileSys::VirtualFile& file) {
|
||||
return FileType::Error;
|
||||
}
|
||||
|
||||
AppLoader_NCA::LoadResult AppLoader_NCA::Load(Kernel::Process& process, Core::System& system) {
|
||||
AppLoader_NCA::LoadResult AppLoader_NCA::Load(Kernel::Process& process) {
|
||||
if (is_loaded) {
|
||||
return {ResultStatus::ErrorAlreadyLoaded, {}};
|
||||
}
|
||||
@@ -52,14 +52,14 @@ AppLoader_NCA::LoadResult AppLoader_NCA::Load(Kernel::Process& process, Core::Sy
|
||||
|
||||
directory_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(exefs, true);
|
||||
|
||||
const auto load_result = directory_loader->Load(process, system);
|
||||
const auto load_result = directory_loader->Load(process);
|
||||
if (load_result.first != ResultStatus::Success) {
|
||||
return load_result;
|
||||
}
|
||||
|
||||
if (nca->GetRomFS() != nullptr && nca->GetRomFS()->GetSize() > 0) {
|
||||
system.GetFileSystemController().RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(
|
||||
*this, system.GetContentProvider(), system.GetFileSystemController()));
|
||||
Core::System::GetInstance().GetFileSystemController().RegisterRomFS(
|
||||
std::make_unique<FileSys::RomFSFactory>(*this));
|
||||
}
|
||||
|
||||
is_loaded = true;
|
||||
|
||||
@@ -8,10 +8,6 @@
|
||||
#include "core/file_sys/vfs.h"
|
||||
#include "core/loader/loader.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace FileSys {
|
||||
class NCA;
|
||||
}
|
||||
@@ -37,7 +33,7 @@ public:
|
||||
return IdentifyType(file);
|
||||
}
|
||||
|
||||
LoadResult Load(Kernel::Process& process, Core::System& system) override;
|
||||
LoadResult Load(Kernel::Process& process) override;
|
||||
|
||||
ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
|
||||
u64 ReadRomFSIVFCOffset() const override;
|
||||
|
||||
@@ -208,7 +208,7 @@ bool AppLoader_NRO::LoadNro(Kernel::Process& process, const FileSys::VfsFile& fi
|
||||
return LoadNroImpl(process, file.ReadAllBytes(), file.GetName());
|
||||
}
|
||||
|
||||
AppLoader_NRO::LoadResult AppLoader_NRO::Load(Kernel::Process& process, Core::System& system) {
|
||||
AppLoader_NRO::LoadResult AppLoader_NRO::Load(Kernel::Process& process) {
|
||||
if (is_loaded) {
|
||||
return {ResultStatus::ErrorAlreadyLoaded, {}};
|
||||
}
|
||||
@@ -218,8 +218,8 @@ AppLoader_NRO::LoadResult AppLoader_NRO::Load(Kernel::Process& process, Core::Sy
|
||||
}
|
||||
|
||||
if (romfs != nullptr) {
|
||||
system.GetFileSystemController().RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(
|
||||
*this, system.GetContentProvider(), system.GetFileSystemController()));
|
||||
Core::System::GetInstance().GetFileSystemController().RegisterRomFS(
|
||||
std::make_unique<FileSys::RomFSFactory>(*this));
|
||||
}
|
||||
|
||||
is_loaded = true;
|
||||
|
||||
@@ -10,10 +10,6 @@
|
||||
#include "common/common_types.h"
|
||||
#include "core/loader/loader.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace FileSys {
|
||||
class NACP;
|
||||
}
|
||||
@@ -41,7 +37,7 @@ public:
|
||||
return IdentifyType(file);
|
||||
}
|
||||
|
||||
LoadResult Load(Kernel::Process& process, Core::System& system) override;
|
||||
LoadResult Load(Kernel::Process& process) override;
|
||||
|
||||
ResultStatus ReadIcon(std::vector<u8>& buffer) override;
|
||||
ResultStatus ReadProgramId(u64& out_program_id) override;
|
||||
|
||||
@@ -71,21 +71,21 @@ FileType AppLoader_NSO::IdentifyType(const FileSys::VirtualFile& file) {
|
||||
return FileType::NSO;
|
||||
}
|
||||
|
||||
std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, Core::System& system,
|
||||
std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
|
||||
const FileSys::VfsFile& file, VAddr load_base,
|
||||
bool should_pass_arguments, bool load_into_process,
|
||||
std::optional<FileSys::PatchManager> pm) {
|
||||
if (file.GetSize() < sizeof(NSOHeader)) {
|
||||
return std::nullopt;
|
||||
return {};
|
||||
}
|
||||
|
||||
NSOHeader nso_header{};
|
||||
if (sizeof(NSOHeader) != file.ReadObject(&nso_header)) {
|
||||
return std::nullopt;
|
||||
return {};
|
||||
}
|
||||
|
||||
if (nso_header.magic != Common::MakeMagic('N', 'S', 'O', '0')) {
|
||||
return std::nullopt;
|
||||
return {};
|
||||
}
|
||||
|
||||
// Build program image
|
||||
@@ -148,6 +148,7 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, Core::S
|
||||
|
||||
// Apply cheats if they exist and the program has a valid title ID
|
||||
if (pm) {
|
||||
auto& system = Core::System::GetInstance();
|
||||
system.SetCurrentProcessBuildID(nso_header.build_id);
|
||||
const auto cheats = pm->CreateCheatList(system, nso_header.build_id);
|
||||
if (!cheats.empty()) {
|
||||
@@ -165,7 +166,7 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, Core::S
|
||||
return load_base + image_size;
|
||||
}
|
||||
|
||||
AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::Process& process, Core::System& system) {
|
||||
AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::Process& process) {
|
||||
if (is_loaded) {
|
||||
return {ResultStatus::ErrorAlreadyLoaded, {}};
|
||||
}
|
||||
@@ -174,7 +175,7 @@ AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::Process& process, Core::Sy
|
||||
|
||||
// Load module
|
||||
const VAddr base_address = process.PageTable().GetCodeRegionStart();
|
||||
if (!LoadModule(process, system, *file, base_address, true, true)) {
|
||||
if (!LoadModule(process, *file, base_address, true, true)) {
|
||||
return {ResultStatus::ErrorLoadingNSO, {}};
|
||||
}
|
||||
|
||||
|
||||
@@ -12,10 +12,6 @@
|
||||
#include "core/file_sys/patch_manager.h"
|
||||
#include "core/loader/loader.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Kernel {
|
||||
class Process;
|
||||
}
|
||||
@@ -84,12 +80,12 @@ public:
|
||||
return IdentifyType(file);
|
||||
}
|
||||
|
||||
static std::optional<VAddr> LoadModule(Kernel::Process& process, Core::System& system,
|
||||
const FileSys::VfsFile& file, VAddr load_base,
|
||||
bool should_pass_arguments, bool load_into_process,
|
||||
static std::optional<VAddr> LoadModule(Kernel::Process& process, const FileSys::VfsFile& file,
|
||||
VAddr load_base, bool should_pass_arguments,
|
||||
bool load_into_process,
|
||||
std::optional<FileSys::PatchManager> pm = {});
|
||||
|
||||
LoadResult Load(Kernel::Process& process, Core::System& system) override;
|
||||
LoadResult Load(Kernel::Process& process) override;
|
||||
|
||||
ResultStatus ReadNSOModules(Modules& modules) override;
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ FileType AppLoader_NSP::IdentifyType(const FileSys::VirtualFile& file) {
|
||||
return FileType::Error;
|
||||
}
|
||||
|
||||
AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::Process& process, Core::System& system) {
|
||||
AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::Process& process) {
|
||||
if (is_loaded) {
|
||||
return {ResultStatus::ErrorAlreadyLoaded, {}};
|
||||
}
|
||||
@@ -99,14 +99,15 @@ AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::Process& process, Core::Sy
|
||||
return {ResultStatus::ErrorNSPMissingProgramNCA, {}};
|
||||
}
|
||||
|
||||
const auto result = secondary_loader->Load(process, system);
|
||||
const auto result = secondary_loader->Load(process);
|
||||
if (result.first != ResultStatus::Success) {
|
||||
return result;
|
||||
}
|
||||
|
||||
FileSys::VirtualFile update_raw;
|
||||
if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) {
|
||||
system.GetFileSystemController().SetPackedUpdate(std::move(update_raw));
|
||||
Core::System::GetInstance().GetFileSystemController().SetPackedUpdate(
|
||||
std::move(update_raw));
|
||||
}
|
||||
|
||||
is_loaded = true;
|
||||
|
||||
@@ -9,10 +9,6 @@
|
||||
#include "core/file_sys/vfs.h"
|
||||
#include "core/loader/loader.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace FileSys {
|
||||
class NACP;
|
||||
class NSP;
|
||||
@@ -39,7 +35,7 @@ public:
|
||||
return IdentifyType(file);
|
||||
}
|
||||
|
||||
LoadResult Load(Kernel::Process& process, Core::System& system) override;
|
||||
LoadResult Load(Kernel::Process& process) override;
|
||||
|
||||
ResultStatus ReadRomFS(FileSys::VirtualFile& file) override;
|
||||
u64 ReadRomFSIVFCOffset() const override;
|
||||
|
||||
@@ -49,7 +49,7 @@ FileType AppLoader_XCI::IdentifyType(const FileSys::VirtualFile& file) {
|
||||
return FileType::Error;
|
||||
}
|
||||
|
||||
AppLoader_XCI::LoadResult AppLoader_XCI::Load(Kernel::Process& process, Core::System& system) {
|
||||
AppLoader_XCI::LoadResult AppLoader_XCI::Load(Kernel::Process& process) {
|
||||
if (is_loaded) {
|
||||
return {ResultStatus::ErrorAlreadyLoaded, {}};
|
||||
}
|
||||
@@ -66,14 +66,15 @@ AppLoader_XCI::LoadResult AppLoader_XCI::Load(Kernel::Process& process, Core::Sy
|
||||
return {ResultStatus::ErrorMissingProductionKeyFile, {}};
|
||||
}
|
||||
|
||||
const auto result = nca_loader->Load(process, system);
|
||||
const auto result = nca_loader->Load(process);
|
||||
if (result.first != ResultStatus::Success) {
|
||||
return result;
|
||||
}
|
||||
|
||||
FileSys::VirtualFile update_raw;
|
||||
if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) {
|
||||
system.GetFileSystemController().SetPackedUpdate(std::move(update_raw));
|
||||
Core::System::GetInstance().GetFileSystemController().SetPackedUpdate(
|
||||
std::move(update_raw));
|
||||
}
|
||||
|
||||
is_loaded = true;
|
||||
|
||||
@@ -9,10 +9,6 @@
|
||||
#include "core/file_sys/vfs.h"
|
||||
#include "core/loader/loader.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace FileSys {
|
||||
class NACP;
|
||||
class XCI;
|
||||
@@ -39,7 +35,7 @@ public:
|
||||
return IdentifyType(file);
|
||||
}
|
||||
|
||||
LoadResult Load(Kernel::Process& process, Core::System& system) override;
|
||||
LoadResult Load(Kernel::Process& process) override;
|
||||
|
||||
ResultStatus ReadRomFS(FileSys::VirtualFile& file) override;
|
||||
u64 ReadRomFSIVFCOffset() const override;
|
||||
|
||||
+1
-1
@@ -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 target The target address to begin mapping from.
|
||||
* @param memory The memory to map.
|
||||
* @param type The page type to map the memory as.
|
||||
*/
|
||||
void MapPages(Common::PageTable& page_table, VAddr base, u64 size, PAddr target,
|
||||
|
||||
@@ -19,24 +19,10 @@
|
||||
#include "core/memory/cheat_engine.h"
|
||||
|
||||
namespace Core::Memory {
|
||||
namespace {
|
||||
|
||||
constexpr auto CHEAT_ENGINE_NS = std::chrono::nanoseconds{1000000000 / 12};
|
||||
constexpr u32 KEYPAD_BITMASK = 0x3FFFFFF;
|
||||
|
||||
std::string_view ExtractName(std::string_view data, std::size_t start_index, char match) {
|
||||
auto end_index = start_index;
|
||||
while (data[end_index] != match) {
|
||||
++end_index;
|
||||
if (end_index > data.size() ||
|
||||
(end_index - start_index - 1) > sizeof(CheatDefinition::readable_name)) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
return data.substr(start_index, end_index - start_index);
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
StandardVmCallbacks::StandardVmCallbacks(Core::System& system, const CheatProcessMetadata& metadata)
|
||||
: metadata(metadata), system(system) {}
|
||||
|
||||
@@ -96,9 +82,26 @@ CheatParser::~CheatParser() = default;
|
||||
|
||||
TextCheatParser::~TextCheatParser() = default;
|
||||
|
||||
std::vector<CheatEntry> TextCheatParser::Parse(std::string_view data) const {
|
||||
namespace {
|
||||
template <char match>
|
||||
std::string_view ExtractName(std::string_view data, std::size_t start_index) {
|
||||
auto end_index = start_index;
|
||||
while (data[end_index] != match) {
|
||||
++end_index;
|
||||
if (end_index > data.size() ||
|
||||
(end_index - start_index - 1) > sizeof(CheatDefinition::readable_name)) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
return data.substr(start_index, end_index - start_index);
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
std::vector<CheatEntry> TextCheatParser::Parse(const Core::System& system,
|
||||
std::string_view data) const {
|
||||
std::vector<CheatEntry> out(1);
|
||||
std::optional<u64> current_entry;
|
||||
std::optional<u64> current_entry = std::nullopt;
|
||||
|
||||
for (std::size_t i = 0; i < data.size(); ++i) {
|
||||
if (::isspace(data[i])) {
|
||||
@@ -112,7 +115,7 @@ std::vector<CheatEntry> TextCheatParser::Parse(std::string_view data) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto name = ExtractName(data, i + 1, '}');
|
||||
const auto name = ExtractName<'}'>(data, i + 1);
|
||||
if (name.empty()) {
|
||||
return {};
|
||||
}
|
||||
@@ -129,7 +132,7 @@ std::vector<CheatEntry> TextCheatParser::Parse(std::string_view data) const {
|
||||
current_entry = out.size();
|
||||
out.emplace_back();
|
||||
|
||||
const auto name = ExtractName(data, i + 1, ']');
|
||||
const auto name = ExtractName<']'>(data, i + 1);
|
||||
if (name.empty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -47,7 +47,8 @@ class CheatParser {
|
||||
public:
|
||||
virtual ~CheatParser();
|
||||
|
||||
[[nodiscard]] virtual std::vector<CheatEntry> Parse(std::string_view data) const = 0;
|
||||
virtual std::vector<CheatEntry> Parse(const Core::System& system,
|
||||
std::string_view data) const = 0;
|
||||
};
|
||||
|
||||
// CheatParser implementation that parses text files
|
||||
@@ -55,7 +56,7 @@ class TextCheatParser final : public CheatParser {
|
||||
public:
|
||||
~TextCheatParser() override;
|
||||
|
||||
[[nodiscard]] std::vector<CheatEntry> Parse(std::string_view data) const override;
|
||||
std::vector<CheatEntry> Parse(const Core::System& system, std::string_view data) const override;
|
||||
};
|
||||
|
||||
// Class that encapsulates a CheatList and manages its interaction with memory and CoreTiming
|
||||
|
||||
@@ -152,7 +152,6 @@ struct Values {
|
||||
|
||||
bool vibration_enabled;
|
||||
|
||||
bool motion_enabled;
|
||||
std::string motion_device;
|
||||
std::string touch_device;
|
||||
TouchscreenInput touchscreen;
|
||||
|
||||
@@ -4,20 +4,9 @@
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4200) // nonstandard extension used : zero-sized array in struct/union
|
||||
#endif
|
||||
#include <libusb.h>
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#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 {
|
||||
|
||||
@@ -294,92 +283,6 @@ 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;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <unordered_map>
|
||||
#include "common/common_types.h"
|
||||
#include "common/threadsafe_queue.h"
|
||||
#include "input_common/main.h"
|
||||
|
||||
struct libusb_context;
|
||||
struct libusb_device;
|
||||
@@ -76,10 +75,6 @@ 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;
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "input_common/main.h"
|
||||
#include "input_common/motion_emu.h"
|
||||
#include "input_common/touch_from_button.h"
|
||||
#include "input_common/udp/client.h"
|
||||
#include "input_common/udp/udp.h"
|
||||
#ifdef HAVE_SDL2
|
||||
#include "input_common/sdl/sdl.h"
|
||||
@@ -22,7 +21,7 @@ namespace InputCommon {
|
||||
|
||||
struct InputSubsystem::Impl {
|
||||
void Initialize() {
|
||||
gcadapter = std::make_shared<GCAdapter::Adapter>();
|
||||
auto gcadapter = std::make_shared<GCAdapter::Adapter>();
|
||||
gcbuttons = std::make_shared<GCButtonFactory>(gcadapter);
|
||||
Input::RegisterFactory<Input::ButtonDevice>("gcpad", gcbuttons);
|
||||
gcanalog = std::make_shared<GCAnalogFactory>(gcadapter);
|
||||
@@ -41,11 +40,7 @@ struct InputSubsystem::Impl {
|
||||
sdl = SDL::Init();
|
||||
#endif
|
||||
|
||||
udp = std::make_shared<InputCommon::CemuhookUDP::Client>();
|
||||
udpmotion = std::make_shared<UDPMotionFactory>(udp);
|
||||
Input::RegisterFactory<Input::MotionDevice>("cemuhookudp", udpmotion);
|
||||
udptouch = std::make_shared<UDPTouchFactory>(udp);
|
||||
Input::RegisterFactory<Input::TouchDevice>("cemuhookudp", udptouch);
|
||||
udp = CemuhookUDP::Init();
|
||||
}
|
||||
|
||||
void Shutdown() {
|
||||
@@ -58,17 +53,12 @@ struct InputSubsystem::Impl {
|
||||
#ifdef HAVE_SDL2
|
||||
sdl.reset();
|
||||
#endif
|
||||
udp.reset();
|
||||
Input::UnregisterFactory<Input::ButtonDevice>("gcpad");
|
||||
Input::UnregisterFactory<Input::AnalogDevice>("gcpad");
|
||||
|
||||
gcbuttons.reset();
|
||||
gcanalog.reset();
|
||||
|
||||
Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp");
|
||||
Input::UnregisterFactory<Input::TouchDevice>("cemuhookudp");
|
||||
|
||||
udpmotion.reset();
|
||||
udptouch.reset();
|
||||
}
|
||||
|
||||
[[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const {
|
||||
@@ -82,8 +72,6 @@ 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;
|
||||
}
|
||||
|
||||
@@ -96,9 +84,6 @@ 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);
|
||||
@@ -116,9 +101,6 @@ 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);
|
||||
@@ -127,29 +109,14 @@ struct InputSubsystem::Impl {
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]] MotionMapping GetMotionMappingForDevice(
|
||||
const Common::ParamPackage& params) const {
|
||||
if (!params.Has("class") || params.Get("class", "") == "any") {
|
||||
return {};
|
||||
}
|
||||
if (params.Get("class", "") == "cemuhookudp") {
|
||||
// TODO return the correct motion device
|
||||
return {};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
std::shared_ptr<Keyboard> keyboard;
|
||||
std::shared_ptr<MotionEmu> motion_emu;
|
||||
#ifdef HAVE_SDL2
|
||||
std::unique_ptr<SDL::State> sdl;
|
||||
#endif
|
||||
std::unique_ptr<CemuhookUDP::State> udp;
|
||||
std::shared_ptr<GCButtonFactory> gcbuttons;
|
||||
std::shared_ptr<GCAnalogFactory> gcanalog;
|
||||
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>()} {}
|
||||
@@ -208,22 +175,6 @@ const GCButtonFactory* InputSubsystem::GetGCButtons() const {
|
||||
return impl->gcbuttons.get();
|
||||
}
|
||||
|
||||
UDPMotionFactory* InputSubsystem::GetUDPMotions() {
|
||||
return impl->udpmotion.get();
|
||||
}
|
||||
|
||||
const UDPMotionFactory* InputSubsystem::GetUDPMotions() const {
|
||||
return impl->udpmotion.get();
|
||||
}
|
||||
|
||||
UDPTouchFactory* InputSubsystem::GetUDPTouch() {
|
||||
return impl->udptouch.get();
|
||||
}
|
||||
|
||||
const UDPTouchFactory* InputSubsystem::GetUDPTouch() const {
|
||||
return impl->udptouch.get();
|
||||
}
|
||||
|
||||
void InputSubsystem::ReloadInputDevices() {
|
||||
if (!impl->udp) {
|
||||
return;
|
||||
|
||||
+1
-23
@@ -21,14 +21,10 @@ namespace Settings::NativeButton {
|
||||
enum Values : int;
|
||||
}
|
||||
|
||||
namespace Settings::NativeMotion {
|
||||
enum Values : int;
|
||||
}
|
||||
|
||||
namespace InputCommon {
|
||||
namespace Polling {
|
||||
|
||||
enum class DeviceType { Button, AnalogPreferred, Motion };
|
||||
enum class DeviceType { Button, AnalogPreferred };
|
||||
|
||||
/**
|
||||
* A class that can be used to get inputs from an input device like controllers without having to
|
||||
@@ -54,8 +50,6 @@ public:
|
||||
|
||||
class GCAnalogFactory;
|
||||
class GCButtonFactory;
|
||||
class UDPMotionFactory;
|
||||
class UDPTouchFactory;
|
||||
class Keyboard;
|
||||
class MotionEmu;
|
||||
|
||||
@@ -65,7 +59,6 @@ class MotionEmu;
|
||||
*/
|
||||
using AnalogMapping = std::unordered_map<Settings::NativeAnalog::Values, Common::ParamPackage>;
|
||||
using ButtonMapping = std::unordered_map<Settings::NativeButton::Values, Common::ParamPackage>;
|
||||
using MotionMapping = std::unordered_map<Settings::NativeMotion::Values, Common::ParamPackage>;
|
||||
|
||||
class InputSubsystem {
|
||||
public:
|
||||
@@ -110,9 +103,6 @@ public:
|
||||
/// Retrieves the button mappings for the given device.
|
||||
[[nodiscard]] ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& device) const;
|
||||
|
||||
/// Retrieves the motion mappings for the given device.
|
||||
[[nodiscard]] MotionMapping GetMotionMappingForDevice(const Common::ParamPackage& device) const;
|
||||
|
||||
/// Retrieves the underlying GameCube analog handler.
|
||||
[[nodiscard]] GCAnalogFactory* GetGCAnalogs();
|
||||
|
||||
@@ -125,18 +115,6 @@ public:
|
||||
/// Retrieves the underlying GameCube button handler.
|
||||
[[nodiscard]] const GCButtonFactory* GetGCButtons() const;
|
||||
|
||||
/// Retrieves the underlying udp motion handler.
|
||||
[[nodiscard]] UDPMotionFactory* GetUDPMotions();
|
||||
|
||||
/// Retrieves the underlying udp motion handler.
|
||||
[[nodiscard]] const UDPMotionFactory* GetUDPMotions() const;
|
||||
|
||||
/// Retrieves the underlying udp touch handler.
|
||||
[[nodiscard]] UDPTouchFactory* GetUDPTouch();
|
||||
|
||||
/// Retrieves the underlying udp touch handler.
|
||||
[[nodiscard]] const UDPTouchFactory* GetUDPTouch() const;
|
||||
|
||||
/// Reloads the input devices
|
||||
void ReloadInputDevices();
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
is_tilting = false;
|
||||
}
|
||||
|
||||
Input::MotionStatus GetStatus() {
|
||||
std::tuple<Common::Vec3<float>, Common::Vec3<float>> GetStatus() {
|
||||
std::lock_guard guard{status_mutex};
|
||||
return status;
|
||||
}
|
||||
@@ -76,7 +76,7 @@ private:
|
||||
|
||||
Common::Event shutdown_event;
|
||||
|
||||
Input::MotionStatus status;
|
||||
std::tuple<Common::Vec3<float>, Common::Vec3<float>> status;
|
||||
std::mutex status_mutex;
|
||||
|
||||
// Note: always keep the thread declaration at the end so that other objects are initialized
|
||||
@@ -113,19 +113,10 @@ private:
|
||||
gravity = QuaternionRotate(inv_q, gravity);
|
||||
angular_rate = QuaternionRotate(inv_q, angular_rate);
|
||||
|
||||
// TODO: Calculate the correct rotation vector and orientation matrix
|
||||
const auto matrix4x4 = q.ToMatrix();
|
||||
const auto rotation = Common::MakeVec(0.0f, 0.0f, 0.0f);
|
||||
const std::array orientation{
|
||||
Common::Vec3f(matrix4x4[0], matrix4x4[1], -matrix4x4[2]),
|
||||
Common::Vec3f(matrix4x4[4], matrix4x4[5], -matrix4x4[6]),
|
||||
Common::Vec3f(-matrix4x4[8], -matrix4x4[9], matrix4x4[10]),
|
||||
};
|
||||
|
||||
// Update the sensor state
|
||||
{
|
||||
std::lock_guard guard{status_mutex};
|
||||
status = std::make_tuple(gravity, angular_rate, rotation, orientation);
|
||||
status = std::make_tuple(gravity, angular_rate);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,7 +131,7 @@ public:
|
||||
device = std::make_shared<MotionEmuDevice>(update_millisecond, sensitivity);
|
||||
}
|
||||
|
||||
Input::MotionStatus GetStatus() const override {
|
||||
std::tuple<Common::Vec3<float>, Common::Vec3<float>> GetStatus() const override {
|
||||
return device->GetStatus();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
@@ -79,33 +78,6 @@ public:
|
||||
return state.axes.at(axis) / (32767.0f * range);
|
||||
}
|
||||
|
||||
bool RumblePlay(f32 amp_low, f32 amp_high, int time) {
|
||||
const u16 raw_amp_low = static_cast<u16>(amp_low * 0xFFFF);
|
||||
const u16 raw_amp_high = static_cast<u16>(amp_high * 0xFFFF);
|
||||
// Lower drastically the number of state changes
|
||||
if (raw_amp_low >> 11 == last_state_rumble_low >> 11 &&
|
||||
raw_amp_high >> 11 == last_state_rumble_high >> 11) {
|
||||
if (raw_amp_low + raw_amp_high != 0 ||
|
||||
last_state_rumble_low + last_state_rumble_high == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Don't change state if last vibration was < 20ms
|
||||
const auto now = std::chrono::system_clock::now();
|
||||
if (std::chrono::duration_cast<std::chrono::milliseconds>(now - last_vibration) <
|
||||
std::chrono::milliseconds(20)) {
|
||||
return raw_amp_low + raw_amp_high == 0;
|
||||
}
|
||||
|
||||
last_vibration = now;
|
||||
last_state_rumble_low = raw_amp_low;
|
||||
last_state_rumble_high = raw_amp_high;
|
||||
if (sdl_joystick) {
|
||||
SDL_JoystickRumble(sdl_joystick.get(), raw_amp_low, raw_amp_high, time);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::tuple<float, float> GetAnalog(int axis_x, int axis_y, float range) const {
|
||||
float x = GetAxis(axis_x, range);
|
||||
float y = GetAxis(axis_y, range);
|
||||
@@ -167,9 +139,6 @@ private:
|
||||
} state;
|
||||
std::string guid;
|
||||
int port;
|
||||
u16 last_state_rumble_high;
|
||||
u16 last_state_rumble_low;
|
||||
std::chrono::time_point<std::chrono::system_clock> last_vibration;
|
||||
std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick;
|
||||
std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller;
|
||||
mutable std::mutex mutex;
|
||||
@@ -238,7 +207,7 @@ void SDLState::InitJoystick(int joystick_index) {
|
||||
sdl_gamecontroller = SDL_GameControllerOpen(joystick_index);
|
||||
}
|
||||
if (!sdl_joystick) {
|
||||
LOG_ERROR(Input, "Failed to open joystick {}", joystick_index);
|
||||
LOG_ERROR(Input, "failed to open joystick {}", joystick_index);
|
||||
return;
|
||||
}
|
||||
const std::string guid = GetGUID(sdl_joystick);
|
||||
@@ -334,12 +303,6 @@ public:
|
||||
return joystick->GetButton(button);
|
||||
}
|
||||
|
||||
bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const override {
|
||||
const f32 new_amp_low = pow(amp_low, 0.5f) * (3.0f - 2.0f * pow(amp_low, 0.15f));
|
||||
const f32 new_amp_high = pow(amp_high, 0.5f) * (3.0f - 2.0f * pow(amp_high, 0.15f));
|
||||
return joystick->RumblePlay(new_amp_low, new_amp_high, 250);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<SDLJoystick> joystick;
|
||||
int button;
|
||||
|
||||
@@ -14,13 +14,6 @@ const std::array<const char*, NumButtons> mapping = {{
|
||||
}};
|
||||
}
|
||||
|
||||
namespace NativeMotion {
|
||||
const std::array<const char*, NumMotions> mapping = {{
|
||||
"motionleft",
|
||||
"motionright",
|
||||
}};
|
||||
}
|
||||
|
||||
namespace NativeAnalog {
|
||||
const std::array<const char*, NumAnalogs> mapping = {{
|
||||
"lstick",
|
||||
|
||||
@@ -66,21 +66,6 @@ constexpr int NUM_STICKS_HID = NumAnalogs;
|
||||
extern const std::array<const char*, NumAnalogs> mapping;
|
||||
} // namespace NativeAnalog
|
||||
|
||||
namespace NativeMotion {
|
||||
enum Values : int {
|
||||
MOTIONLEFT,
|
||||
MOTIONRIGHT,
|
||||
|
||||
NumMotions,
|
||||
};
|
||||
|
||||
constexpr int MOTION_HID_BEGIN = MOTIONLEFT;
|
||||
constexpr int MOTION_HID_END = NumMotions;
|
||||
constexpr int NUM_MOTION_HID = NumMotions;
|
||||
|
||||
extern const std::array<const char*, NumMotions> mapping;
|
||||
} // namespace NativeMotion
|
||||
|
||||
namespace NativeMouseButton {
|
||||
enum Values {
|
||||
Left,
|
||||
@@ -307,7 +292,6 @@ constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods;
|
||||
|
||||
using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>;
|
||||
using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>;
|
||||
using MotionRaw = std::array<std::string, NativeMotion::NumMotions>;
|
||||
using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>;
|
||||
using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>;
|
||||
using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>;
|
||||
@@ -330,7 +314,6 @@ struct PlayerInput {
|
||||
ControllerType controller_type;
|
||||
ButtonsRaw buttons;
|
||||
AnalogsRaw analogs;
|
||||
MotionRaw motions;
|
||||
std::string lstick_mod;
|
||||
std::string rstick_mod;
|
||||
|
||||
|
||||
+30
-146
@@ -2,13 +2,14 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
#include <boost/asio.hpp>
|
||||
#include "common/logging/log.h"
|
||||
#include "core/settings.h"
|
||||
#include "input_common/udp/client.h"
|
||||
#include "input_common/udp/protocol.h"
|
||||
|
||||
@@ -130,59 +131,21 @@ static void SocketLoop(Socket* socket) {
|
||||
socket->Loop();
|
||||
}
|
||||
|
||||
Client::Client() {
|
||||
LOG_INFO(Input, "Udp Initialization started");
|
||||
for (std::size_t client = 0; client < clients.size(); client++) {
|
||||
u8 pad = client % 4;
|
||||
StartCommunication(client, Settings::values.udp_input_address,
|
||||
Settings::values.udp_input_port, pad, 24872);
|
||||
// Set motion parameters
|
||||
// SetGyroThreshold value should be dependent on GyroscopeZeroDriftMode
|
||||
// Real HW values are unknown, 0.0001 is an approximate to Standard
|
||||
clients[client].motion.SetGyroThreshold(0.0001f);
|
||||
}
|
||||
Client::Client(std::shared_ptr<DeviceStatus> status, const std::string& host, u16 port,
|
||||
u8 pad_index, u32 client_id)
|
||||
: status(std::move(status)) {
|
||||
StartCommunication(host, port, pad_index, client_id);
|
||||
}
|
||||
|
||||
Client::~Client() {
|
||||
Reset();
|
||||
socket->Stop();
|
||||
thread.join();
|
||||
}
|
||||
|
||||
std::vector<Common::ParamPackage> Client::GetInputDevices() const {
|
||||
std::vector<Common::ParamPackage> devices;
|
||||
for (std::size_t client = 0; client < clients.size(); client++) {
|
||||
if (!DeviceConnected(client)) {
|
||||
continue;
|
||||
}
|
||||
std::string name = fmt::format("UDP Controller {}", client);
|
||||
devices.emplace_back(Common::ParamPackage{
|
||||
{"class", "cemuhookudp"},
|
||||
{"display", std::move(name)},
|
||||
{"port", std::to_string(client)},
|
||||
});
|
||||
}
|
||||
return devices;
|
||||
}
|
||||
|
||||
bool Client::DeviceConnected(std::size_t pad) const {
|
||||
// Use last timestamp to detect if the socket has stopped sending data
|
||||
const auto now = std::chrono::system_clock::now();
|
||||
u64 time_difference =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(now - clients[pad].last_motion_update)
|
||||
.count();
|
||||
return time_difference < 1000 && clients[pad].active == 1;
|
||||
}
|
||||
|
||||
void Client::ReloadUDPClient() {
|
||||
for (std::size_t client = 0; client < clients.size(); client++) {
|
||||
ReloadSocket(Settings::values.udp_input_address, Settings::values.udp_input_port, client);
|
||||
}
|
||||
}
|
||||
void Client::ReloadSocket(const std::string& host, u16 port, u8 pad_index, u32 client_id) {
|
||||
// client number must be determined from host / port and pad index
|
||||
std::size_t client = pad_index;
|
||||
clients[client].socket->Stop();
|
||||
clients[client].thread.join();
|
||||
StartCommunication(client, host, port, pad_index, client_id);
|
||||
socket->Stop();
|
||||
thread.join();
|
||||
StartCommunication(host, port, pad_index, client_id);
|
||||
}
|
||||
|
||||
void Client::OnVersion(Response::Version data) {
|
||||
@@ -194,39 +157,23 @@ void Client::OnPortInfo(Response::PortInfo data) {
|
||||
}
|
||||
|
||||
void Client::OnPadData(Response::PadData data) {
|
||||
// client number must be determined from host / port and pad index
|
||||
std::size_t client = data.info.id;
|
||||
LOG_TRACE(Input, "PadData packet received");
|
||||
if (data.packet_counter == clients[client].packet_sequence) {
|
||||
if (data.packet_counter <= packet_sequence) {
|
||||
LOG_WARNING(
|
||||
Input,
|
||||
"PadData packet dropped because its stale info. Current count: {} Packet count: {}",
|
||||
clients[client].packet_sequence, data.packet_counter);
|
||||
packet_sequence, data.packet_counter);
|
||||
return;
|
||||
}
|
||||
clients[client].active = data.info.is_pad_active;
|
||||
clients[client].packet_sequence = data.packet_counter;
|
||||
const auto now = std::chrono::system_clock::now();
|
||||
u64 time_difference = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
now - clients[client].last_motion_update)
|
||||
.count();
|
||||
clients[client].last_motion_update = now;
|
||||
Common::Vec3f raw_gyroscope = {data.gyro.pitch, data.gyro.roll, -data.gyro.yaw};
|
||||
clients[client].motion.SetAcceleration({data.accel.x, -data.accel.z, data.accel.y});
|
||||
// Gyroscope values are not it the correct scale from better joy.
|
||||
// Dividing by 312 allows us to make one full turn = 1 turn
|
||||
// This must be a configurable valued called sensitivity
|
||||
clients[client].motion.SetGyroscope(raw_gyroscope / 312.0f);
|
||||
clients[client].motion.UpdateRotation(time_difference);
|
||||
clients[client].motion.UpdateOrientation(time_difference);
|
||||
Common::Vec3f gyroscope = clients[client].motion.GetGyroscope();
|
||||
Common::Vec3f accelerometer = clients[client].motion.GetAcceleration();
|
||||
Common::Vec3f rotation = clients[client].motion.GetRotations();
|
||||
std::array<Common::Vec3f, 3> orientation = clients[client].motion.GetOrientation();
|
||||
|
||||
packet_sequence = data.packet_counter;
|
||||
// TODO: Check how the Switch handles motions and how the CemuhookUDP motion
|
||||
// directions correspond to the ones of the Switch
|
||||
Common::Vec3f accel = Common::MakeVec<float>(data.accel.x, data.accel.y, data.accel.z);
|
||||
Common::Vec3f gyro = Common::MakeVec<float>(data.gyro.pitch, data.gyro.yaw, data.gyro.roll);
|
||||
{
|
||||
std::lock_guard guard(clients[client].status.update_mutex);
|
||||
clients[client].status.motion_status = {accelerometer, gyroscope, rotation, orientation};
|
||||
std::lock_guard guard(status->update_mutex);
|
||||
|
||||
status->motion_status = {accel, gyro};
|
||||
|
||||
// TODO: add a setting for "click" touch. Click touch refers to a device that differentiates
|
||||
// between a simple "tap" and a hard press that causes the touch screen to click.
|
||||
@@ -235,11 +182,11 @@ void Client::OnPadData(Response::PadData data) {
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
|
||||
if (is_active && clients[client].status.touch_calibration) {
|
||||
const u16 min_x = clients[client].status.touch_calibration->min_x;
|
||||
const u16 max_x = clients[client].status.touch_calibration->max_x;
|
||||
const u16 min_y = clients[client].status.touch_calibration->min_y;
|
||||
const u16 max_y = clients[client].status.touch_calibration->max_y;
|
||||
if (is_active && status->touch_calibration) {
|
||||
const u16 min_x = status->touch_calibration->min_x;
|
||||
const u16 max_x = status->touch_calibration->max_x;
|
||||
const u16 min_y = status->touch_calibration->min_y;
|
||||
const u16 max_y = status->touch_calibration->max_y;
|
||||
|
||||
x = (std::clamp(static_cast<u16>(data.touch_1.x), min_x, max_x) - min_x) /
|
||||
static_cast<float>(max_x - min_x);
|
||||
@@ -247,80 +194,17 @@ void Client::OnPadData(Response::PadData data) {
|
||||
static_cast<float>(max_y - min_y);
|
||||
}
|
||||
|
||||
clients[client].status.touch_status = {x, y, is_active};
|
||||
|
||||
if (configuring) {
|
||||
UpdateYuzuSettings(client, accelerometer, gyroscope, is_active);
|
||||
}
|
||||
status->touch_status = {x, y, is_active};
|
||||
}
|
||||
}
|
||||
|
||||
void Client::StartCommunication(std::size_t client, const std::string& host, u16 port, u8 pad_index,
|
||||
u32 client_id) {
|
||||
void Client::StartCommunication(const std::string& host, u16 port, u8 pad_index, u32 client_id) {
|
||||
SocketCallback callback{[this](Response::Version version) { OnVersion(version); },
|
||||
[this](Response::PortInfo info) { OnPortInfo(info); },
|
||||
[this](Response::PadData data) { OnPadData(data); }};
|
||||
LOG_INFO(Input, "Starting communication with UDP input server on {}:{}", host, port);
|
||||
clients[client].socket = std::make_unique<Socket>(host, port, pad_index, client_id, callback);
|
||||
clients[client].thread = std::thread{SocketLoop, clients[client].socket.get()};
|
||||
}
|
||||
|
||||
void Client::Reset() {
|
||||
for (std::size_t client = 0; client < clients.size(); client++) {
|
||||
clients[client].socket->Stop();
|
||||
clients[client].thread.join();
|
||||
}
|
||||
}
|
||||
|
||||
void Client::UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc,
|
||||
const Common::Vec3<float>& gyro, bool touch) {
|
||||
UDPPadStatus pad;
|
||||
if (touch) {
|
||||
pad.touch = PadTouch::Click;
|
||||
pad_queue[client].Push(pad);
|
||||
}
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
if (gyro[i] > 6.0f || gyro[i] < -6.0f) {
|
||||
pad.motion = static_cast<PadMotion>(i);
|
||||
pad.motion_value = gyro[i];
|
||||
pad_queue[client].Push(pad);
|
||||
}
|
||||
if (acc[i] > 2.0f || acc[i] < -2.0f) {
|
||||
pad.motion = static_cast<PadMotion>(i + 3);
|
||||
pad.motion_value = acc[i];
|
||||
pad_queue[client].Push(pad);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Client::BeginConfiguration() {
|
||||
for (auto& pq : pad_queue) {
|
||||
pq.Clear();
|
||||
}
|
||||
configuring = true;
|
||||
}
|
||||
|
||||
void Client::EndConfiguration() {
|
||||
for (auto& pq : pad_queue) {
|
||||
pq.Clear();
|
||||
}
|
||||
configuring = false;
|
||||
}
|
||||
|
||||
DeviceStatus& Client::GetPadState(std::size_t pad) {
|
||||
return clients[pad].status;
|
||||
}
|
||||
|
||||
const DeviceStatus& Client::GetPadState(std::size_t pad) const {
|
||||
return clients[pad].status;
|
||||
}
|
||||
|
||||
std::array<Common::SPSCQueue<UDPPadStatus>, 4>& Client::GetPadQueue() {
|
||||
return pad_queue;
|
||||
}
|
||||
|
||||
const std::array<Common::SPSCQueue<UDPPadStatus>, 4>& Client::GetPadQueue() const {
|
||||
return pad_queue;
|
||||
socket = std::make_unique<Socket>(host, port, pad_index, client_id, callback);
|
||||
thread = std::thread{SocketLoop, this->socket.get()};
|
||||
}
|
||||
|
||||
void TestCommunication(const std::string& host, u16 port, u8 pad_index, u32 client_id,
|
||||
|
||||
@@ -12,12 +12,8 @@
|
||||
#include <thread>
|
||||
#include <tuple>
|
||||
#include "common/common_types.h"
|
||||
#include "common/param_package.h"
|
||||
#include "common/thread.h"
|
||||
#include "common/threadsafe_queue.h"
|
||||
#include "common/vector_math.h"
|
||||
#include "core/frontend/input.h"
|
||||
#include "input_common/motion_input.h"
|
||||
|
||||
namespace InputCommon::CemuhookUDP {
|
||||
|
||||
@@ -32,30 +28,9 @@ struct PortInfo;
|
||||
struct Version;
|
||||
} // namespace Response
|
||||
|
||||
enum class PadMotion {
|
||||
GyroX,
|
||||
GyroY,
|
||||
GyroZ,
|
||||
AccX,
|
||||
AccY,
|
||||
AccZ,
|
||||
Undefined,
|
||||
};
|
||||
|
||||
enum class PadTouch {
|
||||
Click,
|
||||
Undefined,
|
||||
};
|
||||
|
||||
struct UDPPadStatus {
|
||||
PadTouch touch{PadTouch::Undefined};
|
||||
PadMotion motion{PadMotion::Undefined};
|
||||
f32 motion_value{0.0f};
|
||||
};
|
||||
|
||||
struct DeviceStatus {
|
||||
std::mutex update_mutex;
|
||||
Input::MotionStatus motion_status;
|
||||
std::tuple<Common::Vec3<float>, Common::Vec3<float>> motion_status;
|
||||
std::tuple<float, float, bool> touch_status;
|
||||
|
||||
// calibration data for scaling the device's touch area to 3ds
|
||||
@@ -70,58 +45,22 @@ struct DeviceStatus {
|
||||
|
||||
class Client {
|
||||
public:
|
||||
// Initialize the UDP client capture and read sequence
|
||||
Client();
|
||||
|
||||
// Close and release the client
|
||||
explicit Client(std::shared_ptr<DeviceStatus> status, const std::string& host = DEFAULT_ADDR,
|
||||
u16 port = DEFAULT_PORT, u8 pad_index = 0, u32 client_id = 24872);
|
||||
~Client();
|
||||
|
||||
// Used for polling
|
||||
void BeginConfiguration();
|
||||
void EndConfiguration();
|
||||
|
||||
std::vector<Common::ParamPackage> GetInputDevices() const;
|
||||
|
||||
bool DeviceConnected(std::size_t pad) const;
|
||||
void ReloadUDPClient();
|
||||
void ReloadSocket(const std::string& host = "127.0.0.1", u16 port = 26760, u8 pad_index = 0,
|
||||
u32 client_id = 24872);
|
||||
|
||||
std::array<Common::SPSCQueue<UDPPadStatus>, 4>& GetPadQueue();
|
||||
const std::array<Common::SPSCQueue<UDPPadStatus>, 4>& GetPadQueue() const;
|
||||
|
||||
DeviceStatus& GetPadState(std::size_t pad);
|
||||
const DeviceStatus& GetPadState(std::size_t pad) const;
|
||||
|
||||
private:
|
||||
struct ClientData {
|
||||
std::unique_ptr<Socket> socket;
|
||||
DeviceStatus status;
|
||||
std::thread thread;
|
||||
u64 packet_sequence = 0;
|
||||
u8 active;
|
||||
|
||||
// Realtime values
|
||||
// motion is initalized with PID values for drift correction on joycons
|
||||
InputCommon::MotionInput motion{0.3f, 0.005f, 0.0f};
|
||||
std::chrono::time_point<std::chrono::system_clock> last_motion_update;
|
||||
};
|
||||
|
||||
// For shutting down, clear all data, join all threads, release usb
|
||||
void Reset();
|
||||
|
||||
void OnVersion(Response::Version);
|
||||
void OnPortInfo(Response::PortInfo);
|
||||
void OnPadData(Response::PadData);
|
||||
void StartCommunication(std::size_t client, const std::string& host, u16 port, u8 pad_index,
|
||||
u32 client_id);
|
||||
void UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc,
|
||||
const Common::Vec3<float>& gyro, bool touch);
|
||||
void StartCommunication(const std::string& host, u16 port, u8 pad_index, u32 client_id);
|
||||
|
||||
bool configuring = false;
|
||||
|
||||
std::array<ClientData, 4> clients;
|
||||
std::array<Common::SPSCQueue<UDPPadStatus>, 4> pad_queue;
|
||||
std::unique_ptr<Socket> socket;
|
||||
std::shared_ptr<DeviceStatus> status;
|
||||
std::thread thread;
|
||||
u64 packet_sequence = 0;
|
||||
};
|
||||
|
||||
/// An async job allowing configuration of the touchpad calibration.
|
||||
|
||||
+87
-126
@@ -1,144 +1,105 @@
|
||||
// Copyright 2020 yuzu Emulator Project
|
||||
// Copyright 2018 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <atomic>
|
||||
#include <list>
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
#include "common/assert.h"
|
||||
#include "common/threadsafe_queue.h"
|
||||
#include <optional>
|
||||
#include <tuple>
|
||||
|
||||
#include "common/param_package.h"
|
||||
#include "core/frontend/input.h"
|
||||
#include "core/settings.h"
|
||||
#include "input_common/udp/client.h"
|
||||
#include "input_common/udp/udp.h"
|
||||
|
||||
namespace InputCommon {
|
||||
namespace InputCommon::CemuhookUDP {
|
||||
|
||||
class UDPMotion final : public Input::MotionDevice {
|
||||
class UDPTouchDevice final : public Input::TouchDevice {
|
||||
public:
|
||||
UDPMotion(std::string ip_, int port_, int pad_, CemuhookUDP::Client* client_)
|
||||
: ip(ip_), port(port_), pad(pad_), client(client_) {}
|
||||
|
||||
Input::MotionStatus GetStatus() const override {
|
||||
return client->GetPadState(pad).motion_status;
|
||||
}
|
||||
|
||||
private:
|
||||
const std::string ip;
|
||||
const int port;
|
||||
const int pad;
|
||||
CemuhookUDP::Client* client;
|
||||
mutable std::mutex mutex;
|
||||
};
|
||||
|
||||
/// A motion device factory that creates motion devices from JC Adapter
|
||||
UDPMotionFactory::UDPMotionFactory(std::shared_ptr<CemuhookUDP::Client> client_)
|
||||
: client(std::move(client_)) {}
|
||||
|
||||
/**
|
||||
* Creates motion device
|
||||
* @param params contains parameters for creating the device:
|
||||
* - "port": the nth jcpad on the adapter
|
||||
*/
|
||||
std::unique_ptr<Input::MotionDevice> UDPMotionFactory::Create(const Common::ParamPackage& params) {
|
||||
const std::string ip = params.Get("ip", "127.0.0.1");
|
||||
const int port = params.Get("port", 26760);
|
||||
const int pad = params.Get("pad_index", 0);
|
||||
|
||||
return std::make_unique<UDPMotion>(ip, port, pad, client.get());
|
||||
}
|
||||
|
||||
void UDPMotionFactory::BeginConfiguration() {
|
||||
polling = true;
|
||||
client->BeginConfiguration();
|
||||
}
|
||||
|
||||
void UDPMotionFactory::EndConfiguration() {
|
||||
polling = false;
|
||||
client->EndConfiguration();
|
||||
}
|
||||
|
||||
Common::ParamPackage UDPMotionFactory::GetNextInput() {
|
||||
Common::ParamPackage params;
|
||||
CemuhookUDP::UDPPadStatus pad;
|
||||
auto& queue = client->GetPadQueue();
|
||||
for (std::size_t pad_number = 0; pad_number < queue.size(); ++pad_number) {
|
||||
while (queue[pad_number].Pop(pad)) {
|
||||
if (pad.motion == CemuhookUDP::PadMotion::Undefined || std::abs(pad.motion_value) < 1) {
|
||||
continue;
|
||||
}
|
||||
params.Set("engine", "cemuhookudp");
|
||||
params.Set("ip", "127.0.0.1");
|
||||
params.Set("port", 26760);
|
||||
params.Set("pad_index", static_cast<int>(pad_number));
|
||||
params.Set("motion", static_cast<u16>(pad.motion));
|
||||
return params;
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
class UDPTouch final : public Input::TouchDevice {
|
||||
public:
|
||||
UDPTouch(std::string ip_, int port_, int pad_, CemuhookUDP::Client* client_)
|
||||
: ip(std::move(ip_)), port(port_), pad(pad_), client(client_) {}
|
||||
|
||||
explicit UDPTouchDevice(std::shared_ptr<DeviceStatus> status_) : status(std::move(status_)) {}
|
||||
std::tuple<float, float, bool> GetStatus() const override {
|
||||
return client->GetPadState(pad).touch_status;
|
||||
std::lock_guard guard(status->update_mutex);
|
||||
return status->touch_status;
|
||||
}
|
||||
|
||||
private:
|
||||
const std::string ip;
|
||||
const int port;
|
||||
const int pad;
|
||||
CemuhookUDP::Client* client;
|
||||
mutable std::mutex mutex;
|
||||
std::shared_ptr<DeviceStatus> status;
|
||||
};
|
||||
|
||||
/// A motion device factory that creates motion devices from JC Adapter
|
||||
UDPTouchFactory::UDPTouchFactory(std::shared_ptr<CemuhookUDP::Client> client_)
|
||||
: client(std::move(client_)) {}
|
||||
|
||||
/**
|
||||
* Creates motion device
|
||||
* @param params contains parameters for creating the device:
|
||||
* - "port": the nth jcpad on the adapter
|
||||
*/
|
||||
std::unique_ptr<Input::TouchDevice> UDPTouchFactory::Create(const Common::ParamPackage& params) {
|
||||
const std::string ip = params.Get("ip", "127.0.0.1");
|
||||
const int port = params.Get("port", 26760);
|
||||
const int pad = params.Get("pad_index", 0);
|
||||
|
||||
return std::make_unique<UDPTouch>(ip, port, pad, client.get());
|
||||
}
|
||||
|
||||
void UDPTouchFactory::BeginConfiguration() {
|
||||
polling = true;
|
||||
client->BeginConfiguration();
|
||||
}
|
||||
|
||||
void UDPTouchFactory::EndConfiguration() {
|
||||
polling = false;
|
||||
client->EndConfiguration();
|
||||
}
|
||||
|
||||
Common::ParamPackage UDPTouchFactory::GetNextInput() {
|
||||
Common::ParamPackage params;
|
||||
CemuhookUDP::UDPPadStatus pad;
|
||||
auto& queue = client->GetPadQueue();
|
||||
for (std::size_t pad_number = 0; pad_number < queue.size(); ++pad_number) {
|
||||
while (queue[pad_number].Pop(pad)) {
|
||||
if (pad.touch == CemuhookUDP::PadTouch::Undefined) {
|
||||
continue;
|
||||
}
|
||||
params.Set("engine", "cemuhookudp");
|
||||
params.Set("ip", "127.0.0.1");
|
||||
params.Set("port", 26760);
|
||||
params.Set("pad_index", static_cast<int>(pad_number));
|
||||
params.Set("touch", static_cast<u16>(pad.touch));
|
||||
return params;
|
||||
}
|
||||
class UDPMotionDevice final : public Input::MotionDevice {
|
||||
public:
|
||||
explicit UDPMotionDevice(std::shared_ptr<DeviceStatus> status_) : status(std::move(status_)) {}
|
||||
std::tuple<Common::Vec3<float>, Common::Vec3<float>> GetStatus() const override {
|
||||
std::lock_guard guard(status->update_mutex);
|
||||
return status->motion_status;
|
||||
}
|
||||
return params;
|
||||
|
||||
private:
|
||||
std::shared_ptr<DeviceStatus> status;
|
||||
};
|
||||
|
||||
class UDPTouchFactory final : public Input::Factory<Input::TouchDevice> {
|
||||
public:
|
||||
explicit UDPTouchFactory(std::shared_ptr<DeviceStatus> status_) : status(std::move(status_)) {}
|
||||
|
||||
std::unique_ptr<Input::TouchDevice> Create(const Common::ParamPackage& params) override {
|
||||
{
|
||||
std::lock_guard guard(status->update_mutex);
|
||||
status->touch_calibration = DeviceStatus::CalibrationData{};
|
||||
// These default values work well for DS4 but probably not other touch inputs
|
||||
status->touch_calibration->min_x = params.Get("min_x", 100);
|
||||
status->touch_calibration->min_y = params.Get("min_y", 50);
|
||||
status->touch_calibration->max_x = params.Get("max_x", 1800);
|
||||
status->touch_calibration->max_y = params.Get("max_y", 850);
|
||||
}
|
||||
return std::make_unique<UDPTouchDevice>(status);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<DeviceStatus> status;
|
||||
};
|
||||
|
||||
class UDPMotionFactory final : public Input::Factory<Input::MotionDevice> {
|
||||
public:
|
||||
explicit UDPMotionFactory(std::shared_ptr<DeviceStatus> status_) : status(std::move(status_)) {}
|
||||
|
||||
std::unique_ptr<Input::MotionDevice> Create(const Common::ParamPackage& params) override {
|
||||
return std::make_unique<UDPMotionDevice>(status);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<DeviceStatus> status;
|
||||
};
|
||||
|
||||
State::State() {
|
||||
auto status = std::make_shared<DeviceStatus>();
|
||||
client =
|
||||
std::make_unique<Client>(status, Settings::values.udp_input_address,
|
||||
Settings::values.udp_input_port, Settings::values.udp_pad_index);
|
||||
|
||||
motion_factory = std::make_shared<UDPMotionFactory>(status);
|
||||
touch_factory = std::make_shared<UDPTouchFactory>(status);
|
||||
|
||||
Input::RegisterFactory<Input::MotionDevice>("cemuhookudp", motion_factory);
|
||||
Input::RegisterFactory<Input::TouchDevice>("cemuhookudp", touch_factory);
|
||||
}
|
||||
|
||||
} // namespace InputCommon
|
||||
State::~State() {
|
||||
Input::UnregisterFactory<Input::TouchDevice>("cemuhookudp");
|
||||
Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp");
|
||||
}
|
||||
|
||||
std::vector<Common::ParamPackage> State::GetInputDevices() const {
|
||||
// TODO support binding udp devices
|
||||
return {};
|
||||
}
|
||||
|
||||
void State::ReloadUDPClient() {
|
||||
client->ReloadSocket(Settings::values.udp_input_address, Settings::values.udp_input_port,
|
||||
Settings::values.udp_pad_index);
|
||||
}
|
||||
|
||||
std::unique_ptr<State> Init() {
|
||||
return std::make_unique<State>();
|
||||
}
|
||||
} // namespace InputCommon::CemuhookUDP
|
||||
+18
-43
@@ -1,57 +1,32 @@
|
||||
// Copyright 2020 yuzu Emulator Project
|
||||
// Copyright 2018 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include "core/frontend/input.h"
|
||||
#include "input_common/udp/client.h"
|
||||
#include <vector>
|
||||
#include "common/param_package.h"
|
||||
|
||||
namespace InputCommon {
|
||||
namespace InputCommon::CemuhookUDP {
|
||||
|
||||
/// A motion device factory that creates motion devices from udp clients
|
||||
class UDPMotionFactory final : public Input::Factory<Input::MotionDevice> {
|
||||
class Client;
|
||||
class UDPMotionFactory;
|
||||
class UDPTouchFactory;
|
||||
|
||||
class State {
|
||||
public:
|
||||
explicit UDPMotionFactory(std::shared_ptr<CemuhookUDP::Client> client_);
|
||||
|
||||
std::unique_ptr<Input::MotionDevice> Create(const Common::ParamPackage& params) override;
|
||||
|
||||
Common::ParamPackage GetNextInput();
|
||||
|
||||
/// For device input configuration/polling
|
||||
void BeginConfiguration();
|
||||
void EndConfiguration();
|
||||
|
||||
bool IsPolling() const {
|
||||
return polling;
|
||||
}
|
||||
State();
|
||||
~State();
|
||||
void ReloadUDPClient();
|
||||
std::vector<Common::ParamPackage> GetInputDevices() const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<CemuhookUDP::Client> client;
|
||||
bool polling = false;
|
||||
std::unique_ptr<Client> client;
|
||||
std::shared_ptr<UDPMotionFactory> motion_factory;
|
||||
std::shared_ptr<UDPTouchFactory> touch_factory;
|
||||
};
|
||||
|
||||
/// A touch device factory that creates touch devices from udp clients
|
||||
class UDPTouchFactory final : public Input::Factory<Input::TouchDevice> {
|
||||
public:
|
||||
explicit UDPTouchFactory(std::shared_ptr<CemuhookUDP::Client> client_);
|
||||
std::unique_ptr<State> Init();
|
||||
|
||||
std::unique_ptr<Input::TouchDevice> Create(const Common::ParamPackage& params) override;
|
||||
|
||||
Common::ParamPackage GetNextInput();
|
||||
|
||||
/// For device input configuration/polling
|
||||
void BeginConfiguration();
|
||||
void EndConfiguration();
|
||||
|
||||
bool IsPolling() const {
|
||||
return polling;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<CemuhookUDP::Client> client;
|
||||
bool polling = false;
|
||||
};
|
||||
|
||||
} // namespace InputCommon
|
||||
} // namespace InputCommon::CemuhookUDP
|
||||
@@ -190,8 +190,6 @@ if (ENABLE_VULKAN)
|
||||
renderer_vulkan/vk_blit_screen.h
|
||||
renderer_vulkan/vk_buffer_cache.cpp
|
||||
renderer_vulkan/vk_buffer_cache.h
|
||||
renderer_vulkan/vk_command_pool.cpp
|
||||
renderer_vulkan/vk_command_pool.h
|
||||
renderer_vulkan/vk_compute_pass.cpp
|
||||
renderer_vulkan/vk_compute_pass.h
|
||||
renderer_vulkan/vk_compute_pipeline.cpp
|
||||
@@ -206,8 +204,6 @@ if (ENABLE_VULKAN)
|
||||
renderer_vulkan/vk_graphics_pipeline.h
|
||||
renderer_vulkan/vk_image.cpp
|
||||
renderer_vulkan/vk_image.h
|
||||
renderer_vulkan/vk_master_semaphore.cpp
|
||||
renderer_vulkan/vk_master_semaphore.h
|
||||
renderer_vulkan/vk_memory_manager.cpp
|
||||
renderer_vulkan/vk_memory_manager.h
|
||||
renderer_vulkan/vk_pipeline_cache.cpp
|
||||
@@ -218,8 +214,8 @@ if (ENABLE_VULKAN)
|
||||
renderer_vulkan/vk_rasterizer.h
|
||||
renderer_vulkan/vk_renderpass_cache.cpp
|
||||
renderer_vulkan/vk_renderpass_cache.h
|
||||
renderer_vulkan/vk_resource_pool.cpp
|
||||
renderer_vulkan/vk_resource_pool.h
|
||||
renderer_vulkan/vk_resource_manager.cpp
|
||||
renderer_vulkan/vk_resource_manager.h
|
||||
renderer_vulkan/vk_sampler_cache.cpp
|
||||
renderer_vulkan/vk_sampler_cache.h
|
||||
renderer_vulkan/vk_scheduler.cpp
|
||||
@@ -273,5 +269,5 @@ endif()
|
||||
if (MSVC)
|
||||
target_compile_options(video_core PRIVATE /we4267)
|
||||
else()
|
||||
target_compile_options(video_core PRIVATE -Werror=conversion -Wno-error=sign-conversion -Werror=switch)
|
||||
target_compile_options(video_core PRIVATE -Werror=conversion -Wno-error=sign-conversion)
|
||||
endif()
|
||||
@@ -87,12 +87,12 @@ void Fermi2D::HandleSurfaceCopy() {
|
||||
const Common::Rectangle<u32> src_rect{src_blit_x1, src_blit_y1, src_blit_x2, src_blit_y2};
|
||||
const Common::Rectangle<u32> dst_rect{regs.blit_dst_x, regs.blit_dst_y, dst_blit_x2,
|
||||
dst_blit_y2};
|
||||
const Config copy_config{
|
||||
.operation = regs.operation,
|
||||
.filter = regs.blit_control.filter,
|
||||
.src_rect = src_rect,
|
||||
.dst_rect = dst_rect,
|
||||
};
|
||||
Config copy_config;
|
||||
copy_config.operation = regs.operation;
|
||||
copy_config.filter = regs.blit_control.filter;
|
||||
copy_config.src_rect = src_rect;
|
||||
copy_config.dst_rect = dst_rect;
|
||||
|
||||
if (!rasterizer->AccelerateSurfaceCopy(regs.src, regs.dst, copy_config)) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
Loaded 100 of 182 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user