mirror of
https://github.com/mihawk-99/PS5_RetroArch.git
synced 2026-10-22 08:32:30 -05:00
Track A's console step. The loader diagnostic now passes for PPSSPP — passed=true, cycles=8, exports=25, api=1 at identity 73d2aad8…, with "ran 110 initializers" and "symbols=19430 relocations=24812 mapped_bytes=18923520" — so an 18.1 MB C++ core with 392 imports loads, initialises and unloads eight times over. Three blockers fell on the way, each found on the console rather than by reading code: - Unresolvable imports. The first run failed on gai_strerror, the next on glGetString: the loader requires every import to have an address, so a symbol the console leaves null is fatal for a core even though the title tolerates it. The four libScePosixForWebKit symbols (gai_strerror, getaddrinfo, freeaddrinfo, isatty) were never exercised by any shipped core and are now implemented in tooling/ppsspp/ps5-libc-shims.cpp; the 83 OpenGL symbols are excluded by patches/ppsspp/0003-no-opengl.patch, which drops Common/GPU/OpenGL, GPU/GLES, the two libretro GL contexts and PS5's PPSSPP_API_ANY_GL. The core now has zero gl*/egl* imports and the title's table falls from 497 bindings to 410, all of them resolving from libkernel_web or libSceLibcInternal. - The thread pool. ThreadManager::Init multiplies its two arguments (numRealCores * numLogicalCoresPerCpu); the platform branch had set both from sysconf, asking for 256 compute threads and 512 in total. It now takes the physical core count from CPUID leaf 0x80000008 and SMT siblings from the online count: 16 and 32, which is right for this console. - The runtime assets. PPSSPP resolves them as <system>/PPSSPP and warned "Core system files missing". tools/build-ppsspp.sh now stages the pinned source's assets/ — the complete tree, 193 files, 22 MiB — rather than the 187-file partial copy CMake leaves in the build directory (it omits cheats.json, knownfuncs.ini and four others), and tools/build-title.sh publishes it to dist/PPSA99169/system/PPSSPP, verified on the console at /data/homebrew/PPSA99169/system/PPSSPP including flash0, debugger, shaders and lang. The tree's digest is in build.json (ppsspp_assets_sha256 223c78b2…). Also in this commit: patches/ppsspp/0004-software-backend-default.patch makes the libretro software context the PS5 default for ppsspp_backend (the Vulkan renderer cannot come up against a driver with no combined depth/stencil format, and the stalled Vulkan attempt is why earlier runs showed no progress past core init), and the CPU fix above. RetroArch is relinked against the sibling's rung-1.0 driver: PS5_Vulkan d4e73ff, embedded libps5vk.ps5.a d41f934b…, title identity 735f7eb1…. All five gates pass (32 captures replayed). Open, and the next step: the title takes a SIGSEGV on a worker thread during ThreadManager::Init (fault address 0x70, frames inside libkernel.sprx per klog/run-PPSA99169-002106.log), so no PSP frame has been presented. Rung 1.0 also does not yet give PPSSPP's Vulkan renderer the six things it needs: a combined depth/stencil format, attachments smaller than 3840x2160, cull mode, per-channel colour write masks, stencil test with dynamic stencil state, and dynamic blend constants. Console evidence: evidence/ppsspp-native/; replay with bash tools/verify.sh format unit integration evidence.
128 lines
4.3 KiB
C++
128 lines
4.3 KiB
C++
/* PS5 PPSSPP - the libc entry points this target must implement itself.
|
|
* Copyright (C) 2026 Mihawk
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
*
|
|
* These are not PPSSPP's own calls. Each one is made by vendored third-party code
|
|
* that the libretro core links, and the payload SDK declares but does not export
|
|
* them, so the title's generated binding table cannot resolve them:
|
|
*
|
|
* swab ext/libpng17/pngtrans.c, for 16-bit row transforms
|
|
* nl_langinfo ext/armips and ext/SPIRV-Cross, which ask only for the codeset
|
|
* tmpfile ext/lua/liolib.c, io.tmpfile()
|
|
* tmpnam ext/lua/loslib.c, os.tmpname()
|
|
*
|
|
* Four more were added after the first console run, and they are a different kind of
|
|
* case: the SDK's libScePosixForWebKit stub lists them, but no core this title has
|
|
* ever shipped imported anything from that module, and on the console the first
|
|
* load of this core failed with "unresolved native runtime import: gai_strerror" -
|
|
* the loader walked the dynamic symbols in order and reached these four, which means
|
|
* the module's stub-declared exports are not all present at runtime. The symbols are
|
|
* the network resolver and a terminal check, neither of which this title provides:
|
|
*
|
|
* gai_strerror, getaddrinfo, freeaddrinfo PPSSPP's ad-hoc networking
|
|
* isatty terminal detection for log colouring
|
|
*
|
|
* Implementing them inside the core, rather than teaching the title's import table
|
|
* about them, keeps the resolution where the reference is and needs no SDK change.
|
|
* swab and the codeset query are real implementations; the resolver refuses with
|
|
* EAI_FAIL and the temporary-file entries refuse with NULL, all of which the callers
|
|
* already handle. isatty answers 0, which is true: the title's stdout is a log file.
|
|
*/
|
|
#include <cstddef>
|
|
#include <cstdio>
|
|
#include <langinfo.h>
|
|
#include <netdb.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
|
|
extern "C" void swab(const void *from, void *to, ssize_t count)
|
|
{
|
|
if (count <= 0)
|
|
return;
|
|
const auto *source = static_cast<const unsigned char *>(from);
|
|
auto *destination = static_cast<unsigned char *>(to);
|
|
/* POSIX: swap every adjacent pair; a trailing odd byte is left alone. */
|
|
for (ssize_t index = 0; index + 1 < count; index += 2)
|
|
{
|
|
destination[index] = source[index + 1];
|
|
destination[index + 1] = source[index];
|
|
}
|
|
if (count & 1)
|
|
destination[count - 1] = source[count - 1];
|
|
}
|
|
|
|
extern "C" char *nl_langinfo(nl_item item)
|
|
{
|
|
/* The port's filesystem, Lua strings and configuration are UTF-8, and the two
|
|
* callers use this to decide how to interpret a filename or a shader source.
|
|
* Anything else answers as the C locale, which is what the emulator assumes. */
|
|
static char codeset[] = "UTF-8";
|
|
static char c_locale[] = "C";
|
|
static char empty[] = "";
|
|
switch (item)
|
|
{
|
|
case CODESET: return codeset;
|
|
case RADIXCHAR:
|
|
case THOUSEP: return empty;
|
|
default: return c_locale;
|
|
}
|
|
}
|
|
|
|
/* No resolver in this title. PPSSPP uses these for ad-hoc multiplayer, which the
|
|
* frontend does not enable; a non-recoverable answer is the honest one. */
|
|
extern "C" int getaddrinfo(const char *, const char *, const struct addrinfo *,
|
|
struct addrinfo **)
|
|
{
|
|
return EAI_FAIL;
|
|
}
|
|
|
|
extern "C" void freeaddrinfo(struct addrinfo *)
|
|
{
|
|
}
|
|
|
|
extern "C" const char *gai_strerror(int code)
|
|
{
|
|
switch (code)
|
|
{
|
|
case 0: return "no error";
|
|
case EAI_FAIL: return "name resolution is not available in this title";
|
|
case EAI_MEMORY: return "out of memory";
|
|
case EAI_SYSTEM: return "system error";
|
|
default: return "name resolution error";
|
|
}
|
|
}
|
|
|
|
/* The title's stdout is a log file, not a terminal. */
|
|
extern "C" int isatty(int)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
namespace
|
|
{
|
|
/* One line each, so a future failure names the call instead of a NULL. */
|
|
void note(const char *name)
|
|
{
|
|
static bool reported_file = false;
|
|
static bool reported_name = false;
|
|
bool &reported = *name == 't' && name[3] == 'f' ? reported_file : reported_name;
|
|
if (!reported)
|
|
{
|
|
reported = true;
|
|
std::fprintf(stderr, "ppsspp core: %s() has no writable temporary path on this target; returning NULL\n", name);
|
|
}
|
|
}
|
|
} // namespace
|
|
|
|
extern "C" FILE *tmpfile(void)
|
|
{
|
|
note("tmpfile");
|
|
return nullptr;
|
|
}
|
|
|
|
extern "C" char *tmpnam(char *)
|
|
{
|
|
note("tmpnam");
|
|
return nullptr;
|
|
}
|