Compare commits

..

No commits in common. "main" and "v.0.8.0" have entirely different histories.

92 changed files with 655 additions and 3232 deletions

View file

@ -30,7 +30,7 @@ jobs:
- name: Install
run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo add-apt-repository 'deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main'
sudo add-apt-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-19 main'
sudo apt update
sudo apt install clang-format-19
- name: Build
@ -281,13 +281,8 @@ jobs:
with:
submodules: recursive
- name: Add LLVM repository
run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo add-apt-repository 'deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main'
- name: Install dependencies
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 clang-19 mold build-essential libasound2-dev libpulse-dev libopenal-dev libudev-dev
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 clang build-essential libasound2-dev libpulse-dev libopenal-dev libudev-dev
- name: Cache CMake Configuration
uses: actions/cache@v4
@ -309,7 +304,7 @@ jobs:
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
- name: Configure CMake
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=clang-19 -DCMAKE_CXX_COMPILER=clang++-19 -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=mold" -DCMAKE_SHARED_LINKER_FLAGS="-fuse-ld=mold" -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(nproc)
@ -342,13 +337,8 @@ jobs:
with:
submodules: recursive
- name: Add LLVM repository
run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo add-apt-repository 'deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main'
- name: Install dependencies
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 clang-19 mold build-essential qt6-base-dev qt6-tools-dev qt6-multimedia-dev libasound2-dev libpulse-dev libopenal-dev libudev-dev
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 clang build-essential qt6-base-dev qt6-tools-dev qt6-multimedia-dev libasound2-dev libpulse-dev libopenal-dev libudev-dev
- name: Cache CMake Configuration
uses: actions/cache@v4
@ -370,7 +360,7 @@ jobs:
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
- name: Configure CMake
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=clang-19 -DCMAKE_CXX_COMPILER=clang++-19 -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=mold" -DCMAKE_SHARED_LINKER_FLAGS="-fuse-ld=mold" -DENABLE_QT_GUI=ON -DENABLE_UPDATER=ON -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DENABLE_QT_GUI=ON -DENABLE_UPDATER=ON -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(nproc)
@ -395,7 +385,7 @@ jobs:
submodules: recursive
- name: Install dependencies
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 gcc-14 mold build-essential libasound2-dev libpulse-dev libopenal-dev libudev-dev
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 gcc-14 build-essential libasound2-dev libpulse-dev libopenal-dev libudev-dev
- name: Cache CMake Configuration
uses: actions/cache@v4
@ -417,7 +407,7 @@ jobs:
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
- name: Configure CMake
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=mold" -DCMAKE_SHARED_LINKER_FLAGS="-fuse-ld=mold" -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(nproc)
@ -431,7 +421,7 @@ jobs:
submodules: recursive
- name: Install dependencies
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 gcc-14 mold build-essential qt6-base-dev qt6-tools-dev qt6-multimedia-dev libasound2-dev libpulse-dev libopenal-dev libudev-dev
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 gcc-14 build-essential qt6-base-dev qt6-tools-dev qt6-multimedia-dev libasound2-dev libpulse-dev libopenal-dev libudev-dev
- name: Cache CMake Configuration
uses: actions/cache@v4
@ -453,7 +443,7 @@ jobs:
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
- name: Configure CMake
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=mold" -DCMAKE_SHARED_LINKER_FLAGS="-fuse-ld=mold" -DENABLE_QT_GUI=ON -DENABLE_UPDATER=ON -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 -DENABLE_QT_GUI=ON -DENABLE_UPDATER=ON -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(nproc)

47
CMakeLists.txt Normal file → Executable file
View file

@ -203,12 +203,12 @@ execute_process(
# Set Version
set(EMULATOR_VERSION_MAJOR "0")
set(EMULATOR_VERSION_MINOR "8")
set(EMULATOR_VERSION_PATCH "1")
set(EMULATOR_VERSION_PATCH "0")
set_source_files_properties(src/shadps4.rc PROPERTIES COMPILE_DEFINITIONS "EMULATOR_VERSION_MAJOR=${EMULATOR_VERSION_MAJOR};EMULATOR_VERSION_MINOR=${EMULATOR_VERSION_MINOR};EMULATOR_VERSION_PATCH=${EMULATOR_VERSION_PATCH}")
set(APP_VERSION "${EMULATOR_VERSION_MAJOR}.${EMULATOR_VERSION_MINOR}.${EMULATOR_VERSION_PATCH} WIP")
set(APP_IS_RELEASE false)
set(APP_VERSION "${EMULATOR_VERSION_MAJOR}.${EMULATOR_VERSION_MINOR}.${EMULATOR_VERSION_PATCH}")
set(APP_IS_RELEASE true)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/src/common/scm_rev.cpp" @ONLY)
message("end git things, remote: ${GIT_REMOTE_NAME}, branch: ${GIT_BRANCH}")
@ -371,19 +371,11 @@ set(NETWORK_LIBS src/core/libraries/network/http.cpp
src/core/libraries/network/net_ctl_obj.cpp
src/core/libraries/network/net_ctl_obj.h
src/core/libraries/network/net_ctl_codes.h
src/core/libraries/network/net_util.cpp
src/core/libraries/network/net_util.h
src/core/libraries/network/net_error.h
src/core/libraries/network/net.h
src/core/libraries/network/ssl.cpp
src/core/libraries/network/ssl.h
src/core/libraries/network/ssl2.cpp
src/core/libraries/network/ssl2.h
src/core/libraries/network/sys_net.cpp
src/core/libraries/network/sys_net.h
src/core/libraries/network/posix_sockets.cpp
src/core/libraries/network/p2p_sockets.cpp
src/core/libraries/network/sockets.h
)
set(AVPLAYER_LIB src/core/libraries/avplayer/avplayer_common.cpp
@ -848,7 +840,6 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h
src/shader_recompiler/ir/passes/identity_removal_pass.cpp
src/shader_recompiler/ir/passes/ir_passes.h
src/shader_recompiler/ir/passes/lower_buffer_format_to_raw.cpp
src/shader_recompiler/ir/passes/lower_fp64_to_fp32.cpp
src/shader_recompiler/ir/passes/readlane_elimination_pass.cpp
src/shader_recompiler/ir/passes/resource_tracking_pass.cpp
src/shader_recompiler/ir/passes/ring_access_elimination.cpp
@ -1093,31 +1084,33 @@ endif()
if (APPLE)
# Include MoltenVK, along with an ICD file so it can be found by the system Vulkan loader if used for loading layers.
set(MVK_DYLIB_SRC ${CMAKE_CURRENT_BINARY_DIR}/externals/MoltenVK/libMoltenVK.dylib)
if (ENABLE_QT_GUI)
set(MVK_BUNDLE_PATH "Resources/vulkan/icd.d")
set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path/../${MVK_BUNDLE_PATH}")
set(MVK_DST ${CMAKE_CURRENT_BINARY_DIR}/shadps4.app/Contents/${MVK_BUNDLE_PATH})
set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path/../Frameworks")
set(MVK_ICD_DST ${CMAKE_CURRENT_BINARY_DIR}/shadps4.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json)
set(MVK_DYLIB_DST ${CMAKE_CURRENT_BINARY_DIR}/shadps4.app/Contents/Frameworks/libMoltenVK.dylib)
set(MVK_DYLIB_ICD_PATH "../../../Frameworks/libMoltenVK.dylib")
else()
set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path")
set(MVK_DST ${CMAKE_CURRENT_BINARY_DIR})
set(MVK_ICD_DST ${CMAKE_CURRENT_BINARY_DIR}/MoltenVK_icd.json)
set(MVK_DYLIB_DST ${CMAKE_CURRENT_BINARY_DIR}/libMoltenVK.dylib)
set(MVK_DYLIB_ICD_PATH "./libMoltenVK.dylib")
endif()
set(MVK_DYLIB_SRC ${CMAKE_CURRENT_BINARY_DIR}/externals/MoltenVK/libMoltenVK.dylib)
set(MVK_DYLIB_DST ${MVK_DST}/libMoltenVK.dylib)
set(MVK_ICD_SRC ${CMAKE_CURRENT_SOURCE_DIR}/externals/MoltenVK/MoltenVK/MoltenVK/icd/MoltenVK_icd.json)
set(MVK_ICD_DST ${MVK_DST}/MoltenVK_icd.json)
cmake_path(GET MVK_ICD_DST PARENT_PATH MVK_ICD_DST_PARENT)
cmake_path(GET MVK_DYLIB_DST PARENT_PATH MVK_DYLIB_DST_PARENT)
add_custom_command(
OUTPUT ${MVK_DST}
COMMAND ${CMAKE_COMMAND} -E make_directory ${MVK_DST})
set(MVK_ICD "\\\{ \\\"file_format_version\\\": \\\"1.0.0\\\", \\\"ICD\\\": \\\{ \\\"library_path\\\": \\\"${MVK_DYLIB_ICD_PATH}\\\", \\\"api_version\\\": \\\"1.2.0\\\", \\\"is_portability_driver\\\": true \\\} \\\}")
add_custom_command(
OUTPUT ${MVK_ICD_DST}
DEPENDS ${MVK_ICD_SRC} ${MVK_DST}
COMMAND ${CMAKE_COMMAND} -E copy ${MVK_ICD_SRC} ${MVK_ICD_DST})
COMMAND ${CMAKE_COMMAND} -E make_directory ${MVK_ICD_DST_PARENT} && ${CMAKE_COMMAND} -E echo ${MVK_ICD} > ${MVK_ICD_DST})
add_custom_command(
OUTPUT ${MVK_DYLIB_DST}
DEPENDS ${MVK_DYLIB_SRC} ${MVK_DST}
COMMAND ${CMAKE_COMMAND} -E copy ${MVK_DYLIB_SRC} ${MVK_DYLIB_DST})
DEPENDS ${MVK_DYLIB_SRC}
COMMAND ${CMAKE_COMMAND} -E make_directory ${MVK_DYLIB_DST_PARENT} && ${CMAKE_COMMAND} -E copy ${MVK_DYLIB_SRC} ${MVK_DYLIB_DST})
add_custom_target(CopyMoltenVK DEPENDS ${MVK_ICD_DST} ${MVK_DYLIB_DST})
add_dependencies(CopyMoltenVK MoltenVK)
add_dependencies(shadps4 CopyMoltenVK)

@ -1 +1 @@
Subproject commit 87a8e8b13d4ad8835367fea1ebad1896d0460946
Subproject commit 4cf8f94684c53e581eb9cc694dd3305d1f7d9959

@ -1 +1 @@
Subproject commit 7918775748c5e2f5c40d9918ce68825035b5a1e1
Subproject commit 2275d0efc4f2fa46851035d9d3c67c105bc8b99e

2
externals/sirit vendored

@ -1 +1 @@
Subproject commit 09a1416ab1b59ddfebd2618412f118f2004f3b2c
Subproject commit 427a42c9ed99b38204d9107bc3dc14e92458acf1

View file

@ -131,7 +131,9 @@ namespace {
case SeekOrigin::End:
return SEEK_END;
default:
UNREACHABLE_MSG("Impossible SeekOrigin {}", static_cast<u32>(origin));
LOG_ERROR(Common_Filesystem, "Unsupported origin {}, defaulting to SEEK_SET",
static_cast<u32>(origin));
return SEEK_SET;
}
}

View file

