input, timing and other misc

This commit is contained in:
Sajid 2024-10-01 15:12:12 +06:00
parent 6fe61971a3
commit 040e3228e1
16 changed files with 650 additions and 76 deletions

View file

@ -50,10 +50,12 @@ set(SWA_APU_CXX_SOURCES
set(SWA_HID_CXX_SOURCES
"hid/hid.cpp"
"hid/driver/sdl_hid.cpp"
)
set(SWA_CXX_SOURCES
"main.cpp"
"misc_impl.cpp"
${SWA_KERNEL_CXX_SOURCES}
${SWA_CPU_CXX_SOURCES}

View file

@ -38,10 +38,10 @@ void* CodeCache::Find(uint32_t guest) const
SWA_API PPCFunc* KeFindHostFunction(uint32_t guest)
{
return static_cast<PPCFunc*>(gCodeCache.Find(guest));
return static_cast<PPCFunc*>(g_codeCache.Find(guest));
}
SWA_API void KeInsertHostFunction(uint32_t guest, PPCFunc* function)
{
gCodeCache.Insert(guest, function);
g_codeCache.Insert(guest, function);
}

View file

@ -16,4 +16,4 @@ struct CodeCache
SWA_API PPCFunc* KeFindHostFunction(uint32_t guest);
SWA_API void KeInsertHostFunction(uint32_t guest, PPCFunc* function);
extern CodeCache gCodeCache;
extern CodeCache g_codeCache;

View file

@ -13,7 +13,7 @@ struct GuestCode
inline static void Run(void* hostAddress, PPCContext* ctx)
{
ctx->fpscr.loadFromHost();
reinterpret_cast<PPCFunc*>(hostAddress)(*ctx, reinterpret_cast<uint8_t*>(gMemory.base));
reinterpret_cast<PPCFunc*>(hostAddress)(*ctx, reinterpret_cast<uint8_t*>(g_memory.base));
}
inline static void Run(void* hostAddress)

View file

@ -24,30 +24,30 @@ DWORD GuestThread::Start(uint32_t function)
DWORD GuestThread::Start(const GuestThreadParameter& parameter)
{
auto* thread = (uint8_t*)gUserHeap.Alloc(TOTAL_SIZE);
auto* thread = (uint8_t*)g_userHeap.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
*(uint32_t*)thread = std::byteswap(g_memory.MapVirtual(thread + PCR_SIZE)); // tls pointer
*(uint32_t*)(thread + 0x100) = std::byteswap(g_memory.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.fn = (uint8_t*)g_codeCache.bucket;
ppcContext.r1.u64 = g_memory.MapVirtual(thread + PCR_SIZE + TLS_SIZE + TEB_SIZE + STACK_SIZE); // stack pointer
ppcContext.r3.u64 = parameter.value;
ppcContext.r13.u64 = gMemory.MapVirtual(thread);
ppcContext.r13.u64 = g_memory.MapVirtual(thread);
SetPPCContext(ppcContext);
GuestCode::Run(gCodeCache.Find(parameter.function), &ppcContext, gMemory.Translate(0), gMemory.Translate(ppcContext.r1.u32));
gUserHeap.Free(thread);
GuestCode::Run(g_codeCache.Find(parameter.function), &ppcContext, g_memory.Translate(0), g_memory.Translate(ppcContext.r1.u32));
g_userHeap.Free(thread);
return (DWORD)ppcContext.r3.u64;
}
@ -99,7 +99,7 @@ void GuestThread::SetThreadName(uint32_t id, const char* name)
void GuestThread::SetLastError(DWORD error)
{
auto* thread = (char*)gMemory.Translate(GetPPCContext()->r13.u32);
auto* thread = (char*)g_memory.Translate(GetPPCContext()->r13.u32);
if (*(DWORD*)(thread + 0x150))
{
// Program doesn't want errors
@ -113,14 +113,14 @@ void GuestThread::SetLastError(DWORD error)
PPCContext* GuestThread::Invoke(uint32_t address)
{
auto* ctx = GetPPCContext();
GuestCode::Run(gCodeCache.Find(address), ctx);
GuestCode::Run(g_codeCache.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)));
GuestThread::SetThreadName(threadId, (const char*)g_memory.Translate(std::byteswap(*name)));
}
int GetThreadPriorityImpl(uint32_t hThread)
@ -133,19 +133,6 @@ DWORD SetThreadIdealProcessorImpl(uint32_t hThread, DWORD dwIdealProcessor)
return SetThreadIdealProcessor((HANDLE)hThread, dwIdealProcessor);
}
GUEST_FUNCTION_HOOK(sub_831B0ED0, memcpy);
GUEST_FUNCTION_HOOK(sub_831CCB98, memcpy);
GUEST_FUNCTION_HOOK(sub_831CEAE0, memcpy);
GUEST_FUNCTION_HOOK(sub_831CEE04, memcpy);
GUEST_FUNCTION_HOOK(sub_831CF2D0, memcpy);
GUEST_FUNCTION_HOOK(sub_831CF660, memcpy);
GUEST_FUNCTION_HOOK(sub_831B1358, memcpy);
GUEST_FUNCTION_HOOK(sub_831B5E00, memmove);
GUEST_FUNCTION_HOOK(sub_831B0BA0, memset);
GUEST_FUNCTION_HOOK(sub_831CCAA0, memset);
GUEST_FUNCTION_HOOK(sub_82BD4CA8, OutputDebugStringA);
GUEST_FUNCTION_HOOK(sub_82DFA2E8, SetThreadNameImpl);
GUEST_FUNCTION_HOOK(sub_82BD57A8, GetThreadPriorityImpl);
GUEST_FUNCTION_HOOK(sub_82BD5910, SetThreadIdealProcessorImpl);

View file

@ -0,0 +1,256 @@
#include <stdafx.h>
#include <SDL.h>
#include <hid/hid_detail.h>
#define VIBRATION_TIMEOUT_MS 5000
class Controller
{
public:
SDL_GameController* controller{};
SDL_Joystick* joystick{};
SDL_JoystickID id{ -1 };
XAMINPUT_GAMEPAD state{};
XAMINPUT_VIBRATION vibration{ 0, 0 };
Controller() = default;
explicit Controller(int index) : Controller(SDL_GameControllerOpen(index))
{
}
Controller(SDL_GameController* controller) : controller(controller)
{
if (!controller)
{
return;
}
joystick = SDL_GameControllerGetJoystick(controller);
id = SDL_JoystickInstanceID(joystick);
}
void Close()
{
if (controller == nullptr)
{
return;
}
SDL_GameControllerClose(controller);
controller = nullptr;
joystick = nullptr;
id = -1;
}
void PollAxis()
{
auto& pad = state;
pad.sThumbLX = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTX);
pad.sThumbLY = ~SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_LEFTY);
pad.sThumbRX = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX);
pad.sThumbRY = ~SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY);
pad.bLeftTrigger = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT) >> 7;
pad.bRightTrigger = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) >> 7;
}
#define TRANSLATE_INPUT(S, X) SDL_GameControllerGetButton(controller, S) << FirstBitLow(X)
void Poll()
{
if (controller == nullptr)
{
return;
}
auto& pad = state;
pad.wButtons = 0;
pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_DPAD_UP, XAMINPUT_GAMEPAD_DPAD_UP);
pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_DPAD_DOWN, XAMINPUT_GAMEPAD_DPAD_DOWN);
pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_DPAD_LEFT, XAMINPUT_GAMEPAD_DPAD_LEFT);
pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_DPAD_RIGHT, XAMINPUT_GAMEPAD_DPAD_RIGHT);
pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_START, XAMINPUT_GAMEPAD_START);
pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_BACK, XAMINPUT_GAMEPAD_BACK);
pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_LEFTSTICK, XAMINPUT_GAMEPAD_LEFT_THUMB);
pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_RIGHTSTICK, XAMINPUT_GAMEPAD_RIGHT_THUMB);
pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_LEFTSHOULDER, XAMINPUT_GAMEPAD_LEFT_SHOULDER);
pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, XAMINPUT_GAMEPAD_RIGHT_SHOULDER);
pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_A, XAMINPUT_GAMEPAD_A);
pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_B, XAMINPUT_GAMEPAD_B);
pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_X, XAMINPUT_GAMEPAD_X);
pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_Y, XAMINPUT_GAMEPAD_Y);
}
void SetVibration(const XAMINPUT_VIBRATION& vibration)
{
if (controller == nullptr)
{
return;
}
this->vibration = vibration;
SDL_GameControllerRumble(controller, vibration.wLeftMotorSpeed * 256, vibration.wRightMotorSpeed * 256, VIBRATION_TIMEOUT_MS);
}
};
std::array<Controller, 4> g_controllers;
inline Controller* EnsureController(DWORD dwUserIndex)
{
if (!g_controllers[dwUserIndex].controller)
{
return nullptr;
}
return &g_controllers[dwUserIndex];
}
inline size_t FindFreeController()
{
for (size_t i = 0; i < g_controllers.size(); i++)
{
if (!g_controllers[i].controller)
{
return i;
}
}
return -1;
}
inline Controller* FindController(int which)
{
for (auto& controller : g_controllers)
{
if (controller.id == which)
{
return &controller;
}
}
return nullptr;
}
int OnSDLEvent(void*, SDL_Event* event)
{
if (event->type >= SDL_CONTROLLERAXISMOTION && event->type < SDL_FINGERDOWN)
{
if (event->type == SDL_CONTROLLERDEVICEADDED)
{
const auto freeIndex = FindFreeController();
if (freeIndex != -1)
{
g_controllers[freeIndex] = Controller(event->cdevice.which);
}
}
if (event->type == SDL_CONTROLLERDEVICEREMOVED)
{
auto* controller = FindController(event->cdevice.which);
if (controller)
{
controller->Close();
}
}
else if (event->type == SDL_CONTROLLERBUTTONDOWN || event->type == SDL_CONTROLLERBUTTONUP || event->type == SDL_CONTROLLERAXISMOTION)
{
auto* controller = FindController(event->cdevice.which);
if (controller)
{
if (event->type == SDL_CONTROLLERAXISMOTION)
{
controller->PollAxis();
}
else
{
controller->Poll();
}
}
}
}
return 0;
}
void hid::detail::Init()
{
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS3, "1");
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4, "1");
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5, "1");
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_WII, "1");
SDL_SetHint(SDL_HINT_XINPUT_ENABLED, "1");
SDL_InitSubSystem(SDL_INIT_EVENTS);
SDL_AddEventWatch(OnSDLEvent, nullptr);
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
}
uint32_t hid::detail::GetState(uint32_t dwUserIndex, XAMINPUT_STATE* pState)
{
static DWORD packet;
if (!pState)
{
return ERROR_BAD_ARGUMENTS;
}
memset(pState, 0, sizeof(*pState));
pState->dwPacketNumber = packet++;
SDL_JoystickUpdate();
auto* controller = EnsureController(dwUserIndex);
if (controller == nullptr)
{
return ERROR_DEVICE_NOT_CONNECTED;
}
pState->Gamepad = g_controllers[dwUserIndex].state;
return ERROR_SUCCESS;
}
uint32_t hid::detail::SetState(uint32_t dwUserIndex, XAMINPUT_VIBRATION* pVibration)
{
if (!pVibration)
{
return ERROR_BAD_ARGUMENTS;
}
SDL_JoystickUpdate();
auto* controller = EnsureController(dwUserIndex);
if (controller == nullptr)
{
return ERROR_DEVICE_NOT_CONNECTED;
}
controller->SetVibration(*pVibration);
return ERROR_SUCCESS;
}
uint32_t hid::detail::GetCapabilities(uint32_t dwUserIndex, XAMINPUT_CAPABILITIES* pCaps)
{
if (!pCaps)
{
return ERROR_BAD_ARGUMENTS;
}
SDL_JoystickUpdate();
auto* controller = EnsureController(dwUserIndex);
if (controller == nullptr)
{
return ERROR_DEVICE_NOT_CONNECTED;
}
memset(pCaps, 0, sizeof(*pCaps));
pCaps->Type = XAMINPUT_DEVTYPE_GAMEPAD;
pCaps->SubType = XAMINPUT_DEVSUBTYPE_GAMEPAD; // TODO: other types?
pCaps->Flags = 0;
pCaps->Gamepad = controller->state;
pCaps->Vibration = controller->vibration;
return ERROR_SUCCESS;
}

