mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-04-01 18:40:57 -06:00
Merge branch 'shadps4-emu:main' into IRQv5
This commit is contained in:
commit
ed87ea4d0d
3
.gitignore
vendored
3
.gitignore
vendored
@ -418,3 +418,6 @@ FodyWeavers.xsd
|
||||
# JetBrains
|
||||
.idea
|
||||
cmake-build-*
|
||||
|
||||
# Nix Result symlink
|
||||
result
|
||||
|
||||
@ -245,7 +245,7 @@ find_package(VulkanMemoryAllocator 3.1.0 CONFIG)
|
||||
find_package(xbyak 7.07 CONFIG)
|
||||
find_package(xxHash 0.8.2 MODULE)
|
||||
find_package(ZLIB 1.3 MODULE)
|
||||
find_package(Zydis 5.0.0 CONFIG)
|
||||
find_package(Zydis 5.0.0 MODULE)
|
||||
find_package(pugixml 1.14 CONFIG)
|
||||
if (APPLE)
|
||||
find_package(date 3.0.1 CONFIG)
|
||||
@ -1091,6 +1091,8 @@ set(IMGUI src/imgui/imgui_config.h
|
||||
src/imgui/imgui_layer.h
|
||||
src/imgui/imgui_std.h
|
||||
src/imgui/imgui_texture.h
|
||||
src/imgui/imgui_translations.cpp
|
||||
src/imgui/imgui_translations.h
|
||||
src/imgui/renderer/imgui_core.cpp
|
||||
src/imgui/renderer/imgui_core.h
|
||||
src/imgui/renderer/imgui_impl_sdl3.cpp
|
||||
@ -1137,7 +1139,14 @@ create_target_directory_groups(shadps4)
|
||||
|
||||
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui gcn half::half ZLIB::ZLIB PNG::PNG)
|
||||
target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator LibAtrac9 sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::glslang SDL3::SDL3 SDL3_mixer::SDL3_mixer pugixml::pugixml)
|
||||
target_link_libraries(shadps4 PRIVATE stb::headers libusb::usb lfreist-hwinfo::hwinfo nlohmann_json::nlohmann_json miniz::miniz fdk-aac CLI11::CLI11 OpenAL::OpenAL Cpp_Httplib)
|
||||
target_link_libraries(shadps4 PRIVATE stb::headers lfreist-hwinfo::hwinfo nlohmann_json::nlohmann_json miniz::miniz fdk-aac CLI11::CLI11 OpenAL::OpenAL Cpp_Httplib)
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||
target_link_libraries(shadps4 PRIVATE "/usr/lib/libusb.so")
|
||||
target_link_libraries(shadps4 PRIVATE "/usr/local/lib/libuuid.so")
|
||||
else()
|
||||
target_link_libraries(shadps4 PRIVATE libusb::usb)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(shadps4 PRIVATE IMGUI_USER_CONFIG="imgui/imgui_config.h")
|
||||
target_compile_definitions(Dear_ImGui PRIVATE IMGUI_USER_CONFIG="${PROJECT_SOURCE_DIR}/src/imgui/imgui_config.h")
|
||||
@ -1183,6 +1192,8 @@ if (APPLE)
|
||||
|
||||
# Replacement for std::chrono::time_zone
|
||||
target_link_libraries(shadps4 PRIVATE date::date-tz epoll-shim)
|
||||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||
target_link_libraries(shadps4 PRIVATE date::date-tz epoll-shim)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
@ -1274,4 +1285,4 @@ install(TARGETS shadps4 BUNDLE DESTINATION .)
|
||||
else()
|
||||
enable_testing()
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -22,6 +22,7 @@ path = [
|
||||
"documents/Screenshots/Linux/*",
|
||||
"documents/Screenshots/Windows/*",
|
||||
"externals/MoltenVK/MoltenVK_icd.json",
|
||||
"flake.lock",
|
||||
"scripts/ps4_names.txt",
|
||||
"src/images/bronze.png",
|
||||
"src/images/gold.png",
|
||||
@ -130,4 +131,4 @@ SPDX-License-Identifier = "MIT"
|
||||
[[annotations]]
|
||||
path = "src/video_core/host_shaders/fsr/*"
|
||||
SPDX-FileCopyrightText = "Copyright (c) 2021 Advanced Micro Devices, Inc. All rights reserved."
|
||||
SPDX-License-Identifier = "MIT"
|
||||
SPDX-License-Identifier = "MIT"
|
||||
|
||||
@ -53,6 +53,23 @@ sudo zypper install clang git cmake libasound2 libpulse-devel \
|
||||
nix-shell shell.nix
|
||||
```
|
||||
|
||||
#### Nix Flake Development Shell
|
||||
```bash
|
||||
nix develop
|
||||
cmake -S . -B build/ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
||||
ln -s ./build/compile_commands.json .
|
||||
```
|
||||
|
||||
#### Nix Flake Build
|
||||
```bash
|
||||
nix build .?submodules=1#linux.debug
|
||||
```
|
||||
```bash
|
||||
nix build .?submodules=1#linux.release
|
||||
```
|
||||
```bash
|
||||
nix build .?submodules=1#linux.releaseWithDebugInfo
|
||||
```
|
||||
#### Other Linux distributions
|
||||
|
||||
You can try one of two methods:
|
||||
|
||||
24
externals/CMakeLists.txt
vendored
24
externals/CMakeLists.txt
vendored
@ -210,8 +210,15 @@ endif()
|
||||
|
||||
# libusb
|
||||
if (NOT TARGET libusb::usb)
|
||||
add_subdirectory(ext-libusb)
|
||||
add_library(libusb::usb ALIAS usb-1.0)
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||
# YOU MUST USE NATIVE LIBUSB
|
||||
# using anything else will crash instantly, also freebsd will NOT like it
|
||||
# no you cant vendor this libusb, its builtin on freebsd
|
||||
find_package(libusb)
|
||||
else()
|
||||
add_subdirectory(ext-libusb)
|
||||
add_library(libusb::usb ALIAS usb-1.0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Discord RPC
|
||||
@ -233,25 +240,26 @@ endif()
|
||||
set(HWINFO_STATIC ON)
|
||||
add_subdirectory(hwinfo)
|
||||
|
||||
# Apple-only dependencies
|
||||
if (APPLE)
|
||||
if (APPLE OR ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||
# date
|
||||
if (NOT TARGET date::date-tz)
|
||||
option(BUILD_TZ_LIB "" ON)
|
||||
option(USE_SYSTEM_TZ_DB "" ON)
|
||||
add_subdirectory(date)
|
||||
endif()
|
||||
if (NOT TARGET epoll-shim)
|
||||
add_subdirectory(epoll-shim)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Apple-only dependencies
|
||||
if (APPLE)
|
||||
# MoltenVK
|
||||
if (NOT TARGET MoltenVK)
|
||||
set(MVK_EXCLUDE_SPIRV_TOOLS ON)
|
||||
set(MVK_USE_METAL_PRIVATE_API ON)
|
||||
add_subdirectory(MoltenVK)
|
||||
endif()
|
||||
|
||||
if (NOT TARGET epoll-shim)
|
||||
add_subdirectory(epoll-shim)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#windows only
|
||||
|
||||
27
flake.lock
generated
Normal file
27
flake.lock
generated
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1774386573,
|
||||
"narHash": "sha256-4hAV26quOxdC6iyG7kYaZcM3VOskcPUrdCQd/nx8obc=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "46db2e09e1d3f113a13c0d7b81e2f221c63b8ce9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
160
flake.nix
Normal file
160
flake.nix
Normal file
@ -0,0 +1,160 @@
|
||||
## SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project
|
||||
## SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
{
|
||||
description = "shadPS4 Nix Flake";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
|
||||
};
|
||||
|
||||
outputs =
|
||||
{ self, nixpkgs }:
|
||||
let
|
||||
pkgsLinux = nixpkgs.legacyPackages.x86_64-linux;
|
||||
in
|
||||
{
|
||||
devShells.x86_64-linux.default = pkgsLinux.mkShell.override { stdenv = pkgsLinux.clangStdenv; } {
|
||||
packages = with pkgsLinux; [
|
||||
clang-tools
|
||||
cmake
|
||||
pkg-config
|
||||
vulkan-tools
|
||||
|
||||
renderdoc
|
||||
gef
|
||||
strace
|
||||
|
||||
openal
|
||||
zlib.dev
|
||||
libedit.dev
|
||||
vulkan-headers
|
||||
vulkan-utility-libraries
|
||||
ffmpeg.dev
|
||||
fmt.dev
|
||||
glslang.dev
|
||||
wayland.dev
|
||||
stb
|
||||
libpng.dev
|
||||
libuuid
|
||||
|
||||
sdl3.dev
|
||||
alsa-lib
|
||||
hidapi
|
||||
ibus.dev
|
||||
jack2.dev
|
||||
libdecor.dev
|
||||
libthai.dev
|
||||
fribidi.dev
|
||||
libxcb.dev
|
||||
libGL.dev
|
||||
libpulseaudio.dev
|
||||
libusb1.dev
|
||||
libx11.dev
|
||||
libxcursor.dev
|
||||
libxext
|
||||
libxfixes.dev
|
||||
libxi.dev
|
||||
libxinerama.dev
|
||||
libxkbcommon
|
||||
libxrandr.dev
|
||||
libxrender.dev
|
||||
libxtst
|
||||
pipewire.dev
|
||||
libxscrnsaver
|
||||
sndio
|
||||
];
|
||||
shellHook = ''
|
||||
echo "Entering shadPS4 development shell!"
|
||||
'';
|
||||
};
|
||||
|
||||
linux =
|
||||
let
|
||||
execName = "shadps4";
|
||||
nativeInputs = with pkgsLinux; [
|
||||
cmake
|
||||
ninja
|
||||
pkg-config
|
||||
magic-enum
|
||||
fmt
|
||||
eudev
|
||||
];
|
||||
buildInputs = with pkgsLinux; [
|
||||
boost
|
||||
cli11
|
||||
openal
|
||||
nlohmann_json
|
||||
vulkan-loader
|
||||
vulkan-headers
|
||||
vulkan-memory-allocator
|
||||
toml11
|
||||
zlib
|
||||
zydis
|
||||
pugixml
|
||||
ffmpeg
|
||||
libpulseaudio
|
||||
pipewire
|
||||
vulkan-loader
|
||||
wayland
|
||||
wayland-scanner
|
||||
libX11
|
||||
libxrandr
|
||||
libxext
|
||||
libxcursor
|
||||
libxi
|
||||
libxscrnsaver
|
||||
libxtst
|
||||
libxcb
|
||||
libdecor
|
||||
libxkbcommon
|
||||
libGL
|
||||
libuuid
|
||||
];
|
||||
|
||||
defaultFlags = [
|
||||
"-DCMAKE_INSTALL_PREFIX=$out"
|
||||
];
|
||||
in
|
||||
{
|
||||
debug = pkgsLinux.stdenv.mkDerivation {
|
||||
pname = "${execName}";
|
||||
version = "git";
|
||||
system = "x86_64-linux";
|
||||
src = ./.;
|
||||
dontStrip = true;
|
||||
|
||||
nativeBuildInputs = nativeInputs;
|
||||
buildInputs = buildInputs;
|
||||
cmakeFlags = [
|
||||
"-DCMAKE_BUILD_TYPE=Debug"
|
||||
] ++ [defaultFlags];
|
||||
};
|
||||
release = pkgsLinux.stdenv.mkDerivation {
|
||||
pname = "${execName}";
|
||||
version = "git";
|
||||
system = "x86_64-linux";
|
||||
src = ./.;
|
||||
|
||||
nativeBuildInputs = nativeInputs;
|
||||
buildInputs = buildInputs;
|
||||
cmakeFlags = [
|
||||
"-DCMAKE_BUILD_TYPE=Release"
|
||||
] ++ [defaultFlags];
|
||||
};
|
||||
releaseWithDebugInfo = pkgsLinux.stdenv.mkDerivation {
|
||||
pname = "${execName}";
|
||||
version = "git";
|
||||
system = "x86_64-linux";
|
||||
src = ./.;
|
||||
dontStrip = true;
|
||||
|
||||
nativeBuildInputs = nativeInputs;
|
||||
buildInputs = buildInputs;
|
||||
cmakeFlags = [
|
||||
"-DCMAKE_BUILD_TYPE=Release"
|
||||
] ++ [defaultFlags];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __linux__
|
||||
#if __unix__
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
|
||||
@ -7,6 +7,9 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <machine/npx.h>
|
||||
#include <sys/ucontext.h>
|
||||
#else
|
||||
#include <sys/ucontext.h>
|
||||
#endif
|
||||
@ -22,6 +25,16 @@ void* GetXmmPointer(void* ctx, u8 index) {
|
||||
#define CASE(index) \
|
||||
case index: \
|
||||
return (void*)(&((ucontext_t*)ctx)->uc_mcontext->__fs.__fpu_xmm##index);
|
||||
#elif defined(__FreeBSD__)
|
||||
// In mc_fpstate
|
||||
// See <machine/npx.h> for the internals of mc_fpstate[].
|
||||
#define CASE(index) \
|
||||
case index: { \
|
||||
auto& mctx = ((ucontext_t*)ctx)->uc_mcontext; \
|
||||
ASSERT(mctx.mc_fpformat == _MC_FPFMT_XMM); \
|
||||
auto* s_fpu = (struct savefpu*)(&mctx.mc_fpstate[0]); \
|
||||
return (void*)(&(s_fpu->sv_xmm[0])); \
|
||||
}
|
||||
#else
|
||||
#define CASE(index) \
|
||||
case index: \
|
||||
@ -57,6 +70,8 @@ void* GetRip(void* ctx) {
|
||||
return (void*)((EXCEPTION_POINTERS*)ctx)->ContextRecord->Rip;
|
||||
#elif defined(__APPLE__)
|
||||
return (void*)((ucontext_t*)ctx)->uc_mcontext->__ss.__rip;
|
||||
#elif defined(__FreeBSD__)
|
||||
return (void*)((ucontext_t*)ctx)->uc_mcontext.mc_rip;
|
||||
#else
|
||||
return (void*)((ucontext_t*)ctx)->uc_mcontext.gregs[REG_RIP];
|
||||
#endif
|
||||
@ -67,6 +82,8 @@ void IncrementRip(void* ctx, u64 length) {
|
||||
((EXCEPTION_POINTERS*)ctx)->ContextRecord->Rip += length;
|
||||
#elif defined(__APPLE__)
|
||||
((ucontext_t*)ctx)->uc_mcontext->__ss.__rip += length;
|
||||
#elif defined(__FreeBSD__)
|
||||
((ucontext_t*)ctx)->uc_mcontext.mc_rip += length;
|
||||
#else
|
||||
((ucontext_t*)ctx)->uc_mcontext.gregs[REG_RIP] += length;
|
||||
#endif
|
||||
@ -75,18 +92,16 @@ void IncrementRip(void* ctx, u64 length) {
|
||||
bool IsWriteError(void* ctx) {
|
||||
#if defined(_WIN32)
|
||||
return ((EXCEPTION_POINTERS*)ctx)->ExceptionRecord->ExceptionInformation[0] == 1;
|
||||
#elif defined(__APPLE__)
|
||||
#if defined(ARCH_X86_64)
|
||||
#elif defined(__APPLE__) && defined(ARCH_X86_64)
|
||||
return ((ucontext_t*)ctx)->uc_mcontext->__es.__err & 0x2;
|
||||
#elif defined(ARCH_ARM64)
|
||||
#elif defined(__APPLE__) && defined(ARCH_ARM64)
|
||||
return ((ucontext_t*)ctx)->uc_mcontext->__es.__esr & 0x40;
|
||||
#endif
|
||||
#else
|
||||
#if defined(ARCH_X86_64)
|
||||
#elif defined(__FreeBSD__) && defined(ARCH_X86_64)
|
||||
return ((ucontext_t*)ctx)->uc_mcontext.mc_err & 0x2;
|
||||
#elif defined(ARCH_X86_64)
|
||||
return ((ucontext_t*)ctx)->uc_mcontext.gregs[REG_ERR] & 0x2;
|
||||
#else
|
||||
#error "Unsupported architecture"
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
} // namespace Common
|
||||
} // namespace Common
|
||||
|
||||
@ -613,7 +613,11 @@ struct AddressSpace::Impl {
|
||||
user_size = UserSize;
|
||||
|
||||
constexpr int protection_flags = PROT_READ | PROT_WRITE;
|
||||
constexpr int map_flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED;
|
||||
int map_flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED; // compiler knows its constexpr
|
||||
#if !defined(__FreeBSD__)
|
||||
map_flags |= MAP_NORESERVE;
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) && defined(ARCH_X86_64)
|
||||
// On ARM64 Macs, we run into limitations due to the commpage from 0xFC0000000 - 0xFFFFFFFFF
|
||||
// and the GPU carveout region from 0x1000000000 - 0x6FFFFFFFFF. Because this creates gaps
|
||||
@ -628,7 +632,7 @@ struct AddressSpace::Impl {
|
||||
mmap(reinterpret_cast<void*>(USER_MIN), user_size, protection_flags, map_flags, -1, 0));
|
||||
#else
|
||||
const auto virtual_size = system_managed_size + system_reserved_size + user_size;
|
||||
#if defined(ARCH_X86_64)
|
||||
#if defined(ARCH_X86_64) && !defined(__FreeBSD__)
|
||||
const auto virtual_base =
|
||||
reinterpret_cast<u8*>(mmap(reinterpret_cast<void*>(SYSTEM_MANAGED_MIN), virtual_size,
|
||||
protection_flags, map_flags, -1, 0));
|
||||
@ -636,8 +640,10 @@ struct AddressSpace::Impl {
|
||||
system_reserved_base = reinterpret_cast<u8*>(SYSTEM_RESERVED_MIN);
|
||||
user_base = reinterpret_cast<u8*>(USER_MIN);
|
||||
#else
|
||||
// FreeBSD can't stand MAP_FIXED or it may overwrite mmap() itself!
|
||||
// Map memory wherever possible and instruction translation can handle offsetting to the
|
||||
// base.
|
||||
map_flags &= ~MAP_FIXED;
|
||||
const auto virtual_base =
|
||||
reinterpret_cast<u8*>(mmap(nullptr, virtual_size, protection_flags, map_flags, -1, 0));
|
||||
system_managed_base = virtual_base;
|
||||
@ -676,8 +682,13 @@ struct AddressSpace::Impl {
|
||||
}
|
||||
shm_unlink(shm_path.c_str());
|
||||
#else
|
||||
#ifndef __FreeBSD__
|
||||
madvise(virtual_base, virtual_size, MADV_HUGEPAGE);
|
||||
|
||||
#endif
|
||||
// NOTE: If you add MFD_HUGETLB or whatever, remember that FBSD will break (libc bug)
|
||||
// so please, do not, add MFD_* whatever unless you ifdef it away (must be 0 for FBSD)
|
||||
// using sized pages as well causes incessant vm_reclaim calls in kernel, do not use on FBSD
|
||||
// under any circumstances.
|
||||
backing_fd = memfd_create("BackingDmem", 0);
|
||||
if (backing_fd < 0) {
|
||||
LOG_CRITICAL(Kernel_Vmm, "memfd_create failed: {}", strerror(errno));
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
#elif defined(__linux__)
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#elif defined(__APPLE__)
|
||||
#elif defined(__APPLE__) || defined(__FreeBSD__)
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <sys/sysctl.h>
|
||||
@ -48,6 +48,8 @@ bool Core::Debugger::IsDebuggerAttached() {
|
||||
return (info.kp_proc.p_flag & P_TRACED) != 0;
|
||||
}
|
||||
return false;
|
||||
#elif defined(__FreeBSD__)
|
||||
return false;
|
||||
#else
|
||||
#error "Unsupported platform"
|
||||
#endif
|
||||
@ -66,7 +68,7 @@ void Core::Debugger::WaitForDebuggerAttach() {
|
||||
int Core::Debugger::GetCurrentPid() {
|
||||
#if defined(_WIN32)
|
||||
return GetCurrentProcessId();
|
||||
#elif defined(__APPLE__) || defined(__linux__)
|
||||
#elif defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__)
|
||||
return getpid();
|
||||
#else
|
||||
#error "Unsupported platform"
|
||||
@ -88,7 +90,7 @@ void Core::Debugger::WaitForPid(int pid) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
std::cerr << "Waiting for process " << pid << " to exit..." << std::endl;
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
#elif defined(__APPLE__) || defined(__FreeBSD__)
|
||||
while (kill(pid, 0) == 0) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
std::cerr << "Waiting for process " << pid << " to exit..." << std::endl;
|
||||
|
||||
@ -95,7 +95,7 @@ std::filesystem::path MntPoints::GetHostPath(std::string_view path, bool* is_rea
|
||||
std::scoped_lock lk{m_mutex};
|
||||
path_parts.clear();
|
||||
auto current_path = host_path;
|
||||
while (!std::filesystem::exists(current_path)) {
|
||||
while (!current_path.empty() && !std::filesystem::exists(current_path)) {
|
||||
// We have probably cached this if it's a folder.
|
||||
if (auto it = path_cache.find(current_path); it != path_cache.end()) {
|
||||
current_path = it->second;
|
||||
@ -104,38 +104,40 @@ std::filesystem::path MntPoints::GetHostPath(std::string_view path, bool* is_rea
|
||||
path_parts.emplace_back(current_path.filename());
|
||||
current_path = current_path.parent_path();
|
||||
}
|
||||
// We have found an anchor. Traverse parts we recoded and see if they
|
||||
// exist in filesystem but in different case.
|
||||
auto guest_path = current_path;
|
||||
while (!path_parts.empty()) {
|
||||
const auto part = path_parts.back();
|
||||
const auto add_match = [&](const auto& host_part) {
|
||||
current_path /= host_part;
|
||||
guest_path /= part;
|
||||
path_cache[guest_path] = current_path;
|
||||
path_parts.pop_back();
|
||||
};
|
||||
// Can happen when the mismatch is in upper folder.
|
||||
if (std::filesystem::exists(current_path / part)) {
|
||||
add_match(part);
|
||||
continue;
|
||||
}
|
||||
const auto part_low = Common::ToLower(part.string());
|
||||
bool found_match = false;
|
||||
for (const auto& path : std::filesystem::directory_iterator(current_path)) {
|
||||
const auto candidate = path.path().filename();
|
||||
const auto filename = Common::ToLower(candidate.string());
|
||||
// Check if a filename matches in case insensitive manner.
|
||||
if (filename != part_low) {
|
||||
if (!current_path.empty()) {
|
||||
// We have found an anchor. Traverse parts we recoded and see if they
|
||||
// exist in filesystem but in different case.
|
||||
auto guest_path = current_path;
|
||||
while (!path_parts.empty()) {
|
||||
const auto part = path_parts.back();
|
||||
const auto add_match = [&](const auto& host_part) {
|
||||
current_path /= host_part;
|
||||
guest_path /= part;
|
||||
path_cache[guest_path] = current_path;
|
||||
path_parts.pop_back();
|
||||
};
|
||||
// Can happen when the mismatch is in upper folder.
|
||||
if (std::filesystem::exists(current_path / part)) {
|
||||
add_match(part);
|
||||
continue;
|
||||
}
|
||||
// We found a match, record the actual path in the cache.
|
||||
add_match(candidate);
|
||||
found_match = true;
|
||||
break;
|
||||
}
|
||||
if (!found_match) {
|
||||
return std::optional<std::filesystem::path>({});
|
||||
const auto part_low = Common::ToLower(part.string());
|
||||
bool found_match = false;
|
||||
for (const auto& path : std::filesystem::directory_iterator(current_path)) {
|
||||
const auto candidate = path.path().filename();
|
||||
const auto filename = Common::ToLower(candidate.string());
|
||||
// Check if a filename matches in case insensitive manner.
|
||||
if (filename != part_low) {
|
||||
continue;
|
||||
}
|
||||
// We found a match, record the actual path in the cache.
|
||||
add_match(candidate);
|
||||
found_match = true;
|
||||
break;
|
||||
}
|
||||
if (!found_match) {
|
||||
return std::optional<std::filesystem::path>({});
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::optional<std::filesystem::path>(current_path);
|
||||
|
||||
@ -215,6 +215,28 @@ void SigactionHandler(int native_signum, siginfo_t* inf, ucontext_t* raw_context
|
||||
ctx.uc_mcontext.mc_gs = regs.__gs;
|
||||
ctx.uc_mcontext.mc_rip = regs.__rip;
|
||||
ctx.uc_mcontext.mc_addr = reinterpret_cast<uint64_t>(inf->si_addr);
|
||||
#elif defined(__FreeBSD__)
|
||||
const auto& regs = raw_context->uc_mcontext;
|
||||
ctx.uc_mcontext.mc_r8 = regs.mc_r8;
|
||||
ctx.uc_mcontext.mc_r9 = regs.mc_r9;
|
||||
ctx.uc_mcontext.mc_r10 = regs.mc_r10;
|
||||
ctx.uc_mcontext.mc_r11 = regs.mc_r11;
|
||||
ctx.uc_mcontext.mc_r12 = regs.mc_r12;
|
||||
ctx.uc_mcontext.mc_r13 = regs.mc_r13;
|
||||
ctx.uc_mcontext.mc_r14 = regs.mc_r14;
|
||||
ctx.uc_mcontext.mc_r15 = regs.mc_r15;
|
||||
ctx.uc_mcontext.mc_rdi = regs.mc_rdi;
|
||||
ctx.uc_mcontext.mc_rsi = regs.mc_rsi;
|
||||
ctx.uc_mcontext.mc_rbp = regs.mc_rbp;
|
||||
ctx.uc_mcontext.mc_rbx = regs.mc_rbx;
|
||||
ctx.uc_mcontext.mc_rdx = regs.mc_rdx;
|
||||
ctx.uc_mcontext.mc_rax = regs.mc_rax;
|
||||
ctx.uc_mcontext.mc_rcx = regs.mc_rcx;
|
||||
ctx.uc_mcontext.mc_rsp = regs.mc_rsp;
|
||||
ctx.uc_mcontext.mc_fs = regs.mc_fs;
|
||||
ctx.uc_mcontext.mc_gs = regs.mc_gs;
|
||||
ctx.uc_mcontext.mc_rip = regs.mc_rip;
|
||||
ctx.uc_mcontext.mc_addr = uint64_t(regs.mc_addr);
|
||||
#else
|
||||
const auto& regs = raw_context->uc_mcontext.gregs;
|
||||
ctx.uc_mcontext.mc_r8 = regs[REG_R8];
|
||||
@ -303,7 +325,7 @@ s32 PS4_SYSV_ABI posix_sigaction(s32 sig, Sigaction* act, Sigaction* oact) {
|
||||
*__Error() = POSIX_EINVAL;
|
||||
return ORBIS_FAIL;
|
||||
}
|
||||
#ifndef __APPLE__
|
||||
#if !defined(__APPLE__) && !defined(__FreeBSD__)
|
||||
if (native_sig >= __SIGRTMIN && native_sig < SIGRTMIN) {
|
||||
LOG_ERROR(Lib_Kernel, "Guest is attempting to use the HLE libc-reserved signal {}!", sig);
|
||||
*__Error() = POSIX_EINVAL;
|
||||
|
||||
@ -47,7 +47,7 @@ constexpr s32 POSIX_SIGUSR2 = 31;
|
||||
constexpr s32 POSIX_SIGTHR = 32;
|
||||
constexpr s32 POSIX_SIGLIBRT = 33;
|
||||
|
||||
#ifdef __linux__
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
constexpr s32 _SIGEMT = 128;
|
||||
constexpr s32 _SIGINFO = 129;
|
||||
#elif !defined(_WIN32)
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
#include <windows.h>
|
||||
#include "common/ntapi.h"
|
||||
#else
|
||||
#ifdef __APPLE__
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
#include <date/tz.h>
|
||||
#endif
|
||||
#include <ctime>
|
||||
@ -501,7 +501,7 @@ s32 PS4_SYSV_ABI sceKernelConvertUtcToLocaltime(time_t time, time_t* local_time,
|
||||
*dst_sec = res == TIME_ZONE_ID_DAYLIGHT ? -_dstbias : 0;
|
||||
}
|
||||
#else
|
||||
#ifdef __APPLE__
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
// std::chrono::current_zone() not available yet.
|
||||
const auto* time_zone = date::current_zone();
|
||||
#else
|
||||
|
||||
@ -663,10 +663,12 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or
|
||||
return ORBIS_NET_ERROR_EBADF;
|
||||
}
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
epoll_event native_event = {.events = ConvertEpollEventsIn(event->events),
|
||||
.data = {.fd = id}};
|
||||
ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_ADD, *native_handle, &native_event) == 0);
|
||||
epoll->events.emplace_back(id, *event);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case Core::FileSys::FileType::Resolver: {
|
||||
@ -711,10 +713,12 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or
|
||||
return ORBIS_NET_ERROR_EBADF;
|
||||
}
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
epoll_event native_event = {.events = ConvertEpollEventsIn(event->events),
|
||||
.data = {.fd = id}};
|
||||
ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_MOD, *native_handle, &native_event) == 0);
|
||||
*it = {id, *event};
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -752,9 +756,10 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or
|
||||
*sceNetErrnoLoc() = ORBIS_NET_EBADF;
|
||||
return ORBIS_NET_ERROR_EBADF;
|
||||
}
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_DEL, *native_handle, nullptr) == 0);
|
||||
epoll->events.erase(it);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case Core::FileSys::FileType::Resolver: {
|
||||
@ -810,6 +815,9 @@ int PS4_SYSV_ABI sceNetEpollDestroy(OrbisNetId epollid) {
|
||||
|
||||
int PS4_SYSV_ABI sceNetEpollWait(OrbisNetId epollid, OrbisNetEpollEvent* events, int maxevents,
|
||||
int timeout) {
|
||||
#ifdef __FreeBSD__
|
||||
return 0;
|
||||
#else
|
||||
auto file = FDTable::Instance()->GetEpoll(epollid);
|
||||
if (!file) {
|
||||
*sceNetErrnoLoc() = ORBIS_NET_EBADF;
|
||||
@ -836,7 +844,6 @@ int PS4_SYSV_ABI sceNetEpollWait(OrbisNetId epollid, OrbisNetEpollEvent* events,
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
|
||||
if (result < 0) {
|
||||
LOG_ERROR(Lib_Net, "epoll_wait failed with {}", Common::GetLastErrorMsg());
|
||||
switch (errno) {
|
||||
@ -905,8 +912,8 @@ int PS4_SYSV_ABI sceNetEpollWait(OrbisNetId epollid, OrbisNetEpollEvent* events,
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
#endif
|
||||
}
|
||||
|
||||
int* PS4_SYSV_ABI sceNetErrnoLoc() {
|
||||
|
||||
@ -10,12 +10,14 @@ namespace Libraries::Net {
|
||||
u32 ConvertEpollEventsIn(u32 orbis_events) {
|
||||
u32 ret = 0;
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
if ((orbis_events & ORBIS_NET_EPOLLIN) != 0) {
|
||||
ret |= EPOLLIN;
|
||||
}
|
||||
if ((orbis_events & ORBIS_NET_EPOLLOUT) != 0) {
|
||||
ret |= EPOLLOUT;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -23,6 +25,7 @@ u32 ConvertEpollEventsIn(u32 orbis_events) {
|
||||
u32 ConvertEpollEventsOut(u32 epoll_events) {
|
||||
u32 ret = 0;
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
if ((epoll_events & EPOLLIN) != 0) {
|
||||
ret |= ORBIS_NET_EPOLLIN;
|
||||
}
|
||||
@ -35,6 +38,7 @@ u32 ConvertEpollEventsOut(u32 epoll_events) {
|
||||
if ((epoll_events & EPOLLHUP) != 0) {
|
||||
ret |= ORBIS_NET_EPOLLHUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -14,7 +14,8 @@
|
||||
#include <wepoll.h>
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)
|
||||
// ADD libepoll-shim if using freebsd!
|
||||
#include <sys/epoll.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
@ -82,4 +83,4 @@ private:
|
||||
std::mutex m_mutex;
|
||||
};
|
||||
|
||||
} // namespace Libraries::Net
|
||||
} // namespace Libraries::Net
|
||||
|
||||
@ -25,7 +25,7 @@ typedef int net_socket;
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#endif
|
||||
#if __linux__
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
@ -81,6 +81,8 @@ bool NetUtilInternal::RetrieveEthernetAddr() {
|
||||
}
|
||||
freeifaddrs(ifap);
|
||||
}
|
||||
#elif defined(__FreeBSD__)
|
||||
// todo
|
||||
#else
|
||||
ifreq ifr;
|
||||
ifconf ifc;
|
||||
@ -226,7 +228,8 @@ bool NetUtilInternal::RetrieveDefaultGateway() {
|
||||
inet_ntop(AF_INET, gateAddr, str, sizeof(str));
|
||||
this->default_gateway = str;
|
||||
return true;
|
||||
|
||||
#elif defined(__FreeBSD__)
|
||||
return true;
|
||||
#else
|
||||
std::ifstream route{"/proc/net/route"};
|
||||
std::string line;
|
||||
@ -398,4 +401,4 @@ int NetUtilInternal::ResolveHostname(const char* hostname, Libraries::Net::Orbis
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace NetUtil
|
||||
} // namespace NetUtil
|
||||
|
||||
@ -222,8 +222,8 @@ s32 PS4_SYSV_ABI sceNpTrophyCreateContext(OrbisNpTrophyContext* context,
|
||||
const std::string np_comm_id = Common::ElfInfo::Instance().GetNpCommIds()[service_label];
|
||||
const auto trophy_base =
|
||||
Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "trophy" / np_comm_id;
|
||||
ctx.xml_save_file = Common::FS::GetUserPath(Common::FS::PathType::HomeDir) /
|
||||
std::to_string(user_id) / "trophy" / (np_comm_id + ".xml");
|
||||
ctx.xml_save_file =
|
||||
EmulatorSettings.GetHomeDir() / std::to_string(user_id) / "trophy" / (np_comm_id + ".xml");
|
||||
ctx.xml_dir = trophy_base / "Xml";
|
||||
ctx.icons_dir = trophy_base / "Icons";
|
||||
ctx.trophy_xml_path = GetTrophyXmlPath(ctx.xml_dir, EmulatorSettings.GetConsoleLanguage());
|
||||
|
||||
@ -10,6 +10,8 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <machine/sysarch.h>
|
||||
#elif defined(__APPLE__) && defined(ARCH_X86_64)
|
||||
#include <architecture/i386/table.h>
|
||||
#include <boost/icl/interval_set.hpp>
|
||||
@ -157,12 +159,17 @@ Tcb* GetTcbBase() {
|
||||
|
||||
#elif defined(ARCH_X86_64)
|
||||
|
||||
// Other POSIX x86_64
|
||||
|
||||
// Linux x86_64
|
||||
#if defined(__FreeBSD__)
|
||||
void SetTcbBase(void* image_address) {
|
||||
amd64_set_gsbase(image_address);
|
||||
}
|
||||
#else
|
||||
void SetTcbBase(void* image_address) {
|
||||
const int ret = syscall(SYS_arch_prctl, ARCH_SET_GS, (unsigned long)image_address);
|
||||
ASSERT_MSG(ret == 0, "Failed to set GS base: errno {}", errno);
|
||||
}
|
||||
#endif
|
||||
|
||||
Tcb* GetTcbBase() {
|
||||
return Libraries::Kernel::g_curthread->tcb;
|
||||
|
||||
@ -318,10 +318,12 @@ void Emulator::Run(std::filesystem::path file, std::vector<std::string> args,
|
||||
}
|
||||
}
|
||||
for (User user : UserSettings.GetUserManager().GetValidUsers()) {
|
||||
auto const user_trophy_file =
|
||||
Common::FS::GetUserPath(Common::FS::PathType::HomeDir) /
|
||||
std::to_string(user.user_id) / "trophy" / (npCommId + ".xml");
|
||||
auto const user_trophy_file = EmulatorSettings.GetHomeDir() /
|
||||
std::to_string(user.user_id) / "trophy" /
|
||||
(npCommId + ".xml");
|
||||
if (!std::filesystem::exists(user_trophy_file)) {
|
||||
auto temp = user_trophy_file.parent_path();
|
||||
std::filesystem::create_directories(temp);
|
||||
std::error_code discard;
|
||||
std::filesystem::copy_file(trophyDir / "Xml" / "TROPCONF.XML", user_trophy_file,
|
||||
discard);
|
||||
@ -533,7 +535,7 @@ void Emulator::Restart(std::filesystem::path eboot_path,
|
||||
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
#elif defined(__APPLE__) || defined(__linux__)
|
||||
#elif defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__)
|
||||
std::vector<char*> argv;
|
||||
|
||||
// Emulator executable
|
||||
|
||||
58
src/imgui/imgui_translations.cpp
Normal file
58
src/imgui/imgui_translations.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/emulator_settings.h"
|
||||
#include "imgui_translations.h"
|
||||
|
||||
namespace ImguiTranslate {
|
||||
|
||||
const std::map<u32, std::map<std::string, std::string>> langMap = {
|
||||
{0, JapaneseMap},
|
||||
// {1, EnglishUsMap}, - not used
|
||||
{2, FrenchMap},
|
||||
{3, SpanishMap},
|
||||
{4, GermanMap},
|
||||
{5, ItalianMap},
|
||||
{6, DutchMap},
|
||||
{7, PortugesePtMap},
|
||||
{8, RussianMap},
|
||||
{9, KoreanMap},
|
||||
{10, ChineseTraditionalMap},
|
||||
{11, ChineseSimplifiedMap},
|
||||
{12, FinnishMap},
|
||||
{13, SwedishMap},
|
||||
{14, DanishMap},
|
||||
{15, NorwegianMap},
|
||||
{16, PolishMap},
|
||||
{17, PortugeseBrMap},
|
||||
// {18, "English (UK)"}, - not used
|
||||
{19, TurkishMap},
|
||||
{20, SpanishLatinAmericanMap},
|
||||
{21, ArabicMap},
|
||||
{22, FrenchCanadaMap},
|
||||
{23, CzechMap},
|
||||
{24, HungarianMap},
|
||||
{25, GreekMap},
|
||||
{26, RomanianMap},
|
||||
{27, ThaiMap},
|
||||
{28, VietnameseMap},
|
||||
{29, IndonesianMap},
|
||||
{30, UkranianMap},
|
||||
};
|
||||
|
||||
std::string tr(std::string input) {
|
||||
// since we're coding in English
|
||||
if (EmulatorSettings.GetConsoleLanguage() == 1 || EmulatorSettings.GetConsoleLanguage() == 18)
|
||||
return input;
|
||||
|
||||
const std::map<std::string, std::string> translationTable =
|
||||
langMap.at(EmulatorSettings.GetConsoleLanguage());
|
||||
|
||||
if (!translationTable.contains(input)) {
|
||||
return input;
|
||||
}
|
||||
|
||||
return translationTable.at(input);
|
||||
}
|
||||
|
||||
} // namespace ImguiTranslate
|
||||
136
src/imgui/imgui_translations.h
Normal file
136
src/imgui/imgui_translations.h
Normal file
@ -0,0 +1,136 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace ImguiTranslate {
|
||||
|
||||
std::string tr(std::string input);
|
||||
|
||||
///////////// ImGui Translation Tables
|
||||
|
||||
// disable clang line limits for ease of translation
|
||||
// clang-format off
|
||||
|
||||
const std::map<std::string, std::string> JapaneseMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> FrenchMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> FrenchCanadaMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> SpanishMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> SpanishLatinAmericanMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> GermanMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> ItalianMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> DutchMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> PortugesePtMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> PortugeseBrMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> RussianMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> KoreanMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> ChineseTraditionalMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> ChineseSimplifiedMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> FinnishMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> SwedishMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> DanishMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> NorwegianMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> PolishMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> TurkishMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> ArabicMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> CzechMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> HungarianMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> GreekMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> RomanianMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> ThaiMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> VietnameseMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> IndonesianMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> UkranianMap = {
|
||||
{"Trophy Earned", "Trophy Earned"},
|
||||
};
|
||||
|
||||
// clang-format on
|
||||
|
||||
///////////// End ImGui Translation Tables
|
||||
|
||||
} // namespace ImguiTranslate
|
||||
@ -96,7 +96,7 @@ WindowSDL::WindowSDL(s32 width_, s32 height_, Input::GameControllers* controller
|
||||
UNREACHABLE_MSG("Failed to initialize SDL video subsystem: {}", SDL_GetError());
|
||||
}
|
||||
if (!SDL_Init(SDL_INIT_CAMERA)) {
|
||||
UNREACHABLE_MSG("Failed to initialize SDL camera subsystem: {}", SDL_GetError());
|
||||
LOG_ERROR(Input, "Failed to initialize SDL camera subsystem: {}", SDL_GetError());
|
||||
}
|
||||
SDL_InitSubSystem(SDL_INIT_AUDIO);
|
||||
|
||||
@ -141,7 +141,8 @@ WindowSDL::WindowSDL(s32 width_, s32 height_, Input::GameControllers* controller
|
||||
window_info.type = WindowSystemType::Windows;
|
||||
window_info.render_surface = SDL_GetPointerProperty(SDL_GetWindowProperties(window),
|
||||
SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL);
|
||||
#elif defined(SDL_PLATFORM_LINUX)
|
||||
#elif defined(SDL_PLATFORM_LINUX) || defined(__FreeBSD__)
|
||||
// SDL doesn't have a platform define for FreeBSD AAAAAAAAAA
|
||||
if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) {
|
||||
window_info.type = WindowSystemType::X11;
|
||||
window_info.display_connection = SDL_GetPointerProperty(
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
#include "common/logging/log.h"
|
||||
#include "core/emulator_settings.h"
|
||||
|
||||
#ifdef __linux__
|
||||
#ifdef __unix__
|
||||
#include "common/adaptive_mutex.h"
|
||||
#else
|
||||
#include "common/spin_lock.h"
|
||||
|
||||
@ -36,8 +36,8 @@
|
||||
|
||||
namespace VideoCore {
|
||||
|
||||
constexpr size_t PAGE_SIZE = 4_KB;
|
||||
constexpr size_t PAGE_BITS = 12;
|
||||
constexpr size_t PM_PAGE_SIZE = 4_KB;
|
||||
constexpr size_t PM_PAGE_BITS = 12;
|
||||
|
||||
struct PageManager::Impl {
|
||||
struct PageState {
|
||||
@ -85,7 +85,7 @@ struct PageManager::Impl {
|
||||
};
|
||||
|
||||
static constexpr size_t ADDRESS_BITS = 40;
|
||||
static constexpr size_t NUM_ADDRESS_PAGES = 1ULL << (40 - PAGE_BITS);
|
||||
static constexpr size_t NUM_ADDRESS_PAGES = 1ULL << (40 - PM_PAGE_BITS);
|
||||
static constexpr size_t NUM_ADDRESS_LOCKS = NUM_ADDRESS_PAGES / PAGES_PER_LOCK;
|
||||
inline static Vulkan::Rasterizer* rasterizer;
|
||||
#ifdef ENABLE_USERFAULTFD
|
||||
@ -222,8 +222,8 @@ struct PageManager::Impl {
|
||||
void UpdatePageWatchers(VAddr addr, u64 size) {
|
||||
RENDERER_TRACE;
|
||||
|
||||
size_t page = addr >> PAGE_BITS;
|
||||
const u64 page_end = Common::DivCeil(addr + size, PAGE_SIZE);
|
||||
size_t page = addr >> PM_PAGE_BITS;
|
||||
const u64 page_end = Common::DivCeil(addr + size, PM_PAGE_SIZE);
|
||||
|
||||
// Acquire locks for the range of pages
|
||||
const auto lock_start = locks.begin() + (page / PAGES_PER_LOCK);
|
||||
@ -239,15 +239,15 @@ struct PageManager::Impl {
|
||||
if (range_bytes > 0) {
|
||||
RENDERER_TRACE;
|
||||
// Perform pending (un)protect action
|
||||
Protect(range_begin << PAGE_BITS, range_bytes, perms);
|
||||
Protect(range_begin << PM_PAGE_BITS, range_bytes, perms);
|
||||
range_bytes = 0;
|
||||
potential_range_bytes = 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Iterate requested pages
|
||||
const u64 aligned_addr = page << PAGE_BITS;
|
||||
const u64 aligned_end = page_end << PAGE_BITS;
|
||||
const u64 aligned_addr = page << PM_PAGE_BITS;
|
||||
const u64 aligned_end = page_end << PM_PAGE_BITS;
|
||||
if (!rasterizer->IsMapped(aligned_addr, aligned_end - aligned_addr)) {
|
||||
LOG_WARNING(Render,
|
||||
"Tracking memory region {:#x} - {:#x} which is not fully GPU mapped.",
|
||||
@ -266,7 +266,7 @@ struct PageManager::Impl {
|
||||
perms = new_perms;
|
||||
} else if (range_bytes != 0) {
|
||||
// If the protection did not change, extend the potential range
|
||||
potential_range_bytes += PAGE_SIZE;
|
||||
potential_range_bytes += PM_PAGE_SIZE;
|
||||
}
|
||||
|
||||
// Only start a new range if the page must be (un)protected
|
||||
@ -274,7 +274,7 @@ struct PageManager::Impl {
|
||||
if (range_bytes == 0) {
|
||||
// Start a new potential range
|
||||
range_begin = page;
|
||||
potential_range_bytes = PAGE_SIZE;
|
||||
potential_range_bytes = PM_PAGE_SIZE;
|
||||
}
|
||||
// Extend current range up to potential range
|
||||
range_bytes = potential_range_bytes;
|
||||
@ -293,12 +293,12 @@ struct PageManager::Impl {
|
||||
|
||||
if (start_range.second == end_range.second) {
|
||||
// if all pages are contiguous, use the regular UpdatePageWatchers
|
||||
const VAddr start_addr = base_addr + (start_range.first << PAGE_BITS);
|
||||
const u64 size = (start_range.second - start_range.first) << PAGE_BITS;
|
||||
const VAddr start_addr = base_addr + (start_range.first << PM_PAGE_BITS);
|
||||
const u64 size = (start_range.second - start_range.first) << PM_PAGE_BITS;
|
||||
return UpdatePageWatchers<track, is_read>(start_addr, size);
|
||||
}
|
||||
|
||||
size_t base_page = (base_addr >> PAGE_BITS);
|
||||
size_t base_page = (base_addr >> PM_PAGE_BITS);
|
||||
ASSERT(base_page % PAGES_PER_LOCK == 0);
|
||||
std::scoped_lock lk(locks[base_page / PAGES_PER_LOCK]);
|
||||
auto perms = cached_pages[base_page + start_range.first].Perms();
|
||||
@ -310,7 +310,7 @@ struct PageManager::Impl {
|
||||
if (range_bytes > 0) {
|
||||
RENDERER_TRACE;
|
||||
// Perform pending (un)protect action
|
||||
Protect((range_begin << PAGE_BITS), range_bytes, perms);
|
||||
Protect((range_begin << PM_PAGE_BITS), range_bytes, perms);
|
||||
range_bytes = 0;
|
||||
potential_range_bytes = 0;
|
||||
}
|
||||
@ -331,7 +331,7 @@ struct PageManager::Impl {
|
||||
perms = new_perms;
|
||||
} else if (range_bytes != 0) {
|
||||
// If the protection did not change, extend the potential range
|
||||
potential_range_bytes += PAGE_SIZE;
|
||||
potential_range_bytes += PM_PAGE_SIZE;
|
||||
}
|
||||
|
||||
// If the page is not being updated, skip it
|
||||
@ -344,7 +344,7 @@ struct PageManager::Impl {
|
||||
if (range_bytes == 0) {
|
||||
// Start a new potential range
|
||||
range_begin = base_page + page;
|
||||
potential_range_bytes = PAGE_SIZE;
|
||||
potential_range_bytes = PM_PAGE_SIZE;
|
||||
}
|
||||
// Extend current rango up to potential range
|
||||
range_bytes = potential_range_bytes;
|
||||
@ -356,7 +356,7 @@ struct PageManager::Impl {
|
||||
}
|
||||
|
||||
std::array<PageState, NUM_ADDRESS_PAGES> cached_pages{};
|
||||
#ifdef __linux__
|
||||
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
|
||||
using LockType = Common::AdaptiveMutex;
|
||||
#else
|
||||
using LockType = Common::SpinLock;
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include "common/alignment.h"
|
||||
#include "common/types.h"
|
||||
@ -15,9 +16,10 @@ class Rasterizer;
|
||||
namespace VideoCore {
|
||||
|
||||
class PageManager {
|
||||
// PAGE_SIZE and PAGE_BITS conflicts with machine/param.h definitions on freebsd!
|
||||
// Use the same page size as the tracker.
|
||||
static constexpr size_t PAGE_BITS = TRACKER_PAGE_BITS;
|
||||
static constexpr size_t PAGE_SIZE = TRACKER_BYTES_PER_PAGE;
|
||||
static constexpr size_t PM_PAGE_BITS = TRACKER_PAGE_BITS;
|
||||
static constexpr size_t PM_PAGE_SIZE = TRACKER_BYTES_PER_PAGE;
|
||||
|
||||
// Keep the lock granularity the same as region granularity. (since each regions has
|
||||
// itself a lock)
|
||||
@ -43,12 +45,12 @@ public:
|
||||
|
||||
/// Returns page aligned address.
|
||||
static constexpr VAddr GetPageAddr(VAddr addr) {
|
||||
return Common::AlignDown(addr, PAGE_SIZE);
|
||||
return Common::AlignDown(addr, PM_PAGE_SIZE);
|
||||
}
|
||||
|
||||
/// Returns address of the next page.
|
||||
static constexpr VAddr GetNextPageAddr(VAddr addr) {
|
||||
return Common::AlignUp(addr + 1, PAGE_SIZE);
|
||||
return Common::AlignUp(addr + 1, PM_PAGE_SIZE);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user