@ -61,6 +61,8 @@ enum class SeekOrigin : u32 {
SetOrigin, // Seeks from the start of the file.
CurrentPosition, // Seeks from the current file pointer position.
End, // Seeks from the end of the file.
SeekHole, // Seeks from the start of the next hole in the file.
SeekData, // Seeks from the start of the next non-hole region in the file.
};
class IOFile final {

View file

@ -23,7 +23,7 @@
namespace MemoryPatcher {
EXPORT uintptr_t g_eboot_address;
uintptr_t g_eboot_address;
uint64_t g_eboot_image_size;
std::string g_game_serial;
std::string patchFile;
@ -169,8 +169,7 @@ void OnGameLoaded() {
if (type == "mask_jump32")
patchMask = MemoryPatcher::PatchMask::Mask_Jump32;
if ((type == "mask" || type == "mask_jump32") &&
!maskOffsetStr.empty()) {
if (type == "mask" || type == "mask_jump32" && !maskOffsetStr.empty()) {
maskOffsetValue = std::stoi(maskOffsetStr, 0, 10);
}

View file

@ -6,15 +6,9 @@
#include <string>
#include <vector>
#if defined(WIN32)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __attribute__((visibility("default")))
#endif
namespace MemoryPatcher {
extern EXPORT uintptr_t g_eboot_address;
extern uintptr_t g_eboot_address;
extern uint64_t g_eboot_image_size;
extern std::string g_game_serial;
extern std::string patchFile;

View file

@ -19,6 +19,8 @@ enum class MemoryPermission : u32 {
};
DECLARE_ENUM_FLAG_OPERATORS(MemoryPermission)
constexpr VAddr CODE_BASE_OFFSET = 0x100000000ULL;
constexpr VAddr SYSTEM_MANAGED_MIN = 0x00000400000ULL;
constexpr VAddr SYSTEM_MANAGED_MAX = 0x07FFFFBFFFULL;
constexpr VAddr SYSTEM_RESERVED_MIN = 0x07FFFFC000ULL;

View file

@ -40,10 +40,6 @@ public:
return ORBIS_KERNEL_ERROR_EBADF;
}
virtual size_t pwritev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) {
return ORBIS_KERNEL_ERROR_EBADF;
}
virtual s64 lseek(s64 offset, int whence) {
return ORBIS_KERNEL_ERROR_EBADF;
}

View file

@ -2,7 +2,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <cstdlib>
#include <ctime>
#include "common/logging/log.h"
#include "random_device.h"

View file

@ -2,7 +2,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <cstdlib>
#include <ctime>
#include "common/logging/log.h"
#include "srandom_device.h"

View file

@ -2,7 +2,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <cstdlib>
#include <ctime>
#include "common/logging/log.h"
#include "urandom_device.h"

View file

@ -1,11 +1,11 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "SDL3/SDL_log.h"
#include "layer.h"
#include <imgui.h>
#include "SDL3/SDL_log.h"
#include "common/config.h"
#include "common/singleton.h"
#include "common/types.h"

View file

@ -1,14 +1,9 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "options.h"
#include <memory>
#include <imgui.h>
#include "video_core/renderer_vulkan/vk_presenter.h"
extern std::unique_ptr<Vulkan::Presenter> presenter;
#include "options.h"
namespace Core::Devtools {
@ -17,7 +12,6 @@ TOptions Options;
void LoadOptionsConfig(const char* line) {
char str[512];
int i;
float f;
if (sscanf(line, "disassembler_cli_isa=%511[^\n]", str) == 1) {
Options.disassembler_cli_isa = str;
return;
@ -30,26 +24,12 @@ void LoadOptionsConfig(const char* line) {
Options.frame_dump_render_on_collapse = i != 0;
return;
}
if (sscanf(line, "fsr_enabled=%d", &i) == 1) {
presenter->GetFsrSettingsRef().enable = i != 0;
return;
}
if (sscanf(line, "fsr_rcas_enabled=%d", &i) == 1) {
presenter->GetFsrSettingsRef().use_rcas = i != 0;
return;
}
if (sscanf(line, "fsr_rcas_attenuation=%f", &f) == 1) {
presenter->GetFsrSettingsRef().rcas_attenuation = f;
}
}
void SerializeOptionsConfig(ImGuiTextBuffer* buf) {
buf->appendf("disassembler_cli_isa=%s\n", Options.disassembler_cli_isa.c_str());
buf->appendf("disassembler_cli_spv=%s\n", Options.disassembler_cli_spv.c_str());
buf->appendf("frame_dump_render_on_collapse=%d\n", Options.frame_dump_render_on_collapse);
buf->appendf("fsr_enabled=%d\n", presenter->GetFsrSettingsRef().enable);
buf->appendf("fsr_rcas_enabled=%d\n", presenter->GetFsrSettingsRef().use_rcas);
buf->appendf("fsr_rcas_attenuation=%f\n", presenter->GetFsrSettingsRef().rcas_attenuation);
}
} // namespace Core::Devtools

View file

@ -2,7 +2,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <cstdio>
#include <ctime>
#include <fmt/chrono.h>
#include <imgui.h>
#include <magic_enum/magic_enum.hpp>

View file

@ -83,35 +83,9 @@ int PS4_SYSV_ABI sceImeDialogGetPanelPositionAndForm() {
return ORBIS_OK;
}
Error PS4_SYSV_ABI sceImeDialogGetPanelSize(const OrbisImeDialogParam* param, u32* width,
u32* height) {
LOG_INFO(Lib_ImeDialog, "called");
if (!width || !height) {
return Error::INVALID_ADDRESS;
}
switch (param->type) {
case OrbisImeType::Default:
case OrbisImeType::BasicLatin:
case OrbisImeType::Url:
case OrbisImeType::Mail:
*width = 500; // original: 793
if (True(param->option & OrbisImeDialogOption::Multiline)) {
*height = 300; // original: 576
} else {
*height = 150; // original: 476
}
break;
case OrbisImeType::Number:
*width = 370;
*height = 470;
break;
default:
LOG_ERROR(Lib_ImeDialog, "Unknown OrbisImeType: {}", (u32)param->type);
return Error::INVALID_PARAM;
}
return Error::OK;
int PS4_SYSV_ABI sceImeDialogGetPanelSize() {
LOG_ERROR(Lib_ImeDialog, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceImeDialogGetPanelSizeExtended() {

View file

@ -13,7 +13,7 @@ class SymbolsResolver;
namespace Libraries::ImeDialog {
constexpr u32 ORBIS_IME_DIALOG_MAX_TEXT_LENGTH = 2048;
constexpr u32 ORBIS_IME_DIALOG_MAX_TEXT_LENGTH = 0x78;
enum class Error : u32 {
OK = 0x0,
@ -155,8 +155,7 @@ Error PS4_SYSV_ABI sceImeDialogForceClose();
Error PS4_SYSV_ABI sceImeDialogForTestFunction();
int PS4_SYSV_ABI sceImeDialogGetCurrentStarState();
int PS4_SYSV_ABI sceImeDialogGetPanelPositionAndForm();
Error PS4_SYSV_ABI sceImeDialogGetPanelSize(const OrbisImeDialogParam* param, u32* width,
u32* height);
int PS4_SYSV_ABI sceImeDialogGetPanelSize();
int PS4_SYSV_ABI sceImeDialogGetPanelSizeExtended();
Error PS4_SYSV_ABI sceImeDialogGetResult(OrbisImeDialogResult* result);
OrbisImeDialogStatus PS4_SYSV_ABI sceImeDialogGetStatus();

View file

@ -61,18 +61,6 @@ struct SceKernelEvent {
void* udata = nullptr; /* opaque user data identifier */
};
struct OrbisVideoOutEventHint {
u64 event_id : 8;
u64 video_id : 8;
u64 flip_arg : 48;
};
struct OrbisVideoOutEventData {
u64 time : 12;
u64 count : 4;
u64 flip_arg : 48;
};
struct EqueueEvent {
SceKernelEvent event;
void* data = nullptr;
@ -96,18 +84,19 @@ struct EqueueEvent {
void TriggerDisplay(void* data) {
is_triggered = true;
if (data != nullptr) {
auto event_data = static_cast<OrbisVideoOutEventData>(event.data);
auto event_hint_raw = reinterpret_cast<u64>(data);
auto event_hint = static_cast<OrbisVideoOutEventHint>(event_hint_raw);
if (event_hint.event_id == event.ident && event.ident != 0xfe) {
auto hint = reinterpret_cast<u64>(data);
if (hint != 0) {
auto hint_h = static_cast<u32>(hint >> 8) & 0xFFFFFF;
auto ident_h = static_cast<u32>(event.ident >> 40);
if ((static_cast<u32>(hint) & 0xFF) == event.ident && event.ident != 0xFE &&
((hint_h ^ ident_h) & 0xFF) == 0) {
auto time = Common::FencedRDTSC();
auto counter = event_data.count;
if (counter != 0xf) {
counter++;
auto mask = 0xF000;
if ((static_cast<u32>(event.data) & 0xF000) != 0xF000) {
mask = (static_cast<u32>(event.data) + 0x1000) & 0xF000;
}
event.data =
(time & 0xfff) | (counter << 0xc) | (event_hint_raw & 0xffffffffffff0000);
event.data = (mask | static_cast<u64>(static_cast<u32>(time) & 0xFFF) |
(hint & 0xFFFFFFFFFFFF0000));
}
}
}

View file

@ -67,16 +67,10 @@ s32 PS4_SYSV_ABI open(const char* raw_path, s32 flags, u16 mode) {
bool write = (flags & 0x3) == ORBIS_KERNEL_O_WRONLY;
bool rdwr = (flags & 0x3) == ORBIS_KERNEL_O_RDWR;
if (!read && !write && !rdwr) {
// Start by checking for invalid flags.
*__Error() = POSIX_EINVAL;
return -1;
}
bool nonblock = (flags & ORBIS_KERNEL_O_NONBLOCK) != 0;
bool append = (flags & ORBIS_KERNEL_O_APPEND) != 0;
// Flags fsync and sync behave the same
bool sync = (flags & ORBIS_KERNEL_O_SYNC) != 0 || (flags & ORBIS_KERNEL_O_FSYNC) != 0;
bool fsync = (flags & ORBIS_KERNEL_O_FSYNC) != 0;
bool sync = (flags & ORBIS_KERNEL_O_SYNC) != 0;
bool create = (flags & ORBIS_KERNEL_O_CREAT) != 0;
bool truncate = (flags & ORBIS_KERNEL_O_TRUNC) != 0;
bool excl = (flags & ORBIS_KERNEL_O_EXCL) != 0;
@ -84,10 +78,6 @@ s32 PS4_SYSV_ABI open(const char* raw_path, s32 flags, u16 mode) {
bool direct = (flags & ORBIS_KERNEL_O_DIRECT) != 0;
bool directory = (flags & ORBIS_KERNEL_O_DIRECTORY) != 0;
if (sync || direct || dsync || nonblock) {
LOG_WARNING(Kernel_Fs, "flags {:#x} not fully handled", flags);
}
std::string_view path{raw_path};
u32 handle = h->CreateHandle();
auto* file = h->GetFile(handle);
@ -104,127 +94,84 @@ s32 PS4_SYSV_ABI open(const char* raw_path, s32 flags, u16 mode) {
}
}
bool read_only = false;
file->m_guest_name = path;
file->m_host_name = mnt->GetHostPath(file->m_guest_name, &read_only);
bool exists = std::filesystem::exists(file->m_host_name);
s32 e = 0;
if (create) {
if (excl && exists) {
// Error if file exists
h->DeleteHandle(handle);
*__Error() = POSIX_EEXIST;
return -1;
}
if (read_only) {
// Can't create files in a read only directory
h->DeleteHandle(handle);
*__Error() = POSIX_EROFS;
return -1;
}
// Create a file if it doesn't exist
Common::FS::IOFile out(file->m_host_name, Common::FS::FileAccessMode::Write);
} else if (!exists) {
// If we're not creating a file, and it doesn't exist, return ENOENT
h->DeleteHandle(handle);
*__Error() = POSIX_ENOENT;
return -1;
}
if (std::filesystem::is_directory(file->m_host_name) || directory) {
// Directories can be opened even if the directory flag isn't set.
// In these cases, error behavior is identical to the directory code path.
directory = true;
}
if (directory) {
if (!std::filesystem::is_directory(file->m_host_name)) {
// If the opened file is not a directory, return ENOTDIR.
// This will trigger when create & directory is specified, this is expected.
h->DeleteHandle(handle);
*__Error() = POSIX_ENOTDIR;
return -1;
}
file->type = Core::FileSys::FileType::Directory;
// Populate directory contents
mnt->IterateDirectory(file->m_guest_name,
[&file](const auto& ent_path, const auto ent_is_file) {
auto& dir_entry = file->dirents.emplace_back();
dir_entry.name = ent_path.filename().string();
dir_entry.isFile = ent_is_file;
});
file->dirents_index = 0;
if (read) {
e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Read);
} else if (write || rdwr) {
// Cannot open directories with any type of write access
file->m_guest_name = path;
file->m_host_name = mnt->GetHostPath(file->m_guest_name);
if (!std::filesystem::is_directory(file->m_host_name)) { // directory doesn't exist
h->DeleteHandle(handle);
*__Error() = POSIX_EISDIR;
return -1;
}
if (e == EACCES) {
// Hack to bypass some platform limitations, ignore the error and continue as normal.
LOG_WARNING(Kernel_Fs, "Opening directories is not fully supported on this platform");
e = 0;
}
if (truncate) {
// Cannot open directories with truncate
h->DeleteHandle(handle);
*__Error() = POSIX_EISDIR;
*__Error() = POSIX_ENOENT;
return -1;
} else {
if (create) {
return handle; // dir already exists
} else {
mnt->IterateDirectory(file->m_guest_name,
[&file](const auto& ent_path, const auto ent_is_file) {
auto& dir_entry = file->dirents.emplace_back();
dir_entry.name = ent_path.filename().string();
dir_entry.isFile = ent_is_file;
});
file->dirents_index = 0;
}
}
} else {
file->type = Core::FileSys::FileType::Regular;
file->m_guest_name = path;
file->m_host_name = mnt->GetHostPath(file->m_guest_name);
bool exists = std::filesystem::exists(file->m_host_name);
int e = 0;
if (truncate && read_only) {
// Can't open files with truncate flag in a read only directory
h->DeleteHandle(handle);
*__Error() = POSIX_EROFS;
return -1;
} else if (truncate) {
// Open the file as read-write so we can truncate regardless of flags.
// Since open starts by closing the file, this won't interfere with later open calls.
e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::ReadWrite);
if (e == 0) {
// If the file was opened successfully, reduce size to 0
file->f.SetSize(0);
if (create) {
if (excl && exists) {
// Error if file exists
h->DeleteHandle(handle);
*__Error() = POSIX_EEXIST;
return -1;
}
// Create file if it doesn't exist
Common::FS::IOFile out(file->m_host_name, Common::FS::FileAccessMode::Write);
} else if (!exists) {
// File to open doesn't exist, return ENOENT
h->DeleteHandle(handle);
*__Error() = POSIX_ENOENT;
return -1;
}
if (read) {
// Read only
e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Read);
} else if (read_only) {
// Can't open files with write/read-write access in a read only directory
h->DeleteHandle(handle);
*__Error() = POSIX_EROFS;
return -1;
} else if (append) {
// Append can be specified with rdwr or write, but we treat it as a separate mode.
e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Append);
} else if (write) {
// Write only
e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Write);
if (append) {
e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Append);
} else {
e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Write);
}
} else if (rdwr) {
// Read and write
e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::ReadWrite);
if (append) {
e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Append);
} else {
e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::ReadWrite);
}
} else {
// Invalid flags
*__Error() = POSIX_EINVAL;
return -1;
}
if (truncate && e == 0) {
// If the file was opened successfully and truncate was enabled, reduce size to 0
file->f.SetSize(0);
}
if (e != 0) {
// Open failed in platform-specific code, errno needs to be converted.
h->DeleteHandle(handle);
SetPosixErrno(e);
return -1;
}
}
if (e != 0) {
// Open failed in platform-specific code, errno needs to be converted.
h->DeleteHandle(handle);
SetPosixErrno(e);
return -1;
}
file->is_opened = true;
return handle;
}
@ -418,10 +365,10 @@ s64 PS4_SYSV_ABI posix_lseek(s32 fd, s64 offset, s32 whence) {
origin = Common::FS::SeekOrigin::CurrentPosition;
} else if (whence == 2) {
origin = Common::FS::SeekOrigin::End;
} else if (whence == 3 || whence == 4) {
// whence parameter belongs to an unsupported POSIX extension
*__Error() = POSIX_ENOTTY;
return -1;
} else if (whence == 3) {
origin = Common::FS::SeekOrigin::SeekHole;
} else if (whence == 4) {
origin = Common::FS::SeekOrigin::SeekData;
} else {
// whence parameter is invalid
*__Error() = POSIX_EINVAL;
@ -539,13 +486,13 @@ s32 PS4_SYSV_ABI posix_rmdir(const char* path) {
const std::filesystem::path dir_name = mnt->GetHostPath(path, &ro);
if (ro) {
*__Error() = POSIX_EROFS;
if (dir_name.empty() || !std::filesystem::is_directory(dir_name)) {
*__Error() = POSIX_ENOTDIR;
return -1;
}
if (dir_name.empty() || !std::filesystem::is_directory(dir_name)) {
*__Error() = POSIX_ENOTDIR;
if (ro) {
*__Error() = POSIX_EROFS;
return -1;
}
@ -576,7 +523,8 @@ s32 PS4_SYSV_ABI sceKernelRmdir(const char* path) {
s32 PS4_SYSV_ABI posix_stat(const char* path, OrbisKernelStat* sb) {
LOG_INFO(Kernel_Fs, "(PARTIAL) path = {}", path);
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
const auto path_name = mnt->GetHostPath(path);
bool ro = false;
const auto path_name = mnt->GetHostPath(path, &ro);
std::memset(sb, 0, sizeof(OrbisKernelStat));
const bool is_dir = std::filesystem::is_directory(path_name);
const bool is_file = std::filesystem::is_regular_file(path_name);
@ -597,6 +545,9 @@ s32 PS4_SYSV_ABI posix_stat(const char* path, OrbisKernelStat* sb) {
sb->st_blocks = (sb->st_size + 511) / 512;
// TODO incomplete
}
if (ro) {
sb->st_mode &= ~0000555u;
}
return ORBIS_OK;
}
@ -926,7 +877,7 @@ s32 PS4_SYSV_ABI sceKernelGetdirentries(s32 fd, char* buf, s32 nbytes, s64* base
return result;
}
s64 PS4_SYSV_ABI posix_pwritev(s32 fd, const SceKernelIovec* iov, s32 iovcnt, s64 offset) {
s64 PS4_SYSV_ABI posix_pwrite(s32 fd, void* buf, size_t nbytes, s64 offset) {
if (offset < 0) {
*__Error() = POSIX_EINVAL;
return -1;
@ -942,7 +893,7 @@ s64 PS4_SYSV_ABI posix_pwritev(s32 fd, const SceKernelIovec* iov, s32 iovcnt, s6
std::scoped_lock lk{file->m_mutex};
if (file->type == Core::FileSys::FileType::Device) {
s64 result = file->device->pwritev(iov, iovcnt, offset);
s64 result = file->device->pwrite(buf, nbytes, offset);
if (result < 0) {
ErrSceToPosix(result);
return -1;
@ -957,16 +908,7 @@ s64 PS4_SYSV_ABI posix_pwritev(s32 fd, const SceKernelIovec* iov, s32 iovcnt, s6
*__Error() = POSIX_EIO;
return -1;
}
size_t total_written = 0;
for (int i = 0; i < iovcnt; i++) {
total_written += file->f.WriteRaw<u8>(iov[i].iov_base, iov[i].iov_len);
}
return total_written;
}
s64 PS4_SYSV_ABI posix_pwrite(s32 fd, void* buf, size_t nbytes, s64 offset) {
SceKernelIovec iovec{buf, nbytes};
return posix_pwritev(fd, &iovec, 1, offset);
return file->f.WriteRaw<u8>(buf, nbytes);
}
s64 PS4_SYSV_ABI sceKernelPwrite(s32 fd, void* buf, size_t nbytes, s64 offset) {
@ -978,15 +920,6 @@ s64 PS4_SYSV_ABI sceKernelPwrite(s32 fd, void* buf, size_t nbytes, s64 offset) {
return result;
}
s64 PS4_SYSV_ABI sceKernelPwritev(s32 fd, const SceKernelIovec* iov, s32 iovcnt, s64 offset) {
s64 result = posix_pwritev(fd, iov, iovcnt, offset);
if (result < 0) {
LOG_ERROR(Kernel_Fs, "error = {}", *__Error());
return ErrnoToSceKernelError(*__Error());
}
return result;
}
s32 PS4_SYSV_ABI posix_unlink(const char* path) {
if (path == nullptr) {
*__Error() = POSIX_EINVAL;
@ -1084,10 +1017,7 @@ void RegisterFileSystem(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("sfKygSjIbI8", "libkernel", 1, "libkernel", 1, 1, getdirentries);
LIB_FUNCTION("taRWhTJFTgE", "libkernel", 1, "libkernel", 1, 1, sceKernelGetdirentries);
LIB_FUNCTION("C2kJ-byS5rM", "libkernel", 1, "libkernel", 1, 1, posix_pwrite);
LIB_FUNCTION("FCcmRZhWtOk", "libScePosix", 1, "libkernel", 1, 1, posix_pwritev);
LIB_FUNCTION("FCcmRZhWtOk", "libkernel", 1, "libkernel", 1, 1, posix_pwritev);
LIB_FUNCTION("nKWi-N2HBV4", "libkernel", 1, "libkernel", 1, 1, sceKernelPwrite);
LIB_FUNCTION("mBd4AfLP+u8", "libkernel", 1, "libkernel", 1, 1, sceKernelPwritev);
LIB_FUNCTION("AUXVxWeJU-A", "libkernel", 1, "libkernel", 1, 1, sceKernelUnlink);
}

View file

@ -24,7 +24,6 @@
#include "core/libraries/kernel/threads/exception.h"
#include "core/libraries/kernel/time.h"
#include "core/libraries/libs.h"
#include "core/libraries/network/sys_net.h"
#ifdef _WIN64
#include <Rpc.h>
@ -197,6 +196,10 @@ const char* PS4_SYSV_ABI sceKernelGetFsSandboxRandomWord() {
return path;
}
int PS4_SYSV_ABI posix_connect() {
return -1;
}
int PS4_SYSV_ABI _sigprocmask() {
return ORBIS_OK;
}
@ -222,6 +225,7 @@ void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard);
LIB_FUNCTION("PfccT7qURYE", "libkernel", 1, "libkernel", 1, 1, kernel_ioctl);
LIB_FUNCTION("JGfTMBOdUJo", "libkernel", 1, "libkernel", 1, 1, sceKernelGetFsSandboxRandomWord);
LIB_FUNCTION("XVL8So3QJUk", "libkernel", 1, "libkernel", 1, 1, posix_connect);
LIB_FUNCTION("6xVpy0Fdq+I", "libkernel", 1, "libkernel", 1, 1, _sigprocmask);
LIB_FUNCTION("Xjoosiw+XPI", "libkernel", 1, "libkernel", 1, 1, sceKernelUuidCreate);
LIB_FUNCTION("Ou3iL1abvng", "libkernel", 1, "libkernel", 1, 1, stack_chk_fail);
@ -230,25 +234,6 @@ void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("k+AXqu2-eBc", "libScePosix", 1, "libkernel", 1, 1, posix_getpagesize);
LIB_FUNCTION("NWtTN10cJzE", "libSceLibcInternalExt", 1, "libSceLibcInternal", 1, 1,
sceLibcHeapGetTraceInfo);
// network
LIB_FUNCTION("XVL8So3QJUk", "libkernel", 1, "libkernel", 1, 1, Libraries::Net::sys_connect);
LIB_FUNCTION("TU-d9PfIHPM", "libkernel", 1, "libkernel", 1, 1, Libraries::Net::sys_socketex);
LIB_FUNCTION("KuOmgKoqCdY", "libkernel", 1, "libkernel", 1, 1, Libraries::Net::sys_bind);
LIB_FUNCTION("pxnCmagrtao", "libkernel", 1, "libkernel", 1, 1, Libraries::Net::sys_listen);
LIB_FUNCTION("3e+4Iv7IJ8U", "libkernel", 1, "libkernel", 1, 1, Libraries::Net::sys_accept);
LIB_FUNCTION("TU-d9PfIHPM", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_socket);
LIB_FUNCTION("oBr313PppNE", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_sendto);
LIB_FUNCTION("lUk6wrGXyMw", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_recvfrom);
LIB_FUNCTION("fFxGkxF2bVo", "libScePosix", 1, "libkernel", 1, 1,
Libraries::Net::sys_setsockopt);
LIB_FUNCTION("RenI1lL1WFk", "libScePosix", 1, "libkernel", 1, 1,
Libraries::Net::sys_getsockname);
LIB_FUNCTION("KuOmgKoqCdY", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_bind);
LIB_FUNCTION("5jRCs2axtr4", "libScePosix", 1, "libkernel", 1, 1,
Libraries::Net::sceNetInetNtop); // TODO fix it to sys_ ...
LIB_FUNCTION("4n51s0zEf0c", "libScePosix", 1, "libkernel", 1, 1,
Libraries::Net::sceNetInetPton); // TODO fix it to sys_ ...
}
} // namespace Libraries::Kernel

View file

@ -18,7 +18,6 @@ namespace Libraries::Kernel {
void ErrSceToPosix(int result);
int ErrnoToSceKernelError(int e);
void SetPosixErrno(int e);
int* PS4_SYSV_ABI __Error();
template <StringLiteral name, class F, F f>
struct WrapperImpl;

View file

@ -127,62 +127,6 @@ int PS4_SYSV_ABI sceKernelGetModuleInfoFromAddr(VAddr addr, int flags,
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceKernelGetModuleInfo(s32 handle, Core::OrbisKernelModuleInfo* info) {
if (info == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
if (info->st_size != sizeof(Core::OrbisKernelModuleInfo)) {
return ORBIS_KERNEL_ERROR_EINVAL;
}
auto* linker = Common::Singleton<Core::Linker>::Instance();
auto* module = linker->GetModule(handle);
if (module == nullptr) {
return ORBIS_KERNEL_ERROR_ESRCH;
}
*info = module->GetModuleInfo();
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceKernelGetModuleInfoInternal(s32 handle, Core::OrbisKernelModuleInfoEx* info) {
if (info == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
if (info->st_size != sizeof(Core::OrbisKernelModuleInfoEx)) {
return ORBIS_KERNEL_ERROR_EINVAL;
}
auto* linker = Common::Singleton<Core::Linker>::Instance();
auto* module = linker->GetModule(handle);
if (module == nullptr) {
return ORBIS_KERNEL_ERROR_ESRCH;
}
*info = module->GetModuleInfoEx();
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceKernelGetModuleList(s32* handles, u64 num_array, u64* out_count) {
if (handles == nullptr || out_count == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
auto* linker = Common::Singleton<Core::Linker>::Instance();
u64 count = 0;
auto* module = linker->GetModule(count);
while (module != nullptr && count < num_array) {
handles[count] = count;
count++;
module = linker->GetModule(count);
}
if (count == num_array && module != nullptr) {
return ORBIS_KERNEL_ERROR_ENOMEM;
}
*out_count = count;
return ORBIS_OK;
}
s32 PS4_SYSV_ABI exit(s32 status) {
UNREACHABLE_MSG("Exiting with status code {}", status);
return 0;
@ -197,9 +141,6 @@ void RegisterProcess(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("LwG8g3niqwA", "libkernel", 1, "libkernel", 1, 1, sceKernelDlsym);
LIB_FUNCTION("RpQJJVKTiFM", "libkernel", 1, "libkernel", 1, 1, sceKernelGetModuleInfoForUnwind);
LIB_FUNCTION("f7KBOafysXo", "libkernel", 1, "libkernel", 1, 1, sceKernelGetModuleInfoFromAddr);
LIB_FUNCTION("kUpgrXIrz7Q", "libkernel", 1, "libkernel", 1, 1, sceKernelGetModuleInfo);
LIB_FUNCTION("HZO7xOos4xc", "libkernel", 1, "libkernel", 1, 1, sceKernelGetModuleInfoInternal);
LIB_FUNCTION("IuxnUuXk6Bg", "libkernel", 1, "libkernel", 1, 1, sceKernelGetModuleList);
LIB_FUNCTION("6Z83sYWFlA8", "libkernel", 1, "libkernel", 1, 1, exit);
}

View file

@ -10,24 +10,16 @@
#include <arpa/inet.h>
#endif
#include <core/libraries/kernel/kernel.h>
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/singleton.h"
#include "core/libraries/error_codes.h"
#include "core/libraries/libs.h"
#include "core/libraries/network/net.h"
#include "net_error.h"
#include "net_util.h"
#include "netctl.h"
#include "sys_net.h"
namespace Libraries::Net {
static thread_local int32_t net_errno = 0;
static bool g_isNetInitialized = true; // TODO init it properly
int PS4_SYSV_ABI in6addr_any() {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return ORBIS_OK;
@ -69,45 +61,8 @@ int PS4_SYSV_ABI sce_net_in6addr_nodelocal_allnodes() {
}
OrbisNetId PS4_SYSV_ABI sceNetAccept(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_accept(s, addr, paddrlen);
if (result >= 0) {
return result; // Success
}
err = *Libraries::Kernel::__Error(); // Standard errno
// Convert to positive error for comparison
int positiveErr = (err < 0) ? -err : err;
if ((positiveErr & 0xfff0000) != 0) {
// Unknown/fatal error range
*sceNetErrnoLoc() = ORBIS_NET_ERETURN;
return -positiveErr;
}
// Retry if interrupted
} while (positiveErr == ORBIS_NET_EINTR);
if (positiveErr == ORBIS_NET_EADDRINUSE) {
result = -ORBIS_NET_EBADF;
} else if (positiveErr == ORBIS_NET_EALREADY) {
result = -ORBIS_NET_EINTR;
} else {
result = -positiveErr;
}
*sceNetErrnoLoc() = -result;
return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code
LOG_ERROR(Lib_Net, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetAddrConfig6GetInfo() {
@ -166,45 +121,8 @@ int PS4_SYSV_ABI sceNetBandwidthControlSetPolicy() {
}
int PS4_SYSV_ABI sceNetBind(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addrlen) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_bind(s, addr, addrlen);
if (result >= 0) {
return result; // Success
}
err = *Libraries::Kernel::__Error(); // Standard errno
// Convert to positive error for comparison
int positiveErr = (err < 0) ? -err : err;
if ((positiveErr & 0xfff0000) != 0) {
// Unknown/fatal error range
*sceNetErrnoLoc() = ORBIS_NET_ERETURN;
return -positiveErr;
}
// Retry if interrupted
} while (positiveErr == ORBIS_NET_EINTR);
if (positiveErr == ORBIS_NET_EADDRINUSE) {
result = -ORBIS_NET_EBADF;
} else if (positiveErr == ORBIS_NET_EALREADY) {
result = -ORBIS_NET_EINTR;
} else {
result = -positiveErr;
}
*sceNetErrnoLoc() = -result;
return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code
LOG_ERROR(Lib_Net, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetClearDnsCache() {
@ -547,46 +465,9 @@ int PS4_SYSV_ABI sceNetConfigWlanSetDeviceConfig() {
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetConnect(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addrlen) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_connect(s, addr, addrlen);
if (result >= 0) {
return result; // Success
}
err = *Libraries::Kernel::__Error(); // Standard errno
// Convert to positive error for comparison
int positiveErr = (err < 0) ? -err : err;
if ((positiveErr & 0xfff0000) != 0) {
// Unknown/fatal error range
*sceNetErrnoLoc() = ORBIS_NET_ERETURN;
return -positiveErr;
}
// Retry if interrupted
} while (positiveErr == ORBIS_NET_EINTR);
if (positiveErr == ORBIS_NET_EADDRINUSE) {
result = -ORBIS_NET_EBADF;
} else if (positiveErr == ORBIS_NET_EALREADY) {
result = -ORBIS_NET_EINTR;
} else {
result = -positiveErr;
}
*sceNetErrnoLoc() = -result;
return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code
int PS4_SYSV_ABI sceNetConnect() {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetControl() {
@ -759,15 +640,8 @@ int PS4_SYSV_ABI sceNetGetIfnameNumList() {
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetGetMacAddress(Libraries::NetCtl::OrbisNetEtherAddr* addr, int flags) {
if (addr == nullptr) {
LOG_ERROR(Lib_Net, "addr is null!");
return ORBIS_NET_EINVAL;
}
auto* netinfo = Common::Singleton<NetUtil::NetUtilInternal>::Instance();
netinfo->RetrieveEthernetAddr();
memcpy(addr->data, netinfo->GetEthernetAddr().data(), 6);
int PS4_SYSV_ABI sceNetGetMacAddress() {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return ORBIS_OK;
}
@ -781,46 +655,9 @@ int PS4_SYSV_ABI sceNetGetNameToIndex() {
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetGetpeername(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_getpeername(s, addr, paddrlen);
if (result >= 0) {
return result; // Success
}
err = *Libraries::Kernel::__Error(); // Standard errno
// Convert to positive error for comparison
int positiveErr = (err < 0) ? -err : err;
if ((positiveErr & 0xfff0000) != 0) {
// Unknown/fatal error range
*sceNetErrnoLoc() = ORBIS_NET_ERETURN;
return -positiveErr;
}
// Retry if interrupted
} while (positiveErr == ORBIS_NET_EINTR);
if (positiveErr == ORBIS_NET_EADDRINUSE) {
result = -ORBIS_NET_EBADF;
} else if (positiveErr == ORBIS_NET_EALREADY) {
result = -ORBIS_NET_EINTR;
} else {
result = -positiveErr;
}
*sceNetErrnoLoc() = -result;
return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code
int PS4_SYSV_ABI sceNetGetpeername() {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetGetRandom() {
@ -844,87 +681,13 @@ int PS4_SYSV_ABI sceNetGetSockInfo6() {
}
int PS4_SYSV_ABI sceNetGetsockname(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_getsockname(s, addr, paddrlen);
if (result >= 0) {
return result; // Success
}
err = *Libraries::Kernel::__Error(); // Standard errno
// Convert to positive error for comparison
int positiveErr = (err < 0) ? -err : err;
if ((positiveErr & 0xfff0000) != 0) {
// Unknown/fatal error range
*sceNetErrnoLoc() = ORBIS_NET_ERETURN;
return -positiveErr;
}
// Retry if interrupted
} while (positiveErr == ORBIS_NET_EINTR);
if (positiveErr == ORBIS_NET_EADDRINUSE) {
result = -ORBIS_NET_EBADF;
} else if (positiveErr == ORBIS_NET_EALREADY) {
result = -ORBIS_NET_EINTR;
} else {
result = -positiveErr;
}
*sceNetErrnoLoc() = -result;
return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code
LOG_ERROR(Lib_Net, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetGetsockopt(OrbisNetId s, int level, int optname, void* optval, u32* optlen) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_getsockopt(s, level, optname, optval, optlen);
if (result >= 0) {
return result; // Success
}
err = *Libraries::Kernel::__Error(); // Standard errno
// Convert to positive error for comparison
int positiveErr = (err < 0) ? -err : err;
if ((positiveErr & 0xfff0000) != 0) {
// Unknown/fatal error range
*sceNetErrnoLoc() = ORBIS_NET_ERETURN;
return -positiveErr;
}
// Retry if interrupted
} while (positiveErr == ORBIS_NET_EINTR);
if (positiveErr == ORBIS_NET_EADDRINUSE) {
result = -ORBIS_NET_EBADF;
} else if (positiveErr == ORBIS_NET_EALREADY) {
result = -ORBIS_NET_EINTR;
} else {
result = -positiveErr;
}
*sceNetErrnoLoc() = -result;
return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code
LOG_ERROR(Lib_Net, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetGetStatisticsInfo() {
@ -1018,46 +781,9 @@ int PS4_SYSV_ABI sceNetIoctl() {
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetListen(OrbisNetId s, int backlog) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_listen(s, backlog);
if (result >= 0) {
return result; // Success
}
err = *Libraries::Kernel::__Error(); // Standard errno
// Convert to positive error for comparison
int positiveErr = (err < 0) ? -err : err;
if ((positiveErr & 0xfff0000) != 0) {
// Unknown/fatal error range
*sceNetErrnoLoc() = ORBIS_NET_ERETURN;
return -positiveErr;
}
// Retry if interrupted
} while (positiveErr == ORBIS_NET_EINTR);
if (positiveErr == ORBIS_NET_EADDRINUSE) {
result = -ORBIS_NET_EBADF;
} else if (positiveErr == ORBIS_NET_EALREADY) {
result = -ORBIS_NET_EINTR;
} else {
result = -positiveErr;
}
*sceNetErrnoLoc() = -result;
return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code
int PS4_SYSV_ABI sceNetListen() {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetMemoryAllocate() {
@ -1103,131 +829,20 @@ int PS4_SYSV_ABI sceNetPppoeStop() {
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetRecv(OrbisNetId s, void* buf, u64 len, int flags) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_recvfrom(s, buf, len, flags | 0x40000000, nullptr, 0);
if (result >= 0) {
return result; // Success
}
err = *Libraries::Kernel::__Error(); // Standard errno
// Convert to positive error for comparison
int positiveErr = (err < 0) ? -err : err;
if ((positiveErr & 0xfff0000) != 0) {
// Unknown/fatal error range
*sceNetErrnoLoc() = ORBIS_NET_ERETURN;
return -positiveErr;
}
// Retry if interrupted
} while (positiveErr == ORBIS_NET_EINTR);
if (positiveErr == ORBIS_NET_EADDRINUSE) {
result = -ORBIS_NET_EBADF;
} else if (positiveErr == ORBIS_NET_EALREADY) {
result = -ORBIS_NET_EINTR;
} else {
result = -positiveErr;
}
*sceNetErrnoLoc() = -result;
return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code
int PS4_SYSV_ABI sceNetRecv() {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetRecvfrom(OrbisNetId s, void* buf, u64 len, int flags, OrbisNetSockaddr* addr,
u32* paddrlen) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_recvfrom(s, buf, len, flags | 0x40000000, addr, paddrlen);
if (result >= 0) {
return result; // Success
}
err = *Libraries::Kernel::__Error(); // Standard errno
// Convert to positive error for comparison
int positiveErr = (err < 0) ? -err : err;
if ((positiveErr & 0xfff0000) != 0) {
// Unknown/fatal error range
*sceNetErrnoLoc() = ORBIS_NET_ERETURN;
return -positiveErr;
}
// Retry if interrupted
} while (positiveErr == ORBIS_NET_EINTR);
if (positiveErr == ORBIS_NET_EADDRINUSE) {
result = -ORBIS_NET_EBADF;
} else if (positiveErr == ORBIS_NET_EALREADY) {
result = -ORBIS_NET_EINTR;
} else {
result = -positiveErr;
}
*sceNetErrnoLoc() = -result;
return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code
int PS4_SYSV_ABI sceNetRecvfrom(OrbisNetId s, void* buf, size_t len, int flags,
OrbisNetSockaddr* addr, u32* paddrlen) {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetRecvmsg(OrbisNetId s, OrbisNetMsghdr* msg, int flags) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_recvmsg(s, msg, flags | 0x40000000);
if (result >= 0) {
return result; // Success
}
err = *Libraries::Kernel::__Error(); // Standard errno
// Convert to positive error for comparison
int positiveErr = (err < 0) ? -err : err;
if ((positiveErr & 0xfff0000) != 0) {
// Unknown/fatal error range
*sceNetErrnoLoc() = ORBIS_NET_ERETURN;
return -positiveErr;
}
// Retry if interrupted
} while (positiveErr == ORBIS_NET_EINTR);
if (positiveErr == ORBIS_NET_EADDRINUSE) {
result = -ORBIS_NET_EBADF;
} else if (positiveErr == ORBIS_NET_EALREADY) {
result = -ORBIS_NET_EINTR;
} else {
result = -positiveErr;
}
*sceNetErrnoLoc() = -result;
return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code
int PS4_SYSV_ABI sceNetRecvmsg() {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetResolverAbort() {
@ -1300,131 +915,19 @@ int PS4_SYSV_ABI sceNetResolverStartNtoaMultipleRecordsEx() {
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetSend(OrbisNetId s, const void* buf, u64 len, int flags) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_sendto(s, buf, len, flags | 0x40020000, nullptr, 0);
if (result >= 0) {
return result; // Success
}
err = *Libraries::Kernel::__Error(); // Standard errno
// Convert to positive error for comparison
int positiveErr = (err < 0) ? -err : err;
if ((positiveErr & 0xfff0000) != 0) {
// Unknown/fatal error range
*sceNetErrnoLoc() = ORBIS_NET_ERETURN;
return -positiveErr;
}
// Retry if interrupted
} while (positiveErr == ORBIS_NET_EINTR);
if (positiveErr == ORBIS_NET_EADDRINUSE) {
result = -ORBIS_NET_EBADF;
} else if (positiveErr == ORBIS_NET_EALREADY) {
result = -ORBIS_NET_EINTR;
} else {
result = -positiveErr;
}
*sceNetErrnoLoc() = -result;
return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code
int PS4_SYSV_ABI sceNetSend() {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetSendmsg(OrbisNetId s, const OrbisNetMsghdr* msg, int flags) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_sendmsg(s, msg, flags | 0x40020000);
if (result >= 0) {
return result; // Success
}
err = *Libraries::Kernel::__Error(); // Standard errno
// Convert to positive error for comparison
int positiveErr = (err < 0) ? -err : err;
if ((positiveErr & 0xfff0000) != 0) {
// Unknown/fatal error range
*sceNetErrnoLoc() = ORBIS_NET_ERETURN;
return -positiveErr;
}
// Retry if interrupted
} while (positiveErr == ORBIS_NET_EINTR);
if (positiveErr == ORBIS_NET_EADDRINUSE) {
result = -ORBIS_NET_EBADF;
} else if (positiveErr == ORBIS_NET_EALREADY) {
result = -ORBIS_NET_EINTR;
} else {
result = -positiveErr;
}
*sceNetErrnoLoc() = -result;
return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code
int PS4_SYSV_ABI sceNetSendmsg() {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetSendto(OrbisNetId s, const void* buf, u64 len, int flags,
const OrbisNetSockaddr* addr, u32 addrlen) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_sendto(s, buf, len, flags | 0x40020000, addr, addrlen);
if (result >= 0) {
return result; // Success
}
err = *Libraries::Kernel::__Error(); // Standard errno
// Convert to positive error for comparison
int positiveErr = (err < 0) ? -err : err;
if ((positiveErr & 0xfff0000) != 0) {
// Unknown/fatal error range
*sceNetErrnoLoc() = ORBIS_NET_ERETURN;
return -positiveErr;
}
// Retry if interrupted
} while (positiveErr == ORBIS_NET_EINTR);
if (positiveErr == ORBIS_NET_EADDRINUSE) {
result = -ORBIS_NET_EBADF;
} else if (positiveErr == ORBIS_NET_EALREADY) {
result = -ORBIS_NET_EINTR;
} else {
result = -positiveErr;
}
*sceNetErrnoLoc() = -result;
return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code
int PS4_SYSV_ABI sceNetSendto() {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetSetDns6Info() {
@ -1447,47 +950,9 @@ int PS4_SYSV_ABI sceNetSetDnsInfoToKernel() {
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetSetsockopt(OrbisNetId s, int level, int optname, const void* optval,
u32 optlen) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_setsockopt(s, level, optname, optval, optlen);
if (result >= 0) {
return result; // Success
}
err = *Libraries::Kernel::__Error(); // Standard errno
// Convert to positive error for comparison
int positiveErr = (err < 0) ? -err : err;
if ((positiveErr & 0xfff0000) != 0) {
// Unknown/fatal error range
*sceNetErrnoLoc() = ORBIS_NET_ERETURN;
return -positiveErr;
}
// Retry if interrupted
} while (positiveErr == ORBIS_NET_EINTR);
if (positiveErr == ORBIS_NET_EADDRINUSE) {
result = -ORBIS_NET_EBADF;
} else if (positiveErr == ORBIS_NET_EALREADY) {
result = -ORBIS_NET_EINTR;
} else {
result = -positiveErr;
}
*sceNetErrnoLoc() = -result;
return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code
int PS4_SYSV_ABI sceNetSetsockopt() {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetShowIfconfig() {
@ -1570,172 +1035,24 @@ int PS4_SYSV_ABI sceNetShowRouteWithMemory() {
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetShutdown(OrbisNetId s, int how) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_shutdown(s, how);
if (result >= 0) {
return result; // Success
}
err = *Libraries::Kernel::__Error(); // Standard errno
// Convert to positive error for comparison
int positiveErr = (err < 0) ? -err : err;
if ((positiveErr & 0xfff0000) != 0) {
// Unknown/fatal error range
*sceNetErrnoLoc() = ORBIS_NET_ERETURN;
return -positiveErr;
}
// Retry if interrupted
} while (positiveErr == ORBIS_NET_EINTR);
if (positiveErr == ORBIS_NET_EADDRINUSE) {
result = -ORBIS_NET_EBADF;
} else if (positiveErr == ORBIS_NET_EALREADY) {
result = -ORBIS_NET_EINTR;
} else {
result = -positiveErr;
}
*sceNetErrnoLoc() = -result;
return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code
int PS4_SYSV_ABI sceNetShutdown() {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return ORBIS_OK;
}
OrbisNetId PS4_SYSV_ABI sceNetSocket(const char* name, int family, int type, int protocol) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_socketex(name, family, type, protocol);
if (result >= 0) {
return result; // Success
}
err = *Libraries::Kernel::__Error(); // Standard errno
// Convert to positive error for comparison
int positiveErr = (err < 0) ? -err : err;
if ((positiveErr & 0xfff0000) != 0) {
// Unknown/fatal error range
*sceNetErrnoLoc() = ORBIS_NET_ERETURN;
return -positiveErr;
}
// Retry if interrupted
} while (positiveErr == ORBIS_NET_EINTR);
if (positiveErr == ORBIS_NET_EADDRINUSE) {
result = -ORBIS_NET_EBADF;
} else if (positiveErr == ORBIS_NET_EALREADY) {
result = -ORBIS_NET_EINTR;
} else {
result = -positiveErr;
}
*sceNetErrnoLoc() = -result;
return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code
int PS4_SYSV_ABI sceNetSocket(const char* name, int family, int type, int protocol) {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetSocketAbort(OrbisNetId s, int flags) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_netabort(s, flags);
if (result >= 0) {
return result; // Success
}
err = *Libraries::Kernel::__Error(); // Standard errno
// Convert to positive error for comparison
int positiveErr = (err < 0) ? -err : err;
if ((positiveErr & 0xfff0000) != 0) {
// Unknown/fatal error range
*sceNetErrnoLoc() = ORBIS_NET_ERETURN;
return -positiveErr;
}
// Retry if interrupted
} while (positiveErr == ORBIS_NET_EINTR);
if (positiveErr == ORBIS_NET_EADDRINUSE) {
result = -ORBIS_NET_EBADF;
} else if (positiveErr == ORBIS_NET_EALREADY) {
result = -ORBIS_NET_EINTR;
} else {
result = -positiveErr;
}
*sceNetErrnoLoc() = -result;
return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code
int PS4_SYSV_ABI sceNetSocketAbort() {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetSocketClose(OrbisNetId s) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_socketclose(s);
if (result >= 0) {
return result; // Success
}
err = *Libraries::Kernel::__Error(); // Standard errno
// Convert to positive error for comparison
int positiveErr = (err < 0) ? -err : err;
if ((positiveErr & 0xfff0000) != 0) {
// Unknown/fatal error range
*sceNetErrnoLoc() = ORBIS_NET_ERETURN;
return -positiveErr;
}
// Retry if interrupted
} while (positiveErr == ORBIS_NET_EINTR);
if (positiveErr == ORBIS_NET_EADDRINUSE) {
result = -ORBIS_NET_EBADF;
} else if (positiveErr == ORBIS_NET_EALREADY) {
result = -ORBIS_NET_EINTR;
} else {
result = -positiveErr;
}
*sceNetErrnoLoc() = -result;
return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code
int PS4_SYSV_ABI sceNetSocketClose() {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceNetSyncCreate() {

View file

@ -4,7 +4,6 @@
#pragma once
#include "common/types.h"
#include "netctl.h"
namespace Core::Loader {
class SymbolsResolver;
@ -20,63 +19,6 @@ class SymbolsResolver;
namespace Libraries::Net {
enum OrbisNetSocketType : u32 {
ORBIS_NET_SOCK_STREAM = 1,
ORBIS_NET_SOCK_DGRAM = 2,
ORBIS_NET_SOCK_RAW = 3,
ORBIS_NET_SOCK_DGRAM_P2P = 6,
ORBIS_NET_SOCK_STREAM_P2P = 10
};
enum OrbisNetProtocol : u32 {
ORBIS_NET_IPPROTO_IP = 0,
ORBIS_NET_IPPROTO_ICMP = 1,
ORBIS_NET_IPPROTO_IGMP = 2,
ORBIS_NET_IPPROTO_TCP = 6,
ORBIS_NET_IPPROTO_UDP = 17,
ORBIS_NET_SOL_SOCKET = 0xFFFF
};
enum OrbisNetSocketOption : u32 {
/* IP */
ORBIS_NET_IP_HDRINCL = 2,
ORBIS_NET_IP_TOS = 3,
ORBIS_NET_IP_TTL = 4,
ORBIS_NET_IP_MULTICAST_IF = 9,
ORBIS_NET_IP_MULTICAST_TTL = 10,
ORBIS_NET_IP_MULTICAST_LOOP = 11,
ORBIS_NET_IP_ADD_MEMBERSHIP = 12,
ORBIS_NET_IP_DROP_MEMBERSHIP = 13,
ORBIS_NET_IP_TTLCHK = 23,
ORBIS_NET_IP_MAXTTL = 24,
/* TCP */
ORBIS_NET_TCP_NODELAY = 1,
ORBIS_NET_TCP_MAXSEG = 2,
ORBIS_NET_TCP_MSS_TO_ADVERTISE = 3,
/* SOCKET */
ORBIS_NET_SO_REUSEADDR = 0x00000004,
ORBIS_NET_SO_KEEPALIVE = 0x00000008,
ORBIS_NET_SO_BROADCAST = 0x00000020,
ORBIS_NET_SO_LINGER = 0x00000080,
ORBIS_NET_SO_REUSEPORT = 0x00000200,
ORBIS_NET_SO_ONESBCAST = 0x00010000,
ORBIS_NET_SO_USECRYPTO = 0x00020000,
ORBIS_NET_SO_USESIGNATURE = 0x00040000,
ORBIS_NET_SO_SNDBUF = 0x1001,
ORBIS_NET_SO_RCVBUF = 0x1002,
ORBIS_NET_SO_ERROR = 0x1007,
ORBIS_NET_SO_TYPE = 0x1008,
ORBIS_NET_SO_SNDTIMEO = 0x1105,
ORBIS_NET_SO_RCVTIMEO = 0x1106,
ORBIS_NET_SO_ERROR_EX = 0x1107,
ORBIS_NET_SO_ACCEPTTIMEO = 0x1108,
ORBIS_NET_SO_CONNECTTIMEO = 0x1109,
ORBIS_NET_SO_NBIO = 0x1200,
ORBIS_NET_SO_POLICY = 0x1201,
ORBIS_NET_SO_NAME = 0x1202,
ORBIS_NET_SO_PRIORITY = 0x1203
};
using OrbisNetId = s32;
struct OrbisNetSockaddr {
@ -85,30 +27,6 @@ struct OrbisNetSockaddr {
char sa_data[14];
};
struct OrbisNetSockaddrIn {
u8 sin_len;
u8 sin_family;
u16 sin_port;
u32 sin_addr;
u16 sin_vport;
char sin_zero[6];
};
struct OrbisNetIovec {
void* iov_base;
u64 iov_len;
};
struct OrbisNetMsghdr {
void* msg_name;
u32 msg_namelen;
OrbisNetIovec* msg_iov;
int msg_iovlen;
void* msg_control;
u32 msg_controllen;
int msg_flags;
};
int PS4_SYSV_ABI in6addr_any();
int PS4_SYSV_ABI in6addr_loopback();
int PS4_SYSV_ABI sce_net_dummy();
@ -198,7 +116,7 @@ int PS4_SYSV_ABI sceNetConfigWlanInfraLeave();
int PS4_SYSV_ABI sceNetConfigWlanInfraScanJoin();
int PS4_SYSV_ABI sceNetConfigWlanScan();
int PS4_SYSV_ABI sceNetConfigWlanSetDeviceConfig();
int PS4_SYSV_ABI sceNetConnect(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addrlen);
int PS4_SYSV_ABI sceNetConnect();
int PS4_SYSV_ABI sceNetControl();
int PS4_SYSV_ABI sceNetDhcpdStart();
int PS4_SYSV_ABI sceNetDhcpdStop();
@ -233,10 +151,10 @@ int PS4_SYSV_ABI sceNetGetIfList();
int PS4_SYSV_ABI sceNetGetIfListOnce();
int PS4_SYSV_ABI sceNetGetIfName();
int PS4_SYSV_ABI sceNetGetIfnameNumList();
int PS4_SYSV_ABI sceNetGetMacAddress(Libraries::NetCtl::OrbisNetEtherAddr* addr, int flags);
int PS4_SYSV_ABI sceNetGetMacAddress();
int PS4_SYSV_ABI sceNetGetMemoryPoolStats();
int PS4_SYSV_ABI sceNetGetNameToIndex();
int PS4_SYSV_ABI sceNetGetpeername(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen);
int PS4_SYSV_ABI sceNetGetpeername();
int PS4_SYSV_ABI sceNetGetRandom();
int PS4_SYSV_ABI sceNetGetRouteInfo();
int PS4_SYSV_ABI sceNetGetSockInfo();
@ -259,7 +177,7 @@ int PS4_SYSV_ABI sceNetInfoDumpStop();
int PS4_SYSV_ABI sceNetInit();
int PS4_SYSV_ABI sceNetInitParam();
int PS4_SYSV_ABI sceNetIoctl();
int PS4_SYSV_ABI sceNetListen(OrbisNetId s, int backlog);
int PS4_SYSV_ABI sceNetListen();
int PS4_SYSV_ABI sceNetMemoryAllocate();
int PS4_SYSV_ABI sceNetMemoryFree();
u32 PS4_SYSV_ABI sceNetNtohl(u32 net32);
@ -269,10 +187,10 @@ int PS4_SYSV_ABI sceNetPoolCreate(const char* name, int size, int flags);
int PS4_SYSV_ABI sceNetPoolDestroy();
int PS4_SYSV_ABI sceNetPppoeStart();
int PS4_SYSV_ABI sceNetPppoeStop();
int PS4_SYSV_ABI sceNetRecv(OrbisNetId s, void* buf, u64 len, int flags);
int PS4_SYSV_ABI sceNetRecvfrom(OrbisNetId s, void* buf, u64 len, int flags, OrbisNetSockaddr* addr,
u32* paddrlen);
int PS4_SYSV_ABI sceNetRecvmsg(OrbisNetId s, OrbisNetMsghdr* msg, int flags);
int PS4_SYSV_ABI sceNetRecv();
int PS4_SYSV_ABI sceNetRecvfrom(OrbisNetId s, void* buf, size_t len, int flags,
OrbisNetSockaddr* addr, u32* paddrlen);
int PS4_SYSV_ABI sceNetRecvmsg();
int PS4_SYSV_ABI sceNetResolverAbort();
int PS4_SYSV_ABI sceNetResolverConnect();
int PS4_SYSV_ABI sceNetResolverConnectAbort();
@ -287,16 +205,14 @@ int PS4_SYSV_ABI sceNetResolverStartNtoa();
int PS4_SYSV_ABI sceNetResolverStartNtoa6();
int PS4_SYSV_ABI sceNetResolverStartNtoaMultipleRecords();
int PS4_SYSV_ABI sceNetResolverStartNtoaMultipleRecordsEx();
int PS4_SYSV_ABI sceNetSend(OrbisNetId s, const void* buf, u64 len, int flags);
int PS4_SYSV_ABI sceNetSendmsg(OrbisNetId s, const OrbisNetMsghdr* msg, int flags);
int PS4_SYSV_ABI sceNetSendto(OrbisNetId s, const void* buf, u64 len, int flags,
const OrbisNetSockaddr* addr, u32 addrlen);
int PS4_SYSV_ABI sceNetSend();
int PS4_SYSV_ABI sceNetSendmsg();
int PS4_SYSV_ABI sceNetSendto();
int PS4_SYSV_ABI sceNetSetDns6Info();
int PS4_SYSV_ABI sceNetSetDns6InfoToKernel();
int PS4_SYSV_ABI sceNetSetDnsInfo();
int PS4_SYSV_ABI sceNetSetDnsInfoToKernel();
int PS4_SYSV_ABI sceNetSetsockopt(OrbisNetId s, int level, int optname, const void* optval,
u32 optlen);
int PS4_SYSV_ABI sceNetSetsockopt();
int PS4_SYSV_ABI sceNetShowIfconfig();
int PS4_SYSV_ABI sceNetShowIfconfigForBuffer();
int PS4_SYSV_ABI sceNetShowIfconfigWithMemory();
@ -313,10 +229,10 @@ int PS4_SYSV_ABI sceNetShowRoute6ForBuffer();
int PS4_SYSV_ABI sceNetShowRoute6WithMemory();
int PS4_SYSV_ABI sceNetShowRouteForBuffer();
int PS4_SYSV_ABI sceNetShowRouteWithMemory();
int PS4_SYSV_ABI sceNetShutdown(OrbisNetId s, int how);
OrbisNetId PS4_SYSV_ABI sceNetSocket(const char* name, int family, int type, int protocol);
int PS4_SYSV_ABI sceNetSocketAbort(OrbisNetId s, int flags);
int PS4_SYSV_ABI sceNetSocketClose(OrbisNetId s);
int PS4_SYSV_ABI sceNetShutdown();
int PS4_SYSV_ABI sceNetSocket(const char* name, int family, int type, int protocol);
int PS4_SYSV_ABI sceNetSocketAbort();
int PS4_SYSV_ABI sceNetSocketClose();
int PS4_SYSV_ABI sceNetSyncCreate();
int PS4_SYSV_ABI sceNetSyncDestroy();
int PS4_SYSV_ABI sceNetSyncGet();

View file

@ -1,162 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
// net errno codes
constexpr int ORBIS_NET_EPERM = 1;
constexpr int ORBIS_NET_ENOENT = 2;
constexpr int ORBIS_NET_EINTR = 4;
constexpr int ORBIS_NET_EBADF = 9;
constexpr int ORBIS_NET_EACCES = 13;
constexpr int ORBIS_NET_EFAULT = 14;
constexpr int ORBIS_NET_ENOTBLK = 15;
constexpr int ORBIS_NET_EBUSY = 16;
constexpr int ORBIS_NET_EEXIST = 17;
constexpr int ORBIS_NET_ENODEV = 19;
constexpr int ORBIS_NET_EINVAL = 22;
constexpr int ORBIS_NET_EMFILE = 24;
constexpr int ORBIS_NET_ENOSPC = 28;
constexpr int ORBIS_NET_EPIPE = 32;
constexpr int ORBIS_NET_EAGAIN = 35;
constexpr int ORBIS_NET_EWOULDBLOCK = 35;
constexpr int ORBIS_NET_EINPROGRESS = 36;
constexpr int ORBIS_NET_EALREADY = 37;
constexpr int ORBIS_NET_ENOTSOCK = 38;
constexpr int ORBIS_NET_EDESTADDRREQ = 39;
constexpr int ORBIS_NET_EMSGSIZE = 40;
constexpr int ORBIS_NET_EPROTOTYPE = 41;
constexpr int ORBIS_NET_ENOPROTOOPT = 42;
constexpr int ORBIS_NET_EPROTONOSUPPORT = 43;
constexpr int ORBIS_NET_EOPNOTSUPP = 45;
constexpr int ORBIS_NET_EAFNOSUPPORT = 47;
constexpr int ORBIS_NET_EADDRINUSE = 48;
constexpr int ORBIS_NET_EADDRNOTAVAIL = 49;
constexpr int ORBIS_NET_ENETDOWN = 50;
constexpr int ORBIS_NET_ENETUNREACH = 51;
constexpr int ORBIS_NET_ENETRESET = 52;
constexpr int ORBIS_NET_ECONNABORTED = 53;
constexpr int ORBIS_NET_ECONNRESET = 54;
constexpr int ORBIS_NET_EISCONN = 56;
constexpr int ORBIS_NET_ENOTCONN = 57;
constexpr int ORBIS_NET_ETOOMANYREFS = 59;
constexpr int ORBIS_NET_ETIMEDOUT = 60;
constexpr int ORBIS_NET_ECONNREFUSED = 61;
constexpr int ORBIS_NET_ELOOP = 62;
constexpr int ORBIS_NET_ENAMETOOLONG = 63;
constexpr int ORBIS_NET_EHOSTDOWN = 64;
constexpr int ORBIS_NET_EHOSTUNREACH = 65;
constexpr int ORBIS_NET_ENOTEMPTY = 66;
constexpr int ORBIS_NET_EPROCUNAVAIL = 76;
constexpr int ORBIS_NET_EPROTO = 92;
constexpr int ORBIS_NET_EADHOC = 160;
constexpr int ORBIS_NET_EINACTIVEDISABLED = 163;
constexpr int ORBIS_NET_ENODATA = 164;
constexpr int ORBIS_NET_EDESC = 165;
constexpr int ORBIS_NET_EDESCTIMEDOUT = 166;
constexpr int ORBIS_NET_ENOTINIT = 200;
constexpr int ORBIS_NET_ENOLIBMEM = 201;
constexpr int ORBIS_NET_ECALLBACK = 203;
constexpr int ORBIS_NET_EINTERNAL = 204;
constexpr int ORBIS_NET_ERETURN = 205;
constexpr int ORBIS_NET_ENOALLOCMEM = 206;
// errno for dns resolver
constexpr int ORBIS_NET_RESOLVER_EINTERNAL = 220;
constexpr int ORBIS_NET_RESOLVER_EBUSY = 221;
constexpr int ORBIS_NET_RESOLVER_ENOSPACE = 222;
constexpr int ORBIS_NET_RESOLVER_EPACKET = 223;
constexpr int ORBIS_NET_RESOLVER_ENODNS = 225;
constexpr int ORBIS_NET_RESOLVER_ETIMEDOUT = 226;
constexpr int ORBIS_NET_RESOLVER_ENOSUPPORT = 227;
constexpr int ORBIS_NET_RESOLVER_EFORMAT = 228;
constexpr int ORBIS_NET_RESOLVER_ESERVERFAILURE = 229;
constexpr int ORBIS_NET_RESOLVER_ENOHOST = 230;
constexpr int ORBIS_NET_RESOLVER_ENOTIMPLEMENTED = 231;
constexpr int ORBIS_NET_RESOLVER_ESERVERREFUSED = 232;
constexpr int ORBIS_NET_RESOLVER_ENORECORD = 233;
constexpr int ORBIS_NET_RESOLVER_EALIGNMENT = 234;
// common errno
constexpr int ORBIS_NET_ENOMEM = 12;
constexpr int ORBIS_NET_ENOBUFS = 55;
// error codes
constexpr int ORBIS_NET_ERROR_BASE = 0x80410100; // not existed used for calculation
constexpr int ORBIS_NET_ERROR_EPERM = 0x80410101;
constexpr int ORBIS_NET_ERROR_ENOENT = 0x80410102;
constexpr int ORBIS_NET_ERROR_EINTR = 0x80410104;
constexpr int ORBIS_NET_ERROR_EBADF = 0x80410109;
constexpr int ORBIS_NET_ERROR_ENOMEM = 0x8041010c;
constexpr int ORBIS_NET_ERROR_EACCES = 0x8041010d;
constexpr int ORBIS_NET_ERROR_EFAULT = 0x8041010e;
constexpr int ORBIS_NET_ERROR_ENOTBLK = 0x8041010f;
constexpr int ORBIS_NET_ERROR_EEXIST = 0x80410111;
constexpr int ORBIS_NET_ERROR_ENODEV = 0x80410113;
constexpr int ORBIS_NET_ERROR_EINVAL = 0x80410116;
constexpr int ORBIS_NET_ERROR_ENFILE = 0x80410117;
constexpr int ORBIS_NET_ERROR_EMFILE = 0x80410118;
constexpr int ORBIS_NET_ERROR_ENOSPC = 0x8041011c;
constexpr int ORBIS_NET_ERROR_EPIPE = 0x80410120;
constexpr int ORBIS_NET_ERROR_EAGAIN = 0x80410123;
constexpr int ORBIS_NET_ERROR_EWOULDBLOCK = 0x80410123;
constexpr int ORBIS_NET_ERROR_EINPROGRESS = 0x80410124;
constexpr int ORBIS_NET_ERROR_EALREADY = 0x80410125;
constexpr int ORBIS_NET_ERROR_ENOTSOCK = 0x80410126;
constexpr int ORBIS_NET_ERROR_EDESTADDRREQ = 0x80410127;
constexpr int ORBIS_NET_ERROR_EMSGSIZE = 0x80410128;
constexpr int ORBIS_NET_ERROR_EPROTOTYPE = 0x80410129;
constexpr int ORBIS_NET_ERROR_ENOPROTOOPT = 0x8041012a;
constexpr int ORBIS_NET_ERROR_EPROTONOSUPPORT = 0x8041012b;
constexpr int ORBIS_NET_ERROR_EOPNOTSUPP = 0x8041012d;
constexpr int ORBIS_NET_ERROR_EPFNOSUPPORT = 0x8041012e;
constexpr int ORBIS_NET_ERROR_EAFNOSUPPORT = 0x8041012f;
constexpr int ORBIS_NET_ERROR_EADDRINUSE = 0x80410130;
constexpr int ORBIS_NET_ERROR_EADDRNOTAVAIL = 0x80410131;
constexpr int ORBIS_NET_ERROR_ENETDOWN = 0x80410132;
constexpr int ORBIS_NET_ERROR_ENETUNREACH = 0x80410133;
constexpr int ORBIS_NET_ERROR_ENETRESET = 0x80410134;
constexpr int ORBIS_NET_ERROR_ECONNABORTED = 0x80410135;
constexpr int ORBIS_NET_ERROR_ECONNRESET = 0x80410136;
constexpr int ORBIS_NET_ERROR_ENOBUFS = 0x80410137;
constexpr int ORBIS_NET_ERROR_EISCONN = 0x80410138;
constexpr int ORBIS_NET_ERROR_ENOTCONN = 0x80410139;
constexpr int ORBIS_NET_ERROR_ESHUTDOWN = 0x8041013a;
constexpr int ORBIS_NET_ERROR_ETOOMANYREFS = 0x8041013b;
constexpr int ORBIS_NET_ERROR_ETIMEDOUT = 0x8041013c;
constexpr int ORBIS_NET_ERROR_ECONNREFUSED = 0x8041013d;
constexpr int ORBIS_NET_ERROR_ELOOP = 0x8041013e;
constexpr int ORBIS_NET_ERROR_ENAMETOOLONG = 0x8041013f;
constexpr int ORBIS_NET_ERROR_EHOSTDOWN = 0x80410140;
constexpr int ORBIS_NET_ERROR_EHOSTUNREACH = 0x80410141;
constexpr int ORBIS_NET_ERROR_ENOTEMPTY = 0x80410142;
constexpr int ORBIS_NET_ERROR_EPROCUNAVAIL = 0x8041014C;
constexpr int ORBIS_NET_ERROR_ECANCELED = 0x80410157;
constexpr int ORBIS_NET_ERROR_EPROTO = 0x8041015C;
constexpr int ORBIS_NET_ERROR_EADHOC = 0x804101a0;
constexpr int ORBIS_NET_ERROR_ERESERVED161 = 0x804101a1;
constexpr int ORBIS_NET_ERROR_ERESERVED162 = 0x804101a2;
constexpr int ORBIS_NET_ERROR_EINACTIVEDISABLED = 0x804101a3;
constexpr int ORBIS_NET_ERROR_ENODATA = 0x804101a4;
constexpr int ORBIS_NET_ERROR_EDESC = 0x804101a5;
constexpr int ORBIS_NET_ERROR_EDESCTIMEDOUT = 0x804101a6;
constexpr int ORBIS_NET_ERROR_ENOTINIT = 0x804101c8;
constexpr int ORBIS_NET_ERROR_ENOLIBMEM = 0x804101c9;
constexpr int ORBIS_NET_ERROR_ECALLBACK = 0x804101cb;
constexpr int ORBIS_NET_ERROR_EINTERNAL = 0x804101cc;
constexpr int ORBIS_NET_ERROR_ERETURN = 0x804101cd;
constexpr int ORBIS_NET_ERROR_ENOALLOCMEM = 0x804101ce;
constexpr int ORBIS_NET_ERROR_RESOLVER_EINTERNAL = 0x804101dc;
constexpr int ORBIS_NET_ERROR_RESOLVER_EBUSY = 0x804101dd;
constexpr int ORBIS_NET_ERROR_RESOLVER_ENOSPACE = 0x804101de;
constexpr int ORBIS_NET_ERROR_RESOLVER_EPACKET = 0x804101df;
constexpr int ORBIS_NET_ERROR_RESOLVER_ENODNS = 0x804101e1;
constexpr int ORBIS_NET_ERROR_RESOLVER_ETIMEDOUT = 0x804101e2;
constexpr int ORBIS_NET_ERROR_RESOLVER_ENOSUPPORT = 0x804101e3;
constexpr int ORBIS_NET_ERROR_RESOLVER_EFORMAT = 0x804101e4;
constexpr int ORBIS_NET_ERROR_RESOLVER_ESERVERFAILURE = 0x804101e5;
constexpr int ORBIS_NET_ERROR_RESOLVER_ENOHOST = 0x804101e6;
constexpr int ORBIS_NET_ERROR_RESOLVER_ENOTIMPLEMENTED = 0x804101e7;
constexpr int ORBIS_NET_ERROR_RESOLVER_ESERVERREFUSED = 0x804101e8;
constexpr int ORBIS_NET_ERROR_RESOLVER_ENORECORD = 0x804101e9;
constexpr int ORBIS_NET_ERROR_RESOLVER_EALIGNMENT = 0x804101ea;

View file

@ -1,110 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#ifdef _WIN32
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <Ws2tcpip.h>
#include <iphlpapi.h>
#include <winsock2.h>
typedef SOCKET net_socket;
typedef int socklen_t;
#else
#include <cerrno>
#include <arpa/inet.h>
#include <net/if.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>
typedef int net_socket;
#endif
#if defined(__APPLE__)
#include <ifaddrs.h>
#include <net/if_dl.h>
#endif
#include <map>
#include <memory>
#include <mutex>
#include <vector>
#include <string.h>
#include "net_util.h"
namespace NetUtil {
const std::array<u8, 6>& NetUtilInternal::GetEthernetAddr() const {
return ether_address;
}
bool NetUtilInternal::RetrieveEthernetAddr() {
std::scoped_lock lock{m_mutex};
#ifdef _WIN32
std::vector<u8> adapter_infos(sizeof(IP_ADAPTER_INFO));
ULONG size_infos = sizeof(IP_ADAPTER_INFO);
if (GetAdaptersInfo(reinterpret_cast<PIP_ADAPTER_INFO>(adapter_infos.data()), &size_infos) ==
ERROR_BUFFER_OVERFLOW)
adapter_infos.resize(size_infos);
if (GetAdaptersInfo(reinterpret_cast<PIP_ADAPTER_INFO>(adapter_infos.data()), &size_infos) ==
NO_ERROR &&
size_infos) {
PIP_ADAPTER_INFO info = reinterpret_cast<PIP_ADAPTER_INFO>(adapter_infos.data());
memcpy(ether_address.data(), info[0].Address, 6);
return true;
}
#elif defined(__APPLE__)
ifaddrs* ifap;
if (getifaddrs(&ifap) == 0) {
ifaddrs* p;
for (p = ifap; p; p = p->ifa_next) {
if (p->ifa_addr->sa_family == AF_LINK) {
sockaddr_dl* sdp = reinterpret_cast<sockaddr_dl*>(p->ifa_addr);
memcpy(ether_address.data(), sdp->sdl_data + sdp->sdl_nlen, 6);
freeifaddrs(ifap);
return true;
}
}
freeifaddrs(ifap);
}
#else
ifreq ifr;
ifconf ifc;
char buf[1024];
int success = 0;
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sock == -1)
return false;
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;
if (ioctl(sock, SIOCGIFCONF, &ifc) == -1)
return false;
ifreq* it = ifc.ifc_req;
const ifreq* const end = it + (ifc.ifc_len / sizeof(ifreq));
for (; it != end; ++it) {
strcpy(ifr.ifr_name, it->ifr_name);
if (ioctl(sock, SIOCGIFFLAGS, &ifr) == 0) {
if (!(ifr.ifr_flags & IFF_LOOPBACK)) {
if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0) {
success = 1;
break;
}
}
}
}
if (success) {
memcpy(ether_address.data(), ifr.ifr_hwaddr.sa_data, 6);
return true;
}
#endif
return false;
}
} // namespace NetUtil

View file

@ -1,24 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <mutex>
#include "common/types.h"
namespace NetUtil {
class NetUtilInternal {
public:
explicit NetUtilInternal() = default;
~NetUtilInternal() = default;
private:
std::array<u8, 6> ether_address{};
std::mutex m_mutex;
public:
const std::array<u8, 6>& GetEthernetAddr() const;
bool RetrieveEthernetAddr();
};
} // namespace NetUtil

View file

@ -12,13 +12,11 @@
#include <unistd.h>
#endif
#include <common/singleton.h>
#include "common/logging/log.h"
#include "core/libraries/error_codes.h"
#include "core/libraries/libs.h"
#include "core/libraries/network/net_ctl_codes.h"
#include "core/libraries/network/netctl.h"
#include "net_util.h"
namespace Libraries::NetCtl {
@ -164,14 +162,6 @@ int PS4_SYSV_ABI sceNetCtlGetInfo(int code, OrbisNetCtlInfo* info) {
case ORBIS_NET_CTL_INFO_DEVICE:
info->device = ORBIS_NET_CTL_DEVICE_WIRED;
break;
case ORBIS_NET_CTL_INFO_ETHER_ADDR: {
auto* netinfo = Common::Singleton<NetUtil::NetUtilInternal>::Instance();
netinfo->RetrieveEthernetAddr();
memcpy(info->ether_addr.data, netinfo->GetEthernetAddr().data(), 6);
} break;
case ORBIS_NET_CTL_INFO_MTU:
info->mtu = 1500; // default value
break;
case ORBIS_NET_CTL_INFO_LINK:
info->link = ORBIS_NET_CTL_LINK_DISCONNECTED;
break;
@ -193,7 +183,6 @@ int PS4_SYSV_ABI sceNetCtlGetInfo(int code, OrbisNetCtlInfo* info) {
}
break;
}
default:
LOG_ERROR(Lib_NetCtl, "{} unsupported code", code);
}

View file

@ -49,26 +49,8 @@ union OrbisNetCtlInfo {
// GetInfo codes
constexpr int ORBIS_NET_CTL_INFO_DEVICE = 1;
constexpr int ORBIS_NET_CTL_INFO_ETHER_ADDR = 2;
constexpr int ORBIS_NET_CTL_INFO_MTU = 3;
constexpr int ORBIS_NET_CTL_INFO_LINK = 4;
constexpr int ORBIS_NET_CTL_INFO_BSSID = 5;
constexpr int ORBIS_NET_CTL_INFO_SSID = 6;
constexpr int ORBIS_NET_CTL_INFO_WIFI_SECURITY = 7;
constexpr int ORBIS_NET_CTL_INFO_RSSI_DBM = 8;
constexpr int ORBIS_NET_CTL_INFO_RSSI_PERCENTAGE = 9;
constexpr int ORBIS_NET_CTL_INFO_CHANNEL = 10;
constexpr int ORBIS_NET_CTL_INFO_IP_CONFIG = 11;
constexpr int ORBIS_NET_CTL_INFO_DHCP_HOSTNAME = 12;
constexpr int ORBIS_NET_CTL_INFO_PPPOE_AUTH_NAME = 13;
constexpr int ORBIS_NET_CTL_INFO_IP_ADDRESS = 14;
constexpr int ORBIS_NET_CTL_INFO_NETMASK = 15;
constexpr int ORBIS_NET_CTL_INFO_DEFAULT_ROUTE = 16;
constexpr int ORBIS_NET_CTL_INFO_PRIMARY_DNS = 17;
constexpr int ORBIS_NET_CTL_INFO_SECONDARY_DNS = 18;
constexpr int ORBIS_NET_CTL_INFO_HTTP_PROXY_CONFIG = 19;
constexpr int ORBIS_NET_CTL_INFO_HTTP_PROXY_SERVER = 20;
constexpr int ORBIS_NET_CTL_INFO_HTTP_PROXY_PORT = 21;
int PS4_SYSV_ABI sceNetBweCheckCallbackIpcInt();
int PS4_SYSV_ABI sceNetBweClearEventIpcInt();

View file

@ -1,60 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <common/assert.h>
#include "net.h"
#include "net_error.h"
#include "sockets.h"
namespace Libraries::Net {
int P2PSocket::Close() {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return -1;
}
int P2PSocket::SetSocketOptions(int level, int optname, const void* optval, u32 optlen) {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return -1;
}
int P2PSocket::GetSocketOptions(int level, int optname, void* optval, u32* optlen) {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return -1;
}
int P2PSocket::Bind(const OrbisNetSockaddr* addr, u32 addrlen) {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return -1;
}
int P2PSocket::Listen(int backlog) {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return -1;
}
int P2PSocket::SendPacket(const void* msg, u32 len, int flags, const OrbisNetSockaddr* to,
u32 tolen) {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return -1;
}
int P2PSocket::ReceivePacket(void* buf, u32 len, int flags, OrbisNetSockaddr* from, u32* fromlen) {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return -1;
}
SocketPtr P2PSocket::Accept(OrbisNetSockaddr* addr, u32* addrlen) {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return nullptr;
}
int P2PSocket::Connect(const OrbisNetSockaddr* addr, u32 namelen) {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return -1;
}
int P2PSocket::GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return -1;
}
} // namespace Libraries::Net

View file

@ -1,359 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <common/assert.h>
#include "net.h"
#include "net_error.h"
#include "sockets.h"
namespace Libraries::Net {
#ifdef _WIN32
#define ERROR_CASE(errname) \
case (WSA##errname): \
return ORBIS_NET_ERROR_##errname;
#else
#define ERROR_CASE(errname) \
case (errname): \
return ORBIS_NET_ERROR_##errname;
#endif
static int ConvertReturnErrorCode(int retval) {
if (retval < 0) {
#ifdef _WIN32
switch (WSAGetLastError()) {
#else
switch (errno) {
#endif
#ifndef _WIN32 // These errorcodes don't exist in WinSock
ERROR_CASE(EPERM)
ERROR_CASE(ENOENT)
// ERROR_CASE(ESRCH)
// ERROR_CASE(EIO)
// ERROR_CASE(ENXIO)
// ERROR_CASE(E2BIG)
// ERROR_CASE(ENOEXEC)
// ERROR_CASE(EDEADLK)
ERROR_CASE(ENOMEM)
// ERROR_CASE(ECHILD)
// ERROR_CASE(EBUSY)
ERROR_CASE(EEXIST)
// ERROR_CASE(EXDEV)
ERROR_CASE(ENODEV)
// ERROR_CASE(ENOTDIR)
// ERROR_CASE(EISDIR)
ERROR_CASE(ENFILE)
// ERROR_CASE(ENOTTY)
// ERROR_CASE(ETXTBSY)
// ERROR_CASE(EFBIG)
ERROR_CASE(ENOSPC)
// ERROR_CASE(ESPIPE)
// ERROR_CASE(EROFS)
// ERROR_CASE(EMLINK)
ERROR_CASE(EPIPE)
// ERROR_CASE(EDOM)
// ERROR_CASE(ERANGE)
// ERROR_CASE(ENOLCK)
// ERROR_CASE(ENOSYS)
// ERROR_CASE(EIDRM)
// ERROR_CASE(EOVERFLOW)
// ERROR_CASE(EILSEQ)
// ERROR_CASE(ENOTSUP)
ERROR_CASE(ECANCELED)
// ERROR_CASE(EBADMSG)
ERROR_CASE(ENODATA)
// ERROR_CASE(ENOSR)
// ERROR_CASE(ENOSTR)
// ERROR_CASE(ETIME)
#endif
ERROR_CASE(EINTR)
ERROR_CASE(EBADF)
ERROR_CASE(EACCES)
ERROR_CASE(EFAULT)
ERROR_CASE(EINVAL)
ERROR_CASE(EMFILE)
ERROR_CASE(EWOULDBLOCK)
ERROR_CASE(EINPROGRESS)
ERROR_CASE(EALREADY)
ERROR_CASE(ENOTSOCK)
ERROR_CASE(EDESTADDRREQ)
ERROR_CASE(EMSGSIZE)
ERROR_CASE(EPROTOTYPE)
ERROR_CASE(ENOPROTOOPT)
ERROR_CASE(EPROTONOSUPPORT)
#if defined(__APPLE__) || defined(_WIN32)
ERROR_CASE(EOPNOTSUPP)
#endif
ERROR_CASE(EAFNOSUPPORT)
ERROR_CASE(EADDRINUSE)
ERROR_CASE(EADDRNOTAVAIL)
ERROR_CASE(ENETDOWN)
ERROR_CASE(ENETUNREACH)
ERROR_CASE(ENETRESET)
ERROR_CASE(ECONNABORTED)
ERROR_CASE(ECONNRESET)
ERROR_CASE(ENOBUFS)
ERROR_CASE(EISCONN)
ERROR_CASE(ENOTCONN)
ERROR_CASE(ETIMEDOUT)
ERROR_CASE(ECONNREFUSED)
ERROR_CASE(ELOOP)
ERROR_CASE(ENAMETOOLONG)
ERROR_CASE(EHOSTUNREACH)
ERROR_CASE(ENOTEMPTY)
}
return ORBIS_NET_ERROR_EINTERNAL;
}
// if it is 0 or positive return it as it is
return retval;
}
static int ConvertLevels(int level) {
switch (level) {
case ORBIS_NET_SOL_SOCKET:
return SOL_SOCKET;
case ORBIS_NET_IPPROTO_IP:
return IPPROTO_IP;
case ORBIS_NET_IPPROTO_TCP:
return IPPROTO_TCP;
}
return -1;
}
static void convertOrbisNetSockaddrToPosix(const OrbisNetSockaddr* src, sockaddr* dst) {
if (src == nullptr || dst == nullptr)
return;
memset(dst, 0, sizeof(sockaddr));
const OrbisNetSockaddrIn* src_in = (const OrbisNetSockaddrIn*)src;
sockaddr_in* dst_in = (sockaddr_in*)dst;
dst_in->sin_family = src_in->sin_family;
dst_in->sin_port = src_in->sin_port;
memcpy(&dst_in->sin_addr, &src_in->sin_addr, 4);
}
static void convertPosixSockaddrToOrbis(sockaddr* src, OrbisNetSockaddr* dst) {
if (src == nullptr || dst == nullptr)
return;
memset(dst, 0, sizeof(OrbisNetSockaddr));
OrbisNetSockaddrIn* dst_in = (OrbisNetSockaddrIn*)dst;
sockaddr_in* src_in = (sockaddr_in*)src;
dst_in->sin_family = static_cast<unsigned char>(src_in->sin_family);
dst_in->sin_port = src_in->sin_port;
memcpy(&dst_in->sin_addr, &src_in->sin_addr, 4);
}
int PosixSocket::Close() {
#ifdef _WIN32
auto out = closesocket(sock);
#else
auto out = ::close(sock);
#endif
return ConvertReturnErrorCode(out);
}
int PosixSocket::Bind(const OrbisNetSockaddr* addr, u32 addrlen) {
sockaddr addr2;
convertOrbisNetSockaddrToPosix(addr, &addr2);
return ConvertReturnErrorCode(::bind(sock, &addr2, sizeof(sockaddr_in)));
}
int PosixSocket::Listen(int backlog) {
return ConvertReturnErrorCode(::listen(sock, backlog));
}
int PosixSocket::SendPacket(const void* msg, u32 len, int flags, const OrbisNetSockaddr* to,
u32 tolen) {
if (to != nullptr) {
sockaddr addr;
convertOrbisNetSockaddrToPosix(to, &addr);
return ConvertReturnErrorCode(
sendto(sock, (const char*)msg, len, flags, &addr, sizeof(sockaddr_in)));
} else {
return ConvertReturnErrorCode(send(sock, (const char*)msg, len, flags));
}
}
int PosixSocket::ReceivePacket(void* buf, u32 len, int flags, OrbisNetSockaddr* from,
u32* fromlen) {
if (from != nullptr) {
sockaddr addr;
int res = recvfrom(sock, (char*)buf, len, flags, &addr, (socklen_t*)fromlen);
convertPosixSockaddrToOrbis(&addr, from);
*fromlen = sizeof(OrbisNetSockaddrIn);
return ConvertReturnErrorCode(res);
} else {
return ConvertReturnErrorCode(recv(sock, (char*)buf, len, flags));
}
}
SocketPtr PosixSocket::Accept(OrbisNetSockaddr* addr, u32* addrlen) {
sockaddr addr2;
net_socket new_socket = ::accept(sock, &addr2, (socklen_t*)addrlen);
#ifdef _WIN32
if (new_socket != INVALID_SOCKET) {
#else
if (new_socket >= 0) {
#endif
convertPosixSockaddrToOrbis(&addr2, addr);
*addrlen = sizeof(OrbisNetSockaddrIn);
return std::make_shared<PosixSocket>(new_socket);
}
return nullptr;
}
int PosixSocket::Connect(const OrbisNetSockaddr* addr, u32 namelen) {
sockaddr addr2;
convertOrbisNetSockaddrToPosix(addr, &addr2);
return ::connect(sock, &addr2, sizeof(sockaddr_in));
}
int PosixSocket::GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) {
sockaddr addr;
convertOrbisNetSockaddrToPosix(name, &addr);
if (name != nullptr) {
*namelen = sizeof(sockaddr_in);
}
int res = getsockname(sock, &addr, (socklen_t*)namelen);
if (res >= 0) {
convertPosixSockaddrToOrbis(&addr, name);
*namelen = sizeof(OrbisNetSockaddrIn);
}
return res;
}
#define CASE_SETSOCKOPT(opt) \
case ORBIS_NET_##opt: \
return ConvertReturnErrorCode(setsockopt(sock, level, opt, (const char*)optval, optlen))
#define CASE_SETSOCKOPT_VALUE(opt, value) \
case opt: \
if (optlen != sizeof(*value)) { \
return ORBIS_NET_ERROR_EFAULT; \
} \
memcpy(value, optval, optlen); \
return 0
int PosixSocket::SetSocketOptions(int level, int optname, const void* optval, u32 optlen) {
level = ConvertLevels(level);
if (level == SOL_SOCKET) {
switch (optname) {
CASE_SETSOCKOPT(SO_REUSEADDR);
CASE_SETSOCKOPT(SO_KEEPALIVE);
CASE_SETSOCKOPT(SO_BROADCAST);
CASE_SETSOCKOPT(SO_LINGER);
CASE_SETSOCKOPT(SO_SNDBUF);
CASE_SETSOCKOPT(SO_RCVBUF);
CASE_SETSOCKOPT(SO_SNDTIMEO);
CASE_SETSOCKOPT(SO_RCVTIMEO);
CASE_SETSOCKOPT(SO_ERROR);
CASE_SETSOCKOPT(SO_TYPE);
CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_REUSEPORT, &sockopt_so_reuseport);
CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_ONESBCAST, &sockopt_so_onesbcast);
CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_USECRYPTO, &sockopt_so_usecrypto);
CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_USESIGNATURE, &sockopt_so_usesignature);
case ORBIS_NET_SO_NAME:
return ORBIS_NET_ERROR_EINVAL; // don't support set for name
case ORBIS_NET_SO_NBIO: {
if (optlen != sizeof(sockopt_so_nbio)) {
return ORBIS_NET_ERROR_EFAULT;
}
memcpy(&sockopt_so_nbio, optval, optlen);
#ifdef _WIN32
static_assert(sizeof(u_long) == sizeof(sockopt_so_nbio),
"type used for ioctlsocket value does not have the expected size");
return ConvertReturnErrorCode(ioctlsocket(sock, FIONBIO, (u_long*)&sockopt_so_nbio));
#else
return ConvertReturnErrorCode(ioctl(sock, FIONBIO, &sockopt_so_nbio));
#endif
}
}
} else if (level == IPPROTO_IP) {
switch (optname) {
CASE_SETSOCKOPT(IP_HDRINCL);
CASE_SETSOCKOPT(IP_TOS);
CASE_SETSOCKOPT(IP_TTL);
CASE_SETSOCKOPT(IP_MULTICAST_IF);
CASE_SETSOCKOPT(IP_MULTICAST_TTL);
CASE_SETSOCKOPT(IP_MULTICAST_LOOP);
CASE_SETSOCKOPT(IP_ADD_MEMBERSHIP);
CASE_SETSOCKOPT(IP_DROP_MEMBERSHIP);
CASE_SETSOCKOPT_VALUE(ORBIS_NET_IP_TTLCHK, &sockopt_ip_ttlchk);
CASE_SETSOCKOPT_VALUE(ORBIS_NET_IP_MAXTTL, &sockopt_ip_maxttl);
}
} else if (level == IPPROTO_TCP) {
switch (optname) {
CASE_SETSOCKOPT(TCP_NODELAY);
CASE_SETSOCKOPT(TCP_MAXSEG);
CASE_SETSOCKOPT_VALUE(ORBIS_NET_TCP_MSS_TO_ADVERTISE, &sockopt_tcp_mss_to_advertise);
}
}
UNREACHABLE_MSG("Unknown level ={} optname ={}", level, optname);
return 0;
}
#define CASE_GETSOCKOPT(opt) \
case ORBIS_NET_##opt: { \
socklen_t optlen_temp = *optlen; \
auto retval = \
ConvertReturnErrorCode(getsockopt(sock, level, opt, (char*)optval, &optlen_temp)); \
*optlen = optlen_temp; \
return retval; \
}
#define CASE_GETSOCKOPT_VALUE(opt, value) \
case opt: \
if (*optlen < sizeof(value)) { \
*optlen = sizeof(value); \
return ORBIS_NET_ERROR_EFAULT; \
} \
*optlen = sizeof(value); \
*(decltype(value)*)optval = value; \
return 0;
int PosixSocket::GetSocketOptions(int level, int optname, void* optval, u32* optlen) {
level = ConvertLevels(level);
if (level == SOL_SOCKET) {
switch (optname) {
CASE_GETSOCKOPT(SO_REUSEADDR);
CASE_GETSOCKOPT(SO_KEEPALIVE);
CASE_GETSOCKOPT(SO_BROADCAST);
CASE_GETSOCKOPT(SO_LINGER);
CASE_GETSOCKOPT(SO_SNDBUF);
CASE_GETSOCKOPT(SO_RCVBUF);
CASE_GETSOCKOPT(SO_SNDTIMEO);
CASE_GETSOCKOPT(SO_RCVTIMEO);
CASE_GETSOCKOPT(SO_ERROR);
CASE_GETSOCKOPT(SO_TYPE);
CASE_GETSOCKOPT_VALUE(ORBIS_NET_SO_NBIO, sockopt_so_nbio);
CASE_GETSOCKOPT_VALUE(ORBIS_NET_SO_REUSEPORT, sockopt_so_reuseport);
CASE_GETSOCKOPT_VALUE(ORBIS_NET_SO_ONESBCAST, sockopt_so_onesbcast);
CASE_GETSOCKOPT_VALUE(ORBIS_NET_SO_USECRYPTO, sockopt_so_usecrypto);
CASE_GETSOCKOPT_VALUE(ORBIS_NET_SO_USESIGNATURE, sockopt_so_usesignature);
CASE_GETSOCKOPT_VALUE(ORBIS_NET_SO_NAME,
(char)0); // writes an empty string to the output buffer
}
} else if (level == IPPROTO_IP) {
switch (optname) {
CASE_GETSOCKOPT(IP_HDRINCL);
CASE_GETSOCKOPT(IP_TOS);
CASE_GETSOCKOPT(IP_TTL);
CASE_GETSOCKOPT(IP_MULTICAST_IF);
CASE_GETSOCKOPT(IP_MULTICAST_TTL);
CASE_GETSOCKOPT(IP_MULTICAST_LOOP);
CASE_GETSOCKOPT(IP_ADD_MEMBERSHIP);
CASE_GETSOCKOPT(IP_DROP_MEMBERSHIP);
CASE_GETSOCKOPT_VALUE(ORBIS_NET_IP_TTLCHK, sockopt_ip_ttlchk);
CASE_GETSOCKOPT_VALUE(ORBIS_NET_IP_MAXTTL, sockopt_ip_maxttl);
}
} else if (level == IPPROTO_TCP) {
switch (optname) {
CASE_GETSOCKOPT(TCP_NODELAY);
CASE_GETSOCKOPT(TCP_MAXSEG);
CASE_GETSOCKOPT_VALUE(ORBIS_NET_TCP_MSS_TO_ADVERTISE, sockopt_tcp_mss_to_advertise);
}
}
UNREACHABLE_MSG("Unknown level ={} optname ={}", level, optname);
return 0;
}
} // namespace Libraries::Net

View file

@ -1,112 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#ifdef _WIN32
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <Ws2tcpip.h>
#include <iphlpapi.h>
#include <winsock2.h>
typedef SOCKET net_socket;
typedef int socklen_t;
#else
#include <cerrno>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>
typedef int net_socket;
#endif
#include <map>
#include <memory>
#include <mutex>
#include "net.h"
namespace Libraries::Net {
struct Socket;
typedef std::shared_ptr<Socket> SocketPtr;
struct Socket {
explicit Socket(int domain, int type, int protocol) {}
virtual ~Socket() = default;
virtual int Close() = 0;
virtual int SetSocketOptions(int level, int optname, const void* optval, u32 optlen) = 0;
virtual int GetSocketOptions(int level, int optname, void* optval, u32* optlen) = 0;
virtual int Bind(const OrbisNetSockaddr* addr, u32 addrlen) = 0;
virtual int Listen(int backlog) = 0;
virtual int SendPacket(const void* msg, u32 len, int flags, const OrbisNetSockaddr* to,
u32 tolen) = 0;
virtual SocketPtr Accept(OrbisNetSockaddr* addr, u32* addrlen) = 0;
virtual int ReceivePacket(void* buf, u32 len, int flags, OrbisNetSockaddr* from,
u32* fromlen) = 0;
virtual int Connect(const OrbisNetSockaddr* addr, u32 namelen) = 0;
virtual int GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) = 0;
};
struct PosixSocket : public Socket {
net_socket sock;
int sockopt_so_reuseport = 0;
int sockopt_so_onesbcast = 0;
int sockopt_so_usecrypto = 0;
int sockopt_so_usesignature = 0;
int sockopt_so_nbio = 0;
int sockopt_ip_ttlchk = 0;
int sockopt_ip_maxttl = 0;
int sockopt_tcp_mss_to_advertise = 0;
explicit PosixSocket(int domain, int type, int protocol)
: Socket(domain, type, protocol), sock(socket(domain, type, protocol)) {}
explicit PosixSocket(net_socket sock) : Socket(0, 0, 0), sock(sock) {}
int Close() override;
int SetSocketOptions(int level, int optname, const void* optval, u32 optlen) override;
int GetSocketOptions(int level, int optname, void* optval, u32* optlen) override;
int Bind(const OrbisNetSockaddr* addr, u32 addrlen) override;
int Listen(int backlog) override;
int SendPacket(const void* msg, u32 len, int flags, const OrbisNetSockaddr* to,
u32 tolen) override;
int ReceivePacket(void* buf, u32 len, int flags, OrbisNetSockaddr* from, u32* fromlen) override;
SocketPtr Accept(OrbisNetSockaddr* addr, u32* addrlen) override;
int Connect(const OrbisNetSockaddr* addr, u32 namelen) override;
int GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) override;
};
struct P2PSocket : public Socket {
explicit P2PSocket(int domain, int type, int protocol) : Socket(domain, type, protocol) {}
int Close() override;
int SetSocketOptions(int level, int optname, const void* optval, u32 optlen) override;
int GetSocketOptions(int level, int optname, void* optval, u32* optlen) override;
int Bind(const OrbisNetSockaddr* addr, u32 addrlen) override;
int Listen(int backlog) override;
int SendPacket(const void* msg, u32 len, int flags, const OrbisNetSockaddr* to,
u32 tolen) override;
int ReceivePacket(void* buf, u32 len, int flags, OrbisNetSockaddr* from, u32* fromlen) override;
SocketPtr Accept(OrbisNetSockaddr* addr, u32* addrlen) override;
int Connect(const OrbisNetSockaddr* addr, u32 namelen) override;
int GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) override;
};
class NetInternal {
public:
explicit NetInternal() = default;
~NetInternal() = default;
SocketPtr FindSocket(int sockid) {
std::scoped_lock lock{m_mutex};
const auto it = socks.find(sockid);
if (it != socks.end()) {
return it->second;
}
return 0;
}
public:
std::mutex m_mutex;
typedef std::map<int, SocketPtr> NetSockets;
NetSockets socks;
int next_sock_id = 0;
};
} // namespace Libraries::Net

View file

@ -1,229 +0,0 @@
#include "sys_net.h"
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <common/assert.h>
#include <common/logging/log.h>
#include <core/libraries/kernel/kernel.h>
#include "common/singleton.h"
#include "net_error.h"
#include "sockets.h"
#include "sys_net.h"
namespace Libraries::Net {
int PS4_SYSV_ABI sys_connect(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addrlen) {
auto* netcall = Common::Singleton<NetInternal>::Instance();
auto sock = netcall->FindSocket(s);
if (!sock) {
*Libraries::Kernel::__Error() = ORBIS_NET_ERROR_EBADF;
LOG_ERROR(Lib_Net, "socket id is invalid = {}", s);
return -1;
}
int returncode = sock->Connect(addr, addrlen);
if (returncode >= 0) {
return returncode;
}
*Libraries::Kernel::__Error() = returncode;
LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)returncode);
return -1;
}
int PS4_SYSV_ABI sys_bind(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addrlen) {
auto* netcall = Common::Singleton<NetInternal>::Instance();
auto sock = netcall->FindSocket(s);
if (!sock) {
*Libraries::Kernel::__Error() = ORBIS_NET_ERROR_EBADF;
LOG_ERROR(Lib_Net, "socket id is invalid = {}", s);
return -1;
}
int returncode = sock->Bind(addr, addrlen);
if (returncode >= 0) {
return returncode;
}
*Libraries::Kernel::__Error() = returncode;
LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)returncode);
return -1;
}
int PS4_SYSV_ABI sys_accept(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen) {
auto* netcall = Common::Singleton<NetInternal>::Instance();
auto sock = netcall->FindSocket(s);
if (!sock) {
*Libraries::Kernel::__Error() = ORBIS_NET_EBADF;
LOG_ERROR(Lib_Net, "socket id is invalid = {}", s);
return -1;
}
auto new_sock = sock->Accept(addr, paddrlen);
if (!new_sock) {
*Libraries::Kernel::__Error() = ORBIS_NET_EBADF;
LOG_ERROR(Lib_Net, "error creating new socket for accepting");
return -1;
}
auto id = ++netcall->next_sock_id;
netcall->socks.emplace(id, new_sock);
return id;
}
int PS4_SYSV_ABI sys_getpeername(OrbisNetId s, const OrbisNetSockaddr* addr, u32* paddrlen) {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return -1;
}
int PS4_SYSV_ABI sys_getsockname(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen) {
auto* netcall = Common::Singleton<NetInternal>::Instance();
auto sock = netcall->FindSocket(s);
if (!sock) {
*Libraries::Kernel::__Error() = ORBIS_NET_ERROR_EBADF;
LOG_ERROR(Lib_Net, "socket id is invalid = {}", s);
return -1;
}
int returncode = sock->GetSocketAddress(addr, paddrlen);
if (returncode >= 0) {
return returncode;
}
*Libraries::Kernel::__Error() = returncode;
LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)returncode);
return -1;
}
int PS4_SYSV_ABI sys_getsockopt(OrbisNetId s, int level, int optname, void* optval, u32* optlen) {
auto* netcall = Common::Singleton<NetInternal>::Instance();
auto sock = netcall->FindSocket(s);
if (!sock) {
*Libraries::Kernel::__Error() = ORBIS_NET_ERROR_EBADF;
LOG_ERROR(Lib_Net, "socket id is invalid = {}", s);
return -1;
}
int returncode = sock->GetSocketOptions(level, optname, optval, optlen);
if (returncode >= 0) {
return returncode;
}
*Libraries::Kernel::__Error() = returncode;
LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)returncode);
return -1;
}
int PS4_SYSV_ABI sys_listen(OrbisNetId s, int backlog) {
auto* netcall = Common::Singleton<NetInternal>::Instance();
auto sock = netcall->FindSocket(s);
if (!sock) {
*Libraries::Kernel::__Error() = ORBIS_NET_ERROR_EBADF;
LOG_ERROR(Lib_Net, "socket id is invalid = {}", s);
return -1;
}
int returncode = sock->Listen(backlog);
if (returncode >= 0) {
return returncode;
}
*Libraries::Kernel::__Error() = returncode;
LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)returncode);
return -1;
}
int PS4_SYSV_ABI sys_setsockopt(OrbisNetId s, int level, int optname, const void* optval,
u32 optlen) {
auto* netcall = Common::Singleton<NetInternal>::Instance();
auto sock = netcall->FindSocket(s);
if (!sock) {
*Libraries::Kernel::__Error() = ORBIS_NET_ERROR_EBADF;
LOG_ERROR(Lib_Net, "socket id is invalid = {}", s);
return -1;
}
int returncode = sock->SetSocketOptions(level, optname, optval, optlen);
if (returncode >= 0) {
return returncode;
}
*Libraries::Kernel::__Error() = returncode;
LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)returncode);
return -1;
}
int PS4_SYSV_ABI sys_shutdown(OrbisNetId s, int how) {
return -1;
}
int PS4_SYSV_ABI sys_socketex(const char* name, int family, int type, int protocol) {
if (name == nullptr) {
LOG_INFO(Lib_Net, "name = no-named family = {} type = {} protocol = {}", family, type,
protocol);
} else {
LOG_INFO(Lib_Net, "name = {} family = {} type = {} protocol = {}", std::string(name),
family, type, protocol);
}
SocketPtr sock;
switch (type) {
case ORBIS_NET_SOCK_STREAM:
case ORBIS_NET_SOCK_DGRAM:
case ORBIS_NET_SOCK_RAW:
sock = std::make_shared<PosixSocket>(family, type, protocol);
break;
case ORBIS_NET_SOCK_DGRAM_P2P:
case ORBIS_NET_SOCK_STREAM_P2P:
sock = std::make_shared<P2PSocket>(family, type, protocol);
break;
default:
UNREACHABLE_MSG("Unknown type {}", type);
}
auto* netcall = Common::Singleton<NetInternal>::Instance();
auto id = ++netcall->next_sock_id;
netcall->socks.emplace(id, sock);
return id;
}
int PS4_SYSV_ABI sys_socket(int family, int type, int protocol) {
return sys_socketex(nullptr, family, type, protocol);
}
int PS4_SYSV_ABI sys_netabort(OrbisNetId s, int flags) {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return -1;
}
int PS4_SYSV_ABI sys_socketclose(OrbisNetId s) {
auto* netcall = Common::Singleton<NetInternal>::Instance();
auto sock = netcall->FindSocket(s);
if (!sock) {
*Libraries::Kernel::__Error() = ORBIS_NET_ERROR_EBADF;
LOG_ERROR(Lib_Net, "socket id is invalid = {}", s);
return -1;
}
int returncode = sock->Close();
if (returncode >= 0) {
return returncode;
}
*Libraries::Kernel::__Error() = returncode;
LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)returncode);
return -1;
}
int PS4_SYSV_ABI sys_sendto(OrbisNetId s, const void* buf, u64 len, int flags,
const OrbisNetSockaddr* addr, u32 addrlen) {
auto* netcall = Common::Singleton<NetInternal>::Instance();
auto sock = netcall->FindSocket(s);
if (!sock) {
*Libraries::Kernel::__Error() = ORBIS_NET_ERROR_EBADF;
LOG_ERROR(Lib_Net, "socket id is invalid = {}", s);
return -1;
}
int returncode = sock->SendPacket(buf, len, flags, addr, addrlen);
if (returncode >= 0) {
return returncode;
}
*Libraries::Kernel::__Error() = returncode;
LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)returncode);
return -1;
}
int PS4_SYSV_ABI sys_sendmsg(OrbisNetId s, const OrbisNetMsghdr* msg, int flags) {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return -1;
}
int PS4_SYSV_ABI sys_recvfrom(OrbisNetId s, void* buf, u64 len, int flags, OrbisNetSockaddr* addr,
u32* paddrlen) {
auto* netcall = Common::Singleton<NetInternal>::Instance();
auto sock = netcall->FindSocket(s);
if (!sock) {
*Libraries::Kernel::__Error() = ORBIS_NET_ERROR_EBADF;
LOG_ERROR(Lib_Net, "socket id is invalid = {}", s);
return -1;
}
int returncode = sock->ReceivePacket(buf, len, flags, addr, paddrlen);
if (returncode >= 0) {
return returncode;
}
*Libraries::Kernel::__Error() = returncode;
LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)returncode);
return -1;
}
int PS4_SYSV_ABI sys_recvmsg(OrbisNetId s, OrbisNetMsghdr* msg, int flags) {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return -1;
}
} // namespace Libraries::Net

View file

@ -1,31 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/types.h"
#include "net.h"
namespace Libraries::Net {
int PS4_SYSV_ABI sys_connect(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addrlen);
int PS4_SYSV_ABI sys_bind(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addrlen);
int PS4_SYSV_ABI sys_accept(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen);
int PS4_SYSV_ABI sys_getpeername(OrbisNetId s, const OrbisNetSockaddr* addr, u32* paddrlen);
int PS4_SYSV_ABI sys_getsockname(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen);
int PS4_SYSV_ABI sys_getsockopt(OrbisNetId s, int level, int optname, void* optval, u32* optlen);
int PS4_SYSV_ABI sys_listen(OrbisNetId s, int backlog);
int PS4_SYSV_ABI sys_setsockopt(OrbisNetId s, int level, int optname, const void* optval,
u32 optlen);
int PS4_SYSV_ABI sys_shutdown(OrbisNetId s, int how);
int PS4_SYSV_ABI sys_socketex(const char* name, int family, int type, int protocol);
int PS4_SYSV_ABI sys_socket(int family, int type, int protocol);
int PS4_SYSV_ABI sys_netabort(OrbisNetId s, int flags);
int PS4_SYSV_ABI sys_socketclose(OrbisNetId s);
int PS4_SYSV_ABI sys_sendto(OrbisNetId s, const void* buf, u64 len, int flags,
const OrbisNetSockaddr* addr, u32 addrlen);
int PS4_SYSV_ABI sys_sendmsg(OrbisNetId s, const OrbisNetMsghdr* msg, int flags);
int PS4_SYSV_ABI sys_recvfrom(OrbisNetId s, void* buf, u64 len, int flags, OrbisNetSockaddr* addr,
u32* paddrlen);
int PS4_SYSV_ABI sys_recvmsg(OrbisNetId s, OrbisNetMsghdr* msg, int flags);
} // namespace Libraries::Net

View file

@ -49,11 +49,13 @@ void SaveDialogResult::CopyTo(OrbisSaveDataDialogResult& result) const {
result.mode = this->mode;
result.result = this->result;
result.buttonId = this->button_id;
if (result.dirName != nullptr) {
result.dirName->data.FromString(this->dir_name);
}
if (result.param != nullptr && this->param.GetString(SaveParams::MAINTITLE).has_value()) {
result.param->FromSFO(this->param);
if (mode == SaveDataDialogMode::LIST || ElfInfo::Instance().FirmwareVer() >= ElfInfo::FW_45) {
if (result.dirName != nullptr) {
result.dirName->data.FromString(this->dir_name);
}
if (result.param != nullptr && this->param.GetString(SaveParams::MAINTITLE).has_value()) {
result.param->FromSFO(this->param);
}
}
result.userData = this->user_data;
}
@ -343,15 +345,12 @@ SaveDialogUi::SaveDialogUi(SaveDialogUi&& other) noexcept
}
}
SaveDialogUi& SaveDialogUi::operator=(SaveDialogUi&& other) noexcept {
SaveDialogUi& SaveDialogUi::operator=(SaveDialogUi other) {
std::scoped_lock lock(draw_mutex, other.draw_mutex);
using std::swap;
state = other.state;
other.state = nullptr;
status = other.status;
other.status = nullptr;
result = other.result;
other.result = nullptr;
swap(state, other.state);
swap(status, other.status);
swap(result, other.result);
if (status && *status == Status::RUNNING) {
first_render = true;
AddLayer(this);

View file

@ -300,8 +300,7 @@ public:
~SaveDialogUi() override;
SaveDialogUi(const SaveDialogUi& other) = delete;
SaveDialogUi(SaveDialogUi&& other) noexcept;
SaveDialogUi& operator=(SaveDialogUi& other) = delete;
SaveDialogUi& operator=(SaveDialogUi&& other) noexcept;
SaveDialogUi& operator=(SaveDialogUi other);
void Finish(ButtonId buttonId, CommonDialog::Result r = CommonDialog::Result::OK);

View file

@ -19,40 +19,11 @@ int PS4_SYSV_ABI sceSysmoduleGetModuleHandleInternal() {
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceSysmoduleGetModuleInfoForUnwind(VAddr addr, s32 flags,
Kernel::OrbisModuleInfoForUnwind* info) {
LOG_TRACE(Lib_SysModule, "sceSysmoduleGetModuleInfoForUnwind(addr=0x{:X}, flags=0x{:X})", addr,
flags);
s32 res = Kernel::sceKernelGetModuleInfoForUnwind(addr, flags, info);
if (res != 0) {
return res;
}
static constexpr std::array<std::string_view, 17> modules_to_hide = {
"libc.prx",
"libc.sprx",
"libSceAudioLatencyEstimation.prx",
"libSceFace.prx",
"libSceFaceTracker.prx",
"libSceFios2.prx",
"libSceFios2.sprx",
"libSceFontGsm.prx",
"libSceHand.prx",
"libSceHandTracker.prx",
"libSceHeadTracker.prx",
"libSceJobManager.prx",
"libSceNpCppWebApi.prx",
"libSceNpToolkit.prx",
"libSceNpToolkit2.prx",
"libSceS3DConversion.prx",
"libSceSmart.prx",
};
const std::string_view module_name = info->name.data();
if (std::ranges::find(modules_to_hide, module_name) != modules_to_hide.end()) {
std::ranges::fill(info->name, '\0');
}
s32 PS4_SYSV_ABI sceSysmoduleGetModuleInfoForUnwind(VAddr addr, s32 flags, void* info) {
LOG_ERROR(Lib_SysModule, "(STUBBED) called");
Kernel::OrbisModuleInfoForUnwind module_info;
module_info.st_size = 0x130;
s32 res = Kernel::sceKernelGetModuleInfoForUnwind(addr, flags, &module_info);
return res;
}
@ -85,6 +56,7 @@ int PS4_SYSV_ABI sceSysmoduleIsLoadedInternal(OrbisSysModuleInternal id) {
}
int PS4_SYSV_ABI sceSysmoduleLoadModule(OrbisSysModule id) {
auto color_name = magic_enum::enum_name(id);
LOG_ERROR(Lib_SysModule, "(DUMMY) called module = {}", magic_enum::enum_name(id));
return ORBIS_OK;
}

View file

@ -4,7 +4,6 @@
#pragma once
#include "common/types.h"
#include "core/libraries/kernel/process.h"
namespace Core::Loader {
class SymbolsResolver;
@ -153,8 +152,7 @@ enum class OrbisSysModuleInternal : u32 {
};
int PS4_SYSV_ABI sceSysmoduleGetModuleHandleInternal();
s32 PS4_SYSV_ABI sceSysmoduleGetModuleInfoForUnwind(VAddr addr, s32 flags,
Kernel::OrbisModuleInfoForUnwind* info);
s32 PS4_SYSV_ABI sceSysmoduleGetModuleInfoForUnwind(VAddr addr, s32 flags, void* info);
int PS4_SYSV_ABI sceSysmoduleIsCalledFromSysModule();
int PS4_SYSV_ABI sceSysmoduleIsCameraPreloaded();
int PS4_SYSV_ABI sceSysmoduleIsLoaded(OrbisSysModule id);

View file

@ -220,7 +220,7 @@ s32 PS4_SYSV_ABI sceVideoOutGetEventData(const Kernel::SceKernelEvent* ev, s64*
if (ev->ident != static_cast<s32>(OrbisVideoOutInternalEventId::Flip) || ev->data == 0) {
*data = event_data;
} else {
*data = event_data | 0xffff000000000000;
*data = event_data | 0xFFFF000000000000;
}
return ORBIS_OK;
}
@ -233,8 +233,7 @@ s32 PS4_SYSV_ABI sceVideoOutGetEventCount(const Kernel::SceKernelEvent* ev) {
return ORBIS_VIDEO_OUT_ERROR_INVALID_EVENT;
}
auto event_data = static_cast<OrbisVideoOutEventData>(ev->data);
return event_data.count;
return (ev->data >> 0xc) & 0xf;
}
s32 PS4_SYSV_ABI sceVideoOutGetFlipStatus(s32 handle, FlipStatus* status) {

View file

@ -111,12 +111,6 @@ struct SceVideoOutColorSettings {
u32 reserved[3];
};
struct OrbisVideoOutEventData {
u64 time : 12;
u64 count : 4;
u64 flip_arg : 48;
};
void PS4_SYSV_ABI sceVideoOutSetBufferAttribute(BufferAttribute* attribute, PixelFormat pixelFormat,
u32 tilingMode, u32 aspectRatio, u32 width,
u32 height, u32 pitchInPixel);
@ -134,8 +128,8 @@ s32 PS4_SYSV_ABI sceVideoOutGetResolutionStatus(s32 handle, SceVideoOutResolutio
s32 PS4_SYSV_ABI sceVideoOutOpen(SceUserServiceUserId userId, s32 busType, s32 index,
const void* param);
s32 PS4_SYSV_ABI sceVideoOutClose(s32 handle);
s32 PS4_SYSV_ABI sceVideoOutGetEventId(const Kernel::SceKernelEvent* ev);
s32 PS4_SYSV_ABI sceVideoOutGetEventData(const Kernel::SceKernelEvent* ev, s64* data);
int PS4_SYSV_ABI sceVideoOutGetEventId(const Kernel::SceKernelEvent* ev);
int PS4_SYSV_ABI sceVideoOutGetEventData(const Kernel::SceKernelEvent* ev, int64_t* data);
s32 PS4_SYSV_ABI sceVideoOutColorSettingsSetGamma(SceVideoOutColorSettings* settings, float gamma);
s32 PS4_SYSV_ABI sceVideoOutAdjustColor(s32 handle, const SceVideoOutColorSettings* settings);

View file

@ -83,7 +83,7 @@ public:
}
Module* GetModule(s32 index) const {
if (index >= 0 && index < m_modules.size()) {
if (index >= 0 || index < m_modules.size()) {
return m_modules.at(index).get();
}
return nullptr;

View file

@ -142,7 +142,7 @@ PAddr MemoryManager::Allocate(PAddr search_start, PAddr search_end, size_t size,
auto mapping_start = search_start > dmem_area->second.base
? Common::AlignUp(search_start, alignment)
: Common::AlignUp(dmem_area->second.base, alignment);
auto mapping_end = mapping_start + size;
auto mapping_end = Common::AlignUp(mapping_start + size, alignment);
// Find the first free, large enough dmem area in the range.
while ((!dmem_area->second.is_free || dmem_area->second.GetEnd() < mapping_end) &&
@ -151,8 +151,10 @@ PAddr MemoryManager::Allocate(PAddr search_start, PAddr search_end, size_t size,
dmem_area++;
// Update local variables based on the new dmem_area
mapping_start = Common::AlignUp(dmem_area->second.base, alignment);
mapping_end = mapping_start + size;
mapping_start = search_start > dmem_area->second.base
? Common::AlignUp(search_start, alignment)
: Common::AlignUp(dmem_area->second.base, alignment);
mapping_end = Common::AlignUp(mapping_start + size, alignment);
}
if (dmem_area == dmem_map.end()) {

View file

@ -19,7 +19,8 @@ namespace Core {
using EntryFunc = PS4_SYSV_ABI int (*)(size_t args, const void* argp, void* param);
static constexpr u64 ModuleLoadBase = 0x800000000;
static u64 LoadOffset = CODE_BASE_OFFSET;
static constexpr u64 CODE_BASE_INCR = 0x010000000u;
static u64 GetAlignedSize(const elf_program_header& phdr) {
return (phdr.p_align != 0 ? (phdr.p_memsz + (phdr.p_align - 1)) & ~(phdr.p_align - 1)
@ -83,7 +84,7 @@ static std::string StringToNid(std::string_view symbol) {
}
Module::Module(Core::MemoryManager* memory_, const std::filesystem::path& file_, u32& max_tls_index)
: memory{memory_}, file{file_}, name{file.filename().string()} {
: memory{memory_}, file{file_}, name{file.stem().string()} {
elf.Open(file);
if (elf.IsElfFile()) {
LoadModuleToMemory(max_tls_index);
@ -112,8 +113,10 @@ void Module::LoadModuleToMemory(u32& max_tls_index) {
// Map module segments (and possible TLS trampolines)
void** out_addr = reinterpret_cast<void**>(&base_virtual_addr);
memory->MapMemory(out_addr, ModuleLoadBase, aligned_base_size + TrampolineSize,
MemoryProt::CpuReadWrite, MemoryMapFlags::NoFlags, VMAType::Code, name, true);
memory->MapMemory(out_addr, memory->SystemReservedVirtualBase() + LoadOffset,
aligned_base_size + TrampolineSize, MemoryProt::CpuReadWrite,
MemoryMapFlags::Fixed, VMAType::Code, name, true);
LoadOffset += CODE_BASE_INCR * (1 + aligned_base_size / CODE_BASE_INCR);
LOG_INFO(Core_Linker, "Loading module {} to {}", name, fmt::ptr(*out_addr));
#ifdef ARCH_X86_64
@ -132,14 +135,10 @@ void Module::LoadModuleToMemory(u32& max_tls_index) {
if (do_map) {
elf.LoadSegment(segment_addr, phdr.p_offset, phdr.p_filesz);
}
if (info.num_segments < 4) {
auto& segment = info.segments[info.num_segments++];
segment.address = segment_addr;
segment.prot = phdr.p_flags;
segment.size = GetAlignedSize(phdr);
} else {
LOG_ERROR(Core_Linker, "Attempting to add too many segments!");
}
auto& segment = info.segments[info.num_segments++];
segment.address = segment_addr;
segment.prot = phdr.p_flags;
segment.size = GetAlignedSize(phdr);
};
for (u16 i = 0; i < elf_header.e_phnum; i++) {
@ -226,7 +225,7 @@ void Module::LoadModuleToMemory(u32& max_tls_index) {
LOG_INFO(Core_Linker, "program entry addr ..........: {:#018x}", entry_addr);
if (MemoryPatcher::g_eboot_address == 0) {
if (name == "eboot.bin") {
if (name == "eboot") {
MemoryPatcher::g_eboot_address = base_virtual_addr;
MemoryPatcher::g_eboot_image_size = base_size;
MemoryPatcher::OnGameLoaded();

View file

@ -10,16 +10,13 @@
#include "common/logging/log.h"
#ifdef ENABLE_QT_GUI
#include <QtCore>
#include "common/memory_patcher.h"
#endif
#include "common/assert.h"
#ifdef ENABLE_DISCORD_RPC
#include "common/discord_rpc_handler.h"
#endif
#ifdef _WIN32
#include <WinSock2.h>
#endif
#include "common/elf_info.h"
#include "common/memory_patcher.h"
#include "common/ntapi.h"
#include "common/path_util.h"
#include "common/polyfill_thread.h"
@ -49,10 +46,27 @@ Emulator::Emulator() {
#ifdef _WIN32
Common::NtApi::Initialize();
SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS);
// need to init this in order for winsock2 to work
WORD versionWanted = MAKEWORD(2, 2);
WSADATA wsaData;
WSAStartup(versionWanted, &wsaData);
#endif
// Create stdin/stdout/stderr
Common::Singleton<FileSys::HandleTable>::Instance()->CreateStdHandles();
// Defer until after logging is initialized.
memory = Core::Memory::Instance();
controller = Common::Singleton<Input::GameController>::Instance();
linker = Common::Singleton<Core::Linker>::Instance();
// Load renderdoc module.
VideoCore::LoadRenderDoc();
// Start the timer (Play Time)
#ifdef ENABLE_QT_GUI
start_time = std::chrono::steady_clock::now();
const auto user_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
QString filePath = QString::fromStdString((user_dir / "play_time.txt").string());
QFile file(filePath);
ASSERT_MSG(file.open(QIODevice::ReadWrite | QIODevice::Text),
"Error opening or creating play_time.txt");
#endif
}
@ -77,93 +91,58 @@ void Emulator::Run(const std::filesystem::path& file, const std::vector<std::str
// Applications expect to be run from /app0 so mount the file's parent path as app0.
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
mnt->Mount(game_folder, "/app0", true);
mnt->Mount(game_folder, "/app0");
// Certain games may use /hostapp as well such as CUSA001100
mnt->Mount(game_folder, "/hostapp", true);
mnt->Mount(game_folder, "/hostapp");
const auto param_sfo_path = mnt->GetHostPath("/app0/sce_sys/param.sfo");
const auto param_sfo_exists = std::filesystem::exists(param_sfo_path);
auto& game_info = Common::ElfInfo::Instance();
// Load param.sfo details if it exists
// Loading param.sfo file if exists
std::string id;
std::string title;
std::string app_version;
u32 fw_version;
Common::PSFAttributes psf_attributes{};
if (param_sfo_exists) {
auto* param_sfo = Common::Singleton<PSF>::Instance();
ASSERT_MSG(param_sfo->Open(param_sfo_path), "Failed to open param.sfo");
const auto param_sfo_path = mnt->GetHostPath("/app0/sce_sys/param.sfo");
if (!std::filesystem::exists(param_sfo_path) || !Config::getSeparateLogFilesEnabled()) {
Common::Log::Initialize();
Common::Log::Start();
}
if (std::filesystem::exists(param_sfo_path)) {
auto* param_sfo = Common::Singleton<PSF>::Instance();
const bool success = param_sfo->Open(param_sfo_path);
ASSERT_MSG(success, "Failed to open param.sfo");
const auto content_id = param_sfo->GetString("CONTENT_ID");
ASSERT_MSG(content_id.has_value(), "Failed to get CONTENT_ID");
id = std::string(*content_id, 7, 9);
title = param_sfo->GetString("TITLE").value_or("Unknown title");
fw_version = param_sfo->GetInteger("SYSTEM_VER").value_or(0x4700000);
app_version = param_sfo->GetString("APP_VER").value_or("Unknown version");
if (const auto raw_attributes = param_sfo->GetInteger("ATTRIBUTE")) {
psf_attributes.raw = *raw_attributes;
if (Config::getSeparateLogFilesEnabled()) {
Common::Log::Initialize(id + ".log");
Common::Log::Start();
}
}
LOG_INFO(Loader, "Starting shadps4 emulator v{} ", Common::g_version);
LOG_INFO(Loader, "Revision {}", Common::g_scm_rev);
LOG_INFO(Loader, "Branch {}", Common::g_scm_branch);
LOG_INFO(Loader, "Description {}", Common::g_scm_desc);
LOG_INFO(Loader, "Remote {}", Common::g_scm_remote_url);
// Initialize logging as soon as possible
if (!id.empty() && Config::getSeparateLogFilesEnabled()) {
Common::Log::Initialize(id + ".log");
} else {
Common::Log::Initialize();
}
Common::Log::Start();
LOG_INFO(Config, "General LogType: {}", Config::getLogType());
LOG_INFO(Config, "General isNeo: {}", Config::isNeoModeConsole());
LOG_INFO(Config, "GPU isNullGpu: {}", Config::nullGpu());
LOG_INFO(Config, "GPU shouldDumpShaders: {}", Config::dumpShaders());
LOG_INFO(Config, "GPU vblankDivider: {}", Config::vblankDiv());
LOG_INFO(Config, "Vulkan gpuId: {}", Config::getGpuId());
LOG_INFO(Config, "Vulkan vkValidation: {}", Config::vkValidationEnabled());
LOG_INFO(Config, "Vulkan vkValidationSync: {}", Config::vkValidationSyncEnabled());
LOG_INFO(Config, "Vulkan vkValidationGpu: {}", Config::vkValidationGpuEnabled());
LOG_INFO(Config, "Vulkan crashDiagnostics: {}", Config::getVkCrashDiagnosticEnabled());
LOG_INFO(Config, "Vulkan hostMarkers: {}", Config::getVkHostMarkersEnabled());
LOG_INFO(Config, "Vulkan guestMarkers: {}", Config::getVkGuestMarkersEnabled());
LOG_INFO(Config, "Vulkan rdocEnable: {}", Config::isRdocEnabled());
LOG_INFO(Loader, "Starting shadps4 emulator v{} ", Common::g_version);
LOG_INFO(Loader, "Revision {}", Common::g_scm_rev);
LOG_INFO(Loader, "Branch {}", Common::g_scm_branch);
LOG_INFO(Loader, "Description {}", Common::g_scm_desc);
LOG_INFO(Loader, "Remote {}", Common::g_scm_remote_url);
LOG_INFO(Config, "General LogType: {}", Config::getLogType());
LOG_INFO(Config, "General isNeo: {}", Config::isNeoModeConsole());
LOG_INFO(Config, "GPU isNullGpu: {}", Config::nullGpu());
LOG_INFO(Config, "GPU shouldDumpShaders: {}", Config::dumpShaders());
LOG_INFO(Config, "GPU vblankDivider: {}", Config::vblankDiv());
LOG_INFO(Config, "Vulkan gpuId: {}", Config::getGpuId());
LOG_INFO(Config, "Vulkan vkValidation: {}", Config::vkValidationEnabled());
LOG_INFO(Config, "Vulkan vkValidationSync: {}", Config::vkValidationSyncEnabled());
LOG_INFO(Config, "Vulkan vkValidationGpu: {}", Config::vkValidationGpuEnabled());
LOG_INFO(Config, "Vulkan crashDiagnostics: {}", Config::getVkCrashDiagnosticEnabled());
LOG_INFO(Config, "Vulkan hostMarkers: {}", Config::getVkHostMarkersEnabled());
LOG_INFO(Config, "Vulkan guestMarkers: {}", Config::getVkGuestMarkersEnabled());
LOG_INFO(Config, "Vulkan rdocEnable: {}", Config::isRdocEnabled());
if (param_sfo_exists) {
LOG_INFO(Loader, "Game id: {} Title: {}", id, title);
LOG_INFO(Loader, "Fw: {:#x} App Version: {}", fw_version, app_version);
}
if (!args.empty()) {
const auto argc = std::min<size_t>(args.size(), 32);
for (auto i = 0; i < argc; i++) {
LOG_INFO(Loader, "Game argument {}: {}", i, args[i]);
}
if (args.size() > 32) {
LOG_ERROR(Loader, "Too many game arguments, only passing the first 32");
}
}
// Create stdin/stdout/stderr
Common::Singleton<FileSys::HandleTable>::Instance()->CreateStdHandles();
// Initialize components
memory = Core::Memory::Instance();
controller = Common::Singleton<Input::GameController>::Instance();
linker = Common::Singleton<Core::Linker>::Instance();
// Load renderdoc module
VideoCore::LoadRenderDoc();
// Initialize patcher and trophies
if (!id.empty()) {
MemoryPatcher::g_game_serial = id;
Libraries::NpTrophy::game_serial = id;
const auto trophyDir =
Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) / id / "TrophyFiles";
if (!std::filesystem::exists(trophyDir)) {
@ -172,9 +151,41 @@ void Emulator::Run(const std::filesystem::path& file, const std::vector<std::str
LOG_ERROR(Loader, "Couldn't extract trophies");
}
}
#ifdef ENABLE_QT_GUI
MemoryPatcher::g_game_serial = id;
// Timer for 'Play Time'
QTimer* timer = new QTimer();
QObject::connect(timer, &QTimer::timeout, [this, id]() {
UpdatePlayTime(id);
start_time = std::chrono::steady_clock::now();
});
timer->start(60000); // 60000 ms = 1 minute
#endif
title = param_sfo->GetString("TITLE").value_or("Unknown title");
LOG_INFO(Loader, "Game id: {} Title: {}", id, title);
fw_version = param_sfo->GetInteger("SYSTEM_VER").value_or(0x4700000);
app_version = param_sfo->GetString("APP_VER").value_or("Unknown version");
LOG_INFO(Loader, "Fw: {:#x} App Version: {}", fw_version, app_version);
if (const auto raw_attributes = param_sfo->GetInteger("ATTRIBUTE")) {
psf_attributes.raw = *raw_attributes;
}
if (!args.empty()) {
int argc = std::min<int>(args.size(), 32);
for (int i = 0; i < argc; i++) {
LOG_INFO(Loader, "Game argument {}: {}", i, args[i]);
}
if (args.size() > 32) {
LOG_ERROR(Loader, "Too many game arguments, only passing the first 32");
}
}
}
const auto pic1_path = mnt->GetHostPath("/app0/sce_sys/pic1.png");
if (std::filesystem::exists(pic1_path)) {
game_info.splash_path = pic1_path;
}
auto& game_info = Common::ElfInfo::Instance();
game_info.initialized = true;
game_info.game_serial = id;
game_info.title = title;
@ -183,11 +194,6 @@ void Emulator::Run(const std::filesystem::path& file, const std::vector<std::str
game_info.raw_firmware_ver = fw_version;
game_info.psf_attributes = psf_attributes;
const auto pic1_path = mnt->GetHostPath("/app0/sce_sys/pic1.png");
if (std::filesystem::exists(pic1_path)) {
game_info.splash_path = pic1_path;
}
std::string game_title = fmt::format("{} - {} <{}>", id, title, app_version);
std::string window_title = "";
if (Common::g_is_release) {
@ -218,15 +224,11 @@ void Emulator::Run(const std::filesystem::path& file, const std::vector<std::str
std::filesystem::create_directory(mount_data_dir);
}
mnt->Mount(mount_data_dir, "/data"); // should just exist, manually create with game serial
// Mounting temp folders
const auto& mount_temp_dir = Common::FS::GetUserPath(Common::FS::PathType::TempDataDir) / id;
if (std::filesystem::exists(mount_temp_dir)) {
// Temp folder should be cleared on each boot.
std::filesystem::remove_all(mount_temp_dir);
if (!std::filesystem::exists(mount_temp_dir)) {
std::filesystem::create_directory(mount_temp_dir);
}
std::filesystem::create_directory(mount_temp_dir);
mnt->Mount(mount_temp_dir, "/temp0");
mnt->Mount(mount_temp_dir, "/temp0"); // called in app_content ==> stat/mkdir
mnt->Mount(mount_temp_dir, "/temp");
const auto& mount_download_dir =
@ -271,25 +273,6 @@ void Emulator::Run(const std::filesystem::path& file, const std::vector<std::str
}
#endif
// Start the timer (Play Time)
#ifdef ENABLE_QT_GUI
if (!id.empty()) {
auto* timer = new QTimer();
QObject::connect(timer, &QTimer::timeout, [this, id]() {
UpdatePlayTime(id);
start_time = std::chrono::steady_clock::now();
});
timer->start(60000); // 60000 ms = 1 minute
start_time = std::chrono::steady_clock::now();
const auto user_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
QString filePath = QString::fromStdString((user_dir / "play_time.txt").string());
QFile file(filePath);
ASSERT_MSG(file.open(QIODevice::ReadWrite | QIODevice::Text),
"Error opening or creating play_time.txt");
}
#endif
linker->Execute(args);
window->InitTimers();

View file

@ -4,11 +4,8 @@
#pragma once
#include <filesystem>
#include <vector>
#include <imgui.h>
#include "common/types.h"
namespace ImGui {
namespace Core::TextureManager {

View file

@ -112,8 +112,6 @@ void Initialize(const ::Vulkan::Instance& instance, const Frontend::WindowSDL& w
if (const auto dpi = SDL_GetWindowDisplayScale(window.GetSDLWindow()); dpi > 0.0f) {
GetIO().FontGlobalScale = dpi;
}
std::at_quick_exit([] { SaveIniSettingsToDisk(GetIO().IniFilename); });
}
void OnResize() {

View file

@ -154,7 +154,7 @@ int main(int argc, char* argv[]) {
// If no game directory is set and no command line argument, prompt for it
if (Config::getGameInstallDirs().empty()) {
std::cout << "Warning: No game folder set, please set it by calling shadps4"
" with the --add-game-folder <folder_name> argument\n";
" with the --add-game-folder <folder_name> argument";
}
if (!has_game_argument) {

View file

@ -1387,7 +1387,7 @@ void CheatsPatches::applyPatch(const QString& patchName, bool enabled) {
if (type == "mask_jump32")
patchMask = MemoryPatcher::PatchMask::Mask_Jump32;
if ((type == "mask" || type == "mask_jump32") && !maskOffsetStr.toStdString().empty()) {
if (type == "mask" || type == "mask_jump32" && !maskOffsetStr.toStdString().empty()) {
maskOffsetValue = std::stoi(maskOffsetStr.toStdString(), 0, 10);
}

View file

@ -608,28 +608,21 @@ void KBMSettings::CheckMapping(QPushButton*& button) {
MappingTimer -= 1;
button->setText(tr("Press a key") + " [" + QString::number(MappingTimer) + "]");
if (pressedKeys.size() > 0) {
QStringList keyStrings;
for (const QString& buttonAction : pressedKeys) {
keyStrings << buttonAction;
}
QString combo = keyStrings.join(",");
SetMapping(combo);
MappingCompleted = true;
EnableMapping = false;
MappingButton->setText(combo);
pressedKeys.clear();
timer->stop();
}
if (MappingCompleted) {
EnableMapping = false;
EnableMappingButtons();
timer->stop();
button->setText(mapping);
if (mapping == "lshift" || mapping == "lalt" || mapping == "lctrl" || mapping == "lmeta" ||
mapping == "lwin") {
modifier = "";
}
if (modifier != "") {
button->setText(modifier + ", " + mapping);
} else {
button->setText(mapping);
}
}
if (MappingTimer <= 0) {
@ -654,346 +647,322 @@ bool KBMSettings::eventFilter(QObject* obj, QEvent* event) {
}
if (EnableMapping) {
if (Qt::ShiftModifier & QApplication::keyboardModifiers()) {
modifier = "lshift";
} else if (Qt::AltModifier & QApplication::keyboardModifiers()) {
modifier = "lalt";
} else if (Qt::ControlModifier & QApplication::keyboardModifiers()) {
modifier = "lctrl";
} else if (Qt::MetaModifier & QApplication::keyboardModifiers()) {
#ifdef _WIN32
modifier = "lwin";
#else
modifier = "lmeta";
#endif
}
if (event->type() == QEvent::KeyPress) {
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->isAutoRepeat())
return true;
if (pressedKeys.size() >= 3) {
return true;
}
switch (keyEvent->key()) {
case Qt::Key_Space:
pressedKeys.insert("space");
SetMapping("space");
break;
case Qt::Key_Comma:
if (Qt::KeypadModifier & QApplication::keyboardModifiers()) {
pressedKeys.insert("kpcomma");
SetMapping("kpcomma");
} else {
pressedKeys.insert("comma");
SetMapping("comma");
}
break;
case Qt::Key_Period:
if (Qt::KeypadModifier & QApplication::keyboardModifiers()) {
pressedKeys.insert("kpperiod");
SetMapping("kpperiod");
} else {
pressedKeys.insert("period");
SetMapping("period");
}
break;
case Qt::Key_Slash:
if (Qt::KeypadModifier & QApplication::keyboardModifiers())
pressedKeys.insert("kpdivide");
SetMapping("kpdivide");
break;
case Qt::Key_Asterisk:
if (Qt::KeypadModifier & QApplication::keyboardModifiers())
pressedKeys.insert("kpmultiply");
SetMapping("kpmultiply");
break;
case Qt::Key_Question:
pressedKeys.insert("question");
SetMapping("question");
break;
case Qt::Key_Semicolon:
pressedKeys.insert("semicolon");
SetMapping("semicolon");
break;
case Qt::Key_Minus:
if (Qt::KeypadModifier & QApplication::keyboardModifiers()) {
pressedKeys.insert("kpminus");
SetMapping("kpminus");
} else {
pressedKeys.insert("minus");
SetMapping("minus");
}
break;
case Qt::Key_Plus:
if (Qt::KeypadModifier & QApplication::keyboardModifiers()) {
pressedKeys.insert("kpplus");
SetMapping("kpplus");
} else {
pressedKeys.insert("plus");
SetMapping("plus");
}
break;
case Qt::Key_ParenLeft:
pressedKeys.insert("lparenthesis");
SetMapping("lparenthesis");
break;
case Qt::Key_ParenRight:
pressedKeys.insert("rparenthesis");
SetMapping("rparenthesis");
break;
case Qt::Key_BracketLeft:
pressedKeys.insert("lbracket");
SetMapping("lbracket");
break;
case Qt::Key_BracketRight:
pressedKeys.insert("rbracket");
SetMapping("rbracket");
break;
case Qt::Key_BraceLeft:
pressedKeys.insert("lbrace");
SetMapping("lbrace");
break;
case Qt::Key_BraceRight:
pressedKeys.insert("rbrace");
SetMapping("rbrace");
break;
case Qt::Key_Backslash:
pressedKeys.insert("backslash");
SetMapping("backslash");
break;
case Qt::Key_Tab:
pressedKeys.insert("tab");
SetMapping("tab");
break;
case Qt::Key_Backspace:
pressedKeys.insert("backspace");
SetMapping("backspace");
break;
case Qt::Key_Return:
pressedKeys.insert("enter");
SetMapping("enter");
break;
case Qt::Key_Enter:
pressedKeys.insert("kpenter");
break;
case Qt::Key_Home:
pressedKeys.insert("home");
break;
case Qt::Key_End:
pressedKeys.insert("end");
break;
case Qt::Key_PageDown:
pressedKeys.insert("pgdown");
break;
case Qt::Key_PageUp:
pressedKeys.insert("pgup");
break;
case Qt::Key_CapsLock:
pressedKeys.insert("capslock");
SetMapping("kpenter");
break;
case Qt::Key_Escape:
pressedKeys.insert("unmapped");
SetMapping("unmapped");
break;
case Qt::Key_Shift:
if (keyEvent->nativeScanCode() == rshift) {
pressedKeys.insert("rshift");
} else {
pressedKeys.insert("lshift");
}
SetMapping("lshift");
break;
case Qt::Key_Alt:
if (keyEvent->nativeScanCode() == ralt) {
pressedKeys.insert("ralt");
} else {
pressedKeys.insert("lalt");
}
SetMapping("lalt");
break;
case Qt::Key_Control:
if (keyEvent->nativeScanCode() == rctrl) {
pressedKeys.insert("rctrl");
} else {
pressedKeys.insert("lctrl");
}
SetMapping("lctrl");
break;
case Qt::Key_Meta:
activateWindow();
#ifdef _WIN32
pressedKeys.insert("lwin");
SetMapping("lwin");
#else
pressedKeys.insert("lmeta");
SetMapping("lmeta");
#endif
case Qt::Key_1:
if (Qt::KeypadModifier & QApplication::keyboardModifiers()) {
pressedKeys.insert("kp1");
SetMapping("kp1");
} else {
pressedKeys.insert("1");
SetMapping("1");
}
break;
case Qt::Key_2:
if (Qt::KeypadModifier & QApplication::keyboardModifiers()) {
pressedKeys.insert("kp2");
SetMapping("kp2");
} else {
pressedKeys.insert("2");
SetMapping("2");
}
break;
case Qt::Key_3:
if (Qt::KeypadModifier & QApplication::keyboardModifiers()) {
pressedKeys.insert("kp3");
SetMapping("kp3");
} else {
pressedKeys.insert("3");
SetMapping("3");
}
break;
case Qt::Key_4:
if (Qt::KeypadModifier & QApplication::keyboardModifiers()) {
pressedKeys.insert("kp4");
SetMapping("kp4");
} else {
pressedKeys.insert("4");
SetMapping("4");
}
break;
case Qt::Key_5:
if (Qt::KeypadModifier & QApplication::keyboardModifiers()) {
pressedKeys.insert("kp5");
SetMapping("kp5");
} else {
pressedKeys.insert("5");
SetMapping("5");
}
break;
case Qt::Key_6:
if (Qt::KeypadModifier & QApplication::keyboardModifiers()) {
pressedKeys.insert("kp6");
SetMapping("kp6");
} else {
pressedKeys.insert("6");
SetMapping("6");
}
break;
case Qt::Key_7:
if (Qt::KeypadModifier & QApplication::keyboardModifiers()) {
pressedKeys.insert("kp7");
SetMapping("kp7");
} else {
pressedKeys.insert("7");
SetMapping("7");
}
break;
case Qt::Key_8:
if (Qt::KeypadModifier & QApplication::keyboardModifiers()) {
pressedKeys.insert("kp8");
SetMapping("kp8");
} else {
pressedKeys.insert("8");
SetMapping("8");
}
break;
case Qt::Key_9:
if (Qt::KeypadModifier & QApplication::keyboardModifiers()) {
pressedKeys.insert("kp9");
SetMapping("kp9");
} else {
pressedKeys.insert("9");
SetMapping("9");
}
break;
case Qt::Key_0:
if (Qt::KeypadModifier & QApplication::keyboardModifiers()) {
pressedKeys.insert("kp0");
SetMapping("kp0");
} else {
pressedKeys.insert("0");
SetMapping("0");
}
break;
case Qt::Key_Up:
activateWindow();
pressedKeys.insert("up");
SetMapping("up");
break;
case Qt::Key_Down:
pressedKeys.insert("down");
SetMapping("down");
break;
case Qt::Key_Left:
pressedKeys.insert("left");
SetMapping("left");
break;
case Qt::Key_Right:
pressedKeys.insert("right");
SetMapping("right");
break;
case Qt::Key_A:
pressedKeys.insert("a");
SetMapping("a");
break;
case Qt::Key_B:
pressedKeys.insert("b");
SetMapping("b");
break;
case Qt::Key_C:
pressedKeys.insert("c");
SetMapping("c");
break;
case Qt::Key_D:
pressedKeys.insert("d");
SetMapping("d");
break;
case Qt::Key_E:
pressedKeys.insert("e");
SetMapping("e");
break;
case Qt::Key_F:
pressedKeys.insert("f");
SetMapping("f");
break;
case Qt::Key_G:
pressedKeys.insert("g");
SetMapping("g");
break;
case Qt::Key_H:
pressedKeys.insert("h");
SetMapping("h");
break;
case Qt::Key_I:
pressedKeys.insert("i");
SetMapping("i");
break;
case Qt::Key_J:
pressedKeys.insert("j");
SetMapping("j");
break;
case Qt::Key_K:
pressedKeys.insert("k");
SetMapping("k");
break;
case Qt::Key_L:
pressedKeys.insert("l");
SetMapping("l");
break;
case Qt::Key_M:
pressedKeys.insert("m");
SetMapping("m");
break;
case Qt::Key_N:
pressedKeys.insert("n");
SetMapping("n");
break;
case Qt::Key_O:
pressedKeys.insert("o");
SetMapping("o");
break;
case Qt::Key_P:
pressedKeys.insert("p");
SetMapping("p");
break;
case Qt::Key_Q:
pressedKeys.insert("q");
SetMapping("q");
break;
case Qt::Key_R:
pressedKeys.insert("r");
SetMapping("r");
break;
case Qt::Key_S:
pressedKeys.insert("s");
SetMapping("s");
break;
case Qt::Key_T:
pressedKeys.insert("t");
SetMapping("t");
break;
case Qt::Key_U:
pressedKeys.insert("u");
SetMapping("u");
break;
case Qt::Key_V:
pressedKeys.insert("v");
SetMapping("v");
break;
case Qt::Key_W:
pressedKeys.insert("w");
SetMapping("w");
break;
case Qt::Key_X:
pressedKeys.insert("x");
SetMapping("x");
break;
case Qt::Key_Y:
pressedKeys.insert("Y");
SetMapping("Y");
break;
case Qt::Key_Z:
pressedKeys.insert("z");
SetMapping("z");
break;
default:
break;
}
return true;
}
}
if (event->type() == QEvent::MouseButtonPress) {
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
if (pressedKeys.size() < 3) {
if (event->type() == QEvent::MouseButtonPress) {
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
switch (mouseEvent->button()) {
case Qt::LeftButton:
pressedKeys.insert("leftbutton");
SetMapping("leftbutton");
break;
case Qt::RightButton:
pressedKeys.insert("rightbutton");
SetMapping("rightbutton");
break;
case Qt::MiddleButton:
pressedKeys.insert("middlebutton");
SetMapping("middlebutton");
break;
default:
break;
}
return true;
}
}
const QList<QPushButton*> AxisList = {
ui->LStickUpButton, ui->LStickDownButton, ui->LStickLeftButton, ui->LStickRightButton,
ui->RStickUpButton, ui->LStickDownButton, ui->LStickLeftButton, ui->RStickRightButton};
const QList<QPushButton*> AxisList = {
ui->LStickUpButton, ui->LStickDownButton, ui->LStickLeftButton, ui->LStickRightButton,
ui->RStickUpButton, ui->LStickDownButton, ui->LStickLeftButton, ui->RStickRightButton};
if (event->type() == QEvent::Wheel) {
QWheelEvent* wheelEvent = static_cast<QWheelEvent*>(event);
if (pressedKeys.size() < 3) {
if (event->type() == QEvent::Wheel) {
QWheelEvent* wheelEvent = static_cast<QWheelEvent*>(event);
if (wheelEvent->angleDelta().y() > 5) {
if (std::find(AxisList.begin(), AxisList.end(), MappingButton) == AxisList.end()) {
pressedKeys.insert("mousewheelup");
SetMapping("mousewheelup");
} else {
QMessageBox::information(this, tr("Cannot set mapping"),
tr("Mousewheel cannot be mapped to stick outputs"));
}
} else if (wheelEvent->angleDelta().y() < -5) {
if (std::find(AxisList.begin(), AxisList.end(), MappingButton) == AxisList.end()) {
pressedKeys.insert("mousewheeldown");
SetMapping("mousewheeldown");
} else {
QMessageBox::information(this, tr("Cannot set mapping"),
tr("Mousewheel cannot be mapped to stick outputs"));
@ -1003,9 +972,9 @@ bool KBMSettings::eventFilter(QObject* obj, QEvent* event) {
if (std::find(AxisList.begin(), AxisList.end(), MappingButton) == AxisList.end()) {
// QT changes scrolling to horizontal for all widgets with the alt modifier
if (Qt::AltModifier & QApplication::keyboardModifiers()) {
pressedKeys.insert("mousewheelup");
SetMapping("mousewheelup");
} else {
pressedKeys.insert("mousewheelright");
SetMapping("mousewheelright");
}
} else {
QMessageBox::information(this, tr("Cannot set mapping"),
@ -1014,18 +983,18 @@ bool KBMSettings::eventFilter(QObject* obj, QEvent* event) {
} else if (wheelEvent->angleDelta().x() < -5) {
if (std::find(AxisList.begin(), AxisList.end(), MappingButton) == AxisList.end()) {
if (Qt::AltModifier & QApplication::keyboardModifiers()) {
pressedKeys.insert("mousewheeldown");
SetMapping("mousewheeldown");
} else {
pressedKeys.insert("mousewheelleft");
SetMapping("mousewheelleft");
}
} else {
QMessageBox::information(this, tr("Cannot set mapping"),
tr("Mousewheel cannot be mapped to stick outputs"));
}
}
return true;
}
}
return QDialog::eventFilter(obj, event);
}

View file

@ -25,22 +25,6 @@ private:
std::unique_ptr<Ui::KBMSettings> ui;
std::shared_ptr<GameInfoClass> m_game_info;
#ifdef _WIN32
const int lctrl = 29;
const int rctrl = 57373;
const int lalt = 56;
const int ralt = 57400;
const int lshift = 42;
const int rshift = 54;
#else
const int lctrl = 37;
const int rctrl = 105;
const int lalt = 64;
const int ralt = 108;
const int lshift = 50;
const int rshift = 62;
#endif
bool eventFilter(QObject* obj, QEvent* event) override;
void ButtonConnects();
void SetUIValuestoMappings(std::string config_id);
@ -49,7 +33,6 @@ private:
void EnableMappingButtons();
void SetMapping(QString input);
QSet<QString> pressedKeys;
bool EnableMapping = false;
bool MappingCompleted = false;
bool HelpWindowOpen = false;

View file

@ -384,23 +384,23 @@
</message>
<message>
<source>Nothing</source>
<translation>Không chạy đưc</translation>
<translation>Không có </translation>
</message>
<message>
<source>Boots</source>
<translation>Chạy đưc</translation>
<translation>Giày ng</translation>
</message>
<message>
<source>Menus</source>
<translation>Vào đưc menu</translation>
<translation>Menu</translation>
</message>
<message>
<source>Ingame</source>
<translation>Vào đưc trò chơi</translation>
<translation>Trong game</translation>
</message>
<message>
<source>Playable</source>
<translation>Chơi đưc</translation>
<translation>Có thể chơi</translation>
</message>
</context>
<context>
@ -411,7 +411,7 @@
</message>
<message>
<source>D-Pad</source>
<translation>D-Pad</translation>
<translation type="unfinished">D-Pad</translation>
</message>
<message>
<source>Up</source>
@ -447,7 +447,7 @@
</message>
<message>
<source>Common Config</source>
<translation>Cài Đt Chung</translation>
<translation type="unfinished">Common Config</translation>
</message>
<message>
<source>Use per-game configs</source>
@ -551,26 +551,26 @@
</message>
<message>
<source>Save</source>
<translation>Lưu</translation>
<translation type="unfinished">Save</translation>
</message>
<message>
<source>Apply</source>
<translation>Áp dụng</translation>
<translation type="unfinished">Apply</translation>
</message>
<message>
<source>Restore Defaults</source>
<translation>Khôi Phục Mặc Đnh</translation>
<translation type="unfinished">Restore Defaults</translation>
</message>
<message>
<source>Cancel</source>
<translation>Hủy</translation>
<translation type="unfinished">Cancel</translation>
</message>
</context>
<context>
<name>EditorDialog</name>
<message>
<source>Edit Keyboard + Mouse and Controller input bindings</source>
<translation>Tùy chỉnh phím đưc gán cho Bàn phím + Chuột Tay cầm</translation>
<translation type="unfinished">Edit Keyboard + Mouse and Controller input bindings</translation>
</message>
<message>
<source>Use Per-Game configs</source>
@ -578,7 +578,7 @@
</message>
<message>
<source>Error</source>
<translation>Lỗi</translation>
<translation type="unfinished">Error</translation>
</message>
<message>
<source>Could not open the file for reading</source>
@ -590,15 +590,15 @@
</message>
<message>
<source>Save Changes</source>
<translation>Lưu Thay Đi</translation>
<translation type="unfinished">Save Changes</translation>
</message>
<message>
<source>Do you want to save changes?</source>
<translation>Bạn muốn lưu thay đi?</translation>
<translation type="unfinished">Do you want to save changes?</translation>
</message>
<message>
<source>Help</source>
<translation>Trợ giúp</translation>
<translation type="unfinished">Help</translation>
</message>
<message>
<source>Do you want to reset your custom default config to the original default config?</source>
@ -706,15 +706,15 @@
</message>
<message>
<source>h</source>
<translation>giờ</translation>
<translation type="unfinished">h</translation>
</message>
<message>
<source>m</source>
<translation>phút</translation>
<translation type="unfinished">m</translation>
</message>
<message>
<source>s</source>
<translation>giây</translation>
<translation type="unfinished">s</translation>
</message>
<message>
<source>Compatibility is untested</source>
@ -722,23 +722,23 @@
</message>
<message>
<source>Game does not initialize properly / crashes the emulator</source>
<translation>Trò chơi không đưc khởi chạy đúng cách / khiến giả lập bị văng</translation>
<translation type="unfinished">Game does not initialize properly / crashes the emulator</translation>
</message>
<message>
<source>Game boots, but only displays a blank screen</source>
<translation>Trò chơi thể khởi chạy, nhưng chẳng hiện cả</translation>
<translation type="unfinished">Game boots, but only displays a blank screen</translation>
</message>
<message>
<source>Game displays an image but does not go past the menu</source>
<translation>Trò chơi hiển thị đưc hình nh, nhưng không thể tiếp tục từ menu</translation>
<translation type="unfinished">Game displays an image but does not go past the menu</translation>
</message>
<message>
<source>Game has game-breaking glitches or unplayable performance</source>
<translation>Trò chơi lỗi nh hưởng đến trải nghiệm, hoặc hiệu năng khi chơi không n đnh</translation>
<translation type="unfinished">Game has game-breaking glitches or unplayable performance</translation>
</message>
<message>
<source>Game can be completed with playable performance and no major glitches</source>
<translation>Trò chơi thể đưc hoàn thành từ đu đến cuối, hiệu năng n đnh không lỗi nh hưởng đến trải nghiệm</translation>
<translation type="unfinished">Game can be completed with playable performance and no major glitches</translation>
</message>
<message>
<source>Click to see details on github</source>
@ -1170,19 +1170,19 @@
</message>
<message>
<source>Save</source>
<translation>Lưu</translation>
<translation type="unfinished">Save</translation>
</message>
<message>
<source>Apply</source>
<translation>Áp dụng</translation>
<translation type="unfinished">Apply</translation>
</message>
<message>
<source>Restore Defaults</source>
<translation>Khôi Phục Mặc Đnh</translation>
<translation type="unfinished">Restore Defaults</translation>
</message>
<message>
<source>Cancel</source>
<translation>Hủy</translation>
<translation type="unfinished">Cancel</translation>
</message>
</context>
<context>
@ -1193,7 +1193,7 @@
</message>
<message>
<source>Boot Game</source>
<translation>Khởi Chạy Trò Chơi</translation>
<translation type="unfinished">Boot Game</translation>
</message>
<message>
<source>Check for Updates</source>
@ -1201,7 +1201,7 @@
</message>
<message>
<source>About shadPS4</source>
<translation>Thông Tin Về shadPS4</translation>
<translation type="unfinished">About shadPS4</translation>
</message>
<message>
<source>Configure...</source>
@ -1213,23 +1213,23 @@
</message>
<message>
<source>Open shadPS4 Folder</source>
<translation>Mở Thư Mục Của shadPS4</translation>
<translation type="unfinished">Open shadPS4 Folder</translation>
</message>
<message>
<source>Exit</source>
<translation>Thoát</translation>
<translation type="unfinished">Exit</translation>
</message>
<message>
<source>Exit shadPS4</source>
<translation>Thoát shadPS4</translation>
<translation type="unfinished">Exit shadPS4</translation>
</message>
<message>
<source>Exit the application.</source>
<translation>Thoát ng dụng.</translation>
<translation type="unfinished">Exit the application.</translation>
</message>
<message>
<source>Show Game List</source>
<translation>Hiển Thị Danh Sách Trò Chơi</translation>
<translation type="unfinished">Show Game List</translation>
</message>
<message>
<source>Game List Refresh</source>

View file

@ -270,10 +270,6 @@ void SetupCapabilities(const Info& info, const Profile& profile, EmitContext& ct
if (info.has_image_query) {
ctx.AddCapability(spv::Capability::ImageQuery);
}
if (info.uses_atomic_float_min_max && profile.supports_image_fp32_atomic_min_max) {
ctx.AddExtension("SPV_EXT_shader_atomic_float_min_max");
ctx.AddCapability(spv::Capability::AtomicFloat32MinMaxEXT);
}
if (info.uses_lane_id) {
ctx.AddCapability(spv::Capability::GroupNonUniform);
}
@ -339,7 +335,8 @@ void DefineEntryPoint(const Info& info, EmitContext& ctx, Id main) {
ctx.AddExecutionMode(main, spv::ExecutionMode::OriginUpperLeft);
}
if (info.has_discard) {
ctx.AddCapability(spv::Capability::DemoteToHelperInvocation);
ctx.AddExtension("SPV_EXT_demote_to_helper_invocation");
ctx.AddCapability(spv::Capability::DemoteToHelperInvocationEXT);
}
if (info.stores.GetAny(IR::Attribute::Depth)) {
ctx.AddExecutionMode(main, spv::ExecutionMode::DepthReplacing);

View file

@ -38,7 +38,6 @@ Id BufferAtomicU32BoundsCheck(EmitContext& ctx, Id index, Id buffer_size, auto e
const Id ib_label = ctx.OpLabel();
const Id oob_label = ctx.OpLabel();
const Id end_label = ctx.OpLabel();
ctx.OpSelectionMerge(end_label, spv::SelectionControlMask::MaskNone);
ctx.OpBranchConditional(in_bounds, ib_label, oob_label);
ctx.AddLabel(ib_label);
const Id ib_result = emit_func();
@ -75,14 +74,6 @@ Id ImageAtomicU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id va
const auto [scope, semantics]{AtomicArgs(ctx)};
return (ctx.*atomic_func)(ctx.U32[1], pointer, scope, semantics, value);
}
Id ImageAtomicF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value,
Id (Sirit::Module::*atomic_func)(Id, Id, Id, Id, Id)) {
const auto& texture = ctx.images[handle & 0xFFFF];
const Id pointer{ctx.OpImageTexelPointer(ctx.image_f32, texture.id, coords, ctx.ConstU32(0U))};
const auto [scope, semantics]{AtomicArgs(ctx)};
return (ctx.*atomic_func)(ctx.F32[1], pointer, scope, semantics, value);
}
} // Anonymous namespace
Id EmitSharedAtomicIAdd32(EmitContext& ctx, Id offset, Id value) {
@ -195,40 +186,6 @@ Id EmitImageAtomicUMax32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords
return ImageAtomicU32(ctx, inst, handle, coords, value, &Sirit::Module::OpAtomicUMax);
}
Id EmitImageAtomicFMax32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value) {
if (ctx.profile.supports_image_fp32_atomic_min_max) {
return ImageAtomicF32(ctx, inst, handle, coords, value, &Sirit::Module::OpAtomicFMax);
}
const auto u32_value = ctx.OpBitcast(ctx.U32[1], value);
const auto sign_bit_set =
ctx.OpBitFieldUExtract(ctx.U32[1], u32_value, ctx.ConstU32(31u), ctx.ConstU32(1u));
const auto result = ctx.OpSelect(
ctx.F32[1], sign_bit_set,
EmitBitCastF32U32(ctx, EmitImageAtomicUMin32(ctx, inst, handle, coords, u32_value)),
EmitBitCastF32U32(ctx, EmitImageAtomicSMax32(ctx, inst, handle, coords, u32_value)));
return result;
}
Id EmitImageAtomicFMin32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value) {
if (ctx.profile.supports_image_fp32_atomic_min_max) {
return ImageAtomicF32(ctx, inst, handle, coords, value, &Sirit::Module::OpAtomicFMin);
}
const auto u32_value = ctx.OpBitcast(ctx.U32[1], value);
const auto sign_bit_set =
ctx.OpBitFieldUExtract(ctx.U32[1], u32_value, ctx.ConstU32(31u), ctx.ConstU32(1u));
const auto result = ctx.OpSelect(
ctx.F32[1], sign_bit_set,
EmitBitCastF32U32(ctx, EmitImageAtomicUMax32(ctx, inst, handle, coords, u32_value)),
EmitBitCastF32U32(ctx, EmitImageAtomicSMin32(ctx, inst, handle, coords, u32_value)));
return result;
}
Id EmitImageAtomicInc32(EmitContext&, IR::Inst*, u32, Id, Id) {
// TODO: This is not yet implemented
throw NotImplementedException("SPIR-V Instruction");

View file

@ -64,6 +64,10 @@ Id EmitBitCastU32F32(EmitContext& ctx, Id value) {
return ctx.OpBitcast(ctx.U32[1], value);
}
Id EmitBitCastU64F64(EmitContext& ctx, Id value) {
return ctx.OpBitcast(ctx.U64, value);
}
Id EmitBitCastF16U16(EmitContext& ctx, Id value) {
return ctx.OpBitcast(ctx.F16[1], value);
}
@ -72,6 +76,10 @@ Id EmitBitCastF32U32(EmitContext& ctx, Id value) {
return ctx.OpBitcast(ctx.F32[1], value);
}
void EmitBitCastF64U64(EmitContext&) {
UNREACHABLE_MSG("SPIR-V Instruction");
}
Id EmitPackUint2x32(EmitContext& ctx, Id value) {
return ctx.OpBitcast(ctx.U64, value);
}
@ -80,14 +88,10 @@ Id EmitUnpackUint2x32(EmitContext& ctx, Id value) {
return ctx.OpBitcast(ctx.U32[2], value);
}
Id EmitPackDouble2x32(EmitContext& ctx, Id value) {
Id EmitPackFloat2x32(EmitContext& ctx, Id value) {
return ctx.OpBitcast(ctx.F64[1], value);
}
Id EmitUnpackDouble2x32(EmitContext& ctx, Id value) {
return ctx.OpBitcast(ctx.U32[2], value);
}
Id EmitPackUnorm2x16(EmitContext& ctx, Id value) {
return ctx.OpPackUnorm2x16(ctx.U32[1], value);
}

View file

@ -529,7 +529,7 @@ void EmitStoreBufferBoundsCheck(EmitContext& ctx, Id index, Id buffer_size, auto
// Bounds checking enabled, wrap in a conditional branch.
auto compare_index = index;
if (N > 1) {
compare_index = ctx.OpIAdd(ctx.U32[1], index, ctx.ConstU32(N - 1));
index = ctx.OpIAdd(ctx.U32[1], index, ctx.ConstU32(N - 1));
}
const Id in_bounds = ctx.OpULessThan(ctx.U1[1], compare_index, buffer_size);
const Id in_bounds_label = ctx.OpLabel();

View file

@ -202,12 +202,13 @@ Id EmitSelectF32(EmitContext& ctx, Id cond, Id true_value, Id false_value);
Id EmitSelectF64(EmitContext& ctx, Id cond, Id true_value, Id false_value);
Id EmitBitCastU16F16(EmitContext& ctx, Id value);
Id EmitBitCastU32F32(EmitContext& ctx, Id value);
Id EmitBitCastU64F64(EmitContext& ctx, Id value);
Id EmitBitCastF16U16(EmitContext& ctx, Id value);
Id EmitBitCastF32U32(EmitContext& ctx, Id value);
void EmitBitCastF64U64(EmitContext& ctx);
Id EmitPackUint2x32(EmitContext& ctx, Id value);
Id EmitUnpackUint2x32(EmitContext& ctx, Id value);
Id EmitPackDouble2x32(EmitContext& ctx, Id value);
Id EmitUnpackDouble2x32(EmitContext& ctx, Id value);
Id EmitPackFloat2x32(EmitContext& ctx, Id value);
Id EmitPackUnorm2x16(EmitContext& ctx, Id value);
Id EmitUnpackUnorm2x16(EmitContext& ctx, Id value);
Id EmitPackSnorm2x16(EmitContext& ctx, Id value);
@ -482,8 +483,6 @@ Id EmitImageAtomicSMin32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords
Id EmitImageAtomicUMin32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
Id EmitImageAtomicSMax32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
Id EmitImageAtomicUMax32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
Id EmitImageAtomicFMax32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
Id EmitImageAtomicFMin32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
Id EmitImageAtomicInc32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
Id EmitImageAtomicDec32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
Id EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);

View file

@ -869,7 +869,6 @@ void EmitContext::DefineImagesAndSamplers() {
}
if (std::ranges::any_of(info.images, &ImageResource::is_atomic)) {
image_u32 = TypePointer(spv::StorageClass::Image, U32[1]);
image_f32 = TypePointer(spv::StorageClass::Image, F32[1]);
}
if (info.samplers.empty()) {
return;

View file

@ -207,7 +207,6 @@ public:
Id invocation_id{};
Id subgroup_local_invocation_id{};
Id image_u32{};
Id image_f32{};
Id shared_memory_u8{};
Id shared_memory_u16{};

View file

@ -336,7 +336,7 @@ T Translator::GetSrc64(const InstOperand& operand) {
const auto value_lo = ir.GetVectorReg(IR::VectorReg(operand.code));
const auto value_hi = ir.GetVectorReg(IR::VectorReg(operand.code + 1));
if constexpr (is_float) {
value = ir.PackDouble2x32(ir.CompositeConstruct(value_lo, value_hi));
value = ir.PackFloat2x32(ir.CompositeConstruct(value_lo, value_hi));
} else {
value = ir.PackUint2x32(ir.CompositeConstruct(value_lo, value_hi));
}
@ -444,9 +444,10 @@ void Translator::SetDst64(const InstOperand& operand, const IR::U64F64& value_ra
value_untyped = ir.FPSaturate(value_raw);
}
}
const IR::U64 value =
is_float ? ir.BitCast<IR::U64>(IR::F64{value_untyped}) : IR::U64{value_untyped};
const IR::Value unpacked{is_float ? ir.UnpackDouble2x32(IR::F64{value_untyped})
: ir.UnpackUint2x32(IR::U64{value_untyped})};
const IR::Value unpacked{ir.UnpackUint2x32(value)};
const IR::U32 lo{ir.CompositeExtract(unpacked, 0U)};
const IR::U32 hi{ir.CompositeExtract(unpacked, 1U)};
switch (operand.field) {
@ -517,9 +518,7 @@ void Translator::EmitFetch(const GcnInst& inst) {
const auto values =
ir.CompositeConstruct(ir.GetAttribute(attr, 0), ir.GetAttribute(attr, 1),
ir.GetAttribute(attr, 2), ir.GetAttribute(attr, 3));
const auto converted =
IR::ApplyReadNumberConversionVec4(ir, values, buffer.GetNumberConversion());
const auto swizzled = ApplySwizzle(ir, converted, buffer.DstSelect());
const auto swizzled = ApplySwizzle(ir, values, buffer.DstSelect());
for (u32 i = 0; i < 4; i++) {
ir.SetVectorReg(dst_reg++, IR::F32{ir.CompositeExtract(swizzled, i)});
}

View file

@ -513,13 +513,13 @@ void Translator::V_LSHLREV_B32(const GcnInst& inst) {
void Translator::V_AND_B32(const GcnInst& inst) {
const IR::U32 src0{GetSrc(inst.src[0])};
const IR::U32 src1{GetSrc(inst.src[1])};
const IR::U32 src1{ir.GetVectorReg(IR::VectorReg(inst.src[1].code))};
SetDst(inst.dst[0], ir.BitwiseAnd(src0, src1));
}
void Translator::V_OR_B32(bool is_xor, const GcnInst& inst) {
const IR::U32 src0{GetSrc(inst.src[0])};
const IR::U32 src1{GetSrc(inst.src[1])};
const IR::U32 src1{ir.GetVectorReg(IR::VectorReg(inst.src[1].code))};
SetDst(inst.dst[0], is_xor ? ir.BitwiseXor(src0, src1) : IR::U32(ir.BitwiseOr(src0, src1)));
}
@ -579,7 +579,7 @@ void Translator::V_MBCNT_U32_B32(bool is_low, const GcnInst& inst) {
void Translator::V_ADD_I32(const GcnInst& inst) {
// Signed or unsigned components
const IR::U32 src0{GetSrc(inst.src[0])};
const IR::U32 src1{GetSrc(inst.src[1])};
const IR::U32 src1{ir.GetVectorReg(IR::VectorReg(inst.src[1].code))};
const IR::U32 result{ir.IAdd(src0, src1)};
SetDst(inst.dst[0], result);

View file

@ -115,12 +115,8 @@ void Translator::EmitVectorMemory(const GcnInst& inst) {
return IMAGE_ATOMIC(AtomicOp::Smin, inst);
case Opcode::IMAGE_ATOMIC_UMIN:
return IMAGE_ATOMIC(AtomicOp::Umin, inst);
case Opcode::IMAGE_ATOMIC_FMIN:
return IMAGE_ATOMIC(AtomicOp::Fmin, inst);
case Opcode::IMAGE_ATOMIC_SMAX:
return IMAGE_ATOMIC(AtomicOp::Smax, inst);
case Opcode::IMAGE_ATOMIC_FMAX:
return IMAGE_ATOMIC(AtomicOp::Fmax, inst);
case Opcode::IMAGE_ATOMIC_UMAX:
return IMAGE_ATOMIC(AtomicOp::Umax, inst);
case Opcode::IMAGE_ATOMIC_AND:
@ -470,10 +466,6 @@ void Translator::IMAGE_ATOMIC(AtomicOp op, const GcnInst& inst) {
return ir.ImageAtomicIMax(handle, body, value, true, info);
case AtomicOp::Umax:
return ir.ImageAtomicUMax(handle, body, value, info);
case AtomicOp::Fmax:
return ir.ImageAtomicFMax(handle, body, value, info);
case AtomicOp::Fmin:
return ir.ImageAtomicFMin(handle, body, value, info);
case AtomicOp::And:
return ir.ImageAtomicAnd(handle, body, value, info);
case AtomicOp::Or:

View file

@ -196,7 +196,6 @@ struct Info {
bool has_discard{};
bool has_image_gather{};
bool has_image_query{};
bool uses_atomic_float_min_max{};
bool uses_lane_id{};
bool uses_group_quad{};
bool uses_group_ballot{};

View file

@ -84,6 +84,16 @@ IR::F16 IREmitter::BitCast<IR::F16, IR::U16>(const IR::U16& value) {
return Inst<IR::F16>(Opcode::BitCastF16U16, value);
}
template <>
IR::U64 IREmitter::BitCast<IR::U64, IR::F64>(const IR::F64& value) {
return Inst<IR::U64>(Opcode::BitCastU64F64, value);
}
template <>
IR::F64 IREmitter::BitCast<IR::F64, IR::U64>(const IR::U64& value) {
return Inst<IR::F64>(Opcode::BitCastF64U64, value);
}
U1 IREmitter::ConditionRef(const U1& value) {
return Inst<U1>(Opcode::ConditionRef, value);
}
@ -831,12 +841,8 @@ Value IREmitter::UnpackUint2x32(const U64& value) {
return Inst<Value>(Opcode::UnpackUint2x32, value);
}
F64 IREmitter::PackDouble2x32(const Value& vector) {
return Inst<F64>(Opcode::PackDouble2x32, vector);
}
Value IREmitter::UnpackDouble2x32(const F64& value) {
return Inst<Value>(Opcode::UnpackDouble2x32, value);
F64 IREmitter::PackFloat2x32(const Value& vector) {
return Inst<F64>(Opcode::PackFloat2x32, vector);
}
U32 IREmitter::Pack2x16(const AmdGpu::NumberFormat number_format, const Value& vector) {
@ -1870,16 +1876,6 @@ Value IREmitter::ImageAtomicUMax(const Value& handle, const Value& coords, const
return Inst(Opcode::ImageAtomicUMax32, Flags{info}, handle, coords, value);
}
Value IREmitter::ImageAtomicFMax(const Value& handle, const Value& coords, const Value& value,
TextureInstInfo info) {
return Inst(Opcode::ImageAtomicFMax32, Flags{info}, handle, coords, value);
}
Value IREmitter::ImageAtomicFMin(const Value& handle, const Value& coords, const Value& value,
TextureInstInfo info) {
return Inst(Opcode::ImageAtomicFMin32, Flags{info}, handle, coords, value);
}
Value IREmitter::ImageAtomicIMax(const Value& handle, const Value& coords, const Value& value,
bool is_signed, TextureInstInfo info) {
return is_signed ? ImageAtomicSMax(handle, coords, value, info)

View file

@ -181,8 +181,7 @@ public:
[[nodiscard]] U64 PackUint2x32(const Value& vector);
[[nodiscard]] Value UnpackUint2x32(const U64& value);
[[nodiscard]] F64 PackDouble2x32(const Value& vector);
[[nodiscard]] Value UnpackDouble2x32(const F64& value);
[[nodiscard]] F64 PackFloat2x32(const Value& vector);
[[nodiscard]] U32 Pack2x16(AmdGpu::NumberFormat number_format, const Value& vector);
[[nodiscard]] Value Unpack2x16(AmdGpu::NumberFormat number_format, const U32& value);
@ -321,10 +320,6 @@ public:
const Value& value, TextureInstInfo info);
[[nodiscard]] Value ImageAtomicUMax(const Value& handle, const Value& coords,
const Value& value, TextureInstInfo info);
[[nodiscard]] Value ImageAtomicFMax(const Value& handle, const Value& coords,
const Value& value, TextureInstInfo info);
[[nodiscard]] Value ImageAtomicFMin(const Value& handle, const Value& coords,
const Value& value, TextureInstInfo info);
[[nodiscard]] Value ImageAtomicIMax(const Value& handle, const Value& coords,
const Value& value, bool is_signed, TextureInstInfo info);
[[nodiscard]] Value ImageAtomicInc(const Value& handle, const Value& coords, const Value& value,

View file

@ -94,8 +94,6 @@ bool Inst::MayHaveSideEffects() const noexcept {
case Opcode::ImageAtomicUMin32:
case Opcode::ImageAtomicSMax32:
case Opcode::ImageAtomicUMax32:
case Opcode::ImageAtomicFMax32:
case Opcode::ImageAtomicFMin32:
case Opcode::ImageAtomicInc32:
case Opcode::ImageAtomicDec32:
case Opcode::ImageAtomicAnd32:

View file

@ -191,13 +191,14 @@ OPCODE(SelectF64, F64, U1,
// Bitwise conversions
OPCODE(BitCastU16F16, U16, F16, )
OPCODE(BitCastU32F32, U32, F32, )
OPCODE(BitCastU64F64, U64, F64, )
OPCODE(BitCastF16U16, F16, U16, )
OPCODE(BitCastF32U32, F32, U32, )
OPCODE(BitCastF64U64, F64, U64, )
OPCODE(PackUint2x32, U64, U32x2, )
OPCODE(UnpackUint2x32, U32x2, U64, )
OPCODE(PackDouble2x32, F64, U32x2, )
OPCODE(UnpackDouble2x32, U32x2, F64, )
OPCODE(PackFloat2x32, F64, F32x2, )
OPCODE(PackUnorm2x16, U32, F32x2, )
OPCODE(UnpackUnorm2x16, F32x2, U32, )
@ -420,8 +421,6 @@ OPCODE(ImageAtomicSMin32, U32, Opaq
OPCODE(ImageAtomicUMin32, U32, Opaque, Opaque, U32, )
OPCODE(ImageAtomicSMax32, U32, Opaque, Opaque, U32, )
OPCODE(ImageAtomicUMax32, U32, Opaque, Opaque, U32, )
OPCODE(ImageAtomicFMax32, F32, Opaque, Opaque, F32, )
OPCODE(ImageAtomicFMin32, F32, Opaque, Opaque, F32, )
OPCODE(ImageAtomicInc32, U32, Opaque, Opaque, U32, )
OPCODE(ImageAtomicDec32, U32, Opaque, Opaque, U32, )
OPCODE(ImageAtomicAnd32, U32, Opaque, Opaque, U32, )

View file

@ -21,7 +21,6 @@ void ReadLaneEliminationPass(IR::Program& program);
void ResourceTrackingPass(IR::Program& program);
void CollectShaderInfoPass(IR::Program& program);
void LowerBufferFormatToRaw(IR::Program& program);
void LowerFp64ToFp32(IR::Program& program);
void RingAccessElimination(const IR::Program& program, const RuntimeInfo& runtime_info);
void TessellationPreprocess(IR::Program& program, RuntimeInfo& runtime_info);
void HullShaderTransform(IR::Program& program, RuntimeInfo& runtime_info);

View file

@ -196,19 +196,13 @@ static void LowerBufferFormatInst(IR::Block& block, IR::Inst& inst, Info& info)
const auto buffer{desc.GetSharp(info)};
const auto is_inst_typed = flags.inst_data_fmt != AmdGpu::DataFormat::FormatInvalid;
const auto data_format =
is_inst_typed ? AmdGpu::RemapDataFormat(flags.inst_data_fmt.Value()) : buffer.GetDataFmt();
const auto data_format = is_inst_typed ? flags.inst_data_fmt.Value() : buffer.GetDataFmt();
const auto num_format = is_inst_typed ? flags.inst_num_fmt.Value() : buffer.GetNumberFmt();
const auto format_info = FormatInfo{
.data_format = data_format,
.num_format = is_inst_typed
? AmdGpu::RemapNumberFormat(flags.inst_num_fmt.Value(), data_format)
: buffer.GetNumberFmt(),
.swizzle = is_inst_typed
? AmdGpu::RemapSwizzle(flags.inst_data_fmt.Value(), AmdGpu::IdentityMapping)
: buffer.DstSelect(),
.num_conversion = is_inst_typed ? AmdGpu::MapNumberConversion(flags.inst_num_fmt.Value(),
flags.inst_data_fmt.Value())
: buffer.GetNumberConversion(),
.num_format = num_format,
.swizzle = is_inst_typed ? AmdGpu::IdentityMapping : buffer.DstSelect(),
.num_conversion = AmdGpu::MapNumberConversion(num_format),
.num_components = AmdGpu::NumComponents(data_format),
};

View file

@ -1,186 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "shader_recompiler/info.h"
#include "shader_recompiler/ir/basic_block.h"
#include "shader_recompiler/ir/ir_emitter.h"
#include "shader_recompiler/ir/program.h"
namespace Shader::Optimization {
constexpr s32 F64ToF32Exp = +1023 - 127;
constexpr s32 F32ToF64Exp = +127 - 1023;
static IR::F32 PackedF64ToF32(IR::IREmitter& ir, const IR::Value& packed) {
const IR::U32 lo{ir.CompositeExtract(packed, 0)};
const IR::U32 hi{ir.CompositeExtract(packed, 1)};
const IR::U32 sign{ir.BitFieldExtract(hi, ir.Imm32(31), ir.Imm32(1))};
const IR::U32 exp{ir.BitFieldExtract(hi, ir.Imm32(20), ir.Imm32(11))};
const IR::U32 mantissa_hi{ir.BitFieldExtract(hi, ir.Imm32(0), ir.Imm32(20))};
const IR::U32 mantissa_lo{ir.BitFieldExtract(lo, ir.Imm32(29), ir.Imm32(3))};
const IR::U32 mantissa{
ir.BitwiseOr(ir.ShiftLeftLogical(mantissa_hi, ir.Imm32(3)), mantissa_lo)};
const IR::U32 exp_if_subnorm{
ir.Select(ir.IEqual(exp, ir.Imm32(0)), ir.Imm32(0), ir.IAdd(exp, ir.Imm32(F64ToF32Exp)))};
const IR::U32 exp_if_infnan{
ir.Select(ir.IEqual(exp, ir.Imm32(0x7ff)), ir.Imm32(0xff), exp_if_subnorm)};
const IR::U32 result{
ir.BitwiseOr(ir.ShiftLeftLogical(sign, ir.Imm32(31)),
ir.BitwiseOr(ir.ShiftLeftLogical(exp_if_infnan, ir.Imm32(23)), mantissa))};
return ir.BitCast<IR::F32>(result);
}
IR::Value F32ToPackedF64(IR::IREmitter& ir, const IR::Value& raw) {
const IR::U32 value{ir.BitCast<IR::U32>(IR::F32(raw))};
const IR::U32 sign{ir.BitFieldExtract(value, ir.Imm32(31), ir.Imm32(1))};
const IR::U32 exp{ir.BitFieldExtract(value, ir.Imm32(23), ir.Imm32(8))};
const IR::U32 mantissa{ir.BitFieldExtract(value, ir.Imm32(0), ir.Imm32(23))};
const IR::U32 mantissa_hi{ir.BitFieldExtract(mantissa, ir.Imm32(3), ir.Imm32(20))};
const IR::U32 mantissa_lo{ir.BitFieldExtract(mantissa, ir.Imm32(0), ir.Imm32(3))};
const IR::U32 exp_if_subnorm{
ir.Select(ir.IEqual(exp, ir.Imm32(0)), ir.Imm32(0), ir.IAdd(exp, ir.Imm32(F32ToF64Exp)))};
const IR::U32 exp_if_infnan{
ir.Select(ir.IEqual(exp, ir.Imm32(0xff)), ir.Imm32(0x7ff), exp_if_subnorm)};
const IR::U32 lo{ir.ShiftLeftLogical(mantissa_lo, ir.Imm32(29))};
const IR::U32 hi{
ir.BitwiseOr(ir.ShiftLeftLogical(sign, ir.Imm32(31)),
ir.BitwiseOr(ir.ShiftLeftLogical(exp_if_infnan, ir.Imm32(20)), mantissa_hi))};
return ir.CompositeConstruct(lo, hi);
}
static IR::Opcode Replace(IR::Opcode op) {
switch (op) {
case IR::Opcode::CompositeConstructF64x2:
return IR::Opcode::CompositeConstructF32x2;
case IR::Opcode::CompositeConstructF64x3:
return IR::Opcode::CompositeConstructF32x3;
case IR::Opcode::CompositeConstructF64x4:
return IR::Opcode::CompositeConstructF32x4;
case IR::Opcode::CompositeExtractF64x2:
return IR::Opcode::CompositeExtractF32x2;
case IR::Opcode::CompositeExtractF64x3:
return IR::Opcode::CompositeExtractF32x3;
case IR::Opcode::CompositeExtractF64x4:
return IR::Opcode::CompositeExtractF32x4;
case IR::Opcode::CompositeInsertF64x2:
return IR::Opcode::CompositeInsertF32x2;
case IR::Opcode::CompositeInsertF64x3:
return IR::Opcode::CompositeInsertF32x3;
case IR::Opcode::CompositeInsertF64x4:
return IR::Opcode::CompositeInsertF32x4;
case IR::Opcode::CompositeShuffleF64x2:
return IR::Opcode::CompositeShuffleF32x2;
case IR::Opcode::CompositeShuffleF64x3:
return IR::Opcode::CompositeShuffleF32x3;
case IR::Opcode::CompositeShuffleF64x4:
return IR::Opcode::CompositeShuffleF32x4;
case IR::Opcode::SelectF64:
return IR::Opcode::SelectF64;
case IR::Opcode::FPAbs64:
return IR::Opcode::FPAbs32;
case IR::Opcode::FPAdd64:
return IR::Opcode::FPAdd32;
case IR::Opcode::FPFma64:
return IR::Opcode::FPFma32;
case IR::Opcode::FPMax64:
return IR::Opcode::FPMax32;
case IR::Opcode::FPMin64:
return IR::Opcode::FPMin32;
case IR::Opcode::FPMul64:
return IR::Opcode::FPMul32;
case IR::Opcode::FPDiv64:
return IR::Opcode::FPDiv32;
case IR::Opcode::FPNeg64:
return IR::Opcode::FPNeg32;
case IR::Opcode::FPRecip64:
return IR::Opcode::FPRecip32;
case IR::Opcode::FPRecipSqrt64:
return IR::Opcode::FPRecipSqrt32;
case IR::Opcode::FPSaturate64:
return IR::Opcode::FPSaturate32;
case IR::Opcode::FPClamp64:
return IR::Opcode::FPClamp32;
case IR::Opcode::FPRoundEven64:
return IR::Opcode::FPRoundEven32;
case IR::Opcode::FPFloor64:
return IR::Opcode::FPFloor32;
case IR::Opcode::FPCeil64:
return IR::Opcode::FPCeil32;
case IR::Opcode::FPTrunc64:
return IR::Opcode::FPTrunc32;
case IR::Opcode::FPFract64:
return IR::Opcode::FPFract32;
case IR::Opcode::FPFrexpSig64:
return IR::Opcode::FPFrexpSig32;
case IR::Opcode::FPFrexpExp64:
return IR::Opcode::FPFrexpExp32;
case IR::Opcode::FPOrdEqual64:
return IR::Opcode::FPOrdEqual32;
case IR::Opcode::FPUnordEqual64:
return IR::Opcode::FPUnordEqual32;
case IR::Opcode::FPOrdNotEqual64:
return IR::Opcode::FPOrdNotEqual32;
case IR::Opcode::FPUnordNotEqual64:
return IR::Opcode::FPUnordNotEqual32;
case IR::Opcode::FPOrdLessThan64:
return IR::Opcode::FPOrdLessThan32;
case IR::Opcode::FPUnordLessThan64:
return IR::Opcode::FPUnordLessThan32;
case IR::Opcode::FPOrdGreaterThan64:
return IR::Opcode::FPOrdGreaterThan32;
case IR::Opcode::FPUnordGreaterThan64:
return IR::Opcode::FPUnordGreaterThan32;
case IR::Opcode::FPOrdLessThanEqual64:
return IR::Opcode::FPOrdLessThanEqual32;
case IR::Opcode::FPUnordLessThanEqual64:
return IR::Opcode::FPUnordLessThanEqual32;
case IR::Opcode::FPOrdGreaterThanEqual64:
return IR::Opcode::FPOrdGreaterThanEqual32;
case IR::Opcode::FPUnordGreaterThanEqual64:
return IR::Opcode::FPUnordGreaterThanEqual32;
case IR::Opcode::FPIsNan64:
return IR::Opcode::FPIsNan32;
case IR::Opcode::FPIsInf64:
return IR::Opcode::FPIsInf32;
case IR::Opcode::ConvertS32F64:
return IR::Opcode::ConvertS32F32;
case IR::Opcode::ConvertF32F64:
return IR::Opcode::Identity;
case IR::Opcode::ConvertF64F32:
return IR::Opcode::Identity;
case IR::Opcode::ConvertF64S32:
return IR::Opcode::ConvertF32S32;
case IR::Opcode::ConvertF64U32:
return IR::Opcode::ConvertF32U32;
default:
return op;
}
}
static void Lower(IR::Block& block, IR::Inst& inst) {
switch (inst.GetOpcode()) {
case IR::Opcode::PackDouble2x32: {
IR::IREmitter ir(block, IR::Block::InstructionList::s_iterator_to(inst));
inst.ReplaceUsesWith(PackedF64ToF32(ir, inst.Arg(0)));
break;
}
case IR::Opcode::UnpackDouble2x32: {
IR::IREmitter ir(block, IR::Block::InstructionList::s_iterator_to(inst));
inst.ReplaceUsesWith(F32ToPackedF64(ir, inst.Arg(0)));
break;
}
default:
inst.ReplaceOpcode(Replace(inst.GetOpcode()));
break;
}
}
void LowerFp64ToFp32(IR::Program& program) {
for (IR::Block* const block : program.blocks) {
for (IR::Inst& inst : block->Instructions()) {
Lower(*block, inst);
}
}
}
} // namespace Shader::Optimization

View file

@ -101,8 +101,6 @@ bool IsImageAtomicInstruction(const IR::Inst& inst) {
case IR::Opcode::ImageAtomicUMin32:
case IR::Opcode::ImageAtomicSMax32:
case IR::Opcode::ImageAtomicUMax32:
case IR::Opcode::ImageAtomicFMax32:
case IR::Opcode::ImageAtomicFMin32:
case IR::Opcode::ImageAtomicInc32:
case IR::Opcode::ImageAtomicDec32:
case IR::Opcode::ImageAtomicAnd32:

View file

@ -44,8 +44,7 @@ void Visit(Info& info, const IR::Inst& inst) {
case IR::Opcode::BitCastF16U16:
info.uses_fp16 = true;
break;
case IR::Opcode::PackDouble2x32:
case IR::Opcode::UnpackDouble2x32:
case IR::Opcode::BitCastU64F64:
info.uses_fp64 = true;
break;
case IR::Opcode::ImageWrite:
@ -71,10 +70,6 @@ void Visit(Info& info, const IR::Inst& inst) {
case IR::Opcode::ImageQueryLod:
info.has_image_query = true;
break;
case IR::Opcode::ImageAtomicFMax32:
case IR::Opcode::ImageAtomicFMin32:
info.uses_atomic_float_min_max = true;
break;
case IR::Opcode::LaneId:
info.uses_lane_id = true;
break;

View file

@ -34,18 +34,6 @@ inline F32 ApplyReadNumberConversion(IREmitter& ir, const F32& value,
case AmdGpu::NumberConversion::UnormToUbnorm:
// Convert 0...1 to -1...1
return ir.FPSub(ir.FPMul(value, ir.Imm32(2.f)), ir.Imm32(1.f));
case AmdGpu::NumberConversion::Sint8ToSnormNz: {
const IR::U32 additon = ir.IAdd(ir.IMul(ir.BitCast<U32>(value), ir.Imm32(2)), ir.Imm32(1));
const IR::F32 left = ir.ConvertSToF(32, 32, additon);
const IR::F32 max = ir.Imm32(float(std::numeric_limits<u8>::max()));
return ir.FPDiv(left, max);
}
case AmdGpu::NumberConversion::Sint16ToSnormNz: {
const IR::U32 additon = ir.IAdd(ir.IMul(ir.BitCast<U32>(value), ir.Imm32(2)), ir.Imm32(1));
const IR::F32 left = ir.ConvertSToF(32, 32, additon);
const IR::F32 max = ir.Imm32(float(std::numeric_limits<u16>::max()));
return ir.FPDiv(left, max);
}
default:
UNREACHABLE();
}
@ -78,20 +66,6 @@ inline F32 ApplyWriteNumberConversion(IREmitter& ir, const F32& value,
case AmdGpu::NumberConversion::UnormToUbnorm:
// Convert -1...1 to 0...1
return ir.FPDiv(ir.FPAdd(value, ir.Imm32(1.f)), ir.Imm32(2.f));
case AmdGpu::NumberConversion::Sint8ToSnormNz: {
const IR::F32 max = ir.Imm32(float(std::numeric_limits<u8>::max()));
const IR::F32 mul = ir.FPMul(ir.FPClamp(value, ir.Imm32(-1.f), ir.Imm32(1.f)), max);
const IR::F32 left = ir.FPSub(mul, ir.Imm32(1.f));
const IR::U32 raw = ir.ConvertFToS(32, ir.FPDiv(left, ir.Imm32(2.f)));
return ir.BitCast<F32>(raw);
}
case AmdGpu::NumberConversion::Sint16ToSnormNz: {
const IR::F32 max = ir.Imm32(float(std::numeric_limits<u16>::max()));
const IR::F32 mul = ir.FPMul(ir.FPClamp(value, ir.Imm32(-1.f), ir.Imm32(1.f)), max);
const IR::F32 left = ir.FPSub(mul, ir.Imm32(1.f));
const IR::U32 raw = ir.ConvertFToS(32, ir.FPDiv(left, ir.Imm32(2.f)));
return ir.BitCast<F32>(raw);
}
default:
UNREACHABLE();
}

View file

@ -15,7 +15,6 @@ struct Profile {
bool support_int8{};
bool support_int16{};
bool support_int64{};
bool support_float64{};
bool support_vertex_instance_id{};
bool support_float_controls{};
bool support_separate_denorm_behavior{};
@ -29,7 +28,6 @@ struct Profile {
bool supports_native_cube_calc{};
bool supports_trinary_minmax{};
bool supports_robust_buffer_access{};
bool supports_image_fp32_atomic_min_max{};
bool has_broken_spirv_clamp{};
bool lower_left_origin_mode{};
bool needs_manual_interpolation{};

View file

@ -60,9 +60,6 @@ IR::Program TranslateProgram(std::span<const u32> code, Pools& pools, Info& info
program.post_order_blocks = Shader::IR::PostOrder(program.syntax_list.front());
// Run optimization passes
if (!profile.support_float64) {
Shader::Optimization::LowerFp64ToFp32(program);
}
Shader::Optimization::SsaRewritePass(program.post_order_blocks);
Shader::Optimization::ConstantPropagationPass(program.post_order_blocks);
Shader::Optimization::IdentityRemovalPass(program.blocks);

View file

@ -924,11 +924,15 @@ struct Liverpool {
}
[[nodiscard]] NumberFormat GetNumberFmt() const {
return RemapNumberFormat(GetFixedNumberFormat(), info.format);
// There is a small difference between T# and CB number types, account for it.
return RemapNumberFormat(info.number_type == NumberFormat::SnormNz
? NumberFormat::Srgb
: info.number_type.Value(),
info.format);
}
[[nodiscard]] NumberConversion GetNumberConversion() const {
return MapNumberConversion(GetFixedNumberFormat(), info.format);
return MapNumberConversion(info.number_type);
}
[[nodiscard]] CompMapping Swizzle() const {
@ -969,13 +973,6 @@ struct Liverpool {
const auto mrt_swizzle = mrt_swizzles[swap_idx][components_idx];
return RemapSwizzle(info.format, mrt_swizzle);
}
private:
[[nodiscard]] NumberFormat GetFixedNumberFormat() const {
// There is a small difference between T# and CB number types, account for it.
return info.number_type == NumberFormat::SnormNz ? NumberFormat::Srgb
: info.number_type.Value();
}
};
enum ContextRegs : u32 {

View file

@ -68,7 +68,7 @@ struct Buffer {
}
NumberConversion GetNumberConversion() const noexcept {
return MapNumberConversion(NumberFormat(num_format), DataFormat(data_format));
return MapNumberConversion(NumberFormat(num_format));
}
u32 GetStride() const noexcept {
@ -292,7 +292,7 @@ struct Image {
}
NumberConversion GetNumberConversion() const noexcept {
return MapNumberConversion(NumberFormat(num_format), DataFormat(data_format));
return MapNumberConversion(NumberFormat(num_format));
}
TilingMode GetTilingMode() const {

View file

@ -197,8 +197,6 @@ enum class NumberConversion : u32 {
UintToUscaled = 1,
SintToSscaled = 2,
UnormToUbnorm = 3,
Sint8ToSnormNz = 5,
Sint16ToSnormNz = 6,
};
struct CompMapping {
@ -289,7 +287,6 @@ inline NumberFormat RemapNumberFormat(const NumberFormat format, const DataForma
case NumberFormat::Uscaled:
return NumberFormat::Uint;
case NumberFormat::Sscaled:
case NumberFormat::SnormNz:
return NumberFormat::Sint;
case NumberFormat::Ubnorm:
return NumberFormat::Unorm;
@ -339,28 +336,14 @@ inline CompMapping RemapSwizzle(const DataFormat format, const CompMapping swizz
}
}
inline NumberConversion MapNumberConversion(const NumberFormat num_fmt, const DataFormat data_fmt) {
switch (num_fmt) {
inline NumberConversion MapNumberConversion(const NumberFormat format) {
switch (format) {
case NumberFormat::Uscaled:
return NumberConversion::UintToUscaled;
case NumberFormat::Sscaled:
return NumberConversion::SintToSscaled;
case NumberFormat::Ubnorm:
return NumberConversion::UnormToUbnorm;
case NumberFormat::SnormNz: {
switch (data_fmt) {
case DataFormat::Format8:
case DataFormat::Format8_8:
case DataFormat::Format8_8_8_8:
return NumberConversion::Sint8ToSnormNz;
case DataFormat::Format16:
case DataFormat::Format16_16:
case DataFormat::Format16_16_16_16:
return NumberConversion::Sint16ToSnormNz;
default:
UNREACHABLE_MSG("data_fmt = {}", u32(data_fmt));
}
}
default:
return NumberConversion::None;
}

View file

@ -177,8 +177,8 @@ void BufferCache::BindVertexBuffers(const Vulkan::GraphicsPipeline& pipeline) {
if (instance.IsVertexInputDynamicState()) {
cmdbuf.bindVertexBuffers(0, num_buffers, host_buffers.data(), host_offsets.data());
} else {
cmdbuf.bindVertexBuffers2(0, num_buffers, host_buffers.data(), host_offsets.data(),
host_sizes.data(), host_strides.data());
cmdbuf.bindVertexBuffers2EXT(0, num_buffers, host_buffers.data(), host_offsets.data(),
host_sizes.data(), host_strides.data());
}
}

View file

@ -14,7 +14,7 @@
namespace Vulkan::HostPasses {
void PostProcessingPass::Create(vk::Device device, const vk::Format surface_format) {
void PostProcessingPass::Create(vk::Device device) {
static const std::array pp_shaders{
HostShaders::FS_TRI_VERT,
HostShaders::POST_PROCESS_FRAG,
@ -76,9 +76,9 @@ void PostProcessingPass::Create(vk::Device device, const vk::Format surface_form
Check<"create pp pipeline layout">(device.createPipelineLayoutUnique(layout_info));
const std::array pp_color_formats{
surface_format,
vk::Format::eB8G8R8A8Unorm, // swapchain.GetSurfaceFormat().format,
};
const vk::PipelineRenderingCreateInfo pipeline_rendering_ci{
const vk::PipelineRenderingCreateInfoKHR pipeline_rendering_ci{
.colorAttachmentCount = pp_color_formats.size(),
.pColorAttachmentFormats = pp_color_formats.data(),
};

View file

@ -19,7 +19,7 @@ public:
u32 hdr = 0;
};
void Create(vk::Device device, vk::Format surface_format);
void Create(vk::Device device);
void Render(vk::CommandBuffer cmdbuf, vk::ImageView input, vk::Extent2D input_size,
Frame& output, Settings settings);

View file

@ -122,21 +122,21 @@ GraphicsPipeline::GraphicsPipeline(
};
boost::container::static_vector<vk::DynamicState, 20> dynamic_states = {
vk::DynamicState::eViewportWithCount, vk::DynamicState::eScissorWithCount,
vk::DynamicState::eBlendConstants, vk::DynamicState::eDepthTestEnable,
vk::DynamicState::eDepthWriteEnable, vk::DynamicState::eDepthCompareOp,
vk::DynamicState::eDepthBiasEnable, vk::DynamicState::eDepthBias,
vk::DynamicState::eStencilTestEnable, vk::DynamicState::eStencilReference,
vk::DynamicState::eStencilCompareMask, vk::DynamicState::eStencilWriteMask,
vk::DynamicState::eStencilOp, vk::DynamicState::eCullMode,
vk::DynamicState::eFrontFace,
vk::DynamicState::eViewportWithCountEXT, vk::DynamicState::eScissorWithCountEXT,
vk::DynamicState::eBlendConstants, vk::DynamicState::eDepthTestEnableEXT,
vk::DynamicState::eDepthWriteEnableEXT, vk::DynamicState::eDepthCompareOpEXT,
vk::DynamicState::eDepthBiasEnableEXT, vk::DynamicState::eDepthBias,
vk::DynamicState::eStencilTestEnableEXT, vk::DynamicState::eStencilReference,
vk::DynamicState::eStencilCompareMask, vk::DynamicState::eStencilWriteMask,
vk::DynamicState::eStencilOpEXT, vk::DynamicState::eCullModeEXT,
vk::DynamicState::eFrontFaceEXT,
};
if (instance.IsPrimitiveRestartDisableSupported()) {
dynamic_states.push_back(vk::DynamicState::ePrimitiveRestartEnable);
dynamic_states.push_back(vk::DynamicState::ePrimitiveRestartEnableEXT);
}
if (instance.IsDepthBoundsSupported()) {
dynamic_states.push_back(vk::DynamicState::eDepthBoundsTestEnable);
dynamic_states.push_back(vk::DynamicState::eDepthBoundsTestEnableEXT);
dynamic_states.push_back(vk::DynamicState::eDepthBounds);
}
if (instance.IsDynamicColorWriteMaskSupported()) {
@ -145,7 +145,7 @@ GraphicsPipeline::GraphicsPipeline(
if (instance.IsVertexInputDynamicState()) {
dynamic_states.push_back(vk::DynamicState::eVertexInputEXT);
} else if (!vertex_bindings.empty()) {
dynamic_states.push_back(vk::DynamicState::eVertexInputBindingStride);
dynamic_states.push_back(vk::DynamicState::eVertexInputBindingStrideEXT);
}
const vk::PipelineDynamicStateCreateInfo dynamic_info = {
@ -212,7 +212,7 @@ GraphicsPipeline::GraphicsPipeline(
});
}
const vk::PipelineRenderingCreateInfo pipeline_rendering_ci = {
const vk::PipelineRenderingCreateInfoKHR pipeline_rendering_ci = {
.colorAttachmentCount = key.num_color_attachments,
.pColorAttachmentFormats = key.color_formats.data(),
.depthAttachmentFormat = key.depth_format,

View file

@ -203,15 +203,12 @@ std::string Instance::GetDriverVersionName() {
}
bool Instance::CreateDevice() {
const vk::StructureChain feature_chain =
physical_device
.getFeatures2<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVulkan11Features,
vk::PhysicalDeviceVulkan12Features, vk::PhysicalDeviceVulkan13Features,
vk::PhysicalDeviceRobustness2FeaturesEXT,
vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT,
vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT,
vk::PhysicalDevicePortabilitySubsetFeaturesKHR,
vk::PhysicalDeviceShaderAtomicFloat2FeaturesEXT>();
const vk::StructureChain feature_chain = physical_device.getFeatures2<
vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVulkan11Features,
vk::PhysicalDeviceVulkan12Features, vk::PhysicalDeviceRobustness2FeaturesEXT,
vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT,
vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT,
vk::PhysicalDevicePortabilitySubsetFeaturesKHR>();
features = feature_chain.get().features;
const vk::StructureChain properties_chain = physical_device.getProperties2<
@ -243,6 +240,18 @@ bool Instance::CreateDevice() {
return false;
};
// These extensions are promoted by Vulkan 1.3, but for greater compatibility we use Vulkan 1.2
// with extensions.
ASSERT(add_extension(VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME));
ASSERT(add_extension(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME));
ASSERT(add_extension(VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME));
ASSERT(add_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME));
ASSERT(add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME));
ASSERT(add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME));
ASSERT(add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME) ||
driver_id == vk::DriverId::eIntelProprietaryWindows);
ASSERT(add_extension(VK_KHR_MAINTENANCE_4_EXTENSION_NAME));
// Required
ASSERT(add_extension(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
ASSERT(add_extension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME));
@ -273,13 +282,6 @@ bool Instance::CreateDevice() {
image_load_store_lod = add_extension(VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME);
amd_gcn_shader = add_extension(VK_AMD_GCN_SHADER_EXTENSION_NAME);
amd_shader_trinary_minmax = add_extension(VK_AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME);
shader_atomic_float2 = add_extension(VK_EXT_SHADER_ATOMIC_FLOAT_2_EXTENSION_NAME);
if (shader_atomic_float2) {
shader_atomic_float2_features =
feature_chain.get<vk::PhysicalDeviceShaderAtomicFloat2FeaturesEXT>();
LOG_INFO(Render_Vulkan, "- shaderImageFloat32AtomicMinMax: {}",
shader_atomic_float2_features.shaderImageFloat32AtomicMinMax);
}
const bool calibrated_timestamps =
TRACY_GPU_ENABLED ? add_extension(VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME) : false;
@ -322,7 +324,6 @@ bool Instance::CreateDevice() {
feature_chain.get<vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT>();
const auto vk11_features = feature_chain.get<vk::PhysicalDeviceVulkan11Features>();
const auto vk12_features = feature_chain.get<vk::PhysicalDeviceVulkan12Features>();
const auto vk13_features = feature_chain.get<vk::PhysicalDeviceVulkan13Features>();
vk::StructureChain device_chain = {
vk::DeviceCreateInfo{
.queueCreateInfoCount = 1u,
@ -340,7 +341,6 @@ bool Instance::CreateDevice() {
.logicOp = features.logicOp,
.depthBiasClamp = features.depthBiasClamp,
.fillModeNonSolid = features.fillModeNonSolid,
.depthBounds = features.depthBounds,
.multiViewport = features.multiViewport,
.samplerAnisotropy = features.samplerAnisotropy,
.vertexPipelineStoresAndAtomics = features.vertexPipelineStoresAndAtomics,
@ -372,14 +372,26 @@ bool Instance::CreateDevice() {
.hostQueryReset = vk12_features.hostQueryReset,
.timelineSemaphore = vk12_features.timelineSemaphore,
},
vk::PhysicalDeviceVulkan13Features{
.robustImageAccess = vk13_features.robustImageAccess,
.shaderDemoteToHelperInvocation = vk13_features.shaderDemoteToHelperInvocation,
.synchronization2 = vk13_features.synchronization2,
.dynamicRendering = vk13_features.dynamicRendering,
.maintenance4 = vk13_features.maintenance4,
// Vulkan 1.3 promoted extensions
vk::PhysicalDeviceDynamicRenderingFeaturesKHR{
.dynamicRendering = true,
},
// Extensions
vk::PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT{
.shaderDemoteToHelperInvocation = true,
},
vk::PhysicalDeviceSynchronization2Features{
.synchronization2 = true,
},
vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT{
.extendedDynamicState = true,
},
vk::PhysicalDeviceExtendedDynamicState2FeaturesEXT{
.extendedDynamicState2 = true,
},
vk::PhysicalDeviceMaintenance4FeaturesKHR{
.maintenance4 = true,
},
// Other extensions
vk::PhysicalDeviceCustomBorderColorFeaturesEXT{
.customBorderColors = true,
.customBorderColorWithoutFormat = true,
@ -409,10 +421,6 @@ bool Instance::CreateDevice() {
vk::PhysicalDeviceLegacyVertexAttributesFeaturesEXT{
.legacyVertexAttributes = true,
},
vk::PhysicalDeviceShaderAtomicFloat2FeaturesEXT{
.shaderImageFloat32AtomicMinMax =
shader_atomic_float2_features.shaderImageFloat32AtomicMinMax,
},
#ifdef __APPLE__
portability_features,
#endif
@ -442,9 +450,6 @@ bool Instance::CreateDevice() {
if (!legacy_vertex_attributes) {
device_chain.unlink<vk::PhysicalDeviceLegacyVertexAttributesFeaturesEXT>();
}
if (!shader_atomic_float2) {
device_chain.unlink<vk::PhysicalDeviceShaderAtomicFloat2FeaturesEXT>();
}
auto [device_result, dev] = physical_device.createDeviceUnique(device_chain.get());
if (device_result != vk::Result::eSuccess) {
@ -537,14 +542,12 @@ void Instance::CollectDeviceParameters() {
LOG_INFO(Render_Vulkan, "GPU_Vulkan_Extensions: {}", extensions);
}
void Instance::CollectToolingInfo() const {
if (driver_id == vk::DriverId::eAmdProprietary ||
driver_id == vk::DriverId::eIntelProprietaryWindows) {
// AMD: Causes issues with Reshade.
// Intel: Causes crash on start.
void Instance::CollectToolingInfo() {
if (GetDriverID() == vk::DriverId::eAmdProprietary) {
// Currently causes issues with Reshade on AMD proprietary, disabled until fix released.
return;
}
const auto [tools_result, tools] = physical_device.getToolProperties();
const auto [tools_result, tools] = physical_device.getToolPropertiesEXT();
if (tools_result != vk::Result::eSuccess) {
LOG_ERROR(Render_Vulkan, "Could not get Vulkan tool properties: {}",
vk::to_string(tools_result));

View file

@ -89,11 +89,6 @@ public:
return features.depthBounds;
}
/// Returns true if 64-bit floats are supported in shaders
bool IsShaderFloat64Supported() const {
return features.shaderFloat64;
}
/// Returns true when VK_EXT_custom_border_color is supported
bool IsCustomBorderColorSupported() const {
return custom_border_color;
@ -165,12 +160,6 @@ public:
return amd_shader_trinary_minmax;
}
/// Returns true when the shaderImageFloat32AtomicMinMax feature of
/// VK_EXT_shader_atomic_float2 is supported.
bool IsShaderAtomicFloatImage32MinMaxSupported() const {
return shader_atomic_float2 && shader_atomic_float2_features.shaderImageFloat32AtomicMinMax;
}
/// Returns true when geometry shaders are supported by the device
bool IsGeometryStageSupported() const {
return features.geometryShader;
@ -322,7 +311,7 @@ private:
/// Collects telemetry information from the device.
void CollectDeviceParameters();
void CollectToolingInfo() const;
void CollectToolingInfo();
/// Gets the supported feature flags for a format.
[[nodiscard]] vk::FormatFeatureFlags2 GetFormatFeatureFlags(vk::Format format) const;
@ -342,7 +331,6 @@ private:
vk::PhysicalDevicePortabilitySubsetFeaturesKHR portability_features;
vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT dynamic_state_3_features;
vk::PhysicalDeviceRobustness2FeaturesEXT robustness2_features;
vk::PhysicalDeviceShaderAtomicFloat2FeaturesEXT shader_atomic_float2_features;
vk::DriverIdKHR driver_id;
vk::UniqueDebugUtilsMessengerEXT debug_callback{};
std::string vendor_name;
@ -367,7 +355,6 @@ private:
bool image_load_store_lod{};
bool amd_gcn_shader{};
bool amd_shader_trinary_minmax{};
bool shader_atomic_float2{};
bool portability_subset{};
};

View file

@ -26,8 +26,6 @@ using Shader::LogicalStage;
using Shader::Stage;
using Shader::VsOutput;
constexpr static auto SpirvVersion1_6 = 0x00010600U;
constexpr static std::array DescriptorHeapSizes = {
vk::DescriptorPoolSize{vk::DescriptorType::eUniformBuffer, 8192},
vk::DescriptorPoolSize{vk::DescriptorType::eStorageBuffer, 1024},
@ -194,9 +192,8 @@ PipelineCache::PipelineCache(const Instance& instance_, Scheduler& scheduler_,
desc_heap{instance, scheduler.GetMasterSemaphore(), DescriptorHeapSizes} {
const auto& vk12_props = instance.GetVk12Properties();
profile = Shader::Profile{
.supported_spirv = SpirvVersion1_6,
.supported_spirv = instance.ApiVersion() >= VK_API_VERSION_1_3 ? 0x00010600U : 0x00010500U,
.subgroup_size = instance.SubgroupSize(),
.support_float64 = instance.IsShaderFloat64Supported(),
.support_fp32_denorm_preserve = bool(vk12_props.shaderDenormPreserveFloat32),
.support_fp32_denorm_flush = bool(vk12_props.shaderDenormFlushToZeroFloat32),
.support_fp32_round_to_zero = bool(vk12_props.shaderRoundingModeRTZFloat32),
@ -206,7 +203,6 @@ PipelineCache::PipelineCache(const Instance& instance_, Scheduler& scheduler_,
.supports_native_cube_calc = instance_.IsAmdGcnShaderSupported(),
.supports_trinary_minmax = instance_.IsAmdShaderTrinaryMinMaxSupported(),
.supports_robust_buffer_access = instance_.IsRobustBufferAccess2Supported(),
.supports_image_fp32_atomic_min_max = instance_.IsShaderAtomicFloatImage32MinMaxSupported(),
.needs_manual_interpolation = instance.IsFragmentShaderBarycentricSupported() &&
instance.GetDriverID() == vk::DriverId::eNvidiaProprietary,
.needs_lds_barriers = instance.GetDriverID() == vk::DriverId::eNvidiaProprietary ||

View file

@ -18,7 +18,7 @@ class WindowSDL;
namespace Vulkan {
constexpr u32 TargetVulkanApiVersion = VK_API_VERSION_1_3;
constexpr u32 TargetVulkanApiVersion = VK_API_VERSION_1_2;
vk::SurfaceKHR CreateSurface(vk::Instance instance, const Frontend::WindowSDL& emu_window);

View file

@ -130,7 +130,7 @@ Presenter::Presenter(Frontend::WindowSDL& window_, AmdGpu::Liverpool* liverpool_
}
fsr_pass.Create(device, instance.GetAllocator(), num_images);
pp_pass.Create(device, swapchain.GetSurfaceFormat().format);
pp_pass.Create(device);
ImGui::Layer::AddLayer(Common::Singleton<Core::Devtools::Layer>::Instance());
}
@ -270,25 +270,7 @@ Frame* Presenter::PrepareLastFrame() {
return frame;
}
static vk::Format GetFrameViewFormat(const Libraries::VideoOut::PixelFormat format) {
switch (format) {
case Libraries::VideoOut::PixelFormat::A8B8G8R8Srgb:
return vk::Format::eR8G8B8A8Srgb;
case Libraries::VideoOut::PixelFormat::A8R8G8B8Srgb:
return vk::Format::eB8G8R8A8Srgb;
case Libraries::VideoOut::PixelFormat::A2R10G10B10:
case Libraries::VideoOut::PixelFormat::A2R10G10B10Srgb:
case Libraries::VideoOut::PixelFormat::A2R10G10B10Bt2020Pq:
return vk::Format::eA2R10G10B10UnormPack32;
default:
break;
}
UNREACHABLE_MSG("Unknown format={}", static_cast<u32>(format));
return {};
}
Frame* Presenter::PrepareFrameInternal(VideoCore::ImageId image_id,
const Libraries::VideoOut::PixelFormat format, bool is_eop) {
Frame* Presenter::PrepareFrameInternal(VideoCore::ImageId image_id, bool is_eop) {
// Request a free presentation frame.
Frame* frame = GetRenderFrame();
@ -342,7 +324,7 @@ Frame* Presenter::PrepareFrameInternal(VideoCore::ImageId image_id,
cmdbuf);
VideoCore::ImageViewInfo info{};
info.format = GetFrameViewFormat(format);
info.format = image.info.pixel_format;
// Exclude alpha from output frame to avoid blending with UI.
info.mapping = vk::ComponentMapping{
.r = vk::ComponentSwizzle::eIdentity,

View file

@ -70,12 +70,11 @@ public:
auto desc = VideoCore::TextureCache::VideoOutDesc{attribute, cpu_address};
const auto image_id = texture_cache.FindImage(desc);
texture_cache.UpdateImage(image_id, is_eop ? nullptr : &flip_scheduler);
return PrepareFrameInternal(image_id, attribute.attrib.pixel_format, is_eop);
return PrepareFrameInternal(image_id, is_eop);
}
Frame* PrepareBlankFrame(bool is_eop) {
return PrepareFrameInternal(VideoCore::NULL_IMAGE_ID,
Libraries::VideoOut::PixelFormat::Unknown, is_eop);
return PrepareFrameInternal(VideoCore::NULL_IMAGE_ID, is_eop);
}
VideoCore::Image& RegisterVideoOutSurface(
@ -120,8 +119,7 @@ public:
}
private:
Frame* PrepareFrameInternal(VideoCore::ImageId image_id,
Libraries::VideoOut::PixelFormat format, bool is_eop = true);
Frame* PrepareFrameInternal(VideoCore::ImageId image_id, bool is_eop = true);
Frame* GetRenderFrame();
void SetExpectedGameSize(s32 width, s32 height);

View file

@ -696,19 +696,14 @@ void Rasterizer::BindTextures(const Shader::Info& stage, Shader::Backend::Bindin
void Rasterizer::BeginRendering(const GraphicsPipeline& pipeline, RenderState& state) {
int cb_index = 0;
for (auto attach_idx = 0u; attach_idx < state.num_color_attachments; ++attach_idx) {
if (state.color_attachments[attach_idx].imageView == VK_NULL_HANDLE) {
continue;
}
auto& [image_id, desc] = cb_descs[cb_index++];
for (auto& [image_id, desc] : cb_descs) {
if (auto& old_img = texture_cache.GetImage(image_id); old_img.binding.needs_rebind) {
auto& view = texture_cache.FindRenderTarget(desc);
ASSERT(view.image_id != image_id);
image_id = bound_images.emplace_back(view.image_id);
auto& image = texture_cache.GetImage(view.image_id);
state.color_attachments[attach_idx].imageView = *view.image_view;
state.color_attachments[attach_idx].imageLayout = image.last_state.layout;
state.color_attachments[cb_index].imageView = *view.image_view;
state.color_attachments[cb_index].imageLayout = image.last_state.layout;
const auto mip = view.info.range.base.level;
state.width = std::min<u32>(state.width, std::max(image.info.size.width >> mip, 1u));
@ -727,7 +722,8 @@ void Rasterizer::BeginRendering(const GraphicsPipeline& pipeline, RenderState& s
desc.view_info.range);
}
image.usage.render_target = 1u;
state.color_attachments[attach_idx].imageLayout = image.last_state.layout;
state.color_attachments[cb_index].imageLayout = image.last_state.layout;
++cb_index;
}
if (db_desc) {

View file

@ -170,29 +170,29 @@ void Scheduler::SubmitExecution(SubmitInfo& info) {
void DynamicState::Commit(const Instance& instance, const vk::CommandBuffer& cmdbuf) {
if (dirty_state.viewports) {
dirty_state.viewports = false;
cmdbuf.setViewportWithCount(viewports);
cmdbuf.setViewportWithCountEXT(viewports);
}
if (dirty_state.scissors) {
dirty_state.scissors = false;
cmdbuf.setScissorWithCount(scissors);
cmdbuf.setScissorWithCountEXT(scissors);
}
if (dirty_state.depth_test_enabled) {
dirty_state.depth_test_enabled = false;
cmdbuf.setDepthTestEnable(depth_test_enabled);
cmdbuf.setDepthTestEnableEXT(depth_test_enabled);
}
if (dirty_state.depth_write_enabled) {
dirty_state.depth_write_enabled = false;
// Note that this must be set in a command buffer even if depth test is disabled.
cmdbuf.setDepthWriteEnable(depth_write_enabled);
cmdbuf.setDepthWriteEnableEXT(depth_write_enabled);
}
if (depth_test_enabled && dirty_state.depth_compare_op) {
dirty_state.depth_compare_op = false;
cmdbuf.setDepthCompareOp(depth_compare_op);
cmdbuf.setDepthCompareOpEXT(depth_compare_op);
}
if (dirty_state.depth_bounds_test_enabled) {
dirty_state.depth_bounds_test_enabled = false;
if (instance.IsDepthBoundsSupported()) {
cmdbuf.setDepthBoundsTestEnable(depth_bounds_test_enabled);
cmdbuf.setDepthBoundsTestEnableEXT(depth_bounds_test_enabled);
}
}
if (depth_bounds_test_enabled && dirty_state.depth_bounds) {
@ -203,7 +203,7 @@ void DynamicState::Commit(const Instance& instance, const vk::CommandBuffer& cmd
}
if (dirty_state.depth_bias_enabled) {
dirty_state.depth_bias_enabled = false;
cmdbuf.setDepthBiasEnable(depth_bias_enabled);
cmdbuf.setDepthBiasEnableEXT(depth_bias_enabled);
}
if (depth_bias_enabled && dirty_state.depth_bias) {
dirty_state.depth_bias = false;
@ -211,28 +211,28 @@ void DynamicState::Commit(const Instance& instance, const vk::CommandBuffer& cmd
}
if (dirty_state.stencil_test_enabled) {
dirty_state.stencil_test_enabled = false;
cmdbuf.setStencilTestEnable(stencil_test_enabled);
cmdbuf.setStencilTestEnableEXT(stencil_test_enabled);
}
if (stencil_test_enabled) {
if (dirty_state.stencil_front_ops && dirty_state.stencil_back_ops &&
stencil_front_ops == stencil_back_ops) {
dirty_state.stencil_front_ops = false;
dirty_state.stencil_back_ops = false;
cmdbuf.setStencilOp(vk::StencilFaceFlagBits::eFrontAndBack, stencil_front_ops.fail_op,
stencil_front_ops.pass_op, stencil_front_ops.depth_fail_op,
stencil_front_ops.compare_op);
cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eFrontAndBack,
stencil_front_ops.fail_op, stencil_front_ops.pass_op,
stencil_front_ops.depth_fail_op, stencil_front_ops.compare_op);
} else {
if (dirty_state.stencil_front_ops) {
dirty_state.stencil_front_ops = false;
cmdbuf.setStencilOp(vk::StencilFaceFlagBits::eFront, stencil_front_ops.fail_op,
stencil_front_ops.pass_op, stencil_front_ops.depth_fail_op,
stencil_front_ops.compare_op);
cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eFront, stencil_front_ops.fail_op,
stencil_front_ops.pass_op, stencil_front_ops.depth_fail_op,
stencil_front_ops.compare_op);
}
if (dirty_state.stencil_back_ops) {
dirty_state.stencil_back_ops = false;
cmdbuf.setStencilOp(vk::StencilFaceFlagBits::eBack, stencil_back_ops.fail_op,
stencil_back_ops.pass_op, stencil_back_ops.depth_fail_op,
stencil_back_ops.compare_op);
cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eBack, stencil_back_ops.fail_op,
stencil_back_ops.pass_op, stencil_back_ops.depth_fail_op,
stencil_back_ops.compare_op);
}
}
if (dirty_state.stencil_front_reference && dirty_state.stencil_back_reference &&
@ -291,16 +291,16 @@ void DynamicState::Commit(const Instance& instance, const vk::CommandBuffer& cmd
if (dirty_state.primitive_restart_enable) {
dirty_state.primitive_restart_enable = false;
if (instance.IsPrimitiveRestartDisableSupported()) {
cmdbuf.setPrimitiveRestartEnable(primitive_restart_enable);
cmdbuf.setPrimitiveRestartEnableEXT(primitive_restart_enable);
}
}
if (dirty_state.cull_mode) {
dirty_state.cull_mode = false;
cmdbuf.setCullMode(cull_mode);
cmdbuf.setCullModeEXT(cull_mode);
}
if (dirty_state.front_face) {
dirty_state.front_face = false;
cmdbuf.setFrontFace(front_face);
cmdbuf.setFrontFaceEXT(front_face);
}
if (dirty_state.blend_constants) {
dirty_state.blend_constants = false;

View file

@ -16,15 +16,14 @@ using VideoOutFormat = Libraries::VideoOut::PixelFormat;
static vk::Format ConvertPixelFormat(const VideoOutFormat format) {
switch (format) {
case VideoOutFormat::A8B8G8R8Srgb:
// Remaining formats are mapped to RGBA for internal consistency and changed to BGRA in the
// frame image view.
case VideoOutFormat::A8R8G8B8Srgb:
return vk::Format::eB8G8R8A8Srgb;
case VideoOutFormat::A8B8G8R8Srgb:
return vk::Format::eR8G8B8A8Srgb;
case VideoOutFormat::A2R10G10B10:
case VideoOutFormat::A2R10G10B10Srgb:
case VideoOutFormat::A2R10G10B10Bt2020Pq:
return vk::Format::eA2B10G10R10UnormPack32;
return vk::Format::eA2R10G10B10UnormPack32;
default:
break;
}