View file

@ -1,22 +1,23 @@
#include <stdafx.h>
#include "hid.h"
#include "hid_detail.h"
DWORD hid::GetState(DWORD dwUserIndex, XAMINPUT_STATE* pState)
void hid::Init()
{
return 1;
detail::Init();
}
DWORD hid::SetState(DWORD dwUserIndex, XAMINPUT_VIBRATION* pVibration)
uint32_t hid::GetState(uint32_t dwUserIndex, XAMINPUT_STATE* pState)
{
return 1;
return detail::GetState(dwUserIndex, pState);
}
DWORD hid::GetCapabilities(DWORD dwUserIndex, XAMINPUT_CAPABILITIES* pCaps)
uint32_t hid::SetState(uint32_t dwUserIndex, XAMINPUT_VIBRATION* pVibration)
{
return 1;
return detail::SetState(dwUserIndex, pVibration);
}
int hid::OnSDLEvent(void*, SDL_Event* event)
uint32_t hid::GetCapabilities(uint32_t dwUserIndex, XAMINPUT_CAPABILITIES* pCaps)
{
return 0;
return detail::GetCapabilities(dwUserIndex, pCaps);
}

View file

@ -4,10 +4,8 @@ union SDL_Event;
namespace hid
{
void Init();
DWORD GetState(DWORD dwUserIndex, XAMINPUT_STATE* pState);
DWORD SetState(DWORD dwUserIndex, XAMINPUT_VIBRATION* pVibration);
uint32_t GetState(uint32_t dwUserIndex, XAMINPUT_STATE* pState);
uint32_t SetState(uint32_t dwUserIndex, XAMINPUT_VIBRATION* pVibration);
DWORD GetCapabilities(DWORD dwUserIndex, XAMINPUT_CAPABILITIES* pCaps);
int OnSDLEvent(void*, SDL_Event* event);
}
uint32_t GetCapabilities(uint32_t dwUserIndex, XAMINPUT_CAPABILITIES* pCaps);
}

