diff --git a/.github/linux-appimage-qt.sh b/.github/linux-appimage-qt.sh
index 870172457..203d214e3 100755
--- a/.github/linux-appimage-qt.sh
+++ b/.github/linux-appimage-qt.sh
@@ -19,8 +19,12 @@ chmod a+x linuxdeploy-x86_64.AppImage
chmod a+x linuxdeploy-plugin-qt-x86_64.AppImage
chmod a+x linuxdeploy-plugin-checkrt-x86_64.sh
+
# Build AppImage
./linuxdeploy-x86_64.AppImage --appdir AppDir
./linuxdeploy-plugin-checkrt-x86_64.sh --appdir AppDir
+
+cp -a "$GITHUB_WORKSPACE/build/translations" AppDir/usr/bin
+
./linuxdeploy-x86_64.AppImage --appdir AppDir -d "$GITHUB_WORKSPACE"/.github/shadps4.desktop -e "$GITHUB_WORKSPACE"/build/shadps4 -i "$GITHUB_WORKSPACE"/.github/shadps4.png --plugin qt --output appimage
mv Shadps4-x86_64.AppImage Shadps4-qt.AppImage
diff --git a/.github/workflows/linux-qt.yml b/.github/workflows/linux-qt.yml
index 5611ae50f..06e048c0e 100644
--- a/.github/workflows/linux-qt.yml
+++ b/.github/workflows/linux-qt.yml
@@ -23,7 +23,7 @@ jobs:
- name: Install misc packages
run: >
- sudo apt-get update && sudo apt install libx11-dev libxext-dev libwayland-dev libfuse2 clang build-essential qt6-base-dev
+ sudo apt-get update && sudo apt install libx11-dev libxext-dev libwayland-dev libfuse2 clang build-essential qt6-base-dev qt6-tools-dev
- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DENABLE_QT_GUI=ON
@@ -34,8 +34,14 @@ jobs:
- name: Run AppImage packaging script
run: ./.github/linux-appimage-qt.sh
+ - name: Get date and git hash
+ id: vars
+ run: |
+ echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
+ echo "shorthash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
+
- name: Upload executable
uses: actions/upload-artifact@v4
with:
- name: shadps4-linux-qt
+ name: shadps4-linux-qt-${{ steps.vars.outputs.date }}-${{ steps.vars.outputs.shorthash }}
path: Shadps4-qt.AppImage
\ No newline at end of file
diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index ef77a16c8..ee1340984 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -31,10 +31,16 @@ jobs:
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel
+ - name: Get date and git hash
+ id: vars
+ run: |
+ echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
+ echo "shorthash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
+
- name: Upload executable
uses: actions/upload-artifact@v4
with:
- name: shadps4-ubuntu64
+ name: shadps4-ubuntu64-${{ steps.vars.outputs.date }}-${{ steps.vars.outputs.shorthash }}
path: |
${{github.workspace}}/build/shadps4
@@ -44,5 +50,5 @@ jobs:
- name: Upload executable
uses: actions/upload-artifact@v4
with:
- name: shadps4-sdl-appimage
+ name: shadps4-sdl-appimage-${{ steps.vars.outputs.date }}-${{ steps.vars.outputs.shorthash }}
path: Shadps4-sdl.AppImage
diff --git a/.github/workflows/macos-qt.yml b/.github/workflows/macos-qt.yml
index 4b3672dff..f04d3091c 100644
--- a/.github/workflows/macos-qt.yml
+++ b/.github/workflows/macos-qt.yml
@@ -38,7 +38,7 @@ jobs:
host: mac
target: desktop
arch: clang_64
- archives: qtbase
+ archives: qtbase qttools
- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_OSX_ARCHITECTURES=x86_64 -DENABLE_QT_GUI=ON
@@ -53,8 +53,15 @@ jobs:
macdeployqt upload/shadps4.app
tar cf shadps4-macos-qt.tar.gz -C upload .
+ - name: Get date and git hash
+ id: vars
+ run: |
+ echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
+ echo "shorthash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
+
+
- name: Upload executable
uses: actions/upload-artifact@v4
with:
- name: shadps4-macos-qt
+ name: shadps4-macos-qt-${{ steps.vars.outputs.date }}-${{ steps.vars.outputs.shorthash }}
path: shadps4-macos-qt.tar.gz
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
index 1a2a6eff6..0eb0ad17a 100644
--- a/.github/workflows/macos.yml
+++ b/.github/workflows/macos.yml
@@ -45,8 +45,14 @@ jobs:
install_name_tool -add_rpath "@loader_path" upload/shadps4
tar cf shadps4-macos-sdl.tar.gz -C upload .
+ - name: Get date and git hash
+ id: vars
+ run: |
+ echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
+ echo "shorthash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
+
- name: Upload executable
uses: actions/upload-artifact@v4
with:
- name: shadps4-macos-sdl
+ name: shadps4-macos-sdl-${{ steps.vars.outputs.date }}-${{ steps.vars.outputs.shorthash }}
path: shadps4-macos-sdl.tar.gz
diff --git a/.github/workflows/windows-qt.yml b/.github/workflows/windows-qt.yml
index 06a16eb5b..83b1a908b 100644
--- a/.github/workflows/windows-qt.yml
+++ b/.github/workflows/windows-qt.yml
@@ -28,7 +28,7 @@ jobs:
host: windows
target: desktop
arch: win64_msvc2019_64
- archives: qtbase
+ archives: qtbase qttools
- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -T ClangCL -DENABLE_QT_GUI=ON
@@ -41,9 +41,16 @@ jobs:
mkdir upload
move build/Release/shadPS4.exe upload
windeployqt --dir upload upload/shadPS4.exe
+
+ - name: Get date and git hash
+ id: vars
+ shell: pwsh
+ run: |
+ echo "date=$(Get-Date -Format 'yyyy-MM-dd')" >> $env:GITHUB_OUTPUT
+ echo "shorthash=$(git rev-parse --short HEAD)" >> $env:GITHUB_OUTPUT
- name: Upload executable
uses: actions/upload-artifact@v4
with:
- name: shadps4-win64-qt
+ name: shadps4-win64-qt-${{ steps.vars.outputs.date }}-${{ steps.vars.outputs.shorthash }}
path: upload
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 499124863..413277927 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -26,9 +26,16 @@ jobs:
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel
+ - name: Get date and git hash
+ id: vars
+ shell: pwsh
+ run: |
+ echo "date=$(Get-Date -Format 'yyyy-MM-dd')" >> $env:GITHUB_OUTPUT
+ echo "shorthash=$(git rev-parse --short HEAD)" >> $env:GITHUB_OUTPUT
+
- name: Upload executable
uses: actions/upload-artifact@v4
with:
- name: shadps4-win64-sdl
+ name: shadps4-win64-sdl-${{ steps.vars.outputs.date }}-${{ steps.vars.outputs.shorthash }}
path: |
${{github.workspace}}/build/Release/shadPS4.exe
diff --git a/.gitignore b/.gitignore
index 2a3145085..087f29683 100644
--- a/.gitignore
+++ b/.gitignore
@@ -409,3 +409,6 @@ FodyWeavers.xsd
/out/*
/third-party/out/*
/src/common/scm_rev.cpp
+
+# for macOS
+**/.DS_Store
\ No newline at end of file
diff --git a/.gitmodules b/.gitmodules
index 60fb5fbbf..95b0fc0bb 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,66 +1,87 @@
-[submodule "externals/discord-rpc"]
- path = externals/discord-rpc
- url = https://github.com/shadps4-emu/ext-discord-rpc.git
[submodule "externals/cryptopp-cmake"]
path = externals/cryptopp-cmake
url = https://github.com/shadps4-emu/ext-cryptopp-cmake.git
+ shallow = true
[submodule "externals/cryptopp"]
path = externals/cryptopp
url = https://github.com/shadps4-emu/ext-cryptopp.git
+ shallow = true
[submodule "externals/cryptoppwin"]
path = externals/cryptoppwin
url = https://github.com/shadps4-emu/ext-cryptoppwin.git
+ shallow = true
[submodule "externals/zlib-ng"]
path = externals/zlib-ng
url = https://github.com/shadps4-emu/ext-zlib-ng.git
+ shallow = true
[submodule "externals/sdl3"]
path = externals/sdl3
url = https://github.com/shadps4-emu/ext-SDL.git
+ shallow = true
[submodule "externals/fmt"]
path = externals/fmt
url = https://github.com/shadps4-emu/ext-fmt.git
+ shallow = true
[submodule "externals/vulkan-headers"]
path = externals/vulkan-headers
url = https://github.com/KhronosGroup/Vulkan-Headers.git
+ shallow = true
[submodule "externals/vma"]
path = externals/vma
url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
+ shallow = true
[submodule "externals/glslang"]
path = externals/glslang
url = https://github.com/KhronosGroup/glslang.git
+ shallow = true
[submodule "externals/robin-map"]
path = externals/robin-map
url = https://github.com/Tessil/robin-map.git
+ shallow = true
[submodule "externals/xbyak"]
path = externals/xbyak
url = https://github.com/herumi/xbyak.git
+ shallow = true
[submodule "externals/winpthreads"]
path = externals/winpthreads
url = https://github.com/shadps4-emu/winpthreads.git
+ shallow = true
[submodule "externals/magic_enum"]
path = externals/magic_enum
url = https://github.com/Neargye/magic_enum.git
+ shallow = true
[submodule "externals/toml11"]
path = externals/toml11
url = https://github.com/ToruNiina/toml11.git
+ shallow = true
[submodule "externals/zydis"]
path = externals/zydis
url = https://github.com/zyantific/zydis.git
+ shallow = true
[submodule "externals/sirit"]
path = externals/sirit
url = https://github.com/shadps4-emu/sirit.git
+ shallow = true
[submodule "externals/xxhash"]
path = externals/xxhash
url = https://github.com/Cyan4973/xxHash.git
+ shallow = true
[submodule "externals/tracy"]
path = externals/tracy
url = https://github.com/shadps4-emu/tracy.git
+ shallow = true
[submodule "externals/ext-boost"]
path = externals/ext-boost
url = https://github.com/shadps4-emu/ext-boost.git
+ shallow = true
[submodule "externals/date"]
path = externals/date
url = https://github.com/HowardHinnant/date.git
+ shallow = true
[submodule "externals/ffmpeg-core"]
path = externals/ffmpeg-core
- url = https://github.com/shadps4-emu/ext-ffmpeg-core
+ url = https://github.com/shadps4-emu/ext-ffmpeg-core.git
+ shallow = true
+[submodule "externals/half"]
+ path = externals/half
+ url = https://github.com/ROCm/half.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 679325ec8..6c40f0a8f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -17,6 +17,18 @@ endif()
project(shadPS4)
+# Forcing PIE makes sure that the base address is high enough so that it doesn't clash with the PS4 memory.
+if(UNIX AND NOT APPLE)
+ set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
+
+ # check PIE support at link time
+ include(CheckPIESupported)
+ check_pie_supported(OUTPUT_VARIABLE pie_check LANGUAGES C CXX)
+ if(NOT CMAKE_C_LINK_PIE_SUPPORTED OR NOT CMAKE_CXX_LINK_PIE_SUPPORTED)
+ message(WARNING "PIE is not supported at link time: ${pie_check}")
+ endif()
+endif()
+
option(ENABLE_QT_GUI "Enable the Qt GUI. If not selected then the emulator uses a minimal SDL-based UI instead" OFF)
# This function should be passed a list of all files in a target. It will automatically generate file groups
@@ -66,9 +78,8 @@ git_branch_name(GIT_BRANCH)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp" @ONLY)
find_package(Boost 1.84.0 CONFIG)
-find_package(cryptopp 8.9.0 MODULE)
find_package(FFmpeg 5.1.2 MODULE)
-find_package(fmt 10.2.1 CONFIG)
+find_package(fmt 10.2.0 CONFIG)
find_package(glslang 14.2.0 CONFIG)
find_package(magic_enum 0.9.6 CONFIG)
find_package(RenderDoc 1.6.0 MODULE)
@@ -79,8 +90,12 @@ find_package(VulkanHeaders 1.3.289 CONFIG)
find_package(VulkanMemoryAllocator 3.1.0 CONFIG)
find_package(xbyak 7.07 CONFIG)
find_package(xxHash 0.8.2 MODULE)
-find_package(zlib-ng 2.2.0 MODULE)
-find_package(Zydis 4.1.0 CONFIG)
+find_package(zlib-ng 2.1.7 MODULE)
+find_package(Zydis 5.0.0 CONFIG)
+
+if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR NOT MSVC)
+ find_package(cryptopp 8.9.0 MODULE)
+endif()
if (APPLE)
find_package(date 3.0.1 CONFIG)
@@ -92,10 +107,6 @@ check_symbol_exists(pthread_mutex_timedlock "pthread.h" HAVE_PTHREAD_MUTEX_TIMED
if(HAVE_PTHREAD_MUTEX_TIMEDLOCK OR WIN32)
add_compile_options(-DHAVE_PTHREAD_MUTEX_TIMEDLOCK)
endif()
-check_symbol_exists(sem_timedwait "semaphore.h" HAVE_SEM_TIMEDWAIT)
-if(HAVE_SEM_TIMEDWAIT OR WIN32)
- add_compile_options(-DHAVE_SEM_TIMEDWAIT)
-endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
# libc++ requires -fexperimental-library to enable std::jthread and std::stop_token support.
@@ -110,11 +121,27 @@ add_subdirectory(externals)
include_directories(src)
if(ENABLE_QT_GUI)
- find_package(Qt6 REQUIRED COMPONENTS Widgets Concurrent)
+ find_package(Qt6 REQUIRED COMPONENTS Widgets Concurrent LinguistTools Network)
qt_standard_project_setup()
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
+
+ set(QT_TRANSLATIONS "${PROJECT_SOURCE_DIR}/src/qt_gui/translations")
+ file(GLOB_RECURSE TRANSLATIONS_TS ${QT_TRANSLATIONS}/*.ts)
+
+ set_source_files_properties(${TRANSLATIONS_TS} PROPERTIES OUTPUT_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/translations")
+ qt_add_translation(TRANSLATIONS_QM ${TRANSLATIONS_TS})
+
+ set(TRANSLATIONS_QRC ${CMAKE_CURRENT_BINARY_DIR}/translations/translations.qrc)
+ file(WRITE ${TRANSLATIONS_QRC} "\n")
+ foreach (QM ${TRANSLATIONS_QM})
+ get_filename_component(QM_FILE ${QM} NAME)
+ file(APPEND ${TRANSLATIONS_QRC} "${QM_FILE}\n")
+ endforeach (QM)
+ file(APPEND ${TRANSLATIONS_QRC} "")
+
+ qt_add_resources(TRANSLATIONS ${TRANSLATIONS_QRC})
endif()
set(AUDIO_CORE src/audio_core/sdl_audio.cpp
@@ -133,9 +160,10 @@ set(AUDIO_LIB src/core/libraries/audio/audioin.cpp
set(GNM_LIB src/core/libraries/gnmdriver/gnmdriver.cpp
src/core/libraries/gnmdriver/gnmdriver.h
+ src/core/libraries/gnmdriver/gnm_error.h
)
-set(KERNEL_LIB
+set(KERNEL_LIB
src/core/libraries/kernel/event_flag/event_flag.cpp
src/core/libraries/kernel/event_flag/event_flag.h
src/core/libraries/kernel/event_flag/event_flag_obj.cpp
@@ -193,6 +221,7 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp
src/core/libraries/app_content/app_content.h
src/core/libraries/rtc/rtc.cpp
src/core/libraries/rtc/rtc.h
+ src/core/libraries/rtc/rtc_error.h
src/core/libraries/disc_map/disc_map.cpp
src/core/libraries/disc_map/disc_map.h
src/core/libraries/disc_map/disc_map_codes.h
@@ -208,6 +237,12 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp
src/core/libraries/avplayer/avplayer_state.h
src/core/libraries/avplayer/avplayer.cpp
src/core/libraries/avplayer/avplayer.h
+ src/core/libraries/ngs2/ngs2.cpp
+ src/core/libraries/ngs2/ngs2.h
+ src/core/libraries/ngs2/ngs2_error.h
+ src/core/libraries/ngs2/ngs2_impl.cpp
+ src/core/libraries/ngs2/ngs2_impl.h
+ src/core/libraries/ajm/ajm_error.h
)
set(VIDEOOUT_LIB src/core/libraries/videoout/buffer.h
@@ -217,21 +252,7 @@ set(VIDEOOUT_LIB src/core/libraries/videoout/buffer.h
src/core/libraries/videoout/video_out.h
)
-set(LIBC_SOURCES src/core/libraries/libc/libc.cpp
- src/core/libraries/libc/libc.h
- src/core/libraries/libc/printf.h
- src/core/libraries/libc/va_ctx.h
- src/core/libraries/libc/libc_cxa.cpp
- src/core/libraries/libc/libc_cxa.h
- src/core/libraries/libc/libc_stdio.cpp
- src/core/libraries/libc/libc_stdio.h
- src/core/libraries/libc/libc_math.cpp
- src/core/libraries/libc/libc_math.h
- src/core/libraries/libc/libc_string.cpp
- src/core/libraries/libc/libc_string.h
- src/core/libraries/libc/libc_stdlib.cpp
- src/core/libraries/libc/libc_stdlib.h
- src/core/libraries/libc_internal/libc_internal.cpp
+set(LIBC_SOURCES src/core/libraries/libc_internal/libc_internal.cpp
src/core/libraries/libc_internal/libc_internal.h
)
@@ -257,6 +278,7 @@ set(PLAYGO_LIB src/core/libraries/playgo/playgo.cpp
set(RANDOM_LIB src/core/libraries/random/random.cpp
src/core/libraries/random/random.h
+ src/core/libraries/random/random_error.h
)
set(USBD_LIB src/core/libraries/usbd/usbd.cpp
@@ -270,6 +292,7 @@ set(NP_LIBS src/core/libraries/np_manager/np_manager.cpp
src/core/libraries/np_trophy/np_trophy.cpp
src/core/libraries/np_trophy/np_trophy.h
)
+
set(MISC_LIBS src/core/libraries/screenshot/screenshot.cpp
src/core/libraries/screenshot/screenshot.h
)
@@ -336,7 +359,7 @@ set(CORE src/core/aerolib/stubs.cpp
src/core/cpu_patches.cpp
src/core/cpu_patches.h
src/core/crypto/crypto.cpp
- src/core/crypto/crypto.h
+ src/core/crypto/crypto.h
src/core/crypto/keys.h
src/core/file_format/pfs.h
src/core/file_format/pkg.cpp
@@ -361,7 +384,7 @@ set(CORE src/core/aerolib/stubs.cpp
src/core/loader/elf.h
src/core/loader/symbols_resolver.h
src/core/loader/symbols_resolver.cpp
- src/core/libraries/error_codes.h
+ src/core/libraries/error_codes.h
src/core/libraries/libs.h
src/core/libraries/libs.cpp
${AUDIO_LIB}
@@ -419,7 +442,6 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h
src/shader_recompiler/backend/spirv/spirv_emit_context.h
src/shader_recompiler/frontend/translate/data_share.cpp
src/shader_recompiler/frontend/translate/export.cpp
- src/shader_recompiler/frontend/translate/flat_memory.cpp
src/shader_recompiler/frontend/translate/scalar_alu.cpp
src/shader_recompiler/frontend/translate/scalar_memory.cpp
src/shader_recompiler/frontend/translate/translate.cpp
@@ -439,7 +461,7 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h
src/shader_recompiler/frontend/opcodes.h
src/shader_recompiler/frontend/structured_control_flow.cpp
src/shader_recompiler/frontend/structured_control_flow.h
- src/shader_recompiler/ir/passes/constant_propogation_pass.cpp
+ src/shader_recompiler/ir/passes/constant_propagation_pass.cpp
src/shader_recompiler/ir/passes/dead_code_elimination_pass.cpp
src/shader_recompiler/ir/passes/identity_removal_pass.cpp
src/shader_recompiler/ir/passes/ir_passes.h
@@ -477,6 +499,7 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp
src/video_core/amdgpu/pm4_cmds.h
src/video_core/amdgpu/pm4_opcodes.h
src/video_core/amdgpu/resource.h
+ src/video_core/amdgpu/default_context.cpp
src/video_core/buffer_cache/buffer.cpp
src/video_core/buffer_cache/buffer.h
src/video_core/buffer_cache/buffer_cache.cpp
@@ -510,6 +533,8 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp
src/video_core/renderer_vulkan/vk_resource_pool.h
src/video_core/renderer_vulkan/vk_scheduler.cpp
src/video_core/renderer_vulkan/vk_scheduler.h
+ src/video_core/renderer_vulkan/vk_shader_cache.cpp
+ src/video_core/renderer_vulkan/vk_shader_cache.h
src/video_core/renderer_vulkan/vk_shader_util.cpp
src/video_core/renderer_vulkan/vk_shader_util.h
src/video_core/renderer_vulkan/vk_swapchain.cpp
@@ -552,6 +577,10 @@ qt_add_resources(RESOURCE_FILES src/shadps4.qrc)
set(QT_GUI src/qt_gui/about_dialog.cpp
src/qt_gui/about_dialog.h
src/qt_gui/about_dialog.ui
+ src/qt_gui/cheats_patches.cpp
+ src/qt_gui/cheats_patches.h
+ src/qt_gui/memory_patcher.cpp
+ src/qt_gui/memory_patcher.h
src/qt_gui/main_window_ui.h
src/qt_gui/main_window.cpp
src/qt_gui/main_window.h
@@ -579,6 +608,7 @@ set(QT_GUI src/qt_gui/about_dialog.cpp
src/qt_gui/main.cpp
${EMULATOR}
${RESOURCE_FILES}
+ ${TRANSLATIONS}
)
endif()
@@ -618,7 +648,7 @@ target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAlloca
if (APPLE)
# Reserve system-managed memory space.
- target_link_options(shadps4 PRIVATE -Wl,-no_pie,-no_fixup_chains,-no_huge,-pagezero_size,0x400000,-segaddr,GUEST_SYSTEM,0x400000,-image_base,0x10000000000)
+ target_link_options(shadps4 PRIVATE -Wl,-no_pie,-no_fixup_chains,-no_huge,-pagezero_size,0x4000,-segaddr,TCB_SPACE,0x4000,-segaddr,GUEST_SYSTEM,0x400000,-image_base,0x20000000000)
# Link MoltenVK for Vulkan support
find_library(MOLTENVK MoltenVK REQUIRED)
@@ -626,6 +656,9 @@ if (APPLE)
# Replacement for std::chrono::time_zone
target_link_libraries(shadps4 PRIVATE date::date-tz)
+
+ # Half float conversions for F16C patches
+ target_link_libraries(shadps4 PRIVATE half)
endif()
if (NOT ENABLE_QT_GUI)
@@ -639,27 +672,45 @@ else()
endif()
if (ENABLE_QT_GUI)
- target_link_libraries(shadps4 PRIVATE Qt6::Widgets Qt6::Concurrent)
+ target_link_libraries(shadps4 PRIVATE Qt6::Widgets Qt6::Concurrent Qt6::Network)
+ add_definitions(-DENABLE_QT_GUI)
endif()
if (WIN32)
- target_link_libraries(shadps4 PRIVATE mincore winpthreads clang_rt.builtins-x86_64.lib)
- add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS)
+ target_link_libraries(shadps4 PRIVATE mincore winpthreads)
+
+ if (MSVC)
+ # MSVC likes putting opinions on what people can use, disable:
+ add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS)
+ endif()
+
add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN)
+
if (MSVC)
# Needed for conflicts with time.h of windows.h
add_definitions(-D_TIMESPEC_DEFINED)
endif()
+
# Target Windows 10 RS5
add_definitions(-DNTDDI_VERSION=0x0A000006 -D_WIN32_WINNT=0x0A00 -DWINVER=0x0A00)
- # Increase stack commit area
- target_link_options(shadps4 PRIVATE /STACK:0x200000,0x200000)
+
+ if (MSVC)
+ target_link_libraries(shadps4 PRIVATE clang_rt.builtins-x86_64.lib)
+ endif()
+
# Disable ASLR so we can reserve the user area
if (MSVC)
target_link_options(shadps4 PRIVATE /DYNAMICBASE:NO)
else()
target_link_options(shadps4 PRIVATE -Wl,--disable-dynamicbase)
endif()
+
+ # Increase stack commit area (Needed, otherwise there are crashes)
+ if (MSVC)
+ target_link_options(shadps4 PRIVATE /STACK:0x200000,0x200000)
+ else()
+ target_link_options(shadps4 PRIVATE -Wl,--stack,2097152)
+ endif()
endif()
if (WIN32)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a428598c7..cdda7c8c0 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -69,7 +69,7 @@ enum class SomeEnum {
* Note that the asterisks are indented by one space to align to the first line.
*/
struct Position {
- // Always intitialize member variables!
+ // Always initialize member variables!
int x{};
int y{};
};
diff --git a/README.md b/README.md
index 7089b3c01..c99142c78 100644
--- a/README.md
+++ b/README.md
@@ -32,27 +32,30 @@ SPDX-License-Identifier: GPL-2.0-or-later
-# shadPS4
+# General information
-shadPS4 is an early **PlayStation 4** emulator for **Windows**, **Linux** and **macOS** written in C++
+shadPS4 is an early **PlayStation 4** emulator for **Windows**, **Linux** and **macOS** written in C++.
If you encounter problems or have doubts, do not hesitate to look at the [**Quickstart**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Quickstart/Quickstart.md).
To verify that a game works, you can look at [**shadPS4 Game Compatibility**](https://github.com/shadps4-emu/shadps4-game-compatibility).
-To discuss shadPS4 development or suggest ideas, join the [**Discord server**](https://discord.gg/MyZRaBngxA).
+To discuss shadPS4 development, suggest ideas or to ask for help, join our [**Discord server**](https://discord.gg/MyZRaBngxA).
-To get the latest news, go to our [**X (twitter)**](https://x.com/shadps4) or our [**website**](https://shadps4.net/).
+To get the latest news, go to our [**X (Twitter)**](https://x.com/shadps4) or our [**website**](https://shadps4.net/).
# Status
-In development, small games are working like [**Sonic Mania**](https://www.youtube.com/watch?v=AAHoNzhHyCU), [**Undertale**](https://youtu.be/5zIvdy65Ro4), [**Dysmantle**](https://youtu.be/b9xzhLBdESE) and others...
+> [!IMPORTANT]
+> shadPS4 is early in developement, don't expect a flawless experience.
+
+Currently, the emulator successfully runs small games like [**Sonic Mania**](https://www.youtube.com/watch?v=AAHoNzhHyCU), [**Undertale**](https://youtu.be/5zIvdy65Ro4) and it can even *somewhat* run [**Bloodborne**](https://www.youtube.com/watch?v=wC6s0avpQRE).
# Why
-The project started as a fun project. Due to limited free time, it will probably take a while before shadPS4 is able to run anything decent, but we're trying to make small, regular commits.
+This project began as a fun project. Given our limited free time, it may take some time before shadPS4 can run more complex games, but we're committed to making small, regular updates.
-# Build
+# Building
## Windows
@@ -62,7 +65,7 @@ Check the build instructions for [**Windows**](https://github.com/shadps4-emu/sh
Check the build instructions for [**Linux**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/building-linux.md).
-## Build status
+## Building status
Windows
@@ -91,9 +94,16 @@ Check the build instructions for [**Linux**](https://github.com/shadps4-emu/shad
|macOS Qt Build|[](https://github.com/shadps4-emu/shadPS4/actions/workflows/macos-qt.yml)
-# Keyboard Mapping
+# Debugging and reporting issues
-| Controller button | Keyboard |
+For more information on how to test, debug and report issues with the emulator or games, read the [Debugging documentation](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Debugging/Debugging.md).
+
+# Keyboard mapping
+
+> [!NOTE]
+> Xbox and DualShock controllers work out of the box.
+
+| Controller button | Keyboard equivelant |
|-------------|-------------|
LEFT AXIS UP | W |
LEFT AXIS DOWN | S |
@@ -150,4 +160,4 @@ Open a PR and we'll check it :)
# License
-- [**GPL-2.0 license**](https://github.com/shadps4-emu/shadPS4/blob/main/LICENSE)
\ No newline at end of file
+- [**GPL-2.0 license**](https://github.com/shadps4-emu/shadPS4/blob/main/LICENSE)
diff --git a/documents/Debugging/Debugging.md b/documents/Debugging/Debugging.md
new file mode 100644
index 000000000..ef9aab879
--- /dev/null
+++ b/documents/Debugging/Debugging.md
@@ -0,0 +1,156 @@
+
+
+ # Debugging and reporting issues about shadPS4 and games
+
+This document covers information about debugging, troubleshooting and reporting developer-side issues related to shadPS4 and games.
+
+## Setup
+
+This section will guide you through setting up tools for debugging the emulator. This list will likely expand as more tools and platforms receive consistent setups.
+
+
+Windows and Visual Studio
+
+Make sure you have the project set up for building on Windows with Visual Studio and CMake: [Build shadPS4 for Windows
+](https://github.com/shadps4-emu/shadPS4/blob/main/documents/building-windows.md)
+
+1. Open the project folder in Visual Studio **as a folder**. _Do not run `cmake ..` or other commands that set up the project._
+
+2. In the Solution Explorer, click the **Switch between solutions and available views** button.\
+ 
+
+3. Double-click on **CMake Targets View**.\
+ 
+
+4. Under **shadPS4 Project**, right-click on the **shadps4 (executable)** solution and click **Set as Startup Item**. This will let you start and debug shadPS4 using the VS debug buttons, as well as the default F5 shortcut.\
+ 
+
+5. Right-click the **shadps4 (executable)** solution once more and click **Add debug configuration**.
+
+6. Add an `"args: []"` section into the first `configurations` entry.\
+ List your game path as an argument, as if you were launching the non-GUI emulator from the command line.
+ 
+
+7. Set the appropriate CMake configuration for debugging or testing.
+ - For debugging the emulator and games within it, select `x64-Clang-Debug`.
+ - For testing the emulator with compiler optimizations as a release build, it is recommended to select `x64-Clang-RelWithDebInfo`,
+ as debug symbols will still be generated in case you encounter release configuration-exclusive bugs/errors.
+ 
+
+Launch and debug the emulator through **Debug > Start Debugging** (F5 by default), or **Debug > Start Without Debugging** (Ctrl+F5 by default) when testing games for performance.
+
+
+
+## Configuration
+
+You can configure the emulator by editing the `config.toml` file found in the `user` folder created after starting the application.
+
+
+ Some configuration entries worth changing
+
+- `[General]`
+
+ - `logType`: Configures logging synchronization (`sync`/`async`)
+ - By default, the emulator logs messages asynchronously for better performance. Some log messages may end up being received out-of-order.
+ - It can be beneficial to set this to `sync` in order for the log to accurately maintain message order, at the cost of performance.
+ - When communicating about issues with games and the log messages aren't clear due to potentially confusing order, set this to `sync` and send that log as well.
+ - `logFilter`: Sets the logging category for various logging classes.
+ - Format: `: ...`
+ - Multiple classes can be set by separating them with a space. (example: `Render:Warning Debug:Critical Lib.Pad:Error`)
+ - Sub-classes can be specified in the same format as seen in the console/log (such as `Core.Linker`).
+ - All classes and sub-classes can be set by specifying a `*` symbol. (example: `Kernel.*:Critical`)
+ - Valid log levels: `Trace, Debug, Info, Warning, Error, Critical` - in this order, setting a level silences all levels preceding it and logs every level after it.
+ - Examples:
+ - If the log is being spammed with messages coming from Lib.Pad, you can use `Lib.Pad:Critical` to only log critical-level messages.
+ - If you'd like to mute everything, but still want to receive messages from Vulkan rendering: `*:Critical Render.Vulkan:Info`
+
+ - `Fullscreen`: Display the game in a full screen borderless window.
+
+- `[GPU]`
+ - `dumpShaders`: Dump shaders that are loaded by the emulator. Dump path: `../user/shader/dumps`
+ - `nullGpu`: Disables rendering.
+ - `screenWidth` and `screenHeight`: Configures the game window width and height.
+
+- `[Vulkan]`
+ - `validation`-related settings: Use when debugging Vulkan.
+ - `rdocEnable`: Automatically hook RenderDoc when installed. Useful for debugging shaders and game rendering.
+ - `rdocMarkersEnable`: Enable automatic RenderDoc event annotation
+
+- `[LLE]`
+ - `libc`: Use LLE with `libc`.
+
+
+
+## Quick analysis
+
+This section will provide some preliminary steps to take and tips on what to do when you encounter scenarios that require debugging.
+
+
+When a game crashes and breaks in the debugger
+
+1. Analyze the log
+ - A console will open by default when you launch the emulator. It shows the same log messages that go into the log file found at `/user/log/shad_log.txt`.
+
+ - It is recommended that you start analyzing the log bottom-up first:
+ - Are there any critical or error-level messages at the end of the log that would point to a reason for the game crashing?
+ - Do any of the last few messages contain information about the game loading files?
+ - Did the game window draw anything on-screen?
+
+ - Continue analyzing the log from the start to see other errors (such as with initialization, memory mapping, linker errors etc.)
+
+2. Analyze the stack trace
+ - When the emulator is launched through a debugger, it will **break** when an exception or violation is encountered.\
+ _(**breaking** in this context means pausing execution of the program before it continues or stops altogether.
+ Breaks can be intentional as well - these are set with various kinds of **breakpoints**.)_
+
+ - Default setups of most debuggers include a **Stack trace** window/panel that lists the functions the program has called before breaking.
+
+ - The stack trace entries can be navigated to and will show the relevant function, as well as switch to the state that the program was in at the time of execution.\
+ Use the **Locals** and **Watch** windows to investigate variables and other code in these contexts.
+
+ 3. Identify the reason for the crash
+ - **Logs aren't always accurate in determining the reason for a crash.**\
+ Some log entries are reported as errors but may not be fatal for the execution to stop. `Critical` entries are most likely to be the cause for crashes.
+
+ - Pinpoint the area of the emulator where the crash occured\
+ If the stack trace ends with functions that are relevant to rendering, it is safe to assume that the issue is with **rendering**.\
+ Similarly, if a crash is in a library responsible for playing videos, your issue can be narrowed down to the scope of video playback in the emulator.
+
+ - **⚠ Some crashes are intentional**
+ - If you identify **Access violations for writing operations** where the function is (or in cases of game libraries, _looks like_ it is) copying memory,
+ it most likely is an **intentional exception** meant to catch game data being written by the game.
+ This is used by the emulator developers to identify procedures that have to do with game data changing.
+ - Debugging tools usually include an option to not break on certain types of exceptions. **Exclude access violations and other intentional exceptions when debugging to skip these exceptions.**
+ - You can also identify such cases if the game works in Release builds of the emulator. These intentional exceptions are development-time only.
+ - Attempt to **Continue** and observe whether the stack trace and/or variables and registers change when you encounter exceptions.
+
+
+
+## Reporting and communicating about issues
+
+When communicating with the project about game-specific issues, specify an **uniquely identifable game name** along with its `CUSA-xxxxx` code that is specific to the region/variant of the game you're testing.\
+The version number is also important to add at least in the description, especially if you can verify that the game behaves differently across versions.\
+Accurately identifying games will help other developers that own that game recognize your issue by its title and jump in to help test and debug it.
+
+- Examples of good naming schemes:
+ - Amplitude (2016) `CUSA02480`
+ - Rock Band 4 (`CUSA02084`) v1.0
+ - inFamous: Second Son \[`CUSA-00004`\]
+- Examples of unideal naming schemes:
+ - _The Witness_
+ - _GTA 5_
+ - _Watch Dogs_
+
+- If your issue is small or you aren't sure whether you have properly identified something, [join the Discord server](https://discord.gg/MyZRaBngxA) and use the #development channel
+ to concisely explain the issue, as well as any findings you currently have.
+
+- It is recommended that you check the [game compatibility issue tracker](https://github.com/shadps4-emu/shadps4-game-compatibility/issues) and post very short summaries of progress changes there,
+ (such as the game now booting into the menu or getting in-game) for organizational and status update purposes.
+
+- ⚠ **Do not post theoretical, unproven game-specific issues in the emulator issue tracker that you cannot verify and locate in the emulator source code as being a bug.**\
+ Do, however, add information about the game you experienced the issue in, so that it can be tested in a reproducible environment.
+ - Good example: "_Crash in `Shader::Gcn::CFG::EmitBlocks()`, out of bounds list access_" -> _issue description shares stack trace, points to code in the repository and provides relevant information_
+ - Bad example: "_Amplitude crashes on boot, access violation_" -> _issue description reiterates title, focuses on the game instead of the emulator and refuses to elaborate_
diff --git a/documents/Quickstart/1.png b/documents/Quickstart/1.png
deleted file mode 100644
index 6dc0ce2e3..000000000
Binary files a/documents/Quickstart/1.png and /dev/null differ
diff --git a/documents/Quickstart/Quickstart.md b/documents/Quickstart/Quickstart.md
index 4c51b288a..4dd897d85 100644
--- a/documents/Quickstart/Quickstart.md
+++ b/documents/Quickstart/Quickstart.md
@@ -58,4 +58,24 @@ To install PKG files (game and updates), you will need the Qt application (with
## Configure the emulator
-You can configure the emulator in the "user" folder (created after the first start of the application) then in the "config.toml" file. Here you can find lots of parameters to set with True or False.
+You can configure the emulator by editing the `config.toml` file found in the `user` folder created after starting the application.\
+Some settings may be related to more technical development and debugging. For more information on those, see [Debugging](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Debugging/Debugging.md#configuration).
+
+Here's a list of configuration entries that are worth changing:
+
+- `[General]`
+
+ - `Fullscreen`: Display the game in a full screen borderless window.
+
+ - `logType`: Configures logging synchronization (`sync`/`async`)
+ - It can be beneficial to set this to `sync` in order for the log to accurately maintain message order, at the cost of performance.
+ - Use when sending logs to developers. See more about [reporting issues](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Debugging/Debugging.md#reporting-and-communicating-about-issues).
+ - `logFilter`: Sets the logging category for various logging classes.
+ - Format: `: ...`, `: <*:level> ...`
+ - Valid log levels: `Trace, Debug, Info, Warning, Error, Critical` - in this order, setting a level silences all levels preceding it and logs every level after it.
+ - Examples:
+ - If the log is being spammed with messages coming from Lib.Pad, you can use `Lib.Pad:Critical` to only log critical-level messages.
+ - If you'd like to mute everything, but still want to receive messages from Vulkan rendering: `*:Error Render.Vulkan:Info`
+
+- `[GPU]`
+ - `screenWidth` and `screenHeight`: Configures the game window width and height.
\ No newline at end of file
diff --git a/documents/building-windows.md b/documents/building-windows.md
index e00ed90d9..21fd87154 100644
--- a/documents/building-windows.md
+++ b/documents/building-windows.md
@@ -5,21 +5,96 @@ SPDX-License-Identifier: GPL-2.0-or-later
# Build shadPS4 for Windows
-## Download Visual Studio Community 2022
+This tutorial reads as if you have none of the prerequisites already installed. If you do, just ignore the steps regarding installation.
+If you are building to contribute to the project, please omit `--depth 1` from the git invokations.
-Download link: [**Visual Studio 2022**](https://visualstudio.microsoft.com/vs/)
+Note: **ARM64 is not supported!** As of writing, it will not build nor run. The instructions with respect to ARM64 are for developers only.
-## Requirements
+## Option 1: Visual Studio 2022
-### From Visual Studio Community
+### (Prerequisite) Download the Community edition from [**Visual Studio 2022**](https://visualstudio.microsoft.com/vs/)
-- Desktop development with C++
+Once you are within the installer:
+1. Select `Desktop development with C++`
+2. Go to "Individual Components" tab
+3. Search and select `C++ Clang Compiler for Windows` and `MSBuild support for LLVM`
+4. Continue the installation
-### From individual components tab install
+### (Prerequisite) Download [**Qt**](https://doc.qt.io/qt-6/get-and-install-qt.html)
-- C++ Clang Compiler for Windows (17.0.3)
-- MSBuild support for LLVM (Clang-cl) toolset
+Beware, this requires you to create a Qt account. If you do not want to do this, please follow the MSYS2/MinGW compilation method instead.
-- ## Compiling
+1. Under the current, non beta version of Qt (at the time of writing 6.7.2), select the option `MSVC 2019 64-bit` or similar.
+ If you are on Windows on ARM / Qualcomm Snapdragon Elite X, select `MSVC 2019 ARM64` instead.
-- Open Visual Studio Community and select the **x64-Clang-Release**, **x64-Clang-Debug** or **x64-Clang-RelWithDebInfo**. It should compile just fine.
+ Go through the installation normally. If you know what you are doing, you may unselect individual components that eat up too much disk space.
+
+2. Download and install [Qt Visual Studio Tools](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2022)
+
+Once you are finished, you will have to configure Qt within Visual Studio:
+1. Tools -> Options -> Qt -> Versions
+2. Add a new Qt version and navigate it to the correct folder. Should look like so: `C:\Qt\6.7.2\msvc2019_64`
+3. Enable the default checkmark on the new version you just created.
+
+### (Prerequisite) Download [**Git for Windows**](https://git-scm.com/download/win)
+
+Go through the Git for Windows installation as normal
+
+### Cloning the source code
+
+1. Open Git for Windows, navigate to a place where you want to store the shadPS4 source code folder
+2. Clone the repository by running
+ `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4`
+
+### Compiling with Visual Studio GUI
+
+1. Open up Visual Studio, select `Open a local folder` and select the folder with the shadPS4 source code. The folder should contain `CMakeLists.txt`
+2. Change x64-Clang-Debug to x64-Clang-Release if you want a regular, non-debug build.
+3. If you want to build shadPS4 with the Qt Gui:
+ 1. Click x64-Clang-Release and select "Manage Configurations"
+ 2. Look for "CMake command arguments" and add to the text field
+ `-DENABLE_QT_GUI=ON -DCMAKE_PREFIX_PATH=C:\Qt\6.7.2\msvc2019_64`
+ (Change Qt path if you've installed it to non-default path)
+ 3. Press CTRL+S to save and wait a moment for CMake generation
+4. Change the project to build to shadps4.exe
+5. Build -> Build All
+
+Your shadps4.exe will be in `c:\path\to\source\Build\x64-Clang-Release\`
+
+To automatically populate the necessary files to run shadPS4.exe, run in a command prompt or terminal:
+`C:\Qt\6.7.2\msvc2019_64\bin\windeployqt.exe c:\path\to\shadps4.exe`
+(Change Qt path if you've installed it to non-default path)
+
+## Option 2: MSYS2/MinGW
+
+### (Prerequisite) Download [**MSYS2**](https://www.msys2.org/)
+
+Go through the MSYS2 installation as normal
+
+If you are building to distribute, please omit `-DCMAKE_CXX_FLAGS="-O2 -march=native"` within the build configuration step.
+
+Normal x86-based computers, follow:
+1. Open "MSYS2 MINGW64" from your new applications
+2. Run `pacman -Syu`, let it complete;
+3. Run `pacman -S --needed git mingw-w64-x86_64-binutils mingw-w64-x86_64-clang mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-qt6-base`
+4. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4`
+5. Run `cd shadPS4`
+6. Run `cmake -S . -B build -DCMAKE_CXX_COMPILER="clang++.exe" -DCMAKE_C_COMPILER="clang.exe" -DCMAKE_CXX_FLAGS="-O2 -march=native"`
+7. Run `cmake --build build`
+8. To run the finished product, run `./build/shadPS4.exe`
+
+ARM64-based computers, follow:
+1. Open "MSYS2 CLANGARM64" from your new applications
+2. Run `pacman -Syu`, let it complete;
+3. Run `pacman -S --needed git mingw-w64-clang-aarch64-binutils mingw-w64-clang-aarch64-clang mingw-w64-clang-aarch64-cmake mingw-w64-clang-aarch64-ninja mingw-w64-clang-aarch64-qt6-base`
+4. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4`
+5. Run `cd shadPS4`
+6. Run `cmake -S . -B build -DCMAKE_CXX_COMPILER="clang++.exe" -DCMAKE_C_COMPILER="clang.exe" -DCMAKE_CXX_FLAGS="-O2 -march=native"`
+7. Run `cmake --build build`
+8. To run the finished product, run `./build/shadPS4.exe`
+
+## Note on MSYS2 builds
+
+These builds may not be easily copyable to people who do not also have a MSYS2 installation.
+If you want to distribute these builds, you need to copy over the correct DLLs into a distribution folder.
+In order to run them, you must be within the MSYS2 shell environment.
\ No newline at end of file
diff --git a/documents/changelog.txt b/documents/changelog.txt
index 7f9c25268..0e189f58d 100644
--- a/documents/changelog.txt
+++ b/documents/changelog.txt
@@ -1,32 +1,44 @@
+v0.2.0 15/08/2024 - codename validptr
+=================
+- Adding macOS support
+- Big shader recompiler improvements
+- Core improvements
+- GUI improvements
+
+v0.1.0 01/07/2024 - codename madturtle
+=================
+- Added a shader recompiler, with this we have a lot of games that starts to work
+- Rewrote a big part of core
+
v0.0.3 23/03/2024 - codename salad
=================
--Switching to std::thread
--Use unique_ptr where possible
--Replace printf/scanf with type safe fmt
--Implemented sceKernelGetProcessTime
--Implemented sceKernelGetProcessTimeCounter , sceKernelGetProcessTimeCounterFrequency
--Pause emu with P button
--Timers rewrote with std::chrono
--Added sceSystemServiceGetStatus
--Initial FileSystem implementation
--Initial TLS work
--New logging implementation
--Some functions implemented for userService,systemService
--Added sceAudioOut module and output using sdl audio
+- Switching to std::thread
+- Use unique_ptr where possible
+- Replace printf/scanf with type safe fmt
+- Implemented sceKernelGetProcessTime
+- Implemented sceKernelGetProcessTimeCounter, sceKernelGetProcessTimeCounterFrequency
+- Pause emu with P button
+- Timers rewrote with std::chrono
+- Added sceSystemServiceGetStatus
+- Initial FileSystem implementation
+- Initial TLS work
+- New logging implementation
+- Some functions implemented for userService, systemService
+- Added sceAudioOut module and output using SDL audio
v0.0.2 21/10/2023
=================
--using cstdint header in variable types
--run_main_entry: Rewrite in asm for stack setup
--printf libc implementation for work with sysv_abi
--initial pad emulation (only digital pad atm)
--Implemented sceVideoOutIsFlipPending
--Added auto stubs , now unsupported hle function will resolve as empty stubs
--Rewrote libc_cxa functions
--Libc implementations ( _ZdlPv,_Znwm,rand,_Fsin,qsort,free,strncpy,memmove,atan2f,pow,_Sin)
--ET_SCE_DYNAMIC behaves as valid for execution now.
--Initial FileSystem work (not yet usable).
+- Using cstdint header in variable types
+- run_main_entry: Rewrite in asm for stack setup
+- Printf libc implementation for work with sysv_abi
+- Initial pad emulation (only digital pad atm)
+- Implemented sceVideoOutIsFlipPending
+- Added auto stubs, now unsupported hle function will resolve as empty stubs
+- Rewrote libc_cxa functions
+- Libc implementations ( _ZdlPv,_Znwm,rand,_Fsin,qsort,free,strncpy,memmove,atan2f,pow,_Sin)
+- ET_SCE_DYNAMIC behaves as valid for execution now
+- Initial FileSystem work (not yet usable)
v0.0.1 29/09/2023
=================
-First public release . Everything is new
\ No newline at end of file
+First public release. Everything is new.
\ No newline at end of file
diff --git a/documents/readme.txt b/documents/readme.txt
deleted file mode 100644
index 748dd060b..000000000
--- a/documents/readme.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-shadPS4 - A PS4 emulator
-=========================
-
-1. Intro
-2. Current status
-3. Contributors
-4. Greetings
-
-1.Intro
-=======
-shadPS4 is a Play Station 4 emulator for Windows and Linux. Although atm it can't run a lot of stuff, we are working torwards to make it more compatible.
-
-2.Current status
-================
-shadPS4 is a HLE emulator. Currently on a small amount of functions is emulated, which is one of the reasons compatibility is low.
-
-3.Contributors
-==============
-- georgemoralis
-- raphaelthegreat
-- skmp
-- wheremyfoodat
-
-4.Greetings
-===========
-I would like to thank the following people for helping me so far, with coding or moral support.
-
-- wheremyfoodat - or @rodakinos for believed me
-- paris - or OFFTKP for not believing me and that made me a better coder :D
-- skmp - or kornilios for being good old friend
-- PandaBad - our beloved stalker
-- emufan4568 - for advices
-- velocity - for talking 1-2 times per year on discord server. We miss you velocity
-
-- probably more, will include in the next readme :D
diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt
index 0b19034d6..de0317ff9 100644
--- a/externals/CMakeLists.txt
+++ b/externals/CMakeLists.txt
@@ -25,11 +25,6 @@ if (NOT TARGET fmt::fmt)
add_subdirectory(fmt)
endif()
-# Discord-RPC
-set(BUILD_EXAMPLES OFF CACHE BOOL "")
-add_subdirectory(discord-rpc)
-target_include_directories(discord-rpc INTERFACE ./discord-rpc/include)
-
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND MSVC)
# If it is clang and MSVC we will add a static lib
# CryptoPP
@@ -147,11 +142,17 @@ if (WIN32)
target_compile_options(sirit PUBLIC "-Wno-error=unused-command-line-argument")
endif()
-# date
-if (APPLE AND NOT TARGET date::date-tz)
- option(BUILD_TZ_LIB "" ON)
- option(USE_SYSTEM_TZ_DB "" ON)
- add_subdirectory(date)
+if (APPLE)
+ # half
+ add_library(half INTERFACE)
+ target_include_directories(half INTERFACE half/include)
+
+ # date
+ if (NOT TARGET date::date-tz)
+ option(BUILD_TZ_LIB "" ON)
+ option(USE_SYSTEM_TZ_DB "" ON)
+ add_subdirectory(date)
+ endif()
endif()
# Tracy
diff --git a/externals/discord-rpc b/externals/discord-rpc
deleted file mode 160000
index 4ec218155..000000000
--- a/externals/discord-rpc
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 4ec218155d73bcb8022f8f7ca72305d801f84beb
diff --git a/externals/glslang b/externals/glslang
index 4422273e8..12cbda959 160000
--- a/externals/glslang
+++ b/externals/glslang
@@ -1 +1 @@
-Subproject commit 4422273e8464d20b9d8dd403cbfc3049e09a5f23
+Subproject commit 12cbda959b6df2af119a76a73ff906c2bed36884
diff --git a/externals/half b/externals/half
new file mode 160000
index 000000000..1ddada225
--- /dev/null
+++ b/externals/half
@@ -0,0 +1 @@
+Subproject commit 1ddada225144cac0de8f6b5c0dd9acffd99a2e68
diff --git a/externals/robin-map b/externals/robin-map
index 1115dad3f..2c48a1a50 160000
--- a/externals/robin-map
+++ b/externals/robin-map
@@ -1 +1 @@
-Subproject commit 1115dad3ffa0994e3f43b693d9b9cc99944c64c1
+Subproject commit 2c48a1a50203bbaf1e3d0d64c5d726d56f8d3bb3
diff --git a/externals/sirit b/externals/sirit
index 8db09231c..37090c74c 160000
--- a/externals/sirit
+++ b/externals/sirit
@@ -1 +1 @@
-Subproject commit 8db09231c448b913ae905d5237ce2eca46e3fe87
+Subproject commit 37090c74cc6e680f2bc334cac8fd182f7634a1f6
diff --git a/externals/toml11 b/externals/toml11
index 26d403e46..4b7401272 160000
--- a/externals/toml11
+++ b/externals/toml11
@@ -1 +1 @@
-Subproject commit 26d403e46102269e5314199cd313e82e4e17d99a
+Subproject commit 4b740127230472779c4a4d71e1a75aaa3a367a2d
diff --git a/scripts/aerolib.inl b/scripts/aerolib.inl
index a87c3cc4e..64ee32ea2 100644
--- a/scripts/aerolib.inl
+++ b/scripts/aerolib.inl
@@ -114108,7 +114108,7 @@ STUB(
_ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_7Matches2V124RequestCompetitiveResultEE7add_refEv)
STUB("efPahl2FufA",
_ZN3sce2Np9CppWebApi30CommunicationRestrictionStatus2V35Error8fromJsonERKNS_4Json5ValueE)
-STUB("efX3lrPwdKA", sceAppContentAddcontMountByEntitlemetId)
+STUB("efX3lrPwdKA", sceAppContentAddcontMountByEntitlementId)
STUB("efXnxYFN5oE", _ZNSt11range_errorD0Ev)
STUB("efcwuDLsAM0", _ZThn120_NK7WebCore16HTMLMediaElement5mutedEv)
STUB("efhGArzWdxE", _ZN7bmalloc6IsoTLS15s_didInitializeE)
@@ -129493,7 +129493,7 @@ STUB(
STUB("kJlYH5uMAWI", sceNetResolverDestroy)
STUB("kJmdxo4uM+8",
_ZNSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE5_InitERKSt8_Locinfo)
-STUB("kJmjt81mXKQ", sceAppContentAddcontEnqueueDownloadByEntitlemetId)
+STUB("kJmjt81mXKQ", sceAppContentAddcontEnqueueDownloadByEntitlementId)
STUB(
"kJoY9lMIFzY",
_ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_21AdvancedPlayerProfile2V138MatchCompletionRateDisconnectedMetricsEEEEmmEi)
diff --git a/scripts/ps4_names.txt b/scripts/ps4_names.txt
index caad2b4df..6f95cc734 100644
--- a/scripts/ps4_names.txt
+++ b/scripts/ps4_names.txt
@@ -80897,10 +80897,10 @@ sceAppCheckerExecute
sceAppCheckerExecuteEx
sceAppContentAddcontDelete
sceAppContentAddcontEnqueueDownload
-sceAppContentAddcontEnqueueDownloadByEntitlemetId
+sceAppContentAddcontEnqueueDownloadByEntitlementId
sceAppContentAddcontEnqueueDownloadSp
sceAppContentAddcontMount
-sceAppContentAddcontMountByEntitlemetId
+sceAppContentAddcontMountByEntitlementId
sceAppContentAddcontShrink
sceAppContentAddcontUnmount
sceAppContentAppParamGetInt
diff --git a/src/audio_core/sdl_audio.h b/src/audio_core/sdl_audio.h
index 7844bd61b..07e82145e 100644
--- a/src/audio_core/sdl_audio.h
+++ b/src/audio_core/sdl_audio.h
@@ -22,15 +22,15 @@ public:
private:
struct PortOut {
- bool isOpen = false;
- int type = 0;
+ SDL_AudioStream* stream = nullptr;
u32 samples_num = 0;
- u8 sample_size = 0;
u32 freq = 0;
u32 format = -1;
+ int type = 0;
int channels_num = 0;
int volume[8] = {};
- SDL_AudioStream* stream = nullptr;
+ u8 sample_size = 0;
+ bool isOpen = false;
};
std::shared_mutex m_mutex;
std::array portsOut; // main up to 8 ports , BGM 1 port , voice up to 4 ports ,
diff --git a/src/common/config.cpp b/src/common/config.cpp
index 24db6b039..8d87ed3c3 100644
--- a/src/common/config.cpp
+++ b/src/common/config.cpp
@@ -17,10 +17,12 @@ static s32 gpuId = -1; // Vulkan physical device index. Set to negative for auto
static std::string logFilter;
static std::string logType = "async";
static std::string userName = "shadPS4";
+static bool useSpecialPad = false;
+static int specialPadClass = 1;
static bool isDebugDump = false;
-static bool isLibc = true;
static bool isShowSplash = false;
static bool isNullGpu = false;
+static bool shouldCopyGPUBuffers = false;
static bool shouldDumpShaders = false;
static bool shouldDumpPM4 = false;
static u32 vblankDivider = 1;
@@ -46,13 +48,10 @@ u32 m_window_size_H = 720;
std::vector m_pkg_viewer;
std::vector m_elf_viewer;
std::vector m_recent_files;
+std::string emulator_language = "en";
// Settings
u32 m_language = 1; // english
-bool isLleLibc() {
- return isLibc;
-}
-
bool isNeoMode() {
return isNeo;
}
@@ -85,6 +84,14 @@ std::string getUserName() {
return userName;
}
+bool getUseSpecialPad() {
+ return useSpecialPad;
+}
+
+int getSpecialPadClass() {
+ return specialPadClass;
+}
+
bool debugDump() {
return isDebugDump;
}
@@ -97,6 +104,10 @@ bool nullGpu() {
return isNullGpu;
}
+bool copyGPUCmdBuffers() {
+ return shouldCopyGPUBuffers;
+}
+
bool dumpShaders() {
return shouldDumpShaders;
}
@@ -153,6 +164,10 @@ void setNullGpu(bool enable) {
isNullGpu = enable;
}
+void setCopyGPUCmdBuffers(bool enable) {
+ shouldCopyGPUBuffers = enable;
+}
+
void setDumpShaders(bool enable) {
shouldDumpShaders = enable;
}
@@ -189,18 +204,26 @@ void setNeoMode(bool enable) {
isNeo = enable;
}
-void setLogType(std::string type) {
+void setLogType(const std::string& type) {
logType = type;
}
-void setLogFilter(std::string type) {
+void setLogFilter(const std::string& type) {
logFilter = type;
}
-void setUserName(std::string type) {
+void setUserName(const std::string& type) {
userName = type;
}
+void setUseSpecialPad(bool use) {
+ useSpecialPad = use;
+}
+
+void setSpecialPadClass(int type) {
+ specialPadClass = type;
+}
+
void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h) {
main_window_geometry_x = x;
main_window_geometry_y = y;
@@ -219,10 +242,10 @@ void setIconSize(u32 size) {
void setIconSizeGrid(u32 size) {
m_icon_size_grid = size;
}
-void setSliderPositon(u32 pos) {
+void setSliderPosition(u32 pos) {
m_slider_pos = pos;
}
-void setSliderPositonGrid(u32 pos) {
+void setSliderPositionGrid(u32 pos) {
m_slider_pos_grid = pos;
}
void setTableMode(u32 mode) {
@@ -234,19 +257,23 @@ void setMainWindowWidth(u32 width) {
void setMainWindowHeight(u32 height) {
m_window_size_H = height;
}
-void setPkgViewer(std::vector pkgList) {
+void setPkgViewer(const std::vector& pkgList) {
m_pkg_viewer.resize(pkgList.size());
m_pkg_viewer = pkgList;
}
-void setElfViewer(std::vector elfList) {
+void setElfViewer(const std::vector& elfList) {
m_elf_viewer.resize(elfList.size());
m_elf_viewer = elfList;
}
-void setRecentFiles(std::vector recentFiles) {
+void setRecentFiles(const std::vector& recentFiles) {
m_recent_files.resize(recentFiles.size());
m_recent_files = recentFiles;
}
+void setEmulatorLanguage(std::string language) {
+ emulator_language = language;
+}
+
u32 getMainWindowGeometryX() {
return main_window_geometry_x;
}
@@ -271,10 +298,10 @@ u32 getIconSize() {
u32 getIconSizeGrid() {
return m_icon_size_grid;
}
-u32 getSliderPositon() {
+u32 getSliderPosition() {
return m_slider_pos;
}
-u32 getSliderPositonGrid() {
+u32 getSliderPositionGrid() {
return m_slider_pos_grid;
}
u32 getTableMode() {
@@ -296,6 +323,10 @@ std::vector getRecentFiles() {
return m_recent_files;
}
+std::string getEmulatorLanguage() {
+ return emulator_language;
+}
+
u32 GetLanguage() {
return m_language;
}
@@ -326,12 +357,20 @@ void load(const std::filesystem::path& path) {
isShowSplash = toml::find_or(general, "showSplash", true);
}
+ if (data.contains("Input")) {
+ const toml::value& input = data.at("Input");
+
+ useSpecialPad = toml::find_or(input, "useSpecialPad", false);
+ specialPadClass = toml::find_or(input, "specialPadClass", 1);
+ }
+
if (data.contains("GPU")) {
const toml::value& gpu = data.at("GPU");
screenWidth = toml::find_or(gpu, "screenWidth", screenWidth);
screenHeight = toml::find_or(gpu, "screenHeight", screenHeight);
isNullGpu = toml::find_or(gpu, "nullGpu", false);
+ shouldCopyGPUBuffers = toml::find_or(gpu, "copyGPUBuffers", false);
shouldDumpShaders = toml::find_or(gpu, "dumpShaders", false);
shouldDumpPM4 = toml::find_or(gpu, "dumpPM4", false);
vblankDivider = toml::find_or(gpu, "vblankDivider", 1);
@@ -354,12 +393,6 @@ void load(const std::filesystem::path& path) {
isDebugDump = toml::find_or(debug, "DebugDump", false);
}
- if (data.contains("LLE")) {
- const toml::value& lle = data.at("LLE");
-
- isLibc = toml::find_or(lle, "libc", true);
- }
-
if (data.contains("GUI")) {
const toml::value& gui = data.at("GUI");
@@ -379,6 +412,7 @@ void load(const std::filesystem::path& path) {
m_elf_viewer = toml::find_or>(gui, "elfDirs", {});
m_recent_files = toml::find_or>(gui, "recentFiles", {});
m_table_mode = toml::find_or(gui, "gameTableMode", 0);
+ emulator_language = toml::find_or(gui, "emulatorLanguage", "en");
}
if (data.contains("Settings")) {
@@ -412,9 +446,12 @@ void save(const std::filesystem::path& path) {
data["General"]["logType"] = logType;
data["General"]["userName"] = userName;
data["General"]["showSplash"] = isShowSplash;
+ data["Input"]["useSpecialPad"] = useSpecialPad;
+ data["Input"]["specialPadClass"] = specialPadClass;
data["GPU"]["screenWidth"] = screenWidth;
data["GPU"]["screenHeight"] = screenHeight;
data["GPU"]["nullGpu"] = isNullGpu;
+ data["GPU"]["copyGPUBuffers"] = shouldCopyGPUBuffers;
data["GPU"]["dumpShaders"] = shouldDumpShaders;
data["GPU"]["dumpPM4"] = shouldDumpPM4;
data["GPU"]["vblankDivider"] = vblankDivider;
@@ -425,7 +462,6 @@ void save(const std::filesystem::path& path) {
data["Vulkan"]["rdocEnable"] = rdocEnable;
data["Vulkan"]["rdocMarkersEnable"] = rdocMarkersEnable;
data["Debug"]["DebugDump"] = isDebugDump;
- data["LLE"]["libc"] = isLibc;
data["GUI"]["theme"] = mw_themes;
data["GUI"]["iconSize"] = m_icon_size;
data["GUI"]["sliderPos"] = m_slider_pos;
@@ -442,6 +478,7 @@ void save(const std::filesystem::path& path) {
data["GUI"]["pkgDirs"] = m_pkg_viewer;
data["GUI"]["elfDirs"] = m_elf_viewer;
data["GUI"]["recentFiles"] = m_recent_files;
+ data["GUI"]["emulatorLanguage"] = emulator_language;
data["Settings"]["consoleLanguage"] = m_language;
@@ -458,6 +495,8 @@ void setDefaultValues() {
logFilter = "";
logType = "async";
userName = "shadPS4";
+ useSpecialPad = false;
+ specialPadClass = 1;
isDebugDump = false;
isShowSplash = false;
isNullGpu = false;
@@ -466,6 +505,7 @@ void setDefaultValues() {
vblankDivider = 1;
vkValidation = false;
rdocEnable = false;
+ emulator_language = "en";
m_language = 1;
gpuId = -1;
}
diff --git a/src/common/config.h b/src/common/config.h
index 3006f2e2a..11e7d8827 100644
--- a/src/common/config.h
+++ b/src/common/config.h
@@ -17,14 +17,17 @@ std::string getLogFilter();
std::string getLogType();
std::string getUserName();
+bool getUseSpecialPad();
+int getSpecialPadClass();
+
u32 getScreenWidth();
u32 getScreenHeight();
s32 getGpuId();
bool debugDump();
-bool isLleLibc();
bool showSplash();
bool nullGpu();
+bool copyGPUCmdBuffers();
bool dumpShaders();
bool dumpPM4();
bool isRdocEnabled();
@@ -34,6 +37,7 @@ u32 vblankDiv();
void setDebugDump(bool enable);
void setShowSplash(bool enable);
void setNullGpu(bool enable);
+void setCopyGPUCmdBuffers(bool enable);
void setDumpShaders(bool enable);
void setDumpPM4(bool enable);
void setVblankDiv(u32 value);
@@ -43,10 +47,13 @@ void setScreenHeight(u32 height);
void setFullscreenMode(bool enable);
void setLanguage(u32 language);
void setNeoMode(bool enable);
-void setUserName(std::string type);
+void setUserName(const std::string& type);
-void setLogType(std::string type);
-void setLogFilter(std::string type);
+void setUseSpecialPad(bool use);
+void setSpecialPadClass(int type);
+
+void setLogType(const std::string& type);
+void setLogFilter(const std::string& type);
void setVkValidation(bool enable);
void setVkSyncValidation(bool enable);
@@ -62,14 +69,15 @@ void setGameInstallDir(const std::string& dir);
void setMainWindowTheme(u32 theme);
void setIconSize(u32 size);
void setIconSizeGrid(u32 size);
-void setSliderPositon(u32 pos);
-void setSliderPositonGrid(u32 pos);
+void setSliderPosition(u32 pos);
+void setSliderPositionGrid(u32 pos);
void setTableMode(u32 mode);
void setMainWindowWidth(u32 width);
void setMainWindowHeight(u32 height);
-void setPkgViewer(std::vector pkgList);
-void setElfViewer(std::vector elfList);
-void setRecentFiles(std::vector recentFiles);
+void setPkgViewer(const std::vector& pkgList);
+void setElfViewer(const std::vector& elfList);
+void setRecentFiles(const std::vector& recentFiles);
+void setEmulatorLanguage(std::string language);
u32 getMainWindowGeometryX();
u32 getMainWindowGeometryY();
@@ -79,14 +87,15 @@ std::string getGameInstallDir();
u32 getMainWindowTheme();
u32 getIconSize();
u32 getIconSizeGrid();
-u32 getSliderPositon();
-u32 getSliderPositonGrid();
+u32 getSliderPosition();
+u32 getSliderPositionGrid();
u32 getTableMode();
u32 getMainWindowWidth();
u32 getMainWindowHeight();
std::vector getPkgViewer();
std::vector getElfViewer();
std::vector getRecentFiles();
+std::string getEmulatorLanguage();
void setDefaultValues();
diff --git a/src/common/debug.h b/src/common/debug.h
index 50022a156..596ad7b84 100644
--- a/src/common/debug.h
+++ b/src/common/debug.h
@@ -29,7 +29,7 @@ static inline bool IsProfilerConnected() {
#define TRACK_ALLOC(ptr, size, pool) TracyAllocN(std::bit_cast(ptr), (size), (pool))
#define TRACK_FREE(ptr, pool) TracyFreeN(std::bit_cast(ptr), (pool))
-enum MarkersPallete : int {
+enum MarkersPalette : int {
EmulatorMarkerColor = 0x264653,
RendererMarkerColor = 0x2a9d8f,
HleMarkerColor = 0xe9c46a,
diff --git a/src/common/io_file.cpp b/src/common/io_file.cpp
index e1c22d2a1..fbc37a10c 100644
--- a/src/common/io_file.cpp
+++ b/src/common/io_file.cpp
@@ -217,7 +217,7 @@ void IOFile::Close() {
file = nullptr;
#ifdef _WIN64
- if (file_mapping) {
+ if (file_mapping && file_access_mode == FileAccessMode::ReadWrite) {
CloseHandle(std::bit_cast(file_mapping));
}
#endif
@@ -259,8 +259,7 @@ uintptr_t IOFile::GetFileMapping() {
mapping = CreateFileMapping2(hfile, NULL, FILE_MAP_WRITE, PAGE_READWRITE, SEC_COMMIT, 0,
NULL, NULL, 0);
} else {
- mapping = CreateFileMapping2(hfile, NULL, FILE_MAP_READ, PAGE_READONLY, SEC_COMMIT, 0, NULL,
- NULL, 0);
+ mapping = hfile;
}
file_mapping = std::bit_cast(mapping);
diff --git a/src/common/native_clock.cpp b/src/common/native_clock.cpp
index 20d0737a6..c3fa637aa 100644
--- a/src/common/native_clock.cpp
+++ b/src/common/native_clock.cpp
@@ -18,16 +18,16 @@ NativeClock::NativeClock()
us_rdtsc_factor{GetFixedPoint64Factor(std::micro::den, rdtsc_frequency)},
ms_rdtsc_factor{GetFixedPoint64Factor(std::milli::den, rdtsc_frequency)} {}
-u64 NativeClock::GetTimeNS() const {
- return MultiplyHigh(GetUptime(), ns_rdtsc_factor);
+u64 NativeClock::GetTimeNS(u64 base_ptc /*= 0*/) const {
+ return MultiplyHigh(GetUptime() - base_ptc, ns_rdtsc_factor);
}
-u64 NativeClock::GetTimeUS() const {
- return MultiplyHigh(GetUptime(), us_rdtsc_factor);
+u64 NativeClock::GetTimeUS(u64 base_ptc /*= 0*/) const {
+ return MultiplyHigh(GetUptime() - base_ptc, us_rdtsc_factor);
}
-u64 NativeClock::GetTimeMS() const {
- return MultiplyHigh(GetUptime(), ms_rdtsc_factor);
+u64 NativeClock::GetTimeMS(u64 base_ptc /*= 0*/) const {
+ return MultiplyHigh(GetUptime() - base_ptc, ms_rdtsc_factor);
}
u64 NativeClock::GetUptime() const {
diff --git a/src/common/native_clock.h b/src/common/native_clock.h
index 227c8d1ae..b5e389452 100644
--- a/src/common/native_clock.h
+++ b/src/common/native_clock.h
@@ -16,9 +16,9 @@ public:
return rdtsc_frequency;
}
- u64 GetTimeNS() const;
- u64 GetTimeUS() const;
- u64 GetTimeMS() const;
+ u64 GetTimeNS(u64 base_ptc = 0) const;
+ u64 GetTimeUS(u64 base_ptc = 0) const;
+ u64 GetTimeMS(u64 base_ptc = 0) const;
u64 GetUptime() const;
u64 GetProcessTimeUS() const;
diff --git a/src/common/path_util.cpp b/src/common/path_util.cpp
index c1e8a5c0a..e6c1fc1af 100644
--- a/src/common/path_util.cpp
+++ b/src/common/path_util.cpp
@@ -8,6 +8,7 @@
#ifdef __APPLE__
#include
+#include
#include
#endif
@@ -26,23 +27,52 @@ namespace Common::FS {
namespace fs = std::filesystem;
#ifdef __APPLE__
+using IsTranslocatedURLFunc = Boolean (*)(CFURLRef path, bool* isTranslocated,
+ CFErrorRef* __nullable error);
+using CreateOriginalPathForURLFunc = CFURLRef __nullable (*)(CFURLRef translocatedPath,
+ CFErrorRef* __nullable error);
+
+static CFURLRef UntranslocateBundlePath(const CFURLRef bundle_path) {
+ if (void* security_handle =
+ dlopen("/System/Library/Frameworks/Security.framework/Security", RTLD_LAZY)) {
+ SCOPE_EXIT {
+ dlclose(security_handle);
+ };
+
+ const auto IsTranslocatedURL = reinterpret_cast(
+ dlsym(security_handle, "SecTranslocateIsTranslocatedURL"));
+ const auto CreateOriginalPathForURL = reinterpret_cast(
+ dlsym(security_handle, "SecTranslocateCreateOriginalPathForURL"));
+
+ bool is_translocated = false;
+ if (IsTranslocatedURL && CreateOriginalPathForURL &&
+ IsTranslocatedURL(bundle_path, &is_translocated, nullptr) && is_translocated) {
+ return CreateOriginalPathForURL(bundle_path, nullptr);
+ }
+ }
+ return nullptr;
+}
+
static std::filesystem::path GetBundleParentDirectory() {
if (CFBundleRef bundle_ref = CFBundleGetMainBundle()) {
if (CFURLRef bundle_url_ref = CFBundleCopyBundleURL(bundle_ref)) {
SCOPE_EXIT {
CFRelease(bundle_url_ref);
};
- if (CFStringRef bundle_path_ref =
- CFURLCopyFileSystemPath(bundle_url_ref, kCFURLPOSIXPathStyle)) {
- SCOPE_EXIT {
- CFRelease(bundle_path_ref);
- };
- char app_bundle_path[MAXPATHLEN];
- if (CFStringGetFileSystemRepresentation(bundle_path_ref, app_bundle_path,
- sizeof(app_bundle_path))) {
- std::filesystem::path bundle_path{app_bundle_path};
- return bundle_path.parent_path();
+
+ CFURLRef untranslocated_url_ref = UntranslocateBundlePath(bundle_url_ref);
+ SCOPE_EXIT {
+ if (untranslocated_url_ref) {
+ CFRelease(untranslocated_url_ref);
}
+ };
+
+ char app_bundle_path[MAXPATHLEN];
+ if (CFURLGetFileSystemRepresentation(
+ untranslocated_url_ref ? untranslocated_url_ref : bundle_url_ref, true,
+ reinterpret_cast(app_bundle_path), sizeof(app_bundle_path))) {
+ std::filesystem::path bundle_path{app_bundle_path};
+ return bundle_path.parent_path();
}
}
}
@@ -52,11 +82,20 @@ static std::filesystem::path GetBundleParentDirectory() {
static auto UserPaths = [] {
#ifdef __APPLE__
- std::filesystem::current_path(GetBundleParentDirectory());
+ // Start by assuming the base directory is the bundle's parent directory.
+ std::filesystem::path base_dir = GetBundleParentDirectory();
+ std::filesystem::path user_dir = base_dir / PORTABLE_DIR;
+ // Check if the "user" directory exists in the current path:
+ if (!std::filesystem::exists(user_dir)) {
+ // If it doesn't exist, use the new hardcoded path:
+ user_dir =
+ std::filesystem::path(getenv("HOME")) / "Library" / "Application Support" / "shadPS4";
+ }
+#else
+ const auto user_dir = std::filesystem::current_path() / PORTABLE_DIR;
#endif
std::unordered_map paths;
- const auto user_dir = std::filesystem::current_path() / PORTABLE_DIR;
const auto create_path = [&](PathType shad_path, const fs::path& new_path) {
std::filesystem::create_directory(new_path);
@@ -74,6 +113,9 @@ static auto UserPaths = [] {
create_path(PathType::SysModuleDir, user_dir / SYSMODULES_DIR);
create_path(PathType::DownloadDir, user_dir / DOWNLOAD_DIR);
create_path(PathType::CapturesDir, user_dir / CAPTURES_DIR);
+ create_path(PathType::CheatsDir, user_dir / CHEATS_DIR);
+ create_path(PathType::PatchesDir, user_dir / PATCHES_DIR);
+ create_path(PathType::AddonsDir, user_dir / ADDONS_DIR);
return paths;
}();
@@ -122,4 +164,4 @@ void SetUserPath(PathType shad_path, const fs::path& new_path) {
UserPaths.insert_or_assign(shad_path, new_path);
}
-} // namespace Common::FS
+} // namespace Common::FS
\ No newline at end of file
diff --git a/src/common/path_util.h b/src/common/path_util.h
index 263edd46e..bee93c1b9 100644
--- a/src/common/path_util.h
+++ b/src/common/path_util.h
@@ -20,6 +20,9 @@ enum class PathType {
SysModuleDir, // Where system modules are stored.
DownloadDir, // Where downloads/temp files are stored.
CapturesDir, // Where rdoc captures are stored.
+ CheatsDir, // Where cheats are stored.
+ PatchesDir, // Where patches are stored.
+ AddonsDir, // Where additional content is stored.
};
constexpr auto PORTABLE_DIR = "user";
@@ -35,6 +38,9 @@ constexpr auto TEMPDATA_DIR = "temp";
constexpr auto SYSMODULES_DIR = "sys_modules";
constexpr auto DOWNLOAD_DIR = "download";
constexpr auto CAPTURES_DIR = "captures";
+constexpr auto CHEATS_DIR = "cheats";
+constexpr auto PATCHES_DIR = "patches";
+constexpr auto ADDONS_DIR = "addcont";
// Filenames
constexpr auto LOG_FILE = "shad_log.txt";
diff --git a/src/common/slot_vector.h b/src/common/slot_vector.h
index f0982e290..36e647971 100644
--- a/src/common/slot_vector.h
+++ b/src/common/slot_vector.h
@@ -28,9 +28,13 @@ struct SlotId {
template
class SlotVector {
- constexpr static std::size_t InitialCapacity = 1024;
+ constexpr static std::size_t InitialCapacity = 2048;
public:
+ SlotVector() {
+ Reserve(InitialCapacity);
+ }
+
~SlotVector() noexcept {
std::size_t index = 0;
for (u64 bits : stored_bitset) {
@@ -67,19 +71,6 @@ public:
return SlotId{index};
}
- template
- [[nodiscard]] SlotId swap_and_insert(SlotId existing_id, Args&&... args) noexcept {
- const u32 index = FreeValueIndex();
- T& existing_value = values[existing_id.index].object;
-
- new (&values[index].object) T(std::move(existing_value));
- existing_value.~T();
- new (&values[existing_id.index].object) T(std::forward(args)...);
- SetStorageBit(index);
-
- return SlotId{index};
- }
-
void erase(SlotId id) noexcept {
values[id.index].object.~T();
free_list.push_back(id.index);
@@ -151,7 +142,8 @@ private:
const std::size_t old_free_size = free_list.size();
free_list.resize(old_free_size + (new_capacity - values_capacity));
- std::iota(free_list.begin() + old_free_size, free_list.end(),
+ const std::size_t new_free_size = free_list.size();
+ std::iota(free_list.rbegin(), free_list.rbegin() + new_free_size - old_free_size,
static_cast(values_capacity));
delete[] values;
diff --git a/src/common/uint128.h b/src/common/uint128.h
index c44357916..77c4a271d 100644
--- a/src/common/uint128.h
+++ b/src/common/uint128.h
@@ -94,7 +94,7 @@ namespace Common {
// This function divides a u128 by a u32 value and produces two u64 values:
// the result of division and the remainder
-[[nodiscard]] static inline std::pair Divide128On32(u128 dividend, u32 divisor) {
+[[nodiscard]] static inline std::pair Divide128On32(const u128& dividend, u32 divisor) {
u64 remainder = dividend[0] % divisor;
u64 accum = dividend[0] / divisor;
if (dividend[1] == 0)
diff --git a/src/core/address_space.cpp b/src/core/address_space.cpp
index dec761ba9..9dddf1d86 100644
--- a/src/core/address_space.cpp
+++ b/src/core/address_space.cpp
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include
+#include "common/alignment.h"
#include "common/assert.h"
#include "common/error.h"
#include "core/address_space.h"
@@ -130,9 +131,10 @@ struct AddressSpace::Impl {
}
void* Map(VAddr virtual_addr, PAddr phys_addr, size_t size, ULONG prot, uintptr_t fd = 0) {
+ const size_t aligned_size = Common::AlignUp(size, 16_KB);
const auto it = placeholders.find(virtual_addr);
ASSERT_MSG(it != placeholders.end(), "Cannot map already mapped region");
- ASSERT_MSG(virtual_addr >= it->lower() && virtual_addr + size <= it->upper(),
+ ASSERT_MSG(virtual_addr >= it->lower() && virtual_addr + aligned_size <= it->upper(),
"Map range must be fully contained in a placeholder");
// Windows only allows splitting a placeholder into two.
@@ -141,7 +143,7 @@ struct AddressSpace::Impl {
// one at the start and at the end.
const VAddr placeholder_start = it->lower();
const VAddr placeholder_end = it->upper();
- const VAddr virtual_end = virtual_addr + size;
+ const VAddr virtual_end = virtual_addr + aligned_size;
// If the placeholder doesn't exactly start at virtual_addr, split it at the start.
if (placeholder_start != virtual_addr) {
@@ -162,11 +164,23 @@ struct AddressSpace::Impl {
void* ptr = nullptr;
if (phys_addr != -1) {
HANDLE backing = fd ? reinterpret_cast(fd) : backing_handle;
- ptr = MapViewOfFile3(backing, process, reinterpret_cast(virtual_addr), phys_addr,
- size, MEM_REPLACE_PLACEHOLDER, prot, nullptr, 0);
+ if (fd && prot == PAGE_READONLY) {
+ DWORD resultvar;
+ ptr = VirtualAlloc2(process, reinterpret_cast(virtual_addr), aligned_size,
+ MEM_RESERVE | MEM_COMMIT | MEM_REPLACE_PLACEHOLDER,
+ PAGE_READWRITE, nullptr, 0);
+ bool ret = ReadFile(backing, ptr, size, &resultvar, NULL);
+ ASSERT_MSG(ret, "ReadFile failed. {}", Common::GetLastErrorMsg());
+ ret = VirtualProtect(ptr, size, prot, &resultvar);
+ ASSERT_MSG(ret, "VirtualProtect failed. {}", Common::GetLastErrorMsg());
+ } else {
+ ptr = MapViewOfFile3(backing, process, reinterpret_cast(virtual_addr),
+ phys_addr, aligned_size, MEM_REPLACE_PLACEHOLDER, prot,
+ nullptr, 0);
+ }
} else {
ptr =
- VirtualAlloc2(process, reinterpret_cast(virtual_addr), size,
+ VirtualAlloc2(process, reinterpret_cast(virtual_addr), aligned_size,
MEM_RESERVE | MEM_COMMIT | MEM_REPLACE_PLACEHOLDER, prot, nullptr, 0);
}
ASSERT_MSG(ptr, "{}", Common::GetLastErrorMsg());
@@ -465,12 +479,12 @@ void* AddressSpace::MapFile(VAddr virtual_addr, size_t size, size_t offset, u32
}
void AddressSpace::Unmap(VAddr virtual_addr, size_t size, VAddr start_in_vma, VAddr end_in_vma,
- PAddr phys_base, bool is_exec, bool has_backing) {
+ PAddr phys_base, bool is_exec, bool has_backing, bool readonly_file) {
#ifdef _WIN32
// There does not appear to be comparable support for partial unmapping on Windows.
// Unfortunately, a least one title was found to require this. The workaround is to unmap
// the entire allocation and remap the portions outside of the requested unmapping range.
- impl->Unmap(virtual_addr, size, has_backing);
+ impl->Unmap(virtual_addr, size, has_backing && !readonly_file);
// TODO: Determine if any titles require partial unmapping support for flexible allocations.
ASSERT_MSG(has_backing || (start_in_vma == 0 && end_in_vma == size),
diff --git a/src/core/address_space.h b/src/core/address_space.h
index 53041bccb..2a3488d57 100644
--- a/src/core/address_space.h
+++ b/src/core/address_space.h
@@ -92,7 +92,7 @@ public:
/// Unmaps specified virtual memory area.
void Unmap(VAddr virtual_addr, size_t size, VAddr start_in_vma, VAddr end_in_vma,
- PAddr phys_base, bool is_exec, bool has_backing);
+ PAddr phys_base, bool is_exec, bool has_backing, bool readonly_file);
void Protect(VAddr virtual_addr, size_t size, MemoryPermission perms);
diff --git a/src/core/aerolib/aerolib.inl b/src/core/aerolib/aerolib.inl
index a87c3cc4e..64ee32ea2 100644
--- a/src/core/aerolib/aerolib.inl
+++ b/src/core/aerolib/aerolib.inl
@@ -114108,7 +114108,7 @@ STUB(
_ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_7Matches2V124RequestCompetitiveResultEE7add_refEv)
STUB("efPahl2FufA",
_ZN3sce2Np9CppWebApi30CommunicationRestrictionStatus2V35Error8fromJsonERKNS_4Json5ValueE)
-STUB("efX3lrPwdKA", sceAppContentAddcontMountByEntitlemetId)
+STUB("efX3lrPwdKA", sceAppContentAddcontMountByEntitlementId)
STUB("efXnxYFN5oE", _ZNSt11range_errorD0Ev)
STUB("efcwuDLsAM0", _ZThn120_NK7WebCore16HTMLMediaElement5mutedEv)
STUB("efhGArzWdxE", _ZN7bmalloc6IsoTLS15s_didInitializeE)
@@ -129493,7 +129493,7 @@ STUB(
STUB("kJlYH5uMAWI", sceNetResolverDestroy)
STUB("kJmdxo4uM+8",
_ZNSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE5_InitERKSt8_Locinfo)
-STUB("kJmjt81mXKQ", sceAppContentAddcontEnqueueDownloadByEntitlemetId)
+STUB("kJmjt81mXKQ", sceAppContentAddcontEnqueueDownloadByEntitlementId)
STUB(
"kJoY9lMIFzY",
_ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_21AdvancedPlayerProfile2V138MatchCompletionRateDisconnectedMetricsEEEEmmEi)
diff --git a/src/core/aerolib/stubs.cpp b/src/core/aerolib/stubs.cpp
index 5e2d55cdc..2634fc46a 100644
--- a/src/core/aerolib/stubs.cpp
+++ b/src/core/aerolib/stubs.cpp
@@ -13,7 +13,7 @@ namespace Core::AeroLib {
// on lookup, setting up the nid_entry they are matched with
//
// If it runs out of stubs with name information, it will return
-// a default implemetnation without function name details
+// a default implementation without function name details
// Up to 512, larger values lead to more resolve stub slots
// and to longer compile / CI times
diff --git a/src/core/cpu_patches.cpp b/src/core/cpu_patches.cpp
index 42318822b..151d34986 100644
--- a/src/core/cpu_patches.cpp
+++ b/src/core/cpu_patches.cpp
@@ -15,6 +15,7 @@
#else
#include
#ifdef __APPLE__
+#include
#include
#endif
#endif
@@ -30,6 +31,12 @@ static Xbyak::Reg ZydisToXbyakRegister(const ZydisRegister reg) {
if (reg >= ZYDIS_REGISTER_RAX && reg <= ZYDIS_REGISTER_R15) {
return Xbyak::Reg64(reg - ZYDIS_REGISTER_RAX + Xbyak::Operand::RAX);
}
+ if (reg >= ZYDIS_REGISTER_XMM0 && reg <= ZYDIS_REGISTER_XMM31) {
+ return Xbyak::Xmm(reg - ZYDIS_REGISTER_XMM0 + xmm0.getIdx());
+ }
+ if (reg >= ZYDIS_REGISTER_YMM0 && reg <= ZYDIS_REGISTER_YMM31) {
+ return Xbyak::Ymm(reg - ZYDIS_REGISTER_YMM0 + ymm0.getIdx());
+ }
UNREACHABLE_MSG("Unsupported register: {}", static_cast(reg));
}
@@ -66,6 +73,12 @@ static Xbyak::Address ZydisToXbyakMemoryOperand(const ZydisDecodedOperand& opera
return ptr[expression];
}
+static u64 ZydisToXbyakImmediateOperand(const ZydisDecodedOperand& operand) {
+ ASSERT_MSG(operand.type == ZYDIS_OPERAND_TYPE_IMMEDIATE,
+ "Expected immediate operand, got type: {}", static_cast(operand.type));
+ return operand.imm.value.u;
+}
+
static std::unique_ptr ZydisToXbyakOperand(const ZydisDecodedOperand& operand) {
switch (operand.type) {
case ZYDIS_OPERAND_TYPE_REGISTER: {
@@ -110,51 +123,127 @@ static Xbyak::Reg AllocateScratchRegister(
#ifdef __APPLE__
-static constexpr u32 MaxSavedRegisters = 3;
-static pthread_key_t register_save_slots[MaxSavedRegisters];
-static std::once_flag register_save_init_flag;
+static pthread_key_t stack_pointer_slot;
+static pthread_key_t patch_stack_slot;
+static std::once_flag patch_context_slots_init_flag;
+static constexpr u32 patch_stack_size = 0x1000;
static_assert(sizeof(void*) == sizeof(u64),
"Cannot fit a register inside a thread local storage slot.");
-static void InitializeRegisterSaveSlots() {
- for (u32 i = 0; i < MaxSavedRegisters; i++) {
- ASSERT_MSG(pthread_key_create(®ister_save_slots[i], nullptr) == 0,
- "Unable to allocate thread-local register save slot {}", i);
- }
+static void FreePatchStack(void* patch_stack) {
+ // Subtract back to the bottom of the stack for free.
+ std::free(static_cast(patch_stack) - patch_stack_size);
}
+static void InitializePatchContextSlots() {
+ ASSERT_MSG(pthread_key_create(&stack_pointer_slot, nullptr) == 0,
+ "Unable to allocate thread-local register for stack pointer.");
+ ASSERT_MSG(pthread_key_create(&patch_stack_slot, FreePatchStack) == 0,
+ "Unable to allocate thread-local register for patch stack.");
+}
+
+void InitializeThreadPatchStack() {
+ std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots);
+
+ pthread_setspecific(patch_stack_slot,
+ static_cast(std::malloc(patch_stack_size)) + patch_stack_size);
+}
+
+/// Saves the stack pointer to thread local storage and loads the patch stack.
+static void SaveStack(Xbyak::CodeGenerator& c) {
+ std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots);
+
+ // Save original stack pointer and load patch stack.
+ c.putSeg(gs);
+ c.mov(qword[reinterpret_cast(stack_pointer_slot * sizeof(void*))], rsp);
+ c.putSeg(gs);
+ c.mov(rsp, qword[reinterpret_cast(patch_stack_slot * sizeof(void*))]);
+}
+
+/// Restores the stack pointer from thread local storage.
+static void RestoreStack(Xbyak::CodeGenerator& c) {
+ std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots);
+
+ // Save patch stack pointer and load original stack.
+ c.putSeg(gs);
+ c.mov(qword[reinterpret_cast(patch_stack_slot * sizeof(void*))], rsp);
+ c.putSeg(gs);
+ c.mov(rsp, qword[reinterpret_cast(stack_pointer_slot * sizeof(void*))]);
+}
+
+#else
+
+// These utilities are not implemented as we can't save anything to thread local storage without
+// temporary registers.
+void InitializeThreadPatchStack() {
+ // No-op
+}
+
+/// Saves the stack pointer to thread local storage and loads the patch stack.
+static void SaveStack(Xbyak::CodeGenerator& c) {
+ UNIMPLEMENTED();
+}
+
+/// Restores the stack pointer from thread local storage.
+static void RestoreStack(Xbyak::CodeGenerator& c) {
+ UNIMPLEMENTED();
+}
+
+#endif
+
+/// Switches to the patch stack, saves registers, and restores the original stack.
static void SaveRegisters(Xbyak::CodeGenerator& c, const std::initializer_list regs) {
- ASSERT_MSG(regs.size() <= MaxSavedRegisters, "Not enough space to save {} registers.",
- regs.size());
-
- std::call_once(register_save_init_flag, &InitializeRegisterSaveSlots);
-
- u32 index = 0;
+ SaveStack(c);
for (const auto& reg : regs) {
- const auto offset = reinterpret_cast(register_save_slots[index++] * sizeof(void*));
-
- c.putSeg(gs);
- c.mov(qword[offset], reg.cvt64());
+ c.push(reg.cvt64());
}
+ RestoreStack(c);
}
+/// Switches to the patch stack, restores registers, and restores the original stack.
static void RestoreRegisters(Xbyak::CodeGenerator& c,
const std::initializer_list regs) {
- ASSERT_MSG(regs.size() <= MaxSavedRegisters, "Not enough space to restore {} registers.",
- regs.size());
-
- std::call_once(register_save_init_flag, &InitializeRegisterSaveSlots);
-
- u32 index = 0;
+ SaveStack(c);
for (const auto& reg : regs) {
- const auto offset = reinterpret_cast(register_save_slots[index++] * sizeof(void*));
+ c.pop(reg.cvt64());
+ }
+ RestoreStack(c);
+}
- c.putSeg(gs);
- c.mov(reg.cvt64(), qword[offset]);
+/// Switches to the patch stack and stores all registers.
+static void SaveContext(Xbyak::CodeGenerator& c) {
+ SaveStack(c);
+ for (int reg = Xbyak::Operand::RAX; reg <= Xbyak::Operand::R15; reg++) {
+ c.push(Xbyak::Reg64(reg));
+ }
+ for (int reg = 0; reg <= 7; reg++) {
+ c.sub(rsp, 32);
+ c.vmovdqu(ptr[rsp], Xbyak::Ymm(reg));
}
}
+/// Restores all registers and restores the original stack.
+/// If the destination is a register, it is not restored to preserve the output.
+static void RestoreContext(Xbyak::CodeGenerator& c, const Xbyak::Operand& dst) {
+ for (int reg = 7; reg >= 0; reg--) {
+ if ((!dst.isXMM() && !dst.isYMM()) || dst.getIdx() != reg) {
+ c.vmovdqu(Xbyak::Ymm(reg), ptr[rsp]);
+ }
+ c.add(rsp, 32);
+ }
+ for (int reg = Xbyak::Operand::R15; reg >= Xbyak::Operand::RAX; reg--) {
+ if (!dst.isREG() || dst.getIdx() != reg) {
+ c.pop(Xbyak::Reg64(reg));
+ } else {
+ c.add(rsp, 8);
+ }
+ }
+ RestoreStack(c);
+}
+
+#ifdef __APPLE__
+
static void GenerateANDN(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
const auto src1 = ZydisToXbyakRegisterOperand(operands[1]);
@@ -204,9 +293,9 @@ static void GenerateBEXTR(const ZydisDecodedOperand* operands, Xbyak::CodeGenera
c.and_(dst, scratch2);
if (dst.getIdx() == shift.getIdx()) {
- RestoreRegisters(c, {scratch1, scratch2});
+ RestoreRegisters(c, {scratch2, scratch1});
} else {
- RestoreRegisters(c, {scratch1, scratch2, shift});
+ RestoreRegisters(c, {shift, scratch2, scratch1});
}
}
@@ -258,10 +347,138 @@ static void GenerateBLSR(const ZydisDecodedOperand* operands, Xbyak::CodeGenerat
RestoreRegisters(c, {scratch});
}
-bool FilterRosetta2Only(const ZydisDecodedOperand*) {
+static __attribute__((sysv_abi)) void PerformVCVTPH2PS(float* out, const half_float::half* in,
+ const u32 count) {
+ for (u32 i = 0; i < count; i++) {
+ out[i] = half_float::half_cast(in[i]);
+ }
+}
+
+static void GenerateVCVTPH2PS(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
+ const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
+ const auto src = ZydisToXbyakOperand(operands[1]);
+
+ const auto float_count = dst.getBit() / 32;
+ const auto byte_count = float_count * 4;
+
+ SaveContext(c);
+
+ // Allocate stack space for outputs and load into first parameter.
+ c.sub(rsp, byte_count);
+ c.mov(rdi, rsp);
+
+ if (src->isXMM()) {
+ // Allocate stack space for inputs and load into second parameter.
+ c.sub(rsp, byte_count);
+ c.mov(rsi, rsp);
+
+ // Move input to the allocated space.
+ c.movdqu(ptr[rsp], *reinterpret_cast(src.get()));
+ } else {
+ c.lea(rsi, src->getAddress());
+ }
+
+ // Load float count into third parameter.
+ c.mov(rdx, float_count);
+
+ c.mov(rax, reinterpret_cast(PerformVCVTPH2PS));
+ c.call(rax);
+
+ if (src->isXMM()) {
+ // Clean up after inputs space.
+ c.add(rsp, byte_count);
+ }
+
+ // Load outputs into destination register and clean up space.
+ if (dst.isYMM()) {
+ c.vmovdqu(*reinterpret_cast(&dst), ptr[rsp]);
+ } else {
+ c.movdqu(*reinterpret_cast(&dst), ptr[rsp]);
+ }
+ c.add(rsp, byte_count);
+
+ RestoreContext(c, dst);
+}
+
+using SingleToHalfFloatConverter = half_float::half (*)(float);
+static const SingleToHalfFloatConverter SingleToHalfFloatConverters[4] = {
+ half_float::half_cast,
+ half_float::half_cast,
+ half_float::half_cast,
+ half_float::half_cast,
+};
+
+static __attribute__((sysv_abi)) void PerformVCVTPS2PH(half_float::half* out, const float* in,
+ const u32 count, const u8 rounding_mode) {
+ const auto conversion_func = SingleToHalfFloatConverters[rounding_mode];
+
+ for (u32 i = 0; i < count; i++) {
+ out[i] = conversion_func(in[i]);
+ }
+}
+
+static void GenerateVCVTPS2PH(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
+ const auto dst = ZydisToXbyakOperand(operands[0]);
+ const auto src = ZydisToXbyakRegisterOperand(operands[1]);
+ const auto ctrl = ZydisToXbyakImmediateOperand(operands[2]);
+
+ const auto float_count = src.getBit() / 32;
+ const auto byte_count = float_count * 4;
+
+ SaveContext(c);
+
+ if (dst->isXMM()) {
+ // Allocate stack space for outputs and load into first parameter.
+ c.sub(rsp, byte_count);
+ c.mov(rdi, rsp);
+ } else {
+ c.lea(rdi, dst->getAddress());
+ }
+
+ // Allocate stack space for inputs and load into second parameter.
+ c.sub(rsp, byte_count);
+ c.mov(rsi, rsp);
+
+ // Move input to the allocated space.
+ if (src.isYMM()) {
+ c.vmovdqu(ptr[rsp], *reinterpret_cast(&src));
+ } else {
+ c.movdqu(ptr[rsp], *reinterpret_cast(&src));
+ }
+
+ // Load float count into third parameter.
+ c.mov(rdx, float_count);
+
+ // Load rounding mode into fourth parameter.
+ if (ctrl & 4) {
+ // Load from MXCSR.RC.
+ c.stmxcsr(ptr[rsp - 4]);
+ c.mov(rcx, ptr[rsp - 4]);
+ c.shr(rcx, 13);
+ c.and_(rcx, 3);
+ } else {
+ c.mov(rcx, ctrl & 3);
+ }
+
+ c.mov(rax, reinterpret_cast(PerformVCVTPS2PH));
+ c.call(rax);
+
+ // Clean up after inputs space.
+ c.add(rsp, byte_count);
+
+ if (dst->isXMM()) {
+ // Load outputs into destination register and clean up space.
+ c.movdqu(*reinterpret_cast(dst.get()), ptr[rsp]);
+ c.add(rsp, byte_count);
+ }
+
+ RestoreContext(c, *dst);
+}
+
+static bool FilterRosetta2Only(const ZydisDecodedOperand*) {
int ret = 0;
size_t size = sizeof(ret);
- if (sysctlbyname("sysctl.proc_translated", &ret, &size, NULL, 0) != 0) {
+ if (sysctlbyname("sysctl.proc_translated", &ret, &size, nullptr, 0) != 0) {
return false;
}
return ret;
@@ -282,7 +499,6 @@ static bool FilterTcbAccess(const ZydisDecodedOperand* operands) {
static void GenerateTcbAccess(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
- const auto slot = GetTcbKey();
#if defined(_WIN32)
// The following logic is based on the Kernel32.dll asm of TlsGetValue
@@ -290,6 +506,8 @@ static void GenerateTcbAccess(const ZydisDecodedOperand* operands, Xbyak::CodeGe
static constexpr u32 TlsExpansionSlotsOffset = 0x1780;
static constexpr u32 TlsMinimumAvailable = 64;
+ const auto slot = GetTcbKey();
+
// Load the pointer to the table of TLS slots.
c.putSeg(gs);
if (slot < TlsMinimumAvailable) {
@@ -303,11 +521,6 @@ static void GenerateTcbAccess(const ZydisDecodedOperand* operands, Xbyak::CodeGe
// Load the pointer to our buffer.
c.mov(dst, qword[dst + tls_index * sizeof(LPVOID)]);
}
-#elif defined(__APPLE__)
- // The following logic is based on the Darwin implementation of _os_tsd_get_direct, used by
- // pthread_getspecific https://github.com/apple/darwin-xnu/blob/main/libsyscall/os/tsd.h#L89-L96
- c.putSeg(gs);
- c.mov(dst, qword[reinterpret_cast(slot * sizeof(void*))]);
#else
const auto src = ZydisToXbyakMemoryOperand(operands[1]);
@@ -331,20 +544,24 @@ struct PatchInfo {
};
static const std::unordered_map Patches = {
-#if defined(_WIN32) || defined(__APPLE__)
- // Windows and Apple need a trampoline.
+#if defined(_WIN32)
+ // Windows needs a trampoline.
{ZYDIS_MNEMONIC_MOV, {FilterTcbAccess, GenerateTcbAccess, true}},
-#else
+#elif !defined(__APPLE__)
{ZYDIS_MNEMONIC_MOV, {FilterTcbAccess, GenerateTcbAccess, false}},
#endif
#ifdef __APPLE__
- // BMI1 instructions that are not supported by Rosetta 2 on Apple Silicon.
+ // Patches for instruction sets not supported by Rosetta 2.
+ // BMI1
{ZYDIS_MNEMONIC_ANDN, {FilterRosetta2Only, GenerateANDN, true}},
{ZYDIS_MNEMONIC_BEXTR, {FilterRosetta2Only, GenerateBEXTR, true}},
{ZYDIS_MNEMONIC_BLSI, {FilterRosetta2Only, GenerateBLSI, true}},
{ZYDIS_MNEMONIC_BLSMSK, {FilterRosetta2Only, GenerateBLSMSK, true}},
{ZYDIS_MNEMONIC_BLSR, {FilterRosetta2Only, GenerateBLSR, true}},
+ // F16C
+ {ZYDIS_MNEMONIC_VCVTPH2PS, {FilterRosetta2Only, GenerateVCVTPH2PS, true}},
+ {ZYDIS_MNEMONIC_VCVTPS2PH, {FilterRosetta2Only, GenerateVCVTPS2PH, true}},
#endif
};
diff --git a/src/core/cpu_patches.h b/src/core/cpu_patches.h
index 45adbeda3..9126074ed 100644
--- a/src/core/cpu_patches.h
+++ b/src/core/cpu_patches.h
@@ -9,6 +9,12 @@ class CodeGenerator;
namespace Core {
+/// Initializes a stack for the current thread for use by patch implementations.
+void InitializeThreadPatchStack();
+
+/// Cleans up the patch stack for the current thread.
+void CleanupThreadPatchStack();
+
/// Patches CPU instructions that cannot run as-is on the host.
void PatchInstructions(u64 segment_addr, u64 segment_size, Xbyak::CodeGenerator& c);
diff --git a/src/core/crypto/crypto.cpp b/src/core/crypto/crypto.cpp
index 630faa344..aa1c96724 100644
--- a/src/core/crypto/crypto.cpp
+++ b/src/core/crypto/crypto.cpp
@@ -6,18 +6,18 @@
CryptoPP::RSA::PrivateKey Crypto::key_pkg_derived_key3_keyset_init() {
CryptoPP::InvertibleRSAFunction params;
- params.SetPrime1(CryptoPP::Integer(pkg_derived_key3_keyset.Prime1, 0x80));
- params.SetPrime2(CryptoPP::Integer(pkg_derived_key3_keyset.Prime2, 0x80));
+ params.SetPrime1(CryptoPP::Integer(PkgDerivedKey3Keyset::Prime1, 0x80));
+ params.SetPrime2(CryptoPP::Integer(PkgDerivedKey3Keyset::Prime2, 0x80));
- params.SetPublicExponent(CryptoPP::Integer(pkg_derived_key3_keyset.PublicExponent, 4));
- params.SetPrivateExponent(CryptoPP::Integer(pkg_derived_key3_keyset.PrivateExponent, 0x100));
+ params.SetPublicExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::PublicExponent, 4));
+ params.SetPrivateExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::PrivateExponent, 0x100));
- params.SetModPrime1PrivateExponent(CryptoPP::Integer(pkg_derived_key3_keyset.Exponent1, 0x80));
- params.SetModPrime2PrivateExponent(CryptoPP::Integer(pkg_derived_key3_keyset.Exponent2, 0x80));
+ params.SetModPrime1PrivateExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::Exponent1, 0x80));
+ params.SetModPrime2PrivateExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::Exponent2, 0x80));
- params.SetModulus(CryptoPP::Integer(pkg_derived_key3_keyset.Modulus, 0x100));
+ params.SetModulus(CryptoPP::Integer(PkgDerivedKey3Keyset::Modulus, 0x100));
params.SetMultiplicativeInverseOfPrime2ModPrime1(
- CryptoPP::Integer(pkg_derived_key3_keyset.Coefficient, 0x80));
+ CryptoPP::Integer(PkgDerivedKey3Keyset::Coefficient, 0x80));
CryptoPP::RSA::PrivateKey privateKey(params);
@@ -26,18 +26,18 @@ CryptoPP::RSA::PrivateKey Crypto::key_pkg_derived_key3_keyset_init() {
CryptoPP::RSA::PrivateKey Crypto::FakeKeyset_keyset_init() {
CryptoPP::InvertibleRSAFunction params;
- params.SetPrime1(CryptoPP::Integer(FakeKeyset_keyset.Prime1, 0x80));
- params.SetPrime2(CryptoPP::Integer(FakeKeyset_keyset.Prime2, 0x80));
+ params.SetPrime1(CryptoPP::Integer(FakeKeyset::Prime1, 0x80));
+ params.SetPrime2(CryptoPP::Integer(FakeKeyset::Prime2, 0x80));
- params.SetPublicExponent(CryptoPP::Integer(FakeKeyset_keyset.PublicExponent, 4));
- params.SetPrivateExponent(CryptoPP::Integer(FakeKeyset_keyset.PrivateExponent, 0x100));
+ params.SetPublicExponent(CryptoPP::Integer(FakeKeyset::PublicExponent, 4));
+ params.SetPrivateExponent(CryptoPP::Integer(FakeKeyset::PrivateExponent, 0x100));
- params.SetModPrime1PrivateExponent(CryptoPP::Integer(FakeKeyset_keyset.Exponent1, 0x80));
- params.SetModPrime2PrivateExponent(CryptoPP::Integer(FakeKeyset_keyset.Exponent2, 0x80));
+ params.SetModPrime1PrivateExponent(CryptoPP::Integer(FakeKeyset::Exponent1, 0x80));
+ params.SetModPrime2PrivateExponent(CryptoPP::Integer(FakeKeyset::Exponent2, 0x80));
- params.SetModulus(CryptoPP::Integer(FakeKeyset_keyset.Modulus, 0x100));
+ params.SetModulus(CryptoPP::Integer(FakeKeyset::Modulus, 0x100));
params.SetMultiplicativeInverseOfPrime2ModPrime1(
- CryptoPP::Integer(FakeKeyset_keyset.Coefficient, 0x80));
+ CryptoPP::Integer(FakeKeyset::Coefficient, 0x80));
CryptoPP::RSA::PrivateKey privateKey(params);
@@ -46,25 +46,22 @@ CryptoPP::RSA::PrivateKey Crypto::FakeKeyset_keyset_init() {
CryptoPP::RSA::PrivateKey Crypto::DebugRifKeyset_init() {
CryptoPP::InvertibleRSAFunction params;
- params.SetPrime1(
- CryptoPP::Integer(DebugRifKeyset_keyset.Prime1, sizeof(DebugRifKeyset_keyset.Prime1)));
- params.SetPrime2(
- CryptoPP::Integer(DebugRifKeyset_keyset.Prime2, sizeof(DebugRifKeyset_keyset.Prime2)));
+ params.SetPrime1(CryptoPP::Integer(DebugRifKeyset::Prime1, sizeof(DebugRifKeyset::Prime1)));
+ params.SetPrime2(CryptoPP::Integer(DebugRifKeyset::Prime2, sizeof(DebugRifKeyset::Prime2)));
- params.SetPublicExponent(CryptoPP::Integer(DebugRifKeyset_keyset.PrivateExponent,
- sizeof(DebugRifKeyset_keyset.PrivateExponent)));
- params.SetPrivateExponent(CryptoPP::Integer(DebugRifKeyset_keyset.PrivateExponent,
- sizeof(DebugRifKeyset_keyset.PrivateExponent)));
+ params.SetPublicExponent(
+ CryptoPP::Integer(DebugRifKeyset::PublicExponent, sizeof(DebugRifKeyset::PublicExponent)));
+ params.SetPrivateExponent(CryptoPP::Integer(DebugRifKeyset::PrivateExponent,
+ sizeof(DebugRifKeyset::PrivateExponent)));
- params.SetModPrime1PrivateExponent(CryptoPP::Integer(DebugRifKeyset_keyset.Exponent1,
- sizeof(DebugRifKeyset_keyset.Exponent1)));
- params.SetModPrime2PrivateExponent(CryptoPP::Integer(DebugRifKeyset_keyset.Exponent2,
- sizeof(DebugRifKeyset_keyset.Exponent2)));
+ params.SetModPrime1PrivateExponent(
+ CryptoPP::Integer(DebugRifKeyset::Exponent1, sizeof(DebugRifKeyset::Exponent1)));
+ params.SetModPrime2PrivateExponent(
+ CryptoPP::Integer(DebugRifKeyset::Exponent2, sizeof(DebugRifKeyset::Exponent2)));
- params.SetModulus(
- CryptoPP::Integer(DebugRifKeyset_keyset.Modulus, sizeof(DebugRifKeyset_keyset.Modulus)));
- params.SetMultiplicativeInverseOfPrime2ModPrime1(CryptoPP::Integer(
- DebugRifKeyset_keyset.Coefficient, sizeof(DebugRifKeyset_keyset.Coefficient)));
+ params.SetModulus(CryptoPP::Integer(DebugRifKeyset::Modulus, sizeof(DebugRifKeyset::Modulus)));
+ params.SetMultiplicativeInverseOfPrime2ModPrime1(
+ CryptoPP::Integer(DebugRifKeyset::Coefficient, sizeof(DebugRifKeyset::Coefficient)));
CryptoPP::RSA::PrivateKey privateKey(params);
diff --git a/src/core/crypto/crypto.h b/src/core/crypto/crypto.h
index 0c5bc9955..83249bd7d 100644
--- a/src/core/crypto/crypto.h
+++ b/src/core/crypto/crypto.h
@@ -17,10 +17,6 @@
class Crypto {
public:
- PkgDerivedKey3Keyset pkg_derived_key3_keyset;
- FakeKeyset FakeKeyset_keyset;
- DebugRifKeyset DebugRifKeyset_keyset;
-
CryptoPP::RSA::PrivateKey key_pkg_derived_key3_keyset_init();
CryptoPP::RSA::PrivateKey FakeKeyset_keyset_init();
CryptoPP::RSA::PrivateKey DebugRifKeyset_init();
diff --git a/src/core/crypto/keys.h b/src/core/crypto/keys.h
index 37b66bd09..441082481 100644
--- a/src/core/crypto/keys.h
+++ b/src/core/crypto/keys.h
@@ -7,384 +7,299 @@
class FakeKeyset {
public:
// Constructor
- const CryptoPP::byte* Exponent1;
+ static constexpr CryptoPP::byte Exponent1[] = {
+ 0x6D, 0x48, 0xE0, 0x54, 0x40, 0x25, 0xC8, 0x41, 0x29, 0x52, 0x42, 0x27, 0xEB, 0xD2, 0xC7,
+ 0xAB, 0x6B, 0x9C, 0x27, 0x0A, 0xB4, 0x1F, 0x94, 0x4E, 0xFA, 0x42, 0x1D, 0xB7, 0xBC, 0xB9,
+ 0xAE, 0xBC, 0x04, 0x6F, 0x75, 0x8F, 0x10, 0x5F, 0x89, 0xAC, 0xAB, 0x9C, 0xD2, 0xFA, 0xE6,
+ 0xA4, 0x13, 0x83, 0x68, 0xD4, 0x56, 0x38, 0xFE, 0xE5, 0x2B, 0x78, 0x44, 0x9C, 0x34, 0xE6,
+ 0x5A, 0xA0, 0xBE, 0x05, 0x70, 0xAD, 0x15, 0xC3, 0x2D, 0x31, 0xAC, 0x97, 0x5D, 0x88, 0xFC,
+ 0xC1, 0x62, 0x3D, 0xE2, 0xED, 0x11, 0xDB, 0xB6, 0x9E, 0xFC, 0x5A, 0x5A, 0x03, 0xF6, 0xCF,
+ 0x08, 0xD4, 0x5D, 0x90, 0xC9, 0x2A, 0xB9, 0x9B, 0xCF, 0xC8, 0x1A, 0x65, 0xF3, 0x5B, 0xE8,
+ 0x7F, 0xCF, 0xA5, 0xA6, 0x4C, 0x5C, 0x2A, 0x12, 0x0F, 0x92, 0xA5, 0xE3, 0xF0, 0x17, 0x1E,
+ 0x9A, 0x97, 0x45, 0x86, 0xFD, 0xDB, 0x54, 0x25};
// exponent2 = d mod (q - 1)
- const CryptoPP::byte* Exponent2;
+ static constexpr CryptoPP::byte Exponent2[] = {
+ 0x2A, 0x51, 0xCE, 0x02, 0x44, 0x28, 0x50, 0xE8, 0x30, 0x20, 0x7C, 0x9C, 0x55, 0xBF, 0x60,
+ 0x39, 0xBC, 0xD1, 0xF0, 0xE7, 0x68, 0xF8, 0x08, 0x5B, 0x61, 0x1F, 0xA7, 0xBF, 0xD0, 0xE8,
+ 0x8B, 0xB5, 0xB1, 0xD5, 0xD9, 0x16, 0xAC, 0x75, 0x0C, 0x6D, 0xF2, 0xE0, 0xB5, 0x97, 0x75,
+ 0xD2, 0x68, 0x16, 0x1F, 0x00, 0x7D, 0x8B, 0x17, 0xE8, 0x78, 0x48, 0x41, 0x71, 0x2B, 0x18,
+ 0x96, 0x80, 0x11, 0xDB, 0x68, 0x39, 0x9C, 0xD6, 0xE0, 0x72, 0x42, 0x86, 0xF0, 0x1B, 0x16,
+ 0x0D, 0x3E, 0x12, 0x94, 0x3D, 0x25, 0xA8, 0xA9, 0x30, 0x9E, 0x54, 0x5A, 0xD6, 0x36, 0x6C,
+ 0xD6, 0x8C, 0x20, 0x62, 0x8F, 0xA1, 0x6B, 0x1F, 0x7C, 0x6D, 0xB2, 0xB1, 0xC1, 0x2E, 0xAD,
+ 0x36, 0x02, 0x9C, 0x3A, 0xCA, 0x2F, 0x09, 0xD2, 0x45, 0x9E, 0xEB, 0xF2, 0xBC, 0x6C, 0xAA,
+ 0x3B, 0x3E, 0x90, 0xBC, 0x38, 0x67, 0x35, 0x4D};
// e
- const CryptoPP::byte* PublicExponent;
+ static constexpr CryptoPP::byte PublicExponent[] = {0, 1, 0, 1};
// (InverseQ)(q) = 1 mod p
- const CryptoPP::byte* Coefficient;
+ static constexpr CryptoPP::byte Coefficient[] = {
+ 0x0B, 0x67, 0x1C, 0x0D, 0x6C, 0x57, 0xD3, 0xE7, 0x05, 0x65, 0x94, 0x31, 0x56, 0x55, 0xFD,
+ 0x28, 0x08, 0xFA, 0x05, 0x8A, 0xCC, 0x55, 0x39, 0x61, 0x97, 0x63, 0xA0, 0x16, 0x27, 0x3D,
+ 0xED, 0xC1, 0x16, 0x40, 0x2A, 0x12, 0xEA, 0x6F, 0xD9, 0xD8, 0x58, 0x56, 0xA8, 0x56, 0x8B,
+ 0x0D, 0x38, 0x5E, 0x1E, 0x80, 0x3B, 0x5F, 0x40, 0x80, 0x6F, 0x62, 0x4F, 0x28, 0xA2, 0x69,
+ 0xF3, 0xD3, 0xF7, 0xFD, 0xB2, 0xC3, 0x52, 0x43, 0x20, 0x92, 0x9D, 0x97, 0x8D, 0xA0, 0x15,
+ 0x07, 0x15, 0x6E, 0xA4, 0x0D, 0x56, 0xD3, 0x37, 0x1A, 0xC4, 0x9E, 0xDF, 0x02, 0x49, 0xB8,
+ 0x0A, 0x84, 0x62, 0xF5, 0xFA, 0xB9, 0x3F, 0xA4, 0x09, 0x76, 0xCC, 0xAA, 0xB9, 0x9B, 0xA6,
+ 0x4F, 0xC1, 0x6A, 0x64, 0xCE, 0xD8, 0x77, 0xAB, 0x4B, 0xF9, 0xA0, 0xAE, 0xDA, 0xF1, 0x67,
+ 0x87, 0x7C, 0x98, 0x5C, 0x7E, 0xB8, 0x73, 0xF5};
// n = p * q
- const CryptoPP::byte* Modulus;
+ static constexpr CryptoPP::byte Modulus[] = {
+ 0xC6, 0xCF, 0x71, 0xE7, 0xE5, 0x9A, 0xF0, 0xD1, 0x2A, 0x2C, 0x45, 0x8B, 0xF9, 0x2A, 0x0E,
+ 0xC1, 0x43, 0x05, 0x8B, 0xC3, 0x71, 0x17, 0x80, 0x1D, 0xCD, 0x49, 0x7D, 0xDE, 0x35, 0x9D,
+ 0x25, 0x9B, 0xA0, 0xD7, 0xA0, 0xF2, 0x7D, 0x6C, 0x08, 0x7E, 0xAA, 0x55, 0x02, 0x68, 0x2B,
+ 0x23, 0xC6, 0x44, 0xB8, 0x44, 0x18, 0xEB, 0x56, 0xCF, 0x16, 0xA2, 0x48, 0x03, 0xC9, 0xE7,
+ 0x4F, 0x87, 0xEB, 0x3D, 0x30, 0xC3, 0x15, 0x88, 0xBF, 0x20, 0xE7, 0x9D, 0xFF, 0x77, 0x0C,
+ 0xDE, 0x1D, 0x24, 0x1E, 0x63, 0xA9, 0x4F, 0x8A, 0xBF, 0x5B, 0xBE, 0x60, 0x19, 0x68, 0x33,
+ 0x3B, 0xFC, 0xED, 0x9F, 0x47, 0x4E, 0x5F, 0xF8, 0xEA, 0xCB, 0x3D, 0x00, 0xBD, 0x67, 0x01,
+ 0xF9, 0x2C, 0x6D, 0xC6, 0xAC, 0x13, 0x64, 0xE7, 0x67, 0x14, 0xF3, 0xDC, 0x52, 0x69, 0x6A,
+ 0xB9, 0x83, 0x2C, 0x42, 0x30, 0x13, 0x1B, 0xB2, 0xD8, 0xA5, 0x02, 0x0D, 0x79, 0xED, 0x96,
+ 0xB1, 0x0D, 0xF8, 0xCC, 0x0C, 0xDF, 0x81, 0x95, 0x4F, 0x03, 0x58, 0x09, 0x57, 0x0E, 0x80,
+ 0x69, 0x2E, 0xFE, 0xFF, 0x52, 0x77, 0xEA, 0x75, 0x28, 0xA8, 0xFB, 0xC9, 0xBE, 0xBF, 0x9F,
+ 0xBB, 0xB7, 0x79, 0x8E, 0x18, 0x05, 0xE1, 0x80, 0xBD, 0x50, 0x34, 0x94, 0x81, 0xD3, 0x53,
+ 0xC2, 0x69, 0xA2, 0xD2, 0x4C, 0xCF, 0x6C, 0xF4, 0x57, 0x2C, 0x10, 0x4A, 0x3F, 0xFB, 0x22,
+ 0xFD, 0x8B, 0x97, 0xE2, 0xC9, 0x5B, 0xA6, 0x2B, 0xCD, 0xD6, 0x1B, 0x6B, 0xDB, 0x68, 0x7F,
+ 0x4B, 0xC2, 0xA0, 0x50, 0x34, 0xC0, 0x05, 0xE5, 0x8D, 0xEF, 0x24, 0x67, 0xFF, 0x93, 0x40,
+ 0xCF, 0x2D, 0x62, 0xA2, 0xA0, 0x50, 0xB1, 0xF1, 0x3A, 0xA8, 0x3D, 0xFD, 0x80, 0xD1, 0xF9,
+ 0xB8, 0x05, 0x22, 0xAF, 0xC8, 0x35, 0x45, 0x90, 0x58, 0x8E, 0xE3, 0x3A, 0x7C, 0xBD, 0x3E,
+ 0x27};
// p
- const CryptoPP::byte* Prime1;
+ static constexpr CryptoPP::byte Prime1[] = {
+ 0xFE, 0xF6, 0xBF, 0x1D, 0x69, 0xAB, 0x16, 0x25, 0x08, 0x47, 0x55, 0x6B, 0x86, 0xE4, 0x35,
+ 0x88, 0x72, 0x2A, 0xB1, 0x3D, 0xF8, 0xB6, 0x44, 0xCA, 0xB3, 0xAB, 0x19, 0xD1, 0x04, 0x24,
+ 0x28, 0x0A, 0x74, 0x55, 0xB8, 0x15, 0x45, 0x09, 0xCC, 0x13, 0x1C, 0xF2, 0xBA, 0x37, 0xA9,
+ 0x03, 0x90, 0x8F, 0x02, 0x10, 0xFF, 0x25, 0x79, 0x86, 0xCC, 0x18, 0x50, 0x9A, 0x10, 0x5F,
+ 0x5B, 0x4C, 0x1C, 0x4E, 0xB0, 0xA7, 0xE3, 0x59, 0xB1, 0x2D, 0xA0, 0xC6, 0xB0, 0x20, 0x2C,
+ 0x21, 0x33, 0x12, 0xB3, 0xAF, 0x72, 0x34, 0x83, 0xCD, 0x52, 0x2F, 0xAF, 0x0F, 0x20, 0x5A,
+ 0x1B, 0xC0, 0xE2, 0xA3, 0x76, 0x34, 0x0F, 0xD7, 0xFC, 0xC1, 0x41, 0xC9, 0xF9, 0x79, 0x40,
+ 0x17, 0x42, 0x21, 0x3E, 0x9D, 0xFD, 0xC7, 0xC1, 0x50, 0xDE, 0x44, 0x5A, 0xC9, 0x31, 0x89,
+ 0x6A, 0x78, 0x05, 0xBE, 0x65, 0xB4, 0xE8, 0x2D};
// q
- const CryptoPP::byte* Prime2;
- const CryptoPP::byte* PrivateExponent;
-
- // Constructor
- FakeKeyset() {
- // Initialize PrivateExponent
- PrivateExponent = new CryptoPP::byte[0x100]{
- 0x7F, 0x76, 0xCD, 0x0E, 0xE2, 0xD4, 0xDE, 0x05, 0x1C, 0xC6, 0xD9, 0xA8, 0x0E, 0x8D,
- 0xFA, 0x7B, 0xCA, 0x1E, 0xAA, 0x27, 0x1A, 0x40, 0xF8, 0xF1, 0x22, 0x87, 0x35, 0xDD,
- 0xDB, 0xFD, 0xEE, 0xF8, 0xC2, 0xBC, 0xBD, 0x01, 0xFB, 0x8B, 0xE2, 0x3E, 0x63, 0xB2,
- 0xB1, 0x22, 0x5C, 0x56, 0x49, 0x6E, 0x11, 0xBE, 0x07, 0x44, 0x0B, 0x9A, 0x26, 0x66,
- 0xD1, 0x49, 0x2C, 0x8F, 0xD3, 0x1B, 0xCF, 0xA4, 0xA1, 0xB8, 0xD1, 0xFB, 0xA4, 0x9E,
- 0xD2, 0x21, 0x28, 0x83, 0x09, 0x8A, 0xF6, 0xA0, 0x0B, 0xA3, 0xD6, 0x0F, 0x9B, 0x63,
- 0x68, 0xCC, 0xBC, 0x0C, 0x4E, 0x14, 0x5B, 0x27, 0xA4, 0xA9, 0xF4, 0x2B, 0xB9, 0xB8,
- 0x7B, 0xC0, 0xE6, 0x51, 0xAD, 0x1D, 0x77, 0xD4, 0x6B, 0xB9, 0xCE, 0x20, 0xD1, 0x26,
- 0x66, 0x7E, 0x5E, 0x9E, 0xA2, 0xE9, 0x6B, 0x90, 0xF3, 0x73, 0xB8, 0x52, 0x8F, 0x44,
- 0x11, 0x03, 0x0C, 0x13, 0x97, 0x39, 0x3D, 0x13, 0x22, 0x58, 0xD5, 0x43, 0x82, 0x49,
- 0xDA, 0x6E, 0x7C, 0xA1, 0xC5, 0x8C, 0xA5, 0xB0, 0x09, 0xE0, 0xCE, 0x3D, 0xDF, 0xF4,
- 0x9D, 0x3C, 0x97, 0x15, 0xE2, 0x6A, 0xC7, 0x2B, 0x3C, 0x50, 0x93, 0x23, 0xDB, 0xBA,
- 0x4A, 0x22, 0x66, 0x44, 0xAC, 0x78, 0xBB, 0x0E, 0x1A, 0x27, 0x43, 0xB5, 0x71, 0x67,
- 0xAF, 0xF4, 0xAB, 0x48, 0x46, 0x93, 0x73, 0xD0, 0x42, 0xAB, 0x93, 0x63, 0xE5, 0x6C,
- 0x9A, 0xDE, 0x50, 0x24, 0xC0, 0x23, 0x7D, 0x99, 0x79, 0x3F, 0x22, 0x07, 0xE0, 0xC1,
- 0x48, 0x56, 0x1B, 0xDF, 0x83, 0x09, 0x12, 0xB4, 0x2D, 0x45, 0x6B, 0xC9, 0xC0, 0x68,
- 0x85, 0x99, 0x90, 0x79, 0x96, 0x1A, 0xD7, 0xF5, 0x4D, 0x1F, 0x37, 0x83, 0x40, 0x4A,
- 0xEC, 0x39, 0x37, 0xA6, 0x80, 0x92, 0x7D, 0xC5, 0x80, 0xC7, 0xD6, 0x6F, 0xFE, 0x8A,
- 0x79, 0x89, 0xC6, 0xB1};
-
- // Initialize Exponent1
- Exponent1 = new CryptoPP::byte[0x80]{
- 0x6D, 0x48, 0xE0, 0x54, 0x40, 0x25, 0xC8, 0x41, 0x29, 0x52, 0x42, 0x27, 0xEB,
- 0xD2, 0xC7, 0xAB, 0x6B, 0x9C, 0x27, 0x0A, 0xB4, 0x1F, 0x94, 0x4E, 0xFA, 0x42,
- 0x1D, 0xB7, 0xBC, 0xB9, 0xAE, 0xBC, 0x04, 0x6F, 0x75, 0x8F, 0x10, 0x5F, 0x89,
- 0xAC, 0xAB, 0x9C, 0xD2, 0xFA, 0xE6, 0xA4, 0x13, 0x83, 0x68, 0xD4, 0x56, 0x38,
- 0xFE, 0xE5, 0x2B, 0x78, 0x44, 0x9C, 0x34, 0xE6, 0x5A, 0xA0, 0xBE, 0x05, 0x70,
- 0xAD, 0x15, 0xC3, 0x2D, 0x31, 0xAC, 0x97, 0x5D, 0x88, 0xFC, 0xC1, 0x62, 0x3D,
- 0xE2, 0xED, 0x11, 0xDB, 0xB6, 0x9E, 0xFC, 0x5A, 0x5A, 0x03, 0xF6, 0xCF, 0x08,
- 0xD4, 0x5D, 0x90, 0xC9, 0x2A, 0xB9, 0x9B, 0xCF, 0xC8, 0x1A, 0x65, 0xF3, 0x5B,
- 0xE8, 0x7F, 0xCF, 0xA5, 0xA6, 0x4C, 0x5C, 0x2A, 0x12, 0x0F, 0x92, 0xA5, 0xE3,
- 0xF0, 0x17, 0x1E, 0x9A, 0x97, 0x45, 0x86, 0xFD, 0xDB, 0x54, 0x25
-
- };
-
- Exponent2 = new CryptoPP::byte[0x80]{
- 0x2A, 0x51, 0xCE, 0x02, 0x44, 0x28, 0x50, 0xE8, 0x30, 0x20, 0x7C, 0x9C, 0x55,
- 0xBF, 0x60, 0x39, 0xBC, 0xD1, 0xF0, 0xE7, 0x68, 0xF8, 0x08, 0x5B, 0x61, 0x1F,
- 0xA7, 0xBF, 0xD0, 0xE8, 0x8B, 0xB5, 0xB1, 0xD5, 0xD9, 0x16, 0xAC, 0x75, 0x0C,
- 0x6D, 0xF2, 0xE0, 0xB5, 0x97, 0x75, 0xD2, 0x68, 0x16, 0x1F, 0x00, 0x7D, 0x8B,
- 0x17, 0xE8, 0x78, 0x48, 0x41, 0x71, 0x2B, 0x18, 0x96, 0x80, 0x11, 0xDB, 0x68,
- 0x39, 0x9C, 0xD6, 0xE0, 0x72, 0x42, 0x86, 0xF0, 0x1B, 0x16, 0x0D, 0x3E, 0x12,
- 0x94, 0x3D, 0x25, 0xA8, 0xA9, 0x30, 0x9E, 0x54, 0x5A, 0xD6, 0x36, 0x6C, 0xD6,
- 0x8C, 0x20, 0x62, 0x8F, 0xA1, 0x6B, 0x1F, 0x7C, 0x6D, 0xB2, 0xB1, 0xC1, 0x2E,
- 0xAD, 0x36, 0x02, 0x9C, 0x3A, 0xCA, 0x2F, 0x09, 0xD2, 0x45, 0x9E, 0xEB, 0xF2,
- 0xBC, 0x6C, 0xAA, 0x3B, 0x3E, 0x90, 0xBC, 0x38, 0x67, 0x35, 0x4D};
-
- PublicExponent = new CryptoPP::byte[4]{0, 1, 0, 1};
-
- Coefficient = new CryptoPP::byte[0x80]{
- 0x0B, 0x67, 0x1C, 0x0D, 0x6C, 0x57, 0xD3, 0xE7, 0x05, 0x65, 0x94, 0x31, 0x56,
- 0x55, 0xFD, 0x28, 0x08, 0xFA, 0x05, 0x8A, 0xCC, 0x55, 0x39, 0x61, 0x97, 0x63,
- 0xA0, 0x16, 0x27, 0x3D, 0xED, 0xC1, 0x16, 0x40, 0x2A, 0x12, 0xEA, 0x6F, 0xD9,
- 0xD8, 0x58, 0x56, 0xA8, 0x56, 0x8B, 0x0D, 0x38, 0x5E, 0x1E, 0x80, 0x3B, 0x5F,
- 0x40, 0x80, 0x6F, 0x62, 0x4F, 0x28, 0xA2, 0x69, 0xF3, 0xD3, 0xF7, 0xFD, 0xB2,
- 0xC3, 0x52, 0x43, 0x20, 0x92, 0x9D, 0x97, 0x8D, 0xA0, 0x15, 0x07, 0x15, 0x6E,
- 0xA4, 0x0D, 0x56, 0xD3, 0x37, 0x1A, 0xC4, 0x9E, 0xDF, 0x02, 0x49, 0xB8, 0x0A,
- 0x84, 0x62, 0xF5, 0xFA, 0xB9, 0x3F, 0xA4, 0x09, 0x76, 0xCC, 0xAA, 0xB9, 0x9B,
- 0xA6, 0x4F, 0xC1, 0x6A, 0x64, 0xCE, 0xD8, 0x77, 0xAB, 0x4B, 0xF9, 0xA0, 0xAE,
- 0xDA, 0xF1, 0x67, 0x87, 0x7C, 0x98, 0x5C, 0x7E, 0xB8, 0x73, 0xF5};
-
- Modulus = new CryptoPP::byte[0x100]{
- 0xC6, 0xCF, 0x71, 0xE7, 0xE5, 0x9A, 0xF0, 0xD1, 0x2A, 0x2C, 0x45, 0x8B, 0xF9, 0x2A,
- 0x0E, 0xC1, 0x43, 0x05, 0x8B, 0xC3, 0x71, 0x17, 0x80, 0x1D, 0xCD, 0x49, 0x7D, 0xDE,
- 0x35, 0x9D, 0x25, 0x9B, 0xA0, 0xD7, 0xA0, 0xF2, 0x7D, 0x6C, 0x08, 0x7E, 0xAA, 0x55,
- 0x02, 0x68, 0x2B, 0x23, 0xC6, 0x44, 0xB8, 0x44, 0x18, 0xEB, 0x56, 0xCF, 0x16, 0xA2,
- 0x48, 0x03, 0xC9, 0xE7, 0x4F, 0x87, 0xEB, 0x3D, 0x30, 0xC3, 0x15, 0x88, 0xBF, 0x20,
- 0xE7, 0x9D, 0xFF, 0x77, 0x0C, 0xDE, 0x1D, 0x24, 0x1E, 0x63, 0xA9, 0x4F, 0x8A, 0xBF,
- 0x5B, 0xBE, 0x60, 0x19, 0x68, 0x33, 0x3B, 0xFC, 0xED, 0x9F, 0x47, 0x4E, 0x5F, 0xF8,
- 0xEA, 0xCB, 0x3D, 0x00, 0xBD, 0x67, 0x01, 0xF9, 0x2C, 0x6D, 0xC6, 0xAC, 0x13, 0x64,
- 0xE7, 0x67, 0x14, 0xF3, 0xDC, 0x52, 0x69, 0x6A, 0xB9, 0x83, 0x2C, 0x42, 0x30, 0x13,
- 0x1B, 0xB2, 0xD8, 0xA5, 0x02, 0x0D, 0x79, 0xED, 0x96, 0xB1, 0x0D, 0xF8, 0xCC, 0x0C,
- 0xDF, 0x81, 0x95, 0x4F, 0x03, 0x58, 0x09, 0x57, 0x0E, 0x80, 0x69, 0x2E, 0xFE, 0xFF,
- 0x52, 0x77, 0xEA, 0x75, 0x28, 0xA8, 0xFB, 0xC9, 0xBE, 0xBF, 0x9F, 0xBB, 0xB7, 0x79,
- 0x8E, 0x18, 0x05, 0xE1, 0x80, 0xBD, 0x50, 0x34, 0x94, 0x81, 0xD3, 0x53, 0xC2, 0x69,
- 0xA2, 0xD2, 0x4C, 0xCF, 0x6C, 0xF4, 0x57, 0x2C, 0x10, 0x4A, 0x3F, 0xFB, 0x22, 0xFD,
- 0x8B, 0x97, 0xE2, 0xC9, 0x5B, 0xA6, 0x2B, 0xCD, 0xD6, 0x1B, 0x6B, 0xDB, 0x68, 0x7F,
- 0x4B, 0xC2, 0xA0, 0x50, 0x34, 0xC0, 0x05, 0xE5, 0x8D, 0xEF, 0x24, 0x67, 0xFF, 0x93,
- 0x40, 0xCF, 0x2D, 0x62, 0xA2, 0xA0, 0x50, 0xB1, 0xF1, 0x3A, 0xA8, 0x3D, 0xFD, 0x80,
- 0xD1, 0xF9, 0xB8, 0x05, 0x22, 0xAF, 0xC8, 0x35, 0x45, 0x90, 0x58, 0x8E, 0xE3, 0x3A,
- 0x7C, 0xBD, 0x3E, 0x27};
-
- Prime1 = new CryptoPP::byte[0x80]{
- 0xFE, 0xF6, 0xBF, 0x1D, 0x69, 0xAB, 0x16, 0x25, 0x08, 0x47, 0x55, 0x6B, 0x86,
- 0xE4, 0x35, 0x88, 0x72, 0x2A, 0xB1, 0x3D, 0xF8, 0xB6, 0x44, 0xCA, 0xB3, 0xAB,
- 0x19, 0xD1, 0x04, 0x24, 0x28, 0x0A, 0x74, 0x55, 0xB8, 0x15, 0x45, 0x09, 0xCC,
- 0x13, 0x1C, 0xF2, 0xBA, 0x37, 0xA9, 0x03, 0x90, 0x8F, 0x02, 0x10, 0xFF, 0x25,
- 0x79, 0x86, 0xCC, 0x18, 0x50, 0x9A, 0x10, 0x5F, 0x5B, 0x4C, 0x1C, 0x4E, 0xB0,
- 0xA7, 0xE3, 0x59, 0xB1, 0x2D, 0xA0, 0xC6, 0xB0, 0x20, 0x2C, 0x21, 0x33, 0x12,
- 0xB3, 0xAF, 0x72, 0x34, 0x83, 0xCD, 0x52, 0x2F, 0xAF, 0x0F, 0x20, 0x5A, 0x1B,
- 0xC0, 0xE2, 0xA3, 0x76, 0x34, 0x0F, 0xD7, 0xFC, 0xC1, 0x41, 0xC9, 0xF9, 0x79,
- 0x40, 0x17, 0x42, 0x21, 0x3E, 0x9D, 0xFD, 0xC7, 0xC1, 0x50, 0xDE, 0x44, 0x5A,
- 0xC9, 0x31, 0x89, 0x6A, 0x78, 0x05, 0xBE, 0x65, 0xB4, 0xE8, 0x2D};
-
- Prime2 = new CryptoPP::byte[0x80]{
- 0xC7, 0x9E, 0x47, 0x58, 0x00, 0x7D, 0x62, 0x82, 0xB0, 0xD2, 0x22, 0x81, 0xD4,
- 0xA8, 0x97, 0x1B, 0x79, 0x0C, 0x3A, 0xB0, 0xD7, 0xC9, 0x30, 0xE3, 0xC3, 0x53,
- 0x8E, 0x57, 0xEF, 0xF0, 0x9B, 0x9F, 0xB3, 0x90, 0x52, 0xC6, 0x94, 0x22, 0x36,
- 0xAA, 0xE6, 0x4A, 0x5F, 0x72, 0x1D, 0x70, 0xE8, 0x76, 0x58, 0xC8, 0xB2, 0x91,
- 0xCE, 0x9C, 0xC3, 0xE9, 0x09, 0x7F, 0x2E, 0x47, 0x97, 0xCC, 0x90, 0x39, 0x15,
- 0x35, 0x31, 0xDE, 0x1F, 0x0C, 0x8C, 0x0D, 0xC1, 0xC2, 0x92, 0xBE, 0x97, 0xBF,
- 0x2F, 0x91, 0xA1, 0x8C, 0x7D, 0x50, 0xA8, 0x21, 0x2F, 0xD7, 0xA2, 0x9A, 0x7E,
- 0xB5, 0xA7, 0x2A, 0x90, 0x02, 0xD9, 0xF3, 0x3D, 0xD1, 0xEB, 0xB8, 0xE0, 0x5A,
- 0x79, 0x9E, 0x7D, 0x8D, 0xCA, 0x18, 0x6D, 0xBD, 0x9E, 0xA1, 0x80, 0x28, 0x6B,
- 0x2A, 0xFE, 0x51, 0x24, 0x9B, 0x6F, 0x4D, 0x84, 0x77, 0x80, 0x23};
- };
+ static constexpr CryptoPP::byte Prime2[] = {
+ 0xC7, 0x9E, 0x47, 0x58, 0x00, 0x7D, 0x62, 0x82, 0xB0, 0xD2, 0x22, 0x81, 0xD4, 0xA8, 0x97,
+ 0x1B, 0x79, 0x0C, 0x3A, 0xB0, 0xD7, 0xC9, 0x30, 0xE3, 0xC3, 0x53, 0x8E, 0x57, 0xEF, 0xF0,
+ 0x9B, 0x9F, 0xB3, 0x90, 0x52, 0xC6, 0x94, 0x22, 0x36, 0xAA, 0xE6, 0x4A, 0x5F, 0x72, 0x1D,
+ 0x70, 0xE8, 0x76, 0x58, 0xC8, 0xB2, 0x91, 0xCE, 0x9C, 0xC3, 0xE9, 0x09, 0x7F, 0x2E, 0x47,
+ 0x97, 0xCC, 0x90, 0x39, 0x15, 0x35, 0x31, 0xDE, 0x1F, 0x0C, 0x8C, 0x0D, 0xC1, 0xC2, 0x92,
+ 0xBE, 0x97, 0xBF, 0x2F, 0x91, 0xA1, 0x8C, 0x7D, 0x50, 0xA8, 0x21, 0x2F, 0xD7, 0xA2, 0x9A,
+ 0x7E, 0xB5, 0xA7, 0x2A, 0x90, 0x02, 0xD9, 0xF3, 0x3D, 0xD1, 0xEB, 0xB8, 0xE0, 0x5A, 0x79,
+ 0x9E, 0x7D, 0x8D, 0xCA, 0x18, 0x6D, 0xBD, 0x9E, 0xA1, 0x80, 0x28, 0x6B, 0x2A, 0xFE, 0x51,
+ 0x24, 0x9B, 0x6F, 0x4D, 0x84, 0x77, 0x80, 0x23};
+ static constexpr CryptoPP::byte PrivateExponent[] = {
+ 0x7F, 0x76, 0xCD, 0x0E, 0xE2, 0xD4, 0xDE, 0x05, 0x1C, 0xC6, 0xD9, 0xA8, 0x0E, 0x8D, 0xFA,
+ 0x7B, 0xCA, 0x1E, 0xAA, 0x27, 0x1A, 0x40, 0xF8, 0xF1, 0x22, 0x87, 0x35, 0xDD, 0xDB, 0xFD,
+ 0xEE, 0xF8, 0xC2, 0xBC, 0xBD, 0x01, 0xFB, 0x8B, 0xE2, 0x3E, 0x63, 0xB2, 0xB1, 0x22, 0x5C,
+ 0x56, 0x49, 0x6E, 0x11, 0xBE, 0x07, 0x44, 0x0B, 0x9A, 0x26, 0x66, 0xD1, 0x49, 0x2C, 0x8F,
+ 0xD3, 0x1B, 0xCF, 0xA4, 0xA1, 0xB8, 0xD1, 0xFB, 0xA4, 0x9E, 0xD2, 0x21, 0x28, 0x83, 0x09,
+ 0x8A, 0xF6, 0xA0, 0x0B, 0xA3, 0xD6, 0x0F, 0x9B, 0x63, 0x68, 0xCC, 0xBC, 0x0C, 0x4E, 0x14,
+ 0x5B, 0x27, 0xA4, 0xA9, 0xF4, 0x2B, 0xB9, 0xB8, 0x7B, 0xC0, 0xE6, 0x51, 0xAD, 0x1D, 0x77,
+ 0xD4, 0x6B, 0xB9, 0xCE, 0x20, 0xD1, 0x26, 0x66, 0x7E, 0x5E, 0x9E, 0xA2, 0xE9, 0x6B, 0x90,
+ 0xF3, 0x73, 0xB8, 0x52, 0x8F, 0x44, 0x11, 0x03, 0x0C, 0x13, 0x97, 0x39, 0x3D, 0x13, 0x22,
+ 0x58, 0xD5, 0x43, 0x82, 0x49, 0xDA, 0x6E, 0x7C, 0xA1, 0xC5, 0x8C, 0xA5, 0xB0, 0x09, 0xE0,
+ 0xCE, 0x3D, 0xDF, 0xF4, 0x9D, 0x3C, 0x97, 0x15, 0xE2, 0x6A, 0xC7, 0x2B, 0x3C, 0x50, 0x93,
+ 0x23, 0xDB, 0xBA, 0x4A, 0x22, 0x66, 0x44, 0xAC, 0x78, 0xBB, 0x0E, 0x1A, 0x27, 0x43, 0xB5,
+ 0x71, 0x67, 0xAF, 0xF4, 0xAB, 0x48, 0x46, 0x93, 0x73, 0xD0, 0x42, 0xAB, 0x93, 0x63, 0xE5,
+ 0x6C, 0x9A, 0xDE, 0x50, 0x24, 0xC0, 0x23, 0x7D, 0x99, 0x79, 0x3F, 0x22, 0x07, 0xE0, 0xC1,
+ 0x48, 0x56, 0x1B, 0xDF, 0x83, 0x09, 0x12, 0xB4, 0x2D, 0x45, 0x6B, 0xC9, 0xC0, 0x68, 0x85,
+ 0x99, 0x90, 0x79, 0x96, 0x1A, 0xD7, 0xF5, 0x4D, 0x1F, 0x37, 0x83, 0x40, 0x4A, 0xEC, 0x39,
+ 0x37, 0xA6, 0x80, 0x92, 0x7D, 0xC5, 0x80, 0xC7, 0xD6, 0x6F, 0xFE, 0x8A, 0x79, 0x89, 0xC6,
+ 0xB1};
};
class DebugRifKeyset {
public:
- // Constructor
// std::uint8_t* PrivateExponent;
- const CryptoPP::byte* Exponent1;
+ static constexpr CryptoPP::byte Exponent1[] = {
+ 0xCD, 0x9A, 0x61, 0xB0, 0xB8, 0xD5, 0xB4, 0xE4, 0xE4, 0xF6, 0xAB, 0xF7, 0x27, 0xB7, 0x56,
+ 0x59, 0x6B, 0xB9, 0x11, 0xE7, 0xF4, 0x83, 0xAF, 0xB9, 0x73, 0x99, 0x7F, 0x49, 0xA2, 0x9C,
+ 0xF0, 0xB5, 0x6D, 0x37, 0x82, 0x14, 0x15, 0xF1, 0x04, 0x8A, 0xD4, 0x8E, 0xEB, 0x2E, 0x1F,
+ 0xE2, 0x81, 0xA9, 0x62, 0x6E, 0xB1, 0x68, 0x75, 0x62, 0xF3, 0x0F, 0xFE, 0xD4, 0x91, 0x87,
+ 0x98, 0x78, 0xBF, 0x26, 0xB5, 0x07, 0x58, 0xD0, 0xEE, 0x3F, 0x21, 0xE8, 0xC8, 0x0F, 0x5F,
+ 0xFA, 0x1C, 0x64, 0x74, 0x49, 0x52, 0xEB, 0xE7, 0xEE, 0xDE, 0xBA, 0x23, 0x26, 0x4A, 0xF6,
+ 0x9C, 0x1A, 0x09, 0x3F, 0xB9, 0x0B, 0x36, 0x26, 0x1A, 0xBE, 0xA9, 0x76, 0xE6, 0xF2, 0x69,
+ 0xDE, 0xFF, 0xAF, 0xCC, 0x0C, 0x9A, 0x66, 0x03, 0x86, 0x0A, 0x1F, 0x49, 0xA4, 0x10, 0xB6,
+ 0xBC, 0xC3, 0x7C, 0x88, 0xE8, 0xCE, 0x4B, 0xD9};
// exponent2 = d mod (q - 1)
- const CryptoPP::byte* Exponent2;
+ static constexpr CryptoPP::byte Exponent2[] = {
+ 0xB3, 0x73, 0xA3, 0x59, 0xE6, 0x97, 0xC0, 0xAB, 0x3B, 0x68, 0xFC, 0x39, 0xAC, 0xDB, 0x44,
+ 0xB1, 0xB4, 0x9E, 0x35, 0x4D, 0xBE, 0xC5, 0x36, 0x69, 0x6C, 0x3D, 0xC5, 0xFC, 0xFE, 0x4B,
+ 0x2F, 0xDC, 0x86, 0x80, 0x46, 0x96, 0x40, 0x1A, 0x0D, 0x6E, 0xFA, 0x8C, 0xE0, 0x47, 0x91,
+ 0xAC, 0xAD, 0x95, 0x2B, 0x8E, 0x1F, 0xF2, 0x0A, 0x45, 0xF8, 0x29, 0x95, 0x70, 0xC6, 0x88,
+ 0x5F, 0x71, 0x03, 0x99, 0x79, 0xBC, 0x84, 0x71, 0xBD, 0xE8, 0x84, 0x8C, 0x0E, 0xD4, 0x7B,
+ 0x30, 0x74, 0x57, 0x1A, 0x95, 0xE7, 0x90, 0x19, 0x8D, 0xAD, 0x8B, 0x4C, 0x4E, 0xC3, 0xE7,
+ 0x6B, 0x23, 0x86, 0x01, 0xEE, 0x9B, 0xE0, 0x2F, 0x15, 0xA2, 0x2C, 0x4C, 0x39, 0xD3, 0xDF,
+ 0x9C, 0x39, 0x01, 0xF1, 0x8C, 0x44, 0x4A, 0x15, 0x44, 0xDC, 0x51, 0xF7, 0x22, 0xD7, 0x7F,
+ 0x41, 0x7F, 0x68, 0xFA, 0xEE, 0x56, 0xE8, 0x05};
// e
- const CryptoPP::byte* PublicExponent;
+ static constexpr CryptoPP::byte PublicExponent[] = {0x00, 0x01, 0x00, 0x01};
// (InverseQ)(q) = 1 mod p
- const CryptoPP::byte* Coefficient;
+ static constexpr CryptoPP::byte Coefficient[] = {
+ 0xC0, 0x32, 0x43, 0xD3, 0x8C, 0x3D, 0xB4, 0xD2, 0x48, 0x8C, 0x42, 0x41, 0x24, 0x94, 0x6C,
+ 0x80, 0xC9, 0xC1, 0x79, 0x36, 0x7F, 0xAC, 0xC3, 0xFF, 0x6A, 0x25, 0xEB, 0x2C, 0xFB, 0xD4,
+ 0x2B, 0xA0, 0xEB, 0xFE, 0x25, 0xE9, 0xC6, 0x77, 0xCE, 0xFE, 0x2D, 0x23, 0xFE, 0xD0, 0xF4,
+ 0x0F, 0xD9, 0x7E, 0xD5, 0xA5, 0x7D, 0x1F, 0xC0, 0xE8, 0xE8, 0xEC, 0x80, 0x5B, 0xC7, 0xFD,
+ 0xE2, 0xBD, 0x94, 0xA6, 0x2B, 0xDD, 0x6A, 0x60, 0x45, 0x54, 0xAB, 0xCA, 0x42, 0x9C, 0x6A,
+ 0x6C, 0xBF, 0x3C, 0x84, 0xF9, 0xA5, 0x0E, 0x63, 0x0C, 0x51, 0x58, 0x62, 0x6D, 0x5A, 0xB7,
+ 0x3C, 0x3F, 0x49, 0x1A, 0xD0, 0x93, 0xB8, 0x4F, 0x1A, 0x6C, 0x5F, 0xC5, 0xE5, 0xA9, 0x75,
+ 0xD4, 0x86, 0x9E, 0xDF, 0x87, 0x0F, 0x27, 0xB0, 0x26, 0x78, 0x4E, 0xFB, 0xC1, 0x8A, 0x4A,
+ 0x24, 0x3F, 0x7F, 0x8F, 0x9A, 0x12, 0x51, 0xCB};
// n = p * q
- const CryptoPP::byte* Modulus;
+ static constexpr CryptoPP::byte Modulus[] = {
+ 0xC2, 0xD2, 0x44, 0xBC, 0xDD, 0x84, 0x3F, 0xD9, 0xC5, 0x22, 0xAF, 0xF7, 0xFC, 0x88, 0x8A,
+ 0x33, 0x80, 0xED, 0x8E, 0xE2, 0xCC, 0x81, 0xF7, 0xEC, 0xF8, 0x1C, 0x79, 0xBF, 0x02, 0xBB,
+ 0x12, 0x8E, 0x61, 0x68, 0x29, 0x1B, 0x15, 0xB6, 0x5E, 0xC6, 0xF8, 0xBF, 0x5A, 0xE0, 0x3B,
+ 0x6A, 0x6C, 0xD9, 0xD6, 0xF5, 0x75, 0xAB, 0xA0, 0x6F, 0x34, 0x81, 0x34, 0x9A, 0x5B, 0xAD,
+ 0xED, 0x31, 0xE3, 0xC6, 0xEA, 0x1A, 0xD1, 0x13, 0x22, 0xBB, 0xB3, 0xDA, 0xB3, 0xB2, 0x53,
+ 0xBD, 0x45, 0x79, 0x87, 0xAD, 0x0A, 0x01, 0x72, 0x18, 0x10, 0x29, 0x49, 0xF4, 0x41, 0x7F,
+ 0xD6, 0x47, 0x0C, 0x72, 0x92, 0x9E, 0xE9, 0xBB, 0x95, 0xA9, 0x5D, 0x79, 0xEB, 0xE4, 0x30,
+ 0x76, 0x90, 0x45, 0x4B, 0x9D, 0x9C, 0xCF, 0x92, 0x03, 0x60, 0x8C, 0x4B, 0x6C, 0xB3, 0x7A,
+ 0x3A, 0x05, 0x39, 0xA0, 0x66, 0xA9, 0x35, 0xCF, 0xB9, 0xFA, 0xAD, 0x9C, 0xAB, 0xEB, 0xE4,
+ 0x6A, 0x8C, 0xE9, 0x3B, 0xCC, 0x72, 0x12, 0x62, 0x63, 0xBD, 0x80, 0xC4, 0xEE, 0x37, 0x2B,
+ 0x32, 0x03, 0xA3, 0x09, 0xF7, 0xA0, 0x61, 0x57, 0xAD, 0x0D, 0xCF, 0x15, 0x98, 0x9E, 0x4E,
+ 0x49, 0xF8, 0xB5, 0xA3, 0x5C, 0x27, 0xEE, 0x45, 0x04, 0xEA, 0xE4, 0x4B, 0xBC, 0x8F, 0x87,
+ 0xED, 0x19, 0x1E, 0x46, 0x75, 0x63, 0xC4, 0x5B, 0xD5, 0xBC, 0x09, 0x2F, 0x02, 0x73, 0x19,
+ 0x3C, 0x58, 0x55, 0x49, 0x66, 0x4C, 0x11, 0xEC, 0x0F, 0x09, 0xFA, 0xA5, 0x56, 0x0A, 0x5A,
+ 0x63, 0x56, 0xAD, 0xA0, 0x0D, 0x86, 0x08, 0xC1, 0xE6, 0xB6, 0x13, 0x22, 0x49, 0x2F, 0x7C,
+ 0xDB, 0x4C, 0x56, 0x97, 0x0E, 0xC2, 0xD9, 0x2E, 0x87, 0xBC, 0x0E, 0x67, 0xC0, 0x1B, 0x58,
+ 0xBC, 0x64, 0x2B, 0xC2, 0x6E, 0xE2, 0x93, 0x2E, 0xB5, 0x6B, 0x70, 0xA4, 0x42, 0x9F, 0x64,
+ 0xC1};
// p
- const CryptoPP::byte* Prime1;
+ static constexpr CryptoPP::byte Prime1[] = {
+ 0xE5, 0x62, 0xE1, 0x7F, 0x9F, 0x86, 0x08, 0xE2, 0x61, 0xD3, 0xD0, 0x42, 0xE2, 0xC4, 0xB6,
+ 0xA8, 0x51, 0x09, 0x19, 0x14, 0xA4, 0x3A, 0x11, 0x4C, 0x33, 0xA5, 0x9C, 0x01, 0x5E, 0x34,
+ 0xB6, 0x3F, 0x02, 0x1A, 0xCA, 0x47, 0xF1, 0x4F, 0x3B, 0x35, 0x2A, 0x07, 0x20, 0xEC, 0xD8,
+ 0xC1, 0x15, 0xD9, 0xCA, 0x03, 0x4F, 0xB8, 0xE8, 0x09, 0x73, 0x3F, 0x85, 0xB7, 0x41, 0xD5,
+ 0x51, 0x3E, 0x7B, 0xE3, 0x53, 0x2B, 0x48, 0x8B, 0x8E, 0xCB, 0xBA, 0xF7, 0xE0, 0x60, 0xF5,
+ 0x35, 0x0E, 0x6F, 0xB0, 0xD9, 0x2A, 0x99, 0xD0, 0xFF, 0x60, 0x14, 0xED, 0x40, 0xEA, 0xF8,
+ 0xD7, 0x0B, 0xC3, 0x8D, 0x8C, 0xE8, 0x81, 0xB3, 0x75, 0x93, 0x15, 0xB3, 0x7D, 0xF6, 0x39,
+ 0x60, 0x1A, 0x00, 0xE7, 0xC3, 0x27, 0xAD, 0xA4, 0x33, 0xD5, 0x3E, 0xA4, 0x35, 0x48, 0x6F,
+ 0x22, 0xEF, 0x5D, 0xDD, 0x7D, 0x7B, 0x61, 0x05};
// q
- const CryptoPP::byte* Prime2;
- const CryptoPP::byte* PrivateExponent;
-
- // Constructor
- DebugRifKeyset() {
- // Initialize PrivateExponent
- PrivateExponent = new CryptoPP::byte[0x100]{
- 0x01, 0x61, 0xAD, 0xD8, 0x9C, 0x06, 0x89, 0xD0, 0x60, 0xC8, 0x41, 0xF0, 0xB3, 0x83,
- 0x01, 0x5D, 0xE3, 0xA2, 0x6B, 0xA2, 0xBA, 0x9A, 0x0A, 0x58, 0xCD, 0x1A, 0xA0, 0x97,
- 0x64, 0xEC, 0xD0, 0x31, 0x1F, 0xCA, 0x36, 0x0E, 0x69, 0xDD, 0x40, 0xF7, 0x4E, 0xC0,
- 0xC6, 0xA3, 0x73, 0xF0, 0x69, 0x84, 0xB2, 0xF4, 0x4B, 0x29, 0x14, 0x2A, 0x6D, 0xB8,
- 0x23, 0xD8, 0x1B, 0x61, 0xD4, 0x9E, 0x87, 0xB3, 0xBB, 0xA9, 0xC4, 0x85, 0x4A, 0xF8,
- 0x03, 0x4A, 0xBF, 0xFE, 0xF9, 0xFE, 0x8B, 0xDD, 0x54, 0x83, 0xBA, 0xE0, 0x2F, 0x3F,
- 0xB1, 0xEF, 0xA5, 0x05, 0x5D, 0x28, 0x8B, 0xAB, 0xB5, 0xD0, 0x23, 0x2F, 0x8A, 0xCF,
- 0x48, 0x7C, 0xAA, 0xBB, 0xC8, 0x5B, 0x36, 0x27, 0xC5, 0x16, 0xA4, 0xB6, 0x61, 0xAC,
- 0x0C, 0x28, 0x47, 0x79, 0x3F, 0x38, 0xAE, 0x5E, 0x25, 0xC6, 0xAF, 0x35, 0xAE, 0xBC,
- 0xB0, 0xF3, 0xBC, 0xBD, 0xFD, 0xA4, 0x87, 0x0D, 0x14, 0x3D, 0x90, 0xE4, 0xDE, 0x5D,
- 0x1D, 0x46, 0x81, 0xF1, 0x28, 0x6D, 0x2F, 0x2C, 0x5E, 0x97, 0x2D, 0x89, 0x2A, 0x51,
- 0x72, 0x3C, 0x20, 0x02, 0x59, 0xB1, 0x98, 0x93, 0x05, 0x1E, 0x3F, 0xA1, 0x8A, 0x69,
- 0x30, 0x0E, 0x70, 0x84, 0x8B, 0xAE, 0x97, 0xA1, 0x08, 0x95, 0x63, 0x4C, 0xC7, 0xE8,
- 0x5D, 0x59, 0xCA, 0x78, 0x2A, 0x23, 0x87, 0xAC, 0x6F, 0x04, 0x33, 0xB1, 0x61, 0xB9,
- 0xF0, 0x95, 0xDA, 0x33, 0xCC, 0xE0, 0x4C, 0x82, 0x68, 0x82, 0x14, 0x51, 0xBE, 0x49,
- 0x1C, 0x58, 0xA2, 0x8B, 0x05, 0x4E, 0x98, 0x37, 0xEB, 0x94, 0x0B, 0x01, 0x22, 0xDC,
- 0xB3, 0x19, 0xCA, 0x77, 0xA6, 0x6E, 0x97, 0xFF, 0x8A, 0x53, 0x5A, 0xC5, 0x24, 0xE4,
- 0xAF, 0x6E, 0xA8, 0x2B, 0x53, 0xA4, 0xBE, 0x96, 0xA5, 0x7B, 0xCE, 0x22, 0x56, 0xA3,
- 0xF1, 0xCF, 0x14, 0xA5};
-
- // Initialize Exponent1
- Exponent1 = new CryptoPP::byte[0x80]{
- 0xCD, 0x9A, 0x61, 0xB0, 0xB8, 0xD5, 0xB4, 0xE4, 0xE4, 0xF6, 0xAB, 0xF7, 0x27,
- 0xB7, 0x56, 0x59, 0x6B, 0xB9, 0x11, 0xE7, 0xF4, 0x83, 0xAF, 0xB9, 0x73, 0x99,
- 0x7F, 0x49, 0xA2, 0x9C, 0xF0, 0xB5, 0x6D, 0x37, 0x82, 0x14, 0x15, 0xF1, 0x04,
- 0x8A, 0xD4, 0x8E, 0xEB, 0x2E, 0x1F, 0xE2, 0x81, 0xA9, 0x62, 0x6E, 0xB1, 0x68,
- 0x75, 0x62, 0xF3, 0x0F, 0xFE, 0xD4, 0x91, 0x87, 0x98, 0x78, 0xBF, 0x26, 0xB5,
- 0x07, 0x58, 0xD0, 0xEE, 0x3F, 0x21, 0xE8, 0xC8, 0x0F, 0x5F, 0xFA, 0x1C, 0x64,
- 0x74, 0x49, 0x52, 0xEB, 0xE7, 0xEE, 0xDE, 0xBA, 0x23, 0x26, 0x4A, 0xF6, 0x9C,
- 0x1A, 0x09, 0x3F, 0xB9, 0x0B, 0x36, 0x26, 0x1A, 0xBE, 0xA9, 0x76, 0xE6, 0xF2,
- 0x69, 0xDE, 0xFF, 0xAF, 0xCC, 0x0C, 0x9A, 0x66, 0x03, 0x86, 0x0A, 0x1F, 0x49,
- 0xA4, 0x10, 0xB6, 0xBC, 0xC3, 0x7C, 0x88, 0xE8, 0xCE, 0x4B, 0xD9
-
- };
-
- Exponent2 = new CryptoPP::byte[0x80]{
- 0xB3, 0x73, 0xA3, 0x59, 0xE6, 0x97, 0xC0, 0xAB, 0x3B, 0x68, 0xFC, 0x39, 0xAC,
- 0xDB, 0x44, 0xB1, 0xB4, 0x9E, 0x35, 0x4D, 0xBE, 0xC5, 0x36, 0x69, 0x6C, 0x3D,
- 0xC5, 0xFC, 0xFE, 0x4B, 0x2F, 0xDC, 0x86, 0x80, 0x46, 0x96, 0x40, 0x1A, 0x0D,
- 0x6E, 0xFA, 0x8C, 0xE0, 0x47, 0x91, 0xAC, 0xAD, 0x95, 0x2B, 0x8E, 0x1F, 0xF2,
- 0x0A, 0x45, 0xF8, 0x29, 0x95, 0x70, 0xC6, 0x88, 0x5F, 0x71, 0x03, 0x99, 0x79,
- 0xBC, 0x84, 0x71, 0xBD, 0xE8, 0x84, 0x8C, 0x0E, 0xD4, 0x7B, 0x30, 0x74, 0x57,
- 0x1A, 0x95, 0xE7, 0x90, 0x19, 0x8D, 0xAD, 0x8B, 0x4C, 0x4E, 0xC3, 0xE7, 0x6B,
- 0x23, 0x86, 0x01, 0xEE, 0x9B, 0xE0, 0x2F, 0x15, 0xA2, 0x2C, 0x4C, 0x39, 0xD3,
- 0xDF, 0x9C, 0x39, 0x01, 0xF1, 0x8C, 0x44, 0x4A, 0x15, 0x44, 0xDC, 0x51, 0xF7,
- 0x22, 0xD7, 0x7F, 0x41, 0x7F, 0x68, 0xFA, 0xEE, 0x56, 0xE8, 0x05};
-
- PublicExponent = new CryptoPP::byte[4]{0x00, 0x01, 0x00, 0x01};
-
- Coefficient = new CryptoPP::byte[0x80]{
- 0xC0, 0x32, 0x43, 0xD3, 0x8C, 0x3D, 0xB4, 0xD2, 0x48, 0x8C, 0x42, 0x41, 0x24,
- 0x94, 0x6C, 0x80, 0xC9, 0xC1, 0x79, 0x36, 0x7F, 0xAC, 0xC3, 0xFF, 0x6A, 0x25,
- 0xEB, 0x2C, 0xFB, 0xD4, 0x2B, 0xA0, 0xEB, 0xFE, 0x25, 0xE9, 0xC6, 0x77, 0xCE,
- 0xFE, 0x2D, 0x23, 0xFE, 0xD0, 0xF4, 0x0F, 0xD9, 0x7E, 0xD5, 0xA5, 0x7D, 0x1F,
- 0xC0, 0xE8, 0xE8, 0xEC, 0x80, 0x5B, 0xC7, 0xFD, 0xE2, 0xBD, 0x94, 0xA6, 0x2B,
- 0xDD, 0x6A, 0x60, 0x45, 0x54, 0xAB, 0xCA, 0x42, 0x9C, 0x6A, 0x6C, 0xBF, 0x3C,
- 0x84, 0xF9, 0xA5, 0x0E, 0x63, 0x0C, 0x51, 0x58, 0x62, 0x6D, 0x5A, 0xB7, 0x3C,
- 0x3F, 0x49, 0x1A, 0xD0, 0x93, 0xB8, 0x4F, 0x1A, 0x6C, 0x5F, 0xC5, 0xE5, 0xA9,
- 0x75, 0xD4, 0x86, 0x9E, 0xDF, 0x87, 0x0F, 0x27, 0xB0, 0x26, 0x78, 0x4E, 0xFB,
- 0xC1, 0x8A, 0x4A, 0x24, 0x3F, 0x7F, 0x8F, 0x9A, 0x12, 0x51, 0xCB};
-
- Modulus = new CryptoPP::byte[0x100]{
- 0xC2, 0xD2, 0x44, 0xBC, 0xDD, 0x84, 0x3F, 0xD9, 0xC5, 0x22, 0xAF, 0xF7, 0xFC, 0x88,
- 0x8A, 0x33, 0x80, 0xED, 0x8E, 0xE2, 0xCC, 0x81, 0xF7, 0xEC, 0xF8, 0x1C, 0x79, 0xBF,
- 0x02, 0xBB, 0x12, 0x8E, 0x61, 0x68, 0x29, 0x1B, 0x15, 0xB6, 0x5E, 0xC6, 0xF8, 0xBF,
- 0x5A, 0xE0, 0x3B, 0x6A, 0x6C, 0xD9, 0xD6, 0xF5, 0x75, 0xAB, 0xA0, 0x6F, 0x34, 0x81,
- 0x34, 0x9A, 0x5B, 0xAD, 0xED, 0x31, 0xE3, 0xC6, 0xEA, 0x1A, 0xD1, 0x13, 0x22, 0xBB,
- 0xB3, 0xDA, 0xB3, 0xB2, 0x53, 0xBD, 0x45, 0x79, 0x87, 0xAD, 0x0A, 0x01, 0x72, 0x18,
- 0x10, 0x29, 0x49, 0xF4, 0x41, 0x7F, 0xD6, 0x47, 0x0C, 0x72, 0x92, 0x9E, 0xE9, 0xBB,
- 0x95, 0xA9, 0x5D, 0x79, 0xEB, 0xE4, 0x30, 0x76, 0x90, 0x45, 0x4B, 0x9D, 0x9C, 0xCF,
- 0x92, 0x03, 0x60, 0x8C, 0x4B, 0x6C, 0xB3, 0x7A, 0x3A, 0x05, 0x39, 0xA0, 0x66, 0xA9,
- 0x35, 0xCF, 0xB9, 0xFA, 0xAD, 0x9C, 0xAB, 0xEB, 0xE4, 0x6A, 0x8C, 0xE9, 0x3B, 0xCC,
- 0x72, 0x12, 0x62, 0x63, 0xBD, 0x80, 0xC4, 0xEE, 0x37, 0x2B, 0x32, 0x03, 0xA3, 0x09,
- 0xF7, 0xA0, 0x61, 0x57, 0xAD, 0x0D, 0xCF, 0x15, 0x98, 0x9E, 0x4E, 0x49, 0xF8, 0xB5,
- 0xA3, 0x5C, 0x27, 0xEE, 0x45, 0x04, 0xEA, 0xE4, 0x4B, 0xBC, 0x8F, 0x87, 0xED, 0x19,
- 0x1E, 0x46, 0x75, 0x63, 0xC4, 0x5B, 0xD5, 0xBC, 0x09, 0x2F, 0x02, 0x73, 0x19, 0x3C,
- 0x58, 0x55, 0x49, 0x66, 0x4C, 0x11, 0xEC, 0x0F, 0x09, 0xFA, 0xA5, 0x56, 0x0A, 0x5A,
- 0x63, 0x56, 0xAD, 0xA0, 0x0D, 0x86, 0x08, 0xC1, 0xE6, 0xB6, 0x13, 0x22, 0x49, 0x2F,
- 0x7C, 0xDB, 0x4C, 0x56, 0x97, 0x0E, 0xC2, 0xD9, 0x2E, 0x87, 0xBC, 0x0E, 0x67, 0xC0,
- 0x1B, 0x58, 0xBC, 0x64, 0x2B, 0xC2, 0x6E, 0xE2, 0x93, 0x2E, 0xB5, 0x6B, 0x70, 0xA4,
- 0x42, 0x9F, 0x64, 0xC1};
-
- Prime1 = new CryptoPP::byte[0x80]{
- 0xE5, 0x62, 0xE1, 0x7F, 0x9F, 0x86, 0x08, 0xE2, 0x61, 0xD3, 0xD0, 0x42, 0xE2,
- 0xC4, 0xB6, 0xA8, 0x51, 0x09, 0x19, 0x14, 0xA4, 0x3A, 0x11, 0x4C, 0x33, 0xA5,
- 0x9C, 0x01, 0x5E, 0x34, 0xB6, 0x3F, 0x02, 0x1A, 0xCA, 0x47, 0xF1, 0x4F, 0x3B,
- 0x35, 0x2A, 0x07, 0x20, 0xEC, 0xD8, 0xC1, 0x15, 0xD9, 0xCA, 0x03, 0x4F, 0xB8,
- 0xE8, 0x09, 0x73, 0x3F, 0x85, 0xB7, 0x41, 0xD5, 0x51, 0x3E, 0x7B, 0xE3, 0x53,
- 0x2B, 0x48, 0x8B, 0x8E, 0xCB, 0xBA, 0xF7, 0xE0, 0x60, 0xF5, 0x35, 0x0E, 0x6F,
- 0xB0, 0xD9, 0x2A, 0x99, 0xD0, 0xFF, 0x60, 0x14, 0xED, 0x40, 0xEA, 0xF8, 0xD7,
- 0x0B, 0xC3, 0x8D, 0x8C, 0xE8, 0x81, 0xB3, 0x75, 0x93, 0x15, 0xB3, 0x7D, 0xF6,
- 0x39, 0x60, 0x1A, 0x00, 0xE7, 0xC3, 0x27, 0xAD, 0xA4, 0x33, 0xD5, 0x3E, 0xA4,
- 0x35, 0x48, 0x6F, 0x22, 0xEF, 0x5D, 0xDD, 0x7D, 0x7B, 0x61, 0x05};
-
- Prime2 = new CryptoPP::byte[0x80]{
- 0xD9, 0x6C, 0xC2, 0x0C, 0xF7, 0xAE, 0xD1, 0xF3, 0x3B, 0x3B, 0x49, 0x1E, 0x9F,
- 0x12, 0x9C, 0xA1, 0x78, 0x1F, 0x35, 0x1D, 0x98, 0x26, 0x13, 0x71, 0xF9, 0x09,
- 0xFD, 0xF0, 0xAD, 0x38, 0x55, 0xB7, 0xEE, 0x61, 0x04, 0x72, 0x51, 0x87, 0x2E,
- 0x05, 0x84, 0xB1, 0x1D, 0x0C, 0x0D, 0xDB, 0xD4, 0x25, 0x3E, 0x26, 0xED, 0xEA,
- 0xB8, 0xF7, 0x49, 0xFE, 0xA2, 0x94, 0xE6, 0xF2, 0x08, 0x92, 0xA7, 0x85, 0xF5,
- 0x30, 0xB9, 0x84, 0x22, 0xBF, 0xCA, 0xF0, 0x5F, 0xCB, 0x31, 0x20, 0x34, 0x49,
- 0x16, 0x76, 0x34, 0xCC, 0x7A, 0xCB, 0x96, 0xFE, 0x78, 0x7A, 0x41, 0xFE, 0x9A,
- 0xA2, 0x23, 0xF7, 0x68, 0x80, 0xD6, 0xCE, 0x4A, 0x78, 0xA5, 0xB7, 0x05, 0x77,
- 0x81, 0x1F, 0xDE, 0x5E, 0xA8, 0x6E, 0x3E, 0x87, 0xEC, 0x44, 0xD2, 0x69, 0xC6,
- 0x54, 0x91, 0x6B, 0x5E, 0x13, 0x8A, 0x03, 0x87, 0x05, 0x31, 0x8D};
- };
+ static constexpr CryptoPP::byte Prime2[] = {
+ 0xD9, 0x6C, 0xC2, 0x0C, 0xF7, 0xAE, 0xD1, 0xF3, 0x3B, 0x3B, 0x49, 0x1E, 0x9F, 0x12, 0x9C,
+ 0xA1, 0x78, 0x1F, 0x35, 0x1D, 0x98, 0x26, 0x13, 0x71, 0xF9, 0x09, 0xFD, 0xF0, 0xAD, 0x38,
+ 0x55, 0xB7, 0xEE, 0x61, 0x04, 0x72, 0x51, 0x87, 0x2E, 0x05, 0x84, 0xB1, 0x1D, 0x0C, 0x0D,
+ 0xDB, 0xD4, 0x25, 0x3E, 0x26, 0xED, 0xEA, 0xB8, 0xF7, 0x49, 0xFE, 0xA2, 0x94, 0xE6, 0xF2,
+ 0x08, 0x92, 0xA7, 0x85, 0xF5, 0x30, 0xB9, 0x84, 0x22, 0xBF, 0xCA, 0xF0, 0x5F, 0xCB, 0x31,
+ 0x20, 0x34, 0x49, 0x16, 0x76, 0x34, 0xCC, 0x7A, 0xCB, 0x96, 0xFE, 0x78, 0x7A, 0x41, 0xFE,
+ 0x9A, 0xA2, 0x23, 0xF7, 0x68, 0x80, 0xD6, 0xCE, 0x4A, 0x78, 0xA5, 0xB7, 0x05, 0x77, 0x81,
+ 0x1F, 0xDE, 0x5E, 0xA8, 0x6E, 0x3E, 0x87, 0xEC, 0x44, 0xD2, 0x69, 0xC6, 0x54, 0x91, 0x6B,
+ 0x5E, 0x13, 0x8A, 0x03, 0x87, 0x05, 0x31, 0x8D};
+ static constexpr CryptoPP::byte PrivateExponent[] = {
+ 0x01, 0x61, 0xAD, 0xD8, 0x9C, 0x06, 0x89, 0xD0, 0x60, 0xC8, 0x41, 0xF0, 0xB3, 0x83, 0x01,
+ 0x5D, 0xE3, 0xA2, 0x6B, 0xA2, 0xBA, 0x9A, 0x0A, 0x58, 0xCD, 0x1A, 0xA0, 0x97, 0x64, 0xEC,
+ 0xD0, 0x31, 0x1F, 0xCA, 0x36, 0x0E, 0x69, 0xDD, 0x40, 0xF7, 0x4E, 0xC0, 0xC6, 0xA3, 0x73,
+ 0xF0, 0x69, 0x84, 0xB2, 0xF4, 0x4B, 0x29, 0x14, 0x2A, 0x6D, 0xB8, 0x23, 0xD8, 0x1B, 0x61,
+ 0xD4, 0x9E, 0x87, 0xB3, 0xBB, 0xA9, 0xC4, 0x85, 0x4A, 0xF8, 0x03, 0x4A, 0xBF, 0xFE, 0xF9,
+ 0xFE, 0x8B, 0xDD, 0x54, 0x83, 0xBA, 0xE0, 0x2F, 0x3F, 0xB1, 0xEF, 0xA5, 0x05, 0x5D, 0x28,
+ 0x8B, 0xAB, 0xB5, 0xD0, 0x23, 0x2F, 0x8A, 0xCF, 0x48, 0x7C, 0xAA, 0xBB, 0xC8, 0x5B, 0x36,
+ 0x27, 0xC5, 0x16, 0xA4, 0xB6, 0x61, 0xAC, 0x0C, 0x28, 0x47, 0x79, 0x3F, 0x38, 0xAE, 0x5E,
+ 0x25, 0xC6, 0xAF, 0x35, 0xAE, 0xBC, 0xB0, 0xF3, 0xBC, 0xBD, 0xFD, 0xA4, 0x87, 0x0D, 0x14,
+ 0x3D, 0x90, 0xE4, 0xDE, 0x5D, 0x1D, 0x46, 0x81, 0xF1, 0x28, 0x6D, 0x2F, 0x2C, 0x5E, 0x97,
+ 0x2D, 0x89, 0x2A, 0x51, 0x72, 0x3C, 0x20, 0x02, 0x59, 0xB1, 0x98, 0x93, 0x05, 0x1E, 0x3F,
+ 0xA1, 0x8A, 0x69, 0x30, 0x0E, 0x70, 0x84, 0x8B, 0xAE, 0x97, 0xA1, 0x08, 0x95, 0x63, 0x4C,
+ 0xC7, 0xE8, 0x5D, 0x59, 0xCA, 0x78, 0x2A, 0x23, 0x87, 0xAC, 0x6F, 0x04, 0x33, 0xB1, 0x61,
+ 0xB9, 0xF0, 0x95, 0xDA, 0x33, 0xCC, 0xE0, 0x4C, 0x82, 0x68, 0x82, 0x14, 0x51, 0xBE, 0x49,
+ 0x1C, 0x58, 0xA2, 0x8B, 0x05, 0x4E, 0x98, 0x37, 0xEB, 0x94, 0x0B, 0x01, 0x22, 0xDC, 0xB3,
+ 0x19, 0xCA, 0x77, 0xA6, 0x6E, 0x97, 0xFF, 0x8A, 0x53, 0x5A, 0xC5, 0x24, 0xE4, 0xAF, 0x6E,
+ 0xA8, 0x2B, 0x53, 0xA4, 0xBE, 0x96, 0xA5, 0x7B, 0xCE, 0x22, 0x56, 0xA3, 0xF1, 0xCF, 0x14,
+ 0xA5};
};
class PkgDerivedKey3Keyset {
public:
- // PkgDerivedKey3Keyset();
- //~PkgDerivedKey3Keyset();
-
- // Constructor
// std::uint8_t* PrivateExponent;
- const CryptoPP::byte* Exponent1;
+ static constexpr CryptoPP::byte Exponent1[] = {
+ 0x52, 0xCC, 0x2D, 0xA0, 0x9C, 0x9E, 0x75, 0xE7, 0x28, 0xEE, 0x3D, 0xDE, 0xE3, 0x45, 0xD1,
+ 0x4F, 0x94, 0x1C, 0xCC, 0xC8, 0x87, 0x29, 0x45, 0x3B, 0x8D, 0x6E, 0xAB, 0x6E, 0x2A, 0xA7,
+ 0xC7, 0x15, 0x43, 0xA3, 0x04, 0x8F, 0x90, 0x5F, 0xEB, 0xF3, 0x38, 0x4A, 0x77, 0xFA, 0x36,
+ 0xB7, 0x15, 0x76, 0xB6, 0x01, 0x1A, 0x8E, 0x25, 0x87, 0x82, 0xF1, 0x55, 0xD8, 0xC6, 0x43,
+ 0x2A, 0xC0, 0xE5, 0x98, 0xC9, 0x32, 0xD1, 0x94, 0x6F, 0xD9, 0x01, 0xBA, 0x06, 0x81, 0xE0,
+ 0x6D, 0x88, 0xF2, 0x24, 0x2A, 0x25, 0x01, 0x64, 0x5C, 0xBF, 0xF2, 0xD9, 0x99, 0x67, 0x3E,
+ 0xF6, 0x72, 0xEE, 0xE4, 0xE2, 0x33, 0x5C, 0xF8, 0x00, 0x40, 0xE3, 0x2A, 0x9A, 0xF4, 0x3D,
+ 0x22, 0x86, 0x44, 0x3C, 0xFB, 0x0A, 0xA5, 0x7C, 0x3F, 0xCC, 0xF5, 0xF1, 0x16, 0xC4, 0xAC,
+ 0x88, 0xB4, 0xDE, 0x62, 0x94, 0x92, 0x6A, 0x13};
// exponent2 = d mod (q - 1)
- const CryptoPP::byte* Exponent2;
+ static constexpr CryptoPP::byte Exponent2[] = {
+ 0x7C, 0x9D, 0xAD, 0x39, 0xE0, 0xD5, 0x60, 0x14, 0x94, 0x48, 0x19, 0x7F, 0x88, 0x95, 0xD5,
+ 0x8B, 0x80, 0xAD, 0x85, 0x8A, 0x4B, 0x77, 0x37, 0x85, 0xD0, 0x77, 0xBB, 0xBF, 0x89, 0x71,
+ 0x4A, 0x72, 0xCB, 0x72, 0x68, 0x38, 0xEC, 0x02, 0xC6, 0x7D, 0xC6, 0x44, 0x06, 0x33, 0x51,
+ 0x1C, 0xC0, 0xFF, 0x95, 0x8F, 0x0D, 0x75, 0xDC, 0x25, 0xBB, 0x0B, 0x73, 0x91, 0xA9, 0x6D,
+ 0x42, 0xD8, 0x03, 0xB7, 0x68, 0xD4, 0x1E, 0x75, 0x62, 0xA3, 0x70, 0x35, 0x79, 0x78, 0x00,
+ 0xC8, 0xF5, 0xEF, 0x15, 0xB9, 0xFC, 0x4E, 0x47, 0x5A, 0xC8, 0x70, 0x70, 0x5B, 0x52, 0x98,
+ 0xC0, 0xC2, 0x58, 0x4A, 0x70, 0x96, 0xCC, 0xB8, 0x10, 0xE1, 0x2F, 0x78, 0x8B, 0x2B, 0xA1,
+ 0x7F, 0xF9, 0xAC, 0xDE, 0xF0, 0xBB, 0x2B, 0xE2, 0x66, 0xE3, 0x22, 0x92, 0x31, 0x21, 0x57,
+ 0x92, 0xC4, 0xB8, 0xF2, 0x3E, 0x76, 0x20, 0x37};
// e
- const CryptoPP::byte* PublicExponent;
+ static constexpr CryptoPP::byte PublicExponent[] = {0, 1, 0, 1};
// (InverseQ)(q) = 1 mod p
- const CryptoPP::byte* Coefficient;
+ static constexpr CryptoPP::byte Coefficient[] = {
+ 0x45, 0x97, 0x55, 0xD4, 0x22, 0x08, 0x5E, 0xF3, 0x5C, 0xB4, 0x05, 0x7A, 0xFD, 0xAA, 0x42,
+ 0x42, 0xAD, 0x9A, 0x8C, 0xA0, 0x6C, 0xBB, 0x1D, 0x68, 0x54, 0x54, 0x6E, 0x3E, 0x32, 0xE3,
+ 0x53, 0x73, 0x76, 0xF1, 0x3E, 0x01, 0xEA, 0xD3, 0xCF, 0xEB, 0xEB, 0x23, 0x3E, 0xC0, 0xBE,
+ 0xCE, 0xEC, 0x2C, 0x89, 0x5F, 0xA8, 0x27, 0x3A, 0x4C, 0xB7, 0xE6, 0x74, 0xBC, 0x45, 0x4C,
+ 0x26, 0xC8, 0x25, 0xFF, 0x34, 0x63, 0x25, 0x37, 0xE1, 0x48, 0x10, 0xC1, 0x93, 0xA6, 0xAF,
+ 0xEB, 0xBA, 0xE3, 0xA2, 0xF1, 0x3D, 0xEF, 0x63, 0xD8, 0xF4, 0xFD, 0xD3, 0xEE, 0xE2, 0x5D,
+ 0xE9, 0x33, 0xCC, 0xAD, 0xBA, 0x75, 0x5C, 0x85, 0xAF, 0xCE, 0xA9, 0x3D, 0xD1, 0xA2, 0x17,
+ 0xF3, 0xF6, 0x98, 0xB3, 0x50, 0x8E, 0x5E, 0xF6, 0xEB, 0x02, 0x8E, 0xA1, 0x62, 0xA7, 0xD6,
+ 0x2C, 0xEC, 0x91, 0xFF, 0x15, 0x40, 0xD2, 0xE3};
// n = p * q
- const CryptoPP::byte* Modulus;
+ static constexpr CryptoPP::byte Modulus[] = {
+ 0xd2, 0x12, 0xfc, 0x33, 0x5f, 0x6d, 0xdb, 0x83, 0x16, 0x09, 0x62, 0x8b, 0x03, 0x56, 0x27,
+ 0x37, 0x82, 0xd4, 0x77, 0x85, 0x35, 0x29, 0x39, 0x2d, 0x52, 0x6b, 0x8c, 0x4c, 0x8c, 0xfb,
+ 0x06, 0xc1, 0x84, 0x5b, 0xe7, 0xd4, 0xf7, 0xbc, 0xd2, 0x4e, 0x62, 0x45, 0xcd, 0x2a, 0xbb,
+ 0xd7, 0x77, 0x76, 0x45, 0x36, 0x55, 0x27, 0x3f, 0xb3, 0xf5, 0xf9, 0x8e, 0xda, 0x4b, 0xef,
+ 0xaa, 0x59, 0xae, 0xb3, 0x9b, 0xea, 0x54, 0x98, 0xd2, 0x06, 0x32, 0x6a, 0x58, 0x31, 0x2a,
+ 0xe0, 0xd4, 0x4f, 0x90, 0xb5, 0x0a, 0x7d, 0xec, 0xf4, 0x3a, 0x9c, 0x52, 0x67, 0x2d, 0x99,
+ 0x31, 0x8e, 0x0c, 0x43, 0xe6, 0x82, 0xfe, 0x07, 0x46, 0xe1, 0x2e, 0x50, 0xd4, 0x1f, 0x2d,
+ 0x2f, 0x7e, 0xd9, 0x08, 0xba, 0x06, 0xb3, 0xbf, 0x2e, 0x20, 0x3f, 0x4e, 0x3f, 0xfe, 0x44,
+ 0xff, 0xaa, 0x50, 0x43, 0x57, 0x91, 0x69, 0x94, 0x49, 0x15, 0x82, 0x82, 0xe4, 0x0f, 0x4c,
+ 0x8d, 0x9d, 0x2c, 0xc9, 0x5b, 0x1d, 0x64, 0xbf, 0x88, 0x8b, 0xd4, 0xc5, 0x94, 0xe7, 0x65,
+ 0x47, 0x84, 0x1e, 0xe5, 0x79, 0x10, 0xfb, 0x98, 0x93, 0x47, 0xb9, 0x7d, 0x85, 0x12, 0xa6,
+ 0x40, 0x98, 0x2c, 0xf7, 0x92, 0xbc, 0x95, 0x19, 0x32, 0xed, 0xe8, 0x90, 0x56, 0x0d, 0x65,
+ 0xc1, 0xaa, 0x78, 0xc6, 0x2e, 0x54, 0xfd, 0x5f, 0x54, 0xa1, 0xf6, 0x7e, 0xe5, 0xe0, 0x5f,
+ 0x61, 0xc1, 0x20, 0xb4, 0xb9, 0xb4, 0x33, 0x08, 0x70, 0xe4, 0xdf, 0x89, 0x56, 0xed, 0x01,
+ 0x29, 0x46, 0x77, 0x5f, 0x8c, 0xb8, 0xa9, 0xf5, 0x1e, 0x2e, 0xb3, 0xb9, 0xbf, 0xe0, 0x09,
+ 0xb7, 0x8d, 0x28, 0xd4, 0xa6, 0xc3, 0xb8, 0x1e, 0x1f, 0x07, 0xeb, 0xb4, 0x12, 0x0b, 0x95,
+ 0xb8, 0x85, 0x30, 0xfd, 0xdc, 0x39, 0x13, 0xd0, 0x7c, 0xdc, 0x8f, 0xed, 0xf9, 0xc9, 0xa3,
+ 0xc1};
// p
- const CryptoPP::byte* Prime1;
+ static constexpr CryptoPP::byte Prime1[] = {
+ 0xF9, 0x67, 0xAD, 0x99, 0x12, 0x31, 0x0C, 0x56, 0xA2, 0x2E, 0x16, 0x1C, 0x46, 0xB3, 0x4D,
+ 0x5B, 0x43, 0xBE, 0x42, 0xA2, 0xF6, 0x86, 0x96, 0x80, 0x42, 0xC3, 0xC7, 0x3F, 0xC3, 0x42,
+ 0xF5, 0x87, 0x49, 0x33, 0x9F, 0x07, 0x5D, 0x6E, 0x2C, 0x04, 0xFD, 0xE3, 0xE1, 0xB2, 0xAE,
+ 0x0A, 0x0C, 0xF0, 0xC7, 0xA6, 0x1C, 0xA1, 0x63, 0x50, 0xC8, 0x09, 0x9C, 0x51, 0x24, 0x52,
+ 0x6C, 0x5E, 0x5E, 0xBD, 0x1E, 0x27, 0x06, 0xBB, 0xBC, 0x9E, 0x94, 0xE1, 0x35, 0xD4, 0x6D,
+ 0xB3, 0xCB, 0x3C, 0x68, 0xDD, 0x68, 0xB3, 0xFE, 0x6C, 0xCB, 0x8D, 0x82, 0x20, 0x76, 0x23,
+ 0x63, 0xB7, 0xE9, 0x68, 0x10, 0x01, 0x4E, 0xDC, 0xBA, 0x27, 0x5D, 0x01, 0xC1, 0x2D, 0x80,
+ 0x5E, 0x2B, 0xAF, 0x82, 0x6B, 0xD8, 0x84, 0xB6, 0x10, 0x52, 0x86, 0xA7, 0x89, 0x8E, 0xAE,
+ 0x9A, 0xE2, 0x89, 0xC6, 0xF7, 0xD5, 0x87, 0xFB};
// q
- const CryptoPP::byte* Prime2;
- const CryptoPP::byte* PrivateExponent;
-
- PkgDerivedKey3Keyset() {
-
- Prime1 = new CryptoPP::byte[0x80]{
- 0xF9, 0x67, 0xAD, 0x99, 0x12, 0x31, 0x0C, 0x56, 0xA2, 0x2E, 0x16, 0x1C, 0x46,
- 0xB3, 0x4D, 0x5B, 0x43, 0xBE, 0x42, 0xA2, 0xF6, 0x86, 0x96, 0x80, 0x42, 0xC3,
- 0xC7, 0x3F, 0xC3, 0x42, 0xF5, 0x87, 0x49, 0x33, 0x9F, 0x07, 0x5D, 0x6E, 0x2C,
- 0x04, 0xFD, 0xE3, 0xE1, 0xB2, 0xAE, 0x0A, 0x0C, 0xF0, 0xC7, 0xA6, 0x1C, 0xA1,
- 0x63, 0x50, 0xC8, 0x09, 0x9C, 0x51, 0x24, 0x52, 0x6C, 0x5E, 0x5E, 0xBD, 0x1E,
- 0x27, 0x06, 0xBB, 0xBC, 0x9E, 0x94, 0xE1, 0x35, 0xD4, 0x6D, 0xB3, 0xCB, 0x3C,
- 0x68, 0xDD, 0x68, 0xB3, 0xFE, 0x6C, 0xCB, 0x8D, 0x82, 0x20, 0x76, 0x23, 0x63,
- 0xB7, 0xE9, 0x68, 0x10, 0x01, 0x4E, 0xDC, 0xBA, 0x27, 0x5D, 0x01, 0xC1, 0x2D,
- 0x80, 0x5E, 0x2B, 0xAF, 0x82, 0x6B, 0xD8, 0x84, 0xB6, 0x10, 0x52, 0x86, 0xA7,
- 0x89, 0x8E, 0xAE, 0x9A, 0xE2, 0x89, 0xC6, 0xF7, 0xD5, 0x87, 0xFB};
-
- Prime2 = new CryptoPP::byte[0x80]{
- 0xD7, 0xA1, 0x0F, 0x9A, 0x8B, 0xF2, 0xC9, 0x11, 0x95, 0x32, 0x9A, 0x8C, 0xF0,
- 0xD9, 0x40, 0x47, 0xF5, 0x68, 0xA0, 0x0D, 0xBD, 0xC1, 0xFC, 0x43, 0x2F, 0x65,
- 0xF9, 0xC3, 0x61, 0x0F, 0x25, 0x77, 0x54, 0xAD, 0xD7, 0x58, 0xAC, 0x84, 0x40,
- 0x60, 0x8D, 0x3F, 0xF3, 0x65, 0x89, 0x75, 0xB5, 0xC6, 0x2C, 0x51, 0x1A, 0x2F,
- 0x1F, 0x22, 0xE4, 0x43, 0x11, 0x54, 0xBE, 0xC9, 0xB4, 0xC7, 0xB5, 0x1B, 0x05,
- 0x0B, 0xBC, 0x56, 0x9A, 0xCD, 0x4A, 0xD9, 0x73, 0x68, 0x5E, 0x5C, 0xFB, 0x92,
- 0xB7, 0x8B, 0x0D, 0xFF, 0xF5, 0x07, 0xCA, 0xB4, 0xC8, 0x9B, 0x96, 0x3C, 0x07,
- 0x9E, 0x3E, 0x6B, 0x2A, 0x11, 0xF2, 0x8A, 0xB1, 0x8A, 0xD7, 0x2E, 0x1B, 0xA5,
- 0x53, 0x24, 0x06, 0xED, 0x50, 0xB8, 0x90, 0x67, 0xB1, 0xE2, 0x41, 0xC6, 0x92,
- 0x01, 0xEE, 0x10, 0xF0, 0x61, 0xBB, 0xFB, 0xB2, 0x7D, 0x4A, 0x73};
- PrivateExponent = new CryptoPP::byte[0x100]{
- 0x32, 0xD9, 0x03, 0x90, 0x8F, 0xBD, 0xB0, 0x8F, 0x57, 0x2B, 0x28, 0x5E, 0x0B, 0x8D,
- 0xB3, 0xEA, 0x5C, 0xD1, 0x7E, 0xA8, 0x90, 0x88, 0x8C, 0xDD, 0x6A, 0x80, 0xBB, 0xB1,
- 0xDF, 0xC1, 0xF7, 0x0D, 0xAA, 0x32, 0xF0, 0xB7, 0x7C, 0xCB, 0x88, 0x80, 0x0E, 0x8B,
- 0x64, 0xB0, 0xBE, 0x4C, 0xD6, 0x0E, 0x9B, 0x8C, 0x1E, 0x2A, 0x64, 0xE1, 0xF3, 0x5C,
- 0xD7, 0x76, 0x01, 0x41, 0x5E, 0x93, 0x5C, 0x94, 0xFE, 0xDD, 0x46, 0x62, 0xC3, 0x1B,
- 0x5A, 0xE2, 0xA0, 0xBC, 0x2D, 0xEB, 0xC3, 0x98, 0x0A, 0xA7, 0xB7, 0x85, 0x69, 0x70,
- 0x68, 0x2B, 0x64, 0x4A, 0xB3, 0x1F, 0xCC, 0x7D, 0xDC, 0x7C, 0x26, 0xF4, 0x77, 0xF6,
- 0x5C, 0xF2, 0xAE, 0x5A, 0x44, 0x2D, 0xD3, 0xAB, 0x16, 0x62, 0x04, 0x19, 0xBA, 0xFB,
- 0x90, 0xFF, 0xE2, 0x30, 0x50, 0x89, 0x6E, 0xCB, 0x56, 0xB2, 0xEB, 0xC0, 0x91, 0x16,
- 0x92, 0x5E, 0x30, 0x8E, 0xAE, 0xC7, 0x94, 0x5D, 0xFD, 0x35, 0xE1, 0x20, 0xF8, 0xAD,
- 0x3E, 0xBC, 0x08, 0xBF, 0xC0, 0x36, 0x74, 0x9F, 0xD5, 0xBB, 0x52, 0x08, 0xFD, 0x06,
- 0x66, 0xF3, 0x7A, 0xB3, 0x04, 0xF4, 0x75, 0x29, 0x5D, 0xE9, 0x5F, 0xAA, 0x10, 0x30,
- 0xB2, 0x0F, 0x5A, 0x1A, 0xC1, 0x2A, 0xB3, 0xFE, 0xCB, 0x21, 0xAD, 0x80, 0xEC, 0x8F,
- 0x20, 0x09, 0x1C, 0xDB, 0xC5, 0x58, 0x94, 0xC2, 0x9C, 0xC6, 0xCE, 0x82, 0x65, 0x3E,
- 0x57, 0x90, 0xBC, 0xA9, 0x8B, 0x06, 0xB4, 0xF0, 0x72, 0xF6, 0x77, 0xDF, 0x98, 0x64,
- 0xF1, 0xEC, 0xFE, 0x37, 0x2D, 0xBC, 0xAE, 0x8C, 0x08, 0x81, 0x1F, 0xC3, 0xC9, 0x89,
- 0x1A, 0xC7, 0x42, 0x82, 0x4B, 0x2E, 0xDC, 0x8E, 0x8D, 0x73, 0xCE, 0xB1, 0xCC, 0x01,
- 0xD9, 0x08, 0x70, 0x87, 0x3C, 0x44, 0x08, 0xEC, 0x49, 0x8F, 0x81, 0x5A, 0xE2, 0x40,
- 0xFF, 0x77, 0xFC, 0x0D};
- Exponent1 = new CryptoPP::byte[0x80]{
- 0x52, 0xCC, 0x2D, 0xA0, 0x9C, 0x9E, 0x75, 0xE7, 0x28, 0xEE, 0x3D, 0xDE, 0xE3,
- 0x45, 0xD1, 0x4F, 0x94, 0x1C, 0xCC, 0xC8, 0x87, 0x29, 0x45, 0x3B, 0x8D, 0x6E,
- 0xAB, 0x6E, 0x2A, 0xA7, 0xC7, 0x15, 0x43, 0xA3, 0x04, 0x8F, 0x90, 0x5F, 0xEB,
- 0xF3, 0x38, 0x4A, 0x77, 0xFA, 0x36, 0xB7, 0x15, 0x76, 0xB6, 0x01, 0x1A, 0x8E,
- 0x25, 0x87, 0x82, 0xF1, 0x55, 0xD8, 0xC6, 0x43, 0x2A, 0xC0, 0xE5, 0x98, 0xC9,
- 0x32, 0xD1, 0x94, 0x6F, 0xD9, 0x01, 0xBA, 0x06, 0x81, 0xE0, 0x6D, 0x88, 0xF2,
- 0x24, 0x2A, 0x25, 0x01, 0x64, 0x5C, 0xBF, 0xF2, 0xD9, 0x99, 0x67, 0x3E, 0xF6,
- 0x72, 0xEE, 0xE4, 0xE2, 0x33, 0x5C, 0xF8, 0x00, 0x40, 0xE3, 0x2A, 0x9A, 0xF4,
- 0x3D, 0x22, 0x86, 0x44, 0x3C, 0xFB, 0x0A, 0xA5, 0x7C, 0x3F, 0xCC, 0xF5, 0xF1,
- 0x16, 0xC4, 0xAC, 0x88, 0xB4, 0xDE, 0x62, 0x94, 0x92, 0x6A, 0x13};
- Exponent2 = new CryptoPP::byte[0x80]{
- 0x7C, 0x9D, 0xAD, 0x39, 0xE0, 0xD5, 0x60, 0x14, 0x94, 0x48, 0x19, 0x7F, 0x88,
- 0x95, 0xD5, 0x8B, 0x80, 0xAD, 0x85, 0x8A, 0x4B, 0x77, 0x37, 0x85, 0xD0, 0x77,
- 0xBB, 0xBF, 0x89, 0x71, 0x4A, 0x72, 0xCB, 0x72, 0x68, 0x38, 0xEC, 0x02, 0xC6,
- 0x7D, 0xC6, 0x44, 0x06, 0x33, 0x51, 0x1C, 0xC0, 0xFF, 0x95, 0x8F, 0x0D, 0x75,
- 0xDC, 0x25, 0xBB, 0x0B, 0x73, 0x91, 0xA9, 0x6D, 0x42, 0xD8, 0x03, 0xB7, 0x68,
- 0xD4, 0x1E, 0x75, 0x62, 0xA3, 0x70, 0x35, 0x79, 0x78, 0x00, 0xC8, 0xF5, 0xEF,
- 0x15, 0xB9, 0xFC, 0x4E, 0x47, 0x5A, 0xC8, 0x70, 0x70, 0x5B, 0x52, 0x98, 0xC0,
- 0xC2, 0x58, 0x4A, 0x70, 0x96, 0xCC, 0xB8, 0x10, 0xE1, 0x2F, 0x78, 0x8B, 0x2B,
- 0xA1, 0x7F, 0xF9, 0xAC, 0xDE, 0xF0, 0xBB, 0x2B, 0xE2, 0x66, 0xE3, 0x22, 0x92,
- 0x31, 0x21, 0x57, 0x92, 0xC4, 0xB8, 0xF2, 0x3E, 0x76, 0x20, 0x37};
- Coefficient = new CryptoPP::byte[0x80]{
- 0x45, 0x97, 0x55, 0xD4, 0x22, 0x08, 0x5E, 0xF3, 0x5C, 0xB4, 0x05, 0x7A, 0xFD,
- 0xAA, 0x42, 0x42, 0xAD, 0x9A, 0x8C, 0xA0, 0x6C, 0xBB, 0x1D, 0x68, 0x54, 0x54,
- 0x6E, 0x3E, 0x32, 0xE3, 0x53, 0x73, 0x76, 0xF1, 0x3E, 0x01, 0xEA, 0xD3, 0xCF,
- 0xEB, 0xEB, 0x23, 0x3E, 0xC0, 0xBE, 0xCE, 0xEC, 0x2C, 0x89, 0x5F, 0xA8, 0x27,
- 0x3A, 0x4C, 0xB7, 0xE6, 0x74, 0xBC, 0x45, 0x4C, 0x26, 0xC8, 0x25, 0xFF, 0x34,
- 0x63, 0x25, 0x37, 0xE1, 0x48, 0x10, 0xC1, 0x93, 0xA6, 0xAF, 0xEB, 0xBA, 0xE3,
- 0xA2, 0xF1, 0x3D, 0xEF, 0x63, 0xD8, 0xF4, 0xFD, 0xD3, 0xEE, 0xE2, 0x5D, 0xE9,
- 0x33, 0xCC, 0xAD, 0xBA, 0x75, 0x5C, 0x85, 0xAF, 0xCE, 0xA9, 0x3D, 0xD1, 0xA2,
- 0x17, 0xF3, 0xF6, 0x98, 0xB3, 0x50, 0x8E, 0x5E, 0xF6, 0xEB, 0x02, 0x8E, 0xA1,
- 0x62, 0xA7, 0xD6, 0x2C, 0xEC, 0x91, 0xFF, 0x15, 0x40, 0xD2, 0xE3};
- Modulus = new CryptoPP::byte[0x100]{
- 0xd2, 0x12, 0xfc, 0x33, 0x5f, 0x6d, 0xdb, 0x83, 0x16, 0x09, 0x62, 0x8b, 0x03, 0x56,
- 0x27, 0x37, 0x82, 0xd4, 0x77, 0x85, 0x35, 0x29, 0x39, 0x2d, 0x52, 0x6b, 0x8c, 0x4c,
- 0x8c, 0xfb, 0x06, 0xc1, 0x84, 0x5b, 0xe7, 0xd4, 0xf7, 0xbc, 0xd2, 0x4e, 0x62, 0x45,
- 0xcd, 0x2a, 0xbb, 0xd7, 0x77, 0x76, 0x45, 0x36, 0x55, 0x27, 0x3f, 0xb3, 0xf5, 0xf9,
- 0x8e, 0xda, 0x4b, 0xef, 0xaa, 0x59, 0xae, 0xb3, 0x9b, 0xea, 0x54, 0x98, 0xd2, 0x06,
- 0x32, 0x6a, 0x58, 0x31, 0x2a, 0xe0, 0xd4, 0x4f, 0x90, 0xb5, 0x0a, 0x7d, 0xec, 0xf4,
- 0x3a, 0x9c, 0x52, 0x67, 0x2d, 0x99, 0x31, 0x8e, 0x0c, 0x43, 0xe6, 0x82, 0xfe, 0x07,
- 0x46, 0xe1, 0x2e, 0x50, 0xd4, 0x1f, 0x2d, 0x2f, 0x7e, 0xd9, 0x08, 0xba, 0x06, 0xb3,
- 0xbf, 0x2e, 0x20, 0x3f, 0x4e, 0x3f, 0xfe, 0x44, 0xff, 0xaa, 0x50, 0x43, 0x57, 0x91,
- 0x69, 0x94, 0x49, 0x15, 0x82, 0x82, 0xe4, 0x0f, 0x4c, 0x8d, 0x9d, 0x2c, 0xc9, 0x5b,
- 0x1d, 0x64, 0xbf, 0x88, 0x8b, 0xd4, 0xc5, 0x94, 0xe7, 0x65, 0x47, 0x84, 0x1e, 0xe5,
- 0x79, 0x10, 0xfb, 0x98, 0x93, 0x47, 0xb9, 0x7d, 0x85, 0x12, 0xa6, 0x40, 0x98, 0x2c,
- 0xf7, 0x92, 0xbc, 0x95, 0x19, 0x32, 0xed, 0xe8, 0x90, 0x56, 0x0d, 0x65, 0xc1, 0xaa,
- 0x78, 0xc6, 0x2e, 0x54, 0xfd, 0x5f, 0x54, 0xa1, 0xf6, 0x7e, 0xe5, 0xe0, 0x5f, 0x61,
- 0xc1, 0x20, 0xb4, 0xb9, 0xb4, 0x33, 0x08, 0x70, 0xe4, 0xdf, 0x89, 0x56, 0xed, 0x01,
- 0x29, 0x46, 0x77, 0x5f, 0x8c, 0xb8, 0xa9, 0xf5, 0x1e, 0x2e, 0xb3, 0xb9, 0xbf, 0xe0,
- 0x09, 0xb7, 0x8d, 0x28, 0xd4, 0xa6, 0xc3, 0xb8, 0x1e, 0x1f, 0x07, 0xeb, 0xb4, 0x12,
- 0x0b, 0x95, 0xb8, 0x85, 0x30, 0xfd, 0xdc, 0x39, 0x13, 0xd0, 0x7c, 0xdc, 0x8f, 0xed,
- 0xf9, 0xc9, 0xa3, 0xc1};
- PublicExponent = new CryptoPP::byte[4]{0, 1, 0, 1};
- };
+ static constexpr CryptoPP::byte Prime2[] = {
+ 0xD7, 0xA1, 0x0F, 0x9A, 0x8B, 0xF2, 0xC9, 0x11, 0x95, 0x32, 0x9A, 0x8C, 0xF0, 0xD9, 0x40,
+ 0x47, 0xF5, 0x68, 0xA0, 0x0D, 0xBD, 0xC1, 0xFC, 0x43, 0x2F, 0x65, 0xF9, 0xC3, 0x61, 0x0F,
+ 0x25, 0x77, 0x54, 0xAD, 0xD7, 0x58, 0xAC, 0x84, 0x40, 0x60, 0x8D, 0x3F, 0xF3, 0x65, 0x89,
+ 0x75, 0xB5, 0xC6, 0x2C, 0x51, 0x1A, 0x2F, 0x1F, 0x22, 0xE4, 0x43, 0x11, 0x54, 0xBE, 0xC9,
+ 0xB4, 0xC7, 0xB5, 0x1B, 0x05, 0x0B, 0xBC, 0x56, 0x9A, 0xCD, 0x4A, 0xD9, 0x73, 0x68, 0x5E,
+ 0x5C, 0xFB, 0x92, 0xB7, 0x8B, 0x0D, 0xFF, 0xF5, 0x07, 0xCA, 0xB4, 0xC8, 0x9B, 0x96, 0x3C,
+ 0x07, 0x9E, 0x3E, 0x6B, 0x2A, 0x11, 0xF2, 0x8A, 0xB1, 0x8A, 0xD7, 0x2E, 0x1B, 0xA5, 0x53,
+ 0x24, 0x06, 0xED, 0x50, 0xB8, 0x90, 0x67, 0xB1, 0xE2, 0x41, 0xC6, 0x92, 0x01, 0xEE, 0x10,
+ 0xF0, 0x61, 0xBB, 0xFB, 0xB2, 0x7D, 0x4A, 0x73};
+ static constexpr CryptoPP::byte PrivateExponent[] = {
+ 0x32, 0xD9, 0x03, 0x90, 0x8F, 0xBD, 0xB0, 0x8F, 0x57, 0x2B, 0x28, 0x5E, 0x0B, 0x8D, 0xB3,
+ 0xEA, 0x5C, 0xD1, 0x7E, 0xA8, 0x90, 0x88, 0x8C, 0xDD, 0x6A, 0x80, 0xBB, 0xB1, 0xDF, 0xC1,
+ 0xF7, 0x0D, 0xAA, 0x32, 0xF0, 0xB7, 0x7C, 0xCB, 0x88, 0x80, 0x0E, 0x8B, 0x64, 0xB0, 0xBE,
+ 0x4C, 0xD6, 0x0E, 0x9B, 0x8C, 0x1E, 0x2A, 0x64, 0xE1, 0xF3, 0x5C, 0xD7, 0x76, 0x01, 0x41,
+ 0x5E, 0x93, 0x5C, 0x94, 0xFE, 0xDD, 0x46, 0x62, 0xC3, 0x1B, 0x5A, 0xE2, 0xA0, 0xBC, 0x2D,
+ 0xEB, 0xC3, 0x98, 0x0A, 0xA7, 0xB7, 0x85, 0x69, 0x70, 0x68, 0x2B, 0x64, 0x4A, 0xB3, 0x1F,
+ 0xCC, 0x7D, 0xDC, 0x7C, 0x26, 0xF4, 0x77, 0xF6, 0x5C, 0xF2, 0xAE, 0x5A, 0x44, 0x2D, 0xD3,
+ 0xAB, 0x16, 0x62, 0x04, 0x19, 0xBA, 0xFB, 0x90, 0xFF, 0xE2, 0x30, 0x50, 0x89, 0x6E, 0xCB,
+ 0x56, 0xB2, 0xEB, 0xC0, 0x91, 0x16, 0x92, 0x5E, 0x30, 0x8E, 0xAE, 0xC7, 0x94, 0x5D, 0xFD,
+ 0x35, 0xE1, 0x20, 0xF8, 0xAD, 0x3E, 0xBC, 0x08, 0xBF, 0xC0, 0x36, 0x74, 0x9F, 0xD5, 0xBB,
+ 0x52, 0x08, 0xFD, 0x06, 0x66, 0xF3, 0x7A, 0xB3, 0x04, 0xF4, 0x75, 0x29, 0x5D, 0xE9, 0x5F,
+ 0xAA, 0x10, 0x30, 0xB2, 0x0F, 0x5A, 0x1A, 0xC1, 0x2A, 0xB3, 0xFE, 0xCB, 0x21, 0xAD, 0x80,
+ 0xEC, 0x8F, 0x20, 0x09, 0x1C, 0xDB, 0xC5, 0x58, 0x94, 0xC2, 0x9C, 0xC6, 0xCE, 0x82, 0x65,
+ 0x3E, 0x57, 0x90, 0xBC, 0xA9, 0x8B, 0x06, 0xB4, 0xF0, 0x72, 0xF6, 0x77, 0xDF, 0x98, 0x64,
+ 0xF1, 0xEC, 0xFE, 0x37, 0x2D, 0xBC, 0xAE, 0x8C, 0x08, 0x81, 0x1F, 0xC3, 0xC9, 0x89, 0x1A,
+ 0xC7, 0x42, 0x82, 0x4B, 0x2E, 0xDC, 0x8E, 0x8D, 0x73, 0xCE, 0xB1, 0xCC, 0x01, 0xD9, 0x08,
+ 0x70, 0x87, 0x3C, 0x44, 0x08, 0xEC, 0x49, 0x8F, 0x81, 0x5A, 0xE2, 0x40, 0xFF, 0x77, 0xFC,
+ 0x0D};
};
\ No newline at end of file
diff --git a/src/core/file_format/pkg.cpp b/src/core/file_format/pkg.cpp
index 336d81019..d86f3b28d 100644
--- a/src/core/file_format/pkg.cpp
+++ b/src/core/file_format/pkg.cpp
@@ -67,15 +67,19 @@ bool PKG::Open(const std::filesystem::path& filepath) {
file.Seek(0x47); // skip first 7 characters of content_id
file.Read(pkgTitleID);
- file.Seek(0);
- pkg.resize(pkgheader.pkg_promote_size);
- file.Read(pkg);
-
u32 offset = pkgheader.pkg_table_entry_offset;
u32 n_files = pkgheader.pkg_table_entry_count;
+
+ file.Seek(offset);
for (int i = 0; i < n_files; i++) {
- PKGEntry entry;
- std::memcpy(&entry, &pkg[offset + i * 0x20], sizeof(entry));
+ PKGEntry entry{};
+ file.Read(entry.id);
+ file.Read(entry.filename_offset);
+ file.Read(entry.flags1);
+ file.Read(entry.flags2);
+ file.Read(entry.offset);
+ file.Read(entry.size);
+ file.Seek(8, Common::FS::SeekOrigin::CurrentPosition);
// Try to figure out the name
const auto name = GetEntryNameByType(entry.id);
@@ -113,9 +117,6 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::
failreason = "Content size is bigger than pkg size";
return false;
}
- file.Seek(0);
- pkg.resize(pkgheader.pkg_promote_size);
- file.Read(pkg);
u32 offset = pkgheader.pkg_table_entry_offset;
u32 n_files = pkgheader.pkg_table_entry_count;
@@ -126,9 +127,18 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::
std::array, 7> key1;
std::array imgkeydata;
+ file.Seek(offset);
for (int i = 0; i < n_files; i++) {
- PKGEntry entry;
- std::memcpy(&entry, &pkg[offset + i * 0x20], sizeof(entry));
+ PKGEntry entry{};
+ file.Read(entry.id);
+ file.Read(entry.filename_offset);
+ file.Read(entry.flags1);
+ file.Read(entry.flags2);
+ file.Read(entry.offset);
+ file.Read(entry.size);
+ file.Seek(8, Common::FS::SeekOrigin::CurrentPosition);
+
+ auto currentPos = file.Tell();
// Try to figure out the name
const auto name = GetEntryNameByType(entry.id);
@@ -139,8 +149,15 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::
// Just print with id
Common::FS::IOFile out(extract_path / "sce_sys" / std::to_string(entry.id),
Common::FS::FileAccessMode::Write);
- out.WriteRaw(pkg.data() + entry.offset, entry.size);
+ file.Seek(entry.offset);
+
+ std::vector data;
+ data.resize(entry.size);
+ file.ReadRaw(data.data(), entry.size);
+ out.WriteRaw(data.data(), entry.size);
out.Close();
+
+ file.Seek(currentPos);
continue;
}
@@ -178,14 +195,25 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::
}
Common::FS::IOFile out(extract_path / "sce_sys" / name, Common::FS::FileAccessMode::Write);
- out.WriteRaw(pkg.data() + entry.offset, entry.size);
+ file.Seek(entry.offset);
+
+ std::vector data;
+ data.resize(entry.size);
+ file.ReadRaw(data.data(), entry.size);
+ out.WriteRaw(data.data(), entry.size);
out.Close();
// Decrypt Np stuff and overwrite.
if (entry.id == 0x400 || entry.id == 0x401 || entry.id == 0x402 ||
entry.id == 0x403) { // somehow 0x401 is not decrypting
decNp.resize(entry.size);
- std::span cipherNp(pkg.data() + entry.offset, entry.size);
+ file.Seek(entry.offset);
+
+ std::vector data;
+ data.resize(entry.size);
+ file.ReadRaw(data.data(), entry.size);
+
+ std::span cipherNp(data.data(), entry.size);
std::array concatenated_ivkey_dk3_;
std::memcpy(concatenated_ivkey_dk3_.data(), &entry, sizeof(entry));
std::memcpy(concatenated_ivkey_dk3_.data() + sizeof(entry), dk3_.data(), sizeof(dk3_));
@@ -197,6 +225,8 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::
out.Write(decNp);
out.Close();
}
+
+ file.Seek(currentPos);
}
// Extract trophy files
@@ -214,28 +244,31 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::
PKG::crypto.PfsGenCryptoKey(ekpfsKey, seed, dataKey, tweakKey);
const u32 length = pkgheader.pfs_cache_size * 0x2; // Seems to be ok.
- // Read encrypted pfs_image
- std::vector pfs_encrypted(length);
- file.Seek(pkgheader.pfs_image_offset);
- file.Read(pfs_encrypted);
- file.Close();
- // Decrypt the pfs_image.
- std::vector pfs_decrypted(length);
- PKG::crypto.decryptPFS(dataKey, tweakKey, pfs_encrypted, pfs_decrypted, 0);
-
- // Retrieve PFSC from decrypted pfs_image.
- pfsc_offset = GetPFSCOffset(pfs_decrypted);
+ int num_blocks = 0;
std::vector pfsc(length);
- std::memcpy(pfsc.data(), pfs_decrypted.data() + pfsc_offset, length - pfsc_offset);
+ if (length != 0) {
+ // Read encrypted pfs_image
+ std::vector pfs_encrypted(length);
+ file.Seek(pkgheader.pfs_image_offset);
+ file.Read(pfs_encrypted);
+ file.Close();
+ // Decrypt the pfs_image.
+ std::vector pfs_decrypted(length);
+ PKG::crypto.decryptPFS(dataKey, tweakKey, pfs_encrypted, pfs_decrypted, 0);
- PFSCHdr pfsChdr;
- std::memcpy(&pfsChdr, pfsc.data(), sizeof(pfsChdr));
+ // Retrieve PFSC from decrypted pfs_image.
+ pfsc_offset = GetPFSCOffset(pfs_decrypted);
+ std::memcpy(pfsc.data(), pfs_decrypted.data() + pfsc_offset, length - pfsc_offset);
- const int num_blocks = (int)(pfsChdr.data_length / pfsChdr.block_sz2);
- sectorMap.resize(num_blocks + 1); // 8 bytes, need extra 1 to get the last offset.
+ PFSCHdr pfsChdr;
+ std::memcpy(&pfsChdr, pfsc.data(), sizeof(pfsChdr));
- for (int i = 0; i < num_blocks + 1; i++) {
- std::memcpy(§orMap[i], pfsc.data() + pfsChdr.block_offsets + i * 8, 8);
+ num_blocks = (int)(pfsChdr.data_length / pfsChdr.block_sz2);
+ sectorMap.resize(num_blocks + 1); // 8 bytes, need extra 1 to get the last offset.
+
+ for (int i = 0; i < num_blocks + 1; i++) {
+ std::memcpy(§orMap[i], pfsc.data() + pfsChdr.block_offsets + i * 8, 8);
+ }
}
u32 ent_size = 0;
@@ -279,8 +312,8 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::
}
}
- // let's deal with the root/uroot enteries here.
- // Sometimes it's more than 2 enteries (Tomb Raider Remastered)
+ // let's deal with the root/uroot entries here.
+ // Sometimes it's more than 2 entries (Tomb Raider Remastered)
const std::string_view flat_path_table(&decompressedData[0x10], 15);
if (flat_path_table == "flat_path_table") {
uroot_reached = true;
@@ -296,7 +329,15 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::
} else {
// Set the the folder according to the current inode.
// Can be 2 or more (rarely)
- extractPaths[ndinode_counter] = extract_path.parent_path() / GetTitleID();
+ auto parent_path = extract_path.parent_path();
+ auto title_id = GetTitleID();
+
+ if (parent_path.filename() != title_id) {
+ extractPaths[ndinode_counter] = parent_path / title_id;
+ } else {
+ // DLCs path has different structure
+ extractPaths[ndinode_counter] = extract_path;
+ }
uroot_reached = false;
break;
}
diff --git a/src/core/file_format/pkg.h b/src/core/file_format/pkg.h
index b6b09a191..d30d50b44 100644
--- a/src/core/file_format/pkg.h
+++ b/src/core/file_format/pkg.h
@@ -149,7 +149,6 @@ public:
private:
Crypto crypto;
TRP trp;
- std::vector pkg;
u64 pkgSize = 0;
char pkgTitleID[9];
PKGHeader pkgheader;
diff --git a/src/core/file_format/playgo_chunk.cpp b/src/core/file_format/playgo_chunk.cpp
index a430b1ac1..4e2faea45 100644
--- a/src/core/file_format/playgo_chunk.cpp
+++ b/src/core/file_format/playgo_chunk.cpp
@@ -60,7 +60,7 @@ bool PlaygoFile::LoadChunks(const Common::FS::IOFile& file) {
return false;
}
-bool PlaygoFile::load_chunk_data(const Common::FS::IOFile& file, const chunk_t& chunk,
+bool PlaygoFile::load_chunk_data(const Common::FS::IOFile& file, const chunk_t chunk,
std::string& data) {
if (file.IsOpen()) {
if (file.Seek(chunk.offset)) {
diff --git a/src/core/file_format/playgo_chunk.h b/src/core/file_format/playgo_chunk.h
index 439e27d05..b6d38e0e1 100644
--- a/src/core/file_format/playgo_chunk.h
+++ b/src/core/file_format/playgo_chunk.h
@@ -123,7 +123,7 @@ public:
}
private:
- bool load_chunk_data(const Common::FS::IOFile& file, const chunk_t& chunk, std::string& data);
+ bool load_chunk_data(const Common::FS::IOFile& file, const chunk_t chunk, std::string& data);
private:
PlaygoHeader playgoHeader;
diff --git a/src/core/file_format/psf.cpp b/src/core/file_format/psf.cpp
index c11dc05c8..3d076acdc 100644
--- a/src/core/file_format/psf.cpp
+++ b/src/core/file_format/psf.cpp
@@ -9,7 +9,7 @@ PSF::PSF() = default;
PSF::~PSF() = default;
-bool PSF::open(const std::string& filepath, std::vector psfBuffer) {
+bool PSF::open(const std::string& filepath, const std::vector& psfBuffer) {
if (!psfBuffer.empty()) {
psf.resize(psfBuffer.size());
psf = psfBuffer;
diff --git a/src/core/file_format/psf.h b/src/core/file_format/psf.h
index 17e515de2..9a162b1d5 100644
--- a/src/core/file_format/psf.h
+++ b/src/core/file_format/psf.h
@@ -35,7 +35,7 @@ public:
PSF();
~PSF();
- bool open(const std::string& filepath, std::vector psfBuffer);
+ bool open(const std::string& filepath, const std::vector& psfBuffer);
std::string GetString(const std::string& key);
u32 GetInteger(const std::string& key);
diff --git a/src/core/file_sys/fs.cpp b/src/core/file_sys/fs.cpp
index 40d8212bb..199e42a04 100644
--- a/src/core/file_sys/fs.cpp
+++ b/src/core/file_sys/fs.cpp
@@ -48,7 +48,7 @@ std::filesystem::path MntPoints::GetHostPath(std::string_view guest_directory) {
pos = mount->mount.size() + 1;
const auto rel_path = std::string_view(corrected_path).substr(pos);
const auto host_path = mount->host_path / rel_path;
- if (!NeedsCaseInsensiveSearch) {
+ if (!NeedsCaseInsensitiveSearch) {
return host_path;
}
diff --git a/src/core/file_sys/fs.h b/src/core/file_sys/fs.h
index b0fb63242..2c55b0513 100644
--- a/src/core/file_sys/fs.h
+++ b/src/core/file_sys/fs.h
@@ -14,9 +14,9 @@ namespace Core::FileSys {
class MntPoints {
#ifdef _WIN64
- static constexpr bool NeedsCaseInsensiveSearch = false;
+ static constexpr bool NeedsCaseInsensitiveSearch = false;
#else
- static constexpr bool NeedsCaseInsensiveSearch = true;
+ static constexpr bool NeedsCaseInsensitiveSearch = true;
#endif
public:
struct MntPair {
diff --git a/src/core/libraries/ajm/ajm.cpp b/src/core/libraries/ajm/ajm.cpp
index d8d8304ab..441a07f63 100644
--- a/src/core/libraries/ajm/ajm.cpp
+++ b/src/core/libraries/ajm/ajm.cpp
@@ -1,9 +1,10 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-// Generated By moduleGenerator
+#include "ajm.h"
+#include "ajm_error.h"
+
#include "common/logging/log.h"
-#include "core/libraries/ajm/ajm.h"
#include "core/libraries/error_codes.h"
#include "core/libraries/libs.h"
diff --git a/src/core/libraries/ajm/ajm_error.h b/src/core/libraries/ajm/ajm_error.h
new file mode 100644
index 000000000..64129554f
--- /dev/null
+++ b/src/core/libraries/ajm/ajm_error.h
@@ -0,0 +1,28 @@
+// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+constexpr int ORBIS_AJM_ERROR_UNKNOWN = 0x80930001;
+constexpr int ORBIS_AJM_ERROR_INVALID_CONTEXT = 0x80930002;
+constexpr int ORBIS_AJM_ERROR_INVALID_INSTANCE = 0x80930003;
+constexpr int ORBIS_AJM_ERROR_INVALID_BATCH = 0x80930004;
+constexpr int ORBIS_AJM_ERROR_INVALID_PARAMETER = 0x80930005;
+constexpr int ORBIS_AJM_ERROR_OUT_OF_MEMORY = 0x80930006;
+constexpr int ORBIS_AJM_ERROR_OUT_OF_RESOURCES = 0x80930007;
+constexpr int ORBIS_AJM_ERROR_CODEC_NOT_SUPPORTED = 0x80930008;
+constexpr int ORBIS_AJM_ERROR_CODEC_ALREADY_REGISTERED = 0x80930009;
+constexpr int ORBIS_AJM_ERROR_CODEC_NOT_REGISTERED = 0x8093000A;
+constexpr int ORBIS_AJM_ERROR_WRONG_REVISION_FLAG = 0x8093000B;
+constexpr int ORBIS_AJM_ERROR_FLAG_NOT_SUPPORTED = 0x8093000C;
+constexpr int ORBIS_AJM_ERROR_BUSY = 0x8093000D;
+constexpr int ORBIS_AJM_ERROR_BAD_PRIORITY = 0x8093000E;
+constexpr int ORBIS_AJM_ERROR_IN_PROGRESS = 0x8093000F;
+constexpr int ORBIS_AJM_ERROR_RETRY = 0x80930010;
+constexpr int ORBIS_AJM_ERROR_MALFORMED_BATCH = 0x80930011;
+constexpr int ORBIS_AJM_ERROR_JOB_CREATION = 0x80930012;
+constexpr int ORBIS_AJM_ERROR_INVALID_OPCODE = 0x80930013;
+constexpr int ORBIS_AJM_ERROR_PRIORITY_VIOLATION = 0x80930014;
+constexpr int ORBIS_AJM_ERROR_BUFFER_TOO_BIG = 0x80930015;
+constexpr int ORBIS_AJM_ERROR_INVALID_ADDRESS = 0x80930016;
+constexpr int ORBIS_AJM_ERROR_CANCELLED = 0x80930017;
diff --git a/src/core/libraries/app_content/app_content.cpp b/src/core/libraries/app_content/app_content.cpp
index 882f99e49..125d19684 100644
--- a/src/core/libraries/app_content/app_content.cpp
+++ b/src/core/libraries/app_content/app_content.cpp
@@ -1,20 +1,38 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-// Generated By moduleGenerator
#include
-#include
-#include
-#include
-#include
+
#include "app_content.h"
#include "common/io_file.h"
#include "common/logging/log.h"
+#include "common/path_util.h"
+#include "common/singleton.h"
+#include "common/string_util.h"
+#include "core/file_format/psf.h"
+#include "core/file_sys/fs.h"
#include "core/libraries/error_codes.h"
#include "core/libraries/libs.h"
namespace Libraries::AppContent {
+int32_t addcont_count = 0;
+
+struct AddContInfo {
+ char entitlementLabel[ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE];
+ OrbisAppContentAddcontDownloadStatus status;
+ OrbisAppContentGetEntitlementKey key;
+};
+
+std::array addcont_info = {{
+ {"0000000000000000",
+ ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_INSTALLED,
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00}},
+}};
+
+std::string title_id;
+
int PS4_SYSV_ABI _Z5dummyv() {
LOG_ERROR(Lib_AppContent, "(STUBBED) called");
return ORBIS_OK;
@@ -35,9 +53,31 @@ int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownloadSp() {
return ORBIS_OK;
}
-int PS4_SYSV_ABI sceAppContentAddcontMount() {
- LOG_ERROR(Lib_AppContent, "(STUBBED) called");
- return ORBIS_OK;
+int PS4_SYSV_ABI sceAppContentAddcontMount(u32 service_label,
+ const OrbisNpUnifiedEntitlementLabel* entitlement_label,
+ OrbisAppContentMountPoint* mount_point) {
+ LOG_INFO(Lib_AppContent, "called");
+
+ const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::AddonsDir) / title_id /
+ entitlement_label->data;
+ auto* mnt = Common::Singleton::Instance();
+
+ for (int i = 0; i < addcont_count; i++) {
+ if (strncmp(entitlement_label->data, addcont_info[i].entitlementLabel,
+ ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE - 1) != 0) {
+ continue;
+ }
+
+ if (addcont_info[i].status != ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_INSTALLED) {
+ return ORBIS_APP_CONTENT_ERROR_NOT_FOUND;
+ }
+
+ snprintf(mount_point->data, ORBIS_APP_CONTENT_MOUNTPOINT_DATA_MAXSIZE, "/addcont%d", i);
+ mnt->Mount(mount_dir, mount_point->data);
+ return ORBIS_OK;
+ }
+
+ return ORBIS_APP_CONTENT_ERROR_NOT_FOUND;
}
int PS4_SYSV_ABI sceAppContentAddcontShrink() {
@@ -124,22 +164,80 @@ int PS4_SYSV_ABI sceAppContentGetAddcontDownloadProgress() {
return ORBIS_OK;
}
-int PS4_SYSV_ABI sceAppContentGetAddcontInfo() {
- LOG_ERROR(Lib_AppContent, "(STUBBED) called");
- return ORBIS_OK;
+int PS4_SYSV_ABI sceAppContentGetAddcontInfo(u32 service_label,
+ const OrbisNpUnifiedEntitlementLabel* entitlementLabel,
+ OrbisAppContentAddcontInfo* info) {
+ LOG_INFO(Lib_AppContent, "called");
+
+ if (entitlementLabel == nullptr || info == nullptr) {
+ return ORBIS_APP_CONTENT_ERROR_PARAMETER;
+ }
+
+ for (auto i = 0; i < addcont_count; i++) {
+ if (strncmp(entitlementLabel->data, addcont_info[i].entitlementLabel,
+ ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE - 1) != 0) {
+ continue;
+ }
+
+ LOG_INFO(Lib_AppContent, "found DLC {}", entitlementLabel->data);
+
+ strncpy(info->entitlement_label.data, addcont_info[i].entitlementLabel,
+ ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE);
+ info->status = addcont_info[i].status;
+ return ORBIS_OK;
+ }
+
+ return ORBIS_APP_CONTENT_ERROR_DRM_NO_ENTITLEMENT;
}
int PS4_SYSV_ABI sceAppContentGetAddcontInfoList(u32 service_label,
OrbisAppContentAddcontInfo* list, u32 list_num,
u32* hit_num) {
- *hit_num = 0;
- LOG_ERROR(Lib_AppContent, "(DUMMY) called");
+ LOG_INFO(Lib_AppContent, "called");
+
+ if (list_num == 0 || list == nullptr) {
+ if (hit_num == nullptr) {
+ return ORBIS_APP_CONTENT_ERROR_PARAMETER;
+ }
+
+ *hit_num = addcont_count;
+ return ORBIS_OK;
+ }
+
+ int dlcs_to_list = addcont_count < list_num ? addcont_count : list_num;
+ for (int i = 0; i < dlcs_to_list; i++) {
+ strncpy(list[i].entitlement_label.data, addcont_info[i].entitlementLabel,
+ ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE);
+ list[i].status = addcont_info[i].status;
+ }
+
+ if (hit_num != nullptr) {
+ *hit_num = dlcs_to_list;
+ }
+
return ORBIS_OK;
}
-int PS4_SYSV_ABI sceAppContentGetEntitlementKey() {
- LOG_ERROR(Lib_AppContent, "(STUBBED) called");
- return ORBIS_OK;
+int PS4_SYSV_ABI sceAppContentGetEntitlementKey(
+ u32 service_label, const OrbisNpUnifiedEntitlementLabel* entitlement_label,
+ OrbisAppContentGetEntitlementKey* key) {
+ LOG_ERROR(Lib_AppContent, "called");
+
+ if (entitlement_label == nullptr || key == nullptr) {
+ return ORBIS_APP_CONTENT_ERROR_PARAMETER;
+ }
+
+ for (int i = 0; i < addcont_count; i++) {
+ if (strncmp(entitlement_label->data, addcont_info[i].entitlementLabel,
+ ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE - 1) != 0) {
+ continue;
+ }
+
+ memcpy(key->data, addcont_info[i].key.data, ORBIS_APP_CONTENT_ENTITLEMENT_KEY_SIZE);
+ return ORBIS_OK;
+ }
+
+ return ORBIS_APP_CONTENT_ERROR_DRM_NO_ENTITLEMENT;
}
int PS4_SYSV_ABI sceAppContentGetRegion() {
@@ -150,7 +248,25 @@ int PS4_SYSV_ABI sceAppContentGetRegion() {
int PS4_SYSV_ABI sceAppContentInitialize(const OrbisAppContentInitParam* initParam,
OrbisAppContentBootParam* bootParam) {
LOG_ERROR(Lib_AppContent, "(DUMMY) called");
- bootParam->attr = 0; // always 0
+ auto* param_sfo = Common::Singleton::Instance();
+
+ const auto addons_dir = Common::FS::GetUserPath(Common::FS::PathType::AddonsDir);
+ title_id = param_sfo->GetString("TITLE_ID");
+ auto addon_path = addons_dir / title_id;
+ if (std::filesystem::exists(addon_path)) {
+ for (const auto& entry : std::filesystem::directory_iterator(addon_path)) {
+ if (entry.is_directory()) {
+ auto entitlement_label = entry.path().filename().string();
+
+ AddContInfo info{};
+ info.status = ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_INSTALLED;
+ strcpy(info.entitlementLabel, entitlement_label.c_str());
+
+ addcont_info[addcont_count++] = info;
+ }
+ }
+ }
+
return ORBIS_OK;
}
@@ -221,12 +337,12 @@ int PS4_SYSV_ABI Func_C59A36FF8D7C59DA() {
return ORBIS_OK;
}
-int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownloadByEntitlemetId() {
+int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownloadByEntitlementId() {
LOG_ERROR(Lib_AppContent, "(STUBBED) called");
return ORBIS_OK;
}
-int PS4_SYSV_ABI sceAppContentAddcontMountByEntitlemetId() {
+int PS4_SYSV_ABI sceAppContentAddcontMountByEntitlementId() {
LOG_ERROR(Lib_AppContent, "(STUBBED) called");
return ORBIS_OK;
}
@@ -313,9 +429,9 @@ void RegisterlibSceAppContent(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("xZo2-418Wdo", "libSceAppContentBundle", 1, "libSceAppContent", 1, 1,
Func_C59A36FF8D7C59DA);
LIB_FUNCTION("kJmjt81mXKQ", "libSceAppContentIro", 1, "libSceAppContent", 1, 1,
- sceAppContentAddcontEnqueueDownloadByEntitlemetId);
+ sceAppContentAddcontEnqueueDownloadByEntitlementId);
LIB_FUNCTION("efX3lrPwdKA", "libSceAppContentIro", 1, "libSceAppContent", 1, 1,
- sceAppContentAddcontMountByEntitlemetId);
+ sceAppContentAddcontMountByEntitlementId);
LIB_FUNCTION("z9hgjLd1SGA", "libSceAppContentIro", 1, "libSceAppContent", 1, 1,
sceAppContentGetAddcontInfoByEntitlementId);
LIB_FUNCTION("3wUaDTGmjcQ", "libSceAppContentIro", 1, "libSceAppContent", 1, 1,
@@ -324,4 +440,4 @@ void RegisterlibSceAppContent(Core::Loader::SymbolsResolver* sym) {
sceAppContentGetDownloadedStoreCountry);
};
-} // namespace Libraries::AppContent
\ No newline at end of file
+} // namespace Libraries::AppContent
diff --git a/src/core/libraries/app_content/app_content.h b/src/core/libraries/app_content/app_content.h
index ecf69199e..a16da5b40 100644
--- a/src/core/libraries/app_content/app_content.h
+++ b/src/core/libraries/app_content/app_content.h
@@ -41,6 +41,16 @@ struct OrbisAppContentMountPoint {
constexpr int ORBIS_APP_CONTENT_TEMPORARY_DATA_OPTION_NONE = 0;
constexpr int ORBIS_APP_CONTENT_TEMPORARY_DATA_OPTION_FORMAT = (1 << 0);
constexpr int ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE = 17;
+constexpr int ORBIS_APP_CONTENT_ENTITLEMENT_KEY_SIZE = 16;
+constexpr int ORBIS_APP_CONTENT_INFO_LIST_MAX_SIZE = 2500;
+
+enum OrbisAppContentAddcontDownloadStatus : u32 {
+ ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_NO_EXTRA_DATA = 0,
+ ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_NO_IN_QUEUE = 1,
+ ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_DOWNLOADING = 2,
+ ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_DOWNLOAD_SUSPENDED = 3,
+ ORBIS_APP_CONTENT_ADDCONT_DOWNLOAD_STATUS_INSTALLED = 4
+};
struct OrbisNpUnifiedEntitlementLabel {
char data[ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE];
@@ -54,11 +64,17 @@ struct OrbisAppContentAddcontInfo {
u32 status;
};
+struct OrbisAppContentGetEntitlementKey {
+ char data[ORBIS_APP_CONTENT_ENTITLEMENT_KEY_SIZE];
+};
+
int PS4_SYSV_ABI _Z5dummyv();
int PS4_SYSV_ABI sceAppContentAddcontDelete();
int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownload();
int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownloadSp();
-int PS4_SYSV_ABI sceAppContentAddcontMount();
+int PS4_SYSV_ABI sceAppContentAddcontMount(u32 service_label,
+ const OrbisNpUnifiedEntitlementLabel* entitlement_label,
+ OrbisAppContentMountPoint* mount_point);
int PS4_SYSV_ABI sceAppContentAddcontShrink();
int PS4_SYSV_ABI sceAppContentAddcontUnmount();
int PS4_SYSV_ABI sceAppContentAppParamGetInt(OrbisAppContentAppParamId paramId, s32* value);
@@ -70,11 +86,15 @@ int PS4_SYSV_ABI sceAppContentDownload1Shrink();
int PS4_SYSV_ABI sceAppContentDownloadDataFormat();
int PS4_SYSV_ABI sceAppContentDownloadDataGetAvailableSpaceKb();
int PS4_SYSV_ABI sceAppContentGetAddcontDownloadProgress();
-int PS4_SYSV_ABI sceAppContentGetAddcontInfo();
+int PS4_SYSV_ABI sceAppContentGetAddcontInfo(u32 service_label,
+ const OrbisNpUnifiedEntitlementLabel* entitlementLabel,
+ OrbisAppContentAddcontInfo* info);
int PS4_SYSV_ABI sceAppContentGetAddcontInfoList(u32 service_label,
OrbisAppContentAddcontInfo* list, u32 list_num,
u32* hit_num);
-int PS4_SYSV_ABI sceAppContentGetEntitlementKey();
+int PS4_SYSV_ABI sceAppContentGetEntitlementKey(
+ u32 service_label, const OrbisNpUnifiedEntitlementLabel* entitlement_label,
+ OrbisAppContentGetEntitlementKey* key);
int PS4_SYSV_ABI sceAppContentGetRegion();
int PS4_SYSV_ABI sceAppContentInitialize(const OrbisAppContentInitParam* initParam,
OrbisAppContentBootParam* bootParam);
@@ -92,8 +112,8 @@ int PS4_SYSV_ABI sceAppContentTemporaryDataMount2(OrbisAppContentTemporaryDataOp
int PS4_SYSV_ABI sceAppContentTemporaryDataUnmount();
int PS4_SYSV_ABI sceAppContentGetPftFlag();
int PS4_SYSV_ABI Func_C59A36FF8D7C59DA();
-int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownloadByEntitlemetId();
-int PS4_SYSV_ABI sceAppContentAddcontMountByEntitlemetId();
+int PS4_SYSV_ABI sceAppContentAddcontEnqueueDownloadByEntitlementId();
+int PS4_SYSV_ABI sceAppContentAddcontMountByEntitlementId();
int PS4_SYSV_ABI sceAppContentGetAddcontInfoByEntitlementId();
int PS4_SYSV_ABI sceAppContentGetAddcontInfoListByIroTag();
int PS4_SYSV_ABI sceAppContentGetDownloadedStoreCountry();
diff --git a/src/core/libraries/audio/audioout.cpp b/src/core/libraries/audio/audioout.cpp
index cb676afc1..54db4c673 100644
--- a/src/core/libraries/audio/audioout.cpp
+++ b/src/core/libraries/audio/audioout.cpp
@@ -2,9 +2,10 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include
-#include
#include
+
#include "audio_core/sdl_audio.h"
+#include "common/assert.h"
#include "common/logging/log.h"
#include "core/libraries/audio/audioout.h"
#include "core/libraries/error_codes.h"
diff --git a/src/core/libraries/avplayer/avplayer.cpp b/src/core/libraries/avplayer/avplayer.cpp
index bd1f6b503..23e1e987a 100644
--- a/src/core/libraries/avplayer/avplayer.cpp
+++ b/src/core/libraries/avplayer/avplayer.cpp
@@ -40,9 +40,11 @@ int PS4_SYSV_ABI sceAvPlayerChangeStream() {
s32 PS4_SYSV_ABI sceAvPlayerClose(SceAvPlayerHandle handle) {
LOG_TRACE(Lib_AvPlayer, "called");
if (handle == nullptr) {
+ LOG_TRACE(Lib_AvPlayer, "returning ORBIS_AVPLAYER_ERROR_INVALID_PARAMS");
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
}
delete handle;
+ LOG_TRACE(Lib_AvPlayer, "returning ORBIS_OK");
return ORBIS_OK;
}
@@ -257,6 +259,7 @@ s32 PS4_SYSV_ABI sceAvPlayerStart(SceAvPlayerHandle handle) {
s32 PS4_SYSV_ABI sceAvPlayerStop(SceAvPlayerHandle handle) {
LOG_TRACE(Lib_AvPlayer, "called");
if (handle == nullptr) {
+ LOG_TRACE(Lib_AvPlayer, "returning ORBIS_AVPLAYER_ERROR_INVALID_PARAMS");
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
}
const auto res = handle->Stop();
@@ -322,4 +325,4 @@ void RegisterlibSceAvPlayer(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("yN7Jhuv8g24", "libSceAvPlayer", 1, "libSceAvPlayer", 1, 0, sceAvPlayerVprintf);
};
-} // namespace Libraries::AvPlayer
\ No newline at end of file
+} // namespace Libraries::AvPlayer
diff --git a/src/core/libraries/avplayer/avplayer_data_streamer.h b/src/core/libraries/avplayer/avplayer_data_streamer.h
index 04097bb4d..319c88a91 100644
--- a/src/core/libraries/avplayer/avplayer_data_streamer.h
+++ b/src/core/libraries/avplayer/avplayer_data_streamer.h
@@ -7,6 +7,8 @@
#include "common/types.h"
+#include
+
struct AVIOContext;
namespace Libraries::AvPlayer {
@@ -14,6 +16,7 @@ namespace Libraries::AvPlayer {
class IDataStreamer {
public:
virtual ~IDataStreamer() = default;
+ virtual bool Init(std::string_view path) = 0;
virtual AVIOContext* GetContext() = 0;
};
diff --git a/src/core/libraries/avplayer/avplayer_file_streamer.cpp b/src/core/libraries/avplayer/avplayer_file_streamer.cpp
index dc1386a47..c7bd5b5de 100644
--- a/src/core/libraries/avplayer/avplayer_file_streamer.cpp
+++ b/src/core/libraries/avplayer/avplayer_file_streamer.cpp
@@ -18,19 +18,8 @@ extern "C" {
namespace Libraries::AvPlayer {
-AvPlayerFileStreamer::AvPlayerFileStreamer(const SceAvPlayerFileReplacement& file_replacement,
- std::string_view path)
- : m_file_replacement(file_replacement) {
- const auto ptr = m_file_replacement.object_ptr;
- m_fd = m_file_replacement.open(ptr, path.data());
- ASSERT(m_fd >= 0);
- m_file_size = m_file_replacement.size(ptr);
- // avio_buffer is deallocated in `avio_context_free`
- const auto avio_buffer = reinterpret_cast(av_malloc(AVPLAYER_AVIO_BUFFER_SIZE));
- m_avio_context =
- avio_alloc_context(avio_buffer, AVPLAYER_AVIO_BUFFER_SIZE, 0, this,
- &AvPlayerFileStreamer::ReadPacket, nullptr, &AvPlayerFileStreamer::Seek);
-}
+AvPlayerFileStreamer::AvPlayerFileStreamer(const SceAvPlayerFileReplacement& file_replacement)
+ : m_file_replacement(file_replacement) {}
AvPlayerFileStreamer::~AvPlayerFileStreamer() {
if (m_avio_context != nullptr) {
@@ -43,6 +32,21 @@ AvPlayerFileStreamer::~AvPlayerFileStreamer() {
}
}
+bool AvPlayerFileStreamer::Init(std::string_view path) {
+ const auto ptr = m_file_replacement.object_ptr;
+ m_fd = m_file_replacement.open(ptr, path.data());
+ if (m_fd < 0) {
+ return false;
+ }
+ m_file_size = m_file_replacement.size(ptr);
+ // avio_buffer is deallocated in `avio_context_free`
+ const auto avio_buffer = reinterpret_cast(av_malloc(AVPLAYER_AVIO_BUFFER_SIZE));
+ m_avio_context =
+ avio_alloc_context(avio_buffer, AVPLAYER_AVIO_BUFFER_SIZE, 0, this,
+ &AvPlayerFileStreamer::ReadPacket, nullptr, &AvPlayerFileStreamer::Seek);
+ return true;
+}
+
s32 AvPlayerFileStreamer::ReadPacket(void* opaque, u8* buffer, s32 size) {
const auto self = reinterpret_cast(opaque);
if (self->m_position >= self->m_file_size) {
diff --git a/src/core/libraries/avplayer/avplayer_file_streamer.h b/src/core/libraries/avplayer/avplayer_file_streamer.h
index 658ce8c1e..034e40dd4 100644
--- a/src/core/libraries/avplayer/avplayer_file_streamer.h
+++ b/src/core/libraries/avplayer/avplayer_file_streamer.h
@@ -15,9 +15,11 @@ namespace Libraries::AvPlayer {
class AvPlayerFileStreamer : public IDataStreamer {
public:
- AvPlayerFileStreamer(const SceAvPlayerFileReplacement& file_replacement, std::string_view path);
+ AvPlayerFileStreamer(const SceAvPlayerFileReplacement& file_replacement);
~AvPlayerFileStreamer();
+ bool Init(std::string_view path) override;
+
AVIOContext* GetContext() override {
return m_avio_context;
}
diff --git a/src/core/libraries/avplayer/avplayer_impl.cpp b/src/core/libraries/avplayer/avplayer_impl.cpp
index cdfff8277..6de7b4c20 100644
--- a/src/core/libraries/avplayer/avplayer_impl.cpp
+++ b/src/core/libraries/avplayer/avplayer_impl.cpp
@@ -110,7 +110,7 @@ s32 AvPlayer::AddSource(std::string_view path) {
if (path.empty()) {
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
}
- if (AVPLAYER_IS_ERROR(m_state->AddSource(path, GetSourceType(path)))) {
+ if (!m_state->AddSource(path, GetSourceType(path))) {
return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED;
}
return ORBIS_OK;
@@ -128,7 +128,7 @@ s32 AvPlayer::GetStreamCount() {
}
s32 AvPlayer::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) {
- if (AVPLAYER_IS_ERROR(m_state->GetStreamInfo(stream_index, info))) {
+ if (!m_state->GetStreamInfo(stream_index, info)) {
return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED;
}
return ORBIS_OK;
@@ -145,7 +145,10 @@ s32 AvPlayer::EnableStream(u32 stream_index) {
}
s32 AvPlayer::Start() {
- return m_state->Start();
+ if (!m_state->Start()) {
+ return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED;
+ }
+ return ORBIS_OK;
}
bool AvPlayer::GetVideoData(SceAvPlayerFrameInfo& video_info) {
diff --git a/src/core/libraries/avplayer/avplayer_source.cpp b/src/core/libraries/avplayer/avplayer_source.cpp
index 776d389f0..99ba2e8b6 100644
--- a/src/core/libraries/avplayer/avplayer_source.cpp
+++ b/src/core/libraries/avplayer/avplayer_source.cpp
@@ -5,6 +5,7 @@
#include "avplayer_file_streamer.h"
+#include "common/alignment.h"
#include "common/singleton.h"
#include "core/file_sys/fs.h"
#include "core/libraries/kernel/time_management.h"
@@ -23,31 +24,39 @@ namespace Libraries::AvPlayer {
using namespace Kernel;
-AvPlayerSource::AvPlayerSource(AvPlayerStateCallback& state, std::string_view path,
- const SceAvPlayerInitData& init_data,
- SceAvPlayerSourceType source_type)
- : m_state(state), m_memory_replacement(init_data.memory_replacement),
- m_num_output_video_framebuffers(
- std::min(std::max(2, init_data.num_output_video_framebuffers), 16)) {
- AVFormatContext* context = avformat_alloc_context();
- if (init_data.file_replacement.open != nullptr) {
- m_up_data_streamer =
- std::make_unique(init_data.file_replacement, path);
- context->pb = m_up_data_streamer->GetContext();
- ASSERT(!AVPLAYER_IS_ERROR(avformat_open_input(&context, nullptr, nullptr, nullptr)));
- } else {
- const auto mnt = Common::Singleton::Instance();
- const auto filepath = mnt->GetHostPath(path);
- ASSERT(!AVPLAYER_IS_ERROR(
- avformat_open_input(&context, filepath.string().c_str(), nullptr, nullptr)));
- }
- m_avformat_context = AVFormatContextPtr(context, &ReleaseAVFormatContext);
-}
+AvPlayerSource::AvPlayerSource(AvPlayerStateCallback& state) : m_state(state) {}
AvPlayerSource::~AvPlayerSource() {
Stop();
}
+bool AvPlayerSource::Init(const SceAvPlayerInitData& init_data, std::string_view path) {
+ m_memory_replacement = init_data.memory_replacement,
+ m_num_output_video_framebuffers =
+ std::min(std::max(2, init_data.num_output_video_framebuffers), 16);
+
+ AVFormatContext* context = avformat_alloc_context();
+ if (init_data.file_replacement.open != nullptr) {
+ m_up_data_streamer = std::make_unique(init_data.file_replacement);
+ if (!m_up_data_streamer->Init(path)) {
+ return false;
+ }
+ context->pb = m_up_data_streamer->GetContext();
+ if (AVPLAYER_IS_ERROR(avformat_open_input(&context, nullptr, nullptr, nullptr))) {
+ return false;
+ }
+ } else {
+ const auto mnt = Common::Singleton::Instance();
+ const auto filepath = mnt->GetHostPath(path);
+ if (AVPLAYER_IS_ERROR(
+ avformat_open_input(&context, filepath.string().c_str(), nullptr, nullptr))) {
+ return false;
+ }
+ }
+ m_avformat_context = AVFormatContextPtr(context, &ReleaseAVFormatContext);
+ return true;
+}
+
bool AvPlayerSource::FindStreamInfo() {
if (m_avformat_context == nullptr) {
LOG_ERROR(Lib_AvPlayer, "Could not find stream info. NULL context.");
@@ -82,20 +91,20 @@ static s32 CodecTypeToStreamType(AVMediaType codec_type) {
}
}
-static f32 AVRationalToF32(const AVRational& rational) {
+static f32 AVRationalToF32(const AVRational rational) {
return f32(rational.num) / rational.den;
}
-s32 AvPlayerSource::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) {
+bool AvPlayerSource::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) {
info = {};
if (m_avformat_context == nullptr || stream_index >= m_avformat_context->nb_streams) {
LOG_ERROR(Lib_AvPlayer, "Could not get stream {} info.", stream_index);
- return -1;
+ return false;
}
const auto p_stream = m_avformat_context->streams[stream_index];
if (p_stream == nullptr || p_stream->codecpar == nullptr) {
LOG_ERROR(Lib_AvPlayer, "Could not get stream {} info. NULL stream.", stream_index);
- return -1;
+ return false;
}
info.type = CodecTypeToStreamType(p_stream->codecpar->codec_type);
info.start_time = p_stream->start_time;
@@ -111,8 +120,8 @@ s32 AvPlayerSource::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info)
LOG_INFO(Lib_AvPlayer, "Stream {} is a video stream.", stream_index);
info.details.video.aspect_ratio =
f32(p_stream->codecpar->width) / p_stream->codecpar->height;
- info.details.video.width = p_stream->codecpar->width;
- info.details.video.height = p_stream->codecpar->height;
+ info.details.video.width = Common::AlignUp(u32(p_stream->codecpar->width), 16);
+ info.details.video.height = Common::AlignUp(u32(p_stream->codecpar->height), 16);
if (p_lang_node != nullptr) {
std::memcpy(info.details.video.language_code, p_lang_node->value,
std::min(strlen(p_lang_node->value), size_t(3)));
@@ -139,9 +148,9 @@ s32 AvPlayerSource::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info)
break;
default:
LOG_ERROR(Lib_AvPlayer, "Stream {} type is unknown: {}.", stream_index, info.type);
- return -1;
+ return false;
}
- return 0;
+ return true;
}
bool AvPlayerSource::EnableStream(u32 stream_index) {
@@ -167,8 +176,9 @@ bool AvPlayerSource::EnableStream(u32 stream_index) {
LOG_ERROR(Lib_AvPlayer, "Could not open avcodec for video stream {}.", stream_index);
return false;
}
- const auto width = m_video_codec_context->width;
- const auto size = (width * m_video_codec_context->height * 3) / 2;
+ const auto width = Common::AlignUp(u32(m_video_codec_context->width), 16);
+ const auto height = Common::AlignUp(u32(m_video_codec_context->height), 16);
+ const auto size = (width * height * 3) / 2;
for (u64 index = 0; index < m_num_output_video_framebuffers; ++index) {
m_video_buffers.Push(FrameBuffer(m_memory_replacement, 0x100, size));
}
@@ -213,12 +223,12 @@ std::optional AvPlayerSource::HasFrames(u32 num_frames) {
return m_video_packets.Size() > num_frames || m_is_eof;
}
-s32 AvPlayerSource::Start() {
+bool AvPlayerSource::Start() {
std::unique_lock lock(m_state_mutex);
if (m_audio_codec_context == nullptr && m_video_codec_context == nullptr) {
LOG_ERROR(Lib_AvPlayer, "Could not start playback. NULL context.");
- return -1;
+ return false;
}
m_demuxer_thread = std::jthread([this](std::stop_token stop) { this->DemuxerThread(stop); });
m_video_decoder_thread =
@@ -226,7 +236,7 @@ s32 AvPlayerSource::Start() {
m_audio_decoder_thread =
std::jthread([this](std::stop_token stop) { this->AudioDecoderThread(stop); });
m_start_time = std::chrono::high_resolution_clock::now();
- return 0;
+ return true;
}
bool AvPlayerSource::Stop() {
@@ -284,11 +294,6 @@ bool AvPlayerSource::GetVideoData(SceAvPlayerFrameInfo& video_info) {
return true;
}
-static void CopyNV12Data(u8* dst, const AVFrame& src) {
- std::memcpy(dst, src.data[0], src.width * src.height);
- std::memcpy(dst + src.width * src.height, src.data[1], (src.width * src.height) / 2);
-}
-
bool AvPlayerSource::GetVideoData(SceAvPlayerFrameInfoEx& video_info) {
if (!IsActive()) {
return false;
@@ -359,12 +364,16 @@ bool AvPlayerSource::GetAudioData(SceAvPlayerFrameInfo& audio_info) {
audio_info = {};
audio_info.timestamp = frame->info.timestamp;
audio_info.pData = reinterpret_cast(frame->info.pData);
+ audio_info.details.audio.sample_rate = frame->info.details.audio.sample_rate;
audio_info.details.audio.size = frame->info.details.audio.size;
audio_info.details.audio.channel_count = frame->info.details.audio.channel_count;
return true;
}
u64 AvPlayerSource::CurrentTime() {
+ if (!IsActive()) {
+ return 0;
+ }
using namespace std::chrono;
return duration_cast(high_resolution_clock::now() - m_start_time).count();
}
@@ -489,13 +498,17 @@ AvPlayerSource::AVFramePtr AvPlayerSource::ConvertVideoFrame(const AVFrame& fram
nv12_frame->width = frame.width;
nv12_frame->height = frame.height;
nv12_frame->sample_aspect_ratio = frame.sample_aspect_ratio;
+ nv12_frame->crop_top = frame.crop_top;
+ nv12_frame->crop_bottom = frame.crop_bottom;
+ nv12_frame->crop_left = frame.crop_left;
+ nv12_frame->crop_right = frame.crop_right;
av_frame_get_buffer(nv12_frame.get(), 0);
if (m_sws_context == nullptr) {
m_sws_context =
SWSContextPtr(sws_getContext(frame.width, frame.height, AVPixelFormat(frame.format),
- frame.width, frame.height, AV_PIX_FMT_NV12,
+ nv12_frame->width, nv12_frame->height, AV_PIX_FMT_NV12,
SWS_FAST_BILINEAR, nullptr, nullptr, nullptr),
&ReleaseSWSContext);
}
@@ -508,6 +521,26 @@ AvPlayerSource::AVFramePtr AvPlayerSource::ConvertVideoFrame(const AVFrame& fram
return nv12_frame;
}
+static void CopyNV12Data(u8* dst, const AVFrame& src) {
+ const auto width = Common::AlignUp(u32(src.width), 16);
+ const auto height = Common::AlignUp(u32(src.height), 16);
+
+ if (src.width == width) {
+ std::memcpy(dst, src.data[0], src.width * src.height);
+ std::memcpy(dst + src.width * height, src.data[1], (src.width * src.height) / 2);
+ } else {
+ const auto luma_dst = dst;
+ for (u32 y = 0; y < src.height; ++y) {
+ std::memcpy(luma_dst + y * width, src.data[0] + y * src.width, src.width);
+ }
+ const auto chroma_dst = dst + width * height;
+ for (u32 y = 0; y < src.height / 2; ++y) {
+ std::memcpy(chroma_dst + y * (width / 2), src.data[0] + y * (src.width / 2),
+ src.width / 2);
+ }
+ }
+}
+
Frame AvPlayerSource::PrepareVideoFrame(FrameBuffer buffer, const AVFrame& frame) {
ASSERT(frame.format == AV_PIX_FMT_NV12);
@@ -521,6 +554,9 @@ Frame AvPlayerSource::PrepareVideoFrame(FrameBuffer buffer, const AVFrame& frame
const auto num = time_base.num;
const auto timestamp = (num != 0 && den > 1) ? (pkt_dts * num) / den : pkt_dts;
+ const auto width = Common::AlignUp(u32(frame.width), 16);
+ const auto height = Common::AlignUp(u32(frame.height), 16);
+
return Frame{
.buffer = std::move(buffer),
.info =
@@ -531,9 +567,14 @@ Frame AvPlayerSource::PrepareVideoFrame(FrameBuffer buffer, const AVFrame& frame
{
.video =
{
- .width = u32(frame.width),
- .height = u32(frame.height),
+ .width = u32(width),
+ .height = u32(height),
.aspect_ratio = AVRationalToF32(frame.sample_aspect_ratio),
+ .crop_left_offset = u32(frame.crop_left),
+ .crop_right_offset = u32(frame.crop_right + (width - frame.width)),
+ .crop_top_offset = u32(frame.crop_top),
+ .crop_bottom_offset =
+ u32(frame.crop_bottom + (height - frame.height)),
.pitch = u32(frame.linesize[0]),
.luma_bit_depth = 8,
.chroma_bit_depth = 8,
@@ -655,6 +696,7 @@ Frame AvPlayerSource::PrepareAudioFrame(FrameBuffer buffer, const AVFrame& frame
.audio =
{
.channel_count = u16(frame.ch_layout.nb_channels),
+ .sample_rate = u32(frame.sample_rate),
.size = u32(size),
},
},
diff --git a/src/core/libraries/avplayer/avplayer_source.h b/src/core/libraries/avplayer/avplayer_source.h
index 7144e7ee4..906122142 100644
--- a/src/core/libraries/avplayer/avplayer_source.h
+++ b/src/core/libraries/avplayer/avplayer_source.h
@@ -120,17 +120,17 @@ private:
class AvPlayerSource {
public:
- AvPlayerSource(AvPlayerStateCallback& state, std::string_view path,
- const SceAvPlayerInitData& init_data, SceAvPlayerSourceType source_type);
+ AvPlayerSource(AvPlayerStateCallback& state);
~AvPlayerSource();
+ bool Init(const SceAvPlayerInitData& init_data, std::string_view path);
bool FindStreamInfo();
s32 GetStreamCount();
- s32 GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info);
+ bool GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info);
bool EnableStream(u32 stream_index);
void SetLooping(bool is_looping);
std::optional HasFrames(u32 num_frames);
- s32 Start();
+ bool Start();
bool Stop();
bool GetAudioData(SceAvPlayerFrameInfo& audio_info);
bool GetVideoData(SceAvPlayerFrameInfo& video_info);
diff --git a/src/core/libraries/avplayer/avplayer_state.cpp b/src/core/libraries/avplayer/avplayer_state.cpp
index 884cd9408..a512063f2 100644
--- a/src/core/libraries/avplayer/avplayer_state.cpp
+++ b/src/core/libraries/avplayer/avplayer_state.cpp
@@ -24,6 +24,7 @@ void PS4_SYSV_ABI AvPlayerState::AutoPlayEventCallback(void* opaque, s32 event_i
s32 timedtext_stream_index = -1;
const s32 stream_count = self->GetStreamCount();
if (AVPLAYER_IS_ERROR(stream_count)) {
+ self->Stop();
return;
}
if (stream_count == 0) {
@@ -32,7 +33,10 @@ void PS4_SYSV_ABI AvPlayerState::AutoPlayEventCallback(void* opaque, s32 event_i
}
for (u32 stream_index = 0; stream_index < stream_count; ++stream_index) {
SceAvPlayerStreamInfo info{};
- self->GetStreamInfo(stream_index, info);
+ if (!self->GetStreamInfo(stream_index, info)) {
+ self->Stop();
+ return;
+ }
const std::string_view default_language(
reinterpret_cast(self->m_default_language));
@@ -116,23 +120,28 @@ AvPlayerState::~AvPlayerState() {
}
// Called inside GAME thread
-s32 AvPlayerState::AddSource(std::string_view path, SceAvPlayerSourceType source_type) {
+bool AvPlayerState::AddSource(std::string_view path, SceAvPlayerSourceType source_type) {
if (path.empty()) {
LOG_ERROR(Lib_AvPlayer, "File path is empty.");
- return -1;
+ return false;
}
{
std::unique_lock lock(m_source_mutex);
if (m_up_source != nullptr) {
LOG_ERROR(Lib_AvPlayer, "Only one source is supported.");
- return -1;
+ return false;
}
- m_up_source = std::make_unique(*this, path, m_init_data, source_type);
+ m_up_source = std::make_unique(*this);
+ if (!m_up_source->Init(m_init_data, path)) {
+ SetState(AvState::Error);
+ m_up_source.reset();
+ return false;
+ }
}
AddSourceEvent();
- return 0;
+ return true;
}
// Called inside GAME thread
@@ -146,25 +155,25 @@ s32 AvPlayerState::GetStreamCount() {
}
// Called inside GAME thread
-s32 AvPlayerState::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) {
+bool AvPlayerState::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) {
std::shared_lock lock(m_source_mutex);
if (m_up_source == nullptr) {
LOG_ERROR(Lib_AvPlayer, "Could not get stream {} info. No source.", stream_index);
- return -1;
+ return false;
}
return m_up_source->GetStreamInfo(stream_index, info);
}
// Called inside GAME thread
-s32 AvPlayerState::Start() {
+bool AvPlayerState::Start() {
std::shared_lock lock(m_source_mutex);
- if (m_up_source == nullptr || m_up_source->Start() < 0) {
+ if (m_up_source == nullptr || !m_up_source->Start()) {
LOG_ERROR(Lib_AvPlayer, "Could not start playback.");
- return -1;
+ return false;
}
SetState(AvState::Play);
OnPlaybackStateChanged(AvState::Play);
- return 0;
+ return true;
}
void AvPlayerState::AvControllerThread(std::stop_token stop) {
@@ -219,11 +228,14 @@ bool AvPlayerState::Stop() {
if (m_up_source == nullptr || m_current_state == AvState::Stop) {
return false;
}
+ if (!m_up_source->Stop()) {
+ return false;
+ }
if (!SetState(AvState::Stop)) {
return false;
}
OnPlaybackStateChanged(AvState::Stop);
- return m_up_source->Stop();
+ return true;
}
bool AvPlayerState::GetVideoData(SceAvPlayerFrameInfo& video_info) {
diff --git a/src/core/libraries/avplayer/avplayer_state.h b/src/core/libraries/avplayer/avplayer_state.h
index ff80b6cea..a5a3bd689 100644
--- a/src/core/libraries/avplayer/avplayer_state.h
+++ b/src/core/libraries/avplayer/avplayer_state.h
@@ -24,11 +24,11 @@ public:
AvPlayerState(const SceAvPlayerInitData& init_data);
~AvPlayerState();
- s32 AddSource(std::string_view filename, SceAvPlayerSourceType source_type);
+ bool AddSource(std::string_view filename, SceAvPlayerSourceType source_type);
s32 GetStreamCount();
- s32 GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info);
+ bool GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info);
bool EnableStream(u32 stream_index);
- s32 Start();
+ bool Start();
bool Stop();
bool GetAudioData(SceAvPlayerFrameInfo& audio_info);
bool GetVideoData(SceAvPlayerFrameInfo& video_info);
diff --git a/src/core/libraries/dialogs/error_dialog.cpp b/src/core/libraries/dialogs/error_dialog.cpp
index 02f82c096..7df9b1c83 100644
--- a/src/core/libraries/dialogs/error_dialog.cpp
+++ b/src/core/libraries/dialogs/error_dialog.cpp
@@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-// Generated By moduleGenerator
#include "common/logging/log.h"
#include "core/libraries/error_codes.h"
#include "core/libraries/libs.h"
diff --git a/src/core/libraries/dialogs/ime_dialog.cpp b/src/core/libraries/dialogs/ime_dialog.cpp
index e73c1881b..ddb1a89f8 100644
--- a/src/core/libraries/dialogs/ime_dialog.cpp
+++ b/src/core/libraries/dialogs/ime_dialog.cpp
@@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-// Generated By moduleGenerator
#include "common/logging/log.h"
#include "core/libraries/error_codes.h"
#include "core/libraries/libs.h"
diff --git a/src/core/libraries/disc_map/disc_map.cpp b/src/core/libraries/disc_map/disc_map.cpp
index 79f4acb34..bb566a149 100644
--- a/src/core/libraries/disc_map/disc_map.cpp
+++ b/src/core/libraries/disc_map/disc_map.cpp
@@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-// Generated By moduleGenerator
#include "common/logging/log.h"
#include "core/libraries/error_codes.h"
#include "core/libraries/libs.h"
diff --git a/src/core/libraries/error_codes.h b/src/core/libraries/error_codes.h
index 123edcee8..094ea6603 100644
--- a/src/core/libraries/error_codes.h
+++ b/src/core/libraries/error_codes.h
@@ -233,9 +233,6 @@ constexpr int SCE_KERNEL_ERROR_ESDKVERSION = 0x80020063;
constexpr int SCE_KERNEL_ERROR_ESTART = 0x80020064;
constexpr int SCE_KERNEL_ERROR_ESTOP = 0x80020065;
-// libSceRandom error codes
-constexpr int SCE_RANDOM_ERROR_INVALID = 0x817C0016;
-
// videoOut
constexpr int SCE_VIDEO_OUT_ERROR_INVALID_VALUE = 0x80290001; // invalid argument
constexpr int SCE_VIDEO_OUT_ERROR_INVALID_ADDRESS = 0x80290002; // invalid addresses
@@ -249,14 +246,6 @@ constexpr int SCE_VIDEO_OUT_ERROR_SLOT_OCCUPIED = 0x80290010; // slot alr
constexpr int SCE_VIDEO_OUT_ERROR_FLIP_QUEUE_FULL = 0x80290012; // flip queue is full
constexpr int SCE_VIDEO_OUT_ERROR_INVALID_OPTION = 0x8029001A; // Invalid buffer attribute option
-// GnmDriver
-constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_PIPE_ID = 0x80D17000;
-constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_QUEUE_ID = 0x80D17001;
-constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_RING_BASE_ADDR = 0x80D17003;
-constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_RING_SIZE = 0x80D17002;
-constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_READ_PTR_ADDR = 0x80D17004;
-constexpr int ORBIS_GNM_ERROR_FAILURE = 0x8EEE00FF;
-
// Generic
constexpr int ORBIS_OK = 0x00000000;
constexpr int ORBIS_FAIL = 0xFFFFFFFF;
@@ -471,4 +460,6 @@ constexpr int ORBIS_AVPLAYER_ERROR_INFO_AES_ENCRY = 0x806A00B5;
constexpr int ORBIS_AVPLAYER_ERROR_INFO_OTHER_ENCRY = 0x806A00BF;
// AppContent library
-constexpr int ORBIS_APP_CONTENT_ERROR_PARAMETER = 0x80D90002;
\ No newline at end of file
+constexpr int ORBIS_APP_CONTENT_ERROR_PARAMETER = 0x80D90002;
+constexpr int ORBIS_APP_CONTENT_ERROR_DRM_NO_ENTITLEMENT = 0x80D90007;
+constexpr int ORBIS_APP_CONTENT_ERROR_NOT_FOUND = 0x80D90005;
\ No newline at end of file
diff --git a/src/core/libraries/gnmdriver/gnm_error.h b/src/core/libraries/gnmdriver/gnm_error.h
new file mode 100644
index 000000000..eab684a24
--- /dev/null
+++ b/src/core/libraries/gnmdriver/gnm_error.h
@@ -0,0 +1,85 @@
+// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+constexpr int ORBIS_GNM_ERROR_SUBMISSION_FAILED_INVALID_ARGUMENT = 0x80D11000;
+constexpr int ORBIS_GNM_ERROR_SUBMISSION_NOT_ENOUGH_RESOURCES = 0x80D11001;
+constexpr int ORBIS_GNM_ERROR_SUBMISSION_AND_FLIP_FAILED_INVALID_COMMAND_BUFFER = 0x80D11080;
+constexpr int ORBIS_GNM_ERROR_SUBMISSION_AND_FLIP_FAILED_INVALID_QUEUE_FULL = 0x80D11081;
+constexpr int ORBIS_GNM_ERROR_SUBMISSION_AND_FLIP_FAILED_REQUEST_FAILED = 0x80D11082;
+constexpr int ORBIS_GNM_ERROR_SUBMISSION_FAILED_INTERNAL_ERROR = 0x80D110FF;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_WARNING = 0x80D12000;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_WARNING_RWBUFFER_ROTYPE = 0x80D12001;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_WARNING_BLENDING = 0x80D12002;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_WARNING_DRAW_CU_MASK = 0x80D12003;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_WARNING_MRT_SETUP = 0x80D12004;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_WARNING_DEPTH_RT_SETUP = 0x80D12005;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_WARNING_PS_AND_MRT_FORMAT = 0x80D1200F;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_ERROR = 0x80D13000;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_VSHARP = 0x80D13001;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_TSHARP = 0x80D13002;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_RESOURCE = 0x80D13003;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_TABLE_MEMORY = 0x80D13004;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_WRITE_EVENT_OP = 0x80D13005;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_INDEX_BUFFER = 0x80D13006;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_TESS_FACTOR_BUFFER = 0x80D13007;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_SCRATCH_RING = 0x80D13008;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_PRIMITIVE_TYPE = 0x80D13009;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_INDEX_SIZE = 0x80D1300A;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_INLINE_DRAW_SIZE = 0x80D1300B;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_NUM_INPUT_PATCHES = 0x80D1300C;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_GS_MODE = 0x80D1300D;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_SHADER_ADDRESS = 0x80D1300E;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_BORDER_COLOR_TABLE = 0x80D1300F;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_SSHARP = 0x80D13010;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_DISPATCH_DRAW = 0x80D13011;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_ACTIVE_SHADER_STAGE = 0x80D13012;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_DCB = 0x80D13013;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_MISMATCH_SHADER_STAGE = 0x80D13014;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_MRT_SETUP = 0x80D13015;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_BAD_OP_CODE = 0x80D13016;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_DEPTH_RT_SETUP = 0x80D13017;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_NUM_INSTANCES = 0x80D13018;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_SRT = 0x80D13019;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_INVALID_ARGUMENT = 0x80D13FFD;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_FAILED_INTERNAL_ERROR = 0x80D13FFE;
+constexpr int ORBIS_GNM_ERROR_VALIDATION_NOT_ENABLED = 0x80D13FFF;
+constexpr int ORBIS_GNM_ERROR_CAPTURE_FILE_IO = 0x80D15000;
+constexpr int ORBIS_GNM_ERROR_CAPTURE_RAZOR_NOT_LOADED = 0x80D15001;
+constexpr int ORBIS_GNM_ERROR_CAPTURE_NOTHING_TO_CAPTURE = 0x80D15002;
+constexpr int ORBIS_GNM_ERROR_CAPTURE_FAILED_INTERNAL = 0x80D1500F;
+constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_PIPE_ID = 0x80D17000;
+constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_QUEUE_ID = 0x80D17001;
+constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_RING_SIZE = 0x80D17002;
+constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_RING_BASE_ADDR = 0x80D17003;
+constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_READ_PTR_ADDR = 0x80D17004;
+constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INVALID_PIPE_PRIORITY = 0x80D17005;
+constexpr int ORBIS_GNM_ERROR_COMPUTEQUEUE_INTERNAL = 0x80D170FF;
+constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_INVALID_ARGUMENT = 0x80D19000;
+constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_INVALID_SHADER = 0x80D19001;
+constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_STALE_HANDLE = 0x80D19002;
+constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_FULL = 0x80D19003;
+constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_NOT_PERMITTED = 0x80D19004;
+constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_OUTPUT_ARGUMENT_IS_NULL = 0x80D19005;
+constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_OWNER_HANDLE_INVALID = 0x80D19006;
+constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_RESOURCE_HANDLE_INVALID = 0x80D19007;
+constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_RESOURCE_TYPE_INVALID = 0x80D19008;
+constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_GDS_RESOURCE_TYPE_INVALID = 0x80D19009;
+constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_RESOURCE_SIZE_INVALID = 0x80D1900A;
+constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_RESOURCE_ADDRESS_IS_NULL = 0x80D1900B;
+constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_GDS_OFFSET_INVALID = 0x80D1900C;
+constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_RESOURCE_NAME_IS_NULL = 0x80D1900D;
+constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_OWNER_NAME_IS_NULL = 0x80D1900E;
+constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_FIND_CALLBACK_IS_NULL = 0x80D1900F;
+constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_RESOURCE_IS_NOT_SHADER = 0x80D19010;
+constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_USER_MEMORY_PARAM_IS_NULL = 0x80D19011;
+constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_USER_MEMORY_PARAM_NOT_ALIGNED = 0x80D19012;
+constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_INVALID_NAME_LENGTH_PARAM = 0x80D19013;
+constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_INVALID_SIZE_PARAM = 0x80D19014;
+constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_INVALID_NUM_RESOURCES_PARAM = 0x80D19015;
+constexpr int ORBIS_GNM_ERROR_RESOURCE_REGISTRATION_INTERNAL = 0x80D19FFF;
+constexpr int ORBIS_GNM_ERROR_GET_GPU_INFO_PARAMETER_NULL = 0x80D1B000;
+constexpr int ORBIS_GNM_ERROR_GET_GPU_INFO_FAILED = 0x80D1B001;
+constexpr int ORBIS_GNM_ERROR_GET_GPU_INFO_PARAMETER_INVALID = 0x80D1B002;
+constexpr int ORBIS_GNM_ERROR_FAILURE = 0x8EEE00FF;
diff --git a/src/core/libraries/gnmdriver/gnmdriver.cpp b/src/core/libraries/gnmdriver/gnmdriver.cpp
index c2ee6d592..a2ef94037 100644
--- a/src/core/libraries/gnmdriver/gnmdriver.cpp
+++ b/src/core/libraries/gnmdriver/gnmdriver.cpp
@@ -1,6 +1,9 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include "gnm_error.h"
+#include "gnmdriver.h"
+
#include "common/assert.h"
#include "common/config.h"
#include "common/debug.h"
@@ -9,7 +12,6 @@
#include "common/slot_vector.h"
#include "core/address_space.h"
#include "core/libraries/error_codes.h"
-#include "core/libraries/gnmdriver/gnmdriver.h"
#include "core/libraries/kernel/libkernel.h"
#include "core/libraries/libs.h"
#include "core/libraries/videoout/video_out.h"
@@ -55,6 +57,10 @@ static constexpr auto HwInitPacketSize = 0x100u;
// clang-format off
static constexpr std::array InitSequence{
+ // A fake preamble to mimic context reset sent by FW
+ 0xc0001200u, 0u, // IT_CLEAR_STATE
+
+ // Actual init state sequence
0xc0017600u, 0x216u, 0xffffffffu,
0xc0017600u, 0x217u, 0xffffffffu,
0xc0017600u, 0x215u, 0u,
@@ -94,9 +100,13 @@ static constexpr std::array InitSequence{
0xc0036900u, 0x295u, 0x100u, 0x100u, 4u,
0xc0017900u, 0x200u, 0xe0000000u,
};
-static_assert(InitSequence.size() == 0x73);
+static_assert(InitSequence.size() == 0x73 + 2);
static constexpr std::array InitSequence175{
+ // A fake preamble to mimic context reset sent by FW
+ 0xc0001200u, 0u, // IT_CLEAR_STATE
+
+ // Actual init state sequence
0xc0017600u, 0x216u, 0xffffffffu,
0xc0017600u, 0x217u, 0xffffffffu,
0xc0017600u, 0x215u, 0u,
@@ -136,9 +146,13 @@ static constexpr std::array InitSequence175{
0xc0036900u, 0x295u, 0x100u, 0x100u, 4u,
0xc0017900u, 0x200u, 0xe0000000u,
};
-static_assert(InitSequence175.size() == 0x73);
+static_assert(InitSequence175.size() == 0x73 + 2);
static constexpr std::array InitSequence200{
+ // A fake preamble to mimic context reset sent by FW
+ 0xc0001200u, 0u, // IT_CLEAR_STATE
+
+ // Actual init state sequence
0xc0017600u, 0x216u, 0xffffffffu,
0xc0017600u, 0x217u, 0xffffffffu,
0xc0017600u, 0x215u, 0u,
@@ -179,9 +193,13 @@ static constexpr std::array InitSequence200{
0xc0036900u, 0x295u, 0x100u, 0x100u, 4u,
0xc0017900u, 0x200u, 0xe0000000u,
};
-static_assert(InitSequence200.size() == 0x76);
+static_assert(InitSequence200.size() == 0x76 + 2);
static constexpr std::array InitSequence350{
+ // A fake preamble to mimic context reset sent by FW
+ 0xc0001200u, 0u, // IT_CLEAR_STATE
+
+ // Actual init state sequence
0xc0017600u, 0x216u, 0xffffffffu,
0xc0017600u, 0x217u, 0xffffffffu,
0xc0017600u, 0x215u, 0u,
@@ -224,7 +242,7 @@ static constexpr std::array InitSequence350{
0xc0017900u, 0x200u, 0xe0000000u,
0xc0016900u, 0x2aau, 0xffu,
};
-static_assert(InitSequence350.size() == 0x7c);
+static_assert(InitSequence350.size() == 0x7c + 2);
static constexpr std::array CtxInitSequence{
0xc0012800u, 0x80000000u, 0x80000000u,
@@ -632,12 +650,12 @@ s32 PS4_SYSV_ABI sceGnmDrawIndexAuto(u32* cmdbuf, u32 size, u32 index_count, u32
}
s32 PS4_SYSV_ABI sceGnmDrawIndexIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage,
- u32 vertex_sgpr_offset, u32 instance_vgpr_offset,
+ u32 vertex_sgpr_offset, u32 instance_sgpr_offset,
u32 flags) {
LOG_TRACE(Lib_GnmDriver, "called");
if (cmdbuf && (size == 9) && (shader_stage < ShaderStages::Max) &&
- (vertex_sgpr_offset < 0x10u) && (instance_vgpr_offset < 0x10u)) {
+ (vertex_sgpr_offset < 0x10u) && (instance_sgpr_offset < 0x10u)) {
const auto predicate = flags & 1 ? PM4Predicate::PredEnable : PM4Predicate::PredDisable;
cmdbuf = WriteHeader(
@@ -647,7 +665,7 @@ s32 PS4_SYSV_ABI sceGnmDrawIndexIndirect(u32* cmdbuf, u32 size, u32 data_offset,
cmdbuf[0] = data_offset;
cmdbuf[1] = vertex_sgpr_offset == 0 ? 0 : (vertex_sgpr_offset & 0xffffu) + sgpr_offset;
- cmdbuf[2] = instance_vgpr_offset == 0 ? 0 : (instance_vgpr_offset & 0xffffu) + sgpr_offset;
+ cmdbuf[2] = instance_sgpr_offset == 0 ? 0 : (instance_sgpr_offset & 0xffffu) + sgpr_offset;
cmdbuf[3] = 0;
cmdbuf += 4;
@@ -689,11 +707,11 @@ s32 PS4_SYSV_ABI sceGnmDrawIndexOffset(u32* cmdbuf, u32 size, u32 index_offset,
}
s32 PS4_SYSV_ABI sceGnmDrawIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage,
- u32 vertex_sgpr_offset, u32 instance_vgpr_offset, u32 flags) {
+ u32 vertex_sgpr_offset, u32 instance_sgpr_offset, u32 flags) {
LOG_TRACE(Lib_GnmDriver, "called");
if (cmdbuf && (size == 9) && (shader_stage < ShaderStages::Max) &&
- (vertex_sgpr_offset < 0x10u) && (instance_vgpr_offset < 0x10u)) {
+ (vertex_sgpr_offset < 0x10u) && (instance_sgpr_offset < 0x10u)) {
const auto predicate = flags & 1 ? PM4Predicate::PredEnable : PM4Predicate::PredDisable;
cmdbuf = WriteHeader(cmdbuf, 4, PM4ShaderType::ShaderGraphics,
@@ -703,7 +721,7 @@ s32 PS4_SYSV_ABI sceGnmDrawIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32
cmdbuf[0] = data_offset;
cmdbuf[1] = vertex_sgpr_offset == 0 ? 0 : (vertex_sgpr_offset & 0xffffu) + sgpr_offset;
- cmdbuf[2] = instance_vgpr_offset == 0 ? 0 : (instance_vgpr_offset & 0xffffu) + sgpr_offset;
+ cmdbuf[2] = instance_sgpr_offset == 0 ? 0 : (instance_sgpr_offset & 0xffffu) + sgpr_offset;
cmdbuf[3] = 2; // auto index
cmdbuf += 4;
@@ -735,11 +753,11 @@ u32 PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState(u32* cmdbuf, u32 size) {
cmdbuf = ClearContextState(cmdbuf);
}
- std::memcpy(cmdbuf, InitSequence.data(), InitSequence.size() * 4);
- cmdbuf += InitSequence.size();
+ std::memcpy(cmdbuf, &InitSequence[2], (InitSequence.size() - 2) * 4);
+ cmdbuf += InitSequence.size() - 2;
const auto cmdbuf_left =
- HwInitPacketSize - InitSequence.size() - (clear_state ? 0xc : 0) - 1;
+ HwInitPacketSize - (InitSequence.size() - 2) - (clear_state ? 0xc : 0) - 1;
cmdbuf = WriteHeader(cmdbuf, cmdbuf_left);
cmdbuf = WriteBody(cmdbuf, 0u);
@@ -757,10 +775,10 @@ u32 PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState175(u32* cmdbuf, u32 size) {
}
cmdbuf = ClearContextState(cmdbuf);
- std::memcpy(cmdbuf, InitSequence175.data(), InitSequence175.size() * 4);
- cmdbuf += InitSequence175.size();
+ std::memcpy(cmdbuf, &InitSequence175[2], (InitSequence175.size() - 2) * 4);
+ cmdbuf += InitSequence175.size() - 2;
- constexpr auto cmdbuf_left = HwInitPacketSize - InitSequence175.size() - 0xc - 1;
+ constexpr auto cmdbuf_left = HwInitPacketSize - (InitSequence175.size() - 2) - 0xc - 1;
WriteTrailingNop(cmdbuf);
return HwInitPacketSize;
@@ -778,11 +796,11 @@ u32 PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState200(u32* cmdbuf, u32 size) {
cmdbuf = ClearContextState(cmdbuf);
}
- std::memcpy(cmdbuf, InitSequence200.data(), InitSequence200.size() * 4);
- cmdbuf += InitSequence200.size();
+ std::memcpy(cmdbuf, &InitSequence200[2], (InitSequence200.size() - 2) * 4);
+ cmdbuf += InitSequence200.size() - 2;
const auto cmdbuf_left =
- HwInitPacketSize - InitSequence200.size() - (clear_state ? 0xc : 0) - 1;
+ HwInitPacketSize - (InitSequence200.size() - 2) - (clear_state ? 0xc : 0) - 1;
cmdbuf = WriteHeader(cmdbuf, cmdbuf_left);
cmdbuf = WriteBody(cmdbuf, 0u);
@@ -804,11 +822,11 @@ u32 PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState350(u32* cmdbuf, u32 size) {
cmdbuf = ClearContextState(cmdbuf);
}
- std::memcpy(cmdbuf, InitSequence350.data(), InitSequence350.size() * 4);
- cmdbuf += InitSequence350.size();
+ std::memcpy(cmdbuf, &InitSequence350[2], (InitSequence350.size() - 2) * 4);
+ cmdbuf += InitSequence350.size() - 2;
const auto cmdbuf_left =
- HwInitPacketSize - InitSequence350.size() - (clear_state ? 0xc : 0) - 1;
+ HwInitPacketSize - (InitSequence350.size() - 2) - (clear_state ? 0xc : 0) - 1;
cmdbuf = WriteHeader(cmdbuf, cmdbuf_left);
cmdbuf = WriteBody(cmdbuf, 0u);
@@ -1743,7 +1761,7 @@ s32 PS4_SYSV_ABI sceGnmSetVsShader(u32* cmdbuf, u32 size, const u32* vs_regs, u3
return -1;
}
- const u32 var = shader_modifier == 0 ? vs_regs[2] : (vs_regs[2] & 0xfcfffc3f | shader_modifier);
+ const u32 var = shader_modifier == 0 ? vs_regs[2] : (vs_regs[2] & 0xfcfffc3f) | shader_modifier;
cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x48u, vs_regs[0], 0u); // SPI_SHADER_PGM_LO_VS
cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x4au, var, vs_regs[3]); // SPI_SHADER_PGM_RSRC1_VS
cmdbuf = PM4CmdSetData::SetContextReg(cmdbuf, 0x207u, vs_regs[6]); // PA_CL_VS_OUT_CNTL
@@ -2328,9 +2346,9 @@ s32 PS4_SYSV_ABI sceGnmUpdateVsShader(u32* cmdbuf, u32 size, const u32* vs_regs,
return ORBIS_OK;
}
-int PS4_SYSV_ABI sceGnmValidateCommandBuffers() {
- LOG_ERROR(Lib_GnmDriver, "(STUBBED) called");
- return ORBIS_OK;
+s32 PS4_SYSV_ABI sceGnmValidateCommandBuffers() {
+ LOG_TRACE(Lib_GnmDriver, "called");
+ return ORBIS_GNM_ERROR_VALIDATION_NOT_ENABLED; // not available in retail FW;
}
int PS4_SYSV_ABI sceGnmValidateDisableDiagnostics() {
diff --git a/src/core/libraries/gnmdriver/gnmdriver.h b/src/core/libraries/gnmdriver/gnmdriver.h
index 84872297e..754d488f8 100644
--- a/src/core/libraries/gnmdriver/gnmdriver.h
+++ b/src/core/libraries/gnmdriver/gnmdriver.h
@@ -45,7 +45,7 @@ s32 PS4_SYSV_ABI sceGnmDrawIndex(u32* cmdbuf, u32 size, u32 index_count, uintptr
u32 flags, u32 type);
s32 PS4_SYSV_ABI sceGnmDrawIndexAuto(u32* cmdbuf, u32 size, u32 index_count, u32 flags);
s32 PS4_SYSV_ABI sceGnmDrawIndexIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage,
- u32 vertex_sgpr_offset, u32 instance_vgpr_offset,
+ u32 vertex_sgpr_offset, u32 instance_sgpr_offset,
u32 flags);
int PS4_SYSV_ABI sceGnmDrawIndexIndirectCountMulti();
int PS4_SYSV_ABI sceGnmDrawIndexIndirectMulti();
@@ -53,7 +53,7 @@ int PS4_SYSV_ABI sceGnmDrawIndexMultiInstanced();
s32 PS4_SYSV_ABI sceGnmDrawIndexOffset(u32* cmdbuf, u32 size, u32 index_offset, u32 index_count,
u32 flags);
s32 PS4_SYSV_ABI sceGnmDrawIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage,
- u32 vertex_sgpr_offset, u32 instance_vgpr_offset, u32 flags);
+ u32 vertex_sgpr_offset, u32 instance_sgpr_offset, u32 flags);
int PS4_SYSV_ABI sceGnmDrawIndirectCountMulti();
int PS4_SYSV_ABI sceGnmDrawIndirectMulti();
u32 PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState(u32* cmdbuf, u32 size);
@@ -223,7 +223,7 @@ s32 PS4_SYSV_ABI sceGnmUpdatePsShader(u32* cmdbuf, u32 size, const u32* ps_regs)
s32 PS4_SYSV_ABI sceGnmUpdatePsShader350(u32* cmdbuf, u32 size, const u32* ps_regs);
s32 PS4_SYSV_ABI sceGnmUpdateVsShader(u32* cmdbuf, u32 size, const u32* vs_regs,
u32 shader_modifier);
-int PS4_SYSV_ABI sceGnmValidateCommandBuffers();
+s32 PS4_SYSV_ABI sceGnmValidateCommandBuffers();
int PS4_SYSV_ABI sceGnmValidateDisableDiagnostics();
int PS4_SYSV_ABI sceGnmValidateDisableDiagnostics2();
int PS4_SYSV_ABI sceGnmValidateDispatchCommandBuffers();
diff --git a/src/core/libraries/kernel/event_flag/event_flag.cpp b/src/core/libraries/kernel/event_flag/event_flag.cpp
index 8afd139c0..0fd0c3bb7 100644
--- a/src/core/libraries/kernel/event_flag/event_flag.cpp
+++ b/src/core/libraries/kernel/event_flag/event_flag.cpp
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include
+#include "common/assert.h"
#include "common/logging/log.h"
#include "core/libraries/error_codes.h"
#include "core/libraries/libs.h"
diff --git a/src/core/libraries/kernel/event_flag/event_flag_obj.cpp b/src/core/libraries/kernel/event_flag/event_flag_obj.cpp
index ed01d7cc0..6d6dcf7a9 100644
--- a/src/core/libraries/kernel/event_flag/event_flag_obj.cpp
+++ b/src/core/libraries/kernel/event_flag/event_flag_obj.cpp
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include
+
#include "core/libraries/error_codes.h"
#include "event_flag_obj.h"
diff --git a/src/core/libraries/kernel/event_flag/event_flag_obj.h b/src/core/libraries/kernel/event_flag/event_flag_obj.h
index fe50be697..8d1624e2b 100644
--- a/src/core/libraries/kernel/event_flag/event_flag_obj.h
+++ b/src/core/libraries/kernel/event_flag/event_flag_obj.h
@@ -2,8 +2,10 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
+
#include
#include
+
#include "common/types.h"
namespace Libraries::Kernel {
diff --git a/src/core/libraries/kernel/event_queue.cpp b/src/core/libraries/kernel/event_queue.cpp
index 3555fddc9..88918bf54 100644
--- a/src/core/libraries/kernel/event_queue.cpp
+++ b/src/core/libraries/kernel/event_queue.cpp
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include
+
#include "common/assert.h"
#include "core/libraries/kernel/event_queue.h"
diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp
index 990b11d69..f7f58df59 100644
--- a/src/core/libraries/kernel/file_system.cpp
+++ b/src/core/libraries/kernel/file_system.cpp
@@ -538,7 +538,7 @@ void fileSystemSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
// openOrbis (to check if it is valid out of OpenOrbis
LIB_FUNCTION("6c3rCVE-fTU", "libkernel", 1, "libkernel", 1, 1,
- posix_open); // _open shoudld be equal to open function
+ posix_open); // _open should be equal to open function
}
} // namespace Libraries::Kernel
diff --git a/src/core/libraries/kernel/libkernel.h b/src/core/libraries/kernel/libkernel.h
index 5b7f1e722..c28a548ff 100644
--- a/src/core/libraries/kernel/libkernel.h
+++ b/src/core/libraries/kernel/libkernel.h
@@ -4,6 +4,7 @@
#pragma once
#include
+
#include "common/types.h"
namespace Core::Loader {
diff --git a/src/core/libraries/kernel/memory_management.cpp b/src/core/libraries/kernel/memory_management.cpp
index fa3e1bc48..69e19a97e 100644
--- a/src/core/libraries/kernel/memory_management.cpp
+++ b/src/core/libraries/kernel/memory_management.cpp
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include
+
#include "common/alignment.h"
#include "common/assert.h"
#include "common/logging/log.h"
@@ -16,7 +17,8 @@ namespace Libraries::Kernel {
u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize() {
LOG_WARNING(Kernel_Vmm, "called");
- return SCE_KERNEL_MAIN_DMEM_SIZE;
+ const auto* memory = Core::Memory::Instance();
+ return memory->GetTotalDirectSize();
}
int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len,
@@ -53,8 +55,8 @@ int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u
s32 PS4_SYSV_ABI sceKernelAllocateMainDirectMemory(size_t len, size_t alignment, int memoryType,
s64* physAddrOut) {
- return sceKernelAllocateDirectMemory(0, SCE_KERNEL_MAIN_DMEM_SIZE, len, alignment, memoryType,
- physAddrOut);
+ const auto searchEnd = static_cast(sceKernelGetDirectMemorySize());
+ return sceKernelAllocateDirectMemory(0, searchEnd, len, alignment, memoryType, physAddrOut);
}
s32 PS4_SYSV_ABI sceKernelCheckedReleaseDirectMemory(u64 start, size_t len) {
@@ -76,19 +78,28 @@ s32 PS4_SYSV_ABI sceKernelAvailableDirectMemorySize(u64 searchStart, u64 searchE
LOG_WARNING(Kernel_Vmm, "called searchStart = {:#x}, searchEnd = {:#x}, alignment = {:#x}",
searchStart, searchEnd, alignment);
- if (searchEnd <= searchStart) {
+ if (physAddrOut == nullptr || sizeOut == nullptr) {
return ORBIS_KERNEL_ERROR_EINVAL;
}
- if (searchEnd > SCE_KERNEL_MAIN_DMEM_SIZE) {
+ if (searchEnd > sceKernelGetDirectMemorySize()) {
return ORBIS_KERNEL_ERROR_EINVAL;
}
+ if (searchEnd <= searchStart) {
+ return ORBIS_KERNEL_ERROR_ENOMEM;
+ }
auto* memory = Core::Memory::Instance();
- PAddr physAddr;
- s32 result =
- memory->DirectQueryAvailable(searchStart, searchEnd, alignment, &physAddr, sizeOut);
+ PAddr physAddr{};
+ size_t size{};
+ s32 result = memory->DirectQueryAvailable(searchStart, searchEnd, alignment, &physAddr, &size);
+
+ if (size == 0) {
+ return ORBIS_KERNEL_ERROR_ENOMEM;
+ }
+
*physAddrOut = static_cast(physAddr);
+ *sizeOut = size;
return result;
}
@@ -259,6 +270,7 @@ int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len);
s32 PS4_SYSV_ABI sceKernelBatchMap2(OrbisKernelBatchMapEntry* entries, int numEntries,
int* numEntriesOut, int flags) {
+ int result = ORBIS_OK;
int processed = 0;
int result = 0;
for (int i = 0; i < numEntries; i++) {
@@ -267,20 +279,19 @@ s32 PS4_SYSV_ABI sceKernelBatchMap2(OrbisKernelBatchMapEntry* entries, int numEn
break; // break and assign a value to numEntriesOut.
}
- if (entries[i].operation == MemoryOpTypes::ORBIS_KERNEL_MAP_OP_MAP_DIRECT) {
+ switch (entries[i].operation) {
+ case MemoryOpTypes::ORBIS_KERNEL_MAP_OP_MAP_DIRECT: {
result = sceKernelMapNamedDirectMemory(&entries[i].start, entries[i].length,
entries[i].protection, flags,
static_cast(entries[i].offset), 0, "");
- LOG_INFO(
- Kernel_Vmm,
- "BatchMap: entry = {}, operation = {}, len = {:#x}, offset = {:#x}, type = {}, "
- "result = {}",
- i, entries[i].operation, entries[i].length, entries[i].offset, (u8)entries[i].type,
- result);
-
- if (result == 0)
- processed++;
- } else if (entries[i].operation == MemoryOpTypes::ORBIS_KERNEL_MAP_OP_UNMAP) {
+ LOG_INFO(Kernel_Vmm,
+ "entry = {}, operation = {}, len = {:#x}, offset = {:#x}, type = {}, "
+ "result = {}",
+ i, entries[i].operation, entries[i].length, entries[i].offset,
+ (u8)entries[i].type, result);
+ break;
+ }
+ case MemoryOpTypes::ORBIS_KERNEL_MAP_OP_UNMAP: {
result = sceKernelMunmap(entries[i].start, entries[i].length);
LOG_INFO(Kernel_Vmm, "BatchMap: entry = {}, operation = {}, len = {:#x}, result = {}",
i, entries[i].operation, entries[i].length, result);
@@ -314,14 +325,26 @@ s32 PS4_SYSV_ABI sceKernelBatchMap2(OrbisKernelBatchMapEntry* entries, int numEn
result = sceKernelMapNamedFlexibleMemory(&entries[i].start, entries[i].length,
entries[i].protection, flags, "");
LOG_INFO(Kernel_Vmm,
- "BatchMap: entry = {}, operation = {}, len = {:#x}, type = {}, "
+ "entry = {}, operation = {}, len = {:#x}, type = {}, "
"result = {}",
i, entries[i].operation, entries[i].length, (u8)entries[i].type, result);
+ break;
+ }
+ case MemoryOpTypes::ORBIS_KERNEL_MAP_OP_TYPE_PROTECT: {
+ // By now, ignore protection and log it instead
+ LOG_WARNING(Kernel_Vmm,
+ "entry = {}, operation = {}, len = {:#x}, type = {} "
+ "is UNSUPPORTED and skipped",
+ i, entries[i].operation, entries[i].length, (u8)entries[i].type);
+ break;
+ }
+ default: {
+ UNREACHABLE();
+ }
+ }
- if (result == 0)
- processed++;
- } else {
- UNREACHABLE_MSG("called: Unimplemented Operation = {}", entries[i].operation);
+ if (result != ORBIS_OK) {
+ break;
}
}
LOG_INFO(Kernel_Vmm, "sceKernelBatchMap2 finished: processed = {}, result = {}", processed,
diff --git a/src/core/libraries/kernel/memory_management.h b/src/core/libraries/kernel/memory_management.h
index 97018e43f..b48990bfb 100644
--- a/src/core/libraries/kernel/memory_management.h
+++ b/src/core/libraries/kernel/memory_management.h
@@ -6,7 +6,7 @@
#include "common/bit_field.h"
#include "common/types.h"
-constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE = 6_GB; // ~ 6GB
+constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE = 5056_MB; // ~ 5GB
namespace Libraries::Kernel {
diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp
index 689532693..11d472a49 100644
--- a/src/core/libraries/kernel/thread_management.cpp
+++ b/src/core/libraries/kernel/thread_management.cpp
@@ -2,20 +2,23 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include
+#include
#include
-#include
+
#include "common/alignment.h"
#include "common/assert.h"
#include "common/error.h"
#include "common/logging/log.h"
#include "common/singleton.h"
#include "common/thread.h"
+#include "core/cpu_patches.h"
#include "core/libraries/error_codes.h"
#include "core/libraries/kernel/libkernel.h"
#include "core/libraries/kernel/thread_management.h"
#include "core/libraries/kernel/threads/threads.h"
#include "core/libraries/libs.h"
#include "core/linker.h"
+#include "core/tls.h"
#ifdef _WIN64
#include
#else
@@ -510,23 +513,24 @@ int PS4_SYSV_ABI scePthreadMutexattrInit(ScePthreadMutexattr* attr) {
int PS4_SYSV_ABI scePthreadMutexattrSettype(ScePthreadMutexattr* attr, int type) {
int ptype = PTHREAD_MUTEX_DEFAULT;
switch (type) {
- case 1:
+ case ORBIS_PTHREAD_MUTEX_ERRORCHECK:
ptype = PTHREAD_MUTEX_ERRORCHECK;
break;
- case 2:
+ case ORBIS_PTHREAD_MUTEX_RECURSIVE:
ptype = PTHREAD_MUTEX_RECURSIVE;
break;
- case 3:
- case 4:
+ case ORBIS_PTHREAD_MUTEX_NORMAL:
+ case ORBIS_PTHREAD_MUTEX_ADAPTIVE:
ptype = PTHREAD_MUTEX_NORMAL;
break;
default:
- UNREACHABLE_MSG("Invalid type: {}", type);
+ return SCE_KERNEL_ERROR_EINVAL;
}
int result = pthread_mutexattr_settype(&(*attr)->pth_mutex_attr, ptype);
+ ASSERT(result == 0);
- return result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL;
+ return SCE_OK;
}
int PS4_SYSV_ABI scePthreadMutexattrSetprotocol(ScePthreadMutexattr* attr, int protocol) {
@@ -984,12 +988,14 @@ static void cleanup_thread(void* arg) {
destructor(value);
}
}
+ Core::SetTcbBase(nullptr);
thread->is_almost_done = true;
}
static void* run_thread(void* arg) {
auto* thread = static_cast(arg);
Common::SetCurrentThreadName(thread->name.c_str());
+ Core::InitializeThreadPatchStack();
auto* linker = Common::Singleton::Instance();
linker->InitTlsForThread(false);
void* ret = nullptr;
@@ -1123,7 +1129,6 @@ int PS4_SYSV_ABI posix_pthread_join(ScePthread thread, void** res) {
}
int PS4_SYSV_ABI scePthreadDetach(ScePthread thread) {
- LOG_INFO(Kernel_Pthread, "thread create name = {}", thread->name);
thread->is_detached = true;
return ORBIS_OK;
}
@@ -1374,90 +1379,97 @@ int PS4_SYSV_ABI posix_pthread_detach(ScePthread thread) {
return pthread_detach(thread->pth);
}
-int PS4_SYSV_ABI posix_sem_init(sem_t* sem, int pshared, unsigned int value) {
- int result = sem_init(sem, pshared, value);
- if (result == -1) {
- SetPosixErrno(errno);
+int PS4_SYSV_ABI posix_sem_init(PthreadSemInternal** sem, int pshared, unsigned int value) {
+ if (value > ORBIS_KERNEL_SEM_VALUE_MAX) {
+ SetPosixErrno(EINVAL);
+ return -1;
}
- return result;
+ if (sem != nullptr) {
+ *sem = new PthreadSemInternal{
+ .semaphore = std::counting_semaphore{value},
+ .value = {static_cast(value)},
+ };
+ }
+ return 0;
}
-int PS4_SYSV_ABI posix_sem_wait(sem_t* sem) {
- int result = sem_wait(sem);
- if (result == -1) {
- SetPosixErrno(errno);
+int PS4_SYSV_ABI posix_sem_wait(PthreadSemInternal** sem) {
+ if (sem == nullptr || *sem == nullptr) {
+ SetPosixErrno(EINVAL);
+ return -1;
}
- return result;
+ (*sem)->semaphore.acquire();
+ --(*sem)->value;
+ return 0;
}
-int PS4_SYSV_ABI posix_sem_trywait(sem_t* sem) {
- int result = sem_trywait(sem);
- if (result == -1) {
- SetPosixErrno(errno);
+int PS4_SYSV_ABI posix_sem_trywait(PthreadSemInternal** sem) {
+ if (sem == nullptr || *sem == nullptr) {
+ SetPosixErrno(EINVAL);
+ return -1;
}
- return result;
+ if (!(*sem)->semaphore.try_acquire()) {
+ SetPosixErrno(EAGAIN);
+ return -1;
+ }
+ --(*sem)->value;
+ return 0;
}
-#ifndef HAVE_SEM_TIMEDWAIT
-int sem_timedwait(sem_t* sem, const struct timespec* abstime) {
- int rc;
- while ((rc = sem_trywait(sem)) == EAGAIN) {
- struct timespec curr_time;
- clock_gettime(CLOCK_REALTIME, &curr_time);
-
- s64 remaining_ns = 0;
- remaining_ns +=
- (static_cast(abstime->tv_sec) - static_cast(curr_time.tv_sec)) * 1000000000L;
- remaining_ns += static_cast(abstime->tv_nsec) - static_cast(curr_time.tv_nsec);
-
- if (remaining_ns <= 0) {
- return ETIMEDOUT;
- }
-
- struct timespec sleep_time;
- sleep_time.tv_sec = 0;
- if (remaining_ns < 5000000L) {
- sleep_time.tv_nsec = remaining_ns;
- } else {
- sleep_time.tv_nsec = 5000000;
- }
-
- nanosleep(&sleep_time, nullptr);
+int PS4_SYSV_ABI posix_sem_timedwait(PthreadSemInternal** sem, const timespec* t) {
+ if (sem == nullptr || *sem == nullptr) {
+ SetPosixErrno(EINVAL);
+ return -1;
}
- return rc;
-}
-#endif
-int PS4_SYSV_ABI posix_sem_timedwait(sem_t* sem, const timespec* t) {
- int result = sem_timedwait(sem, t);
- if (result == -1) {
- SetPosixErrno(errno);
+ using std::chrono::duration_cast;
+ using std::chrono::nanoseconds;
+ using std::chrono::seconds;
+ using std::chrono::system_clock;
+
+ const system_clock::time_point time{
+ duration_cast(seconds{t->tv_sec} + nanoseconds{t->tv_nsec})};
+ if (!(*sem)->semaphore.try_acquire_until(time)) {
+ SetPosixErrno(ETIMEDOUT);
+ return -1;
}
- return result;
+ --(*sem)->value;
+ return 0;
}
-int PS4_SYSV_ABI posix_sem_post(sem_t* sem) {
- int result = sem_post(sem);
- if (result == -1) {
- SetPosixErrno(errno);
+int PS4_SYSV_ABI posix_sem_post(PthreadSemInternal** sem) {
+ if (sem == nullptr || *sem == nullptr) {
+ SetPosixErrno(EINVAL);
+ return -1;
}
- return result;
+ if ((*sem)->value == ORBIS_KERNEL_SEM_VALUE_MAX) {
+ SetPosixErrno(EOVERFLOW);
+ return -1;
+ }
+ ++(*sem)->value;
+ (*sem)->semaphore.release();
+ return 0;
}
-int PS4_SYSV_ABI posix_sem_destroy(sem_t* sem) {
- int result = sem_destroy(sem);
- if (result == -1) {
- SetPosixErrno(errno);
+int PS4_SYSV_ABI posix_sem_destroy(PthreadSemInternal** sem) {
+ if (sem == nullptr || *sem == nullptr) {
+ SetPosixErrno(EINVAL);
+ return -1;
}
- return result;
+ delete *sem;
+ *sem = nullptr;
+ return 0;
}
-int PS4_SYSV_ABI posix_sem_getvalue(sem_t* sem, int* sval) {
- int result = sem_getvalue(sem, sval);
- if (result == -1) {
- SetPosixErrno(errno);
+int PS4_SYSV_ABI posix_sem_getvalue(PthreadSemInternal** sem, int* sval) {
+ if (sem == nullptr || *sem == nullptr) {
+ SetPosixErrno(EINVAL);
+ return -1;
}
- return result;
+ if (sval) {
+ *sval = (*sem)->value;
+ }
+ return 0;
}
int PS4_SYSV_ABI posix_pthread_attr_getstacksize(const pthread_attr_t* attr, size_t* size) {
diff --git a/src/core/libraries/kernel/thread_management.h b/src/core/libraries/kernel/thread_management.h
index c5935275f..a2b2f6fea 100644
--- a/src/core/libraries/kernel/thread_management.h
+++ b/src/core/libraries/kernel/thread_management.h
@@ -5,10 +5,12 @@
#include
#include
+#include
#include
#include
#include
#include
+
#include "common/types.h"
namespace Core::Loader {
@@ -19,6 +21,12 @@ namespace Libraries::Kernel {
constexpr int ORBIS_KERNEL_PRIO_FIFO_DEFAULT = 700;
constexpr int ORBIS_KERNEL_PRIO_FIFO_HIGHEST = 256;
constexpr int ORBIS_KERNEL_PRIO_FIFO_LOWEST = 767;
+constexpr int ORBIS_KERNEL_SEM_VALUE_MAX = 0x7FFFFFFF;
+
+constexpr int ORBIS_PTHREAD_MUTEX_ERRORCHECK = 1;
+constexpr int ORBIS_PTHREAD_MUTEX_RECURSIVE = 2;
+constexpr int ORBIS_PTHREAD_MUTEX_NORMAL = 3;
+constexpr int ORBIS_PTHREAD_MUTEX_ADAPTIVE = 4;
struct PthreadInternal;
struct PthreadAttrInternal;
@@ -104,6 +112,11 @@ struct PthreadRwInternal {
std::string name;
};
+struct PthreadSemInternal {
+ std::counting_semaphore semaphore;
+ std::atomic value;
+};
+
class PThreadPool {
public:
ScePthread Create();
diff --git a/src/core/libraries/kernel/threads/semaphore.cpp b/src/core/libraries/kernel/threads/semaphore.cpp
index 5304dc57b..63ca25338 100644
--- a/src/core/libraries/kernel/threads/semaphore.cpp
+++ b/src/core/libraries/kernel/threads/semaphore.cpp
@@ -2,10 +2,10 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include
+#include
#include
-#include
-#include
#include
+
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/libraries/error_codes.h"
@@ -13,9 +13,6 @@
namespace Libraries::Kernel {
-using ListBaseHook =
- boost::intrusive::list_base_hook>;
-
class Semaphore {
public:
Semaphore(s32 init_count, s32 max_count, std::string_view name, bool is_fifo)
@@ -37,7 +34,7 @@ public:
// Create waiting thread object and add it into the list of waiters.
WaitingThread waiter{need_count, is_fifo};
- AddWaiter(waiter);
+ AddWaiter(&waiter);
// Perform the wait.
return waiter.Wait(lk, timeout);
@@ -52,14 +49,14 @@ public:
// Wake up threads in order of priority.
for (auto it = wait_list.begin(); it != wait_list.end();) {
- auto& waiter = *it;
- if (waiter.need_count > token_count) {
+ auto* waiter = *it;
+ if (waiter->need_count > token_count) {
it++;
continue;
}
it = wait_list.erase(it);
- token_count -= waiter.need_count;
- waiter.cv.notify_one();
+ token_count -= waiter->need_count;
+ waiter->cv.notify_one();
}
return true;
@@ -70,9 +67,9 @@ public:
if (num_waiters) {
*num_waiters = wait_list.size();
}
- for (auto& waiter : wait_list) {
- waiter.was_cancled = true;
- waiter.cv.notify_one();
+ for (auto* waiter : wait_list) {
+ waiter->was_cancled = true;
+ waiter->cv.notify_one();
}
wait_list.clear();
token_count = set_count < 0 ? init_count : set_count;
@@ -80,7 +77,7 @@ public:
}
public:
- struct WaitingThread : public ListBaseHook {
+ struct WaitingThread {
std::condition_variable cv;
u32 priority;
s32 need_count;
@@ -132,7 +129,7 @@ public:
}
};
- void AddWaiter(WaitingThread& waiter) {
+ void AddWaiter(WaitingThread* waiter) {
// Insert at the end of the list for FIFO order.
if (is_fifo) {
wait_list.push_back(waiter);
@@ -140,16 +137,13 @@ public:
}
// Find the first with priority less then us and insert right before it.
auto it = wait_list.begin();
- while (it != wait_list.end() && it->priority > waiter.priority) {
+ while (it != wait_list.end() && (*it)->priority > waiter->priority) {
it++;
}
wait_list.insert(it, waiter);
}
- using WaitingThreads =
- boost::intrusive::list,
- boost::intrusive::constant_time_size>;
- WaitingThreads wait_list;
+ std::list wait_list;
std::string name;
std::atomic token_count;
std::mutex mutex;
diff --git a/src/core/libraries/kernel/time_management.cpp b/src/core/libraries/kernel/time_management.cpp
index c4854937b..7a6ba4f62 100644
--- a/src/core/libraries/kernel/time_management.cpp
+++ b/src/core/libraries/kernel/time_management.cpp
@@ -2,7 +2,9 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include
+
#include "common/assert.h"
+#include "common/debug.h"
#include "common/native_clock.h"
#include "core/libraries/error_codes.h"
#include "core/libraries/kernel/time_management.h"
@@ -30,7 +32,8 @@ u64 PS4_SYSV_ABI sceKernelGetTscFrequency() {
}
u64 PS4_SYSV_ABI sceKernelGetProcessTime() {
- return clock->GetProcessTimeUS();
+ // TODO: this timer should support suspends, so initial ptc needs to be updated on wake up
+ return clock->GetTimeUS(initial_ptc);
}
u64 PS4_SYSV_ABI sceKernelGetProcessTimeCounter() {
@@ -143,6 +146,7 @@ int PS4_SYSV_ABI sceKernelGettimeofday(OrbisKernelTimeval* tp) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
+#ifdef _WIN64
auto now = std::chrono::system_clock::now();
auto duration = now.time_since_epoch();
auto seconds = std::chrono::duration_cast(duration);
@@ -150,6 +154,12 @@ int PS4_SYSV_ABI sceKernelGettimeofday(OrbisKernelTimeval* tp) {
tp->tv_sec = seconds.count();
tp->tv_usec = microsecs.count();
+#else
+ timeval tv;
+ gettimeofday(&tv, nullptr);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_usec = tv.tv_usec;
+#endif
return ORBIS_OK;
}
diff --git a/src/core/libraries/libc/libc.cpp b/src/core/libraries/libc/libc.cpp
deleted file mode 100644
index dafb16bed..000000000
--- a/src/core/libraries/libc/libc.cpp
+++ /dev/null
@@ -1,496 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include
-#include "common/debug.h"
-#include "common/logging/log.h"
-#include "common/singleton.h"
-#include "core/libraries/libc/libc.h"
-#include "core/libraries/libc/libc_cxa.h"
-#include "core/libraries/libc/libc_math.h"
-#include "core/libraries/libc/libc_stdio.h"
-#include "core/libraries/libc/libc_stdlib.h"
-#include "core/libraries/libc/libc_string.h"
-#include "core/libraries/libs.h"
-
-namespace Libraries::LibC {
-
-constexpr bool log_file_libc = true; // disable it to disable logging
-static u32 g_need_sceLibc = 1;
-
-using cxa_destructor_func_t = void (*)(void*);
-
-struct CxaDestructor {
- cxa_destructor_func_t destructor_func;
- void* destructor_object;
- void* module_id;
-};
-
-struct CContext {
- std::vector cxa;
-};
-
-static PS4_SYSV_ABI int ps4___cxa_atexit(void (*func)(void*), void* arg, void* dso_handle) {
- auto* cc = Common::Singleton::Instance();
- CxaDestructor c{};
- c.destructor_func = func;
- c.destructor_object = arg;
- c.module_id = dso_handle;
- cc->cxa.push_back(c);
- return 0;
-}
-
-void PS4_SYSV_ABI ps4___cxa_finalize(void* d) {
- BREAKPOINT();
-}
-
-void PS4_SYSV_ABI ps4___cxa_pure_virtual() {
- BREAKPOINT();
-}
-
-static PS4_SYSV_ABI void ps4_init_env() {
- LOG_INFO(Lib_LibC, "called");
-}
-
-static PS4_SYSV_ABI void ps4_catchReturnFromMain(int status) {
- LOG_INFO(Lib_LibC, "returned = {}", status);
-}
-
-static PS4_SYSV_ABI void ps4__Assert() {
- LOG_INFO(Lib_LibC, "called");
- BREAKPOINT();
-}
-
-PS4_SYSV_ABI void ps4__ZdlPv(void* ptr) {
- std::free(ptr);
-}
-
-PS4_SYSV_ABI void ps4__ZSt11_Xbad_allocv() {
- LOG_INFO(Lib_LibC, "called");
- BREAKPOINT();
-}
-
-PS4_SYSV_ABI void ps4__ZSt14_Xlength_errorPKc() {
- LOG_INFO(Lib_LibC, "called");
- BREAKPOINT();
-}
-
-PS4_SYSV_ABI void* ps4__Znwm(u64 count) {
- if (count == 0) {
- LOG_INFO(Lib_LibC, "_Znwm count ={}", count);
- BREAKPOINT();
- }
- void* ptr = std::malloc(count);
- return ptr;
-}
-
-static constexpr u16 lowercaseTable[256] = {
- 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B,
- 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
- 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023,
- 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
- 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B,
- 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
- 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073,
- 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
- 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B,
- 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
- 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x0080, 0x0081, 0x0082, 0x0083,
- 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
- 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B,
- 0x009C, 0x009D, 0x009E, 0x009F, 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
- 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3,
- 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
- 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB,
- 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
- 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3,
- 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
- 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB,
- 0x00FC, 0x00FD, 0x00FE, 0x00FF,
-};
-
-const PS4_SYSV_ABI u16* ps4__Getptolower() {
- return &lowercaseTable[0];
-}
-
-static constexpr u16 uppercaseTable[256] = {
- 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B,
- 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
- 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023,
- 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
- 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B,
- 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
- 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053,
- 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
- 0x0060, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B,
- 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
- 0x0058, 0x0059, 0x005A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x0080, 0x0081, 0x0082, 0x0083,
- 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
- 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B,
- 0x009C, 0x009D, 0x009E, 0x009F, 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
- 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3,
- 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
- 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB,
- 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
- 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3,
- 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
- 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB,
- 0x00FC, 0x00FD, 0x00FE, 0x00FF,
-};
-
-const PS4_SYSV_ABI u16* ps4__Getptoupper() {
- return &uppercaseTable[0];
-}
-
-namespace CharacterType {
-enum : u16 {
- HexDigit = 0x1, // '0'-'9', 'A'-'F', 'a'-'f'
- Uppercase = 0x2, // 'A'-'Z'
- Space = 0x4,
- Punctuation = 0x08,
- Lowercase = 0x10, // 'a'-'z'
- DecimalDigit = 0x20, // '0'-'9'
- Control = 0x40, // CR, FF, HT, NL, VT
- Control2 = 0x80, // BEL, BS, etc
- ExtraSpace = 0x100,
- ExtraAlphabetic = 0x200,
- ExtraBlank = 0x400
-};
-}
-
-static constexpr u16 characterTypeTable[256] = {
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control | CharacterType::Control2 | CharacterType::ExtraBlank,
- CharacterType::Control | CharacterType::Control2,
- CharacterType::Control | CharacterType::Control2,
- CharacterType::Control | CharacterType::Control2,
- CharacterType::Control | CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Control2,
- CharacterType::Space, //
- CharacterType::Punctuation, // !
- CharacterType::Punctuation, // "
- CharacterType::Punctuation, // #
- CharacterType::Punctuation, // $
- CharacterType::Punctuation, // %
- CharacterType::Punctuation, // &
- CharacterType::Punctuation, // '
- CharacterType::Punctuation, // (
- CharacterType::Punctuation, // )
- CharacterType::Punctuation, // *
- CharacterType::Punctuation, // +
- CharacterType::Punctuation, // ,
- CharacterType::Punctuation, // -
- CharacterType::Punctuation, // .
- CharacterType::Punctuation, // /
- CharacterType::HexDigit | CharacterType::DecimalDigit, // 0
- CharacterType::HexDigit | CharacterType::DecimalDigit, // 1
- CharacterType::HexDigit | CharacterType::DecimalDigit, // 2
- CharacterType::HexDigit | CharacterType::DecimalDigit, // 3
- CharacterType::HexDigit | CharacterType::DecimalDigit, // 4
- CharacterType::HexDigit | CharacterType::DecimalDigit, // 5
- CharacterType::HexDigit | CharacterType::DecimalDigit, // 6
- CharacterType::HexDigit | CharacterType::DecimalDigit, // 7
- CharacterType::HexDigit | CharacterType::DecimalDigit, // 8
- CharacterType::HexDigit | CharacterType::DecimalDigit, // 9
- CharacterType::Punctuation, // :
- CharacterType::Punctuation, // ;
- CharacterType::Punctuation, // <
- CharacterType::Punctuation, // =
- CharacterType::Punctuation, // >
- CharacterType::Punctuation, // ?
- CharacterType::Punctuation, // @
- CharacterType::HexDigit | CharacterType::Uppercase, // A
- CharacterType::HexDigit | CharacterType::Uppercase, // B
- CharacterType::HexDigit | CharacterType::Uppercase, // C
- CharacterType::HexDigit | CharacterType::Uppercase, // D
- CharacterType::HexDigit | CharacterType::Uppercase, // E
- CharacterType::HexDigit | CharacterType::Uppercase, // F
- CharacterType::Uppercase, // G
- CharacterType::Uppercase, // H
- CharacterType::Uppercase, // I
- CharacterType::Uppercase, // J
- CharacterType::Uppercase, // K
- CharacterType::Uppercase, // L
- CharacterType::Uppercase, // M
- CharacterType::Uppercase, // N
- CharacterType::Uppercase, // O
- CharacterType::Uppercase, // P
- CharacterType::Uppercase, // Q
- CharacterType::Uppercase, // R
- CharacterType::Uppercase, // S
- CharacterType::Uppercase, // T
- CharacterType::Uppercase, // U
- CharacterType::Uppercase, // V
- CharacterType::Uppercase, // W
- CharacterType::Uppercase, // X
- CharacterType::Uppercase, // Y
- CharacterType::Uppercase, // Z
- CharacterType::Punctuation, // [
- CharacterType::Punctuation, //
- CharacterType::Punctuation, // ]
- CharacterType::Punctuation, // ^
- CharacterType::Punctuation, // _
- CharacterType::Punctuation, // `
- CharacterType::HexDigit | CharacterType::Lowercase, // a
- CharacterType::HexDigit | CharacterType::Lowercase, // b
- CharacterType::HexDigit | CharacterType::Lowercase, // c
- CharacterType::HexDigit | CharacterType::Lowercase, // d
- CharacterType::HexDigit | CharacterType::Lowercase, // e
- CharacterType::HexDigit | CharacterType::Lowercase, // f
- CharacterType::Lowercase, // g
- CharacterType::Lowercase, // h
- CharacterType::Lowercase, // i
- CharacterType::Lowercase, // j
- CharacterType::Lowercase, // k
- CharacterType::Lowercase, // l
- CharacterType::Lowercase, // m
- CharacterType::Lowercase, // n
- CharacterType::Lowercase, // o
- CharacterType::Lowercase, // p
- CharacterType::Lowercase, // q
- CharacterType::Lowercase, // r
- CharacterType::Lowercase, // s
- CharacterType::Lowercase, // t
- CharacterType::Lowercase, // u
- CharacterType::Lowercase, // v
- CharacterType::Lowercase, // w
- CharacterType::Lowercase, // x
- CharacterType::Lowercase, // y
- CharacterType::Lowercase, // z
- CharacterType::Punctuation, // {
- CharacterType::Punctuation, // |
- CharacterType::Punctuation, // }
- CharacterType::Punctuation, // ~
- CharacterType::Control2,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
-};
-
-const PS4_SYSV_ABI u16* ps4__Getpctype() {
- return &characterTypeTable[0];
-}
-
-void libcSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
- // cxa functions
- LIB_FUNCTION("3GPpjQdAMTw", "libc", 1, "libc", 1, 1, ps4___cxa_guard_acquire);
- LIB_FUNCTION("9rAeANT2tyE", "libc", 1, "libc", 1, 1, ps4___cxa_guard_release);
- LIB_FUNCTION("2emaaluWzUw", "libc", 1, "libc", 1, 1, ps4___cxa_guard_abort);
-
- // stdlib functions
- LIB_FUNCTION("uMei1W9uyNo", "libc", 1, "libc", 1, 1, ps4_exit);
- LIB_FUNCTION("8G2LB+A3rzg", "libc", 1, "libc", 1, 1, ps4_atexit);
- LIB_FUNCTION("gQX+4GDQjpM", "libc", 1, "libc", 1, 1, ps4_malloc);
- LIB_FUNCTION("tIhsqj0qsFE", "libc", 1, "libc", 1, 1, ps4_free);
- LIB_FUNCTION("cpCOXWMgha0", "libc", 1, "libc", 1, 1, ps4_rand);
- LIB_FUNCTION("AEJdIVZTEmo", "libc", 1, "libc", 1, 1, ps4_qsort);
-
- // math functions
- LIB_FUNCTION("EH-x713A99c", "libc", 1, "libc", 1, 1, ps4_atan2f);
- LIB_FUNCTION("QI-x0SL8jhw", "libc", 1, "libc", 1, 1, ps4_acosf);
- LIB_FUNCTION("ZE6RNL+eLbk", "libc", 1, "libc", 1, 1, ps4_tanf);
- LIB_FUNCTION("GZWjF-YIFFk", "libc", 1, "libc", 1, 1, ps4_asinf);
- LIB_FUNCTION("9LCjpWyQ5Zc", "libc", 1, "libc", 1, 1, ps4_pow);
- LIB_FUNCTION("cCXjU72Z0Ow", "libc", 1, "libc", 1, 1, ps4__Sin);
- LIB_FUNCTION("ZtjspkJQ+vw", "libc", 1, "libc", 1, 1, ps4__Fsin);
- LIB_FUNCTION("dnaeGXbjP6E", "libc", 1, "libc", 1, 1, ps4_exp2);
- LIB_FUNCTION("1D0H2KNjshE", "libc", 1, "libc", 1, 1, ps4_powf);
- LIB_FUNCTION("DDHG1a6+3q0", "libc", 1, "libc", 1, 1, ps4_roundf);
-
- // string functions
- LIB_FUNCTION("Ovb2dSJOAuE", "libc", 1, "libc", 1, 1, ps4_strcmp);
- LIB_FUNCTION("j4ViWNHEgww", "libc", 1, "libc", 1, 1, ps4_strlen);
- LIB_FUNCTION("6sJWiWSRuqk", "libc", 1, "libc", 1, 1, ps4_strncpy);
- LIB_FUNCTION("+P6FRGH4LfA", "libc", 1, "libc", 1, 1, ps4_memmove);
- LIB_FUNCTION("kiZSXIWd9vg", "libc", 1, "libc", 1, 1, ps4_strcpy);
- LIB_FUNCTION("Ls4tzzhimqQ", "libc", 1, "libc", 1, 1, ps4_strcat);
- LIB_FUNCTION("DfivPArhucg", "libc", 1, "libc", 1, 1, ps4_memcmp);
- LIB_FUNCTION("Q3VBxCXhUHs", "libc", 1, "libc", 1, 1, ps4_memcpy);
- LIB_FUNCTION("8zTFvBIAIN8", "libc", 1, "libc", 1, 1, ps4_memset);
- LIB_FUNCTION("9yDWMxEFdJU", "libc", 1, "libc", 1, 1, ps4_strrchr);
- LIB_FUNCTION("aesyjrHVWy4", "libc", 1, "libc", 1, 1, ps4_strncmp);
- LIB_FUNCTION("g7zzzLDYGw0", "libc", 1, "libc", 1, 1, ps4_strdup);
-
- // stdio functions
- LIB_FUNCTION("xeYO4u7uyJ0", "libc", 1, "libc", 1, 1, ps4_fopen);
- // LIB_FUNCTION("hcuQgD53UxM", "libc", 1, "libc", 1, 1, ps4_printf);
- LIB_FUNCTION("Q2V+iqvjgC0", "libc", 1, "libc", 1, 1, ps4_vsnprintf);
- LIB_FUNCTION("YQ0navp+YIc", "libc", 1, "libc", 1, 1, ps4_puts);
- // LIB_FUNCTION("fffwELXNVFA", "libc", 1, "libc", 1, 1, ps4_fprintf);
- LIB_FUNCTION("QMFyLoqNxIg", "libc", 1, "libc", 1, 1, ps4_setvbuf);
- LIB_FUNCTION("uodLYyUip20", "libc", 1, "libc", 1, 1, ps4_fclose);
- LIB_FUNCTION("rQFVBXp-Cxg", "libc", 1, "libc", 1, 1, ps4_fseek);
- LIB_FUNCTION("SHlt7EhOtqA", "libc", 1, "libc", 1, 1, ps4_fgetpos);
- LIB_FUNCTION("lbB+UlZqVG0", "libc", 1, "libc", 1, 1, ps4_fread);
- LIB_FUNCTION("Qazy8LmXTvw", "libc", 1, "libc", 1, 1, ps4_ftell);
-
- // misc
- LIB_OBJ("P330P3dFF68", "libc", 1, "libc", 1, 1, &g_need_sceLibc);
- LIB_OBJ("2sWzhYqFH4E", "libc", 1, "libc", 1, 1, stdout);
- LIB_OBJ("H8AprKeZtNg", "libc", 1, "libc", 1, 1, stderr);
- LIB_FUNCTION("bzQExy189ZI", "libc", 1, "libc", 1, 1, ps4_init_env);
- LIB_FUNCTION("XKRegsFpEpk", "libc", 1, "libc", 1, 1, ps4_catchReturnFromMain);
- LIB_FUNCTION("-QgqOT5u2Vk", "libc", 1, "libc", 1, 1, ps4__Assert);
- LIB_FUNCTION("z+P+xCnWLBk", "libc", 1, "libc", 1, 1, ps4__ZdlPv);
- LIB_FUNCTION("eT2UsmTewbU", "libc", 1, "libc", 1, 1, ps4__ZSt11_Xbad_allocv);
- LIB_FUNCTION("tQIo+GIPklo", "libc", 1, "libc", 1, 1, ps4__ZSt14_Xlength_errorPKc);
- LIB_FUNCTION("fJnpuVVBbKk", "libc", 1, "libc", 1, 1, ps4__Znwm);
- LIB_FUNCTION("tsvEmnenz48", "libc", 1, "libc", 1, 1, ps4___cxa_atexit);
- LIB_FUNCTION("H2e8t5ScQGc", "libc", 1, "libc", 1, 1, ps4___cxa_finalize);
- LIB_FUNCTION("zr094EQ39Ww", "libc", 1, "libc", 1, 1, ps4___cxa_pure_virtual);
- LIB_FUNCTION("1uJgoVq3bQU", "libc", 1, "libc", 1, 1, ps4__Getptolower);
- LIB_FUNCTION("rcQCUr0EaRU", "libc", 1, "libc", 1, 1, ps4__Getptoupper);
- LIB_FUNCTION("sUP1hBaouOw", "libc", 1, "libc", 1, 1, ps4__Getpctype);
-}
-
-}; // namespace Libraries::LibC
diff --git a/src/core/libraries/libc/libc.h b/src/core/libraries/libc/libc.h
deleted file mode 100644
index 6504b8d71..000000000
--- a/src/core/libraries/libc/libc.h
+++ /dev/null
@@ -1,14 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-namespace Core::Loader {
-class SymbolsResolver;
-}
-
-namespace Libraries::LibC {
-
-void libcSymbolsRegister(Core::Loader::SymbolsResolver* sym);
-
-} // namespace Libraries::LibC
diff --git a/src/core/libraries/libc/libc_cxa.cpp b/src/core/libraries/libc/libc_cxa.cpp
deleted file mode 100644
index ff10d3f08..000000000
--- a/src/core/libraries/libc/libc_cxa.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "common/logging/log.h"
-#include "core/libraries/libc/libc_cxa.h"
-
-// adapted from
-// https://opensource.apple.com/source/libcppabi/libcppabi-14/src/cxa_guard.cxx.auto.html
-
-namespace Libraries::LibC {
-
-// This file implements the __cxa_guard_* functions as defined at:
-// http://www.codesourcery.com/public/cxx-abi/abi.html
-//
-// The goal of these functions is to support thread-safe, one-time
-// initialization of function scope variables. The compiler will generate
-// code like the following:
-//
-// if ( obj_guard.first_byte == 0 ) {
-// if ( __cxa_guard_acquire(&obj_guard) ) {
-// try {
-// ... initialize the object ...;
-// }
-// catch (...) {
-// __cxa_guard_abort(&obj_guard);
-// throw;
-// }
-// ... queue object destructor with __cxa_atexit() ...;
-// __cxa_guard_release(&obj_guard);
-// }
-// }
-//
-// Notes:
-// ojb_guard is a 64-bytes in size and statically initialized to zero.
-//
-// Section 6.7 of the C++ Spec says "If control re-enters the declaration
-// recursively while the object is being initialized, the behavior is
-// undefined". This implementation calls abort().
-//
-
-// Note don't use function local statics to avoid use of cxa functions...
-static pthread_mutex_t __guard_mutex;
-static pthread_once_t __once_control = PTHREAD_ONCE_INIT;
-
-static void makeRecusiveMutex() {
- pthread_mutexattr_t recursiveMutexAttr;
- pthread_mutexattr_init(&recursiveMutexAttr);
- pthread_mutexattr_settype(&recursiveMutexAttr, PTHREAD_MUTEX_RECURSIVE);
- pthread_mutex_init(&__guard_mutex, &recursiveMutexAttr);
-}
-
-__attribute__((noinline)) static pthread_mutex_t* guard_mutex() {
- pthread_once(&__once_control, &makeRecusiveMutex);
- return &__guard_mutex;
-}
-
-// helper functions for getting/setting flags in guard_object
-static bool initializerHasRun(u64* guard_object) {
- return (*((u8*)guard_object) != 0);
-}
-
-static void setInitializerHasRun(u64* guard_object) {
- *((u8*)guard_object) = 1;
-}
-
-static bool inUse(u64* guard_object) {
- return (((u8*)guard_object)[1] != 0);
-}
-
-static void setInUse(u64* guard_object) {
- ((u8*)guard_object)[1] = 1;
-}
-
-static void setNotInUse(u64* guard_object) {
- ((u8*)guard_object)[1] = 0;
-}
-
-//
-// Returns 1 if the caller needs to run the initializer and then either
-// call __cxa_guard_release() or __cxa_guard_abort(). If zero is returned,
-// then the initializer has already been run. This function blocks
-// if another thread is currently running the initializer. This function
-// aborts if called again on the same guard object without an intervening
-// call to __cxa_guard_release() or __cxa_guard_abort().
-//
-int PS4_SYSV_ABI ps4___cxa_guard_acquire(u64* guard_object) {
- // Double check that the initializer has not already been run
- if (initializerHasRun(guard_object))
- return 0;
-
- // We now need to acquire a lock that allows only one thread
- // to run the initializer. If a different thread calls
- // __cxa_guard_acquire() with the same guard object, we want
- // that thread to block until this thread is done running the
- // initializer and calls __cxa_guard_release(). But if the same
- // thread calls __cxa_guard_acquire() with the same guard object,
- // we want to abort.
- // To implement this we have one global pthread recursive mutex
- // shared by all guard objects, but only one at a time.
-
- int result = ::pthread_mutex_lock(guard_mutex());
- if (result != 0) {
- LOG_ERROR(Lib_LibC, "pthread_mutex_lock failed with {}", result);
- }
- // At this point all other threads will block in __cxa_guard_acquire()
-
- // Check if another thread has completed initializer run
- if (initializerHasRun(guard_object)) {
- int result = ::pthread_mutex_unlock(guard_mutex());
- if (result != 0) {
- LOG_ERROR(Lib_LibC, "pthread_mutex_lock failed with {}", result);
- }
- return 0;
- }
-
- // The pthread mutex is recursive to allow other lazy initialized
- // function locals to be evaluated during evaluation of this one.
- // But if the same thread can call __cxa_guard_acquire() on the
- // *same* guard object again, we call abort();
- if (inUse(guard_object)) {
- LOG_ERROR(Lib_LibC,
- "initializer for function local static variable called enclosing function");
- }
-
- // mark this guard object as being in use
- setInUse(guard_object);
-
- // return non-zero to tell caller to run initializer
- return 1;
-}
-
-//
-// Sets the first byte of the guard_object to a non-zero value.
-// Releases any locks acquired by __cxa_guard_acquire().
-//
-void PS4_SYSV_ABI ps4___cxa_guard_release(u64* guard_object) {
- // first mark initalizer as having been run, so
- // other threads won't try to re-run it.
- setInitializerHasRun(guard_object);
-
- // release global mutex
- int result = ::pthread_mutex_unlock(guard_mutex());
- if (result != 0) {
- LOG_ERROR(Lib_LibC, "pthread_mutex_unlock failed with {}", result);
- }
-}
-
-//
-// Releases any locks acquired by __cxa_guard_acquire().
-//
-void PS4_SYSV_ABI ps4___cxa_guard_abort(u64* guard_object) {
- int result = ::pthread_mutex_unlock(guard_mutex());
- if (result != 0) {
- LOG_ERROR(Lib_LibC, "pthread_mutex_unlock failed with {}", result);
- }
-
- // now reset state, so possible to try to initialize again
- setNotInUse(guard_object);
-}
-
-} // namespace Libraries::LibC
diff --git a/src/core/libraries/libc/libc_cxa.h b/src/core/libraries/libc/libc_cxa.h
deleted file mode 100644
index 2594493eb..000000000
--- a/src/core/libraries/libc/libc_cxa.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include
-#include "common/types.h"
-
-namespace Libraries::LibC {
-
-int PS4_SYSV_ABI ps4___cxa_guard_acquire(u64* guard_object);
-void PS4_SYSV_ABI ps4___cxa_guard_release(u64* guard_object);
-void PS4_SYSV_ABI ps4___cxa_guard_abort(u64* guard_object);
-
-} // namespace Libraries::LibC
diff --git a/src/core/libraries/libc/libc_math.cpp b/src/core/libraries/libc/libc_math.cpp
deleted file mode 100644
index 3b51c80e2..000000000
--- a/src/core/libraries/libc/libc_math.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include
-#include "common/assert.h"
-#include "core/libraries/libc/libc_math.h"
-
-namespace Libraries::LibC {
-
-float PS4_SYSV_ABI ps4_atan2f(float y, float x) {
- return atan2f(y, x);
-}
-
-float PS4_SYSV_ABI ps4_acosf(float num) {
- return acosf(num);
-}
-
-float PS4_SYSV_ABI ps4_tanf(float num) {
- return tanf(num);
-}
-
-float PS4_SYSV_ABI ps4_asinf(float num) {
- return asinf(num);
-}
-
-double PS4_SYSV_ABI ps4_pow(double base, double exponent) {
- return pow(base, exponent);
-}
-
-float PS4_SYSV_ABI ps4_powf(float x, float y) {
- return powf(x, y);
-}
-
-float PS4_SYSV_ABI ps4_roundf(float arg) {
- return roundf(arg);
-}
-
-double PS4_SYSV_ABI ps4__Sin(double x) {
- return sin(x);
-}
-
-float PS4_SYSV_ABI ps4__Fsin(float arg, unsigned int m, int n) {
- ASSERT(n == 0);
- if (m != 0) {
- return cosf(arg);
- } else {
- return sinf(arg);
- }
-}
-
-double PS4_SYSV_ABI ps4_exp2(double arg) {
- return exp2(arg);
-}
-
-} // namespace Libraries::LibC
diff --git a/src/core/libraries/libc/libc_math.h b/src/core/libraries/libc/libc_math.h
deleted file mode 100644
index f73a33f14..000000000
--- a/src/core/libraries/libc/libc_math.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "common/types.h"
-
-namespace Libraries::LibC {
-
-float PS4_SYSV_ABI ps4_atan2f(float y, float x);
-float PS4_SYSV_ABI ps4_acosf(float num);
-float PS4_SYSV_ABI ps4_tanf(float num);
-float PS4_SYSV_ABI ps4_asinf(float num);
-double PS4_SYSV_ABI ps4_pow(double base, double exponent);
-double PS4_SYSV_ABI ps4__Sin(double x);
-float PS4_SYSV_ABI ps4__Fsin(float arg, unsigned int, int);
-double PS4_SYSV_ABI ps4_exp2(double arg);
-float PS4_SYSV_ABI ps4_powf(float x, float y);
-float PS4_SYSV_ABI ps4_roundf(float arg);
-
-} // namespace Libraries::LibC
diff --git a/src/core/libraries/libc/libc_stdio.cpp b/src/core/libraries/libc/libc_stdio.cpp
deleted file mode 100644
index 2b15bd369..000000000
--- a/src/core/libraries/libc/libc_stdio.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "common/logging/log.h"
-#include "common/singleton.h"
-#include "core/file_sys/fs.h"
-#include "core/libraries/libc/libc_stdio.h"
-
-namespace Libraries::LibC {
-
-std::FILE* PS4_SYSV_ABI ps4_fopen(const char* filename, const char* mode) {
- auto* mnt = Common::Singleton::Instance();
- const auto host_path = mnt->GetHostPath(filename).string();
- FILE* f = std::fopen(host_path.c_str(), mode);
- if (f != nullptr) {
- LOG_INFO(Lib_LibC, "fopen = {}", host_path);
- } else {
- LOG_INFO(Lib_LibC, "fopen can't open = {}", host_path);
- }
- return f;
-}
-
-int PS4_SYSV_ABI ps4_fclose(FILE* stream) {
- LOG_INFO(Lib_LibC, "callled");
- int ret = 0;
- if (stream != nullptr) {
- ret = fclose(stream);
- }
- return ret;
-}
-
-int PS4_SYSV_ABI ps4_setvbuf(FILE* stream, char* buf, int mode, size_t size) {
- return setvbuf(stream, buf, mode, size);
-}
-
-int PS4_SYSV_ABI ps4_fseek(FILE* stream, long offset, int whence) {
- return fseek(stream, offset, whence);
-}
-
-int PS4_SYSV_ABI ps4_fgetpos(FILE* stream, fpos_t* pos) {
- return fgetpos(stream, pos);
-}
-
-std::size_t PS4_SYSV_ABI ps4_fread(void* ptr, size_t size, size_t nmemb, FILE* stream) {
- return fread(ptr, size, nmemb, stream);
-}
-
-int PS4_SYSV_ABI ps4_printf(VA_ARGS) {
- VA_CTX(ctx);
- return printf_ctx(&ctx);
-}
-
-int PS4_SYSV_ABI ps4_fprintf(FILE* file, VA_ARGS) {
- int fd = fileno(file);
- if (fd == 1 || fd == 2) { // output stdout and stderr to console
- VA_CTX(ctx);
- return printf_ctx(&ctx);
- } else {
- VA_CTX(ctx);
- char buf[256];
- fprintf_ctx(&ctx, buf);
- return fprintf(file, "%s", buf);
- }
-}
-
-int PS4_SYSV_ABI ps4_vsnprintf(char* s, size_t n, const char* format, VaList* arg) {
- return vsnprintf_ctx(s, n, format, arg);
-}
-
-int PS4_SYSV_ABI ps4_puts(const char* s) {
- return std::puts(s);
-}
-
-long PS4_SYSV_ABI ps4_ftell(FILE* stream) {
- return ftell(stream);
-}
-
-} // namespace Libraries::LibC
diff --git a/src/core/libraries/libc/libc_stdio.h b/src/core/libraries/libc/libc_stdio.h
deleted file mode 100644
index 806c17c28..000000000
--- a/src/core/libraries/libc/libc_stdio.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "common/types.h"
-#include "core/libraries/libc/printf.h"
-
-namespace Libraries::LibC {
-
-std::FILE* PS4_SYSV_ABI ps4_fopen(const char* filename, const char* mode);
-int PS4_SYSV_ABI ps4_printf(VA_ARGS);
-int PS4_SYSV_ABI ps4_vsnprintf(char* s, size_t n, const char* format, VaList* arg);
-int PS4_SYSV_ABI ps4_puts(const char* s);
-int PS4_SYSV_ABI ps4_fprintf(FILE* file, VA_ARGS);
-int PS4_SYSV_ABI ps4_setvbuf(FILE* stream, char* buf, int mode, size_t size);
-int PS4_SYSV_ABI ps4_fclose(FILE* stream);
-int PS4_SYSV_ABI ps4_fseek(FILE* stream, long offset, int whence);
-int PS4_SYSV_ABI ps4_fgetpos(FILE* stream, fpos_t* pos);
-std::size_t PS4_SYSV_ABI ps4_fread(void* ptr, size_t size, size_t nmemb, FILE* stream);
-long PS4_SYSV_ABI ps4_ftell(FILE* stream);
-
-} // namespace Libraries::LibC
diff --git a/src/core/libraries/libc/libc_stdlib.cpp b/src/core/libraries/libc/libc_stdlib.cpp
deleted file mode 100644
index e71838780..000000000
--- a/src/core/libraries/libc/libc_stdlib.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include
-#include "common/assert.h"
-#include "core/libraries/libc/libc_stdlib.h"
-
-namespace Libraries::LibC {
-
-void PS4_SYSV_ABI ps4_exit(int code) {
- std::exit(code);
-}
-
-int PS4_SYSV_ABI ps4_atexit(void (*func)()) {
- int rt = std::atexit(func);
- ASSERT_MSG(rt == 0, "atexit returned {}", rt);
- return rt;
-}
-
-void* PS4_SYSV_ABI ps4_malloc(size_t size) {
- return std::malloc(size);
-}
-
-void PS4_SYSV_ABI ps4_free(void* ptr) {
- std::free(ptr);
-}
-
-typedef int(PS4_SYSV_ABI* pfunc_QsortCmp)(const void*, const void*);
-thread_local static pfunc_QsortCmp compair_ps4;
-
-int qsort_compair(const void* arg1, const void* arg2) {
- return compair_ps4(arg1, arg2);
-}
-
-void PS4_SYSV_ABI ps4_qsort(void* ptr, size_t count, size_t size,
- int(PS4_SYSV_ABI* comp)(const void*, const void*)) {
- compair_ps4 = comp;
- std::qsort(ptr, count, size, qsort_compair);
-}
-
-int PS4_SYSV_ABI ps4_rand() {
- return std::rand();
-}
-
-} // namespace Libraries::LibC
diff --git a/src/core/libraries/libc/libc_stdlib.h b/src/core/libraries/libc/libc_stdlib.h
deleted file mode 100644
index 4bb5f6c13..000000000
--- a/src/core/libraries/libc/libc_stdlib.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include
-#include "common/types.h"
-
-namespace Libraries::LibC {
-
-void PS4_SYSV_ABI ps4_exit(int code);
-int PS4_SYSV_ABI ps4_atexit(void (*func)());
-void* PS4_SYSV_ABI ps4_malloc(size_t size);
-void PS4_SYSV_ABI ps4_free(void* ptr);
-void PS4_SYSV_ABI ps4_qsort(void* ptr, size_t count, size_t size,
- int(PS4_SYSV_ABI* comp)(const void*, const void*));
-int PS4_SYSV_ABI ps4_rand();
-
-} // namespace Libraries::LibC
diff --git a/src/core/libraries/libc/libc_string.cpp b/src/core/libraries/libc/libc_string.cpp
deleted file mode 100644
index af7524e6e..000000000
--- a/src/core/libraries/libc/libc_string.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include
-#include
-#include "core/libraries/libc/libc_string.h"
-
-namespace Libraries::LibC {
-
-int PS4_SYSV_ABI ps4_memcmp(const void* s1, const void* s2, size_t n) {
- return std::memcmp(s1, s2, n);
-}
-
-void* PS4_SYSV_ABI ps4_memcpy(void* dest, const void* src, size_t n) {
- return std::memcpy(dest, src, n);
-}
-
-void* PS4_SYSV_ABI ps4_memset(void* s, int c, size_t n) {
- return std::memset(s, c, n);
-}
-
-int PS4_SYSV_ABI ps4_strcmp(const char* str1, const char* str2) {
- return std::strcmp(str1, str2);
-}
-
-char* PS4_SYSV_ABI ps4_strncpy(char* dest, const char* src, size_t count) {
- return std::strncpy(dest, src, count);
-}
-
-void* PS4_SYSV_ABI ps4_memmove(void* dest, const void* src, std::size_t count) {
- return std::memmove(dest, src, count);
-}
-
-char* PS4_SYSV_ABI ps4_strcpy(char* dest, const char* src) {
- return std::strcpy(dest, src);
-}
-
-char* PS4_SYSV_ABI ps4_strcat(char* dest, const char* src) {
- return std::strcat(dest, src);
-}
-
-size_t PS4_SYSV_ABI ps4_strlen(const char* str) {
- return std::strlen(str);
-}
-
-char* PS4_SYSV_ABI ps4_strrchr(const char* s, int c) {
- return (char*)strrchr(s, c);
-}
-
-int PS4_SYSV_ABI ps4_strncmp(const char* s1, const char* s2, size_t n) {
- return strncmp(s1, s2, n);
-}
-
-char* PS4_SYSV_ABI ps4_strdup(const char* str1) {
- char* dup = (char*)std::malloc(std::strlen(str1) + 1);
- if (dup != NULL)
- strcpy(dup, str1);
- return dup;
-}
-
-} // namespace Libraries::LibC
diff --git a/src/core/libraries/libc/libc_string.h b/src/core/libraries/libc/libc_string.h
deleted file mode 100644
index 3e575fa30..000000000
--- a/src/core/libraries/libc/libc_string.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include
-#include "common/types.h"
-
-namespace Libraries::LibC {
-
-int PS4_SYSV_ABI ps4_memcmp(const void* s1, const void* s2, size_t n);
-void* PS4_SYSV_ABI ps4_memcpy(void* dest, const void* src, size_t n);
-void* PS4_SYSV_ABI ps4_memset(void* s, int c, size_t n);
-int PS4_SYSV_ABI ps4_strcmp(const char* str1, const char* str2);
-char* PS4_SYSV_ABI ps4_strncpy(char* dest, const char* src, size_t count);
-void* PS4_SYSV_ABI ps4_memmove(void* dest, const void* src, std::size_t count);
-char* PS4_SYSV_ABI ps4_strcpy(char* destination, const char* source);
-char* PS4_SYSV_ABI ps4_strcat(char* dest, const char* src);
-size_t PS4_SYSV_ABI ps4_strlen(const char* str);
-char* PS4_SYSV_ABI ps4_strrchr(const char* s, int c);
-int PS4_SYSV_ABI ps4_strncmp(const char* s1, const char* s2, size_t n);
-char* PS4_SYSV_ABI ps4_strdup(const char* str1);
-
-} // namespace Libraries::LibC
diff --git a/src/core/libraries/libc/printf.h b/src/core/libraries/libc/printf.h
deleted file mode 100644
index e84654274..000000000
--- a/src/core/libraries/libc/printf.h
+++ /dev/null
@@ -1,753 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2014-2018 Marco Paland (info@paland.com)
-// SPDX-License-Identifier: MIT
-
-///////////////////////////////////////////////////////////////////////////////
-// \author (c) Marco Paland (info@paland.com)
-// 2014-2018, PALANDesign Hannover, Germany
-//
-// \license The MIT License (MIT)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-// \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on
-// embedded systems with a very limited resources.
-// Use this instead of bloated standard/newlib printf.
-// These routines are thread safe and reentrant!
-//
-///////////////////////////////////////////////////////////////////////////////
-// Vita3K emulator project
-// Copyright (C) 2023 Vita3K team
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-// copied from Vita3k project at 6/10/2023 (latest update 30/06/2023)
-// modifications for adapting va_args parameters
-
-#pragma once
-
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "va_ctx.h"
-
-namespace Libraries::LibC {
-// ntoa conversion buffer size, this must be big enough to hold
-// one converted numeric number including padded zeros (dynamically created on stack)
-// 32 byte is a good default
-#define PRINTF_NTOA_BUFFER_SIZE 32U
-
-// ftoa conversion buffer size, this must be big enough to hold
-// one converted float number including padded zeros (dynamically created on stack)
-// 32 byte is a good default
-#define PRINTF_FTOA_BUFFER_SIZE 32U
-
-// define this to support floating point (%f)
-#define PRINTF_SUPPORT_FLOAT
-
-// define this to support long long types (%llu or %p)
-#define PRINTF_SUPPORT_LONG_LONG
-
-// define this to support the ptrdiff_t type (%t)
-// ptrdiff_t is normally defined in as long or long long type
-#define PRINTF_SUPPORT_PTRDIFF_T
-
-///////////////////////////////////////////////////////////////////////////////
-
-// internal flag definitions
-#define FLAGS_ZEROPAD (1U << 0U)
-#define FLAGS_LEFT (1U << 1U)
-#define FLAGS_PLUS (1U << 2U)
-#define FLAGS_SPACE (1U << 3U)
-#define FLAGS_HASH (1U << 4U)
-#define FLAGS_UPPERCASE (1U << 5U)
-#define FLAGS_CHAR (1U << 6U)
-#define FLAGS_SHORT (1U << 7U)
-#define FLAGS_LONG (1U << 8U)
-#define FLAGS_LONG_LONG (1U << 9U)
-#define FLAGS_PRECISION (1U << 10U)
-#define FLAGS_WIDTH (1U << 11U)
-
-// output function type
-typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen);
-
-// wrapper (used as buffer) for output function type
-typedef struct {
- void (*fct)(char character, void* arg);
- void* arg;
-} out_fct_wrap_type;
-
-// internal buffer output
-static inline void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen) {
- if (idx < maxlen) {
- ((char*)buffer)[idx] = character;
- }
-}
-
-// internal null output
-static inline void _out_null(char character, void* buffer, size_t idx, size_t maxlen) {
- (void)character;
- (void)buffer;
- (void)idx;
- (void)maxlen;
-}
-
-// internal output function wrapper
-static inline void _out_fct(char character, void* buffer, size_t idx, size_t maxlen) {
- (void)idx;
- (void)maxlen;
- // buffer is the output fct pointer
- ((out_fct_wrap_type*)buffer)->fct(character, ((out_fct_wrap_type*)buffer)->arg);
-}
-
-// internal strlen
-// \return The length of the string (excluding the terminating 0)
-static inline unsigned int _strlen(const char* str) {
- const char* s;
- for (s = str; *s; ++s)
- ;
- return (unsigned int)(s - str);
-}
-
-// internal test if char is a digit (0-9)
-// \return true if char is a digit
-static inline bool _is_digit(char ch) {
- return (ch >= '0') && (ch <= '9');
-}
-
-// internal ASCII string to unsigned int conversion
-static inline unsigned int _atoi(const char** str) {
- unsigned int i = 0U;
- while (_is_digit(**str)) {
- i = i * 10U + (unsigned int)(*((*str)++) - '0');
- }
- return i;
-}
-
-// internal itoa format
-static inline size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, size_t maxlen,
- char* buf, size_t len, bool negative, unsigned int base,
- unsigned int prec, unsigned int width, unsigned int flags) {
- const size_t start_idx = idx;
-
- // pad leading zeros
- while (!(flags & FLAGS_LEFT) && (len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
- buf[len++] = '0';
- }
- while (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD) && (len < width) &&
- (len < PRINTF_NTOA_BUFFER_SIZE)) {
- buf[len++] = '0';
- }
-
- // handle hash
- if (flags & FLAGS_HASH) {
- if (((len == prec) || (len == width)) && (len > 0U)) {
- len--;
- if ((base == 16U) && (len > 0U)) {
- len--;
- }
- }
- if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
- buf[len++] = 'x';
- }
- if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
- buf[len++] = 'X';
- }
- if (len < PRINTF_NTOA_BUFFER_SIZE) {
- buf[len++] = '0';
- }
- }
-
- // handle sign
- if ((len == width) && (negative || (flags & FLAGS_PLUS) || (flags & FLAGS_SPACE))) {
- len--;
- }
- if (len < PRINTF_NTOA_BUFFER_SIZE) {
- if (negative) {
- buf[len++] = '-';
- } else if (flags & FLAGS_PLUS) {
- buf[len++] = '+'; // ignore the space if the '+' exists
- } else if (flags & FLAGS_SPACE) {
- buf[len++] = ' ';
- }
- }
-
- // pad spaces up to given width
- if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) {
- for (size_t i = len; i < width; i++) {
- out(' ', buffer, idx++, maxlen);
- }
- }
-
- // reverse string
- for (size_t i = 0U; i < len; i++) {
- out(buf[len - i - 1U], buffer, idx++, maxlen);
- }
-
- // append pad spaces up to given width
- if (flags & FLAGS_LEFT) {
- while (idx - start_idx < width) {
- out(' ', buffer, idx++, maxlen);
- }
- }
-
- return idx;
-}
-
-// internal itoa for 'long' type
-static inline size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen,
- unsigned long value, bool negative, unsigned long base,
- unsigned int prec, unsigned int width, unsigned int flags) {
- char buf[PRINTF_NTOA_BUFFER_SIZE];
- size_t len = 0U;
-
- // write if precision != 0 and value is != 0
- if (!(flags & FLAGS_PRECISION) || value) {
- do {
- const char digit = (char)(value % base);
- buf[len++] =
- digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
- value /= base;
- } while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
- }
-
- return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec,
- width, flags);
-}
-
-// internal itoa for 'long long' type
-#if defined(PRINTF_SUPPORT_LONG_LONG)
-static inline size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen,
- unsigned long long value, bool negative,
- unsigned long long base, unsigned int prec, unsigned int width,
- unsigned int flags) {
- char buf[PRINTF_NTOA_BUFFER_SIZE];
- size_t len = 0U;
-
- // write if precision != 0 and value is != 0
- if (!(flags & FLAGS_PRECISION) || value) {
- do {
- const char digit = (char)(value % base);
- buf[len++] =
- digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
- value /= base;
- } while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
- }
-
- return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec,
- width, flags);
-}
-#endif // PRINTF_SUPPORT_LONG_LONG
-
-#if defined(PRINTF_SUPPORT_FLOAT)
-static inline size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value,
- unsigned int prec, unsigned int width, unsigned int flags) {
- char buf[PRINTF_FTOA_BUFFER_SIZE];
- size_t len = 0U;
- double diff = 0.0;
-
- // if input is larger than thres_max, revert to exponential
- const double thres_max = (double)0x7FFFFFFF;
-
- // powers of 10
- static const double pow10[] = {1, 10, 100, 1000, 10000,
- 100000, 1000000, 10000000, 100000000, 1000000000};
-
- // test for negative
- bool negative = false;
- if (value < 0) {
- negative = true;
- value = 0 - value;
- }
-
- // set default precision to 6, if not set explicitly
- if (!(flags & FLAGS_PRECISION)) {
- prec = 6U;
- }
- // limit precision to 9, cause a prec >= 10 can lead to overflow errors
- while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) {
- buf[len++] = '0';
- prec--;
- }
-
- int whole = (int)value;
- double tmp = (value - whole) * pow10[prec];
- unsigned long frac = (unsigned long)tmp;
- diff = tmp - frac;
-
- if (diff > 0.5) {
- ++frac;
- // handle rollover, e.g. case 0.99 with prec 1 is 1.0
- if (frac >= pow10[prec]) {
- frac = 0;
- ++whole;
- }
- } else if ((diff == 0.5) && ((frac == 0U) || (frac & 1U))) {
- // if halfway, round up if odd, OR if last digit is 0
- ++frac;
- }
-
- // TBD: for very large numbers switch back to native sprintf for exponentials. Anyone want to
- // write code to replace this? Normal printf behavior is to print EVERY whole number digit which
- // can be 100s of characters overflowing your buffers == bad
- if (value > thres_max) {
- return 0U;
- }
-
- if (prec == 0U) {
- diff = value - (double)whole;
- if (diff > 0.5) {
- // greater than 0.5, round up, e.g. 1.6 -> 2
- ++whole;
- } else if ((diff == 0.5) && (whole & 1)) {
- // exactly 0.5 and ODD, then round up
- // 1.5 -> 2, but 2.5 -> 2
- ++whole;
- }
- } else {
- unsigned int count = prec;
- // now do fractional part, as an unsigned number
- while (len < PRINTF_FTOA_BUFFER_SIZE) {
- --count;
- buf[len++] = (char)(48U + (frac % 10U));
- if (!(frac /= 10U)) {
- break;
- }
- }
- // add extra 0s
- while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) {
- buf[len++] = '0';
- }
- if (len < PRINTF_FTOA_BUFFER_SIZE) {
- // add decimal
- buf[len++] = '.';
- }
- }
-
- // do whole part, number is reversed
- while (len < PRINTF_FTOA_BUFFER_SIZE) {
- buf[len++] = (char)(48 + (whole % 10));
- if (!(whole /= 10)) {
- break;
- }
- }
-
- // pad leading zeros
- while (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD) && (len < width) &&
- (len < PRINTF_FTOA_BUFFER_SIZE)) {
- buf[len++] = '0';
- }
-
- // handle sign
- if ((len == width) && (negative || (flags & FLAGS_PLUS) || (flags & FLAGS_SPACE))) {
- len--;
- }
- if (len < PRINTF_FTOA_BUFFER_SIZE) {
- if (negative) {
- buf[len++] = '-';
- } else if (flags & FLAGS_PLUS) {
- buf[len++] = '+'; // ignore the space if the '+' exists
- } else if (flags & FLAGS_SPACE) {
- buf[len++] = ' ';
- }
- }
-
- // pad spaces up to given width
- if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) {
- for (size_t i = len; i < width; i++) {
- out(' ', buffer, idx++, maxlen);
- }
- }
-
- // reverse string
- for (size_t i = 0U; i < len; i++) {
- out(buf[len - i - 1U], buffer, idx++, maxlen);
- }
-
- // append pad spaces up to given width
- if (flags & FLAGS_LEFT) {
- while (idx < width) {
- out(' ', buffer, idx++, maxlen);
- }
- }
-
- return idx;
-}
-#endif // PRINTF_SUPPORT_FLOAT
-
-// internal vsnprintf
-static inline int _vsnprintf(out_fct_type out, char* buffer, const char* format, VaList* va_list) {
- unsigned int flags, width, precision, n;
- size_t idx = 0U;
- auto maxlen = static_cast(-1);
-
- if (!buffer) {
- // use null output function
- out = _out_null;
- }
-
- while (*format) {
- // format specifier? %[flags][width][.precision][length]
- if (*format != '%') {
- // no
- out(*format, buffer, idx++, maxlen);
- format++;
- continue;
- } else {
- // yes, evaluate it
- format++;
- }
-
- // evaluate flags
- flags = 0U;
- do {
- switch (*format) {
- case '0':
- flags |= FLAGS_ZEROPAD;
- format++;
- n = 1U;
- break;
- case '-':
- flags |= FLAGS_LEFT;
- format++;
- n = 1U;
- break;
- case '+':
- flags |= FLAGS_PLUS;
- format++;
- n = 1U;
- break;
- case ' ':
- flags |= FLAGS_SPACE;
- format++;
- n = 1U;
- break;
- case '#':
- flags |= FLAGS_HASH;
- format++;
- n = 1U;
- break;
- default:
- n = 0U;
- break;
- }
- } while (n);
-
- // evaluate width field
- width = 0U;
- if (_is_digit(*format)) {
- width = _atoi(&format);
- } else if (*format == '*') {
- const int w = vaArgInteger(va_list); // const int w = va.next(cpu, mem);
-
- if (w < 0) {
- flags |= FLAGS_LEFT; // reverse padding
- width = (unsigned int)-w;
- } else {
- width = (unsigned int)w;
- }
- format++;
- }
-
- // evaluate precision field
- precision = 0U;
- if (*format == '.') {
- flags |= FLAGS_PRECISION;
- format++;
- if (_is_digit(*format)) {
- precision = _atoi(&format);
- } else if (*format == '*') {
- precision =
- vaArgInteger(va_list); // precision = (unsigned int)va.next(cpu, mem);
- format++;
- }
- }
-
- // evaluate length field
- switch (*format) {
- case 'l':
- flags |= FLAGS_LONG;
- format++;
- if (*format == 'l') {
- flags |= FLAGS_LONG_LONG;
- format++;
- }
- break;
- case 'h':
- flags |= FLAGS_SHORT;
- format++;
- if (*format == 'h') {
- flags |= FLAGS_CHAR;
- format++;
- }
- break;
-#if defined(PRINTF_SUPPORT_PTRDIFF_T)
- case 't':
- flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
- format++;
- break;
-#endif
- case 'j':
- flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
- format++;
- break;
- case 'z':
- flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
- format++;
- break;
- default:
- break;
- }
-
- // evaluate specifier
- switch (*format) {
- case 'd':
- case 'i':
- case 'u':
- case 'x':
- case 'X':
- case 'o':
- case 'b': {
- // set the base
- unsigned int base;
- if (*format == 'x' || *format == 'X') {
- base = 16U;
- } else if (*format == 'o') {
- base = 8U;
- } else if (*format == 'b') {
- base = 2U;
- flags &= ~FLAGS_HASH; // no hash for bin format
- } else {
- base = 10U;
- flags &= ~FLAGS_HASH; // no hash for dec format
- }
- // uppercase
- if (*format == 'X') {
- flags |= FLAGS_UPPERCASE;
- }
-
- // no plus or space flag for u, x, X, o, b
- if ((*format != 'i') && (*format != 'd')) {
- flags &= ~(FLAGS_PLUS | FLAGS_SPACE);
- }
-
- // convert the integer
- if ((*format == 'i') || (*format == 'd')) {
- // signed
- if (flags & FLAGS_LONG_LONG) {
-#if defined(PRINTF_SUPPORT_LONG_LONG)
- auto value = vaArgLongLong(
- va_list); // const long long value = va.next(cpu, mem);
- idx = _ntoa_long_long(out, buffer, idx, maxlen,
- (unsigned long long)(value > 0 ? value : 0 - value),
- value < 0, base, precision, width, flags);
-#endif
- } else if (flags & FLAGS_LONG) {
- auto value = vaArgLong(va_list); // const long value = va.next(cpu, mem);
- idx = _ntoa_long(out, buffer, idx, maxlen,
- (unsigned long)(value > 0 ? value : 0 - value), value < 0,
- base, precision, width, flags);
- } else {
- // const int value = (flags & FLAGS_CHAR) ? (char)va.next(cpu, mem) :
- // (flags & FLAGS_SHORT) ? (short int)va.next(cpu, mem): va.next(cpu,
- // mem);
- const int value =
- (flags & FLAGS_CHAR) ? static_cast(vaArgInteger(va_list))
- : (flags & FLAGS_SHORT) ? static_cast(vaArgInteger(va_list))
- : vaArgInteger(va_list);
- idx = _ntoa_long(out, buffer, idx, maxlen,
- (unsigned int)(value > 0 ? value : 0 - value), value < 0, base,
- precision, width, flags);
- }
- } else {
- // unsigned
- if (flags & FLAGS_LONG_LONG) {
-#if defined(PRINTF_SUPPORT_LONG_LONG)
- // idx = _ntoa_long_long(out, buffer, idx, maxlen, va.next(cpu, mem), false, base, precision, width, flags);
- idx = _ntoa_long_long(out, buffer, idx, maxlen,
- static_cast(vaArgLongLong(va_list)), false, base,
- precision, width, flags);
-#endif
- } else if (flags & FLAGS_LONG) {
- // idx = _ntoa_long(out, buffer, idx, maxlen, va.next(cpu, mem),
- // false, base, precision, width, flags);
- idx = _ntoa_long(out, buffer, idx, maxlen, static_cast(vaArgLong(va_list)),
- false, base, precision, width, flags);
- } else {
- // const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned
- // char)va.next(cpu, mem) : (flags & FLAGS_SHORT) ?
- // (unsigned short int)va.next(cpu, mem) : va.next(cpu, mem);
- const unsigned int value =
- (flags & FLAGS_CHAR) ? static_cast(vaArgInteger(va_list))
- : (flags & FLAGS_SHORT) ? static_cast(vaArgInteger(va_list))
- : static_cast(vaArgInteger(va_list));
- idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width,
- flags);
- }
- }
- format++;
- break;
- }
-#if defined(PRINTF_SUPPORT_FLOAT)
- case 'f':
- case 'F':
- // idx = _ftoa(out, buffer, idx, maxlen, va.next(cpu, mem), precision, width,
- // flags);
- idx = _ftoa(out, buffer, idx, maxlen, vaArgDouble(va_list), precision, width, flags);
- format++;
- break;
-#endif // PRINTF_SUPPORT_FLOAT
- case 'c': {
- unsigned int l = 1U;
- // pre padding
- if (!(flags & FLAGS_LEFT)) {
- while (l++ < width) {
- out(' ', buffer, idx++, maxlen);
- }
- }
- // char output
- // out((char)va.next(cpu, mem), buffer, idx++, maxlen);
- out(static_cast(vaArgInteger(va_list)), buffer, idx++, maxlen);
- // post padding
- if (flags & FLAGS_LEFT) {
- while (l++ < width) {
- out(' ', buffer, idx++, maxlen);
- }
- }
- format++;
- break;
- }
-
- case 's': {
- const char* p = vaArgPtr(
- va_list); // const char *p = va.next>(cpu, mem).get(mem);
- p = p != nullptr ? p : "(null)";
- unsigned int l = _strlen(p);
- // pre padding
- if (flags & FLAGS_PRECISION) {
- l = (l < precision ? l : precision);
- }
- if (!(flags & FLAGS_LEFT)) {
- while (l++ < width) {
- out(' ', buffer, idx++, maxlen);
- }
- }
- // string output
- while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) {
- out(*(p++), buffer, idx++, maxlen);
- }
- // post padding
- if (flags & FLAGS_LEFT) {
- while (l++ < width) {
- out(' ', buffer, idx++, maxlen);
- }
- }
- format++;
- break;
- }
-
- case 'p': {
- width = sizeof(void*) * 2U;
- flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE;
-#if defined(PRINTF_SUPPORT_LONG_LONG)
- const bool is_ll = sizeof(uintptr_t) == sizeof(long long);
- if (is_ll) {
- // idx = _ntoa_long_long(out, buffer, idx, maxlen,
- // (uintptr_t)va.next>(cpu, mem).address(), false, 16U, precision, width,
- // flags);
- idx = _ntoa_long_long(out, buffer, idx, maxlen,
- reinterpret_cast(vaArgPtr(va_list)), false,
- 16U, precision, width, flags);
- } else {
-#endif
- // idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned
- // long)((uintptr_t)va.next>(cpu, mem).address()), false, 16U, precision,
- // width, flags);
- idx = _ntoa_long(
- out, buffer, idx, maxlen,
- static_cast(reinterpret_cast(vaArgPtr(va_list))),
- false, 16U, precision, width, flags);
-#if defined(PRINTF_SUPPORT_LONG_LONG)
- }
-#endif
- format++;
- break;
- }
-
- case '%':
- out('%', buffer, idx++, maxlen);
- format++;
- break;
-
- default:
- out(*format, buffer, idx++, maxlen);
- format++;
- break;
- }
- }
-
- // termination
- out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen);
-
- // return written chars without terminating \0
- return (int)idx;
-}
-
-static int printf_ctx(VaCtx* ctx) {
- const char* format = vaArgPtr(&ctx->va_list);
- char buffer[256];
- int result = _vsnprintf(_out_buffer, buffer, format, &ctx->va_list);
- printf("%s", buffer);
- return result;
-}
-
-static int fprintf_ctx(VaCtx* ctx, char* buf) {
- const char* format = vaArgPtr(&ctx->va_list);
- char buffer[256];
- int result = _vsnprintf(_out_buffer, buffer, format, &ctx->va_list);
- std::strcpy(buf, buffer);
- return result;
-}
-
-static int vsnprintf_ctx(char* s, size_t n, const char* format, VaList* arg) {
- char buffer[n];
- int result = _vsnprintf(_out_buffer, buffer, format, arg);
- std::strcpy(s, buffer);
- return result;
-}
-} // namespace Libraries::LibC
diff --git a/src/core/libraries/libc/va_ctx.h b/src/core/libraries/libc/va_ctx.h
deleted file mode 100644
index 1c0314959..000000000
--- a/src/core/libraries/libc/va_ctx.h
+++ /dev/null
@@ -1,110 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include
-#include "common/types.h"
-
-#define VA_ARGS \
- uint64_t rdi, uint64_t rsi, uint64_t rdx, uint64_t rcx, uint64_t r8, uint64_t r9, \
- uint64_t overflow_arg_area, __m128 xmm0, __m128 xmm1, __m128 xmm2, __m128 xmm3, \
- __m128 xmm4, __m128 xmm5, __m128 xmm6, __m128 xmm7, ...
-
-#define VA_CTX(ctx) \
- alignas(16) VaCtx ctx; \
- (ctx).reg_save_area.gp[0] = rdi; \
- (ctx).reg_save_area.gp[1] = rsi; \
- (ctx).reg_save_area.gp[2] = rdx; \
- (ctx).reg_save_area.gp[3] = rcx; \
- (ctx).reg_save_area.gp[4] = r8; \
- (ctx).reg_save_area.gp[5] = r9; \
- (ctx).reg_save_area.fp[0] = xmm0; \
- (ctx).reg_save_area.fp[1] = xmm1; \
- (ctx).reg_save_area.fp[2] = xmm2; \
- (ctx).reg_save_area.fp[3] = xmm3; \
- (ctx).reg_save_area.fp[4] = xmm4; \
- (ctx).reg_save_area.fp[5] = xmm5; \
- (ctx).reg_save_area.fp[6] = xmm6; \
- (ctx).reg_save_area.fp[7] = xmm7; \
- (ctx).va_list.reg_save_area = &(ctx).reg_save_area; \
- (ctx).va_list.gp_offset = offsetof(VaRegSave, gp); \
- (ctx).va_list.fp_offset = offsetof(VaRegSave, fp); \
- (ctx).va_list.overflow_arg_area = &overflow_arg_area;
-
-namespace Libraries::LibC {
-
-// https://stackoverflow.com/questions/4958384/what-is-the-format-of-the-x86-64-va-list-structure
-
-struct VaList {
- u32 gp_offset;
- u32 fp_offset;
- void* overflow_arg_area;
- void* reg_save_area;
-};
-
-struct VaRegSave {
- u64 gp[6];
- __m128 fp[8];
-};
-
-struct VaCtx {
- VaRegSave reg_save_area;
- VaList va_list;
-};
-
-template
-T vaArgRegSaveAreaGp(VaList* l) {
- auto* addr = reinterpret_cast