Compare commits

...

69 Commits

Author SHA1 Message Date
Marcin Mikołajczyk
824d332d0f
Setsockopt fixes (#3308)
* setsockopt: return correct error values for EPROCUNAVAIL

* setsockopt: handle SO_CONNECTTIMEO
2025-07-23 21:34:25 +03:00
TheTurtle
19c3d05ac1
shader_recompiler: Use VM bit for conditional discard (#3306) 2025-07-23 20:58:09 +03:00
Marcin Mikołajczyk
8dc50ffc79
Ssl stub (#3307)
* Correctly return zero root CA certs

* Stub sceHttpsGetCaList
2025-07-23 20:34:07 +03:00
Marcin Mikołajczyk
ea37ea11fc
Network config (#3292)
* Config entry isConnectedToNetwork

* Respect Config::isConnectedToNetwork when returning connection state

* Return connection status in NetCtlGetInfo

* Print connection data in log
2025-07-23 20:07:42 +03:00
TheTurtle
4d3578edbe
shader_recompiler: Fix incorrect bary coord loads when unsupported (#3303)
* shader_recompiler: Fix incorrect bary coord loads when unsupported

Also properly set sample rate shading

* emit_spirv: Implement BaryCoordSmoothCentroid
2025-07-23 19:46:06 +03:00
Stephen Miller
800b332f60
Core: Only update configs when using a different build. (#3299)
* Use a config version constant to check for config updates

Should address the largest issue with the prior update logic, where configs with removed/additional entries will no longer force config updates on every emulator boot.
This also makes it easier to add config entries, since you don't need to keep track of how many entries you add, or how many entries you removed.

* Use git revision hash instead of constant

In exchange for updating configs on every update, this removes the need for PR authors to manually change a constant when adding new settings.
2025-07-23 12:04:00 +03:00
DanielSvoboda
b4ec1bd371
qt: fix broken interface (#3301) 2025-07-23 11:01:55 +03:00
georgemoralis
0ad7fcb341
Microphone support (#3228)
* initial drafts

* initial implementation

* clang+reuse

* restore main

* improved AudioInInput

* fix microphone

* +

* +

* adds microphone selection to the interface

* added squidbus review fixes

* Update src/core/libraries/audio/audioin.cpp

Co-authored-by: squidbus <175574877+squidbus@users.noreply.github.com>

* Update src/core/libraries/audio/audioin.cpp

Co-authored-by: squidbus <175574877+squidbus@users.noreply.github.com>

* Increased entries in config.cpp

---------

Co-authored-by: DanielSvoboda <daniel.svoboda@hotmail.com>
Co-authored-by: squidbus <175574877+squidbus@users.noreply.github.com>
2025-07-23 06:54:18 +03:00
georgemoralis
16a6469b75
[ci skip] Qt GUI: Update Translation. (#3297)
Co-authored-by: georgemoralis <4313123+georgemoralis@users.noreply.github.com>
2025-07-23 06:53:34 +03:00
TheTurtle
7502739425
control_flow_graph: Treat empty conditional branch as noop (#3296) 2025-07-23 06:09:14 +03:00
DanielSvoboda
de11de43f2
qt: fix display full version string in Release channel (#3295) 2025-07-23 05:36:55 +03:00
georgemoralis
14ef56d148 clang fix 2025-07-23 00:11:09 +03:00
georgemoralis
9e2af5f619
New Crowdin updates (#3270)
* New translations en_us.ts (Greek)

* New translations en_us.ts (Vietnamese)

* New translations en_us.ts (Indonesian)

* New translations en_us.ts (Vietnamese)
2025-07-23 00:00:21 +03:00
Valdis Bogdāns
637e503685
Ime fixes (#3288)
* - typo fix
- added validations for sceImeKeyboardOpen/Close
- fixed mistakes in logs
- additional  log spam for debuging

* Disable user id validation

Disable user id validation until user manager is ready.

---------

Co-authored-by: w1naenator <valdis.bogdans@hotmail.com>
2025-07-22 11:27:02 +03:00
rainmakerv2
1fc9eedbab
Add default trophy sound (#3271)
* Add default trophy sound

* delete include to removed folder

* remove redundant conditions

* Change trophy sound - credit to Tlarok
2025-07-22 00:52:20 +03:00
kalaposfos13
bad9cd097a
Make remote link verification for disabling the autoupdater case-independent (#3287) 2025-07-22 00:52:01 +03:00
georgemoralis
a4c5fa4b5c
Using custom usb lib (#3284)
* added ext-libusb to overcome sysv_abi changes

* Fully remove libusb submodule
2025-07-21 12:24:11 +03:00
kalaposfos13
95a386308a
Implement sceKernelError (#3282)
* Implement sceKernelError

* Oh come on
2025-07-20 22:52:44 +03:00
Randomuser8219
0706223aaf
Small typo fix for avplayer assert (#3283)
Found that this assert message was typoed when running Knack 2 through a debugger.
2025-07-20 22:52:31 +03:00
Marcin Mikołajczyk
fd03fe2b5a
Register posix_rename (#3281) 2025-07-20 22:07:37 +03:00
kalaposfos13
f0cd981548
Implement sceAudioOutGetLastOutputTime (#3279)
* Implement sceAudioOutGetLastOutputTime

* Error returns

* Logging
2025-07-20 21:15:16 +03:00
Marcin Mikołajczyk
bd0102c8d0
Misc fixes (#3171) 2025-07-20 20:52:05 +03:00
TheTurtle
0b72a795eb
vk_rasterizer: Improve stencil clears (#3268) 2025-07-19 02:39:54 +03:00
TheTurtle
2ae7037c08
texture_cache: Clamp buffer image height to microtile height (#3261)
Co-authored-by: georgemoralis <giorgosmrls@gmail.com>
2025-07-18 13:14:41 +03:00
Valdis Bogdāns
af67473de3
Ime lib fixes (#3244)
* IME fixes

- Moved enums, flags, and structs to ime_common.h to simplify usage with Ime and ImeDialog
- Updated Ime to use an enum as the return type, consistent with ImeDialog
- Removed duplicate definition of OrbisImeKeycode
- Added OrbisImeLanguage as a flags enum
- Added missing options to OrbisImeOption
- Removed OrbisImeDialogOption; OrbisImeOption should be used instead
- Added OrbisImeTextAreaMode
- Updated OrbisImeTextAreaMode
- Fixed OrbisImeEventParam by adding the missing member OrbisImePanelType panel_type
- Updated the sceImeOpen declaration to use extended parameters (not yet implemented)
-Fixed Diablo III (CUSA00434) assertion failure on ImeDialog initialization

* Ime lib fixes
- Updated functions to consistently use the Error enum type for return values.
- Added detailed logging to aid future IME/OSK development and debugging.
- Now use OrbisUserServiceUserId (s32) and OrbisImeKeycodeState in relevant functions and structs.
- Introduced a generic template method to generate full bitmasks for all Orbis flag-style enums, simplifying validation and mask creation.
- Implemented additional parameter validations in sceImeOpen.
- Added missing enums: OrbisDisableDevice, OrbisImeInputMethodState, OrbisImeInitExtKeyboardMode, OrbisImeKeycodeState, and other USB keyboard-related enums.
- Fixed incorrect usage of format specifiers in calls to logging macros (LOG_*).

* Data Type Fixes

- Replaced the use of the type alias OrbisUserServiceUserId = s32 with Libraries::UserService::OrbisUserServiceUserId directly.

* Fixed IDE warnings
- generate_full_mask now returns const instead of constexpr.
- Added argument list to std::unique_lock<std::mutex> construction for clarity.

* Clang fixes

* Removed unneccessary comment

---------

Co-authored-by: w1naenator <valdis.bogdans@hotmail.com>
2025-07-18 12:40:05 +03:00
TheTurtle
b56039b15a
vk_pipeline_cache: Add fallbacks for R8Srgb and B5G6R5 (#3264)
* vk_pipeline_cache: Add fallbacks for R8Srgb and B5G6R5

* blit_helper: Fix validation error

* renderer_vulkan: Emulate B5G6R5 with swizzle
2025-07-18 12:25:07 +03:00
baggins183
3019bfb978
Implement MUBUF instructions for shorts/bytes (#2856)
* implement loads/store instructions for types smaller than dwords

* initialize s16/s8 types

* set profile for int8/16/64

* also need to zero extend u8/u16 to u32 result

* document unrelated bugs with atomic fmin/max

* remove profile checks and simple emit for added opcodes

---------

Co-authored-by: georgemoralis <giorgosmrls@gmail.com>
2025-07-18 12:04:50 +03:00
kalaposfos13
76f003d388
Disable autoupdate on branches that aren't the official main (#3262)
* Disable autoupdate on branches that aren't the official main

* Change to status messages because Fire Cube was complaining about this
2025-07-18 11:37:29 +03:00
UltraDaCat
fafd3fb564
Volume slider that adjusts how loud games are on a global level (#3240)
* Update config.cpp

* Update config.h

* Update sdl_audio.cpp

* Update settings_dialog.cpp

* Update settings_dialog.h

* Update settings_dialog.ui

* Update gui_settings.h

* Update audioout.cpp

* Update audioout.h

* Update settings_dialog.cpp

* remove leftover settings_dialog.ui

* Update settings_dialog.ui

---------

Co-authored-by: georgemoralis <giorgosmrls@gmail.com>
2025-07-18 11:20:05 +03:00
DanielSvoboda
e914099ae2
new compatibility repository (#3265) 2025-07-18 10:50:32 +03:00
georgemoralis
1689cdb1a2
Update Readme with new compatibility list link 2025-07-17 20:30:14 +03:00
kalaposfos13
fddded8d20
Add an unreachable on hitting ud2 instead of getting stuck in an infinite loop (#3257)
* Add an unreachable on hitting ud2 instead of getting stuck in an infinite loop

* Add [[unlikely]] to get ahead of the inevitable PR review comment
2025-07-16 18:06:58 +03:00
georgemoralis
161aa49f37
New Crowdin updates (#3219)
* New translations en_us.ts (Ukrainian)

* New translations en_us.ts (Ukrainian)

* New translations en_us.ts (Spanish)

* New translations en_us.ts (Albanian)

* New translations en_us.ts (Polish)

* New translations en_us.ts (Polish)

* New translations en_us.ts (Turkish)

* New translations en_us.ts (German)
2025-07-16 18:04:27 +03:00
kalaposfos13
68b147488e
If CONTENT_ID is empty in param.sfo, try using TITLE_ID as fallback (#3258)
* If CONTENT_ID is empty in param.sfo, try using TITLE_ID as fallback

* Remove assert that is now not needed and fix me switching up variable names
2025-07-16 18:03:39 +03:00
Stephen Miller
aeab525a7f
Fix create flag handling in open (#3255)
If the create flag is specified, but the file already exists, then the file should open successfully, regardless of permissions.
This fixes a crash seen in Phantasy Star Online 2 New Genesis (CUSA29813)
2025-07-16 12:30:20 +03:00
kalaposfos13
499451bb80
Standardize RegisterLib names for HLE libraries (#3234) 2025-07-16 12:23:03 +03:00
TheTurtle
cf8a6efd37
liverpool_to_vk: Don't use remapped format for clear value (#3254) 2025-07-16 01:54:56 +03:00
TheTurtle
6e350a5085
Avoid clearing HTILE when shader contains address calculation (#3252)
* resource_tracking: Mark image as written when its used with atomics

* texture_cache: Remove meta registered flag

Mostly useless and it is possible for images to switch metas

* vk_rasterizer: Use xor as heuristic for HTILE clear
2025-07-16 01:28:03 +03:00
DanielSvoboda
a82698d601
qt: fix gui emulatorLanguage (#3250) 2025-07-16 00:15:59 +03:00
TheTurtle
83475ac828
attribute: Correct bary coord function (#3253) 2025-07-15 22:55:57 +03:00
Marcin Mikołajczyk
6d6068e0e2
Fix ff1_i32_b64 not accepting vcc as its argument (#3251) 2025-07-15 11:39:37 -07:00
TheTurtle
4407ebdd9b
shader_recompiler: Implement guest barycentrics (#3245)
* shader_recompiler: Implement guest barycentrics

* Review comments and some cleanup
2025-07-15 18:49:12 +03:00
TheTurtle
87f6cce7b1
vk_instance: Remove usage of depth clamp control (#3248) 2025-07-15 18:36:13 +03:00
Stephen Miller
bf623d4f85
Libraries: Implement sceAudio3dTerminate (#3247)
* sceAudio3dTerminate

My First Gran Turismo® (CUSA49696) uses this while initializing it's audio system. Without it, the game spams errored sceAudio3dInitialize calls.

* Properly close AudioOut handle

Based on library decompilation.
2025-07-15 15:48:05 +03:00
Stephen Miller
97daee836a
Core: Fix read-only file unmaps on Windows (#3246)
* Fix read-only file unmaps

Fixes Genshin Impact (CUSA23681)

* Slight cleanup

Don't need `post_merge_it` anymore.
2025-07-15 14:11:56 +03:00
kalaposfos13
b68ca43166
Implement sceKernelGetSystemSwVersion (#3243)
* Implement sceKernelGetSystemSwVersion

* Set the reported firmware version to that of the game executable
2025-07-14 23:44:13 +03:00
TheTurtle
00f4eeddaf
renderer_vulkan: Handle more miscellaneous GPU settings (#3241)
* renderer_vulkan: Respect provoking vertex setting

* renderer_vulkan: Handle rasterization discard

* renderer_vulkan: Implement logic ops

* renderer_vulkan: Properly implement depth clamp and clip

* renderer_vulkan: Handle line width

* Fix build

* vk_pipeline_cache: Don't check depth clamp without a depth buffer

* liverpool: Fix line control offset

* vk_pipeline_cache: Don't run search if depth clamp is disabled

* vk_pipeline_cache: Allow using viewport range when it's more restrictive then depth clamp

* liverpool: Disable depth clip when near and far planes have different setting

* vk_graphics_pipeline: Move warning to pipeline

* vk_pipeline_cache: Revert viewport check and remove log

* vk_graphics_pipeline: Enable depth clamp when depth clip is disabled and extension is not supported

Without the depth clip extension depth clipping is controlled by depth clamping
2025-07-14 21:23:18 +03:00
TheTurtle
399a725343
shader_recompiler: Replace buffer pulling with attribute divisor for instance step rates (#3238)
* shader_recompiler: Replace buffer pulling with attribute divisor for instance step rates

* flatten_extended_userdata: Remove special step rate buffer handling

* Review comments

* spirv_emit_context: Name all instance rate attribs properly

* spirv: Merge ReadConstBuffer again

template function only has 1 user now

* attribute: Add missing attributes

* translate: Reimplement step rate instance id

* Resolve validation warnings

* shader_recompiler: Separate vertex inputs from LS stage, cleanup tess
2025-07-14 00:32:02 +03:00
TheTurtle
b403e1be33
vk_rasterizer: Set render area to max when no framebuffers are bound (#3227) 2025-07-10 22:14:02 +03:00
TheTurtle
8bc30270c8
shader_recompiler: Implement ff1 with subgroup ops (#3225) 2025-07-10 21:52:56 +03:00
TheTurtle
88abb93669
ir_passes: Fold readlane with ff1 pattern (#3224) 2025-07-10 14:19:44 +03:00
kalaposfos13
ee97c5c110
Define S_TRAP as InstCategory::FlowControl (#3223) 2025-07-10 13:53:38 +03:00
TheTurtle
27cbd6647f
shader_recompiler: Reorganize data share operations and implement GDS bit (#3222)
* shader_recompiler: Reorganize data share operations and implement GDS bit

* Review comments
2025-07-10 13:38:50 +03:00
IndecisiveTurtle
dc6ef99dc7 vector_memory: Handle immediate but non zero offset too
Signed-off-by: georgemoralis <giorgosmrls@gmail.com>
2025-07-09 18:40:05 +03:00
TheTurtle
7d4b875ee3
Random fixes (#3216)
* buffer_cache: Handle inline data to flexible memory

* control_flow: Fix single instruction scopes edge case

Fixes the following pattern

v_cmpx_gt_u32 cond
buffer_store_dword value
.LABEL:

Before
buffer[index] = value;

After
if (cond)
{
    buffer[index] = value;
}

* vector_memory: Handle soffset when offen is false

When offen is not used we can substitute the offset argument with soffset and have it handled correctly

* scalar_alu: Handle sharp moves with S_MOV_B64

This fixes unable to track sharp errors when this pattern is used in a shader

* emulator: Add log

* video_core: Bump binary info search range and buffer num
2025-07-09 17:00:06 +03:00
Paris Oplopoios
f5336358ea
Zero top bits in INSERTQ/EXTRQ (#3217)
* Zero top bits in INSERTQ/EXTRQ

* Clang-format

* Don't assert
2025-07-09 13:55:21 +03:00
Fire Cube
df4314f831
Extend Qt detection to support multiple drives (#3209) 2025-07-08 18:39:51 -07:00
kalaposfos13
e5f899aae3
Fix brace elision for designated initializer warning (#3215) 2025-07-08 18:38:28 -07:00
TheTurtle
2d1a2982df
buffer_cache: Bring back upload batching and temporary buffer (#3211)
* buffer_cache: Bring back upload batching and temporary buffer

Because that PR fused the write and read protections under a single function call, it was a requirement to move the actual memory copy part inside the lambda to perform it before the read protection kicks in. However on certain large data transfers it had potential for data corruption. If, for example, an upload had two copies, a 400MB and a 300MB one, the first one would fit in the staging buffer, very likely with an induced stall. However the second one wouldn't have space to fit alongside the other data, but it's also small enough for the buffer to fit it, so the staging buffer would cause a flush and wait to copy it, overwriting the previous transfer.

To address this the upload function has been reworked to allow for batching like previously but with the new locking behavior. Also the condition to use temporary buffers has been expanded to also include cases when staging buffer will stall, which should increase performance a little in some cases.

* buffer_cache: Move buffer barriers and copy outside of lock range
2025-07-08 10:32:39 +03:00
Valdis Bogdāns
ddede4a52d
IME fixes (#3207)
- Moved enums, flags, and structs to ime_common.h to simplify usage with Ime and ImeDialog
- Updated Ime to use an enum as the return type, consistent with ImeDialog
- Removed duplicate definition of OrbisImeKeycode
- Added OrbisImeLanguage as a flags enum
- Added missing options to OrbisImeOption
- Removed OrbisImeDialogOption; OrbisImeOption should be used instead
- Added OrbisImeTextAreaMode
- Updated OrbisImeTextAreaMode
- Fixed OrbisImeEventParam by adding the missing member OrbisImePanelType panel_type
- Updated the sceImeOpen declaration to use extended parameters (not yet implemented)
-Fixed Diablo III (CUSA00434) assertion failure on ImeDialog initialization

Co-authored-by: w1naenator <valdis.bogdans@hotmail.com>
2025-07-08 01:04:16 +03:00
Fire Cube
80f7ec2681
video_out: Internal Resolution Support (#3194)
* impl

* clang

* clang+

* update total_entries too
2025-07-07 19:17:56 +03:00
TheTurtle
7fedbd52e0
texture_cache: Async download of GPU modified linear images (#3204)
* texture_cache: Async download of GPU modified linear images

* liverpool: Back to less submits

* texture_cache: Don't download depth images

* config: Add option for linear image readback
2025-07-07 16:23:20 +03:00
georgemoralis
d6163a6edb uber fix 2025-07-07 13:37:08 +03:00
Paris Oplopoios
4eaa992aff
Rename 'AddCary' to 'AddCarry' (#3206) 2025-07-07 13:29:11 +03:00
squidbus
70eef0de90
texture_cache: Change depth resolve new image back to max of resources. (#3205) 2025-07-07 13:03:19 +03:00
Paris Oplopoios
146e81a56a
Fix V_ADDC_U32 carry-out edge cases (#3200)
* Fix V_ADDC_U32 carry-out edge cases

* Use IAddCarry instead
2025-07-07 12:44:06 +03:00
Marcin Mikołajczyk
5eef2fd28a
mmap executable memory (#3201) 2025-07-07 12:26:27 +03:00
Stephen Miller
d1f5a7e8fb
libkernel mprotect export (#3199) 2025-07-06 22:03:59 +02:00
kalaposfos13
78cb5334cf started 0.10.1 WIP 2025-07-06 20:54:56 +02:00
242 changed files with 4011 additions and 2124 deletions

View File

@ -17,7 +17,7 @@ body:
This repository does not provide support for game patches. If you are having issues with patches please refer to [Cheats and Patches Repository](https://github.com/shadps4-emu/ps4_cheats).
Before submitting an issue please check [Game Compatibility Repository](https://github.com/shadps4-emu/shadps4-game-compatibility) for the information about the status of the game.
Before submitting an issue please check [Game Compatibility Repository](https://github.com/shadps4-compatibility/shadps4-game-compatibility) for the information about the status of the game.
Please make an effort to make sure your issue isn't already reported.

6
.gitmodules vendored
View File

@ -103,6 +103,6 @@
path = externals/MoltenVK/cereal
url = https://github.com/USCiLab/cereal
shallow = true
[submodule "externals/libusb"]
path = externals/libusb
url = https://github.com/libusb/libusb-cmake.git
[submodule "externals/ext-libusb"]
path = externals/ext-libusb
url = https://github.com/shadps4-emu/ext-libusb.git

View File

@ -126,7 +126,7 @@ execute_process(
# If there's no upstream set or the command failed, check remote.pushDefault
if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
message("check default push")
message(STATUS "check default push")
execute_process(
COMMAND git config --get remote.pushDefault
OUTPUT_VARIABLE GIT_REMOTE_NAME
@ -134,30 +134,30 @@ if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
message("got remote: ${GIT_REMOTE_NAME}")
message(STATUS "got remote: ${GIT_REMOTE_NAME}")
endif()
# If running in GitHub Actions and the above fails
if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
message("check github")
message(STATUS "check github")
set(GIT_REMOTE_NAME "origin")
# Retrieve environment variables
if (DEFINED ENV{GITHUB_HEAD_REF} AND NOT "$ENV{GITHUB_HEAD_REF}" STREQUAL "")
message("github head ref: $ENV{GITHUB_HEAD_REF}")
message(STATUS "github head ref: $ENV{GITHUB_HEAD_REF}")
set(GITHUB_HEAD_REF "$ENV{GITHUB_HEAD_REF}")
else()
set(GITHUB_HEAD_REF "")
endif()
if (DEFINED ENV{GITHUB_REF} AND NOT "$ENV{GITHUB_REF}" STREQUAL "")
message("github ref: $ENV{GITHUB_REF}")
message(STATUS "github ref: $ENV{GITHUB_REF}")
string(REGEX REPLACE "^refs/[^/]*/" "" GITHUB_BRANCH "$ENV{GITHUB_REF}")
string(REGEX MATCH "refs/pull/([0-9]+)/merge" MATCHED_REF "$ENV{GITHUB_REF}")
if (MATCHED_REF)
set(PR_NUMBER "${CMAKE_MATCH_1}")
set(GITHUB_BRANCH "")
message("PR number: ${PR_NUMBER}")
message(STATUS "PR number: ${PR_NUMBER}")
else()
set(PR_NUMBER "")
endif()
@ -179,7 +179,7 @@ if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
elseif ("${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_REF}" STREQUAL "")
set(GIT_BRANCH "${GITHUB_REF}")
elseif("${GIT_BRANCH}" STREQUAL "")
message("couldn't find branch")
message(STATUS "couldn't find branch")
set(GIT_BRANCH "detached-head")
endif()
else()
@ -188,13 +188,13 @@ else()
if (INDEX GREATER -1)
string(SUBSTRING "${GIT_REMOTE_NAME}" 0 "${INDEX}" GIT_REMOTE_NAME)
elseif("${GIT_REMOTE_NAME}" STREQUAL "")
message("reset to origin")
message(STATUS "reset to origin")
set(GIT_REMOTE_NAME "origin")
endif()
endif()
# Get remote link
message("getting remote link")
message(STATUS "getting remote link")
execute_process(
COMMAND git config --get remote.${GIT_REMOTE_NAME}.url
OUTPUT_VARIABLE GIT_REMOTE_URL
@ -204,15 +204,21 @@ execute_process(
# Set Version
set(EMULATOR_VERSION_MAJOR "0")
set(EMULATOR_VERSION_MINOR "10")
set(EMULATOR_VERSION_PATCH "0")
set(EMULATOR_VERSION_PATCH "1")
set_source_files_properties(src/shadps4.rc PROPERTIES COMPILE_DEFINITIONS "EMULATOR_VERSION_MAJOR=${EMULATOR_VERSION_MAJOR};EMULATOR_VERSION_MINOR=${EMULATOR_VERSION_MINOR};EMULATOR_VERSION_PATCH=${EMULATOR_VERSION_PATCH}")
set(APP_VERSION "${EMULATOR_VERSION_MAJOR}.${EMULATOR_VERSION_MINOR}.${EMULATOR_VERSION_PATCH}")
set(APP_IS_RELEASE true)
set(APP_VERSION "${EMULATOR_VERSION_MAJOR}.${EMULATOR_VERSION_MINOR}.${EMULATOR_VERSION_PATCH} WIP")
set(APP_IS_RELEASE false)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/src/common/scm_rev.cpp" @ONLY)
message("end git things, remote: ${GIT_REMOTE_NAME}, branch: ${GIT_BRANCH}")
message("-- end git things, remote: ${GIT_REMOTE_NAME}, branch: ${GIT_BRANCH}, link: ${GIT_REMOTE_URL}")
string(TOLOWER "${GIT_REMOTE_URL}" GIT_REMOTE_URL_LOWER)
if(NOT GIT_REMOTE_URL_LOWER MATCHES "shadps4-emu/shadps4" OR NOT GIT_BRANCH STREQUAL "main")
message(STATUS "not main, disabling auto update")
set(ENABLE_UPDATER OFF)
endif()
if(WIN32 AND ENABLE_QT_GUI AND NOT CMAKE_PREFIX_PATH)
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/DetectQtInstallation.cmake")
@ -238,7 +244,6 @@ find_package(xxHash 0.8.2 MODULE)
find_package(ZLIB 1.3 MODULE)
find_package(Zydis 5.0.0 CONFIG)
find_package(pugixml 1.14 CONFIG)
find_package(libusb 1.0.27 MODULE)
if (APPLE)
find_package(date 3.0.1 CONFIG)
endif()
@ -255,7 +260,6 @@ endif()
add_subdirectory(externals)
include_directories(src)
include_directories(Resources)
if(ENABLE_QT_GUI)
find_package(Qt6 REQUIRED COMPONENTS Widgets Concurrent LinguistTools Network Multimedia)
@ -300,6 +304,8 @@ set(AJM_LIB src/core/libraries/ajm/ajm.cpp
set(AUDIO_LIB src/core/libraries/audio/audioin.cpp
src/core/libraries/audio/audioin.h
src/core/libraries/audio/sdl_in.h
src/core/libraries/audio/sdl_in.cpp
src/core/libraries/voice/voice.cpp
src/core/libraries/voice/voice.h
src/core/libraries/audio/audioout.cpp
@ -1237,6 +1243,7 @@ include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/CMakeRC.cmake")
cmrc_add_resource_library(embedded-resources
ALIAS res::embedded
NAMESPACE res
src/images/trophy.wav
src/images/bronze.png
src/images/gold.png
src/images/platinum.png

View File

@ -37,7 +37,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
**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/wiki/I.-Quick-start-%5BUsers%5D).\
To verify that a game works, you can look at [**shadPS4 Game Compatibility**](https://github.com/shadps4-emu/shadps4-game-compatibility).\
To verify that a game works, you can look at [**shadPS4 Game Compatibility**](https://github.com/shadps4-compatibility/shadps4-game-compatibility).\
To discuss shadPS4 development, suggest ideas or to ask for help, join our [**Discord server**](https://discord.gg/bFJxfftGW6).\
To get the latest news, go to our [**X (Twitter)**](https://x.com/shadps4) or our [**website**](https://shadps4.net/).\
For those who'd like to donate to the project, we now have a [**Kofi page**](https://ko-fi.com/shadps4)!

View File

@ -73,6 +73,7 @@ path = [
"src/images/shadps4.svg",
"src/images/website.svg",
"src/images/youtube.svg",
"src/images/trophy.wav",
"src/shadps4.qrc",
"src/shadps4.rc",
"src/qt_gui/translations/update_translation.sh",

View File

@ -1,14 +1,28 @@
# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
file(GLOB QT_KITS LIST_DIRECTORIES true "C:/Qt/*/msvc*_64")
list(SORT QT_KITS COMPARE NATURAL)
list(REVERSE QT_KITS)
if(QT_KITS)
list(GET QT_KITS 0 QT_PREFIX)
set(CMAKE_PREFIX_PATH "${QT_PREFIX}" CACHE PATH "Qt prefix autodetected" FORCE)
message(STATUS "Auto-detected Qt prefix: ${QT_PREFIX}")
else()
message(STATUS "findQt.cmake: no QtDirectory found in C:/Qt please set CMAKE_PREFIX_PATH manually")
endif()
set(highest_version "0")
set(CANDIDATE_DRIVES A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)
foreach(drive ${CANDIDATE_DRIVES})
file(GLOB kits LIST_DIRECTORIES true CONFIGURE_DEPENDS "${drive}:/Qt/*/msvc*_64")
foreach(kit IN LISTS kits)
get_filename_component(version_dir "${kit}" DIRECTORY)
get_filename_component(kit_version "${version_dir}" NAME)
message(STATUS "DetectQtInstallation.cmake: Detected Qt: ${kit}")
if (kit_version VERSION_GREATER highest_version)
set(highest_version "${kit_version}")
set(QT_PREFIX "${kit}")
endif()
endforeach()
endforeach()
if(QT_PREFIX)
set(CMAKE_PREFIX_PATH "${QT_PREFIX}" CACHE PATH "Qt prefix autodetected" FORCE)
message(STATUS "DetectQtInstallation.cmake: Choose newest Qt: ${QT_PREFIX}")
else()
message(STATUS "DetectQtInstallation.cmake: No QtDirectory found in <drive>:/Qt please set CMAKE_PREFIX_PATH manually")
endif()

View File

@ -147,7 +147,7 @@ Accurately identifying games will help other developers that own that game recog
- 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,
- It is recommended that you check the [game compatibility issue tracker](https://github.com/shadps4-compatibility/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.**\

View File

@ -197,7 +197,7 @@ endif()
# libusb
if (NOT TARGET libusb::usb)
add_subdirectory(libusb)
add_subdirectory(ext-libusb)
add_library(libusb::usb ALIAS usb-1.0)
endif()

1
externals/ext-libusb vendored Submodule

@ -0,0 +1 @@
Subproject commit e1f4ac1472bdf6aab27f8b836a2f47df85465bac

1
externals/libusb vendored

@ -1 +0,0 @@
Subproject commit a63a7e43e0950a595cf4b98a0eaf4051749ace5f

2
externals/sirit vendored

@ -1 +1 @@
Subproject commit 6b450704f6fedb9413d0c89a9eb59d028eb1e6c0
Subproject commit 282083a595dcca86814dedab2f2b0363ef38f1ec

View File

@ -32,6 +32,7 @@ std::filesystem::path find_fs_path_or(const basic_value<TC>& v, const K& ky,
namespace Config {
// General
static int volumeSlider = 100;
static bool isNeo = false;
static bool isDevKit = false;
static bool isPSNSignedIn = false;
@ -46,6 +47,7 @@ static bool isShowSplash = false;
static std::string isSideTrophy = "right";
static bool compatibilityData = false;
static bool checkCompatibilityOnStartup = false;
static bool isConnectedToNetwork = false;
// Input
static int cursorState = HideCursorState::Idle;
@ -54,17 +56,21 @@ static bool useSpecialPad = false;
static int specialPadClass = 1;
static bool isMotionControlsEnabled = true;
static bool useUnifiedInputConfig = true;
static std::string micDevice = "Default Device";
// These two entries aren't stored in the config
static bool overrideControllerColor = false;
static int controllerCustomColorRGB[3] = {0, 0, 255};
// GPU
static u32 screenWidth = 1280;
static u32 screenHeight = 720;
static u32 windowWidth = 1280;
static u32 windowHeight = 720;
static u32 internalScreenWidth = 1280;
static u32 internalScreenHeight = 720;
static bool isNullGpu = false;
static bool shouldCopyGPUBuffers = false;
static bool readbacksEnabled = false;
static bool readbackLinearImagesEnabled = false;
static bool directMemoryAccessEnabled = false;
static bool shouldDumpShaders = false;
static bool shouldPatchShaders = false;
@ -102,9 +108,12 @@ u32 m_language = 1; // english
// Keys
static std::string trophyKey = "";
// Expected number of items in the config file
static constexpr u64 total_entries = 51;
// Config version, used to determine if a user's config file is outdated.
static std::string config_version = Common::g_scm_rev;
int getVolumeSlider() {
return volumeSlider;
}
bool allowHDR() {
return isHDRAllowed;
}
@ -154,6 +163,10 @@ std::filesystem::path GetSaveDataPath() {
return save_data_path;
}
void setVolumeSlider(int volumeValue) {
volumeSlider = volumeValue;
}
void setLoadGameSizeEnabled(bool enable) {
load_game_size = enable;
}
@ -190,16 +203,28 @@ int getCursorHideTimeout() {
return cursorHideTimeout;
}
std::string getMicDevice() {
return micDevice;
}
double getTrophyNotificationDuration() {
return trophyNotificationDuration;
}
u32 getScreenWidth() {
return screenWidth;
u32 getWindowWidth() {
return windowWidth;
}
u32 getScreenHeight() {
return screenHeight;
u32 getWindowHeight() {
return windowHeight;
}
u32 getInternalScreenWidth() {
return internalScreenHeight;
}
u32 getInternalScreenHeight() {
return internalScreenHeight;
}
s32 getGpuId() {
@ -262,6 +287,10 @@ bool readbacks() {
return readbacksEnabled;
}
bool readbackLinearImages() {
return readbackLinearImagesEnabled;
}
bool directMemoryAccess() {
return directMemoryAccessEnabled;
}
@ -330,16 +359,28 @@ bool getCheckCompatibilityOnStartup() {
return checkCompatibilityOnStartup;
}
bool getIsConnectedToNetwork() {
return isConnectedToNetwork;
}
void setGpuId(s32 selectedGpuId) {
gpuId = selectedGpuId;
}
void setScreenWidth(u32 width) {
screenWidth = width;
void setWindowWidth(u32 width) {
windowWidth = width;
}
void setScreenHeight(u32 height) {
screenHeight = height;
void setWindowHeight(u32 height) {
windowHeight = height;
}
void setInternalScreenWidth(u32 width) {
internalScreenWidth = width;
}
void setInternalScreenHeight(u32 height) {
internalScreenHeight = height;
}
void setDebugDump(bool enable) {
@ -421,6 +462,11 @@ void setCursorState(s16 newCursorState) {
void setCursorHideTimeout(int newcursorHideTimeout) {
cursorHideTimeout = newcursorHideTimeout;
}
void setMicDevice(std::string device) {
micDevice = device;
}
void setTrophyNotificationDuration(double newTrophyNotificationDuration) {
trophyNotificationDuration = newTrophyNotificationDuration;
}
@ -582,11 +628,10 @@ void load(const std::filesystem::path& path) {
return;
}
u64 entry_count = 0;
if (data.contains("General")) {
const toml::value& general = data.at("General");
volumeSlider = toml::find_or<int>(general, "volumeSlider", volumeSlider);
isNeo = toml::find_or<bool>(general, "isPS4Pro", isNeo);
isDevKit = toml::find_or<bool>(general, "isDevKit", isDevKit);
isPSNSignedIn = toml::find_or<bool>(general, "isPSNSignedIn", isPSNSignedIn);
@ -603,9 +648,10 @@ void load(const std::filesystem::path& path) {
compatibilityData = toml::find_or<bool>(general, "compatibilityEnabled", compatibilityData);
checkCompatibilityOnStartup = toml::find_or<bool>(general, "checkCompatibilityOnStartup",
checkCompatibilityOnStartup);
chooseHomeTab = toml::find_or<std::string>(general, "chooseHomeTab", chooseHomeTab);
entry_count += general.size();
isConnectedToNetwork =
toml::find_or<bool>(general, "isConnectedToNetwork", isConnectedToNetwork);
chooseHomeTab = toml::find_or<std::string>(general, "chooseHomeTab", chooseHomeTab);
}
if (data.contains("Input")) {
@ -619,18 +665,22 @@ void load(const std::filesystem::path& path) {
toml::find_or<bool>(input, "isMotionControlsEnabled", isMotionControlsEnabled);
useUnifiedInputConfig =
toml::find_or<bool>(input, "useUnifiedInputConfig", useUnifiedInputConfig);
entry_count += input.size();
micDevice = toml::find_or<std::string>(input, "micDevice", micDevice);
}
if (data.contains("GPU")) {
const toml::value& gpu = data.at("GPU");
screenWidth = toml::find_or<int>(gpu, "screenWidth", screenWidth);
screenHeight = toml::find_or<int>(gpu, "screenHeight", screenHeight);
windowWidth = toml::find_or<int>(gpu, "screenWidth", windowWidth);
windowHeight = toml::find_or<int>(gpu, "screenHeight", windowHeight);
internalScreenWidth = toml::find_or<int>(gpu, "internalScreenWidth", internalScreenWidth);
internalScreenHeight =
toml::find_or<int>(gpu, "internalScreenHeight", internalScreenHeight);
isNullGpu = toml::find_or<bool>(gpu, "nullGpu", isNullGpu);
shouldCopyGPUBuffers = toml::find_or<bool>(gpu, "copyGPUBuffers", shouldCopyGPUBuffers);
readbacksEnabled = toml::find_or<bool>(gpu, "readbacks", readbacksEnabled);
readbackLinearImagesEnabled =
toml::find_or<bool>(gpu, "readbackLinearImages", readbackLinearImagesEnabled);
directMemoryAccessEnabled =
toml::find_or<bool>(gpu, "directMemoryAccess", directMemoryAccessEnabled);
shouldDumpShaders = toml::find_or<bool>(gpu, "dumpShaders", shouldDumpShaders);
@ -639,8 +689,6 @@ void load(const std::filesystem::path& path) {
isFullscreen = toml::find_or<bool>(gpu, "Fullscreen", isFullscreen);
fullscreenMode = toml::find_or<std::string>(gpu, "FullscreenMode", fullscreenMode);
isHDRAllowed = toml::find_or<bool>(gpu, "allowHDR", isHDRAllowed);
entry_count += gpu.size();
}
if (data.contains("Vulkan")) {
@ -654,10 +702,9 @@ void load(const std::filesystem::path& path) {
vkHostMarkers = toml::find_or<bool>(vk, "hostMarkers", vkHostMarkers);
vkGuestMarkers = toml::find_or<bool>(vk, "guestMarkers", vkGuestMarkers);
rdocEnable = toml::find_or<bool>(vk, "rdocEnable", rdocEnable);
entry_count += vk.size();
}
std::string current_version = {};
if (data.contains("Debug")) {
const toml::value& debug = data.at("Debug");
@ -666,8 +713,7 @@ void load(const std::filesystem::path& path) {
toml::find_or<bool>(debug, "isSeparateLogFilesEnabled", isSeparateLogFilesEnabled);
isShaderDebug = toml::find_or<bool>(debug, "CollectShader", isShaderDebug);
isFpsColor = toml::find_or<bool>(debug, "FPSColor", isFpsColor);
entry_count += debug.size();
current_version = toml::find_or<std::string>(debug, "ConfigVersion", current_version);
}
if (data.contains("GUI")) {
@ -699,26 +745,20 @@ void load(const std::filesystem::path& path) {
settings_addon_install_dir =
toml::find_fs_path_or(gui, "addonInstallDir", settings_addon_install_dir);
entry_count += gui.size();
}
if (data.contains("Settings")) {
const toml::value& settings = data.at("Settings");
m_language = toml::find_or<int>(settings, "consoleLanguage", m_language);
entry_count += settings.size();
}
if (data.contains("Keys")) {
const toml::value& keys = data.at("Keys");
trophyKey = toml::find_or<std::string>(keys, "TrophyKey", trophyKey);
entry_count += keys.size();
}
// Run save after loading to generate any missing fields with default values.
if (entry_count != total_entries) {
if (config_version != current_version) {
fmt::print("Outdated config detected, updating config file.\n");
save(path);
}
@ -777,6 +817,7 @@ void save(const std::filesystem::path& path) {
fmt::print("Saving new configuration file {}\n", fmt::UTF(path.u8string()));
}
data["General"]["volumeSlider"] = volumeSlider;
data["General"]["isPS4Pro"] = isNeo;
data["General"]["isDevKit"] = isDevKit;
data["General"]["isPSNSignedIn"] = isPSNSignedIn;
@ -791,17 +832,22 @@ void save(const std::filesystem::path& path) {
data["General"]["sideTrophy"] = isSideTrophy;
data["General"]["compatibilityEnabled"] = compatibilityData;
data["General"]["checkCompatibilityOnStartup"] = checkCompatibilityOnStartup;
data["General"]["isConnectedToNetwork"] = isConnectedToNetwork;
data["Input"]["cursorState"] = cursorState;
data["Input"]["cursorHideTimeout"] = cursorHideTimeout;
data["Input"]["useSpecialPad"] = useSpecialPad;
data["Input"]["specialPadClass"] = specialPadClass;
data["Input"]["isMotionControlsEnabled"] = isMotionControlsEnabled;
data["Input"]["useUnifiedInputConfig"] = useUnifiedInputConfig;
data["GPU"]["screenWidth"] = screenWidth;
data["GPU"]["screenHeight"] = screenHeight;
data["Input"]["micDevice"] = micDevice;
data["GPU"]["screenWidth"] = windowWidth;
data["GPU"]["screenHeight"] = windowHeight;
data["GPU"]["internalScreenWidth"] = internalScreenWidth;
data["GPU"]["internalScreenHeight"] = internalScreenHeight;
data["GPU"]["nullGpu"] = isNullGpu;
data["GPU"]["copyGPUBuffers"] = shouldCopyGPUBuffers;
data["GPU"]["readbacks"] = readbacksEnabled;
data["GPU"]["readbackLinearImages"] = readbackLinearImagesEnabled;
data["GPU"]["directMemoryAccess"] = directMemoryAccessEnabled;
data["GPU"]["dumpShaders"] = shouldDumpShaders;
data["GPU"]["patchShaders"] = shouldPatchShaders;
@ -821,6 +867,7 @@ void save(const std::filesystem::path& path) {
data["Debug"]["CollectShader"] = isShaderDebug;
data["Debug"]["isSeparateLogFilesEnabled"] = isSeparateLogFilesEnabled;
data["Debug"]["FPSColor"] = isFpsColor;
data["Debug"]["ConfigVersion"] = config_version;
data["Keys"]["TrophyKey"] = trophyKey;
std::vector<std::string> install_dirs;
@ -869,6 +916,7 @@ void save(const std::filesystem::path& path) {
void setDefaultValues() {
// General
volumeSlider = 100;
isNeo = false;
isDevKit = false;
isPSNSignedIn = false;
@ -883,6 +931,7 @@ void setDefaultValues() {
isSideTrophy = "right";
compatibilityData = false;
checkCompatibilityOnStartup = false;
isConnectedToNetwork = false;
// Input
cursorState = HideCursorState::Idle;
@ -895,13 +944,17 @@ void setDefaultValues() {
controllerCustomColorRGB[0] = 0;
controllerCustomColorRGB[1] = 0;
controllerCustomColorRGB[2] = 255;
micDevice = "Default Device";
// GPU
screenWidth = 1280;
screenHeight = 720;
windowWidth = 1280;
windowHeight = 720;
internalScreenWidth = 1280;
internalScreenHeight = 720;
isNullGpu = false;
shouldCopyGPUBuffers = false;
readbacksEnabled = false;
readbackLinearImagesEnabled = false;
directMemoryAccessEnabled = false;
shouldDumpShaders = false;
shouldPatchShaders = false;

View File

@ -19,16 +19,22 @@ enum HideCursorState : int { Never, Idle, Always };
void load(const std::filesystem::path& path);
void save(const std::filesystem::path& path);
int getVolumeSlider();
void setVolumeSlider(int volumeValue);
std::string getTrophyKey();
void setTrophyKey(std::string key);
bool getIsFullscreen();
void setIsFullscreen(bool enable);
std::string getFullscreenMode();
void setFullscreenMode(std::string mode);
u32 getScreenWidth();
u32 getScreenHeight();
void setScreenWidth(u32 width);
void setScreenHeight(u32 height);
u32 getWindowWidth();
u32 getWindowHeight();
void setWindowWidth(u32 width);
void setWindowHeight(u32 height);
u32 getInternalScreenWidth();
u32 getInternalScreenHeight();
void setInternalScreenWidth(u32 width);
void setInternalScreenHeight(u32 height);
bool debugDump();
void setDebugDump(bool enable);
s32 getGpuId();
@ -47,6 +53,7 @@ bool copyGPUCmdBuffers();
void setCopyGPUCmdBuffers(bool enable);
bool readbacks();
void setReadbacks(bool enable);
bool readbackLinearImages();
bool directMemoryAccess();
void setDirectMemoryAccess(bool enable);
bool dumpShaders();
@ -78,7 +85,9 @@ void setLogFilter(const std::string& type);
double getTrophyNotificationDuration();
void setTrophyNotificationDuration(double newTrophyNotificationDuration);
int getCursorHideTimeout();
std::string getMicDevice();
void setCursorHideTimeout(int newcursorHideTimeout);
void setMicDevice(std::string device);
void setSeparateLogFilesEnabled(bool enabled);
bool getSeparateLogFilesEnabled();
u32 GetLanguage();
@ -104,6 +113,7 @@ std::filesystem::path GetSaveDataPath();
void setLoadGameSizeEnabled(bool enable);
bool getCompatibilityEnabled();
bool getCheckCompatibilityOnStartup();
bool getIsConnectedToNetwork();
std::string getUserName();
std::string getChooseHomeTab();
bool GetUseUnifiedInputConfig();

View File

@ -358,9 +358,17 @@ enum PosixPageProtection {
[[nodiscard]] constexpr PosixPageProtection ToPosixProt(Core::MemoryProt prot) {
if (True(prot & Core::MemoryProt::CpuReadWrite) ||
True(prot & Core::MemoryProt::GpuReadWrite)) {
if (True(prot & Core::MemoryProt::CpuExec)) {
return PAGE_EXECUTE_READWRITE;
} else {
return PAGE_READWRITE;
}
} else if (True(prot & Core::MemoryProt::CpuRead) || True(prot & Core::MemoryProt::GpuRead)) {
if (True(prot & Core::MemoryProt::CpuExec)) {
return PAGE_EXECUTE_READ;
} else {
return PAGE_READONLY;
}
} else {
return PAGE_NOACCESS;
}

View File

@ -163,7 +163,9 @@ static void GenerateEXTRQ(void* /* address */, const ZydisDecodedOperand* operan
mask = (1ULL << length) - 1;
}
ASSERT_MSG(length + index <= 64, "length + index must be less than or equal to 64.");
if (length + index > 64) {
mask = 0xFFFF'FFFF'FFFF'FFFF;
}
// Get lower qword from xmm register
c.vmovq(scratch1, xmm_dst);
@ -177,8 +179,8 @@ static void GenerateEXTRQ(void* /* address */, const ZydisDecodedOperand* operan
c.mov(scratch2, mask);
c.and_(scratch1, scratch2);
// Writeback to xmm register, extrq instruction says top 64-bits are undefined so we don't
// care to preserve them
// Writeback to xmm register, extrq instruction says top 64-bits are undefined but zeroed on
// AMD CPUs
c.vmovq(xmm_dst, scratch1);
c.pop(scratch2);
@ -287,7 +289,9 @@ static void GenerateINSERTQ(void* /* address */, const ZydisDecodedOperand* oper
mask_value = (1ULL << length) - 1;
}
ASSERT_MSG(length + index <= 64, "length + index must be less than or equal to 64.");
if (length + index > 64) {
mask_value = 0xFFFF'FFFF'FFFF'FFFF;
}
c.vmovq(scratch1, xmm_src);
c.vmovq(scratch2, xmm_dst);
@ -307,8 +311,9 @@ static void GenerateINSERTQ(void* /* address */, const ZydisDecodedOperand* oper
// dst |= src
c.or_(scratch2, scratch1);
// Insert scratch2 into low 64 bits of dst, upper 64 bits are unaffected
c.vpinsrq(xmm_dst, xmm_dst, scratch2, 0);
// Insert scratch2 into low 64 bits of dst, upper 64 bits are undefined but zeroed on AMD
// CPUs
c.vmovq(xmm_dst, scratch2);
c.pop(mask);
c.pop(scratch2);
@ -374,7 +379,7 @@ static void GenerateINSERTQ(void* /* address */, const ZydisDecodedOperand* oper
c.and_(scratch2, mask);
c.or_(scratch2, scratch1);
// Upper 64 bits are undefined in insertq
// Upper 64 bits are undefined in insertq but AMD CPUs zero them
c.vmovq(xmm_dst, scratch2);
c.pop(mask);
@ -635,6 +640,7 @@ static bool TryExecuteIllegalInstruction(void* ctx, void* code_address) {
lowQWordDst >>= index;
lowQWordDst &= mask;
memset((u8*)dst + sizeof(u64), 0, sizeof(u64));
memcpy(dst, &lowQWordDst, sizeof(lowQWordDst));
Common::IncrementRip(ctx, 4);
@ -675,6 +681,7 @@ static bool TryExecuteIllegalInstruction(void* ctx, void* code_address) {
lowQWordDst &= ~(mask << index);
lowQWordDst |= lowQWordSrc << index;
memset((u8*)dst + sizeof(u64), 0, sizeof(u64));
memcpy(dst, &lowQWordDst, sizeof(lowQWordDst));
Common::IncrementRip(ctx, 4);
@ -746,6 +753,10 @@ static bool PatchesIllegalInstructionHandler(void* context) {
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
const auto status =
Common::Decoder::Instance()->decodeInstruction(instruction, operands, code_address);
if (ZYAN_SUCCESS(status) && instruction.mnemonic == ZydisMnemonic::ZYDIS_MNEMONIC_UD2)
[[unlikely]] {
UNREACHABLE_MSG("ud2 at code address {:#x}", (u64)code_address);
}
LOG_ERROR(Core, "Failed to patch address {:x} -- mnemonic: {}", (u64)code_address,
ZYAN_SUCCESS(status) ? ZydisMnemonicGetString(instruction.mnemonic)
: "Failed to decode");

View File

@ -219,7 +219,7 @@ int PS4_SYSV_ABI sceAjmStrError() {
return ORBIS_OK;
}
void RegisterlibSceAjm(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("NVDXiUesSbA", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmBatchCancel);
LIB_FUNCTION("WfAiBW8Wcek", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmBatchErrorDump);
LIB_FUNCTION("dmDybN--Fn8", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmBatchJobControlBufferRa);

View File

@ -229,5 +229,5 @@ int PS4_SYSV_ABI sceAjmModuleRegister(u32 context, AjmCodecType codec_type, s64
int PS4_SYSV_ABI sceAjmModuleUnregister();
int PS4_SYSV_ABI sceAjmStrError();
void RegisterlibSceAjm(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Ajm

View File

@ -369,7 +369,7 @@ int PS4_SYSV_ABI sceAppContentGetDownloadedStoreCountry() {
return ORBIS_OK;
}
void RegisterlibSceAppContent(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("AS45QoYHjc4", "libSceAppContent", 1, "libSceAppContentUtil", 1, 1, _Z5dummyv);
LIB_FUNCTION("ZiATpP9gEkA", "libSceAppContent", 1, "libSceAppContentUtil", 1, 1,
sceAppContentAddcontDelete);

View File

@ -119,5 +119,5 @@ int PS4_SYSV_ABI sceAppContentGetAddcontInfoByEntitlementId();
int PS4_SYSV_ABI sceAppContentGetAddcontInfoListByIroTag();
int PS4_SYSV_ABI sceAppContentGetDownloadedStoreCountry();
void RegisterlibSceAppContent(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::AppContent

View File

@ -3,18 +3,21 @@
#include "common/logging/log.h"
#include "core/libraries/audio/audioin.h"
#include "core/libraries/audio/sdl_in.h"
#include "core/libraries/error_codes.h"
#include "core/libraries/libs.h"
namespace Libraries::AudioIn {
static std::unique_ptr<SDLAudioIn> audio = std::make_unique<SDLAudioIn>();
int PS4_SYSV_ABI sceAudioInChangeAppModuleState() {
LOG_ERROR(Lib_AudioIn, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceAudioInClose() {
LOG_ERROR(Lib_AudioIn, "(STUBBED) called");
int PS4_SYSV_ABI sceAudioInClose(s32 handle) {
audio->AudioInClose(handle);
return ORBIS_OK;
}
@ -93,9 +96,13 @@ int PS4_SYSV_ABI sceAudioInGetSilentState() {
return ORBIS_OK;
}
int PS4_SYSV_ABI sceAudioInHqOpen() {
LOG_ERROR(Lib_AudioIn, "(STUBBED) called");
return ORBIS_OK;
int PS4_SYSV_ABI sceAudioInHqOpen(Libraries::UserService::OrbisUserServiceUserId userId, u32 type,
u32 index, u32 len, u32 freq, u32 param) {
int result = audio->AudioInOpen(type, len, freq, param);
if (result < 0) {
LOG_ERROR(Lib_AudioIn, "Error returned {:#x}", result);
}
return result;
}
int PS4_SYSV_ABI sceAudioInHqOpenEx() {
@ -108,9 +115,8 @@ int PS4_SYSV_ABI sceAudioInInit() {
return ORBIS_OK;
}
int PS4_SYSV_ABI sceAudioInInput() {
LOG_ERROR(Lib_AudioIn, "(STUBBED) called");
return ORBIS_OK;
int PS4_SYSV_ABI sceAudioInInput(s32 handle, void* dest) {
return audio->AudioInInput(handle, dest);
}
int PS4_SYSV_ABI sceAudioInInputs() {
@ -123,9 +129,13 @@ int PS4_SYSV_ABI sceAudioInIsSharedDevice() {
return ORBIS_OK;
}
int PS4_SYSV_ABI sceAudioInOpen() {
LOG_ERROR(Lib_AudioIn, "(DUMMY) called");
return 0x80260005; // ports are full return
int PS4_SYSV_ABI sceAudioInOpen(Libraries::UserService::OrbisUserServiceUserId userId, u32 type,
u32 index, u32 len, u32 freq, u32 param) {
int result = audio->AudioInOpen(type, len, freq, param);
if (result < 0) {
LOG_ERROR(Lib_AudioIn, "Error returned {:#x}", result);
}
return result;
}
int PS4_SYSV_ABI sceAudioInOpenEx() {
@ -218,7 +228,7 @@ int PS4_SYSV_ABI sceAudioInVmicWrite() {
return ORBIS_OK;
}
void RegisterlibSceAudioIn(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("IQtWgnrw6v8", "libSceAudioIn", 1, "libSceAudioIn", 1, 1,
sceAudioInChangeAppModuleState);
LIB_FUNCTION("Jh6WbHhnI68", "libSceAudioIn", 1, "libSceAudioIn", 1, 1, sceAudioInClose);

View File

@ -3,6 +3,7 @@
#pragma once
#include <core/libraries/system/userservice.h>
#include "common/types.h"
namespace Core::Loader {
@ -11,8 +12,12 @@ class SymbolsResolver;
namespace Libraries::AudioIn {
enum class OrbisAudioInParamFormat : u32 { S16Mono = 0, S16Stereo = 2 };
enum class OrbisAudioInType : u32 { VoiceChat = 0, General = 1, VoiceRecognition = 5 };
int PS4_SYSV_ABI sceAudioInChangeAppModuleState();
int PS4_SYSV_ABI sceAudioInClose();
int PS4_SYSV_ABI sceAudioInClose(s32 handle);
int PS4_SYSV_ABI sceAudioInCountPorts();
int PS4_SYSV_ABI sceAudioInDeviceHqOpen();
int PS4_SYSV_ABI sceAudioInDeviceIdHqOpen();
@ -28,13 +33,15 @@ int PS4_SYSV_ABI sceAudioInGetGain();
int PS4_SYSV_ABI sceAudioInGetHandleStatusInfo();
int PS4_SYSV_ABI sceAudioInGetRerouteCount();
int PS4_SYSV_ABI sceAudioInGetSilentState();
int PS4_SYSV_ABI sceAudioInHqOpen();
int PS4_SYSV_ABI sceAudioInHqOpen(Libraries::UserService::OrbisUserServiceUserId userId, u32 type,
u32 index, u32 len, u32 freq, u32 param);
int PS4_SYSV_ABI sceAudioInHqOpenEx();
int PS4_SYSV_ABI sceAudioInInit();
int PS4_SYSV_ABI sceAudioInInput();
int PS4_SYSV_ABI sceAudioInInput(s32 handle, void* dest);
int PS4_SYSV_ABI sceAudioInInputs();
int PS4_SYSV_ABI sceAudioInIsSharedDevice();
int PS4_SYSV_ABI sceAudioInOpen();
int PS4_SYSV_ABI sceAudioInOpen(Libraries::UserService::OrbisUserServiceUserId userId, u32 type,
u32 index, u32 len, u32 freq, u32 param);
int PS4_SYSV_ABI sceAudioInOpenEx();
int PS4_SYSV_ABI sceAudioInSetAllMute();
int PS4_SYSV_ABI sceAudioInSetCompressorPreGain();
@ -54,5 +61,5 @@ int PS4_SYSV_ABI sceAudioInVmicCreate();
int PS4_SYSV_ABI sceAudioInVmicDestroy();
int PS4_SYSV_ABI sceAudioInVmicWrite();
void RegisterlibSceAudioIn(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::AudioIn

View File

@ -14,6 +14,7 @@
#include "core/libraries/audio/audioout.h"
#include "core/libraries/audio/audioout_backend.h"
#include "core/libraries/audio/audioout_error.h"
#include "core/libraries/kernel/time.h"
#include "core/libraries/libs.h"
namespace Libraries::AudioOut {
@ -168,8 +169,19 @@ int PS4_SYSV_ABI sceAudioOutGetInfoOpenNum() {
return ORBIS_OK;
}
int PS4_SYSV_ABI sceAudioOutGetLastOutputTime() {
LOG_ERROR(Lib_AudioOut, "(STUBBED) called");
int PS4_SYSV_ABI sceAudioOutGetLastOutputTime(s32 handle, u64* output_time) {
LOG_DEBUG(Lib_AudioOut, "called, handle: {}, output time: {}", handle, fmt::ptr(output_time));
if (!output_time) {
return ORBIS_AUDIO_OUT_ERROR_INVALID_POINTER;
}
if (handle >= ports_out.size()) {
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
}
auto& port = ports_out.at(handle - 1);
if (!port.IsOpen()) {
return ORBIS_AUDIO_OUT_ERROR_NOT_OPENED;
}
*output_time = port.last_output_time;
return ORBIS_OK;
}
@ -396,6 +408,7 @@ s32 PS4_SYSV_ABI sceAudioOutOutput(s32 handle, void* ptr) {
if (ptr != nullptr && port.IsOpen()) {
std::memcpy(port.output_buffer, ptr, port.BufferSize());
port.output_ready = true;
port.last_output_time = Kernel::sceKernelGetProcessTime();
}
}
port.output_cv.notify_one();
@ -523,9 +536,24 @@ s32 PS4_SYSV_ABI sceAudioOutSetVolume(s32 handle, s32 flag, s32* vol) {
}
port.impl->SetVolume(port.volume);
}
AdjustVol();
return ORBIS_OK;
}
void AdjustVol() {
if (audio == nullptr) {
return;
}
for (int i = 0; i < ports_out.size(); i++) {
std::unique_lock lock{ports_out[i].mutex};
if (!ports_out[i].IsOpen()) {
continue;
}
ports_out[i].impl->SetVolume(ports_out[i].volume);
}
}
int PS4_SYSV_ABI sceAudioOutSetVolumeDown() {
LOG_ERROR(Lib_AudioOut, "(STUBBED) called");
return ORBIS_OK;
@ -596,7 +624,7 @@ int PS4_SYSV_ABI sceAudioOutSetSystemDebugState() {
return ORBIS_OK;
}
void RegisterlibSceAudioOut(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("cx2dYFbzIAg", "libSceAudioOutDeviceService", 1, "libSceAudioOut", 1, 1,
sceAudioOutDeviceIdOpen);
LIB_FUNCTION("tKumjQSzhys", "libSceAudioDeviceControl", 1, "libSceAudioOut", 1, 1,

View File

@ -96,6 +96,7 @@ struct PortOut {
AudioFormatInfo format_info;
u32 sample_rate;
u32 buffer_frames;
u64 last_output_time;
std::array<s32, 8> volume;
[[nodiscard]] bool IsOpen() const {
@ -127,7 +128,7 @@ int PS4_SYSV_ABI sceAudioOutGetFocusEnablePid();
int PS4_SYSV_ABI sceAudioOutGetHandleStatusInfo();
int PS4_SYSV_ABI sceAudioOutGetInfo();
int PS4_SYSV_ABI sceAudioOutGetInfoOpenNum();
int PS4_SYSV_ABI sceAudioOutGetLastOutputTime();
int PS4_SYSV_ABI sceAudioOutGetLastOutputTime(s32 handle, u64* output_time);
int PS4_SYSV_ABI sceAudioOutGetPortState(s32 handle, OrbisAudioOutPortState* state);
int PS4_SYSV_ABI sceAudioOutGetSimulatedBusUsableStatusByBusType();
int PS4_SYSV_ABI sceAudioOutGetSimulatedHandleStatusInfo();
@ -181,5 +182,6 @@ int PS4_SYSV_ABI sceAudioOutSystemControlSet();
int PS4_SYSV_ABI sceAudioOutSparkControlSetEqCoef();
int PS4_SYSV_ABI sceAudioOutSetSystemDebugState();
void RegisterlibSceAudioOut(Core::Loader::SymbolsResolver* sym);
void AdjustVol();
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::AudioOut

View File

@ -4,6 +4,7 @@
#include <thread>
#include <SDL3/SDL_audio.h>
#include <SDL3/SDL_hints.h>
#include <common/config.h>
#include "common/logging/log.h"
#include "core/libraries/audio/audioout.h"
@ -41,6 +42,7 @@ public:
stream = nullptr;
return;
}
SDL_SetAudioStreamGain(stream, Config::getVolumeSlider() / 100.0f);
}
~SDLPortBackend() override {
@ -77,7 +79,8 @@ public:
}
// SDL does not have per-channel volumes, for now just take the maximum of the channels.
const auto vol = *std::ranges::max_element(ch_volumes);
if (!SDL_SetAudioStreamGain(stream, static_cast<float>(vol) / SCE_AUDIO_OUT_VOLUME_0DB)) {
if (!SDL_SetAudioStreamGain(stream, static_cast<float>(vol) / SCE_AUDIO_OUT_VOLUME_0DB *
Config::getVolumeSlider() / 100.0f)) {
LOG_WARNING(Lib_AudioOut, "Failed to change SDL audio stream volume: {}",
SDL_GetError());
}

View File

@ -0,0 +1,135 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <cstring>
#include <common/config.h>
#include <common/logging/log.h>
#include "sdl_in.h"
int SDLAudioIn::AudioInit() {
return SDL_InitSubSystem(SDL_INIT_AUDIO);
}
int SDLAudioIn::AudioInOpen(int type, uint32_t samples_num, uint32_t freq, uint32_t format) {
std::scoped_lock lock{m_mutex};
for (int id = 0; id < static_cast<int>(portsIn.size()); ++id) {
auto& port = portsIn[id];
if (!port.isOpen) {
port.isOpen = true;
port.type = type;
port.samples_num = samples_num;
port.freq = freq;
port.format = format;
SDL_AudioFormat sampleFormat;
switch (format) {
case Libraries::AudioIn::ORBIS_AUDIO_IN_PARAM_FORMAT_S16_MONO:
sampleFormat = SDL_AUDIO_S16;
port.channels_num = 1;
port.sample_size = 2;
break;
case Libraries::AudioIn::ORBIS_AUDIO_IN_PARAM_FORMAT_S16_STEREO:
sampleFormat = SDL_AUDIO_S16;
port.channels_num = 2;
port.sample_size = 2;
break;
default:
port.isOpen = false;
return ORBIS_AUDIO_IN_ERROR_INVALID_PORT;
}
SDL_AudioSpec fmt;
SDL_zero(fmt);
fmt.format = sampleFormat;
fmt.channels = port.channels_num;
fmt.freq = port.freq;
std::string micDevStr = Config::getMicDevice();
uint32_t devId;
if (micDevStr == "None") {
return ORBIS_AUDIO_IN_ERROR_INVALID_PORT;
} else if (micDevStr == "Default Device") {
devId = SDL_AUDIO_DEVICE_DEFAULT_RECORDING;
} else {
try {
devId = static_cast<uint32_t>(std::stoul(micDevStr));
} catch (const std::exception& e) {
return ORBIS_AUDIO_IN_ERROR_INVALID_PORT;
}
}
port.stream = SDL_OpenAudioDeviceStream(devId, &fmt, nullptr, nullptr);
if (!port.stream) {
port.isOpen = false;
return ORBIS_AUDIO_IN_ERROR_INVALID_PORT;
}
if (SDL_ResumeAudioStreamDevice(port.stream) == false) {
SDL_DestroyAudioStream(port.stream);
port = {};
return ORBIS_AUDIO_IN_ERROR_STREAM_FAIL;
}
return id + 1;
}
}
return ORBIS_AUDIO_IN_ERROR_INVALID_PORT;
}
int SDLAudioIn::AudioInInput(int handle, void* out_buffer) {
std::scoped_lock lock{m_mutex};
if (handle < 1 || handle > static_cast<int>(portsIn.size()) || !out_buffer)
return ORBIS_AUDIO_IN_ERROR_INVALID_PORT;
auto& port = portsIn[handle - 1];
if (!port.isOpen)
return ORBIS_AUDIO_IN_ERROR_INVALID_PORT;
const int bytesToRead = port.samples_num * port.sample_size * port.channels_num;
if (out_buffer == nullptr) {
int attempts = 0;
while (SDL_GetAudioStreamAvailable(port.stream) > 0) {
SDL_Delay(1);
if (++attempts > 1000) {
return ORBIS_AUDIO_IN_ERROR_TIMEOUT;
}
}
return 0; // done
}
int attempts = 0;
while (SDL_GetAudioStreamAvailable(port.stream) < bytesToRead) {
SDL_Delay(1);
if (++attempts > 1000) {
return ORBIS_AUDIO_IN_ERROR_TIMEOUT;
}
}
const int bytesRead = SDL_GetAudioStreamData(port.stream, out_buffer, bytesToRead);
if (bytesRead < 0) {
// SDL_GetAudioStreamData failed
LOG_ERROR(Lib_AudioIn, "AudioInInput error: {}", SDL_GetError());
return ORBIS_AUDIO_IN_ERROR_STREAM_FAIL;
}
const int framesRead = bytesRead / (port.sample_size * port.channels_num);
return framesRead;
}
void SDLAudioIn::AudioInClose(int handle) {
std::scoped_lock lock{m_mutex};
if (handle < 1 || handle > (int)portsIn.size())
return;
auto& port = portsIn[handle - 1];
if (!port.isOpen)
return;
SDL_DestroyAudioStream(port.stream);
port = {};
}

View File

@ -0,0 +1,42 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <array>
#include <mutex>
#include <SDL3/SDL.h>
namespace Libraries::AudioIn {
enum OrbisAudioInParam {
ORBIS_AUDIO_IN_PARAM_FORMAT_S16_MONO = 0,
ORBIS_AUDIO_IN_PARAM_FORMAT_S16_STEREO = 2
};
}
#define ORBIS_AUDIO_IN_ERROR_INVALID_PORT -1
#define ORBIS_AUDIO_IN_ERROR_TIMEOUT -2
#define ORBIS_AUDIO_IN_ERROR_STREAM_FAIL -3
class SDLAudioIn {
public:
int AudioInit();
int AudioInOpen(int type, uint32_t samples_num, uint32_t freq, uint32_t format);
int AudioInInput(int handle, void* out_buffer);
void AudioInClose(int handle);
private:
struct AudioInPort {
bool isOpen = false;
int type = 0;
uint32_t samples_num = 0;
uint32_t freq = 0;
int channels_num = 0;
int sample_size = 0;
uint32_t format = 0;
SDL_AudioStream* stream = nullptr;
};
std::array<AudioInPort, 8> portsIn;
std::mutex m_mutex;
};

View File

@ -526,11 +526,18 @@ s32 PS4_SYSV_ABI sceAudio3dStrError() {
}
s32 PS4_SYSV_ABI sceAudio3dTerminate() {
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
LOG_INFO(Lib_Audio3d, "called");
if (!state) {
return ORBIS_AUDIO3D_ERROR_NOT_READY;
}
AudioOut::sceAudioOutOutput(state->audio_out_handle, nullptr);
AudioOut::sceAudioOutClose(state->audio_out_handle);
state.release();
return ORBIS_OK;
}
void RegisterlibSceAudio3d(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("pZlOm1aF3aA", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dAudioOutClose);
LIB_FUNCTION("ucEsi62soTo", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dAudioOutOpen);
LIB_FUNCTION("7NYEzJ9SJbM", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,

View File

@ -141,5 +141,5 @@ s32 PS4_SYSV_ABI sceAudio3dSetGpuRenderer();
s32 PS4_SYSV_ABI sceAudio3dStrError();
s32 PS4_SYSV_ABI sceAudio3dTerminate();
void RegisterlibSceAudio3d(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Audio3d

View File

@ -278,7 +278,7 @@ s32 PS4_SYSV_ABI sceAvPlayerVprintf(const char* format, va_list args) {
return ORBIS_OK;
}
void RegisterlibSceAvPlayer(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("KMcEa+rHsIo", "libSceAvPlayer", 1, "libSceAvPlayer", 1, 0, sceAvPlayerAddSource);
LIB_FUNCTION("x8uvuFOPZhU", "libSceAvPlayer", 1, "libSceAvPlayer", 1, 0,
sceAvPlayerAddSourceEx);

View File

@ -290,6 +290,6 @@ enum class SceAvPlayerAvSyncMode {
using SceAvPlayerLogCallback = int PS4_SYSV_ABI (*)(void* p, const char* format, va_list args);
void RegisterlibSceAvPlayer(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::AvPlayer

View File

@ -40,7 +40,7 @@ public:
FrameBuffer(const SceAvPlayerMemAllocator& memory_replacement, u32 align, u32 size) noexcept
: m_memory_replacement(memory_replacement),
m_data(Allocate(memory_replacement, align, size)) {
ASSERT_MSG(m_data, "Could not allocated frame buffer.");
ASSERT_MSG(m_data, "Could not allocate frame buffer.");
}
~FrameBuffer() {

View File

@ -410,7 +410,7 @@ s32 PS4_SYSV_ABI sceCameraStopByHandle() {
return ORBIS_OK;
}
void RegisterlibSceCamera(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("QhjrPkRPUZQ", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraAccGetData);
LIB_FUNCTION("UFonL7xopFM", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraAudioClose);
LIB_FUNCTION("fkZE7Hup2ro", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraAudioGetData);

View File

@ -304,5 +304,5 @@ s32 PS4_SYSV_ABI sceCameraStartByHandle();
s32 PS4_SYSV_ABI sceCameraStop(s32 handle);
s32 PS4_SYSV_ABI sceCameraStopByHandle();
void RegisterlibSceCamera(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Camera

View File

@ -102,7 +102,7 @@ s32 PS4_SYSV_ABI sceCompanionHttpdUnregisterRequestCallback() {
return ORBIS_OK;
}
void RegisterlibSceCompanionHttpd(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("8pWltDG7h6A", "libSceCompanionHttpd", 1, "libSceCompanionHttpd", 1, 1,
sceCompanionHttpdAddHeader);
LIB_FUNCTION("B-QBMeFdNgY", "libSceCompanionHttpd", 1, "libSceCompanionHttpd", 1, 1,

View File

@ -87,5 +87,5 @@ s32 PS4_SYSV_ABI sceCompanionHttpdTerminate();
s32 PS4_SYSV_ABI sceCompanionHttpdUnregisterRequestBodyReceptionCallback();
s32 PS4_SYSV_ABI sceCompanionHttpdUnregisterRequestCallback();
void RegisterlibSceCompanionHttpd(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::CompanionHttpd

View File

@ -56,7 +56,7 @@ s32 PS4_SYSV_ABI sceCompanionUtilTerminate() {
return ORBIS_OK;
}
void RegisterlibSceCompanionUtil(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("cE5Msy11WhU", "libSceCompanionUtil", 1, "libSceCompanionUtil", 1, 1,
sceCompanionUtilGetEvent);
LIB_FUNCTION("MaVrz79mT5o", "libSceCompanionUtil", 1, "libSceCompanionUtil", 1, 1,

View File

@ -29,5 +29,5 @@ s32 PS4_SYSV_ABI sceCompanionUtilInitialize();
s32 PS4_SYSV_ABI sceCompanionUtilOptParamInitialize();
s32 PS4_SYSV_ABI sceCompanionUtilTerminate();
void RegisterlibSceCompanionUtil(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::CompanionUtil

View File

@ -34,7 +34,7 @@ int PS4_SYSV_ABI Func_E7EBCE96E92F91F8() {
return ORBIS_DISC_MAP_ERROR_NO_BITMAP_INFO;
}
void RegisterlibSceDiscMap(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("fl1eoDnwQ4s", "libSceDiscMap", 1, "libSceDiscMap", 1, 1,
sceDiscMapGetPackageSize);
LIB_FUNCTION("lbQKqsERhtE", "libSceDiscMap", 1, "libSceDiscMap", 1, 1,

View File

@ -18,5 +18,5 @@ int PS4_SYSV_ABI Func_8A828CAEE7EDD5E9(char* path, s64 offset, s64 nbytes, int*
int* ret2);
int PS4_SYSV_ABI Func_E7EBCE96E92F91F8();
void RegisterlibSceDiscMap(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::DiscMap

View File

@ -545,7 +545,7 @@ s32 PS4_SYSV_ABI sceFiberSwitch(OrbisFiber* fiber, u64 arg_on_run_to, u64* arg_o
return sceFiberSwitchImpl(fiber, nullptr, 0, arg_on_run_to, arg_on_run);
}
void RegisterlibSceFiber(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("hVYD7Ou2pCQ", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberInitialize);
LIB_FUNCTION("7+OJIpko9RY", "libSceFiber", 1, "libSceFiber", 1, 1,
sceFiberInitializeImpl); // _sceFiberInitializeWithInternalOptionImpl

View File

@ -116,5 +116,5 @@ s32 PS4_SYSV_ABI sceFiberRename(OrbisFiber* fiber, const char* name);
s32 PS4_SYSV_ABI sceFiberGetThreadFramePointerAddress(u64* addr_frame_pointer);
void RegisterlibSceFiber(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Fiber

View File

@ -246,7 +246,7 @@ int PS4_SYSV_ABI sceGameLiveStreamingUnregisterCallback() {
return ORBIS_OK;
}
void RegisterlibSceGameLiveStreaming(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("caqgDl+V9qA", "libSceGameLiveStreaming_debug", 1, "libSceGameLiveStreaming", 1, 1,
sceGameLiveStreamingStartDebugBroadcast);
LIB_FUNCTION("0i8Lrllxwow", "libSceGameLiveStreaming_debug", 1, "libSceGameLiveStreaming", 1, 1,

View File

@ -77,5 +77,5 @@ int PS4_SYSV_ABI sceGameLiveStreamingStopSocialFeedbackMessageFiltering();
int PS4_SYSV_ABI sceGameLiveStreamingTerminate();
int PS4_SYSV_ABI sceGameLiveStreamingUnregisterCallback();
void RegisterlibSceGameLiveStreaming(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::GameLiveStreaming

View File

@ -2823,7 +2823,7 @@ int PS4_SYSV_ABI Func_F916890425496553() {
return ORBIS_OK;
}
void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LOG_INFO(Lib_GnmDriver, "Initializing presenter");
liverpool = std::make_unique<AmdGpu::Liverpool>();
presenter = std::make_unique<Vulkan::Presenter>(*g_window, liverpool.get());

View File

@ -297,5 +297,5 @@ int PS4_SYSV_ABI Func_BFB41C057478F0BF();
int PS4_SYSV_ABI Func_E51D44DB8151238C();
int PS4_SYSV_ABI Func_F916890425496553();
void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::GnmDriver

View File

@ -939,7 +939,7 @@ s32 PS4_SYSV_ABI Func_FF2E0E53015FE231() {
return ORBIS_OK;
}
void RegisterlibSceHmd(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("8gH1aLgty5I", "libsceHmdReprojectionMultilayer", 1, "libSceHmd", 1, 1,
sceHmdReprojectionStartMultilayer);
LIB_FUNCTION("gEokC+OGI8g", "libSceHmdDistortion", 1, "libSceHmd", 1, 1,

View File

@ -199,5 +199,5 @@ s32 PS4_SYSV_ABI Func_B9A6FA0735EC7E49();
s32 PS4_SYSV_ABI Func_FC193BD653F2AF2E();
s32 PS4_SYSV_ABI Func_FF2E0E53015FE231();
void RegisterlibSceHmd(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Hmd

View File

@ -190,7 +190,7 @@ Status PS4_SYSV_ABI sceErrorDialogUpdateStatus() {
return g_status;
}
void RegisterlibSceErrorDialog(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("ekXHb1kDBl0", "libSceErrorDialog", 1, "libSceErrorDialog", 1, 1,
sceErrorDialogClose);
LIB_FUNCTION("t2FvHRXzgqk", "libSceErrorDialog", 1, "libSceErrorDialog", 1, 1,

View File

@ -24,5 +24,5 @@ int PS4_SYSV_ABI sceErrorDialogOpenWithReport();
CommonDialog::Error PS4_SYSV_ABI sceErrorDialogTerminate();
CommonDialog::Status PS4_SYSV_ABI sceErrorDialogUpdateStatus();
void RegisterlibSceErrorDialog(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::ErrorDialog

View File

@ -18,9 +18,11 @@ static ImeUi g_ime_ui;
class ImeHandler {
public:
ImeHandler(const OrbisImeKeyboardParam* param) {
LOG_INFO(Lib_Ime, "Creating ImeHandler for keyboard");
Init(param, false);
}
ImeHandler(const OrbisImeParam* param) {
LOG_INFO(Lib_Ime, "Creating ImeHandler for IME");
Init(param, true);
}
~ImeHandler() = default;
@ -38,13 +40,18 @@ public:
openEvent.id = (ime_mode ? OrbisImeEventId::Open : OrbisImeEventId::KeyboardOpen);
if (ime_mode) {
sceImeGetPanelSize(&m_param.ime, &openEvent.param.rect.width,
LOG_INFO(Lib_Ime, "calling sceImeGetPanelSize");
Error e = sceImeGetPanelSize(&m_param.ime, &openEvent.param.rect.width,
&openEvent.param.rect.height);
if (e != Error::OK) {
LOG_ERROR(Lib_Ime, "sceImeGetPanelSize returned 0x{:X}", static_cast<u32>(e));
}
openEvent.param.rect.x = m_param.ime.posx;
openEvent.param.rect.y = m_param.ime.posy;
} else {
openEvent.param.resource_id_array.userId = 1;
openEvent.param.resource_id_array.resourceId[0] = 1;
openEvent.param.resource_id_array.user_id = 1;
openEvent.param.resource_id_array.resource_id[0] = 1;
}
// Are we supposed to call the event handler on init with
@ -59,13 +66,13 @@ public:
}
}
s32 Update(OrbisImeEventHandler handler) {
Error Update(OrbisImeEventHandler handler) {
if (!m_ime_mode) {
/* We don't handle any events for ImeKeyboard */
return ORBIS_OK;
return Error::OK;
}
std::unique_lock lock{g_ime_state.queue_mutex};
std::unique_lock<std::mutex> lock{g_ime_state.queue_mutex};
while (!g_ime_state.event_queue.empty()) {
OrbisImeEvent event = g_ime_state.event_queue.front();
@ -73,7 +80,7 @@ public:
Execute(handler, &event, false);
}
return ORBIS_OK;
return Error::OK;
}
void Execute(OrbisImeEventHandler handler, OrbisImeEvent* event, bool use_param_handler) {
@ -94,14 +101,14 @@ public:
}
}
s32 SetText(const char16_t* text, u32 length) {
Error SetText(const char16_t* text, u32 length) {
g_ime_state.SetText(text, length);
return ORBIS_OK;
return Error::OK;
}
s32 SetCaret(const OrbisImeCaret* caret) {
Error SetCaret(const OrbisImeCaret* caret) {
g_ime_state.SetCaret(caret->index);
return ORBIS_OK;
return Error::OK;
}
bool IsIme() {
@ -144,17 +151,22 @@ int PS4_SYSV_ABI sceImeCheckUpdateTextInfo() {
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceImeClose() {
LOG_INFO(Lib_Ime, "(STUBBED) called");
Error PS4_SYSV_ABI sceImeClose() {
LOG_INFO(Lib_Ime, "called");
if (!g_ime_handler) {
return ORBIS_IME_ERROR_NOT_OPENED;
return Error::NOT_OPENED;
}
g_ime_handler.release();
if (g_keyboard_handler) {
return Error::INTERNAL;
}
g_ime_ui = ImeUi();
g_ime_state = ImeState();
return ORBIS_OK;
LOG_INFO(Lib_Ime, "IME closed successfully");
return Error::OK;
}
int PS4_SYSV_ABI sceImeConfigGet() {
@ -222,40 +234,87 @@ int PS4_SYSV_ABI sceImeGetPanelPositionAndForm() {
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceImeGetPanelSize(const OrbisImeParam* param, u32* width, u32* height) {
LOG_INFO(Lib_Ime, "called");
Error PS4_SYSV_ABI sceImeGetPanelSize(const OrbisImeParam* param, u32* width, u32* height) {
LOG_INFO(Lib_Ime, "sceImeGetPanelSize called");
if (!width || !height) {
return ORBIS_IME_ERROR_INVALID_ADDRESS;
if (!param) {
LOG_ERROR(Lib_Ime, "Invalid param: NULL");
return Error::INVALID_ADDRESS;
}
if (!width) {
LOG_ERROR(Lib_Ime, "Invalid *width: NULL");
return Error::INVALID_ADDRESS;
}
if (!height) {
LOG_ERROR(Lib_Ime, "Invalid *height: NULL");
return Error::INVALID_ADDRESS;
}
if (static_cast<u32>(param->option) & ~0x7BFF) { // Basic check for invalid options
LOG_ERROR(Lib_Ime, "Invalid option 0x{:X}", static_cast<u32>(param->option));
return Error::INVALID_OPTION;
}
switch (param->type) {
case OrbisImeType::Default:
*width = 500; // dummy value
*height = 100; // dummy value
LOG_DEBUG(Lib_Ime, "param->type: Default ({})", static_cast<u32>(param->type));
break;
case OrbisImeType::BasicLatin:
*width = 500; // dummy value
*height = 100; // dummy value
LOG_DEBUG(Lib_Ime, "param->type: BasicLatin ({})", static_cast<u32>(param->type));
break;
case OrbisImeType::Url:
*width = 500; // dummy value
*height = 100; // dummy value
LOG_DEBUG(Lib_Ime, "param->type: Url ({})", static_cast<u32>(param->type));
break;
case OrbisImeType::Mail:
// We set our custom sizes, commented sizes are the original ones
*width = 500; // 793
*height = 100; // 408
LOG_DEBUG(Lib_Ime, "param->type: Mail ({})", static_cast<u32>(param->type));
break;
case OrbisImeType::Number:
*width = 370;
*height = 402;
LOG_DEBUG(Lib_Ime, "param->type: Number ({})", static_cast<u32>(param->type));
break;
default:
LOG_ERROR(Lib_Ime, "Invalid param->type: ({})", static_cast<u32>(param->type));
return Error::INVALID_TYPE;
}
return ORBIS_OK;
LOG_INFO(Lib_Ime, "IME panel size: width={}, height={}", *width, *height);
return Error::OK;
}
s32 PS4_SYSV_ABI sceImeKeyboardClose(s32 userId) {
LOG_INFO(Lib_Ime, "(STUBBED) called");
Error PS4_SYSV_ABI sceImeKeyboardClose(Libraries::UserService::OrbisUserServiceUserId userId) {
LOG_INFO(Lib_Ime, "called");
if (!g_keyboard_handler) {
return ORBIS_IME_ERROR_NOT_OPENED;
LOG_ERROR(Lib_Ime, "No keyboard handler is open");
return Error::NOT_OPENED;
}
if ((userId < 0 || userId > 4) &&
false) { // TODO: Check for valid user IDs. Disabled until user manager is ready.
// Maybe g_keyboard_handler should hold a user ID and I must compare it here?
LOG_ERROR(Lib_Ime, "Invalid userId: {}", userId);
return Error::INVALID_USER_ID;
}
g_keyboard_handler.release();
return ORBIS_OK;
if (g_ime_handler) {
LOG_ERROR(Lib_Ime, "failed to close keyboard handler, IME handler is still open");
return Error::INTERNAL;
}
LOG_INFO(Lib_Ime, "Keyboard handler closed successfully for user ID: {}", userId);
return Error::OK;
}
int PS4_SYSV_ABI sceImeKeyboardGetInfo() {
@ -268,25 +327,62 @@ int PS4_SYSV_ABI sceImeKeyboardGetResourceId() {
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceImeKeyboardOpen(s32 userId, const OrbisImeKeyboardParam* param) {
Error PS4_SYSV_ABI sceImeKeyboardOpen(Libraries::UserService::OrbisUserServiceUserId userId,
const OrbisImeKeyboardParam* param) {
LOG_INFO(Lib_Ime, "called");
if (!param) {
return ORBIS_IME_ERROR_INVALID_ADDRESS;
}
if (!param->arg) {
return ORBIS_IME_ERROR_INVALID_ARG;
LOG_ERROR(Lib_Ime, "Invalid param: NULL");
return Error::INVALID_ADDRESS;
}
if (!param->handler) {
return ORBIS_IME_ERROR_INVALID_HANDLER;
LOG_ERROR(Lib_Ime, "Invalid param->handler: NULL");
return Error::INVALID_HANDLER;
}
// seems like arg is optional, need to check if it is used in the handler
if (!param->arg && false) { // Todo: check if arg is used in the handler, temporarily disabled
LOG_ERROR(Lib_Ime, "Invalid param->arg: NULL");
return Error::INVALID_ARG;
}
if (static_cast<u32>(param->option) & ~kValidOrbisImeKeyboardOptionMask) {
LOG_ERROR(Lib_Ime,
"Invalid param->option\n"
"option: {:032b}\n"
"validMask: {:032b}",
static_cast<u32>(param->option), kValidOrbisImeKeyboardOptionMask);
return Error::INVALID_OPTION;
}
if ((userId < 0 || userId > 4) &&
false) { // TODO: Check for valid user IDs. Disabled until user manager is ready.
LOG_ERROR(Lib_Ime, "Invalid userId: {}", userId);
return Error::INVALID_USER_ID;
}
for (size_t i = 0; i < sizeof(param->reserved1); ++i) {
if (param->reserved1[i] != 0) {
LOG_ERROR(Lib_Ime, "Invalid reserved1: not zeroed");
return Error::INVALID_RESERVED;
}
}
for (size_t i = 0; i < sizeof(param->reserved2); ++i) {
if (param->reserved2[i] != 0) {
LOG_ERROR(Lib_Ime, "Invalid reserved2: not zeroed");
return Error::INVALID_RESERVED;
}
}
if (false) { // Todo: figure out what it is, always true for now
LOG_ERROR(Lib_Ime, "USB keyboard some special kind of failure");
return Error::CONNECTION_FAILED;
}
if (g_keyboard_handler) {
return ORBIS_IME_ERROR_BUSY;
LOG_ERROR(Lib_Ime, "Keyboard handler is already open");
return Error::BUSY;
}
g_keyboard_handler = std::make_unique<ImeHandler>(param);
return ORBIS_OK;
if (!g_keyboard_handler) {
LOG_ERROR(Lib_Ime, "Failed to create keyboard handler");
return Error::INTERNAL; // or Error::NO_MEMORY;
}
LOG_INFO(Lib_Ime, "Keyboard handler created successfully for user ID: {}", userId);
return Error::OK;
}
int PS4_SYSV_ABI sceImeKeyboardOpenInternal() {
@ -304,18 +400,190 @@ int PS4_SYSV_ABI sceImeKeyboardUpdate() {
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceImeOpen(const OrbisImeParam* param, const void* extended) {
Error PS4_SYSV_ABI sceImeOpen(const OrbisImeParam* param, const OrbisImeParamExtended* extended) {
LOG_INFO(Lib_Ime, "called");
if (!param) {
return ORBIS_IME_ERROR_INVALID_ADDRESS;
LOG_ERROR(Lib_Ime, "Invalid param: NULL");
return Error::INVALID_ADDRESS;
} else {
// LOG_DEBUG values for debugging purposes
LOG_DEBUG(Lib_Ime, "param->user_id: {}", param->user_id);
LOG_DEBUG(Lib_Ime, "param->type: {}", static_cast<u32>(param->type));
LOG_DEBUG(Lib_Ime, "param->supported_languages: {:064b}",
static_cast<u64>(param->supported_languages));
LOG_DEBUG(Lib_Ime, "param->enter_label: {}", static_cast<u32>(param->enter_label));
LOG_DEBUG(Lib_Ime, "param->input_method: {}", static_cast<u32>(param->input_method));
LOG_DEBUG(Lib_Ime, "param->filter: {:p}", reinterpret_cast<void*>(param->filter));
LOG_DEBUG(Lib_Ime, "param->option: {:032b}", static_cast<u32>(param->option));
LOG_DEBUG(Lib_Ime, "param->maxTextLength: {}", param->maxTextLength);
LOG_DEBUG(Lib_Ime, "param->inputTextBuffer: {:p}",
static_cast<const void*>(param->inputTextBuffer));
LOG_DEBUG(Lib_Ime, "param->posx: {}", param->posx);
LOG_DEBUG(Lib_Ime, "param->posy: {}", param->posy);
LOG_DEBUG(Lib_Ime, "param->horizontal_alignment: {}",
static_cast<u32>(param->horizontal_alignment));
LOG_DEBUG(Lib_Ime, "param->vertical_alignment: {}",
static_cast<u32>(param->vertical_alignment));
LOG_DEBUG(Lib_Ime, "param->work: {:p}", param->work);
LOG_DEBUG(Lib_Ime, "param->arg: {:p}", param->arg);
LOG_DEBUG(Lib_Ime, "param->handler: {:p}", reinterpret_cast<void*>(param->handler));
}
if (!extended) {
LOG_INFO(Lib_Ime, "Not used extended: NULL");
} else {
LOG_DEBUG(Lib_Ime, "extended->option: {:032b}", static_cast<u32>(extended->option));
LOG_DEBUG(Lib_Ime, "extended->color_base: {{{},{},{},{}}}", extended->color_base.r,
extended->color_base.g, extended->color_base.b, extended->color_base.a);
LOG_DEBUG(Lib_Ime, "extended->color_line: {{{},{},{},{}}}", extended->color_line.r,
extended->color_line.g, extended->color_line.b, extended->color_line.a);
LOG_DEBUG(Lib_Ime, "extended->color_text_field: {{{},{},{},{}}}",
extended->color_text_field.r, extended->color_text_field.g,
extended->color_text_field.b, extended->color_text_field.a);
LOG_DEBUG(Lib_Ime, "extended->color_preedit: {{{},{},{},{}}}", extended->color_preedit.r,
extended->color_preedit.g, extended->color_preedit.b, extended->color_preedit.a);
LOG_DEBUG(Lib_Ime, "extended->color_button_default: {{{},{},{},{}}}",
extended->color_button_default.r, extended->color_button_default.g,
extended->color_button_default.b, extended->color_button_default.a);
LOG_DEBUG(Lib_Ime, "extended->color_button_function: {{{},{},{},{}}}",
extended->color_button_function.r, extended->color_button_function.g,
extended->color_button_function.b, extended->color_button_function.a);
LOG_DEBUG(Lib_Ime, "extended->color_button_symbol: {{{},{},{},{}}}",
extended->color_button_symbol.r, extended->color_button_symbol.g,
extended->color_button_symbol.b, extended->color_button_symbol.a);
LOG_DEBUG(Lib_Ime, "extended->color_text: {{{},{},{},{}}}", extended->color_text.r,
extended->color_text.g, extended->color_text.b, extended->color_text.a);
LOG_DEBUG(Lib_Ime, "extended->color_special: {{{},{},{},{}}}", extended->color_special.r,
extended->color_special.g, extended->color_special.b, extended->color_special.a);
LOG_DEBUG(Lib_Ime, "extended->priority: {}", static_cast<u32>(extended->priority));
LOG_DEBUG(Lib_Ime, "extended->additional_dictionary_path: {:p}",
static_cast<const void*>(extended->additional_dictionary_path));
LOG_DEBUG(Lib_Ime, "extended->ext_keyboard_filter: {:p}",
reinterpret_cast<void*>(extended->ext_keyboard_filter));
LOG_DEBUG(Lib_Ime, "extended->disable_device: {:032b}",
static_cast<u32>(extended->disable_device));
LOG_DEBUG(Lib_Ime, "extended->ext_keyboard_mode: {}", extended->ext_keyboard_mode);
}
if (param->user_id < 1 || param->user_id > 4) { // Todo: check valid user IDs
LOG_ERROR(Lib_Ime, "Invalid user_id: {}", static_cast<u32>(param->user_id));
return Error::INVALID_USER_ID;
}
if (!magic_enum::enum_contains(param->type)) {
LOG_ERROR(Lib_Ime, "Invalid type: {}", static_cast<u32>(param->type));
return Error::INVALID_TYPE;
}
if (static_cast<u64>(param->supported_languages) & ~kValidOrbisImeLanguageMask) {
LOG_ERROR(Lib_Ime,
"Invalid supported_languages\n"
"supported_languages: {:064b}\n"
"valid_mask: {:064b}",
static_cast<u64>(param->supported_languages), kValidOrbisImeLanguageMask);
return Error::INVALID_SUPPORTED_LANGUAGES;
}
if (!magic_enum::enum_contains(param->enter_label)) {
LOG_ERROR(Lib_Ime, "Invalid enter_label: {}", static_cast<u32>(param->enter_label));
return Error::INVALID_ENTER_LABEL;
}
if (!magic_enum::enum_contains(param->input_method)) {
LOG_ERROR(Lib_Ime, "Invalid input_method: {}", static_cast<u32>(param->input_method));
return Error::INVALID_INPUT_METHOD;
}
if (static_cast<u32>(param->option) & ~kValidImeOptionMask) {
LOG_ERROR(Lib_Ime, "option has invalid bits set (0x{:X}), mask=(0x{:X})",
static_cast<u32>(param->option), kValidImeOptionMask);
return Error::INVALID_OPTION;
}
if (param->maxTextLength == 0 || param->maxTextLength > ORBIS_IME_DIALOG_MAX_TEXT_LENGTH) {
LOG_ERROR(Lib_Ime, "Invalid maxTextLength: {}", param->maxTextLength);
return Error::INVALID_MAX_TEXT_LENGTH;
}
if (!param->inputTextBuffer) {
LOG_ERROR(Lib_Ime, "Invalid inputTextBuffer: NULL");
return Error::INVALID_INPUT_TEXT_BUFFER;
}
bool useHighRes = True(param->option & OrbisImeOption::USE_OVER_2K_COORDINATES);
const float maxWidth = useHighRes ? 3840.0f : 1920.0f;
const float maxHeight = useHighRes ? 2160.0f : 1080.0f;
if (param->posx < 0.0f || param->posx >= maxWidth) {
LOG_ERROR(Lib_Ime, "Invalid posx: {}, range: 0.0 - {}", param->posx, maxWidth);
return Error::INVALID_POSX;
}
if (param->posy < 0.0f || param->posy >= maxHeight) {
LOG_ERROR(Lib_Ime, "Invalid posy: {}, range: 0.0 - {}", param->posy, maxHeight);
return Error::INVALID_POSY;
}
if (!magic_enum::enum_contains(param->horizontal_alignment)) {
LOG_ERROR(Lib_Ime, "Invalid horizontal_alignment: {}",
static_cast<u32>(param->horizontal_alignment));
return Error::INVALID_HORIZONTALIGNMENT;
}
if (!magic_enum::enum_contains(param->vertical_alignment)) {
LOG_ERROR(Lib_Ime, "Invalid vertical_alignment: {}",
static_cast<u32>(param->vertical_alignment));
return Error::INVALID_VERTICALALIGNMENT;
}
if (extended) {
u32 ext_option_value = static_cast<u32>(extended->option);
if (ext_option_value & ~kValidImeExtOptionMask) {
LOG_ERROR(Lib_Ime,
"Invalid extended->option\n"
"option: {:032b}\n"
"valid_mask: {:032b}",
ext_option_value, kValidImeExtOptionMask);
return Error::INVALID_EXTENDED;
}
}
if (!param->work) {
LOG_ERROR(Lib_Ime, "Invalid work: NULL");
return Error::INVALID_WORK;
}
// Todo: validate arg
if (false) {
LOG_ERROR(Lib_Ime, "Invalid arg: NULL");
return Error::INVALID_ARG;
}
// Todo: validate handler
if (false) {
LOG_ERROR(Lib_Ime, "Invalid handler: NULL");
return Error::INVALID_HANDLER;
}
for (size_t i = 0; i < sizeof(param->reserved); ++i) {
if (param->reserved[i] != 0) {
LOG_ERROR(Lib_Ime, "Invalid reserved: not zeroed");
return Error::INVALID_RESERVED;
}
}
if (g_ime_handler) {
return ORBIS_IME_ERROR_BUSY;
LOG_ERROR(Lib_Ime, "IME handler is already open");
return Error::BUSY;
}
g_ime_handler = std::make_unique<ImeHandler>(param);
return ORBIS_OK;
if (!g_ime_handler) {
LOG_ERROR(Lib_Ime, "Failed to create IME handler");
return Error::NO_MEMORY; // or Error::INTERNAL
}
LOG_INFO(Lib_Ime, "IME handler created successfully");
return Error::OK;
}
int PS4_SYSV_ABI sceImeOpenInternal() {
@ -324,7 +592,7 @@ int PS4_SYSV_ABI sceImeOpenInternal() {
}
void PS4_SYSV_ABI sceImeParamInit(OrbisImeParam* param) {
LOG_INFO(Lib_Ime, "called");
LOG_INFO(Lib_Ime, "sceImeParamInit called");
if (!param) {
return;
@ -339,27 +607,27 @@ int PS4_SYSV_ABI sceImeSetCandidateIndex() {
return ORBIS_OK;
}
int PS4_SYSV_ABI sceImeSetCaret(const OrbisImeCaret* caret) {
Error PS4_SYSV_ABI sceImeSetCaret(const OrbisImeCaret* caret) {
LOG_TRACE(Lib_Ime, "called");
if (!g_ime_handler) {
return ORBIS_IME_ERROR_NOT_OPENED;
return Error::NOT_OPENED;
}
if (!caret) {
return ORBIS_IME_ERROR_INVALID_ADDRESS;
return Error::INVALID_ADDRESS;
}
return g_ime_handler->SetCaret(caret);
}
s32 PS4_SYSV_ABI sceImeSetText(const char16_t* text, u32 length) {
Error PS4_SYSV_ABI sceImeSetText(const char16_t* text, u32 length) {
LOG_TRACE(Lib_Ime, "called");
if (!g_ime_handler) {
return ORBIS_IME_ERROR_NOT_OPENED;
return Error::NOT_OPENED;
}
if (!text) {
return ORBIS_IME_ERROR_INVALID_ADDRESS;
return Error::INVALID_ADDRESS;
}
return g_ime_handler->SetText(text, length);
@ -370,7 +638,7 @@ int PS4_SYSV_ABI sceImeSetTextGeometry() {
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceImeUpdate(OrbisImeEventHandler handler) {
Error PS4_SYSV_ABI sceImeUpdate(OrbisImeEventHandler handler) {
if (g_ime_handler) {
g_ime_handler->Update(handler);
}
@ -380,10 +648,10 @@ s32 PS4_SYSV_ABI sceImeUpdate(OrbisImeEventHandler handler) {
}
if (!g_ime_handler || !g_keyboard_handler) {
return ORBIS_IME_ERROR_NOT_OPENED;
return Error::NOT_OPENED;
}
return ORBIS_OK;
return Error::OK;
}
int PS4_SYSV_ABI sceImeVshClearPreedit() {
@ -481,7 +749,7 @@ int PS4_SYSV_ABI sceImeVshUpdateContext2() {
return ORBIS_OK;
}
void RegisterlibSceIme(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("mN+ZoSN-8hQ", "libSceIme", 1, "libSceIme", 1, 1, FinalizeImeModule);
LIB_FUNCTION("uTW+63goeJs", "libSceIme", 1, "libSceIme", 1, 1, InitializeImeModule);
LIB_FUNCTION("Lf3DeGWC6xg", "libSceIme", 1, "libSceIme", 1, 1, sceImeCheckFilterText);

View File

@ -13,78 +13,12 @@ class SymbolsResolver;
namespace Libraries::Ime {
constexpr u32 ORBIS_IME_MAX_TEXT_LENGTH = 2048;
enum class OrbisImeKeyboardOption : u32 {
Default = 0,
Repeat = 1,
RepeatEachKey = 2,
AddOsk = 4,
EffectiveWithIme = 8,
DisableResume = 16,
DisableCapslockWithoutShift = 32,
};
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeKeyboardOption)
enum class OrbisImeOption : u32 {
DEFAULT = 0,
MULTILINE = 1,
NO_AUTO_CAPITALIZATION = 2,
PASSWORD = 4,
LANGUAGES_FORCED = 8,
EXT_KEYBOARD = 16,
NO_LEARNING = 32,
FIXED_POSITION = 64,
DISABLE_RESUME = 256,
DISABLE_AUTO_SPACE = 512,
DISABLE_POSITION_ADJUSTMENT = 2048,
EXPANDED_PREEDIT_BUFFER = 4096,
USE_JAPANESE_EISUU_KEY_AS_CAPSLOCK = 8192,
USE_2K_COORDINATES = 16384,
};
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeOption)
struct OrbisImeKeyboardParam {
OrbisImeKeyboardOption option;
s8 reserved1[4];
void* arg;
OrbisImeEventHandler handler;
s8 reserved2[8];
};
struct OrbisImeParam {
s32 user_id;
OrbisImeType type;
u64 supported_languages;
OrbisImeEnterLabel enter_label;
OrbisImeInputMethod input_method;
OrbisImeTextFilter filter;
OrbisImeOption option;
u32 maxTextLength;
char16_t* inputTextBuffer;
float posx;
float posy;
OrbisImeHorizontalAlignment horizontal_alignment;
OrbisImeVerticalAlignment vertical_alignment;
void* work;
void* arg;
OrbisImeEventHandler handler;
s8 reserved[8];
};
struct OrbisImeCaret {
f32 x;
f32 y;
u32 height;
u32 index;
};
int PS4_SYSV_ABI FinalizeImeModule();
int PS4_SYSV_ABI InitializeImeModule();
int PS4_SYSV_ABI sceImeCheckFilterText();
int PS4_SYSV_ABI sceImeCheckRemoteEventParam();
int PS4_SYSV_ABI sceImeCheckUpdateTextInfo();
int PS4_SYSV_ABI sceImeClose();
Error PS4_SYSV_ABI sceImeClose();
int PS4_SYSV_ABI sceImeConfigGet();
int PS4_SYSV_ABI sceImeConfigSet();
int PS4_SYSV_ABI sceImeConfirmCandidate();
@ -98,22 +32,23 @@ int PS4_SYSV_ABI sceImeDisableController();
int PS4_SYSV_ABI sceImeFilterText();
int PS4_SYSV_ABI sceImeForTestFunction();
int PS4_SYSV_ABI sceImeGetPanelPositionAndForm();
s32 PS4_SYSV_ABI sceImeGetPanelSize(const OrbisImeParam* param, u32* width, u32* height);
s32 PS4_SYSV_ABI sceImeKeyboardClose(s32 userId);
Error PS4_SYSV_ABI sceImeGetPanelSize(const OrbisImeParam* param, u32* width, u32* height);
Error PS4_SYSV_ABI sceImeKeyboardClose(Libraries::UserService::OrbisUserServiceUserId userId);
int PS4_SYSV_ABI sceImeKeyboardGetInfo();
int PS4_SYSV_ABI sceImeKeyboardGetResourceId();
s32 PS4_SYSV_ABI sceImeKeyboardOpen(s32 userId, const OrbisImeKeyboardParam* param);
Error PS4_SYSV_ABI sceImeKeyboardOpen(Libraries::UserService::OrbisUserServiceUserId userId,
const OrbisImeKeyboardParam* param);
int PS4_SYSV_ABI sceImeKeyboardOpenInternal();
int PS4_SYSV_ABI sceImeKeyboardSetMode();
int PS4_SYSV_ABI sceImeKeyboardUpdate();
s32 PS4_SYSV_ABI sceImeOpen(const OrbisImeParam* param, const void* extended);
Error PS4_SYSV_ABI sceImeOpen(const OrbisImeParam* param, const OrbisImeParamExtended* extended);
int PS4_SYSV_ABI sceImeOpenInternal();
void PS4_SYSV_ABI sceImeParamInit(OrbisImeParam* param);
int PS4_SYSV_ABI sceImeSetCandidateIndex();
s32 PS4_SYSV_ABI sceImeSetCaret(const OrbisImeCaret* caret);
s32 PS4_SYSV_ABI sceImeSetText(const char16_t* text, u32 length);
Error PS4_SYSV_ABI sceImeSetCaret(const OrbisImeCaret* caret);
Error PS4_SYSV_ABI sceImeSetText(const char16_t* text, u32 length);
int PS4_SYSV_ABI sceImeSetTextGeometry();
s32 PS4_SYSV_ABI sceImeUpdate(OrbisImeEventHandler handler);
Error PS4_SYSV_ABI sceImeUpdate(OrbisImeEventHandler handler);
int PS4_SYSV_ABI sceImeVshClearPreedit();
int PS4_SYSV_ABI sceImeVshClose();
int PS4_SYSV_ABI sceImeVshConfirmPreedit();
@ -134,6 +69,6 @@ int PS4_SYSV_ABI sceImeVshUpdate();
int PS4_SYSV_ABI sceImeVshUpdateContext();
int PS4_SYSV_ABI sceImeVshUpdateContext2();
void RegisterlibSceIme(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Ime

View File

@ -3,9 +3,273 @@
#pragma once
#include <core/libraries/system/userservice.h>
#include <magic_enum/magic_enum.hpp>
#include "common/enum.h"
#include "common/types.h"
#include "core/libraries/rtc/rtc.h"
constexpr u32 ORBIS_IME_MAX_TEXT_LENGTH = 2048;
constexpr u32 ORBIS_IME_DIALOG_MAX_TEXT_LENGTH = 2048;
template <typename E>
const std::underlying_type_t<E> generate_full_mask() {
static_assert(std::is_enum_v<E>, "E must be an enum type.");
static_assert(magic_enum::customize::enum_range<E>::is_flags,
"E must be marked as is_flags = true.");
using U = std::underlying_type_t<E>;
const auto values = magic_enum::enum_values<E>();
U mask = 0;
// Use index-based loop for better constexpr compatibility
for (std::size_t i = 0; i < values.size(); ++i) {
mask |= static_cast<U>(values[i]);
}
return mask;
}
enum class Error : u32 {
OK = 0x0,
// ImeDialog library
BUSY = 0x80bc0001,
NOT_OPENED = 0x80bc0002,
NO_MEMORY = 0x80bc0003,
CONNECTION_FAILED = 0x80bc0004,
TOO_MANY_REQUESTS = 0x80bc0005,
INVALID_TEXT = 0x80bc0006,
EVENT_OVERFLOW = 0x80bc0007,
NOT_ACTIVE = 0x80bc0008,
IME_SUSPENDING = 0x80bc0009,
DEVICE_IN_USE = 0x80bc000a,
INVALID_USER_ID = 0x80bc0010,
INVALID_TYPE = 0x80bc0011,
INVALID_SUPPORTED_LANGUAGES = 0x80bc0012,
INVALID_ENTER_LABEL = 0x80bc0013,
INVALID_INPUT_METHOD = 0x80bc0014,
INVALID_OPTION = 0x80bc0015,
INVALID_MAX_TEXT_LENGTH = 0x80bc0016,
INVALID_INPUT_TEXT_BUFFER = 0x80bc0017,
INVALID_POSX = 0x80bc0018,
INVALID_POSY = 0x80bc0019,
INVALID_HORIZONTALIGNMENT = 0x80bc001a,
INVALID_VERTICALALIGNMENT = 0x80bc001b,
INVALID_EXTENDED = 0x80bc001c,
INVALID_KEYBOARD_TYPE = 0x80bc001d,
INVALID_WORK = 0x80bc0020,
INVALID_ARG = 0x80bc0021,
INVALID_HANDLER = 0x80bc0022,
NO_RESOURCE_ID = 0x80bc0023,
INVALID_MODE = 0x80bc0024,
INVALID_PARAM = 0x80bc0030,
INVALID_ADDRESS = 0x80bc0031,
INVALID_RESERVED = 0x80bc0032,
INVALID_TIMING = 0x80bc0033,
INTERNAL = 0x80bc00ff,
// Ime library
DIALOG_INVALID_TITLE = 0x80bc0101,
DIALOG_NOT_RUNNING = 0x80bc0105,
DIALOG_NOT_FINISHED = 0x80bc0106,
DIALOG_NOT_IN_USE = 0x80bc0107
};
enum class OrbisImeOption : u32 {
DEFAULT = 0,
MULTILINE = 1,
NO_AUTO_CAPITALIZATION = 2,
PASSWORD = 4,
LANGUAGES_FORCED = 8,
EXT_KEYBOARD = 16,
NO_LEARNING = 32,
FIXED_POSITION = 64,
DISABLE_COPY_PASTE = 128,
DISABLE_RESUME = 256,
DISABLE_AUTO_SPACE = 512,
DISABLE_POSITION_ADJUSTMENT = 2048,
EXPANDED_PREEDIT_BUFFER = 4096,
USE_JAPANESE_EISUU_KEY_AS_CAPSLOCK = 8192,
USE_OVER_2K_COORDINATES = 16384,
};
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeOption);
template <>
struct magic_enum::customize::enum_range<OrbisImeOption> {
static constexpr bool is_flags = true;
};
const u32 kValidImeOptionMask = generate_full_mask<OrbisImeOption>();
enum class OrbisImeExtOption : u32 {
DEFAULT = 0x00000000,
SET_PRIORITY = 0x00000002,
PRIORITY_FULL_WIDTH = 0x00000008,
PRIORITY_FIXED_PANEL = 0x00000010,
DISABLE_POINTER = 0x00000040,
ENABLE_ADDITIONAL_DICTIONARY = 0x00000080,
DISABLE_STARTUP_SE = 0x00000100,
DISABLE_LIST_FOR_EXT_KEYBOARD = 0x00000200,
HIDE_KEYPANEL_IF_EXT_KEYBOARD = 0x00000400,
INIT_EXT_KEYBOARD_MODE = 0x00000800,
ENABLE_ACCESSIBILITY = 0x00001000, // ImeDialog unly
ADDITIONAL_DICTIONARY_PRIORITY_MODE = 0x00004000, // ImeDialog only
};
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeExtOption);
constexpr u32 kValidImeExtOptionMask = static_cast<u32>(
OrbisImeExtOption::SET_PRIORITY | OrbisImeExtOption::PRIORITY_FULL_WIDTH |
OrbisImeExtOption::PRIORITY_FIXED_PANEL | OrbisImeExtOption::DISABLE_POINTER |
OrbisImeExtOption::ENABLE_ADDITIONAL_DICTIONARY | OrbisImeExtOption::DISABLE_STARTUP_SE |
OrbisImeExtOption::DISABLE_LIST_FOR_EXT_KEYBOARD |
OrbisImeExtOption::HIDE_KEYPANEL_IF_EXT_KEYBOARD | OrbisImeExtOption::INIT_EXT_KEYBOARD_MODE);
template <>
struct magic_enum::customize::enum_range<OrbisImeExtOption> {
static constexpr bool is_flags = true;
};
const u32 kValidImeDialogExtOptionMask = generate_full_mask<OrbisImeExtOption>();
enum class OrbisImeLanguage : u64 {
DANISH = 0x0000000000000001,
GERMAN = 0x0000000000000002,
ENGLISH_US = 0x0000000000000004,
SPANISH = 0x0000000000000008,
FRENCH = 0x0000000000000010,
ITALIAN = 0x0000000000000020,
DUTCH = 0x0000000000000040,
NORWEGIAN = 0x0000000000000080,
POLISH = 0x0000000000000100,
PORTUGUESE_PT = 0x0000000000000200,
RUSSIAN = 0x0000000000000400,
FINNISH = 0x0000000000000800,
SWEDISH = 0x0000000000001000,
JAPANESE = 0x0000000000002000,
KOREAN = 0x0000000000004000,
SIMPLIFIED_CHINESE = 0x0000000000008000,
TRADITIONAL_CHINESE = 0x0000000000010000,
PORTUGUESE_BR = 0x0000000000020000,
ENGLISH_GB = 0x0000000000040000,
TURKISH = 0x0000000000080000,
SPANISH_LA = 0x0000000000100000,
ARABIC = 0x0000000001000000,
FRENCH_CA = 0x0000000002000000,
THAI = 0x0000000004000000,
CZECH = 0x0000000008000000,
GREEK = 0x0000000010000000,
INDONESIAN = 0x0000000020000000,
VIETNAMESE = 0x0000000040000000,
ROMANIAN = 0x0000000080000000,
HUNGARIAN = 0x0000000100000000,
};
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeLanguage);
template <>
struct magic_enum::customize::enum_range<OrbisImeLanguage> {
static constexpr bool is_flags = true;
};
const u64 kValidOrbisImeLanguageMask = generate_full_mask<OrbisImeLanguage>();
enum class OrbisImeDisableDevice : u32 {
DEFAULT = 0x00000000,
CONTROLLER = 0x00000001,
EXT_KEYBOARD = 0x00000002,
REMOTE_OSK = 0x00000004,
};
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeDisableDevice);
template <>
struct magic_enum::customize::enum_range<OrbisImeDisableDevice> {
static constexpr bool is_flags = true;
};
const u32 kValidOrbisImeDisableDeviceMask = generate_full_mask<OrbisImeDisableDevice>();
enum class OrbisImeInputMethodState : u32 {
PREEDIT = 0x01000000,
SELECTED = 0x02000000,
NATIVE = 0x04000000,
NATIVE2 = 0x08000000,
FULL_WIDTH = 0x10000000,
};
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeInputMethodState);
template <>
struct magic_enum::customize::enum_range<OrbisImeInputMethodState> {
static constexpr bool is_flags = true;
};
const u32 kValidOrbisImeInputMethodStateMask = generate_full_mask<OrbisImeInputMethodState>();
enum class OrbisImeInitExtKeyboardMode : u32 {
ISABLE_ARABIC_INDIC_NUMERALS = 0x00000001,
ENABLE_FORMAT_CHARACTERS = 0x00000002,
INPUT_METHOD_STATE_NATIVE = 0x04000000,
INPUT_METHOD_STATE_NATIVE2 = 0x08000000,
INPUT_METHOD_STATE_FULL_WIDTH = 0x10000000,
};
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeInitExtKeyboardMode);
template <>
struct magic_enum::customize::enum_range<OrbisImeInitExtKeyboardMode> {
static constexpr bool is_flags = true;
};
const u32 kValidOrbisImeInitExtKeyboardModeMask = generate_full_mask<OrbisImeInitExtKeyboardMode>();
enum class OrbisImeKeycodeState : u32 {
KEYCODE_VALID = 0x00000001,
CHARACTER_VALID = 0x00000002,
WITH_IME = 0x00000004,
FROM_OSK = 0x00000008,
FROM_OSK_SHORTCUT = 0x00000010,
FROM_IME_OPERATION = 0x00000020,
REPLACE_CHARACTER = 0x00000040,
CONTINUOUS_EVENT = 0x00000080,
MODIFIER_L_CTRL = 0x00000100,
MODIFIER_L_SHIFT = 0x00000200,
MODIFIER_L_ALT = 0x00000400,
MODIFIER_L_GUI = 0x00000800,
MODIFIER_R_CTRL = 0x00001000,
MODIFIER_R_SHIFT = 0x00002000,
MODIFIER_R_ALT = 0x00004000,
MODIFIER_R_GUI = 0x00008000,
LED_NUM_LOCK = 0x00010000,
LED_CAPS_LOCK = 0x00020000,
LED_SCROLL_LOCK = 0x00040000,
RESERVED1 = 0x00080000,
RESERVED2 = 0x00100000,
FROM_IME_INPUT = 0x00200000,
};
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeKeycodeState);
template <>
struct magic_enum::customize::enum_range<OrbisImeKeycodeState> {
static constexpr bool is_flags = true;
};
const u32 kValidOrbisImeKeycodeStateMask = generate_full_mask<OrbisImeKeycodeState>();
enum class OrbisImeKeyboardOption : u32 {
Default = 0,
Repeat = 1,
RepeatEachKey = 2,
AddOsk = 4,
EffectiveWithIme = 8,
DisableResume = 16,
DisableCapslockWithoutShift = 32,
};
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeKeyboardOption)
template <>
struct magic_enum::customize::enum_range<OrbisImeKeyboardOption> {
static constexpr bool is_flags = true;
};
const u32 kValidOrbisImeKeyboardOptionMask = generate_full_mask<OrbisImeKeyboardOption>();
enum class OrbisImeKeyboardMode : u32 {
Auto = 0,
Manual = 1,
Alphabet = 0,
Native = 2,
Part = 4,
Katakana = 8,
Hkana = 16,
ArabicIndicNumerals = 32,
DisableFormatCharacters = 64,
};
enum class OrbisImeType : u32 {
Default = 0,
BasicLatin = 1,
@ -41,6 +305,7 @@ enum class OrbisImeEventId : u32 {
Open = 0,
UpdateText = 1,
UpdateCaret = 2,
ChangeSize = 3,
PressClose = 4,
PressEnter = 5,
Abort = 6,
@ -51,10 +316,14 @@ enum class OrbisImeEventId : u32 {
CandidateDone = 11,
CandidateCancel = 12,
ChangeDevice = 14,
JumpToNextObject = 15,
JumpToBeforeObject = 16,
ChangeWindowType = 17,
ChangeInputMethodState = 18,
KeyboardOpen = 256,
KeyboardKeycodeDoen = 257,
KeyboardKeycodeDown = 257,
KeyboardKeycodeUp = 258,
KeyboardKeycodeRepeat = 259,
KeyboardConnection = 260,
@ -110,6 +379,13 @@ enum class OrbisImeDeviceType : u32 {
RemoteOsk = 3,
};
enum class OrbisImePanelPriority : u32 {
Default = 0,
Alphabet = 1,
Symbol = 2,
Accent = 3,
};
struct OrbisImeRect {
f32 x;
f32 y;
@ -117,8 +393,22 @@ struct OrbisImeRect {
u32 height;
};
struct OrbisImeColor {
u8 r;
u8 g;
u8 b;
u8 a;
};
enum class OrbisImeTextAreaMode : u32 {
Disable = 0,
Edit = 1,
Preedit = 2,
Select = 3,
};
struct OrbisImeTextAreaProperty {
u32 mode; // OrbisImeTextAreaMode
OrbisImeTextAreaMode mode;
u32 index;
s32 length;
};
@ -135,14 +425,14 @@ struct OrbisImeKeycode {
char16_t character;
u32 status;
OrbisImeKeyboardType type;
s32 user_id;
Libraries::UserService::OrbisUserServiceUserId user_id;
u32 resource_id;
Libraries::Rtc::OrbisRtcTick timestamp;
};
struct OrbisImeKeyboardResourceIdArray {
s32 userId;
u32 resourceId[5];
Libraries::UserService::OrbisUserServiceUserId user_id;
u32 resource_id[5];
};
enum class OrbisImeCaretMovementDirection : u32 {
@ -159,6 +449,16 @@ enum class OrbisImeCaretMovementDirection : u32 {
Bottom = 10,
};
enum class OrbisImePanelType : u32 {
Hide = 0,
Osk = 1,
Dialog = 2,
Candidate = 3,
Edit = 4,
EditAndCandidate = 5,
Accessibility = 6,
};
union OrbisImeEventParam {
OrbisImeRect rect;
OrbisImeEditText text;
@ -168,6 +468,7 @@ union OrbisImeEventParam {
char16_t* candidate_word;
s32 candidate_index;
OrbisImeDeviceType device_type;
OrbisImePanelType panel_type;
u32 input_method_state;
s8 reserved[64];
};
@ -177,7 +478,84 @@ struct OrbisImeEvent {
OrbisImeEventParam param;
};
using OrbisImeExtKeyboardFilter = PS4_SYSV_ABI int (*)(const OrbisImeKeycode* srcKeycode,
u16* outKeycode, u32* outStatus,
void* reserved);
using OrbisImeTextFilter = PS4_SYSV_ABI int (*)(char16_t* outText, u32* outTextLength,
const char16_t* srcText, u32 srcTextLength);
using OrbisImeEventHandler = PS4_SYSV_ABI void (*)(void* arg, const OrbisImeEvent* e);
struct OrbisImeKeyboardParam {
OrbisImeKeyboardOption option;
s8 reserved1[4];
void* arg;
OrbisImeEventHandler handler;
s8 reserved2[8];
};
struct OrbisImeParam {
Libraries::UserService::OrbisUserServiceUserId user_id;
OrbisImeType type;
OrbisImeLanguage supported_languages;
OrbisImeEnterLabel enter_label;
OrbisImeInputMethod input_method;
OrbisImeTextFilter filter;
OrbisImeOption option;
u32 maxTextLength;
char16_t* inputTextBuffer;
f32 posx;
f32 posy;
OrbisImeHorizontalAlignment horizontal_alignment;
OrbisImeVerticalAlignment vertical_alignment;
void* work;
void* arg;
OrbisImeEventHandler handler;
s8 reserved[8];
};
struct OrbisImeCaret {
f32 x;
f32 y;
u32 height;
u32 index;
};
struct OrbisImeDialogParam {
Libraries::UserService::OrbisUserServiceUserId user_id;
OrbisImeType type;
OrbisImeLanguage supported_languages;
OrbisImeEnterLabel enter_label;
OrbisImeInputMethod input_method;
OrbisImeTextFilter filter;
OrbisImeOption option;
u32 max_text_length;
char16_t* input_text_buffer;
f32 posx;
f32 posy;
OrbisImeHorizontalAlignment horizontal_alignment;
OrbisImeVerticalAlignment vertical_alignment;
const char16_t* placeholder;
const char16_t* title;
s8 reserved[16];
};
struct OrbisImeParamExtended {
OrbisImeExtOption option;
OrbisImeColor color_base;
OrbisImeColor color_line;
OrbisImeColor color_text_field;
OrbisImeColor color_preedit;
OrbisImeColor color_button_default;
OrbisImeColor color_button_function;
OrbisImeColor color_button_symbol;
OrbisImeColor color_text;
OrbisImeColor color_special;
OrbisImePanelPriority priority;
char* additional_dictionary_path;
OrbisImeExtKeyboardFilter ext_keyboard_filter;
OrbisImeDisableDevice disable_device;
u32 ext_keyboard_mode;
s8 reserved[60];
};

View File

@ -20,19 +20,19 @@ static OrbisImeDialogResult g_ime_dlg_result{};
static ImeDialogState g_ime_dlg_state{};
static ImeDialogUi g_ime_dlg_ui;
static bool IsValidOption(OrbisImeDialogOption option, OrbisImeType type) {
if (False(~option &
(OrbisImeDialogOption::Multiline | OrbisImeDialogOption::NoAutoCompletion))) {
static bool IsValidOption(OrbisImeOption option, OrbisImeType type) {
if (False(~option & (OrbisImeOption::MULTILINE |
OrbisImeOption::NO_AUTO_CAPITALIZATION /* NoAutoCompletion */))) {
return false;
}
if (True(option & OrbisImeDialogOption::Multiline) && type != OrbisImeType::Default &&
if (True(option & OrbisImeOption::MULTILINE) && type != OrbisImeType::Default &&
type != OrbisImeType::BasicLatin) {
return false;
}
if (True(option & OrbisImeDialogOption::NoAutoCompletion) && type != OrbisImeType::Number &&
type != OrbisImeType::BasicLatin) {
if (True(option & OrbisImeOption::NO_AUTO_CAPITALIZATION /* NoAutoCompletion */) &&
type != OrbisImeType::Number && type != OrbisImeType::BasicLatin) {
return false;
}
@ -96,7 +96,7 @@ Error PS4_SYSV_ABI sceImeDialogGetPanelSize(const OrbisImeDialogParam* param, u3
case OrbisImeType::Url:
case OrbisImeType::Mail:
*width = 500; // original: 793
if (True(param->option & OrbisImeDialogOption::Multiline)) {
if (True(param->option & OrbisImeOption::MULTILINE)) {
*height = 300; // original: 576
} else {
*height = 150; // original: 476
@ -149,18 +149,47 @@ OrbisImeDialogStatus PS4_SYSV_ABI sceImeDialogGetStatus() {
}
Error PS4_SYSV_ABI sceImeDialogInit(OrbisImeDialogParam* param, OrbisImeParamExtended* extended) {
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: entering, param={}, extended={}",
static_cast<void*>(param), static_cast<void*>(extended));
if (param == nullptr) {
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: param is null");
return Error::INVALID_ADDRESS;
} else {
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.user_id = {}",
static_cast<u32>(param->user_id));
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.type = {}", static_cast<u32>(param->type));
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.supported_languages = 0x{:X}",
static_cast<u64>(param->supported_languages));
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.enter_label = {}",
static_cast<u32>(param->enter_label));
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.input_method = {}",
static_cast<u32>(param->input_method));
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.filter = {}", (void*)param->filter);
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.option = 0x{:X}",
static_cast<u32>(param->option));
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.max_text_length = {}",
param->max_text_length);
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.input_text_buffer = {}",
(void*)param->input_text_buffer);
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.posx = {}", param->posx);
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.posy = {}", param->posy);
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.horizontal_alignment = {}",
static_cast<u32>(param->horizontal_alignment));
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.vertical_alignment = {}",
static_cast<u32>(param->vertical_alignment));
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.placeholder = {}",
param->placeholder ? "<non-null>" : "NULL");
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.title = {}",
param->title ? "<non-null>" : "NULL");
}
if (g_ime_dlg_status != OrbisImeDialogStatus::None) {
LOG_INFO(Lib_ImeDialog, "IME dialog is already running");
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: busy (status={})", (u32)g_ime_dlg_status);
return Error::BUSY;
}
if (param == nullptr) {
LOG_INFO(Lib_ImeDialog, "called with param (NULL)");
return Error::INVALID_ADDRESS;
}
if (!magic_enum::enum_contains(param->type)) {
LOG_INFO(Lib_ImeDialog, "Invalid param->type");
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: invalid param->type={}", (u32)param->type);
return Error::INVALID_ADDRESS;
}
@ -169,15 +198,15 @@ Error PS4_SYSV_ABI sceImeDialogInit(OrbisImeDialogParam* param, OrbisImeParamExt
if (param->posx < 0.0f ||
param->posx >=
MAX_X_POSITIONS[False(param->option & OrbisImeDialogOption::LargeResolution)]) {
LOG_INFO(Lib_ImeDialog, "Invalid param->posx");
MAX_X_POSITIONS[False(param->option & OrbisImeOption::USE_OVER_2K_COORDINATES)]) {
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: invalid posx={}", param->posx);
return Error::INVALID_POSX;
}
if (param->posy < 0.0f ||
param->posy >=
MAX_Y_POSITIONS[False(param->option & OrbisImeDialogOption::LargeResolution)]) {
LOG_INFO(Lib_ImeDialog, "Invalid param->posy");
MAX_Y_POSITIONS[False(param->option & OrbisImeOption::USE_OVER_2K_COORDINATES)]) {
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: invalid posy={}", param->posy);
return Error::INVALID_POSY;
}
@ -192,44 +221,55 @@ Error PS4_SYSV_ABI sceImeDialogInit(OrbisImeDialogParam* param, OrbisImeParamExt
}
if (!IsValidOption(param->option, param->type)) {
LOG_INFO(Lib_ImeDialog, "Invalid param->option");
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: invalid option=0x{:X}for type={}",
static_cast<u32>(param->option), (u32)param->type);
return Error::INVALID_PARAM;
}
if (param->input_text_buffer == nullptr) {
LOG_INFO(Lib_ImeDialog, "Invalid param->inputTextBuffer");
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: input_text_buffer is null");
return Error::INVALID_INPUT_TEXT_BUFFER;
}
if (extended) {
if (!magic_enum::enum_contains(extended->priority)) {
LOG_INFO(Lib_ImeDialog, "Invalid extended->priority");
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: Invalid extended->priority");
return Error::INVALID_EXTENDED;
}
// TODO: do correct extended->option validation
if ((extended->ext_keyboard_mode & 0xe3fffffc) != 0) {
LOG_INFO(Lib_ImeDialog, "Invalid extended->extKeyboardMode");
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: Invalid extended->extKeyboardMode");
return Error::INVALID_EXTENDED;
}
if (extended->disable_device > 7) {
LOG_INFO(Lib_ImeDialog, "Invalid extended->disableDevice");
if (static_cast<u32>(extended->disable_device) & ~kValidOrbisImeDisableDeviceMask) {
LOG_ERROR(Lib_ImeDialog,
"sceImeDialogInit: disable_device has invalid bits set (0x{:X})",
static_cast<u32>(extended->disable_device));
return Error::INVALID_EXTENDED;
}
}
if (param->max_text_length > ORBIS_IME_DIALOG_MAX_TEXT_LENGTH) {
LOG_INFO(Lib_ImeDialog, "Invalid param->maxTextLength");
if (param->max_text_length == 0 || param->max_text_length > ORBIS_IME_MAX_TEXT_LENGTH) {
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: invalid max_text_length={}",
param->max_text_length);
return Error::INVALID_MAX_TEXT_LENGTH;
}
// Title string validation
if (param->title != nullptr && !std::char_traits<char16_t>::length(param->title)) {
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: title is empty");
return Error::INVALID_PARAM;
}
g_ime_dlg_result = {};
g_ime_dlg_state = ImeDialogState(param, extended);
g_ime_dlg_status = OrbisImeDialogStatus::Running;
g_ime_dlg_ui = ImeDialogUi(&g_ime_dlg_state, &g_ime_dlg_status, &g_ime_dlg_result);
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: successful, status now=Running");
return Error::OK;
}
@ -271,7 +311,7 @@ Error PS4_SYSV_ABI sceImeDialogTerm() {
return Error::OK;
}
void RegisterlibSceImeDialog(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("oBmw4xrmfKs", "libSceImeDialog", 1, "libSceImeDialog", 1, 1, sceImeDialogAbort);
LIB_FUNCTION("bX4H+sxPI-o", "libSceImeDialog", 1, "libSceImeDialog", 1, 1,
sceImeDialogForceClose);

View File

@ -13,50 +13,6 @@ class SymbolsResolver;
namespace Libraries::ImeDialog {
constexpr u32 ORBIS_IME_DIALOG_MAX_TEXT_LENGTH = 2048;
enum class Error : u32 {
OK = 0x0,
BUSY = 0x80bc0001,
NOT_OPENED = 0x80bc0002,
NO_MEMORY = 0x80bc0003,
CONNECTION_FAILED = 0x80bc0004,
TOO_MANY_REQUESTS = 0x80bc0005,
INVALID_TEXT = 0x80bc0006,
EVENT_OVERFLOW = 0x80bc0007,
NOT_ACTIVE = 0x80bc0008,
IME_SUSPENDING = 0x80bc0009,
DEVICE_IN_USE = 0x80bc000a,
INVALID_USER_ID = 0x80bc0010,
INVALID_TYPE = 0x80bc0011,
INVALID_SUPPORTED_LANGUAGES = 0x80bc0012,
INVALID_ENTER_LABEL = 0x80bc0013,
INVALID_INPUT_METHOD = 0x80bc0014,
INVALID_OPTION = 0x80bc0015,
INVALID_MAX_TEXT_LENGTH = 0x80bc0016,
INVALID_INPUT_TEXT_BUFFER = 0x80bc0017,
INVALID_POSX = 0x80bc0018,
INVALID_POSY = 0x80bc0019,
INVALID_HORIZONTALIGNMENT = 0x80bc001a,
INVALID_VERTICALALIGNMENT = 0x80bc001b,
INVALID_EXTENDED = 0x80bc001c,
INVALID_KEYBOARD_TYPE = 0x80bc001d,
INVALID_WORK = 0x80bc0020,
INVALID_ARG = 0x80bc0021,
INVALID_HANDLER = 0x80bc0022,
NO_RESOURCE_ID = 0x80bc0023,
INVALID_MODE = 0x80bc0024,
INVALID_PARAM = 0x80bc0030,
INVALID_ADDRESS = 0x80bc0031,
INVALID_RESERVED = 0x80bc0032,
INVALID_TIMING = 0x80bc0033,
INTERNAL = 0x80bc00ff,
DIALOG_INVALID_TITLE = 0x80bc0101,
DIALOG_NOT_RUNNING = 0x80bc0105,
DIALOG_NOT_FINISHED = 0x80bc0106,
DIALOG_NOT_IN_USE = 0x80bc0107,
};
enum class OrbisImeDialogStatus : u32 {
None = 0,
Running = 1,
@ -69,87 +25,11 @@ enum class OrbisImeDialogEndStatus : u32 {
Aborted = 2,
};
enum class OrbisImeDialogOption : u32 {
Default = 0,
Multiline = 1,
NoAutoCorrection = 2,
NoAutoCompletion = 4,
// TODO: Document missing options
LargeResolution = 1024,
};
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeDialogOption)
enum class OrbisImePanelPriority : u32 {
Default = 0,
Alphabet = 1,
Symbol = 2,
Accent = 3,
};
struct OrbisImeColor {
u8 r;
u8 g;
u8 b;
u8 a;
};
struct OrbisImeDialogResult {
OrbisImeDialogEndStatus endstatus;
s32 reserved[12];
};
struct OrbisImeKeycode {
u16 keycode;
char16_t character;
u32 status;
OrbisImeKeyboardType type;
s32 user_id;
u32 resource_id;
u64 timestamp;
};
using OrbisImeExtKeyboardFilter = PS4_SYSV_ABI int (*)(const OrbisImeKeycode* srcKeycode,
u16* outKeycode, u32* outStatus,
void* reserved);
struct OrbisImeDialogParam {
s32 user_id;
OrbisImeType type;
u64 supported_languages;
OrbisImeEnterLabel enter_label;
OrbisImeInputMethod input_method;
OrbisImeTextFilter filter;
OrbisImeDialogOption option;
u32 max_text_length;
char16_t* input_text_buffer;
float posx;
float posy;
OrbisImeHorizontalAlignment horizontal_alignment;
OrbisImeVerticalAlignment vertical_alignment;
const char16_t* placeholder;
const char16_t* title;
s8 reserved[16];
};
struct OrbisImeParamExtended {
u32 option; // OrbisImeDialogOptionExtended
OrbisImeColor color_base;
OrbisImeColor color_line;
OrbisImeColor color_text_field;
OrbisImeColor color_preedit;
OrbisImeColor color_button_default;
OrbisImeColor color_button_function;
OrbisImeColor color_button_symbol;
OrbisImeColor color_text;
OrbisImeColor color_special;
OrbisImePanelPriority priority;
char* additional_dictionary_path;
OrbisImeExtKeyboardFilter ext_keyboard_filter;
uint32_t disable_device;
uint32_t ext_keyboard_mode;
int8_t reserved[60];
};
Error PS4_SYSV_ABI sceImeDialogAbort();
Error PS4_SYSV_ABI sceImeDialogForceClose();
Error PS4_SYSV_ABI sceImeDialogForTestFunction();
@ -167,5 +47,5 @@ int PS4_SYSV_ABI sceImeDialogInitInternal3();
int PS4_SYSV_ABI sceImeDialogSetPanelPosition();
Error PS4_SYSV_ABI sceImeDialogTerm();
void RegisterlibSceImeDialog(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::ImeDialog

View File

@ -21,12 +21,16 @@ namespace Libraries::ImeDialog {
ImeDialogState::ImeDialogState(const OrbisImeDialogParam* param,
const OrbisImeParamExtended* extended) {
LOG_INFO(Lib_ImeDialog, ">> ImeDialogState::Ctor: param={}, text_buffer={}",
static_cast<const void*>(param),
static_cast<void*>(param ? param->input_text_buffer : nullptr));
if (!param) {
LOG_ERROR(Lib_ImeDialog, " param==nullptr, returning without init");
return;
}
user_id = param->user_id;
is_multi_line = True(param->option & OrbisImeDialogOption::Multiline);
is_multi_line = True(param->option & OrbisImeOption::MULTILINE);
is_numeric = param->type == OrbisImeType::Number;
type = param->type;
enter_label = param->enter_label;
@ -220,6 +224,7 @@ void ImeDialogUi::Free() {
void ImeDialogUi::Draw() {
std::unique_lock lock{draw_mutex};
LOG_INFO(Lib_ImeDialog, ">> ImeDialogUi::Draw: first_render=%d", first_render);
if (!state) {
return;
@ -259,9 +264,13 @@ void ImeDialogUi::Draw() {
}
if (state->is_multi_line) {
LOG_INFO(Lib_ImeDialog, " Drawing multi-line widget…");
DrawMultiLineInputText();
LOG_INFO(Lib_ImeDialog, " Done DrawMultiLineInputText");
} else {
LOG_INFO(Lib_ImeDialog, " Drawing input text widget…");
DrawInputText();
LOG_INFO(Lib_ImeDialog, " Done DrawInputText");
}
SetCursorPosY(GetCursorPosY() + 10.0f);
@ -306,6 +315,7 @@ void ImeDialogUi::Draw() {
End();
first_render = false;
LOG_INFO(Lib_ImeDialog, "<< ImeDialogUi::Draw complete");
}
void ImeDialogUi::DrawInputText() {
@ -316,7 +326,7 @@ void ImeDialogUi::DrawInputText() {
}
const char* placeholder = state->placeholder.empty() ? nullptr : state->placeholder.data();
if (InputTextEx("##ImeDialogInput", placeholder, state->current_text.begin(),
state->max_text_length, input_size, ImGuiInputTextFlags_CallbackCharFilter,
state->max_text_length + 1, input_size, ImGuiInputTextFlags_CallbackCharFilter,
InputTextCallback, this)) {
state->input_changed = true;
}
@ -332,7 +342,7 @@ void ImeDialogUi::DrawMultiLineInputText() {
}
const char* placeholder = state->placeholder.empty() ? nullptr : state->placeholder.data();
if (InputTextEx("##ImeDialogInput", placeholder, state->current_text.begin(),
state->max_text_length, input_size, flags, InputTextCallback, this)) {
state->max_text_length + 1, input_size, flags, InputTextCallback, this)) {
state->input_changed = true;
}
}
@ -341,13 +351,19 @@ int ImeDialogUi::InputTextCallback(ImGuiInputTextCallbackData* data) {
ImeDialogUi* ui = static_cast<ImeDialogUi*>(data->UserData);
ASSERT(ui);
LOG_DEBUG(Lib_ImeDialog, ">> InputTextCallback: EventFlag={}, EventChar={}", data->EventFlag,
data->EventChar);
// Should we filter punctuation?
if (ui->state->is_numeric && (data->EventChar < '0' || data->EventChar > '9') &&
data->EventChar != '\b' && data->EventChar != ',' && data->EventChar != '.') {
LOG_INFO(Lib_ImeDialog, "InputTextCallback: rejecting non-digit char '{}'",
static_cast<char>(data->EventChar));
return 1;
}
if (!ui->state->keyboard_filter) {
LOG_DEBUG(Lib_ImeDialog, "InputTextCallback: no keyboard_filter, accepting char");
return 0;
}
@ -363,20 +379,24 @@ int ImeDialogUi::InputTextCallback(ImGuiInputTextCallbackData* data) {
// the current language?)
.user_id = ui->state->user_id,
.resource_id = 0,
.timestamp = 0,
.timestamp = {0},
};
if (!ui->state->ConvertUTF8ToOrbis(event_char, 4, &src_keycode.character, 1)) {
LOG_ERROR(Lib_ImeDialog, "Failed to convert orbis char to utf8");
LOG_ERROR(Lib_ImeDialog, "InputTextCallback: ConvertUTF8ToOrbis failed");
return 0;
}
LOG_DEBUG(Lib_ImeDialog, "InputTextCallback: converted to Orbis char={:#X}",
static_cast<uint16_t>(src_keycode.character));
src_keycode.keycode = src_keycode.character; // TODO set this to the correct value
u16 out_keycode;
u32 out_status;
ui->state->CallKeyboardFilter(&src_keycode, &out_keycode, &out_status);
bool keep = ui->state->CallKeyboardFilter(&src_keycode, &out_keycode, &out_status);
LOG_DEBUG(Lib_ImeDialog,
"InputTextCallback: CallKeyboardFilter returned %s (keycode=0x%X, status=0x%X)",
keep ? "true" : "false", out_keycode, out_status);
// TODO. set the keycode
return 0;

View File

@ -44,7 +44,7 @@ ImeState& ImeState::operator=(ImeState&& other) noexcept {
}
void ImeState::SendEvent(OrbisImeEvent* event) {
std::unique_lock lock{queue_mutex};
std::unique_lock<std::mutex> lock{queue_mutex};
event_queue.push(*event);
}
@ -108,7 +108,7 @@ ImeUi& ImeUi::operator=(ImeUi&& other) {
}
void ImeUi::Draw() {
std::unique_lock lock{draw_mutex};
std::unique_lock<std::mutex> lock{draw_mutex};
if (!state) {
return;
@ -199,7 +199,7 @@ int ImeUi::InputTextCallback(ImGuiInputTextCallbackData* data) {
eventParam.caret_index = data->CursorPos;
eventParam.area_num = 1;
eventParam.text_area[0].mode = 1; // Edit mode
eventParam.text_area[0].mode = OrbisImeTextAreaMode::Edit;
eventParam.text_area[0].index = data->CursorPos;
eventParam.text_area[0].length = data->BufTextLen;

View File

@ -197,7 +197,7 @@ s32 PS4_SYSV_ABI sceJpegEncQueryMemorySize(const OrbisJpegEncCreateParam* param)
return ORBIS_JPEG_ENC_MINIMUM_MEMORY_SIZE;
}
void RegisterlibSceJpegEnc(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("K+rocojkr-I", "libSceJpegEnc", 1, "libSceJpegEnc", 1, 1, sceJpegEncCreate);
LIB_FUNCTION("j1LyMdaM+C0", "libSceJpegEnc", 1, "libSceJpegEnc", 1, 1, sceJpegEncDelete);
LIB_FUNCTION("QbrU0cUghEM", "libSceJpegEnc", 1, "libSceJpegEnc", 1, 1, sceJpegEncEncode);

View File

@ -80,5 +80,5 @@ s32 PS4_SYSV_ABI sceJpegEncEncode(OrbisJpegEncHandle handle, const OrbisJpegEncE
OrbisJpegEncOutputInfo* output_info);
s32 PS4_SYSV_ABI sceJpegEncQueryMemorySize(const OrbisJpegEncCreateParam* param);
void RegisterlibSceJpegEnc(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::JpegEnc

View File

@ -118,6 +118,7 @@ s32 PS4_SYSV_ABI open(const char* raw_path, s32 flags, u16 mode) {
return -1;
}
if (!exists) {
if (read_only) {
// Can't create files in a read only directory
h->DeleteHandle(handle);
@ -126,6 +127,7 @@ s32 PS4_SYSV_ABI open(const char* raw_path, s32 flags, u16 mode) {
}
// Create a file if it doesn't exist
Common::FS::IOFile out(file->m_host_name, Common::FS::FileAccessMode::Write);
}
} else if (!exists) {
// If we're not creating a file, and it doesn't exist, return ENOENT
h->DeleteHandle(handle);
@ -1091,6 +1093,8 @@ void RegisterFileSystem(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("kBwCPsYX-m4", "libkernel", 1, "libkernel", 1, 1, sceKernelFstat);
LIB_FUNCTION("ih4CD9-gghM", "libkernel", 1, "libkernel", 1, 1, posix_ftruncate);
LIB_FUNCTION("VW3TVZiM4-E", "libkernel", 1, "libkernel", 1, 1, sceKernelFtruncate);
LIB_FUNCTION("NN01qLRhiqU", "libScePosix", 1, "libkernel", 1, 1, posix_rename);
LIB_FUNCTION("NN01qLRhiqU", "libkernel", 1, "libkernel", 1, 1, posix_rename);
LIB_FUNCTION("52NcYU9+lEo", "libkernel", 1, "libkernel", 1, 1, sceKernelRename);
LIB_FUNCTION("yTj62I7kw4s", "libkernel", 1, "libkernel", 1, 1, sceKernelPreadv);
LIB_FUNCTION("ezv-RSBNKqI", "libScePosix", 1, "libkernel", 1, 1, posix_pread);

View File

@ -6,6 +6,7 @@
#include "common/assert.h"
#include "common/debug.h"
#include "common/elf_info.h"
#include "common/logging/log.h"
#include "common/polyfill_thread.h"
#include "common/thread.h"
@ -90,6 +91,13 @@ s32 ErrnoToSceKernelError(s32 error) {
return error + ORBIS_KERNEL_ERROR_UNKNOWN;
}
s32 PS4_SYSV_ABI sceKernelError(s32 posix_error) {
if (posix_error == 0) {
return 0;
}
return posix_error + ORBIS_KERNEL_ERROR_UNKNOWN;
}
void SetPosixErrno(s32 e) {
// Some error numbers are different between supported OSes
switch (e) {
@ -243,7 +251,20 @@ s32 PS4_SYSV_ABI sceKernelSetGPO() {
return ORBIS_OK;
}
void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
s32 PS4_SYSV_ABI sceKernelGetSystemSwVersion(SwVersionStruct* ret) {
if (ret == nullptr) {
return ORBIS_OK; // but why?
}
ASSERT(ret->struct_size == 40);
u32 fake_fw = Common::ElfInfo::Instance().RawFirmwareVer();
ret->hex_representation = fake_fw;
std::snprintf(ret->text_representation, 28, "%2x.%03x.%03x", fake_fw >> 0x18,
fake_fw >> 0xc & 0xfff, fake_fw & 0xfff); // why %2x?
LOG_INFO(Lib_Kernel, "called, returned sw version: {}", ret->text_representation);
return ORBIS_OK;
}
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
service_thread = std::jthread{KernelServiceThread};
Libraries::Kernel::RegisterFileSystem(sym);
@ -258,6 +279,8 @@ void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
Libraries::Kernel::RegisterDebug(sym);
LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard);
LIB_FUNCTION("D4yla3vx4tY", "libkernel", 1, "libkernel", 1, 1, sceKernelError);
LIB_FUNCTION("Mv1zUObHvXI", "libkernel", 1, "libkernel", 1, 1, sceKernelGetSystemSwVersion);
LIB_FUNCTION("PfccT7qURYE", "libkernel", 1, "libkernel", 1, 1, kernel_ioctl);
LIB_FUNCTION("JGfTMBOdUJo", "libkernel", 1, "libkernel", 1, 1, sceKernelGetFsSandboxRandomWord);
LIB_FUNCTION("6xVpy0Fdq+I", "libkernel", 1, "libkernel", 1, 1, _sigprocmask);

View File

@ -35,6 +35,12 @@ struct OrbisWrapperImpl<PS4_SYSV_ABI R (*)(Args...), f> {
s32* PS4_SYSV_ABI __Error();
void RegisterKernel(Core::Loader::SymbolsResolver* sym);
struct SwVersionStruct {
u64 struct_size;
char text_representation[0x1c];
u32 hex_representation;
};
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Kernel

View File

@ -573,11 +573,12 @@ void* PS4_SYSV_ABI posix_mmap(void* addr, u64 len, s32 prot, s32 flags, s32 fd,
auto* memory = Core::Memory::Instance();
const auto mem_prot = static_cast<Core::MemoryProt>(prot);
const auto mem_flags = static_cast<Core::MemoryMapFlags>(flags);
const auto is_exec = True(mem_prot & Core::MemoryProt::CpuExec);
s32 result = ORBIS_OK;
if (fd == -1) {
result = memory->MapMemory(&addr_out, std::bit_cast<VAddr>(addr), len, mem_prot, mem_flags,
Core::VMAType::Flexible);
Core::VMAType::Flexible, "anon", is_exec);
} else {
result = memory->MapFile(&addr_out, std::bit_cast<VAddr>(addr), len, mem_prot, mem_flags,
fd, phys_addr);
@ -711,6 +712,7 @@ void RegisterMemory(Core::Loader::SymbolsResolver* sym) {
sceKernelConfiguredFlexibleMemorySize);
LIB_FUNCTION("vSMAm3cxYTY", "libkernel", 1, "libkernel", 1, 1, sceKernelMprotect);
LIB_FUNCTION("YQOfxL4QfeU", "libkernel", 1, "libkernel", 1, 1, posix_mprotect);
LIB_FUNCTION("YQOfxL4QfeU", "libScePosix", 1, "libkernel", 1, 1, posix_mprotect);
LIB_FUNCTION("9bfdLIyuwCY", "libkernel", 1, "libkernel", 1, 1, sceKernelMtypeprotect);

View File

@ -261,7 +261,7 @@ s32 PS4_SYSV_ABI scePngDecQueryMemorySize(const OrbisPngDecCreateParam* param) {
return sizeof(PngHandler);
}
void RegisterlibScePngDec(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("m0uW+8pFyaw", "libScePngDec", 1, "libScePngDec", 1, 1, scePngDecCreate);
LIB_FUNCTION("WC216DD3El4", "libScePngDec", 1, "libScePngDec", 1, 1, scePngDecDecode);
LIB_FUNCTION("cJ--1xAbj-I", "libScePngDec", 1, "libScePngDec", 1, 1,

View File

@ -79,5 +79,5 @@ s32 PS4_SYSV_ABI scePngDecParseHeader(const OrbisPngDecParseParam* param,
OrbisPngDecImageInfo* imageInfo);
s32 PS4_SYSV_ABI scePngDecQueryMemorySize(const OrbisPngDecCreateParam* param);
void RegisterlibScePngDec(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::PngDec

View File

@ -70,66 +70,66 @@ namespace Libraries {
void InitHLELibs(Core::Loader::SymbolsResolver* sym) {
LOG_INFO(Lib_Kernel, "Initializing HLE libraries");
Libraries::Kernel::RegisterKernel(sym);
Libraries::GnmDriver::RegisterlibSceGnmDriver(sym);
Libraries::Kernel::RegisterLib(sym);
Libraries::GnmDriver::RegisterLib(sym);
Libraries::VideoOut::RegisterLib(sym);
Libraries::UserService::RegisterlibSceUserService(sym);
Libraries::SystemService::RegisterlibSceSystemService(sym);
Libraries::CommonDialog::RegisterlibSceCommonDialog(sym);
Libraries::MsgDialog::RegisterlibSceMsgDialog(sym);
Libraries::AudioOut::RegisterlibSceAudioOut(sym);
Libraries::Http::RegisterlibSceHttp(sym);
Libraries::Http2::RegisterlibSceHttp2(sym);
Libraries::Net::RegisterlibSceNet(sym);
Libraries::NetCtl::RegisterlibSceNetCtl(sym);
Libraries::SaveData::RegisterlibSceSaveData(sym);
Libraries::SaveData::Dialog::RegisterlibSceSaveDataDialog(sym);
Libraries::Ssl::RegisterlibSceSsl(sym);
Libraries::Ssl2::RegisterlibSceSsl2(sym);
Libraries::SysModule::RegisterlibSceSysmodule(sym);
Libraries::Posix::Registerlibsceposix(sym);
Libraries::AudioIn::RegisterlibSceAudioIn(sym);
Libraries::NpCommon::RegisterlibSceNpCommon(sym);
Libraries::NpManager::RegisterlibSceNpManager(sym);
Libraries::NpScore::RegisterlibSceNpScore(sym);
Libraries::NpTrophy::RegisterlibSceNpTrophy(sym);
Libraries::NpWebApi::RegisterlibSceNpWebApi(sym);
Libraries::NpAuth::RegisterlibSceNpAuth(sym);
Libraries::ScreenShot::RegisterlibSceScreenShot(sym);
Libraries::AppContent::RegisterlibSceAppContent(sym);
Libraries::PngDec::RegisterlibScePngDec(sym);
Libraries::PlayGo::RegisterlibScePlayGo(sym);
Libraries::PlayGo::Dialog::RegisterlibScePlayGoDialog(sym);
Libraries::Random::RegisterlibSceRandom(sym);
Libraries::Usbd::RegisterlibSceUsbd(sym);
Libraries::Pad::RegisterlibScePad(sym);
Libraries::Ajm::RegisterlibSceAjm(sym);
Libraries::ErrorDialog::RegisterlibSceErrorDialog(sym);
Libraries::ImeDialog::RegisterlibSceImeDialog(sym);
Libraries::AvPlayer::RegisterlibSceAvPlayer(sym);
Libraries::Vdec2::RegisterlibSceVdec2(sym);
Libraries::Audio3d::RegisterlibSceAudio3d(sym);
Libraries::Ime::RegisterlibSceIme(sym);
Libraries::GameLiveStreaming::RegisterlibSceGameLiveStreaming(sym);
Libraries::SharePlay::RegisterlibSceSharePlay(sym);
Libraries::Remoteplay::RegisterlibSceRemoteplay(sym);
Libraries::Videodec::RegisterlibSceVideodec(sym);
Libraries::RazorCpu::RegisterlibSceRazorCpu(sym);
Libraries::Move::RegisterlibSceMove(sym);
Libraries::Fiber::RegisterlibSceFiber(sym);
Libraries::JpegEnc::RegisterlibSceJpegEnc(sym);
Libraries::Mouse::RegisterlibSceMouse(sym);
Libraries::WebBrowserDialog::RegisterlibSceWebBrowserDialog(sym);
Libraries::NpParty::RegisterlibSceNpParty(sym);
Libraries::Zlib::RegisterlibSceZlib(sym);
Libraries::Hmd::RegisterlibSceHmd(sym);
Libraries::DiscMap::RegisterlibSceDiscMap(sym);
Libraries::Ulobjmgr::RegisterlibSceUlobjmgr(sym);
Libraries::SigninDialog::RegisterlibSceSigninDialog(sym);
Libraries::Camera::RegisterlibSceCamera(sym);
Libraries::CompanionHttpd::RegisterlibSceCompanionHttpd(sym);
Libraries::CompanionUtil::RegisterlibSceCompanionUtil(sym);
Libraries::Voice::RegisterlibSceVoice(sym);
Libraries::UserService::RegisterLib(sym);
Libraries::SystemService::RegisterLib(sym);
Libraries::CommonDialog::RegisterLib(sym);
Libraries::MsgDialog::RegisterLib(sym);
Libraries::AudioOut::RegisterLib(sym);
Libraries::Http::RegisterLib(sym);
Libraries::Http2::RegisterLib(sym);
Libraries::Net::RegisterLib(sym);
Libraries::NetCtl::RegisterLib(sym);
Libraries::SaveData::RegisterLib(sym);
Libraries::SaveData::Dialog::RegisterLib(sym);
Libraries::Ssl::RegisterLib(sym);
Libraries::Ssl2::RegisterLib(sym);
Libraries::SysModule::RegisterLib(sym);
Libraries::Posix::RegisterLib(sym);
Libraries::AudioIn::RegisterLib(sym);
Libraries::NpCommon::RegisterLib(sym);
Libraries::NpManager::RegisterLib(sym);
Libraries::NpScore::RegisterLib(sym);
Libraries::NpTrophy::RegisterLib(sym);
Libraries::NpWebApi::RegisterLib(sym);
Libraries::NpAuth::RegisterLib(sym);
Libraries::ScreenShot::RegisterLib(sym);
Libraries::AppContent::RegisterLib(sym);
Libraries::PngDec::RegisterLib(sym);
Libraries::PlayGo::RegisterLib(sym);
Libraries::PlayGo::Dialog::RegisterLib(sym);
Libraries::Random::RegisterLib(sym);
Libraries::Usbd::RegisterLib(sym);
Libraries::Pad::RegisterLib(sym);
Libraries::Ajm::RegisterLib(sym);
Libraries::ErrorDialog::RegisterLib(sym);
Libraries::ImeDialog::RegisterLib(sym);
Libraries::AvPlayer::RegisterLib(sym);
Libraries::Vdec2::RegisterLib(sym);
Libraries::Audio3d::RegisterLib(sym);
Libraries::Ime::RegisterLib(sym);
Libraries::GameLiveStreaming::RegisterLib(sym);
Libraries::SharePlay::RegisterLib(sym);
Libraries::Remoteplay::RegisterLib(sym);
Libraries::Videodec::RegisterLib(sym);
Libraries::RazorCpu::RegisterLib(sym);
Libraries::Move::RegisterLib(sym);
Libraries::Fiber::RegisterLib(sym);
Libraries::JpegEnc::RegisterLib(sym);
Libraries::Mouse::RegisterLib(sym);
Libraries::WebBrowserDialog::RegisterLib(sym);
Libraries::NpParty::RegisterLib(sym);
Libraries::Zlib::RegisterLib(sym);
Libraries::Hmd::RegisterLib(sym);
Libraries::DiscMap::RegisterLib(sym);
Libraries::Ulobjmgr::RegisterLib(sym);
Libraries::SigninDialog::RegisterLib(sym);
Libraries::Camera::RegisterLib(sym);
Libraries::CompanionHttpd::RegisterLib(sym);
Libraries::CompanionUtil::RegisterLib(sym);
Libraries::Voice::RegisterLib(sym);
}
} // namespace Libraries

View File

@ -79,7 +79,7 @@ int PS4_SYSV_ABI sceMouseSetProcessPrivilege() {
return ORBIS_OK;
}
void RegisterlibSceMouse(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("cAnT0Rw-IwU", "libSceMouse", 1, "libSceMouse", 1, 1, sceMouseClose);
LIB_FUNCTION("Ymyy1HSSJLQ", "libSceMouse", 1, "libSceMouse", 1, 1, sceMouseConnectPort);
LIB_FUNCTION("BRXOoXQtb+k", "libSceMouse", 1, "libSceMouse", 1, 1, sceMouseDebugGetDeviceId);

View File

@ -25,5 +25,5 @@ int PS4_SYSV_ABI sceMouseSetHandType();
int PS4_SYSV_ABI sceMouseSetPointerSpeed();
int PS4_SYSV_ABI sceMouseSetProcessPrivilege();
void RegisterlibSceMouse(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Mouse

View File

@ -38,7 +38,7 @@ int PS4_SYSV_ABI sceMoveInit() {
return ORBIS_OK;
}
void RegisterlibSceMove(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("HzC60MfjJxU", "libSceMove", 1, "libSceMove", 1, 1, sceMoveOpen);
LIB_FUNCTION("GWXTyxs4QbE", "libSceMove", 1, "libSceMove", 1, 1, sceMoveGetDeviceInfo);
LIB_FUNCTION("ttU+JOhShl4", "libSceMove", 1, "libSceMove", 1, 1, sceMoveReadStateLatest);

View File

@ -17,5 +17,5 @@ int PS4_SYSV_ABI sceMoveReadStateRecent();
int PS4_SYSV_ABI sceMoveTerm();
int PS4_SYSV_ABI sceMoveInit();
void RegisterlibSceMove(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Move

View File

@ -186,7 +186,7 @@ int PS4_SYSV_ABI sceHttpGetAcceptEncodingGZIPEnabled() {
int PS4_SYSV_ABI sceHttpGetAllResponseHeaders() {
LOG_ERROR(Lib_Http, "(STUBBED) called");
return ORBIS_OK;
return ORBIS_FAIL;
}
int PS4_SYSV_ABI sceHttpGetAuthEnabled() {
@ -492,8 +492,9 @@ int PS4_SYSV_ABI sceHttpsFreeCaList() {
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttpsGetCaList() {
LOG_ERROR(Lib_Http, "(STUBBED) called");
int PS4_SYSV_ABI sceHttpsGetCaList(int httpCtxId, OrbisHttpsCaList* list) {
LOG_ERROR(Lib_Http, "(DUMMY) called, httpCtxId = {}", httpCtxId);
list->certsNum = 0;
return ORBIS_OK;
}
@ -847,7 +848,7 @@ int PS4_SYSV_ABI sceHttpWaitRequest() {
return ORBIS_OK;
}
void RegisterlibSceHttp(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("hvG6GfBMXg8", "libSceHttp", 1, "libSceHttp", 1, 1, sceHttpAbortRequest);
LIB_FUNCTION("JKl06ZIAl6A", "libSceHttp", 1, "libSceHttp", 1, 1, sceHttpAbortRequestForce);
LIB_FUNCTION("sWQiqKvYTVA", "libSceHttp", 1, "libSceHttp", 1, 1, sceHttpAbortWaitRequest);

View File

@ -4,6 +4,7 @@
#pragma once
#include "common/types.h"
#include "core/libraries/network/ssl.h"
namespace Core::Loader {
class SymbolsResolver;
@ -24,6 +25,8 @@ struct OrbisHttpUriElement {
u8 reserved[10];
};
using OrbisHttpsCaList = Libraries::Ssl::OrbisSslCaList;
int PS4_SYSV_ABI sceHttpAbortRequest();
int PS4_SYSV_ABI sceHttpAbortRequestForce();
int PS4_SYSV_ABI sceHttpAbortWaitRequest();
@ -120,7 +123,7 @@ int PS4_SYSV_ABI sceHttpSetResponseHeaderMaxSize();
int PS4_SYSV_ABI sceHttpSetSendTimeOut();
int PS4_SYSV_ABI sceHttpSetSocketCreationCallback();
int PS4_SYSV_ABI sceHttpsFreeCaList();
int PS4_SYSV_ABI sceHttpsGetCaList();
int PS4_SYSV_ABI sceHttpsGetCaList(int httpCtxId, OrbisHttpsCaList* list);
int PS4_SYSV_ABI sceHttpsGetSslError();
int PS4_SYSV_ABI sceHttpsLoadCert();
int PS4_SYSV_ABI sceHttpsSetMinSslVersion();
@ -141,5 +144,5 @@ int PS4_SYSV_ABI sceHttpUriSweepPath(char* dst, const char* src, size_t srcSize)
int PS4_SYSV_ABI sceHttpUriUnescape(char* out, size_t* require, size_t prepare, const char* in);
int PS4_SYSV_ABI sceHttpWaitRequest();
void RegisterlibSceHttp(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Http

View File

@ -289,7 +289,7 @@ int PS4_SYSV_ABI sceHttp2WaitAsync() {
return ORBIS_OK;
}
void RegisterlibSceHttp2(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("AS45QoYHjc4", "libSceHttp2", 1, "libSceHttp2", 1, 1, _Z5dummyv);
LIB_FUNCTION("IZ-qjhRqvjk", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2AbortRequest);
LIB_FUNCTION("flPxnowtvWY", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2AddCookie);

View File

@ -68,5 +68,5 @@ int PS4_SYSV_ABI sceHttp2SslEnableOption();
int PS4_SYSV_ABI sceHttp2Term();
int PS4_SYSV_ABI sceHttp2WaitAsync();
void RegisterlibSceHttp2(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Http2

View File

@ -1942,7 +1942,7 @@ int PS4_SYSV_ABI sceNetEmulationSet() {
return ORBIS_OK;
}
void RegisterlibSceNet(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("ZRAJo-A-ukc", "libSceNet", 1, "libSceNet", 1, 1, in6addr_any);
LIB_FUNCTION("XCuA-GqjA-k", "libSceNet", 1, "libSceNet", 1, 1, in6addr_loopback);
LIB_FUNCTION("VZgoeBxPXUQ", "libSceNet", 1, "libSceNet", 1, 1, sce_net_dummy);

View File

@ -336,5 +336,5 @@ int PS4_SYSV_ABI Func_0E707A589F751C68();
int PS4_SYSV_ABI sceNetEmulationGet();
int PS4_SYSV_ABI sceNetEmulationSet();
void RegisterlibSceNet(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Net

View File

@ -2,6 +2,8 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
#include "common/config.h"
#include "common/logging/log.h"
#include "core/libraries/network/net_ctl_codes.h"
#include "core/libraries/network/net_ctl_obj.h"
#include "core/tls.h"
@ -44,18 +46,22 @@ s32 NetCtlInternal::RegisterNpToolkitCallback(OrbisNetCtlCallbackForNpToolkit fu
void NetCtlInternal::CheckCallback() {
std::scoped_lock lock{m_mutex};
const auto event = Config::getIsConnectedToNetwork() ? ORBIS_NET_CTL_EVENT_TYPE_IPOBTAINED
: ORBIS_NET_CTL_EVENT_TYPE_DISCONNECTED;
for (const auto [func, arg] : callbacks) {
if (func != nullptr) {
Core::ExecuteGuest(func, ORBIS_NET_CTL_EVENT_TYPE_DISCONNECTED, arg);
Core::ExecuteGuest(func, event, arg);
}
}
}
void NetCtlInternal::CheckNpToolkitCallback() {
std::scoped_lock lock{m_mutex};
const auto event = Config::getIsConnectedToNetwork() ? ORBIS_NET_CTL_EVENT_TYPE_IPOBTAINED
: ORBIS_NET_CTL_EVENT_TYPE_DISCONNECTED;
for (const auto [func, arg] : nptool_callbacks) {
if (func != nullptr) {
Core::ExecuteGuest(func, ORBIS_NET_CTL_EVENT_TYPE_DISCONNECTED, arg);
Core::ExecuteGuest(func, event, arg);
}
}
}

View File

@ -13,6 +13,7 @@
#endif
#include <common/singleton.h>
#include "common/config.h"
#include "common/logging/log.h"
#include "core/libraries/error_codes.h"
#include "core/libraries/libs.h"
@ -160,6 +161,8 @@ int PS4_SYSV_ABI sceNetCtlGetIfStat() {
}
int PS4_SYSV_ABI sceNetCtlGetInfo(int code, OrbisNetCtlInfo* info) {
LOG_DEBUG(Lib_NetCtl, "code = {}", code);
switch (code) {
case ORBIS_NET_CTL_INFO_DEVICE:
info->device = ORBIS_NET_CTL_DEVICE_WIRED;
@ -173,7 +176,8 @@ int PS4_SYSV_ABI sceNetCtlGetInfo(int code, OrbisNetCtlInfo* info) {
info->mtu = 1500; // default value
break;
case ORBIS_NET_CTL_INFO_LINK:
info->link = ORBIS_NET_CTL_LINK_DISCONNECTED;
info->link = Config::getIsConnectedToNetwork() ? ORBIS_NET_CTL_LINK_CONNECTED
: ORBIS_NET_CTL_LINK_DISCONNECTED;
break;
case ORBIS_NET_CTL_INFO_IP_ADDRESS: {
strcpy(info->ip_address,
@ -271,7 +275,11 @@ int PS4_SYSV_ABI sceNetCtlGetScanInfoForSsidScanIpcInt() {
}
int PS4_SYSV_ABI sceNetCtlGetState(int* state) {
*state = ORBIS_NET_CTL_STATE_DISCONNECTED;
const auto connected = Config::getIsConnectedToNetwork();
LOG_DEBUG(Lib_NetCtl, "connected = {}", connected);
const auto current_state =
connected ? ORBIS_NET_CTL_STATE_IPOBTAINED : ORBIS_NET_CTL_STATE_DISCONNECTED;
*state = current_state;
return ORBIS_OK;
}
@ -547,7 +555,7 @@ int PS4_SYSV_ABI sceNetCtlApRpUnregisterCallback() {
return ORBIS_OK;
}
void RegisterlibSceNetCtl(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("XtClSOC1xcU", "libSceNetBwe", 1, "libSceNetCtl", 1, 1,
sceNetBweCheckCallbackIpcInt);
LIB_FUNCTION("YALqoY4aeY0", "libSceNetBwe", 1, "libSceNetCtl", 1, 1, sceNetBweClearEventIpcInt);

View File

@ -165,5 +165,5 @@ int PS4_SYSV_ABI sceNetCtlApRpStartWithRetry();
int PS4_SYSV_ABI sceNetCtlApRpStop();
int PS4_SYSV_ABI sceNetCtlApRpUnregisterCallback();
void RegisterlibSceNetCtl(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::NetCtl

View File

@ -257,13 +257,14 @@ int PosixSocket::SetSocketOptions(int level, int optname, const void* optval, u3
CASE_SETSOCKOPT(SO_RCVTIMEO);
CASE_SETSOCKOPT(SO_ERROR);
CASE_SETSOCKOPT(SO_TYPE);
CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_CONNECTTIMEO, &sockopt_so_connecttimeo);
CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_REUSEPORT, &sockopt_so_reuseport);
CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_ONESBCAST, &sockopt_so_onesbcast);
CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_USECRYPTO, &sockopt_so_usecrypto);
CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_USESIGNATURE, &sockopt_so_usesignature);
case ORBIS_NET_SO_LINGER: {
if (socket_type != ORBIS_NET_SOCK_STREAM) {
return ORBIS_NET_EPROCUNAVAIL;
return ORBIS_NET_ERROR_EPROCUNAVAIL;
}
if (optlen < sizeof(OrbisNetLinger)) {
LOG_ERROR(Lib_Net, "size missmatched! optlen = {} OrbisNetLinger={}", optlen,
@ -309,7 +310,7 @@ int PosixSocket::SetSocketOptions(int level, int optname, const void* optval, u3
CASE_SETSOCKOPT_VALUE(ORBIS_NET_IP_MAXTTL, &sockopt_ip_maxttl);
case ORBIS_NET_IP_HDRINCL: {
if (socket_type != ORBIS_NET_SOCK_RAW) {
return ORBIS_NET_EPROCUNAVAIL;
return ORBIS_NET_ERROR_EPROCUNAVAIL;
}
return ConvertReturnErrorCode(
setsockopt(sock, level, optname, (const char*)optval, optlen));
@ -361,6 +362,7 @@ int PosixSocket::GetSocketOptions(int level, int optname, void* optval, u32* opt
CASE_GETSOCKOPT(SO_ERROR);
CASE_GETSOCKOPT(SO_TYPE);
CASE_GETSOCKOPT_VALUE(ORBIS_NET_SO_NBIO, sockopt_so_nbio);
CASE_GETSOCKOPT_VALUE(ORBIS_NET_SO_CONNECTTIMEO, sockopt_so_connecttimeo);
CASE_GETSOCKOPT_VALUE(ORBIS_NET_SO_REUSEPORT, sockopt_so_reuseport);
CASE_GETSOCKOPT_VALUE(ORBIS_NET_SO_ONESBCAST, sockopt_so_onesbcast);
CASE_GETSOCKOPT_VALUE(ORBIS_NET_SO_USECRYPTO, sockopt_so_usecrypto);

View File

@ -56,6 +56,7 @@ struct Socket {
struct PosixSocket : public Socket {
net_socket sock;
int sockopt_so_connecttimeo = 0;
int sockopt_so_reuseport = 0;
int sockopt_so_onesbcast = 0;
int sockopt_so_usecrypto = 0;

View File

@ -633,8 +633,17 @@ int PS4_SYSV_ABI sceSslFreeSslCertName() {
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslGetCaCerts() {
struct OrbisSslCaCerts {
void* certs;
u64 num;
void* pool;
};
int PS4_SYSV_ABI sceSslGetCaCerts(int sslCtxId, OrbisSslCaCerts* certs) {
LOG_ERROR(Lib_Ssl, "(STUBBED) called");
certs->certs = nullptr;
certs->num = 0;
certs->pool = nullptr;
return ORBIS_OK;
}
@ -1050,7 +1059,7 @@ int PS4_SYSV_ABI Func_28F8791A771D39C7() {
return ORBIS_OK;
}
void RegisterlibSceSsl(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("Pgt0gg14ewU", "libSceSsl", 1, "libSceSsl", 1, 1,
CA_MGMT_allocCertDistinguishedName);
LIB_FUNCTION("wJ5jCpkCv-c", "libSceSsl", 1, "libSceSsl", 1, 1,

View File

@ -11,6 +11,13 @@ class SymbolsResolver;
namespace Libraries::Ssl {
struct OrbisSslCaCerts;
struct OrbisSslCaList {
void* certs;
int certsNum;
};
int PS4_SYSV_ABI CA_MGMT_allocCertDistinguishedName();
int PS4_SYSV_ABI CA_MGMT_certDistinguishedNameCompare();
int PS4_SYSV_ABI CA_MGMT_convertKeyBlobToPKCS8Key();
@ -136,7 +143,7 @@ int PS4_SYSV_ABI sceSslEnableOptionInternal();
int PS4_SYSV_ABI sceSslFreeCaCerts();
int PS4_SYSV_ABI sceSslFreeCaList();
int PS4_SYSV_ABI sceSslFreeSslCertName();
int PS4_SYSV_ABI sceSslGetCaCerts();
int PS4_SYSV_ABI sceSslGetCaCerts(int sslCtxId, OrbisSslCaCerts* certs);
int PS4_SYSV_ABI sceSslGetCaList();
int PS4_SYSV_ABI sceSslGetIssuerName();
int PS4_SYSV_ABI sceSslGetMemoryPoolStats();
@ -220,5 +227,5 @@ int PS4_SYSV_ABI VLONG_freeVlongQueue();
int PS4_SYSV_ABI Func_22E76E60BC0587D7();
int PS4_SYSV_ABI Func_28F8791A771D39C7();
void RegisterlibSceSsl(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Ssl

View File

@ -128,8 +128,18 @@ int PS4_SYSV_ABI sceSslGetAlpnSelected() {
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslGetCaCerts() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
struct OrbisSslCaCerts {
void* certs;
u64 num;
void* pool;
};
int PS4_SYSV_ABI sceSslGetCaCerts(int sslCtxId, OrbisSslCaCerts* certs) {
// check if it is same as libSceSsl
LOG_ERROR(Lib_Ssl2, "(DUMMY) called");
certs->certs = nullptr;
certs->num = 0;
certs->pool = nullptr;
return ORBIS_OK;
}
@ -290,7 +300,7 @@ int PS4_SYSV_ABI Func_28F8791A771D39C7() {
return ORBIS_OK;
}
void RegisterlibSceSsl2(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("Md+HYkCBZB4", "libSceSsl", 1, "libSceSsl", 2, 1, CA_MGMT_extractKeyBlobEx);
LIB_FUNCTION("9bKYzKP6kYU", "libSceSsl", 1, "libSceSsl", 2, 1, CA_MGMT_extractPublicKeyInfo);
LIB_FUNCTION("ipLIammTj2Q", "libSceSsl", 1, "libSceSsl", 2, 1, CA_MGMT_freeKeyBlob);

View File

@ -10,5 +10,5 @@ class SymbolsResolver;
}
namespace Libraries::Ssl2 {
void RegisterlibSceSsl2(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Ssl2

View File

@ -73,7 +73,7 @@ s32 PS4_SYSV_ABI sceNpAuthWaitAsync() {
return ORBIS_OK;
}
void RegisterlibSceNpAuth(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("KxGkOrQJTqY", "libSceNpAuthCompat", 1, "libSceNpAuth", 1, 1,
sceNpAuthGetAuthorizationCode);
LIB_FUNCTION("uaB-LoJqHis", "libSceNpAuthCompat", 1, "libSceNpAuth", 1, 1, sceNpAuthGetIdToken);

View File

@ -25,5 +25,5 @@ s32 PS4_SYSV_ABI sceNpAuthPollAsync();
s32 PS4_SYSV_ABI sceNpAuthSetTimeout();
s32 PS4_SYSV_ABI sceNpAuthWaitAsync();
void RegisterlibSceNpAuth(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::NpAuth

View File

@ -6129,7 +6129,7 @@ int PS4_SYSV_ABI Func_FFF4A3E279FB44A7() {
return ORBIS_OK;
}
void RegisterlibSceNpCommon(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("i8UmXTSq7N4", "libSceNpCommonCompat", 1, "libSceNpCommon", 1, 1, sceNpCmpNpId);
LIB_FUNCTION("TcwEFnakiSc", "libSceNpCommonCompat", 1, "libSceNpCommon", 1, 1,
sceNpCmpNpIdInOrder);

View File

@ -1241,5 +1241,5 @@ int PS4_SYSV_ABI Func_FE55EE32098D0D58();
int PS4_SYSV_ABI Func_FE79841022E1DA1C();
int PS4_SYSV_ABI Func_FFF4A3E279FB44A7();
void RegisterlibSceNpCommon(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::NpCommon

View File

@ -2563,7 +2563,7 @@ int PS4_SYSV_ABI sceNpUnregisterStateCallbackForToolkit() {
return ORBIS_OK;
}
void RegisterlibSceNpManager(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("70N4VzVCpQg", "libSceNpManagerForSys", 1, "libSceNpManager", 1, 1,
Func_EF4378573542A508);
LIB_FUNCTION("pHLjntY0psg", "libSceNpManager", 1, "libSceNpManager", 1, 1,

View File

@ -542,5 +542,5 @@ int PS4_SYSV_ABI sceNpRegisterStateCallbackForToolkit(OrbisNpStateCallbackForNpT
void* userdata);
int PS4_SYSV_ABI sceNpUnregisterStateCallbackForToolkit();
void RegisterlibSceNpManager(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::NpManager

View File

@ -138,7 +138,7 @@ s32 PS4_SYSV_ABI sceNpPartyUnregisterPrivateHandler() {
return ORBIS_OK;
}
void RegisterlibSceNpParty(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("3e4k2mzLkmc", "libSceNpParty", 1, "libSceNpParty", 1, 1, sceNpPartyCheckCallback);
LIB_FUNCTION("nOZRy-slBoA", "libSceNpParty", 1, "libSceNpParty", 1, 1, sceNpPartyCreate);
LIB_FUNCTION("XQSUbbnpPBA", "libSceNpParty", 1, "libSceNpParty", 1, 1, sceNpPartyCreateA);

View File

@ -40,5 +40,5 @@ s32 PS4_SYSV_ABI sceNpPartyUnregisterPrivateHandler();
s32 PS4_SYSV_ABI module_start();
s32 PS4_SYSV_ABI module_stop();
void RegisterlibSceNpParty(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::NpParty

View File

@ -263,7 +263,7 @@ int PS4_SYSV_ABI sceNpScoreWaitAsync() {
return ORBIS_OK;
}
void RegisterlibSceNpScore(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("1i7kmKbX6hk", "libSceNpScore", 1, "libSceNpScore", 1, 1, sceNpScoreAbortRequest);
LIB_FUNCTION("2b3TI0mDYiI", "libSceNpScore", 1, "libSceNpScore", 1, 1, sceNpScoreCensorComment);
LIB_FUNCTION("4eOvDyN-aZc", "libSceNpScore", 1, "libSceNpScore", 1, 1,

View File

@ -63,5 +63,5 @@ int PS4_SYSV_ABI sceNpScoreSetThreadParam();
int PS4_SYSV_ABI sceNpScoreSetTimeout();
int PS4_SYSV_ABI sceNpScoreWaitAsync();
void RegisterlibSceNpScore(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::NpScore

View File

@ -1023,7 +1023,7 @@ int PS4_SYSV_ABI Func_FA7A2DD770447552() {
return ORBIS_OK;
}
void RegisterlibSceNpTrophy(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("aTnHs7W-9Uk", "libSceNpTrophy", 1, "libSceNpTrophy", 1, 1,
sceNpTrophyAbortHandle);
LIB_FUNCTION("cqGkYAN-gRw", "libSceNpTrophy", 1, "libSceNpTrophy", 1, 1,

View File

@ -225,5 +225,5 @@ int PS4_SYSV_ABI Func_9F80071876FFA5F6();
int PS4_SYSV_ABI Func_F8EF6F5350A91990();
int PS4_SYSV_ABI Func_FA7A2DD770447552();
void RegisterlibSceNpTrophy(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::NpTrophy

View File

@ -5,8 +5,8 @@
#include <filesystem>
#include <fstream>
#include <mutex>
#include <SDL3/SDL_audio.h>
#include <cmrc/cmrc.hpp>
#include <common/path_util.h>
#include <imgui.h>
#ifdef ENABLE_QT_GUI
@ -15,6 +15,7 @@
#include "common/assert.h"
#include "common/config.h"
#include "common/path_util.h"
#include "common/singleton.h"
#include "imgui/imgui_std.h"
#include "trophy_ui.h"
@ -73,6 +74,7 @@ TrophyUI::TrophyUI(const std::filesystem::path& trophyIconPath, const std::strin
}
std::vector<u8> imgdata;
auto resource = cmrc::res::get_filesystem();
if (!customPath.empty()) {
std::ifstream file(customPath, std::ios::binary);
if (file) {
@ -82,7 +84,6 @@ TrophyUI::TrophyUI(const std::filesystem::path& trophyIconPath, const std::strin
LOG_ERROR(Lib_NpTrophy, "Could not open custom file for trophy in {}", customPath);
}
} else {
auto resource = cmrc::res::get_filesystem();
auto file = resource.open(pathString);
imgdata = std::vector<u8>(file.begin(), file.end());
}
@ -91,17 +92,56 @@ TrophyUI::TrophyUI(const std::filesystem::path& trophyIconPath, const std::strin
AddLayer(this);
bool customsoundplayed = false;
#ifdef ENABLE_QT_GUI
QString musicPathWav = QString::fromStdString(CustomTrophy_Dir.string() + "/trophy.wav");
QString musicPathMp3 = QString::fromStdString(CustomTrophy_Dir.string() + "/trophy.mp3");
if (fs::exists(musicPathWav.toStdString())) {
BackgroundMusicPlayer::getInstance().setVolume(100);
BackgroundMusicPlayer::getInstance().playMusic(musicPathWav, false);
customsoundplayed = true;
} else if (fs::exists(musicPathMp3.toStdString())) {
BackgroundMusicPlayer::getInstance().setVolume(100);
BackgroundMusicPlayer::getInstance().playMusic(musicPathMp3, false);
customsoundplayed = true;
}
#endif
if (!customsoundplayed) {
auto soundFile = resource.open("src/images/trophy.wav");
std::vector<u8> soundData = std::vector<u8>(soundFile.begin(), soundFile.end());
SDL_AudioSpec spec;
Uint8* audioBuf;
Uint32 audioLen;
if (!SDL_LoadWAV_IO(SDL_IOFromMem(soundData.data(), soundData.size()), true, &spec,
&audioBuf, &audioLen)) {
LOG_ERROR(Lib_NpTrophy, "Cannot load trophy sound: {}", SDL_GetError());
SDL_free(audioBuf);
return;
}
SDL_AudioStream* stream =
SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, nullptr, nullptr);
if (!stream) {
LOG_ERROR(Lib_NpTrophy, "Cannot create audio stream for trophy sound: {}",
SDL_GetError());
SDL_free(audioBuf);
return;
}
if (!SDL_PutAudioStreamData(stream, audioBuf, audioLen)) {
LOG_ERROR(Lib_NpTrophy, "Cannot add trophy sound data to stream: {}", SDL_GetError());
SDL_free(audioBuf);
return;
}
// Set audio gain 20% higher since audio file itself is soft
SDL_SetAudioStreamGain(stream, Config::getVolumeSlider() / 100.0f * 1.2f);
SDL_ResumeAudioStreamDevice(stream);
SDL_free(audioBuf);
}
}
TrophyUI::~TrophyUI() {

View File

@ -509,7 +509,7 @@ s32 PS4_SYSV_ABI Func_F9A32E8685627436() {
return ORBIS_OK;
}
void RegisterlibSceNpWebApi(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("x1Y7yiYSk7c", "libSceNpWebApiCompat", 1, "libSceNpWebApi", 1, 1,
sceNpWebApiCreateContext);
LIB_FUNCTION("y5Ta5JCzQHY", "libSceNpWebApiCompat", 1, "libSceNpWebApi", 1, 1,

View File

@ -112,5 +112,5 @@ s32 PS4_SYSV_ABI Func_E324765D18EE4D12();
s32 PS4_SYSV_ABI Func_E789F980D907B653();
s32 PS4_SYSV_ABI Func_F9A32E8685627436();
void RegisterlibSceNpWebApi(Core::Loader::SymbolsResolver* sym);
void RegisterLib(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::NpWebApi

View File

@ -761,7 +761,7 @@ int PS4_SYSV_ABI Func_EF103E845B6F0420() {
return ORBIS_OK;
}
void RegisterlibScePad(Core::Loader::SymbolsResolver* sym) {
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("6ncge5+l5Qs", "libScePad", 1, "libScePad", 1, 1, scePadClose);
LIB_FUNCTION("kazv1NzSB8c", "libScePad", 1, "libScePad", 1, 1, scePadConnectPort);
LIB_FUNCTION("AcslpN1jHR8", "libScePad", 1, "libScePad", 1, 1,

Some files were not shown because too many files have changed in this diff Show More