View file

@ -0,0 +1,10 @@
#pragma once
namespace hid::detail
{
void Init();
uint32_t GetState(uint32_t dwUserIndex, XAMINPUT_STATE* pState);
uint32_t SetState(uint32_t dwUserIndex, XAMINPUT_VIBRATION* pVibration);
uint32_t GetCapabilities(uint32_t dwUserIndex, XAMINPUT_CAPABILITIES* pCaps);
}

View file

@ -8,11 +8,11 @@ constexpr size_t RESERVED_END = 0xA0000000;
void Heap::Init()
{
gMemory.Alloc(0x20000, RESERVED_BEGIN - 0x20000, MEM_COMMIT);
heap = o1heapInit(gMemory.Translate(0x20000), RESERVED_BEGIN - 0x20000);
g_memory.Alloc(0x20000, RESERVED_BEGIN - 0x20000, MEM_COMMIT);
heap = o1heapInit(g_memory.Translate(0x20000), RESERVED_BEGIN - 0x20000);
gMemory.Alloc(RESERVED_END, 0x100000000 - RESERVED_END, MEM_COMMIT);
physicalHeap = o1heapInit(gMemory.Translate(RESERVED_END), 0x100000000 - RESERVED_END);
g_memory.Alloc(RESERVED_END, 0x100000000 - RESERVED_END, MEM_COMMIT);
physicalHeap = o1heapInit(g_memory.Translate(RESERVED_END), 0x100000000 - RESERVED_END);
}
void* Heap::Alloc(size_t size)
@ -62,35 +62,35 @@ size_t Heap::Size(void* ptr)
uint32_t RtlAllocateHeap(uint32_t heapHandle, uint32_t flags, uint32_t size)
{
void* ptr = gUserHeap.Alloc(size);
void* ptr = g_userHeap.Alloc(size);
if ((flags & 0x8) != 0)
memset(ptr, 0, size);
assert(ptr);
return gMemory.MapVirtual(ptr);
return g_memory.MapVirtual(ptr);
}
uint32_t RtlReAllocateHeap(uint32_t heapHandle, uint32_t flags, uint32_t memoryPointer, uint32_t size)
{
void* ptr = gUserHeap.Alloc(size);
void* ptr = g_userHeap.Alloc(size);
if ((flags & 0x8) != 0)
memset(ptr, 0, size);
if (memoryPointer != 0)
{
void* oldPtr = gMemory.Translate(memoryPointer);
memcpy(ptr, oldPtr, std::min<size_t>(size, gUserHeap.Size(oldPtr)));
gUserHeap.Free(oldPtr);
void* oldPtr = g_memory.Translate(memoryPointer);
memcpy(ptr, oldPtr, std::min<size_t>(size, g_userHeap.Size(oldPtr)));
g_userHeap.Free(oldPtr);
}
assert(ptr);
return gMemory.MapVirtual(ptr);
return g_memory.MapVirtual(ptr);
}
uint32_t RtlFreeHeap(uint32_t heapHandle, uint32_t flags, uint32_t memoryPointer)
{
if (memoryPointer != NULL)
gUserHeap.Free(gMemory.Translate(memoryPointer));
g_userHeap.Free(g_memory.Translate(memoryPointer));
return true;
}
@ -98,7 +98,7 @@ uint32_t RtlFreeHeap(uint32_t heapHandle, uint32_t flags, uint32_t memoryPointer
uint32_t RtlSizeHeap(uint32_t heapHandle, uint32_t flags, uint32_t memoryPointer)
{
if (memoryPointer != NULL)
return (uint32_t)gUserHeap.Size(gMemory.Translate(memoryPointer));
return (uint32_t)g_userHeap.Size(g_memory.Translate(memoryPointer));
return 0;
}
@ -106,20 +106,20 @@ uint32_t RtlSizeHeap(uint32_t heapHandle, uint32_t flags, uint32_t memoryPointer
SWA_API uint32_t XAlloc(uint32_t size, uint32_t flags)
{
void* ptr = (flags & 0x80000000) != 0 ?
gUserHeap.AllocPhysical(size, (1ull << ((flags >> 24) & 0xF))) :
gUserHeap.Alloc(size);
g_userHeap.AllocPhysical(size, (1ull << ((flags >> 24) & 0xF))) :
g_userHeap.Alloc(size);
if ((flags & 0x40000000) != 0)
memset(ptr, 0, size);
assert(ptr);
return gMemory.MapVirtual(ptr);
return g_memory.MapVirtual(ptr);
}
SWA_API void XFree(uint32_t baseAddress, uint32_t flags)
{
if (baseAddress != NULL)
gUserHeap.Free(gMemory.Translate(baseAddress));
g_userHeap.Free(g_memory.Translate(baseAddress));
}
GUEST_FUNCTION_STUB(sub_82BD7788); // HeapCreate

View file

@ -35,4 +35,4 @@ struct Heap
}
};
extern Heap gUserHeap;
extern Heap g_userHeap;

