Compare commits
23 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f9b64d280 | ||
|
|
c5b3c8d06b | ||
|
|
39c8d18feb | ||
|
|
d291fc1a51 | ||
|
|
4c348f4069 | ||
|
|
419a59a7b1 | ||
|
|
f250011ba0 | ||
|
|
e1600b0962 | ||
|
|
61b246a3a9 | ||
|
|
06e65de93c | ||
|
|
7a99226785 | ||
|
|
dffaffaac1 | ||
|
|
3446eb79b5 | ||
|
|
92adb69fa7 | ||
|
|
a54aee290f | ||
|
|
a220d8799e | ||
|
|
2a24b1c973 | ||
|
|
6380731486 | ||
|
|
2cbce77b92 | ||
|
|
9d665cb8db | ||
|
|
2978232390 | ||
|
|
03b574ae22 | ||
|
|
4d4bbe756f |
3
externals/CMakeLists.txt
vendored
3
externals/CMakeLists.txt
vendored
@@ -90,6 +90,9 @@ if (ENABLE_WEB_SERVICE)
|
||||
target_include_directories(httplib INTERFACE ./httplib)
|
||||
target_compile_definitions(httplib INTERFACE -DCPPHTTPLIB_OPENSSL_SUPPORT)
|
||||
target_link_libraries(httplib INTERFACE ${OPENSSL_LIBRARIES})
|
||||
if (WIN32)
|
||||
target_link_libraries(httplib INTERFACE crypt32 cryptui ws2_32)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Opus
|
||||
|
||||
4489
externals/httplib/httplib.h
vendored
4489
externals/httplib/httplib.h
vendored
File diff suppressed because it is too large
Load Diff
@@ -46,10 +46,13 @@ create_target_directory_groups(audio_core)
|
||||
|
||||
if (NOT MSVC)
|
||||
target_compile_options(audio_core PRIVATE
|
||||
-Werror=conversion
|
||||
-Werror=ignored-qualifiers
|
||||
-Werror=implicit-fallthrough
|
||||
-Werror=reorder
|
||||
-Werror=sign-compare
|
||||
-Werror=unused-but-set-parameter
|
||||
-Werror=unused-but-set-variable
|
||||
-Werror=unused-variable
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -55,7 +55,8 @@ void Filter::Process(std::vector<s16>& signal) {
|
||||
/// @param total_count The total number of biquads to be cascaded.
|
||||
/// @param index 0-index of the biquad to calculate the Q value for.
|
||||
static double CascadingBiquadQ(std::size_t total_count, std::size_t index) {
|
||||
const double pole = M_PI * (2 * index + 1) / (4.0 * total_count);
|
||||
const auto pole =
|
||||
M_PI * static_cast<double>(2 * index + 1) / (4.0 * static_cast<double>(total_count));
|
||||
return 1.0 / (2.0 * std::cos(pole));
|
||||
}
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ std::vector<s16> Interpolate(InterpolationState& state, std::vector<s16> input,
|
||||
return {};
|
||||
|
||||
if (ratio <= 0) {
|
||||
LOG_CRITICAL(Audio, "Nonsensical interpolation ratio {}", ratio);
|
||||
LOG_ERROR(Audio, "Nonsensical interpolation ratio {}", ratio);
|
||||
return input;
|
||||
}
|
||||
|
||||
@@ -164,7 +164,8 @@ std::vector<s16> Interpolate(InterpolationState& state, std::vector<s16> input,
|
||||
const std::size_t num_frames{input.size() / 2};
|
||||
|
||||
std::vector<s16> output;
|
||||
output.reserve(static_cast<std::size_t>(input.size() / ratio + InterpolationState::taps));
|
||||
output.reserve(static_cast<std::size_t>(static_cast<double>(input.size()) / ratio +
|
||||
InterpolationState::taps));
|
||||
|
||||
for (std::size_t frame{}; frame < num_frames; ++frame) {
|
||||
const std::size_t lut_index{(state.fraction >> 8) * InterpolationState::taps};
|
||||
|
||||
@@ -793,7 +793,6 @@ s32 CommandGenerator::DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_s
|
||||
// Decode entire frame
|
||||
if (remaining_samples >= static_cast<int>(SAMPLES_PER_FRAME)) {
|
||||
for (std::size_t i = 0; i < SAMPLES_PER_FRAME / 2; i++) {
|
||||
|
||||
// Sample 1
|
||||
const s32 s0 = SIGNED_NIBBLES[buffer[buffer_offset] >> 4];
|
||||
const s32 s1 = SIGNED_NIBBLES[buffer[buffer_offset++] & 0xf];
|
||||
@@ -802,7 +801,7 @@ s32 CommandGenerator::DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_s
|
||||
sample_buffer[cur_mix_offset++] = sample_1;
|
||||
sample_buffer[cur_mix_offset++] = sample_2;
|
||||
}
|
||||
remaining_samples -= SAMPLES_PER_FRAME;
|
||||
remaining_samples -= static_cast<int>(SAMPLES_PER_FRAME);
|
||||
position_in_frame += SAMPLES_PER_FRAME;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -93,8 +93,10 @@ public:
|
||||
constexpr s32 clev{707}; // center mixing level coefficient
|
||||
constexpr s32 slev{707}; // surround mixing level coefficient
|
||||
|
||||
buf.push_back(left + (clev * center / 1000) + (slev * surround_left / 1000));
|
||||
buf.push_back(right + (clev * center / 1000) + (slev * surround_right / 1000));
|
||||
buf.push_back(static_cast<s16>(left + (clev * center / 1000) +
|
||||
(slev * surround_left / 1000)));
|
||||
buf.push_back(static_cast<s16>(right + (clev * center / 1000) +
|
||||
(slev * surround_right / 1000)));
|
||||
}
|
||||
queue.Push(buf);
|
||||
return;
|
||||
|
||||
@@ -128,7 +128,10 @@ void ServerVoiceInfo::UpdateParameters(const VoiceInfo::InParams& voice_in,
|
||||
in_params.wave_buffer_count = voice_in.wave_buffer_count;
|
||||
in_params.wave_bufffer_head = voice_in.wave_buffer_head;
|
||||
if (behavior_info.IsFlushVoiceWaveBuffersSupported()) {
|
||||
in_params.wave_buffer_flush_request_count += voice_in.wave_buffer_flush_request_count;
|
||||
const auto in_request_count = in_params.wave_buffer_flush_request_count;
|
||||
const auto voice_request_count = voice_in.wave_buffer_flush_request_count;
|
||||
in_params.wave_buffer_flush_request_count =
|
||||
static_cast<u8>(in_request_count + voice_request_count);
|
||||
}
|
||||
in_params.mix_id = voice_in.mix_id;
|
||||
if (behavior_info.IsSplitterSupported()) {
|
||||
|
||||
@@ -192,4 +192,9 @@ create_target_directory_groups(common)
|
||||
find_package(Boost 1.71 COMPONENTS context headers REQUIRED)
|
||||
|
||||
target_link_libraries(common PUBLIC ${Boost_LIBRARIES} fmt::fmt microprofile)
|
||||
target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd xbyak)
|
||||
target_link_libraries(common PRIVATE lz4::lz4 xbyak)
|
||||
if (MSVC)
|
||||
target_link_libraries(common PRIVATE zstd::zstd)
|
||||
else()
|
||||
target_link_libraries(common PRIVATE zstd)
|
||||
endif()
|
||||
|
||||
@@ -16,14 +16,14 @@ namespace Common {
|
||||
|
||||
[[nodiscard]] constexpr u8 ToHexNibble(char c) {
|
||||
if (c >= 65 && c <= 70) {
|
||||
return c - 55;
|
||||
return static_cast<u8>(c - 55);
|
||||
}
|
||||
|
||||
if (c >= 97 && c <= 102) {
|
||||
return c - 87;
|
||||
return static_cast<u8>(c - 87);
|
||||
}
|
||||
|
||||
return c - 48;
|
||||
return static_cast<u8>(c - 48);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::vector<u8> HexStringToVector(std::string_view str, bool little_endian);
|
||||
@@ -33,11 +33,11 @@ template <std::size_t Size, bool le = false>
|
||||
std::array<u8, Size> out{};
|
||||
if constexpr (le) {
|
||||
for (std::size_t i = 2 * Size - 2; i <= 2 * Size; i -= 2) {
|
||||
out[i / 2] = (ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]);
|
||||
out[i / 2] = static_cast<u8>((ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]));
|
||||
}
|
||||
} else {
|
||||
for (std::size_t i = 0; i < 2 * Size; i += 2) {
|
||||
out[i / 2] = (ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]);
|
||||
out[i / 2] = static_cast<u8>((ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]));
|
||||
}
|
||||
}
|
||||
return out;
|
||||
|
||||
@@ -623,6 +623,17 @@ if (MSVC)
|
||||
# 'context' : truncation from 'type1' to 'type2'
|
||||
/we4305
|
||||
)
|
||||
else()
|
||||
target_compile_options(core PRIVATE
|
||||
-Werror=conversion
|
||||
-Werror=ignored-qualifiers
|
||||
-Werror=implicit-fallthrough
|
||||
-Werror=reorder
|
||||
-Werror=sign-compare
|
||||
-Werror=unused-but-set-parameter
|
||||
-Werror=unused-but-set-variable
|
||||
-Werror=unused-variable
|
||||
)
|
||||
endif()
|
||||
|
||||
create_target_directory_groups(core)
|
||||
|
||||
@@ -411,7 +411,7 @@ Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& ke
|
||||
// Combine sources and seed
|
||||
for (auto& source : sd_key_sources) {
|
||||
for (std::size_t i = 0; i < source.size(); ++i) {
|
||||
source[i] ^= sd_seed[i & 0xF];
|
||||
source[i] = static_cast<u8>(source[i] ^ sd_seed[i & 0xF]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -266,8 +266,9 @@ std::multimap<u64, VirtualFile> RomFSBuildContext::Build() {
|
||||
cur_file->offset = file_partition_size;
|
||||
file_partition_size += cur_file->size;
|
||||
cur_file->entry_offset = entry_offset;
|
||||
entry_offset += sizeof(RomFSFileEntry) +
|
||||
Common::AlignUp(cur_file->path_len - cur_file->cur_path_ofs, 4);
|
||||
entry_offset +=
|
||||
static_cast<u32>(sizeof(RomFSFileEntry) +
|
||||
Common::AlignUp(cur_file->path_len - cur_file->cur_path_ofs, 4));
|
||||
prev_file = cur_file;
|
||||
}
|
||||
// Assign deferred parent/sibling ownership.
|
||||
@@ -284,8 +285,9 @@ std::multimap<u64, VirtualFile> RomFSBuildContext::Build() {
|
||||
for (const auto& it : directories) {
|
||||
cur_dir = it.second;
|
||||
cur_dir->entry_offset = entry_offset;
|
||||
entry_offset += sizeof(RomFSDirectoryEntry) +
|
||||
Common::AlignUp(cur_dir->path_len - cur_dir->cur_path_ofs, 4);
|
||||
entry_offset +=
|
||||
static_cast<u32>(sizeof(RomFSDirectoryEntry) +
|
||||
Common::AlignUp(cur_dir->path_len - cur_dir->cur_path_ofs, 4));
|
||||
}
|
||||
// Assign deferred parent/sibling ownership.
|
||||
for (auto it = directories.rbegin(); it->second != root; ++it) {
|
||||
|
||||
@@ -299,7 +299,7 @@ void IPSwitchCompiler::Parse() {
|
||||
patch_text->GetName(), offset, Common::HexToString(replace));
|
||||
}
|
||||
|
||||
patch.records.insert_or_assign(offset, std::move(replace));
|
||||
patch.records.insert_or_assign(static_cast<u32>(offset), std::move(replace));
|
||||
}
|
||||
|
||||
patches.push_back(std::move(patch));
|
||||
|
||||
@@ -108,7 +108,7 @@ std::vector<u8> CNMT::Serialize() const {
|
||||
memcpy(out.data() + sizeof(CNMTHeader), &opt_header, sizeof(OptionalHeader));
|
||||
}
|
||||
|
||||
auto offset = header.table_offset;
|
||||
u64_le offset = header.table_offset;
|
||||
|
||||
for (const auto& rec : content_records) {
|
||||
memcpy(out.data() + offset + sizeof(CNMTHeader), &rec, sizeof(ContentRecord));
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
namespace FileSys {
|
||||
namespace {
|
||||
|
||||
constexpr u64 SINGLE_BYTE_MODULUS = 0x100;
|
||||
constexpr u32 SINGLE_BYTE_MODULUS = 0x100;
|
||||
constexpr u64 DLC_BASE_TITLE_ID_MASK = 0xFFFFFFFFFFFFE000;
|
||||
|
||||
constexpr std::array<const char*, 14> EXEFS_FILE_NAMES{
|
||||
|
||||
@@ -19,38 +19,6 @@
|
||||
#include "core/loader/loader.h"
|
||||
|
||||
namespace FileSys {
|
||||
namespace {
|
||||
void SetTicketKeys(const std::vector<VirtualFile>& files) {
|
||||
auto& keys = Core::Crypto::KeyManager::Instance();
|
||||
|
||||
for (const auto& ticket_file : files) {
|
||||
if (ticket_file == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ticket_file->GetExtension() != "tik") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ticket_file->GetSize() <
|
||||
Core::Crypto::TICKET_FILE_TITLEKEY_OFFSET + sizeof(Core::Crypto::Key128)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Core::Crypto::Key128 key{};
|
||||
ticket_file->Read(key.data(), key.size(), Core::Crypto::TICKET_FILE_TITLEKEY_OFFSET);
|
||||
|
||||
// We get the name without the extension in order to create the rights ID.
|
||||
std::string name_only(ticket_file->GetName());
|
||||
name_only.erase(name_only.size() - 4);
|
||||
|
||||
const auto rights_id_raw = Common::HexStringToArray<16>(name_only);
|
||||
u128 rights_id;
|
||||
std::memcpy(rights_id.data(), rights_id_raw.data(), sizeof(u128));
|
||||
keys.SetKey(Core::Crypto::S128KeyType::Titlekey, key, rights_id[1], rights_id[0]);
|
||||
}
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
NSP::NSP(VirtualFile file_)
|
||||
: file(std::move(file_)), status{Loader::ResultStatus::Success},
|
||||
@@ -232,6 +200,35 @@ VirtualDir NSP::GetParentDirectory() const {
|
||||
return file->GetContainingDirectory();
|
||||
}
|
||||
|
||||
void NSP::SetTicketKeys(const std::vector<VirtualFile>& files) {
|
||||
for (const auto& ticket_file : files) {
|
||||
if (ticket_file == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ticket_file->GetExtension() != "tik") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ticket_file->GetSize() <
|
||||
Core::Crypto::TICKET_FILE_TITLEKEY_OFFSET + sizeof(Core::Crypto::Key128)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Core::Crypto::Key128 key{};
|
||||
ticket_file->Read(key.data(), key.size(), Core::Crypto::TICKET_FILE_TITLEKEY_OFFSET);
|
||||
|
||||
// We get the name without the extension in order to create the rights ID.
|
||||
std::string name_only(ticket_file->GetName());
|
||||
name_only.erase(name_only.size() - 4);
|
||||
|
||||
const auto rights_id_raw = Common::HexStringToArray<16>(name_only);
|
||||
u128 rights_id;
|
||||
std::memcpy(rights_id.data(), rights_id_raw.data(), sizeof(u128));
|
||||
keys.SetKey(Core::Crypto::S128KeyType::Titlekey, key, rights_id[1], rights_id[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void NSP::InitializeExeFSAndRomFS(const std::vector<VirtualFile>& files) {
|
||||
exefs = pfs;
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ public:
|
||||
VirtualDir GetParentDirectory() const override;
|
||||
|
||||
private:
|
||||
void SetTicketKeys(const std::vector<VirtualFile>& files);
|
||||
void InitializeExeFSAndRomFS(const std::vector<VirtualFile>& files);
|
||||
void ReadNCAs(const std::vector<VirtualFile>& files);
|
||||
|
||||
|
||||
@@ -84,10 +84,12 @@ void EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) {
|
||||
return;
|
||||
|
||||
std::lock_guard guard{touch_state->mutex};
|
||||
touch_state->touch_x = static_cast<float>(framebuffer_x - framebuffer_layout.screen.left) /
|
||||
(framebuffer_layout.screen.right - framebuffer_layout.screen.left);
|
||||
touch_state->touch_y = static_cast<float>(framebuffer_y - framebuffer_layout.screen.top) /
|
||||
(framebuffer_layout.screen.bottom - framebuffer_layout.screen.top);
|
||||
touch_state->touch_x =
|
||||
static_cast<float>(framebuffer_x - framebuffer_layout.screen.left) /
|
||||
static_cast<float>(framebuffer_layout.screen.right - framebuffer_layout.screen.left);
|
||||
touch_state->touch_y =
|
||||
static_cast<float>(framebuffer_y - framebuffer_layout.screen.top) /
|
||||
static_cast<float>(framebuffer_layout.screen.bottom - framebuffer_layout.screen.top);
|
||||
|
||||
touch_state->touch_pressed = true;
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@ namespace Layout {
|
||||
template <class T>
|
||||
static Common::Rectangle<T> MaxRectangle(Common::Rectangle<T> window_area,
|
||||
float screen_aspect_ratio) {
|
||||
float scale = std::min(static_cast<float>(window_area.GetWidth()),
|
||||
window_area.GetHeight() / screen_aspect_ratio);
|
||||
const float scale = std::min(static_cast<float>(window_area.GetWidth()),
|
||||
static_cast<float>(window_area.GetHeight()) / screen_aspect_ratio);
|
||||
return Common::Rectangle<T>{0, 0, static_cast<T>(std::round(scale)),
|
||||
static_cast<T>(std::round(scale * screen_aspect_ratio))};
|
||||
}
|
||||
@@ -27,7 +27,7 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height) {
|
||||
// so just calculate them both even if the other isn't showing.
|
||||
FramebufferLayout res{width, height, false, {}};
|
||||
|
||||
const float window_aspect_ratio = static_cast<float>(height) / width;
|
||||
const float window_aspect_ratio = static_cast<float>(height) / static_cast<float>(width);
|
||||
const float emulation_aspect_ratio = EmulationAspectRatio(
|
||||
static_cast<AspectRatio>(Settings::values.aspect_ratio.GetValue()), window_aspect_ratio);
|
||||
|
||||
|
||||
@@ -291,11 +291,11 @@ static void FpuWrite(std::size_t id, u128 val, Kernel::Thread* thread = nullptr)
|
||||
*/
|
||||
static u8 HexCharToValue(u8 hex) {
|
||||
if (hex >= '0' && hex <= '9') {
|
||||
return hex - '0';
|
||||
return static_cast<u8>(hex - '0');
|
||||
} else if (hex >= 'a' && hex <= 'f') {
|
||||
return hex - 'a' + 0xA;
|
||||
return static_cast<u8>(hex - 'a' + 0xA);
|
||||
} else if (hex >= 'A' && hex <= 'F') {
|
||||
return hex - 'A' + 0xA;
|
||||
return static_cast<u8>(hex - 'A' + 0xA);
|
||||
}
|
||||
|
||||
LOG_ERROR(Debug_GDBStub, "Invalid nibble: {} ({:02X})", hex, hex);
|
||||
@@ -310,9 +310,9 @@ static u8 HexCharToValue(u8 hex) {
|
||||
static u8 NibbleToHex(u8 n) {
|
||||
n &= 0xF;
|
||||
if (n < 0xA) {
|
||||
return '0' + n;
|
||||
return static_cast<u8>('0' + n);
|
||||
} else {
|
||||
return 'a' + n - 0xA;
|
||||
return static_cast<u8>('a' + n - 0xA);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,8 +355,8 @@ static u64 HexToLong(const u8* src, std::size_t len) {
|
||||
*/
|
||||
static void MemToGdbHex(u8* dest, const u8* src, std::size_t len) {
|
||||
while (len-- > 0) {
|
||||
u8 tmp = *src++;
|
||||
*dest++ = NibbleToHex(tmp >> 4);
|
||||
const u8 tmp = *src++;
|
||||
*dest++ = NibbleToHex(static_cast<u8>(tmp >> 4));
|
||||
*dest++ = NibbleToHex(tmp);
|
||||
}
|
||||
}
|
||||
@@ -370,7 +370,7 @@ static void MemToGdbHex(u8* dest, const u8* src, std::size_t len) {
|
||||
*/
|
||||
static void GdbHexToMem(u8* dest, const u8* src, std::size_t len) {
|
||||
while (len-- > 0) {
|
||||
*dest++ = (HexCharToValue(src[0]) << 4) | HexCharToValue(src[1]);
|
||||
*dest++ = static_cast<u8>((HexCharToValue(src[0]) << 4) | HexCharToValue(src[1]));
|
||||
src += 2;
|
||||
}
|
||||
}
|
||||
@@ -602,22 +602,22 @@ static void SendReply(const char* reply) {
|
||||
|
||||
memcpy(command_buffer + 1, reply, command_length);
|
||||
|
||||
u8 checksum = CalculateChecksum(command_buffer, command_length + 1);
|
||||
const u8 checksum = CalculateChecksum(command_buffer, command_length + 1);
|
||||
command_buffer[0] = GDB_STUB_START;
|
||||
command_buffer[command_length + 1] = GDB_STUB_END;
|
||||
command_buffer[command_length + 2] = NibbleToHex(checksum >> 4);
|
||||
command_buffer[command_length + 2] = NibbleToHex(static_cast<u8>(checksum >> 4));
|
||||
command_buffer[command_length + 3] = NibbleToHex(checksum);
|
||||
|
||||
u8* ptr = command_buffer;
|
||||
u32 left = command_length + 4;
|
||||
while (left > 0) {
|
||||
int sent_size = send(gdbserver_socket, reinterpret_cast<char*>(ptr), left, 0);
|
||||
const auto sent_size = send(gdbserver_socket, reinterpret_cast<char*>(ptr), left, 0);
|
||||
if (sent_size < 0) {
|
||||
LOG_ERROR(Debug_GDBStub, "gdb: send failed");
|
||||
return Shutdown();
|
||||
}
|
||||
|
||||
left -= sent_size;
|
||||
left -= static_cast<u32>(sent_size);
|
||||
ptr += sent_size;
|
||||
}
|
||||
}
|
||||
@@ -777,10 +777,10 @@ static void ReadCommand() {
|
||||
command_buffer[command_length++] = c;
|
||||
}
|
||||
|
||||
u8 checksum_received = HexCharToValue(ReadByte()) << 4;
|
||||
checksum_received |= HexCharToValue(ReadByte());
|
||||
auto checksum_received = static_cast<u32>(HexCharToValue(ReadByte()) << 4);
|
||||
checksum_received |= static_cast<u32>(HexCharToValue(ReadByte()));
|
||||
|
||||
u8 checksum_calculated = CalculateChecksum(command_buffer, command_length);
|
||||
const u32 checksum_calculated = CalculateChecksum(command_buffer, command_length);
|
||||
|
||||
if (checksum_received != checksum_calculated) {
|
||||
LOG_ERROR(Debug_GDBStub,
|
||||
|
||||
@@ -38,10 +38,11 @@ public:
|
||||
explicit RequestHelperBase(Kernel::HLERequestContext& context)
|
||||
: context(&context), cmdbuf(context.CommandBuffer()) {}
|
||||
|
||||
void Skip(unsigned size_in_words, bool set_to_null) {
|
||||
if (set_to_null)
|
||||
void Skip(u32 size_in_words, bool set_to_null) {
|
||||
if (set_to_null) {
|
||||
memset(cmdbuf + index, 0, size_in_words * sizeof(u32));
|
||||
index += size_in_words;
|
||||
}
|
||||
index += static_cast<ptrdiff_t>(size_in_words);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,15 +50,15 @@ public:
|
||||
*/
|
||||
void AlignWithPadding() {
|
||||
if (index & 3) {
|
||||
Skip(4 - (index & 3), true);
|
||||
Skip(static_cast<u32>(4 - (index & 3)), true);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned GetCurrentOffset() const {
|
||||
return static_cast<unsigned>(index);
|
||||
u32 GetCurrentOffset() const {
|
||||
return static_cast<u32>(index);
|
||||
}
|
||||
|
||||
void SetCurrentOffset(unsigned offset) {
|
||||
void SetCurrentOffset(u32 offset) {
|
||||
index = static_cast<ptrdiff_t>(offset);
|
||||
}
|
||||
};
|
||||
@@ -89,7 +90,7 @@ public:
|
||||
|
||||
// The entire size of the raw data section in u32 units, including the 16 bytes of mandatory
|
||||
// padding.
|
||||
u32 raw_data_size = sizeof(IPC::DataPayloadHeader) / 4 + 4 + normal_params_size;
|
||||
u64 raw_data_size = sizeof(IPC::DataPayloadHeader) / 4 + 4 + normal_params_size;
|
||||
|
||||
u32 num_handles_to_move{};
|
||||
u32 num_domain_objects{};
|
||||
@@ -105,7 +106,7 @@ public:
|
||||
raw_data_size += sizeof(DomainMessageHeader) / 4 + num_domain_objects;
|
||||
}
|
||||
|
||||
header.data_size.Assign(raw_data_size);
|
||||
header.data_size.Assign(static_cast<u32>(raw_data_size));
|
||||
if (num_handles_to_copy || num_handles_to_move) {
|
||||
header.enable_handle_descriptor.Assign(1);
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ std::shared_ptr<Object> HandleTable::GetGeneric(Handle handle) const {
|
||||
|
||||
void HandleTable::Clear() {
|
||||
for (u16 i = 0; i < table_size; ++i) {
|
||||
generations[i] = i + 1;
|
||||
generations[i] = static_cast<u16>(i + 1);
|
||||
objects[i] = nullptr;
|
||||
}
|
||||
next_free_slot = 0;
|
||||
|
||||
@@ -72,7 +72,7 @@ u32 GlobalScheduler::SelectThreads() {
|
||||
if (top_thread != nullptr) {
|
||||
// TODO(Blinkhawk): Implement Thread Pinning
|
||||
} else {
|
||||
idle_cores |= (1ul << core);
|
||||
idle_cores |= (1U << core);
|
||||
}
|
||||
top_threads[core] = top_thread;
|
||||
}
|
||||
@@ -126,7 +126,7 @@ u32 GlobalScheduler::SelectThreads() {
|
||||
top_threads[core_id] = suggested;
|
||||
}
|
||||
|
||||
idle_cores &= ~(1ul << core_id);
|
||||
idle_cores &= ~(1U << core_id);
|
||||
}
|
||||
u32 cores_needing_context_switch{};
|
||||
for (u32 core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) {
|
||||
@@ -134,7 +134,7 @@ u32 GlobalScheduler::SelectThreads() {
|
||||
ASSERT(top_threads[core] == nullptr ||
|
||||
static_cast<u32>(top_threads[core]->GetProcessorID()) == core);
|
||||
if (update_thread(top_threads[core], sched)) {
|
||||
cores_needing_context_switch |= (1ul << core);
|
||||
cores_needing_context_switch |= (1U << core);
|
||||
}
|
||||
}
|
||||
return cores_needing_context_switch;
|
||||
@@ -364,7 +364,7 @@ void GlobalScheduler::EnableInterruptAndSchedule(u32 cores_pending_reschedule,
|
||||
} else {
|
||||
must_context_switch = true;
|
||||
}
|
||||
cores_pending_reschedule &= ~(1ul << core);
|
||||
cores_pending_reschedule &= ~(1U << core);
|
||||
}
|
||||
if (must_context_switch) {
|
||||
auto& core_scheduler = kernel.CurrentScheduler();
|
||||
@@ -767,7 +767,7 @@ void Scheduler::SwitchToCurrent() {
|
||||
current_thread->context_guard.unlock();
|
||||
break;
|
||||
}
|
||||
if (current_thread->GetProcessorID() != core_id) {
|
||||
if (static_cast<u32>(current_thread->GetProcessorID()) != core_id) {
|
||||
current_thread->context_guard.unlock();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -196,7 +196,9 @@ private:
|
||||
const std::string& content_type_name) {
|
||||
if (client == nullptr) {
|
||||
client = std::make_unique<httplib::SSLClient>(BOXCAT_HOSTNAME, PORT);
|
||||
client->set_timeout_sec(timeout_seconds);
|
||||
client->set_connection_timeout(timeout_seconds);
|
||||
client->set_read_timeout(timeout_seconds);
|
||||
client->set_write_timeout(timeout_seconds);
|
||||
}
|
||||
|
||||
httplib::Headers headers{
|
||||
@@ -255,7 +257,7 @@ private:
|
||||
return out;
|
||||
}
|
||||
|
||||
std::unique_ptr<httplib::Client> client;
|
||||
std::unique_ptr<httplib::SSLClient> client;
|
||||
std::string path;
|
||||
u64 title_id;
|
||||
u64 build_id;
|
||||
@@ -443,7 +445,9 @@ std::optional<std::vector<u8>> Boxcat::GetLaunchParameter(TitleIDVersion title)
|
||||
Boxcat::StatusResult Boxcat::GetStatus(std::optional<std::string>& global,
|
||||
std::map<std::string, EventStatus>& games) {
|
||||
httplib::SSLClient client{BOXCAT_HOSTNAME, static_cast<int>(PORT)};
|
||||
client.set_timeout_sec(static_cast<int>(TIMEOUT_SECONDS));
|
||||
client.set_connection_timeout(static_cast<int>(TIMEOUT_SECONDS));
|
||||
client.set_read_timeout(static_cast<int>(TIMEOUT_SECONDS));
|
||||
client.set_write_timeout(static_cast<int>(TIMEOUT_SECONDS));
|
||||
|
||||
httplib::Headers headers{
|
||||
{std::string("Game-Assets-API-Version"), std::string(BOXCAT_API_VERSION)},
|
||||
|
||||
@@ -42,8 +42,8 @@ void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing,
|
||||
cur_entry.modifier = 0;
|
||||
if (Settings::values.keyboard_enabled) {
|
||||
for (std::size_t i = 0; i < keyboard_keys.size(); ++i) {
|
||||
cur_entry.key[i / KEYS_PER_BYTE] |=
|
||||
(keyboard_keys[i]->GetStatus() << (i % KEYS_PER_BYTE));
|
||||
auto& entry = cur_entry.key[i / KEYS_PER_BYTE];
|
||||
entry = static_cast<u8>(entry | (keyboard_keys[i]->GetStatus() << (i % KEYS_PER_BYTE)));
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < keyboard_mods.size(); ++i) {
|
||||
|
||||
@@ -269,7 +269,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] =
|
||||
@@ -391,18 +390,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:
|
||||
@@ -541,18 +528,6 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
|
||||
}
|
||||
}
|
||||
|
||||
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 =
|
||||
@@ -846,6 +821,15 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const {
|
||||
return unintended_home_button_input_protection[NPadIdToIndex(npad_id)];
|
||||
}
|
||||
|
||||
void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled,
|
||||
u32 npad_id) {
|
||||
unintended_home_button_input_protection[NPadIdToIndex(npad_id)] = is_protection_enabled;
|
||||
}
|
||||
|
||||
void Controller_NPad::SetVibrationEnabled(bool can_vibrate) {
|
||||
can_controllers_vibrate = can_vibrate;
|
||||
}
|
||||
|
||||
@@ -146,6 +146,8 @@ public:
|
||||
bool IsSixAxisSensorAtRest() const;
|
||||
void SetSixAxisEnabled(bool six_axis_status);
|
||||
LedPattern GetLedPattern(u32 npad_id);
|
||||
bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const;
|
||||
void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id);
|
||||
void SetVibrationEnabled(bool can_vibrate);
|
||||
bool IsVibrationEnabled() const;
|
||||
void ClearAllConnectedControllers();
|
||||
@@ -387,6 +389,7 @@ private:
|
||||
std::array<Kernel::EventPair, 10> styleset_changed_events;
|
||||
Vibration last_processed_vibration{};
|
||||
std::array<ControllerHolder, 10> connected_controllers{};
|
||||
std::array<bool, 10> unintended_home_button_input_protection{};
|
||||
GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard};
|
||||
bool can_controllers_vibrate{true};
|
||||
bool sixaxis_sensors_enabled{true};
|
||||
|
||||
@@ -224,8 +224,8 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) {
|
||||
{128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"},
|
||||
{129, &Hid::GetNpadHandheldActivationMode, "GetNpadHandheldActivationMode"},
|
||||
{130, &Hid::SwapNpadAssignment, "SwapNpadAssignment"},
|
||||
{131, nullptr, "IsUnintendedHomeButtonInputProtectionEnabled"},
|
||||
{132, nullptr, "EnableUnintendedHomeButtonInputProtection"},
|
||||
{131, &Hid::IsUnintendedHomeButtonInputProtectionEnabled, "IsUnintendedHomeButtonInputProtectionEnabled"},
|
||||
{132, &Hid::EnableUnintendedHomeButtonInputProtection, "EnableUnintendedHomeButtonInputProtection"},
|
||||
{133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"},
|
||||
{134, nullptr, "SetNpadAnalogStickUseCenterClamp"},
|
||||
{135, nullptr, "SetNpadCaptureButtonAssignment"},
|
||||
@@ -475,7 +475,7 @@ void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) {
|
||||
|
||||
void Hid::EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto enable{rp.Pop<bool>()};
|
||||
[[maybe_unused]] const auto enable{rp.Pop<bool>()};
|
||||
const auto handle{rp.Pop<u32>()};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
|
||||
@@ -809,6 +809,40 @@ void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto npad_id{rp.Pop<u32>()};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
|
||||
LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", npad_id,
|
||||
applet_resource_user_id);
|
||||
|
||||
auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<bool>(controller.IsUnintendedHomeButtonInputProtectionEnabled(npad_id));
|
||||
}
|
||||
|
||||
void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto unintended_home_button_input_protection{rp.Pop<bool>()};
|
||||
const auto npad_id{rp.Pop<u32>()};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
|
||||
LOG_WARNING(Service_HID,
|
||||
"(STUBBED) called, unintended_home_button_input_protection={}, npad_id={},"
|
||||
"applet_resource_user_id={}",
|
||||
npad_id, unintended_home_button_input_protection, applet_resource_user_id);
|
||||
|
||||
auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
|
||||
controller.SetUnintendedHomeButtonInputProtectionEnabled(
|
||||
unintended_home_button_input_protection, npad_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
|
||||
@@ -123,6 +123,8 @@ private:
|
||||
void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx);
|
||||
void GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx);
|
||||
void SwapNpadAssignment(Kernel::HLERequestContext& ctx);
|
||||
void IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx);
|
||||
void EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx);
|
||||
void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx);
|
||||
void EndPermitVibrationSession(Kernel::HLERequestContext& ctx);
|
||||
void SendVibrationValue(Kernel::HLERequestContext& ctx);
|
||||
|
||||
@@ -428,7 +428,7 @@ bool MiiManager::IsFullDatabase() const {
|
||||
}
|
||||
|
||||
u32 MiiManager::GetCount(SourceFlag source_flag) const {
|
||||
u32 count{};
|
||||
std::size_t count{};
|
||||
if ((source_flag & SourceFlag::Database) != SourceFlag::None) {
|
||||
// TODO(bunnei): We don't implement the Mii database, but when we do, update this
|
||||
count += 0;
|
||||
@@ -436,7 +436,7 @@ u32 MiiManager::GetCount(SourceFlag source_flag) const {
|
||||
if ((source_flag & SourceFlag::Default) != SourceFlag::None) {
|
||||
count += DefaultMiiCount;
|
||||
}
|
||||
return count;
|
||||
return static_cast<u32>(count);
|
||||
}
|
||||
|
||||
ResultVal<MiiInfo> MiiManager::UpdateLatest([[maybe_unused]] const MiiInfo& info,
|
||||
|
||||
@@ -89,9 +89,9 @@ Network::Protocol Translate(Type type, Protocol protocol) {
|
||||
}
|
||||
}
|
||||
|
||||
u16 TranslatePollEventsToHost(u16 flags) {
|
||||
u16 result = 0;
|
||||
const auto translate = [&result, &flags](u16 from, u16 to) {
|
||||
u16 TranslatePollEventsToHost(u32 flags) {
|
||||
u32 result = 0;
|
||||
const auto translate = [&result, &flags](u32 from, u32 to) {
|
||||
if ((flags & from) != 0) {
|
||||
flags &= ~from;
|
||||
result |= to;
|
||||
@@ -105,12 +105,12 @@ u16 TranslatePollEventsToHost(u16 flags) {
|
||||
translate(POLL_NVAL, Network::POLL_NVAL);
|
||||
|
||||
UNIMPLEMENTED_IF_MSG(flags != 0, "Unimplemented flags={}", flags);
|
||||
return result;
|
||||
return static_cast<u16>(result);
|
||||
}
|
||||
|
||||
u16 TranslatePollEventsToGuest(u16 flags) {
|
||||
u16 result = 0;
|
||||
const auto translate = [&result, &flags](u16 from, u16 to) {
|
||||
u16 TranslatePollEventsToGuest(u32 flags) {
|
||||
u32 result = 0;
|
||||
const auto translate = [&result, &flags](u32 from, u32 to) {
|
||||
if ((flags & from) != 0) {
|
||||
flags &= ~from;
|
||||
result |= to;
|
||||
@@ -125,7 +125,7 @@ u16 TranslatePollEventsToGuest(u16 flags) {
|
||||
translate(Network::POLL_NVAL, POLL_NVAL);
|
||||
|
||||
UNIMPLEMENTED_IF_MSG(flags != 0, "Unimplemented flags={}", flags);
|
||||
return result;
|
||||
return static_cast<u16>(result);
|
||||
}
|
||||
|
||||
Network::SockAddrIn Translate(SockAddrIn value) {
|
||||
|
||||
@@ -31,10 +31,10 @@ Network::Type Translate(Type type);
|
||||
Network::Protocol Translate(Type type, Protocol protocol);
|
||||
|
||||
/// Translate abstract poll event flags to guest poll event flags
|
||||
u16 TranslatePollEventsToHost(u16 flags);
|
||||
u16 TranslatePollEventsToHost(u32 flags);
|
||||
|
||||
/// Translate guest poll event flags to abstract poll event flags
|
||||
u16 TranslatePollEventsToGuest(u16 flags);
|
||||
u16 TranslatePollEventsToGuest(u32 flags);
|
||||
|
||||
/// Translate guest socket address structure to abstract socket address structure
|
||||
Network::SockAddrIn Translate(SockAddrIn value);
|
||||
|
||||
@@ -820,7 +820,10 @@ static ResultCode ToCalendarTimeImpl(const TimeZoneRule& rules, s64 time, Calend
|
||||
const ResultCode result{
|
||||
ToCalendarTimeInternal(rules, time, calendar_time, calendar.additiona_info)};
|
||||
calendar.time.year = static_cast<s16>(calendar_time.year);
|
||||
calendar.time.month = calendar_time.month + 1; // Internal impl. uses 0-indexed month
|
||||
|
||||
// Internal impl. uses 0-indexed month
|
||||
calendar.time.month = static_cast<s8>(calendar_time.month + 1);
|
||||
|
||||
calendar.time.day = calendar_time.day;
|
||||
calendar.time.hour = calendar_time.hour;
|
||||
calendar.time.minute = calendar_time.minute;
|
||||
@@ -872,13 +875,15 @@ ResultCode TimeZoneManager::ToPosixTime(const TimeZoneRule& rules,
|
||||
const CalendarTime& calendar_time, s64& posix_time) const {
|
||||
posix_time = 0;
|
||||
|
||||
CalendarTimeInternal internal_time{};
|
||||
internal_time.year = calendar_time.year;
|
||||
internal_time.month = calendar_time.month - 1; // Internal impl. uses 0-indexed month
|
||||
internal_time.day = calendar_time.day;
|
||||
internal_time.hour = calendar_time.hour;
|
||||
internal_time.minute = calendar_time.minute;
|
||||
internal_time.second = calendar_time.second;
|
||||
CalendarTimeInternal internal_time{
|
||||
.year = calendar_time.year,
|
||||
// Internal impl. uses 0-indexed month
|
||||
.month = static_cast<s8>(calendar_time.month - 1),
|
||||
.day = calendar_time.day,
|
||||
.hour = calendar_time.hour,
|
||||
.minute = calendar_time.minute,
|
||||
.second = calendar_time.second,
|
||||
};
|
||||
|
||||
s32 hour{internal_time.hour};
|
||||
s32 minute{internal_time.minute};
|
||||
|
||||
@@ -159,7 +159,7 @@ public:
|
||||
header.data_size = static_cast<u32_le>(write_index - sizeof(Header));
|
||||
header.data_offset = sizeof(Header);
|
||||
header.objects_size = 4;
|
||||
header.objects_offset = sizeof(Header) + header.data_size;
|
||||
header.objects_offset = static_cast<u32>(sizeof(Header) + header.data_size);
|
||||
std::memcpy(buffer.data(), &header, sizeof(Header));
|
||||
|
||||
return buffer;
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Loader {
|
||||
|
||||
namespace {
|
||||
constexpr u32 PageAlignSize(u32 size) {
|
||||
return (size + Core::Memory::PAGE_MASK) & ~Core::Memory::PAGE_MASK;
|
||||
return static_cast<u32>((size + Core::Memory::PAGE_MASK) & ~Core::Memory::PAGE_MASK);
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ FileType AppLoader_NRO::IdentifyType(const FileSys::VirtualFile& file) {
|
||||
}
|
||||
|
||||
static constexpr u32 PageAlignSize(u32 size) {
|
||||
return (size + Core::Memory::PAGE_MASK) & ~Core::Memory::PAGE_MASK;
|
||||
return static_cast<u32>((size + Core::Memory::PAGE_MASK) & ~Core::Memory::PAGE_MASK);
|
||||
}
|
||||
|
||||
static bool LoadNroImpl(Kernel::Process& process, const std::vector<u8>& data,
|
||||
|
||||
@@ -47,7 +47,7 @@ std::vector<u8> DecompressSegment(const std::vector<u8>& compressed_data,
|
||||
}
|
||||
|
||||
constexpr u32 PageAlignSize(u32 size) {
|
||||
return (size + Core::Memory::PAGE_MASK) & ~Core::Memory::PAGE_MASK;
|
||||
return static_cast<u32>((size + Core::Memory::PAGE_MASK) & ~Core::Memory::PAGE_MASK);
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ struct NSOHeader {
|
||||
static_assert(sizeof(NSOHeader) == 0x100, "NSOHeader has incorrect size.");
|
||||
static_assert(std::is_trivially_copyable_v<NSOHeader>, "NSOHeader must be trivially copyable.");
|
||||
|
||||
constexpr u64 NSO_ARGUMENT_DATA_ALLOCATION_SIZE = 0x9000;
|
||||
constexpr u32 NSO_ARGUMENT_DATA_ALLOCATION_SIZE = 0x9000;
|
||||
|
||||
struct NSOArgumentHeader {
|
||||
u32_le allocated_size;
|
||||
|
||||
@@ -120,9 +120,9 @@ struct Memory::Impl {
|
||||
if ((addr & 1) == 0) {
|
||||
return Read<u16_le>(addr);
|
||||
} else {
|
||||
const u8 a{Read<u8>(addr)};
|
||||
const u8 b{Read<u8>(addr + sizeof(u8))};
|
||||
return (static_cast<u16>(b) << 8) | a;
|
||||
const u32 a{Read<u8>(addr)};
|
||||
const u32 b{Read<u8>(addr + sizeof(u8))};
|
||||
return static_cast<u16>((b << 8) | a);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,9 +130,9 @@ struct Memory::Impl {
|
||||
if ((addr & 3) == 0) {
|
||||
return Read<u32_le>(addr);
|
||||
} else {
|
||||
const u16 a{Read16(addr)};
|
||||
const u16 b{Read16(addr + sizeof(u16))};
|
||||
return (static_cast<u32>(b) << 16) | a;
|
||||
const u32 a{Read16(addr)};
|
||||
const u32 b{Read16(addr + sizeof(u16))};
|
||||
return (b << 16) | a;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -153,8 +153,9 @@ std::vector<CheatEntry> TextCheatParser::Parse(std::string_view data) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto value = static_cast<u32>(std::stoul(hex, nullptr, 0x10));
|
||||
out[*current_entry].definition.opcodes[out[*current_entry].definition.num_opcodes++] =
|
||||
std::stoul(hex, nullptr, 0x10);
|
||||
value;
|
||||
|
||||
i += 8;
|
||||
} else {
|
||||
|
||||
@@ -238,14 +238,14 @@ SockAddrIn TranslateToSockAddrIn(sockaddr input_) {
|
||||
return result;
|
||||
}
|
||||
|
||||
u16 TranslatePollEvents(u16 events) {
|
||||
u16 result = 0;
|
||||
u16 TranslatePollEvents(u32 events) {
|
||||
u32 result = 0;
|
||||
|
||||
if (events & POLL_IN) {
|
||||
if ((events & POLL_IN) != 0) {
|
||||
events &= ~POLL_IN;
|
||||
result |= POLLIN;
|
||||
}
|
||||
if (events & POLL_PRI) {
|
||||
if ((events & POLL_PRI) != 0) {
|
||||
events &= ~POLL_PRI;
|
||||
#ifdef _WIN32
|
||||
LOG_WARNING(Service, "Winsock doesn't support POLLPRI");
|
||||
@@ -253,20 +253,20 @@ u16 TranslatePollEvents(u16 events) {
|
||||
result |= POLL_PRI;
|
||||
#endif
|
||||
}
|
||||
if (events & POLL_OUT) {
|
||||
if ((events & POLL_OUT) != 0) {
|
||||
events &= ~POLL_OUT;
|
||||
result |= POLLOUT;
|
||||
}
|
||||
|
||||
UNIMPLEMENTED_IF_MSG(events != 0, "Unhandled guest events=0x{:x}", events);
|
||||
|
||||
return result;
|
||||
return static_cast<u16>(result);
|
||||
}
|
||||
|
||||
u16 TranslatePollRevents(u16 revents) {
|
||||
u16 result = 0;
|
||||
const auto translate = [&result, &revents](int host, unsigned guest) {
|
||||
if (revents & host) {
|
||||
u16 TranslatePollRevents(u32 revents) {
|
||||
u32 result = 0;
|
||||
const auto translate = [&result, &revents](u32 host, u32 guest) {
|
||||
if ((revents & host) != 0) {
|
||||
revents &= ~host;
|
||||
result |= guest;
|
||||
}
|
||||
@@ -280,7 +280,7 @@ u16 TranslatePollRevents(u16 revents) {
|
||||
|
||||
UNIMPLEMENTED_IF_MSG(revents != 0, "Unhandled host revents=0x{:x}", revents);
|
||||
|
||||
return result;
|
||||
return static_cast<u16>(result);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -350,7 +350,7 @@ std::pair<s32, Errno> Poll(std::vector<PollFD>& pollfds, s32 timeout) {
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < num; ++i) {
|
||||
pollfds[i].revents = TranslatePollRevents(host_pollfds[i].revents);
|
||||
pollfds[i].revents = TranslatePollRevents(static_cast<u32>(host_pollfds[i].revents));
|
||||
}
|
||||
|
||||
if (result > 0) {
|
||||
@@ -408,7 +408,7 @@ std::pair<Socket::AcceptResult, Errno> Socket::Accept() {
|
||||
|
||||
Errno Socket::Connect(SockAddrIn addr_in) {
|
||||
const sockaddr host_addr_in = TranslateFromSockAddrIn(addr_in);
|
||||
if (connect(fd, &host_addr_in, sizeof(host_addr_in)) != INVALID_SOCKET) {
|
||||
if (connect(fd, &host_addr_in, sizeof(host_addr_in)) != SOCKET_ERROR) {
|
||||
return Errno::SUCCESS;
|
||||
}
|
||||
|
||||
@@ -503,10 +503,10 @@ std::pair<s32, Errno> Socket::Recv(int flags, std::vector<u8>& message) {
|
||||
ASSERT(flags == 0);
|
||||
ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max()));
|
||||
|
||||
const int result =
|
||||
const auto result =
|
||||
recv(fd, reinterpret_cast<char*>(message.data()), static_cast<int>(message.size()), 0);
|
||||
if (result != SOCKET_ERROR) {
|
||||
return {result, Errno::SUCCESS};
|
||||
return {static_cast<s32>(result), Errno::SUCCESS};
|
||||
}
|
||||
|
||||
switch (const int ec = LastError()) {
|
||||
@@ -531,14 +531,14 @@ std::pair<s32, Errno> Socket::RecvFrom(int flags, std::vector<u8>& message, Sock
|
||||
socklen_t* const p_addrlen = addr ? &addrlen : nullptr;
|
||||
sockaddr* const p_addr_in = addr ? &addr_in : nullptr;
|
||||
|
||||
const int result = recvfrom(fd, reinterpret_cast<char*>(message.data()),
|
||||
static_cast<int>(message.size()), 0, p_addr_in, p_addrlen);
|
||||
const auto result = recvfrom(fd, reinterpret_cast<char*>(message.data()),
|
||||
static_cast<int>(message.size()), 0, p_addr_in, p_addrlen);
|
||||
if (result != SOCKET_ERROR) {
|
||||
if (addr) {
|
||||
ASSERT(addrlen == sizeof(addr_in));
|
||||
*addr = TranslateToSockAddrIn(addr_in);
|
||||
}
|
||||
return {result, Errno::SUCCESS};
|
||||
return {static_cast<s32>(result), Errno::SUCCESS};
|
||||
}
|
||||
|
||||
switch (const int ec = LastError()) {
|
||||
@@ -558,10 +558,10 @@ std::pair<s32, Errno> Socket::Send(const std::vector<u8>& message, int flags) {
|
||||
ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max()));
|
||||
ASSERT(flags == 0);
|
||||
|
||||
const int result = send(fd, reinterpret_cast<const char*>(message.data()),
|
||||
static_cast<int>(message.size()), 0);
|
||||
const auto result = send(fd, reinterpret_cast<const char*>(message.data()),
|
||||
static_cast<int>(message.size()), 0);
|
||||
if (result != SOCKET_ERROR) {
|
||||
return {result, Errno::SUCCESS};
|
||||
return {static_cast<s32>(result), Errno::SUCCESS};
|
||||
}
|
||||
|
||||
const int ec = LastError();
|
||||
@@ -591,10 +591,10 @@ std::pair<s32, Errno> Socket::SendTo(u32 flags, const std::vector<u8>& message,
|
||||
to = &host_addr_in;
|
||||
}
|
||||
|
||||
const int result = sendto(fd, reinterpret_cast<const char*>(message.data()),
|
||||
static_cast<int>(message.size()), 0, to, tolen);
|
||||
const auto result = sendto(fd, reinterpret_cast<const char*>(message.data()),
|
||||
static_cast<int>(message.size()), 0, to, tolen);
|
||||
if (result != SOCKET_ERROR) {
|
||||
return {result, Errno::SUCCESS};
|
||||
return {static_cast<s32>(result), Errno::SUCCESS};
|
||||
}
|
||||
|
||||
const int ec = LastError();
|
||||
|
||||
@@ -7,6 +7,8 @@ add_library(input_common STATIC
|
||||
main.h
|
||||
motion_emu.cpp
|
||||
motion_emu.h
|
||||
motion_from_button.cpp
|
||||
motion_from_button.h
|
||||
motion_input.cpp
|
||||
motion_input.h
|
||||
settings.cpp
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "input_common/keyboard.h"
|
||||
#include "input_common/main.h"
|
||||
#include "input_common/motion_emu.h"
|
||||
#include "input_common/motion_from_button.h"
|
||||
#include "input_common/touch_from_button.h"
|
||||
#include "input_common/udp/client.h"
|
||||
#include "input_common/udp/udp.h"
|
||||
@@ -32,6 +33,8 @@ struct InputSubsystem::Impl {
|
||||
Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard);
|
||||
Input::RegisterFactory<Input::AnalogDevice>("analog_from_button",
|
||||
std::make_shared<AnalogFromButton>());
|
||||
Input::RegisterFactory<Input::MotionDevice>("keyboard",
|
||||
std::make_shared<MotionFromButton>());
|
||||
motion_emu = std::make_shared<MotionEmu>();
|
||||
Input::RegisterFactory<Input::MotionDevice>("motion_emu", motion_emu);
|
||||
Input::RegisterFactory<Input::TouchDevice>("touch_from_button",
|
||||
@@ -50,6 +53,7 @@ struct InputSubsystem::Impl {
|
||||
|
||||
void Shutdown() {
|
||||
Input::UnregisterFactory<Input::ButtonDevice>("keyboard");
|
||||
Input::UnregisterFactory<Input::MotionDevice>("keyboard");
|
||||
keyboard.reset();
|
||||
Input::UnregisterFactory<Input::AnalogDevice>("analog_from_button");
|
||||
Input::UnregisterFactory<Input::MotionDevice>("motion_emu");
|
||||
|
||||
34
src/input_common/motion_from_button.cpp
Normal file
34
src/input_common/motion_from_button.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright 2020 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "input_common/motion_from_button.h"
|
||||
#include "input_common/motion_input.h"
|
||||
|
||||
namespace InputCommon {
|
||||
|
||||
class MotionKey final : public Input::MotionDevice {
|
||||
public:
|
||||
using Button = std::unique_ptr<Input::ButtonDevice>;
|
||||
|
||||
MotionKey(Button key_) : key(std::move(key_)) {}
|
||||
|
||||
Input::MotionStatus GetStatus() const override {
|
||||
|
||||
if (key->GetStatus()) {
|
||||
return motion.GetRandomMotion(2, 6);
|
||||
}
|
||||
return motion.GetRandomMotion(0, 0);
|
||||
}
|
||||
|
||||
private:
|
||||
Button key;
|
||||
InputCommon::MotionInput motion{0.0f, 0.0f, 0.0f};
|
||||
};
|
||||
|
||||
std::unique_ptr<Input::MotionDevice> MotionFromButton::Create(const Common::ParamPackage& params) {
|
||||
auto key = Input::CreateDevice<Input::ButtonDevice>(params.Serialize());
|
||||
return std::make_unique<MotionKey>(std::move(key));
|
||||
}
|
||||
|
||||
} // namespace InputCommon
|
||||
25
src/input_common/motion_from_button.h
Normal file
25
src/input_common/motion_from_button.h
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright 2020 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/frontend/input.h"
|
||||
|
||||
namespace InputCommon {
|
||||
|
||||
/**
|
||||
* An motion device factory that takes a keyboard button and uses it as a random
|
||||
* motion device.
|
||||
*/
|
||||
class MotionFromButton final : public Input::Factory<Input::MotionDevice> {
|
||||
public:
|
||||
/**
|
||||
* Creates an motion device from button devices
|
||||
* @param params contains parameters for creating the device:
|
||||
* - "key": a serialized ParamPackage for creating a button device
|
||||
*/
|
||||
std::unique_ptr<Input::MotionDevice> Create(const Common::ParamPackage& params) override;
|
||||
};
|
||||
|
||||
} // namespace InputCommon
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included
|
||||
|
||||
#include <random>
|
||||
#include "common/math_util.h"
|
||||
#include "input_common/motion_input.h"
|
||||
|
||||
@@ -16,8 +17,16 @@ void MotionInput::SetAcceleration(const Common::Vec3f& acceleration) {
|
||||
|
||||
void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) {
|
||||
gyro = gyroscope - gyro_drift;
|
||||
|
||||
// Auto adjust drift to minimize drift
|
||||
if (!IsMoving(0.1f)) {
|
||||
gyro_drift = (gyro_drift * 0.9999f) + (gyroscope * 0.0001f);
|
||||
}
|
||||
|
||||
if (gyro.Length2() < gyro_threshold) {
|
||||
gyro = {};
|
||||
} else {
|
||||
only_accelerometer = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +77,7 @@ void MotionInput::UpdateOrientation(u64 elapsed_time) {
|
||||
f32 q4 = quat.xyz[2];
|
||||
const f32 sample_period = elapsed_time / 1000000.0f;
|
||||
|
||||
// ignore invalid elapsed time
|
||||
// Ignore invalid elapsed time
|
||||
if (sample_period > 0.1f) {
|
||||
return;
|
||||
}
|
||||
@@ -80,6 +89,13 @@ void MotionInput::UpdateOrientation(u64 elapsed_time) {
|
||||
rad_gyro.y = -swap;
|
||||
rad_gyro.z = -rad_gyro.z;
|
||||
|
||||
// Clear gyro values if there is no gyro present
|
||||
if (only_accelerometer) {
|
||||
rad_gyro.x = 0;
|
||||
rad_gyro.y = 0;
|
||||
rad_gyro.z = 0;
|
||||
}
|
||||
|
||||
// Ignore drift correction if acceleration is not reliable
|
||||
if (accel.Length() >= 0.75f && accel.Length() <= 1.25f) {
|
||||
const f32 ax = -normal_accel.x;
|
||||
@@ -92,8 +108,11 @@ void MotionInput::UpdateOrientation(u64 elapsed_time) {
|
||||
const f32 vz = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4;
|
||||
|
||||
// Error is cross product between estimated direction and measured direction of gravity
|
||||
const Common::Vec3f new_real_error = {az * vx - ax * vz, ay * vz - az * vy,
|
||||
ax * vy - ay * vx};
|
||||
const Common::Vec3f new_real_error = {
|
||||
az * vx - ax * vz,
|
||||
ay * vz - az * vy,
|
||||
ax * vy - ay * vx,
|
||||
};
|
||||
|
||||
derivative_error = new_real_error - real_error;
|
||||
real_error = new_real_error;
|
||||
@@ -106,9 +125,22 @@ void MotionInput::UpdateOrientation(u64 elapsed_time) {
|
||||
}
|
||||
|
||||
// Apply feedback terms
|
||||
rad_gyro += kp * real_error;
|
||||
rad_gyro += ki * integral_error;
|
||||
rad_gyro += kd * derivative_error;
|
||||
if (!only_accelerometer) {
|
||||
rad_gyro += kp * real_error;
|
||||
rad_gyro += ki * integral_error;
|
||||
rad_gyro += kd * derivative_error;
|
||||
} else {
|
||||
// Give more weight to acelerometer values to compensate for the lack of gyro
|
||||
rad_gyro += 35.0f * kp * real_error;
|
||||
rad_gyro += 10.0f * ki * integral_error;
|
||||
rad_gyro += 10.0f * kd * derivative_error;
|
||||
|
||||
// Emulate gyro values for games that need them
|
||||
gyro.x = -rad_gyro.y;
|
||||
gyro.y = rad_gyro.x;
|
||||
gyro.z = -rad_gyro.z;
|
||||
UpdateRotation(elapsed_time);
|
||||
}
|
||||
}
|
||||
|
||||
const f32 gx = rad_gyro.y;
|
||||
@@ -159,18 +191,49 @@ Common::Vec3f MotionInput::GetRotations() const {
|
||||
return rotations;
|
||||
}
|
||||
|
||||
Input::MotionStatus MotionInput::GetMotion() const {
|
||||
const Common::Vec3f gyroscope = GetGyroscope();
|
||||
const Common::Vec3f accelerometer = GetAcceleration();
|
||||
const Common::Vec3f rotation = GetRotations();
|
||||
const std::array<Common::Vec3f, 3> orientation = GetOrientation();
|
||||
return {accelerometer, gyroscope, rotation, orientation};
|
||||
}
|
||||
|
||||
Input::MotionStatus MotionInput::GetRandomMotion(int accel_magnitude, int gyro_magnitude) const {
|
||||
std::random_device device;
|
||||
std::mt19937 gen(device());
|
||||
std::uniform_int_distribution<s16> distribution(-1000, 1000);
|
||||
const Common::Vec3f gyroscope = {
|
||||
distribution(gen) * 0.001f,
|
||||
distribution(gen) * 0.001f,
|
||||
distribution(gen) * 0.001f,
|
||||
};
|
||||
const Common::Vec3f accelerometer = {
|
||||
distribution(gen) * 0.001f,
|
||||
distribution(gen) * 0.001f,
|
||||
distribution(gen) * 0.001f,
|
||||
};
|
||||
const Common::Vec3f rotation = {};
|
||||
const std::array<Common::Vec3f, 3> orientation = {
|
||||
Common::Vec3f{1.0f, 0, 0},
|
||||
Common::Vec3f{0, 1.0f, 0},
|
||||
Common::Vec3f{0, 0, 1.0f},
|
||||
};
|
||||
return {accelerometer * accel_magnitude, gyroscope * gyro_magnitude, rotation, orientation};
|
||||
}
|
||||
|
||||
void MotionInput::ResetOrientation() {
|
||||
if (!reset_enabled) {
|
||||
if (!reset_enabled || only_accelerometer) {
|
||||
return;
|
||||
}
|
||||
if (!IsMoving(0.5f) && accel.z <= -0.9f) {
|
||||
++reset_counter;
|
||||
if (reset_counter > 900) {
|
||||
// TODO: calculate quaternion from gravity vector
|
||||
quat.w = 0;
|
||||
quat.xyz[0] = 0;
|
||||
quat.xyz[1] = 0;
|
||||
quat.xyz[2] = -1;
|
||||
SetOrientationFromAccelerometer();
|
||||
integral_error = {};
|
||||
reset_counter = 0;
|
||||
}
|
||||
@@ -178,4 +241,65 @@ void MotionInput::ResetOrientation() {
|
||||
reset_counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MotionInput::SetOrientationFromAccelerometer() {
|
||||
int iterations = 0;
|
||||
const f32 sample_period = 0.015f;
|
||||
|
||||
const auto normal_accel = accel.Normalized();
|
||||
const f32 ax = -normal_accel.x;
|
||||
const f32 ay = normal_accel.y;
|
||||
const f32 az = -normal_accel.z;
|
||||
|
||||
while (!IsCalibrated(0.01f) && ++iterations < 100) {
|
||||
// Short name local variable for readability
|
||||
f32 q1 = quat.w;
|
||||
f32 q2 = quat.xyz[0];
|
||||
f32 q3 = quat.xyz[1];
|
||||
f32 q4 = quat.xyz[2];
|
||||
|
||||
Common::Vec3f rad_gyro = {};
|
||||
const f32 ax = -normal_accel.x;
|
||||
const f32 ay = normal_accel.y;
|
||||
const f32 az = -normal_accel.z;
|
||||
|
||||
// Estimated direction of gravity
|
||||
const f32 vx = 2.0f * (q2 * q4 - q1 * q3);
|
||||
const f32 vy = 2.0f * (q1 * q2 + q3 * q4);
|
||||
const f32 vz = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4;
|
||||
|
||||
// Error is cross product between estimated direction and measured direction of gravity
|
||||
const Common::Vec3f new_real_error = {
|
||||
az * vx - ax * vz,
|
||||
ay * vz - az * vy,
|
||||
ax * vy - ay * vx,
|
||||
};
|
||||
|
||||
derivative_error = new_real_error - real_error;
|
||||
real_error = new_real_error;
|
||||
|
||||
rad_gyro += 10.0f * kp * real_error;
|
||||
rad_gyro += 5.0f * ki * integral_error;
|
||||
rad_gyro += 10.0f * kd * derivative_error;
|
||||
|
||||
const f32 gx = rad_gyro.y;
|
||||
const f32 gy = rad_gyro.x;
|
||||
const f32 gz = rad_gyro.z;
|
||||
|
||||
// Integrate rate of change of quaternion
|
||||
const f32 pa = q2;
|
||||
const f32 pb = q3;
|
||||
const f32 pc = q4;
|
||||
q1 = q1 + (-q2 * gx - q3 * gy - q4 * gz) * (0.5f * sample_period);
|
||||
q2 = pa + (q1 * gx + pb * gz - pc * gy) * (0.5f * sample_period);
|
||||
q3 = pb + (q1 * gy - pa * gz + pc * gx) * (0.5f * sample_period);
|
||||
q4 = pc + (q1 * gz + pa * gy - pb * gx) * (0.5f * sample_period);
|
||||
|
||||
quat.w = q1;
|
||||
quat.xyz[0] = q2;
|
||||
quat.xyz[1] = q3;
|
||||
quat.xyz[2] = q4;
|
||||
quat = quat.Normalized();
|
||||
}
|
||||
}
|
||||
} // namespace InputCommon
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "common/common_types.h"
|
||||
#include "common/quaternion.h"
|
||||
#include "common/vector_math.h"
|
||||
#include "core/frontend/input.h"
|
||||
|
||||
namespace InputCommon {
|
||||
|
||||
@@ -37,12 +38,15 @@ public:
|
||||
Common::Vec3f GetGyroscope() const;
|
||||
Common::Vec3f GetRotations() const;
|
||||
Common::Quaternion<f32> GetQuaternion() const;
|
||||
Input::MotionStatus GetMotion() const;
|
||||
Input::MotionStatus GetRandomMotion(int accel_magnitude, int gyro_magnitude) const;
|
||||
|
||||
bool IsMoving(f32 sensitivity) const;
|
||||
bool IsCalibrated(f32 sensitivity) const;
|
||||
|
||||
private:
|
||||
void ResetOrientation();
|
||||
void SetOrientationFromAccelerometer();
|
||||
|
||||
// PID constants
|
||||
const f32 kp;
|
||||
@@ -63,6 +67,7 @@ private:
|
||||
f32 gyro_threshold = 0.0f;
|
||||
u32 reset_counter = 0;
|
||||
bool reset_enabled = true;
|
||||
bool only_accelerometer = true;
|
||||
};
|
||||
|
||||
} // namespace InputCommon
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "common/param_package.h"
|
||||
#include "common/threadsafe_queue.h"
|
||||
#include "core/frontend/input.h"
|
||||
#include "input_common/motion_input.h"
|
||||
#include "input_common/sdl/sdl_impl.h"
|
||||
#include "input_common/settings.h"
|
||||
|
||||
@@ -123,6 +124,10 @@ public:
|
||||
return std::make_tuple(x, y);
|
||||
}
|
||||
|
||||
const InputCommon::MotionInput& GetMotion() const {
|
||||
return motion;
|
||||
}
|
||||
|
||||
void SetHat(int hat, Uint8 direction) {
|
||||
std::lock_guard lock{mutex};
|
||||
state.hats.insert_or_assign(hat, direction);
|
||||
@@ -173,6 +178,9 @@ private:
|
||||
std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick;
|
||||
std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller;
|
||||
mutable std::mutex mutex;
|
||||
|
||||
// motion is initalized without PID values as motion input is not aviable for SDL2
|
||||
InputCommon::MotionInput motion{0.0f, 0.0f, 0.0f};
|
||||
};
|
||||
|
||||
std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& guid, int port) {
|
||||
@@ -423,6 +431,68 @@ private:
|
||||
const float range;
|
||||
};
|
||||
|
||||
class SDLDirectionMotion final : public Input::MotionDevice {
|
||||
public:
|
||||
explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_)
|
||||
: joystick(std::move(joystick_)), hat(hat_), direction(direction_) {}
|
||||
|
||||
Input::MotionStatus GetStatus() const override {
|
||||
if (joystick->GetHatDirection(hat, direction)) {
|
||||
return joystick->GetMotion().GetRandomMotion(2, 6);
|
||||
}
|
||||
return joystick->GetMotion().GetRandomMotion(0, 0);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<SDLJoystick> joystick;
|
||||
int hat;
|
||||
Uint8 direction;
|
||||
};
|
||||
|
||||
class SDLAxisMotion final : public Input::MotionDevice {
|
||||
public:
|
||||
explicit SDLAxisMotion(std::shared_ptr<SDLJoystick> joystick_, int axis_, float threshold_,
|
||||
bool trigger_if_greater_)
|
||||
: joystick(std::move(joystick_)), axis(axis_), threshold(threshold_),
|
||||
trigger_if_greater(trigger_if_greater_) {}
|
||||
|
||||
Input::MotionStatus GetStatus() const override {
|
||||
const float axis_value = joystick->GetAxis(axis, 1.0f);
|
||||
bool trigger = axis_value < threshold;
|
||||
if (trigger_if_greater) {
|
||||
trigger = axis_value > threshold;
|
||||
}
|
||||
|
||||
if (trigger) {
|
||||
return joystick->GetMotion().GetRandomMotion(2, 6);
|
||||
}
|
||||
return joystick->GetMotion().GetRandomMotion(0, 0);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<SDLJoystick> joystick;
|
||||
int axis;
|
||||
float threshold;
|
||||
bool trigger_if_greater;
|
||||
};
|
||||
|
||||
class SDLButtonMotion final : public Input::MotionDevice {
|
||||
public:
|
||||
explicit SDLButtonMotion(std::shared_ptr<SDLJoystick> joystick_, int button_)
|
||||
: joystick(std::move(joystick_)), button(button_) {}
|
||||
|
||||
Input::MotionStatus GetStatus() const override {
|
||||
if (joystick->GetButton(button)) {
|
||||
return joystick->GetMotion().GetRandomMotion(2, 6);
|
||||
}
|
||||
return joystick->GetMotion().GetRandomMotion(0, 0);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<SDLJoystick> joystick;
|
||||
int button;
|
||||
};
|
||||
|
||||
/// A button device factory that creates button devices from SDL joystick
|
||||
class SDLButtonFactory final : public Input::Factory<Input::ButtonDevice> {
|
||||
public:
|
||||
@@ -529,12 +599,78 @@ private:
|
||||
SDLState& state;
|
||||
};
|
||||
|
||||
/// A motion device factory that creates motion devices from SDL joystick
|
||||
class SDLMotionFactory final : public Input::Factory<Input::MotionDevice> {
|
||||
public:
|
||||
explicit SDLMotionFactory(SDLState& state_) : state(state_) {}
|
||||
/**
|
||||
* Creates motion device from joystick axes
|
||||
* @param params contains parameters for creating the device:
|
||||
* - "guid": the guid of the joystick to bind
|
||||
* - "port": the nth joystick of the same type
|
||||
*/
|
||||
std::unique_ptr<Input::MotionDevice> Create(const Common::ParamPackage& params) override {
|
||||
const std::string guid = params.Get("guid", "0");
|
||||
const int port = params.Get("port", 0);
|
||||
|
||||
auto joystick = state.GetSDLJoystickByGUID(guid, port);
|
||||
|
||||
if (params.Has("hat")) {
|
||||
const int hat = params.Get("hat", 0);
|
||||
const std::string direction_name = params.Get("direction", "");
|
||||
Uint8 direction;
|
||||
if (direction_name == "up") {
|
||||
direction = SDL_HAT_UP;
|
||||
} else if (direction_name == "down") {
|
||||
direction = SDL_HAT_DOWN;
|
||||
} else if (direction_name == "left") {
|
||||
direction = SDL_HAT_LEFT;
|
||||
} else if (direction_name == "right") {
|
||||
direction = SDL_HAT_RIGHT;
|
||||
} else {
|
||||
direction = 0;
|
||||
}
|
||||
// This is necessary so accessing GetHat with hat won't crash
|
||||
joystick->SetHat(hat, SDL_HAT_CENTERED);
|
||||
return std::make_unique<SDLDirectionMotion>(joystick, hat, direction);
|
||||
}
|
||||
|
||||
if (params.Has("axis")) {
|
||||
const int axis = params.Get("axis", 0);
|
||||
const float threshold = params.Get("threshold", 0.5f);
|
||||
const std::string direction_name = params.Get("direction", "");
|
||||
bool trigger_if_greater;
|
||||
if (direction_name == "+") {
|
||||
trigger_if_greater = true;
|
||||
} else if (direction_name == "-") {
|
||||
trigger_if_greater = false;
|
||||
} else {
|
||||
trigger_if_greater = true;
|
||||
LOG_ERROR(Input, "Unknown direction {}", direction_name);
|
||||
}
|
||||
// This is necessary so accessing GetAxis with axis won't crash
|
||||
joystick->SetAxis(axis, 0);
|
||||
return std::make_unique<SDLAxisMotion>(joystick, axis, threshold, trigger_if_greater);
|
||||
}
|
||||
|
||||
const int button = params.Get("button", 0);
|
||||
// This is necessary so accessing GetButton with button won't crash
|
||||
joystick->SetButton(button, false);
|
||||
return std::make_unique<SDLButtonMotion>(joystick, button);
|
||||
}
|
||||
|
||||
private:
|
||||
SDLState& state;
|
||||
};
|
||||
|
||||
SDLState::SDLState() {
|
||||
using namespace Input;
|
||||
analog_factory = std::make_shared<SDLAnalogFactory>(*this);
|
||||
button_factory = std::make_shared<SDLButtonFactory>(*this);
|
||||
motion_factory = std::make_shared<SDLMotionFactory>(*this);
|
||||
RegisterFactory<AnalogDevice>("sdl", analog_factory);
|
||||
RegisterFactory<ButtonDevice>("sdl", button_factory);
|
||||
RegisterFactory<MotionDevice>("sdl", motion_factory);
|
||||
|
||||
// If the frontend is going to manage the event loop, then we dont start one here
|
||||
start_thread = !SDL_WasInit(SDL_INIT_JOYSTICK);
|
||||
@@ -570,6 +706,7 @@ SDLState::~SDLState() {
|
||||
using namespace Input;
|
||||
UnregisterFactory<ButtonDevice>("sdl");
|
||||
UnregisterFactory<AnalogDevice>("sdl");
|
||||
UnregisterFactory<MotionDevice>("sdl");
|
||||
|
||||
CloseJoysticks();
|
||||
SDL_DelEventWatch(&SDLEventWatcher, this);
|
||||
@@ -681,6 +818,27 @@ Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Eve
|
||||
return {};
|
||||
}
|
||||
|
||||
Common::ParamPackage SDLEventToMotionParamPackage(SDLState& state, const SDL_Event& event) {
|
||||
switch (event.type) {
|
||||
case SDL_JOYAXISMOTION: {
|
||||
const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);
|
||||
return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
|
||||
event.jaxis.axis, event.jaxis.value);
|
||||
}
|
||||
case SDL_JOYBUTTONUP: {
|
||||
const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which);
|
||||
return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
|
||||
event.jbutton.button);
|
||||
}
|
||||
case SDL_JOYHATMOTION: {
|
||||
const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which);
|
||||
return BuildHatParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
|
||||
event.jhat.hat, event.jhat.value);
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
Common::ParamPackage BuildParamPackageForBinding(int port, const std::string& guid,
|
||||
const SDL_GameControllerButtonBind& binding) {
|
||||
switch (binding.bindType) {
|
||||
@@ -846,6 +1004,35 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class SDLMotionPoller final : public SDLPoller {
|
||||
public:
|
||||
explicit SDLMotionPoller(SDLState& state_) : SDLPoller(state_) {}
|
||||
|
||||
Common::ParamPackage GetNextInput() override {
|
||||
SDL_Event event;
|
||||
while (state.event_queue.Pop(event)) {
|
||||
const auto package = FromEvent(event);
|
||||
if (package) {
|
||||
return *package;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
[[nodiscard]] std::optional<Common::ParamPackage> FromEvent(const SDL_Event& event) const {
|
||||
switch (event.type) {
|
||||
case SDL_JOYAXISMOTION:
|
||||
if (std::abs(event.jaxis.value / 32767.0) < 0.5) {
|
||||
break;
|
||||
}
|
||||
[[fallthrough]];
|
||||
case SDL_JOYBUTTONUP:
|
||||
case SDL_JOYHATMOTION:
|
||||
return {SDLEventToMotionParamPackage(state, event)};
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Attempts to match the press to a controller joy axis (left/right stick) and if a match
|
||||
* isn't found, checks if the event matches anything from SDLButtonPoller and uses that
|
||||
@@ -937,6 +1124,9 @@ SDLState::Pollers SDLState::GetPollers(InputCommon::Polling::DeviceType type) {
|
||||
case InputCommon::Polling::DeviceType::Button:
|
||||
pollers.emplace_back(std::make_unique<Polling::SDLButtonPoller>(*this));
|
||||
break;
|
||||
case InputCommon::Polling::DeviceType::Motion:
|
||||
pollers.emplace_back(std::make_unique<Polling::SDLMotionPoller>(*this));
|
||||
break;
|
||||
}
|
||||
|
||||
return pollers;
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace InputCommon::SDL {
|
||||
|
||||
class SDLAnalogFactory;
|
||||
class SDLButtonFactory;
|
||||
class SDLMotionFactory;
|
||||
class SDLJoystick;
|
||||
|
||||
class SDLState : public State {
|
||||
@@ -71,6 +72,7 @@ private:
|
||||
|
||||
std::shared_ptr<SDLButtonFactory> button_factory;
|
||||
std::shared_ptr<SDLAnalogFactory> analog_factory;
|
||||
std::shared_ptr<SDLMotionFactory> motion_factory;
|
||||
|
||||
bool start_thread = false;
|
||||
std::atomic<bool> initialized = false;
|
||||
|
||||
@@ -219,14 +219,10 @@ void Client::OnPadData(Response::PadData data) {
|
||||
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();
|
||||
|
||||
{
|
||||
std::lock_guard guard(clients[client].status.update_mutex);
|
||||
clients[client].status.motion_status = {accelerometer, gyroscope, rotation, orientation};
|
||||
clients[client].status.motion_status = clients[client].motion.GetMotion();
|
||||
|
||||
// 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.
|
||||
@@ -250,6 +246,8 @@ void Client::OnPadData(Response::PadData data) {
|
||||
clients[client].status.touch_status = {x, y, is_active};
|
||||
|
||||
if (configuring) {
|
||||
const Common::Vec3f gyroscope = clients[client].motion.GetGyroscope();
|
||||
const Common::Vec3f accelerometer = clients[client].motion.GetAcceleration();
|
||||
UpdateYuzuSettings(client, accelerometer, gyroscope, is_active);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,5 +273,12 @@ 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
|
||||
-Werror=switch
|
||||
-Werror=unused-variable
|
||||
-Werror=unused-but-set-variable
|
||||
-Werror=class-memaccess
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -114,8 +114,6 @@ void MaxwellDMA::CopyBlockLinearToPitch() {
|
||||
const u32 block_depth = src_params.block_size.depth;
|
||||
const size_t src_size =
|
||||
CalculateSize(true, bytes_per_pixel, width, height, depth, block_height, block_depth);
|
||||
const size_t src_layer_size =
|
||||
CalculateSize(true, bytes_per_pixel, width, height, 1, block_height, block_depth);
|
||||
|
||||
if (read_buffer.size() < src_size) {
|
||||
read_buffer.resize(src_size);
|
||||
|
||||
@@ -41,30 +41,30 @@ struct Header {
|
||||
BitField<26, 1, u32> does_load_or_store;
|
||||
BitField<27, 1, u32> does_fp64;
|
||||
BitField<28, 4, u32> stream_out_mask;
|
||||
} common0{};
|
||||
} common0;
|
||||
|
||||
union {
|
||||
BitField<0, 24, u32> shader_local_memory_low_size;
|
||||
BitField<24, 8, u32> per_patch_attribute_count;
|
||||
} common1{};
|
||||
} common1;
|
||||
|
||||
union {
|
||||
BitField<0, 24, u32> shader_local_memory_high_size;
|
||||
BitField<24, 8, u32> threads_per_input_primitive;
|
||||
} common2{};
|
||||
} common2;
|
||||
|
||||
union {
|
||||
BitField<0, 24, u32> shader_local_memory_crs_size;
|
||||
BitField<24, 4, OutputTopology> output_topology;
|
||||
BitField<28, 4, u32> reserved;
|
||||
} common3{};
|
||||
} common3;
|
||||
|
||||
union {
|
||||
BitField<0, 12, u32> max_output_vertices;
|
||||
BitField<12, 8, u32> store_req_start; // NOTE: not used by geometry shaders.
|
||||
BitField<20, 4, u32> reserved;
|
||||
BitField<24, 8, u32> store_req_end; // NOTE: not used by geometry shaders.
|
||||
} common4{};
|
||||
} common4;
|
||||
|
||||
union {
|
||||
struct {
|
||||
@@ -145,7 +145,7 @@ struct Header {
|
||||
}
|
||||
} ps;
|
||||
|
||||
std::array<u32, 0xF> raw{};
|
||||
std::array<u32, 0xF> raw;
|
||||
};
|
||||
|
||||
u64 GetLocalMemorySize() const {
|
||||
@@ -153,7 +153,6 @@ struct Header {
|
||||
(common2.shader_local_memory_high_size << 24));
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(Header) == 0x50, "Incorrect structure size");
|
||||
|
||||
} // namespace Tegra::Shader
|
||||
|
||||
@@ -193,7 +193,6 @@ bool IsASTCSupported() {
|
||||
Device::Device()
|
||||
: max_uniform_buffers{BuildMaxUniformBuffers()}, base_bindings{BuildBaseBindings()} {
|
||||
const std::string_view vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
|
||||
const std::string_view renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
|
||||
const std::string_view version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
|
||||
const std::vector extensions = GetExtensions();
|
||||
|
||||
|
||||
@@ -292,33 +292,36 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
|
||||
break;
|
||||
}
|
||||
|
||||
const u64 base_index = is_array ? 1 : 0;
|
||||
const u64 num_components = [texture_type] {
|
||||
switch (texture_type) {
|
||||
case TextureType::Texture1D:
|
||||
return 1;
|
||||
case TextureType::Texture2D:
|
||||
return 2;
|
||||
case TextureType::TextureCube:
|
||||
return 3;
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Unhandled texture type {}", static_cast<int>(texture_type));
|
||||
return 2;
|
||||
}
|
||||
}();
|
||||
// TODO: What's the array component used for?
|
||||
|
||||
std::vector<Node> coords;
|
||||
|
||||
// TODO: Add coordinates for different samplers once other texture types are implemented.
|
||||
switch (texture_type) {
|
||||
case TextureType::Texture1D:
|
||||
coords.push_back(GetRegister(instr.gpr8));
|
||||
break;
|
||||
case TextureType::Texture2D:
|
||||
coords.push_back(GetRegister(instr.gpr8.Value() + 0));
|
||||
coords.push_back(GetRegister(instr.gpr8.Value() + 1));
|
||||
break;
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Unhandled texture type {}", static_cast<int>(texture_type));
|
||||
|
||||
// Fallback to interpreting as a 2D texture for now
|
||||
coords.push_back(GetRegister(instr.gpr8.Value() + 0));
|
||||
coords.push_back(GetRegister(instr.gpr8.Value() + 1));
|
||||
coords.reserve(num_components);
|
||||
for (u64 component = 0; component < num_components; ++component) {
|
||||
coords.push_back(GetRegister(instr.gpr8.Value() + base_index + component));
|
||||
}
|
||||
|
||||
u32 indexer = 0;
|
||||
for (u32 element = 0; element < 2; ++element) {
|
||||
if (!instr.tmml.IsComponentEnabled(element)) {
|
||||
continue;
|
||||
}
|
||||
auto params = coords;
|
||||
MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element, index_var};
|
||||
const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params));
|
||||
SetTemporary(bb, indexer++, value);
|
||||
Node value = Operation(OperationCode::TextureQueryLod, meta, coords);
|
||||
SetTemporary(bb, indexer++, std::move(value));
|
||||
}
|
||||
for (u32 i = 0; i < indexer; ++i) {
|
||||
SetRegister(bb, instr.gpr0.Value() + i, GetTemporary(i));
|
||||
|
||||
@@ -67,28 +67,25 @@ struct Client::Impl {
|
||||
const std::string& jwt = "", const std::string& username = "",
|
||||
const std::string& token = "") {
|
||||
if (cli == nullptr) {
|
||||
auto parsedUrl = LUrlParser::clParseURL::ParseURL(host);
|
||||
int port;
|
||||
const auto parsedUrl = LUrlParser::clParseURL::ParseURL(host);
|
||||
int port{};
|
||||
if (parsedUrl.m_Scheme == "http") {
|
||||
if (!parsedUrl.GetPort(&port)) {
|
||||
port = HTTP_PORT;
|
||||
}
|
||||
cli = std::make_unique<httplib::Client>(parsedUrl.m_Host.c_str(), port);
|
||||
} else if (parsedUrl.m_Scheme == "https") {
|
||||
if (!parsedUrl.GetPort(&port)) {
|
||||
port = HTTPS_PORT;
|
||||
}
|
||||
cli = std::make_unique<httplib::SSLClient>(parsedUrl.m_Host.c_str(), port);
|
||||
} else {
|
||||
LOG_ERROR(WebService, "Bad URL scheme {}", parsedUrl.m_Scheme);
|
||||
return WebResult{WebResult::Code::InvalidURL, "Bad URL scheme", ""};
|
||||
}
|
||||
cli = std::make_unique<httplib::Client>(parsedUrl.m_Host.c_str(), port);
|
||||
}
|
||||
if (cli == nullptr) {
|
||||
LOG_ERROR(WebService, "Invalid URL {}", host + path);
|
||||
return WebResult{WebResult::Code::InvalidURL, "Invalid URL", ""};
|
||||
}
|
||||
cli->set_timeout_sec(TIMEOUT_SECONDS);
|
||||
cli->set_connection_timeout(TIMEOUT_SECONDS);
|
||||
cli->set_read_timeout(TIMEOUT_SECONDS);
|
||||
cli->set_write_timeout(TIMEOUT_SECONDS);
|
||||
|
||||
httplib::Headers params;
|
||||
if (!jwt.empty()) {
|
||||
|
||||
Reference in New Issue
Block a user