Initial Commit

This commit is contained in:
Sajid
2024-09-30 12:06:17 +06:00
commit db51236165
42 changed files with 4843 additions and 0 deletions
+37
View File
@@ -0,0 +1,37 @@
#include <stdafx.h>
#include "code_cache.h"
#include "ppc_context.h"
CodeCache::CodeCache()
{
bucket = (char*)VirtualAlloc(nullptr, 0x200000000, MEM_RESERVE, PAGE_READWRITE);
assert(bucket);
}
CodeCache::~CodeCache()
{
VirtualFree(bucket, 0, MEM_RELEASE);
}
void CodeCache::Init()
{
for (size_t i = 0; PPCFuncMappings[i].guest != 0; i++)
{
if (PPCFuncMappings[i].host != nullptr)
{
VirtualAlloc(bucket + PPCFuncMappings[i].guest * 2, sizeof(void*), MEM_COMMIT, PAGE_READWRITE);
*(void**)(bucket + PPCFuncMappings[i].guest * 2) = PPCFuncMappings[i].host;
}
}
}
void CodeCache::Insert(uint32_t guest, const void* host)
{
VirtualAlloc(bucket + static_cast<uint64_t>(guest) * 2, sizeof(void*), MEM_COMMIT, PAGE_READWRITE);
*reinterpret_cast<const void**>(bucket + static_cast<uint64_t>(guest) * 2) = host;
}
void* CodeCache::Find(uint32_t guest) const
{
return *reinterpret_cast<void**>(bucket + static_cast<uint64_t>(guest) * 2);
}
+16
View File
@@ -0,0 +1,16 @@
#pragma once
struct CodeCache
{
char* bucket{};
CodeCache();
~CodeCache();
void Init();
void Insert(uint32_t guest, const void* host);
void* Find(uint32_t guest) const;
};
extern CodeCache gCodeCache;
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include "ppc_context.h"
#include "memory.h"
struct GuestCode
{
inline static void Run(void* hostAddress, PPCContext* ctx, void* baseAddress, void* callStack)
{
ctx->fpscr.loadFromHost();
reinterpret_cast<PPCFunc*>(hostAddress)(*ctx, reinterpret_cast<uint8_t*>(baseAddress));
}
inline static void Run(void* hostAddress, PPCContext* ctx)
{
ctx->fpscr.loadFromHost();
reinterpret_cast<PPCFunc*>(hostAddress)(*ctx, reinterpret_cast<uint8_t*>(gMemory.base));
}
inline static void Run(void* hostAddress)
{
Run(hostAddress, GetPPCContext());
}
};
+143
View File
@@ -0,0 +1,143 @@
#include <stdafx.h>
#include "guest_thread.h"
#include <kernel/memory.h>
#include <kernel/heap.h>
#include <kernel/function.h>
#include "code_cache.h"
#include "guest_code.h"
#include "ppc_context.h"
constexpr size_t PCR_SIZE = 0xAB0;
constexpr size_t TLS_SIZE = 0x100;
constexpr size_t TEB_SIZE = 0x2E0;
constexpr size_t STACK_SIZE = 0x40000;
constexpr size_t CALL_STACK_SIZE = 0x8000;
constexpr size_t TOTAL_SIZE = PCR_SIZE + TLS_SIZE + TEB_SIZE + STACK_SIZE + CALL_STACK_SIZE;
constexpr size_t TEB_OFFSET = PCR_SIZE + TLS_SIZE;
DWORD GuestThread::Start(uint32_t function)
{
const GuestThreadParameter parameter{ function };
return Start(parameter);
}
DWORD GuestThread::Start(const GuestThreadParameter& parameter)
{
auto* thread = (uint8_t*)gUserHeap.Alloc(TOTAL_SIZE);
const auto procMask = (uint8_t)(parameter.flags >> 24);
const auto cpuNumber = procMask == 0 ? 0 : 7 - std::countl_zero(procMask);
memset(thread, 0, TOTAL_SIZE);
*(uint32_t*)thread = std::byteswap(gMemory.MapVirtual(thread + PCR_SIZE)); // tls pointer
*(uint32_t*)(thread + 0x100) = std::byteswap(gMemory.MapVirtual(thread + PCR_SIZE + TLS_SIZE)); // teb pointer
*(thread + 0x10C) = cpuNumber;
*(uint32_t*)(thread + PCR_SIZE + 0x10) = 0xFFFFFFFF; // that one TLS entry that felt quirky
*(uint32_t*)(thread + PCR_SIZE + TLS_SIZE + 0x14C) = std::byteswap(GetCurrentThreadId()); // thread id
PPCContext ppcContext{};
ppcContext.fn = (uint8_t*)gCodeCache.bucket;
ppcContext.r1.u64 = gMemory.MapVirtual(thread + PCR_SIZE + TLS_SIZE + TEB_SIZE + STACK_SIZE); // stack pointer
ppcContext.r3.u64 = parameter.value;
ppcContext.r13.u64 = gMemory.MapVirtual(thread);
SetPPCContext(ppcContext);
GuestCode::Run(gCodeCache.Find(parameter.function), &ppcContext, gMemory.Translate(0), gMemory.Translate(ppcContext.r1.u32));
gUserHeap.Free(thread);
return (DWORD)ppcContext.r3.u64;
}
DWORD HostThreadStart(void* pParameter)
{
auto* parameter = static_cast<GuestThreadParameter*>(pParameter);
const auto result = GuestThread::Start(*parameter);
delete parameter;
return result;
}
HANDLE GuestThread::Start(uint32_t function, uint32_t parameter, uint32_t flags, LPDWORD threadId)
{
const auto hostCreationFlags = (flags & 1) != 0 ? CREATE_SUSPENDED : 0;
//return CreateThread(nullptr, 0, Start, (void*)((uint64_t(parameter) << 32) | function), suspended ? CREATE_SUSPENDED : 0, threadId);
return CreateThread(nullptr, 0, HostThreadStart, new GuestThreadParameter{ function, parameter, flags }, hostCreationFlags, threadId);
}
void GuestThread::SetThreadName(uint32_t id, const char* name)
{
#pragma pack(push,8)
const DWORD MS_VC_EXCEPTION = 0x406D1388;
typedef struct tagTHREADNAME_INFO
{
DWORD dwType; // Must be 0x1000.
LPCSTR szName; // Pointer to name (in user addr space).
DWORD dwThreadID; // Thread ID (-1=caller thread).
DWORD dwFlags; // Reserved for future use, must be zero.
} THREADNAME_INFO;
#pragma pack(pop)
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = name;
info.dwThreadID = id;
info.dwFlags = 0;
__try
{
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
}
}
void GuestThread::SetLastError(DWORD error)
{
auto* thread = (char*)gMemory.Translate(GetPPCContext()->r13.u32);
if (*(DWORD*)(thread + 0x150))
{
// Program doesn't want errors
return;
}
// TEB + 0x160 : Win32LastError
*(DWORD*)(thread + TEB_OFFSET + 0x160) = std::byteswap(error);
}
PPCContext* GuestThread::Invoke(uint32_t address)
{
auto* ctx = GetPPCContext();
GuestCode::Run(gCodeCache.Find(address), ctx);
return ctx;
}
void SetThreadNameImpl(uint32_t a1, uint32_t threadId, uint32_t* name)
{
GuestThread::SetThreadName(threadId, (const char*)gMemory.Translate(std::byteswap(*name)));
}
int GetThreadPriorityImpl(uint32_t hThread)
{
return GetThreadPriority((HANDLE)hThread);
}
DWORD SetThreadIdealProcessorImpl(uint32_t hThread, DWORD dwIdealProcessor)
{
return SetThreadIdealProcessor((HANDLE)hThread, dwIdealProcessor);
}
GUEST_FUNCTION_HOOK(sub_82DFA2E8, SetThreadNameImpl);
GUEST_FUNCTION_HOOK(sub_82BD57A8, GetThreadPriorityImpl);
GUEST_FUNCTION_HOOK(sub_82BD5910, SetThreadIdealProcessorImpl);
void GuestThread::InitHooks()
{
}
+21
View File
@@ -0,0 +1,21 @@
#pragma once
struct PPCContext;
struct GuestThreadParameter
{
uint32_t function;
uint32_t value;
uint32_t flags;
};
struct GuestThread
{
static DWORD Start(uint32_t function);
static DWORD Start(const GuestThreadParameter& parameter);
static HANDLE Start(uint32_t function, uint32_t parameter, uint32_t flags, LPDWORD threadId);
static void SetThreadName(uint32_t id, const char* name);
static void SetLastError(DWORD error);
static PPCContext* Invoke(uint32_t address);
static void InitHooks();
};
+15
View File
@@ -0,0 +1,15 @@
#pragma once
#include "ppc/ppc_context.h"
#include "ppc/ppc_recomp_shared.h"
inline thread_local PPCContext* gPPCContext;
inline PPCContext* GetPPCContext()
{
return gPPCContext;
}
inline void SetPPCContext(PPCContext& ctx)
{
gPPCContext = &ctx;
}