View file

@ -701,7 +701,7 @@ void KfAcquireSpinLock(uint32_t* spinLock)
const auto ctx = GetPPCContext();
//printf("!!! STUB !!! KfAcquireSpinLock\n");
while (InterlockedCompareExchange((volatile long*)spinLock, std::byteswap(*(uint32_t*)(gMemory.Translate(ctx->r13.u32 + 0x110))), 0) != 0)
while (InterlockedCompareExchange((volatile long*)spinLock, std::byteswap(*(uint32_t*)(g_memory.Translate(ctx->r13.u32 + 0x110))), 0) != 0)
{
Sleep(0);
}
@ -717,7 +717,7 @@ void MmFreePhysicalMemory(uint32_t type, uint32_t guestAddress)
{
//printf("!!! STUB !!! MmFreePhysicalMemory\n");
if (guestAddress != NULL)
gUserHeap.Free(gMemory.Translate(guestAddress));
g_userHeap.Free(g_memory.Translate(guestAddress));
}
bool VdPersistDisplay(uint32_t a1, uint32_t* a2)
@ -748,7 +748,7 @@ void KeAcquireSpinLockAtRaisedIrql(uint32_t* spinLock)
const auto ctx = GetPPCContext();
//printf("!!! STUB !!! KeAcquireSpinLockAtRaisedIrql\n");
while (InterlockedCompareExchange((volatile long*)spinLock, std::byteswap(*(uint32_t*)(gMemory.Translate(ctx->r13.u32 + 0x110))), 0) != 0)
while (InterlockedCompareExchange((volatile long*)spinLock, std::byteswap(*(uint32_t*)(g_memory.Translate(ctx->r13.u32 + 0x110))), 0) != 0)
{
Sleep(0);
}
@ -891,7 +891,7 @@ uint32_t MmAllocatePhysicalMemoryEx(
uint32_t alignment)
{
printf("MmAllocatePhysicalMemoryEx(): %x %x %x %x %x %x\n", flags, size, protect, minAddress, maxAddress, alignment);
return gMemory.MapVirtual(gUserHeap.AllocPhysical(size, alignment));
return g_memory.MapVirtual(g_userHeap.AllocPhysical(size, alignment));
}
void ObDeleteSymbolicLink()
@ -997,7 +997,7 @@ DWORD XMsgInProcessCall(uint32_t app, uint32_t message, XDWORD* param1, XDWORD*
if (message == 0x7001B)
{
uint32_t* ptr = (uint32_t*)gMemory.Translate(param1[1]);
uint32_t* ptr = (uint32_t*)g_memory.Translate(param1[1]);
ptr[0] = 0;
ptr[1] = 0;
}

View file

@ -33,5 +33,5 @@ uint32_t Memory::MapVirtual(void* host) const noexcept
SWA_API void* MmGetHostAddress(uint32_t ptr)
{
return gMemory.Translate(ptr);
return g_memory.Translate(ptr);
}

View file

@ -19,4 +19,4 @@ public:
};
SWA_API void* MmGetHostAddress(uint32_t ptr);
extern Memory gMemory;
extern Memory g_memory;

