mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-04-20 19:44:46 +00:00
Merge branch 'main' of https://github.com/shadps4-emu/shadPS4 into missed
This commit is contained in:
commit
417d068016
21 changed files with 374 additions and 43 deletions
4
.gitmodules
vendored
4
.gitmodules
vendored
|
@ -51,10 +51,10 @@
|
|||
url = https://github.com/zyantific/zydis.git
|
||||
[submodule "externals/sirit"]
|
||||
path = externals/sirit
|
||||
url = https://github.com/raphaelthegreat/sirit
|
||||
url = https://github.com/raphaelthegreat/sirit.git
|
||||
[submodule "externals/xxhash"]
|
||||
path = externals/xxhash
|
||||
url = https://github.com/Cyan4973/xxHash.git
|
||||
[submodule "externals/tracy"]
|
||||
path = externals/tracy
|
||||
url = https://github.com/shadps4-emu/tracy
|
||||
url = https://github.com/shadps4-emu/tracy.git
|
||||
|
|
31
.reuse/dep5
31
.reuse/dep5
|
@ -3,17 +3,27 @@ Comment: It is best to use this file to record copyright information about
|
|||
generated, binary and third party files
|
||||
|
||||
Files: CMakeSettings.json
|
||||
scripts/ps4_names.txt
|
||||
documents/changelog.txt
|
||||
documents/readme.txt
|
||||
documents/Screenshots/screenshot.png
|
||||
.github/shadps4.desktop
|
||||
.github/shadps4.png
|
||||
.gitmodules
|
||||
src/images/shadps4.ico
|
||||
documents/changelog.txt
|
||||
documents/readme.txt
|
||||
documents/Screenshots/screenshot.png
|
||||
documents/Screenshots/Sonic Mania.png
|
||||
documents/Screenshots/Undertale.png
|
||||
documents/Screenshots/We are DOOMED.png
|
||||
externals/stb_image.h
|
||||
externals/tracy/*
|
||||
scripts/ps4_names.txt
|
||||
src/images/controller_icon.png
|
||||
src/images/exit_icon.png
|
||||
src/images/file_icon.png
|
||||
src/images/flag_china.png
|
||||
src/images/flag_eu.png
|
||||
src/images/flag_jp.png
|
||||
src/images/flag_unk.png
|
||||
src/images/flag_us.png
|
||||
src/images/flag_world.png
|
||||
src/images/folder_icon.png
|
||||
src/images/grid_icon.png
|
||||
src/images/iconsize_icon.png
|
||||
|
@ -24,16 +34,9 @@ Files: CMakeSettings.json
|
|||
src/images/refresh_icon.png
|
||||
src/images/settings_icon.png
|
||||
src/images/stop_icon.png
|
||||
src/images/shadps4.ico
|
||||
src/images/themes_icon.png
|
||||
src/images/flag_jp.png
|
||||
src/images/flag_eu.png
|
||||
src/images/flag_us.png
|
||||
src/images/flag_china.png
|
||||
src/images/flag_world.png
|
||||
src/images/flag_unk.png
|
||||
src/shadps4.rc
|
||||
src/shadps4.qrc
|
||||
externals/stb_image.h
|
||||
externals/tracy/*
|
||||
src/shadps4.rc
|
||||
Copyright: shadPS4 Emulator Project
|
||||
License: GPL-2.0-or-later
|
||||
|
|
|
@ -10,7 +10,7 @@ if (NOT CMAKE_BUILD_TYPE)
|
|||
set(CMAKE_BUILD_TYPE Release)
|
||||
endif()
|
||||
|
||||
project(shadps4)
|
||||
project(shadPS4)
|
||||
|
||||
option(ENABLE_QT_GUI "Enable the Qt GUI. If not selected then the emulator uses a minimal SDL-based UI instead" OFF)
|
||||
|
||||
|
@ -192,6 +192,10 @@ set(PAD_LIB src/core/libraries/pad/pad.cpp
|
|||
src/core/libraries/pad/pad.h
|
||||
)
|
||||
|
||||
set(PNG_LIB src/core/libraries/libpng/pngdec.cpp
|
||||
src/core/libraries/libpng/pngdec.h
|
||||
)
|
||||
|
||||
set(NP_LIBS src/core/libraries/np_manager/np_manager.cpp
|
||||
src/core/libraries/np_manager/np_manager.h
|
||||
src/core/libraries/np_score/np_score.cpp
|
||||
|
@ -292,6 +296,7 @@ set(CORE src/core/aerolib/stubs.cpp
|
|||
${PAD_LIB}
|
||||
${VIDEOOUT_LIB}
|
||||
${NP_LIBS}
|
||||
${PNG_LIB}
|
||||
${MISC_LIBS}
|
||||
src/core/linker.cpp
|
||||
src/core/linker.h
|
||||
|
|
16
README.md
16
README.md
|
@ -27,10 +27,18 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
|||
<a href="https://github.com/shadps4-emu/shadPS4/stargazers">
|
||||
<img src="https://img.shields.io/github/stars/shadps4-emu/shadPS4" width="120">
|
||||
|
||||
<h1 align="center">
|
||||
<br>
|
||||
<a href="https://shadps4.net/"><img src="https://github.com/shadps4-emu/shadPS4/blob/main/documents/Screenshots/screenshot.png" width="550"></a>
|
||||
<br>
|
||||
<p align="center">
|
||||
<a href="https://shadps4.net/">
|
||||
<img src="https://github.com/shadps4-emu/shadPS4/blob/main/documents/Screenshots/Sonic Mania.png" width="500">
|
||||
|
||||
<a href="https://shadps4.net/">
|
||||
<img src="https://github.com/shadps4-emu/shadPS4/blob/main/documents/Screenshots/screenshot.png" width="500">
|
||||
|
||||
<a href="https://shadps4.net/">
|
||||
<img src="https://github.com/shadps4-emu/shadPS4/blob/main/documents/Screenshots/Undertale.png" width="500">
|
||||
|
||||
<a href="https://shadps4.net/">
|
||||
<img src="https://github.com/shadps4-emu/shadPS4/blob/main/documents/Screenshots/We are DOOMED.png" width="500">
|
||||
|
||||
# shadPS4
|
||||
|
||||
|
|
BIN
documents/Screenshots/Sonic Mania.png
Normal file
BIN
documents/Screenshots/Sonic Mania.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 140 KiB |
BIN
documents/Screenshots/Undertale.png
Normal file
BIN
documents/Screenshots/Undertale.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
BIN
documents/Screenshots/We are DOOMED.png
Normal file
BIN
documents/Screenshots/We are DOOMED.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 175 KiB |
2
externals/glslang
vendored
2
externals/glslang
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 73eccd4b67985d344578cade8958214cee0a3f6e
|
||||
Subproject commit a92c61f8456fa9731c0b000a2c6fc52a740c2be7
|
2
externals/toml11
vendored
2
externals/toml11
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 85faca9cbe8d76324ff38c1801be44c63e12d5be
|
||||
Subproject commit b389bbc4ebf90fa2fe7651de3046fb19f661ba3c
|
2
externals/vulkan-headers
vendored
2
externals/vulkan-headers
vendored
|
@ -1 +1 @@
|
|||
Subproject commit d192041a2fc9c9fd8ae67d8ae3f32c5511541f04
|
||||
Subproject commit 05fe2cc910a68c9ba5dac07db46ef78573acee72
|
2
externals/xbyak
vendored
2
externals/xbyak
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 80477f635345e8f13efc512d84b01b94cad92cd9
|
||||
Subproject commit aabb091ae37068498751fd58202a9854408ecb0e
|
2
externals/xxhash
vendored
2
externals/xxhash
vendored
|
@ -1 +1 @@
|
|||
Subproject commit ac3a25da3d957d9ef3e4114d9f8332d34ce83a46
|
||||
Subproject commit b0adcc54188c3130b1793e7b19c62eb1e669f7df
|
2
externals/zydis
vendored
2
externals/zydis
vendored
|
@ -1 +1 @@
|
|||
Subproject commit fd3e9a6cc8bdcc617b531feda186699e51664f76
|
||||
Subproject commit 5a68f639e4f01604cc7bfc8d313f583a8137e3d3
|
|
@ -104,6 +104,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
|||
SUB(Lib, AppContent) \
|
||||
SUB(Lib, Rtc) \
|
||||
SUB(Lib, DiscMap) \
|
||||
SUB(Lib, Png) \
|
||||
CLS(Frontend) \
|
||||
CLS(Render) \
|
||||
SUB(Render, Vulkan) \
|
||||
|
|
|
@ -71,6 +71,7 @@ enum class Class : u8 {
|
|||
Lib_AppContent, ///< The LibSceAppContent implementation.
|
||||
Lib_Rtc, ///< The LibSceRtc implementation.
|
||||
Lib_DiscMap, ///< The LibSceDiscMap implementation.
|
||||
Lib_Png, ///< The LibScePng implementation.
|
||||
Frontend, ///< Emulator UI
|
||||
Render, ///< Video Core
|
||||
Render_Vulkan, ///< Vulkan backend
|
||||
|
|
|
@ -687,7 +687,7 @@ int PS4_SYSV_ABI scePthreadCondTimedwait(ScePthreadCond* cond, ScePthreadMutex*
|
|||
time.tv_nsec = ((usec % 1000000) * 1000);
|
||||
int result = pthread_cond_timedwait(&(*cond)->cond, &(*mutex)->pth_mutex, &time);
|
||||
|
||||
LOG_INFO(Kernel_Pthread, "scePthreadCondTimedwait, result={}", result);
|
||||
// LOG_INFO(Kernel_Pthread, "scePthreadCondTimedwait, result={}", result);
|
||||
|
||||
switch (result) {
|
||||
case 0:
|
||||
|
@ -1026,7 +1026,7 @@ int PS4_SYSV_ABI scePthreadCondSignal(ScePthreadCond* cond) {
|
|||
|
||||
int result = pthread_cond_signal(&(*cond)->cond);
|
||||
|
||||
LOG_INFO(Kernel_Pthread, "scePthreadCondSignal, result={}", result);
|
||||
// LOG_INFO(Kernel_Pthread, "scePthreadCondSignal, result={}", result);
|
||||
|
||||
switch (result) {
|
||||
case 0:
|
||||
|
@ -1240,7 +1240,19 @@ int PS4_SYSV_ABI scePthreadSetschedparam(ScePthread thread, int policy,
|
|||
int PS4_SYSV_ABI scePthreadOnce(int* once_control, void (*init_routine)(void)) {
|
||||
return pthread_once(reinterpret_cast<pthread_once_t*>(once_control), init_routine);
|
||||
}
|
||||
int PS4_SYSV_ABI posix_pthread_create(ScePthread* thread, const ScePthreadAttr* attr,
|
||||
pthreadEntryFunc start_routine, void* arg) {
|
||||
LOG_INFO(Kernel_Pthread, "posix pthread_create redirect to scePthreadCreate");
|
||||
|
||||
int result = scePthreadCreate(thread, attr, start_routine, arg, "");
|
||||
if (result != 0) {
|
||||
int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP
|
||||
? result + -SCE_KERNEL_ERROR_UNKNOWN
|
||||
: POSIX_EOTHER;
|
||||
return rt;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("lZzFeSxPl08", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_setcancelstate);
|
||||
LIB_FUNCTION("0TyVk4MSLt0", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_cond_init);
|
||||
|
@ -1270,7 +1282,8 @@ void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
|||
LIB_FUNCTION("oIRFTjoILbg", "libkernel", 1, "libkernel", 1, 1, scePthreadSetschedparam);
|
||||
LIB_FUNCTION("UTXzJbWhhTE", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrSetstacksize);
|
||||
LIB_FUNCTION("vNe1w4diLCs", "libkernel", 1, "libkernel", 1, 1, __tls_get_addr);
|
||||
|
||||
LIB_FUNCTION("OxhIB8LB-PQ", "libkernel", 1, "libkernel", 1, 1, posix_pthread_create);
|
||||
LIB_FUNCTION("OxhIB8LB-PQ", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_create);
|
||||
LIB_FUNCTION("bt3CTBKmGyI", "libkernel", 1, "libkernel", 1, 1, scePthreadSetaffinity);
|
||||
LIB_FUNCTION("6UgtwV+0zb4", "libkernel", 1, "libkernel", 1, 1, scePthreadCreate);
|
||||
LIB_FUNCTION("T72hz6ffq08", "libkernel", 1, "libkernel", 1, 1, scePthreadYield);
|
||||
|
|
|
@ -63,13 +63,7 @@ int PS4_SYSV_ABI sceKernelUsleep(u32 microseconds) {
|
|||
}
|
||||
|
||||
int PS4_SYSV_ABI posix_usleep(u32 microseconds) {
|
||||
#ifdef _WIN64
|
||||
ASSERT(microseconds >= 1000 || microseconds == 0);
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(microseconds));
|
||||
return 0;
|
||||
#else
|
||||
return usleep(microseconds);
|
||||
#endif
|
||||
return sceKernelUsleep(microseconds);
|
||||
}
|
||||
|
||||
u32 PS4_SYSV_ABI sceKernelSleep(u32 seconds) {
|
||||
|
@ -83,11 +77,15 @@ int PS4_SYSV_ABI sceKernelClockGettime(s32 clock_id, OrbisKernelTimespec* tp) {
|
|||
}
|
||||
clockid_t pclock_id = CLOCK_REALTIME;
|
||||
switch (clock_id) {
|
||||
case 0:
|
||||
case ORBIS_CLOCK_REALTIME:
|
||||
case ORBIS_CLOCK_REALTIME_PRECISE:
|
||||
case ORBIS_CLOCK_REALTIME_FAST:
|
||||
pclock_id = CLOCK_REALTIME;
|
||||
break;
|
||||
case 13:
|
||||
case 4:
|
||||
case ORBIS_CLOCK_SECOND:
|
||||
case ORBIS_CLOCK_MONOTONIC:
|
||||
case ORBIS_CLOCK_MONOTONIC_PRECISE:
|
||||
case ORBIS_CLOCK_MONOTONIC_FAST:
|
||||
pclock_id = CLOCK_MONOTONIC;
|
||||
break;
|
||||
default:
|
||||
|
@ -104,7 +102,7 @@ int PS4_SYSV_ABI sceKernelClockGettime(s32 clock_id, OrbisKernelTimespec* tp) {
|
|||
return SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI clock_gettime(s32 clock_id, OrbisKernelTimespec* time) {
|
||||
int PS4_SYSV_ABI posix_clock_gettime(s32 clock_id, OrbisKernelTimespec* time) {
|
||||
int result = sceKernelClockGettime(clock_id, time);
|
||||
if (result < 0) {
|
||||
UNREACHABLE(); // TODO return posix error code
|
||||
|
@ -175,6 +173,37 @@ s32 PS4_SYSV_ABI sceKernelGettimezone(OrbisKernelTimezone* tz) {
|
|||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI posix_clock_getres(u32 clock_id, OrbisKernelTimespec* res) {
|
||||
if (res == nullptr) {
|
||||
return SCE_KERNEL_ERROR_EFAULT;
|
||||
}
|
||||
clockid_t pclock_id = CLOCK_REALTIME;
|
||||
switch (clock_id) {
|
||||
case ORBIS_CLOCK_REALTIME:
|
||||
case ORBIS_CLOCK_REALTIME_PRECISE:
|
||||
case ORBIS_CLOCK_REALTIME_FAST:
|
||||
pclock_id = CLOCK_REALTIME;
|
||||
break;
|
||||
case ORBIS_CLOCK_SECOND:
|
||||
case ORBIS_CLOCK_MONOTONIC:
|
||||
case ORBIS_CLOCK_MONOTONIC_PRECISE:
|
||||
case ORBIS_CLOCK_MONOTONIC_FAST:
|
||||
pclock_id = CLOCK_MONOTONIC;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
timespec t{};
|
||||
int result = clock_getres(pclock_id, &t);
|
||||
res->tv_sec = t.tv_sec;
|
||||
res->tv_nsec = t.tv_nsec;
|
||||
if (result == 0) {
|
||||
return SCE_OK;
|
||||
}
|
||||
return SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
|
||||
void timeSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
||||
clock = std::make_unique<Common::NativeClock>();
|
||||
initial_ptc = clock->GetUptime();
|
||||
|
@ -187,6 +216,7 @@ void timeSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
|||
LIB_FUNCTION("ejekcaNQNq0", "libkernel", 1, "libkernel", 1, 1, sceKernelGettimeofday);
|
||||
LIB_FUNCTION("n88vx3C5nW8", "libkernel", 1, "libkernel", 1, 1, gettimeofday);
|
||||
LIB_FUNCTION("n88vx3C5nW8", "libScePosix", 1, "libkernel", 1, 1, gettimeofday);
|
||||
LIB_FUNCTION("QvsZxomvUHs", "libkernel", 1, "libkernel", 1, 1, sceKernelNanosleep);
|
||||
LIB_FUNCTION("1jfXLRVzisc", "libkernel", 1, "libkernel", 1, 1, sceKernelUsleep);
|
||||
LIB_FUNCTION("QcteRwbsnV0", "libkernel", 1, "libkernel", 1, 1, posix_usleep);
|
||||
LIB_FUNCTION("QcteRwbsnV0", "libScePosix", 1, "libkernel", 1, 1, posix_usleep);
|
||||
|
@ -195,9 +225,10 @@ void timeSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
|||
LIB_FUNCTION("yS8U2TGCe1A", "libkernel", 1, "libkernel", 1, 1, posix_nanosleep);
|
||||
LIB_FUNCTION("yS8U2TGCe1A", "libScePosix", 1, "libkernel", 1, 1, posix_nanosleep);
|
||||
LIB_FUNCTION("QBi7HCK03hw", "libkernel", 1, "libkernel", 1, 1, sceKernelClockGettime);
|
||||
LIB_FUNCTION("lLMT9vJAck0", "libkernel", 1, "libkernel", 1, 1, clock_gettime);
|
||||
LIB_FUNCTION("lLMT9vJAck0", "libScePosix", 1, "libkernel", 1, 1, clock_gettime);
|
||||
LIB_FUNCTION("kOcnerypnQA", "libkernel", 1, "libkernel", 1, 1, sceKernelGettimezone);
|
||||
LIB_FUNCTION("lLMT9vJAck0", "libkernel", 1, "libkernel", 1, 1, posix_clock_gettime);
|
||||
LIB_FUNCTION("lLMT9vJAck0", "libScePosix", 1, "libkernel", 1, 1, posix_clock_gettime);
|
||||
LIB_FUNCTION("smIj7eqzZE8", "libScePosix", 1, "libkernel", 1, 1, posix_clock_getres);
|
||||
}
|
||||
|
||||
} // namespace Libraries::Kernel
|
||||
|
|
|
@ -26,6 +26,25 @@ struct OrbisKernelTimespec {
|
|||
s64 tv_nsec;
|
||||
};
|
||||
|
||||
constexpr int ORBIS_CLOCK_REALTIME = 0;
|
||||
constexpr int ORBIS_CLOCK_VIRTUAL = 1;
|
||||
constexpr int ORBIS_CLOCK_PROF = 2;
|
||||
constexpr int ORBIS_CLOCK_MONOTONIC = 4;
|
||||
constexpr int ORBIS_CLOCK_UPTIME = 5;
|
||||
constexpr int ORBIS_CLOCK_UPTIME_PRECISE = 7;
|
||||
constexpr int ORBIS_CLOCK_UPTIME_FAST = 8;
|
||||
constexpr int ORBIS_CLOCK_REALTIME_PRECISE = 9;
|
||||
constexpr int ORBIS_CLOCK_REALTIME_FAST = 10;
|
||||
constexpr int ORBIS_CLOCK_MONOTONIC_PRECISE = 11;
|
||||
constexpr int ORBIS_CLOCK_MONOTONIC_FAST = 12;
|
||||
constexpr int ORBIS_CLOCK_SECOND = 13;
|
||||
constexpr int ORBIS_CLOCK_THREAD_CPUTIME_ID = 14;
|
||||
constexpr int ORBIS_CLOCK_PROCTIME = 15;
|
||||
constexpr int ORBIS_CLOCK_EXT_NETWORK = 16;
|
||||
constexpr int ORBIS_CLOCK_EXT_DEBUG_NETWORK = 17;
|
||||
constexpr int ORBIS_CLOCK_EXT_AD_NETWORK = 18;
|
||||
constexpr int ORBIS_CLOCK_EXT_RAW_NETWORK = 19;
|
||||
|
||||
u64 PS4_SYSV_ABI sceKernelGetTscFrequency();
|
||||
u64 PS4_SYSV_ABI sceKernelGetProcessTime();
|
||||
u64 PS4_SYSV_ABI sceKernelGetProcessTimeCounter();
|
||||
|
|
169
src/core/libraries/libpng/pngdec.cpp
Normal file
169
src/core/libraries/libpng/pngdec.cpp
Normal file
|
@ -0,0 +1,169 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/libs.h"
|
||||
#include "externals/stb_image.h"
|
||||
#include "pngdec.h"
|
||||
|
||||
namespace Libraries::PngDec {
|
||||
|
||||
void setImageInfoParams(OrbisPngDecImageInfo* imageInfo, int width, int height, int channels,
|
||||
bool isInterlaced, bool isTransparent) {
|
||||
if (imageInfo != nullptr) {
|
||||
imageInfo->imageWidth = width;
|
||||
imageInfo->imageHeight = height;
|
||||
imageInfo->bitDepth = 8; // always 8?
|
||||
switch (channels) { // clut missing
|
||||
case 1:
|
||||
imageInfo->colorSpace = OrbisPngDecColorSpace::ORBIS_PNG_DEC_COLOR_SPACE_GRAYSCALE;
|
||||
break;
|
||||
case 2:
|
||||
imageInfo->colorSpace =
|
||||
OrbisPngDecColorSpace::ORBIS_PNG_DEC_COLOR_SPACE_GRAYSCALE_ALPHA;
|
||||
break;
|
||||
case 3:
|
||||
imageInfo->colorSpace = OrbisPngDecColorSpace::ORBIS_PNG_DEC_COLOR_SPACE_RGB;
|
||||
break;
|
||||
case 4:
|
||||
imageInfo->colorSpace = OrbisPngDecColorSpace::ORBIS_PNG_DEC_COLOR_SPACE_RGBA;
|
||||
break;
|
||||
default:
|
||||
imageInfo->colorSpace = OrbisPngDecColorSpace::ORBIS_PNG_DEC_COLOR_SPACE_RGB;
|
||||
break;
|
||||
}
|
||||
imageInfo->imageFlag = 0;
|
||||
if (isInterlaced) {
|
||||
imageInfo->imageFlag |= ORBIS_PNG_DEC_IMAGE_FLAG_ADAM7_INTERLACE;
|
||||
}
|
||||
if (isTransparent) {
|
||||
imageInfo->imageFlag |= ORBIS_PNG_DEC_IMAGE_FLAG_TRNS_CHUNK_EXIST;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool checktRNS(const u8* png_raw, int size) {
|
||||
for (int i = 30; i < size - 4; i += 4) {
|
||||
if (std::memcmp(png_raw + i, "tRNS", 4) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI scePngDecCreate(const OrbisPngDecCreateParam* param, void* memoryAddress,
|
||||
u32 memorySize, OrbisPngDecHandle* handle) {
|
||||
if (param == nullptr || param->attribute > 1) {
|
||||
LOG_ERROR(Lib_Png, "Invalid param!");
|
||||
return ORBIS_PNG_DEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
if (memoryAddress == nullptr) {
|
||||
LOG_ERROR(Lib_Png, "Invalid memory address!");
|
||||
return ORBIS_PNG_DEC_ERROR_INVALID_ADDR;
|
||||
}
|
||||
if (param->maxImageWidth - 1 > 1000000) {
|
||||
LOG_ERROR(Lib_Png, "Invalid size! width = {}", param->maxImageWidth);
|
||||
return ORBIS_PNG_DEC_ERROR_INVALID_SIZE;
|
||||
}
|
||||
const OrbisPngDecCreateParam* nextParam = param + 1;
|
||||
int ret = (8 << (reinterpret_cast<uintptr_t>(nextParam) & 0x1f)) *
|
||||
(param->maxImageWidth + 0x47U & 0xfffffff8) +
|
||||
0xd000;
|
||||
*handle = reinterpret_cast<OrbisPngDecHandle>(ret);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI scePngDecDecode(OrbisPngDecHandle handle, const OrbisPngDecDecodeParam* param,
|
||||
OrbisPngDecImageInfo* imageInfo) {
|
||||
if (handle == nullptr) {
|
||||
LOG_ERROR(Lib_Png, "invalid handle!");
|
||||
return ORBIS_PNG_DEC_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (param == nullptr) {
|
||||
LOG_ERROR(Lib_Png, "Invalid param!");
|
||||
return ORBIS_PNG_DEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
if (param->pngMemAddr == nullptr || param->pngMemAddr == nullptr) {
|
||||
LOG_ERROR(Lib_Png, "invalid image address!");
|
||||
return ORBIS_PNG_DEC_ERROR_INVALID_ADDR;
|
||||
}
|
||||
|
||||
int width, height, channels;
|
||||
const u8* png_raw = (const u8*)param->pngMemAddr;
|
||||
u8* img = stbi_load_from_memory(png_raw, param->pngMemSize, &width, &height, &channels,
|
||||
STBI_rgb_alpha); // STBI_rgb_alpha?
|
||||
if (!img) {
|
||||
LOG_ERROR(Lib_Png, "Decoding failed!");
|
||||
return ORBIS_PNG_DEC_ERROR_DECODE_ERROR;
|
||||
}
|
||||
bool isInterlaced = (png_raw[28] == 1);
|
||||
bool isTransparent = checktRNS(png_raw, param->pngMemSize);
|
||||
setImageInfoParams(imageInfo, width, height, channels, isInterlaced, isTransparent);
|
||||
u8* imageBuffer = (u8*)(param->imageMemAddr);
|
||||
memcpy(imageBuffer, img, width * height * 4); // copy/pass decoded data
|
||||
stbi_image_free(img);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI scePngDecDecodeWithInputControl() {
|
||||
LOG_ERROR(Lib_Png, "(STUBBED)called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI scePngDecDelete(OrbisPngDecHandle handle) {
|
||||
handle = nullptr; // ?
|
||||
LOG_ERROR(Lib_Png, "(STUBBED)called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI scePngDecParseHeader(const OrbisPngDecParseParam* param,
|
||||
OrbisPngDecImageInfo* imageInfo) {
|
||||
if (param == nullptr) {
|
||||
LOG_ERROR(Lib_Png, "Invalid param!");
|
||||
return ORBIS_PNG_DEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
int width, height, channels;
|
||||
const u8* png_raw = (const u8*)(param->pngMemAddr);
|
||||
int img = stbi_info_from_memory(png_raw, param->pngMemSize, &width, &height, &channels);
|
||||
if (img == 0) {
|
||||
LOG_ERROR(Lib_Png, "Decoding failed!");
|
||||
return ORBIS_PNG_DEC_ERROR_DECODE_ERROR;
|
||||
}
|
||||
bool isInterlaced = (png_raw[28] == 1);
|
||||
bool isTransparent = checktRNS(png_raw, param->pngMemSize);
|
||||
setImageInfoParams(imageInfo, width, height, channels, isInterlaced, isTransparent);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI scePngDecQueryMemorySize(const OrbisPngDecCreateParam* param) {
|
||||
if (param == nullptr) {
|
||||
LOG_ERROR(Lib_Png, "Invalid param!");
|
||||
return ORBIS_PNG_DEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
if (param->attribute > 1) {
|
||||
LOG_ERROR(Lib_Png, "Invalid attribute! attribute = {}", param->attribute);
|
||||
return ORBIS_PNG_DEC_ERROR_INVALID_ADDR;
|
||||
}
|
||||
if (param->maxImageWidth - 1 > 1000000) {
|
||||
LOG_ERROR(Lib_Png, "Invalid size! width = {}", param->maxImageWidth);
|
||||
return ORBIS_PNG_DEC_ERROR_INVALID_SIZE;
|
||||
}
|
||||
int ret =
|
||||
(8 << ((u8)param->attribute & 0x1f)) * (param->maxImageWidth + 0x47U & 0xfffffff8) + 0xd090;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void RegisterlibScePngDec(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,
|
||||
scePngDecDecodeWithInputControl);
|
||||
LIB_FUNCTION("QbD+eENEwo8", "libScePngDec", 1, "libScePngDec", 1, 1, scePngDecDelete);
|
||||
LIB_FUNCTION("U6h4e5JRPaQ", "libScePngDec", 1, "libScePngDec", 1, 1, scePngDecParseHeader);
|
||||
LIB_FUNCTION("-6srIGbLTIU", "libScePngDec", 1, "libScePngDec", 1, 1, scePngDecQueryMemorySize);
|
||||
LIB_FUNCTION("cJ--1xAbj-I", "libScePngDec_jvm", 1, "libScePngDec", 1, 1,
|
||||
scePngDecDecodeWithInputControl);
|
||||
};
|
||||
|
||||
} // namespace Libraries::PngDec
|
79
src/core/libraries/libpng/pngdec.h
Normal file
79
src/core/libraries/libpng/pngdec.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/types.h"
|
||||
|
||||
namespace Core::Loader {
|
||||
class SymbolsResolver;
|
||||
}
|
||||
namespace Libraries::PngDec {
|
||||
|
||||
constexpr int ORBIS_PNG_DEC_ERROR_INVALID_ADDR = 0x80690001;
|
||||
constexpr int ORBIS_PNG_DEC_ERROR_INVALID_SIZE = 0x80690002;
|
||||
constexpr int ORBIS_PNG_DEC_ERROR_INVALID_PARAM = 0x80690003;
|
||||
constexpr int ORBIS_PNG_DEC_ERROR_INVALID_HANDLE = 0x80690004;
|
||||
constexpr int ORBIS_PNG_DEC_ERROR_INVALID_WORK_MEMORY = 0x80690005;
|
||||
constexpr int ORBIS_PNG_DEC_ERROR_INVALID_DATA = 0x80690010;
|
||||
constexpr int ORBIS_PNG_DEC_ERROR_UNSUPPORT_DATA = 0x80690011;
|
||||
constexpr int ORBIS_PNG_DEC_ERROR_DECODE_ERROR = 0x80690012;
|
||||
constexpr int ORBIS_PNG_DEC_ERROR_FATAL = 0x80690020;
|
||||
|
||||
typedef struct OrbisPngDecParseParam {
|
||||
const void* pngMemAddr;
|
||||
u32 pngMemSize;
|
||||
u32 reserved;
|
||||
} OrbisPngDecParseParam;
|
||||
|
||||
typedef struct OrbisPngDecImageInfo {
|
||||
u32 imageWidth;
|
||||
u32 imageHeight;
|
||||
u16 colorSpace;
|
||||
u16 bitDepth;
|
||||
u32 imageFlag;
|
||||
} OrbisPngDecImageInfo;
|
||||
|
||||
typedef enum OrbisPngDecColorSpace {
|
||||
ORBIS_PNG_DEC_COLOR_SPACE_GRAYSCALE = 2,
|
||||
ORBIS_PNG_DEC_COLOR_SPACE_RGB,
|
||||
ORBIS_PNG_DEC_COLOR_SPACE_CLUT,
|
||||
ORBIS_PNG_DEC_COLOR_SPACE_GRAYSCALE_ALPHA = 18,
|
||||
ORBIS_PNG_DEC_COLOR_SPACE_RGBA
|
||||
} ScePngDecColorSpace;
|
||||
|
||||
typedef enum OrbisPngDecImageFlag {
|
||||
ORBIS_PNG_DEC_IMAGE_FLAG_ADAM7_INTERLACE = 1,
|
||||
ORBIS_PNG_DEC_IMAGE_FLAG_TRNS_CHUNK_EXIST = 2
|
||||
} OrbisPngDecImageFlag;
|
||||
|
||||
typedef struct OrbisPngDecCreateParam {
|
||||
u32 thisSize;
|
||||
u32 attribute;
|
||||
u32 maxImageWidth;
|
||||
} OrbisPngDecCreateParam;
|
||||
|
||||
typedef void* OrbisPngDecHandle;
|
||||
|
||||
typedef struct OrbisPngDecDecodeParam {
|
||||
const void* pngMemAddr;
|
||||
void* imageMemAddr;
|
||||
u32 pngMemSize;
|
||||
u32 imageMemSize;
|
||||
u16 pixelFormat;
|
||||
u16 alphaValue;
|
||||
u32 imagePitch;
|
||||
} OrbisPngDecDecodeParam;
|
||||
|
||||
s32 PS4_SYSV_ABI scePngDecCreate(const OrbisPngDecCreateParam* param, void* memoryAddress,
|
||||
u32 memorySize, OrbisPngDecHandle* handle);
|
||||
s32 PS4_SYSV_ABI scePngDecDecode(OrbisPngDecHandle handle, const OrbisPngDecDecodeParam* param,
|
||||
OrbisPngDecImageInfo* imageInfo);
|
||||
s32 PS4_SYSV_ABI scePngDecDecodeWithInputControl();
|
||||
s32 PS4_SYSV_ABI scePngDecDelete(OrbisPngDecHandle handle);
|
||||
s32 PS4_SYSV_ABI scePngDecParseHeader(const OrbisPngDecParseParam* param,
|
||||
OrbisPngDecImageInfo* imageInfo);
|
||||
s32 PS4_SYSV_ABI scePngDecQueryMemorySize(const OrbisPngDecCreateParam* param);
|
||||
|
||||
void RegisterlibScePngDec(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::PngDec
|
|
@ -30,6 +30,7 @@
|
|||
#include "core/libraries/system/systemservice.h"
|
||||
#include "core/libraries/system/userservice.h"
|
||||
#include "core/libraries/videoout/video_out.h"
|
||||
#include "src/core/libraries/libpng/pngdec.h"
|
||||
|
||||
namespace Libraries {
|
||||
|
||||
|
@ -65,6 +66,7 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) {
|
|||
Libraries::AppContent::RegisterlibSceAppContent(sym);
|
||||
Libraries::Rtc::RegisterlibSceRtc(sym);
|
||||
Libraries::DiscMap::RegisterlibSceDiscMap(sym);
|
||||
Libraries::PngDec::RegisterlibScePngDec(sym);
|
||||
}
|
||||
|
||||
} // namespace Libraries
|
||||
|
|
Loading…
Add table
Reference in a new issue