mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-22 03:46:53 +02:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ccddd6fb94 | |||
| e559771a08 | |||
| b870a77176 | |||
| 62eaead3a3 | |||
| d7808d9cb4 | |||
| 8267c422b5 | |||
| b46e141762 | |||
| cfa140fb12 |
Vendored
+37
-3
@@ -10,7 +10,14 @@
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}\\_Build\\vscode-clang\\launcher",
|
||||
"environment": [],
|
||||
"externalConsole": false
|
||||
"externalConsole": false,
|
||||
"linux": {
|
||||
"type": "cppdbg",
|
||||
"program": "${workspaceFolder}/_Build/vscode-clang/launcher/launcher",
|
||||
"cwd": "${workspaceFolder}/_Build/vscode-clang/launcher",
|
||||
"MIMode": "gdb",
|
||||
"miDebuggerPath": "/usr/bin/gdb"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Debug kyty_emulator",
|
||||
@@ -25,13 +32,40 @@
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}\\_Build\\vscode-clang",
|
||||
"environment": [],
|
||||
"externalConsole": true
|
||||
"externalConsole": true,
|
||||
"linux": {
|
||||
"type": "cppdbg",
|
||||
"program": "${workspaceFolder}/_Build/vscode-clang/kyty_emulator",
|
||||
"cwd": "${workspaceFolder}/_Build/vscode-clang",
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"miDebuggerPath": "/usr/bin/gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Pass Kyty's internal signals to its handlers",
|
||||
"text": "handle SIG37 SIGSEGV SIGBUS SIGILL nostop noprint pass",
|
||||
"ignoreFailures": false
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Attach to running kyty_emulator",
|
||||
"type": "cppvsdbg",
|
||||
"request": "attach",
|
||||
"processId": "${command:pickProcess}"
|
||||
"processId": "${command:pickProcess}",
|
||||
"linux": {
|
||||
"type": "cppdbg",
|
||||
"MIMode": "gdb",
|
||||
"miDebuggerPath": "/usr/bin/gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Pass Kyty's internal signals to its handlers",
|
||||
"text": "handle SIG37 SIGSEGV SIGBUS SIGILL nostop noprint pass",
|
||||
"ignoreFailures": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -524,6 +524,16 @@ if(NOT KYTY_CLANG_CL)
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTING)
|
||||
add_test(NAME emulator_user_name_cli
|
||||
COMMAND $<TARGET_FILE:kyty_emulator> --help --user-name 1234567890123456)
|
||||
add_test(NAME emulator_user_name_too_long
|
||||
COMMAND $<TARGET_FILE:kyty_emulator> --help --user-name 12345678901234567)
|
||||
set_tests_properties(emulator_user_name_too_long PROPERTIES WILL_FAIL TRUE)
|
||||
add_test(NAME emulator_present_mode_cli
|
||||
COMMAND $<TARGET_FILE:kyty_emulator> --help --present-mode Immediate)
|
||||
add_test(NAME emulator_present_mode_invalid
|
||||
COMMAND $<TARGET_FILE:kyty_emulator> --help --present-mode Invalid)
|
||||
set_tests_properties(emulator_present_mode_invalid PROPERTIES WILL_FAIL TRUE)
|
||||
add_test(NAME ime_dialog COMMAND $<TARGET_FILE:ime_dialog_tests>)
|
||||
add_test(NAME shader_cfg COMMAND $<TARGET_FILE:shader_cfg_tests>)
|
||||
add_test(NAME scalar_provenance COMMAND $<TARGET_FILE:scalar_provenance_tests>)
|
||||
|
||||
@@ -21,6 +21,8 @@ void Shutdown() {
|
||||
|
||||
void Load(const ConfigOptions& cfg) {
|
||||
EXIT_IF(g_config == nullptr);
|
||||
EXIT_IF(cfg.user_name.empty() || cfg.user_name.size() > MAX_USER_NAME_LENGTH);
|
||||
EXIT_IF(!IsConfiguredUserIdValid(cfg.user_id));
|
||||
|
||||
*g_config = cfg;
|
||||
}
|
||||
@@ -33,6 +35,18 @@ uint32_t GetScreenHeight() {
|
||||
return g_config->screen_height;
|
||||
}
|
||||
|
||||
const std::string& GetUserName() {
|
||||
return g_config->user_name;
|
||||
}
|
||||
|
||||
int32_t GetUserId() {
|
||||
return g_config->user_id;
|
||||
}
|
||||
|
||||
PresentMode GetPresentMode() {
|
||||
return g_config->present_mode;
|
||||
}
|
||||
|
||||
bool FullscreenEnabled() {
|
||||
return g_config->fullscreen_enabled;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "common/common.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -26,14 +27,27 @@ enum class ProfilerDirection { None, Network };
|
||||
|
||||
enum class OutputDirection { Silent, Console, File };
|
||||
|
||||
enum class PresentMode { Fifo, Mailbox, Immediate };
|
||||
|
||||
using Keymap = std::vector<std::string>;
|
||||
|
||||
constexpr uint32_t DEFAULT_CONSOLE_LANGUAGE = 1;
|
||||
constexpr uint32_t MAX_CONSOLE_LANGUAGE = 29;
|
||||
constexpr std::size_t MAX_USER_NAME_LENGTH = 16;
|
||||
constexpr int32_t DEFAULT_USER_ID = 1000;
|
||||
|
||||
constexpr bool IsConfiguredUserIdValid(int32_t user_id) {
|
||||
constexpr int32_t USER_ID_EVERYONE = 0xfe;
|
||||
constexpr int32_t USER_ID_SYSTEM = 0xff;
|
||||
return user_id >= 0 && user_id != USER_ID_EVERYONE && user_id != USER_ID_SYSTEM;
|
||||
}
|
||||
|
||||
struct ConfigOptions {
|
||||
uint32_t screen_width = 1280;
|
||||
uint32_t screen_height = 720;
|
||||
std::string user_name = "Kyty";
|
||||
int32_t user_id = DEFAULT_USER_ID;
|
||||
PresentMode present_mode = PresentMode::Fifo;
|
||||
bool fullscreen_enabled = false;
|
||||
uint32_t vblank_frequency = 60;
|
||||
uint32_t console_language = DEFAULT_CONSOLE_LANGUAGE;
|
||||
@@ -63,6 +77,9 @@ void Load(const ConfigOptions& cfg);
|
||||
|
||||
uint32_t GetScreenWidth();
|
||||
uint32_t GetScreenHeight();
|
||||
const std::string& GetUserName();
|
||||
int32_t GetUserId();
|
||||
PresentMode GetPresentMode();
|
||||
bool FullscreenEnabled();
|
||||
uint32_t GetVblankFrequency();
|
||||
uint32_t GetConsoleLanguage();
|
||||
|
||||
@@ -1,30 +1,9 @@
|
||||
#include "SDL.h"
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_gamecontroller.h"
|
||||
#include "SDL_hints.h"
|
||||
#include "SDL_joystick.h"
|
||||
#include "SDL_keyboard.h"
|
||||
#include "SDL_keycode.h"
|
||||
#include "SDL_mouse.h"
|
||||
#include "SDL_pixels.h"
|
||||
#include "SDL_rwops.h"
|
||||
#include "SDL_stdinc.h"
|
||||
#include "SDL_surface.h"
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_touch.h"
|
||||
#include "SDL_video.h"
|
||||
#include "SDL_vulkan.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/common.h"
|
||||
#include "common/emulatorConfig.h"
|
||||
#include "common/file.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/profiler.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "common/systemInfo.h"
|
||||
#include "common/threads.h"
|
||||
#include "common/timer.h"
|
||||
#include "graphics/host_gpu/graphicContext.h"
|
||||
#include "graphics/host_gpu/renderer/render.h"
|
||||
#include "graphics/host_gpu/renderer/renderContext.h"
|
||||
@@ -34,19 +13,11 @@
|
||||
#include "graphics/presentation/presenter.h"
|
||||
#include "graphics/presentation/videoOut.h"
|
||||
#include "graphics/presentation/window/windowInternal.h"
|
||||
#include "libs/controller.h"
|
||||
#include "loader/systemContent.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <deque>
|
||||
#include <fmt/format.h>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <vulkan/vk_platform.h>
|
||||
|
||||
@@ -334,7 +305,6 @@ public:
|
||||
|
||||
private:
|
||||
void Destroy();
|
||||
void RefreshSurfaceSize();
|
||||
|
||||
WindowContext& m_window;
|
||||
vk::SwapchainKHR m_handle = nullptr;
|
||||
@@ -396,12 +366,12 @@ struct Presenter::Impl {
|
||||
|
||||
void Swapchain::Create() {
|
||||
auto& graphics = m_window.graphic_ctx;
|
||||
EXIT_IF(graphics.screen_width == 0);
|
||||
EXIT_IF(graphics.screen_height == 0);
|
||||
EXIT_IF(graphics.device == nullptr);
|
||||
EXIT_IF(m_window.surface == nullptr);
|
||||
|
||||
Common::LockGuard lock(m_window.mutex);
|
||||
EXIT_IF(graphics.screen_width == 0);
|
||||
EXIT_IF(graphics.screen_height == 0);
|
||||
const auto& surface = m_window.surface_capabilities;
|
||||
EXIT_NOT_IMPLEMENTED(surface.formats.empty());
|
||||
|
||||
@@ -459,7 +429,21 @@ void Swapchain::Create() {
|
||||
create_info.imageSharingMode = vk::SharingMode::eExclusive;
|
||||
create_info.preTransform = transform;
|
||||
create_info.compositeAlpha = composite;
|
||||
create_info.presentMode = vk::PresentModeKHR::eFifo;
|
||||
switch (Config::GetPresentMode()) {
|
||||
case Config::PresentMode::Mailbox:
|
||||
create_info.presentMode = vk::PresentModeKHR::eMailbox;
|
||||
break;
|
||||
case Config::PresentMode::Immediate:
|
||||
create_info.presentMode = vk::PresentModeKHR::eImmediate;
|
||||
break;
|
||||
case Config::PresentMode::Fifo:
|
||||
default: create_info.presentMode = vk::PresentModeKHR::eFifo; break;
|
||||
}
|
||||
if (std::find(surface.present_modes.begin(), surface.present_modes.end(),
|
||||
create_info.presentMode) == surface.present_modes.end()) {
|
||||
LOGF("warning: requested present mode is unavailable; falling back to Fifo\n");
|
||||
create_info.presentMode = vk::PresentModeKHR::eFifo;
|
||||
}
|
||||
create_info.clipped = VK_TRUE;
|
||||
RequireVulkanSuccess(graphics.device.createSwapchainKHR(&create_info, nullptr, &m_handle),
|
||||
"vkCreateSwapchainKHR");
|
||||
@@ -554,30 +538,18 @@ void Swapchain::Destroy() {
|
||||
m_render_complete.clear();
|
||||
}
|
||||
|
||||
void Swapchain::RefreshSurfaceSize() {
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
SDL_Vulkan_GetDrawableSize(m_window.window, &width, &height);
|
||||
if (width > 0 && height > 0) {
|
||||
m_window.graphic_ctx.screen_width = static_cast<uint32_t>(width);
|
||||
m_window.graphic_ctx.screen_height = static_cast<uint32_t>(height);
|
||||
}
|
||||
|
||||
m_window.RefreshSurfaceCapabilities();
|
||||
}
|
||||
|
||||
void Swapchain::Recreate(bool surface_lost) {
|
||||
Destroy();
|
||||
if (surface_lost) {
|
||||
#if defined(__APPLE__)
|
||||
// Surface recreation goes through SDL_Vulkan_CreateSurface, which touches the
|
||||
// window's view/layer and must run on the main thread on macOS.
|
||||
m_window.RunOnMainThread([this] { m_window.RecreateSurface(); }, true);
|
||||
m_window.RunOnMainThread([this] { m_window.RecreateSurface(); });
|
||||
#else
|
||||
m_window.RecreateSurface();
|
||||
#endif
|
||||
}
|
||||
RefreshSurfaceSize();
|
||||
m_window.RefreshSurfaceCapabilities();
|
||||
Create();
|
||||
}
|
||||
|
||||
@@ -803,29 +775,6 @@ void Presenter::Present(Frame& frame, bool reuse) {
|
||||
KYTY_PROFILER_FUNCTION();
|
||||
m_impl->frames.ValidateForPresent(&frame, reuse);
|
||||
|
||||
auto& window = m_impl->window;
|
||||
if (window.window_hidden) {
|
||||
#if defined(__APPLE__)
|
||||
// AppKit traps if a window is shown off the main thread; marshal and wait so the
|
||||
// swapchain below is recreated against a visible window.
|
||||
window.RunOnMainThread(
|
||||
[&window] {
|
||||
window.UpdateIcon();
|
||||
SDL_ShowWindow(window.window);
|
||||
SDL_RaiseWindow(window.window);
|
||||
},
|
||||
true);
|
||||
#else
|
||||
window.UpdateIcon();
|
||||
|
||||
SDL_ShowWindow(window.window);
|
||||
SDL_RaiseWindow(window.window);
|
||||
#endif
|
||||
|
||||
window.window_hidden = false;
|
||||
m_impl->RecoverSwapchain(Swapchain::Status::Recreate);
|
||||
}
|
||||
|
||||
const auto ime_visual = GetImeVisualState();
|
||||
auto& swapchain = m_impl->swapchain;
|
||||
for (uint32_t attempt = 0; attempt < 2; attempt++) {
|
||||
@@ -848,7 +797,7 @@ void Presenter::Present(Frame& frame, bool reuse) {
|
||||
}
|
||||
|
||||
m_impl->presented_ime_revision.store(ime_visual.revision, std::memory_order_release);
|
||||
window.UpdateTitle();
|
||||
m_impl->window.UpdateTitle();
|
||||
m_impl->frames.Release(&frame, true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "common/logging/log.h"
|
||||
#include "common/profiler.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "common/systemInfo.h"
|
||||
#include "common/threads.h"
|
||||
#include "common/timer.h"
|
||||
#include "graphics/host_gpu/graphicContext.h"
|
||||
@@ -1037,10 +1036,6 @@ void WindowContext::CreateVulkan() {
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(device_name, device_properties.deviceName, sizeof(device_name));
|
||||
std::snprintf(processor_name, sizeof(processor_name), "%s",
|
||||
Common::GetSystemInfo().ProcessorName.c_str());
|
||||
|
||||
VulkanInitSubgroupSizeControl(graphic_ctx.physical_device, graphic_ctx);
|
||||
|
||||
graphic_ctx.device = VulkanCreateDevice(graphic_ctx.physical_device, r, queue_family,
|
||||
@@ -1079,7 +1074,6 @@ void WindowContext::RecreateSurface() {
|
||||
EXIT("Could not recreate the Vulkan surface: %s\n", SDL_GetError());
|
||||
}
|
||||
surface = native_surface;
|
||||
RefreshSurfaceCapabilities();
|
||||
}
|
||||
|
||||
WindowContext::~WindowContext() {
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "common/file.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/profiler.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "common/systemInfo.h"
|
||||
#include "common/threads.h"
|
||||
#include "common/timer.h"
|
||||
@@ -39,21 +38,18 @@
|
||||
#include "libs/controller.h"
|
||||
#include "loader/systemContent.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <vulkan/vk_platform.h>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#define STBI_NO_SIMD
|
||||
#include "stb_image.h"
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
// IWYU pragma: no_include <intrin.h>
|
||||
|
||||
#define KYTY_ENABLE_DEBUG_PRINTF
|
||||
@@ -197,8 +193,6 @@ std::unique_ptr<WindowContext> g_window;
|
||||
} // namespace
|
||||
|
||||
constexpr const char* KYTY_SDL_WINDOW_CAPTION = "Game";
|
||||
constexpr uint32_t KYTY_SDL_WINDOW_FLAGS =
|
||||
(static_cast<uint32_t>(SDL_WINDOW_HIDDEN) | static_cast<uint32_t>(SDL_WINDOW_VULKAN));
|
||||
constexpr int KYTY_SDL_WINDOWPOS_CENTERED = SDL_WINDOWPOS_CENTERED; /*NOLINT(hicpp-signed-bitwise)*/
|
||||
|
||||
static void SetPause(WindowLoopState& game, bool flag) {
|
||||
@@ -407,6 +401,7 @@ static void GameEventDidEnterForeground(WindowLoopState& game) {
|
||||
|
||||
void WindowContext::Resize(uint32_t new_width, uint32_t new_height) {
|
||||
EXIT_IF(new_width == 0 || new_height == 0);
|
||||
Common::LockGuard lock(mutex);
|
||||
graphic_ctx.screen_width = new_width;
|
||||
graphic_ctx.screen_height = new_height;
|
||||
}
|
||||
@@ -728,8 +723,7 @@ void WindowContext::ProcessEvent(double time_s) {
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__APPLE__)
|
||||
void WindowContext::RunOnMainThread(std::function<void()> task, bool wait) {
|
||||
void WindowContext::RunOnMainThread(std::function<void()> task) {
|
||||
if (Common::Thread::IsMainThread()) {
|
||||
task();
|
||||
return;
|
||||
@@ -747,9 +741,6 @@ void WindowContext::RunOnMainThread(std::function<void()> task, bool wait) {
|
||||
event.type = SDL_USEREVENT;
|
||||
SDL_PushEvent(&event);
|
||||
|
||||
if (!wait) {
|
||||
return;
|
||||
}
|
||||
Common::LockGuard lock(main_task_mutex);
|
||||
while (main_tasks_run < ticket) {
|
||||
main_task_done.Wait(&main_task_mutex);
|
||||
@@ -772,7 +763,6 @@ void WindowContext::DrainMainThreadTasks() {
|
||||
main_tasks_run += tasks.size();
|
||||
main_task_done.SignalAll();
|
||||
}
|
||||
#endif
|
||||
|
||||
void WindowContext::Run() {
|
||||
Common::Timer timer;
|
||||
@@ -783,9 +773,7 @@ void WindowContext::Run() {
|
||||
loop.paused.store(false, std::memory_order_release);
|
||||
|
||||
while (!loop.need_exit) {
|
||||
#if defined(__APPLE__)
|
||||
DrainMainThreadTasks();
|
||||
#endif
|
||||
if (loop.paused.load(std::memory_order_acquire)) {
|
||||
if (!timer.IsPaused()) {
|
||||
timer.Pause();
|
||||
@@ -821,10 +809,7 @@ static void WindowCreate(WindowContext& context) {
|
||||
|
||||
LOGF("WindowCreate(): width = %d, height = %d\n", width, height);
|
||||
|
||||
uint32_t window_flags = KYTY_SDL_WINDOW_FLAGS;
|
||||
if (Config::FullscreenEnabled()) {
|
||||
window_flags |= static_cast<uint32_t>(SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
}
|
||||
uint32_t window_flags = WindowContext::InitialWindowFlags(Config::FullscreenEnabled());
|
||||
#if defined(__APPLE__)
|
||||
// macOS 26 window chrome (CoreUI asset decode, SwiftUI titlebar) has been observed
|
||||
// throwing NSExceptions under Rosetta during the first CATransaction commit. A
|
||||
@@ -836,13 +821,20 @@ static void WindowCreate(WindowContext& context) {
|
||||
context.window = SDL_CreateWindow(KYTY_SDL_WINDOW_CAPTION, KYTY_SDL_WINDOWPOS_CENTERED,
|
||||
KYTY_SDL_WINDOWPOS_CENTERED, width, height, window_flags);
|
||||
|
||||
context.window_hidden = true;
|
||||
|
||||
if (context.window == nullptr) {
|
||||
EXIT("%s\n", SDL_GetError());
|
||||
}
|
||||
|
||||
SDL_SetWindowResizable(context.window, SDL_FALSE);
|
||||
context.UpdateIcon();
|
||||
}
|
||||
|
||||
uint32_t WindowContext::InitialWindowFlags(bool fullscreen) noexcept {
|
||||
auto flags = static_cast<uint32_t>(SDL_WINDOW_VULKAN);
|
||||
if (fullscreen) {
|
||||
flags |= static_cast<uint32_t>(SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
Presenter& WindowInit(uint32_t width, uint32_t height) {
|
||||
@@ -959,6 +951,7 @@ void WindowContext::UpdateTitle() {
|
||||
Loader::SystemContentParamSfoGetString("TITLE_ID", title_id, sizeof(title_id));
|
||||
static bool has_app_ver =
|
||||
Loader::SystemContentParamSfoGetString("APP_VER", app_ver, sizeof(app_ver));
|
||||
static const std::string processor_name = Common::GetSystemInfo().ProcessorName;
|
||||
static uint64_t fps_start = Common::Timer::QueryPerformanceCounter();
|
||||
static uint64_t frame_num = 0;
|
||||
static uint64_t fps_frames = 0;
|
||||
@@ -983,19 +976,14 @@ void WindowContext::UpdateTitle() {
|
||||
fps_frames = 0;
|
||||
}
|
||||
|
||||
auto fps = fmt::format(
|
||||
const auto* device_name = graphic_ctx.GetPhysicalDeviceProperties().deviceName.data();
|
||||
auto text = fmt::format(
|
||||
"[{} | {}] {}{}{}{}{}{}[{}] [{}], frame: {}, fps: {:f}", KYTY_BUILD_LABEL, build_type,
|
||||
(has_title ? title : ""), (has_title ? ", " : ""), (has_title_id ? title_id : ""),
|
||||
(has_title_id ? ", " : ""), (has_app_ver ? app_ver : ""), (has_app_ver ? " " : ""),
|
||||
device_name, processor_name, frame_num, current_fps);
|
||||
|
||||
#if defined(__APPLE__)
|
||||
// AppKit traps on title changes off the main thread; fire-and-forget keeps present pacing.
|
||||
RunOnMainThread([this, fps = std::move(fps)] { SDL_SetWindowTitle(window, fps.c_str()); },
|
||||
false);
|
||||
#else
|
||||
SDL_SetWindowTitle(window, fps.c_str());
|
||||
#endif
|
||||
RunOnMainThread([this, text = std::move(text)] { SDL_SetWindowTitle(window, text.c_str()); });
|
||||
}
|
||||
|
||||
} // namespace Libs::Graphics
|
||||
|
||||
@@ -9,13 +9,10 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <functional>
|
||||
#endif
|
||||
|
||||
namespace Libs::Graphics {
|
||||
|
||||
class Presenter;
|
||||
@@ -39,6 +36,7 @@ struct WindowContext {
|
||||
KYTY_CLASS_NO_COPY(WindowContext);
|
||||
|
||||
[[nodiscard]] static vk::PhysicalDeviceVulkan13Features RequiredVulkan13Features() noexcept;
|
||||
[[nodiscard]] static uint32_t InitialWindowFlags(bool fullscreen) noexcept;
|
||||
void CreateVulkan();
|
||||
void RecreateSurface();
|
||||
void RefreshSurfaceCapabilities();
|
||||
@@ -49,36 +47,25 @@ struct WindowContext {
|
||||
void ProcessDisplayEvent(const SDL_DisplayEvent& event);
|
||||
void ProcessEvent(double time_seconds);
|
||||
void Run();
|
||||
|
||||
#if defined(__APPLE__)
|
||||
// AppKit only allows window operations (show, icon, title, view/layer changes) on the
|
||||
// main thread; the present thread marshals them through the SDL main loop with these.
|
||||
// wait=true blocks until the task has run on the main thread.
|
||||
void RunOnMainThread(std::function<void()> task, bool wait);
|
||||
// SDL window operations must complete on the main thread.
|
||||
void RunOnMainThread(std::function<void()> task);
|
||||
void DrainMainThreadTasks();
|
||||
#endif
|
||||
|
||||
GraphicContext graphic_ctx;
|
||||
SDL_Window* window = nullptr;
|
||||
bool window_hidden = true;
|
||||
vk::SurfaceKHR surface = nullptr;
|
||||
SurfaceCapabilities surface_capabilities;
|
||||
std::unique_ptr<RenderContext> render_context;
|
||||
std::unique_ptr<Presenter> presenter;
|
||||
WindowLoopState loop;
|
||||
|
||||
char device_name[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE] = {0};
|
||||
char processor_name[64] = {0};
|
||||
|
||||
Common::Mutex mutex;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
Common::Mutex main_task_mutex;
|
||||
Common::CondVar main_task_done;
|
||||
std::vector<std::function<void()>> main_tasks; // guarded by main_task_mutex
|
||||
uint64_t main_tasks_queued = 0; // guarded by main_task_mutex
|
||||
uint64_t main_tasks_run = 0; // guarded by main_task_mutex
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace Libs::Graphics
|
||||
|
||||
@@ -102,27 +102,75 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_user_name">
|
||||
<property name="text">
|
||||
<string>User name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="MandatoryLineEdit" name="lineEdit_user_name">
|
||||
<property name="toolTip">
|
||||
<string>Local user name exposed to games</string>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_user_id">
|
||||
<property name="text">
|
||||
<string>User ID:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="spinBox_user_id">
|
||||
<property name="toolTip">
|
||||
<string>Local user ID exposed to games</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>2147483647</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>Screen resolution:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="comboBox_screen_resolution">
|
||||
<property name="toolTip">
|
||||
<string>Window resolution</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_present_mode">
|
||||
<property name="text">
|
||||
<string>Present mode:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="comboBox_present_mode">
|
||||
<property name="toolTip">
|
||||
<string>Vulkan swapchain presentation mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_vblank_frequency">
|
||||
<property name="text">
|
||||
<string>Vblank frequency:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="5" column="1">
|
||||
<widget class="QSpinBox" name="spinBox_vblank_frequency">
|
||||
<property name="toolTip">
|
||||
<string>Virtual display refresh rate used for frame pacing</string>
|
||||
@@ -138,56 +186,56 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_console_language">
|
||||
<property name="text">
|
||||
<string>Console language:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="comboBox_console_language">
|
||||
<property name="toolTip">
|
||||
<string>Language</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="text">
|
||||
<string>Shader optimization type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<item row="7" column="1">
|
||||
<widget class="QComboBox" name="comboBox_shader_optimization_type">
|
||||
<property name="toolTip">
|
||||
<string>Optimize shaders for code size or performance</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="text">
|
||||
<string>Shader log direction:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<item row="8" column="1">
|
||||
<widget class="QComboBox" name="comboBox_shader_log_direction">
|
||||
<property name="toolTip">
|
||||
<string>Dump shaders to file or console window. If enabled may decrease emulator performance</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_22">
|
||||
<property name="text">
|
||||
<string>Shader log folder:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<item row="9" column="1">
|
||||
<widget class="MandatoryLineEdit" name="lineEdit_shader_log_folder">
|
||||
<property name="toolTip">
|
||||
<string>Specify directory to dump shaders</string>
|
||||
@@ -197,14 +245,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_24">
|
||||
<property name="text">
|
||||
<string>Command buffer dump folder:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<item row="10" column="1">
|
||||
<widget class="MandatoryLineEdit" name="lineEdit_cmd_dump_folder">
|
||||
<property name="toolTip">
|
||||
<string>Specify directory to dump command buffers</string>
|
||||
@@ -214,28 +262,28 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_25">
|
||||
<property name="text">
|
||||
<string>Printf direction:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<item row="11" column="1">
|
||||
<widget class="QComboBox" name="comboBox_printf_direction">
|
||||
<property name="toolTip">
|
||||
<string>Print logs to file or console window. If enabled may decrease emulator performance</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="label_26">
|
||||
<property name="text">
|
||||
<string>Printf output file:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<item row="12" column="1">
|
||||
<widget class="MandatoryLineEdit" name="lineEdit_printf_file">
|
||||
<property name="toolTip">
|
||||
<string>Specify file to dump logs</string>
|
||||
@@ -245,14 +293,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<item row="13" column="0">
|
||||
<widget class="QLabel" name="label_27">
|
||||
<property name="text">
|
||||
<string>Profiler direction:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<item row="13" column="1">
|
||||
<widget class="QComboBox" name="comboBox_profiler_direction">
|
||||
<property name="toolTip">
|
||||
<string>Enable or disable profiler. If enabled may decrease emulator performance</string>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define LAUNCHER_INCLUDE_CONFIGURATION_H_
|
||||
|
||||
#include "common.h"
|
||||
#include "common/emulatorConfig.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QChar>
|
||||
@@ -54,12 +55,17 @@ public:
|
||||
enum class Resolution {
|
||||
R1280X720,
|
||||
R1920X1080,
|
||||
R2560X1440,
|
||||
R3840X2160,
|
||||
};
|
||||
Q_ENUM(Resolution)
|
||||
|
||||
enum class ShaderOptimizationType { None, Size, Performance };
|
||||
Q_ENUM(ShaderOptimizationType)
|
||||
|
||||
enum class PresentMode { Fifo, Mailbox, Immediate };
|
||||
Q_ENUM(PresentMode)
|
||||
|
||||
enum class ShaderLogDirection { Silent, Console, File };
|
||||
Q_ENUM(ShaderLogDirection)
|
||||
|
||||
@@ -85,6 +91,9 @@ public:
|
||||
QString game_comment;
|
||||
|
||||
Resolution screen_resolution = Resolution::R1280X720;
|
||||
QString user_name = "Kyty";
|
||||
int user_id = Config::DEFAULT_USER_ID;
|
||||
PresentMode present_mode = PresentMode::Fifo;
|
||||
bool fullscreen_enabled = false;
|
||||
int vblank_frequency = 60;
|
||||
int console_language = DEFAULT_CONSOLE_LANGUAGE;
|
||||
@@ -108,6 +117,9 @@ public:
|
||||
|
||||
void CopyEmulatorSettingsFrom(const Configuration& other) {
|
||||
screen_resolution = other.screen_resolution;
|
||||
user_name = other.user_name;
|
||||
user_id = other.user_id;
|
||||
present_mode = other.present_mode;
|
||||
fullscreen_enabled = other.fullscreen_enabled;
|
||||
vblank_frequency = other.vblank_frequency;
|
||||
console_language = other.console_language;
|
||||
@@ -148,6 +160,9 @@ public:
|
||||
KYTY_CFG_SET(game_path);
|
||||
KYTY_CFG_SET(custom_settings);
|
||||
KYTY_CFG_SET(screen_resolution);
|
||||
KYTY_CFG_SET(user_name);
|
||||
KYTY_CFG_SET(user_id);
|
||||
KYTY_CFG_SET(present_mode);
|
||||
KYTY_CFG_SET(fullscreen_enabled);
|
||||
KYTY_CFG_SET(vblank_frequency);
|
||||
KYTY_CFG_SET(console_language);
|
||||
@@ -175,6 +190,16 @@ public:
|
||||
KYTY_CFG_GET(game_path);
|
||||
KYTY_CFG_GET(custom_settings);
|
||||
KYTY_CFG_GET(screen_resolution);
|
||||
user_name = s->value("user_name", user_name).toString();
|
||||
bool user_id_ok = false;
|
||||
auto saved_user_id = s->value("user_id", user_id).toInt(&user_id_ok);
|
||||
user_id = user_id_ok && Config::IsConfiguredUserIdValid(saved_user_id)
|
||||
? saved_user_id
|
||||
: Config::DEFAULT_USER_ID;
|
||||
KYTY_CFG_GET(present_mode);
|
||||
if (EnumToText(present_mode).isEmpty()) {
|
||||
present_mode = PresentMode::Fifo;
|
||||
}
|
||||
KYTY_CFG_GET(fullscreen_enabled);
|
||||
vblank_frequency = s->value("vblank_frequency", vblank_frequency).toInt();
|
||||
console_language = s->value("console_language", console_language).toInt();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "configurationEditDialog.h"
|
||||
|
||||
#include "common/emulatorConfig.h"
|
||||
#include "configuration.h"
|
||||
#include "mandatoryLineEdit.h"
|
||||
|
||||
@@ -12,6 +13,7 @@
|
||||
#include <QGroupBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLayout>
|
||||
#include <QLineEdit>
|
||||
#include <QListView>
|
||||
#include <QListWidget>
|
||||
#include <QMessageBox>
|
||||
@@ -152,7 +154,11 @@ static void ListInit(QComboBox* combo, T value) {
|
||||
}
|
||||
|
||||
void ConfigurationEditDialog::Init(const Configuration& info) {
|
||||
m_ui->lineEdit_user_name->setMaxLength(static_cast<int>(Config::MAX_USER_NAME_LENGTH));
|
||||
m_ui->lineEdit_user_name->setText(info.user_name);
|
||||
m_ui->spinBox_user_id->setValue(info.user_id);
|
||||
ListInit(m_ui->comboBox_screen_resolution, info.screen_resolution);
|
||||
ListInit(m_ui->comboBox_present_mode, info.present_mode);
|
||||
m_ui->checkBox_fullscreen->setChecked(info.fullscreen_enabled);
|
||||
m_ui->spinBox_vblank_frequency->setValue(info.vblank_frequency);
|
||||
m_ui->comboBox_console_language->clear();
|
||||
@@ -283,8 +289,12 @@ void ConfigurationEditDialog::moveEvent(QMoveEvent* event) {
|
||||
}
|
||||
|
||||
static void UpdateInfo(Configuration& info, Ui::ConfigurationEditDialog& ui) {
|
||||
info.user_name = ui.lineEdit_user_name->text().trimmed();
|
||||
info.user_id = ui.spinBox_user_id->value();
|
||||
info.screen_resolution =
|
||||
TextToEnum<Configuration::Resolution>(ui.comboBox_screen_resolution->currentText());
|
||||
info.present_mode =
|
||||
TextToEnum<Configuration::PresentMode>(ui.comboBox_present_mode->currentText());
|
||||
info.fullscreen_enabled = ui.checkBox_fullscreen->isChecked();
|
||||
info.vblank_frequency = ui.spinBox_vblank_frequency->value();
|
||||
info.console_language = ui.comboBox_console_language->currentIndex();
|
||||
@@ -322,6 +332,19 @@ void ConfigurationEditDialog::save() {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto user_name = m_ui->lineEdit_user_name->text().trimmed();
|
||||
if (user_name.isEmpty() || user_name.toUtf8().size() > Config::MAX_USER_NAME_LENGTH) {
|
||||
QMessageBox::critical(this, tr("Save failed"),
|
||||
tr("User name must contain 1-16 UTF-8 bytes"));
|
||||
return;
|
||||
}
|
||||
m_ui->lineEdit_user_name->setText(user_name);
|
||||
if (!Config::IsConfiguredUserIdValid(m_ui->spinBox_user_id->value())) {
|
||||
QMessageBox::critical(this, tr("Save failed"),
|
||||
tr("User ID cannot be 254 (everyone) or 255 (system)"));
|
||||
return;
|
||||
}
|
||||
|
||||
update_info();
|
||||
|
||||
emit accept();
|
||||
|
||||
@@ -204,6 +204,9 @@ static QStringList CreateEmulatorArgs(const Configuration& info) {
|
||||
|
||||
args << "--screen-width" << r.at(0);
|
||||
args << "--screen-height" << r.at(1);
|
||||
args << "--user-name" << info.user_name;
|
||||
args << "--user-id" << QString::number(info.user_id);
|
||||
args << "--present-mode" << EnumToText(info.present_mode);
|
||||
if (info.fullscreen_enabled) {
|
||||
args << "--fullscreen";
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/common.h"
|
||||
#include "common/emulatorConfig.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "common/threads.h"
|
||||
@@ -358,13 +359,12 @@ int KYTY_SYSV_ABI PadInit() {
|
||||
}
|
||||
|
||||
static bool PadOpenArgsAreValid(int user_id, int type, int index) {
|
||||
constexpr int user_id_initial = 1000;
|
||||
constexpr int user_id_system = 0xff;
|
||||
constexpr int port_type_standard = 0;
|
||||
constexpr int port_type_special = 2;
|
||||
constexpr int port_type_remote = 16;
|
||||
const bool personal_port =
|
||||
user_id == user_id_initial && (type == port_type_standard || type == port_type_special);
|
||||
user_id == Config::GetUserId() && (type == port_type_standard || type == port_type_special);
|
||||
const bool system_remote_control = user_id == user_id_system && type == port_type_remote;
|
||||
return index == 0 && (personal_port || system_remote_control);
|
||||
}
|
||||
|
||||
+5
-5
@@ -1,5 +1,6 @@
|
||||
#include "libs/dialog.h"
|
||||
|
||||
#include "common/emulatorConfig.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "libs/errno.h"
|
||||
@@ -41,7 +42,6 @@ constexpr int LOGIN_RESULT_OK = 0;
|
||||
constexpr int LOGIN_MODE_ALL_USERS = 0;
|
||||
constexpr int LOGIN_MODE_NOT_LOGGED_IN = 1;
|
||||
constexpr int LOGIN_USER_INVALID = -1;
|
||||
constexpr int LOGIN_USER_ID = 1000;
|
||||
|
||||
constexpr int LOGIN_ERROR_NOT_INITIALIZED = static_cast<int>(0x81340001u);
|
||||
constexpr int LOGIN_ERROR_ALREADY_INITIALIZED = static_cast<int>(0x81340002u);
|
||||
@@ -67,7 +67,7 @@ static_assert(sizeof(LoginDialogResult) == 16);
|
||||
static_assert(sizeof(LoginDialogParam) == 64);
|
||||
|
||||
static int g_login_status = LOGIN_STATUS_NONE;
|
||||
static int g_login_selected_user = LOGIN_USER_ID;
|
||||
static int g_login_selected_user = LOGIN_USER_INVALID;
|
||||
|
||||
int KYTY_SYSV_ABI LoginDialogInitialize() {
|
||||
PRINT_NAME();
|
||||
@@ -77,7 +77,7 @@ int KYTY_SYSV_ABI LoginDialogInitialize() {
|
||||
}
|
||||
|
||||
g_login_status = LOGIN_STATUS_INITIALIZED;
|
||||
g_login_selected_user = LOGIN_USER_ID;
|
||||
g_login_selected_user = Config::GetUserId();
|
||||
|
||||
return OK;
|
||||
}
|
||||
@@ -90,7 +90,7 @@ int KYTY_SYSV_ABI LoginDialogTerminate() {
|
||||
}
|
||||
|
||||
g_login_status = LOGIN_STATUS_NONE;
|
||||
g_login_selected_user = LOGIN_USER_ID;
|
||||
g_login_selected_user = LOGIN_USER_INVALID;
|
||||
|
||||
return OK;
|
||||
}
|
||||
@@ -112,7 +112,7 @@ int KYTY_SYSV_ABI LoginDialogOpen(const void* param) {
|
||||
}
|
||||
|
||||
g_login_selected_user =
|
||||
p->initial_focus != LOGIN_USER_INVALID ? p->initial_focus : LOGIN_USER_ID;
|
||||
p->initial_focus != LOGIN_USER_INVALID ? p->initial_focus : Config::GetUserId();
|
||||
|
||||
LOGF("\t size = %d\n"
|
||||
"\t mode = %d\n"
|
||||
|
||||
+1
-18
@@ -327,25 +327,8 @@ static KYTY_SYSV_ABI int setenv(const char* name, const char* value, int overwri
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (overwrite == 0 && std::getenv(name) != nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
||||
const auto ret = ::_putenv_s(name, value);
|
||||
if (ret != 0) {
|
||||
*Posix::GetErrorAddr() = ret;
|
||||
return -1;
|
||||
}
|
||||
// Guest environment changes must not leak into emulator host libraries.
|
||||
return 0;
|
||||
#else
|
||||
const auto ret = ::setenv(name, value, overwrite);
|
||||
if (ret != 0) {
|
||||
*Posix::GetErrorAddr() = errno;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int64_t libc_time(int64_t* timer) {
|
||||
|
||||
+16
-16
@@ -1,11 +1,10 @@
|
||||
#include "common/abi.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "common/emulatorConfig.h"
|
||||
#include "libs/errno.h"
|
||||
#include "libs/libs.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
|
||||
#include <cinttypes>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
@@ -57,7 +56,7 @@ static KYTY_SYSV_ABI int UserServiceGetInitialUser(int* user_id) {
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(user_id == nullptr);
|
||||
|
||||
*user_id = 1000;
|
||||
*user_id = Config::GetUserId();
|
||||
|
||||
return OK;
|
||||
}
|
||||
@@ -72,7 +71,7 @@ static KYTY_SYSV_ABI int UserServiceGetEvent(SceUserServiceEvent* event) {
|
||||
if (!logged_in) {
|
||||
logged_in = true;
|
||||
event->event_type = UserServiceEventTypeLogin;
|
||||
event->user_id = 1000;
|
||||
event->user_id = Config::GetUserId();
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -84,7 +83,7 @@ static KYTY_SYSV_ABI int UserServiceGetLoginUserIdList(UserServiceLoginUserIdLis
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(user_id_list == nullptr);
|
||||
|
||||
user_id_list->user_id[0] = 1000;
|
||||
user_id_list->user_id[0] = Config::GetUserId();
|
||||
user_id_list->user_id[1] = -1;
|
||||
user_id_list->user_id[2] = -1;
|
||||
user_id_list->user_id[3] = -1;
|
||||
@@ -93,10 +92,11 @@ static KYTY_SYSV_ABI int UserServiceGetLoginUserIdList(UserServiceLoginUserIdLis
|
||||
}
|
||||
|
||||
static KYTY_SYSV_ABI int UserServiceGetUserName(int user_id, char* name, size_t size) {
|
||||
EXIT_NOT_IMPLEMENTED(user_id != 1000);
|
||||
EXIT_NOT_IMPLEMENTED(user_id != Config::GetUserId());
|
||||
EXIT_NOT_IMPLEMENTED(size < 5);
|
||||
|
||||
int s = snprintf(name, size, "%s", "Kyty");
|
||||
const auto& user_name = Config::GetUserName();
|
||||
int s = snprintf(name, size, "%s", user_name.c_str());
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(static_cast<size_t>(s) >= size);
|
||||
|
||||
@@ -109,7 +109,7 @@ static KYTY_SYSV_ABI int UserServiceGetUserNumber(int user_id, int32_t* number)
|
||||
if (number == nullptr) {
|
||||
return USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (user_id != 1000) {
|
||||
if (user_id != Config::GetUserId()) {
|
||||
return USER_SERVICE_ERROR_NOT_LOGGED_IN;
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ static KYTY_SYSV_ABI int UserServiceGetGamePresets(int user_id, UserServiceGameP
|
||||
if (presets == nullptr) {
|
||||
return USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (user_id != 1000) {
|
||||
if (user_id != Config::GetUserId()) {
|
||||
return USER_SERVICE_ERROR_NOT_LOGGED_IN;
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ static KYTY_SYSV_ABI int UserServiceGetAccessibilityVibration(int user_id, int32
|
||||
if (vibration == nullptr) {
|
||||
return USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (user_id != 1000) {
|
||||
if (user_id != Config::GetUserId()) {
|
||||
return USER_SERVICE_ERROR_NOT_LOGGED_IN;
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ static KYTY_SYSV_ABI int UserServiceGetAccessibilityTriggerEffect(int user_
|
||||
if (trigger_effect == nullptr) {
|
||||
return USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (user_id != 1000) {
|
||||
if (user_id != Config::GetUserId()) {
|
||||
return USER_SERVICE_ERROR_NOT_LOGGED_IN;
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ static KYTY_SYSV_ABI int UserServiceGetAgeLevel(int user_id, uint32_t* age_level
|
||||
if (age_level == nullptr) {
|
||||
return USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (user_id != 1000) {
|
||||
if (user_id != Config::GetUserId()) {
|
||||
return USER_SERVICE_ERROR_NOT_LOGGED_IN;
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ static KYTY_SYSV_ABI int UserServiceGetAccessibilityChatTranscription(int u
|
||||
if (chat_transcription == nullptr) {
|
||||
return USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (user_id != 1000) {
|
||||
if (user_id != Config::GetUserId()) {
|
||||
return USER_SERVICE_ERROR_NOT_LOGGED_IN;
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ UserServiceGetAccessibilityPressAndHoldDelay(int user_id, int32_t* press_and_hol
|
||||
if (press_and_hold_delay == nullptr) {
|
||||
return USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (user_id != 1000) {
|
||||
if (user_id != Config::GetUserId()) {
|
||||
return USER_SERVICE_ERROR_NOT_LOGGED_IN;
|
||||
}
|
||||
|
||||
@@ -224,7 +224,7 @@ static KYTY_SYSV_ABI int UserServiceGetAccessibilityZoomEnabled(int user_id
|
||||
if (zoom_enabled == nullptr) {
|
||||
return USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (user_id != 1000) {
|
||||
if (user_id != Config::GetUserId()) {
|
||||
return USER_SERVICE_ERROR_NOT_LOGGED_IN;
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ static KYTY_SYSV_ABI int UserServiceGetAccessibilityZoomFollowFocus(int use
|
||||
if (zoom_follow_focus == nullptr) {
|
||||
return USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (user_id != 1000) {
|
||||
if (user_id != Config::GetUserId()) {
|
||||
return USER_SERVICE_ERROR_NOT_LOGGED_IN;
|
||||
}
|
||||
|
||||
|
||||
+73
-63
@@ -16,11 +16,6 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// POSIX uses plain int file descriptors for sockets; provide the Winsock spellings
|
||||
// the shared (non-guarded) code paths reference.
|
||||
using SOCKET = int;
|
||||
static constexpr SOCKET INVALID_SOCKET = -1;
|
||||
#endif
|
||||
|
||||
#include "common/assert.h"
|
||||
@@ -823,9 +818,11 @@ struct NetEtherAddr {
|
||||
#if defined(_WIN32)
|
||||
using NativeSocket = SOCKET;
|
||||
static constexpr NativeSocket INVALID_NATIVE_SOCKET = INVALID_SOCKET;
|
||||
using SocketLength = int;
|
||||
#else
|
||||
using NativeSocket = int;
|
||||
static constexpr NativeSocket INVALID_NATIVE_SOCKET = -1;
|
||||
using SocketLength = socklen_t;
|
||||
#endif
|
||||
|
||||
struct SocketSlot {
|
||||
@@ -898,7 +895,12 @@ static bool EnsureSocketBackend() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int SetPosixSocketError(int error) {
|
||||
static int SetGuestSocketError(int error) {
|
||||
*Posix::GetErrorAddr() = error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int SetHostSocketError(int error) {
|
||||
int posix_error = Posix::POSIX_EIO;
|
||||
#if defined(_WIN32)
|
||||
switch (error) {
|
||||
@@ -933,17 +935,31 @@ static int SetPosixSocketError(int error) {
|
||||
default: break;
|
||||
}
|
||||
#else
|
||||
posix_error = error;
|
||||
switch (error) {
|
||||
case EACCES: posix_error = Posix::POSIX_EACCES; break;
|
||||
case EADDRINUSE: posix_error = Posix::POSIX_EADDRINUSE; break;
|
||||
case EADDRNOTAVAIL: posix_error = Posix::POSIX_EADDRNOTAVAIL; break;
|
||||
case EAFNOSUPPORT: posix_error = Posix::POSIX_EAFNOSUPPORT; break;
|
||||
case EBADF: posix_error = Posix::POSIX_EBADF; break;
|
||||
case EFAULT: posix_error = Posix::POSIX_EFAULT; break;
|
||||
case EINVAL: posix_error = Posix::POSIX_EINVAL; break;
|
||||
case EMFILE: posix_error = Posix::POSIX_EMFILE; break;
|
||||
case ENFILE: posix_error = Posix::POSIX_ENFILE; break;
|
||||
case ENOBUFS: posix_error = Posix::POSIX_ENOBUFS; break;
|
||||
case ENOMEM: posix_error = Posix::POSIX_ENOMEM; break;
|
||||
case ENOTSOCK: posix_error = Posix::POSIX_ENOTSOCK; break;
|
||||
case EPROTONOSUPPORT: posix_error = Posix::POSIX_EPROTONOSUPPORT; break;
|
||||
default: break;
|
||||
}
|
||||
#endif
|
||||
*Posix::GetErrorAddr() = posix_error;
|
||||
return -1;
|
||||
return SetGuestSocketError(posix_error);
|
||||
}
|
||||
|
||||
static int SetPosixSocketError() {
|
||||
static int SetHostSocketError() {
|
||||
#if defined(_WIN32)
|
||||
return SetPosixSocketError(WSAGetLastError());
|
||||
return SetHostSocketError(WSAGetLastError());
|
||||
#else
|
||||
return SetPosixSocketError(errno);
|
||||
return SetHostSocketError(errno);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -991,9 +1007,8 @@ static int ConvertMessageFlags(int flags) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
static int ConvertGuestSockaddr(const void* addr, uint32_t addrlen, sockaddr_storage* out,
|
||||
int* out_len) {
|
||||
SocketLength* out_len) {
|
||||
EXIT_IF(out == nullptr);
|
||||
EXIT_IF(out_len == nullptr);
|
||||
|
||||
@@ -1028,6 +1043,7 @@ static int ConvertGuestSockaddr(const void* addr, uint32_t addrlen, sockaddr_sto
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
static int ConvertHostSockaddr(const sockaddr_storage* addr, int addrlen, void* out,
|
||||
uint32_t* out_len) {
|
||||
EXIT_IF(addr == nullptr);
|
||||
@@ -1364,7 +1380,7 @@ int KYTY_SYSV_ABI NetGetSockInfo(int s, void* info, int n, int flags) {
|
||||
|
||||
int KYTY_SYSV_ABI EpollCreate(const char* name, int flags) {
|
||||
if (name == nullptr || flags != 0) {
|
||||
return SetPosixSocketError(Posix::POSIX_EINVAL);
|
||||
return SetGuestSocketError(Posix::POSIX_EINVAL);
|
||||
}
|
||||
|
||||
std::lock_guard lock(g_epoll_mutex);
|
||||
@@ -1378,7 +1394,7 @@ int KYTY_SYSV_ABI EpollCreate(const char* name, int flags) {
|
||||
}
|
||||
}
|
||||
|
||||
return SetPosixSocketError(Posix::POSIX_EMFILE);
|
||||
return SetGuestSocketError(Posix::POSIX_EMFILE);
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI EpollControl(int eid, int op, int id, const NetEpollEvent* event) {
|
||||
@@ -1387,22 +1403,22 @@ int KYTY_SYSV_ABI EpollControl(int eid, int op, int id, const NetEpollEvent* eve
|
||||
constexpr int EPOLL_CTL_DEL = 3;
|
||||
|
||||
if ((op == EPOLL_CTL_ADD || op == EPOLL_CTL_MOD) && event == nullptr) {
|
||||
return SetPosixSocketError(Posix::POSIX_EINVAL);
|
||||
return SetGuestSocketError(Posix::POSIX_EINVAL);
|
||||
}
|
||||
if (op == EPOLL_CTL_DEL && event != nullptr) {
|
||||
return SetPosixSocketError(Posix::POSIX_EINVAL);
|
||||
return SetGuestSocketError(Posix::POSIX_EINVAL);
|
||||
}
|
||||
if (op < EPOLL_CTL_ADD || op > EPOLL_CTL_DEL) {
|
||||
return SetPosixSocketError(Posix::POSIX_EINVAL);
|
||||
return SetGuestSocketError(Posix::POSIX_EINVAL);
|
||||
}
|
||||
if (!IsSocket(id)) {
|
||||
return SetPosixSocketError(Posix::POSIX_EBADF);
|
||||
return SetGuestSocketError(Posix::POSIX_EBADF);
|
||||
}
|
||||
|
||||
std::lock_guard lock(g_epoll_mutex);
|
||||
auto* slot = GetEpollSlot(eid);
|
||||
if (slot == nullptr) {
|
||||
return SetPosixSocketError(Posix::POSIX_EBADF);
|
||||
return SetGuestSocketError(Posix::POSIX_EBADF);
|
||||
}
|
||||
|
||||
auto registration = std::find_if(slot->registrations.begin(), slot->registrations.end(),
|
||||
@@ -1410,19 +1426,19 @@ int KYTY_SYSV_ABI EpollControl(int eid, int op, int id, const NetEpollEvent* eve
|
||||
switch (op) {
|
||||
case EPOLL_CTL_ADD:
|
||||
if (registration != slot->registrations.end()) {
|
||||
return SetPosixSocketError(Posix::POSIX_EEXIST);
|
||||
return SetGuestSocketError(Posix::POSIX_EEXIST);
|
||||
}
|
||||
slot->registrations.push_back({id, *event});
|
||||
break;
|
||||
case EPOLL_CTL_MOD:
|
||||
if (registration == slot->registrations.end()) {
|
||||
return SetPosixSocketError(Posix::POSIX_ENOENT);
|
||||
return SetGuestSocketError(Posix::POSIX_ENOENT);
|
||||
}
|
||||
registration->event = *event;
|
||||
break;
|
||||
case EPOLL_CTL_DEL:
|
||||
if (registration == slot->registrations.end()) {
|
||||
return SetPosixSocketError(Posix::POSIX_ENOENT);
|
||||
return SetGuestSocketError(Posix::POSIX_ENOENT);
|
||||
}
|
||||
slot->registrations.erase(registration);
|
||||
break;
|
||||
@@ -1435,10 +1451,10 @@ int KYTY_SYSV_ABI EpollControl(int eid, int op, int id, const NetEpollEvent* eve
|
||||
|
||||
int KYTY_SYSV_ABI EpollWait(int eid, NetEpollEvent* events, int maxevents, int timeout) {
|
||||
if (events == nullptr) {
|
||||
return SetPosixSocketError(Posix::POSIX_EFAULT);
|
||||
return SetGuestSocketError(Posix::POSIX_EFAULT);
|
||||
}
|
||||
if (maxevents <= 0 || timeout < -1) {
|
||||
return SetPosixSocketError(Posix::POSIX_EINVAL);
|
||||
return SetGuestSocketError(Posix::POSIX_EINVAL);
|
||||
}
|
||||
|
||||
std::vector<EpollRegistration> registrations;
|
||||
@@ -1446,7 +1462,7 @@ int KYTY_SYSV_ABI EpollWait(int eid, NetEpollEvent* events, int maxevents, int t
|
||||
std::unique_lock lock(g_epoll_mutex);
|
||||
auto* slot = GetEpollSlot(eid);
|
||||
if (slot == nullptr) {
|
||||
return SetPosixSocketError(Posix::POSIX_EBADF);
|
||||
return SetGuestSocketError(Posix::POSIX_EBADF);
|
||||
}
|
||||
|
||||
if (slot->registrations.empty() && timeout != 0) {
|
||||
@@ -1461,7 +1477,7 @@ int KYTY_SYSV_ABI EpollWait(int eid, NetEpollEvent* events, int maxevents, int t
|
||||
}
|
||||
slot = GetEpollSlot(eid);
|
||||
if (slot == nullptr) {
|
||||
return SetPosixSocketError(Posix::POSIX_EBADF);
|
||||
return SetGuestSocketError(Posix::POSIX_EBADF);
|
||||
}
|
||||
}
|
||||
registrations = slot->registrations;
|
||||
@@ -1492,7 +1508,7 @@ int KYTY_SYSV_ABI EpollWait(int eid, NetEpollEvent* events, int maxevents, int t
|
||||
continue;
|
||||
}
|
||||
if (host_registrations.size() >= FD_SETSIZE) {
|
||||
return SetPosixSocketError(Posix::POSIX_EINVAL);
|
||||
return SetGuestSocketError(Posix::POSIX_EINVAL);
|
||||
}
|
||||
if ((registration.event.events & EPOLL_IN) != 0) {
|
||||
FD_SET(socket, &host_read);
|
||||
@@ -1518,7 +1534,7 @@ int KYTY_SYSV_ABI EpollWait(int eid, NetEpollEvent* events, int maxevents, int t
|
||||
|
||||
const int result = ::select(0, &host_read, &host_write, &host_except, host_timeout_ptr);
|
||||
if (result == SOCKET_ERROR) {
|
||||
return SetPosixSocketError();
|
||||
return SetHostSocketError();
|
||||
}
|
||||
if (result == 0) {
|
||||
return 0;
|
||||
@@ -1552,7 +1568,7 @@ int KYTY_SYSV_ABI EpollWait(int eid, NetEpollEvent* events, int maxevents, int t
|
||||
return count;
|
||||
#else
|
||||
(void)timeout;
|
||||
return SetPosixSocketError(Posix::POSIX_ENOSYS);
|
||||
return SetGuestSocketError(Posix::POSIX_ENOSYS);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1560,7 +1576,7 @@ int KYTY_SYSV_ABI EpollDestroy(int eid) {
|
||||
std::lock_guard lock(g_epoll_mutex);
|
||||
auto* slot = GetEpollSlot(eid);
|
||||
if (slot == nullptr) {
|
||||
return SetPosixSocketError(Posix::POSIX_EBADF);
|
||||
return SetGuestSocketError(Posix::POSIX_EBADF);
|
||||
}
|
||||
|
||||
slot->used = false;
|
||||
@@ -1582,14 +1598,15 @@ int KYTY_SYSV_ABI SocketClose(int s) {
|
||||
RemoveSocketFromEpolls(s);
|
||||
|
||||
#if defined(_WIN32)
|
||||
if (closesocket(socket) == SOCKET_ERROR) {
|
||||
const int result = closesocket(socket);
|
||||
#else
|
||||
const int result = ::close(socket);
|
||||
#endif
|
||||
if (result != 0) {
|
||||
return NET_ERROR_EBADF;
|
||||
}
|
||||
|
||||
return OK;
|
||||
#else
|
||||
return NET_ERROR_ENOSYS;
|
||||
#endif
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI Socket(int family, int type, int protocol) {
|
||||
@@ -1601,7 +1618,7 @@ int KYTY_SYSV_ABI Socket(int family, int type, int protocol) {
|
||||
family, type, protocol);
|
||||
|
||||
if (!EnsureSocketBackend()) {
|
||||
return SetPosixSocketError(Posix::POSIX_ENETDOWN);
|
||||
return SetGuestSocketError(Posix::POSIX_ENETDOWN);
|
||||
}
|
||||
|
||||
const int host_family = ConvertFamily(family);
|
||||
@@ -1610,25 +1627,24 @@ int KYTY_SYSV_ABI Socket(int family, int type, int protocol) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
NativeSocket socket = ::socket(host_family, type, protocol);
|
||||
if (socket == INVALID_NATIVE_SOCKET) {
|
||||
return SetPosixSocketError();
|
||||
return SetHostSocketError();
|
||||
}
|
||||
|
||||
const int fd = AllocSocketFd(socket);
|
||||
if (fd < 0) {
|
||||
#if defined(_WIN32)
|
||||
closesocket(socket);
|
||||
#else
|
||||
::close(socket);
|
||||
#endif
|
||||
*Posix::GetErrorAddr() = Posix::POSIX_EMFILE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOGF("\t fd = %d\n", fd);
|
||||
return fd;
|
||||
#else
|
||||
*Posix::GetErrorAddr() = Posix::POSIX_ENOSYS;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI Bind(int s, const void* addr, uint32_t addrlen) {
|
||||
@@ -1645,23 +1661,17 @@ int KYTY_SYSV_ABI Bind(int s, const void* addr, uint32_t addrlen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
sockaddr_storage host_addr {};
|
||||
int host_addrlen = 0;
|
||||
SocketLength host_addrlen = 0;
|
||||
if (ConvertGuestSockaddr(addr, addrlen, &host_addr, &host_addrlen) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (::bind(socket, reinterpret_cast<const sockaddr*>(&host_addr), host_addrlen) ==
|
||||
SOCKET_ERROR) {
|
||||
return SetPosixSocketError();
|
||||
if (::bind(socket, reinterpret_cast<const sockaddr*>(&host_addr), host_addrlen) != 0) {
|
||||
return SetHostSocketError();
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else
|
||||
*Posix::GetErrorAddr() = Posix::POSIX_ENOSYS;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI Connect(int s, const void* addr, uint32_t addrlen) {
|
||||
@@ -1687,7 +1697,7 @@ int KYTY_SYSV_ABI Connect(int s, const void* addr, uint32_t addrlen) {
|
||||
|
||||
if (::connect(socket, reinterpret_cast<const sockaddr*>(&host_addr), host_addrlen) ==
|
||||
SOCKET_ERROR) {
|
||||
return SetPosixSocketError();
|
||||
return SetHostSocketError();
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1712,7 +1722,7 @@ int KYTY_SYSV_ABI Listen(int s, int backlog) {
|
||||
|
||||
#if defined(_WIN32)
|
||||
if (::listen(socket, backlog) == SOCKET_ERROR) {
|
||||
return SetPosixSocketError();
|
||||
return SetHostSocketError();
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1742,7 +1752,7 @@ int KYTY_SYSV_ABI Accept(int s, void* addr, uint32_t* addrlen) {
|
||||
NativeSocket accepted =
|
||||
::accept(socket, reinterpret_cast<sockaddr*>(&host_addr), &host_addrlen);
|
||||
if (accepted == INVALID_NATIVE_SOCKET) {
|
||||
return SetPosixSocketError();
|
||||
return SetHostSocketError();
|
||||
}
|
||||
|
||||
const int fd = AllocSocketFd(accepted);
|
||||
@@ -1791,7 +1801,7 @@ int KYTY_SYSV_ABI Shutdown(int s, int how) {
|
||||
|
||||
#if defined(_WIN32)
|
||||
if (::shutdown(socket, how) == SOCKET_ERROR) {
|
||||
return SetPosixSocketError();
|
||||
return SetHostSocketError();
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1821,7 +1831,7 @@ int KYTY_SYSV_ABI Getsockname(int s, void* addr, uint32_t* addrlen) {
|
||||
int host_addrlen = sizeof(host_addr);
|
||||
if (::getsockname(socket, reinterpret_cast<sockaddr*>(&host_addr), &host_addrlen) ==
|
||||
SOCKET_ERROR) {
|
||||
return SetPosixSocketError();
|
||||
return SetHostSocketError();
|
||||
}
|
||||
|
||||
return ConvertHostSockaddr(&host_addr, host_addrlen, addr, addrlen);
|
||||
@@ -1850,7 +1860,7 @@ int KYTY_SYSV_ABI Getsockopt(int s, int level, int optname, void* optval, uint32
|
||||
int len = static_cast<int>(*optlen);
|
||||
if (::getsockopt(socket, ConvertSocketOptionLevel(level), optname, static_cast<char*>(optval),
|
||||
&len) == SOCKET_ERROR) {
|
||||
return SetPosixSocketError();
|
||||
return SetHostSocketError();
|
||||
}
|
||||
*optlen = static_cast<uint32_t>(len);
|
||||
return 0;
|
||||
@@ -1881,14 +1891,14 @@ int KYTY_SYSV_ABI Setsockopt(int s, int level, int optname, const void* optval,
|
||||
optlen >= sizeof(int)) {
|
||||
u_long enabled = (*static_cast<const int*>(optval) != 0 ? 1 : 0);
|
||||
if (ioctlsocket(socket, FIONBIO, &enabled) == SOCKET_ERROR) {
|
||||
return SetPosixSocketError();
|
||||
return SetHostSocketError();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (::setsockopt(socket, ConvertSocketOptionLevel(level), optname,
|
||||
static_cast<const char*>(optval), static_cast<int>(optlen)) == SOCKET_ERROR) {
|
||||
return SetPosixSocketError();
|
||||
return SetHostSocketError();
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1941,7 +1951,7 @@ int64_t KYTY_SYSV_ABI Sendto(int s, const void* buf, uint64_t len, int flags, co
|
||||
reinterpret_cast<const sockaddr*>(&host_addr), host_addrlen);
|
||||
}
|
||||
if (result == SOCKET_ERROR) {
|
||||
return SetPosixSocketError();
|
||||
return SetHostSocketError();
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -2000,7 +2010,7 @@ int64_t KYTY_SYSV_ABI Recvfrom(int s, void* buf, uint64_t len, int flags, void*
|
||||
}
|
||||
}
|
||||
if (result == SOCKET_ERROR) {
|
||||
return SetPosixSocketError();
|
||||
return SetHostSocketError();
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -2101,7 +2111,7 @@ int KYTY_SYSV_ABI Select(int nfds, void* readfds, void* writefds, void* exceptfd
|
||||
|
||||
const int result = ::select(0, read_ptr, write_ptr, except_ptr, host_timeout_ptr);
|
||||
if (result == SOCKET_ERROR) {
|
||||
return SetPosixSocketError();
|
||||
return SetHostSocketError();
|
||||
}
|
||||
|
||||
GuestFdZero(readfds, nfds);
|
||||
|
||||
@@ -47,6 +47,11 @@ static void PrintUsage() {
|
||||
" --game-patch <json> Validated patch plan to apply before entry.\n");
|
||||
::printf(" --screen-width <num> Window width. Default: 1280.\n");
|
||||
::printf(" --screen-height <num> Window height. Default: 720.\n");
|
||||
::printf(
|
||||
" --user-name <name> Local user name (1-16 bytes). Default: Kyty.\n");
|
||||
::printf(" --user-id <num> Local user ID. Default: %d.\n",
|
||||
Config::DEFAULT_USER_ID);
|
||||
::printf(" --present-mode <value> Fifo, Mailbox, or Immediate. Default: Fifo.\n");
|
||||
::printf(" --fullscreen Run in borderless desktop fullscreen.\n");
|
||||
::printf(" --vblank-frequency <num> Virtual vblank frequency. Default: 60.\n");
|
||||
::printf(" --console-language <0-29> Console language. Default: 1 (English US).\n");
|
||||
@@ -122,6 +127,17 @@ static bool ParseConsoleLanguage(const std::string& value, uint32_t& out) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ParseUserId(const std::string& value, int32_t& out) {
|
||||
int32_t user_id = 0;
|
||||
auto [end, error] = std::from_chars(value.data(), value.data() + value.size(), user_id);
|
||||
if (error != std::errc {} || end != value.data() + value.size() ||
|
||||
!Config::IsConfiguredUserIdValid(user_id)) {
|
||||
return false;
|
||||
}
|
||||
out = user_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ParseArgs(int argc, char* argv[], RunOptions& options, bool& show_help) {
|
||||
show_help = false;
|
||||
|
||||
@@ -201,6 +217,23 @@ static bool ParseArgs(int argc, char* argv[], RunOptions& options, bool& show_he
|
||||
options.config.screen_width = static_cast<uint32_t>(Common::ToInt32(value));
|
||||
} else if (arg == "--screen-height") {
|
||||
options.config.screen_height = static_cast<uint32_t>(Common::ToInt32(value));
|
||||
} else if (arg == "--user-name") {
|
||||
if (value.empty() || value.size() > Config::MAX_USER_NAME_LENGTH) {
|
||||
::printf("invalid user name: must contain 1-%zu bytes\n",
|
||||
Config::MAX_USER_NAME_LENGTH);
|
||||
return false;
|
||||
}
|
||||
options.config.user_name = value;
|
||||
} else if (arg == "--user-id") {
|
||||
if (!ParseUserId(value, options.config.user_id)) {
|
||||
::printf("invalid user ID: %s\n", value.c_str());
|
||||
return false;
|
||||
}
|
||||
} else if (arg == "--present-mode") {
|
||||
if (!ParseEnum(value, options.config.present_mode)) {
|
||||
::printf("invalid present mode: %s\n", value.c_str());
|
||||
return false;
|
||||
}
|
||||
} else if (arg == "--vblank-frequency") {
|
||||
const int32_t vblank_frequency = Common::ToInt32(value);
|
||||
options.config.vblank_frequency =
|
||||
|
||||
Reference in New Issue
Block a user