View file

@ -10,15 +10,16 @@
#include <file.h>
#include <xex.h>
#include <apu/audio.h>
#include <hid/hid.h>
#define GAME_XEX_PATH "game:\\default.xex"
const size_t XMAIOBegin = 0x7FEA0000;
const size_t XMAIOEnd = XMAIOBegin + 0x0000FFFF;
Memory gMemory{ reinterpret_cast<void*>(0x100000000), 0x100000000 };
Heap gUserHeap;
CodeCache gCodeCache;
Memory g_memory{ reinterpret_cast<void*>(0x100000000), 0x100000000 };
Heap g_userHeap;
CodeCache g_codeCache;
// Name inspired from nt's entry point
void KiSystemStartup()
@ -27,11 +28,11 @@ void KiSystemStartup()
CoInitializeEx(nullptr, COINIT_MULTITHREADED);
#endif
gMemory.Alloc(0x10000, 0x1000, MEM_COMMIT);
gUserHeap.Init();
gCodeCache.Init();
g_memory.Alloc(0x10000, 0x1000, MEM_COMMIT);
g_userHeap.Init();
g_codeCache.Init();
gMemory.Alloc(XMAIOBegin, 0xFFFF, MEM_COMMIT);
g_memory.Alloc(XMAIOBegin, 0xFFFF, MEM_COMMIT);
const auto gameContent = XamMakeContent(XCONTENTTYPE_RESERVED, "Game");
const auto updateContent = XamMakeContent(XCONTENTTYPE_RESERVED, "Update");
@ -55,6 +56,7 @@ void KiSystemStartup()
XamContentCreateEx(0, "D", &gameContent, OPEN_EXISTING, nullptr, nullptr, 0, 0, nullptr);
XAudioInitializeSystem();
hid::Init();
}
uint32_t LdrLoadModule(const char* path)
@ -69,7 +71,7 @@ uint32_t LdrLoadModule(const char* path)
auto* xex = reinterpret_cast<XEX_HEADER*>(loadResult->data());
auto security = reinterpret_cast<XEX2_SECURITY_INFO*>((char*)xex + xex->AddressOfSecurityInfo);
gMemory.Alloc(security->ImageBase, security->SizeOfImage, MEM_COMMIT);
g_memory.Alloc(security->ImageBase, security->SizeOfImage, MEM_COMMIT);
auto format = Xex2FindOptionalHeader<XEX_FILE_FORMAT_INFO>(xex, XEX_HEADER_FILE_FORMAT_INFO);
auto entry = *Xex2FindOptionalHeader<uint32_t>(xex, XEX_HEADER_ENTRY_POINT);
@ -79,7 +81,7 @@ uint32_t LdrLoadModule(const char* path)
if (format->CompressionType == 1)
{
auto srcData = (char*)xex + xex->SizeOfHeader;
auto destData = (char*)gMemory.Translate(security->ImageBase);
auto destData = (char*)g_memory.Translate(security->ImageBase);
auto numBlocks = (format->SizeOfHeader / sizeof(XEX_BASIC_FILE_COMPRESSION_INFO)) - 1;
auto blocks = reinterpret_cast<const XEX_BASIC_FILE_COMPRESSION_INFO*>(format + 1);

View file

@ -0,0 +1,318 @@
#include "stdafx.h"
#include <kernel/function.h>
// TODO: Multiplatform support
void CriErrNotify1(const char* message)
{
OutputDebugStringA(message);
OutputDebugStringA("\n");
}
void CriErrNotify2(uint32_t category, const char* message)
{
OutputDebugStringA(message);
OutputDebugStringA("\n");
}
BOOL QueryPerformanceCounterImpl(LARGE_INTEGER* lpPerformanceCount)
{
BOOL result = QueryPerformanceCounter(lpPerformanceCount);
ByteSwap(lpPerformanceCount->QuadPart);
return result;
}
BOOL QueryPerformanceFrequencyImpl(LARGE_INTEGER* lpFrequency)
{
BOOL result = QueryPerformanceFrequency(lpFrequency);
ByteSwap(lpFrequency->QuadPart);
return result;
}
// https://learn.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-memorystatus
typedef struct _XMEMORYSTATUS {
XDWORD dwLength;
XDWORD dwMemoryLoad;
XDWORD dwTotalPhys;
XDWORD dwAvailPhys;
XDWORD dwTotalPageFile;
XDWORD dwAvailPageFile;
XDWORD dwTotalVirtual;
XDWORD dwAvailVirtual;
} XMEMORYSTATUS, *XLPMEMORYSTATUS;
void GlobalMemoryStatusImpl(XLPMEMORYSTATUS lpMemoryStatus)
{
lpMemoryStatus->dwLength = sizeof(XMEMORYSTATUS);
lpMemoryStatus->dwMemoryLoad = 0;
lpMemoryStatus->dwTotalPhys = 0x20000000;
lpMemoryStatus->dwAvailPhys = 0x20000000;
lpMemoryStatus->dwTotalPageFile = 0x20000000;
lpMemoryStatus->dwAvailPageFile = 0x20000000;
lpMemoryStatus->dwTotalVirtual = 0x20000000;
lpMemoryStatus->dwAvailVirtual = 0x20000000;
}
GUEST_FUNCTION_HOOK(sub_831B0ED0, memcpy);
GUEST_FUNCTION_HOOK(sub_831CCB98, memcpy);
GUEST_FUNCTION_HOOK(sub_831CEAE0, memcpy);
GUEST_FUNCTION_HOOK(sub_831CEE04, memcpy);
GUEST_FUNCTION_HOOK(sub_831CF2D0, memcpy);
GUEST_FUNCTION_HOOK(sub_831CF660, memcpy);
GUEST_FUNCTION_HOOK(sub_831B1358, memcpy);
GUEST_FUNCTION_HOOK(sub_831B5E00, memmove);
GUEST_FUNCTION_HOOK(sub_831B0BA0, memset);
GUEST_FUNCTION_HOOK(sub_831CCAA0, memset);
GUEST_FUNCTION_HOOK(sub_82BD4CA8, OutputDebugStringA);
#ifdef _DEBUG
GUEST_FUNCTION_HOOK(sub_8312EB48, CriErrNotify1);
GUEST_FUNCTION_HOOK(sub_83185B00, CriErrNotify1);
GUEST_FUNCTION_HOOK(sub_831683E0, CriErrNotify2);
#endif
GUEST_FUNCTION_HOOK(sub_82BD4AC8, QueryPerformanceCounterImpl);
GUEST_FUNCTION_HOOK(sub_831CD040, QueryPerformanceFrequencyImpl);
GUEST_FUNCTION_HOOK(sub_82BD4BC0, GlobalMemoryStatusImpl);
#if defined(PPC_CONFIG_NON_VOLATILE_AS_LOCAL) && defined(PPC_CONFIG_NON_ARGUMENT_AS_LOCAL)
GUEST_FUNCTION_STUB(sub_831B1400);
GUEST_FUNCTION_STUB(__savefpr_15);
GUEST_FUNCTION_STUB(__savefpr_16);
GUEST_FUNCTION_STUB(__savefpr_17);
GUEST_FUNCTION_STUB(__savefpr_18);
GUEST_FUNCTION_STUB(__savefpr_19);
GUEST_FUNCTION_STUB(__savefpr_20);
GUEST_FUNCTION_STUB(__savefpr_21);
GUEST_FUNCTION_STUB(__savefpr_22);
GUEST_FUNCTION_STUB(__savefpr_23);
GUEST_FUNCTION_STUB(__savefpr_24);
GUEST_FUNCTION_STUB(__savefpr_25);
GUEST_FUNCTION_STUB(__savefpr_26);
GUEST_FUNCTION_STUB(__savefpr_27);
GUEST_FUNCTION_STUB(__savefpr_28);
GUEST_FUNCTION_STUB(__savefpr_29);
GUEST_FUNCTION_STUB(__savefpr_30);
GUEST_FUNCTION_STUB(__savefpr_31);
GUEST_FUNCTION_STUB(sub_831B144C);
GUEST_FUNCTION_STUB(__restfpr_15);
GUEST_FUNCTION_STUB(__restfpr_16);
GUEST_FUNCTION_STUB(__restfpr_17);
GUEST_FUNCTION_STUB(__restfpr_18);
GUEST_FUNCTION_STUB(__restfpr_19);
GUEST_FUNCTION_STUB(__restfpr_20);
GUEST_FUNCTION_STUB(__restfpr_21);
GUEST_FUNCTION_STUB(__restfpr_22);
GUEST_FUNCTION_STUB(__restfpr_23);
GUEST_FUNCTION_STUB(__restfpr_24);
GUEST_FUNCTION_STUB(__restfpr_25);
GUEST_FUNCTION_STUB(__restfpr_26);
GUEST_FUNCTION_STUB(__restfpr_27);
GUEST_FUNCTION_STUB(__restfpr_28);
GUEST_FUNCTION_STUB(__restfpr_29);
GUEST_FUNCTION_STUB(__restfpr_30);
GUEST_FUNCTION_STUB(__restfpr_31);
GUEST_FUNCTION_STUB(sub_831B0AF0);
GUEST_FUNCTION_STUB(__savegprlr_15);
GUEST_FUNCTION_STUB(__savegprlr_16);
GUEST_FUNCTION_STUB(__savegprlr_17);
GUEST_FUNCTION_STUB(__savegprlr_18);
GUEST_FUNCTION_STUB(__savegprlr_19);
GUEST_FUNCTION_STUB(__savegprlr_20);
GUEST_FUNCTION_STUB(__savegprlr_21);
GUEST_FUNCTION_STUB(__savegprlr_22);
GUEST_FUNCTION_STUB(__savegprlr_23);
GUEST_FUNCTION_STUB(__savegprlr_24);
GUEST_FUNCTION_STUB(__savegprlr_25);
GUEST_FUNCTION_STUB(__savegprlr_26);
GUEST_FUNCTION_STUB(__savegprlr_27);
GUEST_FUNCTION_STUB(__savegprlr_28);
GUEST_FUNCTION_STUB(__savegprlr_29);
GUEST_FUNCTION_STUB(__savegprlr_30);
GUEST_FUNCTION_STUB(__savegprlr_31);
GUEST_FUNCTION_STUB(sub_831B0B40);
GUEST_FUNCTION_STUB(__restgprlr_15);
GUEST_FUNCTION_STUB(__restgprlr_16);
GUEST_FUNCTION_STUB(__restgprlr_17);
GUEST_FUNCTION_STUB(__restgprlr_18);
GUEST_FUNCTION_STUB(__restgprlr_19);
GUEST_FUNCTION_STUB(__restgprlr_20);
GUEST_FUNCTION_STUB(__restgprlr_21);
GUEST_FUNCTION_STUB(__restgprlr_22);
GUEST_FUNCTION_STUB(__restgprlr_23);
GUEST_FUNCTION_STUB(__restgprlr_24);
GUEST_FUNCTION_STUB(__restgprlr_25);
GUEST_FUNCTION_STUB(__restgprlr_26);
GUEST_FUNCTION_STUB(__restgprlr_27);
GUEST_FUNCTION_STUB(__restgprlr_28);
GUEST_FUNCTION_STUB(__restgprlr_29);
GUEST_FUNCTION_STUB(__restgprlr_30);
GUEST_FUNCTION_STUB(__restgprlr_31);
GUEST_FUNCTION_STUB(sub_831B3450);
GUEST_FUNCTION_STUB(__savevmx_15);
GUEST_FUNCTION_STUB(__savevmx_16);
GUEST_FUNCTION_STUB(__savevmx_17);
GUEST_FUNCTION_STUB(__savevmx_18);
GUEST_FUNCTION_STUB(__savevmx_19);
GUEST_FUNCTION_STUB(__savevmx_20);
GUEST_FUNCTION_STUB(__savevmx_21);
GUEST_FUNCTION_STUB(__savevmx_22);
GUEST_FUNCTION_STUB(__savevmx_23);
GUEST_FUNCTION_STUB(__savevmx_24);
GUEST_FUNCTION_STUB(__savevmx_25);
GUEST_FUNCTION_STUB(__savevmx_26);
GUEST_FUNCTION_STUB(__savevmx_27);
GUEST_FUNCTION_STUB(__savevmx_28);
GUEST_FUNCTION_STUB(__savevmx_29);
GUEST_FUNCTION_STUB(__savevmx_30);
GUEST_FUNCTION_STUB(__savevmx_31);
GUEST_FUNCTION_STUB(__savevmx_64);
GUEST_FUNCTION_STUB(__savevmx_65);
GUEST_FUNCTION_STUB(__savevmx_66);
GUEST_FUNCTION_STUB(__savevmx_67);
GUEST_FUNCTION_STUB(__savevmx_68);
GUEST_FUNCTION_STUB(__savevmx_69);
GUEST_FUNCTION_STUB(__savevmx_70);
GUEST_FUNCTION_STUB(__savevmx_71);
GUEST_FUNCTION_STUB(__savevmx_72);
GUEST_FUNCTION_STUB(__savevmx_73);
GUEST_FUNCTION_STUB(__savevmx_74);
GUEST_FUNCTION_STUB(__savevmx_75);
GUEST_FUNCTION_STUB(__savevmx_76);
GUEST_FUNCTION_STUB(__savevmx_77);
GUEST_FUNCTION_STUB(__savevmx_78);
GUEST_FUNCTION_STUB(__savevmx_79);
GUEST_FUNCTION_STUB(__savevmx_80);
GUEST_FUNCTION_STUB(__savevmx_81);
GUEST_FUNCTION_STUB(__savevmx_82);
GUEST_FUNCTION_STUB(__savevmx_83);
GUEST_FUNCTION_STUB(__savevmx_84);
GUEST_FUNCTION_STUB(__savevmx_85);
GUEST_FUNCTION_STUB(__savevmx_86);
GUEST_FUNCTION_STUB(__savevmx_87);
GUEST_FUNCTION_STUB(__savevmx_88);
GUEST_FUNCTION_STUB(__savevmx_89);
GUEST_FUNCTION_STUB(__savevmx_90);
GUEST_FUNCTION_STUB(__savevmx_91);
GUEST_FUNCTION_STUB(__savevmx_92);
GUEST_FUNCTION_STUB(__savevmx_93);
GUEST_FUNCTION_STUB(__savevmx_94);
GUEST_FUNCTION_STUB(__savevmx_95);
GUEST_FUNCTION_STUB(__savevmx_96);
GUEST_FUNCTION_STUB(__savevmx_97);
GUEST_FUNCTION_STUB(__savevmx_98);
GUEST_FUNCTION_STUB(__savevmx_99);
GUEST_FUNCTION_STUB(__savevmx_100);
GUEST_FUNCTION_STUB(__savevmx_101);
GUEST_FUNCTION_STUB(__savevmx_102);
GUEST_FUNCTION_STUB(__savevmx_103);
GUEST_FUNCTION_STUB(__savevmx_104);
GUEST_FUNCTION_STUB(__savevmx_105);
GUEST_FUNCTION_STUB(__savevmx_106);
GUEST_FUNCTION_STUB(__savevmx_107);
GUEST_FUNCTION_STUB(__savevmx_108);
GUEST_FUNCTION_STUB(__savevmx_109);
GUEST_FUNCTION_STUB(__savevmx_110);
GUEST_FUNCTION_STUB(__savevmx_111);
GUEST_FUNCTION_STUB(__savevmx_112);
GUEST_FUNCTION_STUB(__savevmx_113);
GUEST_FUNCTION_STUB(__savevmx_114);
GUEST_FUNCTION_STUB(__savevmx_115);
GUEST_FUNCTION_STUB(__savevmx_116);
GUEST_FUNCTION_STUB(__savevmx_117);
GUEST_FUNCTION_STUB(__savevmx_118);
GUEST_FUNCTION_STUB(__savevmx_119);
GUEST_FUNCTION_STUB(__savevmx_120);
GUEST_FUNCTION_STUB(__savevmx_121);
GUEST_FUNCTION_STUB(__savevmx_122);
GUEST_FUNCTION_STUB(__savevmx_123);
GUEST_FUNCTION_STUB(__savevmx_124);
GUEST_FUNCTION_STUB(__savevmx_125);
GUEST_FUNCTION_STUB(__savevmx_126);
GUEST_FUNCTION_STUB(__savevmx_127);
GUEST_FUNCTION_STUB(sub_831B36E8);
GUEST_FUNCTION_STUB(__restvmx_15);
GUEST_FUNCTION_STUB(__restvmx_16);
GUEST_FUNCTION_STUB(__restvmx_17);
GUEST_FUNCTION_STUB(__restvmx_18);
GUEST_FUNCTION_STUB(__restvmx_19);
GUEST_FUNCTION_STUB(__restvmx_20);
GUEST_FUNCTION_STUB(__restvmx_21);
GUEST_FUNCTION_STUB(__restvmx_22);
GUEST_FUNCTION_STUB(__restvmx_23);
GUEST_FUNCTION_STUB(__restvmx_24);
GUEST_FUNCTION_STUB(__restvmx_25);
GUEST_FUNCTION_STUB(__restvmx_26);
GUEST_FUNCTION_STUB(__restvmx_27);
GUEST_FUNCTION_STUB(__restvmx_28);
GUEST_FUNCTION_STUB(__restvmx_29);
GUEST_FUNCTION_STUB(__restvmx_30);
GUEST_FUNCTION_STUB(__restvmx_31);
GUEST_FUNCTION_STUB(__restvmx_64);
GUEST_FUNCTION_STUB(__restvmx_65);
GUEST_FUNCTION_STUB(__restvmx_66);
GUEST_FUNCTION_STUB(__restvmx_67);
GUEST_FUNCTION_STUB(__restvmx_68);
GUEST_FUNCTION_STUB(__restvmx_69);
GUEST_FUNCTION_STUB(__restvmx_70);
GUEST_FUNCTION_STUB(__restvmx_71);
GUEST_FUNCTION_STUB(__restvmx_72);
GUEST_FUNCTION_STUB(__restvmx_73);
GUEST_FUNCTION_STUB(__restvmx_74);
GUEST_FUNCTION_STUB(__restvmx_75);
GUEST_FUNCTION_STUB(__restvmx_76);
GUEST_FUNCTION_STUB(__restvmx_77);
GUEST_FUNCTION_STUB(__restvmx_78);
GUEST_FUNCTION_STUB(__restvmx_79);
GUEST_FUNCTION_STUB(__restvmx_80);
GUEST_FUNCTION_STUB(__restvmx_81);
GUEST_FUNCTION_STUB(__restvmx_82);
GUEST_FUNCTION_STUB(__restvmx_83);
GUEST_FUNCTION_STUB(__restvmx_84);
GUEST_FUNCTION_STUB(__restvmx_85);
GUEST_FUNCTION_STUB(__restvmx_86);
GUEST_FUNCTION_STUB(__restvmx_87);
GUEST_FUNCTION_STUB(__restvmx_88);
GUEST_FUNCTION_STUB(__restvmx_89);
GUEST_FUNCTION_STUB(__restvmx_90);
GUEST_FUNCTION_STUB(__restvmx_91);
GUEST_FUNCTION_STUB(__restvmx_92);
GUEST_FUNCTION_STUB(__restvmx_93);
GUEST_FUNCTION_STUB(__restvmx_94);
GUEST_FUNCTION_STUB(__restvmx_95);
GUEST_FUNCTION_STUB(__restvmx_96);
GUEST_FUNCTION_STUB(__restvmx_97);
GUEST_FUNCTION_STUB(__restvmx_98);
GUEST_FUNCTION_STUB(__restvmx_99);
GUEST_FUNCTION_STUB(__restvmx_100);
GUEST_FUNCTION_STUB(__restvmx_101);
GUEST_FUNCTION_STUB(__restvmx_102);
GUEST_FUNCTION_STUB(__restvmx_103);
GUEST_FUNCTION_STUB(__restvmx_104);
GUEST_FUNCTION_STUB(__restvmx_105);
GUEST_FUNCTION_STUB(__restvmx_106);
GUEST_FUNCTION_STUB(__restvmx_107);
GUEST_FUNCTION_STUB(__restvmx_108);
GUEST_FUNCTION_STUB(__restvmx_109);
GUEST_FUNCTION_STUB(__restvmx_110);
GUEST_FUNCTION_STUB(__restvmx_111);
GUEST_FUNCTION_STUB(__restvmx_112);
GUEST_FUNCTION_STUB(__restvmx_113);
GUEST_FUNCTION_STUB(__restvmx_114);
GUEST_FUNCTION_STUB(__restvmx_115);
GUEST_FUNCTION_STUB(__restvmx_116);
GUEST_FUNCTION_STUB(__restvmx_117);
GUEST_FUNCTION_STUB(__restvmx_118);
GUEST_FUNCTION_STUB(__restvmx_119);
GUEST_FUNCTION_STUB(__restvmx_120);
GUEST_FUNCTION_STUB(__restvmx_121);
GUEST_FUNCTION_STUB(__restvmx_122);
GUEST_FUNCTION_STUB(__restvmx_123);
GUEST_FUNCTION_STUB(__restvmx_124);
GUEST_FUNCTION_STUB(__restvmx_125);
GUEST_FUNCTION_STUB(__restvmx_126);
GUEST_FUNCTION_STUB(__restvmx_127);
#endif