format all source code with clang-format

This commit is contained in:
DH 2025-04-05 22:50:45 +03:00
parent 6bbaf18e71
commit 42cb5d7977
1234 changed files with 90082 additions and 82954 deletions

View file

@ -110,9 +110,9 @@ enum class ErrorCode : int {
}; };
} // namespace orbis } // namespace orbis
#define ORBIS_RET_ON_ERROR(...) \ #define ORBIS_RET_ON_ERROR(...) \
do { \ do { \
if (auto errc___ = (__VA_ARGS__); errc___ != ::orbis::ErrorCode{}) { \ if (auto errc___ = (__VA_ARGS__); errc___ != ::orbis::ErrorCode{}) { \
return errc___; \ return errc___; \
} \ } \
} while (false) } while (false)

View file

@ -65,8 +65,8 @@ struct ProcessOps {
uint64_t arg3); uint64_t arg3);
SysResult (*dynlib_unload_prx)(Thread *thread, ModuleHandle handle); SysResult (*dynlib_unload_prx)(Thread *thread, ModuleHandle handle);
SysResult (*thr_create)(Thread *thread, ptr<UContext> ctxt, SysResult (*thr_create)(Thread *thread, ptr<UContext> ctxt, ptr<slong> arg,
ptr<slong> arg, sint flags); sint flags);
SysResult (*thr_new)(Thread *thread, ptr<thr_param> param, sint param_size); SysResult (*thr_new)(Thread *thread, ptr<thr_param> param, sint param_size);
SysResult (*thr_exit)(Thread *thread, ptr<slong> state); SysResult (*thr_exit)(Thread *thread, ptr<slong> state);
SysResult (*thr_kill)(Thread *thread, slong id, sint sig); SysResult (*thr_kill)(Thread *thread, slong id, sint sig);

View file

@ -83,7 +83,6 @@ struct UContext {
static_assert(sizeof(UContext) == 0x500); static_assert(sizeof(UContext) == 0x500);
enum Signal { enum Signal {
kSigHup = 1, kSigHup = 1,
kSigInt = 2, kSigInt = 2,

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "orbis-config.hpp"
#include "error/ErrorCode.hpp" #include "error/ErrorCode.hpp"
#include "orbis-config.hpp"
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
@ -49,8 +49,7 @@ struct Uio {
return {}; return {};
} }
template<typename T> template <typename T> ErrorCode write(const T &object) {
ErrorCode write(const T &object) {
return write(&object, sizeof(T)); return write(&object, sizeof(T));
} }
}; };

View file

@ -54,7 +54,6 @@ inline constexpr auto kUmtxOpNwakePrivate = 21;
inline constexpr auto kUmtxOpMutexWake2 = 22; inline constexpr auto kUmtxOpMutexWake2 = 22;
inline constexpr auto kUmtxOpMutexWake3 = 23; inline constexpr auto kUmtxOpMutexWake3 = 23;
inline constexpr auto kSemNamed = 2; inline constexpr auto kSemNamed = 2;
struct umtx { struct umtx {

View file

@ -203,7 +203,8 @@ static orbis::SysResult doRelocation(orbis::Process *process,
auto &defModule = module->importedModules.at(symbol.moduleIndex); auto &defModule = module->importedModules.at(symbol.moduleIndex);
if (!defModule) { if (!defModule) {
// std::printf("'%s' ('%s') uses undefined symbol '%llx' in unloaded module " // std::printf("'%s' ('%s') uses undefined symbol '%llx' in unloaded
// module "
// "'%s', rel %u\n", // "'%s', rel %u\n",
// module->moduleName, module->soName, // module->moduleName, module->soName,
// (unsigned long long)symbol.id, // (unsigned long long)symbol.id,
@ -295,7 +296,8 @@ static orbis::SysResult doRelocation(orbis::Process *process,
if (defObj == nullptr) { if (defObj == nullptr) {
return orbis::ErrorCode::INVAL; return orbis::ErrorCode::INVAL;
} }
*where32 = S ? reinterpret_cast<std::uintptr_t>(defObj->base) + S + A - P : 0; *where32 =
S ? reinterpret_cast<std::uintptr_t>(defObj->base) + S + A - P : 0;
return {}; return {};
} }
// case kRelCopy: // case kRelCopy:

View file

@ -12,8 +12,8 @@ static orbis::ErrorCode pipe_read(orbis::File *file, orbis::Uio *uio,
while (true) { while (true) {
if (pipe->data.empty()) { if (pipe->data.empty()) {
// pipe->cv.wait(file->mtx); // pipe->cv.wait(file->mtx);
// ORBIS_LOG_ERROR(__FUNCTION__, "wakeup", thread->name, thread->tid, file); // ORBIS_LOG_ERROR(__FUNCTION__, "wakeup", thread->name, thread->tid,
// continue; // file); continue;
return orbis::ErrorCode::WOULDBLOCK; return orbis::ErrorCode::WOULDBLOCK;
} }
@ -32,7 +32,8 @@ static orbis::ErrorCode pipe_read(orbis::File *file, orbis::Uio *uio,
uio->offset += size; uio->offset += size;
std::memcpy(vec.base, pipe->data.data(), size); std::memcpy(vec.base, pipe->data.data(), size);
ORBIS_LOG_ERROR(__FUNCTION__, thread->name, thread->tid, file, size, pipe->data.size(), uio->offset, file->nextOff); ORBIS_LOG_ERROR(__FUNCTION__, thread->name, thread->tid, file, size,
pipe->data.size(), uio->offset, file->nextOff);
if (pipe->data.size() == size) { if (pipe->data.size() == size) {
pipe->data.clear(); pipe->data.clear();
@ -69,9 +70,10 @@ static orbis::ErrorCode pipe_write(orbis::File *file, orbis::Uio *uio,
uio->resid -= cnt; uio->resid -= cnt;
uio->offset += cnt; uio->offset += cnt;
ORBIS_LOG_ERROR(__FUNCTION__, thread->name, thread->tid, file, uio->resid, uio->offset, file->nextOff, cnt); ORBIS_LOG_ERROR(__FUNCTION__, thread->name, thread->tid, file, uio->resid,
uio->offset, file->nextOff, cnt);
thread->where(); thread->where();
return{}; return {};
} }
static orbis::FileOps pipe_ops = { static orbis::FileOps pipe_ops = {
@ -79,7 +81,8 @@ static orbis::FileOps pipe_ops = {
.write = pipe_write, .write = pipe_write,
}; };
std::pair<orbis::Ref<orbis::Pipe>, orbis::Ref<orbis::Pipe>> orbis::createPipe() { std::pair<orbis::Ref<orbis::Pipe>, orbis::Ref<orbis::Pipe>>
orbis::createPipe() {
auto a = knew<Pipe>(); auto a = knew<Pipe>();
auto b = knew<Pipe>(); auto b = knew<Pipe>();
a->event = knew<EventEmitter>(); a->event = knew<EventEmitter>();

View file

@ -1,15 +1,12 @@
#include "sys/sysproto.hpp" #include "sys/sysproto.hpp"
orbis::SysResult orbis::sys_getcontext(Thread *thread, orbis::SysResult orbis::sys_getcontext(Thread *thread, ptr<UContext> ucp) {
ptr<UContext> ucp) {
return ErrorCode::NOSYS; return ErrorCode::NOSYS;
} }
orbis::SysResult orbis::sys_setcontext(Thread *thread, orbis::SysResult orbis::sys_setcontext(Thread *thread, ptr<UContext> ucp) {
ptr<UContext> ucp) {
return ErrorCode::NOSYS; return ErrorCode::NOSYS;
} }
orbis::SysResult orbis::sys_swapcontext(Thread *thread, orbis::SysResult orbis::sys_swapcontext(Thread *thread, ptr<UContext> oucp,
ptr<UContext> oucp,
ptr<UContext> ucp) { ptr<UContext> ucp) {
return ErrorCode::NOSYS; return ErrorCode::NOSYS;
} }

View file

@ -148,7 +148,8 @@ orbis::SysResult orbis::sys_cpuset_setaffinity(Thread *thread, cpulevel_t level,
auto threadHandle = whichThread->getNativeHandle(); auto threadHandle = whichThread->getNativeHandle();
auto hostCpuSet = toHostCpuSet(whichThread->affinity); auto hostCpuSet = toHostCpuSet(whichThread->affinity);
ORBIS_LOG_ERROR(__FUNCTION__, threadHandle, thread->tid, id); ORBIS_LOG_ERROR(__FUNCTION__, threadHandle, thread->tid, id);
if (pthread_setaffinity_np(threadHandle, sizeof(hostCpuSet), &hostCpuSet)) { if (pthread_setaffinity_np(threadHandle, sizeof(hostCpuSet),
&hostCpuSet)) {
ORBIS_LOG_ERROR(__FUNCTION__, ORBIS_LOG_ERROR(__FUNCTION__,
"failed to set affinity mask for host thread", "failed to set affinity mask for host thread",
whichThread->hostTid, whichThread->affinity.bits); whichThread->hostTid, whichThread->affinity.bits);

View file

@ -2,8 +2,8 @@
#include "orbis/utils/Logs.hpp" #include "orbis/utils/Logs.hpp"
#include "stat.hpp" #include "stat.hpp"
#include "sys/sysproto.hpp" #include "sys/sysproto.hpp"
#include "thread/Thread.hpp"
#include "thread/Process.hpp" #include "thread/Process.hpp"
#include "thread/Thread.hpp"
orbis::SysResult orbis::sys_getdtablesize(Thread *thread) { orbis::SysResult orbis::sys_getdtablesize(Thread *thread) {
return ErrorCode::NOSYS; return ErrorCode::NOSYS;

View file

@ -1,7 +1,7 @@
#include "sys/sysproto.hpp" #include "sys/sysproto.hpp"
#include "thread/Thread.hpp"
#include "thread/Process.hpp" #include "thread/Process.hpp"
#include "thread/ProcessOps.hpp" #include "thread/ProcessOps.hpp"
#include "thread/Thread.hpp"
orbis::SysResult orbis::sys_execve(Thread *thread, ptr<char> fname, orbis::SysResult orbis::sys_execve(Thread *thread, ptr<char> fname,
ptr<ptr<char>> argv, ptr<ptr<char>> envv) { ptr<ptr<char>> argv, ptr<ptr<char>> envv) {

View file

@ -1,11 +1,11 @@
#include "KernelContext.hpp" #include "KernelContext.hpp"
#include "sys/sysproto.hpp" #include "sys/sysproto.hpp"
#include "thread/Process.hpp"
#include "thread/ProcessOps.hpp" #include "thread/ProcessOps.hpp"
#include "utils/Logs.hpp" #include "utils/Logs.hpp"
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
#include "thread/Process.hpp"
orbis::SysResult orbis::sys_exit(Thread *thread, sint status) { orbis::SysResult orbis::sys_exit(Thread *thread, sint status) {
if (auto exit = thread->tproc->ops->exit) { if (auto exit = thread->tproc->ops->exit) {

View file

@ -1,8 +1,8 @@
#include "file.hpp" #include "file.hpp"
#include "orbis/utils/Logs.hpp" #include "orbis/utils/Logs.hpp"
#include "sys/sysproto.hpp" #include "sys/sysproto.hpp"
#include "thread/Thread.hpp"
#include "thread/Process.hpp" #include "thread/Process.hpp"
#include "thread/Thread.hpp"
#include "uio.hpp" #include "uio.hpp"
#include <sstream> #include <sstream>

View file

@ -1,6 +1,6 @@
#include "sys/sysproto.hpp" #include "sys/sysproto.hpp"
#include "thread/Thread.hpp"
#include "thread/Process.hpp" #include "thread/Process.hpp"
#include "thread/Thread.hpp"
#include "utils/Logs.hpp" #include "utils/Logs.hpp"
#include <pipe.hpp> #include <pipe.hpp>

View file

@ -59,12 +59,12 @@ orbis::SysResult orbis::sys_rtprio_thread(Thread *thread, sint function,
hostPolicy = SCHED_IDLE; hostPolicy = SCHED_IDLE;
} }
if (pthread_setschedparam(targetThread->getNativeHandle(), if (pthread_setschedparam(targetThread->getNativeHandle(), hostPolicy,
hostPolicy, &hostParam)) { &hostParam)) {
ORBIS_LOG_ERROR(__FUNCTION__, "failed to set host priority", ORBIS_LOG_ERROR(
hostPriority, targetThread->prio.prio, __FUNCTION__, "failed to set host priority", hostPriority,
targetThread->prio.type, errno, targetThread->prio.prio, targetThread->prio.type, errno,
targetThread->getNativeHandle(), prioMin, prioMax, errno); targetThread->getNativeHandle(), prioMin, prioMax, errno);
} }
} else { } else {
ORBIS_LOG_ERROR(__FUNCTION__, "set host priority", hostPriority, ORBIS_LOG_ERROR(__FUNCTION__, "set host priority", hostPriority,

View file

@ -1165,8 +1165,7 @@ orbis::sys_dynlib_get_info_ex(Thread *thread, SceKernelModule handle,
result.ehFrame = module->ehFrame; result.ehFrame = module->ehFrame;
result.ehFrameHdrSize = module->ehFrameHdrSize; result.ehFrameHdrSize = module->ehFrameHdrSize;
result.ehFrameSize = module->ehFrameSize; result.ehFrameSize = module->ehFrameSize;
std::memcpy(result.segments, module->segments, std::memcpy(result.segments, module->segments, sizeof(ModuleSegment) * 2);
sizeof(ModuleSegment) * 2);
result.segmentCount = 2; result.segmentCount = 2;
result.refCount = 1; result.refCount = 1;
ORBIS_LOG_WARNING(__FUNCTION__, result.id, result.name, result.tlsIndex, ORBIS_LOG_WARNING(__FUNCTION__, result.id, result.name, result.tlsIndex,

View file

@ -140,14 +140,15 @@ orbis::SysResult orbis::sys_sigreturn(Thread *thread, ptr<UContext> sigcntxp) {
ORBIS_LOG_WARNING(__FUNCTION__, sigcntxp); ORBIS_LOG_WARNING(__FUNCTION__, sigcntxp);
// auto sigRet = thread->sigReturns.front(); // auto sigRet = thread->sigReturns.front();
// thread->sigReturns.erase(thread->sigReturns.begin(), thread->sigReturns.begin() + 1); // thread->sigReturns.erase(thread->sigReturns.begin(),
// writeRegister(thread->context, RegisterId::rip, sigRet.rip); // thread->sigReturns.begin() + 1); writeRegister(thread->context,
// writeRegister(thread->context, RegisterId::rsp, sigRet.rsp); // RegisterId::rip, sigRet.rip); writeRegister(thread->context,
// ORBIS_LOG_ERROR(__FUNCTION__, sigRet.rip, sigRet.rsp); // RegisterId::rsp, sigRet.rsp); ORBIS_LOG_ERROR(__FUNCTION__, sigRet.rip,
// sigRet.rsp);
return {}; return {};
} }
orbis::SysResult orbis::nosys(Thread *thread) { orbis::SysResult orbis::nosys(Thread *thread) {
thread->sendSignal(kSigSys); thread->sendSignal(kSigSys);
return{}; return {};
} }

View file

@ -2,6 +2,6 @@
#include <thread> #include <thread>
orbis::SysResult orbis::sys_yield(Thread *thread) { orbis::SysResult orbis::sys_yield(Thread *thread) {
std::this_thread::yield(); std::this_thread::yield();
return {}; return {};
} }

View file

@ -1,11 +1,10 @@
#include "sys/sysproto.hpp" #include "sys/sysproto.hpp"
#include "thread/Process.hpp"
#include "thread/ProcessOps.hpp" #include "thread/ProcessOps.hpp"
#include "thread/Thread.hpp" #include "thread/Thread.hpp"
#include "thread/Process.hpp"
#include "ucontext.hpp" #include "ucontext.hpp"
orbis::SysResult orbis::sys_thr_create(Thread *thread, orbis::SysResult orbis::sys_thr_create(Thread *thread, ptr<UContext> ctxt,
ptr<UContext> ctxt,
ptr<slong> arg, sint flags) { ptr<slong> arg, sint flags) {
if (auto thr_create = thread->tproc->ops->thr_create) { if (auto thr_create = thread->tproc->ops->thr_create) {
return thr_create(thread, ctxt, arg, flags); return thr_create(thread, ctxt, arg, flags);

View file

@ -1,8 +1,8 @@
#include "file.hpp" #include "file.hpp"
#include "sys/sysproto.hpp" #include "sys/sysproto.hpp"
#include "thread/Process.hpp"
#include "thread/ProcessOps.hpp" #include "thread/ProcessOps.hpp"
#include "thread/Thread.hpp" #include "thread/Thread.hpp"
#include "thread/Process.hpp"
#include "uio.hpp" #include "uio.hpp"
#include "utils/Logs.hpp" #include "utils/Logs.hpp"
#include <sys/socket.h> #include <sys/socket.h>
@ -128,7 +128,8 @@ orbis::SysResult orbis::sys_recvfrom(Thread *thread, sint s, caddr_t buf,
} }
if (auto recvfrom = file->ops->recvfrom) { if (auto recvfrom = file->ops->recvfrom) {
return SysResult::notAnError(recvfrom(file.get(), buf, len, flags, from, fromlenaddr, thread)); return SysResult::notAnError(
recvfrom(file.get(), buf, len, flags, from, fromlenaddr, thread));
} }
return ErrorCode::NOTSUP; return ErrorCode::NOTSUP;

View file

@ -1,9 +1,9 @@
#include "file.hpp" #include "file.hpp"
#include "orbis-config.hpp" #include "orbis-config.hpp"
#include "sys/sysproto.hpp" #include "sys/sysproto.hpp"
#include "thread/Process.hpp"
#include "thread/ProcessOps.hpp" #include "thread/ProcessOps.hpp"
#include "thread/Thread.hpp" #include "thread/Thread.hpp"
#include "thread/Process.hpp"
orbis::SysResult orbis::sys_shm_open(Thread *thread, ptr<const char> path, orbis::SysResult orbis::sys_shm_open(Thread *thread, ptr<const char> path,
sint flags, mode_t mode) { sint flags, mode_t mode) {

View file

@ -1,8 +1,8 @@
#include "stat.hpp" #include "stat.hpp"
#include "sys/sysproto.hpp" #include "sys/sysproto.hpp"
#include "thread/Process.hpp"
#include "thread/ProcessOps.hpp" #include "thread/ProcessOps.hpp"
#include "thread/Thread.hpp" #include "thread/Thread.hpp"
#include "thread/Process.hpp"
#include "utils/Logs.hpp" #include "utils/Logs.hpp"
#include <filesystem> #include <filesystem>
#include <span> #include <span>
@ -71,8 +71,8 @@ orbis::SysResult orbis::sys_chroot(Thread *thread, ptr<char> path) {
} }
// volatile bool debuggerPresent = false; // volatile bool debuggerPresent = false;
orbis::SysResult orbis::sys_open(Thread *thread, ptr<const char> path, sint flags, orbis::SysResult orbis::sys_open(Thread *thread, ptr<const char> path,
sint mode) { sint flags, sint mode) {
if (auto open = thread->tproc->ops->open) { if (auto open = thread->tproc->ops->open) {
Ref<File> file; Ref<File> file;
auto result = open(thread, path, flags, mode, &file); auto result = open(thread, path, flags, mode, &file);
@ -82,16 +82,18 @@ orbis::SysResult orbis::sys_open(Thread *thread, ptr<const char> path, sint flag
auto fd = thread->tproc->fileDescriptors.insert(file); auto fd = thread->tproc->fileDescriptors.insert(file);
thread->retval[0] = fd; thread->retval[0] = fd;
// if (path == std::string_view{"/app0/psm/Application/resource/Sce.Vsh.ShellUI.SystemMessage.rco"}) { // if (path ==
// std::string_view{"/app0/psm/Application/resource/Sce.Vsh.ShellUI.SystemMessage.rco"})
// {
ORBIS_LOG_SUCCESS(__FUNCTION__, thread->tid, path, flags, mode, fd); ORBIS_LOG_SUCCESS(__FUNCTION__, thread->tid, path, flags, mode, fd);
if (path == std::string_view{"/app0/wave/wave1.fbxd"}) { if (path == std::string_view{"/app0/wave/wave1.fbxd"}) {
thread->where(); thread->where();
} }
// while (debuggerPresent == false) { // while (debuggerPresent == false) {
// std::this_thread::sleep_for(std::chrono::seconds(1)); // std::this_thread::sleep_for(std::chrono::seconds(1));
// } // }
// // thread->where(); // // thread->where();
// } // }
return {}; return {};
} }
@ -288,13 +290,14 @@ orbis::SysResult orbis::sys_readlink(Thread *thread, ptr<char> path,
} }
Ref<File> file; Ref<File> file;
if (auto error = thread->tproc->ops->open(thread, path, 0, 0, &file); error.value()) { if (auto error = thread->tproc->ops->open(thread, path, 0, 0, &file);
error.value()) {
return error; return error;
} }
ORBIS_RET_ON_ERROR(uwriteRaw(buf, _path, pathLen)); ORBIS_RET_ON_ERROR(uwriteRaw(buf, _path, pathLen));
thread->retval[0] = pathLen; thread->retval[0] = pathLen;
return{}; return {};
} }
orbis::SysResult orbis::sys_readlinkat(Thread *thread, sint fd, ptr<char> path, orbis::SysResult orbis::sys_readlinkat(Thread *thread, sint fd, ptr<char> path,
ptr<char> buf, size_t bufsize) { ptr<char> buf, size_t bufsize) {

View file

@ -1,14 +1,14 @@
#include "sys/sysproto.hpp" #include "sys/sysproto.hpp"
#include "thread/Thread.hpp"
#include "thread/Process.hpp" #include "thread/Process.hpp"
#include "thread/Thread.hpp"
#include <mutex> #include <mutex>
#include <string> #include <string>
orbis::SysResult orbis::sys___getcwd(Thread *thread, ptr<char> buf, orbis::SysResult orbis::sys___getcwd(Thread *thread, ptr<char> buf,
uint buflen) { uint buflen) {
std::string cwd; std::string cwd;
{ {
std::lock_guard lock(thread->tproc->mtx); std::lock_guard lock(thread->tproc->mtx);
cwd = std::string(thread->tproc->cwd); cwd = std::string(thread->tproc->cwd);
@ -19,5 +19,5 @@ orbis::SysResult orbis::sys___getcwd(Thread *thread, ptr<char> buf,
} }
ORBIS_RET_ON_ERROR(uwriteRaw(buf, cwd.data(), cwd.size() + 1)); ORBIS_RET_ON_ERROR(uwriteRaw(buf, cwd.data(), cwd.size() + 1));
return{}; return {};
} }

View file

@ -1,7 +1,7 @@
#include "sys/sysproto.hpp" #include "sys/sysproto.hpp"
#include "thread/Process.hpp"
#include "thread/ProcessOps.hpp" #include "thread/ProcessOps.hpp"
#include "thread/Thread.hpp" #include "thread/Thread.hpp"
#include "thread/Process.hpp"
orbis::SysResult orbis::sys_mount(Thread *thread, ptr<char> type, orbis::SysResult orbis::sys_mount(Thread *thread, ptr<char> type,
ptr<char> path, sint flags, caddr_t data) { ptr<char> path, sint flags, caddr_t data) {

View file

@ -1,8 +1,8 @@
#include "error.hpp" #include "error.hpp"
#include "sys/sysproto.hpp" #include "sys/sysproto.hpp"
#include "thread/Process.hpp"
#include "thread/ProcessOps.hpp" #include "thread/ProcessOps.hpp"
#include "thread/Thread.hpp" #include "thread/Thread.hpp"
#include "thread/Process.hpp"
orbis::SysResult orbis::sys_sbrk(Thread *, sint) { orbis::SysResult orbis::sys_sbrk(Thread *, sint) {
return ErrorCode::OPNOTSUPP; return ErrorCode::OPNOTSUPP;

View file

@ -47,7 +47,8 @@ void shared_mutex::impl_lock_shared(unsigned val) {
if ((old % c_sig) + c_one >= c_sig) if ((old % c_sig) + c_one >= c_sig)
std::abort(); // "shared_mutex overflow" std::abort(); // "shared_mutex overflow"
while (impl_wait() != std::errc{}) {} while (impl_wait() != std::errc{}) {
}
lock_downgrade(); lock_downgrade();
} }
void shared_mutex::impl_unlock_shared(unsigned old) { void shared_mutex::impl_unlock_shared(unsigned old) {
@ -80,7 +81,7 @@ std::errc shared_mutex::impl_wait() {
} }
} }
return{}; return {};
} }
void shared_mutex::impl_signal() { void shared_mutex::impl_signal() {
m_value += c_sig; m_value += c_sig;
@ -120,7 +121,8 @@ void shared_mutex::impl_lock(unsigned val) {
if ((old % c_sig) + c_one >= c_sig) if ((old % c_sig) + c_one >= c_sig)
std::abort(); // "shared_mutex overflow" std::abort(); // "shared_mutex overflow"
while (impl_wait() != std::errc{}) {} while (impl_wait() != std::errc{}) {
}
} }
void shared_mutex::impl_unlock(unsigned old) { void shared_mutex::impl_unlock(unsigned old) {
if (old - c_one >= c_err) if (old - c_one >= c_err)
@ -152,7 +154,8 @@ void shared_mutex::impl_lock_upgrade() {
return; return;
} }
while (impl_wait() != std::errc{}) {} while (impl_wait() != std::errc{}) {
}
} }
bool shared_mutex::lock_forced(int count) { bool shared_mutex::lock_forced(int count) {
if (count == 0) if (count == 0)

View file

@ -102,7 +102,7 @@ add_subdirectory(yaml-cpp)
# OpenGL # OpenGL
if (NOT ANDROID) if (NOT ANDROID AND NOT WITHOUT_OPENGL)
find_package(OpenGL REQUIRED OPTIONAL_COMPONENTS EGL) find_package(OpenGL REQUIRED OPTIONAL_COMPONENTS EGL)
add_library(3rdparty_opengl INTERFACE) add_library(3rdparty_opengl INTERFACE)
@ -212,7 +212,7 @@ endif()
add_subdirectory(asmjit EXCLUDE_FROM_ALL) add_subdirectory(asmjit EXCLUDE_FROM_ALL)
# OpenAL # OpenAL
if (NOT ANDROID) if (NOT ANDROID AND NOT WITHOUT_OPENAL)
add_subdirectory(OpenAL EXCLUDE_FROM_ALL) add_subdirectory(OpenAL EXCLUDE_FROM_ALL)
else() else()
add_library(3rdparty_openal INTERFACE) add_library(3rdparty_openal INTERFACE)
@ -303,7 +303,7 @@ endif()
# GLEW # GLEW
add_library(3rdparty_glew INTERFACE) add_library(3rdparty_glew INTERFACE)
if(NOT MSVC AND NOT ANDROID) if(NOT MSVC AND NOT ANDROID AND NOT WITHOUT_OPENGLEW)
find_package(GLEW REQUIRED) find_package(GLEW REQUIRED)
target_link_libraries(3rdparty_glew INTERFACE GLEW::GLEW) target_link_libraries(3rdparty_glew INTERFACE GLEW::GLEW)
endif() endif()

View file

@ -2,6 +2,7 @@ option(ZSTD_BUILD_PROGRAMS "BUILD PROGRAMS" OFF)
option(ZSTD_BUILD_SHARED "BUILD SHARED LIBRARIES" OFF) option(ZSTD_BUILD_SHARED "BUILD SHARED LIBRARIES" OFF)
option(ZSTD_BUILD_STATIC "BUILD STATIC LIBRARIES" ON) option(ZSTD_BUILD_STATIC "BUILD STATIC LIBRARIES" ON)
option(ZSTD_BUILD_TESTS "BUILD TESTS" OFF) option(ZSTD_BUILD_TESTS "BUILD TESTS" OFF)
option(ZSTD_USE_STATIC_RUNTIME "LINK TO STATIC RUN-TIME LIBRARIES" ON)
add_subdirectory(zstd/build/cmake EXLUDE_FROM_ALL) add_subdirectory(zstd/build/cmake EXLUDE_FROM_ALL)
add_library(3rdparty_zstd INTERFACE) add_library(3rdparty_zstd INTERFACE)

View file

@ -101,8 +101,8 @@ if(MSVC)
add_compile_options(/MP) add_compile_options(/MP)
endif() endif()
if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8) if(CMAKE_SIZEOF_VOID_P AND NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
message( FATAL_ERROR "RPCS3 can only be compiled on 64-bit platforms." ) message( FATAL_ERROR "RPCS3 can only be compiled on 64-bit platforms. ${CMAKE_SIZEOF_VOID_P}" )
endif() endif()
find_program(CCACHE_FOUND ccache) find_program(CCACHE_FOUND ccache)

View file

@ -19,7 +19,8 @@ struct bf_base
using compact_type = std::conditional_t<can_be_packed, std::conditional_t<std::is_unsigned_v<vtype>, uint, int>, vtype>; using compact_type = std::conditional_t<can_be_packed, std::conditional_t<std::is_unsigned_v<vtype>, uint, int>, vtype>;
// Datatype bitsize // Datatype bitsize
static constexpr uint bitmax = sizeof(T) * 8; static_assert(N - 1 < bitmax, "bf_base<> error: N out of bounds"); static constexpr uint bitmax = sizeof(T) * 8;
static_assert(N - 1 < bitmax, "bf_base<> error: N out of bounds");
// Field bitsize // Field bitsize
static constexpr uint bitsize = N; static constexpr uint bitsize = N;
@ -44,7 +45,8 @@ struct bf_t : bf_base<T, N>
using compact_type = typename bf_t::compact_type; using compact_type = typename bf_t::compact_type;
// Field offset // Field offset
static constexpr uint bitpos = I; static_assert(bitpos + N <= bf_t::bitmax, "bf_t<> error: I out of bounds"); static constexpr uint bitpos = I;
static_assert(bitpos + N <= bf_t::bitmax, "bf_t<> error: I out of bounds");
// Get bitmask of size N, at I pos // Get bitmask of size N, at I pos
static constexpr utype data_mask() static constexpr utype data_mask()
@ -92,64 +94,64 @@ struct bf_t : bf_base<T, N>
} }
// Store bitfield value // Store bitfield value
bf_t& operator =(compact_type value) noexcept bf_t& operator=(compact_type value) noexcept
{ {
this->m_data = static_cast<vtype>((this->m_data & ~data_mask()) | insert(value)); this->m_data = static_cast<vtype>((this->m_data & ~data_mask()) | insert(value));
return *this; return *this;
} }
compact_type operator ++(int) compact_type operator++(int)
{ {
compact_type result = *this; compact_type result = *this;
*this = static_cast<compact_type>(result + 1u); *this = static_cast<compact_type>(result + 1u);
return result; return result;
} }
bf_t& operator ++() bf_t& operator++()
{ {
return *this = static_cast<compact_type>(*this + 1u); return *this = static_cast<compact_type>(*this + 1u);
} }
compact_type operator --(int) compact_type operator--(int)
{ {
compact_type result = *this; compact_type result = *this;
*this = static_cast<compact_type>(result - 1u); *this = static_cast<compact_type>(result - 1u);
return result; return result;
} }
bf_t& operator --() bf_t& operator--()
{ {
return *this = static_cast<compact_type>(*this - 1u); return *this = static_cast<compact_type>(*this - 1u);
} }
bf_t& operator +=(compact_type right) bf_t& operator+=(compact_type right)
{ {
return *this = static_cast<compact_type>(*this + right); return *this = static_cast<compact_type>(*this + right);
} }
bf_t& operator -=(compact_type right) bf_t& operator-=(compact_type right)
{ {
return *this = static_cast<compact_type>(*this - right); return *this = static_cast<compact_type>(*this - right);
} }
bf_t& operator *=(compact_type right) bf_t& operator*=(compact_type right)
{ {
return *this = static_cast<compact_type>(*this * right); return *this = static_cast<compact_type>(*this * right);
} }
bf_t& operator &=(compact_type right) bf_t& operator&=(compact_type right)
{ {
this->m_data &= static_cast<vtype>(((static_cast<utype>(right + 0u) & bf_t::vmask) << bitpos) | ~(bf_t::vmask << bitpos)); this->m_data &= static_cast<vtype>(((static_cast<utype>(right + 0u) & bf_t::vmask) << bitpos) | ~(bf_t::vmask << bitpos));
return *this; return *this;
} }
bf_t& operator |=(compact_type right) bf_t& operator|=(compact_type right)
{ {
this->m_data |= static_cast<vtype>((static_cast<utype>(right + 0u) & bf_t::vmask) << bitpos); this->m_data |= static_cast<vtype>((static_cast<utype>(right + 0u) & bf_t::vmask) << bitpos);
return *this; return *this;
} }
bf_t& operator ^=(compact_type right) bf_t& operator^=(compact_type right)
{ {
this->m_data ^= static_cast<vtype>((static_cast<utype>(right + 0u) & bf_t::vmask) << bitpos); this->m_data ^= static_cast<vtype>((static_cast<utype>(right + 0u) & bf_t::vmask) << bitpos);
return *this; return *this;
@ -157,13 +159,19 @@ struct bf_t : bf_base<T, N>
}; };
template <typename T, uint I, uint N> template <typename T, uint I, uint N>
struct std::common_type<bf_t<T, I, N>, bf_t<T, I, N>> : std::common_type<T> {}; struct std::common_type<bf_t<T, I, N>, bf_t<T, I, N>> : std::common_type<T>
{
};
template <typename T, uint I, uint N, typename T2> template <typename T, uint I, uint N, typename T2>
struct std::common_type<bf_t<T, I, N>, T2> : std::common_type<T2, std::common_type_t<T>> {}; struct std::common_type<bf_t<T, I, N>, T2> : std::common_type<T2, std::common_type_t<T>>
{
};
template <typename T, uint I, uint N, typename T2> template <typename T, uint I, uint N, typename T2>
struct std::common_type<T2, bf_t<T, I, N>> : std::common_type<std::common_type_t<T>, T2> {}; struct std::common_type<T2, bf_t<T, I, N>> : std::common_type<std::common_type_t<T>, T2>
{
};
// Field pack (concatenated from left to right) // Field pack (concatenated from left to right)
template <typename F = void, typename... Fields> template <typename F = void, typename... Fields>
@ -199,7 +207,7 @@ struct cf_t : bf_base<typename F::type, F::bitsize + cf_t<Fields...>::bitsize>
} }
// Store value // Store value
cf_t& operator =(compact_type value) noexcept cf_t& operator=(compact_type value) noexcept
{ {
this->m_data = (this->m_data & ~data_mask()) | insert(value); this->m_data = (this->m_data & ~data_mask()) | insert(value);
return *this; return *this;

File diff suppressed because it is too large Load diff

View file

@ -10,7 +10,7 @@ LOG_CHANNEL(cfg_log, "CFG");
template <> template <>
void fmt_class_string<cfg::node>::format(std::string& out, u64 arg) void fmt_class_string<cfg::node>::format(std::string& out, u64 arg)
{ {
out += get_object(arg).to_string(); out += get_object(arg).to_string();
} }
namespace cfg namespace cfg
@ -69,7 +69,7 @@ namespace cfg
// Incrementally load config entries from YAML::Node. // Incrementally load config entries from YAML::Node.
// The config value is preserved if the corresponding YAML node doesn't exist. // The config value is preserved if the corresponding YAML node doesn't exist.
static void decode(const YAML::Node& data, class _base& rhs, bool dynamic = false); static void decode(const YAML::Node& data, class _base& rhs, bool dynamic = false);
} } // namespace cfg
std::vector<std::string> cfg::make_int_range(s64 min, s64 max) std::vector<std::string> cfg::make_int_range(s64 min, s64 max)
{ {
@ -80,7 +80,8 @@ bool try_to_int64(s64* out, std::string_view value, s64 min, s64 max)
{ {
if (value.empty()) if (value.empty())
{ {
if (out) cfg_log.error("cfg::try_to_int64(): called with an empty string"); if (out)
cfg_log.error("cfg::try_to_int64(): called with an empty string");
return false; return false;
} }
@ -107,7 +108,8 @@ bool try_to_int64(s64* out, std::string_view value, s64 min, s64 max)
if (ret.ec != std::errc() || ret.ptr != end || (start[0] == '-' && sign < 0)) if (ret.ec != std::errc() || ret.ptr != end || (start[0] == '-' && sign < 0))
{ {
if (out) cfg_log.error("cfg::try_to_int64('%s'): invalid integer", value); if (out)
cfg_log.error("cfg::try_to_int64('%s'): invalid integer", value);
return false; return false;
} }
@ -115,11 +117,13 @@ bool try_to_int64(s64* out, std::string_view value, s64 min, s64 max)
if (result < min || result > max) if (result < min || result > max)
{ {
if (out) cfg_log.error("cfg::try_to_int64('%s'): out of bounds (val=%d, min=%d, max=%d)", value, result, min, max); if (out)
cfg_log.error("cfg::try_to_int64('%s'): out of bounds (val=%d, min=%d, max=%d)", value, result, min, max);
return false; return false;
} }
if (out) *out = result; if (out)
*out = result;
return true; return true;
} }
@ -132,7 +136,8 @@ bool try_to_uint64(u64* out, std::string_view value, u64 min, u64 max)
{ {
if (value.empty()) if (value.empty())
{ {
if (out) cfg_log.error("cfg::try_to_uint64(): called with an empty string"); if (out)
cfg_log.error("cfg::try_to_uint64(): called with an empty string");
return false; return false;
} }
@ -152,17 +157,20 @@ bool try_to_uint64(u64* out, std::string_view value, u64 min, u64 max)
if (ret.ec != std::errc() || ret.ptr != end) if (ret.ec != std::errc() || ret.ptr != end)
{ {
if (out) cfg_log.error("cfg::try_to_uint64('%s'): invalid integer", value); if (out)
cfg_log.error("cfg::try_to_uint64('%s'): invalid integer", value);
return false; return false;
} }
if (result < min || result > max) if (result < min || result > max)
{ {
if (out) cfg_log.error("cfg::try_to_uint64('%s'): out of bounds (val=%u, min=%u, max=%u)", value, result, min, max); if (out)
cfg_log.error("cfg::try_to_uint64('%s'): out of bounds (val=%u, min=%u, max=%u)", value, result, min, max);
return false; return false;
} }
if (out) *out = result; if (out)
*out = result;
return true; return true;
} }
@ -175,7 +183,8 @@ bool try_to_float(f64* out, std::string_view value, f64 min, f64 max)
{ {
if (value.empty()) if (value.empty())
{ {
if (out) cfg_log.error("cfg::try_to_float(): called with an empty string"); if (out)
cfg_log.error("cfg::try_to_float(): called with an empty string");
return false; return false;
} }
@ -188,36 +197,42 @@ bool try_to_float(f64* out, std::string_view value, f64 min, f64 max)
if (end_check != str.data() + str.size()) if (end_check != str.data() + str.size())
{ {
if (out) cfg_log.error("cfg::try_to_float('%s'): invalid float", value); if (out)
cfg_log.error("cfg::try_to_float('%s'): invalid float", value);
return false; return false;
} }
if (result < min || result > max) if (result < min || result > max)
{ {
if (out) cfg_log.error("cfg::try_to_float('%s'): out of bounds (val=%f, min=%f, max=%f)", value, result, min, max); if (out)
cfg_log.error("cfg::try_to_float('%s'): out of bounds (val=%f, min=%f, max=%f)", value, result, min, max);
return false; return false;
} }
if (out) *out = result; if (out)
*out = result;
return true; return true;
} }
bool try_to_string(std::string* out, const f64& value) bool try_to_string(std::string* out, const f64& value)
{ {
#ifdef __APPLE__ #ifdef __APPLE__
if (out) *out = std::to_string(value); if (out)
*out = std::to_string(value);
return true; return true;
#else #else
std::array<char, 32> str{}; std::array<char, 32> str{};
if (auto [ptr, ec] = std::to_chars(str.data(), str.data() + str.size(), value, std::chars_format::fixed); ec == std::errc()) if (auto [ptr, ec] = std::to_chars(str.data(), str.data() + str.size(), value, std::chars_format::fixed); ec == std::errc())
{ {
if (out) *out = std::string(str.data(), ptr); if (out)
*out = std::string(str.data(), ptr);
return true; return true;
} }
else else
{ {
if (out) cfg_log.error("cfg::try_to_string(): could not convert value '%f' to string. error='%s'", value, std::make_error_code(ec).message()); if (out)
cfg_log.error("cfg::try_to_string(): could not convert value '%f' to string. error='%s'", value, std::make_error_code(ec).message());
return false; return false;
} }
#endif #endif
@ -235,7 +250,8 @@ bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) f
if (var == value) if (var == value)
{ {
if (out) *out = i; if (out)
*out = i;
return true; return true;
} }
@ -271,17 +287,20 @@ bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) f
if (ret.ec != std::errc() || ret.ptr != end) if (ret.ec != std::errc() || ret.ptr != end)
{ {
if (out) cfg_log.error("cfg::try_to_enum_value('%s'): invalid enum or integer", value); if (out)
cfg_log.error("cfg::try_to_enum_value('%s'): invalid enum or integer", value);
return false; return false;
} }
if (result > max) if (result > max)
{ {
if (out) cfg_log.error("cfg::try_to_enum_value('%s'): out of bounds(val=%u, min=0, max=%u)", value, result, max); if (out)
cfg_log.error("cfg::try_to_enum_value('%s'): out of bounds(val=%u, min=0, max=%u)", value, result, max);
return false; return false;
} }
if (out) *out = result; if (out)
*out = result;
return true; return true;
} }
@ -354,7 +373,7 @@ void cfg::encode(YAML::Emitter& out, const cfg::_base& rhs)
} }
case type::node_map: case type::node_map:
{ {
//out << YAML::Block; // Does nothing, output is in Flow mode still (TODO) // out << YAML::Block; // Does nothing, output is in Flow mode still (TODO)
out << YAML::BeginMap; out << YAML::BeginMap;
for (const auto& np : static_cast<const node_map_entry&>(rhs).get_map()) for (const auto& np : static_cast<const node_map_entry&>(rhs).get_map())
{ {
@ -369,7 +388,8 @@ void cfg::encode(YAML::Emitter& out, const cfg::_base& rhs)
out << YAML::BeginMap; out << YAML::BeginMap;
for (const auto& np : static_cast<const log_entry&>(rhs).get_map()) for (const auto& np : static_cast<const log_entry&>(rhs).get_map())
{ {
if (np.second == logs::level::notice) continue; if (np.second == logs::level::notice)
continue;
out << YAML::Key << np.first; out << YAML::Key << np.first;
out << YAML::Value << fmt::format("%s", np.second); out << YAML::Value << fmt::format("%s", np.second);
} }
@ -418,7 +438,8 @@ void cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic)
for (const auto& pair : data) for (const auto& pair : data)
{ {
if (!pair.first.IsScalar()) continue; if (!pair.first.IsScalar())
continue;
// Find the key among existing nodes // Find the key among existing nodes
for (const auto& node : static_cast<node&>(rhs).get_nodes()) for (const auto& node : static_cast<node&>(rhs).get_nodes())
@ -455,7 +476,8 @@ void cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic)
for (const auto& pair : data) for (const auto& pair : data)
{ {
if (!pair.first.IsScalar() || !pair.second.IsScalar()) continue; if (!pair.first.IsScalar() || !pair.second.IsScalar())
continue;
values.emplace(pair.first.Scalar(), pair.second.Scalar()); values.emplace(pair.first.Scalar(), pair.second.Scalar());
} }
@ -474,7 +496,8 @@ void cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic)
for (const auto& pair : data) for (const auto& pair : data)
{ {
if (!pair.first.IsScalar() || !pair.second.IsScalar()) continue; if (!pair.first.IsScalar() || !pair.second.IsScalar())
continue;
u64 value; u64 value;
if (cfg::try_to_enum_value(&value, &fmt_class_string<logs::level>::format, pair.second.Scalar())) if (cfg::try_to_enum_value(&value, &fmt_class_string<logs::level>::format, pair.second.Scalar()))
@ -497,13 +520,15 @@ void cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic)
for (const auto& pair : data) for (const auto& pair : data)
{ {
if (!pair.first.IsScalar() || !pair.second.IsMap()) continue; if (!pair.first.IsScalar() || !pair.second.IsMap())
continue;
device_info info{}; device_info info{};
for (const auto& key_value : pair.second) for (const auto& key_value : pair.second)
{ {
if (!key_value.first.IsScalar() || !key_value.second.IsScalar()) continue; if (!key_value.first.IsScalar() || !key_value.second.IsScalar())
continue;
if (key_value.first.Scalar() == "Path") if (key_value.first.Scalar() == "Path")
info.path = key_value.second.Scalar(); info.path = key_value.second.Scalar();
@ -546,7 +571,7 @@ std::string cfg::node::to_string() const
return {out.c_str(), out.size()}; return {out.c_str(), out.size()};
} }
nlohmann::ordered_json cfg::node::to_json() const nlohmann::ordered_json cfg::node::to_json() const
{ {
auto result = nlohmann::ordered_json::object(); auto result = nlohmann::ordered_json::object();
@ -558,14 +583,14 @@ nlohmann::ordered_json cfg::node::to_json() const
return result; return result;
} }
bool cfg::node::from_json(const nlohmann::json &json, bool dynamic) bool cfg::node::from_json(const nlohmann::json& json, bool dynamic)
{ {
if (!json.is_object()) if (!json.is_object())
{ {
return false; return false;
} }
auto find_node = [this](std::string_view name) -> _base * auto find_node = [this](std::string_view name) -> _base*
{ {
for (const auto& node : get_nodes()) for (const auto& node : get_nodes())
{ {
@ -578,8 +603,7 @@ bool cfg::node::from_json(const nlohmann::json &json, bool dynamic)
return nullptr; return nullptr;
}; };
for (auto& [key, value] : json.get<nlohmann::json::object_t>())
for (auto &[key, value] : json.get<nlohmann::json::object_t>())
{ {
auto keyNode = find_node(key); auto keyNode = find_node(key);

View file

@ -36,16 +36,16 @@ namespace cfg
enum class type : unsigned enum class type : unsigned
{ {
node = 0, // cfg::node type node = 0, // cfg::node type
_bool, // cfg::_bool type _bool, // cfg::_bool type
_enum, // cfg::_enum type _enum, // cfg::_enum type
_int, // cfg::_int type _int, // cfg::_int type
uint, // cfg::uint type uint, // cfg::uint type
string, // cfg::string type string, // cfg::string type
set, // cfg::set_entry type set, // cfg::set_entry type
map, // cfg::map_entry type map, // cfg::map_entry type
node_map, // cfg::node_map_entry type node_map, // cfg::node_map_entry type
log, // cfg::log_entry type log, // cfg::log_entry type
device, // cfg::device_entry type device, // cfg::device_entry type
}; };
// Config tree entry abstract base class // Config tree entry abstract base class
@ -75,19 +75,34 @@ namespace cfg
virtual ~_base() = default; virtual ~_base() = default;
// Get unique ID // Get unique ID
u32 get_id() const { return m_id; } u32 get_id() const
{
return m_id;
}
// Get parent // Get parent
_base* get_parent() const { return m_parent; } _base* get_parent() const
{
return m_parent;
}
// Get type // Get type
type get_type() const { return m_type; } type get_type() const
{
return m_type;
}
// Get name // Get name
const std::string& get_name() const { return m_name; } const std::string& get_name() const
{
return m_name;
}
// Get dynamic property for reloading configs during games // Get dynamic property for reloading configs during games
bool get_is_dynamic() const { return m_dynamic; } bool get_is_dynamic() const
{
return m_dynamic;
}
// Reset defaults // Reset defaults
virtual void from_default() = 0; virtual void from_default() = 0;
@ -99,7 +114,7 @@ namespace cfg
} }
virtual nlohmann::ordered_json to_json() const = 0; virtual nlohmann::ordered_json to_json() const = 0;
virtual bool from_json(const nlohmann::json &, bool dynamic = false) = 0; virtual bool from_json(const nlohmann::json&, bool dynamic = false) = 0;
// Convert default to string (optional) // Convert default to string (optional)
virtual std::string def_to_string() const virtual std::string def_to_string() const
@ -154,7 +169,7 @@ namespace cfg
// Deserialize node // Deserialize node
bool from_string(std::string_view value, bool dynamic = false) override; bool from_string(std::string_view value, bool dynamic = false) override;
bool from_json(const nlohmann::json &, bool dynamic = false) override; bool from_json(const nlohmann::json&, bool dynamic = false) override;
// Set default values // Set default values
void from_default() override; void from_default() override;
@ -168,9 +183,7 @@ namespace cfg
bool def; bool def;
_bool(node* owner, std::string name, bool def = false, bool dynamic = false) _bool(node* owner, std::string name, bool def = false, bool dynamic = false)
: _base(type::_bool, owner, std::move(name), dynamic) : _base(type::_bool, owner, std::move(name), dynamic), m_value(def), def(def)
, m_value(def)
, def(def)
{ {
} }
@ -193,8 +206,7 @@ namespace cfg
nlohmann::ordered_json to_json() const override nlohmann::ordered_json to_json() const override
{ {
return return {
{
{"type", "bool"}, {"type", "bool"},
{"value", m_value.load()}, {"value", m_value.load()},
{"default", def}, {"default", def},
@ -226,7 +238,7 @@ namespace cfg
return true; return true;
} }
bool from_json(const nlohmann::json &json, bool) override bool from_json(const nlohmann::json& json, bool) override
{ {
if (!json.is_boolean()) if (!json.is_boolean())
{ {
@ -253,9 +265,7 @@ namespace cfg
const T def; const T def;
_enum(node* owner, const std::string& name, T value = {}, bool dynamic = false) _enum(node* owner, const std::string& name, T value = {}, bool dynamic = false)
: _base(type::_enum, owner, name, dynamic) : _base(type::_enum, owner, name, dynamic), m_value(value), def(value)
, m_value(value)
, def(value)
{ {
} }
@ -293,8 +303,7 @@ namespace cfg
nlohmann::ordered_json to_json() const override nlohmann::ordered_json to_json() const override
{ {
return return {
{
{"type", "enum"}, {"type", "enum"},
{"value", to_string()}, {"value", to_string()},
{"default", def_to_string()}, {"default", def_to_string()},
@ -323,7 +332,7 @@ namespace cfg
return false; return false;
} }
bool from_json(const nlohmann::json &json, bool dynamic) override bool from_json(const nlohmann::json& json, bool dynamic) override
{ {
if (!json.is_string()) if (!json.is_string())
{ {
@ -360,13 +369,9 @@ namespace cfg
static constexpr s64 min = Min; static constexpr s64 min = Min;
_int(node* owner, const std::string& name, int_type def = std::min<int_type>(Max, std::max<int_type>(Min, 0)), bool dynamic = false, _int(node* owner, const std::string& name, int_type def = std::min<int_type>(Max, std::max<int_type>(Min, 0)), bool dynamic = false,
std::function<s64()> min_fn = nullptr, std::function<s64()> min_fn = nullptr,
std::function<s64()> max_fn = nullptr) std::function<s64()> max_fn = nullptr)
: _base(type::_int, owner, name, dynamic) : _base(type::_int, owner, name, dynamic), m_value(def), m_min_fn(std::move(min_fn)), m_max_fn(std::move(max_fn)), def(def)
, m_value(def)
, m_min_fn(std::move(min_fn))
, m_max_fn(std::move(max_fn))
, def(def)
{ {
} }
@ -412,8 +417,7 @@ namespace cfg
nlohmann::ordered_json to_json() const override nlohmann::ordered_json to_json() const override
{ {
return return {
{
{"type", "int"}, {"type", "int"},
{"value", to_string()}, {"value", to_string()},
{"default", def_to_string()}, {"default", def_to_string()},
@ -439,7 +443,7 @@ namespace cfg
return false; return false;
} }
bool from_json(const nlohmann::json &json, bool) override bool from_json(const nlohmann::json& json, bool) override
{ {
if (!json.is_number_integer()) if (!json.is_number_integer())
{ {
@ -485,9 +489,7 @@ namespace cfg
static constexpr float_type min = Min; static constexpr float_type min = Min;
_float(node* owner, const std::string& name, float_type def = std::min<float_type>(Max, std::max<float_type>(Min, 0)), bool dynamic = false) _float(node* owner, const std::string& name, float_type def = std::min<float_type>(Max, std::max<float_type>(Min, 0)), bool dynamic = false)
: _base(type::_int, owner, name, dynamic) : _base(type::_int, owner, name, dynamic), m_value(def), def(def)
, m_value(def)
, def(def)
{ {
} }
@ -519,8 +521,7 @@ namespace cfg
nlohmann::ordered_json to_json() const override nlohmann::ordered_json to_json() const override
{ {
return return {
{
{"type", "float"}, {"type", "float"},
{"value", to_string()}, {"value", to_string()},
{"default", def_to_string()}, {"default", def_to_string()},
@ -552,7 +553,7 @@ namespace cfg
return false; return false;
} }
bool from_json(const nlohmann::json &json, bool) override bool from_json(const nlohmann::json& json, bool) override
{ {
if (!json.is_number_float()) if (!json.is_number_float())
{ {
@ -606,9 +607,7 @@ namespace cfg
static constexpr u64 min = Min; static constexpr u64 min = Min;
uint(node* owner, const std::string& name, int_type def = std::max<int_type>(Min, 0), bool dynamic = false) uint(node* owner, const std::string& name, int_type def = std::max<int_type>(Min, 0), bool dynamic = false)
: _base(type::uint, owner, name, dynamic) : _base(type::uint, owner, name, dynamic), m_value(def), def(def)
, m_value(def)
, def(def)
{ {
} }
@ -634,8 +633,7 @@ namespace cfg
nlohmann::ordered_json to_json() const override nlohmann::ordered_json to_json() const override
{ {
return return {
{
{"type", "uint"}, {"type", "uint"},
{"value", to_string()}, {"value", to_string()},
{"default", def_to_string()}, {"default", def_to_string()},
@ -661,7 +659,7 @@ namespace cfg
return false; return false;
} }
bool from_json(const nlohmann::json &json, bool) override bool from_json(const nlohmann::json& json, bool) override
{ {
if (!json.is_number_unsigned()) if (!json.is_number_unsigned())
{ {
@ -705,9 +703,7 @@ namespace cfg
std::string def; std::string def;
string(node* owner, std::string name, std::string def = {}, bool dynamic = false) string(node* owner, std::string name, std::string def = {}, bool dynamic = false)
: _base(type::string, owner, std::move(name), dynamic) : _base(type::string, owner, std::move(name), dynamic), m_value(def), def(std::move(def))
, m_value(def)
, def(std::move(def))
{ {
} }
@ -725,8 +721,7 @@ namespace cfg
nlohmann::ordered_json to_json() const override nlohmann::ordered_json to_json() const override
{ {
return return {
{
{"type", "string"}, {"type", "string"},
{"value", to_string()}, {"value", to_string()},
{"default", def_to_string()}, {"default", def_to_string()},
@ -744,7 +739,7 @@ namespace cfg
return true; return true;
} }
bool from_json(const nlohmann::json &json, bool) override bool from_json(const nlohmann::json& json, bool) override
{ {
if (!json.is_string()) if (!json.is_string())
{ {
@ -782,13 +777,12 @@ namespace cfg
std::vector<std::string> to_list() const override std::vector<std::string> to_list() const override
{ {
return { m_set.begin(), m_set.end() }; return {m_set.begin(), m_set.end()};
} }
nlohmann::ordered_json to_json() const override nlohmann::ordered_json to_json() const override
{ {
return return {
{
{"type", "set"}, {"type", "set"},
{"value", to_list()}, {"value", to_list()},
}; };
@ -796,12 +790,12 @@ namespace cfg
bool from_list(std::vector<std::string>&& list) override bool from_list(std::vector<std::string>&& list) override
{ {
m_set = { std::make_move_iterator(list.begin()), std::make_move_iterator(list.end()) }; m_set = {std::make_move_iterator(list.begin()), std::make_move_iterator(list.end())};
return true; return true;
} }
bool from_json(const nlohmann::json &json, bool) override bool from_json(const nlohmann::json& json, bool) override
{ {
if (!json.is_array()) if (!json.is_array())
{ {
@ -813,7 +807,7 @@ namespace cfg
std::vector<std::string> string_array; std::vector<std::string> string_array;
string_array.reserve(array.size()); string_array.reserve(array.size());
for (auto &elem : array) for (auto& elem : array)
{ {
if (!elem.is_string()) if (!elem.is_string())
{ {
@ -827,7 +821,7 @@ namespace cfg
} }
}; };
template<typename T> template <typename T>
using map_of_type = std::map<std::string, T, std::less<>>; using map_of_type = std::map<std::string, T, std::less<>>;
class map_entry : public _base class map_entry : public _base
@ -847,22 +841,20 @@ namespace cfg
nlohmann::ordered_json to_json() const override nlohmann::ordered_json to_json() const override
{ {
return return {
{
{"type", "map"}, {"type", "map"},
{"value", m_map}, {"value", m_map},
}; };
} }
bool from_json(const nlohmann::json& json, bool) override
bool from_json(const nlohmann::json &json, bool) override
{ {
if (!json.is_object()) if (!json.is_object())
{ {
return false; return false;
} }
for (auto &elem : json.get<nlohmann::json::object_t>()) for (auto& elem : json.get<nlohmann::json::object_t>())
{ {
set_value(elem.first, elem.second); set_value(elem.first, elem.second);
} }
@ -915,22 +907,21 @@ namespace cfg
values[key] = level_string; values[key] = level_string;
} }
return return {
{
{"type", "log_map"}, {"type", "log_map"},
{"values", values}, {"values", values},
{"levels", levels}, {"levels", levels},
}; };
} }
bool from_json(const nlohmann::json &json, bool) override bool from_json(const nlohmann::json& json, bool) override
{ {
if (!json.is_object()) if (!json.is_object())
{ {
return false; return false;
} }
for (auto [key, valueString] : json.get<nlohmann::json::object_t>()) for (auto [key, valueString] : json.get<nlohmann::json::object_t>())
{ {
if (!valueString.is_string()) if (!valueString.is_string())
{ {
@ -978,7 +969,7 @@ namespace cfg
}; };
} }
bool from_json(const nlohmann::json &json) bool from_json(const nlohmann::json& json)
{ {
if (json.contains("path")) if (json.contains("path"))
{ {
@ -1031,8 +1022,7 @@ namespace cfg
public: public:
device_entry(node* owner, const std::string& name, map_of_type<device_info> def = {}) device_entry(node* owner, const std::string& name, map_of_type<device_info> def = {})
: _base(type::device, owner, name, true) : _base(type::device, owner, name, true), m_map(std::move(def))
, m_map(std::move(def))
{ {
m_default = m_map; m_default = m_map;
} }
@ -1042,7 +1032,7 @@ namespace cfg
return {}; return {};
} }
bool from_json(const nlohmann::json &, bool) override bool from_json(const nlohmann::json&, bool) override
{ {
return false; return false;
} }
@ -1061,4 +1051,4 @@ namespace cfg
void from_default() override; void from_default() override;
}; };
} } // namespace cfg

View file

@ -25,7 +25,7 @@ std::string g_android_cache_dir;
#include "Utilities/StrUtil.h" #include "Utilities/StrUtil.h"
#include <cwchar> #include <cwchar>
#include <Windows.h> #include <windows.h>
static std::unique_ptr<wchar_t[]> to_wchar(std::string_view source) static std::unique_ptr<wchar_t[]> to_wchar(std::string_view source)
{ {
@ -205,7 +205,7 @@ namespace fs
std::unordered_map<std::string, shared_ptr<device_base>> m_map{}; std::unordered_map<std::string, shared_ptr<device_base>> m_map{};
public: public:
shared_ptr<device_base> get_device(const std::string& path, std::string_view *device_path = nullptr); shared_ptr<device_base> get_device(const std::string& path, std::string_view* device_path = nullptr);
shared_ptr<device_base> set_device(const std::string& name, shared_ptr<device_base>); shared_ptr<device_base> set_device(const std::string& name, shared_ptr<device_base>);
}; };
@ -402,8 +402,7 @@ namespace fs
public: public:
windows_file(HANDLE handle) windows_file(HANDLE handle)
: m_handle(handle) : m_handle(handle), m_pos(0)
, m_pos(0)
{ {
} }
@ -577,7 +576,8 @@ namespace fs
const s64 new_pos = const s64 new_pos =
whence == fs::seek_set ? offset : whence == fs::seek_set ? offset :
whence == fs::seek_cur ? offset + m_pos : whence == fs::seek_cur ? offset + m_pos :
whence == fs::seek_end ? offset + size() : -1; whence == fs::seek_end ? offset + size() :
-1;
if (new_pos < 0) if (new_pos < 0)
{ {
@ -766,7 +766,8 @@ namespace fs
const int mode = const int mode =
whence == seek_set ? SEEK_SET : whence == seek_set ? SEEK_SET :
whence == seek_cur ? SEEK_CUR : SEEK_END; whence == seek_cur ? SEEK_CUR :
SEEK_END;
const auto result = ::lseek(m_fd, offset, mode); const auto result = ::lseek(m_fd, offset, mode);
@ -833,9 +834,9 @@ namespace fs
} }
}; };
#endif #endif
} } // namespace fs
shared_ptr<fs::device_base> fs::device_manager::get_device(const std::string& path, std::string_view *device_path) shared_ptr<fs::device_base> fs::device_manager::get_device(const std::string& path, std::string_view* device_path)
{ {
auto prefix = path.substr(0, path.find_first_of("/\\", 1)); auto prefix = path.substr(0, path.find_first_of("/\\", 1));
@ -885,7 +886,7 @@ shared_ptr<fs::device_base> fs::device_manager::set_device(const std::string& na
return null_ptr; return null_ptr;
} }
shared_ptr<fs::device_base> fs::get_virtual_device(const std::string& path, std::string_view *device_path) shared_ptr<fs::device_base> fs::get_virtual_device(const std::string& path, std::string_view* device_path)
{ {
// Every virtual device path must have specific name at the beginning // Every virtual device path must have specific name at the beginning
if ((path.starts_with("/vfsv0_") || path.starts_with("\\vfsv0_")) && path.size() >= 8 + 22 && path[29] == '_' && path.find_first_of("/\\", 1) > 29) if ((path.starts_with("/vfsv0_") || path.starts_with("\\vfsv0_")) && path.size() >= 8 + 22 && path[29] == '_' && path.find_first_of("/\\", 1) > 29)
@ -1019,7 +1020,10 @@ bool fs::get_stat(const std::string& path, stat_t& info)
struct close_t struct close_t
{ {
HANDLE handle; HANDLE handle;
~close_t() { FindClose(handle); } ~close_t()
{
FindClose(handle);
}
}; };
for (close_t find_manage{handle}; attrs.cFileName != wpath_view.substr(wpath_view.find_last_of(wdelim) + 1);) for (close_t find_manage{handle}; attrs.cFileName != wpath_view.substr(wpath_view.find_last_of(wdelim) + 1);)
@ -1426,7 +1430,7 @@ bool fs::copy_file(const std::string& from, const std::string& to, bool overwrit
if (::fcopyfile(input, output, 0, COPYFILE_ALL)) if (::fcopyfile(input, output, 0, COPYFILE_ALL))
#elif defined(__linux__) || defined(__sun) #elif defined(__linux__) || defined(__sun)
// sendfile will work with non-socket output (i.e. regular file) on Linux 2.6.33+ // sendfile will work with non-socket output (i.e. regular file) on Linux 2.6.33+
struct ::stat fileinfo = { 0 }; struct ::stat fileinfo = {0};
bool result = ::fstat(input, &fileinfo) != -1; bool result = ::fstat(input, &fileinfo) != -1;
if (result) if (result)
{ {
@ -1466,7 +1470,7 @@ bool fs::copy_file(const std::string& from, const std::string& to, bool overwrit
} }
std::ifstream in{from, std::ios::binary}; std::ifstream in{from, std::ios::binary};
std::ofstream out{to, std::ios::binary}; std::ofstream out{to, std::ios::binary};
if (!in.good() || !out.good()) if (!in.good() || !out.good())
{ {
@ -1653,15 +1657,18 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
#ifdef _WIN32 #ifdef _WIN32
DWORD access = 0; DWORD access = 0;
if (mode & fs::read) access |= GENERIC_READ; if (mode & fs::read)
if (mode & fs::write) access |= DELETE | (mode & fs::append ? FILE_APPEND_DATA : GENERIC_WRITE); access |= GENERIC_READ;
if (mode & fs::write)
access |= DELETE | (mode & fs::append ? FILE_APPEND_DATA : GENERIC_WRITE);
DWORD disp = 0; DWORD disp = 0;
if (mode & fs::create) if (mode & fs::create)
{ {
disp = disp =
mode & fs::excl ? CREATE_NEW : mode & fs::excl ? CREATE_NEW :
mode & fs::trunc ? CREATE_ALWAYS : OPEN_ALWAYS; mode & fs::trunc ? CREATE_ALWAYS :
OPEN_ALWAYS;
} }
else else
{ {
@ -1697,14 +1704,21 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
#else #else
int flags = O_CLOEXEC; // Ensures all files are closed on execl for auto updater int flags = O_CLOEXEC; // Ensures all files are closed on execl for auto updater
if (mode & fs::read && mode & fs::write) flags |= O_RDWR; if (mode & fs::read && mode & fs::write)
else if (mode & fs::read) flags |= O_RDONLY; flags |= O_RDWR;
else if (mode & fs::write) flags |= O_WRONLY; else if (mode & fs::read)
flags |= O_RDONLY;
else if (mode & fs::write)
flags |= O_WRONLY;
if (mode & fs::append) flags |= O_APPEND; if (mode & fs::append)
if (mode & fs::create) flags |= O_CREAT; flags |= O_APPEND;
if (mode & fs::trunc && !(mode & fs::lock)) flags |= O_TRUNC; if (mode & fs::create)
if (mode & fs::excl) flags |= O_EXCL; flags |= O_CREAT;
if (mode & fs::trunc && !(mode & fs::lock))
flags |= O_TRUNC;
if (mode & fs::excl)
flags |= O_EXCL;
int perm = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; int perm = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
@ -1753,8 +1767,6 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
#endif #endif
} }
fs::file fs::file::from_native_handle(native_handle handle) fs::file fs::file::from_native_handle(native_handle handle)
{ {
fs::file result; fs::file result;
@ -1779,8 +1791,7 @@ fs::file::file(const void* ptr, usz size)
public: public:
memory_stream(const void* ptr, u64 size) memory_stream(const void* ptr, u64 size)
: m_ptr(static_cast<const char*>(ptr)) : m_ptr(static_cast<const char*>(ptr)), m_size(size)
, m_size(size)
{ {
} }
@ -1834,7 +1845,8 @@ fs::file::file(const void* ptr, usz size)
const s64 new_pos = const s64 new_pos =
whence == fs::seek_set ? offset : whence == fs::seek_set ? offset :
whence == fs::seek_cur ? offset + m_pos : whence == fs::seek_cur ? offset + m_pos :
whence == fs::seek_end ? offset + size() : -1; whence == fs::seek_end ? offset + size() :
-1;
if (new_pos < 0) if (new_pos < 0)
{ {
@ -2006,7 +2018,7 @@ bool fs::dir::open(const std::string& path)
if (::fstatat(::dirfd(m_dd), found->d_name, &file_info, 0) != 0) if (::fstatat(::dirfd(m_dd), found->d_name, &file_info, 0) != 0)
{ {
//failed metadata (broken symlink?), ignore and skip to next file // failed metadata (broken symlink?), ignore and skip to next file
return read(info); return read(info);
} }
@ -2455,11 +2467,11 @@ fs::file fs::make_gather(std::vector<fs::file> files)
files[it->second].seek(pos - it->first, fs::seek_end); files[it->second].seek(pos - it->first, fs::seek_end);
const u64 count = std::min<u64>(it->first - pos, buf_max); const u64 count = std::min<u64>(it->first - pos, buf_max);
const u64 read = files[it->second].read(buf_out, count); const u64 read = files[it->second].read(buf_out, count);
buf_out += count; buf_out += count;
buf_max -= count; buf_max -= count;
pos += read; pos += read;
if (read < count || buf_max == 0) if (read < count || buf_max == 0)
{ {
@ -2489,11 +2501,11 @@ fs::file fs::make_gather(std::vector<fs::file> files)
for (auto it = ends.upper_bound(pos); it != ends.end(); ++it) for (auto it = ends.upper_bound(pos); it != ends.end(); ++it)
{ {
const u64 count = std::min<u64>(it->first - pos, buf_max); const u64 count = std::min<u64>(it->first - pos, buf_max);
const u64 read = files[it->second].read_at(files[it->second].size() + pos - it->first, buf_out, count); const u64 read = files[it->second].read_at(files[it->second].size() + pos - it->first, buf_out, count);
buf_out += count; buf_out += count;
buf_max -= count; buf_max -= count;
pos += read; pos += read;
if (read < count || buf_max == 0) if (read < count || buf_max == 0)
{ {
@ -2518,7 +2530,8 @@ fs::file fs::make_gather(std::vector<fs::file> files)
const s64 new_pos = const s64 new_pos =
whence == fs::seek_set ? offset : whence == fs::seek_set ? offset :
whence == fs::seek_cur ? offset + pos : whence == fs::seek_cur ? offset + pos :
whence == fs::seek_end ? offset + end : -1; whence == fs::seek_end ? offset + end :
-1;
if (new_pos < 0) if (new_pos < 0)
{ {
@ -2581,8 +2594,7 @@ bool fs::pending_file::open(std::string_view path)
} }
m_path.clear(); m_path.clear();
} } while (fs::g_tls_error == fs::error::exist); // Only retry if failed due to existing file
while (fs::g_tls_error == fs::error::exist); // Only retry if failed due to existing file
return file.operator bool(); return file.operator bool();
} }
@ -2626,8 +2638,7 @@ bool fs::pending_file::commit(bool overwrite)
const auto ws1 = to_wchar(m_path); const auto ws1 = to_wchar(m_path);
const HANDLE file_handle = !overwrite ? INVALID_HANDLE_VALUE const HANDLE file_handle = !overwrite ? INVALID_HANDLE_VALUE : CreateFileW(ws1.get(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
: CreateFileW(ws1.get(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
while (file_handle != INVALID_HANDLE_VALUE) while (file_handle != INVALID_HANDLE_VALUE)
{ {
@ -2734,8 +2745,7 @@ bool fs::pending_file::commit(bool overwrite)
break; break;
} }
} } while (fs::g_tls_error == fs::error::exist); // Only retry if failed due to existing file
while (fs::g_tls_error == fs::error::exist); // Only retry if failed due to existing file
if (write_temp_path) if (write_temp_path)
{ {
@ -2787,23 +2797,23 @@ stx::generator<fs::dir_entry&> fs::list_dir_recursively(const std::string& path)
} }
} }
template<> template <>
void fmt_class_string<fs::seek_mode>::format(std::string& out, u64 arg) void fmt_class_string<fs::seek_mode>::format(std::string& out, u64 arg)
{ {
format_enum(out, arg, [](auto arg) format_enum(out, arg, [](auto arg)
{
switch (arg)
{ {
STR_CASE(fs::seek_mode::seek_set); switch (arg)
STR_CASE(fs::seek_mode::seek_cur); {
STR_CASE(fs::seek_mode::seek_end); STR_CASE(fs::seek_mode::seek_set);
} STR_CASE(fs::seek_mode::seek_cur);
STR_CASE(fs::seek_mode::seek_end);
}
return unknown; return unknown;
}); });
} }
template<> template <>
void fmt_class_string<fs::error>::format(std::string& out, u64 arg) void fmt_class_string<fs::error>::format(std::string& out, u64 arg)
{ {
if (arg == static_cast<u64>(fs::error::unknown)) if (arg == static_cast<u64>(fs::error::unknown))
@ -2818,29 +2828,29 @@ void fmt_class_string<fs::error>::format(std::string& out, u64 arg)
} }
format_enum(out, arg, [](auto arg) format_enum(out, arg, [](auto arg)
{
switch (arg)
{ {
case fs::error::ok: return "OK"; switch (arg)
{
case fs::error::ok: return "OK";
case fs::error::inval: return "Invalid arguments"; case fs::error::inval: return "Invalid arguments";
case fs::error::noent: return "Not found"; case fs::error::noent: return "Not found";
case fs::error::exist: return "Already exists"; case fs::error::exist: return "Already exists";
case fs::error::acces: return "Access violation"; case fs::error::acces: return "Access violation";
case fs::error::notempty: return "Not empty"; case fs::error::notempty: return "Not empty";
case fs::error::readonly: return "Read only"; case fs::error::readonly: return "Read only";
case fs::error::isdir: return "Is a directory"; case fs::error::isdir: return "Is a directory";
case fs::error::toolong: return "Path too long"; case fs::error::toolong: return "Path too long";
case fs::error::nospace: return "Not enough space on the device"; case fs::error::nospace: return "Not enough space on the device";
case fs::error::xdev: return "Device mismatch"; case fs::error::xdev: return "Device mismatch";
case fs::error::unknown: return "Unknown system error"; case fs::error::unknown: return "Unknown system error";
} }
return unknown; return unknown;
}); });
} }
template<> template <>
void fmt_class_string<fs::file_id>::format(std::string& out, u64 arg) void fmt_class_string<fs::file_id>::format(std::string& out, u64 arg)
{ {
const fs::file_id& id = get_object(arg); const fs::file_id& id = get_object(arg);

View file

@ -38,15 +38,15 @@ namespace fs
__bitset_enum_max __bitset_enum_max
}; };
constexpr auto read = +open_mode::read; // Enable reading constexpr auto read = +open_mode::read; // Enable reading
constexpr auto write = +open_mode::write; // Enable writing constexpr auto write = +open_mode::write; // Enable writing
constexpr auto append = +open_mode::append; // Always append to the end of the file constexpr auto append = +open_mode::append; // Always append to the end of the file
constexpr auto create = +open_mode::create; // Create file if it doesn't exist constexpr auto create = +open_mode::create; // Create file if it doesn't exist
constexpr auto trunc = +open_mode::trunc; // Clear opened file if it's not empty constexpr auto trunc = +open_mode::trunc; // Clear opened file if it's not empty
constexpr auto excl = +open_mode::excl; // Failure if the file already exists (used with `create`) constexpr auto excl = +open_mode::excl; // Failure if the file already exists (used with `create`)
constexpr auto lock = +open_mode::lock; // Prevent opening the file more than once constexpr auto lock = +open_mode::lock; // Prevent opening the file more than once
constexpr auto unread = +open_mode::unread; // Aggressively prevent reading the opened file (do not use) constexpr auto unread = +open_mode::unread; // Aggressively prevent reading the opened file (do not use)
constexpr auto isfile = +open_mode::isfile; // Ensure valid fs::file handle is not of directory constexpr auto isfile = +open_mode::isfile; // Ensure valid fs::file handle is not of directory
constexpr auto write_new = write + create + excl; constexpr auto write_new = write + create + excl;
constexpr auto rewrite = write + create + trunc; constexpr auto rewrite = write + create + trunc;
@ -182,10 +182,12 @@ namespace fs
[[noreturn]] void xfail(std::source_location); [[noreturn]] void xfail(std::source_location);
[[noreturn]] void xovfl(); [[noreturn]] void xovfl();
constexpr struct pod_tag_t{} pod_tag; constexpr struct pod_tag_t
{
} pod_tag;
// Get virtual device for specified path (nullptr for real path) // Get virtual device for specified path (nullptr for real path)
shared_ptr<device_base> get_virtual_device(const std::string& path, std::string_view *device_path); shared_ptr<device_base> get_virtual_device(const std::string& path, std::string_view* device_path);
// Set virtual device with specified name (nullptr for deletion) // Set virtual device with specified name (nullptr for deletion)
shared_ptr<device_base> set_virtual_device(const std::string& name, shared_ptr<device_base> device); shared_ptr<device_base> set_virtual_device(const std::string& name, shared_ptr<device_base> device);
@ -305,21 +307,24 @@ namespace fs
// Change file size (possibly appending zero bytes) // Change file size (possibly appending zero bytes)
bool trunc(u64 length, std::source_location src_loc = std::source_location::current()) const bool trunc(u64 length, std::source_location src_loc = std::source_location::current()) const
{ {
if (!m_file) xnull(src_loc); if (!m_file)
xnull(src_loc);
return m_file->trunc(length); return m_file->trunc(length);
} }
// Get file information // Get file information
stat_t get_stat(std::source_location src_loc = std::source_location::current()) const stat_t get_stat(std::source_location src_loc = std::source_location::current()) const
{ {
if (!m_file) xnull(src_loc); if (!m_file)
xnull(src_loc);
return m_file->get_stat(); return m_file->get_stat();
} }
// Sync file buffers // Sync file buffers
void sync(std::source_location src_loc = std::source_location::current()) const void sync(std::source_location src_loc = std::source_location::current()) const
{ {
if (!m_file) xnull(src_loc); if (!m_file)
xnull(src_loc);
return m_file->sync(); return m_file->sync();
} }
@ -329,80 +334,95 @@ namespace fs
// Read the data from the file and return the amount of data written in buffer // Read the data from the file and return the amount of data written in buffer
u64 read(void* buffer, u64 count, std::source_location src_loc = std::source_location::current()) const u64 read(void* buffer, u64 count, std::source_location src_loc = std::source_location::current()) const
{ {
if (!m_file) xnull(src_loc); if (!m_file)
xnull(src_loc);
return m_file->read(buffer, count); return m_file->read(buffer, count);
} }
// Read the data from the file at specified offset in thread-safe manner // Read the data from the file at specified offset in thread-safe manner
u64 read_at(u64 offset, void* buffer, u64 count, std::source_location src_loc = std::source_location::current()) const u64 read_at(u64 offset, void* buffer, u64 count, std::source_location src_loc = std::source_location::current()) const
{ {
if (!m_file) xnull(src_loc); if (!m_file)
xnull(src_loc);
return m_file->read_at(offset, buffer, count); return m_file->read_at(offset, buffer, count);
} }
// Write the data to the file and return the amount of data actually written // Write the data to the file and return the amount of data actually written
u64 write(const void* buffer, u64 count, std::source_location src_loc = std::source_location::current()) const u64 write(const void* buffer, u64 count, std::source_location src_loc = std::source_location::current()) const
{ {
if (!m_file) xnull(src_loc); if (!m_file)
xnull(src_loc);
return m_file->write(buffer, count); return m_file->write(buffer, count);
} }
u64 write_at(u64 offset, const void* buffer, u64 count, std::source_location src_loc = std::source_location::current()) const u64 write_at(u64 offset, const void* buffer, u64 count, std::source_location src_loc = std::source_location::current()) const
{ {
if (!m_file) xnull(src_loc); if (!m_file)
xnull(src_loc);
return m_file->write_at(offset, buffer, count); return m_file->write_at(offset, buffer, count);
} }
// Change current position, returns resulting position // Change current position, returns resulting position
u64 seek(s64 offset, seek_mode whence = seek_set, std::source_location src_loc = std::source_location::current()) const u64 seek(s64 offset, seek_mode whence = seek_set, std::source_location src_loc = std::source_location::current()) const
{ {
if (!m_file) xnull(src_loc); if (!m_file)
xnull(src_loc);
return m_file->seek(offset, whence); return m_file->seek(offset, whence);
} }
// Get file size // Get file size
u64 size(std::source_location src_loc = std::source_location::current()) const u64 size(std::source_location src_loc = std::source_location::current()) const
{ {
if (!m_file) xnull(src_loc); if (!m_file)
xnull(src_loc);
return m_file->size(); return m_file->size();
} }
// Get current position // Get current position
u64 pos(std::source_location src_loc = std::source_location::current()) const u64 pos(std::source_location src_loc = std::source_location::current()) const
{ {
if (!m_file) xnull(src_loc); if (!m_file)
xnull(src_loc);
return m_file->seek(0, seek_cur); return m_file->seek(0, seek_cur);
} }
// Write std::basic_string unconditionally // Write std::basic_string unconditionally
template <typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>) template <typename T>
requires(std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
const file& write(const std::basic_string<T>& str, std::source_location src_loc = std::source_location::current()) const const file& write(const std::basic_string<T>& str, std::source_location src_loc = std::source_location::current()) const
{ {
if (write(str.data(), str.size() * sizeof(T), src_loc) != str.size() * sizeof(T)) xfail(src_loc); if (write(str.data(), str.size() * sizeof(T), src_loc) != str.size() * sizeof(T))
xfail(src_loc);
return *this; return *this;
} }
// Write POD unconditionally // Write POD unconditionally
template <typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>) template <typename T>
requires(std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
const file& write(const T& data, std::source_location src_loc = std::source_location::current()) const const file& write(const T& data, std::source_location src_loc = std::source_location::current()) const
{ {
if (write(std::addressof(data), sizeof(T), src_loc) != sizeof(T)) xfail(src_loc); if (write(std::addressof(data), sizeof(T), src_loc) != sizeof(T))
xfail(src_loc);
return *this; return *this;
} }
// Write POD std::vector unconditionally // Write POD std::vector unconditionally
template <typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>) template <typename T>
requires(std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
const file& write(const std::vector<T>& vec, std::source_location src_loc = std::source_location::current()) const const file& write(const std::vector<T>& vec, std::source_location src_loc = std::source_location::current()) const
{ {
if (write(vec.data(), vec.size() * sizeof(T), src_loc) != vec.size() * sizeof(T)) xfail(src_loc); if (write(vec.data(), vec.size() * sizeof(T), src_loc) != vec.size() * sizeof(T))
xfail(src_loc);
return *this; return *this;
} }
// Read std::basic_string // Read std::basic_string
template <typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>) template <typename T>
requires(std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
bool read(std::basic_string<T>& str, usz _size = umax, std::source_location src_loc = std::source_location::current()) const bool read(std::basic_string<T>& str, usz _size = umax, std::source_location src_loc = std::source_location::current()) const
{ {
if (!m_file) xnull(src_loc); if (!m_file)
xnull(src_loc);
if (_size != umax) if (_size != umax)
{ {
@ -419,7 +439,8 @@ namespace fs
} }
// Read POD, sizeof(T) is used // Read POD, sizeof(T) is used
template <typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>) template <typename T>
requires(std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
bool read(T& data, bool read(T& data,
pod_tag_t = pod_tag, std::source_location src_loc = std::source_location::current()) const pod_tag_t = pod_tag, std::source_location src_loc = std::source_location::current()) const
{ {
@ -427,10 +448,12 @@ namespace fs
} }
// Read POD std::vector // Read POD std::vector
template <typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>) template <typename T>
requires(std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
bool read(std::vector<T>& vec, usz _size = umax, bool use_offs = false, usz offset = umax, std::source_location src_loc = std::source_location::current()) const bool read(std::vector<T>& vec, usz _size = umax, bool use_offs = false, usz offset = umax, std::source_location src_loc = std::source_location::current()) const
{ {
if (!m_file) xnull(src_loc); if (!m_file)
xnull(src_loc);
if (_size != umax) if (_size != umax)
{ {
@ -452,11 +475,13 @@ namespace fs
} }
// Read POD (experimental) // Read POD (experimental)
template <typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>) template <typename T>
requires(std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
T read(pod_tag_t = pod_tag, std::source_location src_loc = std::source_location::current()) const T read(pod_tag_t = pod_tag, std::source_location src_loc = std::source_location::current()) const
{ {
T result; T result;
if (!read(result, pod_tag, src_loc)) xfail(src_loc); if (!read(result, pod_tag, src_loc))
xfail(src_loc);
return result; return result;
} }
@ -467,17 +492,20 @@ namespace fs
std::basic_string<T> result; std::basic_string<T> result;
result.resize(size() / sizeof(T)); result.resize(size() / sizeof(T));
seek(0); seek(0);
if (!read(result, result.size(), src_loc)) xfail(src_loc); if (!read(result, result.size(), src_loc))
xfail(src_loc);
return result; return result;
} }
// Read full file to std::vector // Read full file to std::vector
template<typename T> requires (std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>) template <typename T>
requires(std::is_trivially_copyable_v<T> && !std::is_pointer_v<T>)
std::vector<T> to_vector(std::source_location src_loc = std::source_location::current()) const std::vector<T> to_vector(std::source_location src_loc = std::source_location::current()) const
{ {
std::vector<T> result; std::vector<T> result;
result.resize(size() / sizeof(T)); result.resize(size() / sizeof(T));
if (!read(result, result.size(), true, 0, src_loc)) xfail(src_loc); if (!read(result, result.size(), true, 0, src_loc))
xfail(src_loc);
return result; return result;
} }
@ -490,7 +518,8 @@ namespace fs
// Gathered write // Gathered write
u64 write_gather(const iovec_clone* buffers, u64 buf_count, std::source_location src_loc = std::source_location::current()) const u64 write_gather(const iovec_clone* buffers, u64 buf_count, std::source_location src_loc = std::source_location::current()) const
{ {
if (!m_file) xnull(src_loc); if (!m_file)
xnull(src_loc);
return m_file->write_gather(buffers, buf_count); return m_file->write_gather(buffers, buf_count);
} }
}; };
@ -536,14 +565,16 @@ namespace fs
// Get next directory entry // Get next directory entry
bool read(dir_entry& out, std::source_location src_loc = std::source_location::current()) const bool read(dir_entry& out, std::source_location src_loc = std::source_location::current()) const
{ {
if (!m_dir) xnull(src_loc); if (!m_dir)
xnull(src_loc);
return m_dir->read(out); return m_dir->read(out);
} }
// Reset to the beginning // Reset to the beginning
void rewind(std::source_location src_loc = std::source_location::current()) const void rewind(std::source_location src_loc = std::source_location::current()) const
{ {
if (!m_dir) xnull(src_loc); if (!m_dir)
xnull(src_loc);
return m_dir->rewind(); return m_dir->rewind();
} }
@ -586,7 +617,7 @@ namespace fs
iterator& operator=(iterator&&) = default; iterator& operator=(iterator&&) = default;
dir_entry& operator *() dir_entry& operator*()
{ {
return m_entry; return m_entry;
} }
@ -604,7 +635,7 @@ namespace fs
return old; return old;
} }
bool operator !=(const iterator& rhs) const bool operator!=(const iterator& rhs) const
{ {
return m_parent != rhs.m_parent; return m_parent != rhs.m_parent;
} }
@ -625,23 +656,26 @@ namespace fs
{ {
std::vector<fs::dir_entry> m_entries; std::vector<fs::dir_entry> m_entries;
std::size_t m_offset = 0; std::size_t m_offset = 0;
public: public:
virtual_dir(std::vector<fs::dir_entry> entries) virtual_dir(std::vector<fs::dir_entry> entries)
: m_entries(std::move(entries)) {} : m_entries(std::move(entries)) {}
bool read(fs::dir_entry &entry) override bool read(fs::dir_entry& entry) override
{ {
if (m_offset < m_entries.size()) if (m_offset < m_entries.size())
{ {
entry = m_entries[m_offset++]; entry = m_entries[m_offset++];
return true; return true;
} }
return false; return false;
} }
void rewind() override { m_offset = 0; } void rewind() override
{
m_offset = 0;
}
}; };
// Get executable path // Get executable path
@ -730,9 +764,7 @@ namespace fs
u64 pos; u64 pos;
container_stream(T&& obj, const stat_t& init_stat = {}) container_stream(T&& obj, const stat_t& init_stat = {})
: obj(std::forward<T>(obj)) : obj(std::forward<T>(obj)), pos(0), m_stat(init_stat)
, pos(0)
, m_stat(init_stat)
{ {
} }
@ -795,7 +827,7 @@ namespace fs
if (pos > old_size) if (pos > old_size)
{ {
// Reserve memory // Reserve memory
obj.reserve(pos + size); obj.reserve(pos + size);
// Fill gap if necessary (default-initialized) // Fill gap if necessary (default-initialized)
@ -812,7 +844,8 @@ namespace fs
obj.insert(obj.end(), src + overlap, src + size); obj.insert(obj.end(), src + overlap, src + size);
pos += size; pos += size;
if (size) update_time(true); if (size)
update_time(true);
return size; return size;
} }
@ -821,7 +854,8 @@ namespace fs
const s64 new_pos = const s64 new_pos =
whence == fs::seek_set ? offset : whence == fs::seek_set ? offset :
whence == fs::seek_cur ? offset + pos : whence == fs::seek_cur ? offset + pos :
whence == fs::seek_end ? offset + size() : -1; whence == fs::seek_end ? offset + size() :
-1;
if (new_pos < 0) if (new_pos < 0)
{ {
@ -899,4 +933,4 @@ namespace fs
file make_gather(std::vector<file>); file make_gather(std::vector<file>);
stx::generator<dir_entry&> list_dir_recursively(const std::string& path); stx::generator<dir_entry&> list_dir_recursively(const std::string& path);
} } // namespace fs

View file

@ -432,7 +432,7 @@ namespace asmjit
c.bind(next); c.bind(next);
} }
#endif #endif
} } // namespace asmjit
// Build runtime function with asmjit::X86Assembler // Build runtime function with asmjit::X86Assembler
template <typename FT, typename Asm = native_asm, typename F> template <typename FT, typename Asm = native_asm, typename F>
@ -501,7 +501,7 @@ namespace llvm
class ExecutionEngine; class ExecutionEngine;
class Module; class Module;
class StringRef; class StringRef;
} } // namespace llvm
enum class thread_state : u32; enum class thread_state : u32;
@ -569,6 +569,6 @@ public:
bool add_sub_disk_space(ssz space); bool add_sub_disk_space(ssz space);
}; };
const char *fallback_cpu_detection(); const char* fallback_cpu_detection();
#endif // LLVM_AVAILABLE #endif // LLVM_AVAILABLE

View file

@ -80,7 +80,7 @@ void jit_announce(uptr func, usz size, std::string_view name)
{ {
u64 addr; // RPCS3 process address u64 addr; // RPCS3 process address
u32 size; // Function size u32 size; // Function size
u32 off; // Function offset u32 off; // Function offset
}; };
// Write index entry at the beginning of file, and data + NTS name at fixed offset // Write index entry at the beginning of file, and data + NTS name at fixed offset
@ -157,30 +157,30 @@ static u8* add_jit_memory(usz size, usz align)
// Simple allocation by incrementing pointer to the next free data // Simple allocation by incrementing pointer to the next free data
const u64 pos = Ctr.atomic_op([&](u64& ctr) -> u64 const u64 pos = Ctr.atomic_op([&](u64& ctr) -> u64
{
const u64 _pos = utils::align(ctr & 0xffff'ffff, align);
const u64 _new = utils::align(_pos + size, align);
if (_new > 0x40000000) [[unlikely]]
{ {
// Sorry, we failed, and further attempts should fail too. const u64 _pos = utils::align(ctr & 0xffff'ffff, align);
ctr |= 0x40000000; const u64 _new = utils::align(_pos + size, align);
return -1;
}
// Last allocation is stored in highest bits if (_new > 0x40000000) [[unlikely]]
olda = ctr >> 32; {
newa = olda; // Sorry, we failed, and further attempts should fail too.
ctr |= 0x40000000;
return -1;
}
// Check the necessity to commit more memory // Last allocation is stored in highest bits
if (_new > olda) [[unlikely]] olda = ctr >> 32;
{ newa = olda;
newa = utils::align(_new, 0x200000);
}
ctr += _new - (ctr & 0xffff'ffff); // Check the necessity to commit more memory
return _pos; if (_new > olda) [[unlikely]]
}); {
newa = utils::align(_new, 0x200000);
}
ctr += _new - (ctr & 0xffff'ffff);
return _pos;
});
if (pos == umax) [[unlikely]] if (pos == umax) [[unlikely]]
{ {
@ -196,12 +196,12 @@ static u8* add_jit_memory(usz size, usz align)
#endif #endif
// Acknowledge committed memory // Acknowledge committed memory
Ctr.atomic_op([&](u64& ctr) Ctr.atomic_op([&](u64& ctr)
{
if ((ctr >> 32) < newa)
{ {
ctr += (newa - (ctr >> 32)) << 32; if ((ctr >> 32) < newa)
} {
}); ctr += (newa - (ctr >> 32)) << 32;
}
});
} }
ensure(pointer + pos >= get_jit_memory() + Off); ensure(pointer + pos >= get_jit_memory() + Off);
@ -364,17 +364,17 @@ jit_runtime_base& asmjit::get_global_runtime()
uchar* _alloc(usz size, usz align) noexcept override uchar* _alloc(usz size, usz align) noexcept override
{ {
return m_pos.atomic_op([&](uchar*& pos) -> uchar* return m_pos.atomic_op([&](uchar*& pos) -> uchar*
{
const auto r = reinterpret_cast<uchar*>(utils::align(uptr(pos), align));
if (r >= pos && r + size > pos && r + size <= m_max)
{ {
pos = r + size; const auto r = reinterpret_cast<uchar*>(utils::align(uptr(pos), align));
return r;
}
return nullptr; if (r >= pos && r + size > pos && r + size <= m_max)
}); {
pos = r + size;
return r;
}
return nullptr;
});
} }
private: private:
@ -389,8 +389,7 @@ jit_runtime_base& asmjit::get_global_runtime()
} }
asmjit::inline_runtime::inline_runtime(uchar* data, usz size) asmjit::inline_runtime::inline_runtime(uchar* data, usz size)
: m_data(data) : m_data(data), m_size(size)
, m_size(size)
{ {
} }

View file

@ -99,39 +99,39 @@ static u64 make_null_function(const std::string& name)
// Build a "null" function that contains its name // Build a "null" function that contains its name
const auto func = build_function_asm<void (*)()>("NULL", [&](native_asm& c, auto& args) const auto func = build_function_asm<void (*)()>("NULL", [&](native_asm& c, auto& args)
{ {
#if defined(ARCH_X64) #if defined(ARCH_X64)
Label data = c.newLabel(); Label data = c.newLabel();
c.lea(args[0], x86::qword_ptr(data, 0)); c.lea(args[0], x86::qword_ptr(data, 0));
c.jmp(Imm(&null)); c.jmp(Imm(&null));
c.align(AlignMode::kCode, 16); c.align(AlignMode::kCode, 16);
c.bind(data); c.bind(data);
// Copy function name bytes // Copy function name bytes
for (char ch : name) for (char ch : name)
c.db(ch); c.db(ch);
c.db(0); c.db(0);
c.align(AlignMode::kData, 16); c.align(AlignMode::kData, 16);
#else #else
// AArch64 implementation // AArch64 implementation
Label data = c.newLabel(); Label data = c.newLabel();
Label jump_address = c.newLabel(); Label jump_address = c.newLabel();
c.ldr(args[0], arm::ptr(data, 0)); c.ldr(args[0], arm::ptr(data, 0));
c.ldr(a64::x14, arm::ptr(jump_address, 0)); c.ldr(a64::x14, arm::ptr(jump_address, 0));
c.br(a64::x14); c.br(a64::x14);
// Data frame // Data frame
c.align(AlignMode::kCode, 16); c.align(AlignMode::kCode, 16);
c.bind(jump_address); c.bind(jump_address);
c.embedUInt64(reinterpret_cast<u64>(&null)); c.embedUInt64(reinterpret_cast<u64>(&null));
c.align(AlignMode::kData, 16); c.align(AlignMode::kData, 16);
c.bind(data); c.bind(data);
c.embed(name.c_str(), name.size()); c.embed(name.c_str(), name.size());
c.embedUInt8(0U); c.embedUInt8(0U);
c.align(AlignMode::kData, 16); c.align(AlignMode::kData, 16);
#endif #endif
}); });
func_ptr = reinterpret_cast<u64>(func); func_ptr = reinterpret_cast<u64>(func);
return func_ptr; return func_ptr;
@ -203,7 +203,7 @@ struct MemoryManager1 : llvm::RTDyldMemoryManager
m_code_mems = ptr; m_code_mems = ptr;
// ptr += c_max_size; // ptr += c_max_size;
// m_data_ro_mems = ptr; // m_data_ro_mems = ptr;
ptr += c_max_size; ptr += c_max_size;
m_data_rw_mems = ptr; m_data_rw_mems = ptr;
} }
@ -246,7 +246,7 @@ struct MemoryManager1 : llvm::RTDyldMemoryManager
u8* allocate(u64& alloc_pos, void* block, uptr size, u64 align, utils::protection prot) u8* allocate(u64& alloc_pos, void* block, uptr size, u64 align, utils::protection prot)
{ {
align = align ? align : 16; align = align ? align : 16;
const u64 sizea = utils::align(size, align); const u64 sizea = utils::align(size, align);
if (!size || align > c_page_size || sizea > c_max_size || sizea < size) if (!size || align > c_page_size || sizea > c_max_size || sizea < size)
@ -312,7 +312,7 @@ struct MemoryManager1 : llvm::RTDyldMemoryManager
if (is_ro) if (is_ro)
{ {
// Disabled // Disabled
//return allocate(data_ro_ptr, m_data_ro_mems, size, align, utils::protection::rw); // return allocate(data_ro_ptr, m_data_ro_mems, size, align, utils::protection::rw);
} }
return allocate(data_rw_ptr, m_data_rw_mems, size, align, utils::protection::rw); return allocate(data_rw_ptr, m_data_rw_mems, size, align, utils::protection::rw);
@ -402,8 +402,7 @@ class ObjectCache final : public llvm::ObjectCache
public: public:
ObjectCache(const std::string& path, jit_compiler* compiler = nullptr) ObjectCache(const std::string& path, jit_compiler* compiler = nullptr)
: m_path(path) : m_path(path), m_compiler(compiler)
, m_compiler(compiler)
{ {
} }
@ -414,7 +413,7 @@ public:
std::string name = m_path; std::string name = m_path;
name.append(_module->getName()); name.append(_module->getName());
//fs::file(name, fs::rewrite).write(obj.getBufferStart(), obj.getBufferSize()); // fs::file(name, fs::rewrite).write(obj.getBufferStart(), obj.getBufferSize());
name.append(".gz"); name.append(".gz");
if (!obj.getBufferSize()) if (!obj.getBufferSize())
@ -628,36 +627,37 @@ bool jit_compiler::add_sub_disk_space(ssz space)
} }
return m_disk_space.fetch_op([sub_size = static_cast<usz>(0 - space)](usz& val) return m_disk_space.fetch_op([sub_size = static_cast<usz>(0 - space)](usz& val)
{ {
if (val >= sub_size) if (val >= sub_size)
{ {
val -= sub_size; val -= sub_size;
return true; return true;
} }
return false; return false;
}).second; })
.second;
} }
jit_compiler::jit_compiler(const std::unordered_map<std::string, u64>& _link, const std::string& _cpu, u32 flags, std::function<u64(const std::string&)> symbols_cement) noexcept jit_compiler::jit_compiler(const std::unordered_map<std::string, u64>& _link, const std::string& _cpu, u32 flags, std::function<u64(const std::string&)> symbols_cement) noexcept
: m_context(new llvm::LLVMContext) : m_context(new llvm::LLVMContext), m_cpu(cpu(_cpu))
, m_cpu(cpu(_cpu))
{ {
[[maybe_unused]] static const bool s_install_llvm_error_handler = []() [[maybe_unused]] static const bool s_install_llvm_error_handler = []()
{ {
llvm::remove_fatal_error_handler(); llvm::remove_fatal_error_handler();
llvm::install_fatal_error_handler([](void*, const char* msg, bool) llvm::install_fatal_error_handler([](void*, const char* msg, bool)
{ {
const std::string_view out = msg ? msg : ""; const std::string_view out = msg ? msg : "";
fmt::throw_exception("LLVM Emergency Exit Invoked: '%s'", out); fmt::throw_exception("LLVM Emergency Exit Invoked: '%s'", out);
}, nullptr); },
nullptr);
return true; return true;
}(); }();
std::string result; std::string result;
auto null_mod = std::make_unique<llvm::Module> ("null_", *m_context); auto null_mod = std::make_unique<llvm::Module>("null_", *m_context);
null_mod->setTargetTriple(jit_compiler::triple1()); null_mod->setTargetTriple(jit_compiler::triple1());
std::unique_ptr<llvm::RTDyldMemoryManager> mem; std::unique_ptr<llvm::RTDyldMemoryManager> mem;
@ -682,17 +682,17 @@ jit_compiler::jit_compiler(const std::unordered_map<std::string, u64>& _link, co
{ {
m_engine.reset(llvm::EngineBuilder(std::move(null_mod)) m_engine.reset(llvm::EngineBuilder(std::move(null_mod))
.setErrorStr(&result) .setErrorStr(&result)
.setEngineKind(llvm::EngineKind::JIT) .setEngineKind(llvm::EngineKind::JIT)
.setMCJITMemoryManager(std::move(mem)) .setMCJITMemoryManager(std::move(mem))
.setOptLevel(llvm::CodeGenOptLevel::Aggressive) .setOptLevel(llvm::CodeGenOptLevel::Aggressive)
.setCodeModel(flags & 0x2 ? llvm::CodeModel::Large : llvm::CodeModel::Small) .setCodeModel(flags & 0x2 ? llvm::CodeModel::Large : llvm::CodeModel::Small)
#ifdef __APPLE__ #ifdef __APPLE__
//.setCodeModel(llvm::CodeModel::Large) //.setCodeModel(llvm::CodeModel::Large)
#endif #endif
.setRelocationModel(llvm::Reloc::Model::PIC_) .setRelocationModel(llvm::Reloc::Model::PIC_)
.setMCPU(m_cpu) .setMCPU(m_cpu)
.create()); .create());
} }
if (!_link.empty()) if (!_link.empty())
@ -824,7 +824,7 @@ u64 jit_compiler::get(const std::string& name)
return m_engine->getGlobalValueAddress(name); return m_engine->getGlobalValueAddress(name);
} }
const char * fallback_cpu_detection() const char* fallback_cpu_detection()
{ {
#if defined(ARCH_X64) #if defined(ARCH_X64)
// If we got here we either have a very old and outdated CPU or a new CPU that has not been seen by LLVM yet. // If we got here we either have a very old and outdated CPU or a new CPU that has not been seen by LLVM yet.

View file

@ -1,21 +1,21 @@
/* /*
* Lightweight URL & URI parser (RFC 1738, RFC 3986) * Lightweight URL & URI parser (RFC 1738, RFC 3986)
* https://github.com/corporateshark/LUrlParser * https://github.com/corporateshark/LUrlParser
* *
* The MIT License (MIT) * The MIT License (MIT)
* *
* Copyright (C) 2015 Sergey Kosarevsky (sk@linderdaum.com) * Copyright (C) 2015 Sergey Kosarevsky (sk@linderdaum.com)
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in all * The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software. * copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -32,29 +32,38 @@
#include <cstdlib> #include <cstdlib>
// check if the scheme name is valid // check if the scheme name is valid
static bool IsSchemeValid( const std::string& SchemeName ) static bool IsSchemeValid(const std::string& SchemeName)
{ {
return std::all_of(SchemeName.cbegin(), SchemeName.cend(), [](const auto& c) return std::all_of(SchemeName.cbegin(), SchemeName.cend(), [](const auto& c)
{ {
return isalpha(c) || c == '+' || c == '-' || c == '.'; return isalpha(c) || c == '+' || c == '-' || c == '.';
}); });
} }
bool LUrlParser::clParseURL::GetPort( int* OutPort ) const bool LUrlParser::clParseURL::GetPort(int* OutPort) const
{ {
if ( !IsValid() ) { return false; } if (!IsValid())
{
return false;
}
const int Port = atoi( m_Port.c_str() ); const int Port = atoi(m_Port.c_str());
if ( Port <= 0 || Port > 65535 ) { return false; } if (Port <= 0 || Port > 65535)
{
return false;
}
if ( OutPort ) { *OutPort = Port; } if (OutPort)
{
*OutPort = Port;
}
return true; return true;
} }
// based on RFC 1738 and RFC 3986 // based on RFC 1738 and RFC 3986
LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL ) LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL(const std::string& URL)
{ {
LUrlParser::clParseURL Result; LUrlParser::clParseURL Result;
@ -68,26 +77,26 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL
// try to read scheme // try to read scheme
{ {
const char* LocalString = strchr( CurrentString, ':' ); const char* LocalString = strchr(CurrentString, ':');
if ( !LocalString ) if (!LocalString)
{ {
return clParseURL( LUrlParserError_NoUrlCharacter ); return clParseURL(LUrlParserError_NoUrlCharacter);
} }
// save the scheme name // save the scheme name
Result.m_Scheme = std::string( CurrentString, LocalString - CurrentString ); Result.m_Scheme = std::string(CurrentString, LocalString - CurrentString);
if ( !IsSchemeValid( Result.m_Scheme ) ) if (!IsSchemeValid(Result.m_Scheme))
{ {
return clParseURL( LUrlParserError_InvalidSchemeName ); return clParseURL(LUrlParserError_InvalidSchemeName);
} }
// scheme should be lowercase // scheme should be lowercase
std::transform( Result.m_Scheme.begin(), Result.m_Scheme.end(), Result.m_Scheme.begin(), ::tolower ); std::transform(Result.m_Scheme.begin(), Result.m_Scheme.end(), Result.m_Scheme.begin(), ::tolower);
// skip ':' // skip ':'
CurrentString = LocalString+1; CurrentString = LocalString + 1;
} }
/* /*
@ -96,23 +105,25 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL
*/ */
// skip "//" // skip "//"
if ( *CurrentString++ != '/' ) return clParseURL( LUrlParserError_NoDoubleSlash ); if (*CurrentString++ != '/')
if ( *CurrentString++ != '/' ) return clParseURL( LUrlParserError_NoDoubleSlash ); return clParseURL(LUrlParserError_NoDoubleSlash);
if (*CurrentString++ != '/')
return clParseURL(LUrlParserError_NoDoubleSlash);
// check if the user name and password are specified // check if the user name and password are specified
bool bHasUserName = false; bool bHasUserName = false;
const char* LocalString = CurrentString; const char* LocalString = CurrentString;
while ( *LocalString ) while (*LocalString)
{ {
if ( *LocalString == '@' ) if (*LocalString == '@')
{ {
// user name and password are specified // user name and password are specified
bHasUserName = true; bHasUserName = true;
break; break;
} }
else if ( *LocalString == '/' ) else if (*LocalString == '/')
{ {
// end of <host>:<port> specification // end of <host>:<port> specification
bHasUserName = false; bHasUserName = false;
@ -125,17 +136,18 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL
// user name and password // user name and password
LocalString = CurrentString; LocalString = CurrentString;
if ( bHasUserName ) if (bHasUserName)
{ {
// read user name // read user name
while ( *LocalString && *LocalString != ':' && *LocalString != '@' ) LocalString++; while (*LocalString && *LocalString != ':' && *LocalString != '@')
LocalString++;
Result.m_UserName = std::string( CurrentString, LocalString - CurrentString ); Result.m_UserName = std::string(CurrentString, LocalString - CurrentString);
// proceed with the current pointer // proceed with the current pointer
CurrentString = LocalString; CurrentString = LocalString;
if ( *CurrentString == ':' ) if (*CurrentString == ':')
{ {
// skip ':' // skip ':'
CurrentString++; CurrentString++;
@ -143,36 +155,37 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL
// read password // read password
LocalString = CurrentString; LocalString = CurrentString;
while ( *LocalString && *LocalString != '@' ) LocalString++; while (*LocalString && *LocalString != '@')
LocalString++;
Result.m_Password = std::string( CurrentString, LocalString - CurrentString ); Result.m_Password = std::string(CurrentString, LocalString - CurrentString);
CurrentString = LocalString; CurrentString = LocalString;
} }
// skip '@' // skip '@'
if ( *CurrentString != '@' ) if (*CurrentString != '@')
{ {
return clParseURL( LUrlParserError_NoAtSign ); return clParseURL(LUrlParserError_NoAtSign);
} }
CurrentString++; CurrentString++;
} }
bool bHasBracket = ( *CurrentString == '[' ); bool bHasBracket = (*CurrentString == '[');
// go ahead, read the host name // go ahead, read the host name
LocalString = CurrentString; LocalString = CurrentString;
while ( *LocalString ) while (*LocalString)
{ {
if ( bHasBracket && *LocalString == ']' ) if (bHasBracket && *LocalString == ']')
{ {
// end of IPv6 address // end of IPv6 address
LocalString++; LocalString++;
break; break;
} }
else if ( !bHasBracket && ( *LocalString == ':' || *LocalString == '/' ) ) else if (!bHasBracket && (*LocalString == ':' || *LocalString == '/'))
{ {
// port number is specified // port number is specified
break; break;
@ -181,27 +194,28 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL
LocalString++; LocalString++;
} }
Result.m_Host = std::string( CurrentString, LocalString - CurrentString ); Result.m_Host = std::string(CurrentString, LocalString - CurrentString);
CurrentString = LocalString; CurrentString = LocalString;
// is port number specified? // is port number specified?
if ( *CurrentString == ':' ) if (*CurrentString == ':')
{ {
CurrentString++; CurrentString++;
// read port number // read port number
LocalString = CurrentString; LocalString = CurrentString;
while ( *LocalString && *LocalString != '/' ) LocalString++; while (*LocalString && *LocalString != '/')
LocalString++;
Result.m_Port = std::string( CurrentString, LocalString - CurrentString ); Result.m_Port = std::string(CurrentString, LocalString - CurrentString);
CurrentString = LocalString; CurrentString = LocalString;
} }
// end of string // end of string
if ( !*CurrentString ) if (!*CurrentString)
{ {
Result.m_ErrorCode = LUrlParserError_Ok; Result.m_ErrorCode = LUrlParserError_Ok;
@ -209,9 +223,9 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL
} }
// skip '/' // skip '/'
if ( *CurrentString != '/' ) if (*CurrentString != '/')
{ {
return clParseURL( LUrlParserError_NoSlash ); return clParseURL(LUrlParserError_NoSlash);
} }
CurrentString++; CurrentString++;
@ -219,14 +233,15 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL
// parse the path // parse the path
LocalString = CurrentString; LocalString = CurrentString;
while ( *LocalString && *LocalString != '#' && *LocalString != '?' ) LocalString++; while (*LocalString && *LocalString != '#' && *LocalString != '?')
LocalString++;
Result.m_Path = std::string( CurrentString, LocalString - CurrentString ); Result.m_Path = std::string(CurrentString, LocalString - CurrentString);
CurrentString = LocalString; CurrentString = LocalString;
// check for query // check for query
if ( *CurrentString == '?' ) if (*CurrentString == '?')
{ {
// skip '?' // skip '?'
CurrentString++; CurrentString++;
@ -234,15 +249,16 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL
// read query // read query
LocalString = CurrentString; LocalString = CurrentString;
while ( *LocalString && *LocalString != '#' ) LocalString++; while (*LocalString && *LocalString != '#')
LocalString++;
Result.m_Query = std::string( CurrentString, LocalString - CurrentString ); Result.m_Query = std::string(CurrentString, LocalString - CurrentString);
CurrentString = LocalString; CurrentString = LocalString;
} }
// check for fragment // check for fragment
if ( *CurrentString == '#' ) if (*CurrentString == '#')
{ {
// skip '#' // skip '#'
CurrentString++; CurrentString++;
@ -250,9 +266,10 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL
// read fragment // read fragment
LocalString = CurrentString; LocalString = CurrentString;
while ( *LocalString ) LocalString++; while (*LocalString)
LocalString++;
Result.m_Fragment = std::string( CurrentString, LocalString - CurrentString ); Result.m_Fragment = std::string(CurrentString, LocalString - CurrentString);
CurrentString = LocalString; CurrentString = LocalString;
} }

View file

@ -57,22 +57,27 @@ namespace LUrlParser
std::string m_Password{}; std::string m_Password{};
clParseURL() clParseURL()
: m_ErrorCode( LUrlParserError_Uninitialized ) : m_ErrorCode(LUrlParserError_Uninitialized)
{} {
}
/// return 'true' if the parsing was successful /// return 'true' if the parsing was successful
bool IsValid() const { return m_ErrorCode == LUrlParserError_Ok; } bool IsValid() const
{
return m_ErrorCode == LUrlParserError_Ok;
}
/// helper to convert the port number to int, return 'true' if the port is valid (within the 0..65535 range) /// helper to convert the port number to int, return 'true' if the port is valid (within the 0..65535 range)
bool GetPort( int* OutPort ) const; bool GetPort(int* OutPort) const;
/// parse the URL /// parse the URL
static clParseURL ParseURL( const std::string& URL ); static clParseURL ParseURL(const std::string& URL);
private: private:
explicit clParseURL( LUrlParserError ErrorCode ) explicit clParseURL(LUrlParserError ErrorCode)
: m_ErrorCode( ErrorCode ) : m_ErrorCode(ErrorCode)
{} {
}
}; };
} // namespace LUrlParser } // namespace LUrlParser

View file

@ -8,10 +8,11 @@
#include <codecvt> #include <codecvt>
#include <algorithm> #include <algorithm>
#include <string_view> #include <string_view>
#include <string>
#include "Thread.h" #include "Thread.h"
#ifdef _WIN32 #ifdef _WIN32
#include <Windows.h> #include <windows.h>
#else #else
#include <errno.h> #include <errno.h>
#endif #endif
@ -568,19 +569,18 @@ void fmt_class_string<std::source_location>::format(std::string& out, u64 arg)
if (std::string_view full_func{loc.function_name() ? loc.function_name() : ""}; !full_func.empty()) if (std::string_view full_func{loc.function_name() ? loc.function_name() : ""}; !full_func.empty())
{ {
// Remove useless disambiguators // Remove useless disambiguators
std::string func = fmt::replace_all(std::string(full_func), { std::string func = fmt::replace_all(std::string(full_func), {{"struct ", ""},
{"struct ", ""}, {"class ", ""},
{"class ", ""}, {"enum ", ""},
{"enum ", ""}, {"typename ", ""},
{"typename ", ""},
#ifdef _MSC_VER #ifdef _MSC_VER
{"__cdecl ", ""}, {"__cdecl ", ""},
#endif #endif
{"unsigned long long", "ullong"}, {"unsigned long long", "ullong"},
//{"unsigned long", "ulong"}, // ullong //{"unsigned long", "ulong"}, // ullong
{"unsigned int", "uint"}, {"unsigned int", "uint"},
{"unsigned short", "ushort"}, {"unsigned short", "ushort"},
{"unsigned char", "uchar"}}); {"unsigned char", "uchar"}});
// Remove function argument signature for long names // Remove function argument signature for long names
for (usz index = func.find_first_of('('); index != umax && func.size() >= 100u; index = func.find_first_of('(', index)) for (usz index = func.find_first_of('('); index != umax && func.size() >= 100u; index = func.find_first_of('(', index))
@ -670,7 +670,7 @@ namespace fmt
} }
struct cfmt_src; struct cfmt_src;
} } // namespace fmt
// Temporary implementation // Temporary implementation
struct fmt::cfmt_src struct fmt::cfmt_src
@ -713,14 +713,16 @@ struct fmt::cfmt_src
usz type(usz extra) const usz type(usz extra) const
{ {
// Hack: use known function pointers to determine type // Hack: use known function pointers to determine type
#define TYPE(type) \ #define TYPE(type) \
if (sup[extra].fmt_string == &fmt_class_string<type>::format) return sizeof(type); if (sup[extra].fmt_string == &fmt_class_string<type>::format) \
return sizeof(type);
TYPE(int); TYPE(int);
TYPE(llong); TYPE(llong);
TYPE(schar); TYPE(schar);
TYPE(short); TYPE(short);
if constexpr (std::is_signed_v<char>) TYPE(char); if constexpr (std::is_signed_v<char>)
TYPE(char);
TYPE(long); TYPE(long);
TYPE(s128); TYPE(s128);
@ -731,14 +733,14 @@ struct fmt::cfmt_src
return 0; return 0;
} }
static constexpr usz size_char = 1; static constexpr usz size_char = 1;
static constexpr usz size_short = 2; static constexpr usz size_short = 2;
static constexpr usz size_int = 0; static constexpr usz size_int = 0;
static constexpr usz size_long = sizeof(ulong); static constexpr usz size_long = sizeof(ulong);
static constexpr usz size_llong = sizeof(ullong); static constexpr usz size_llong = sizeof(ullong);
static constexpr usz size_size = sizeof(usz); static constexpr usz size_size = sizeof(usz);
static constexpr usz size_max = sizeof(std::uintmax_t); static constexpr usz size_max = sizeof(std::uintmax_t);
static constexpr usz size_diff = sizeof(std::ptrdiff_t); static constexpr usz size_diff = sizeof(std::ptrdiff_t);
}; };
void fmt::raw_append(std::string& out, const char* fmt, const fmt_type_info* sup, const u64* args) noexcept void fmt::raw_append(std::string& out, const char* fmt, const fmt_type_info* sup, const u64* args) noexcept
@ -806,7 +808,7 @@ std::vector<std::string> fmt::split(std::string_view source, std::initializer_li
continue; continue;
} }
result.emplace_back(std::string(piece)); result.emplace_back(piece);
} }
if (result.empty() && !is_skip_empty) if (result.empty() && !is_skip_empty)

View file

@ -7,7 +7,7 @@
namespace fmt namespace fmt
{ {
template <typename CharT, usz N, typename... Args> template <typename CharT, usz N, typename... Args>
static std::string format(const CharT(&)[N], const Args&...); static std::string format(const CharT (&)[N], const Args&...);
#ifdef _WIN32 #ifdef _WIN32
struct win_error struct win_error
@ -20,7 +20,7 @@ namespace fmt
std::string win_error_to_string(unsigned long error, void* module_handle = nullptr); std::string win_error_to_string(unsigned long error, void* module_handle = nullptr);
std::string win_error_to_string(const win_error& error); std::string win_error_to_string(const win_error& error);
#endif #endif
} } // namespace fmt
template <typename T> template <typename T>
struct fmt_unveil struct fmt_unveil
@ -146,7 +146,7 @@ struct fmt_class_string
} }
// Enum -> string function type // Enum -> string function type
using convert_t = const char*(*)(T value); using convert_t = const char* (*)(T value);
// Helper function (safely converts arg to enum value) // Helper function (safely converts arg to enum value)
static FORCE_INLINE SAFE_BUFFERS(void) format_enum(std::string& out, u64 arg, convert_t convert) static FORCE_INLINE SAFE_BUFFERS(void) format_enum(std::string& out, u64 arg, convert_t convert)
@ -250,11 +250,10 @@ struct fmt_class_string<wchar_t*> : fmt_class_string<const wchar_t*>
namespace fmt namespace fmt
{ {
template <typename T> template <typename T>
concept StringConvertible = requires (T & t) concept StringConvertible = requires(T& t) {
{
{ t.to_string() } -> std::convertible_to<std::string>; { t.to_string() } -> std::convertible_to<std::string>;
}; };
} } // namespace fmt
template <fmt::StringConvertible T> template <fmt::StringConvertible T>
struct fmt_class_string<T> struct fmt_class_string<T>
@ -274,8 +273,8 @@ namespace fmt
{ {
// Both uchar and std::byte are allowed // Both uchar and std::byte are allowed
template <typename T> template <typename T>
concept ByteArray = requires (T& t) { const_cast<std::conditional_t<std::is_same_v<decltype(std::as_const(t[0])), const std::byte&>, std::byte, uchar>&>(std::data(t)[0]); }; concept ByteArray = requires(T& t) { const_cast<std::conditional_t<std::is_same_v<decltype(std::as_const(t[0])), const std::byte&>, std::byte, uchar>&>(std::data(t)[0]); };
} } // namespace fmt
template <fmt::ByteArray T> template <fmt::ByteArray T>
struct fmt_class_string<T> struct fmt_class_string<T>
@ -301,8 +300,7 @@ struct fmt_type_info
template <typename T> template <typename T>
static constexpr fmt_type_info make() static constexpr fmt_type_info make()
{ {
return fmt_type_info return fmt_type_info{
{
&fmt_class_string<T>::format, &fmt_class_string<T>::format,
}; };
} }
@ -310,7 +308,7 @@ struct fmt_type_info
// Argument array type (each element generated via fmt_unveil<>) // Argument array type (each element generated via fmt_unveil<>)
template <typename... Args> template <typename... Args>
using fmt_args_t = const u64(&&)[sizeof...(Args) + 1]; using fmt_args_t = const u64 (&&)[sizeof...(Args) + 1];
template <typename Arg> template <typename Arg>
using fmt_unveil_t = typename fmt_unveil<Arg>::type; using fmt_unveil_t = typename fmt_unveil<Arg>::type;
@ -327,14 +325,12 @@ namespace fmt
template <typename T> template <typename T>
base57(const T& arg) noexcept base57(const T& arg) noexcept
: data(reinterpret_cast<const uchar*>(std::addressof(arg))) : data(reinterpret_cast<const uchar*>(std::addressof(arg))), size(sizeof(T))
, size(sizeof(T))
{ {
} }
base57(const uchar* data, usz size) noexcept base57(const uchar* data, usz size) noexcept
: data(data) : data(data), size(size)
, size(size)
{ {
} }
}; };
@ -348,8 +344,7 @@ namespace fmt
base57_result& operator=(base57_result&&) = default; base57_result& operator=(base57_result&&) = default;
explicit base57_result(usz size) noexcept explicit base57_result(usz size) noexcept
: base57(size ? new uchar[size] : nullptr, size) : base57(size ? new uchar[size] : nullptr, size), memory(const_cast<uchar*>(this->data))
, memory(const_cast<uchar*>(this->data))
{ {
} }
@ -364,14 +359,14 @@ namespace fmt
// Formatting function // Formatting function
template <typename CharT, usz N, typename... Args> template <typename CharT, usz N, typename... Args>
FORCE_INLINE SAFE_BUFFERS(void) append(std::string& out, const CharT(&fmt)[N], const Args&... args) FORCE_INLINE SAFE_BUFFERS(void) append(std::string& out, const CharT (&fmt)[N], const Args&... args)
{ {
raw_append(out, reinterpret_cast<const char*>(fmt), type_info_v<Args...>, fmt_args_t<Args...>{fmt_unveil<Args>::get(args)...}); raw_append(out, reinterpret_cast<const char*>(fmt), type_info_v<Args...>, fmt_args_t<Args...>{fmt_unveil<Args>::get(args)...});
} }
// Formatting function // Formatting function
template <typename CharT, usz N, typename... Args> template <typename CharT, usz N, typename... Args>
FORCE_INLINE SAFE_BUFFERS(std::string) format(const CharT(&fmt)[N], const Args&... args) FORCE_INLINE SAFE_BUFFERS(std::string) format(const CharT (&fmt)[N], const Args&... args)
{ {
std::string result; std::string result;
append(result, fmt, args...); append(result, fmt, args...);
@ -385,9 +380,11 @@ namespace fmt
template <typename CharT, usz N, typename... Args> template <typename CharT, usz N, typename... Args>
struct throw_exception struct throw_exception
{ {
struct args_break_t {}; struct args_break_t
{
};
[[noreturn]] FORCE_INLINE SAFE_BUFFERS() throw_exception(const CharT(&fmt)[N], const Args&... args, [[noreturn]] FORCE_INLINE SAFE_BUFFERS() throw_exception(const CharT (&fmt)[N], const Args&... args,
args_break_t = args_break_t{}, std::source_location src_loc = std::source_location::current()) args_break_t = args_break_t{}, std::source_location src_loc = std::source_location::current())
{ {
raw_throw_exception(src_loc, reinterpret_cast<const char*>(fmt), type_info_v<Args...>, fmt_args_t<Args...>{fmt_unveil<Args>::get(args)...}); raw_throw_exception(src_loc, reinterpret_cast<const char*>(fmt), type_info_v<Args...>, fmt_args_t<Args...>{fmt_unveil<Args>::get(args)...});
@ -399,7 +396,7 @@ namespace fmt
}; };
template <typename CharT, usz N, typename... Args> template <typename CharT, usz N, typename... Args>
throw_exception(const CharT(&)[N], const Args&...) -> throw_exception<CharT, N, Args...>; throw_exception(const CharT (&)[N], const Args&...) -> throw_exception<CharT, N, Args...>;
// Helper template: pack format variables // Helper template: pack format variables
template <typename Arg = void, typename... Args> template <typename Arg = void, typename... Args>
@ -412,8 +409,7 @@ namespace fmt
// Store only references, unveil op is postponed // Store only references, unveil op is postponed
tie(Arg&& arg, Args&&... args) noexcept tie(Arg&& arg, Args&&... args) noexcept
: arg(std::forward<Arg>(arg)) : arg(std::forward<Arg>(arg)), next(std::forward<Args>(args)...)
, next(std::forward<Args>(args)...)
{ {
} }
@ -445,7 +441,7 @@ namespace fmt
// Ensure with formatting // Ensure with formatting
template <typename T, typename CharT, usz N, typename... Args> template <typename T, typename CharT, usz N, typename... Args>
decltype(auto) ensure(T&& arg, const CharT(&fmt)[N], tie<Args...> args, std::source_location src_loc = std::source_location::current()) noexcept decltype(auto) ensure(T&& arg, const CharT (&fmt)[N], tie<Args...> args, std::source_location src_loc = std::source_location::current()) noexcept
{ {
if (std::forward<T>(arg)) [[likely]] if (std::forward<T>(arg)) [[likely]]
{ {
@ -458,4 +454,4 @@ namespace fmt
raw_throw_exception(src_loc, reinterpret_cast<const char*>(fmt), type_info_v<std::remove_cvref_t<Args>...>, +data); raw_throw_exception(src_loc, reinterpret_cast<const char*>(fmt), type_info_v<std::remove_cvref_t<Args>...>, +data);
} }
} } // namespace fmt

View file

@ -96,8 +96,7 @@ namespace fmt
return src; return src;
} }
static inline static inline std::string replace_all(std::string src, const std::vector<std::pair<std::string, std::string>>& list)
std::string replace_all(std::string src, const std::vector<std::pair<std::string, std::string>>& list)
{ {
for (usz pos = 0; pos < src.length(); ++pos) for (usz pos = 0; pos < src.length(); ++pos)
{ {
@ -138,7 +137,7 @@ namespace fmt
std::string result; std::string result;
auto it = source.begin(); auto it = source.begin();
auto end = source.end(); auto end = source.end();
for (--end; it != end; ++it) for (--end; it != end; ++it)
{ {
@ -164,7 +163,7 @@ namespace fmt
if (first) if (first)
{ {
result = fmt::merge(v, separator); result = fmt::merge(v, separator);
first = false; first = false;
} }
else else
{ {
@ -211,4 +210,4 @@ namespace fmt
return hash_type{}(str); return hash_type{}(str);
} }
}; };
} } // namespace fmt

View file

@ -16,7 +16,7 @@
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
#include <Windows.h> #include <windows.h>
#include <Psapi.h> #include <Psapi.h>
#include <process.h> #include <process.h>
#include <sysinfoapi.h> #include <sysinfoapi.h>
@ -56,34 +56,34 @@ DYNAMIC_IMPORT_RENAME("Kernel32.dll", SetThreadDescriptionImport, "SetThreadDesc
#endif #endif
#if defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #if defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
# include <sys/sysctl.h> #include <sys/sysctl.h>
# include <unistd.h> #include <unistd.h>
# if defined(__DragonFly__) || defined(__FreeBSD__) #if defined(__DragonFly__) || defined(__FreeBSD__)
# include <sys/user.h> #include <sys/user.h>
# endif #endif
# if defined(__OpenBSD__) #if defined(__OpenBSD__)
# include <sys/param.h> #include <sys/param.h>
# include <sys/proc.h> #include <sys/proc.h>
# endif #endif
# if defined(__NetBSD__) #if defined(__NetBSD__)
# undef KERN_PROC #undef KERN_PROC
# define KERN_PROC KERN_PROC2 #define KERN_PROC KERN_PROC2
# define kinfo_proc kinfo_proc2 #define kinfo_proc kinfo_proc2
# endif #endif
# if defined(__APPLE__) #if defined(__APPLE__)
# define KP_FLAGS kp_proc.p_flag #define KP_FLAGS kp_proc.p_flag
# elif defined(__DragonFly__) #elif defined(__DragonFly__)
# define KP_FLAGS kp_flags #define KP_FLAGS kp_flags
# elif defined(__FreeBSD__) #elif defined(__FreeBSD__)
# define KP_FLAGS ki_flag #define KP_FLAGS ki_flag
# elif defined(__NetBSD__) #elif defined(__NetBSD__)
# define KP_FLAGS p_flag #define KP_FLAGS p_flag
# elif defined(__OpenBSD__) #elif defined(__OpenBSD__)
# define KP_FLAGS p_psflags #define KP_FLAGS p_psflags
# define P_TRACED PS_TRACED #define P_TRACED PS_TRACED
# endif #endif
#endif #endif
#include "util/vm.hpp" #include "util/vm.hpp"
@ -104,27 +104,29 @@ thread_local u64 g_tls_fault_spu = 0;
thread_local u64 g_tls_wait_time = 0; thread_local u64 g_tls_wait_time = 0;
thread_local u64 g_tls_wait_fail = 0; thread_local u64 g_tls_wait_fail = 0;
thread_local bool g_tls_access_violation_recovered = false; thread_local bool g_tls_access_violation_recovered = false;
extern thread_local std::string(*g_tls_log_prefix)(); extern thread_local std::string (*g_tls_log_prefix)();
// Report error and call std::abort(), defined in main.cpp // Report error and call std::abort(), defined in main.cpp
[[noreturn]] void report_fatal_error(std::string_view text, bool is_html = false, bool include_help_text = true); [[noreturn]] void report_fatal_error(std::string_view text, bool is_html = false, bool include_help_text = true);
enum cpu_threads_emulation_info_dump_t : u32 {}; enum cpu_threads_emulation_info_dump_t : u32
{
};
template<> template <>
void fmt_class_string<thread_class>::format(std::string& out, u64 arg) void fmt_class_string<thread_class>::format(std::string& out, u64 arg)
{ {
format_enum(out, arg, [](thread_class value) format_enum(out, arg, [](thread_class value)
{
switch (value)
{ {
case thread_class::general: return "General"; switch (value)
case thread_class::ppu: return "PPU"; {
case thread_class::spu: return "SPU"; case thread_class::general: return "General";
case thread_class::rsx: return "RSX"; case thread_class::ppu: return "PPU";
} case thread_class::spu: return "SPU";
return unknown; case thread_class::rsx: return "RSX";
}); }
return unknown;
});
} }
std::string dump_useful_thread_info() std::string dump_useful_thread_info()
@ -148,10 +150,10 @@ bool IsDebuggerPresent()
KERN_PROC, KERN_PROC,
KERN_PROC_PID, KERN_PROC_PID,
getpid(), getpid(),
# if defined(__NetBSD__) || defined(__OpenBSD__) #if defined(__NetBSD__) || defined(__OpenBSD__)
sizeof(struct kinfo_proc), sizeof(struct kinfo_proc),
1, 1,
# endif #endif
}; };
u_int miblen = std::size(mib); u_int miblen = std::size(mib);
struct kinfo_proc info; struct kinfo_proc info;
@ -318,9 +320,9 @@ void decode_x64_reg_op(const u8* code, x64_op_t& out_op, x64_reg_t& out_reg, usz
enum : u8 enum : u8
{ {
LOCK = 0xf0, LOCK = 0xf0,
REPNE = 0xf2, REPNE = 0xf2,
REPE = 0xf3, REPE = 0xf3,
}; };
// check prefixes: // check prefixes:
@ -590,7 +592,7 @@ void decode_x64_reg_op(const u8* code, x64_op_t& out_op, x64_reg_t& out_reg, usz
{ {
switch (get_modRM_reg(code, 0)) switch (get_modRM_reg(code, 0))
{ {
//case 0: out_op = X64OP_ADD; break; // TODO: strange info in instruction manual // case 0: out_op = X64OP_ADD; break; // TODO: strange info in instruction manual
case 1: out_op = X64OP_OR; break; case 1: out_op = X64OP_OR; break;
case 2: out_op = X64OP_ADC; break; case 2: out_op = X64OP_ADC; break;
case 3: out_op = X64OP_SBB; break; case 3: out_op = X64OP_SBB; break;
@ -758,7 +760,7 @@ void decode_x64_reg_op(const u8* code, x64_op_t& out_op, x64_reg_t& out_reg, usz
const u8 opx = op1 == 0xc5 ? op2 : op3; const u8 opx = op1 == 0xc5 ? op2 : op3;
// Implied prefixes // Implied prefixes
rex |= op2 & 0x80 ? 0 : 0x4; // REX.R rex |= op2 & 0x80 ? 0 : 0x4; // REX.R
rex |= op1 == 0xc4 && op3 & 0x80 ? 0x8 : 0; // REX.W ??? rex |= op1 == 0xc4 && op3 & 0x80 ? 0x8 : 0; // REX.W ???
oso = (opx & 0x3) == 0x1; oso = (opx & 0x3) == 0x1;
repe = (opx & 0x3) == 0x2; repe = (opx & 0x3) == 0x2;
@ -773,50 +775,52 @@ void decode_x64_reg_op(const u8* code, x64_op_t& out_op, x64_reg_t& out_reg, usz
s_tls_reg3 = x64_reg_t{vreg}; s_tls_reg3 = x64_reg_t{vreg};
if (vopm == 0x1) switch (vop1) // Implied leading byte 0x0F if (vopm == 0x1)
{ switch (vop1) // Implied leading byte 0x0F
case 0x11:
case 0x29:
{
if (!repe && !repne) // VMOVAPS/VMOVAPD/VMOVUPS/VMOVUPD mem,reg
{ {
out_op = X64OP_STORE; case 0x11:
out_reg = get_modRM_reg_xmm(code, rex); case 0x29:
out_size = vlen;
out_length += get_modRM_size(code);
return;
}
break;
}
case 0x7f:
{
if (repe || oso) // VMOVDQU/VMOVDQA mem,reg
{ {
out_op = X64OP_STORE; if (!repe && !repne) // VMOVAPS/VMOVAPD/VMOVUPS/VMOVUPD mem,reg
out_reg = get_modRM_reg_xmm(code, rex); {
out_size = vlen; out_op = X64OP_STORE;
out_length += get_modRM_size(code); out_reg = get_modRM_reg_xmm(code, rex);
return; out_size = vlen;
out_length += get_modRM_size(code);
return;
}
break;
}
case 0x7f:
{
if (repe || oso) // VMOVDQU/VMOVDQA mem,reg
{
out_op = X64OP_STORE;
out_reg = get_modRM_reg_xmm(code, rex);
out_size = vlen;
out_length += get_modRM_size(code);
return;
}
break;
}
} }
break;
}
}
if (vopm == 0x2) switch (vop1) // Implied leading bytes 0x0F 0x38 if (vopm == 0x2)
{ switch (vop1) // Implied leading bytes 0x0F 0x38
case 0xf7:
{
if (!repe && !repne && vlen == 16) // BEXTR r32,mem,r32
{ {
out_op = X64OP_BEXTR; case 0xf7:
out_reg = get_modRM_reg_xmm(code, rex); {
out_size = opx & 0x80 ? 8 : 4; if (!repe && !repne && vlen == 16) // BEXTR r32,mem,r32
out_length += get_modRM_size(code); {
return; out_op = X64OP_BEXTR;
out_reg = get_modRM_reg_xmm(code, rex);
out_size = opx & 0x80 ? 8 : 4;
out_length += get_modRM_size(code);
return;
}
break;
}
} }
break;
}
}
break; break;
} }
@ -900,10 +904,10 @@ typedef ucontext_t x64_context;
#define XMMREG(context, reg) (reinterpret_cast<v128*>(&(context)->uc_mcontext->__fs.__fpu_xmm0.__xmm_reg[reg])) #define XMMREG(context, reg) (reinterpret_cast<v128*>(&(context)->uc_mcontext->__fs.__fpu_xmm0.__xmm_reg[reg]))
#define EFLAGS(context) ((context)->uc_mcontext->__ss.__rflags) #define EFLAGS(context) ((context)->uc_mcontext->__ss.__rflags)
u64* darwin_x64reg(x64_context *context, int reg) u64* darwin_x64reg(x64_context* context, int reg)
{ {
auto *state = &context->uc_mcontext->__ss; auto* state = &context->uc_mcontext->__ss;
switch(reg) switch (reg)
{ {
case 0: return &state->__rax; case 0: return &state->__rax;
case 1: return &state->__rcx; case 1: return &state->__rcx;
@ -932,16 +936,16 @@ u64* darwin_x64reg(x64_context *context, int reg)
#define X64REG(context, reg) (freebsd_x64reg(context, reg)) #define X64REG(context, reg) (freebsd_x64reg(context, reg))
#ifdef __DragonFly__ #ifdef __DragonFly__
# define XMMREG(context, reg) (reinterpret_cast<v128*>((reinterpret_cast<union savefpu*>(context)->uc_mcontext.mc_fpregs)->sv_xmm.sv_xmm[reg])) #define XMMREG(context, reg) (reinterpret_cast<v128*>((reinterpret_cast<union savefpu*>(context)->uc_mcontext.mc_fpregs)->sv_xmm.sv_xmm[reg]))
#else #else
# define XMMREG(context, reg) (reinterpret_cast<v128*>((reinterpret_cast<struct savefpu*>(context)->uc_mcontext.mc_fpstate)->sv_xmm[reg])) #define XMMREG(context, reg) (reinterpret_cast<v128*>((reinterpret_cast<struct savefpu*>(context)->uc_mcontext.mc_fpstate)->sv_xmm[reg]))
#endif #endif
#define EFLAGS(context) ((context)->uc_mcontext.mc_rflags) #define EFLAGS(context) ((context)->uc_mcontext.mc_rflags)
register_t* freebsd_x64reg(x64_context *context, int reg) register_t* freebsd_x64reg(x64_context* context, int reg)
{ {
auto *state = &context->uc_mcontext; auto* state = &context->uc_mcontext;
switch(reg) switch (reg)
{ {
case 0: return &state->mc_rax; case 0: return &state->mc_rax;
case 1: return &state->mc_rcx; case 1: return &state->mc_rcx;
@ -972,10 +976,10 @@ register_t* freebsd_x64reg(x64_context *context, int reg)
#define XMMREG(context, reg) (reinterpret_cast<v128*>((context)->sc_fpstate->fx_xmm[reg])) #define XMMREG(context, reg) (reinterpret_cast<v128*>((context)->sc_fpstate->fx_xmm[reg]))
#define EFLAGS(context) ((context)->sc_rflags) #define EFLAGS(context) ((context)->sc_rflags)
long* openbsd_x64reg(x64_context *context, int reg) long* openbsd_x64reg(x64_context* context, int reg)
{ {
auto *state = &context; auto* state = &context;
switch(reg) switch (reg)
{ {
case 0: return &state->sc_rax; case 0: return &state->sc_rax;
case 1: return &state->sc_rcx; case 1: return &state->sc_rcx;
@ -1003,10 +1007,9 @@ long* openbsd_x64reg(x64_context *context, int reg)
#elif defined(__NetBSD__) #elif defined(__NetBSD__)
static const decltype(_REG_RAX) reg_table[] = static const decltype(_REG_RAX) reg_table[] =
{ {
_REG_RAX, _REG_RCX, _REG_RDX, _REG_RBX, _REG_RSP, _REG_RBP, _REG_RSI, _REG_RDI, _REG_RAX, _REG_RCX, _REG_RDX, _REG_RBX, _REG_RSP, _REG_RBP, _REG_RSI, _REG_RDI,
_REG_R8, _REG_R9, _REG_R10, _REG_R11, _REG_R12, _REG_R13, _REG_R14, _REG_R15, _REG_RIP _REG_R8, _REG_R9, _REG_R10, _REG_R11, _REG_R12, _REG_R13, _REG_R14, _REG_R15, _REG_RIP};
};
#define X64REG(context, reg) (&(context)->uc_mcontext.__gregs[reg_table[reg]]) #define X64REG(context, reg) (&(context)->uc_mcontext.__gregs[reg_table[reg]])
#define XMM_sig(context, reg) (reinterpret_cast<v128*>(((struct fxsave64*)(context)->uc_mcontext.__fpregs)->fx_xmm[reg])) #define XMM_sig(context, reg) (reinterpret_cast<v128*>(((struct fxsave64*)(context)->uc_mcontext.__fpregs)->fx_xmm[reg]))
@ -1015,10 +1018,9 @@ static const decltype(_REG_RAX) reg_table[] =
#else #else
static const int reg_table[] = static const int reg_table[] =
{ {
REG_RAX, REG_RCX, REG_RDX, REG_RBX, REG_RSP, REG_RBP, REG_RSI, REG_RDI, REG_RAX, REG_RCX, REG_RDX, REG_RBX, REG_RSP, REG_RBP, REG_RSI, REG_RDI,
REG_R8, REG_R9, REG_R10, REG_R11, REG_R12, REG_R13, REG_R14, REG_R15, REG_RIP REG_R8, REG_R9, REG_R10, REG_R11, REG_R12, REG_R13, REG_R14, REG_R15, REG_RIP};
};
#define X64REG(context, reg) (&(context)->uc_mcontext.gregs[reg_table[reg]]) #define X64REG(context, reg) (&(context)->uc_mcontext.gregs[reg_table[reg]])
#ifdef __sun #ifdef __sun
@ -1374,138 +1376,140 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
} }
// check if address is RawSPU MMIO register // check if address is RawSPU MMIO register
do if (addr - RAW_SPU_BASE_ADDR < (6 * RAW_SPU_OFFSET) && (addr % RAW_SPU_OFFSET) >= RAW_SPU_PROB_OFFSET) do
{ if (addr - RAW_SPU_BASE_ADDR < (6 * RAW_SPU_OFFSET) && (addr % RAW_SPU_OFFSET) >= RAW_SPU_PROB_OFFSET)
auto thread = idm::get_unlocked<named_thread<spu_thread>>(spu_thread::find_raw_spu((addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET)); {
auto thread = idm::get_unlocked<named_thread<spu_thread>>(spu_thread::find_raw_spu((addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET));
if (!thread) if (!thread)
{
break;
}
if (!a_size || !d_size || !i_size)
{
sig_log.error("Invalid or unsupported instruction (op=%d, reg=%d, d_size=%lld, a_size=0x%llx, i_size=%lld)", +op, +reg, d_size, a_size, i_size);
report_opcode();
return false;
}
if (a_size != 4)
{
// Might be unimplemented, such as writing MFC proxy EAL+EAH using 64-bit store
break;
}
switch (op)
{
case X64OP_LOAD:
case X64OP_LOAD_BE:
case X64OP_LOAD_CMP:
case X64OP_LOAD_TEST:
{
u32 value;
if (is_writing || !thread->read_reg(addr, value))
{ {
break;
}
if (!a_size || !d_size || !i_size)
{
sig_log.error("Invalid or unsupported instruction (op=%d, reg=%d, d_size=%lld, a_size=0x%llx, i_size=%lld)", +op, +reg, d_size, a_size, i_size);
report_opcode();
return false; return false;
} }
if (op != X64OP_LOAD_BE) if (a_size != 4)
{ {
// Might be unimplemented, such as writing MFC proxy EAL+EAH using 64-bit store
break;
}
switch (op)
{
case X64OP_LOAD:
case X64OP_LOAD_BE:
case X64OP_LOAD_CMP:
case X64OP_LOAD_TEST:
{
u32 value;
if (is_writing || !thread->read_reg(addr, value))
{
return false;
}
if (op != X64OP_LOAD_BE)
{
value = stx::se_storage<u32>::swap(value);
}
if (op == X64OP_LOAD_CMP)
{
u64 rvalue;
if (!get_x64_reg_value(context, reg, d_size, i_size, rvalue) || !set_x64_cmp_flags(context, d_size, value, rvalue))
{
return false;
}
break;
}
if (op == X64OP_LOAD_TEST)
{
u64 rvalue;
if (!get_x64_reg_value(context, reg, d_size, i_size, rvalue) || !set_x64_cmp_flags(context, d_size, value & rvalue, 0))
{
return false;
}
break;
}
if (!put_x64_reg_value(context, reg, d_size, value))
{
return false;
}
break;
}
case X64OP_BEXTR:
{
u32 value;
if (is_writing || !thread->read_reg(addr, value))
{
return false;
}
value = stx::se_storage<u32>::swap(value); value = stx::se_storage<u32>::swap(value);
}
if (op == X64OP_LOAD_CMP) u64 ctrl;
{ if (!get_x64_reg_value(context, s_tls_reg3, d_size, i_size, ctrl))
u64 rvalue; {
if (!get_x64_reg_value(context, reg, d_size, i_size, rvalue) || !set_x64_cmp_flags(context, d_size, value, rvalue)) return false;
}
u8 start = ctrl & 0xff;
u8 _len = (ctrl & 0xff00) >> 8;
if (_len > 32)
_len = 32;
if (start > 32)
start = 32;
value = (u64{value} >> start) & ~(u64{umax} << _len);
if (!put_x64_reg_value(context, reg, d_size, value) || !set_x64_cmp_flags(context, d_size, value, 0))
{ {
return false; return false;
} }
break; break;
} }
case X64OP_STORE:
if (op == X64OP_LOAD_TEST) case X64OP_STORE_BE:
{ {
u64 rvalue; u64 reg_value;
if (!get_x64_reg_value(context, reg, d_size, i_size, rvalue) || !set_x64_cmp_flags(context, d_size, value & rvalue, 0)) if (!is_writing || !get_x64_reg_value(context, reg, d_size, i_size, reg_value))
{
return false;
}
u32 val32 = static_cast<u32>(reg_value);
if (!thread->write_reg(addr, op == X64OP_STORE ? stx::se_storage<u32>::swap(val32) : val32))
{ {
return false; return false;
} }
break; break;
} }
case X64OP_MOVS: // possibly, TODO
if (!put_x64_reg_value(context, reg, d_size, value)) case X64OP_STOS:
default:
{ {
sig_log.error("Invalid or unsupported operation (op=%d, reg=%d, d_size=%lld, i_size=%lld)", +op, +reg, d_size, i_size);
report_opcode();
return false; return false;
} }
}
break; // skip processed instruction
RIP(context) += i_size;
g_tls_fault_spu++;
return true;
} }
case X64OP_BEXTR: while (0);
{
u32 value;
if (is_writing || !thread->read_reg(addr, value))
{
return false;
}
value = stx::se_storage<u32>::swap(value);
u64 ctrl;
if (!get_x64_reg_value(context, s_tls_reg3, d_size, i_size, ctrl))
{
return false;
}
u8 start = ctrl & 0xff;
u8 _len = (ctrl & 0xff00) >> 8;
if (_len > 32)
_len = 32;
if (start > 32)
start = 32;
value = (u64{value} >> start) & ~(u64{umax} << _len);
if (!put_x64_reg_value(context, reg, d_size, value) || !set_x64_cmp_flags(context, d_size, value, 0))
{
return false;
}
break;
}
case X64OP_STORE:
case X64OP_STORE_BE:
{
u64 reg_value;
if (!is_writing || !get_x64_reg_value(context, reg, d_size, i_size, reg_value))
{
return false;
}
u32 val32 = static_cast<u32>(reg_value);
if (!thread->write_reg(addr, op == X64OP_STORE ? stx::se_storage<u32>::swap(val32) : val32))
{
return false;
}
break;
}
case X64OP_MOVS: // possibly, TODO
case X64OP_STOS:
default:
{
sig_log.error("Invalid or unsupported operation (op=%d, reg=%d, d_size=%lld, i_size=%lld)", +op, +reg, d_size, i_size);
report_opcode();
return false;
}
}
// skip processed instruction
RIP(context) += i_size;
g_tls_fault_spu++;
return true;
} while (0);
#else #else
static_cast<void>(context); static_cast<void>(context);
#endif /* ARCH_ */ #endif /* ARCH_ */
@ -1578,8 +1582,8 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
else if (auto spu = cpu->try_get<spu_thread>()) else if (auto spu = cpu->try_get<spu_thread>())
{ {
const u64 type = spu->get_type() == spu_type::threaded ? const u64 type = spu->get_type() == spu_type::threaded ?
SYS_MEMORY_PAGE_FAULT_TYPE_SPU_THREAD : SYS_MEMORY_PAGE_FAULT_TYPE_SPU_THREAD :
SYS_MEMORY_PAGE_FAULT_TYPE_RAW_SPU; SYS_MEMORY_PAGE_FAULT_TYPE_RAW_SPU;
data2 = (type << 32) | spu->lv2_id; data2 = (type << 32) | spu->lv2_id;
} }
@ -1602,7 +1606,6 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
} }
} }
// Now, place the page fault event onto table so that other functions [sys_mmapper_free_address and pagefault recovery funcs etc] // Now, place the page fault event onto table so that other functions [sys_mmapper_free_address and pagefault recovery funcs etc]
// know that this thread is page faulted and where. // know that this thread is page faulted and where.
@ -1843,12 +1846,12 @@ static LONG exception_handler(PEXCEPTION_POINTERS pExp) noexcept
case EXCEPTION_INT_DIVIDE_BY_ZERO: case EXCEPTION_INT_DIVIDE_BY_ZERO:
case EXCEPTION_NONCONTINUABLE_EXCEPTION: case EXCEPTION_NONCONTINUABLE_EXCEPTION:
case EXCEPTION_PRIV_INSTRUCTION: case EXCEPTION_PRIV_INSTRUCTION:
//case EXCEPTION_STACK_OVERFLOW: // case EXCEPTION_STACK_OVERFLOW:
{ {
sys_log.notice("\n%s", dump_useful_thread_info()); sys_log.notice("\n%s", dump_useful_thread_info());
logs::listener::sync_all(); logs::listener::sync_all();
break; break;
} }
default: default:
{ {
break; break;
@ -1866,7 +1869,8 @@ static LONG exception_filter(PEXCEPTION_POINTERS pExp) noexcept
{ {
const auto cause = const auto cause =
pExp->ExceptionRecord->ExceptionInformation[0] == 8 ? "executing" : pExp->ExceptionRecord->ExceptionInformation[0] == 8 ? "executing" :
pExp->ExceptionRecord->ExceptionInformation[0] == 1 ? "writing" : "reading"; pExp->ExceptionRecord->ExceptionInformation[0] == 1 ? "writing" :
"reading";
fmt::append(msg, "Segfault %s location %p at %p.\n", cause, pExp->ExceptionRecord->ExceptionInformation[1], pExp->ExceptionRecord->ExceptionAddress); fmt::append(msg, "Segfault %s location %p at %p.\n", cause, pExp->ExceptionRecord->ExceptionInformation[1], pExp->ExceptionRecord->ExceptionAddress);
@ -1916,7 +1920,7 @@ static LONG exception_filter(PEXCEPTION_POINTERS pExp) noexcept
fmt::append(msg, "Function address: %p (base+0x%x).\n", func_addr, rtf->BeginAddress); fmt::append(msg, "Function address: %p (base+0x%x).\n", func_addr, rtf->BeginAddress);
// Access UNWIND_INFO structure // Access UNWIND_INFO structure
//const auto uw = (u8*)(unwind_base + rtf->UnwindData); // const auto uw = (u8*)(unwind_base + rtf->UnwindData);
} }
for (HMODULE _module : modules) for (HMODULE _module : modules)
@ -2014,19 +2018,19 @@ static void signal_handler(int /*sig*/, siginfo_t* info, void* uct) noexcept
#else #else
const u32 insn = is_executing ? 0 : *reinterpret_cast<u32*>(RIP(context)); const u32 insn = is_executing ? 0 : *reinterpret_cast<u32*>(RIP(context));
const bool is_writing = const bool is_writing =
(insn & 0xbfff0000) == 0x0c000000 || // STR <Wt>, [<Xn>, #<imm>] (store word with immediate offset) (insn & 0xbfff0000) == 0x0c000000 || // STR <Wt>, [<Xn>, #<imm>] (store word with immediate offset)
(insn & 0xbfe00000) == 0x0c800000 || // STP <Wt1>, <Wt2>, [<Xn>, #<imm>] (store pair of registers with immediate offset) (insn & 0xbfe00000) == 0x0c800000 || // STP <Wt1>, <Wt2>, [<Xn>, #<imm>] (store pair of registers with immediate offset)
(insn & 0xbfdf0000) == 0x0d000000 || // STR <Wt>, [<Xn>, <Xm>] (store word with register offset) (insn & 0xbfdf0000) == 0x0d000000 || // STR <Wt>, [<Xn>, <Xm>] (store word with register offset)
(insn & 0xbfc00000) == 0x0d800000 || // STP <Wt1>, <Wt2>, [<Xn>, <Xm>] (store pair of registers with register offset) (insn & 0xbfc00000) == 0x0d800000 || // STP <Wt1>, <Wt2>, [<Xn>, <Xm>] (store pair of registers with register offset)
(insn & 0x3f400000) == 0x08000000 || // STR <Vd>, [<Xn>, #<imm>] (store SIMD/FP register with immediate offset) (insn & 0x3f400000) == 0x08000000 || // STR <Vd>, [<Xn>, #<imm>] (store SIMD/FP register with immediate offset)
(insn & 0x3bc00000) == 0x39000000 || // STR <Wt>, [<Xn>, #<imm>] (store word with immediate offset) (insn & 0x3bc00000) == 0x39000000 || // STR <Wt>, [<Xn>, #<imm>] (store word with immediate offset)
(insn & 0x3fc00000) == 0x3d800000 || // STR <Vd>, [<Xn>, <Xm>] (store SIMD/FP register with register offset) (insn & 0x3fc00000) == 0x3d800000 || // STR <Vd>, [<Xn>, <Xm>] (store SIMD/FP register with register offset)
(insn & 0x3bc00000) == 0x38000000 || // STR <Wt>, [<Xn>, <Xm>] (store word with register offset) (insn & 0x3bc00000) == 0x38000000 || // STR <Wt>, [<Xn>, <Xm>] (store word with register offset)
(insn & 0x3fe00000) == 0x3c800000 || // STUR <Vd>, [<Xn>, #<imm>] (store unprivileged register with immediate offset) (insn & 0x3fe00000) == 0x3c800000 || // STUR <Vd>, [<Xn>, #<imm>] (store unprivileged register with immediate offset)
(insn & 0x3fe00000) == 0x3ca00000 || // STR <Vd>, [<Xn>, #<imm>] (store SIMD/FP register with immediate offset) (insn & 0x3fe00000) == 0x3ca00000 || // STR <Vd>, [<Xn>, #<imm>] (store SIMD/FP register with immediate offset)
(insn & 0x3a400000) == 0x28000000 || // STP <Wt1>, <Wt2>, [<Xn>, #<imm>] (store pair of registers with immediate offset) (insn & 0x3a400000) == 0x28000000 || // STP <Wt1>, <Wt2>, [<Xn>, #<imm>] (store pair of registers with immediate offset)
(insn & 0xbf000000) == 0xad000000 || // STP <Vd1>, <Vd2>, [<Xn>, #<imm>] (store SIMD/FP 128-bit register pair with immediate offset) (insn & 0xbf000000) == 0xad000000 || // STP <Vd1>, <Vd2>, [<Xn>, #<imm>] (store SIMD/FP 128-bit register pair with immediate offset)
(insn & 0xbf000000) == 0x6d000000; // STP <Dd1>, <Dd2>, [<Xn>, #<imm>] (store SIMD/FP 64-bit register pair with immediate offset) (insn & 0xbf000000) == 0x6d000000; // STP <Dd1>, <Dd2>, [<Xn>, #<imm>] (store SIMD/FP 64-bit register pair with immediate offset)
#endif #endif
#else #else
@ -2034,7 +2038,8 @@ static void signal_handler(int /*sig*/, siginfo_t* info, void* uct) noexcept
#endif #endif
const u64 exec64 = (reinterpret_cast<u64>(info->si_addr) - reinterpret_cast<u64>(vm::g_exec_addr)) / 2; const u64 exec64 = (reinterpret_cast<u64>(info->si_addr) - reinterpret_cast<u64>(vm::g_exec_addr)) / 2;
const auto cause = is_executing ? "executing" : is_writing ? "writing" : "reading"; const auto cause = is_executing ? "executing" : is_writing ? "writing" :
"reading";
if (auto [addr, ok] = vm::try_get_addr(info->si_addr); ok && !is_executing) if (auto [addr, ok] = vm::try_get_addr(info->si_addr); ok && !is_executing)
{ {
@ -2144,15 +2149,15 @@ const bool s_exception_handler_set = []() -> bool
const bool s_terminate_handler_set = []() -> bool const bool s_terminate_handler_set = []() -> bool
{ {
std::set_terminate([]() std::set_terminate([]()
{
if (IsDebuggerPresent())
{ {
logs::listener::sync_all(); if (IsDebuggerPresent())
utils::trap(); {
} logs::listener::sync_all();
utils::trap();
}
report_fatal_error("RPCS3 has abnormally terminated."); report_fatal_error("RPCS3 has abnormally terminated.");
}); });
return true; return true;
}(); }();
@ -2161,15 +2166,15 @@ thread_local DECLARE(thread_ctrl::g_tls_this_thread) = nullptr;
thread_local DECLARE(thread_ctrl::g_tls_error_callback) = nullptr; thread_local DECLARE(thread_ctrl::g_tls_error_callback) = nullptr;
DECLARE(thread_ctrl::g_native_core_layout) { native_core_arrangement::undefined }; DECLARE(thread_ctrl::g_native_core_layout){native_core_arrangement::undefined};
void thread_base::start() void thread_base::start()
{ {
m_sync.atomic_op([&](u32& v) m_sync.atomic_op([&](u32& v)
{ {
v &= ~static_cast<u32>(thread_state::mask); v &= ~static_cast<u32>(thread_state::mask);
v |= static_cast<u32>(thread_state::created); v |= static_cast<u32>(thread_state::created);
}); });
#ifdef _WIN32 #ifdef _WIN32
m_thread = ::_beginthreadex(nullptr, 0, entry_point, this, CREATE_SUSPENDED, nullptr); m_thread = ::_beginthreadex(nullptr, 0, entry_point, this, CREATE_SUSPENDED, nullptr);
@ -2206,18 +2211,18 @@ void thread_base::initialize(void (*error_cb)())
}; };
atomic_wait_engine::set_wait_callback([](const void*, u64 attempts, u64 stamp0) -> bool atomic_wait_engine::set_wait_callback([](const void*, u64 attempts, u64 stamp0) -> bool
{
if (attempts == umax)
{ {
g_tls_wait_time += utils::get_tsc() - stamp0; if (attempts == umax)
} {
else if (attempts > 1) g_tls_wait_time += utils::get_tsc() - stamp0;
{ }
g_tls_wait_fail += attempts - 1; else if (attempts > 1)
} {
g_tls_wait_fail += attempts - 1;
}
return true; return true;
}); });
set_name(thread_ctrl::get_name_cached()); set_name(thread_ctrl::get_name_cached());
} }
@ -2241,22 +2246,23 @@ void thread_base::set_name(std::string name)
}; };
// Set thread name for VS debugger // Set thread name for VS debugger
if (IsDebuggerPresent()) [&]() NEVER_INLINE if (IsDebuggerPresent())
{ [&]() NEVER_INLINE
THREADNAME_INFO info; {
info.dwType = 0x1000; THREADNAME_INFO info;
info.szName = name.c_str(); info.dwType = 0x1000;
info.dwThreadID = -1; info.szName = name.c_str();
info.dwFlags = 0; info.dwThreadID = -1;
info.dwFlags = 0;
__try __try
{ {
RaiseException(0x406D1388, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info); RaiseException(0x406D1388, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
} }
__except (EXCEPTION_EXECUTE_HANDLER) __except (EXCEPTION_EXECUTE_HANDLER)
{ {
} }
}(); }();
#endif #endif
#if defined(__APPLE__) #if defined(__APPLE__)
@ -2341,10 +2347,10 @@ u64 thread_base::finalize(thread_state result_state) noexcept
// Set result state (errored or finalized) // Set result state (errored or finalized)
m_sync.fetch_op([&](u32& v) m_sync.fetch_op([&](u32& v)
{ {
v &= -4; v &= -4;
v |= static_cast<u32>(result_state); v |= static_cast<u32>(result_state);
}); });
// Signal waiting threads // Signal waiting threads
m_sync.notify_all(); m_sync.notify_all();
@ -2361,7 +2367,10 @@ thread_base::native_entry thread_base::finalize(u64 _self) noexcept
g_tls_wait_fail = 0; g_tls_wait_fail = 0;
g_tls_access_violation_recovered = false; g_tls_access_violation_recovered = false;
g_tls_log_prefix = []() -> std::string { return {}; }; g_tls_log_prefix = []() -> std::string
{
return {};
};
if (_self == umax) if (_self == umax)
{ {
@ -2378,42 +2387,42 @@ thread_base::native_entry thread_base::finalize(u64 _self) noexcept
return nullptr; return nullptr;
} }
thread_base::native_entry thread_base::make_trampoline(u64(*entry)(thread_base* _base)) thread_base::native_entry thread_base::make_trampoline(u64 (*entry)(thread_base* _base))
{ {
return build_function_asm<native_entry>("", [&](native_asm& c, auto& args) return build_function_asm<native_entry>("", [&](native_asm& c, auto& args)
{ {
using namespace asmjit; using namespace asmjit;
#if defined(ARCH_X64) #if defined(ARCH_X64)
Label _ret = c.newLabel(); Label _ret = c.newLabel();
c.push(x86::rbp); c.push(x86::rbp);
c.sub(x86::rsp, 0x20); c.sub(x86::rsp, 0x20);
// Call entry point (TODO: support for detached threads missing?) // Call entry point (TODO: support for detached threads missing?)
c.call(entry); c.call(entry);
// Call finalize, return if zero // Call finalize, return if zero
c.mov(args[0], x86::rax); c.mov(args[0], x86::rax);
c.call(static_cast<native_entry(*)(u64)>(&finalize)); c.call(static_cast<native_entry (*)(u64)>(&finalize));
c.test(x86::rax, x86::rax); c.test(x86::rax, x86::rax);
c.jz(_ret); c.jz(_ret);
// Otherwise, call it as an entry point with first arg = new current thread // Otherwise, call it as an entry point with first arg = new current thread
c.mov(x86::rbp, x86::rax); c.mov(x86::rbp, x86::rax);
c.call(thread_ctrl::get_current); c.call(thread_ctrl::get_current);
c.mov(args[0], x86::rax); c.mov(args[0], x86::rax);
c.add(x86::rsp, 0x28); c.add(x86::rsp, 0x28);
c.jmp(x86::rbp); c.jmp(x86::rbp);
c.bind(_ret); c.bind(_ret);
c.add(x86::rsp, 0x28); c.add(x86::rsp, 0x28);
c.ret(); c.ret();
#else #else
UNUSED(c); UNUSED(c);
UNUSED(args); UNUSED(args);
UNUSED(entry); UNUSED(entry);
#endif #endif
}); });
} }
thread_state thread_ctrl::state() thread_state thread_ctrl::state()
@ -2516,7 +2525,6 @@ void thread_ctrl::wait_for(u64 usec, [[maybe_unused]] bool alert /* true */)
list.wait(atomic_wait_timeout{usec <= 0xffff'ffff'ffff'ffff / 1000 ? usec * 1000 : 0xffff'ffff'ffff'ffff}); list.wait(atomic_wait_timeout{usec <= 0xffff'ffff'ffff'ffff / 1000 ? usec * 1000 : 0xffff'ffff'ffff'ffff});
} }
void thread_ctrl::wait_until(u64* wait_time, u64 add_time, u64 min_wait, bool update_to_current_time) void thread_ctrl::wait_until(u64* wait_time, u64 add_time, u64 min_wait, bool update_to_current_time)
{ {
*wait_time = utils::add_saturate<u64>(*wait_time, add_time); *wait_time = utils::add_saturate<u64>(*wait_time, add_time);
@ -2609,20 +2617,19 @@ std::string thread_ctrl::get_name_cached()
if (!_this->m_tname.is_equal(name_cache)) [[unlikely]] if (!_this->m_tname.is_equal(name_cache)) [[unlikely]]
{ {
_this->m_tname.peek_op([&](const shared_ptr<std::string>& ptr) _this->m_tname.peek_op([&](const shared_ptr<std::string>& ptr)
{
if (ptr != name_cache)
{ {
name_cache = ptr; if (ptr != name_cache)
} {
}); name_cache = ptr;
}
});
} }
return *name_cache; return *name_cache;
} }
thread_base::thread_base(native_entry entry, std::string name) noexcept thread_base::thread_base(native_entry entry, std::string name) noexcept
: entry_point(entry) : entry_point(entry), m_tname(make_single_value(std::move(name)))
, m_tname(make_single_value(std::move(name)))
{ {
} }
@ -2709,7 +2716,7 @@ u64 thread_base::get_cycles()
if (ret == KERN_SUCCESS) if (ret == KERN_SUCCESS)
{ {
cycles = static_cast<u64>(info.user_time.seconds + info.system_time.seconds) * 1'000'000'000 + cycles = static_cast<u64>(info.user_time.seconds + info.system_time.seconds) * 1'000'000'000 +
static_cast<u64>(info.user_time.microseconds + info.system_time.microseconds) * 1'000; static_cast<u64>(info.user_time.microseconds + info.system_time.microseconds) * 1'000;
#else #else
clockid_t _clock; clockid_t _clock;
struct timespec thread_time; struct timespec thread_time;
@ -2836,22 +2843,23 @@ void thread_base::exec()
const u64 current_break = get_system_time() & -2; const u64 current_break = get_system_time() & -2;
if (s_last_break.fetch_op([current_break](u64& v) if (s_last_break.fetch_op([current_break](u64& v)
{ {
if (current_break >= (v & -2) && current_break - (v & -2) >= 20'000'000) if (current_break >= (v & -2) && current_break - (v & -2) >= 20'000'000)
{ {
v = current_break; v = current_break;
return true; return true;
} }
// Let's allow a single more thread to halt the debugger so the programmer sees the pattern // Let's allow a single more thread to halt the debugger so the programmer sees the pattern
if (!(v & 1)) if (!(v & 1))
{ {
v |= 1; v |= 1;
return true; return true;
} }
return false; return false;
}).second) })
.second)
{ {
utils::trap(); utils::trap();
} }
@ -2913,7 +2921,7 @@ void thread_ctrl::detect_cpu_layout()
std::vector<u8> buffer(buffer_size); std::vector<u8> buffer(buffer_size);
if (!GetLogicalProcessorInformationEx(relationship, if (!GetLogicalProcessorInformationEx(relationship,
reinterpret_cast<SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *>(buffer.data()), &buffer_size)) reinterpret_cast<SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*>(buffer.data()), &buffer_size))
{ {
sig_log.error("GetLogicalProcessorInformationEx failed (size=%u, error=%s)", buffer_size, fmt::win_error{GetLastError(), nullptr}); sig_log.error("GetLogicalProcessorInformationEx failed (size=%u, error=%s)", buffer_size, fmt::win_error{GetLastError(), nullptr});
} }
@ -2925,7 +2933,7 @@ void thread_ctrl::detect_cpu_layout()
while (ptr < end) while (ptr < end)
{ {
auto info = reinterpret_cast<SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *>(ptr); auto info = reinterpret_cast<SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*>(ptr);
if (info->Relationship == relationship && info->Processor.Flags == LTP_PC_SMT) if (info->Relationship == relationship && info->Processor.Flags == LTP_PC_SMT)
{ {
g_native_core_layout.store(native_core_arrangement::intel_ht); g_native_core_layout.store(native_core_arrangement::intel_ht);
@ -2945,16 +2953,15 @@ u64 thread_ctrl::get_affinity_mask(thread_class group)
#ifdef ANDROID #ifdef ANDROID
u64 mask = 0; u64 mask = 0;
thread_class affinities[] = thread_class affinities[] =
{ {
g_cfg.core.affinity.cpu0.get(), g_cfg.core.affinity.cpu0.get(),
g_cfg.core.affinity.cpu1.get(), g_cfg.core.affinity.cpu1.get(),
g_cfg.core.affinity.cpu2.get(), g_cfg.core.affinity.cpu2.get(),
g_cfg.core.affinity.cpu3.get(), g_cfg.core.affinity.cpu3.get(),
g_cfg.core.affinity.cpu4.get(), g_cfg.core.affinity.cpu4.get(),
g_cfg.core.affinity.cpu5.get(), g_cfg.core.affinity.cpu5.get(),
g_cfg.core.affinity.cpu6.get(), g_cfg.core.affinity.cpu6.get(),
g_cfg.core.affinity.cpu7.get() g_cfg.core.affinity.cpu7.get()};
};
for (std::size_t i = 0; i < std::min<std::size_t>(std::thread::hardware_concurrency(), std::size(affinities)); ++i) for (std::size_t i = 0; i < std::min<std::size_t>(std::thread::hardware_concurrency(), std::size(affinities)); ++i)
{ {
@ -3248,7 +3255,7 @@ void thread_ctrl::set_thread_affinity_mask(u64 mask)
} }
#elif __APPLE__ #elif __APPLE__
// Supports only one core // Supports only one core
thread_affinity_policy_data_t policy = { static_cast<integer_t>(std::countr_zero(mask)) }; thread_affinity_policy_data_t policy = {static_cast<integer_t>(std::countr_zero(mask))};
thread_port_t mach_thread = pthread_mach_thread_np(pthread_self()); thread_port_t mach_thread = pthread_mach_thread_np(pthread_self());
thread_policy_set(mach_thread, THREAD_AFFINITY_POLICY, reinterpret_cast<thread_policy_t>(&policy), !mask ? 0 : 1); thread_policy_set(mach_thread, THREAD_AFFINITY_POLICY, reinterpret_cast<thread_policy_t>(&policy), !mask ? 0 : 1);
#elif (defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__)) #elif (defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__))

View file

@ -27,8 +27,8 @@ enum class thread_state : u32
{ {
created = 0, // Initial state created = 0, // Initial state
aborting = 1, // The thread has been joined in the destructor or explicitly aborted aborting = 1, // The thread has been joined in the destructor or explicitly aborted
errored = 2, // Set after the emergency_exit call errored = 2, // Set after the emergency_exit call
finished = 3, // Final state, always set at the end of thread execution finished = 3, // Final state, always set at the end of thread execution
mask = 3, mask = 3,
destroying_context = 7, // Special value assigned to destroy data explicitly before the destructor destroying_context = 7, // Special value assigned to destroy data explicitly before the destructor
}; };
@ -46,7 +46,8 @@ struct result_storage
using type = void; using type = void;
}; };
template <typename Ctx, typename... Args> requires (!std::is_void_v<std::invoke_result_t<Ctx, Args&&...>>) template <typename Ctx, typename... Args>
requires(!std::is_void_v<std::invoke_result_t<Ctx, Args && ...>>)
struct result_storage<Ctx, Args...> struct result_storage<Ctx, Args...>
{ {
using T = std::invoke_result_t<Ctx, Args&&...>; using T = std::invoke_result_t<Ctx, Args&&...>;
@ -81,8 +82,7 @@ struct result_storage<Ctx, Args...>
}; };
template <typename T> template <typename T>
concept NamedThreadName = requires (const T&) concept NamedThreadName = requires(const T&) {
{
std::string(T::thread_name); std::string(T::thread_name);
}; };
@ -96,7 +96,7 @@ class thread_future
thread_future* prev{}; thread_future* prev{};
protected: protected:
atomic_t<void(*)(thread_base*, thread_future*)> exec{}; atomic_t<void (*)(thread_base*, thread_future*)> exec{};
atomic_t<u32> done{0}; atomic_t<u32> done{0};
@ -122,7 +122,7 @@ public:
#ifdef _WIN32 #ifdef _WIN32
using native_entry = uint(__stdcall*)(void* arg); using native_entry = uint(__stdcall*)(void* arg);
#else #else
using native_entry = void*(*)(void* arg); using native_entry = void* (*)(void* arg);
#endif #endif
const native_entry entry_point; const native_entry entry_point;
@ -161,7 +161,7 @@ private:
static native_entry finalize(u64 _self) noexcept; static native_entry finalize(u64 _self) noexcept;
// Make entry point // Make entry point
static native_entry make_trampoline(u64(*entry)(thread_base* _base)); static native_entry make_trampoline(u64 (*entry)(thread_base* _base));
friend class thread_ctrl; friend class thread_ctrl;
@ -201,7 +201,7 @@ class thread_ctrl final
static thread_local thread_base* g_tls_this_thread; static thread_local thread_base* g_tls_this_thread;
// Error handling details // Error handling details
static thread_local void(*g_tls_error_callback)(); static thread_local void (*g_tls_error_callback)();
// Target cpu core layout // Target cpu core layout
static atomic_t<native_core_arrangement> g_native_core_layout; static atomic_t<native_core_arrangement> g_native_core_layout;
@ -306,13 +306,20 @@ public:
template <typename T, typename U> template <typename T, typename U>
static inline void wait_on(T& wait, U old, u64 usec = -1) static inline void wait_on(T& wait, U old, u64 usec = -1)
{ {
wait_on_custom<1>([&](atomic_wait::list<3>& list) { list.template set<0>(wait, old); }, usec); wait_on_custom<1>([&](atomic_wait::list<3>& list)
{
list.template set<0>(wait, old);
},
usec);
} }
template <typename T> template <typename T>
static inline void wait_on(T& wait) static inline void wait_on(T& wait)
{ {
wait_on_custom<1>([&](atomic_wait::list<3>& list) { list.template set<0>(wait); }); wait_on_custom<1>([&](atomic_wait::list<3>& list)
{
list.template set<0>(wait);
});
} }
// Exit. // Exit.
@ -386,8 +393,7 @@ class thread_future_t : public thread_future, result_storage<Ctx, std::condition
public: public:
thread_future_t(Ctx&& func, Args&&... args) noexcept thread_future_t(Ctx&& func, Args&&... args) noexcept
: m_args(std::forward<Args>(args)...) : m_args(std::forward<Args>(args)...), m_func(std::forward<Ctx>(func))
, m_func(std::forward<Ctx>(func))
{ {
thread_future::exec.raw() = +[](thread_base* tb, thread_future* tf) thread_future::exec.raw() = +[](thread_base* tb, thread_future* tf)
{ {
@ -472,13 +478,13 @@ class named_thread final : public Context, result_storage<Context>, thread_base
u64 entry_point2() u64 entry_point2()
{ {
thread::initialize([]() thread::initialize([]()
{
if constexpr (!result::empty)
{ {
// Construct using default constructor in the case of failure if constexpr (!result::empty)
static_cast<result*>(static_cast<named_thread*>(thread_ctrl::get_current()))->init(); {
} // Construct using default constructor in the case of failure
}); static_cast<result*>(static_cast<named_thread*>(thread_ctrl::get_current()))->init();
}
});
if constexpr (result::empty) if constexpr (result::empty)
{ {
@ -527,37 +533,37 @@ class named_thread final : public Context, result_storage<Context>, thread_base
public: public:
// Forwarding constructor with default name (also potentially the default constructor) // Forwarding constructor with default name (also potentially the default constructor)
template <typename... Args> requires (std::is_constructible_v<Context, Args&&...>) && (!(std::is_same_v<std::remove_cvref_t<Args>, stx::launch_retainer> || ...)) && (NamedThreadName<Context>) template <typename... Args>
requires(std::is_constructible_v<Context, Args && ...>) && (!(std::is_same_v<std::remove_cvref_t<Args>, stx::launch_retainer> || ...)) && (NamedThreadName<Context>)
named_thread(Args&&... args) noexcept named_thread(Args&&... args) noexcept
: Context(std::forward<Args>(args)...) : Context(std::forward<Args>(args)...), thread(trampoline, std::string(Context::thread_name))
, thread(trampoline, std::string(Context::thread_name))
{ {
thread::start(); thread::start();
} }
// Forwarding constructor with default name, does not automatically run the thread // Forwarding constructor with default name, does not automatically run the thread
template <typename... Args> requires (std::is_constructible_v<Context, Args&&...>) && (NamedThreadName<Context>) template <typename... Args>
requires(std::is_constructible_v<Context, Args && ...>) && (NamedThreadName<Context>)
named_thread(const stx::launch_retainer&, Args&&... args) noexcept named_thread(const stx::launch_retainer&, Args&&... args) noexcept
: Context(std::forward<Args>(args)...) : Context(std::forward<Args>(args)...), thread(trampoline, std::string(Context::thread_name))
, thread(trampoline, std::string(Context::thread_name))
{ {
// Create a stand-by thread context // Create a stand-by thread context
m_sync |= static_cast<u32>(thread_state::finished); m_sync |= static_cast<u32>(thread_state::finished);
} }
// Normal forwarding constructor // Normal forwarding constructor
template <typename... Args> requires (std::is_constructible_v<Context, Args&&...>) && (!NamedThreadName<Context>) template <typename... Args>
requires(std::is_constructible_v<Context, Args && ...>) && (!NamedThreadName<Context>)
named_thread(std::string name, Args&&... args) noexcept named_thread(std::string name, Args&&... args) noexcept
: Context(std::forward<Args>(args)...) : Context(std::forward<Args>(args)...), thread(trampoline, std::move(name))
, thread(trampoline, std::move(name))
{ {
thread::start(); thread::start();
} }
// Lambda constructor, also the implicit deduction guide candidate // Lambda constructor, also the implicit deduction guide candidate
named_thread(std::string_view name, Context&& f) noexcept requires (!NamedThreadName<Context>) named_thread(std::string_view name, Context&& f) noexcept
: Context(std::forward<Context>(f)) requires(!NamedThreadName<Context>)
, thread(trampoline, std::string(name)) : Context(std::forward<Context>(f)), thread(trampoline, std::string(name))
{ {
thread::start(); thread::start();
} }
@ -683,7 +689,11 @@ public:
// Try to abort by assigning thread_state::aborting/finished // Try to abort by assigning thread_state::aborting/finished
// Join thread by thread_state::finished // Join thread by thread_state::finished
if (s >= thread_state::aborting && thread::m_sync.fetch_op([](u32& v) { return !(v & 3) && (v |= 1); }).second) if (s >= thread_state::aborting && thread::m_sync.fetch_op([](u32& v)
{
return !(v & 3) && (v |= 1);
})
.second)
{ {
notify_sync = true; notify_sync = true;
} }
@ -747,8 +757,7 @@ class named_thread_group final
public: public:
// Lambda constructor, also the implicit deduction guide candidate // Lambda constructor, also the implicit deduction guide candidate
named_thread_group(std::string_view name, u32 count, Context&& f) noexcept named_thread_group(std::string_view name, u32 count, Context&& f) noexcept
: m_count(count) : m_count(count), m_threads(nullptr)
, m_threads(nullptr)
{ {
if (count == 0) if (count == 0)
{ {
@ -771,8 +780,7 @@ public:
// Constructor with a function performed before adding more threads // Constructor with a function performed before adding more threads
template <typename CheckAndPrepare> template <typename CheckAndPrepare>
named_thread_group(std::string_view name, u32 count, Context&& f, CheckAndPrepare&& check) noexcept named_thread_group(std::string_view name, u32 count, Context&& f, CheckAndPrepare&& check) noexcept
: m_count(count) : m_count(count), m_threads(nullptr)
, m_threads(nullptr)
{ {
if (count == 0) if (count == 0)
{ {
@ -812,8 +820,7 @@ public:
// Default constructor // Default constructor
named_thread_group(std::string_view name, u32 count) noexcept named_thread_group(std::string_view name, u32 count) noexcept
: m_count(count) : m_count(count), m_threads(nullptr)
, m_threads(nullptr)
{ {
if (count == 0) if (count == 0)
{ {
@ -840,7 +847,7 @@ public:
for (u32 i = 0; i < m_count; i++) for (u32 i = 0; i < m_count; i++)
{ {
std::as_const(*std::launder(m_threads + i))(); std::as_const (*std::launder(m_threads + i))();
if (std::as_const(*std::launder(m_threads + i)) != thread_state::finished) if (std::as_const(*std::launder(m_threads + i)) != thread_state::finished)
result = false; result = false;

View file

@ -33,7 +33,6 @@ namespace utils
return (val & (get_page_size() - 1)) == 0; return (val & (get_page_size() - 1)) == 0;
} }
/** /**
* Address Range utility class * Address Range utility class
*/ */
@ -41,7 +40,7 @@ namespace utils
{ {
public: public:
u32 start = umax; // First address in range u32 start = umax; // First address in range
u32 end = 0; // Last address u32 end = 0; // Last address
private: private:
// Helper constexprs // Helper constexprs
@ -105,7 +104,7 @@ namespace utils
} }
// Overlapping checks // Overlapping checks
bool overlaps(const address_range &other) const bool overlaps(const address_range& other) const
{ {
AUDIT(valid() && other.valid()); AUDIT(valid() && other.valid());
return range_overlaps(start, end, other.start, other.end); return range_overlaps(start, end, other.start, other.end);
@ -117,16 +116,16 @@ namespace utils
return address_overlaps(addr, start, end); return address_overlaps(addr, start, end);
} }
bool inside(const address_range &other) const bool inside(const address_range& other) const
{ {
AUDIT(valid() && other.valid()); AUDIT(valid() && other.valid());
return range_inside_range(start, end, other.start, other.end); return range_inside_range(start, end, other.start, other.end);
} }
inline bool inside(const address_range_vector &vec) const; inline bool inside(const address_range_vector& vec) const;
inline bool overlaps(const address_range_vector &vec) const; inline bool overlaps(const address_range_vector& vec) const;
bool touches(const address_range &other) const bool touches(const address_range& other) const
{ {
AUDIT(valid() && other.valid()); AUDIT(valid() && other.valid());
// returns true if there is overlap, or if sections are side-by-side // returns true if there is overlap, or if sections are side-by-side
@ -134,7 +133,7 @@ namespace utils
} }
// Utilities // Utilities
s32 signed_distance(const address_range &other) const s32 signed_distance(const address_range& other) const
{ {
if (touches(other)) if (touches(other))
{ {
@ -152,7 +151,7 @@ namespace utils
return -static_cast<s32>(start - other.end - 1); return -static_cast<s32>(start - other.end - 1);
} }
u32 distance(const address_range &other) const u32 distance(const address_range& other) const
{ {
if (touches(other)) if (touches(other))
{ {
@ -170,15 +169,14 @@ namespace utils
return (start - other.end - 1); return (start - other.end - 1);
} }
address_range get_min_max(const address_range &other) const address_range get_min_max(const address_range& other) const
{ {
return { return {
std::min(valid() ? start : umax, other.valid() ? other.start : umax), std::min(valid() ? start : umax, other.valid() ? other.start : umax),
std::max(valid() ? end : 0, other.valid() ? other.end : 0) std::max(valid() ? end : 0, other.valid() ? other.end : 0)};
};
} }
void set_min_max(const address_range &other) void set_min_max(const address_range& other)
{ {
*this = get_min_max(other); *this = get_min_max(other);
} }
@ -191,7 +189,7 @@ namespace utils
address_range to_page_range() const address_range to_page_range() const
{ {
AUDIT(valid()); AUDIT(valid());
return { page_start(start), page_end(end) }; return {page_start(start), page_end(end)};
} }
void page_align() void page_align()
@ -202,17 +200,17 @@ namespace utils
AUDIT(is_page_range()); AUDIT(is_page_range());
} }
address_range get_intersect(const address_range &clamp) const address_range get_intersect(const address_range& clamp) const
{ {
if (!valid() || !clamp.valid()) if (!valid() || !clamp.valid())
{ {
return {}; return {};
} }
return { std::max(start, clamp.start), std::min(end, clamp.end) }; return {std::max(start, clamp.start), std::min(end, clamp.end)};
} }
void intersect(const address_range &clamp) void intersect(const address_range& clamp)
{ {
if (!clamp.valid()) if (!clamp.valid())
{ {
@ -238,7 +236,7 @@ namespace utils
} }
// Comparison Operators // Comparison Operators
bool operator ==(const address_range& other) const bool operator==(const address_range& other) const
{ {
return (start == other.start && end == other.end); return (start == other.start && end == other.end);
} }
@ -257,7 +255,6 @@ namespace utils
return address_range::start_end(page_start(addr), page_end(addr)); return address_range::start_end(page_start(addr), page_end(addr));
} }
/** /**
* Address Range Vector utility class * Address Range Vector utility class
* *
@ -276,20 +273,50 @@ namespace utils
public: public:
// Wrapped functions // Wrapped functions
inline void reserve(usz nr) { data.reserve(nr); } inline void reserve(usz nr)
inline void clear() { data.clear(); } {
inline size_type size() const { return data.size(); } data.reserve(nr);
inline bool empty() const { return data.empty(); } }
inline address_range& operator[](size_type n) { return data[n]; } inline void clear()
inline const address_range& operator[](size_type n) const { return data[n]; } {
inline iterator begin() { return data.begin(); } data.clear();
inline const_iterator begin() const { return data.begin(); } }
inline iterator end() { return data.end(); } inline size_type size() const
inline const_iterator end() const { return data.end(); } {
return data.size();
}
inline bool empty() const
{
return data.empty();
}
inline address_range& operator[](size_type n)
{
return data[n];
}
inline const address_range& operator[](size_type n) const
{
return data[n];
}
inline iterator begin()
{
return data.begin();
}
inline const_iterator begin() const
{
return data.begin();
}
inline iterator end()
{
return data.end();
}
inline const_iterator end() const
{
return data.end();
}
// Search for ranges that touch new_range. If found, merge instead of adding new_range. // Search for ranges that touch new_range. If found, merge instead of adding new_range.
// When adding a new range, re-use invalid ranges whenever possible // When adding a new range, re-use invalid ranges whenever possible
void merge(const address_range &new_range) void merge(const address_range& new_range)
{ {
// Note the case where we have // Note the case where we have
// AAAA BBBB // AAAA BBBB
@ -301,10 +328,10 @@ namespace utils
return; return;
} }
address_range *found = nullptr; address_range* found = nullptr;
address_range *invalid = nullptr; address_range* invalid = nullptr;
for (auto &existing : data) for (auto& existing : data)
{ {
if (!existing.valid()) if (!existing.valid())
{ {
@ -347,16 +374,16 @@ namespace utils
AUDIT(check_consistency()); AUDIT(check_consistency());
} }
void merge(const address_range_vector &other) void merge(const address_range_vector& other)
{ {
for (const address_range &new_range : other) for (const address_range& new_range : other)
{ {
merge(new_range); merge(new_range);
} }
} }
// Exclude a given range from data // Exclude a given range from data
void exclude(const address_range &exclusion) void exclude(const address_range& exclusion)
{ {
// Note the case where we have // Note the case where we have
// AAAAAAA // AAAAAAA
@ -371,13 +398,13 @@ namespace utils
return; return;
} }
address_range *invalid = nullptr; // try to re-use an invalid range instead of calling push_back address_range* invalid = nullptr; // try to re-use an invalid range instead of calling push_back
// We use index access because we might have to push_back within the loop, which could invalidate the iterators // We use index access because we might have to push_back within the loop, which could invalidate the iterators
size_type _size = data.size(); size_type _size = data.size();
for (size_type n = 0; n < _size; ++n) for (size_type n = 0; n < _size; ++n)
{ {
address_range &existing = data[n]; address_range& existing = data[n];
if (!existing.valid()) if (!existing.valid())
{ {
@ -393,7 +420,7 @@ namespace utils
} }
const bool head_excluded = exclusion.overlaps(existing.start); // This section has its start inside excluded range const bool head_excluded = exclusion.overlaps(existing.start); // This section has its start inside excluded range
const bool tail_excluded = exclusion.overlaps(existing.end); // This section has its end inside excluded range const bool tail_excluded = exclusion.overlaps(existing.end); // This section has its end inside excluded range
if (head_excluded && tail_excluded) if (head_excluded && tail_excluded)
{ {
@ -438,9 +465,9 @@ namespace utils
AUDIT(!overlaps(exclusion)); AUDIT(!overlaps(exclusion));
} }
void exclude(const address_range_vector &other) void exclude(const address_range_vector& other)
{ {
for (const address_range &exclusion : other) for (const address_range& exclusion : other)
{ {
exclude(exclusion); exclude(exclusion);
} }
@ -454,7 +481,7 @@ namespace utils
for (usz i = 0; i < _size; ++i) for (usz i = 0; i < _size; ++i)
{ {
const auto &r1 = data[i]; const auto& r1 = data[i];
if (!r1.valid()) if (!r1.valid())
{ {
continue; continue;
@ -462,7 +489,7 @@ namespace utils
for (usz j = i + 1; j < _size; ++j) for (usz j = i + 1; j < _size; ++j)
{ {
const auto &r2 = data[j]; const auto& r2 = data[j];
if (!r2.valid()) if (!r2.valid())
{ {
continue; continue;
@ -478,25 +505,25 @@ namespace utils
} }
// Test for overlap with a given range // Test for overlap with a given range
bool overlaps(const address_range &range) const bool overlaps(const address_range& range) const
{ {
return std::any_of(data.cbegin(), data.cend(), [&range](const address_range& cur) return std::any_of(data.cbegin(), data.cend(), [&range](const address_range& cur)
{ {
return cur.valid() && cur.overlaps(range); return cur.valid() && cur.overlaps(range);
}); });
} }
// Test for overlap with a given address_range vector // Test for overlap with a given address_range vector
bool overlaps(const address_range_vector &other) const bool overlaps(const address_range_vector& other) const
{ {
for (const address_range &rng1 : data) for (const address_range& rng1 : data)
{ {
if (!rng1.valid()) if (!rng1.valid())
{ {
continue; continue;
} }
for (const address_range &rng2 : other.data) for (const address_range& rng2 : other.data)
{ {
if (!rng2.valid()) if (!rng2.valid())
{ {
@ -513,39 +540,37 @@ namespace utils
} }
// Test if a given range is fully contained inside this vector // Test if a given range is fully contained inside this vector
bool contains(const address_range &range) const bool contains(const address_range& range) const
{ {
return std::any_of(this->begin(), this->end(), [&range](const address_range& cur) return std::any_of(this->begin(), this->end(), [&range](const address_range& cur)
{ {
return cur.valid() && cur.inside(range); return cur.valid() && cur.inside(range);
}); });
} }
// Test if all ranges in this vector are full contained inside a specific range // Test if all ranges in this vector are full contained inside a specific range
bool inside(const address_range &range) const bool inside(const address_range& range) const
{ {
return std::all_of(this->begin(), this->end(), [&range](const address_range& cur) return std::all_of(this->begin(), this->end(), [&range](const address_range& cur)
{ {
return !cur.valid() || cur.inside(range); return !cur.valid() || cur.inside(range);
}); });
} }
}; };
// These declarations must be done after address_range_vector has been defined // These declarations must be done after address_range_vector has been defined
bool address_range::inside(const address_range_vector &vec) const bool address_range::inside(const address_range_vector& vec) const
{ {
return vec.contains(*this); return vec.contains(*this);
} }
bool address_range::overlaps(const address_range_vector &vec) const bool address_range::overlaps(const address_range_vector& vec) const
{ {
return vec.overlaps(*this); return vec.overlaps(*this);
} }
} // namespace utils } // namespace utils
namespace std namespace std
{ {
static_assert(sizeof(usz) >= 2 * sizeof(u32), "usz must be at least twice the size of u32"); static_assert(sizeof(usz) >= 2 * sizeof(u32), "usz must be at least twice the size of u32");
@ -556,7 +581,7 @@ namespace std
usz operator()(const utils::address_range& k) const usz operator()(const utils::address_range& k) const
{ {
// we can guarantee a unique hash since our type is 64 bits and usz as well // we can guarantee a unique hash since our type is 64 bits and usz as well
return (usz{ k.start } << 32) | usz{ k.end }; return (usz{k.start} << 32) | usz{k.end};
} }
}; };
} } // namespace std

View file

@ -21,73 +21,73 @@ template <>
void fmt_class_string<YAML::NodeType::value>::format(std::string& out, u64 arg) void fmt_class_string<YAML::NodeType::value>::format(std::string& out, u64 arg)
{ {
format_enum(out, arg, [](YAML::NodeType::value value) format_enum(out, arg, [](YAML::NodeType::value value)
{
switch (value)
{ {
case YAML::NodeType::Undefined: return "Undefined"; switch (value)
case YAML::NodeType::Null: return "Null"; {
case YAML::NodeType::Scalar: return "Scalar"; case YAML::NodeType::Undefined: return "Undefined";
case YAML::NodeType::Sequence: return "Sequence"; case YAML::NodeType::Null: return "Null";
case YAML::NodeType::Map: return "Map"; case YAML::NodeType::Scalar: return "Scalar";
} case YAML::NodeType::Sequence: return "Sequence";
case YAML::NodeType::Map: return "Map";
}
return unknown; return unknown;
}); });
} }
template <> template <>
void fmt_class_string<patch_configurable_type>::format(std::string& out, u64 arg) void fmt_class_string<patch_configurable_type>::format(std::string& out, u64 arg)
{ {
format_enum(out, arg, [](patch_configurable_type value) format_enum(out, arg, [](patch_configurable_type value)
{
switch (value)
{ {
case patch_configurable_type::double_range: return "double_range"; switch (value)
case patch_configurable_type::double_enum: return "double_enum"; {
case patch_configurable_type::long_range: return "long_range"; case patch_configurable_type::double_range: return "double_range";
case patch_configurable_type::long_enum: return "long_enum"; case patch_configurable_type::double_enum: return "double_enum";
} case patch_configurable_type::long_range: return "long_range";
case patch_configurable_type::long_enum: return "long_enum";
}
return unknown; return unknown;
}); });
} }
template <> template <>
void fmt_class_string<patch_type>::format(std::string& out, u64 arg) void fmt_class_string<patch_type>::format(std::string& out, u64 arg)
{ {
format_enum(out, arg, [](patch_type value) format_enum(out, arg, [](patch_type value)
{
switch (value)
{ {
case patch_type::invalid: return "invalid"; switch (value)
case patch_type::alloc: return "alloc"; {
case patch_type::code_alloc: return "calloc"; case patch_type::invalid: return "invalid";
case patch_type::jump: return "jump"; case patch_type::alloc: return "alloc";
case patch_type::jump_link: return "jumpl"; case patch_type::code_alloc: return "calloc";
case patch_type::jump_func: return "jumpf"; case patch_type::jump: return "jump";
case patch_type::load: return "load"; case patch_type::jump_link: return "jumpl";
case patch_type::byte: return "byte"; case patch_type::jump_func: return "jumpf";
case patch_type::le16: return "le16"; case patch_type::load: return "load";
case patch_type::le32: return "le32"; case patch_type::byte: return "byte";
case patch_type::le64: return "le64"; case patch_type::le16: return "le16";
case patch_type::bef32: return "bef32"; case patch_type::le32: return "le32";
case patch_type::bef64: return "bef64"; case patch_type::le64: return "le64";
case patch_type::be16: return "be16"; case patch_type::bef32: return "bef32";
case patch_type::be32: return "be32"; case patch_type::bef64: return "bef64";
case patch_type::bd32: return "bd32"; case patch_type::be16: return "be16";
case patch_type::be64: return "be64"; case patch_type::be32: return "be32";
case patch_type::bd64: return "bd64"; case patch_type::bd32: return "bd32";
case patch_type::lef32: return "lef32"; case patch_type::be64: return "be64";
case patch_type::lef64: return "lef64"; case patch_type::bd64: return "bd64";
case patch_type::bp_exec: return "bpex"; case patch_type::lef32: return "lef32";
case patch_type::utf8: return "utf8"; case patch_type::lef64: return "lef64";
case patch_type::c_utf8: return "cutf8"; case patch_type::bp_exec: return "bpex";
case patch_type::move_file: return "move_file"; case patch_type::utf8: return "utf8";
case patch_type::hide_file: return "hide_file"; case patch_type::c_utf8: return "cutf8";
} case patch_type::move_file: return "move_file";
case patch_type::hide_file: return "hide_file";
}
return unknown; return unknown;
}); });
} }
void patch_engine::patch_config_value::set_and_check_value(f64 new_value, std::string_view name) void patch_engine::patch_config_value::set_and_check_value(f64 new_value, std::string_view name)
@ -97,7 +97,10 @@ void patch_engine::patch_config_value::set_and_check_value(f64 new_value, std::s
case patch_configurable_type::double_enum: case patch_configurable_type::double_enum:
case patch_configurable_type::long_enum: case patch_configurable_type::long_enum:
{ {
if (std::none_of(allowed_values.begin(), allowed_values.end(), [&new_value](const patch_allowed_value& allowed_value){ return allowed_value.value == new_value; })) if (std::none_of(allowed_values.begin(), allowed_values.end(), [&new_value](const patch_allowed_value& allowed_value)
{
return allowed_value.value == new_value;
}))
{ {
patch_log.error("Can't set configurable enumerated value '%s' to %f. Using default value %f", name, new_value, value); patch_log.error("Can't set configurable enumerated value '%s' to %f. Using default value %f", name, new_value, value);
return; return;
@ -243,7 +246,7 @@ bool patch_engine::load(patch_map& patches_map, const std::string& path, std::st
// Find or create an entry matching the key/hash in our map // Find or create an entry matching the key/hash in our map
patch_container& container = patches_map[main_key]; patch_container& container = patches_map[main_key];
container.hash = main_key; container.hash = main_key;
container.version = version; container.version = version;
// Go through each patch // Go through each patch
@ -268,10 +271,10 @@ bool patch_engine::load(patch_map& patches_map, const std::string& path, std::st
continue; continue;
} }
struct patch_info info {}; struct patch_info info{};
info.description = description; info.description = description;
info.hash = main_key; info.hash = main_key;
info.version = version; info.version = version;
info.source_path = path; info.source_path = path;
if (const auto games_node = patches_entry.second[patch_key::games]) if (const auto games_node = patches_entry.second[patch_key::games])
@ -329,7 +332,10 @@ bool patch_engine::load(patch_map& patches_map, const std::string& path, std::st
is_valid = false; is_valid = false;
continue; continue;
} }
else if (serial.size() != 9 || !std::all_of(serial.begin(), serial.end(), [](char c) { return std::isalnum(c); })) else if (serial.size() != 9 || !std::all_of(serial.begin(), serial.end(), [](char c)
{
return std::isalnum(c);
}))
{ {
append_log_message(log_messages, fmt::format("Error: Serial '%s' invalid (patch: %s, key: %s, location: %s, file: %s)", serial, description, main_key, get_yaml_node_location(serial_node), path), &patch_log.error); append_log_message(log_messages, fmt::format("Error: Serial '%s' invalid (patch: %s, key: %s, location: %s, file: %s)", serial, description, main_key, get_yaml_node_location(serial_node), path), &patch_log.error);
is_valid = false; is_valid = false;
@ -457,7 +463,7 @@ bool patch_engine::load(patch_map& patches_map, const std::string& path, std::st
const std::string& str_type = config_value_type_node.Scalar(); const std::string& str_type = config_value_type_node.Scalar();
bool is_valid_type = false; bool is_valid_type = false;
for (patch_configurable_type type : { patch_configurable_type::double_range, patch_configurable_type::double_enum, patch_configurable_type::long_range, patch_configurable_type::long_enum }) for (patch_configurable_type type : {patch_configurable_type::double_range, patch_configurable_type::double_enum, patch_configurable_type::long_range, patch_configurable_type::long_enum})
{ {
if (str_type == fmt::format("%s", type)) if (str_type == fmt::format("%s", type))
{ {
@ -558,7 +564,10 @@ bool patch_engine::load(patch_map& patches_map, const std::string& path, std::st
new_allowed_value.label = allowed_value.first.Scalar(); new_allowed_value.label = allowed_value.first.Scalar();
new_allowed_value.value = get_and_check_config_value(allowed_value.second); new_allowed_value.value = get_and_check_config_value(allowed_value.second);
if (std::any_of(config_value.allowed_values.begin(), config_value.allowed_values.end(), [&new_allowed_value](const patch_allowed_value& other){ return new_allowed_value.value == other.value || new_allowed_value.label == other.label; })) if (std::any_of(config_value.allowed_values.begin(), config_value.allowed_values.end(), [&new_allowed_value](const patch_allowed_value& other)
{
return new_allowed_value.value == other.value || new_allowed_value.label == other.label;
}))
{ {
append_log_message(log_messages, fmt::format("Error: Skipping configurable allowed value. Another entry with the same label or value already exists. (patch: %s, key: %s, location: %s, file: %s)", description, main_key, get_yaml_node_location(allowed_value), path), &patch_log.error); append_log_message(log_messages, fmt::format("Error: Skipping configurable allowed value. Another entry with the same label or value already exists. (patch: %s, key: %s, location: %s, file: %s)", description, main_key, get_yaml_node_location(allowed_value), path), &patch_log.error);
is_valid = false; is_valid = false;
@ -581,7 +590,10 @@ bool patch_engine::load(patch_map& patches_map, const std::string& path, std::st
is_valid = false; is_valid = false;
} }
if (std::none_of(config_value.allowed_values.begin(), config_value.allowed_values.end(), [&config_value](const patch_allowed_value& other){ return other.value == config_value.value; })) if (std::none_of(config_value.allowed_values.begin(), config_value.allowed_values.end(), [&config_value](const patch_allowed_value& other)
{
return other.value == config_value.value;
}))
{ {
append_log_message(log_messages, fmt::format("Error: Configurable value was not found in allowed values (key: %s, location: %s, file: %s)", main_key, get_yaml_node_location(config_value_allowed_values_node), path), &patch_log.error); append_log_message(log_messages, fmt::format("Error: Configurable value was not found in allowed values (key: %s, location: %s, file: %s)", main_key, get_yaml_node_location(config_value_allowed_values_node), path), &patch_log.error);
is_valid = false; is_valid = false;
@ -643,7 +655,7 @@ bool patch_engine::load(patch_map& patches_map, const std::string& path, std::st
if (!importing) if (!importing)
{ {
patch_log.warning("A lower patch version was found ('%s' vs '%s') for %s: %s (in file %s)", existing_version, info.patch_version, main_key, description, container.patch_info_map[description].source_path); patch_log.warning("A lower patch version was found ('%s' vs '%s') for %s: %s (in file %s)", existing_version, info.patch_version, main_key, description, container.patch_info_map[description].source_path);
} }
} }
@ -685,8 +697,8 @@ bool patch_engine::add_patch_data(YAML::Node node, patch_info& info, u32 modifie
return false; return false;
} }
const auto type_node = node[0]; const auto type_node = node[0];
const auto addr_node = node[1]; const auto addr_node = node[1];
const auto value_node = node[2]; const auto value_node = node[2];
const auto type = get_patch_type(type_node); const auto type = get_patch_type(type_node);
@ -738,10 +750,10 @@ bool patch_engine::add_patch_data(YAML::Node node, patch_info& info, u32 modifie
} }
patch_data p_data{}; patch_data p_data{};
p_data.type = type; p_data.type = type;
p_data.offset = addr_node.as<u32>(0) + modifier; p_data.offset = addr_node.as<u32>(0) + modifier;
p_data.original_offset = addr_node.Scalar(); p_data.original_offset = addr_node.Scalar();
p_data.original_value = value_node.Scalar(); p_data.original_value = value_node.Scalar();
const bool is_config_value = info.default_config_values.contains(p_data.original_value); const bool is_config_value = info.default_config_values.contains(p_data.original_value);
const patch_config_value config_value = is_config_value ? ::at32(info.default_config_values, p_data.original_value) : patch_config_value{}; const patch_config_value config_value = is_config_value ? ::at32(info.default_config_values, p_data.original_value) : patch_config_value{};
@ -954,7 +966,8 @@ static usz apply_modification(std::vector<u32>& applied, patch_engine::patch_inf
for (const patch_engine::patch_data& p : patch.data_list) for (const patch_engine::patch_data& p : patch.data_list)
{ {
if (p.type != patch_type::alloc) continue; if (p.type != patch_type::alloc)
continue;
// Do not allow null address or if resultant ptr is not a VM ptr // Do not allow null address or if resultant ptr is not a VM ptr
if (const u32 alloc_at = (p.offset & -4096); alloc_at >> 16) if (const u32 alloc_at = (p.offset & -4096); alloc_at >> 16)
@ -1008,14 +1021,14 @@ static usz apply_modification(std::vector<u32>& applied, patch_engine::patch_inf
// Revert in case of failure // Revert in case of failure
std::for_each(applied.begin() + old_applied_size, applied.end(), [&](u32 index) std::for_each(applied.begin() + old_applied_size, applied.end(), [&](u32 index)
{ {
const u32 addr = std::exchange(patch.data_list[index].alloc_addr, 0); const u32 addr = std::exchange(patch.data_list[index].alloc_addr, 0);
vm::dealloc(addr); vm::dealloc(addr);
auto alloc_map = vm::get(vm::any, addr); auto alloc_map = vm::get(vm::any, addr);
unmap_vm_area(alloc_map); unmap_vm_area(alloc_map);
}); });
applied.resize(old_applied_size); applied.resize(old_applied_size);
return old_applied_size; return old_applied_size;
@ -1568,12 +1581,11 @@ void patch_engine::apply(std::vector<u32>& applied_total, const std::string& nam
// Sort specific patches after global patches // Sort specific patches after global patches
// So they will determine the end results // So they will determine the end results
const auto patch_super_list = const auto patch_super_list =
{ {
&patches_for_all_serials_and_all_versions, &patches_for_all_serials_and_all_versions,
&patches_for_all_serials_and_this_version, &patches_for_all_serials_and_this_version,
&patches_for_this_serial_and_all_versions, &patches_for_this_serial_and_all_versions,
&patches_for_this_serial_and_this_version &patches_for_this_serial_and_this_version};
};
// Filter by patch group (reverse so specific patches will be prioritized over globals) // Filter by patch group (reverse so specific patches will be prioritized over globals)
for (auto it = std::rbegin(patch_super_list); it != std::rend(patch_super_list); it++) for (auto it = std::rbegin(patch_super_list); it != std::rend(patch_super_list); it++)
@ -1790,11 +1802,16 @@ static void append_patches(patch_engine::patch_map& existing_patches, const patc
} }
} }
if (!new_info.patch_version.empty()) info.patch_version = new_info.patch_version; if (!new_info.patch_version.empty())
if (!new_info.author.empty()) info.author = new_info.author; info.patch_version = new_info.patch_version;
if (!new_info.notes.empty()) info.notes = new_info.notes; if (!new_info.author.empty())
if (!new_info.data_list.empty()) info.data_list = new_info.data_list; info.author = new_info.author;
if (!new_info.source_path.empty()) info.source_path = new_info.source_path; if (!new_info.notes.empty())
info.notes = new_info.notes;
if (!new_info.data_list.empty())
info.data_list = new_info.data_list;
if (!new_info.source_path.empty())
info.source_path = new_info.source_path;
count++; count++;
} }
@ -1850,10 +1867,14 @@ bool patch_engine::save_patches(const patch_map& patches, const std::string& pat
out << YAML::EndMap; out << YAML::EndMap;
if (!info.author.empty()) out << patch_key::author << info.author; if (!info.author.empty())
if (!info.patch_version.empty()) out << patch_key::patch_version << info.patch_version; out << patch_key::author << info.author;
if (!info.patch_group.empty()) out << patch_key::group << info.patch_group; if (!info.patch_version.empty())
if (!info.notes.empty()) out << patch_key::notes << info.notes; out << patch_key::patch_version << info.patch_version;
if (!info.patch_group.empty())
out << patch_key::group << info.patch_group;
if (!info.notes.empty())
out << patch_key::notes << info.notes;
if (!info.default_config_values.empty()) if (!info.default_config_values.empty())
{ {
@ -1964,7 +1985,7 @@ patch_engine::patch_map patch_engine::load_config()
const std::string path = get_patch_config_path(); const std::string path = get_patch_config_path();
patch_log.notice("Loading patch config file %s", path); patch_log.notice("Loading patch config file %s", path);
if (fs::file f{ path }) if (fs::file f{path})
{ {
auto [root, error] = yaml_load(f.to_string()); auto [root, error] = yaml_load(f.to_string());

View file

@ -26,7 +26,7 @@ namespace patch_key
static const std::string min = "Min"; static const std::string min = "Min";
static const std::string max = "Max"; static const std::string max = "Max";
static const std::string allowed_values = "Allowed Values"; static const std::string allowed_values = "Allowed Values";
} } // namespace patch_key
inline static const std::string patch_engine_version = "1.2"; inline static const std::string patch_engine_version = "1.2";
@ -34,11 +34,11 @@ enum class patch_type
{ {
invalid, invalid,
load, load,
alloc, // Allocate memory at address (zeroized executable memory) alloc, // Allocate memory at address (zeroized executable memory)
code_alloc,// Allocate memory somewhere, saves branch to memory at specfied address (filled with PPU NOP and branch for returning) code_alloc, // Allocate memory somewhere, saves branch to memory at specfied address (filled with PPU NOP and branch for returning)
jump, // Install special 32-bit jump instruction (PPU only atm) jump, // Install special 32-bit jump instruction (PPU only atm)
jump_link, // jump + set link (PPU only atm) jump_link, // jump + set link (PPU only atm)
jump_func, // jump to exported function (PPU only, forever) jump_func, // jump to exported function (PPU only, forever)
byte, byte,
le16, le16,
le32, le32,
@ -52,9 +52,9 @@ enum class patch_type
bd64, // be64 with data hint (non-code) bd64, // be64 with data hint (non-code)
bef32, bef32,
bef64, bef64,
bp_exec, // Execution Breakpoint bp_exec, // Execution Breakpoint
utf8, // Text of string (not null-terminated automatically) utf8, // Text of string (not null-terminated automatically)
c_utf8, // Text of string (null-terminated automatically) c_utf8, // Text of string (null-terminated automatically)
move_file, // Move file move_file, // Move file
hide_file, // Hide file hide_file, // Hide file
}; };
@ -80,7 +80,7 @@ public:
patch_type type = patch_type::load; patch_type type = patch_type::load;
u32 offset = 0; u32 offset = 0;
std::string original_offset{}; // Used for specifying paths std::string original_offset{}; // Used for specifying paths
std::string original_value{}; // Used for import consistency (avoid rounding etc.) std::string original_value{}; // Used for import consistency (avoid rounding etc.)
union union
{ {
u64 long_value; u64 long_value;

View file

@ -6,10 +6,10 @@ To enable bs_t<>, enum scope must contain `__bitset_enum_max` entry.
enum class flagzz : u32 enum class flagzz : u32
{ {
flag1, // Bit indices start from zero flag1, // Bit indices start from zero
flag2, flag2,
__bitset_enum_max // It must be the last value __bitset_enum_max // It must be the last value
}; };
This also enables helper operators for this enum type. This also enables helper operators for this enum type.
@ -26,8 +26,7 @@ Intersection (&) and symmetric difference (^) is also available.
#include "Utilities/StrFmt.h" #include "Utilities/StrFmt.h"
template <typename T> template <typename T>
concept BitSetEnum = std::is_enum_v<T> && requires(T x) concept BitSetEnum = std::is_enum_v<T> && requires(T x) {
{
T::__bitset_enum_max; T::__bitset_enum_max;
}; };
@ -91,56 +90,56 @@ public:
} }
// Copy // Copy
constexpr bs_t operator +() const constexpr bs_t operator+() const
{ {
return *this; return *this;
} }
constexpr bs_t& operator +=(bs_t rhs) constexpr bs_t& operator+=(bs_t rhs)
{ {
m_data |= static_cast<under>(rhs); m_data |= static_cast<under>(rhs);
return *this; return *this;
} }
constexpr bs_t& operator -=(bs_t rhs) constexpr bs_t& operator-=(bs_t rhs)
{ {
m_data &= ~static_cast<under>(rhs); m_data &= ~static_cast<under>(rhs);
return *this; return *this;
} }
constexpr bs_t& operator &=(bs_t rhs) constexpr bs_t& operator&=(bs_t rhs)
{ {
m_data &= static_cast<under>(rhs); m_data &= static_cast<under>(rhs);
return *this; return *this;
} }
constexpr bs_t& operator ^=(bs_t rhs) constexpr bs_t& operator^=(bs_t rhs)
{ {
m_data ^= static_cast<under>(rhs); m_data ^= static_cast<under>(rhs);
return *this; return *this;
} }
friend constexpr bs_t operator +(bs_t lhs, bs_t rhs) friend constexpr bs_t operator+(bs_t lhs, bs_t rhs)
{ {
return bs_t(0, lhs.m_data | rhs.m_data); return bs_t(0, lhs.m_data | rhs.m_data);
} }
friend constexpr bs_t operator -(bs_t lhs, bs_t rhs) friend constexpr bs_t operator-(bs_t lhs, bs_t rhs)
{ {
return bs_t(0, lhs.m_data & ~rhs.m_data); return bs_t(0, lhs.m_data & ~rhs.m_data);
} }
friend constexpr bs_t operator &(bs_t lhs, bs_t rhs) friend constexpr bs_t operator&(bs_t lhs, bs_t rhs)
{ {
return bs_t(0, lhs.m_data & rhs.m_data); return bs_t(0, lhs.m_data & rhs.m_data);
} }
friend constexpr bs_t operator ^(bs_t lhs, bs_t rhs) friend constexpr bs_t operator^(bs_t lhs, bs_t rhs)
{ {
return bs_t(0, lhs.m_data ^ rhs.m_data); return bs_t(0, lhs.m_data ^ rhs.m_data);
} }
constexpr bool operator ==(bs_t rhs) const noexcept constexpr bool operator==(bs_t rhs) const noexcept
{ {
return m_data == rhs.m_data; return m_data == rhs.m_data;
} }
@ -179,63 +178,71 @@ public:
// Unary '+' operator: promote plain enum value to bitset value // Unary '+' operator: promote plain enum value to bitset value
template <BitSetEnum T> template <BitSetEnum T>
constexpr bs_t<T> operator +(T bit) constexpr bs_t<T> operator+(T bit)
{ {
return bs_t<T>(bit); return bs_t<T>(bit);
} }
// Binary '+' operator: bitset union // Binary '+' operator: bitset union
template <BitSetEnum T, typename U> requires (std::is_constructible_v<bs_t<T>, U>) template <BitSetEnum T, typename U>
constexpr bs_t<T> operator +(T lhs, const U& rhs) requires(std::is_constructible_v<bs_t<T>, U>)
constexpr bs_t<T> operator+(T lhs, const U& rhs)
{ {
return bs_t<T>(lhs) + bs_t<T>(rhs); return bs_t<T>(lhs) + bs_t<T>(rhs);
} }
// Binary '+' operator: bitset union // Binary '+' operator: bitset union
template <typename U, BitSetEnum T> requires (std::is_constructible_v<bs_t<T>, U> && !std::is_enum_v<U>) template <typename U, BitSetEnum T>
constexpr bs_t<T> operator +(const U& lhs, T rhs) requires(std::is_constructible_v<bs_t<T>, U> && !std::is_enum_v<U>)
constexpr bs_t<T> operator+(const U& lhs, T rhs)
{ {
return bs_t<T>(lhs) + bs_t<T>(rhs); return bs_t<T>(lhs) + bs_t<T>(rhs);
} }
// Binary '-' operator: bitset difference // Binary '-' operator: bitset difference
template <BitSetEnum T, typename U> requires (std::is_constructible_v<bs_t<T>, U>) template <BitSetEnum T, typename U>
constexpr bs_t<T> operator -(T lhs, const U& rhs) requires(std::is_constructible_v<bs_t<T>, U>)
constexpr bs_t<T> operator-(T lhs, const U& rhs)
{ {
return bs_t<T>(lhs) - bs_t<T>(rhs); return bs_t<T>(lhs) - bs_t<T>(rhs);
} }
// Binary '-' operator: bitset difference // Binary '-' operator: bitset difference
template <typename U, BitSetEnum T> requires (std::is_constructible_v<bs_t<T>, U> && !std::is_enum_v<U>) template <typename U, BitSetEnum T>
constexpr bs_t<T> operator -(const U& lhs, T rhs) requires(std::is_constructible_v<bs_t<T>, U> && !std::is_enum_v<U>)
constexpr bs_t<T> operator-(const U& lhs, T rhs)
{ {
return bs_t<T>(lhs) - bs_t<T>(rhs); return bs_t<T>(lhs) - bs_t<T>(rhs);
} }
// Binary '&' operator: bitset intersection // Binary '&' operator: bitset intersection
template <BitSetEnum T, typename U> requires (std::is_constructible_v<bs_t<T>, U>) template <BitSetEnum T, typename U>
constexpr bs_t<T> operator &(T lhs, const U& rhs) requires(std::is_constructible_v<bs_t<T>, U>)
constexpr bs_t<T> operator&(T lhs, const U& rhs)
{ {
return bs_t<T>(lhs) & bs_t<T>(rhs); return bs_t<T>(lhs) & bs_t<T>(rhs);
} }
// Binary '&' operator: bitset intersection // Binary '&' operator: bitset intersection
template <typename U, BitSetEnum T> requires (std::is_constructible_v<bs_t<T>, U> && !std::is_enum_v<U>) template <typename U, BitSetEnum T>
constexpr bs_t<T> operator &(const U& lhs, T rhs) requires(std::is_constructible_v<bs_t<T>, U> && !std::is_enum_v<U>)
constexpr bs_t<T> operator&(const U& lhs, T rhs)
{ {
return bs_t<T>(lhs) & bs_t<T>(rhs); return bs_t<T>(lhs) & bs_t<T>(rhs);
} }
// Binary '^' operator: bitset symmetric difference // Binary '^' operator: bitset symmetric difference
template <BitSetEnum T, typename U> requires (std::is_constructible_v<bs_t<T>, U>) template <BitSetEnum T, typename U>
constexpr bs_t<T> operator ^(T lhs, const U& rhs) requires(std::is_constructible_v<bs_t<T>, U>)
constexpr bs_t<T> operator^(T lhs, const U& rhs)
{ {
return bs_t<T>(lhs) ^ bs_t<T>(rhs); return bs_t<T>(lhs) ^ bs_t<T>(rhs);
} }
// Binary '^' operator: bitset symmetric difference // Binary '^' operator: bitset symmetric difference
template <typename U, BitSetEnum T> requires (std::is_constructible_v<bs_t<T>, U> && !std::is_enum_v<U>) template <typename U, BitSetEnum T>
constexpr bs_t<T> operator ^(const U& lhs, T rhs) requires(std::is_constructible_v<bs_t<T>, U> && !std::is_enum_v<U>)
constexpr bs_t<T> operator^(const U& lhs, T rhs)
{ {
return bs_t<T>(lhs) ^ bs_t<T>(rhs); return bs_t<T>(lhs) ^ bs_t<T>(rhs);
} }
@ -261,7 +268,7 @@ public:
atomic_bs_t(const atomic_bs_t&) = delete; atomic_bs_t(const atomic_bs_t&) = delete;
atomic_bs_t& operator =(const atomic_bs_t&) = delete; atomic_bs_t& operator=(const atomic_bs_t&) = delete;
explicit constexpr atomic_bs_t(bs_t value) explicit constexpr atomic_bs_t(bs_t value)
: base(value) : base(value)
@ -285,7 +292,7 @@ public:
return static_cast<under>(base::load()); return static_cast<under>(base::load());
} }
bs_t operator +() const bs_t operator+() const
{ {
return base::load(); return base::load();
} }
@ -300,7 +307,7 @@ public:
return bs_t(0, atomic_storage<under>::or_fetch(m_data.m_data, rhs.m_data)); return bs_t(0, atomic_storage<under>::or_fetch(m_data.m_data, rhs.m_data));
} }
bs_t operator +=(const bs_t& rhs) bs_t operator+=(const bs_t& rhs)
{ {
return add_fetch(rhs); return add_fetch(rhs);
} }
@ -315,7 +322,7 @@ public:
return bs_t(0, atomic_storage<under>::and_fetch(m_data.m_data, ~rhs.m_data)); return bs_t(0, atomic_storage<under>::and_fetch(m_data.m_data, ~rhs.m_data));
} }
bs_t operator -=(const bs_t& rhs) bs_t operator-=(const bs_t& rhs)
{ {
return sub_fetch(rhs); return sub_fetch(rhs);
} }
@ -330,7 +337,7 @@ public:
return bs_t(0, atomic_storage<under>::and_fetch(m_data.m_data, rhs.m_data)); return bs_t(0, atomic_storage<under>::and_fetch(m_data.m_data, rhs.m_data));
} }
bs_t operator &=(const bs_t& rhs) bs_t operator&=(const bs_t& rhs)
{ {
return and_fetch(rhs); return and_fetch(rhs);
} }
@ -345,14 +352,14 @@ public:
return bs_t(0, atomic_storage<under>::xor_fetch(m_data.m_data, rhs.m_data)); return bs_t(0, atomic_storage<under>::xor_fetch(m_data.m_data, rhs.m_data));
} }
bs_t operator ^=(const bs_t& rhs) bs_t operator^=(const bs_t& rhs)
{ {
return xor_fetch(rhs); return xor_fetch(rhs);
} }
auto fetch_or(const bs_t&) = delete; auto fetch_or(const bs_t&) = delete;
auto or_fetch(const bs_t&) = delete; auto or_fetch(const bs_t&) = delete;
auto operator |=(const bs_t&) = delete; auto operator|=(const bs_t&) = delete;
bool test_and_set(T rhs) bool test_and_set(T rhs)
{ {

File diff suppressed because it is too large Load diff

View file

@ -8,23 +8,23 @@ template <>
void fmt_class_string<cheat_type>::format(std::string& out, u64 arg) void fmt_class_string<cheat_type>::format(std::string& out, u64 arg)
{ {
format_enum(out, arg, [](cheat_type value) format_enum(out, arg, [](cheat_type value)
{
switch (value)
{ {
case cheat_type::unsigned_8_cheat: return "Unsigned 8 bits"; switch (value)
case cheat_type::unsigned_16_cheat: return "Unsigned 16 bits"; {
case cheat_type::unsigned_32_cheat: return "Unsigned 32 bits"; case cheat_type::unsigned_8_cheat: return "Unsigned 8 bits";
case cheat_type::unsigned_64_cheat: return "Unsigned 64 bits"; case cheat_type::unsigned_16_cheat: return "Unsigned 16 bits";
case cheat_type::signed_8_cheat: return "Signed 8 bits"; case cheat_type::unsigned_32_cheat: return "Unsigned 32 bits";
case cheat_type::signed_16_cheat: return "Signed 16 bits"; case cheat_type::unsigned_64_cheat: return "Unsigned 64 bits";
case cheat_type::signed_32_cheat: return "Signed 32 bits"; case cheat_type::signed_8_cheat: return "Signed 8 bits";
case cheat_type::signed_64_cheat: return "Signed 64 bits"; case cheat_type::signed_16_cheat: return "Signed 16 bits";
case cheat_type::float_32_cheat: return "Float 32 bits"; case cheat_type::signed_32_cheat: return "Signed 32 bits";
case cheat_type::max: break; case cheat_type::signed_64_cheat: return "Signed 64 bits";
} case cheat_type::float_32_cheat: return "Float 32 bits";
case cheat_type::max: break;
}
return unknown; return unknown;
}); });
} }
bool cheat_info::from_str(const std::string& cheat_line) bool cheat_info::from_str(const std::string& cheat_line)
@ -38,11 +38,11 @@ bool cheat_info::from_str(const std::string& cheat_line)
return false; return false;
} }
game = cheat_vec[0]; game = cheat_vec[0];
description = cheat_vec[1]; description = cheat_vec[1];
type = cheat_type{::narrow<u8>(val64)}; type = cheat_type{::narrow<u8>(val64)};
offset = std::stoul(cheat_vec[3]); offset = std::stoul(cheat_vec[3]);
red_script = cheat_vec[4]; red_script = cheat_vec[4];
return true; return true;
} }

View file

@ -12,31 +12,31 @@ void cond_variable::imp_wait(u32 _old, u64 _timeout) noexcept
// Cleanup // Cleanup
m_value.atomic_op([](u32& value) m_value.atomic_op([](u32& value)
{
// Remove waiter (c_waiter_mask)
value -= 1;
if ((value & c_waiter_mask) == 0)
{ {
// Last waiter removed, clean signals // Remove waiter (c_waiter_mask)
value = 0; value -= 1;
}
}); if ((value & c_waiter_mask) == 0)
{
// Last waiter removed, clean signals
value = 0;
}
});
} }
void cond_variable::imp_wake(u32 _count) noexcept void cond_variable::imp_wake(u32 _count) noexcept
{ {
const auto [_old, ok] = m_value.fetch_op([](u32& value) const auto [_old, ok] = m_value.fetch_op([](u32& value)
{
if (!value || (value & c_signal_mask) == c_signal_mask)
{ {
return false; if (!value || (value & c_signal_mask) == c_signal_mask)
} {
return false;
}
// Add signal // Add signal
value += c_signal_mask & (0 - c_signal_mask); value += c_signal_mask & (0 - c_signal_mask);
return true; return true;
}); });
if (!ok || !_count) if (!ok || !_count)
{ {

View file

@ -20,17 +20,17 @@ protected:
u32 add_waiter() noexcept u32 add_waiter() noexcept
{ {
return m_value.atomic_op([](u32& value) -> u32 return m_value.atomic_op([](u32& value) -> u32
{
if ((value & c_signal_mask) == c_signal_mask || (value & c_waiter_mask) == c_waiter_mask)
{ {
// Signal or waiter overflow, return immediately if ((value & c_signal_mask) == c_signal_mask || (value & c_waiter_mask) == c_waiter_mask)
return 0; {
} // Signal or waiter overflow, return immediately
return 0;
}
// Add waiter (c_waiter_mask) // Add waiter (c_waiter_mask)
value += 1; value += 1;
return value; return value;
}); });
} }
// Internal waiting function // Internal waiting function

View file

@ -39,7 +39,7 @@ namespace date_time
return str; return str;
} }
template<char separator = 0> template <char separator = 0>
static inline std::string current_time_narrow() static inline std::string current_time_narrow()
{ {
char str[80]; char str[80];
@ -47,7 +47,7 @@ namespace date_time
std::string parse_buf; std::string parse_buf;
if constexpr(separator != 0) if constexpr (separator != 0)
parse_buf = std::string("%Y") + separator + "%m" + separator + "%d" + separator + "%H" + separator + "%M" + separator + "%S"; parse_buf = std::string("%Y") + separator + "%m" + separator + "%d" + separator + "%H" + separator + "%M" + separator + "%S";
else else
parse_buf = "%Y%m%d%H%M%S"; parse_buf = "%Y%m%d%H%M%S";
@ -55,4 +55,4 @@ namespace date_time
strftime(str, sizeof(str), parse_buf.c_str(), &now); strftime(str, sizeof(str), parse_buf.c_str(), &now);
return str; return str;
} }
} } // namespace date_time

File diff suppressed because it is too large Load diff

View file

@ -30,7 +30,7 @@ public:
} }
} }
T& operator [](usz index) T& operator[](usz index)
{ {
lf_array* _this = this; lf_array* _this = this;
@ -49,7 +49,7 @@ public:
if (!next) if (!next)
{ {
// Do not allow access beyond many element more at a time // Do not allow access beyond many element more at a time
ensure(!installed && index - i < N * 2); ensure(!installed && index - i < N * 2);
installed = true; installed = true;
@ -73,7 +73,8 @@ public:
return *result; return *result;
} }
template <typename F> requires (std::is_invocable_v<F, T&>) template <typename F>
requires(std::is_invocable_v<F, T&>)
auto for_each(F&& func, bool is_finite = true) auto for_each(F&& func, bool is_finite = true)
{ {
lf_array* _this = this; lf_array* _this = this;
@ -143,7 +144,7 @@ public:
// Simple lock-free FIFO queue base. Based on lf_array<T, N> itself. Currently uses 32-bit counters. // Simple lock-free FIFO queue base. Based on lf_array<T, N> itself. Currently uses 32-bit counters.
// There is no "push_end" or "pop_begin" provided, the queue element must signal its state on its own. // There is no "push_end" or "pop_begin" provided, the queue element must signal its state on its own.
template<typename T, usz N = std::max<usz>(256 / sizeof(T), 1)> template <typename T, usz N = std::max<usz>(256 / sizeof(T), 1)>
class lf_fifo : public lf_array<T, N> class lf_fifo : public lf_array<T, N>
{ {
// LSB 32-bit: push, MSB 32-bit: pop // LSB 32-bit: push, MSB 32-bit: pop
@ -176,17 +177,17 @@ public:
u32 pop_end(u32 count = 1) u32 pop_end(u32 count = 1)
{ {
return m_ctrl.atomic_op([&](u64& ctrl) return m_ctrl.atomic_op([&](u64& ctrl)
{
ctrl += u64{count} << 32;
if (ctrl >> 32 == static_cast<u32>(ctrl))
{ {
// Clean if possible ctrl += u64{count} << 32;
ctrl = 0;
}
return static_cast<u32>(ctrl >> 32); if (ctrl >> 32 == static_cast<u32>(ctrl))
}); {
// Clean if possible
ctrl = 0;
}
return static_cast<u32>(ctrl >> 32);
});
} }
}; };
@ -214,8 +215,7 @@ class lf_queue_item final
template <typename... Args> template <typename... Args>
constexpr lf_queue_item(lf_queue_item* link, Args&&... args) constexpr lf_queue_item(lf_queue_item* link, Args&&... args)
: m_link(link) : m_link(link), m_data(std::forward<Args>(args)...)
, m_data(std::forward<Args>(args)...)
{ {
} }
@ -248,28 +248,28 @@ class lf_queue_iterator
public: public:
constexpr lf_queue_iterator() = default; constexpr lf_queue_iterator() = default;
bool operator ==(const lf_queue_iterator& rhs) const bool operator==(const lf_queue_iterator& rhs) const
{ {
return m_ptr == rhs.m_ptr; return m_ptr == rhs.m_ptr;
} }
T& operator *() const T& operator*() const
{ {
return m_ptr->m_data; return m_ptr->m_data;
} }
T* operator ->() const T* operator->() const
{ {
return &m_ptr->m_data; return &m_ptr->m_data;
} }
lf_queue_iterator& operator ++() lf_queue_iterator& operator++()
{ {
m_ptr = m_ptr->m_link; m_ptr = m_ptr->m_link;
return *this; return *this;
} }
lf_queue_iterator operator ++(int) lf_queue_iterator operator++(int)
{ {
lf_queue_iterator result; lf_queue_iterator result;
result.m_ptr = m_ptr; result.m_ptr = m_ptr;
@ -298,9 +298,9 @@ public:
r.m_head = nullptr; r.m_head = nullptr;
} }
lf_queue_slice& operator =(const lf_queue_slice&) = delete; lf_queue_slice& operator=(const lf_queue_slice&) = delete;
lf_queue_slice& operator =(lf_queue_slice&& r) noexcept lf_queue_slice& operator=(lf_queue_slice&& r) noexcept
{ {
if (this != &r) if (this != &r)
{ {
@ -317,12 +317,12 @@ public:
delete m_head; delete m_head;
} }
T& operator *() const T& operator*() const
{ {
return m_head->m_data; return m_head->m_data;
} }
T* operator ->() const T* operator->() const
{ {
return &m_head->m_data; return &m_head->m_data;
} }
@ -402,11 +402,10 @@ class lf_queue final
do do
{ {
auto* pprev = prev->m_link; auto* pprev = prev->m_link;
prev->m_link = head; prev->m_link = head;
head = std::exchange(prev, pprev); head = std::exchange(prev, pprev);
} } while (prev);
while (prev);
} }
return head; return head;
@ -573,8 +572,7 @@ public:
// Set to not check already checked items // Set to not check already checked items
_chk = _old; _chk = _old;
} } while (!m_head.compare_exchange(_old, item));
while (!m_head.compare_exchange(_old, item));
return &item->m_data; return &item->m_data;
} }

View file

@ -59,15 +59,15 @@ void shared_mutex::imp_wait()
while (true) while (true)
{ {
const auto [old, ok] = m_value.fetch_op([](u32& value) const auto [old, ok] = m_value.fetch_op([](u32& value)
{
if (value >= c_sig)
{ {
value -= c_sig; if (value >= c_sig)
return true; {
} value -= c_sig;
return true;
}
return false; return false;
}); });
if (ok) if (ok)
{ {

View file

@ -7,11 +7,11 @@
// Patch utilities specific to PPU code // Patch utilities specific to PPU code
struct ppu_patch_block_registry_t struct ppu_patch_block_registry_t
{ {
ppu_patch_block_registry_t() = default; ppu_patch_block_registry_t() = default;
ppu_patch_block_registry_t(const ppu_patch_block_registry_t&) = delete; ppu_patch_block_registry_t(const ppu_patch_block_registry_t&) = delete;
ppu_patch_block_registry_t& operator=(const ppu_patch_block_registry_t&) = delete; ppu_patch_block_registry_t& operator=(const ppu_patch_block_registry_t&) = delete;
std::unordered_set<u32> block_addresses{}; std::unordered_set<u32> block_addresses{};
}; };
void ppu_register_range(u32 addr, u32 size); void ppu_register_range(u32 addr, u32 size);

View file

@ -33,7 +33,7 @@ struct rXmlDocument
{ {
rXmlDocument(); rXmlDocument();
rXmlDocument(const rXmlDocument& other) = delete; rXmlDocument(const rXmlDocument& other) = delete;
rXmlDocument &operator=(const rXmlDocument& other) = delete; rXmlDocument& operator=(const rXmlDocument& other) = delete;
pugi::xml_parse_result Read(std::string_view data); pugi::xml_parse_result Read(std::string_view data);
virtual std::shared_ptr<rXmlNode> GetRoot(); virtual std::shared_ptr<rXmlNode> GetRoot();

View file

@ -22,26 +22,26 @@ void semaphore_base::imp_wait()
{ {
// Try hard way // Try hard way
const u32 value = m_value.fetch_op([&](u32& value) const u32 value = m_value.fetch_op([&](u32& value)
{
ensure(value != c_waiter_mask); // "semaphore_base: overflow"
if (value & c_value_mask)
{ {
// Obtain signal ensure(value != c_waiter_mask); // "semaphore_base: overflow"
value -= c_value;
if (waits) if (value & c_value_mask)
{ {
// Remove waiter // Obtain signal
value -= c_waiter; value -= c_value;
if (waits)
{
// Remove waiter
value -= c_waiter;
}
} }
} else if (!waits)
else if (!waits) {
{ // Add waiter
// Add waiter value += c_waiter;
value += c_waiter; }
} });
});
if (value & c_value_mask) if (value & c_value_mask)
{ {
@ -67,15 +67,15 @@ bool semaphore_base::try_post(u32 _max)
{ {
// Conditional increment // Conditional increment
const auto [value, ok] = m_value.fetch_op([&](u32& value) const auto [value, ok] = m_value.fetch_op([&](u32& value)
{
if ((value & c_value_mask) <= _max)
{ {
value += c_value; if ((value & c_value_mask) <= _max)
return true; {
} value += c_value;
return true;
}
return false; return false;
}); });
if (!ok) if (!ok)
{ {

View file

@ -42,15 +42,16 @@ protected:
bool try_wait() bool try_wait()
{ {
return m_value.fetch_op([](u32& value) return m_value.fetch_op([](u32& value)
{ {
if (value & c_value_mask) if (value & c_value_mask)
{ {
value -= c_value; value -= c_value;
return true; return true;
} }
return false; return false;
}).second; })
.second;
} }
void post(u32 _max) void post(u32 _max)

View file

@ -30,7 +30,8 @@ simple_ringbuf::simple_ringbuf(const simple_ringbuf& other)
simple_ringbuf& simple_ringbuf::operator=(const simple_ringbuf& other) simple_ringbuf& simple_ringbuf::operator=(const simple_ringbuf& other)
{ {
if (this == &other) return *this; if (this == &other)
return *this;
ctr_state old = other.rw_ptr.load(); ctr_state old = other.rw_ptr.load();
@ -61,7 +62,8 @@ simple_ringbuf::simple_ringbuf(simple_ringbuf&& other)
simple_ringbuf& simple_ringbuf::operator=(simple_ringbuf&& other) simple_ringbuf& simple_ringbuf::operator=(simple_ringbuf&& other)
{ {
if (this == &other) return *this; if (this == &other)
return *this;
const ctr_state other_rw_ptr = other.rw_ptr.load(); const ctr_state other_rw_ptr = other.rw_ptr.load();
buf = std::move(other.buf); buf = std::move(other.buf);
@ -117,20 +119,21 @@ void simple_ringbuf::set_buf_size(u64 size)
void simple_ringbuf::writer_flush(u64 cnt) void simple_ringbuf::writer_flush(u64 cnt)
{ {
rw_ptr.atomic_op([&](ctr_state& val) rw_ptr.atomic_op([&](ctr_state& val)
{ {
const u64 used = get_used_size(val); const u64 used = get_used_size(val);
if (used == 0) return; if (used == 0)
return;
val.write_ptr += buf.size() - std::min<u64>(used, cnt); val.write_ptr += buf.size() - std::min<u64>(used, cnt);
}); });
} }
void simple_ringbuf::reader_flush(u64 cnt) void simple_ringbuf::reader_flush(u64 cnt)
{ {
rw_ptr.atomic_op([&](ctr_state& val) rw_ptr.atomic_op([&](ctr_state& val)
{ {
val.read_ptr += std::min(get_used_size(val), cnt); val.read_ptr += std::min(get_used_size(val), cnt);
}); });
} }
u64 simple_ringbuf::push(const void* data, u64 size, bool force) u64 simple_ringbuf::push(const void* data, u64 size, bool force)
@ -138,33 +141,33 @@ u64 simple_ringbuf::push(const void* data, u64 size, bool force)
ensure(data != nullptr); ensure(data != nullptr);
return rw_ptr.atomic_op([&](ctr_state& val) -> u64 return rw_ptr.atomic_op([&](ctr_state& val) -> u64
{
const u64 buf_size = buf.size();
const u64 old = val.write_ptr % buf_size;
const u64 free_size = get_free_size(val);
const u64 to_push = std::min(size, free_size);
const auto b_data = static_cast<const u8*>(data);
if (!to_push || (!force && free_size < size))
{ {
return 0; const u64 buf_size = buf.size();
} const u64 old = val.write_ptr % buf_size;
const u64 free_size = get_free_size(val);
const u64 to_push = std::min(size, free_size);
const auto b_data = static_cast<const u8*>(data);
if (old + to_push > buf_size) if (!to_push || (!force && free_size < size))
{ {
const auto first_write_sz = buf_size - old; return 0;
memcpy(&buf[old], b_data, first_write_sz); }
memcpy(&buf[0], b_data + first_write_sz, to_push - first_write_sz);
}
else
{
memcpy(&buf[old], b_data, to_push);
}
val.write_ptr += to_push; if (old + to_push > buf_size)
{
const auto first_write_sz = buf_size - old;
memcpy(&buf[old], b_data, first_write_sz);
memcpy(&buf[0], b_data + first_write_sz, to_push - first_write_sz);
}
else
{
memcpy(&buf[old], b_data, to_push);
}
return to_push; val.write_ptr += to_push;
});
return to_push;
});
} }
u64 simple_ringbuf::pop(void* data, u64 size, bool force) u64 simple_ringbuf::pop(void* data, u64 size, bool force)
@ -172,31 +175,31 @@ u64 simple_ringbuf::pop(void* data, u64 size, bool force)
ensure(data != nullptr); ensure(data != nullptr);
return rw_ptr.atomic_op([&](ctr_state& val) -> u64 return rw_ptr.atomic_op([&](ctr_state& val) -> u64
{
const u64 buf_size = buf.size();
const u64 old = val.read_ptr % buf_size;
const u64 used_size = get_used_size(val);
const u64 to_pop = std::min(size, used_size);
const auto b_data = static_cast<u8*>(data);
if (!to_pop || (!force && used_size < size))
{ {
return 0; const u64 buf_size = buf.size();
} const u64 old = val.read_ptr % buf_size;
const u64 used_size = get_used_size(val);
const u64 to_pop = std::min(size, used_size);
const auto b_data = static_cast<u8*>(data);
if (old + to_pop > buf_size) if (!to_pop || (!force && used_size < size))
{ {
const auto first_read_sz = buf_size - old; return 0;
memcpy(b_data, &buf[old], first_read_sz); }
memcpy(b_data + first_read_sz, &buf[0], to_pop - first_read_sz);
}
else
{
memcpy(b_data, &buf[old], to_pop);
}
val.read_ptr += to_pop; if (old + to_pop > buf_size)
{
const auto first_read_sz = buf_size - old;
memcpy(b_data, &buf[old], first_read_sz);
memcpy(b_data + first_read_sz, &buf[0], to_pop - first_read_sz);
}
else
{
memcpy(b_data, &buf[old], to_pop);
}
return to_pop; val.read_ptr += to_pop;
});
return to_pop;
});
} }

View file

@ -8,7 +8,6 @@
class simple_ringbuf class simple_ringbuf
{ {
public: public:
simple_ringbuf(u64 size = 0); simple_ringbuf(u64 size = 0);
virtual ~simple_ringbuf(); virtual ~simple_ringbuf();
@ -34,11 +33,10 @@ public:
void reader_flush(u64 cnt = umax); void reader_flush(u64 cnt = umax);
private: private:
struct ctr_state struct ctr_state
{ {
alignas(sizeof(u64) * 2) alignas(sizeof(u64) * 2)
u64 read_ptr = 0; u64 read_ptr = 0;
u64 write_ptr = 0; u64 write_ptr = 0;
auto operator<=>(const ctr_state& other) const = default; auto operator<=>(const ctr_state& other) const = default;

View file

@ -3,7 +3,7 @@
#ifdef _WIN32 #ifdef _WIN32
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <Windows.h> #include <windows.h>
#define DBGHELP_TRANSLATE_TCHAR #define DBGHELP_TRANSLATE_TCHAR
#include <DbgHelp.h> #include <DbgHelp.h>
#include <codecvt> #include <codecvt>
@ -57,15 +57,15 @@ namespace utils
while (max_depth--) while (max_depth--)
{ {
if (!StackWalk64( if (!StackWalk64(
IMAGE_FILE_MACHINE_AMD64, IMAGE_FILE_MACHINE_AMD64,
hProcess, hProcess,
hThread, hThread,
&stack, &stack,
&context, &context,
NULL, NULL,
SymFunctionTableAccess64, SymFunctionTableAccess64,
SymGetModuleBase64, SymGetModuleBase64,
NULL)) NULL))
{ {
break; break;
} }
@ -150,4 +150,4 @@ namespace utils
return result; return result;
} }
#endif #endif
} } // namespace utils

View file

@ -9,8 +9,7 @@ namespace utils
// Printing utilities // Printing utilities
template <typename T> template <typename T>
concept Logger = requires (T& t, const std::string& msg) concept Logger = requires(T& t, const std::string& msg) {
{
{ t.print(msg) }; { t.print(msg) };
}; };
@ -21,14 +20,15 @@ namespace utils
public: public:
print_to_log(logs::channel& chan) print_to_log(logs::channel& chan)
: log(chan) : log(chan)
{} {
}
void print(const std::string& s) void print(const std::string& s)
{ {
log.error("%s", s); log.error("%s", s);
} }
}; };
} } // namespace stack_trace
std::vector<void*> get_backtrace(int max_depth = 255); std::vector<void*> get_backtrace(int max_depth = 255);
std::vector<std::string> get_backtrace_symbols(const std::vector<void*>& stack); std::vector<std::string> get_backtrace_symbols(const std::vector<void*>& stack);
@ -43,4 +43,4 @@ namespace utils
logger.print(line); logger.print(line);
} }
} }
} } // namespace utils

View file

@ -9,7 +9,7 @@
#ifndef NOMINMAX #ifndef NOMINMAX
#define NOMINMAX #define NOMINMAX
#endif #endif
#include <Windows.h> #include <windows.h>
#include <ctime> #include <ctime>
#elif __linux__ #elif __linux__
#include <sys/syscall.h> #include <sys/syscall.h>
@ -20,12 +20,18 @@
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
#if !defined(NTSTATUS)
typedef _Return_type_success_(return >= 0) LONG NTSTATUS;
#endif
#ifndef __GNUC__
DYNAMIC_IMPORT("ntdll.dll", NtWaitForKeyedEvent, NTSTATUS(HANDLE, PVOID Key, BOOLEAN Alertable, PLARGE_INTEGER Timeout)); DYNAMIC_IMPORT("ntdll.dll", NtWaitForKeyedEvent, NTSTATUS(HANDLE, PVOID Key, BOOLEAN Alertable, PLARGE_INTEGER Timeout));
DYNAMIC_IMPORT("ntdll.dll", NtReleaseKeyedEvent, NTSTATUS(HANDLE, PVOID Key, BOOLEAN Alertable, PLARGE_INTEGER Timeout)); DYNAMIC_IMPORT("ntdll.dll", NtReleaseKeyedEvent, NTSTATUS(HANDLE, PVOID Key, BOOLEAN Alertable, PLARGE_INTEGER Timeout));
DYNAMIC_IMPORT("ntdll.dll", NtWaitForSingleObject, NTSTATUS(HANDLE Handle, BOOLEAN Alertable, PLARGE_INTEGER Timeout)); DYNAMIC_IMPORT("ntdll.dll", NtWaitForSingleObject, NTSTATUS(HANDLE Handle, BOOLEAN Alertable, PLARGE_INTEGER Timeout));
DYNAMIC_IMPORT("ntdll.dll", NtDelayExecution, NTSTATUS(BOOLEAN Alertable, PLARGE_INTEGER DelayInterval)); DYNAMIC_IMPORT("ntdll.dll", NtDelayExecution, NTSTATUS(BOOLEAN Alertable, PLARGE_INTEGER DelayInterval));
DYNAMIC_IMPORT("ntdll.dll", NtWaitForAlertByThreadId, NTSTATUS(PVOID Address, PLARGE_INTEGER Timeout)); DYNAMIC_IMPORT("ntdll.dll", NtWaitForAlertByThreadId, NTSTATUS(PVOID Address, PLARGE_INTEGER Timeout));
DYNAMIC_IMPORT("ntdll.dll", NtAlertThreadByThreadId, NTSTATUS(DWORD_PTR ThreadId)); DYNAMIC_IMPORT("ntdll.dll", NtAlertThreadByThreadId, NTSTATUS(DWORD_PTR ThreadId));
#endif
constexpr NTSTATUS NTSTATUS_SUCCESS = 0; constexpr NTSTATUS NTSTATUS_SUCCESS = 0;
constexpr NTSTATUS NTSTATUS_ALERTED = 0x101; constexpr NTSTATUS NTSTATUS_ALERTED = 0x101;
@ -81,9 +87,9 @@ inline int futex(volatile void* uaddr, int futex_op, uint val, const timespec* t
{ {
struct waiter struct waiter
{ {
uint val; uint val;
uint mask; uint mask;
std::condition_variable cv; std::condition_variable cv;
}; };
std::mutex mutex; std::mutex mutex;

View file

@ -7,7 +7,6 @@
class universal_pool class universal_pool
{ {
public: public:
universal_pool(u32 gc_interval = 10000) : gc_interval(gc_interval) universal_pool(u32 gc_interval = 10000) : gc_interval(gc_interval)
{ {
} }
@ -27,7 +26,7 @@ public:
} }
template <typename F> template <typename F>
requires (std::invocable<F&> && std::is_same_v<std::invoke_result_t<F&>, std::shared_ptr<void>>) requires(std::invocable<F&> && std::is_same_v<std::invoke_result_t<F&>, std::shared_ptr<void>>)
void add_op(F func) void add_op(F func)
{ {
std::lock_guard lock(mutex); std::lock_guard lock(mutex);
@ -45,7 +44,6 @@ public:
} }
private: private:
void delete_unused() void delete_unused()
{ {
const u32 gc_int = gc_interval.observe(); const u32 gc_int = gc_interval.observe();
@ -53,11 +51,12 @@ private:
if (u64 crnt_time = get_system_time(); gc_int == 0 || crnt_time > gc_last_time + gc_int) if (u64 crnt_time = get_system_time(); gc_int == 0 || crnt_time > gc_last_time + gc_int)
{ {
gc_last_time = crnt_time; gc_last_time = crnt_time;
storage.erase storage.erase(
( std::remove_if(storage.begin(), storage.end(), [](auto& obj)
std::remove_if(storage.begin(), storage.end(), [](auto& obj) { return obj.use_count() <= 1; }), {
storage.end() return obj.use_count() <= 1;
); }),
storage.end());
} }
} }
@ -67,11 +66,10 @@ private:
atomic_t<u32> gc_interval = 0; atomic_t<u32> gc_interval = 0;
}; };
template<typename T> template <typename T>
class transactional_storage class transactional_storage
{ {
public: public:
transactional_storage(std::shared_ptr<universal_pool> pool, std::shared_ptr<T> obj = std::make_shared<T>()) transactional_storage(std::shared_ptr<universal_pool> pool, std::shared_ptr<T> obj = std::make_shared<T>())
{ {
ensure(pool && obj); ensure(pool && obj);
@ -98,7 +96,8 @@ public:
transactional_storage& operator=(transactional_storage&& other) transactional_storage& operator=(transactional_storage&& other)
{ {
if (this == &other) return *this; if (this == &other)
return *this;
pool = std::move(other.pool); pool = std::move(other.pool);
@ -127,33 +126,32 @@ public:
} }
pool->add_op([&]() -> std::shared_ptr<void> pool->add_op([&]() -> std::shared_ptr<void>
{
{ {
std::lock_guard lock{current_mutex}; {
current = obj; std::lock_guard lock{current_mutex};
} current = obj;
return std::move(obj); }
}); return std::move(obj);
});
} }
template <typename F> template <typename F>
requires (std::invocable<F&> && std::is_same_v<std::invoke_result_t<F&>, std::shared_ptr<T>>) requires(std::invocable<F&> && std::is_same_v<std::invoke_result_t<F&>, std::shared_ptr<T>>)
void add_op(F func) void add_op(F func)
{ {
pool->add_op([&]() -> std::shared_ptr<void> pool->add_op([&]() -> std::shared_ptr<void>
{
std::shared_ptr<T> obj = std::invoke(func);
if (obj)
{ {
std::lock_guard lock{current_mutex}; std::shared_ptr<T> obj = std::invoke(func);
current = obj; if (obj)
} {
return obj; std::lock_guard lock{current_mutex};
}); current = obj;
}
return obj;
});
} }
private: private:
shared_mutex current_mutex{}; shared_mutex current_mutex{};
std::shared_ptr<T> current{}; std::shared_ptr<T> current{};
std::shared_ptr<universal_pool> pool{}; std::shared_ptr<universal_pool> pool{};

View file

@ -99,4 +99,4 @@ namespace utils
return 0; return 0;
} }
} } // namespace utils

View file

@ -27,12 +27,7 @@ namespace utils
public: public:
constexpr version(uint hi, uint mid, uint lo, version_type type, uint type_index, const char* postfix) constexpr version(uint hi, uint mid, uint lo, version_type type, uint type_index, const char* postfix)
: m_hi(hi) : m_hi(hi), m_mid(mid), m_lo(lo), m_type(type), m_type_index(type_index), m_postfix(postfix)
, m_mid(mid)
, m_lo(lo)
, m_type(type)
, m_type_index(type_index)
, m_postfix(postfix)
{ {
} }
@ -72,4 +67,4 @@ namespace utils
// Generic version comparison (e.g. 0.0.5 vs 1.3) // Generic version comparison (e.g. 0.0.5 vs 1.3)
int compare_versions(const std::string& v1, const std::string& v2, bool& ok); int compare_versions(const std::string& v1, const std::string& v2, bool& ok);
} } // namespace utils

View file

@ -29,8 +29,11 @@
std::string to_hex(std::uint64_t value, bool prfx = true) std::string to_hex(std::uint64_t value, bool prfx = true)
{ {
char buf[20]{}, *ptr = buf + 19; char buf[20]{}, *ptr = buf + 19;
do *--ptr = "0123456789abcdef"[value % 16], value /= 16; while (value); do
if (!prfx) return ptr; *--ptr = "0123456789abcdef"[value % 16], value /= 16;
while (value);
if (!prfx)
return ptr;
*--ptr = 'x'; *--ptr = 'x';
*--ptr = '0'; *--ptr = '0';
return ptr; return ptr;
@ -200,7 +203,9 @@ int main(int argc, char* argv[])
} }
else else
{ {
while ((dup2(fds[1], STDOUT_FILENO) == -1) && (errno == EINTR)) {} while ((dup2(fds[1], STDOUT_FILENO) == -1) && (errno == EINTR))
{
}
close(fds[1]); close(fds[1]);
close(fds[0]); close(fds[0]);
// Fallthrough // Fallthrough

File diff suppressed because it is too large Load diff

View file

@ -35,11 +35,11 @@ typedef UINT32 uint32_t;
#include <inttypes.h> #include <inttypes.h>
#endif #endif
#define AES_ENCRYPT 1 #define AES_ENCRYPT 1
#define AES_DECRYPT 0 #define AES_DECRYPT 0
#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ #define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ #define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
// Regular implementation // Regular implementation
// //
@ -49,130 +49,130 @@ typedef UINT32 uint32_t;
*/ */
typedef struct typedef struct
{ {
int nr; /*!< number of rounds */ int nr; /*!< number of rounds */
uint32_t *rk; /*!< AES round keys */ uint32_t* rk; /*!< AES round keys */
uint32_t buf[68]; /*!< unaligned data */ uint32_t buf[68]; /*!< unaligned data */
} } aes_context;
aes_context;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
/** /**
* \brief AES key schedule (encryption) * \brief AES key schedule (encryption)
* *
* \param ctx AES context to be initialized * \param ctx AES context to be initialized
* \param key encryption key * \param key encryption key
* \param keysize must be 128, 192 or 256 * \param keysize must be 128, 192 or 256
* *
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
*/ */
int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize ); int aes_setkey_enc(aes_context* ctx, const unsigned char* key, unsigned int keysize);
/** /**
* \brief AES key schedule (decryption) * \brief AES key schedule (decryption)
* *
* \param ctx AES context to be initialized * \param ctx AES context to be initialized
* \param key decryption key * \param key decryption key
* \param keysize must be 128, 192 or 256 * \param keysize must be 128, 192 or 256
* *
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
*/ */
int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize ); int aes_setkey_dec(aes_context* ctx, const unsigned char* key, unsigned int keysize);
/** /**
* \brief AES-ECB block encryption/decryption * \brief AES-ECB block encryption/decryption
* *
* \param ctx AES context * \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT * \param mode AES_ENCRYPT or AES_DECRYPT
* \param input 16-byte input block * \param input 16-byte input block
* \param output 16-byte output block * \param output 16-byte output block
* *
* \return 0 if successful * \return 0 if successful
*/ */
int aes_crypt_ecb( aes_context *ctx, int aes_crypt_ecb(aes_context* ctx,
int mode, int mode,
const unsigned char input[16], const unsigned char input[16],
unsigned char output[16] ); unsigned char output[16]);
/** /**
* \brief AES-CBC buffer encryption/decryption * \brief AES-CBC buffer encryption/decryption
* Length should be a multiple of the block * Length should be a multiple of the block
* size (16 bytes) * size (16 bytes)
* *
* \param ctx AES context * \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT * \param mode AES_ENCRYPT or AES_DECRYPT
* \param length length of the input data * \param length length of the input data
* \param iv initialization vector (updated after use) * \param iv initialization vector (updated after use)
* \param input buffer holding the input data * \param input buffer holding the input data
* \param output buffer holding the output data * \param output buffer holding the output data
* *
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH
*/ */
int aes_crypt_cbc( aes_context *ctx, int aes_crypt_cbc(aes_context* ctx,
int mode, int mode,
size_t length, size_t length,
unsigned char iv[16], unsigned char iv[16],
const unsigned char *input, const unsigned char* input,
unsigned char *output ); unsigned char* output);
/** /**
* \brief AES-CFB128 buffer encryption/decryption. * \brief AES-CFB128 buffer encryption/decryption.
* *
* Note: Due to the nature of CFB you should use the same key schedule for * Note: Due to the nature of CFB you should use the same key schedule for
* both encryption and decryption. So a context initialized with * both encryption and decryption. So a context initialized with
* aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT. * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
* *
* both * both
* \param ctx AES context * \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT * \param mode AES_ENCRYPT or AES_DECRYPT
* \param length length of the input data * \param length length of the input data
* \param iv_off offset in IV (updated after use) * \param iv_off offset in IV (updated after use)
* \param iv initialization vector (updated after use) * \param iv initialization vector (updated after use)
* \param input buffer holding the input data * \param input buffer holding the input data
* \param output buffer holding the output data * \param output buffer holding the output data
* *
* \return 0 if successful * \return 0 if successful
*/ */
int aes_crypt_cfb128( aes_context *ctx, int aes_crypt_cfb128(aes_context* ctx,
int mode, int mode,
size_t length, size_t length,
size_t *iv_off, size_t* iv_off,
unsigned char iv[16], unsigned char iv[16],
const unsigned char *input, const unsigned char* input,
unsigned char *output ); unsigned char* output);
/** /**
* \brief AES-CTR buffer encryption/decryption * \brief AES-CTR buffer encryption/decryption
* *
* Warning: You have to keep the maximum use of your counter in mind! * Warning: You have to keep the maximum use of your counter in mind!
* *
* Note: Due to the nature of CTR you should use the same key schedule for * Note: Due to the nature of CTR you should use the same key schedule for
* both encryption and decryption. So a context initialized with * both encryption and decryption. So a context initialized with
* aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT. * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
* *
* \param length The length of the data * \param length The length of the data
* \param nc_off The offset in the current stream_block (for resuming * \param nc_off The offset in the current stream_block (for resuming
* within current cipher stream). The offset pointer to * within current cipher stream). The offset pointer to
* should be 0 at the start of a stream. * should be 0 at the start of a stream.
* \param nonce_counter The 128-bit nonce and counter. * \param nonce_counter The 128-bit nonce and counter.
* \param stream_block The saved stream-block for resuming. Is overwritten * \param stream_block The saved stream-block for resuming. Is overwritten
* by the function. * by the function.
* \param input The input data stream * \param input The input data stream
* \param output The output data stream * \param output The output data stream
* *
* \return 0 if successful * \return 0 if successful
*/ */
int aes_crypt_ctr( aes_context *ctx, int aes_crypt_ctr(aes_context* ctx,
size_t length, size_t length,
size_t *nc_off, size_t* nc_off,
unsigned char nonce_counter[16], unsigned char nonce_counter[16],
unsigned char stream_block[16], unsigned char stream_block[16],
const unsigned char *input, const unsigned char* input,
unsigned char *output ); unsigned char* output);
void aes_cmac(aes_context *ctx, size_t length, unsigned char *input, unsigned char *output); void aes_cmac(aes_context* ctx, size_t length, unsigned char* input, unsigned char* output);
#ifdef __cplusplus #ifdef __cplusplus
} }

File diff suppressed because it is too large Load diff

View file

@ -29,74 +29,75 @@
#include "aes.h" #include "aes.h"
#define POLARSSL_AESNI_AES 0x02000000u #define POLARSSL_AESNI_AES 0x02000000u
#define POLARSSL_AESNI_CLMUL 0x00000002u #define POLARSSL_AESNI_CLMUL 0x00000002u
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
/** /**
* \brief AES-NI features detection routine * \brief AES-NI features detection routine
* *
* \param what The feature to detect * \param what The feature to detect
* (POLARSSL_AESNI_AES or POLARSSL_AESNI_CLMUL) * (POLARSSL_AESNI_AES or POLARSSL_AESNI_CLMUL)
* *
* \return 1 if CPU has support for the feature, 0 otherwise * \return 1 if CPU has support for the feature, 0 otherwise
*/ */
int aesni_supports( unsigned int what ); int aesni_supports(unsigned int what);
/** /**
* \brief AES-NI AES-ECB block en(de)cryption * \brief AES-NI AES-ECB block en(de)cryption
* *
* \param ctx AES context * \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT * \param mode AES_ENCRYPT or AES_DECRYPT
* \param input 16-byte input block * \param input 16-byte input block
* \param output 16-byte output block * \param output 16-byte output block
* *
* \return 0 on success (cannot fail) * \return 0 on success (cannot fail)
*/ */
int aesni_crypt_ecb( aes_context *ctx, int aesni_crypt_ecb(aes_context* ctx,
int mode, int mode,
const unsigned char input[16], const unsigned char input[16],
unsigned char output[16] ); unsigned char output[16]);
/** /**
* \brief GCM multiplication: c = a * b in GF(2^128) * \brief GCM multiplication: c = a * b in GF(2^128)
* *
* \param c Result * \param c Result
* \param a First operand * \param a First operand
* \param b Second operand * \param b Second operand
* *
* \note Both operands and result are bit strings interpreted as * \note Both operands and result are bit strings interpreted as
* elements of GF(2^128) as per the GCM spec. * elements of GF(2^128) as per the GCM spec.
*/ */
void aesni_gcm_mult( unsigned char c[16], void aesni_gcm_mult(unsigned char c[16],
const unsigned char a[16], const unsigned char a[16],
const unsigned char b[16] ); const unsigned char b[16]);
/** /**
* \brief Compute decryption round keys from encryption round keys * \brief Compute decryption round keys from encryption round keys
* *
* \param invkey Round keys for the equivalent inverse cipher * \param invkey Round keys for the equivalent inverse cipher
* \param fwdkey Original round keys (for encryption) * \param fwdkey Original round keys (for encryption)
* \param nr Number of rounds (that is, number of round keys minus one) * \param nr Number of rounds (that is, number of round keys minus one)
*/ */
void aesni_inverse_key( unsigned char *invkey, void aesni_inverse_key(unsigned char* invkey,
const unsigned char *fwdkey, int nr ); const unsigned char* fwdkey, int nr);
/** /**
* \brief Perform key expansion (for encryption) * \brief Perform key expansion (for encryption)
* *
* \param rk Destination buffer where the round keys are written * \param rk Destination buffer where the round keys are written
* \param key Encryption key * \param key Encryption key
* \param bits Key size in bits (must be 128, 192 or 256) * \param bits Key size in bits (must be 128, 192 or 256)
* *
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
*/ */
int aesni_setkey_enc( unsigned char *rk, int aesni_setkey_enc(unsigned char* rk,
const unsigned char *key, const unsigned char* key,
size_t bits ); size_t bits);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -139,7 +139,7 @@ usz decrypt_binaries_t::decrypt(std::string_view klic_input)
{ {
const std::string exec_ext = fmt::to_lower(_module).ends_with(".sprx") ? ".prx" : ".elf"; const std::string exec_ext = fmt::to_lower(_module).ends_with(".sprx") ? ".prx" : ".elf";
const std::string new_path = file_magic == "NPD\0"_u32 ? old_path + ".unedat" : const std::string new_path = file_magic == "NPD\0"_u32 ? old_path + ".unedat" :
old_path.substr(0, old_path.find_last_of('.')) + exec_ext; old_path.substr(0, old_path.find_last_of('.')) + exec_ext;
if (fs::file new_file{new_path, fs::rewrite}) if (fs::file new_file{new_path, fs::rewrite})
{ {

View file

@ -2,25 +2,25 @@
class decrypt_binaries_t class decrypt_binaries_t
{ {
std::vector<u128> m_klics; std::vector<u128> m_klics;
std::vector<std::string> m_modules; std::vector<std::string> m_modules;
usz m_index = 0; usz m_index = 0;
public: public:
decrypt_binaries_t(std::vector<std::string> modules) noexcept decrypt_binaries_t(std::vector<std::string> modules) noexcept
: m_modules(std::move(modules)) : m_modules(std::move(modules))
{ {
} }
usz decrypt(std::string_view klic_input = {}); usz decrypt(std::string_view klic_input = {});
bool done() const bool done() const
{ {
return m_index >= m_modules.size(); return m_index >= m_modules.size();
} }
const std::string& operator[](usz index) const const std::string& operator[](usz index) const
{ {
return ::at32(m_modules, index); return ::at32(m_modules, index);
} }
}; };

View file

@ -24,7 +24,7 @@ static u8 bn_add_1(u8* d, const u8* a, const u8* b, u32 n)
for (u32 i = n - 1; i != umax; i--) for (u32 i = n - 1; i != umax; i--)
{ {
const u32 dig = a[i] + b[i] + c; const u32 dig = a[i] + b[i] + c;
c = dig >> 8; c = dig >> 8;
d[i] = dig; d[i] = dig;
} }
@ -37,7 +37,7 @@ static u8 bn_sub_1(u8* d, const u8* a, const u8* b, u32 n)
for (u32 i = n - 1; i != umax; i--) for (u32 i = n - 1; i != umax; i--)
{ {
const u32 dig = a[i] + 255 - b[i] + c; const u32 dig = a[i] + 255 - b[i] + c;
c = dig >> 8; c = dig >> 8;
d[i] = dig; d[i] = dig;
} }
@ -65,22 +65,134 @@ static void bn_sub(u8* d, const u8* a, const u8* b, const u8* N, u32 n)
} }
static constexpr u8 inv256[0x80] = { static constexpr u8 inv256[0x80] = {
0x01, 0xab, 0xcd, 0xb7, 0x39, 0xa3, 0xc5, 0xef, 0x01,
0xf1, 0x1b, 0x3d, 0xa7, 0x29, 0x13, 0x35, 0xdf, 0xab,
0xe1, 0x8b, 0xad, 0x97, 0x19, 0x83, 0xa5, 0xcf, 0xcd,
0xd1, 0xfb, 0x1d, 0x87, 0x09, 0xf3, 0x15, 0xbf, 0xb7,
0xc1, 0x6b, 0x8d, 0x77, 0xf9, 0x63, 0x85, 0xaf, 0x39,
0xb1, 0xdb, 0xfd, 0x67, 0xe9, 0xd3, 0xf5, 0x9f, 0xa3,
0xa1, 0x4b, 0x6d, 0x57, 0xd9, 0x43, 0x65, 0x8f, 0xc5,
0x91, 0xbb, 0xdd, 0x47, 0xc9, 0xb3, 0xd5, 0x7f, 0xef,
0x81, 0x2b, 0x4d, 0x37, 0xb9, 0x23, 0x45, 0x6f, 0xf1,
0x71, 0x9b, 0xbd, 0x27, 0xa9, 0x93, 0xb5, 0x5f, 0x1b,
0x61, 0x0b, 0x2d, 0x17, 0x99, 0x03, 0x25, 0x4f, 0x3d,
0x51, 0x7b, 0x9d, 0x07, 0x89, 0x73, 0x95, 0x3f, 0xa7,
0x41, 0xeb, 0x0d, 0xf7, 0x79, 0xe3, 0x05, 0x2f, 0x29,
0x31, 0x5b, 0x7d, 0xe7, 0x69, 0x53, 0x75, 0x1f, 0x13,
0x21, 0xcb, 0xed, 0xd7, 0x59, 0xc3, 0xe5, 0x0f, 0x35,
0x11, 0x3b, 0x5d, 0xc7, 0x49, 0x33, 0x55, 0xff, 0xdf,
0xe1,
0x8b,
0xad,
0x97,
0x19,
0x83,
0xa5,
0xcf,
0xd1,
0xfb,
0x1d,
0x87,
0x09,
0xf3,
0x15,
0xbf,
0xc1,
0x6b,
0x8d,
0x77,
0xf9,
0x63,
0x85,
0xaf,
0xb1,
0xdb,
0xfd,
0x67,
0xe9,
0xd3,
0xf5,
0x9f,
0xa1,
0x4b,
0x6d,
0x57,
0xd9,
0x43,
0x65,
0x8f,
0x91,
0xbb,
0xdd,
0x47,
0xc9,
0xb3,
0xd5,
0x7f,
0x81,
0x2b,
0x4d,
0x37,
0xb9,
0x23,
0x45,
0x6f,
0x71,
0x9b,
0xbd,
0x27,
0xa9,
0x93,
0xb5,
0x5f,
0x61,
0x0b,
0x2d,
0x17,
0x99,
0x03,
0x25,
0x4f,
0x51,
0x7b,
0x9d,
0x07,
0x89,
0x73,
0x95,
0x3f,
0x41,
0xeb,
0x0d,
0xf7,
0x79,
0xe3,
0x05,
0x2f,
0x31,
0x5b,
0x7d,
0xe7,
0x69,
0x53,
0x75,
0x1f,
0x21,
0xcb,
0xed,
0xd7,
0x59,
0xc3,
0xe5,
0x0f,
0x11,
0x3b,
0x5d,
0xc7,
0x49,
0x33,
0x55,
0xff,
}; };
static void bn_mon_muladd_dig(u8* d, const u8* a, u8 b, const u8* N, u32 n) static void bn_mon_muladd_dig(u8* d, const u8* a, u8 b, const u8* N, u32 n)
@ -384,7 +496,8 @@ static bool check_ecdsa(const struct point* Q, u8* R, u8* S, const u8* hash)
void ecdsa_set_curve(const u8* p, const u8* a, const u8* b, const u8* N, const u8* Gx, const u8* Gy) void ecdsa_set_curve(const u8* p, const u8* a, const u8* b, const u8* N, const u8* Gx, const u8* Gy)
{ {
if (ec_curve_initialized) return; if (ec_curve_initialized)
return;
memcpy(ec_p, p, 20); memcpy(ec_p, p, 20);
memcpy(ec_a, a, 20); memcpy(ec_a, a, 20);
@ -403,7 +516,8 @@ void ecdsa_set_curve(const u8* p, const u8* a, const u8* b, const u8* N, const u
void ecdsa_set_pub(const u8* Q) void ecdsa_set_pub(const u8* Q)
{ {
if (ec_pub_initialized) return; if (ec_pub_initialized)
return;
memcpy(ec_Q.x, Q, 20); memcpy(ec_Q.x, Q, 20);
memcpy(ec_Q.y, Q + 20, 20); memcpy(ec_Q.y, Q + 20, 20);

View file

@ -8,9 +8,9 @@ LOG_CHANNEL(key_vault_log, "KEY_VAULT");
SELF_KEY::SELF_KEY(u64 ver_start, u64 ver_end, u16 rev, u32 type, const std::string& e, const std::string& r, const std::string& pb, const std::string& pr, u32 ct) SELF_KEY::SELF_KEY(u64 ver_start, u64 ver_end, u16 rev, u32 type, const std::string& e, const std::string& r, const std::string& pb, const std::string& pr, u32 ct)
{ {
version_start = ver_start; version_start = ver_start;
version_end = ver_end; version_end = ver_end;
revision = rev; revision = rev;
self_type = type; self_type = type;
hex_to_bytes(erk, e.c_str(), 0); hex_to_bytes(erk, e.c_str(), 0);
hex_to_bytes(riv, r.c_str(), 0); hex_to_bytes(riv, r.c_str(), 0);
hex_to_bytes(pub, pb.c_str(), 0); hex_to_bytes(pub, pb.c_str(), 0);
@ -787,19 +787,19 @@ void rap_to_rif(const unsigned char* rap, unsigned char* rif)
} }
for (i = 15; i >= 1; --i) for (i = 15; i >= 1; --i)
{ {
const int p = RAP_PBOX[i]; const int p = RAP_PBOX[i];
const int pp = RAP_PBOX[i - 1]; const int pp = RAP_PBOX[i - 1];
key[p] ^= key[pp]; key[p] ^= key[pp];
} }
int o = 0; int o = 0;
for (i = 0; i < 16; ++i) for (i = 0; i < 16; ++i)
{ {
const int p = RAP_PBOX[i]; const int p = RAP_PBOX[i];
const unsigned char kc = key[p] - o; const unsigned char kc = key[p] - o;
const unsigned char ec2 = RAP_E2[p]; const unsigned char ec2 = RAP_E2[p];
if (o != 1 || kc != 0xFF) if (o != 1 || kc != 0xFF)
{ {
o = kc < ec2 ? 1 : 0; o = kc < ec2 ? 1 : 0;
key[p] = kc - ec2; key[p] = kc - ec2;
} }
else if (kc == 0xFF) else if (kc == 0xFF)

View file

@ -65,153 +65,118 @@ constexpr u8 SC_ISO_SERIES_INTERNAL_KEY_3[PASSPHRASE_KEY_LEN] = {
}; };
constexpr u8 PKG_AES_KEY_IDU[0x10] = { constexpr u8 PKG_AES_KEY_IDU[0x10] = {
0x5d, 0xb9, 0x11, 0xe6, 0xb7, 0xe5, 0x0a, 0x7d, 0x32, 0x15, 0x38, 0xfd, 0x7c, 0x66, 0xf1, 0x7b 0x5d, 0xb9, 0x11, 0xe6, 0xb7, 0xe5, 0x0a, 0x7d, 0x32, 0x15, 0x38, 0xfd, 0x7c, 0x66, 0xf1, 0x7b};
};
constexpr u8 PKG_AES_KEY[0x10] = { constexpr u8 PKG_AES_KEY[0x10] = {
0x2e, 0x7b, 0x71, 0xd7, 0xc9, 0xc9, 0xa1, 0x4e, 0xa3, 0x22, 0x1f, 0x18, 0x88, 0x28, 0xb8, 0xf8 0x2e, 0x7b, 0x71, 0xd7, 0xc9, 0xc9, 0xa1, 0x4e, 0xa3, 0x22, 0x1f, 0x18, 0x88, 0x28, 0xb8, 0xf8};
};
constexpr u8 PKG_AES_KEY2[0x10] = { constexpr u8 PKG_AES_KEY2[0x10] = {
0x07, 0xf2, 0xc6, 0x82, 0x90, 0xb5, 0x0d, 0x2c, 0x33, 0x81, 0x8d, 0x70, 0x9b, 0x60, 0xe6, 0x2b 0x07, 0xf2, 0xc6, 0x82, 0x90, 0xb5, 0x0d, 0x2c, 0x33, 0x81, 0x8d, 0x70, 0x9b, 0x60, 0xe6, 0x2b};
};
constexpr u8 PKG_AES_KEY_VITA_1[0x10] = { constexpr u8 PKG_AES_KEY_VITA_1[0x10] = {
0xE3, 0x1A, 0x70, 0xC9, 0xCE, 0x1D, 0xD7, 0x2B, 0xF3, 0xC0, 0x62, 0x29, 0x63, 0xF2, 0xEC, 0xCB 0xE3, 0x1A, 0x70, 0xC9, 0xCE, 0x1D, 0xD7, 0x2B, 0xF3, 0xC0, 0x62, 0x29, 0x63, 0xF2, 0xEC, 0xCB};
};
constexpr u8 PKG_AES_KEY_VITA_2[0x10] = { constexpr u8 PKG_AES_KEY_VITA_2[0x10] = {
0x42, 0x3A, 0xCA, 0x3A, 0x2B, 0xD5, 0x64, 0x9F, 0x96, 0x86, 0xAB, 0xAD, 0x6F, 0xD8, 0x80, 0x1F 0x42, 0x3A, 0xCA, 0x3A, 0x2B, 0xD5, 0x64, 0x9F, 0x96, 0x86, 0xAB, 0xAD, 0x6F, 0xD8, 0x80, 0x1F};
};
constexpr u8 PKG_AES_KEY_VITA_3[0x10] = { constexpr u8 PKG_AES_KEY_VITA_3[0x10] = {
0xAF, 0x07, 0xFD, 0x59, 0x65, 0x25, 0x27, 0xBA, 0xF1, 0x33, 0x89, 0x66, 0x8B, 0x17, 0xD9, 0xEA 0xAF, 0x07, 0xFD, 0x59, 0x65, 0x25, 0x27, 0xBA, 0xF1, 0x33, 0x89, 0x66, 0x8B, 0x17, 0xD9, 0xEA};
};
constexpr u8 NP_IDPS[0x10] = { constexpr u8 NP_IDPS[0x10] = {
0x5E, 0x06, 0xE0, 0x4F, 0xD9, 0x4A, 0x71, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 0x5E, 0x06, 0xE0, 0x4F, 0xD9, 0x4A, 0x71, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
};
constexpr u8 NP_KLIC_FREE[0x10] = { constexpr u8 NP_KLIC_FREE[0x10] = {
0x72, 0xF9, 0x90, 0x78, 0x8F, 0x9C, 0xFF, 0x74, 0x57, 0x25, 0xF0, 0x8E, 0x4C, 0x12, 0x83, 0x87 0x72, 0xF9, 0x90, 0x78, 0x8F, 0x9C, 0xFF, 0x74, 0x57, 0x25, 0xF0, 0x8E, 0x4C, 0x12, 0x83, 0x87};
};
constexpr u8 NP_OMAC_KEY_2[0x10] = { constexpr u8 NP_OMAC_KEY_2[0x10] = {
0x6B, 0xA5, 0x29, 0x76, 0xEF, 0xDA, 0x16, 0xEF, 0x3C, 0x33, 0x9F, 0xB2, 0x97, 0x1E, 0x25, 0x6B 0x6B, 0xA5, 0x29, 0x76, 0xEF, 0xDA, 0x16, 0xEF, 0x3C, 0x33, 0x9F, 0xB2, 0x97, 0x1E, 0x25, 0x6B};
};
constexpr u8 NP_OMAC_KEY_3[0x10] = { constexpr u8 NP_OMAC_KEY_3[0x10] = {
0x9B, 0x51, 0x5F, 0xEA, 0xCF, 0x75, 0x06, 0x49, 0x81, 0xAA, 0x60, 0x4D, 0x91, 0xA5, 0x4E, 0x97 0x9B, 0x51, 0x5F, 0xEA, 0xCF, 0x75, 0x06, 0x49, 0x81, 0xAA, 0x60, 0x4D, 0x91, 0xA5, 0x4E, 0x97};
};
constexpr u8 NP_KLIC_KEY[0x10] = { constexpr u8 NP_KLIC_KEY[0x10] = {
0xF2, 0xFB, 0xCA, 0x7A, 0x75, 0xB0, 0x4E, 0xDC, 0x13, 0x90, 0x63, 0x8C, 0xCD, 0xFD, 0xD1, 0xEE 0xF2, 0xFB, 0xCA, 0x7A, 0x75, 0xB0, 0x4E, 0xDC, 0x13, 0x90, 0x63, 0x8C, 0xCD, 0xFD, 0xD1, 0xEE};
};
constexpr u8 NP_RIF_KEY[0x10] = { constexpr u8 NP_RIF_KEY[0x10] = {
0xDA, 0x7D, 0x4B, 0x5E, 0x49, 0x9A, 0x4F, 0x53, 0xB1, 0xC1, 0xA1, 0x4A, 0x74, 0x84, 0x44, 0x3B 0xDA, 0x7D, 0x4B, 0x5E, 0x49, 0x9A, 0x4F, 0x53, 0xB1, 0xC1, 0xA1, 0x4A, 0x74, 0x84, 0x44, 0x3B};
};
// PSP Minis // PSP Minis
constexpr u8 NP_PSP_KEY_1[0x10] = { constexpr u8 NP_PSP_KEY_1[0x10] = {
0x2A, 0x6A, 0xFB, 0xCF, 0x43, 0xD1, 0x57, 0x9F, 0x7D, 0x73, 0x87, 0x41, 0xA1, 0x3B, 0xD4, 0x2E 0x2A, 0x6A, 0xFB, 0xCF, 0x43, 0xD1, 0x57, 0x9F, 0x7D, 0x73, 0x87, 0x41, 0xA1, 0x3B, 0xD4, 0x2E};
};
// PSP Remasters // PSP Remasters
constexpr u8 NP_PSP_KEY_2[0x10] = { constexpr u8 NP_PSP_KEY_2[0x10] = {
0x0D, 0xB8, 0x57, 0x32, 0x36, 0x6C, 0xD7, 0x34, 0xFC, 0x87, 0x9E, 0x74, 0x33, 0x43, 0xBB, 0x4F 0x0D, 0xB8, 0x57, 0x32, 0x36, 0x6C, 0xD7, 0x34, 0xFC, 0x87, 0x9E, 0x74, 0x33, 0x43, 0xBB, 0x4F};
};
constexpr u8 NP_PSX_KEY[0x10] = { constexpr u8 NP_PSX_KEY[0x10] = {
0x52, 0xC0, 0xB5, 0xCA, 0x76, 0xD6, 0x13, 0x4B, 0xB4, 0x5F, 0xC6, 0x6C, 0xA6, 0x37, 0xF2, 0xC1 0x52, 0xC0, 0xB5, 0xCA, 0x76, 0xD6, 0x13, 0x4B, 0xB4, 0x5F, 0xC6, 0x6C, 0xA6, 0x37, 0xF2, 0xC1};
};
constexpr u8 RAP_KEY[0x10] = { constexpr u8 RAP_KEY[0x10] = {
0x86, 0x9F, 0x77, 0x45, 0xC1, 0x3F, 0xD8, 0x90, 0xCC, 0xF2, 0x91, 0x88, 0xE3, 0xCC, 0x3E, 0xDF 0x86, 0x9F, 0x77, 0x45, 0xC1, 0x3F, 0xD8, 0x90, 0xCC, 0xF2, 0x91, 0x88, 0xE3, 0xCC, 0x3E, 0xDF};
};
constexpr u8 RAP_PBOX[0x10] = { constexpr u8 RAP_PBOX[0x10] = {
0x0C, 0x03, 0x06, 0x04, 0x01, 0x0B, 0x0F, 0x08, 0x02, 0x07, 0x00, 0x05, 0x0A, 0x0E, 0x0D, 0x09 0x0C, 0x03, 0x06, 0x04, 0x01, 0x0B, 0x0F, 0x08, 0x02, 0x07, 0x00, 0x05, 0x0A, 0x0E, 0x0D, 0x09};
};
constexpr u8 RAP_E1[0x10] = { constexpr u8 RAP_E1[0x10] = {
0xA9, 0x3E, 0x1F, 0xD6, 0x7C, 0x55, 0xA3, 0x29, 0xB7, 0x5F, 0xDD, 0xA6, 0x2A, 0x95, 0xC7, 0xA5 0xA9, 0x3E, 0x1F, 0xD6, 0x7C, 0x55, 0xA3, 0x29, 0xB7, 0x5F, 0xDD, 0xA6, 0x2A, 0x95, 0xC7, 0xA5};
};
constexpr u8 RAP_E2[0x10] = { constexpr u8 RAP_E2[0x10] = {
0x67, 0xD4, 0x5D, 0xA3, 0x29, 0x6D, 0x00, 0x6A, 0x4E, 0x7C, 0x53, 0x7B, 0xF5, 0x53, 0x8C, 0x74 0x67, 0xD4, 0x5D, 0xA3, 0x29, 0x6D, 0x00, 0x6A, 0x4E, 0x7C, 0x53, 0x7B, 0xF5, 0x53, 0x8C, 0x74};
};
constexpr u8 SDAT_KEY[0x10] = { constexpr u8 SDAT_KEY[0x10] = {
0x0D, 0x65, 0x5E, 0xF8, 0xE6, 0x74, 0xA9, 0x8A, 0xB8, 0x50, 0x5C, 0xFA, 0x7D, 0x01, 0x29, 0x33 0x0D, 0x65, 0x5E, 0xF8, 0xE6, 0x74, 0xA9, 0x8A, 0xB8, 0x50, 0x5C, 0xFA, 0x7D, 0x01, 0x29, 0x33};
};
constexpr u8 EDAT_KEY_0[0x10] = { constexpr u8 EDAT_KEY_0[0x10] = {
0xBE, 0x95, 0x9C, 0xA8, 0x30, 0x8D, 0xEF, 0xA2, 0xE5, 0xE1, 0x80, 0xC6, 0x37, 0x12, 0xA9, 0xAE 0xBE, 0x95, 0x9C, 0xA8, 0x30, 0x8D, 0xEF, 0xA2, 0xE5, 0xE1, 0x80, 0xC6, 0x37, 0x12, 0xA9, 0xAE};
};
constexpr u8 EDAT_HASH_0[0x10] = { constexpr u8 EDAT_HASH_0[0x10] = {
0xEF, 0xFE, 0x5B, 0xD1, 0x65, 0x2E, 0xEB, 0xC1, 0x19, 0x18, 0xCF, 0x7C, 0x04, 0xD4, 0xF0, 0x11 0xEF, 0xFE, 0x5B, 0xD1, 0x65, 0x2E, 0xEB, 0xC1, 0x19, 0x18, 0xCF, 0x7C, 0x04, 0xD4, 0xF0, 0x11};
};
constexpr u8 EDAT_KEY_1[0x10] = { constexpr u8 EDAT_KEY_1[0x10] = {
0x4C, 0xA9, 0xC1, 0x4B, 0x01, 0xC9, 0x53, 0x09, 0x96, 0x9B, 0xEC, 0x68, 0xAA, 0x0B, 0xC0, 0x81 0x4C, 0xA9, 0xC1, 0x4B, 0x01, 0xC9, 0x53, 0x09, 0x96, 0x9B, 0xEC, 0x68, 0xAA, 0x0B, 0xC0, 0x81};
};
constexpr u8 EDAT_HASH_1[0x10] = { constexpr u8 EDAT_HASH_1[0x10] = {
0x3D, 0x92, 0x69, 0x9B, 0x70, 0x5B, 0x07, 0x38, 0x54, 0xD8, 0xFC, 0xC6, 0xC7, 0x67, 0x27, 0x47 0x3D, 0x92, 0x69, 0x9B, 0x70, 0x5B, 0x07, 0x38, 0x54, 0xD8, 0xFC, 0xC6, 0xC7, 0x67, 0x27, 0x47};
};
constexpr u8 EDAT_IV[0x10] = { constexpr u8 EDAT_IV[0x10] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
};
constexpr u8 VSH_CURVE_P[0x14] = { constexpr u8 VSH_CURVE_P[0x14] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
};
constexpr u8 VSH_CURVE_A[0x14] = { constexpr u8 VSH_CURVE_A[0x14] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC};
};
constexpr u8 VSH_CURVE_B[0x14] = { constexpr u8 VSH_CURVE_B[0x14] = {
0xA6, 0x8B, 0xED, 0xC3, 0x34, 0x18, 0x02, 0x9C, 0x1D, 0x3C, 0xE3, 0x3B, 0x9A, 0x32, 0x1F, 0xCC, 0xBB, 0x9E, 0x0F, 0x0B 0xA6, 0x8B, 0xED, 0xC3, 0x34, 0x18, 0x02, 0x9C, 0x1D, 0x3C, 0xE3, 0x3B, 0x9A, 0x32, 0x1F, 0xCC, 0xBB, 0x9E, 0x0F, 0x0B};
};
constexpr u8 VSH_CURVE_N[0x15] = { constexpr u8 VSH_CURVE_N[0x15] = {
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xB5, 0xAE, 0x3C, 0x52, 0x3E, 0x63, 0x94, 0x4F, 0x21, 0x27 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xB5, 0xAE, 0x3C, 0x52, 0x3E, 0x63, 0x94, 0x4F, 0x21, 0x27};
};
constexpr u8 VSH_CURVE_GX[0x14] = { constexpr u8 VSH_CURVE_GX[0x14] = {
0x12, 0x8E, 0xC4, 0x25, 0x64, 0x87, 0xFD, 0x8F, 0xDF, 0x64, 0xE2, 0x43, 0x7B, 0xC0, 0xA1, 0xF6, 0xD5, 0xAF, 0xDE, 0x2C 0x12, 0x8E, 0xC4, 0x25, 0x64, 0x87, 0xFD, 0x8F, 0xDF, 0x64, 0xE2, 0x43, 0x7B, 0xC0, 0xA1, 0xF6, 0xD5, 0xAF, 0xDE, 0x2C};
};
constexpr u8 VSH_CURVE_GY[0x14] = { constexpr u8 VSH_CURVE_GY[0x14] = {
0x59, 0x58, 0x55, 0x7E, 0xB1, 0xDB, 0x00, 0x12, 0x60, 0x42, 0x55, 0x24, 0xDB, 0xC3, 0x79, 0xD5, 0xAC, 0x5F, 0x4A, 0xDF 0x59, 0x58, 0x55, 0x7E, 0xB1, 0xDB, 0x00, 0x12, 0x60, 0x42, 0x55, 0x24, 0xDB, 0xC3, 0x79, 0xD5, 0xAC, 0x5F, 0x4A, 0xDF};
};
constexpr u8 VSH_PUB[0x28] = { constexpr u8 VSH_PUB[0x28] = {
0x62, 0x27, 0xB0, 0x0A, 0x02, 0x85, 0x6F, 0xB0, 0x41, 0x08, 0x87, 0x67, 0x19, 0xE0, 0xA0, 0x18, 0x32, 0x91, 0xEE, 0xB9, 0x62, 0x27, 0xB0, 0x0A, 0x02, 0x85, 0x6F, 0xB0, 0x41, 0x08, 0x87, 0x67, 0x19, 0xE0, 0xA0, 0x18, 0x32, 0x91, 0xEE, 0xB9,
0x6E, 0x73, 0x6A, 0xBF, 0x81, 0xF7, 0x0E, 0xE9, 0x16, 0x1B, 0x0D, 0xDE, 0xB0, 0x26, 0x76, 0x1A, 0xFF, 0x7B, 0xC8, 0x5B 0x6E, 0x73, 0x6A, 0xBF, 0x81, 0xF7, 0x0E, 0xE9, 0x16, 0x1B, 0x0D, 0xDE, 0xB0, 0x26, 0x76, 0x1A, 0xFF, 0x7B, 0xC8, 0x5B};
};
constexpr u8 SCEPKG_RIV[0x10] = { constexpr u8 SCEPKG_RIV[0x10] = {
0x4A, 0xCE, 0xF0, 0x12, 0x24, 0xFB, 0xEE, 0xDF, 0x82, 0x45, 0xF8, 0xFF, 0x10, 0x21, 0x1E, 0x6E 0x4A, 0xCE, 0xF0, 0x12, 0x24, 0xFB, 0xEE, 0xDF, 0x82, 0x45, 0xF8, 0xFF, 0x10, 0x21, 0x1E, 0x6E};
};
constexpr u8 SCEPKG_ERK[0x20] = { constexpr u8 SCEPKG_ERK[0x20] = {
0xA9, 0x78, 0x18, 0xBD, 0x19, 0x3A, 0x67, 0xA1, 0x6F, 0xE8, 0x3A, 0x85, 0x5E, 0x1B, 0xE9, 0xFB, 0x56, 0x40, 0x93, 0x8D, 0xA9, 0x78, 0x18, 0xBD, 0x19, 0x3A, 0x67, 0xA1, 0x6F, 0xE8, 0x3A, 0x85, 0x5E, 0x1B, 0xE9, 0xFB, 0x56, 0x40, 0x93, 0x8D,
0x4D, 0xBC, 0xB2, 0xCB, 0x52, 0xC5, 0xA2, 0xF8, 0xB0, 0x2B, 0x10, 0x31 0x4D, 0xBC, 0xB2, 0xCB, 0x52, 0xC5, 0xA2, 0xF8, 0xB0, 0x2B, 0x10, 0x31};
};
constexpr u8 PUP_KEY[0x40] = { constexpr u8 PUP_KEY[0x40] = {
0xF4, 0x91, 0xAD, 0x94, 0xC6, 0x81, 0x10, 0x96, 0x91, 0x5F, 0xD5, 0xD2, 0x44, 0x81, 0xAE, 0xDC, 0xED, 0xED, 0xBE, 0x6B, 0xF4, 0x91, 0xAD, 0x94, 0xC6, 0x81, 0x10, 0x96, 0x91, 0x5F, 0xD5, 0xD2, 0x44, 0x81, 0xAE, 0xDC, 0xED, 0xED, 0xBE, 0x6B,
0xE5, 0x13, 0x72, 0x4D, 0xD8, 0xF7, 0xB6, 0x91, 0xE8, 0x8A, 0x38, 0xF4, 0xB5, 0x16, 0x2B, 0xFB, 0xEC, 0xBE, 0x3A, 0x62, 0xE5, 0x13, 0x72, 0x4D, 0xD8, 0xF7, 0xB6, 0x91, 0xE8, 0x8A, 0x38, 0xF4, 0xB5, 0x16, 0x2B, 0xFB, 0xEC, 0xBE, 0x3A, 0x62,
0x18, 0x5D, 0xD7, 0xC9, 0x4D, 0xA2, 0x22, 0x5A, 0xDA, 0x3F, 0xBF, 0xCE, 0x55, 0x5B, 0x9E, 0xA9, 0x64, 0x98, 0x29, 0xEB, 0x18, 0x5D, 0xD7, 0xC9, 0x4D, 0xA2, 0x22, 0x5A, 0xDA, 0x3F, 0xBF, 0xCE, 0x55, 0x5B, 0x9E, 0xA9, 0x64, 0x98, 0x29, 0xEB,
0x30, 0xCE, 0x83, 0x66 0x30, 0xCE, 0x83, 0x66};
};
// name; location; notes // name; location; notes
constexpr s64 PAID_01 = 0x0003CD28CB47D3C1L; // spu_token_processor.self; CoreOS; Only for 2E - 083.007 constexpr s64 PAID_01 = 0x0003CD28CB47D3C1L; // spu_token_processor.self; CoreOS; Only for 2E - 083.007
constexpr s64 PAID_02 = 0x1010000001000001L; // vsh / games / utilities; /dev_flash/, cell_root/target/images; only for 2E - 080.006 constexpr s64 PAID_02 = 0x1010000001000001L; // vsh / games / utilities; /dev_flash/, cell_root/target/images; only for 2E - 080.006
constexpr s64 PAID_03 = 0x1010000001000003L; // retail games and their updates constexpr s64 PAID_03 = 0x1010000001000003L; // retail games and their updates

View file

@ -6,7 +6,7 @@
#include <vector> #include <vector>
#include "lz.h" #include "lz.h"
void decode_range(unsigned int *range, unsigned int *code, unsigned char **src) void decode_range(unsigned int* range, unsigned int* code, unsigned char** src)
{ {
if (!((*range) >> 24)) if (!((*range) >> 24))
{ {
@ -15,20 +15,22 @@ void decode_range(unsigned int *range, unsigned int *code, unsigned char **src)
} }
} }
int decode_bit(unsigned int *range, unsigned int *code, int *index, unsigned char **src, unsigned char *c) int decode_bit(unsigned int* range, unsigned int* code, int* index, unsigned char** src, unsigned char* c)
{ {
decode_range(range, code, src); decode_range(range, code, src);
unsigned int val = ((*range) >> 8) * (*c); unsigned int val = ((*range) >> 8) * (*c);
*c -= ((*c) >> 3); *c -= ((*c) >> 3);
if (index) (*index) <<= 1; if (index)
(*index) <<= 1;
if (*code < val) if (*code < val)
{ {
*range = val; *range = val;
*c += 31; *c += 31;
if (index) (*index)++; if (index)
(*index)++;
return 1; return 1;
} }
else else
@ -39,7 +41,7 @@ int decode_bit(unsigned int *range, unsigned int *code, int *index, unsigned cha
} }
} }
int decode_number(unsigned char *ptr, int index, int *bit_flag, unsigned int *range, unsigned int *code, unsigned char **src) int decode_number(unsigned char* ptr, int index, int* bit_flag, unsigned int* range, unsigned int* code, unsigned char** src)
{ {
int i = 1; int i = 1;
@ -79,7 +81,7 @@ int decode_number(unsigned char *ptr, int index, int *bit_flag, unsigned int *ra
return i; return i;
} }
int decode_word(unsigned char *ptr, int index, int *bit_flag, unsigned int *range, unsigned int *code, unsigned char **src) int decode_word(unsigned char* ptr, int index, int* bit_flag, unsigned int* range, unsigned int* code, unsigned char** src)
{ {
int i = 1; int i = 1;
index /= 8; index /= 8;
@ -120,7 +122,7 @@ int decode_word(unsigned char *ptr, int index, int *bit_flag, unsigned int *rang
return i; return i;
} }
int decompress(unsigned char *out, unsigned char *in, unsigned int size) int decompress(unsigned char* out, unsigned char* in, unsigned int size)
{ {
int result; int result;
@ -133,8 +135,8 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
const unsigned char *buf_start, *buf_end; const unsigned char *buf_start, *buf_end;
unsigned char prev = 0; unsigned char prev = 0;
unsigned char *start = out; unsigned char* start = out;
const unsigned char *end = (out + size); const unsigned char* end = (out + size);
unsigned char head = in[0]; unsigned char head = in[0];
unsigned int range = 0xFFFFFFFF; unsigned int range = 0xFFFFFFFF;
@ -160,11 +162,13 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
{ {
// Start reading at 0xB68. // Start reading at 0xB68.
tmp_sect1 = tmp + offset + 0xB68; tmp_sect1 = tmp + offset + 0xB68;
if (!decode_bit(&range, &code, 0, &in, tmp_sect1)) // Raw char. if (!decode_bit(&range, &code, 0, &in, tmp_sect1)) // Raw char.
{ {
// Adjust offset and check for stream end. // Adjust offset and check for stream end.
if (offset > 0) offset--; if (offset > 0)
if (start == end) return static_cast<int>(start - out); offset--;
if (start == end)
return static_cast<int>(start - out);
// Locate first section. // Locate first section.
int sect = ((((((static_cast<int>(start - out)) & 7) << 8) + prev) >> head) & 7) * 0xFF - 1; int sect = ((((((static_cast<int>(start - out)) & 7) << 8) + prev) >> head) & 7) * 0xFF - 1;
@ -180,7 +184,7 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
// Save index. // Save index.
*start++ = index; *start++ = index;
} }
else // Compressed char stream. else // Compressed char stream.
{ {
int index = -1; int index = -1;
@ -205,7 +209,8 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
// Decode the data length (8 bit fields). // Decode the data length (8 bit fields).
data_length = decode_number(tmp_sect1, index, &bit_flag, &range, &code, &in); data_length = decode_number(tmp_sect1, index, &bit_flag, &range, &code, &in);
if (data_length == 0xFF) return static_cast<int>(start - out); // End of stream. if (data_length == 0xFF)
return static_cast<int>(start - out); // End of stream.
} }
else else
{ {
@ -217,7 +222,7 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
if ((data_length <= 2)) if ((data_length <= 2))
{ {
tmp_sect2 += 0xF8; tmp_sect2 += 0xF8;
b_size = 0x40; // Block size is now 0x40. b_size = 0x40; // Block size is now 0x40.
} }
int diff = 0; int diff = 0;
@ -234,7 +239,8 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
if ((diff > 0) || (bit_flag != 0)) if ((diff > 0) || (bit_flag != 0))
{ {
// Adjust diff if needed. // Adjust diff if needed.
if (bit_flag == 0) diff -= 8; if (bit_flag == 0)
diff -= 8;
// Locate section. // Locate section.
tmp_sect3 = tmp + 0x928 + diff; tmp_sect3 = tmp + 0x928 + diff;
@ -272,7 +278,6 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
{ {
*start++ = *buf_start++; *start++ = *buf_start++;
} while (start < buf_end); } while (start < buf_end);
} }
prev = *(start - 1); prev = *(start - 1);
} }

View file

@ -6,8 +6,8 @@
// Reverse-engineered custom LempelZivMarkov based compression. // Reverse-engineered custom LempelZivMarkov based compression.
void decode_range(unsigned int *range, unsigned int *code, unsigned char **src); void decode_range(unsigned int* range, unsigned int* code, unsigned char** src);
int decode_bit(unsigned int *range, unsigned int *code, int *index, unsigned char **src, unsigned char *c); int decode_bit(unsigned int* range, unsigned int* code, int* index, unsigned char** src, unsigned char* c);
int decode_number(unsigned char *ptr, int index, int *bit_flag, unsigned int *range, unsigned int *code, unsigned char **src); int decode_number(unsigned char* ptr, int index, int* bit_flag, unsigned int* range, unsigned int* code, unsigned char** src);
int decode_word(unsigned char *ptr, int index, int *bit_flag, unsigned int *range, unsigned int *code, unsigned char **src); int decode_word(unsigned char* ptr, int index, int* bit_flag, unsigned int* range, unsigned int* code, unsigned char** src);
int decompress(unsigned char *out, unsigned char *in, unsigned int size); int decompress(unsigned char* out, unsigned char* in, unsigned int size);

View file

@ -37,199 +37,197 @@
* 32-bit integer manipulation macros (little endian) * 32-bit integer manipulation macros (little endian)
*/ */
#ifndef GET_UINT32_LE #ifndef GET_UINT32_LE
#define GET_UINT32_LE(n,b,i) \ #define GET_UINT32_LE(n, b, i) \
{ \ { \
(n) = ( static_cast<uint32_t>((b)[(i) ]) ) \ (n) = (static_cast<uint32_t>((b)[(i)])) | (static_cast<uint32_t>((b)[(i) + 1]) << 8) | (static_cast<uint32_t>((b)[(i) + 2]) << 16) | (static_cast<uint32_t>((b)[(i) + 3]) << 24); \
| ( static_cast<uint32_t>((b)[(i) + 1]) << 8 ) \ }
| ( static_cast<uint32_t>((b)[(i) + 2]) << 16 ) \
| ( static_cast<uint32_t>((b)[(i) + 3]) << 24 );\
}
#endif #endif
#ifndef PUT_UINT32_LE #ifndef PUT_UINT32_LE
#define PUT_UINT32_LE(n,b,i) \ #define PUT_UINT32_LE(n, b, i) \
{ \ { \
(b)[(i) ] = static_cast<unsigned char>(( (n) ) & 0xFF ); \ (b)[(i)] = static_cast<unsigned char>(((n)) & 0xFF); \
(b)[(i) + 1] = static_cast<unsigned char>(( (n) >> 8 ) & 0xFF ); \ (b)[(i) + 1] = static_cast<unsigned char>(((n) >> 8) & 0xFF); \
(b)[(i) + 2] = static_cast<unsigned char>(( (n) >> 16 ) & 0xFF ); \ (b)[(i) + 2] = static_cast<unsigned char>(((n) >> 16) & 0xFF); \
(b)[(i) + 3] = static_cast<unsigned char>(( (n) >> 24 ) & 0xFF ); \ (b)[(i) + 3] = static_cast<unsigned char>(((n) >> 24) & 0xFF); \
} }
#endif #endif
void mbedtls_md5_init( mbedtls_md5_context *ctx ) void mbedtls_md5_init(mbedtls_md5_context* ctx)
{ {
memset( ctx, 0, sizeof( mbedtls_md5_context ) ); memset(ctx, 0, sizeof(mbedtls_md5_context));
} }
void mbedtls_md5_free( mbedtls_md5_context *ctx ) void mbedtls_md5_free(mbedtls_md5_context* ctx)
{ {
if( ctx == NULL ) if (ctx == NULL)
return; return;
mbedtls_zeroize( ctx, sizeof( mbedtls_md5_context ) ); mbedtls_zeroize(ctx, sizeof(mbedtls_md5_context));
} }
void mbedtls_md5_clone( mbedtls_md5_context *dst, void mbedtls_md5_clone(mbedtls_md5_context* dst,
const mbedtls_md5_context *src ) const mbedtls_md5_context* src)
{ {
*dst = *src; *dst = *src;
} }
/* /*
* MD5 context setup * MD5 context setup
*/ */
int mbedtls_md5_starts_ret( mbedtls_md5_context *ctx ) int mbedtls_md5_starts_ret(mbedtls_md5_context* ctx)
{ {
ctx->total[0] = 0; ctx->total[0] = 0;
ctx->total[1] = 0; ctx->total[1] = 0;
ctx->state[0] = 0x67452301; ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89; ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE; ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476; ctx->state[3] = 0x10325476;
return( 0 ); return (0);
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED) #if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_md5_starts( mbedtls_md5_context *ctx ) void mbedtls_md5_starts(mbedtls_md5_context* ctx)
{ {
mbedtls_md5_starts_ret( ctx ); mbedtls_md5_starts_ret(ctx);
} }
#endif #endif
#if !defined(MBEDTLS_MD5_PROCESS_ALT) #if !defined(MBEDTLS_MD5_PROCESS_ALT)
int mbedtls_internal_md5_process( mbedtls_md5_context *ctx, int mbedtls_internal_md5_process(mbedtls_md5_context* ctx,
const unsigned char data[64] ) const unsigned char data[64])
{ {
uint32_t X[16], A, B, C, D; uint32_t X[16], A, B, C, D;
GET_UINT32_LE( X[ 0], data, 0 ); GET_UINT32_LE(X[0], data, 0);
GET_UINT32_LE( X[ 1], data, 4 ); GET_UINT32_LE(X[1], data, 4);
GET_UINT32_LE( X[ 2], data, 8 ); GET_UINT32_LE(X[2], data, 8);
GET_UINT32_LE( X[ 3], data, 12 ); GET_UINT32_LE(X[3], data, 12);
GET_UINT32_LE( X[ 4], data, 16 ); GET_UINT32_LE(X[4], data, 16);
GET_UINT32_LE( X[ 5], data, 20 ); GET_UINT32_LE(X[5], data, 20);
GET_UINT32_LE( X[ 6], data, 24 ); GET_UINT32_LE(X[6], data, 24);
GET_UINT32_LE( X[ 7], data, 28 ); GET_UINT32_LE(X[7], data, 28);
GET_UINT32_LE( X[ 8], data, 32 ); GET_UINT32_LE(X[8], data, 32);
GET_UINT32_LE( X[ 9], data, 36 ); GET_UINT32_LE(X[9], data, 36);
GET_UINT32_LE( X[10], data, 40 ); GET_UINT32_LE(X[10], data, 40);
GET_UINT32_LE( X[11], data, 44 ); GET_UINT32_LE(X[11], data, 44);
GET_UINT32_LE( X[12], data, 48 ); GET_UINT32_LE(X[12], data, 48);
GET_UINT32_LE( X[13], data, 52 ); GET_UINT32_LE(X[13], data, 52);
GET_UINT32_LE( X[14], data, 56 ); GET_UINT32_LE(X[14], data, 56);
GET_UINT32_LE( X[15], data, 60 ); GET_UINT32_LE(X[15], data, 60);
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) #define S(x, n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
#define P(a,b,c,d,k,s,t) \ #define P(a, b, c, d, k, s, t) \
{ \ { \
a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ a += F(b, c, d) + X[k] + t; \
} a = S(a, s) + b; \
}
A = ctx->state[0]; A = ctx->state[0];
B = ctx->state[1]; B = ctx->state[1];
C = ctx->state[2]; C = ctx->state[2];
D = ctx->state[3]; D = ctx->state[3];
#define F(x,y,z) (z ^ (x & (y ^ z))) #define F(x, y, z) (z ^ (x & (y ^ z)))
P( A, B, C, D, 0, 7, 0xD76AA478 ); P(A, B, C, D, 0, 7, 0xD76AA478);
P( D, A, B, C, 1, 12, 0xE8C7B756 ); P(D, A, B, C, 1, 12, 0xE8C7B756);
P( C, D, A, B, 2, 17, 0x242070DB ); P(C, D, A, B, 2, 17, 0x242070DB);
P( B, C, D, A, 3, 22, 0xC1BDCEEE ); P(B, C, D, A, 3, 22, 0xC1BDCEEE);
P( A, B, C, D, 4, 7, 0xF57C0FAF ); P(A, B, C, D, 4, 7, 0xF57C0FAF);
P( D, A, B, C, 5, 12, 0x4787C62A ); P(D, A, B, C, 5, 12, 0x4787C62A);
P( C, D, A, B, 6, 17, 0xA8304613 ); P(C, D, A, B, 6, 17, 0xA8304613);
P( B, C, D, A, 7, 22, 0xFD469501 ); P(B, C, D, A, 7, 22, 0xFD469501);
P( A, B, C, D, 8, 7, 0x698098D8 ); P(A, B, C, D, 8, 7, 0x698098D8);
P( D, A, B, C, 9, 12, 0x8B44F7AF ); P(D, A, B, C, 9, 12, 0x8B44F7AF);
P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); P(C, D, A, B, 10, 17, 0xFFFF5BB1);
P( B, C, D, A, 11, 22, 0x895CD7BE ); P(B, C, D, A, 11, 22, 0x895CD7BE);
P( A, B, C, D, 12, 7, 0x6B901122 ); P(A, B, C, D, 12, 7, 0x6B901122);
P( D, A, B, C, 13, 12, 0xFD987193 ); P(D, A, B, C, 13, 12, 0xFD987193);
P( C, D, A, B, 14, 17, 0xA679438E ); P(C, D, A, B, 14, 17, 0xA679438E);
P( B, C, D, A, 15, 22, 0x49B40821 ); P(B, C, D, A, 15, 22, 0x49B40821);
#undef F #undef F
#define F(x,y,z) (y ^ (z & (x ^ y))) #define F(x, y, z) (y ^ (z & (x ^ y)))
P( A, B, C, D, 1, 5, 0xF61E2562 ); P(A, B, C, D, 1, 5, 0xF61E2562);
P( D, A, B, C, 6, 9, 0xC040B340 ); P(D, A, B, C, 6, 9, 0xC040B340);
P( C, D, A, B, 11, 14, 0x265E5A51 ); P(C, D, A, B, 11, 14, 0x265E5A51);
P( B, C, D, A, 0, 20, 0xE9B6C7AA ); P(B, C, D, A, 0, 20, 0xE9B6C7AA);
P( A, B, C, D, 5, 5, 0xD62F105D ); P(A, B, C, D, 5, 5, 0xD62F105D);
P( D, A, B, C, 10, 9, 0x02441453 ); P(D, A, B, C, 10, 9, 0x02441453);
P( C, D, A, B, 15, 14, 0xD8A1E681 ); P(C, D, A, B, 15, 14, 0xD8A1E681);
P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); P(B, C, D, A, 4, 20, 0xE7D3FBC8);
P( A, B, C, D, 9, 5, 0x21E1CDE6 ); P(A, B, C, D, 9, 5, 0x21E1CDE6);
P( D, A, B, C, 14, 9, 0xC33707D6 ); P(D, A, B, C, 14, 9, 0xC33707D6);
P( C, D, A, B, 3, 14, 0xF4D50D87 ); P(C, D, A, B, 3, 14, 0xF4D50D87);
P( B, C, D, A, 8, 20, 0x455A14ED ); P(B, C, D, A, 8, 20, 0x455A14ED);
P( A, B, C, D, 13, 5, 0xA9E3E905 ); P(A, B, C, D, 13, 5, 0xA9E3E905);
P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); P(D, A, B, C, 2, 9, 0xFCEFA3F8);
P( C, D, A, B, 7, 14, 0x676F02D9 ); P(C, D, A, B, 7, 14, 0x676F02D9);
P( B, C, D, A, 12, 20, 0x8D2A4C8A ); P(B, C, D, A, 12, 20, 0x8D2A4C8A);
#undef F #undef F
#define F(x,y,z) (x ^ y ^ z) #define F(x, y, z) (x ^ y ^ z)
P( A, B, C, D, 5, 4, 0xFFFA3942 ); P(A, B, C, D, 5, 4, 0xFFFA3942);
P( D, A, B, C, 8, 11, 0x8771F681 ); P(D, A, B, C, 8, 11, 0x8771F681);
P( C, D, A, B, 11, 16, 0x6D9D6122 ); P(C, D, A, B, 11, 16, 0x6D9D6122);
P( B, C, D, A, 14, 23, 0xFDE5380C ); P(B, C, D, A, 14, 23, 0xFDE5380C);
P( A, B, C, D, 1, 4, 0xA4BEEA44 ); P(A, B, C, D, 1, 4, 0xA4BEEA44);
P( D, A, B, C, 4, 11, 0x4BDECFA9 ); P(D, A, B, C, 4, 11, 0x4BDECFA9);
P( C, D, A, B, 7, 16, 0xF6BB4B60 ); P(C, D, A, B, 7, 16, 0xF6BB4B60);
P( B, C, D, A, 10, 23, 0xBEBFBC70 ); P(B, C, D, A, 10, 23, 0xBEBFBC70);
P( A, B, C, D, 13, 4, 0x289B7EC6 ); P(A, B, C, D, 13, 4, 0x289B7EC6);
P( D, A, B, C, 0, 11, 0xEAA127FA ); P(D, A, B, C, 0, 11, 0xEAA127FA);
P( C, D, A, B, 3, 16, 0xD4EF3085 ); P(C, D, A, B, 3, 16, 0xD4EF3085);
P( B, C, D, A, 6, 23, 0x04881D05 ); P(B, C, D, A, 6, 23, 0x04881D05);
P( A, B, C, D, 9, 4, 0xD9D4D039 ); P(A, B, C, D, 9, 4, 0xD9D4D039);
P( D, A, B, C, 12, 11, 0xE6DB99E5 ); P(D, A, B, C, 12, 11, 0xE6DB99E5);
P( C, D, A, B, 15, 16, 0x1FA27CF8 ); P(C, D, A, B, 15, 16, 0x1FA27CF8);
P( B, C, D, A, 2, 23, 0xC4AC5665 ); P(B, C, D, A, 2, 23, 0xC4AC5665);
#undef F #undef F
#define F(x,y,z) (y ^ (x | ~z)) #define F(x, y, z) (y ^ (x | ~z))
P( A, B, C, D, 0, 6, 0xF4292244 ); P(A, B, C, D, 0, 6, 0xF4292244);
P( D, A, B, C, 7, 10, 0x432AFF97 ); P(D, A, B, C, 7, 10, 0x432AFF97);
P( C, D, A, B, 14, 15, 0xAB9423A7 ); P(C, D, A, B, 14, 15, 0xAB9423A7);
P( B, C, D, A, 5, 21, 0xFC93A039 ); P(B, C, D, A, 5, 21, 0xFC93A039);
P( A, B, C, D, 12, 6, 0x655B59C3 ); P(A, B, C, D, 12, 6, 0x655B59C3);
P( D, A, B, C, 3, 10, 0x8F0CCC92 ); P(D, A, B, C, 3, 10, 0x8F0CCC92);
P( C, D, A, B, 10, 15, 0xFFEFF47D ); P(C, D, A, B, 10, 15, 0xFFEFF47D);
P( B, C, D, A, 1, 21, 0x85845DD1 ); P(B, C, D, A, 1, 21, 0x85845DD1);
P( A, B, C, D, 8, 6, 0x6FA87E4F ); P(A, B, C, D, 8, 6, 0x6FA87E4F);
P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); P(D, A, B, C, 15, 10, 0xFE2CE6E0);
P( C, D, A, B, 6, 15, 0xA3014314 ); P(C, D, A, B, 6, 15, 0xA3014314);
P( B, C, D, A, 13, 21, 0x4E0811A1 ); P(B, C, D, A, 13, 21, 0x4E0811A1);
P( A, B, C, D, 4, 6, 0xF7537E82 ); P(A, B, C, D, 4, 6, 0xF7537E82);
P( D, A, B, C, 11, 10, 0xBD3AF235 ); P(D, A, B, C, 11, 10, 0xBD3AF235);
P( C, D, A, B, 2, 15, 0x2AD7D2BB ); P(C, D, A, B, 2, 15, 0x2AD7D2BB);
P( B, C, D, A, 9, 21, 0xEB86D391 ); P(B, C, D, A, 9, 21, 0xEB86D391);
#undef F #undef F
ctx->state[0] += A; ctx->state[0] += A;
ctx->state[1] += B; ctx->state[1] += B;
ctx->state[2] += C; ctx->state[2] += C;
ctx->state[3] += D; ctx->state[3] += D;
return( 0 ); return (0);
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED) #if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_md5_process( mbedtls_md5_context *ctx, void mbedtls_md5_process(mbedtls_md5_context* ctx,
const unsigned char data[64] ) const unsigned char data[64])
{ {
mbedtls_internal_md5_process( ctx, data ); mbedtls_internal_md5_process(ctx, data);
} }
#endif #endif
#endif /* !MBEDTLS_MD5_PROCESS_ALT */ #endif /* !MBEDTLS_MD5_PROCESS_ALT */
@ -237,125 +235,124 @@ void mbedtls_md5_process( mbedtls_md5_context *ctx,
/* /*
* MD5 process buffer * MD5 process buffer
*/ */
int mbedtls_md5_update_ret( mbedtls_md5_context *ctx, int mbedtls_md5_update_ret(mbedtls_md5_context* ctx,
const unsigned char *input, const unsigned char* input,
size_t ilen ) size_t ilen)
{ {
int ret; int ret;
size_t fill; size_t fill;
uint32_t left; uint32_t left;
if( ilen == 0 ) if (ilen == 0)
return( 0 ); return (0);
left = ctx->total[0] & 0x3F; left = ctx->total[0] & 0x3F;
fill = 64 - left; fill = 64 - left;
ctx->total[0] += static_cast<uint32_t>(ilen); ctx->total[0] += static_cast<uint32_t>(ilen);
ctx->total[0] &= 0xFFFFFFFF; ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < static_cast<uint32_t>(ilen) ) if (ctx->total[0] < static_cast<uint32_t>(ilen))
ctx->total[1]++; ctx->total[1]++;
if( left && ilen >= fill ) if (left && ilen >= fill)
{ {
memcpy( ctx->buffer + left, input, fill ); memcpy(ctx->buffer + left, input, fill);
if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0)
return( ret ); return (ret);
input += fill; input += fill;
ilen -= fill; ilen -= fill;
left = 0; left = 0;
} }
while( ilen >= 64 ) while (ilen >= 64)
{ {
if( ( ret = mbedtls_internal_md5_process( ctx, input ) ) != 0 ) if ((ret = mbedtls_internal_md5_process(ctx, input)) != 0)
return( ret ); return (ret);
input += 64; input += 64;
ilen -= 64; ilen -= 64;
} }
if( ilen > 0 ) if (ilen > 0)
{ {
memcpy( ctx->buffer + left, input, ilen ); memcpy(ctx->buffer + left, input, ilen);
} }
return( 0 ); return (0);
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED) #if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_md5_update( mbedtls_md5_context *ctx, void mbedtls_md5_update(mbedtls_md5_context* ctx,
const unsigned char *input, const unsigned char* input,
size_t ilen ) size_t ilen)
{ {
mbedtls_md5_update_ret( ctx, input, ilen ); mbedtls_md5_update_ret(ctx, input, ilen);
} }
#endif #endif
/* /*
* MD5 final digest * MD5 final digest
*/ */
int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, int mbedtls_md5_finish_ret(mbedtls_md5_context* ctx,
unsigned char output[16] ) unsigned char output[16])
{ {
int ret; int ret;
uint32_t used; uint32_t used;
uint32_t high, low; uint32_t high, low;
/* /*
* Add padding: 0x80 then 0x00 until 8 bytes remain for the length * Add padding: 0x80 then 0x00 until 8 bytes remain for the length
*/ */
used = ctx->total[0] & 0x3F; used = ctx->total[0] & 0x3F;
ctx->buffer[used++] = 0x80; ctx->buffer[used++] = 0x80;
if( used <= 56 ) if (used <= 56)
{ {
/* Enough room for padding + length in current block */ /* Enough room for padding + length in current block */
memset( ctx->buffer + used, 0, 56 - used ); memset(ctx->buffer + used, 0, 56 - used);
} }
else else
{ {
/* We'll need an extra block */ /* We'll need an extra block */
memset( ctx->buffer + used, 0, 64 - used ); memset(ctx->buffer + used, 0, 64 - used);
if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0)
return( ret ); return (ret);
memset( ctx->buffer, 0, 56 ); memset(ctx->buffer, 0, 56);
} }
/* /*
* Add message length * Add message length
*/ */
high = ( ctx->total[0] >> 29 ) high = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
| ( ctx->total[1] << 3 ); low = (ctx->total[0] << 3);
low = ( ctx->total[0] << 3 );
PUT_UINT32_LE( low, ctx->buffer, 56 ); PUT_UINT32_LE(low, ctx->buffer, 56);
PUT_UINT32_LE( high, ctx->buffer, 60 ); PUT_UINT32_LE(high, ctx->buffer, 60);
if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0)
return( ret ); return (ret);
/* /*
* Output final state * Output final state
*/ */
PUT_UINT32_LE( ctx->state[0], output, 0 ); PUT_UINT32_LE(ctx->state[0], output, 0);
PUT_UINT32_LE( ctx->state[1], output, 4 ); PUT_UINT32_LE(ctx->state[1], output, 4);
PUT_UINT32_LE( ctx->state[2], output, 8 ); PUT_UINT32_LE(ctx->state[2], output, 8);
PUT_UINT32_LE( ctx->state[3], output, 12 ); PUT_UINT32_LE(ctx->state[3], output, 12);
return( 0 ); return (0);
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED) #if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_md5_finish( mbedtls_md5_context *ctx, void mbedtls_md5_finish(mbedtls_md5_context* ctx,
unsigned char output[16] ) unsigned char output[16])
{ {
mbedtls_md5_finish_ret( ctx, output ); mbedtls_md5_finish_ret(ctx, output);
} }
#endif #endif
@ -364,36 +361,36 @@ void mbedtls_md5_finish( mbedtls_md5_context *ctx,
/* /*
* output = MD5( input buffer ) * output = MD5( input buffer )
*/ */
int mbedtls_md5_ret( const unsigned char *input, int mbedtls_md5_ret(const unsigned char* input,
size_t ilen, size_t ilen,
unsigned char output[16] ) unsigned char output[16])
{ {
int ret; int ret;
mbedtls_md5_context ctx; mbedtls_md5_context ctx;
mbedtls_md5_init( &ctx ); mbedtls_md5_init(&ctx);
if( ( ret = mbedtls_md5_starts_ret( &ctx ) ) != 0 ) if ((ret = mbedtls_md5_starts_ret(&ctx)) != 0)
goto exit; goto exit;
if( ( ret = mbedtls_md5_update_ret( &ctx, input, ilen ) ) != 0 ) if ((ret = mbedtls_md5_update_ret(&ctx, input, ilen)) != 0)
goto exit; goto exit;
if( ( ret = mbedtls_md5_finish_ret( &ctx, output ) ) != 0 ) if ((ret = mbedtls_md5_finish_ret(&ctx, output)) != 0)
goto exit; goto exit;
exit: exit:
mbedtls_md5_free( &ctx ); mbedtls_md5_free(&ctx);
return( ret ); return (ret);
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED) #if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_md5( const unsigned char *input, void mbedtls_md5(const unsigned char* input,
size_t ilen, size_t ilen,
unsigned char output[16] ) unsigned char output[16])
{ {
mbedtls_md5_ret( input, ilen, output ); mbedtls_md5_ret(input, ilen, output);
} }
#endif #endif
@ -402,77 +399,74 @@ void mbedtls_md5( const unsigned char *input,
* RFC 1321 test vectors * RFC 1321 test vectors
*/ */
static const unsigned char md5_test_buf[7][81] = static const unsigned char md5_test_buf[7][81] =
{ {
{ "" }, {""},
{ "a" }, {"a"},
{ "abc" }, {"abc"},
{ "message digest" }, {"message digest"},
{ "abcdefghijklmnopqrstuvwxyz" }, {"abcdefghijklmnopqrstuvwxyz"},
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"},
{ "12345678901234567890123456789012345678901234567890123456789012" {"12345678901234567890123456789012345678901234567890123456789012"
"345678901234567890" } "345678901234567890"}};
};
static const size_t md5_test_buflen[7] = static const size_t md5_test_buflen[7] =
{ {
0, 1, 3, 14, 26, 62, 80 0, 1, 3, 14, 26, 62, 80};
};
static const unsigned char md5_test_sum[7][16] = static const unsigned char md5_test_sum[7][16] =
{ {
{ 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, {0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E }, 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E},
{ 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, {0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 }, 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61},
{ 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, {0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 }, 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72},
{ 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, {0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 }, 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0},
{ 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00, {0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B }, 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B},
{ 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5, {0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F }, 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F},
{ 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, {0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A } 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A}};
};
/* /*
* Checkup routine * Checkup routine
*/ */
int mbedtls_md5_self_test( int verbose ) int mbedtls_md5_self_test(int verbose)
{ {
int i, ret = 0; int i, ret = 0;
unsigned char md5sum[16]; unsigned char md5sum[16];
for( i = 0; i < 7; i++ ) for (i = 0; i < 7; i++)
{ {
if( verbose != 0 ) if (verbose != 0)
mbedtls_printf( " MD5 test #%d: ", i + 1 ); mbedtls_printf(" MD5 test #%d: ", i + 1);
ret = mbedtls_md5_ret( md5_test_buf[i], md5_test_buflen[i], md5sum ); ret = mbedtls_md5_ret(md5_test_buf[i], md5_test_buflen[i], md5sum);
if( ret != 0 ) if (ret != 0)
goto fail; goto fail;
if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 ) if (memcmp(md5sum, md5_test_sum[i], 16) != 0)
{ {
ret = 1; ret = 1;
goto fail; goto fail;
} }
if( verbose != 0 ) if (verbose != 0)
mbedtls_printf( "passed\n" ); mbedtls_printf("passed\n");
} }
if( verbose != 0 ) if (verbose != 0)
mbedtls_printf( "\n" ); mbedtls_printf("\n");
return( 0 ); return (0);
fail: fail:
if( verbose != 0 ) if (verbose != 0)
mbedtls_printf( "failed\n" ); mbedtls_printf("failed\n");
return( ret ); return (ret);
} }
#endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SELF_TEST */

View file

@ -34,269 +34,269 @@
#include <stdint.h> #include <stdint.h>
/* MBEDTLS_ERR_MD5_HW_ACCEL_FAILED is deprecated and should not be used. */ /* MBEDTLS_ERR_MD5_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED -0x002F /**< MD5 hardware accelerator failed */ #define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED -0x002F /**< MD5 hardware accelerator failed */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
#if !defined(MBEDTLS_MD5_ALT) #if !defined(MBEDTLS_MD5_ALT)
// Regular implementation // Regular implementation
// //
/** /**
* \brief MD5 context structure * \brief MD5 context structure
* *
* \warning MD5 is considered a weak message digest and its use * \warning MD5 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering * constitutes a security risk. We recommend considering
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
typedef struct mbedtls_md5_context typedef struct mbedtls_md5_context
{ {
uint32_t total[2]; /*!< number of bytes processed */ uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[4]; /*!< intermediate digest state */ uint32_t state[4]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */ unsigned char buffer[64]; /*!< data block being processed */
} } mbedtls_md5_context;
mbedtls_md5_context;
#else /* MBEDTLS_MD5_ALT */ #else /* MBEDTLS_MD5_ALT */
#include "md5_alt.h" #include "md5_alt.h"
#endif /* MBEDTLS_MD5_ALT */ #endif /* MBEDTLS_MD5_ALT */
/** /**
* \brief Initialize MD5 context * \brief Initialize MD5 context
* *
* \param ctx MD5 context to be initialized * \param ctx MD5 context to be initialized
* *
* \warning MD5 is considered a weak message digest and its use * \warning MD5 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering * constitutes a security risk. We recommend considering
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
void mbedtls_md5_init( mbedtls_md5_context *ctx ); void mbedtls_md5_init(mbedtls_md5_context* ctx);
/** /**
* \brief Clear MD5 context * \brief Clear MD5 context
* *
* \param ctx MD5 context to be cleared * \param ctx MD5 context to be cleared
* *
* \warning MD5 is considered a weak message digest and its use * \warning MD5 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering * constitutes a security risk. We recommend considering
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
void mbedtls_md5_free( mbedtls_md5_context *ctx ); void mbedtls_md5_free(mbedtls_md5_context* ctx);
/** /**
* \brief Clone (the state of) an MD5 context * \brief Clone (the state of) an MD5 context
* *
* \param dst The destination context * \param dst The destination context
* \param src The context to be cloned * \param src The context to be cloned
* *
* \warning MD5 is considered a weak message digest and its use * \warning MD5 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering * constitutes a security risk. We recommend considering
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
void mbedtls_md5_clone( mbedtls_md5_context *dst, void mbedtls_md5_clone(mbedtls_md5_context* dst,
const mbedtls_md5_context *src ); const mbedtls_md5_context* src);
/** /**
* \brief MD5 context setup * \brief MD5 context setup
* *
* \param ctx context to be initialized * \param ctx context to be initialized
* *
* \return 0 if successful * \return 0 if successful
* *
* \warning MD5 is considered a weak message digest and its use * \warning MD5 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering * constitutes a security risk. We recommend considering
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
int mbedtls_md5_starts_ret( mbedtls_md5_context *ctx ); int mbedtls_md5_starts_ret(mbedtls_md5_context* ctx);
/** /**
* \brief MD5 process buffer * \brief MD5 process buffer
* *
* \param ctx MD5 context * \param ctx MD5 context
* \param input buffer holding the data * \param input buffer holding the data
* \param ilen length of the input data * \param ilen length of the input data
* *
* \return 0 if successful * \return 0 if successful
* *
* \warning MD5 is considered a weak message digest and its use * \warning MD5 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering * constitutes a security risk. We recommend considering
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
int mbedtls_md5_update_ret( mbedtls_md5_context *ctx, int mbedtls_md5_update_ret(mbedtls_md5_context* ctx,
const unsigned char *input, const unsigned char* input,
size_t ilen ); size_t ilen);
/** /**
* \brief MD5 final digest * \brief MD5 final digest
* *
* \param ctx MD5 context * \param ctx MD5 context
* \param output MD5 checksum result * \param output MD5 checksum result
* *
* \return 0 if successful * \return 0 if successful
* *
* \warning MD5 is considered a weak message digest and its use * \warning MD5 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering * constitutes a security risk. We recommend considering
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, int mbedtls_md5_finish_ret(mbedtls_md5_context* ctx,
unsigned char output[16] ); unsigned char output[16]);
/** /**
* \brief MD5 process data block (internal use only) * \brief MD5 process data block (internal use only)
* *
* \param ctx MD5 context * \param ctx MD5 context
* \param data buffer holding one block of data * \param data buffer holding one block of data
* *
* \return 0 if successful * \return 0 if successful
* *
* \warning MD5 is considered a weak message digest and its use * \warning MD5 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering * constitutes a security risk. We recommend considering
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
int mbedtls_internal_md5_process( mbedtls_md5_context *ctx, int mbedtls_internal_md5_process(mbedtls_md5_context* ctx,
const unsigned char data[64] ); const unsigned char data[64]);
#if !defined(MBEDTLS_DEPRECATED_REMOVED) #if !defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING) #if defined(MBEDTLS_DEPRECATED_WARNING)
#define MBEDTLS_DEPRECATED __attribute__((deprecated)) #define MBEDTLS_DEPRECATED __attribute__((deprecated))
#else #else
#define MBEDTLS_DEPRECATED #define MBEDTLS_DEPRECATED
#endif #endif
/** /**
* \brief MD5 context setup * \brief MD5 context setup
* *
* \deprecated Superseded by mbedtls_md5_starts_ret() in 2.7.0 * \deprecated Superseded by mbedtls_md5_starts_ret() in 2.7.0
* *
* \param ctx context to be initialized * \param ctx context to be initialized
* *
* \warning MD5 is considered a weak message digest and its use * \warning MD5 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering * constitutes a security risk. We recommend considering
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
MBEDTLS_DEPRECATED void mbedtls_md5_starts( mbedtls_md5_context *ctx ); MBEDTLS_DEPRECATED void mbedtls_md5_starts(mbedtls_md5_context* ctx);
/** /**
* \brief MD5 process buffer * \brief MD5 process buffer
* *
* \deprecated Superseded by mbedtls_md5_update_ret() in 2.7.0 * \deprecated Superseded by mbedtls_md5_update_ret() in 2.7.0
* *
* \param ctx MD5 context * \param ctx MD5 context
* \param input buffer holding the data * \param input buffer holding the data
* \param ilen length of the input data * \param ilen length of the input data
* *
* \warning MD5 is considered a weak message digest and its use * \warning MD5 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering * constitutes a security risk. We recommend considering
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
MBEDTLS_DEPRECATED void mbedtls_md5_update( mbedtls_md5_context *ctx, MBEDTLS_DEPRECATED void mbedtls_md5_update(mbedtls_md5_context* ctx,
const unsigned char *input, const unsigned char* input,
size_t ilen ); size_t ilen);
/** /**
* \brief MD5 final digest * \brief MD5 final digest
* *
* \deprecated Superseded by mbedtls_md5_finish_ret() in 2.7.0 * \deprecated Superseded by mbedtls_md5_finish_ret() in 2.7.0
* *
* \param ctx MD5 context * \param ctx MD5 context
* \param output MD5 checksum result * \param output MD5 checksum result
* *
* \warning MD5 is considered a weak message digest and its use * \warning MD5 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering * constitutes a security risk. We recommend considering
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
MBEDTLS_DEPRECATED void mbedtls_md5_finish( mbedtls_md5_context *ctx, MBEDTLS_DEPRECATED void mbedtls_md5_finish(mbedtls_md5_context* ctx,
unsigned char output[16] ); unsigned char output[16]);
/** /**
* \brief MD5 process data block (internal use only) * \brief MD5 process data block (internal use only)
* *
* \deprecated Superseded by mbedtls_internal_md5_process() in 2.7.0 * \deprecated Superseded by mbedtls_internal_md5_process() in 2.7.0
* *
* \param ctx MD5 context * \param ctx MD5 context
* \param data buffer holding one block of data * \param data buffer holding one block of data
* *
* \warning MD5 is considered a weak message digest and its use * \warning MD5 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering * constitutes a security risk. We recommend considering
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
MBEDTLS_DEPRECATED void mbedtls_md5_process( mbedtls_md5_context *ctx, MBEDTLS_DEPRECATED void mbedtls_md5_process(mbedtls_md5_context* ctx,
const unsigned char data[64] ); const unsigned char data[64]);
#undef MBEDTLS_DEPRECATED #undef MBEDTLS_DEPRECATED
#endif /* !MBEDTLS_DEPRECATED_REMOVED */ #endif /* !MBEDTLS_DEPRECATED_REMOVED */
/** /**
* \brief Output = MD5( input buffer ) * \brief Output = MD5( input buffer )
* *
* \param input buffer holding the data * \param input buffer holding the data
* \param ilen length of the input data * \param ilen length of the input data
* \param output MD5 checksum result * \param output MD5 checksum result
* *
* \return 0 if successful * \return 0 if successful
* *
* \warning MD5 is considered a weak message digest and its use * \warning MD5 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering * constitutes a security risk. We recommend considering
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
int mbedtls_md5_ret( const unsigned char *input, int mbedtls_md5_ret(const unsigned char* input,
size_t ilen, size_t ilen,
unsigned char output[16] ); unsigned char output[16]);
#if !defined(MBEDTLS_DEPRECATED_REMOVED) #if !defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING) #if defined(MBEDTLS_DEPRECATED_WARNING)
#define MBEDTLS_DEPRECATED __attribute__((deprecated)) #define MBEDTLS_DEPRECATED __attribute__((deprecated))
#else #else
#define MBEDTLS_DEPRECATED #define MBEDTLS_DEPRECATED
#endif #endif
/** /**
* \brief Output = MD5( input buffer ) * \brief Output = MD5( input buffer )
* *
* \deprecated Superseded by mbedtls_md5_ret() in 2.7.0 * \deprecated Superseded by mbedtls_md5_ret() in 2.7.0
* *
* \param input buffer holding the data * \param input buffer holding the data
* \param ilen length of the input data * \param ilen length of the input data
* \param output MD5 checksum result * \param output MD5 checksum result
* *
* \warning MD5 is considered a weak message digest and its use * \warning MD5 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering * constitutes a security risk. We recommend considering
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
MBEDTLS_DEPRECATED void mbedtls_md5( const unsigned char *input, MBEDTLS_DEPRECATED void mbedtls_md5(const unsigned char* input,
size_t ilen, size_t ilen,
unsigned char output[16] ); unsigned char output[16]);
#undef MBEDTLS_DEPRECATED #undef MBEDTLS_DEPRECATED
#endif /* !MBEDTLS_DEPRECATED_REMOVED */ #endif /* !MBEDTLS_DEPRECATED_REMOVED */
#if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_SELF_TEST)
/** /**
* \brief Checkup routine * \brief Checkup routine
* *
* \return 0 if successful, or 1 if the test failed * \return 0 if successful, or 1 if the test failed
* *
* \warning MD5 is considered a weak message digest and its use * \warning MD5 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering * constitutes a security risk. We recommend considering
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
int mbedtls_md5_self_test( int verbose ); int mbedtls_md5_self_test(int verbose);
#endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SELF_TEST */

View file

@ -35,363 +35,358 @@
* 32-bit integer manipulation macros (big endian) * 32-bit integer manipulation macros (big endian)
*/ */
#ifndef GET_UINT32_BE #ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \ #define GET_UINT32_BE(n, b, i) \
{ \ { \
(n) = ( static_cast<uint32_t>((b)[(i) ]) << 24 ) \ (n) = (static_cast<uint32_t>((b)[(i)]) << 24) | (static_cast<uint32_t>((b)[(i) + 1]) << 16) | (static_cast<uint32_t>((b)[(i) + 2]) << 8) | (static_cast<uint32_t>((b)[(i) + 3])); \
| ( static_cast<uint32_t>((b)[(i) + 1]) << 16 ) \ }
| ( static_cast<uint32_t>((b)[(i) + 2]) << 8 ) \
| ( static_cast<uint32_t>((b)[(i) + 3]) );\
}
#endif #endif
#ifndef PUT_UINT32_BE #ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \ #define PUT_UINT32_BE(n, b, i) \
{ \ { \
(b)[(i) ] = static_cast<unsigned char> ( (n) >> 24 ); \ (b)[(i)] = static_cast<unsigned char>((n) >> 24); \
(b)[(i) + 1] = static_cast<unsigned char> ( (n) >> 16 ); \ (b)[(i) + 1] = static_cast<unsigned char>((n) >> 16); \
(b)[(i) + 2] = static_cast<unsigned char> ( (n) >> 8 ); \ (b)[(i) + 2] = static_cast<unsigned char>((n) >> 8); \
(b)[(i) + 3] = static_cast<unsigned char> ( (n) ); \ (b)[(i) + 3] = static_cast<unsigned char>((n)); \
} }
#endif #endif
/* /*
* SHA-1 context setup * SHA-1 context setup
*/ */
void sha1_starts( sha1_context *ctx ) void sha1_starts(sha1_context* ctx)
{ {
ctx->total[0] = 0; ctx->total[0] = 0;
ctx->total[1] = 0; ctx->total[1] = 0;
ctx->state[0] = 0x67452301; ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89; ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE; ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476; ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0; ctx->state[4] = 0xC3D2E1F0;
} }
void sha1_process( sha1_context *ctx, const unsigned char data[64] ) void sha1_process(sha1_context* ctx, const unsigned char data[64])
{ {
uint32_t temp, W[16], A, B, C, D, E; uint32_t temp, W[16], A, B, C, D, E;
GET_UINT32_BE( W[ 0], data, 0 ); GET_UINT32_BE(W[0], data, 0);
GET_UINT32_BE( W[ 1], data, 4 ); GET_UINT32_BE(W[1], data, 4);
GET_UINT32_BE( W[ 2], data, 8 ); GET_UINT32_BE(W[2], data, 8);
GET_UINT32_BE( W[ 3], data, 12 ); GET_UINT32_BE(W[3], data, 12);
GET_UINT32_BE( W[ 4], data, 16 ); GET_UINT32_BE(W[4], data, 16);
GET_UINT32_BE( W[ 5], data, 20 ); GET_UINT32_BE(W[5], data, 20);
GET_UINT32_BE( W[ 6], data, 24 ); GET_UINT32_BE(W[6], data, 24);
GET_UINT32_BE( W[ 7], data, 28 ); GET_UINT32_BE(W[7], data, 28);
GET_UINT32_BE( W[ 8], data, 32 ); GET_UINT32_BE(W[8], data, 32);
GET_UINT32_BE( W[ 9], data, 36 ); GET_UINT32_BE(W[9], data, 36);
GET_UINT32_BE( W[10], data, 40 ); GET_UINT32_BE(W[10], data, 40);
GET_UINT32_BE( W[11], data, 44 ); GET_UINT32_BE(W[11], data, 44);
GET_UINT32_BE( W[12], data, 48 ); GET_UINT32_BE(W[12], data, 48);
GET_UINT32_BE( W[13], data, 52 ); GET_UINT32_BE(W[13], data, 52);
GET_UINT32_BE( W[14], data, 56 ); GET_UINT32_BE(W[14], data, 56);
GET_UINT32_BE( W[15], data, 60 ); GET_UINT32_BE(W[15], data, 60);
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) #define S(x, n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
#define R(t) \ #define R(t) \
( \ ( \
temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \ temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \
W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \ W[(t - 14) & 0x0F] ^ W[t & 0x0F], \
( W[t & 0x0F] = S(temp,1) ) \ (W[t & 0x0F] = S(temp, 1)))
)
#define P(a,b,c,d,e,x) \ #define P(a, b, c, d, e, x) \
{ \ { \
e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ e += S(a, 5) + F(b, c, d) + K + x; \
} b = S(b, 30); \
}
A = ctx->state[0]; A = ctx->state[0];
B = ctx->state[1]; B = ctx->state[1];
C = ctx->state[2]; C = ctx->state[2];
D = ctx->state[3]; D = ctx->state[3];
E = ctx->state[4]; E = ctx->state[4];
#define F(x,y,z) (z ^ (x & (y ^ z))) #define F(x, y, z) (z ^ (x & (y ^ z)))
#define K 0x5A827999 #define K 0x5A827999
P( A, B, C, D, E, W[0] ); P(A, B, C, D, E, W[0]);
P( E, A, B, C, D, W[1] ); P(E, A, B, C, D, W[1]);
P( D, E, A, B, C, W[2] ); P(D, E, A, B, C, W[2]);
P( C, D, E, A, B, W[3] ); P(C, D, E, A, B, W[3]);
P( B, C, D, E, A, W[4] ); P(B, C, D, E, A, W[4]);
P( A, B, C, D, E, W[5] ); P(A, B, C, D, E, W[5]);
P( E, A, B, C, D, W[6] ); P(E, A, B, C, D, W[6]);
P( D, E, A, B, C, W[7] ); P(D, E, A, B, C, W[7]);
P( C, D, E, A, B, W[8] ); P(C, D, E, A, B, W[8]);
P( B, C, D, E, A, W[9] ); P(B, C, D, E, A, W[9]);
P( A, B, C, D, E, W[10] ); P(A, B, C, D, E, W[10]);
P( E, A, B, C, D, W[11] ); P(E, A, B, C, D, W[11]);
P( D, E, A, B, C, W[12] ); P(D, E, A, B, C, W[12]);
P( C, D, E, A, B, W[13] ); P(C, D, E, A, B, W[13]);
P( B, C, D, E, A, W[14] ); P(B, C, D, E, A, W[14]);
P( A, B, C, D, E, W[15] ); P(A, B, C, D, E, W[15]);
P( E, A, B, C, D, R(16) ); P(E, A, B, C, D, R(16));
P( D, E, A, B, C, R(17) ); P(D, E, A, B, C, R(17));
P( C, D, E, A, B, R(18) ); P(C, D, E, A, B, R(18));
P( B, C, D, E, A, R(19) ); P(B, C, D, E, A, R(19));
#undef K #undef K
#undef F #undef F
#define F(x,y,z) (x ^ y ^ z) #define F(x, y, z) (x ^ y ^ z)
#define K 0x6ED9EBA1 #define K 0x6ED9EBA1
P( A, B, C, D, E, R(20) ); P(A, B, C, D, E, R(20));
P( E, A, B, C, D, R(21) ); P(E, A, B, C, D, R(21));
P( D, E, A, B, C, R(22) ); P(D, E, A, B, C, R(22));
P( C, D, E, A, B, R(23) ); P(C, D, E, A, B, R(23));
P( B, C, D, E, A, R(24) ); P(B, C, D, E, A, R(24));
P( A, B, C, D, E, R(25) ); P(A, B, C, D, E, R(25));
P( E, A, B, C, D, R(26) ); P(E, A, B, C, D, R(26));
P( D, E, A, B, C, R(27) ); P(D, E, A, B, C, R(27));
P( C, D, E, A, B, R(28) ); P(C, D, E, A, B, R(28));
P( B, C, D, E, A, R(29) ); P(B, C, D, E, A, R(29));
P( A, B, C, D, E, R(30) ); P(A, B, C, D, E, R(30));
P( E, A, B, C, D, R(31) ); P(E, A, B, C, D, R(31));
P( D, E, A, B, C, R(32) ); P(D, E, A, B, C, R(32));
P( C, D, E, A, B, R(33) ); P(C, D, E, A, B, R(33));
P( B, C, D, E, A, R(34) ); P(B, C, D, E, A, R(34));
P( A, B, C, D, E, R(35) ); P(A, B, C, D, E, R(35));
P( E, A, B, C, D, R(36) ); P(E, A, B, C, D, R(36));
P( D, E, A, B, C, R(37) ); P(D, E, A, B, C, R(37));
P( C, D, E, A, B, R(38) ); P(C, D, E, A, B, R(38));
P( B, C, D, E, A, R(39) ); P(B, C, D, E, A, R(39));
#undef K #undef K
#undef F #undef F
#define F(x,y,z) ((x & y) | (z & (x | y))) #define F(x, y, z) ((x & y) | (z & (x | y)))
#define K 0x8F1BBCDC #define K 0x8F1BBCDC
P( A, B, C, D, E, R(40) ); P(A, B, C, D, E, R(40));
P( E, A, B, C, D, R(41) ); P(E, A, B, C, D, R(41));
P( D, E, A, B, C, R(42) ); P(D, E, A, B, C, R(42));
P( C, D, E, A, B, R(43) ); P(C, D, E, A, B, R(43));
P( B, C, D, E, A, R(44) ); P(B, C, D, E, A, R(44));
P( A, B, C, D, E, R(45) ); P(A, B, C, D, E, R(45));
P( E, A, B, C, D, R(46) ); P(E, A, B, C, D, R(46));
P( D, E, A, B, C, R(47) ); P(D, E, A, B, C, R(47));
P( C, D, E, A, B, R(48) ); P(C, D, E, A, B, R(48));
P( B, C, D, E, A, R(49) ); P(B, C, D, E, A, R(49));
P( A, B, C, D, E, R(50) ); P(A, B, C, D, E, R(50));
P( E, A, B, C, D, R(51) ); P(E, A, B, C, D, R(51));
P( D, E, A, B, C, R(52) ); P(D, E, A, B, C, R(52));
P( C, D, E, A, B, R(53) ); P(C, D, E, A, B, R(53));
P( B, C, D, E, A, R(54) ); P(B, C, D, E, A, R(54));
P( A, B, C, D, E, R(55) ); P(A, B, C, D, E, R(55));
P( E, A, B, C, D, R(56) ); P(E, A, B, C, D, R(56));
P( D, E, A, B, C, R(57) ); P(D, E, A, B, C, R(57));
P( C, D, E, A, B, R(58) ); P(C, D, E, A, B, R(58));
P( B, C, D, E, A, R(59) ); P(B, C, D, E, A, R(59));
#undef K #undef K
#undef F #undef F
#define F(x,y,z) (x ^ y ^ z) #define F(x, y, z) (x ^ y ^ z)
#define K 0xCA62C1D6 #define K 0xCA62C1D6
P( A, B, C, D, E, R(60) ); P(A, B, C, D, E, R(60));
P( E, A, B, C, D, R(61) ); P(E, A, B, C, D, R(61));
P( D, E, A, B, C, R(62) ); P(D, E, A, B, C, R(62));
P( C, D, E, A, B, R(63) ); P(C, D, E, A, B, R(63));
P( B, C, D, E, A, R(64) ); P(B, C, D, E, A, R(64));
P( A, B, C, D, E, R(65) ); P(A, B, C, D, E, R(65));
P( E, A, B, C, D, R(66) ); P(E, A, B, C, D, R(66));
P( D, E, A, B, C, R(67) ); P(D, E, A, B, C, R(67));
P( C, D, E, A, B, R(68) ); P(C, D, E, A, B, R(68));
P( B, C, D, E, A, R(69) ); P(B, C, D, E, A, R(69));
P( A, B, C, D, E, R(70) ); P(A, B, C, D, E, R(70));
P( E, A, B, C, D, R(71) ); P(E, A, B, C, D, R(71));
P( D, E, A, B, C, R(72) ); P(D, E, A, B, C, R(72));
P( C, D, E, A, B, R(73) ); P(C, D, E, A, B, R(73));
P( B, C, D, E, A, R(74) ); P(B, C, D, E, A, R(74));
P( A, B, C, D, E, R(75) ); P(A, B, C, D, E, R(75));
P( E, A, B, C, D, R(76) ); P(E, A, B, C, D, R(76));
P( D, E, A, B, C, R(77) ); P(D, E, A, B, C, R(77));
P( C, D, E, A, B, R(78) ); P(C, D, E, A, B, R(78));
P( B, C, D, E, A, R(79) ); P(B, C, D, E, A, R(79));
#undef K #undef K
#undef F #undef F
ctx->state[0] += A; ctx->state[0] += A;
ctx->state[1] += B; ctx->state[1] += B;
ctx->state[2] += C; ctx->state[2] += C;
ctx->state[3] += D; ctx->state[3] += D;
ctx->state[4] += E; ctx->state[4] += E;
} }
/* /*
* SHA-1 process buffer * SHA-1 process buffer
*/ */
void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen ) void sha1_update(sha1_context* ctx, const unsigned char* input, size_t ilen)
{ {
size_t fill; size_t fill;
uint32_t left; uint32_t left;
// TODO:: Syphurith: Orz. It is said that size_t is an unsigned type.. // TODO:: Syphurith: Orz. It is said that size_t is an unsigned type..
if( ilen <= 0 ) if (ilen <= 0)
return; return;
left = ctx->total[0] & 0x3F; left = ctx->total[0] & 0x3F;
fill = 64 - left; fill = 64 - left;
ctx->total[0] += static_cast<uint32_t>(ilen); ctx->total[0] += static_cast<uint32_t>(ilen);
ctx->total[0] &= 0xFFFFFFFF; ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < static_cast<uint32_t>(ilen) ) if (ctx->total[0] < static_cast<uint32_t>(ilen))
ctx->total[1]++; ctx->total[1]++;
if( left && ilen >= fill ) if (left && ilen >= fill)
{ {
memcpy( ctx->buffer + left, input, fill ); memcpy(ctx->buffer + left, input, fill);
sha1_process( ctx, ctx->buffer ); sha1_process(ctx, ctx->buffer);
input += fill; input += fill;
ilen -= fill; ilen -= fill;
left = 0; left = 0;
} }
while( ilen >= 64 ) while (ilen >= 64)
{ {
sha1_process( ctx, input ); sha1_process(ctx, input);
input += 64; input += 64;
ilen -= 64; ilen -= 64;
} }
if( ilen > 0 ) if (ilen > 0)
memcpy( ctx->buffer + left, input, ilen ); memcpy(ctx->buffer + left, input, ilen);
} }
static const unsigned char sha1_padding[64] = static const unsigned char sha1_padding[64] =
{ {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
};
/* /*
* SHA-1 final digest * SHA-1 final digest
*/ */
void sha1_finish( sha1_context *ctx, unsigned char output[20] ) void sha1_finish(sha1_context* ctx, unsigned char output[20])
{ {
uint32_t last, padn; uint32_t last, padn;
uint32_t high, low; uint32_t high, low;
unsigned char msglen[8]; unsigned char msglen[8];
high = ( ctx->total[0] >> 29 ) high = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
| ( ctx->total[1] << 3 ); low = (ctx->total[0] << 3);
low = ( ctx->total[0] << 3 );
PUT_UINT32_BE( high, msglen, 0 ); PUT_UINT32_BE(high, msglen, 0);
PUT_UINT32_BE( low, msglen, 4 ); PUT_UINT32_BE(low, msglen, 4);
last = ctx->total[0] & 0x3F; last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); padn = (last < 56) ? (56 - last) : (120 - last);
sha1_update( ctx, sha1_padding, padn ); sha1_update(ctx, sha1_padding, padn);
sha1_update( ctx, msglen, 8 ); sha1_update(ctx, msglen, 8);
PUT_UINT32_BE( ctx->state[0], output, 0 ); PUT_UINT32_BE(ctx->state[0], output, 0);
PUT_UINT32_BE( ctx->state[1], output, 4 ); PUT_UINT32_BE(ctx->state[1], output, 4);
PUT_UINT32_BE( ctx->state[2], output, 8 ); PUT_UINT32_BE(ctx->state[2], output, 8);
PUT_UINT32_BE( ctx->state[3], output, 12 ); PUT_UINT32_BE(ctx->state[3], output, 12);
PUT_UINT32_BE( ctx->state[4], output, 16 ); PUT_UINT32_BE(ctx->state[4], output, 16);
} }
/* /*
* output = SHA-1( input buffer ) * output = SHA-1( input buffer )
*/ */
void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ) void sha1(const unsigned char* input, size_t ilen, unsigned char output[20])
{ {
sha1_context ctx; sha1_context ctx;
sha1_starts( &ctx ); sha1_starts(&ctx);
sha1_update( &ctx, input, ilen ); sha1_update(&ctx, input, ilen);
sha1_finish( &ctx, output ); sha1_finish(&ctx, output);
mbedtls_zeroize( &ctx, sizeof( sha1_context ) ); mbedtls_zeroize(&ctx, sizeof(sha1_context));
} }
/* /*
* SHA-1 HMAC context setup * SHA-1 HMAC context setup
*/ */
void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen ) void sha1_hmac_starts(sha1_context* ctx, const unsigned char* key, size_t keylen)
{ {
size_t i; size_t i;
unsigned char sum[20]; unsigned char sum[20];
if( keylen > 64 ) if (keylen > 64)
{ {
sha1( key, keylen, sum ); sha1(key, keylen, sum);
keylen = 20; keylen = 20;
key = sum; key = sum;
} }
memset( ctx->ipad, 0x36, 64 ); memset(ctx->ipad, 0x36, 64);
memset( ctx->opad, 0x5C, 64 ); memset(ctx->opad, 0x5C, 64);
for( i = 0; i < keylen; i++ ) for (i = 0; i < keylen; i++)
{ {
ctx->ipad[i] ^= key[i]; ctx->ipad[i] ^= key[i];
ctx->opad[i] ^= key[i]; ctx->opad[i] ^= key[i];
} }
sha1_starts( ctx ); sha1_starts(ctx);
sha1_update( ctx, ctx->ipad, 64 ); sha1_update(ctx, ctx->ipad, 64);
mbedtls_zeroize( sum, sizeof( sum ) ); mbedtls_zeroize(sum, sizeof(sum));
} }
/* /*
* SHA-1 HMAC process buffer * SHA-1 HMAC process buffer
*/ */
void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen ) void sha1_hmac_update(sha1_context* ctx, const unsigned char* input, size_t ilen)
{ {
sha1_update( ctx, input, ilen ); sha1_update(ctx, input, ilen);
} }
/* /*
* SHA-1 HMAC final digest * SHA-1 HMAC final digest
*/ */
void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] ) void sha1_hmac_finish(sha1_context* ctx, unsigned char output[20])
{ {
unsigned char tmpbuf[20]; unsigned char tmpbuf[20];
sha1_finish( ctx, tmpbuf ); sha1_finish(ctx, tmpbuf);
sha1_starts( ctx ); sha1_starts(ctx);
sha1_update( ctx, ctx->opad, 64 ); sha1_update(ctx, ctx->opad, 64);
sha1_update( ctx, tmpbuf, 20 ); sha1_update(ctx, tmpbuf, 20);
sha1_finish( ctx, output ); sha1_finish(ctx, output);
memset( tmpbuf, 0, sizeof( tmpbuf ) ); memset(tmpbuf, 0, sizeof(tmpbuf));
} }
/* /*
* SHA1 HMAC context reset * SHA1 HMAC context reset
*/ */
void sha1_hmac_reset( sha1_context *ctx ) void sha1_hmac_reset(sha1_context* ctx)
{ {
sha1_starts( ctx ); sha1_starts(ctx);
sha1_update( ctx, ctx->ipad, 64 ); sha1_update(ctx, ctx->ipad, 64);
} }
/* /*
* output = HMAC-SHA-1( hmac key, input buffer ) * output = HMAC-SHA-1( hmac key, input buffer )
*/ */
void sha1_hmac( const unsigned char *key, size_t keylen, void sha1_hmac(const unsigned char* key, size_t keylen,
const unsigned char *input, size_t ilen, const unsigned char* input, size_t ilen,
unsigned char output[20] ) unsigned char output[20])
{ {
sha1_context ctx; sha1_context ctx;
sha1_hmac_starts( &ctx, key, keylen ); sha1_hmac_starts(&ctx, key, keylen);
sha1_hmac_update( &ctx, input, ilen ); sha1_hmac_update(&ctx, input, ilen);
sha1_hmac_finish( &ctx, output ); sha1_hmac_finish(&ctx, output);
memset( &ctx, 0, sizeof( sha1_context ) ); memset(&ctx, 0, sizeof(sha1_context));
} }

View file

@ -35,7 +35,7 @@ typedef UINT32 uint32_t;
#include <inttypes.h> #include <inttypes.h>
#endif #endif
#define POLARSSL_ERR_SHA1_FILE_IO_ERROR -0x0076 /**< Read/write error in file. */ #define POLARSSL_ERR_SHA1_FILE_IO_ERROR -0x0076 /**< Read/write error in file. */
// Regular implementation // Regular implementation
// //
@ -45,118 +45,119 @@ typedef UINT32 uint32_t;
*/ */
typedef struct typedef struct
{ {
uint32_t total[2]; /*!< number of bytes processed */ uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[5]; /*!< intermediate digest state */ uint32_t state[5]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */ unsigned char buffer[64]; /*!< data block being processed */
unsigned char ipad[64]; /*!< HMAC: inner padding */ unsigned char ipad[64]; /*!< HMAC: inner padding */
unsigned char opad[64]; /*!< HMAC: outer padding */ unsigned char opad[64]; /*!< HMAC: outer padding */
} } sha1_context;
sha1_context;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
/** /**
* \brief SHA-1 context setup * \brief SHA-1 context setup
* *
* \param ctx context to be initialized * \param ctx context to be initialized
*/ */
void sha1_starts( sha1_context *ctx ); void sha1_starts(sha1_context* ctx);
/** /**
* \brief SHA-1 process buffer * \brief SHA-1 process buffer
* *
* \param ctx SHA-1 context * \param ctx SHA-1 context
* \param input buffer holding the data * \param input buffer holding the data
* \param ilen length of the input data * \param ilen length of the input data
*/ */
void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen ); void sha1_update(sha1_context* ctx, const unsigned char* input, size_t ilen);
/** /**
* \brief SHA-1 final digest * \brief SHA-1 final digest
* *
* \param ctx SHA-1 context * \param ctx SHA-1 context
* \param output SHA-1 checksum result * \param output SHA-1 checksum result
*/ */
void sha1_finish( sha1_context *ctx, unsigned char output[20] ); void sha1_finish(sha1_context* ctx, unsigned char output[20]);
/* Internal use */ /* Internal use */
void sha1_process( sha1_context *ctx, const unsigned char data[64] ); void sha1_process(sha1_context* ctx, const unsigned char data[64]);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
/** /**
* \brief Output = SHA-1( input buffer ) * \brief Output = SHA-1( input buffer )
* *
* \param input buffer holding the data * \param input buffer holding the data
* \param ilen length of the input data * \param ilen length of the input data
* \param output SHA-1 checksum result * \param output SHA-1 checksum result
*/ */
void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ); void sha1(const unsigned char* input, size_t ilen, unsigned char output[20]);
/** /**
* \brief Output = SHA-1( file contents ) * \brief Output = SHA-1( file contents )
* *
* \param path input file name * \param path input file name
* \param output SHA-1 checksum result * \param output SHA-1 checksum result
* *
* \return 0 if successful, or POLARSSL_ERR_SHA1_FILE_IO_ERROR * \return 0 if successful, or POLARSSL_ERR_SHA1_FILE_IO_ERROR
*/ */
int sha1_file( const char *path, unsigned char output[20] ); int sha1_file(const char* path, unsigned char output[20]);
/** /**
* \brief SHA-1 HMAC context setup * \brief SHA-1 HMAC context setup
* *
* \param ctx HMAC context to be initialized * \param ctx HMAC context to be initialized
* \param key HMAC secret key * \param key HMAC secret key
* \param keylen length of the HMAC key * \param keylen length of the HMAC key
*/ */
void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen ); void sha1_hmac_starts(sha1_context* ctx, const unsigned char* key, size_t keylen);
/** /**
* \brief SHA-1 HMAC process buffer * \brief SHA-1 HMAC process buffer
* *
* \param ctx HMAC context * \param ctx HMAC context
* \param input buffer holding the data * \param input buffer holding the data
* \param ilen length of the input data * \param ilen length of the input data
*/ */
void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen ); void sha1_hmac_update(sha1_context* ctx, const unsigned char* input, size_t ilen);
/** /**
* \brief SHA-1 HMAC final digest * \brief SHA-1 HMAC final digest
* *
* \param ctx HMAC context * \param ctx HMAC context
* \param output SHA-1 HMAC checksum result * \param output SHA-1 HMAC checksum result
*/ */
void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] ); void sha1_hmac_finish(sha1_context* ctx, unsigned char output[20]);
/** /**
* \brief SHA-1 HMAC context reset * \brief SHA-1 HMAC context reset
* *
* \param ctx HMAC context to be reset * \param ctx HMAC context to be reset
*/ */
void sha1_hmac_reset( sha1_context *ctx ); void sha1_hmac_reset(sha1_context* ctx);
/** /**
* \brief Output = HMAC-SHA-1( hmac key, input buffer ) * \brief Output = HMAC-SHA-1( hmac key, input buffer )
* *
* \param key HMAC secret key * \param key HMAC secret key
* \param keylen length of the HMAC key * \param keylen length of the HMAC key
* \param input buffer holding the data * \param input buffer holding the data
* \param ilen length of the input data * \param ilen length of the input data
* \param output HMAC-SHA-1 result * \param output HMAC-SHA-1 result
*/ */
void sha1_hmac( const unsigned char *key, size_t keylen, void sha1_hmac(const unsigned char* key, size_t keylen,
const unsigned char *input, size_t ilen, const unsigned char* input, size_t ilen,
unsigned char output[20] ); unsigned char output[20]);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -38,8 +38,8 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#define mbedtls_printf printf #define mbedtls_printf printf
#define mbedtls_calloc calloc #define mbedtls_calloc calloc
#define mbedtls_free free #define mbedtls_free free
#endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SELF_TEST */
@ -52,211 +52,265 @@
* 32-bit integer manipulation macros (big endian) * 32-bit integer manipulation macros (big endian)
*/ */
#ifndef GET_UINT32_BE #ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \ #define GET_UINT32_BE(n, b, i) \
do { \ do \
(n) = ( static_cast<uint32_t>((b)[(i) ]) << 24 ) \ { \
| ( static_cast<uint32_t>((b)[(i) + 1]) << 16 ) \ (n) = (static_cast<uint32_t>((b)[(i)]) << 24) | (static_cast<uint32_t>((b)[(i) + 1]) << 16) | (static_cast<uint32_t>((b)[(i) + 2]) << 8) | (static_cast<uint32_t>((b)[(i) + 3])); \
| ( static_cast<uint32_t>((b)[(i) + 2]) << 8 ) \ } while (0)
| ( static_cast<uint32_t>((b)[(i) + 3]) );\
} while( 0 )
#endif #endif
#ifndef PUT_UINT32_BE #ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \ #define PUT_UINT32_BE(n, b, i) \
do { \ do \
(b)[(i) ] = static_cast<unsigned char> ( (n) >> 24 ); \ { \
(b)[(i) + 1] = static_cast<unsigned char> ( (n) >> 16 ); \ (b)[(i)] = static_cast<unsigned char>((n) >> 24); \
(b)[(i) + 2] = static_cast<unsigned char> ( (n) >> 8 ); \ (b)[(i) + 1] = static_cast<unsigned char>((n) >> 16); \
(b)[(i) + 3] = static_cast<unsigned char> ( (n) ); \ (b)[(i) + 2] = static_cast<unsigned char>((n) >> 8); \
} while( 0 ) (b)[(i) + 3] = static_cast<unsigned char>((n)); \
} while (0)
#endif #endif
void mbedtls_sha256_init( mbedtls_sha256_context *ctx ) void mbedtls_sha256_init(mbedtls_sha256_context* ctx)
{ {
SHA256_VALIDATE( ctx != NULL ); SHA256_VALIDATE(ctx != NULL);
memset( ctx, 0, sizeof( mbedtls_sha256_context ) ); memset(ctx, 0, sizeof(mbedtls_sha256_context));
} }
void mbedtls_sha256_free( mbedtls_sha256_context *ctx ) void mbedtls_sha256_free(mbedtls_sha256_context* ctx)
{ {
if( ctx == NULL ) if (ctx == NULL)
return; return;
mbedtls_zeroize(ctx, sizeof(mbedtls_sha256_context)); mbedtls_zeroize(ctx, sizeof(mbedtls_sha256_context));
} }
void mbedtls_sha256_clone( mbedtls_sha256_context *dst, void mbedtls_sha256_clone(mbedtls_sha256_context* dst,
const mbedtls_sha256_context *src ) const mbedtls_sha256_context* src)
{ {
SHA256_VALIDATE( dst != NULL ); SHA256_VALIDATE(dst != NULL);
SHA256_VALIDATE( src != NULL ); SHA256_VALIDATE(src != NULL);
*dst = *src; *dst = *src;
} }
/* /*
* SHA-256 context setup * SHA-256 context setup
*/ */
int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ) int mbedtls_sha256_starts_ret(mbedtls_sha256_context* ctx, int is224)
{ {
SHA256_VALIDATE_RET( ctx != NULL ); SHA256_VALIDATE_RET(ctx != NULL);
SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 ); SHA256_VALIDATE_RET(is224 == 0 || is224 == 1);
ctx->total[0] = 0; ctx->total[0] = 0;
ctx->total[1] = 0; ctx->total[1] = 0;
if( is224 == 0 ) if (is224 == 0)
{ {
/* SHA-256 */ /* SHA-256 */
ctx->state[0] = 0x6A09E667; ctx->state[0] = 0x6A09E667;
ctx->state[1] = 0xBB67AE85; ctx->state[1] = 0xBB67AE85;
ctx->state[2] = 0x3C6EF372; ctx->state[2] = 0x3C6EF372;
ctx->state[3] = 0xA54FF53A; ctx->state[3] = 0xA54FF53A;
ctx->state[4] = 0x510E527F; ctx->state[4] = 0x510E527F;
ctx->state[5] = 0x9B05688C; ctx->state[5] = 0x9B05688C;
ctx->state[6] = 0x1F83D9AB; ctx->state[6] = 0x1F83D9AB;
ctx->state[7] = 0x5BE0CD19; ctx->state[7] = 0x5BE0CD19;
} }
else else
{ {
/* SHA-224 */ /* SHA-224 */
ctx->state[0] = 0xC1059ED8; ctx->state[0] = 0xC1059ED8;
ctx->state[1] = 0x367CD507; ctx->state[1] = 0x367CD507;
ctx->state[2] = 0x3070DD17; ctx->state[2] = 0x3070DD17;
ctx->state[3] = 0xF70E5939; ctx->state[3] = 0xF70E5939;
ctx->state[4] = 0xFFC00B31; ctx->state[4] = 0xFFC00B31;
ctx->state[5] = 0x68581511; ctx->state[5] = 0x68581511;
ctx->state[6] = 0x64F98FA7; ctx->state[6] = 0x64F98FA7;
ctx->state[7] = 0xBEFA4FA4; ctx->state[7] = 0xBEFA4FA4;
} }
ctx->is224 = is224; ctx->is224 = is224;
return( 0 ); return (0);
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED) #if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, void mbedtls_sha256_starts(mbedtls_sha256_context* ctx,
int is224 ) int is224)
{ {
mbedtls_sha256_starts_ret( ctx, is224 ); mbedtls_sha256_starts_ret(ctx, is224);
} }
#endif #endif
#if !defined(MBEDTLS_SHA256_PROCESS_ALT) #if !defined(MBEDTLS_SHA256_PROCESS_ALT)
static const uint32_t K[] = static const uint32_t K[] =
{ {
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x428A2F98,
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0x71374491,
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0xB5C0FBCF,
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE9B5DBA5,
0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 0x3956C25B,
0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 0x59F111F1,
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0x923F82A4,
0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, 0xAB1C5ED5,
0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0xD807AA98,
0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0x12835B01,
0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0x243185BE,
0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 0x550C7DC3,
0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x72BE5D74,
0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 0x80DEB1FE,
0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x9BDC06A7,
0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, 0xC19BF174,
0xE49B69C1,
0xEFBE4786,
0x0FC19DC6,
0x240CA1CC,
0x2DE92C6F,
0x4A7484AA,
0x5CB0A9DC,
0x76F988DA,
0x983E5152,
0xA831C66D,
0xB00327C8,
0xBF597FC7,
0xC6E00BF3,
0xD5A79147,
0x06CA6351,
0x14292967,
0x27B70A85,
0x2E1B2138,
0x4D2C6DFC,
0x53380D13,
0x650A7354,
0x766A0ABB,
0x81C2C92E,
0x92722C85,
0xA2BFE8A1,
0xA81A664B,
0xC24B8B70,
0xC76C51A3,
0xD192E819,
0xD6990624,
0xF40E3585,
0x106AA070,
0x19A4C116,
0x1E376C08,
0x2748774C,
0x34B0BCB5,
0x391C0CB3,
0x4ED8AA4A,
0x5B9CCA4F,
0x682E6FF3,
0x748F82EE,
0x78A5636F,
0x84C87814,
0x8CC70208,
0x90BEFFFA,
0xA4506CEB,
0xBEF9A3F7,
0xC67178F2,
}; };
#define SHR(x,n) (((x) & 0xFFFFFFFF) >> (n)) #define SHR(x, n) (((x) & 0xFFFFFFFF) >> (n))
#define ROTR(x,n) (SHR(x,n) | ((x) << (32 - (n)))) #define ROTR(x, n) (SHR(x, n) | ((x) << (32 - (n))))
#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) #define S0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))
#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) #define S1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) #define S2(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) #define S3(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
#define F0(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) #define F0(x, y, z) (((x) & (y)) | ((z) & ((x) | (y))))
#define F1(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) #define F1(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
#define R(t) \ #define R(t) \
( \ ( \
W[t] = S1(W[(t) - 2]) + W[(t) - 7] + \ W[t] = S1(W[(t) - 2]) + W[(t) - 7] + \
S0(W[(t) - 15]) + W[(t) - 16] \ S0(W[(t) - 15]) + W[(t) - 16])
)
#define P(a,b,c,d,e,f,g,h,x,K) \ #define P(a, b, c, d, e, f, g, h, x, K) \
do \ do \
{ \ { \
temp1 = (h) + S3(e) + F1((e),(f),(g)) + (K) + (x); \ temp1 = (h) + S3(e) + F1((e), (f), (g)) + (K) + (x); \
temp2 = S2(a) + F0((a),(b),(c)); \ temp2 = S2(a) + F0((a), (b), (c)); \
(d) += temp1; (h) = temp1 + temp2; \ (d) += temp1; \
} while( 0 ) (h) = temp1 + temp2; \
} while (0)
int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, int mbedtls_internal_sha256_process(mbedtls_sha256_context* ctx,
const unsigned char data[64] ) const unsigned char data[64])
{ {
uint32_t temp1, temp2, W[64]; uint32_t temp1, temp2, W[64];
uint32_t A[8]; uint32_t A[8];
unsigned int i; unsigned int i;
SHA256_VALIDATE_RET( ctx != NULL ); SHA256_VALIDATE_RET(ctx != NULL);
SHA256_VALIDATE_RET( (const unsigned char *)data != NULL ); SHA256_VALIDATE_RET((const unsigned char*)data != NULL);
for( i = 0; i < 8; i++ ) for (i = 0; i < 8; i++)
A[i] = ctx->state[i]; A[i] = ctx->state[i];
#if defined(MBEDTLS_SHA256_SMALLER) #if defined(MBEDTLS_SHA256_SMALLER)
for( i = 0; i < 64; i++ ) for (i = 0; i < 64; i++)
{ {
if( i < 16 ) if (i < 16)
GET_UINT32_BE( W[i], data, 4 * i ); GET_UINT32_BE(W[i], data, 4 * i);
else else
R( i ); R(i);
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] ); P(A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i]);
temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3]; temp1 = A[7];
A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1; A[7] = A[6];
} A[6] = A[5];
#else /* MBEDTLS_SHA256_SMALLER */ A[5] = A[4];
for( i = 0; i < 16; i++ ) A[4] = A[3];
GET_UINT32_BE( W[i], data, 4 * i ); A[3] = A[2];
A[2] = A[1];
A[1] = A[0];
A[0] = temp1;
}
#else /* MBEDTLS_SHA256_SMALLER */
for (i = 0; i < 16; i++)
GET_UINT32_BE(W[i], data, 4 * i);
for( i = 0; i < 16; i += 8 ) for (i = 0; i < 16; i += 8)
{ {
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] ); P(A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i + 0], K[i + 0]);
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i+1], K[i+1] ); P(A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i + 1], K[i + 1]);
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i+2], K[i+2] ); P(A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i + 2], K[i + 2]);
P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i+3], K[i+3] ); P(A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i + 3], K[i + 3]);
P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i+4], K[i+4] ); P(A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i + 4], K[i + 4]);
P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i+5], K[i+5] ); P(A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i + 5], K[i + 5]);
P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i+6], K[i+6] ); P(A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i + 6], K[i + 6]);
P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i+7], K[i+7] ); P(A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i + 7], K[i + 7]);
} }
for( i = 16; i < 64; i += 8 ) for (i = 16; i < 64; i += 8)
{ {
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i+0), K[i+0] ); P(A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i + 0), K[i + 0]);
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i+1), K[i+1] ); P(A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i + 1), K[i + 1]);
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i+2), K[i+2] ); P(A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i + 2), K[i + 2]);
P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i+3), K[i+3] ); P(A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i + 3), K[i + 3]);
P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i+4), K[i+4] ); P(A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i + 4), K[i + 4]);
P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i+5), K[i+5] ); P(A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i + 5), K[i + 5]);
P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i+6), K[i+6] ); P(A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i + 6), K[i + 6]);
P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i+7), K[i+7] ); P(A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i + 7), K[i + 7]);
} }
#endif /* MBEDTLS_SHA256_SMALLER */ #endif /* MBEDTLS_SHA256_SMALLER */
for( i = 0; i < 8; i++ ) for (i = 0; i < 8; i++)
ctx->state[i] += A[i]; ctx->state[i] += A[i];
return( 0 ); return (0);
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED) #if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha256_process( mbedtls_sha256_context *ctx, void mbedtls_sha256_process(mbedtls_sha256_context* ctx,
const unsigned char data[64] ) const unsigned char data[64])
{ {
mbedtls_internal_sha256_process( ctx, data ); mbedtls_internal_sha256_process(ctx, data);
} }
#endif #endif
#endif /* !MBEDTLS_SHA256_PROCESS_ALT */ #endif /* !MBEDTLS_SHA256_PROCESS_ALT */
@ -264,136 +318,135 @@ void mbedtls_sha256_process( mbedtls_sha256_context *ctx,
/* /*
* SHA-256 process buffer * SHA-256 process buffer
*/ */
int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, int mbedtls_sha256_update_ret(mbedtls_sha256_context* ctx,
const unsigned char *input, const unsigned char* input,
size_t ilen ) size_t ilen)
{ {
int ret; int ret;
size_t fill; size_t fill;
uint32_t left; uint32_t left;
SHA256_VALIDATE_RET( ctx != NULL ); SHA256_VALIDATE_RET(ctx != NULL);
SHA256_VALIDATE_RET( ilen == 0 || input != NULL ); SHA256_VALIDATE_RET(ilen == 0 || input != NULL);
if( ilen == 0 ) if (ilen == 0)
return( 0 ); return (0);
left = ctx->total[0] & 0x3F; left = ctx->total[0] & 0x3F;
fill = 64 - left; fill = 64 - left;
ctx->total[0] += static_cast<uint32_t>(ilen); ctx->total[0] += static_cast<uint32_t>(ilen);
ctx->total[0] &= 0xFFFFFFFF; ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < static_cast<uint32_t>(ilen) ) if (ctx->total[0] < static_cast<uint32_t>(ilen))
ctx->total[1]++; ctx->total[1]++;
if( left && ilen >= fill ) if (left && ilen >= fill)
{ {
memcpy( ctx->buffer + left, input, fill ); memcpy(ctx->buffer + left, input, fill);
if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0)
return( ret ); return (ret);
input += fill; input += fill;
ilen -= fill; ilen -= fill;
left = 0; left = 0;
} }
while( ilen >= 64 ) while (ilen >= 64)
{ {
if( ( ret = mbedtls_internal_sha256_process( ctx, input ) ) != 0 ) if ((ret = mbedtls_internal_sha256_process(ctx, input)) != 0)
return( ret ); return (ret);
input += 64; input += 64;
ilen -= 64; ilen -= 64;
} }
if( ilen > 0 ) if (ilen > 0)
memcpy( ctx->buffer + left, input, ilen ); memcpy(ctx->buffer + left, input, ilen);
return( 0 ); return (0);
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED) #if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha256_update( mbedtls_sha256_context *ctx, void mbedtls_sha256_update(mbedtls_sha256_context* ctx,
const unsigned char *input, const unsigned char* input,
size_t ilen ) size_t ilen)
{ {
mbedtls_sha256_update_ret( ctx, input, ilen ); mbedtls_sha256_update_ret(ctx, input, ilen);
} }
#endif #endif
/* /*
* SHA-256 final digest * SHA-256 final digest
*/ */
int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, int mbedtls_sha256_finish_ret(mbedtls_sha256_context* ctx,
unsigned char output[32] ) unsigned char output[32])
{ {
int ret; int ret;
uint32_t used; uint32_t used;
uint32_t high, low; uint32_t high, low;
SHA256_VALIDATE_RET( ctx != NULL ); SHA256_VALIDATE_RET(ctx != NULL);
SHA256_VALIDATE_RET( (unsigned char *)output != NULL ); SHA256_VALIDATE_RET((unsigned char*)output != NULL);
/* /*
* Add padding: 0x80 then 0x00 until 8 bytes remain for the length * Add padding: 0x80 then 0x00 until 8 bytes remain for the length
*/ */
used = ctx->total[0] & 0x3F; used = ctx->total[0] & 0x3F;
ctx->buffer[used++] = 0x80; ctx->buffer[used++] = 0x80;
if( used <= 56 ) if (used <= 56)
{ {
/* Enough room for padding + length in current block */ /* Enough room for padding + length in current block */
memset( ctx->buffer + used, 0, 56 - used ); memset(ctx->buffer + used, 0, 56 - used);
} }
else else
{ {
/* We'll need an extra block */ /* We'll need an extra block */
memset( ctx->buffer + used, 0, 64 - used ); memset(ctx->buffer + used, 0, 64 - used);
if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0)
return( ret ); return (ret);
memset( ctx->buffer, 0, 56 ); memset(ctx->buffer, 0, 56);
} }
/* /*
* Add message length * Add message length
*/ */
high = ( ctx->total[0] >> 29 ) high = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
| ( ctx->total[1] << 3 ); low = (ctx->total[0] << 3);
low = ( ctx->total[0] << 3 );
PUT_UINT32_BE( high, ctx->buffer, 56 ); PUT_UINT32_BE(high, ctx->buffer, 56);
PUT_UINT32_BE( low, ctx->buffer, 60 ); PUT_UINT32_BE(low, ctx->buffer, 60);
if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0)
return( ret ); return (ret);
/* /*
* Output final state * Output final state
*/ */
PUT_UINT32_BE( ctx->state[0], output, 0 ); PUT_UINT32_BE(ctx->state[0], output, 0);
PUT_UINT32_BE( ctx->state[1], output, 4 ); PUT_UINT32_BE(ctx->state[1], output, 4);
PUT_UINT32_BE( ctx->state[2], output, 8 ); PUT_UINT32_BE(ctx->state[2], output, 8);
PUT_UINT32_BE( ctx->state[3], output, 12 ); PUT_UINT32_BE(ctx->state[3], output, 12);
PUT_UINT32_BE( ctx->state[4], output, 16 ); PUT_UINT32_BE(ctx->state[4], output, 16);
PUT_UINT32_BE( ctx->state[5], output, 20 ); PUT_UINT32_BE(ctx->state[5], output, 20);
PUT_UINT32_BE( ctx->state[6], output, 24 ); PUT_UINT32_BE(ctx->state[6], output, 24);
if( ctx->is224 == 0 ) if (ctx->is224 == 0)
PUT_UINT32_BE( ctx->state[7], output, 28 ); PUT_UINT32_BE(ctx->state[7], output, 28);
return( 0 ); return (0);
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED) #if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, void mbedtls_sha256_finish(mbedtls_sha256_context* ctx,
unsigned char output[32] ) unsigned char output[32])
{ {
mbedtls_sha256_finish_ret( ctx, output ); mbedtls_sha256_finish_ret(ctx, output);
} }
#endif #endif
@ -402,41 +455,41 @@ void mbedtls_sha256_finish( mbedtls_sha256_context *ctx,
/* /*
* output = SHA-256( input buffer ) * output = SHA-256( input buffer )
*/ */
int mbedtls_sha256_ret( const unsigned char *input, int mbedtls_sha256_ret(const unsigned char* input,
size_t ilen, size_t ilen,
unsigned char output[32], unsigned char output[32],
int is224 ) int is224)
{ {
int ret; int ret;
mbedtls_sha256_context ctx; mbedtls_sha256_context ctx;
SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 ); SHA256_VALIDATE_RET(is224 == 0 || is224 == 1);
SHA256_VALIDATE_RET( ilen == 0 || input != NULL ); SHA256_VALIDATE_RET(ilen == 0 || input != NULL);
SHA256_VALIDATE_RET( (unsigned char *)output != NULL ); SHA256_VALIDATE_RET((unsigned char*)output != NULL);
mbedtls_sha256_init( &ctx ); mbedtls_sha256_init(&ctx);
if( ( ret = mbedtls_sha256_starts_ret( &ctx, is224 ) ) != 0 ) if ((ret = mbedtls_sha256_starts_ret(&ctx, is224)) != 0)
goto exit; goto exit;
if( ( ret = mbedtls_sha256_update_ret( &ctx, input, ilen ) ) != 0 ) if ((ret = mbedtls_sha256_update_ret(&ctx, input, ilen)) != 0)
goto exit; goto exit;
if( ( ret = mbedtls_sha256_finish_ret( &ctx, output ) ) != 0 ) if ((ret = mbedtls_sha256_finish_ret(&ctx, output)) != 0)
goto exit; goto exit;
exit: exit:
mbedtls_sha256_free( &ctx ); mbedtls_sha256_free(&ctx);
return( ret ); return (ret);
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED) #if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha256( const unsigned char *input, void mbedtls_sha256(const unsigned char* input,
size_t ilen, size_t ilen,
unsigned char output[32], unsigned char output[32],
int is224 ) int is224)
{ {
mbedtls_sha256_ret( input, ilen, output, is224 ); mbedtls_sha256_ret(input, ilen, output, is224);
} }
#endif #endif

View file

@ -33,243 +33,243 @@
#include <stdint.h> #include <stdint.h>
/* MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED is deprecated and should not be used. */ /* MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED -0x0037 /**< SHA-256 hardware accelerator failed */ #define MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED -0x0037 /**< SHA-256 hardware accelerator failed */
#define MBEDTLS_ERR_SHA256_BAD_INPUT_DATA -0x0074 /**< SHA-256 input data was malformed. */ #define MBEDTLS_ERR_SHA256_BAD_INPUT_DATA -0x0074 /**< SHA-256 input data was malformed. */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
#if !defined(MBEDTLS_SHA256_ALT) #if !defined(MBEDTLS_SHA256_ALT)
// Regular implementation // Regular implementation
// //
/** /**
* \brief The SHA-256 context structure. * \brief The SHA-256 context structure.
* *
* The structure is used both for SHA-256 and for SHA-224 * The structure is used both for SHA-256 and for SHA-224
* checksum calculations. The choice between these two is * checksum calculations. The choice between these two is
* made in the call to mbedtls_sha256_starts_ret(). * made in the call to mbedtls_sha256_starts_ret().
*/ */
typedef struct mbedtls_sha256_context typedef struct mbedtls_sha256_context
{ {
uint32_t total[2]; /*!< The number of Bytes processed. */ uint32_t total[2]; /*!< The number of Bytes processed. */
uint32_t state[8]; /*!< The intermediate digest state. */ uint32_t state[8]; /*!< The intermediate digest state. */
unsigned char buffer[64]; /*!< The data block being processed. */ unsigned char buffer[64]; /*!< The data block being processed. */
int is224; /*!< Determines which function to use: int is224; /*!< Determines which function to use:
0: Use SHA-256, or 1: Use SHA-224. */ 0: Use SHA-256, or 1: Use SHA-224. */
} } mbedtls_sha256_context;
mbedtls_sha256_context;
#else /* MBEDTLS_SHA256_ALT */ #else /* MBEDTLS_SHA256_ALT */
#include "sha256_alt.h" #include "sha256_alt.h"
#endif /* MBEDTLS_SHA256_ALT */ #endif /* MBEDTLS_SHA256_ALT */
/** /**
* \brief This function initializes a SHA-256 context. * \brief This function initializes a SHA-256 context.
* *
* \param ctx The SHA-256 context to initialize. This must not be \c NULL. * \param ctx The SHA-256 context to initialize. This must not be \c NULL.
*/ */
void mbedtls_sha256_init( mbedtls_sha256_context *ctx ); void mbedtls_sha256_init(mbedtls_sha256_context* ctx);
/** /**
* \brief This function clears a SHA-256 context. * \brief This function clears a SHA-256 context.
* *
* \param ctx The SHA-256 context to clear. This may be \c NULL, in which * \param ctx The SHA-256 context to clear. This may be \c NULL, in which
* case this function returns immediately. If it is not \c NULL, * case this function returns immediately. If it is not \c NULL,
* it must point to an initialized SHA-256 context. * it must point to an initialized SHA-256 context.
*/ */
void mbedtls_sha256_free( mbedtls_sha256_context *ctx ); void mbedtls_sha256_free(mbedtls_sha256_context* ctx);
/** /**
* \brief This function clones the state of a SHA-256 context. * \brief This function clones the state of a SHA-256 context.
* *
* \param dst The destination context. This must be initialized. * \param dst The destination context. This must be initialized.
* \param src The context to clone. This must be initialized. * \param src The context to clone. This must be initialized.
*/ */
void mbedtls_sha256_clone( mbedtls_sha256_context *dst, void mbedtls_sha256_clone(mbedtls_sha256_context* dst,
const mbedtls_sha256_context *src ); const mbedtls_sha256_context* src);
/** /**
* \brief This function starts a SHA-224 or SHA-256 checksum * \brief This function starts a SHA-224 or SHA-256 checksum
* calculation. * calculation.
* *
* \param ctx The context to use. This must be initialized. * \param ctx The context to use. This must be initialized.
* \param is224 This determines which function to use. This must be * \param is224 This determines which function to use. This must be
* either \c 0 for SHA-256, or \c 1 for SHA-224. * either \c 0 for SHA-256, or \c 1 for SHA-224.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return A negative error code on failure. * \return A negative error code on failure.
*/ */
int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ); int mbedtls_sha256_starts_ret(mbedtls_sha256_context* ctx, int is224);
/** /**
* \brief This function feeds an input buffer into an ongoing * \brief This function feeds an input buffer into an ongoing
* SHA-256 checksum calculation. * SHA-256 checksum calculation.
* *
* \param ctx The SHA-256 context. This must be initialized * \param ctx The SHA-256 context. This must be initialized
* and have a hash operation started. * and have a hash operation started.
* \param input The buffer holding the data. This must be a readable * \param input The buffer holding the data. This must be a readable
* buffer of length \p ilen Bytes. * buffer of length \p ilen Bytes.
* \param ilen The length of the input data in Bytes. * \param ilen The length of the input data in Bytes.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return A negative error code on failure. * \return A negative error code on failure.
*/ */
int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, int mbedtls_sha256_update_ret(mbedtls_sha256_context* ctx,
const unsigned char *input, const unsigned char* input,
size_t ilen ); size_t ilen);
/** /**
* \brief This function finishes the SHA-256 operation, and writes * \brief This function finishes the SHA-256 operation, and writes
* the result to the output buffer. * the result to the output buffer.
* *
* \param ctx The SHA-256 context. This must be initialized * \param ctx The SHA-256 context. This must be initialized
* and have a hash operation started. * and have a hash operation started.
* \param output The SHA-224 or SHA-256 checksum result. * \param output The SHA-224 or SHA-256 checksum result.
* This must be a writable buffer of length \c 32 Bytes. * This must be a writable buffer of length \c 32 Bytes.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return A negative error code on failure. * \return A negative error code on failure.
*/ */
int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, int mbedtls_sha256_finish_ret(mbedtls_sha256_context* ctx,
unsigned char output[32] ); unsigned char output[32]);
/** /**
* \brief This function processes a single data block within * \brief This function processes a single data block within
* the ongoing SHA-256 computation. This function is for * the ongoing SHA-256 computation. This function is for
* internal use only. * internal use only.
* *
* \param ctx The SHA-256 context. This must be initialized. * \param ctx The SHA-256 context. This must be initialized.
* \param data The buffer holding one block of data. This must * \param data The buffer holding one block of data. This must
* be a readable buffer of length \c 64 Bytes. * be a readable buffer of length \c 64 Bytes.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return A negative error code on failure. * \return A negative error code on failure.
*/ */
int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, int mbedtls_internal_sha256_process(mbedtls_sha256_context* ctx,
const unsigned char data[64] ); const unsigned char data[64]);
#if !defined(MBEDTLS_DEPRECATED_REMOVED) #if !defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING) #if defined(MBEDTLS_DEPRECATED_WARNING)
#define MBEDTLS_DEPRECATED __attribute__((deprecated)) #define MBEDTLS_DEPRECATED __attribute__((deprecated))
#else #else
#define MBEDTLS_DEPRECATED #define MBEDTLS_DEPRECATED
#endif #endif
/** /**
* \brief This function starts a SHA-224 or SHA-256 checksum * \brief This function starts a SHA-224 or SHA-256 checksum
* calculation. * calculation.
* *
* \deprecated Superseded by mbedtls_sha256_starts_ret() in 2.7.0. * \deprecated Superseded by mbedtls_sha256_starts_ret() in 2.7.0.
* *
* \param ctx The context to use. This must be initialized. * \param ctx The context to use. This must be initialized.
* \param is224 Determines which function to use. This must be * \param is224 Determines which function to use. This must be
* either \c 0 for SHA-256, or \c 1 for SHA-224. * either \c 0 for SHA-256, or \c 1 for SHA-224.
*/ */
MBEDTLS_DEPRECATED void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, MBEDTLS_DEPRECATED void mbedtls_sha256_starts(mbedtls_sha256_context* ctx,
int is224 ); int is224);
/** /**
* \brief This function feeds an input buffer into an ongoing * \brief This function feeds an input buffer into an ongoing
* SHA-256 checksum calculation. * SHA-256 checksum calculation.
* *
* \deprecated Superseded by mbedtls_sha256_update_ret() in 2.7.0. * \deprecated Superseded by mbedtls_sha256_update_ret() in 2.7.0.
* *
* \param ctx The SHA-256 context to use. This must be * \param ctx The SHA-256 context to use. This must be
* initialized and have a hash operation started. * initialized and have a hash operation started.
* \param input The buffer holding the data. This must be a readable * \param input The buffer holding the data. This must be a readable
* buffer of length \p ilen Bytes. * buffer of length \p ilen Bytes.
* \param ilen The length of the input data in Bytes. * \param ilen The length of the input data in Bytes.
*/ */
MBEDTLS_DEPRECATED void mbedtls_sha256_update( mbedtls_sha256_context *ctx, MBEDTLS_DEPRECATED void mbedtls_sha256_update(mbedtls_sha256_context* ctx,
const unsigned char *input, const unsigned char* input,
size_t ilen ); size_t ilen);
/** /**
* \brief This function finishes the SHA-256 operation, and writes * \brief This function finishes the SHA-256 operation, and writes
* the result to the output buffer. * the result to the output buffer.
* *
* \deprecated Superseded by mbedtls_sha256_finish_ret() in 2.7.0. * \deprecated Superseded by mbedtls_sha256_finish_ret() in 2.7.0.
* *
* \param ctx The SHA-256 context. This must be initialized and * \param ctx The SHA-256 context. This must be initialized and
* have a hash operation started. * have a hash operation started.
* \param output The SHA-224 or SHA-256 checksum result. This must be * \param output The SHA-224 or SHA-256 checksum result. This must be
* a writable buffer of length \c 32 Bytes. * a writable buffer of length \c 32 Bytes.
*/ */
MBEDTLS_DEPRECATED void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, MBEDTLS_DEPRECATED void mbedtls_sha256_finish(mbedtls_sha256_context* ctx,
unsigned char output[32] ); unsigned char output[32]);
/** /**
* \brief This function processes a single data block within * \brief This function processes a single data block within
* the ongoing SHA-256 computation. This function is for * the ongoing SHA-256 computation. This function is for
* internal use only. * internal use only.
* *
* \deprecated Superseded by mbedtls_internal_sha256_process() in 2.7.0. * \deprecated Superseded by mbedtls_internal_sha256_process() in 2.7.0.
* *
* \param ctx The SHA-256 context. This must be initialized. * \param ctx The SHA-256 context. This must be initialized.
* \param data The buffer holding one block of data. This must be * \param data The buffer holding one block of data. This must be
* a readable buffer of size \c 64 Bytes. * a readable buffer of size \c 64 Bytes.
*/ */
MBEDTLS_DEPRECATED void mbedtls_sha256_process( mbedtls_sha256_context *ctx, MBEDTLS_DEPRECATED void mbedtls_sha256_process(mbedtls_sha256_context* ctx,
const unsigned char data[64] ); const unsigned char data[64]);
#undef MBEDTLS_DEPRECATED #undef MBEDTLS_DEPRECATED
#endif /* !MBEDTLS_DEPRECATED_REMOVED */ #endif /* !MBEDTLS_DEPRECATED_REMOVED */
/** /**
* \brief This function calculates the SHA-224 or SHA-256 * \brief This function calculates the SHA-224 or SHA-256
* checksum of a buffer. * checksum of a buffer.
* *
* The function allocates the context, performs the * The function allocates the context, performs the
* calculation, and frees the context. * calculation, and frees the context.
* *
* The SHA-256 result is calculated as * The SHA-256 result is calculated as
* output = SHA-256(input buffer). * output = SHA-256(input buffer).
* *
* \param input The buffer holding the data. This must be a readable * \param input The buffer holding the data. This must be a readable
* buffer of length \p ilen Bytes. * buffer of length \p ilen Bytes.
* \param ilen The length of the input data in Bytes. * \param ilen The length of the input data in Bytes.
* \param output The SHA-224 or SHA-256 checksum result. This must * \param output The SHA-224 or SHA-256 checksum result. This must
* be a writable buffer of length \c 32 Bytes. * be a writable buffer of length \c 32 Bytes.
* \param is224 Determines which function to use. This must be * \param is224 Determines which function to use. This must be
* either \c 0 for SHA-256, or \c 1 for SHA-224. * either \c 0 for SHA-256, or \c 1 for SHA-224.
*/ */
int mbedtls_sha256_ret( const unsigned char *input, int mbedtls_sha256_ret(const unsigned char* input,
size_t ilen, size_t ilen,
unsigned char output[32], unsigned char output[32],
int is224 ); int is224);
#if !defined(MBEDTLS_DEPRECATED_REMOVED) #if !defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING) #if defined(MBEDTLS_DEPRECATED_WARNING)
#define MBEDTLS_DEPRECATED __attribute__((deprecated)) #define MBEDTLS_DEPRECATED __attribute__((deprecated))
#else #else
#define MBEDTLS_DEPRECATED #define MBEDTLS_DEPRECATED
#endif #endif
/** /**
* \brief This function calculates the SHA-224 or SHA-256 checksum * \brief This function calculates the SHA-224 or SHA-256 checksum
* of a buffer. * of a buffer.
* *
* The function allocates the context, performs the * The function allocates the context, performs the
* calculation, and frees the context. * calculation, and frees the context.
* *
* The SHA-256 result is calculated as * The SHA-256 result is calculated as
* output = SHA-256(input buffer). * output = SHA-256(input buffer).
* *
* \deprecated Superseded by mbedtls_sha256_ret() in 2.7.0. * \deprecated Superseded by mbedtls_sha256_ret() in 2.7.0.
* *
* \param input The buffer holding the data. This must be a readable * \param input The buffer holding the data. This must be a readable
* buffer of length \p ilen Bytes. * buffer of length \p ilen Bytes.
* \param ilen The length of the input data in Bytes. * \param ilen The length of the input data in Bytes.
* \param output The SHA-224 or SHA-256 checksum result. This must be * \param output The SHA-224 or SHA-256 checksum result. This must be
* a writable buffer of length \c 32 Bytes. * a writable buffer of length \c 32 Bytes.
* \param is224 Determines which function to use. This must be either * \param is224 Determines which function to use. This must be either
* \c 0 for SHA-256, or \c 1 for SHA-224. * \c 0 for SHA-256, or \c 1 for SHA-224.
*/ */
MBEDTLS_DEPRECATED void mbedtls_sha256( const unsigned char *input, MBEDTLS_DEPRECATED void mbedtls_sha256(const unsigned char* input,
size_t ilen, size_t ilen,
unsigned char output[32], unsigned char output[32],
int is224 ); int is224);
#undef MBEDTLS_DEPRECATED #undef MBEDTLS_DEPRECATED
#endif /* !MBEDTLS_DEPRECATED_REMOVED */ #endif /* !MBEDTLS_DEPRECATED_REMOVED */

View file

@ -14,7 +14,7 @@
LOG_CHANNEL(edat_log, "EDAT"); LOG_CHANNEL(edat_log, "EDAT");
void generate_key(int crypto_mode, int version, unsigned char *key_final, unsigned char *iv_final, unsigned char *key, unsigned char *iv) void generate_key(int crypto_mode, int version, unsigned char* key_final, unsigned char* iv_final, unsigned char* key, unsigned char* iv)
{ {
int mode = crypto_mode & 0xF0000000; int mode = crypto_mode & 0xF0000000;
uchar temp_iv[16]{}; uchar temp_iv[16]{};
@ -42,7 +42,7 @@ void generate_key(int crypto_mode, int version, unsigned char *key_final, unsign
} }
} }
void generate_hash(int hash_mode, int version, unsigned char *hash_final, unsigned char *hash) void generate_hash(int hash_mode, int version, unsigned char* hash_final, unsigned char* hash)
{ {
int mode = hash_mode & 0xF0000000; int mode = hash_mode & 0xF0000000;
uchar temp_iv[16]{}; uchar temp_iv[16]{};
@ -67,7 +67,7 @@ void generate_hash(int hash_mode, int version, unsigned char *hash_final, unsign
}; };
} }
bool decrypt(int hash_mode, int crypto_mode, int version, unsigned char *in, unsigned char *out, usz length, unsigned char *key, unsigned char *iv, unsigned char *hash, unsigned char *test_hash) bool decrypt(int hash_mode, int crypto_mode, int version, unsigned char* in, unsigned char* out, usz length, unsigned char* key, unsigned char* iv, unsigned char* hash, unsigned char* test_hash)
{ {
// Setup buffers for key, iv and hash. // Setup buffers for key, iv and hash.
unsigned char key_final[0x10] = {}; unsigned char key_final[0x10] = {};
@ -82,11 +82,11 @@ bool decrypt(int hash_mode, int crypto_mode, int version, unsigned char *in, uns
else else
generate_hash(hash_mode, version, hash_final_10, hash); generate_hash(hash_mode, version, hash_final_10, hash);
if ((crypto_mode & 0xFF) == 0x01) // No algorithm. if ((crypto_mode & 0xFF) == 0x01) // No algorithm.
{ {
memcpy(out, in, length); memcpy(out, in, length);
} }
else if ((crypto_mode & 0xFF) == 0x02) // AES128-CBC else if ((crypto_mode & 0xFF) == 0x02) // AES128-CBC
{ {
aescbc128_decrypt(key_final, iv_final, in, out, length); aescbc128_decrypt(key_final, iv_final, in, out, length);
} }
@ -100,11 +100,11 @@ bool decrypt(int hash_mode, int crypto_mode, int version, unsigned char *in, uns
{ {
return hmac_hash_compare(hash_final_14, 0x14, in, length, test_hash, 0x14); return hmac_hash_compare(hash_final_14, 0x14, in, length, test_hash, 0x14);
} }
else if ((hash_mode & 0xFF) == 0x02) // 0x10 AES-CMAC else if ((hash_mode & 0xFF) == 0x02) // 0x10 AES-CMAC
{ {
return cmac_hash_compare(hash_final_10, 0x10, in, length, test_hash, 0x10); return cmac_hash_compare(hash_final_10, 0x10, in, length, test_hash, 0x10);
} }
else if ((hash_mode & 0xFF) == 0x04) //0x10 SHA1-HMAC else if ((hash_mode & 0xFF) == 0x04) // 0x10 SHA1-HMAC
{ {
return hmac_hash_compare(hash_final_10, 0x10, in, length, test_hash, 0x10); return hmac_hash_compare(hash_final_10, 0x10, in, length, test_hash, 0x10);
} }
@ -143,10 +143,10 @@ std::tuple<u64, s32, s32> dec_section(unsigned char* metadata)
return std::make_tuple(offset, length, compression_end); return std::make_tuple(offset, length, compression_end);
} }
u128 get_block_key(int block, NPD_HEADER *npd) u128 get_block_key(int block, NPD_HEADER* npd)
{ {
unsigned char empty_key[0x10] = {}; unsigned char empty_key[0x10] = {};
unsigned char *src_key = (npd->version <= 1) ? empty_key : npd->dev_hash; unsigned char* src_key = (npd->version <= 1) ? empty_key : npd->dev_hash;
u128 dest_key{}; u128 dest_key{};
std::memcpy(&dest_key, src_key, 0xC); std::memcpy(&dest_key, src_key, 0xC);
@ -158,15 +158,15 @@ u128 get_block_key(int block, NPD_HEADER *npd)
// for out data, allocate a buffer the size of 'edat->block_size' // for out data, allocate a buffer the size of 'edat->block_size'
// Also, set 'in file' to the beginning of the encrypted data, which may be offset if inside another file, but normally just reset to beginning of file // Also, set 'in file' to the beginning of the encrypted data, which may be offset if inside another file, but normally just reset to beginning of file
// returns number of bytes written, -1 for error // returns number of bytes written, -1 for error
s64 decrypt_block(const fs::file* in, u8* out, EDAT_HEADER *edat, NPD_HEADER *npd, u8* crypt_key, u32 block_num, u32 total_blocks, u64 size_left, bool is_out_buffer_aligned = false) s64 decrypt_block(const fs::file* in, u8* out, EDAT_HEADER* edat, NPD_HEADER* npd, u8* crypt_key, u32 block_num, u32 total_blocks, u64 size_left, bool is_out_buffer_aligned = false)
{ {
// Get metadata info and setup buffers. // Get metadata info and setup buffers.
const int metadata_section_size = ((edat->flags & EDAT_COMPRESSED_FLAG) != 0 || (edat->flags & EDAT_FLAG_0x20) != 0) ? 0x20 : 0x10; const int metadata_section_size = ((edat->flags & EDAT_COMPRESSED_FLAG) != 0 || (edat->flags & EDAT_FLAG_0x20) != 0) ? 0x20 : 0x10;
const int metadata_offset = 0x100; const int metadata_offset = 0x100;
u8 hash[0x10] = { 0 }; u8 hash[0x10] = {0};
u8 key_result[0x10] = { 0 }; u8 key_result[0x10] = {0};
u8 hash_result[0x14] = { 0 }; u8 hash_result[0x14] = {0};
u64 offset = 0; u64 offset = 0;
u64 metadata_sec_offset = 0; u64 metadata_sec_offset = 0;
@ -258,7 +258,7 @@ s64 decrypt_block(const fs::file* in, u8* out, EDAT_HEADER *edat, NPD_HEADER *np
if ((edat->flags & EDAT_FLAG_0x10) != 0) if ((edat->flags & EDAT_FLAG_0x10) != 0)
{ {
aesecb128_encrypt(crypt_key, key_result, hash); // If FLAG 0x10 is set, encrypt again to get the final hash. aesecb128_encrypt(crypt_key, key_result, hash); // If FLAG 0x10 is set, encrypt again to get the final hash.
} }
else else
{ {
@ -344,10 +344,10 @@ s64 decrypt_block(const fs::file* in, u8* out, EDAT_HEADER *edat, NPD_HEADER *np
// set file offset to beginning before calling // set file offset to beginning before calling
bool check_data(u8* key, EDAT_HEADER* edat, NPD_HEADER* npd, const fs::file* f, bool verbose) bool check_data(u8* key, EDAT_HEADER* edat, NPD_HEADER* npd, const fs::file* f, bool verbose)
{ {
u8 header[0xA0] = { 0 }; u8 header[0xA0] = {0};
u8 empty_header[0xA0] = { 0 }; u8 empty_header[0xA0] = {0};
u8 header_hash[0x10] = { 0 }; u8 header_hash[0x10] = {0};
u8 metadata_hash[0x10] = { 0 }; u8 metadata_hash[0x10] = {0};
const u64 file_offset = f->pos(); const u64 file_offset = f->pos();
@ -402,8 +402,8 @@ bool check_data(u8* key, EDAT_HEADER* edat, NPD_HEADER* npd, const fs::file* f,
} }
// Setup header key and iv buffers. // Setup header key and iv buffers.
unsigned char header_key[0x10] = { 0 }; unsigned char header_key[0x10] = {0};
unsigned char header_iv[0x10] = { 0 }; unsigned char header_iv[0x10] = {0};
// Test the header hash (located at offset 0xA0). // Test the header hash (located at offset 0xA0).
if (!decrypt(hash_mode, crypto_mode, (npd->version == 4), header, empty_header, 0xA0, header_key, header_iv, key, header_hash)) if (!decrypt(hash_mode, crypto_mode, (npd->version == 4), header, empty_header, 0xA0, header_key, header_iv, key, header_hash))
@ -474,12 +474,12 @@ bool check_data(u8* key, EDAT_HEADER* edat, NPD_HEADER* npd, const fs::file* f,
if ((edat->flags & EDAT_DEBUG_DATA_FLAG) == 0) if ((edat->flags & EDAT_DEBUG_DATA_FLAG) == 0)
{ {
// Setup buffers. // Setup buffers.
unsigned char metadata_signature[0x28] = { 0 }; unsigned char metadata_signature[0x28] = {0};
unsigned char header_signature[0x28] = { 0 }; unsigned char header_signature[0x28] = {0};
unsigned char signature_hash[20] = { 0 }; unsigned char signature_hash[20] = {0};
unsigned char signature_r[0x15] = { 0 }; unsigned char signature_r[0x15] = {0};
unsigned char signature_s[0x15] = { 0 }; unsigned char signature_s[0x15] = {0};
unsigned char zero_buf[0x15] = { 0 }; unsigned char zero_buf[0x15] = {0};
// Setup ECDSA curve and public key. // Setup ECDSA curve and public key.
ecdsa_set_curve(VSH_CURVE_P, VSH_CURVE_A, VSH_CURVE_B, VSH_CURVE_N, VSH_CURVE_GX, VSH_CURVE_GY); ecdsa_set_curve(VSH_CURVE_P, VSH_CURVE_A, VSH_CURVE_B, VSH_CURVE_N, VSH_CURVE_GX, VSH_CURVE_GY);
@ -503,7 +503,7 @@ bool check_data(u8* key, EDAT_HEADER* edat, NPD_HEADER* npd, const fs::file* f,
else else
{ {
// Setup signature hash. // Setup signature hash.
if ((edat->flags & EDAT_FLAG_0x20) != 0) //Sony failed again, they used buffer from 0x100 with half size of real metadata. if ((edat->flags & EDAT_FLAG_0x20) != 0) // Sony failed again, they used buffer from 0x100 with half size of real metadata.
{ {
const usz metadata_buf_size = block_num * 0x10; const usz metadata_buf_size = block_num * 0x10;
@ -553,7 +553,7 @@ bool check_data(u8* key, EDAT_HEADER* edat, NPD_HEADER* npd, const fs::file* f,
return true; return true;
} }
bool validate_dev_klic(const u8* klicensee, NPD_HEADER *npd) bool validate_dev_klic(const u8* klicensee, NPD_HEADER* npd)
{ {
if ((npd->license & 0x3) != 0x3) if ((npd->license & 0x3) != 0x3)
{ {
@ -718,7 +718,7 @@ bool VerifyEDATHeaderWithKLicense(const fs::file& input, const std::string& inpu
} }
// Decrypts full file // Decrypts full file
fs::file DecryptEDAT(const fs::file& input, const std::string& input_file_name, int mode, u8 *custom_klic) fs::file DecryptEDAT(const fs::file& input, const std::string& input_file_name, int mode, u8* custom_klic)
{ {
if (!input) if (!input)
{ {
@ -758,16 +758,16 @@ fs::file DecryptEDAT(const fs::file& input, const std::string& input_file_name,
memcpy(&devklic, NP_PSP_KEY_2, 0x10); memcpy(&devklic, NP_PSP_KEY_2, 0x10);
break; break;
case 8: case 8:
{
if (custom_klic != NULL)
memcpy(&devklic, custom_klic, 0x10);
else
{ {
if (custom_klic != NULL) edat_log.error("Invalid custom klic!");
memcpy(&devklic, custom_klic, 0x10); return fs::file{};
else
{
edat_log.error("Invalid custom klic!");
return fs::file{};
}
break;
} }
break;
}
default: default:
edat_log.error("Invalid mode!"); edat_log.error("Invalid mode!");
return fs::file{}; return fs::file{};
@ -829,7 +829,7 @@ bool EDATADecrypter::ReadHeader()
// //
} }
// Type 2: Use key from RAP file (RIF key). (also used for type 1 at the moment) // Type 2: Use key from RAP file (RIF key). (also used for type 1 at the moment)
else else
{ {
const std::string rap_path = rpcs3::utils::get_rap_file_path(npdHeader.content_id); const std::string rap_path = rpcs3::utils::get_rap_file_path(npdHeader.content_id);
@ -853,7 +853,7 @@ bool EDATADecrypter::ReadHeader()
// k the ecdsa_verify function in this check_data function takes a ridiculous amount of time // k the ecdsa_verify function in this check_data function takes a ridiculous amount of time
// like it slows down load time by a factor of x20, at least, so its ignored for now // like it slows down load time by a factor of x20, at least, so its ignored for now
//if (!check_data(reinterpret_cast<u8*>(&dec_key), &edatHeader, &npdHeader, &edata_file, false)) // if (!check_data(reinterpret_cast<u8*>(&dec_key), &edatHeader, &npdHeader, &edata_file, false))
//{ //{
// edat_log.error("NPDRM check_data() failed!"); // edat_log.error("NPDRM check_data() failed!");
// return false; // return false;

View file

@ -20,7 +20,10 @@ struct loaded_npdrm_keys
void install_decryption_key(u128 key) void install_decryption_key(u128 key)
{ {
dec_keys_pos.atomic_op([&](u64& pos) { dec_keys[pos++ % std::size(dec_keys)] = key; }); dec_keys_pos.atomic_op([&](u64& pos)
{
dec_keys[pos++ % std::size(dec_keys)] = key;
});
} }
// TODO: Check if correct for ELF files usage // TODO: Check if correct for ELF files usage
@ -59,10 +62,10 @@ struct EDAT_HEADER
}; };
// Decrypts full file, or null/empty file // Decrypts full file, or null/empty file
extern fs::file DecryptEDAT(const fs::file& input, const std::string& input_file_name, int mode, u8 *custom_klic); extern fs::file DecryptEDAT(const fs::file& input, const std::string& input_file_name, int mode, u8* custom_klic);
extern void read_npd_edat_header(const fs::file* input, NPD_HEADER& NPD, EDAT_HEADER& EDAT); extern void read_npd_edat_header(const fs::file* input, NPD_HEADER& NPD, EDAT_HEADER& EDAT);
extern bool VerifyEDATHeaderWithKLicense(const fs::file& input, const std::string& input_file_name, const u8* custom_klic, NPD_HEADER *npd_out = nullptr); extern bool VerifyEDATHeaderWithKLicense(const fs::file& input, const std::string& input_file_name, const u8* custom_klic, NPD_HEADER* npd_out = nullptr);
u128 GetEdatRifKeyFromRapFile(const fs::file& rap_file); u128 GetEdatRifKeyFromRapFile(const fs::file& rap_file);
@ -84,20 +87,12 @@ struct EDATADecrypter final : fs::file_base
public: public:
EDATADecrypter(fs::file&& input, u128 dec_key = {}, std::string file_name = {}, bool is_key_final = true) noexcept EDATADecrypter(fs::file&& input, u128 dec_key = {}, std::string file_name = {}, bool is_key_final = true) noexcept
: m_edata_file(std::move(input)) : m_edata_file(std::move(input)), edata_file(m_edata_file), m_file_name(std::move(file_name)), m_is_key_final(is_key_final), dec_key(dec_key)
, edata_file(m_edata_file)
, m_file_name(std::move(file_name))
, m_is_key_final(is_key_final)
, dec_key(dec_key)
{ {
} }
EDATADecrypter(const fs::file& input, u128 dec_key = {}, std::string file_name = {}, bool is_key_final = true) noexcept EDATADecrypter(const fs::file& input, u128 dec_key = {}, std::string file_name = {}, bool is_key_final = true) noexcept
: m_edata_file(fs::file{}) : m_edata_file(fs::file{}), edata_file(input), m_file_name(std::move(file_name)), m_is_key_final(is_key_final), dec_key(dec_key)
, edata_file(input)
, m_file_name(std::move(file_name))
, m_is_key_final(is_key_final)
, dec_key(dec_key)
{ {
} }
@ -140,7 +135,8 @@ public:
const s64 new_pos = const s64 new_pos =
whence == fs::seek_set ? offset : whence == fs::seek_set ? offset :
whence == fs::seek_cur ? offset + pos : whence == fs::seek_cur ? offset + pos :
whence == fs::seek_end ? offset + size() : -1; whence == fs::seek_end ? offset + size() :
-1;
if (new_pos < 0) if (new_pos < 0)
{ {
@ -152,7 +148,10 @@ public:
return pos; return pos;
} }
u64 size() override { return file_size; } u64 size() override
{
return file_size;
}
fs::file_id get_id() override fs::file_id get_id() override
{ {

View file

@ -17,8 +17,7 @@
LOG_CHANNEL(pkg_log, "PKG"); LOG_CHANNEL(pkg_log, "PKG");
package_reader::package_reader(const std::string& path, fs::file file) package_reader::package_reader(const std::string& path, fs::file file)
: m_path(path) : m_path(path), m_file(std::move(file))
, m_file(std::move(file))
{ {
if (!m_file && !m_file.open(path)) if (!m_file && !m_file.open(path))
{ {
@ -108,10 +107,10 @@ bool package_reader::read_header()
pkg_log.notice("Extended header: main_and_ext_headers_hmac_offset = 0x%x = %d", ext_header.main_and_ext_headers_hmac_offset, ext_header.main_and_ext_headers_hmac_offset); pkg_log.notice("Extended header: main_and_ext_headers_hmac_offset = 0x%x = %d", ext_header.main_and_ext_headers_hmac_offset, ext_header.main_and_ext_headers_hmac_offset);
pkg_log.notice("Extended header: metadata_header_hmac_offset = 0x%x = %d", ext_header.metadata_header_hmac_offset, ext_header.metadata_header_hmac_offset); pkg_log.notice("Extended header: metadata_header_hmac_offset = 0x%x = %d", ext_header.metadata_header_hmac_offset, ext_header.metadata_header_hmac_offset);
pkg_log.notice("Extended header: tail_offset = 0x%x = %d", ext_header.tail_offset, ext_header.tail_offset); pkg_log.notice("Extended header: tail_offset = 0x%x = %d", ext_header.tail_offset, ext_header.tail_offset);
//pkg_log.notice("Extended header: padding1 = 0x%x = %d", ext_header.padding1, ext_header.padding1); // pkg_log.notice("Extended header: padding1 = 0x%x = %d", ext_header.padding1, ext_header.padding1);
pkg_log.notice("Extended header: pkg_key_id = 0x%x = %d", ext_header.pkg_key_id, ext_header.pkg_key_id); pkg_log.notice("Extended header: pkg_key_id = 0x%x = %d", ext_header.pkg_key_id, ext_header.pkg_key_id);
pkg_log.notice("Extended header: full_header_hmac_offset = 0x%x = %d", ext_header.full_header_hmac_offset, ext_header.full_header_hmac_offset); pkg_log.notice("Extended header: full_header_hmac_offset = 0x%x = %d", ext_header.full_header_hmac_offset, ext_header.full_header_hmac_offset);
//pkg_log.notice("Extended header: padding2 = 0x%x = %d", ext_header.padding2, ext_header.padding2); // pkg_log.notice("Extended header: padding2 = 0x%x = %d", ext_header.padding2, ext_header.padding2);
} }
if (m_header.pkg_magic != std::bit_cast<le_t<u32>>("\x7FPKG"_u32)) if (m_header.pkg_magic != std::bit_cast<le_t<u32>>("\x7FPKG"_u32))
@ -128,7 +127,7 @@ bool package_reader::read_header()
switch (const u16 type = m_header.pkg_type) switch (const u16 type = m_header.pkg_type)
{ {
case PKG_RELEASE_TYPE_DEBUG: break; case PKG_RELEASE_TYPE_DEBUG: break;
case PKG_RELEASE_TYPE_RELEASE: break; case PKG_RELEASE_TYPE_RELEASE: break;
default: default:
{ {
@ -500,7 +499,9 @@ bool package_reader::set_decryption_key()
// TODO: Not all the keys seem to match the content types. I was only able to install a dlc (0x16) with PKG_AES_KEY_VITA_1 // TODO: Not all the keys seem to match the content types. I was only able to install a dlc (0x16) with PKG_AES_KEY_VITA_1
aes_context ctx; aes_context ctx;
aes_setkey_enc(&ctx, m_metadata.content_type == 0x15u ? PKG_AES_KEY_VITA_1 : m_metadata.content_type == 0x16u ? PKG_AES_KEY_VITA_2 : PKG_AES_KEY_VITA_3, 128); aes_setkey_enc(&ctx, m_metadata.content_type == 0x15u ? PKG_AES_KEY_VITA_1 : m_metadata.content_type == 0x16u ? PKG_AES_KEY_VITA_2 :
PKG_AES_KEY_VITA_3,
128);
aes_crypt_ecb(&ctx, AES_ENCRYPT, reinterpret_cast<const uchar*>(&m_header.klicensee), m_dec_key.data()); aes_crypt_ecb(&ctx, AES_ENCRYPT, reinterpret_cast<const uchar*>(&m_header.klicensee), m_dec_key.data());
return true; return true;
} }
@ -661,9 +662,9 @@ package_install_result package_reader::check_target_app_version() const
return {package_install_result::error_type::other}; return {package_install_result::error_type::other};
} }
const auto category = psf::get_string(m_psf, "CATEGORY", ""); const auto category = psf::get_string(m_psf, "CATEGORY", "");
const auto title_id = psf::get_string(m_psf, "TITLE_ID", ""); const auto title_id = psf::get_string(m_psf, "TITLE_ID", "");
const auto app_ver = psf::get_string(m_psf, "APP_VER", ""); const auto app_ver = psf::get_string(m_psf, "APP_VER", "");
const auto target_app_ver = psf::get_string(m_psf, "TARGET_APP_VER", ""); const auto target_app_ver = psf::get_string(m_psf, "TARGET_APP_VER", "");
if (category != "GD") if (category != "GD")
@ -708,7 +709,7 @@ package_install_result package_reader::check_target_app_version() const
const auto installed_psf = psf::load_object(installed_sfo_file, sfo_path); const auto installed_psf = psf::load_object(installed_sfo_file, sfo_path);
const auto installed_title_id = psf::get_string(installed_psf, "TITLE_ID", ""); const auto installed_title_id = psf::get_string(installed_psf, "TITLE_ID", "");
const auto installed_app_ver = psf::get_string(installed_psf, "APP_VER", ""); const auto installed_app_ver = psf::get_string(installed_psf, "APP_VER", "");
if (title_id != installed_title_id || installed_app_ver.empty()) if (title_id != installed_title_id || installed_app_ver.empty())
{ {
@ -915,14 +916,12 @@ bool package_reader::fill_data(std::map<std::string, install_entry*>& all_instal
auto map_ptr = &*all_install_entries.try_emplace(true_path).first; auto map_ptr = &*all_install_entries.try_emplace(true_path).first;
m_install_entries.push_back({ m_install_entries.push_back({.weak_reference = map_ptr,
.weak_reference = map_ptr,
.name = std::string(name), .name = std::string(name),
.file_offset = entry.file_offset, .file_offset = entry.file_offset,
.file_size = entry.file_size, .file_size = entry.file_size,
.type = entry.type, .type = entry.type,
.pad = entry.pad .pad = entry.pad});
});
if (map_ptr->second && !(entry.type & PKG_FILE_ENTRY_OVERWRITE)) if (map_ptr->second && !(entry.type & PKG_FILE_ENTRY_OVERWRITE))
{ {
@ -946,7 +945,7 @@ bool package_reader::fill_data(std::map<std::string, install_entry*>& all_instal
return true; return true;
} }
fs::file DecryptEDAT(const fs::file& input, const std::string& input_file_name, int mode, u8 *custom_klic); fs::file DecryptEDAT(const fs::file& input, const std::string& input_file_name, int mode, u8* custom_klic);
void package_reader::extract_worker() void package_reader::extract_worker()
{ {
@ -956,15 +955,16 @@ void package_reader::extract_worker()
{ {
// Make sure m_entry_indexer does not exceed m_install_entries // Make sure m_entry_indexer does not exceed m_install_entries
const usz index = m_entry_indexer.fetch_op([this](usz& v) const usz index = m_entry_indexer.fetch_op([this](usz& v)
{ {
if (v < m_install_entries.size()) if (v < m_install_entries.size())
{ {
v++; v++;
return true; return true;
} }
return false; return false;
}).first; })
.first;
if (index >= m_install_entries.size()) if (index >= m_install_entries.size())
{ {
@ -1027,7 +1027,7 @@ void package_reader::extract_worker()
pkg_log.warning("NPDRM EDAT!"); pkg_log.warning("NPDRM EDAT!");
} }
if (fs::file out{ path, did_overwrite ? fs::rewrite : fs::write_new }) if (fs::file out{path, did_overwrite ? fs::rewrite : fs::write_new})
{ {
bool extract_success = true; bool extract_success = true;
@ -1038,9 +1038,7 @@ void package_reader::extract_worker()
usz m_pos; usz m_pos;
explicit pkg_file_reader(std::function<u64(u64, void* buffer, u64)> read_func, const install_entry& entry) noexcept explicit pkg_file_reader(std::function<u64(u64, void* buffer, u64)> read_func, const install_entry& entry) noexcept
: m_read_func(std::move(read_func)) : m_read_func(std::move(read_func)), m_entry(entry), m_pos(0)
, m_entry(entry)
, m_pos(0)
{ {
} }
@ -1078,7 +1076,8 @@ void package_reader::extract_worker()
const s64 new_pos = const s64 new_pos =
whence == fs::seek_set ? offset : whence == fs::seek_set ? offset :
whence == fs::seek_cur ? offset + m_pos : whence == fs::seek_cur ? offset + m_pos :
whence == fs::seek_end ? offset + size() : -1; whence == fs::seek_end ? offset + size() :
-1;
if (new_pos < 0) if (new_pos < 0)
{ {
@ -1107,78 +1106,79 @@ void package_reader::extract_worker()
read_cache.clear(); read_cache.clear();
auto reader = std::make_unique<pkg_file_reader>([&, cache_off = u64{umax}](usz pos, void* ptr, usz size) mutable -> u64 auto reader = std::make_unique<pkg_file_reader>([&, cache_off = u64{umax}](usz pos, void* ptr, usz size) mutable -> u64
{
if (pos >= entry.file_size || !size)
{ {
return 0; if (pos >= entry.file_size || !size)
}
size = std::min<u64>(entry.file_size - pos, size);
u64 size_cache_end = 0;
u64 read_size = 0;
// Check if exists in cache
if (!read_cache.empty() && cache_off <= pos && pos < cache_off + read_cache.size())
{
read_size = std::min<u64>(pos + size, cache_off + read_cache.size()) - pos;
std::memcpy(ptr, read_cache.data() + (pos - cache_off), read_size);
pos += read_size;
}
else if (!read_cache.empty() && cache_off < pos + size && cache_off + read_cache.size() >= pos + size)
{
size_cache_end = size - (std::max<u64>(cache_off, pos) - pos);
std::memcpy(static_cast<u8*>(ptr) + (cache_off - pos), read_cache.data(), size_cache_end);
size -= size_cache_end;
}
if (pos >= entry.file_size || !size)
{
return read_size + size_cache_end;
}
// Try to cache for later
if (size <= BUF_SIZE && !size_cache_end && !read_size)
{
const u64 block_size = std::min<u64>({BUF_SIZE, std::max<u64>(size * 5 / 3, 65536), entry.file_size - pos});
read_cache.resize(block_size + BUF_PADDING);
cache_off = pos;
const usz advance_size = decrypt(entry.file_offset + pos, block_size, is_psp ? PKG_AES_KEY2 : m_dec_key.data(), read_cache.data());
if (!advance_size)
{ {
cache_off = umax;
return 0; return 0;
} }
read_cache.resize(advance_size); size = std::min<u64>(entry.file_size - pos, size);
size = std::min<usz>(advance_size, size); u64 size_cache_end = 0;
std::memcpy(ptr, read_cache.data(), size); u64 read_size = 0;
return size;
}
while (read_size < size) // Check if exists in cache
{ if (!read_cache.empty() && cache_off <= pos && pos < cache_off + read_cache.size())
const u64 block_size = std::min<u64>(BUF_SIZE, size - read_size);
const usz advance_size = decrypt(entry.file_offset + pos, block_size, is_psp ? PKG_AES_KEY2 : m_dec_key.data(), static_cast<u8*>(ptr) + read_size);
if (!advance_size)
{ {
break; read_size = std::min<u64>(pos + size, cache_off + read_cache.size()) - pos;
std::memcpy(ptr, read_cache.data() + (pos - cache_off), read_size);
pos += read_size;
}
else if (!read_cache.empty() && cache_off < pos + size && cache_off + read_cache.size() >= pos + size)
{
size_cache_end = size - (std::max<u64>(cache_off, pos) - pos);
std::memcpy(static_cast<u8*>(ptr) + (cache_off - pos), read_cache.data(), size_cache_end);
size -= size_cache_end;
} }
read_size += advance_size; if (pos >= entry.file_size || !size)
pos += advance_size; {
} return read_size + size_cache_end;
}
return read_size + size_cache_end; // Try to cache for later
}, entry); if (size <= BUF_SIZE && !size_cache_end && !read_size)
{
const u64 block_size = std::min<u64>({BUF_SIZE, std::max<u64>(size * 5 / 3, 65536), entry.file_size - pos});
read_cache.resize(block_size + BUF_PADDING);
cache_off = pos;
const usz advance_size = decrypt(entry.file_offset + pos, block_size, is_psp ? PKG_AES_KEY2 : m_dec_key.data(), read_cache.data());
if (!advance_size)
{
cache_off = umax;
return 0;
}
read_cache.resize(advance_size);
size = std::min<usz>(advance_size, size);
std::memcpy(ptr, read_cache.data(), size);
return size;
}
while (read_size < size)
{
const u64 block_size = std::min<u64>(BUF_SIZE, size - read_size);
const usz advance_size = decrypt(entry.file_offset + pos, block_size, is_psp ? PKG_AES_KEY2 : m_dec_key.data(), static_cast<u8*>(ptr) + read_size);
if (!advance_size)
{
break;
}
read_size += advance_size;
pos += advance_size;
}
return read_size + size_cache_end;
},
entry);
fs::file in_data; fs::file in_data;
in_data.reset(std::move(reader)); in_data.reset(std::move(reader));
@ -1308,9 +1308,9 @@ package_install_result package_reader::extract_data(std::deque<package_reader>&
const usz thread_count = std::min<usz>(utils::get_thread_count(), reader.m_install_entries.size()); const usz thread_count = std::min<usz>(utils::get_thread_count(), reader.m_install_entries.size());
named_thread_group workers("PKG Installer "sv, std::max<u32>(::narrow<u32>(thread_count), 1) - 1, [&]() named_thread_group workers("PKG Installer "sv, std::max<u32>(::narrow<u32>(thread_count), 1) - 1, [&]()
{ {
reader.extract_worker(); reader.extract_worker();
}); });
reader.extract_worker(); reader.extract_worker();
workers.join(); workers.join();
@ -1373,7 +1373,8 @@ package_install_result package_reader::extract_data(std::deque<package_reader>&
void package_reader::archive_seek(const s64 new_offset, const fs::seek_mode damode) void package_reader::archive_seek(const s64 new_offset, const fs::seek_mode damode)
{ {
if (m_file) m_file.seek(new_offset, damode); if (m_file)
m_file.seek(new_offset, damode);
} }
u64 package_reader::archive_read(void* data_ptr, const u64 num_bytes) u64 package_reader::archive_read(void* data_ptr, const u64 num_bytes)
@ -1412,12 +1413,12 @@ usz package_reader::decrypt(u64 offset, u64 size, const uchar* key, void* local_
{ {
// Debug key // Debug key
be_t<u64> input[8] = be_t<u64> input[8] =
{ {
m_header.qa_digest[0], m_header.qa_digest[0],
m_header.qa_digest[0], m_header.qa_digest[0],
m_header.qa_digest[1], m_header.qa_digest[1],
m_header.qa_digest[1], m_header.qa_digest[1],
}; };
for (u64 i = 0; i < blocks; i++) for (u64 i = 0; i < blocks; i++)
{ {

View file

@ -12,69 +12,69 @@
// Constants // Constants
enum : u32 enum : u32
{ {
PKG_HEADER_SIZE = 0xC0, // sizeof(pkg_header) + sizeof(pkg_unk_checksum) PKG_HEADER_SIZE = 0xC0, // sizeof(pkg_header) + sizeof(pkg_unk_checksum)
PKG_HEADER_SIZE2 = 0x280, PKG_HEADER_SIZE2 = 0x280,
PKG_MAX_FILENAME_SIZE = 256, PKG_MAX_FILENAME_SIZE = 256,
}; };
enum : u16 enum : u16
{ {
PKG_RELEASE_TYPE_RELEASE = 0x8000, PKG_RELEASE_TYPE_RELEASE = 0x8000,
PKG_RELEASE_TYPE_DEBUG = 0x0000, PKG_RELEASE_TYPE_DEBUG = 0x0000,
PKG_PLATFORM_TYPE_PS3 = 0x0001, PKG_PLATFORM_TYPE_PS3 = 0x0001,
PKG_PLATFORM_TYPE_PSP_PSVITA = 0x0002, PKG_PLATFORM_TYPE_PSP_PSVITA = 0x0002,
}; };
enum : u32 enum : u32
{ {
PKG_FILE_ENTRY_NPDRM = 1, PKG_FILE_ENTRY_NPDRM = 1,
PKG_FILE_ENTRY_NPDRMEDAT = 2, PKG_FILE_ENTRY_NPDRMEDAT = 2,
PKG_FILE_ENTRY_REGULAR = 3, PKG_FILE_ENTRY_REGULAR = 3,
PKG_FILE_ENTRY_FOLDER = 4, PKG_FILE_ENTRY_FOLDER = 4,
PKG_FILE_ENTRY_UNK0 = 5, PKG_FILE_ENTRY_UNK0 = 5,
PKG_FILE_ENTRY_UNK1 = 6, PKG_FILE_ENTRY_UNK1 = 6,
PKG_FILE_ENTRY_SDAT = 9, PKG_FILE_ENTRY_SDAT = 9,
PKG_FILE_ENTRY_OVERWRITE = 0x80000000, PKG_FILE_ENTRY_OVERWRITE = 0x80000000,
PKG_FILE_ENTRY_PSP = 0x10000000, PKG_FILE_ENTRY_PSP = 0x10000000,
PKG_FILE_ENTRY_KNOWN_BITS = 0xff | PKG_FILE_ENTRY_PSP | PKG_FILE_ENTRY_OVERWRITE, PKG_FILE_ENTRY_KNOWN_BITS = 0xff | PKG_FILE_ENTRY_PSP | PKG_FILE_ENTRY_OVERWRITE,
}; };
enum : u32 enum : u32
{ {
PKG_CONTENT_TYPE_UNKNOWN_1 = 0x01, // ? PKG_CONTENT_TYPE_UNKNOWN_1 = 0x01, // ?
PKG_CONTENT_TYPE_UNKNOWN_2 = 0x02, // ? PKG_CONTENT_TYPE_UNKNOWN_2 = 0x02, // ?
PKG_CONTENT_TYPE_UNKNOWN_3 = 0x03, // ? PKG_CONTENT_TYPE_UNKNOWN_3 = 0x03, // ?
PKG_CONTENT_TYPE_GAME_DATA = 0x04, // GameData (also patches) PKG_CONTENT_TYPE_GAME_DATA = 0x04, // GameData (also patches)
PKG_CONTENT_TYPE_GAME_EXEC = 0x05, // GameExec PKG_CONTENT_TYPE_GAME_EXEC = 0x05, // GameExec
PKG_CONTENT_TYPE_PS1_EMU = 0x06, // PS1emu PKG_CONTENT_TYPE_PS1_EMU = 0x06, // PS1emu
PKG_CONTENT_TYPE_PC_ENGINE = 0x07, // PSP & PCEngine PKG_CONTENT_TYPE_PC_ENGINE = 0x07, // PSP & PCEngine
PKG_CONTENT_TYPE_UNKNOWN_4 = 0x08, // ? PKG_CONTENT_TYPE_UNKNOWN_4 = 0x08, // ?
PKG_CONTENT_TYPE_THEME = 0x09, // Theme PKG_CONTENT_TYPE_THEME = 0x09, // Theme
PKG_CONTENT_TYPE_WIDGET = 0x0A, // Widget PKG_CONTENT_TYPE_WIDGET = 0x0A, // Widget
PKG_CONTENT_TYPE_LICENSE = 0x0B, // License PKG_CONTENT_TYPE_LICENSE = 0x0B, // License
PKG_CONTENT_TYPE_VSH_MODULE = 0x0C, // VSHModule PKG_CONTENT_TYPE_VSH_MODULE = 0x0C, // VSHModule
PKG_CONTENT_TYPE_PSN_AVATAR = 0x0D, // PSN Avatar PKG_CONTENT_TYPE_PSN_AVATAR = 0x0D, // PSN Avatar
PKG_CONTENT_TYPE_PSP_GO = 0x0E, // PSPgo PKG_CONTENT_TYPE_PSP_GO = 0x0E, // PSPgo
PKG_CONTENT_TYPE_MINIS = 0x0F, // Minis PKG_CONTENT_TYPE_MINIS = 0x0F, // Minis
PKG_CONTENT_TYPE_NEOGEO = 0x10, // NEOGEO PKG_CONTENT_TYPE_NEOGEO = 0x10, // NEOGEO
PKG_CONTENT_TYPE_VMC = 0x11, // VMC PKG_CONTENT_TYPE_VMC = 0x11, // VMC
PKG_CONTENT_TYPE_PS2_CLASSIC = 0x12, // ?PS2Classic? Seen on PS2 classic PKG_CONTENT_TYPE_PS2_CLASSIC = 0x12, // ?PS2Classic? Seen on PS2 classic
PKG_CONTENT_TYPE_UNKNOWN_5 = 0x13, // ? PKG_CONTENT_TYPE_UNKNOWN_5 = 0x13, // ?
PKG_CONTENT_TYPE_PSP_REMASTERED = 0x14, // ? PKG_CONTENT_TYPE_PSP_REMASTERED = 0x14, // ?
PKG_CONTENT_TYPE_PSP2_GD = 0x15, // PSVita Game Data PKG_CONTENT_TYPE_PSP2_GD = 0x15, // PSVita Game Data
PKG_CONTENT_TYPE_PSP2_AC = 0x16, // PSVita Additional Content PKG_CONTENT_TYPE_PSP2_AC = 0x16, // PSVita Additional Content
PKG_CONTENT_TYPE_PSP2_LA = 0x17, // PSVita LiveArea PKG_CONTENT_TYPE_PSP2_LA = 0x17, // PSVita LiveArea
PKG_CONTENT_TYPE_PSM_1 = 0x18, // PSVita PSM ? PKG_CONTENT_TYPE_PSM_1 = 0x18, // PSVita PSM ?
PKG_CONTENT_TYPE_WT = 0x19, // Web TV ? PKG_CONTENT_TYPE_WT = 0x19, // Web TV ?
PKG_CONTENT_TYPE_UNKNOWN_6 = 0x1A, // ? PKG_CONTENT_TYPE_UNKNOWN_6 = 0x1A, // ?
PKG_CONTENT_TYPE_UNKNOWN_7 = 0x1B, // ? PKG_CONTENT_TYPE_UNKNOWN_7 = 0x1B, // ?
PKG_CONTENT_TYPE_UNKNOWN_8 = 0x1C, // ? PKG_CONTENT_TYPE_UNKNOWN_8 = 0x1C, // ?
PKG_CONTENT_TYPE_PSM_2 = 0x1D, // PSVita PSM ? PKG_CONTENT_TYPE_PSM_2 = 0x1D, // PSVita PSM ?
PKG_CONTENT_TYPE_UNKNOWN_9 = 0x1E, // ? PKG_CONTENT_TYPE_UNKNOWN_9 = 0x1E, // ?
PKG_CONTENT_TYPE_PSP2_THEME = 0x1F, // PSVita Theme PKG_CONTENT_TYPE_PSP2_THEME = 0x1F, // PSVita Theme
}; };
// Structs // Structs
@ -93,7 +93,7 @@ struct PKGHeader
char title_id[48]; // Title ID char title_id[48]; // Title ID
be_t<u64> qa_digest[2]; // This should be the hash of "files + attribs" be_t<u64> qa_digest[2]; // This should be the hash of "files + attribs"
be_t<u128> klicensee; // Nonce be_t<u128> klicensee; // Nonce
// + some stuff // + some stuff
}; };
// Extended header in PSP and PSVita packages // Extended header in PSP and PSVita packages
@ -107,19 +107,19 @@ struct PKGExtHeader
be_t<u32> metadata_header_hmac_offset; // ex: 0x360, 0x390, 0x490 be_t<u32> metadata_header_hmac_offset; // ex: 0x360, 0x390, 0x490
be_t<u64> tail_offset; // tail size seams to be always 0x1A0 be_t<u64> tail_offset; // tail size seams to be always 0x1A0
be_t<u32> padding1; be_t<u32> padding1;
be_t<u32> pkg_key_id; // Id of the AES key used for decryption. PSP = 0x1, PSVita = 0xC0000002, PSM = 0xC0000004 be_t<u32> pkg_key_id; // Id of the AES key used for decryption. PSP = 0x1, PSVita = 0xC0000002, PSM = 0xC0000004
be_t<u32> full_header_hmac_offset; // ex: none (old pkg): 0, 0x930 be_t<u32> full_header_hmac_offset; // ex: none (old pkg): 0, 0x930
u8 padding2[20]; u8 padding2[20];
}; };
struct PKGEntry struct PKGEntry
{ {
be_t<u32> name_offset; // File name offset be_t<u32> name_offset; // File name offset
be_t<u32> name_size; // File name size be_t<u32> name_size; // File name size
be_t<u64> file_offset; // File offset be_t<u64> file_offset; // File offset
be_t<u64> file_size; // File size be_t<u64> file_size; // File size
be_t<u32> type; // File type be_t<u32> type; // File type
be_t<u32> pad; // Padding (zeros) be_t<u32> pad; // Padding (zeros)
}; };
// https://www.psdevwiki.com/ps3/PKG_files#PKG_Metadata // https://www.psdevwiki.com/ps3/PKG_files#PKG_Metadata
@ -144,22 +144,23 @@ private:
} }
return result; return result;
} }
public:
be_t<u32> drm_type{ 0 };
be_t<u32> content_type{ 0 };
be_t<u32> package_type{ 0 };
be_t<u64> package_size{ 0 };
u8 qa_digest[24]{ 0 };
be_t<u64> unk_0x9{ 0 }; public:
be_t<u64> unk_0xB{ 0 }; be_t<u32> drm_type{0};
be_t<u32> content_type{0};
be_t<u32> package_type{0};
be_t<u64> package_size{0};
u8 qa_digest[24]{0};
be_t<u64> unk_0x9{0};
be_t<u64> unk_0xB{0};
struct package_revision struct package_revision
{ {
struct package_revision_data struct package_revision_data
{ {
u8 make_package_npdrm_ver[2]{ 0 }; u8 make_package_npdrm_ver[2]{0};
u8 version[2]{ 0 }; u8 version[2]{0};
} data{}; } data{};
std::string make_package_npdrm_ver; std::string make_package_npdrm_ver;
@ -180,10 +181,10 @@ public:
{ {
struct software_revision_data struct software_revision_data
{ {
u8 unk[1]{ 0 }; u8 unk[1]{0};
u8 firmware_version[3]{ 0 }; u8 firmware_version[3]{0};
u8 version[2]{ 0 }; u8 version[2]{0};
u8 app_version[2]{ 0 }; u8 app_version[2]{0};
} data{}; } data{};
std::string unk; // maybe hardware id std::string unk; // maybe hardware id
@ -212,9 +213,9 @@ public:
struct vita_item_info // size is 0x28 (40) struct vita_item_info // size is 0x28 (40)
{ {
be_t<u32> offset{ 0 }; be_t<u32> offset{0};
be_t<u32> size{ 0 }; be_t<u32> size{0};
u8 sha256[32]{ 0 }; u8 sha256[32]{0};
std::string to_string() const std::string to_string() const
{ {
@ -224,12 +225,12 @@ public:
struct vita_sfo_info // size is 0x38 (56) struct vita_sfo_info // size is 0x38 (56)
{ {
be_t<u32> param_offset{ 0 }; be_t<u32> param_offset{0};
be_t<u16> param_size{ 0 }; be_t<u16> param_size{0};
be_t<u32> unk_1{ 0 }; // seen values: 0x00000001-0x00000018, 0x0000001b-0x0000001c be_t<u32> unk_1{0}; // seen values: 0x00000001-0x00000018, 0x0000001b-0x0000001c
be_t<u32> psp2_system_ver{ 0 }; // BCD encoded be_t<u32> psp2_system_ver{0}; // BCD encoded
u8 unk_2[8]{ 0 }; u8 unk_2[8]{0};
u8 param_digest[32]{ 0 }; // SHA256 of param_data. Called ParamDigest: This is sha256 digest of param.sfo. u8 param_digest[32]{0}; // SHA256 of param_data. Called ParamDigest: This is sha256 digest of param.sfo.
std::string to_string() const std::string to_string() const
{ {
@ -240,10 +241,10 @@ public:
struct vita_unknown_data_info // size is 0x48 (72) struct vita_unknown_data_info // size is 0x48 (72)
{ {
be_t<u32> unknown_data_offset{ 0 }; be_t<u32> unknown_data_offset{0};
be_t<u16> unknown_data_size{ 0 }; // ex: 0x320 be_t<u16> unknown_data_size{0}; // ex: 0x320
u8 unk[32]{ 0 }; u8 unk[32]{0};
u8 unknown_data_sha256[32]{ 0 }; u8 unknown_data_sha256[32]{0};
std::string to_string() const std::string to_string() const
{ {
@ -254,13 +255,13 @@ public:
struct vita_entirety_info // size is 0x38 (56) struct vita_entirety_info // size is 0x38 (56)
{ {
be_t<u32> entirety_data_offset{ 0 }; // located just before SFO be_t<u32> entirety_data_offset{0}; // located just before SFO
be_t<u32> entirety_data_size{ 0 }; // ex: 0xA0, C0, 0x100, 0x120, 0x160 be_t<u32> entirety_data_size{0}; // ex: 0xA0, C0, 0x100, 0x120, 0x160
be_t<u16> flags{ 0 }; // ex: EE 00, FE 10, FE 78, FE F8, FF 10, FF 90, FF D0, flags indicating which digests it embeds be_t<u16> flags{0}; // ex: EE 00, FE 10, FE 78, FE F8, FF 10, FF 90, FF D0, flags indicating which digests it embeds
be_t<u16> unk_1{ 0 }; // always 00 00 be_t<u16> unk_1{0}; // always 00 00
be_t<u32> unk_2{ 0 }; // ex: 1, 0 be_t<u32> unk_2{0}; // ex: 1, 0
u8 unk_3[8]{ 0 }; u8 unk_3[8]{0};
u8 entirety_digest[32]{ 0 }; u8 entirety_digest[32]{0};
std::string to_string() const std::string to_string() const
{ {
@ -271,9 +272,9 @@ public:
struct vita_version_info // size is 0x28 (40) struct vita_version_info // size is 0x28 (40)
{ {
be_t<u32> publishing_tools_version{ 0 }; be_t<u32> publishing_tools_version{0};
be_t<u32> psf_builder_version{ 0 }; be_t<u32> psf_builder_version{0};
u8 padding[32]{ 0 }; u8 padding[32]{0};
std::string to_string() const std::string to_string() const
{ {
@ -284,10 +285,10 @@ public:
struct vita_self_info // size is 0x38 (56) struct vita_self_info // size is 0x38 (56)
{ {
be_t<u32> self_info_offset{ 0 }; // offset to the first self_info_data_element be_t<u32> self_info_offset{0}; // offset to the first self_info_data_element
be_t<u32> self_info_size{ 0 }; // usually 0x10 or 0x20 be_t<u32> self_info_size{0}; // usually 0x10 or 0x20
u8 unk[16]{ 0 }; u8 unk[16]{0};
u8 self_sha256[32]{ 0 }; u8 self_sha256[32]{0};
std::string to_string() const std::string to_string() const
{ {
@ -346,17 +347,26 @@ public:
error_dirty error_dirty
}; };
bool is_valid() const { return m_is_valid; } bool is_valid() const
{
return m_is_valid;
}
package_install_result check_target_app_version() const; package_install_result check_target_app_version() const;
static package_install_result extract_data(std::deque<package_reader>& readers, std::deque<std::string>& bootable_paths); static package_install_result extract_data(std::deque<package_reader>& readers, std::deque<std::string>& bootable_paths);
const psf::registry& get_psf() const { return m_psf; } const psf::registry& get_psf() const
result get_result() const { return m_result; }; {
return m_psf;
}
result get_result() const
{
return m_result;
};
int get_progress(int maximum = 100) const; int get_progress(int maximum = 100) const;
void abort_extract(); void abort_extract();
fs::file &file() fs::file& file()
{ {
return m_file; return m_file;
} }

View file

@ -188,14 +188,13 @@ void WriteShdr(const fs::file& f, Elf32_Shdr& shdr)
Write32(f, shdr.sh_entsize); Write32(f, shdr.sh_entsize);
} }
void program_identification_header::Load(const fs::file& f) void program_identification_header::Load(const fs::file& f)
{ {
program_authority_id = Read64(f); program_authority_id = Read64(f);
program_vendor_id = Read32(f); program_vendor_id = Read32(f);
program_type = Read32(f); program_type = Read32(f);
program_sceversion = Read64(f); program_sceversion = Read64(f);
padding = Read64(f); padding = Read64(f);
} }
void program_identification_header::Show() const void program_identification_header::Show() const
@ -208,11 +207,11 @@ void program_identification_header::Show() const
void segment_ext_header::Load(const fs::file& f) void segment_ext_header::Load(const fs::file& f)
{ {
offset = Read64(f); offset = Read64(f);
size = Read64(f); size = Read64(f);
compression = Read32(f); compression = Read32(f);
unknown = Read32(f); unknown = Read32(f);
encryption = Read64(f); encryption = Read64(f);
} }
void segment_ext_header::Show() const void segment_ext_header::Show() const
@ -227,9 +226,9 @@ void segment_ext_header::Show() const
void version_header::Load(const fs::file& f) void version_header::Load(const fs::file& f)
{ {
subheader_type = Read32(f); subheader_type = Read32(f);
present = Read32(f); present = Read32(f);
size = Read32(f); size = Read32(f);
unknown4 = Read32(f); unknown4 = Read32(f);
} }
void version_header::Show() const void version_header::Show() const
@ -364,12 +363,12 @@ void MetadataHeader::Load(u8* in)
{ {
// Endian swap. // Endian swap.
signature_input_length = read_from_ptr<be_t<u64>>(in); signature_input_length = read_from_ptr<be_t<u64>>(in);
unknown1 = read_from_ptr<be_t<u32>>(in, 8); unknown1 = read_from_ptr<be_t<u32>>(in, 8);
section_count = read_from_ptr<be_t<u32>>(in, 12); section_count = read_from_ptr<be_t<u32>>(in, 12);
key_count = read_from_ptr<be_t<u32>>(in, 16); key_count = read_from_ptr<be_t<u32>>(in, 16);
opt_header_size = read_from_ptr<be_t<u32>>(in, 20); opt_header_size = read_from_ptr<be_t<u32>>(in, 20);
unknown2 = read_from_ptr<be_t<u32>>(in, 24); unknown2 = read_from_ptr<be_t<u32>>(in, 24);
unknown3 = read_from_ptr<be_t<u32>>(in, 28); unknown3 = read_from_ptr<be_t<u32>>(in, 28);
} }
void MetadataHeader::Show() const void MetadataHeader::Show() const
@ -387,15 +386,15 @@ void MetadataSectionHeader::Load(u8* in)
{ {
// Endian swap. // Endian swap.
data_offset = read_from_ptr<be_t<u64>>(in); data_offset = read_from_ptr<be_t<u64>>(in);
data_size = read_from_ptr<be_t<u64>>(in, 8); data_size = read_from_ptr<be_t<u64>>(in, 8);
type = read_from_ptr<be_t<u32>>(in, 16); type = read_from_ptr<be_t<u32>>(in, 16);
program_idx = read_from_ptr<be_t<u32>>(in, 20); program_idx = read_from_ptr<be_t<u32>>(in, 20);
hashed = read_from_ptr<be_t<u32>>(in, 24); hashed = read_from_ptr<be_t<u32>>(in, 24);
sha1_idx = read_from_ptr<be_t<u32>>(in, 28); sha1_idx = read_from_ptr<be_t<u32>>(in, 28);
encrypted = read_from_ptr<be_t<u32>>(in, 32); encrypted = read_from_ptr<be_t<u32>>(in, 32);
key_idx = read_from_ptr<be_t<u32>>(in, 36); key_idx = read_from_ptr<be_t<u32>>(in, 36);
iv_idx = read_from_ptr<be_t<u32>>(in, 40); iv_idx = read_from_ptr<be_t<u32>>(in, 40);
compressed = read_from_ptr<be_t<u32>>(in, 44); compressed = read_from_ptr<be_t<u32>>(in, 44);
} }
void MetadataSectionHeader::Show() const void MetadataSectionHeader::Show() const
@ -421,13 +420,13 @@ void SectionHash::Load(const fs::file& f)
void CapabilitiesInfo::Load(const fs::file& f) void CapabilitiesInfo::Load(const fs::file& f)
{ {
type = Read32(f); type = Read32(f);
capabilities_size = Read32(f); capabilities_size = Read32(f);
next = Read32(f); next = Read32(f);
unknown1 = Read32(f); unknown1 = Read32(f);
unknown2 = Read64(f); unknown2 = Read64(f);
unknown3 = Read64(f); unknown3 = Read64(f);
flags = Read64(f); flags = Read64(f);
unknown4 = Read32(f); unknown4 = Read32(f);
unknown5 = Read32(f); unknown5 = Read32(f);
} }
@ -601,8 +600,7 @@ void ext_hdr::Load(const fs::file& f)
} }
SCEDecrypter::SCEDecrypter(const fs::file& s) SCEDecrypter::SCEDecrypter(const fs::file& s)
: sce_f(s) : sce_f(s), data_buf_length(0)
, data_buf_length(0)
{ {
} }
@ -647,7 +645,7 @@ bool SCEDecrypter::LoadMetadata(const u8 erk[32], const u8 riv[16])
if ((sce_hdr.se_flags & 0x8000) != 0x8000) if ((sce_hdr.se_flags & 0x8000) != 0x8000)
{ {
// Decrypt the metadata info. // Decrypt the metadata info.
aes_setkey_dec(&aes, metadata_key, 256); // AES-256 aes_setkey_dec(&aes, metadata_key, 256); // AES-256
aes_crypt_cbc(&aes, AES_DECRYPT, sizeof(meta_info), metadata_iv, metadata_info.get(), metadata_info.get()); aes_crypt_cbc(&aes, AES_DECRYPT, sizeof(meta_info), metadata_iv, metadata_info.get(), metadata_info.get());
} }
@ -789,15 +787,15 @@ std::vector<fs::file> SCEDecrypter::MakeFile()
if (out_f.pos() != out_f.size()) if (out_f.pos() != out_f.size())
fmt::throw_exception("MakeELF written bytes (%llu) does not equal buffer size (%llu).", out_f.pos(), out_f.size()); fmt::throw_exception("MakeELF written bytes (%llu) does not equal buffer size (%llu).", out_f.pos(), out_f.size());
if (is_valid) vec.push_back(std::move(out_f)); if (is_valid)
vec.push_back(std::move(out_f));
} }
return vec; return vec;
} }
SELFDecrypter::SELFDecrypter(const fs::file& s) SELFDecrypter::SELFDecrypter(const fs::file& s)
: self_f(s) : self_f(s), key_v()
, key_v()
{ {
} }
@ -843,13 +841,13 @@ bool SELFDecrypter::LoadHeaders(bool isElf32, SelfAdditionalInfo* out_info)
if (isElf32) if (isElf32)
{ {
phdr32_arr.clear(); phdr32_arr.clear();
if(elf32_hdr.e_phoff == 0 && elf32_hdr.e_phnum) if (elf32_hdr.e_phoff == 0 && elf32_hdr.e_phnum)
{ {
self_log.error("ELF program header offset is null!"); self_log.error("ELF program header offset is null!");
return false; return false;
} }
self_f.seek(m_ext_hdr.phdr_offset); self_f.seek(m_ext_hdr.phdr_offset);
for(u32 i = 0; i < elf32_hdr.e_phnum; ++i) for (u32 i = 0; i < elf32_hdr.e_phnum; ++i)
{ {
phdr32_arr.emplace_back(); phdr32_arr.emplace_back();
phdr32_arr.back().Load(self_f); phdr32_arr.back().Load(self_f);
@ -878,7 +876,7 @@ bool SELFDecrypter::LoadHeaders(bool isElf32, SelfAdditionalInfo* out_info)
m_seg_ext_hdr.clear(); m_seg_ext_hdr.clear();
self_f.seek(m_ext_hdr.segment_ext_hdr_offset); self_f.seek(m_ext_hdr.segment_ext_hdr_offset);
for(u32 i = 0; i < (isElf32 ? elf32_hdr.e_phnum : elf64_hdr.e_phnum); ++i) for (u32 i = 0; i < (isElf32 ? elf32_hdr.e_phnum : elf64_hdr.e_phnum); ++i)
{ {
if (self_f.pos() >= self_f.size()) if (self_f.pos() >= self_f.size())
{ {
@ -934,7 +932,7 @@ bool SELFDecrypter::LoadHeaders(bool isElf32, SelfAdditionalInfo* out_info)
self_f.seek(m_ext_hdr.shdr_offset); self_f.seek(m_ext_hdr.shdr_offset);
for(u32 i = 0; i < elf32_hdr.e_shnum; ++i) for (u32 i = 0; i < elf32_hdr.e_shnum; ++i)
{ {
shdr32_arr.emplace_back(); shdr32_arr.emplace_back();
shdr32_arr.back().Load(self_f); shdr32_arr.back().Load(self_f);
@ -951,7 +949,7 @@ bool SELFDecrypter::LoadHeaders(bool isElf32, SelfAdditionalInfo* out_info)
self_f.seek(m_ext_hdr.shdr_offset); self_f.seek(m_ext_hdr.shdr_offset);
for(u32 i = 0; i < elf64_hdr.e_shnum; ++i) for (u32 i = 0; i < elf64_hdr.e_shnum; ++i)
{ {
shdr64_arr.emplace_back(); shdr64_arr.emplace_back();
shdr64_arr.back().Load(self_f); shdr64_arr.back().Load(self_f);
@ -986,12 +984,12 @@ void SELFDecrypter::ShowHeaders(bool isElf32)
self_log.notice("----------------------------------------------------"); self_log.notice("----------------------------------------------------");
self_log.notice("ELF program headers"); self_log.notice("ELF program headers");
self_log.notice("----------------------------------------------------"); self_log.notice("----------------------------------------------------");
for(unsigned int i = 0; i < ((isElf32) ? phdr32_arr.size() : phdr64_arr.size()); i++) for (unsigned int i = 0; i < ((isElf32) ? phdr32_arr.size() : phdr64_arr.size()); i++)
isElf32 ? phdr32_arr[i].Show() : phdr64_arr[i].Show(); isElf32 ? phdr32_arr[i].Show() : phdr64_arr[i].Show();
self_log.notice("----------------------------------------------------"); self_log.notice("----------------------------------------------------");
self_log.notice("Section info"); self_log.notice("Section info");
self_log.notice("----------------------------------------------------"); self_log.notice("----------------------------------------------------");
for(unsigned int i = 0; i < m_seg_ext_hdr.size(); i++) for (unsigned int i = 0; i < m_seg_ext_hdr.size(); i++)
m_seg_ext_hdr[i].Show(); m_seg_ext_hdr[i].Show();
self_log.notice("----------------------------------------------------"); self_log.notice("----------------------------------------------------");
self_log.notice("SCE version info"); self_log.notice("SCE version info");
@ -1000,17 +998,17 @@ void SELFDecrypter::ShowHeaders(bool isElf32)
self_log.notice("----------------------------------------------------"); self_log.notice("----------------------------------------------------");
self_log.notice("Control info"); self_log.notice("Control info");
self_log.notice("----------------------------------------------------"); self_log.notice("----------------------------------------------------");
for(unsigned int i = 0; i < m_supplemental_hdr_arr.size(); i++) for (unsigned int i = 0; i < m_supplemental_hdr_arr.size(); i++)
m_supplemental_hdr_arr[i].Show(); m_supplemental_hdr_arr[i].Show();
self_log.notice("----------------------------------------------------"); self_log.notice("----------------------------------------------------");
self_log.notice("ELF section headers"); self_log.notice("ELF section headers");
self_log.notice("----------------------------------------------------"); self_log.notice("----------------------------------------------------");
for(unsigned int i = 0; i < ((isElf32) ? shdr32_arr.size() : shdr64_arr.size()); i++) for (unsigned int i = 0; i < ((isElf32) ? shdr32_arr.size() : shdr64_arr.size()); i++)
isElf32 ? shdr32_arr[i].Show() : shdr64_arr[i].Show(); isElf32 ? shdr32_arr[i].Show() : shdr64_arr[i].Show();
self_log.notice("----------------------------------------------------"); self_log.notice("----------------------------------------------------");
} }
bool SELFDecrypter::DecryptNPDRM(u8 *metadata, u32 metadata_size) bool SELFDecrypter::DecryptNPDRM(u8* metadata, u32 metadata_size)
{ {
aes_context aes; aes_context aes;
u8 npdrm_key[0x10]; u8 npdrm_key[0x10];
@ -1025,7 +1023,7 @@ bool SELFDecrypter::DecryptNPDRM(u8 *metadata, u32 metadata_size)
return true; return true;
} }
if (npd->license == 1) // Network license. if (npd->license == 1) // Network license.
{ {
// Try to find a RAP file to get the key. // Try to find a RAP file to get the key.
if (!GetKeyFromRap(npd->content_id, npdrm_key)) if (!GetKeyFromRap(npd->content_id, npdrm_key))
@ -1034,7 +1032,7 @@ bool SELFDecrypter::DecryptNPDRM(u8 *metadata, u32 metadata_size)
return false; return false;
} }
} }
else if (npd->license == 2) // Local license. else if (npd->license == 2) // Local license.
{ {
// Try to find a RAP file to get the key. // Try to find a RAP file to get the key.
if (!GetKeyFromRap(npd->content_id, npdrm_key)) if (!GetKeyFromRap(npd->content_id, npdrm_key))
@ -1043,7 +1041,7 @@ bool SELFDecrypter::DecryptNPDRM(u8 *metadata, u32 metadata_size)
return false; return false;
} }
} }
else if (npd->license == 3) // Free license. else if (npd->license == 3) // Free license.
{ {
// Use klicensee if available. (may be set to NP_KLIC_FREE if none is set) // Use klicensee if available. (may be set to NP_KLIC_FREE if none is set)
std::memcpy(npdrm_key, key_v.GetKlicenseeKey(), 0x10); std::memcpy(npdrm_key, key_v.GetKlicenseeKey(), 0x10);
@ -1118,7 +1116,7 @@ bool SELFDecrypter::LoadMetadata(const u8* klic_key)
return false; return false;
// Decrypt the metadata info. // Decrypt the metadata info.
aes_setkey_dec(&aes, metadata_key, 256); // AES-256 aes_setkey_dec(&aes, metadata_key, 256); // AES-256
aes_crypt_cbc(&aes, AES_DECRYPT, sizeof(meta_info), metadata_iv, metadata_info.get(), metadata_info.get()); aes_crypt_cbc(&aes, AES_DECRYPT, sizeof(meta_info), metadata_iv, metadata_info.get(), metadata_info.get());
} }
@ -1191,7 +1189,7 @@ bool SELFDecrypter::DecryptData()
if (meta_shdr[i].encrypted == 3) if (meta_shdr[i].encrypted == 3)
{ {
// Make sure the key and iv are not out of boundaries. // Make sure the key and iv are not out of boundaries.
if((meta_shdr[i].key_idx <= meta_hdr.key_count - 1) && (meta_shdr[i].iv_idx <= meta_hdr.key_count)) if ((meta_shdr[i].key_idx <= meta_hdr.key_count - 1) && (meta_shdr[i].iv_idx <= meta_hdr.key_count))
{ {
// Get the key and iv from the previously stored key buffer. // Get the key and iv from the previously stored key buffer.
memcpy(data_key, data_keys.get() + meta_shdr[i].key_idx * 0x10, 0x10); memcpy(data_key, data_keys.get() + meta_shdr[i].key_idx * 0x10, 0x10);
@ -1256,8 +1254,9 @@ bool SELFDecrypter::GetKeyFromRap(const char* content_id, u8* npdrm_key)
if (!rap_file) if (!rap_file)
{ {
self_log.fatal("Failed to locate the game license file: %s." self_log.fatal("Failed to locate the game license file: %s."
"\nEnsure the .rap license file is placed in the dev_hdd0/home/%s/exdata folder with a lowercase file extension." "\nEnsure the .rap license file is placed in the dev_hdd0/home/%s/exdata folder with a lowercase file extension."
"\nIf you need assistance on dumping the license file from your PS3, read our quickstart guide: https://rpcs3.net/quickstart", rap_path, Emu.GetUsr()); "\nIf you need assistance on dumping the license file from your PS3, read our quickstart guide: https://rpcs3.net/quickstart",
rap_path, Emu.GetUsr());
return false; return false;
} }
@ -1277,7 +1276,8 @@ bool SELFDecrypter::GetKeyFromRap(const char* content_id, u8* npdrm_key)
static bool IsSelfElf32(const fs::file& f) static bool IsSelfElf32(const fs::file& f)
{ {
if (!f) return false; if (!f)
return false;
f.seek(0); f.seek(0);
@ -1454,7 +1454,7 @@ bool verify_npdrm_self_headers(const fs::file& self, u8* klic_key, NPD_HEADER* n
return true; return true;
} }
bool get_npdrm_self_header(const fs::file& self, NPD_HEADER &npd_out) bool get_npdrm_self_header(const fs::file& self, NPD_HEADER& npd_out)
{ {
if (!self) if (!self)
return false; return false;

View file

@ -14,19 +14,19 @@ LOG_CHANNEL(self_log, "SELF");
// SCE-specific definitions for e_type: // SCE-specific definitions for e_type:
enum enum
{ {
ET_SCE_EXEC = 0xFE00, // SCE Executable - PRX2 ET_SCE_EXEC = 0xFE00, // SCE Executable - PRX2
ET_SCE_RELEXEC = 0xFE04, // SCE Relocatable Executable - PRX2 ET_SCE_RELEXEC = 0xFE04, // SCE Relocatable Executable - PRX2
ET_SCE_STUBLIB = 0xFE0C, // SCE SDK Stubs ET_SCE_STUBLIB = 0xFE0C, // SCE SDK Stubs
ET_SCE_DYNEXEC = 0xFE10, // SCE EXEC_ASLR (PS4 Executable with ASLR) ET_SCE_DYNEXEC = 0xFE10, // SCE EXEC_ASLR (PS4 Executable with ASLR)
ET_SCE_DYNAMIC = 0xFE18, // ? ET_SCE_DYNAMIC = 0xFE18, // ?
ET_SCE_IOPRELEXEC = 0xFF80, // SCE IOP Relocatable Executable ET_SCE_IOPRELEXEC = 0xFF80, // SCE IOP Relocatable Executable
ET_SCE_IOPRELEXEC2 = 0xFF81, // SCE IOP Relocatable Executable Version 2 ET_SCE_IOPRELEXEC2 = 0xFF81, // SCE IOP Relocatable Executable Version 2
ET_SCE_EERELEXEC = 0xFF90, // SCE EE Relocatable Executable ET_SCE_EERELEXEC = 0xFF90, // SCE EE Relocatable Executable
ET_SCE_EERELEXEC2 = 0xFF91, // SCE EE Relocatable Executable Version 2 ET_SCE_EERELEXEC2 = 0xFF91, // SCE EE Relocatable Executable Version 2
ET_SCE_PSPRELEXEC = 0xFFA0, // SCE PSP Relocatable Executable ET_SCE_PSPRELEXEC = 0xFFA0, // SCE PSP Relocatable Executable
ET_SCE_PPURELEXEC = 0xFFA4, // SCE PPU Relocatable Executable ET_SCE_PPURELEXEC = 0xFFA4, // SCE PPU Relocatable Executable
ET_SCE_ARMRELEXEC = 0xFFA5, // ?SCE ARM Relocatable Executable (PS Vita System Software earlier or equal 0.931.010) ET_SCE_ARMRELEXEC = 0xFFA5, // ?SCE ARM Relocatable Executable (PS Vita System Software earlier or equal 0.931.010)
ET_SCE_PSPOVERLAY = 0xFFA8, // ? ET_SCE_PSPOVERLAY = 0xFFA8, // ?
}; };
enum enum
@ -36,21 +36,21 @@ enum
enum enum
{ {
PT_SCE_RELA = 0x60000000, PT_SCE_RELA = 0x60000000,
PT_SCE_LICINFO_1 = 0x60000001, PT_SCE_LICINFO_1 = 0x60000001,
PT_SCE_LICINFO_2 = 0x60000002, PT_SCE_LICINFO_2 = 0x60000002,
PT_SCE_DYNLIBDATA = 0x61000000, PT_SCE_DYNLIBDATA = 0x61000000,
PT_SCE_PROCPARAM = 0x61000001, PT_SCE_PROCPARAM = 0x61000001,
PT_SCE_UNK_61000010 = 0x61000010, PT_SCE_UNK_61000010 = 0x61000010,
PT_SCE_COMMENT = 0x6FFFFF00, PT_SCE_COMMENT = 0x6FFFFF00,
PT_SCE_LIBVERSION = 0x6FFFFF01, PT_SCE_LIBVERSION = 0x6FFFFF01,
PT_SCE_UNK_70000001 = 0x70000001, PT_SCE_UNK_70000001 = 0x70000001,
PT_SCE_IOPMOD = 0x70000080, PT_SCE_IOPMOD = 0x70000080,
PT_SCE_EEMOD = 0x70000090, PT_SCE_EEMOD = 0x70000090,
PT_SCE_PSPRELA = 0x700000A0, PT_SCE_PSPRELA = 0x700000A0,
PT_SCE_PSPRELA2 = 0x700000A1, PT_SCE_PSPRELA2 = 0x700000A1,
PT_SCE_PPURELA = 0x700000A4, PT_SCE_PPURELA = 0x700000A4,
PT_SCE_SEGSYM = 0x700000A8, PT_SCE_SEGSYM = 0x700000A8,
}; };
enum enum
@ -65,10 +65,10 @@ enum
enum enum
{ {
SHT_SCE_RELA = 0x60000000, SHT_SCE_RELA = 0x60000000,
SHT_SCE_NID = 0x61000001, SHT_SCE_NID = 0x61000001,
SHT_SCE_IOPMOD = 0x70000080, SHT_SCE_IOPMOD = 0x70000080,
SHT_SCE_EEMOD = 0x70000090, SHT_SCE_EEMOD = 0x70000090,
SHT_SCE_PSPRELA = 0x700000A0, SHT_SCE_PSPRELA = 0x700000A0,
SHT_SCE_PPURELA = 0x700000A4, SHT_SCE_PPURELA = 0x700000A4,
}; };
@ -132,8 +132,8 @@ struct supplemental_header
// type 2, 0x40 bytes // type 2, 0x40 bytes
struct // 0x30 bytes of data struct // 0x30 bytes of data
{ {
u8 constant[0x14]; // same for every PS3/PS Vita SELF, hardcoded in make_fself.exe: 627CB1808AB938E32C8C091708726A579E2586E4 u8 constant[0x14]; // same for every PS3/PS Vita SELF, hardcoded in make_fself.exe: 627CB1808AB938E32C8C091708726A579E2586E4
u8 elf_digest[0x14]; // SHA-1. Hash F2C552BF716ED24759CBE8A0A9A6DB9965F3811C is blacklisted by appldr u8 elf_digest[0x14]; // SHA-1. Hash F2C552BF716ED24759CBE8A0A9A6DB9965F3811C is blacklisted by appldr
u64 required_system_version; // filled on Sony authentication server, contains decimal PS3_SYSTEM_VER value from PARAM.SFO u64 required_system_version; // filled on Sony authentication server, contains decimal PS3_SYSTEM_VER value from PARAM.SFO
} PS3_elf_digest_header_40; } PS3_elf_digest_header_40;
@ -155,7 +155,6 @@ struct supplemental_header
void Show() const; void Show() const;
}; };
struct MetadataInfo struct MetadataInfo
{ {
u8 key[0x10]; u8 key[0x10];
@ -242,32 +241,41 @@ struct SelfSection
struct Elf32_Ehdr struct Elf32_Ehdr
{ {
//u8 e_ident[16]; // ELF identification // u8 e_ident[16]; // ELF identification
u32 e_magic; u32 e_magic;
u8 e_class; u8 e_class;
u8 e_data; u8 e_data;
u8 e_curver; u8 e_curver;
u8 e_os_abi; u8 e_os_abi;
u64 e_abi_ver; u64 e_abi_ver;
u16 e_type; // object file type u16 e_type; // object file type
u16 e_machine; // machine type u16 e_machine; // machine type
u32 e_version; // object file version u32 e_version; // object file version
u32 e_entry; // entry point address u32 e_entry; // entry point address
u32 e_phoff; // program header offset u32 e_phoff; // program header offset
u32 e_shoff; // section header offset u32 e_shoff; // section header offset
u32 e_flags; // processor-specific flags u32 e_flags; // processor-specific flags
u16 e_ehsize; // ELF header size u16 e_ehsize; // ELF header size
u16 e_phentsize; // size of program header entry u16 e_phentsize; // size of program header entry
u16 e_phnum; // number of program header entries u16 e_phnum; // number of program header entries
u16 e_shentsize; // size of section header entry u16 e_shentsize; // size of section header entry
u16 e_shnum; // number of section header entries u16 e_shnum; // number of section header entries
u16 e_shstrndx; // section name string table index u16 e_shstrndx; // section name string table index
void Load(const fs::file& f); void Load(const fs::file& f);
static void Show() {} static void Show() {}
bool IsLittleEndian() const { return e_data == 1; } bool IsLittleEndian() const
bool CheckMagic() const { return e_magic == 0x7F454C46; } {
u32 GetEntry() const { return e_entry; } return e_data == 1;
}
bool CheckMagic() const
{
return e_magic == 0x7F454C46;
}
u32 GetEntry() const
{
return e_entry;
}
}; };
struct Elf32_Shdr struct Elf32_Shdr
@ -306,31 +314,37 @@ struct Elf32_Phdr
struct Elf64_Ehdr struct Elf64_Ehdr
{ {
//u8 e_ident[16]; // ELF identification // u8 e_ident[16]; // ELF identification
u32 e_magic; u32 e_magic;
u8 e_class; u8 e_class;
u8 e_data; u8 e_data;
u8 e_curver; u8 e_curver;
u8 e_os_abi; u8 e_os_abi;
u64 e_abi_ver; u64 e_abi_ver;
u16 e_type; // object file type u16 e_type; // object file type
u16 e_machine; // machine type u16 e_machine; // machine type
u32 e_version; // object file version u32 e_version; // object file version
u64 e_entry; // entry point address u64 e_entry; // entry point address
u64 e_phoff; // program header offset u64 e_phoff; // program header offset
u64 e_shoff; // section header offset u64 e_shoff; // section header offset
u32 e_flags; // processor-specific flags u32 e_flags; // processor-specific flags
u16 e_ehsize; // ELF header size u16 e_ehsize; // ELF header size
u16 e_phentsize; // size of program header entry u16 e_phentsize; // size of program header entry
u16 e_phnum; // number of program header entries u16 e_phnum; // number of program header entries
u16 e_shentsize; // size of section header entry u16 e_shentsize; // size of section header entry
u16 e_shnum; // number of section header entries u16 e_shnum; // number of section header entries
u16 e_shstrndx; // section name string table index u16 e_shstrndx; // section name string table index
void Load(const fs::file& f); void Load(const fs::file& f);
static void Show() {} static void Show() {}
bool CheckMagic() const { return e_magic == 0x7F454C46; } bool CheckMagic() const
u64 GetEntry() const { return e_entry; } {
return e_magic == 0x7F454C46;
}
u64 GetEntry() const
{
return e_entry;
}
}; };
struct Elf64_Shdr struct Elf64_Shdr
@ -347,7 +361,7 @@ struct Elf64_Shdr
u64 sh_entsize; // size of entries, if section has table u64 sh_entsize; // size of entries, if section has table
void Load(const fs::file& f); void Load(const fs::file& f);
static void Show(){} static void Show() {}
}; };
struct Elf64_Phdr struct Elf64_Phdr
@ -362,7 +376,7 @@ struct Elf64_Phdr
u64 p_align; // Segment alignment u64 p_align; // Segment alignment
void Load(const fs::file& f); void Load(const fs::file& f);
static void Show(){} static void Show() {}
}; };
struct SceHeader struct SceHeader
@ -376,8 +390,11 @@ struct SceHeader
u64 se_esize; u64 se_esize;
void Load(const fs::file& f); void Load(const fs::file& f);
static void Show(){} static void Show() {}
bool CheckMagic() const { return se_magic == 0x53434500; } bool CheckMagic() const
{
return se_magic == 0x53434500;
}
}; };
struct ext_hdr struct ext_hdr
@ -394,7 +411,7 @@ struct ext_hdr
u64 padding; u64 padding;
void Load(const fs::file& f); void Load(const fs::file& f);
static void Show(){} static void Show() {}
}; };
struct SelfAdditionalInfo struct SelfAdditionalInfo
@ -478,12 +495,12 @@ public:
void ShowHeaders(bool isElf32); void ShowHeaders(bool isElf32);
bool LoadMetadata(const u8* klic_key); bool LoadMetadata(const u8* klic_key);
bool DecryptData(); bool DecryptData();
bool DecryptNPDRM(u8 *metadata, u32 metadata_size); bool DecryptNPDRM(u8* metadata, u32 metadata_size);
const NPD_HEADER* GetNPDHeader() const; const NPD_HEADER* GetNPDHeader() const;
static bool GetKeyFromRap(const char *content_id, u8 *npdrm_key); static bool GetKeyFromRap(const char* content_id, u8* npdrm_key);
private: private:
template<typename EHdr, typename SHdr, typename PHdr> template <typename EHdr, typename SHdr, typename PHdr>
void WriteElf(fs::file& e, EHdr ehdr, SHdr shdr, PHdr phdr) void WriteElf(fs::file& e, EHdr ehdr, SHdr shdr, PHdr phdr)
{ {
// Set initial offset. // Set initial offset.

View file

@ -30,7 +30,7 @@ std::vector<u8> unzip(const void* src, usz size)
zs.avail_in = static_cast<uInt>(size); zs.avail_in = static_cast<uInt>(size);
zs.next_in = reinterpret_cast<const u8*>(src); zs.next_in = reinterpret_cast<const u8*>(src);
zs.avail_out = static_cast<uInt>(out.size()); zs.avail_out = static_cast<uInt>(out.size());
zs.next_out = out.data(); zs.next_out = out.data();
while (zs.avail_in) while (zs.avail_in)
{ {

View file

@ -31,11 +31,11 @@ u64 hex_to_u64(const char* hex_str)
while (length--) while (length--)
{ {
c = *hex_str++; c = *hex_str++;
if((c >= '0') && (c <= '9')) if ((c >= '0') && (c <= '9'))
tmp = c - '0'; tmp = c - '0';
else if((c >= 'a') && (c <= 'f')) else if ((c >= 'a') && (c <= 'f'))
tmp = c - 'a' + 10; tmp = c - 'a' + 10;
else if((c >= 'A') && (c <= 'F')) else if ((c >= 'A') && (c <= 'F'))
tmp = c - 'A' + 10; tmp = c - 'A' + 10;
else else
tmp = 0; tmp = 0;
@ -64,9 +64,8 @@ void hex_to_bytes(unsigned char* data, const char* hex_str, unsigned int str_len
} }
} }
// Crypto functions (AES128-CBC, AES128-ECB, SHA1-HMAC and AES-CMAC). // Crypto functions (AES128-CBC, AES128-ECB, SHA1-HMAC and AES-CMAC).
void aescbc128_decrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, usz len) void aescbc128_decrypt(unsigned char* key, unsigned char* iv, unsigned char* in, unsigned char* out, usz len)
{ {
aes_context ctx; aes_context ctx;
aes_setkey_dec(&ctx, key, 128); aes_setkey_dec(&ctx, key, 128);
@ -76,7 +75,7 @@ void aescbc128_decrypt(unsigned char *key, unsigned char *iv, unsigned char *in,
memset(iv, 0, 0x10); memset(iv, 0, 0x10);
} }
void aescbc128_encrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, usz len) void aescbc128_encrypt(unsigned char* key, unsigned char* iv, unsigned char* in, unsigned char* out, usz len)
{ {
aes_context ctx; aes_context ctx;
aes_setkey_enc(&ctx, key, 128); aes_setkey_enc(&ctx, key, 128);
@ -86,14 +85,14 @@ void aescbc128_encrypt(unsigned char *key, unsigned char *iv, unsigned char *in,
memset(iv, 0, 0x10); memset(iv, 0, 0x10);
} }
void aesecb128_encrypt(unsigned char *key, unsigned char *in, unsigned char *out) void aesecb128_encrypt(unsigned char* key, unsigned char* in, unsigned char* out)
{ {
aes_context ctx; aes_context ctx;
aes_setkey_enc(&ctx, key, 128); aes_setkey_enc(&ctx, key, 128);
aes_crypt_ecb(&ctx, AES_ENCRYPT, in, out); aes_crypt_ecb(&ctx, AES_ENCRYPT, in, out);
} }
bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, usz in_len, unsigned char *hash, usz hash_len) bool hmac_hash_compare(unsigned char* key, int key_len, unsigned char* in, usz in_len, unsigned char* hash, usz hash_len)
{ {
const std::unique_ptr<u8[]> out(new u8[key_len]); const std::unique_ptr<u8[]> out(new u8[key_len]);
@ -102,12 +101,12 @@ bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, usz i
return std::memcmp(out.get(), hash, hash_len) == 0; return std::memcmp(out.get(), hash, hash_len) == 0;
} }
void hmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, usz in_len, unsigned char *hash) void hmac_hash_forge(unsigned char* key, int key_len, unsigned char* in, usz in_len, unsigned char* hash)
{ {
sha1_hmac(key, key_len, in, in_len, hash); sha1_hmac(key, key_len, in, in_len, hash);
} }
bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, usz in_len, unsigned char *hash, usz hash_len) bool cmac_hash_compare(unsigned char* key, int key_len, unsigned char* in, usz in_len, unsigned char* hash, usz hash_len)
{ {
const std::unique_ptr<u8[]> out(new u8[key_len]); const std::unique_ptr<u8[]> out(new u8[key_len]);
@ -118,7 +117,7 @@ bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, usz i
return std::memcmp(out.get(), hash, hash_len) == 0; return std::memcmp(out.get(), hash, hash_len) == 0;
} }
void cmac_hash_forge(unsigned char *key, int /*key_len*/, unsigned char *in, usz in_len, unsigned char *hash) void cmac_hash_forge(unsigned char* key, int /*key_len*/, unsigned char* in, usz in_len, unsigned char* hash)
{ {
aes_context ctx; aes_context ctx;
aes_setkey_enc(&ctx, key, 128); aes_setkey_enc(&ctx, key, 128);
@ -152,21 +151,20 @@ std::string sha256_get_hash(const char* data, usz size, bool lower_case)
for (usz index = 0; index < 32; index++) for (usz index = 0; index < 32; index++)
{ {
const auto pal = lower_case ? "0123456789abcdef" : "0123456789ABCDEF"; const auto pal = lower_case ? "0123456789abcdef" : "0123456789ABCDEF";
res_hash_string[index * 2] = pal[res_hash[index] >> 4]; res_hash_string[index * 2] = pal[res_hash[index] >> 4];
res_hash_string[(index * 2) + 1] = pal[res_hash[index] & 15]; res_hash_string[(index * 2) + 1] = pal[res_hash[index] & 15];
} }
return res_hash_string; return res_hash_string;
} }
void mbedtls_zeroize(void *v, size_t n) void mbedtls_zeroize(void* v, size_t n)
{ {
static void *(*const volatile unop_memset)(void *, int, size_t) = &memset; static void* (*const volatile unop_memset)(void*, int, size_t) = &memset;
(void)unop_memset(v, 0, n); (void)unop_memset(v, 0, n);
} }
// SC passphrase crypto // SC passphrase crypto
void sc_form_key(const u8* sc_key, const std::array<u8, PASSPHRASE_KEY_LEN>& laid_paid, u8* key) void sc_form_key(const u8* sc_key, const std::array<u8, PASSPHRASE_KEY_LEN>& laid_paid, u8* key)
@ -229,7 +227,7 @@ const u8* vtrm_portability_type_mapper(int type)
// No idea what this type stands for // No idea what this type stands for
switch (type) switch (type)
{ {
//case 0: return key_for_type_1; // case 0: return key_for_type_1;
case 1: return SC_ISO_SERIES_KEY_2; case 1: return SC_ISO_SERIES_KEY_2;
case 2: return SC_ISO_SERIES_KEY_1; case 2: return SC_ISO_SERIES_KEY_1;
case 3: return SC_KEY_FOR_MASTER_2; case 3: return SC_KEY_FOR_MASTER_2;

View file

@ -8,7 +8,10 @@
#include <stdlib.h> #include <stdlib.h>
enum { CRYPTO_MAX_PATH = 4096 }; enum
{
CRYPTO_MAX_PATH = 4096
};
char* extract_file_name(const char* file_path, char real_file_name[CRYPTO_MAX_PATH]); char* extract_file_name(const char* file_path, char real_file_name[CRYPTO_MAX_PATH]);
@ -16,17 +19,17 @@ std::string sha256_get_hash(const char* data, usz size, bool lower_case);
// Hex string conversion auxiliary functions. // Hex string conversion auxiliary functions.
u64 hex_to_u64(const char* hex_str); u64 hex_to_u64(const char* hex_str);
void hex_to_bytes(unsigned char *data, const char *hex_str, unsigned int str_length); void hex_to_bytes(unsigned char* data, const char* hex_str, unsigned int str_length);
// Crypto functions (AES128-CBC, AES128-ECB, SHA1-HMAC and AES-CMAC). // Crypto functions (AES128-CBC, AES128-ECB, SHA1-HMAC and AES-CMAC).
void aescbc128_decrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, usz len); void aescbc128_decrypt(unsigned char* key, unsigned char* iv, unsigned char* in, unsigned char* out, usz len);
void aescbc128_encrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, usz len); void aescbc128_encrypt(unsigned char* key, unsigned char* iv, unsigned char* in, unsigned char* out, usz len);
void aesecb128_encrypt(unsigned char *key, unsigned char *in, unsigned char *out); void aesecb128_encrypt(unsigned char* key, unsigned char* in, unsigned char* out);
bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, usz in_len, unsigned char *hash, usz hash_len); bool hmac_hash_compare(unsigned char* key, int key_len, unsigned char* in, usz in_len, unsigned char* hash, usz hash_len);
void hmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, usz in_len, unsigned char *hash); void hmac_hash_forge(unsigned char* key, int key_len, unsigned char* in, usz in_len, unsigned char* hash);
bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, usz in_len, unsigned char *hash, usz hash_len); bool cmac_hash_compare(unsigned char* key, int key_len, unsigned char* in, usz in_len, unsigned char* hash, usz hash_len);
void cmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, usz in_len, unsigned char *hash); void cmac_hash_forge(unsigned char* key, int key_len, unsigned char* in, usz in_len, unsigned char* hash);
void mbedtls_zeroize(void *v, size_t n); void mbedtls_zeroize(void* v, size_t n);
// SC passphrase crypto // SC passphrase crypto

View file

@ -17,11 +17,11 @@ enum : u32
enum class AudioFreq : u32 enum class AudioFreq : u32
{ {
FREQ_32K = 32000, FREQ_32K = 32000,
FREQ_44K = 44100, FREQ_44K = 44100,
FREQ_48K = 48000, FREQ_48K = 48000,
FREQ_88K = 88200, FREQ_88K = 88200,
FREQ_96K = 96000, FREQ_96K = 96000,
FREQ_176K = 176400, FREQ_176K = 176400,
FREQ_192K = 192000, FREQ_192K = 192000,
}; };
@ -35,7 +35,7 @@ enum class AudioSampleSize : u32
// This enum is only used for emulation // This enum is only used for emulation
enum class AudioChannelCnt : u32 enum class AudioChannelCnt : u32
{ {
STEREO = 2, STEREO = 2,
SURROUND_5_1 = 6, SURROUND_5_1 = 6,
SURROUND_7_1 = 8, SURROUND_7_1 = 8,
}; };
@ -49,7 +49,6 @@ enum class AudioStateEvent : u32
class AudioBackend class AudioBackend
{ {
public: public:
struct VolumeParam struct VolumeParam
{ {
f32 initial_volume = 1.0f; f32 initial_volume = 1.0f;
@ -93,7 +92,10 @@ public:
virtual f64 GetCallbackFrameLen() = 0; virtual f64 GetCallbackFrameLen() = 0;
// Returns true if audio is currently being played, false otherwise. Reflects end result of Play() and Pause() calls. // Returns true if audio is currently being played, false otherwise. Reflects end result of Play() and Pause() calls.
virtual bool IsPlaying() { return m_playing; } virtual bool IsPlaying()
{
return m_playing;
}
// Start playing enqueued data. // Start playing enqueued data.
virtual void Play() = 0; virtual void Play() = 0;
@ -105,17 +107,26 @@ public:
* This virtual method should be reimplemented if backend can fail to be initialized under non-error conditions * This virtual method should be reimplemented if backend can fail to be initialized under non-error conditions
* eg. when there is no audio devices attached * eg. when there is no audio devices attached
*/ */
virtual bool Initialized() { return true; } virtual bool Initialized()
{
return true;
}
/* /*
* This virtual method should be reimplemented if backend can fail during normal operation * This virtual method should be reimplemented if backend can fail during normal operation
*/ */
virtual bool Operational() { return true; } virtual bool Operational()
{
return true;
}
/* /*
* This virtual method should be reimplemented if backend can report device changes * This virtual method should be reimplemented if backend can report device changes
*/ */
virtual bool DefaultDeviceChanged() { return false; } virtual bool DefaultDeviceChanged()
{
return false;
}
/* /*
* Helper methods * Helper methods
@ -180,20 +191,21 @@ public:
/* /*
* Downmix audio stream. * Downmix audio stream.
*/ */
template<AudioChannelCnt src_ch_cnt, audio_channel_layout dst_layout> template <AudioChannelCnt src_ch_cnt, audio_channel_layout dst_layout>
static void downmix(u32 sample_cnt, const f32* src, f32* dst) static void downmix(u32 sample_cnt, const f32* src, f32* dst)
{ {
const u32 dst_ch_cnt = default_layout_channel_count(dst_layout); const u32 dst_ch_cnt = default_layout_channel_count(dst_layout);
if (static_cast<u32>(src_ch_cnt) <= dst_ch_cnt) fmt::throw_exception("src channel count must be bigger than dst channel count"); if (static_cast<u32>(src_ch_cnt) <= dst_ch_cnt)
fmt::throw_exception("src channel count must be bigger than dst channel count");
static constexpr f32 center_coef = std::numbers::sqrt2_v<f32> / 2; static constexpr f32 center_coef = std::numbers::sqrt2_v<f32> / 2;
static constexpr f32 surround_coef = std::numbers::sqrt2_v<f32> / 2; static constexpr f32 surround_coef = std::numbers::sqrt2_v<f32> / 2;
for (u32 src_sample = 0, dst_sample = 0; src_sample < sample_cnt; src_sample += static_cast<u32>(src_ch_cnt), dst_sample += dst_ch_cnt) for (u32 src_sample = 0, dst_sample = 0; src_sample < sample_cnt; src_sample += static_cast<u32>(src_ch_cnt), dst_sample += dst_ch_cnt)
{ {
const f32 left = src[src_sample + 0]; const f32 left = src[src_sample + 0];
const f32 right = src[src_sample + 1]; const f32 right = src[src_sample + 1];
if constexpr (src_ch_cnt == AudioChannelCnt::STEREO) if constexpr (src_ch_cnt == AudioChannelCnt::STEREO)
{ {
if constexpr (dst_layout == audio_channel_layout::mono) if constexpr (dst_layout == audio_channel_layout::mono)
@ -203,9 +215,9 @@ public:
} }
else if constexpr (src_ch_cnt == AudioChannelCnt::SURROUND_5_1) else if constexpr (src_ch_cnt == AudioChannelCnt::SURROUND_5_1)
{ {
const f32 center = src[src_sample + 2]; const f32 center = src[src_sample + 2];
const f32 low_freq = src[src_sample + 3]; const f32 low_freq = src[src_sample + 3];
const f32 side_left = src[src_sample + 4]; const f32 side_left = src[src_sample + 4];
const f32 side_right = src[src_sample + 5]; const f32 side_right = src[src_sample + 5];
if constexpr (dst_layout == audio_channel_layout::quadraphonic || dst_layout == audio_channel_layout::quadraphonic_lfe) if constexpr (dst_layout == audio_channel_layout::quadraphonic || dst_layout == audio_channel_layout::quadraphonic_lfe)
@ -239,11 +251,11 @@ public:
} }
else if constexpr (src_ch_cnt == AudioChannelCnt::SURROUND_7_1) else if constexpr (src_ch_cnt == AudioChannelCnt::SURROUND_7_1)
{ {
const f32 center = src[src_sample + 2]; const f32 center = src[src_sample + 2];
const f32 low_freq = src[src_sample + 3]; const f32 low_freq = src[src_sample + 3];
const f32 rear_left = src[src_sample + 4]; const f32 rear_left = src[src_sample + 4];
const f32 rear_right = src[src_sample + 5]; const f32 rear_right = src[src_sample + 5];
const f32 side_left = src[src_sample + 6]; const f32 side_left = src[src_sample + 6];
const f32 side_right = src[src_sample + 7]; const f32 side_right = src[src_sample + 7];
if constexpr (dst_layout == audio_channel_layout::surround_5_1) if constexpr (dst_layout == audio_channel_layout::surround_5_1)
@ -372,12 +384,12 @@ protected:
void setup_channel_layout(u32 input_channel_count, u32 output_channel_count, audio_channel_layout layout, logs::channel& log); void setup_channel_layout(u32 input_channel_count, u32 output_channel_count, audio_channel_layout layout, logs::channel& log);
AudioSampleSize m_sample_size = AudioSampleSize::FLOAT; AudioSampleSize m_sample_size = AudioSampleSize::FLOAT;
AudioFreq m_sampling_rate = AudioFreq::FREQ_48K; AudioFreq m_sampling_rate = AudioFreq::FREQ_48K;
u32 m_channels = 2; u32 m_channels = 2;
audio_channel_layout m_layout = audio_channel_layout::automatic; audio_channel_layout m_layout = audio_channel_layout::automatic;
std::timed_mutex m_cb_mutex{}; std::timed_mutex m_cb_mutex{};
std::function<u32(u32, void *)> m_write_callback{}; std::function<u32(u32, void*)> m_write_callback{};
shared_mutex m_state_cb_mutex{}; shared_mutex m_state_cb_mutex{};
std::function<void(AudioStateEvent)> m_state_callback{}; std::function<void(AudioStateEvent)> m_state_callback{};
@ -385,6 +397,5 @@ protected:
bool m_playing = false; bool m_playing = false;
private: private:
static constexpr f32 VOLUME_CHANGE_DURATION = 0.016f; // sec static constexpr f32 VOLUME_CHANGE_DURATION = 0.016f; // sec
}; };

View file

@ -8,9 +8,9 @@ struct WAVHeader
{ {
struct RIFFHeader struct RIFFHeader
{ {
u8 ID[4] = { 'R', 'I', 'F', 'F' }; u8 ID[4] = {'R', 'I', 'F', 'F'};
le_t<u32> Size{}; // FileSize - 8 le_t<u32> Size{}; // FileSize - 8
u8 WAVE[4] = { 'W', 'A', 'V', 'E' }; u8 WAVE[4] = {'W', 'A', 'V', 'E'};
RIFFHeader() = default; RIFFHeader() = default;
@ -22,31 +22,26 @@ struct WAVHeader
struct FMTHeader struct FMTHeader
{ {
u8 ID[4] = { 'f', 'm', 't', ' ' }; u8 ID[4] = {'f', 'm', 't', ' '};
le_t<u32> Size = 16; le_t<u32> Size = 16;
le_t<u16> AudioFormat{}; // 1 for PCM, 3 for IEEE Floating Point le_t<u16> AudioFormat{}; // 1 for PCM, 3 for IEEE Floating Point
le_t<u16> NumChannels{}; // 1, 2, 6, 8 le_t<u16> NumChannels{}; // 1, 2, 6, 8
le_t<u32> SampleRate{}; // 44100-192000 le_t<u32> SampleRate{}; // 44100-192000
le_t<u32> ByteRate{}; // SampleRate * NumChannels * BitsPerSample/8 le_t<u32> ByteRate{}; // SampleRate * NumChannels * BitsPerSample/8
le_t<u16> BlockAlign{}; // NumChannels * BitsPerSample/8 le_t<u16> BlockAlign{}; // NumChannels * BitsPerSample/8
le_t<u16> BitsPerSample{}; // SampleSize * 8 le_t<u16> BitsPerSample{}; // SampleSize * 8
FMTHeader() = default; FMTHeader() = default;
FMTHeader(AudioChannelCnt ch, AudioFreq sample_rate, AudioSampleSize sample_size) FMTHeader(AudioChannelCnt ch, AudioFreq sample_rate, AudioSampleSize sample_size)
: AudioFormat(sample_size == AudioSampleSize::FLOAT ? 3 : 1) : AudioFormat(sample_size == AudioSampleSize::FLOAT ? 3 : 1), NumChannels(static_cast<u16>(ch)), SampleRate(static_cast<u32>(sample_rate)), ByteRate(SampleRate * NumChannels * static_cast<u32>(sample_size)), BlockAlign(NumChannels * static_cast<u32>(sample_size)), BitsPerSample(static_cast<u32>(sample_size) * 8)
, NumChannels(static_cast<u16>(ch))
, SampleRate(static_cast<u32>(sample_rate))
, ByteRate(SampleRate * NumChannels * static_cast<u32>(sample_size))
, BlockAlign(NumChannels * static_cast<u32>(sample_size))
, BitsPerSample(static_cast<u32>(sample_size) * 8)
{ {
} }
} FMT; } FMT;
struct FACTChunk struct FACTChunk
{ {
u8 ID[4] = { 'f', 'a', 'c', 't' }; u8 ID[4] = {'f', 'a', 'c', 't'};
le_t<u32> ChunkLength = 4; le_t<u32> ChunkLength = 4;
le_t<u32> SampleLength = 0; // total samples per channel le_t<u32> SampleLength = 0; // total samples per channel
@ -58,16 +53,13 @@ struct WAVHeader
} }
} FACT; } FACT;
u8 ID[4] = { 'd', 'a', 't', 'a' }; u8 ID[4] = {'d', 'a', 't', 'a'};
le_t<u32> Size{}; // size of data (256 * NumChannels * sizeof(f32)) le_t<u32> Size{}; // size of data (256 * NumChannels * sizeof(f32))
WAVHeader() = default; WAVHeader() = default;
WAVHeader(AudioChannelCnt ch, AudioFreq sample_rate, AudioSampleSize sample_size) WAVHeader(AudioChannelCnt ch, AudioFreq sample_rate, AudioSampleSize sample_size)
: RIFF(sizeof(RIFFHeader) + sizeof(FMTHeader)) : RIFF(sizeof(RIFFHeader) + sizeof(FMTHeader)), FMT(ch, sample_rate, sample_size), FACT(0), Size(0)
, FMT(ch, sample_rate, sample_size)
, FACT(0)
, Size(0)
{ {
} }
}; };
@ -85,6 +77,12 @@ public:
void Close(); void Close();
void WriteData(const void* buffer, u32 size); void WriteData(const void* buffer, u32 size);
u16 GetCh() const { return m_header.FMT.NumChannels; } u16 GetCh() const
u16 GetSampleSize() const { return m_header.FMT.BitsPerSample / 8; } {
return m_header.FMT.NumChannels;
}
u16 GetSampleSize() const
{
return m_header.FMT.BitsPerSample / 8;
}
}; };

View file

@ -6,7 +6,7 @@
#include "Emu/Audio/audio_device_enumerator.h" #include "Emu/Audio/audio_device_enumerator.h"
#ifdef _WIN32 #ifdef _WIN32
#include <Windows.h> #include <windows.h>
#include <system_error> #include <system_error>
#endif #endif
@ -23,7 +23,7 @@ CubebBackend::CubebBackend()
} }
#endif #endif
cubeb *ctx{}; cubeb* ctx{};
if (int err = cubeb_init(&ctx, "RPCS3", nullptr)) if (int err = cubeb_init(&ctx, "RPCS3", nullptr))
{ {
Cubeb.error("cubeb_init() failed: %i", err); Cubeb.error("cubeb_init() failed: %i", err);
@ -112,8 +112,10 @@ bool CubebBackend::Open(std::string_view dev_id, AudioFreq freq, AudioSampleSize
const bool use_default_device = dev_id.empty() || dev_id == audio_device_enumerator::DEFAULT_DEV_ID; const bool use_default_device = dev_id.empty() || dev_id == audio_device_enumerator::DEFAULT_DEV_ID;
if (use_default_device) Cubeb.notice("Trying to open default device"); if (use_default_device)
else Cubeb.notice("Trying to open device with dev_id='%s'", dev_id); Cubeb.notice("Trying to open default device");
else
Cubeb.notice("Trying to open device with dev_id='%s'", dev_id);
device_handle device = GetDevice(use_default_device ? "" : dev_id); device_handle device = GetDevice(use_default_device ? "" : dev_id);
@ -164,14 +166,14 @@ bool CubebBackend::Open(std::string_view dev_id, AudioFreq freq, AudioSampleSize
{ {
switch (m_layout) switch (m_layout)
{ {
case audio_channel_layout::automatic: break; case audio_channel_layout::automatic: break;
case audio_channel_layout::mono: return CUBEB_LAYOUT_MONO; case audio_channel_layout::mono: return CUBEB_LAYOUT_MONO;
case audio_channel_layout::stereo: return CUBEB_LAYOUT_STEREO; case audio_channel_layout::stereo: return CUBEB_LAYOUT_STEREO;
case audio_channel_layout::stereo_lfe: return CUBEB_LAYOUT_STEREO_LFE; case audio_channel_layout::stereo_lfe: return CUBEB_LAYOUT_STEREO_LFE;
case audio_channel_layout::quadraphonic: return CUBEB_LAYOUT_QUAD; case audio_channel_layout::quadraphonic: return CUBEB_LAYOUT_QUAD;
case audio_channel_layout::quadraphonic_lfe: return CUBEB_LAYOUT_QUAD_LFE; case audio_channel_layout::quadraphonic_lfe: return CUBEB_LAYOUT_QUAD_LFE;
case audio_channel_layout::surround_5_1: return CUBEB_LAYOUT_3F2_LFE; case audio_channel_layout::surround_5_1: return CUBEB_LAYOUT_3F2_LFE;
case audio_channel_layout::surround_7_1: return CUBEB_LAYOUT_3F4_LFE; case audio_channel_layout::surround_7_1: return CUBEB_LAYOUT_3F4_LFE;
} }
fmt::throw_exception("Invalid audio layout %d", static_cast<u32>(m_layout)); fmt::throw_exception("Invalid audio layout %d", static_cast<u32>(m_layout));
@ -240,7 +242,8 @@ void CubebBackend::Play()
return; return;
} }
if (m_playing) return; if (m_playing)
return;
std::lock_guard lock(m_cb_mutex); std::lock_guard lock(m_cb_mutex);
m_playing = true; m_playing = true;
@ -254,7 +257,8 @@ void CubebBackend::Pause()
return; return;
} }
if (!m_playing) return; if (!m_playing)
return;
std::lock_guard lock(m_cb_mutex); std::lock_guard lock(m_cb_mutex);
m_playing = false; m_playing = false;
@ -283,8 +287,10 @@ CubebBackend::device_handle CubebBackend::GetDevice(std::string_view dev_id)
{ {
const bool default_dev = dev_id.empty(); const bool default_dev = dev_id.empty();
if (default_dev) Cubeb.notice("Searching for default device"); if (default_dev)
else Cubeb.notice("Searching for device with dev_id='%s'", dev_id); Cubeb.notice("Searching for default device");
else
Cubeb.notice("Searching for device with dev_id='%s'", dev_id);
cubeb_device_collection dev_collection{}; cubeb_device_collection dev_collection{};
if (int err = cubeb_enumerate_devices(m_ctx, CUBEB_DEVICE_TYPE_OUTPUT, &dev_collection)) if (int err = cubeb_enumerate_devices(m_ctx, CUBEB_DEVICE_TYPE_OUTPUT, &dev_collection))
@ -363,13 +369,12 @@ CubebBackend::device_handle CubebBackend::GetDefaultDeviceAlt(AudioFreq freq, Au
Cubeb.notice("Starting alternative search for default device with freq=%d, sample_size=%d and ch_cnt=%d", static_cast<u32>(freq), static_cast<u32>(sample_size), static_cast<u32>(ch_cnt)); Cubeb.notice("Starting alternative search for default device with freq=%d, sample_size=%d and ch_cnt=%d", static_cast<u32>(freq), static_cast<u32>(sample_size), static_cast<u32>(ch_cnt));
cubeb_stream_params param = cubeb_stream_params param =
{ {
.format = sample_size == AudioSampleSize::S16 ? CUBEB_SAMPLE_S16NE : CUBEB_SAMPLE_FLOAT32NE, .format = sample_size == AudioSampleSize::S16 ? CUBEB_SAMPLE_S16NE : CUBEB_SAMPLE_FLOAT32NE,
.rate = static_cast<u32>(freq), .rate = static_cast<u32>(freq),
.channels = static_cast<u32>(ch_cnt), .channels = static_cast<u32>(ch_cnt),
.layout = CUBEB_LAYOUT_UNDEFINED, .layout = CUBEB_LAYOUT_UNDEFINED,
.prefs = CUBEB_STREAM_PREF_DISABLE_DEVICE_SWITCHING .prefs = CUBEB_STREAM_PREF_DISABLE_DEVICE_SWITCHING};
};
u32 min_latency{}; u32 min_latency{};
if (int err = cubeb_get_min_latency(m_ctx, &param, &min_latency)) if (int err = cubeb_get_min_latency(m_ctx, &param, &min_latency))
@ -379,7 +384,10 @@ CubebBackend::device_handle CubebBackend::GetDefaultDeviceAlt(AudioFreq freq, Au
} }
cubeb_stream* tmp_stream{}; cubeb_stream* tmp_stream{};
static auto dummy_data_cb = [](cubeb_stream*, void*, void const*, void*, long) -> long { return 0; }; static auto dummy_data_cb = [](cubeb_stream*, void*, void const*, void*, long) -> long
{
return 0;
};
static auto dummy_state_cb = [](cubeb_stream*, void*, cubeb_state) {}; static auto dummy_state_cb = [](cubeb_stream*, void*, cubeb_state) {};
if (int err = cubeb_stream_init(m_ctx, &tmp_stream, "Default device detector", nullptr, nullptr, nullptr, &param, min_latency, dummy_data_cb, dummy_state_cb, nullptr)) if (int err = cubeb_stream_init(m_ctx, &tmp_stream, "Default device detector", nullptr, nullptr, nullptr, &param, min_latency, dummy_data_cb, dummy_state_cb, nullptr))

View file

@ -14,7 +14,10 @@ public:
CubebBackend(const CubebBackend&) = delete; CubebBackend(const CubebBackend&) = delete;
CubebBackend& operator=(const CubebBackend&) = delete; CubebBackend& operator=(const CubebBackend&) = delete;
std::string_view GetName() const override { return "Cubeb"sv; } std::string_view GetName() const override
{
return "Cubeb"sv;
}
bool Initialized() override; bool Initialized() override;
bool Operational() override; bool Operational() override;
@ -51,7 +54,7 @@ private:
static long data_cb(cubeb_stream* stream, void* user_ptr, void const* input_buffer, void* output_buffer, long nframes); static long data_cb(cubeb_stream* stream, void* user_ptr, void const* input_buffer, void* output_buffer, long nframes);
static void state_cb(cubeb_stream* stream, void* user_ptr, cubeb_state state); static void state_cb(cubeb_stream* stream, void* user_ptr, cubeb_state state);
static void device_collection_changed_cb(cubeb* context, void* user_ptr); static void device_collection_changed_cb(cubeb* context, void* user_ptr);
static void log_cb(const char *fmt, ...); static void log_cb(const char* fmt, ...);
struct device_handle struct device_handle
{ {

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