Compare commits

..

3 Commits

Author SHA1 Message Date
lizzie c9d5ddab57 2026-09-15 19:47:11
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-15 19:47:11 +00:00
lizzie 1eb44e3ea6 2026-09-15 19:39:00
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-15 19:39:00 +00:00
lizzie 6c96d9f43d 2026-09-15 07:59:31
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-15 07:59:31 +00:00
14 changed files with 62 additions and 184 deletions
-2
View File
@@ -115,8 +115,6 @@ add_library(
stb.h
steady_clock.cpp
steady_clock.h
stream.cpp
stream.h
string_util.cpp
string_util.h
swap.h
+4 -5
View File
@@ -24,7 +24,7 @@ std::string NativeErrorToString(int e) {
DWORD res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, e, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
LPSTR(&err_str), 1, nullptr);
reinterpret_cast<LPSTR>(&err_str), 1, nullptr);
if (!res) {
return "(FormatMessageA failed to format error)";
}
@@ -32,10 +32,9 @@ std::string NativeErrorToString(int e) {
LocalFree(err_str);
return ret;
#else
char err_str[256];
// See https://github.com/llvm/llvm-project/blob/c8fdb5f8b93c3e1da5e2ff3ba8b18627d6147b51/openmp/runtime/src/kmp_i18n.cpp#L711
// musl doesn't provide a macro gate but defines strerror_r() even if _GNU_SOURCE is defined
#if defined(__managarm__) || (defined(__GLIBC__) || defined(__BIONIC__)) || defined(_GNU_SOURCE)
char err_str[255];
#if defined(__ANDROID__) || \
(defined(__GLIBC__) && (_GNU_SOURCE || (_POSIX_C_SOURCE < 200112L && _XOPEN_SOURCE < 600)))
// Thread safe (GNU-specific)
const char* str = strerror_r(e, err_str, sizeof(err_str));
return std::string(str);
-46
View File
@@ -1,46 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <stdexcept>
#include "common/common_types.h"
#include "common/stream.h"
namespace Common {
Stream::Stream() = default;
Stream::~Stream() = default;
void Stream::Seek(s32 offset, SeekOrigin origin) {
if (origin == SeekOrigin::SetOrigin) {
if (offset < 0) {
position = 0;
} else if (position >= buffer.size()) {
position = buffer.size();
} else {
position = offset;
}
} else if (origin == SeekOrigin::FromCurrentPos) {
Seek(static_cast<s32>(position) + offset, SeekOrigin::SetOrigin);
} else if (origin == SeekOrigin::FromEnd) {
Seek(static_cast<s32>(buffer.size()) - offset, SeekOrigin::SetOrigin);
}
}
u8 Stream::ReadByte() {
if (position < buffer.size()) {
return buffer[position++];
} else {
throw std::out_of_range("Attempting to read a byte not within the buffer range");
}
}
void Stream::WriteByte(u8 byte) {
if (position == buffer.size()) {
buffer.push_back(byte);
position++;
} else {
buffer.insert(buffer.begin() + position, byte);
}
}
} // namespace Common
-55
View File
@@ -1,55 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <vector>
#include "common/common_types.h"
namespace Common {
enum class SeekOrigin {
SetOrigin,
FromCurrentPos,
FromEnd,
};
class Stream {
public:
/// Stream creates a bitstream and provides common functionality on the stream.
explicit Stream();
~Stream();
Stream(const Stream&) = delete;
Stream& operator=(const Stream&) = delete;
Stream(Stream&&) = default;
Stream& operator=(Stream&&) = default;
/// Reposition bitstream "cursor" to the specified offset from origin
void Seek(s32 offset, SeekOrigin origin);
/// Reads next byte in the stream buffer and increments position
u8 ReadByte();
/// Writes byte at current position
void WriteByte(u8 byte);
[[nodiscard]] std::size_t GetPosition() const {
return position;
}
[[nodiscard]] std::vector<u8>& GetBuffer() {
return buffer;
}
[[nodiscard]] const std::vector<u8>& GetBuffer() const {
return buffer;
}
private:
std::vector<u8> buffer;
std::size_t position{0};
};
} // namespace Common
+2 -2
View File
@@ -796,8 +796,6 @@ add_library(core STATIC
hle/service/ns/application_manager_interface.h
hle/service/ns/application_version_interface.cpp
hle/service/ns/application_version_interface.h
hle/service/ns/async_result.cpp
hle/service/ns/async_result.h
hle/service/ns/content_management_interface.cpp
hle/service/ns/content_management_interface.h
hle/service/ns/develop_interface.cpp
@@ -812,6 +810,8 @@ add_library(core STATIC
hle/service/ns/ecommerce_interface.h
hle/service/ns/factory_reset_interface.cpp
hle/service/ns/factory_reset_interface.h
hle/service/ns/i_async_result.cpp
hle/service/ns/i_async_result.h
hle/service/ns/language.cpp
hle/service/ns/language.h
hle/service/ns/ns.cpp
+8 -25
View File
@@ -12,7 +12,6 @@
#include "hid_core/frontend/emulated_controller.h"
#include "hid_core/hid_core.h"
#include "hid_core/hid_types.h"
#include <array>
namespace Core::Frontend {
@@ -30,39 +29,23 @@ void DefaultControllerApplet::ReconfigureControllers(ReconfigureCallback callbac
const std::size_t min_supported_players =
parameters.enable_single_mode ? 1 : parameters.min_players;
using Core::HID::NpadStyleIndex;
const std::size_t max_supported_players = parameters.enable_single_mode ? 1 : parameters.max_players;
std::size_t num_selected_players = 0;
std::array<bool, HID::HIDCore::available_controllers> keep_connected{};
// reserve existing AND valid players before filling slots. include Handheld, but not other
for (std::size_t index = 0; index < hid_core.available_controllers - 1; ++index) {
const auto* controller = hid_core.GetEmulatedControllerByIndex(index);
if (!parameters.keep_controllers_connected || !controller->IsConnected() || num_selected_players >= max_supported_players) continue;
const auto style = controller->GetNpadStyleIndex();
keep_connected[index] =
(style == NpadStyleIndex::Fullkey && parameters.allow_pro_controller) ||
(style == NpadStyleIndex::JoyconDual && parameters.allow_dual_joycons) ||
(style == NpadStyleIndex::JoyconLeft && parameters.allow_left_joycon) ||
(style == NpadStyleIndex::JoyconRight && parameters.allow_right_joycon) ||
(style == NpadStyleIndex::Handheld && parameters.enable_single_mode && parameters.allow_handheld && !Settings::IsDockedMode()) ||
(style == NpadStyleIndex::GameCube && parameters.allow_gamecube_controller);
num_selected_players += keep_connected[index];
}
// Disconnect Handheld first.
auto* handheld = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
if (!keep_connected[hid_core.available_controllers - 2]) handheld->Disconnect();
handheld->Disconnect();
// Deduce the best configuration based on the input parameters.
for (std::size_t index = 0; index < hid_core.available_controllers - 2; ++index) {
auto* controller = hid_core.GetEmulatedControllerByIndex(index);
if (keep_connected[index]) continue;
// First, disconnect all controllers regardless of the value of keep_controllers_connected.
// This makes it easy to connect the desired controllers.
controller->Disconnect();
// only add players still needed to reach the minimum
if (num_selected_players >= min_supported_players) continue;
++num_selected_players;
// Only connect the minimum number of required players.
if (index >= min_supported_players) {
continue;
}
// Connect controllers based on the following priority list from highest to lowest priority:
// Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld
@@ -7,7 +7,7 @@
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/ns/async_result.h"
#include "core/hle/service/ns/i_async_result.h"
#include "core/hle/service/ns/language.h"
#include "core/hle/service/ns/ns_types.h"
#include "core/hle/service/os/event.h"
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/ns/async_result.h"
#include "core/hle/service/ns/i_async_result.h"
#include <cstring>
@@ -32,4 +32,4 @@ Result IAsyncResult::Cancel() {
R_SUCCEED();
}
} // namespace Service::NS
} // namespace Service::NS
@@ -311,30 +311,27 @@ void IReadOnlyApplicationControlDataInterface::ListApplicationIcon(HLERequestCon
// u64 - app count
memory.WriteBlock(t_mem_address + out_length, &app_count, sizeof(u64));
out_length += sizeof(u64);
ASSERT(out_length <= t_mem->GetSize());
// [list of u64] - size of icons
for (size_t i = 0; i < app_count; ++i) {
const u64 app_id = app_ids_buffer[i];
const FileSys::PatchManager pm{app_id, system.GetFileSystemController(), system.GetContentProvider()};
if (const auto control = pm.GetControlMetadata(); control.second) {
u64 full_size = control.second->GetSize();
memory.WriteBlock(t_mem_address + out_length, &full_size, sizeof(u64));
}
const auto control = pm.GetControlMetadata();
u64 full_size = control.second->GetSize();
memory.WriteBlock(t_mem_address + out_length, &full_size, sizeof(u64));
out_length += sizeof(u64);
ASSERT(out_length <= t_mem->GetSize());
}
// [list of raw icon data]
std::vector<u8> full_icon_data;
for (size_t i = 0; i < app_count; ++i) {
const u64 app_id = app_ids_buffer[i];
const FileSys::PatchManager pm{app_id, system.GetFileSystemController(), system.GetContentProvider()};
if (const auto control = pm.GetControlMetadata(); control.second) {
if (auto const full_size = control.second->GetSize(); full_size > 0) {
std::vector<u8> full_icon_data(full_size);
control.second->Read(full_icon_data.data(), full_size, 0);
memory.WriteBlock(t_mem_address + out_length, full_icon_data.data(), full_size);
out_length += full_size;
ASSERT(out_length <= t_mem->GetSize());
}
const auto control = pm.GetControlMetadata();
auto const full_size = control.second->GetSize();
if (full_size > 0) {
full_icon_data.resize(full_size);
control.second->Read(full_icon_data.data(), full_size, 0);
memory.WriteBlock(t_mem_address + out_length, full_icon_data.data(), full_size);
out_length += full_size;
}
}
}
@@ -348,12 +345,6 @@ void IReadOnlyApplicationControlDataInterface::ListApplicationIcon(HLERequestCon
void IReadOnlyApplicationControlDataInterface::ListApplicationTitle(HLERequestContext& ctx) {
const auto app_ids_buffer = ctx.ReadBuffer();
const size_t app_count = app_ids_buffer.size() / sizeof(u64);
std::vector<u64> application_ids(app_count);
if (app_count > 0) {
std::memcpy(application_ids.data(), app_ids_buffer.data(), app_count * sizeof(u64));
}
auto t_mem_obj = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(ctx.GetCopyHandle(0));
auto* t_mem = t_mem_obj.GetPointerUnsafe();
constexpr size_t title_entry_size = sizeof(FileSys::LanguageEntry);
@@ -363,9 +354,8 @@ void IReadOnlyApplicationControlDataInterface::ListApplicationTitle(HLERequestCo
auto& memory = system.ApplicationMemory();
const auto t_mem_address = t_mem->GetSourceAddress();
for (size_t i = 0; i < app_count; ++i) {
const u64 app_id = application_ids[i];
const FileSys::PatchManager pm{app_id, system.GetFileSystemController(),
system.GetContentProvider()};
const u64 app_id = app_ids_buffer[i];
const FileSys::PatchManager pm{app_id, system.GetFileSystemController(), system.GetContentProvider()};
const auto control = pm.GetControlMetadata();
FileSys::LanguageEntry entry{};
if (control.first != nullptr) {
+20 -19
View File
@@ -892,20 +892,28 @@ void VpxRangeEncoder::Write(bool bit, s32 probability) {
count += shift;
if (count >= 0) {
const s32 offset = shift - count;
if (((low_value << (offset - 1)) >> 31) != 0) {
const s32 current_pos = static_cast<s32>(base_stream.GetPosition());
base_stream.Seek(-1, Common::SeekOrigin::FromCurrentPos);
while (PeekByte() == 0xff) {
base_stream.WriteByte(0);
base_stream.Seek(-2, Common::SeekOrigin::FromCurrentPos);
auto const write_byte = [&](u8 byte) {
if (stream_pos == stream_data.size()) {
stream_data.push_back(byte);
++stream_pos;
} else {
stream_data.insert(stream_data.begin() + stream_pos, byte);
}
base_stream.WriteByte(static_cast<u8>((PeekByte() + 1)));
base_stream.Seek(current_pos, Common::SeekOrigin::SetOrigin);
};
const s32 offset = shift - count;
if (((low_value << (offset - 1)) >> 31) != 0) {
auto const current_pos = stream_pos;
--stream_pos;
while (stream_data[stream_pos] == 0xff) {
write_byte(0);
stream_pos -= 2;
}
write_byte(stream_data[stream_pos] + 1);
stream_pos = current_pos;
}
base_stream.WriteByte(static_cast<u8>((low_value >> (24 - offset))));
write_byte(u8((low_value >> (24 - offset))));
++stream_pos;
low_value <<= offset;
shift = count;
@@ -923,13 +931,6 @@ void VpxRangeEncoder::End() {
}
}
u8 VpxRangeEncoder::PeekByte() {
const u8 value = base_stream.ReadByte();
base_stream.Seek(-1, Common::SeekOrigin::FromCurrentPos);
return value;
}
VpxBitStreamWriter::VpxBitStreamWriter() = default;
VpxBitStreamWriter::~VpxBitStreamWriter() = default;
+6 -4
View File
@@ -12,7 +12,6 @@
#include "common/common_types.h"
#include "common/scratch_buffer.h"
#include "common/stream.h"
#include "video_core/host1x/codecs/decoder.h"
#include "video_core/host1x/codec_types.h"
#include "video_core/host1x/nvdec_common.h"
@@ -52,16 +51,19 @@ public:
void End();
[[nodiscard]] std::vector<u8>& GetBuffer() {
return base_stream.GetBuffer();
return stream_data;
}
[[nodiscard]] const std::vector<u8>& GetBuffer() const {
return base_stream.GetBuffer();
return stream_data;
}
private:
u8 PeekByte();
Common::Stream base_stream{};
std::vector<u8> stream_data{};
size_t stream_pos;
u32 low_value{};
u32 range{0xff};
s32 count{-24};
@@ -2850,6 +2850,8 @@ Sampler::VariantKey Sampler::MakeKey(const ImageView& image_view, bool is_depth)
VariantKey key{};
key.reduce_anisotropy = has_added_anisotropy && !image_view.SupportsAnisotropy();
key.force_nearest = has_linear_filtering && IsPixelFormatInteger(image_view.format);
key.drop_depth_comparison =
is_depth && has_depth_comparison && !image_view.SupportsDepthComparison();
key.drop_reduction = has_minmax_reduction && !image_view.SupportsMinmaxFilter();
key.drop_custom_border = has_custom_border_colors && image_view.RequiresBorderColorFormat();
key.srgb_border = has_srgb_border_color && IsPixelFormatSRGB(image_view.format);
@@ -2927,6 +2929,9 @@ VkSampler Sampler::Emplace(VariantKey key) {
create_info.anisotropyEnable = static_cast<VkBool32>(default_anisotropy > 1.0f);
create_info.maxAnisotropy = default_anisotropy;
}
if (key.drop_depth_comparison) {
create_info.compareEnable = VK_FALSE;
}
if (!custom_border) {
create_info.borderColor = ConvertBorderColor(color);
}
@@ -536,6 +536,7 @@ private:
struct VariantKey {
bool reduce_anisotropy;
bool force_nearest;
bool drop_depth_comparison;
bool drop_reduction;
bool drop_custom_border;
bool srgb_border;