fix(libc): update locale signatures + add sysv abi to math funcs
This commit is contained in:
parent
2778c1e86e
commit
9a4c8eab8b
|
|
@ -12,9 +12,9 @@ Execution reaches `_start`, [stack unwinding](core/libs/prx/libc/src/exception/U
|
|||
|
||||
The [shader recompiler](core/shader/recompiler/Recompiler.cpp) successfully produces validated via [Spirv-Tools](3rdparty/SPIRV-Tools) SPIR-V.
|
||||
|
||||
The real game successfully presents the logo and loads the main menu, then crashes before the menu buttons appear.
|
||||
The real game reaches the main menu, which renders correctly with buttons and audio.
|
||||
|
||||
Current error: Access Violation at ~frame 168.
|
||||
Current stop: [libScePad](core/libs/prx/libScePad) does not record the input, so the button cannot be pressed.
|
||||
|
||||
## Build
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <limits>
|
||||
|
||||
#include "prx/libc/include/General.hpp"
|
||||
#include "prx/libc/include/ApplicationHeap.hpp"
|
||||
|
|
@ -50,14 +51,14 @@ constexpr std::array<short, 257> MakeClassificationTable() {
|
|||
std::array<short, 257> table{};
|
||||
for (unsigned int value = 0; value < 256; ++value) {
|
||||
short mask = 0;
|
||||
if (value < 32 || value == 127) mask |= 0x20;
|
||||
if (value == ' ' || (value >= '\t' && value <= '\r')) mask |= 0x08;
|
||||
if (value == ' ' || value == '\t') mask |= 0x40;
|
||||
if (value >= 'A' && value <= 'Z') mask |= 0x101;
|
||||
if (value >= 'a' && value <= 'z') mask |= 0x102;
|
||||
if (value >= '0' && value <= '9') mask |= 0x04;
|
||||
if ((value >= '0' && value <= '9') || (value >= 'A' && value <= 'F') || (value >= 'a' && value <= 'f')) mask |= 0x80;
|
||||
if (value >= 33 && value <= 126 && (mask & 0x107) == 0) mask |= 0x10;
|
||||
if (value < 32 || value == 127) mask |= 0x80;
|
||||
if (value == ' ') mask |= 0x04;
|
||||
if (value >= '\t' && value <= '\r') mask |= 0x40;
|
||||
if (value >= 'A' && value <= 'Z') mask |= 0x02;
|
||||
if (value >= 'a' && value <= 'z') mask |= 0x10;
|
||||
if (value >= '0' && value <= '9') mask |= 0x20;
|
||||
if ((value >= '0' && value <= '9') || (value >= 'A' && value <= 'F') || (value >= 'a' && value <= 'f')) mask |= 0x01;
|
||||
if (value >= 33 && value <= 126 && (mask & 0x232) == 0) mask |= 0x08;
|
||||
table[value + 1] = mask;
|
||||
}
|
||||
return table;
|
||||
|
|
@ -102,11 +103,12 @@ void APS5_VABI _ZNSt8ios_baseD2Ev_nid_postfix(GuestLocale::IosBase* self) {
|
|||
self->locale = nullptr;
|
||||
}
|
||||
|
||||
void APS5_VABI _ZNSt6locale5_InitEv_nid_postfix() {
|
||||
GuestLocale::Implementation* APS5_VABI _ZNSt6locale5_InitEv_nid_postfix() {
|
||||
std::lock_guard<std::mutex> lock(g_localeInitMutex);
|
||||
if (!g_localeInitialized) {
|
||||
g_localeInitialized = true;
|
||||
}
|
||||
return &g_classicLocale;
|
||||
}
|
||||
|
||||
void APS5_VABI _ZNSt6locale5facet9_RegisterEv_nid_postfix(GuestLocale::Facet* self) {
|
||||
|
|
@ -135,25 +137,23 @@ void APS5_VABI _ZNSt8_LocinfoD1Ev_nid_postfix(GuestLocale::LocinfoStorage* self)
|
|||
if (self == nullptr) throw std::invalid_argument("_Locinfo destructor: null object");
|
||||
}
|
||||
|
||||
wchar_t* APS5_VABI _Mbtowcx_nid_postfix(wchar_t* dst, const char* src, std::size_t count, mbstate_t* st) {
|
||||
while (count > 0) {
|
||||
std::size_t result = std::mbrtowc(dst, src, count, st);
|
||||
if (result == static_cast<std::size_t>(-1) || result == static_cast<std::size_t>(-2))
|
||||
return nullptr;
|
||||
if (result == 0)
|
||||
return dst;
|
||||
src += result;
|
||||
count -= result;
|
||||
++dst;
|
||||
}
|
||||
return dst;
|
||||
int APS5_VABI _Mbtowcx_nid_postfix(std::uint16_t* dst, const char* src, std::size_t count, mbstate_t* st) {
|
||||
if (dst == nullptr || src == nullptr || st == nullptr || count == 0) throw std::invalid_argument("_Mbtowcx: invalid conversion arguments");
|
||||
wchar_t converted{};
|
||||
const auto result = std::mbrtowc(&converted, src, count, st);
|
||||
if (result == static_cast<std::size_t>(-1)) throw std::runtime_error("_Mbtowcx: invalid multibyte character");
|
||||
if (result == static_cast<std::size_t>(-2)) throw std::runtime_error("_Mbtowcx: incomplete multibyte character");
|
||||
if (result > static_cast<std::size_t>(std::numeric_limits<int>::max()) || static_cast<std::uint32_t>(converted) > 0xffff) throw std::runtime_error("_Mbtowcx: conversion exceeds guest character limits");
|
||||
*dst = static_cast<std::uint16_t>(converted);
|
||||
return static_cast<int>(result);
|
||||
}
|
||||
|
||||
char* APS5_VABI _Wctombx_nid_postfix(char* dst, wchar_t src, mbstate_t* st) {
|
||||
std::size_t result = std::wcrtomb(dst, src, st);
|
||||
if (result == static_cast<std::size_t>(-1))
|
||||
return nullptr;
|
||||
return dst + result;
|
||||
int APS5_VABI _Wctombx_nid_postfix(char* dst, std::uint16_t src, mbstate_t* st) {
|
||||
if (dst == nullptr || st == nullptr) throw std::invalid_argument("_Wctombx: invalid conversion arguments");
|
||||
const auto result = std::wcrtomb(dst, static_cast<wchar_t>(src), st);
|
||||
if (result == static_cast<std::size_t>(-1)) throw std::runtime_error("_Wctombx: invalid wide character");
|
||||
if (result > static_cast<std::size_t>(std::numeric_limits<int>::max())) throw std::runtime_error("_Wctombx: conversion size exceeds guest limits");
|
||||
return static_cast<int>(result);
|
||||
}
|
||||
|
||||
const short* APS5_VABI _Getpctype_nid_postfix() {
|
||||
|
|
|
|||
|
|
@ -4,47 +4,47 @@
|
|||
|
||||
extern "C" {
|
||||
|
||||
double cbrt_nid_postfix(double x) { return std::cbrt(x); }
|
||||
double asin_nid_postfix(double x) { return std::asin(x); }
|
||||
double acos_nid_postfix(double x) { return std::acos(x); }
|
||||
double exp_nid_postfix(double x) { return std::exp(x); }
|
||||
double atan_nid_postfix(double x) { return std::atan(x); }
|
||||
double tan_nid_postfix(double x) { return std::tan(x); }
|
||||
double log2_nid_postfix(double x) { return std::log2(x); }
|
||||
double log_nid_postfix(double x) { return std::log(x); }
|
||||
double APS5_VABI cbrt_nid_postfix(double x) { return std::cbrt(x); }
|
||||
double APS5_VABI asin_nid_postfix(double x) { return std::asin(x); }
|
||||
double APS5_VABI acos_nid_postfix(double x) { return std::acos(x); }
|
||||
double APS5_VABI exp_nid_postfix(double x) { return std::exp(x); }
|
||||
double APS5_VABI atan_nid_postfix(double x) { return std::atan(x); }
|
||||
double APS5_VABI tan_nid_postfix(double x) { return std::tan(x); }
|
||||
double APS5_VABI log2_nid_postfix(double x) { return std::log2(x); }
|
||||
double APS5_VABI log_nid_postfix(double x) { return std::log(x); }
|
||||
|
||||
float sinf_nid_postfix(float x) { return std::sin(x); }
|
||||
float cosf_nid_postfix(float x) { return std::cos(x); }
|
||||
float APS5_VABI sinf_nid_postfix(float x) { return std::sin(x); }
|
||||
float APS5_VABI cosf_nid_postfix(float x) { return std::cos(x); }
|
||||
|
||||
void APS5_VABI sincosf_nid_postfix(float x, float* sinp, float* cosp) {
|
||||
*sinp = std::sin(x);
|
||||
*cosp = std::cos(x);
|
||||
}
|
||||
|
||||
double sin_nid_postfix(double x) { return std::sin(x); }
|
||||
double cos_nid_postfix(double x) { return std::cos(x); }
|
||||
double APS5_VABI sin_nid_postfix(double x) { return std::sin(x); }
|
||||
double APS5_VABI cos_nid_postfix(double x) { return std::cos(x); }
|
||||
|
||||
void APS5_VABI sincos_nid_postfix(double x, double* sinp, double* cosp) {
|
||||
*sinp = std::sin(x);
|
||||
*cosp = std::cos(x);
|
||||
}
|
||||
|
||||
float atanf_nid_postfix(float x) { return std::atan(x); }
|
||||
double atan2_nid_postfix(double y, double x) { return std::atan2(y, x); }
|
||||
float powf_nid_postfix(float base, float exp) { return std::pow(base, exp); }
|
||||
double pow_nid_postfix(double base, double exp) { return std::pow(base, exp); }
|
||||
float expf_nid_postfix(float x) { return std::exp(x); }
|
||||
float exp2f_nid_postfix(float x) { return std::exp2(x); }
|
||||
float logf_nid_postfix(float x) { return std::log(x); }
|
||||
float log2f_nid_postfix(float x) { return std::log2(x); }
|
||||
double log10_nid_postfix(double x) { return std::log10(x); }
|
||||
float ldexpf_nid_postfix(float x, int exp) { return std::ldexp(x, exp); }
|
||||
double fmod_nid_postfix(double x, double y) { return std::fmod(x, y); }
|
||||
float roundf_nid_postfix(float x) { return std::round(x); }
|
||||
double round_nid_postfix(double x) { return std::round(x); }
|
||||
float APS5_VABI atanf_nid_postfix(float x) { return std::atan(x); }
|
||||
double APS5_VABI atan2_nid_postfix(double y, double x) { return std::atan2(y, x); }
|
||||
float APS5_VABI powf_nid_postfix(float base, float exp) { return std::pow(base, exp); }
|
||||
double APS5_VABI pow_nid_postfix(double base, double exp) { return std::pow(base, exp); }
|
||||
float APS5_VABI expf_nid_postfix(float x) { return std::exp(x); }
|
||||
float APS5_VABI exp2f_nid_postfix(float x) { return std::exp2(x); }
|
||||
float APS5_VABI logf_nid_postfix(float x) { return std::log(x); }
|
||||
float APS5_VABI log2f_nid_postfix(float x) { return std::log2(x); }
|
||||
double APS5_VABI log10_nid_postfix(double x) { return std::log10(x); }
|
||||
float APS5_VABI ldexpf_nid_postfix(float x, int exp) { return std::ldexp(x, exp); }
|
||||
double APS5_VABI fmod_nid_postfix(double x, double y) { return std::fmod(x, y); }
|
||||
float APS5_VABI roundf_nid_postfix(float x) { return std::round(x); }
|
||||
double APS5_VABI round_nid_postfix(double x) { return std::round(x); }
|
||||
|
||||
int __isfinite_nid_postfix(double x) { return std::isfinite(x) ? 1 : 0; }
|
||||
int __isnan_nid_postfix(double x) { return std::isnan(x) ? 1 : 0; }
|
||||
int __signbit_nid_postfix(double x) { return std::signbit(x) ? 1 : 0; }
|
||||
int APS5_VABI __isfinite_nid_postfix(double x) { return std::isfinite(x) ? 1 : 0; }
|
||||
int APS5_VABI __isnan_nid_postfix(double x) { return std::isnan(x) ? 1 : 0; }
|
||||
int APS5_VABI __signbit_nid_postfix(double x) { return std::signbit(x) ? 1 : 0; }
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
#include "prx/libc/include/GuestLocale.hpp"
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <cwchar>
|
||||
#include <climits>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <thread>
|
||||
|
|
@ -9,7 +11,7 @@
|
|||
extern "C" {
|
||||
extern GuestLocale::Implementation* _ZSt21_sceLibcClassicLocale_nid_postfix;
|
||||
GuestLocale::Implementation* APS5_VABI _ZNSt6locale16_GetgloballocaleEv_nid_postfix();
|
||||
void APS5_VABI _ZNSt6locale5_InitEv_nid_postfix();
|
||||
GuestLocale::Implementation* APS5_VABI _ZNSt6locale5_InitEv_nid_postfix();
|
||||
void APS5_VABI _ZNSt6locale5facet9_RegisterEv_nid_postfix(GuestLocale::Facet* self);
|
||||
void APS5_VABI _ZNSt8_LocinfoC1EPKc_nid_postfix(GuestLocale::LocinfoStorage* self, const char* localeName);
|
||||
void APS5_VABI _ZNSt8_LocinfoD1Ev_nid_postfix(GuestLocale::LocinfoStorage* self);
|
||||
|
|
@ -17,6 +19,8 @@ void APS5_VABI _ZNSt8ios_baseD2Ev_nid_postfix(GuestLocale::IosBase* self);
|
|||
const short* APS5_VABI _Getpctype_nid_postfix();
|
||||
const short* APS5_VABI _Getptolower_nid_postfix();
|
||||
const short* APS5_VABI _Getptoupper_nid_postfix();
|
||||
int APS5_VABI _Mbtowcx_nid_postfix(std::uint16_t* dst, const char* src, std::size_t count, std::mbstate_t* st);
|
||||
int APS5_VABI _Wctombx_nid_postfix(char* dst, std::uint16_t src, std::mbstate_t* st);
|
||||
void APS5_VABI _Locksyslock_nid_postfix();
|
||||
void APS5_VABI _Unlocksyslock_nid_postfix();
|
||||
|
||||
|
|
@ -40,8 +44,8 @@ static void RequireException(TAction action) {
|
|||
static void CheckGuestCalls() {
|
||||
auto* locale = _ZSt21_sceLibcClassicLocale_nid_postfix;
|
||||
Require(locale != nullptr && locale == _ZNSt6locale16_GetgloballocaleEv_nid_postfix());
|
||||
_ZNSt6locale5_InitEv_nid_postfix();
|
||||
_ZNSt6locale5_InitEv_nid_postfix();
|
||||
Require(_ZNSt6locale5_InitEv_nid_postfix() == locale);
|
||||
Require(_ZNSt6locale5_InitEv_nid_postfix() == locale);
|
||||
const std::byte* table = nullptr;
|
||||
std::memcpy(&table, locale, sizeof(table));
|
||||
void (APS5_VABI *retain)(GuestLocale::Facet*) = nullptr;
|
||||
|
|
@ -88,10 +92,10 @@ static void CheckCharacterTables() {
|
|||
const auto* lower = _Getptolower_nid_postfix();
|
||||
const auto* upper = _Getptoupper_nid_postfix();
|
||||
Require(classification[-1] == 0 && lower[-1] == -1 && upper[-1] == -1);
|
||||
Require(classification['A'] == 0x181 && classification['a'] == 0x182);
|
||||
Require(classification['G'] == 0x101 && classification['0'] == 0x84);
|
||||
Require(classification[' '] == 0x48 && classification['\t'] == 0x68);
|
||||
Require(classification['\n'] == 0x28 && classification['!'] == 0x10);
|
||||
Require(classification['A'] == 0x03 && classification['a'] == 0x11);
|
||||
Require(classification['G'] == 0x02 && classification['0'] == 0x21);
|
||||
Require(classification[' '] == 0x04 && classification['\t'] == 0xc0);
|
||||
Require(classification['\n'] == 0xc0 && classification['!'] == 0x08);
|
||||
for (int value = 0; value < 256; ++value) {
|
||||
Require(lower[value] == (value >= 'A' && value <= 'Z' ? value + 32 : value));
|
||||
Require(upper[value] == (value >= 'a' && value <= 'z' ? value - 32 : value));
|
||||
|
|
@ -99,6 +103,32 @@ static void CheckCharacterTables() {
|
|||
}
|
||||
}
|
||||
|
||||
static void CheckCharacterConversions() {
|
||||
const auto* classification = _Getpctype_nid_postfix();
|
||||
for (std::uint16_t value = 0; value < 128; ++value) {
|
||||
std::array<char, MB_LEN_MAX + 1> bytes{};
|
||||
bytes.fill('!');
|
||||
std::mbstate_t encodeState{};
|
||||
Require(_Wctombx_nid_postfix(bytes.data(), value, &encodeState) == 1);
|
||||
Require(bytes[0] == static_cast<char>(value) && bytes[1] == '!');
|
||||
std::array<std::uint16_t, 2> wide{0xffff, 0x1234};
|
||||
std::mbstate_t decodeState{};
|
||||
Require(_Mbtowcx_nid_postfix(wide.data(), bytes.data(), 2, &decodeState) == (value == 0 ? 0 : 1));
|
||||
Require(wide[0] == value && wide[1] == 0x1234);
|
||||
const bool alnum = (value >= '0' && value <= '9') || (value >= 'A' && value <= 'Z') || (value >= 'a' && value <= 'z');
|
||||
Require(((classification[static_cast<unsigned char>(bytes[0])] & 0x232) != 0) == alnum);
|
||||
}
|
||||
std::mbstate_t state{};
|
||||
char byte{};
|
||||
std::uint16_t wide{};
|
||||
RequireException([&] { _Mbtowcx_nid_postfix(&wide, "]", 0, &state); });
|
||||
RequireException([&] { _Mbtowcx_nid_postfix(nullptr, "]", 1, &state); });
|
||||
RequireException([&] { _Mbtowcx_nid_postfix(&wide, nullptr, 1, &state); });
|
||||
RequireException([&] { _Mbtowcx_nid_postfix(&wide, "]", 1, nullptr); });
|
||||
RequireException([&] { _Wctombx_nid_postfix(nullptr, ']', &state); });
|
||||
RequireException([&] { _Wctombx_nid_postfix(&byte, ']', nullptr); });
|
||||
}
|
||||
|
||||
static void CheckStreamDestruction() {
|
||||
struct GuardedStream {
|
||||
std::uint64_t before = 0x12345678;
|
||||
|
|
@ -118,6 +148,7 @@ int main() {
|
|||
CheckGuestCalls();
|
||||
CheckLocinfoAlignment();
|
||||
CheckCharacterTables();
|
||||
CheckCharacterConversions();
|
||||
CheckStreamDestruction();
|
||||
_Locksyslock_nid_postfix();
|
||||
_Locksyslock_nid_postfix();
|
||||
|
|
|
|||
Loading…
Reference in New Issue