Merge pull request #105 from SamG-Coder/codex/quake-native-imports

fix(relinker,libs): decode EMMS and add native string and thread APIs
This commit is contained in:
boykopovar 2026-09-29 01:59:28 +03:00 committed by GitHub
commit cc41e847c8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 176 additions and 1 deletions

View File

@ -5,6 +5,8 @@ target_sources(libc PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/specifics/windows/CrashReport.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/specifics/linux/DlIteratePhdr.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Strings.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/AllocatingStrings.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/WideConversion.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/StringExtensions.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Math.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Time.cpp

View File

@ -0,0 +1,82 @@
#include "prx/libc/include/ApplicationHeap.hpp"
#include "prx/libc/include/General.hpp"
#include <cerrno>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <memory>
#include <new>
#include <string>
#ifdef _WIN32
#include "prx/libc/include/WindowsFormatting.hpp"
#endif
extern "C" {
char* APS5_VABI strndup_nid_postfix(const char* source, std::size_t limit) {
std::size_t length = 0;
while (length < limit && source[length] != '\0') ++length;
try {
auto* result = static_cast<char*>(ApplicationHeapAllocate_nid_no_patch(length + 1));
if (!result) { errno = 12; return nullptr; }
std::memcpy(result, source, length);
result[length] = '\0';
return result;
} catch (const std::bad_alloc&) {
errno = 12;
return nullptr;
}
}
int APS5_VABI asprintf_nid_postfix(char** destination, const char* format, ...) {
if (!destination) { errno = 22; return -1; }
*destination = nullptr;
if (!format) { errno = 22; return -1; }
#ifdef _WIN32
__builtin_sysv_va_list args;
__builtin_sysv_va_start(args, format);
#else
std::va_list args;
va_start(args, format);
#endif
int result = -1;
try {
#ifdef _WIN32
std::string text;
const int count = LibcDetail::FormatWindows(nullptr, 0, format, args, &text);
const char* source = text.c_str();
#else
char* text = nullptr;
const int count = ::vasprintf(&text, format, args);
std::unique_ptr<char, decltype(&std::free)> owner(text, std::free);
const char* source = text;
#endif
if (count >= 0) {
auto* output = static_cast<char*>(ApplicationHeapAllocate_nid_no_patch(static_cast<std::size_t>(count) + 1));
if (output) {
std::memcpy(output, source, static_cast<std::size_t>(count) + 1);
*destination = output;
result = count;
} else errno = 12;
}
} catch (const std::bad_alloc&) {
errno = 12;
} catch (...) {
#ifdef _WIN32
__builtin_sysv_va_end(args);
#else
va_end(args);
#endif
throw;
}
#ifdef _WIN32
__builtin_sysv_va_end(args);
#else
va_end(args);
#endif
return result;
}
}

View File

@ -0,0 +1,19 @@
#include "prx/libc/include/general/VabiMacros.hpp"
#include <cerrno>
#include <cstddef>
#include <cstdint>
extern "C" std::size_t APS5_VABI wcstombs_nid_postfix(char* destination, const std::uint16_t* source, std::size_t capacity) {
std::size_t count = 0;
while (!destination || count < capacity) {
const auto value = source[count];
if (value > 255) {
errno = 86;
return static_cast<std::size_t>(-1);
}
if (destination) destination[count] = static_cast<char>(value);
if (value == 0) break;
++count;
}
return count;
}

View File

@ -20,6 +20,7 @@ add_library(libkernel SHARED EXCLUDE_FROM_ALL
${CMAKE_CURRENT_SOURCE_DIR}/Pthread/src/Rwlock.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Pthread/src/Sem.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Pthread/Posix/Attr.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Pthread/Posix/Barrier.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Pthread/Posix/Cond.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Pthread/Posix/Mutex.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Pthread/Posix/Rwlock.cpp

View File

@ -0,0 +1,61 @@
#include "prx/libc/include/General.hpp"
#include <condition_variable>
#include <cstdint>
#include <mutex>
#include <new>
struct PthreadBarrierPrivate {
std::mutex mutex;
std::condition_variable changed;
unsigned count;
unsigned arrived = 0;
unsigned active = 0;
std::uint64_t generation = 0;
};
extern "C" {
int APS5_VABI pthread_barrier_init_nid_postfix(PthreadBarrierPrivate** barrier, const void* attr, unsigned count) {
if (!barrier || count == 0) return 22;
if (attr) NotImplemented_nid_no_patch("pthread_barrier_init: non-default attributes");
try {
auto* value = new PthreadBarrierPrivate;
value->count = count;
*barrier = value;
return 0;
} catch (const std::bad_alloc&) {
return 12;
}
}
int APS5_VABI pthread_barrier_wait_nid_postfix(PthreadBarrierPrivate** barrier) {
if (!barrier || !*barrier) return 22;
auto& value = **barrier;
std::unique_lock lock(value.mutex);
const auto generation = value.generation;
++value.active;
if (++value.arrived == value.count) {
value.arrived = 0;
++value.generation;
value.changed.notify_all();
--value.active;
return -1;
}
value.changed.wait(lock, [&] { return value.generation != generation; });
--value.active;
return 0;
}
int APS5_VABI pthread_barrier_destroy_nid_postfix(PthreadBarrierPrivate** barrier) {
if (!barrier || !*barrier) return 22;
auto* value = *barrier;
{
std::lock_guard lock(value->mutex);
if (value->active != 0) return 16;
}
delete value;
*barrier = nullptr;
return 0;
}
}

View File

@ -57,6 +57,15 @@ Pthread APS5_VABI pthread_self_nid_postfix(void) {
return scePthreadSelf();
}
int APS5_VABI pthread_equal_nid_postfix(Pthread first, Pthread second) {
return first == second;
}
int APS5_VABI sched_yield_nid_postfix(void) {
std::this_thread::yield();
return 0;
}
int APS5_VABI pthread_setcancelstate_nid_postfix(int state, int* old_state) {
return PosixThread::ToErrno(scePthreadSetcancelstate(state, old_state));
}

View File

@ -130,6 +130,7 @@ inline constexpr std::uint8_t TwoByteModRmRangeFMin = 0x38;
inline constexpr std::uint8_t TwoByteModRmRangeFMax = 0x3A;
inline constexpr std::uint8_t TwoByteModRmRangeGMin = 0x54;
inline constexpr std::uint8_t TwoByteModRmRangeGMax = 0x7F;
inline constexpr std::uint8_t TwoByteEmms = 0x77;
inline constexpr std::uint8_t TwoByteModRmRangeHMin = 0xD0;
inline constexpr std::uint8_t TwoByteModRmRangeHMax = 0xFE;
inline constexpr std::uint8_t TwoByteNopModRm = 0x1F;

View File

@ -252,7 +252,7 @@ std::size_t X64InstructionDecoder::Decode(const std::uint8_t* data, std::size_t
(opcode >= TwoByteModRmRangeCMin && opcode <= TwoByteModRmRangeCMax) ||
(opcode >= TwoByteModRmRangeDMin && opcode <= TwoByteModRmRangeDMax) ||
(opcode >= TwoByteModRmRangeEMin && opcode <= TwoByteModRmRangeEMax) ||
(opcode >= TwoByteModRmRangeGMin && opcode <= TwoByteModRmRangeGMax) ||
(opcode >= TwoByteModRmRangeGMin && opcode <= TwoByteModRmRangeGMax && opcode != TwoByteEmms) ||
(opcode >= TwoByteModRmRangeHMin && opcode <= TwoByteModRmRangeHMax) ||
(opcode >= TwoByteModRmRangeIMin && opcode <= TwoByteModRmRangeIMax) ||
(opcode >= TwoBytePrefetchGrpMin && opcode <= TwoBytePrefetchGrpMax) ||