// Copyright (c) 2012- PPSSPP Project. // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, version 2.0 or later versions. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License 2.0 for more details. // A copy of the GPL 2.0 should have been included with the program. // If not, see http://www.gnu.org/licenses/ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include "Core/Config.h" #include "Core/HLE/HLE.h" #include "Core/MIPS/MIPS.h" #include "Core/MIPS/MIPSCodeUtils.h" #include "Core/MIPS/MIPSInt.h" #include "Common/LogManager.h" #include "../FileSystems/FileSystem.h" #include "../FileSystems/MetaFileSystem.h" #include "../PSPLoaders.h" #include "../../Core/CoreTiming.h" #include "../../Core/SaveState.h" #include "../../Core/System.h" #include "../../GPU/GPUInterface.h" #include "../../GPU/GPUState.h" #include "__sceAudio.h" #include "sceAtrac.h" #include "sceAudio.h" #include "sceCtrl.h" #include "sceDisplay.h" #include "sceFont.h" #include "sceGe.h" #include "sceIo.h" #include "sceKernel.h" #include "sceKernelAlarm.h" #include "sceKernelInterrupt.h" #include "sceKernelThread.h" #include "sceKernelMemory.h" #include "sceKernelMutex.h" #include "sceKernelMbx.h" #include "sceKernelMsgPipe.h" #include "sceKernelInterrupt.h" #include "sceKernelSemaphore.h" #include "sceKernelEventFlag.h" #include "sceKernelVTimer.h" #include "sceKernelTime.h" #include "sceMpeg.h" #include "sceNet.h" #include "scePower.h" #include "sceUtility.h" #include "sceUmd.h" #include "sceSsl.h" #include "sceSas.h" #include "scePsmf.h" #include "sceImpose.h" #include "sceUsb.h" #include "scePspNpDrm_user.h" #include "../Util/PPGeDraw.h" /* 17: [MIPS32 R4K 00000000 ]: Loader: Type: 1 Vaddr: 00000000 Filesz: 2856816 Memsz: 2856816 18: [MIPS32 R4K 00000000 ]: Loader: Loadable Segment Copied to 0898dab0, size 002b9770 19: [MIPS32 R4K 00000000 ]: Loader: Type: 1 Vaddr: 002b9770 Filesz: 14964 Memsz: 733156 20: [MIPS32 R4K 00000000 ]: Loader: Loadable Segment Copied to 08c47220, size 000b2fe4 */ static bool kernelRunning = false; KernelObjectPool kernelObjects; KernelStats kernelStats; void __KernelInit() { if (kernelRunning) { ERROR_LOG(HLE, "Can't init kernel when kernel is running"); return; } __KernelTimeInit(); __InterruptsInit(); __KernelMemoryInit(); __KernelThreadingInit(); __KernelAlarmInit(); __KernelVTimerInit(); __KernelEventFlagInit(); __KernelMbxInit(); __KernelMutexInit(); __KernelSemaInit(); __IoInit(); __AudioInit(); __SasInit(); __AtracInit(); __DisplayInit(); __GeInit(); __PowerInit(); __UtilityInit(); __UmdInit(); __MpegInit(PSP_CoreParameter().useMediaEngine); __PsmfInit(); __CtrlInit(); __SslInit(); __ImposeInit(); __UsbInit(); __FontInit(); __NetInit(); SaveState::Init(); // Must be after IO, as it may create a directory // "Internal" PSP libraries __PPGeInit(); kernelRunning = true; INFO_LOG(HLE, "Kernel initialized."); } void __KernelShutdown() { if (!kernelRunning) { ERROR_LOG(HLE, "Can't shut down kernel - not running"); return; } kernelObjects.List(); INFO_LOG(HLE, "Shutting down kernel - %i kernel objects alive", kernelObjects.GetCount()); hleCurrentThreadName = NULL; kernelObjects.Clear(); __NetShutdown(); __FontShutdown(); __MpegShutdown(); __PsmfShutdown(); __PPGeShutdown(); __CtrlShutdown(); __UtilityShutdown(); __GeShutdown(); __SasShutdown(); __DisplayShutdown(); __AtracShutdown(); __AudioShutdown(); __IoShutdown(); __KernelMutexShutdown(); __KernelThreadingShutdown(); __KernelMemoryShutdown(); __InterruptsShutdown(); CoreTiming::ClearPendingEvents(); CoreTiming::UnregisterAllEvents(); kernelRunning = false; } void __KernelDoState(PointerWrap &p) { std::string git_version = PPSSPP_GIT_VERSION; p.Do(git_version); if (git_version != PPSSPP_GIT_VERSION) WARN_LOG(HLE, "Warning: this savestate was generated by a different version of PPSSPP. It may not load properly."); p.Do(kernelRunning); kernelObjects.DoState(p); p.DoMarker("KernelObjects"); __InterruptsDoState(p); // Memory needs to be after kernel objects, which may free kernel memory. __KernelMemoryDoState(p); __KernelThreadingDoState(p); __KernelAlarmDoState(p); __KernelVTimerDoState(p); __KernelEventFlagDoState(p); __KernelMbxDoState(p); __KernelModuleDoState(p); __KernelMutexDoState(p); __KernelSemaDoState(p); __KernelTimeDoState(p); __AtracDoState(p); __AudioDoState(p); __CtrlDoState(p); __DisplayDoState(p); __FontDoState(p); __GeDoState(p); __ImposeDoState(p); __IoDoState(p); __MpegDoState(p); __NetDoState(p); __PowerDoState(p); __PsmfDoState(p); __PsmfPlayerDoState(p); __SasDoState(p); __SslDoState(p); __UmdDoState(p); __UtilityDoState(p); __UsbDoState(p); __PPGeDoState(p); __InterruptsDoStateLate(p); __KernelThreadingDoStateLate(p); } bool __KernelIsRunning() { return kernelRunning; } void sceKernelExitGame() { INFO_LOG(HLE,"sceKernelExitGame"); if (!PSP_CoreParameter().headLess) PanicAlert("Game exited"); __KernelSwitchOffThread("game exited"); Core_Stop(); } void sceKernelExitGameWithStatus() { INFO_LOG(HLE,"sceKernelExitGameWithStatus"); if (!PSP_CoreParameter().headLess) PanicAlert("Game exited (with status)"); __KernelSwitchOffThread("game exited"); Core_Stop(); } u32 sceKernelRegisterExitCallback(u32 cbId) { DEBUG_LOG(HLE,"NOP sceKernelRegisterExitCallback(%i)", cbId); return 0; } u32 sceKernelDevkitVersion() { int firmwareVersion = 150; int major = firmwareVersion / 100; int minor = (firmwareVersion / 10) % 10; int revision = firmwareVersion % 10; int devkitVersion = (major << 24) | (minor << 16) | (revision << 8) | 0x10; DEBUG_LOG(HLE,"sceKernelDevkitVersion (%i) ", devkitVersion); return devkitVersion; } u32 sceKernelRegisterKprintfHandler() { ERROR_LOG(HLE,"UNIMPL sceKernelRegisterKprintfHandler()"); return 0; } void sceKernelRegisterDefaultExceptionHandler() { ERROR_LOG(HLE,"UNIMPL sceKernelRegisterDefaultExceptionHandler()"); RETURN(0); } void sceKernelSetGPO(u32 ledAddr) { // Sets debug LEDs. DEBUG_LOG(HLE,"sceKernelSetGPO(%02x)", ledAddr); } u32 sceKernelGetGPI() { // Always returns 0 on production systems. DEBUG_LOG(HLE,"0=sceKernelGetGPI()"); return 0; } // #define LOG_CACHE // Don't even log these by default, they're spammy and we probably won't // need to emulate them. Useful for invalidating cached textures though, // and in the future display lists (although hashing takes care of those // for now). int sceKernelDcacheInvalidateRange(u32 addr, int size) { #ifdef LOG_CACHE NOTICE_LOG(HLE,"sceKernelDcacheInvalidateRange(%08x, %i)", addr, size); #endif if (size < 0 || (int) addr + size < 0) return SCE_KERNEL_ERROR_ILLEGAL_ADDR; if (size > 0) { if ((addr % 64) != 0 || (size % 64) != 0) return SCE_KERNEL_ERROR_CACHE_ALIGNMENT; if (addr != 0) gpu->InvalidateCache(addr, size); } return 0; } int sceKernelIcacheInvalidateRange(u32 addr, int size) { DEBUG_LOG(HLE,"sceKernelIcacheInvalidateRange(%08x, %i)", addr, size); // TODO: Make the JIT hash and compare the touched blocks. return 0; } int sceKernelDcacheWritebackAll() { #ifdef LOG_CACHE NOTICE_LOG(HLE,"sceKernelDcacheWritebackAll()"); #endif // Some games seem to use this a lot, it doesn't make sense // to zap the whole texture cache. gpu->InvalidateCacheHint(0, -1); return 0; } int sceKernelDcacheWritebackRange(u32 addr, int size) { #ifdef LOG_CACHE NOTICE_LOG(HLE,"sceKernelDcacheWritebackRange(%08x, %i)", addr, size); #endif if (size < 0) return SCE_KERNEL_ERROR_INVALID_SIZE; if (size > 0 && addr != 0) { gpu->InvalidateCache(addr, size); } return 0; } int sceKernelDcacheWritebackInvalidateRange(u32 addr, int size) { #ifdef LOG_CACHE NOTICE_LOG(HLE,"sceKernelDcacheInvalidateRange(%08x, %i)", addr, size); #endif if (size < 0) return SCE_KERNEL_ERROR_INVALID_SIZE; if (size > 0 && addr != 0) { gpu->InvalidateCache(addr, size); } return 0; } int sceKernelDcacheWritebackInvalidateAll() { #ifdef LOG_CACHE NOTICE_LOG(HLE,"sceKernelDcacheInvalidateAll()"); #endif gpu->InvalidateCacheHint(0, -1); return 0; } u32 sceKernelIcacheInvalidateAll() { #ifdef LOG_CACHE NOTICE_LOG(CPU, "Icache invalidated - should clear JIT someday"); #endif return 0; } u32 sceKernelIcacheClearAll() { #ifdef LOG_CACHE NOTICE_LOG(CPU, "Icache cleared - should clear JIT someday"); #endif DEBUG_LOG(CPU, "Icache cleared - should clear JIT someday"); return 0; } KernelObjectPool::KernelObjectPool() { memset(occupied, 0, sizeof(bool)*maxCount); nextID = 16; } SceUID KernelObjectPool::Create(KernelObject *obj, int rangeBottom, int rangeTop) { if (rangeTop > maxCount) rangeTop = maxCount; if (nextID >= rangeBottom && nextID < rangeTop) rangeBottom = nextID++; for (int i = rangeBottom; i < rangeTop; i++) { if (!occupied[i]) { occupied[i] = true; pool[i] = obj; pool[i]->uid = i + handleOffset; return i + handleOffset; } } _dbg_assert_(HLE, 0); return 0; } bool KernelObjectPool::IsValid(SceUID handle) { int index = handle - handleOffset; if (index < 0) return false; if (index >= maxCount) return false; return occupied[index]; } void KernelObjectPool::Clear() { for (int i=0; iGetQuickInfo(buffer,256); INFO_LOG(HLE, "KO %i: %s \"%s\": %s", i + handleOffset, pool[i]->GetTypeName(), pool[i]->GetName(), buffer); } else { strcpy(buffer,"WTF? Zero Pointer"); } } } } int KernelObjectPool::GetCount() { int count = 0; for (int i=0; iuid = i + handleOffset; // Already logged an error. if (pool[i] == NULL) return; } else { type = pool[i]->GetIDType(); p.Do(type); } pool[i]->DoState(p); } p.DoMarker("KernelObjectPool"); } KernelObject *KernelObjectPool::CreateByIDType(int type) { // Used for save states. This is ugly, but what other way is there? switch (type) { case SCE_KERNEL_TMID_Alarm: return __KernelAlarmObject(); case SCE_KERNEL_TMID_EventFlag: return __KernelEventFlagObject(); case SCE_KERNEL_TMID_Mbox: return __KernelMbxObject(); case SCE_KERNEL_TMID_Fpl: return __KernelMemoryFPLObject(); case SCE_KERNEL_TMID_Vpl: return __KernelMemoryVPLObject(); case PPSSPP_KERNEL_TMID_PMB: return __KernelMemoryPMBObject(); case PPSSPP_KERNEL_TMID_Module: return __KernelModuleObject(); case SCE_KERNEL_TMID_Mpipe: return __KernelMsgPipeObject(); case SCE_KERNEL_TMID_Mutex: return __KernelMutexObject(); case SCE_KERNEL_TMID_LwMutex: return __KernelLwMutexObject(); case SCE_KERNEL_TMID_Semaphore: return __KernelSemaphoreObject(); case SCE_KERNEL_TMID_Callback: return __KernelCallbackObject(); case SCE_KERNEL_TMID_Thread: return __KernelThreadObject(); case SCE_KERNEL_TMID_VTimer: return __KernelVTimerObject(); case PPSSPP_KERNEL_TMID_File: return __KernelFileNodeObject(); case PPSSPP_KERNEL_TMID_DirList: return __KernelDirListingObject(); default: ERROR_LOG(COMMON, "Unable to load state: could not find object type %d.", type); return NULL; } } struct SystemStatus { SceSize size; SceUInt status; SceUInt clockPart1; SceUInt clockPart2; SceUInt perfcounter1; SceUInt perfcounter2; SceUInt perfcounter3; }; int sceKernelReferSystemStatus(u32 statusPtr) { DEBUG_LOG(HLE, "sceKernelReferSystemStatus(%08x)", statusPtr); if (Memory::IsValidAddress(statusPtr)) { SystemStatus status; memset(&status, 0, sizeof(SystemStatus)); status.size = sizeof(SystemStatus); // TODO: Fill in the struct! Memory::WriteStruct(statusPtr, &status); } return 0; } struct DebugProfilerRegs { u32 enable; u32 systemck; u32 cpuck; u32 internal; u32 memory; u32 copz; u32 vfpu; u32 sleep; u32 bus_access; u32 uncached_load; u32 uncached_store; u32 cached_load; u32 cached_store; u32 i_miss; u32 d_miss; u32 d_writeback; u32 cop0_inst; u32 fpu_inst; u32 vfpu_inst; u32 local_bus; }; u32 sceKernelReferThreadProfiler(u32 statusPtr) { ERROR_LOG(HLE, "FAKE sceKernelReferThreadProfiler()"); // Can we confirm that the struct above is the right struct? // If so, re-enable this code. //DebugProfilerRegs regs; //memset(®s, 0, sizeof(regs)); // TODO: fill the struct. //if (Memory::IsValidAddress(statusPtr)) { // Memory::WriteStruct(statusPtr, ®s); //} return 0; } int sceKernelReferGlobalProfiler(u32 statusPtr) { DEBUG_LOG(HLE, "UNIMPL sceKernelReferGlobalProfiler(%08x)", statusPtr); // Ignore for now return 0; } const HLEFunction ThreadManForUser[] = { {0x55C20A00,&WrapI_CUUU, "sceKernelCreateEventFlag"}, {0x812346E4,&WrapU_IU, "sceKernelClearEventFlag"}, {0xEF9E4C70,&WrapU_I, "sceKernelDeleteEventFlag"}, {0x1fb15a32,&WrapU_IU, "sceKernelSetEventFlag"}, {0x402FCF22,&WrapI_IUUUU, "sceKernelWaitEventFlag"}, {0x328C546A,&WrapI_IUUUU, "sceKernelWaitEventFlagCB"}, {0x30FD48F0,&WrapI_IUUUU, "sceKernelPollEventFlag"}, {0xCD203292,&WrapU_IUU, "sceKernelCancelEventFlag"}, {0xA66B0120,&WrapU_IU, "sceKernelReferEventFlagStatus"}, {0x8FFDF9A2,&WrapI_IIU, "sceKernelCancelSema"}, {0xD6DA4BA1,&WrapI_CUIIU, "sceKernelCreateSema"}, {0x28b6489c,&WrapI_I, "sceKernelDeleteSema"}, {0x58b1f937,&WrapI_II, "sceKernelPollSema"}, {0xBC6FEBC5,&WrapI_IU, "sceKernelReferSemaStatus"}, {0x3F53E640,&WrapI_II, "sceKernelSignalSema"}, {0x4E3A1105,&WrapI_IIU, "sceKernelWaitSema", HLE_NOT_DISPATCH_SUSPENDED}, {0x6d212bac,&WrapI_IIU, "sceKernelWaitSemaCB", HLE_NOT_DISPATCH_SUSPENDED}, {0x60107536,&WrapI_U, "sceKernelDeleteLwMutex"}, {0x19CFF145,&WrapI_UCUIU, "sceKernelCreateLwMutex"}, {0x4C145944,&WrapI_IU, "sceKernelReferLwMutexStatusByID"}, // NOTE: LockLwMutex, UnlockLwMutex, and ReferLwMutexStatus are in Kernel_Library, see sceKernelInterrupt.cpp. {0xf8170fbe,&WrapI_I, "sceKernelDeleteMutex"}, {0xB011B11F,&WrapI_IIU, "sceKernelLockMutex", HLE_NOT_DISPATCH_SUSPENDED}, {0x5bf4dd27,&WrapI_IIU, "sceKernelLockMutexCB", HLE_NOT_DISPATCH_SUSPENDED}, {0x6b30100f,&WrapI_II, "sceKernelUnlockMutex"}, {0xb7d098c6,&WrapI_CUIU, "sceKernelCreateMutex"}, {0x0DDCD2C9,&WrapI_II, "sceKernelTryLockMutex"}, {0xA9C2CB9A,&WrapI_IU, "sceKernelReferMutexStatus"}, {0xFCCFAD26,sceKernelCancelWakeupThread,"sceKernelCancelWakeupThread"}, {0xea748e31,sceKernelChangeCurrentThreadAttr,"sceKernelChangeCurrentThreadAttr"}, {0x71bc9871,sceKernelChangeThreadPriority,"sceKernelChangeThreadPriority"}, {0x446D8DE6,WrapI_CUUIUU,"sceKernelCreateThread"}, {0x9fa03cd3,WrapI_I,"sceKernelDeleteThread"}, {0xBD123D9E,sceKernelDelaySysClockThread,"sceKernelDelaySysClockThread"}, {0x1181E963,sceKernelDelaySysClockThreadCB,"sceKernelDelaySysClockThreadCB"}, {0xceadeb47,WrapI_U,"sceKernelDelayThread"}, {0x68da9e36,WrapI_U,"sceKernelDelayThreadCB"}, {0xaa73c935,WrapV_I,"sceKernelExitThread"}, {0x809ce29b,WrapV_I,"sceKernelExitDeleteThread"}, {0x94aa61ee,sceKernelGetThreadCurrentPriority,"sceKernelGetThreadCurrentPriority"}, {0x293b45b8,WrapI_V,"sceKernelGetThreadId"}, {0x3B183E26,sceKernelGetThreadExitStatus,"sceKernelGetThreadExitStatus"}, {0x52089CA1,sceKernelGetThreadStackFreeSize,"sceKernelGetThreadStackFreeSize"}, {0xFFC36A14,WrapU_UU,"sceKernelReferThreadRunStatus"}, {0x17c1684e,WrapU_UU,"sceKernelReferThreadStatus"}, {0x2C34E053,WrapI_I,"sceKernelReleaseWaitThread"}, {0x75156e8f,sceKernelResumeThread,"sceKernelResumeThread"}, {0x3ad58b8c,&WrapU_V,"sceKernelSuspendDispatchThread"}, {0x27e22ec2,&WrapU_U,"sceKernelResumeDispatchThread"}, {0x912354a7,&WrapI_I,"sceKernelRotateThreadReadyQueue"}, {0x9ACE131E,sceKernelSleepThread,"sceKernelSleepThread"}, {0x82826f70,sceKernelSleepThreadCB,"sceKernelSleepThreadCB"}, {0xF475845D,&WrapI_IUU,"sceKernelStartThread"}, {0x9944f31f,sceKernelSuspendThread,"sceKernelSuspendThread"}, {0x616403ba,WrapI_I,"sceKernelTerminateThread"}, {0x383f7bcc,WrapI_I,"sceKernelTerminateDeleteThread"}, {0x840E8133,WrapI_IU,"sceKernelWaitThreadEndCB"}, {0xd13bde95,WrapI_V,"sceKernelCheckThreadStack"}, {0x94416130,WrapU_UUUU,"sceKernelGetThreadmanIdList"}, {0x57CF62DD,WrapU_U,"sceKernelGetThreadmanIdType"}, {0xBC80EC7C,WrapU_UUUU, "sceKernelExtendThreadStack"}, {0x82BC5777,WrapU64_V,"sceKernelGetSystemTimeWide"}, {0xdb738f35,WrapI_U,"sceKernelGetSystemTime"}, {0x369ed59d,WrapU_V,"sceKernelGetSystemTimeLow"}, {0x8218B4DD,WrapI_U,"sceKernelReferGlobalProfiler"}, {0x627E6F3A,WrapI_U,"sceKernelReferSystemStatus"}, {0x64D4540E,WrapU_U,"sceKernelReferThreadProfiler"}, //Fifa Street 2 uses alarms {0x6652b8ca,WrapI_UUU,"sceKernelSetAlarm"}, {0xB2C25152,WrapI_UUU,"sceKernelSetSysClockAlarm"}, {0x7e65b999,WrapI_I,"sceKernelCancelAlarm"}, {0xDAA3F564,WrapI_IU,"sceKernelReferAlarmStatus"}, {0xba6b92e2,WrapI_UUU,"sceKernelSysClock2USec"}, {0x110dec9a,WrapI_UU,"sceKernelUSec2SysClock"}, {0xC8CD158C,WrapU64_U,"sceKernelUSec2SysClockWide"}, {0xE1619D7C,WrapI_UUUU,"sceKernelSysClock2USecWide"}, {0x278C0DF5,WrapI_IU,"sceKernelWaitThreadEnd"}, {0xd59ead2f,sceKernelWakeupThread,"sceKernelWakeupThread"}, //AI Go, audio? {0x0C106E53,0,"sceKernelRegisterThreadEventHandler"}, {0x72F3C145,0,"sceKernelReleaseThreadEventHandler"}, {0x369EEB6B,0,"sceKernelReferThreadEventHandlerStatus"}, {0x349d6d6c,sceKernelCheckCallback,"sceKernelCheckCallback"}, {0xE81CAF8F,sceKernelCreateCallback,"sceKernelCreateCallback"}, {0xEDBA5844,sceKernelDeleteCallback,"sceKernelDeleteCallback"}, {0xC11BA8C4,sceKernelNotifyCallback,"sceKernelNotifyCallback"}, {0xBA4051D6,sceKernelCancelCallback,"sceKernelCancelCallback"}, {0x2A3D44FF,sceKernelGetCallbackCount,"sceKernelGetCallbackCount"}, {0x730ED8BC,sceKernelReferCallbackStatus,"sceKernelReferCallbackStatus"}, {0x8125221D,&WrapI_CUU,"sceKernelCreateMbx"}, {0x86255ADA,&WrapI_I,"sceKernelDeleteMbx"}, {0xE9B3061E,&WrapI_IU,"sceKernelSendMbx"}, {0x18260574,&WrapI_IUU,"sceKernelReceiveMbx"}, {0xF3986382,&WrapI_IUU,"sceKernelReceiveMbxCB"}, {0x0D81716A,&WrapI_IU,"sceKernelPollMbx"}, {0x87D4DD36,&WrapI_IU,"sceKernelCancelReceiveMbx"}, {0xA8E8C846,&WrapI_IU,"sceKernelReferMbxStatus"}, {0x7C0DC2A0,sceKernelCreateMsgPipe,"sceKernelCreateMsgPipe"}, {0xF0B7DA1C,sceKernelDeleteMsgPipe,"sceKernelDeleteMsgPipe"}, {0x876DBFAD,sceKernelSendMsgPipe,"sceKernelSendMsgPipe"}, {0x7C41F2C2,sceKernelSendMsgPipeCB,"sceKernelSendMsgPipeCB"}, {0x884C9F90,sceKernelTrySendMsgPipe,"sceKernelTrySendMsgPipe"}, {0x74829B76,sceKernelReceiveMsgPipe,"sceKernelReceiveMsgPipe"}, {0xFBFA697D,sceKernelReceiveMsgPipeCB,"sceKernelReceiveMsgPipeCB"}, {0xDF52098F,sceKernelTryReceiveMsgPipe,"sceKernelTryReceiveMsgPipe"}, {0x349B864D,sceKernelCancelMsgPipe,"sceKernelCancelMsgPipe"}, {0x33BE4024,sceKernelReferMsgPipeStatus,"sceKernelReferMsgPipeStatus"}, {0x56C039B5,WrapI_CIUUU,"sceKernelCreateVpl"}, {0x89B3D48C,WrapI_I,"sceKernelDeleteVpl"}, {0xBED27435,WrapI_IUUU,"sceKernelAllocateVpl"}, {0xEC0A693F,WrapI_IUUU,"sceKernelAllocateVplCB"}, {0xAF36D708,WrapI_IUU,"sceKernelTryAllocateVpl"}, {0xB736E9FF,WrapI_IU,"sceKernelFreeVpl"}, {0x1D371B8A,WrapI_IU,"sceKernelCancelVpl"}, {0x39810265,WrapI_IU,"sceKernelReferVplStatus"}, {0xC07BB470,sceKernelCreateFpl,"sceKernelCreateFpl"}, {0xED1410E0,sceKernelDeleteFpl,"sceKernelDeleteFpl"}, {0xD979E9BF,sceKernelAllocateFpl,"sceKernelAllocateFpl"}, {0xE7282CB6,sceKernelAllocateFplCB,"sceKernelAllocateFplCB"}, {0x623AE665,sceKernelTryAllocateFpl,"sceKernelTryAllocateFpl"}, {0xF6414A71,sceKernelFreeFpl,"sceKernelFreeFpl"}, {0xA8AA591F,sceKernelCancelFpl,"sceKernelCancelFpl"}, {0xD8199E4C,sceKernelReferFplStatus,"sceKernelReferFplStatus"}, {0x20fff560,WrapU_CU,"sceKernelCreateVTimer"}, {0x328F9E52,WrapU_U,"sceKernelDeleteVTimer"}, {0xc68d9437,WrapU_U,"sceKernelStartVTimer"}, {0xD0AEEE87,WrapU_U,"sceKernelStopVTimer"}, {0xD2D615EF,WrapU_U,"sceKernelCancelVTimerHandler"}, {0xB3A59970,WrapU_UU,"sceKernelGetVTimerBase"}, {0xB7C18B77,WrapU64_U,"sceKernelGetVTimerBaseWide"}, {0x034A921F,WrapU_UU,"sceKernelGetVTimerTime"}, {0xC0B3FFD2,WrapU64_U,"sceKernelGetVTimerTimeWide"}, {0x5F32BEAA,WrapU_UU,"sceKernelReferVTimerStatus"}, {0x542AD630,WrapU_UU,"sceKernelSetVTimerTime"}, {0xFB6425C3,WrapU_UU64,"sceKernelSetVTimerTimeWide"}, {0xd8b299ae,WrapU_UUUU,"sceKernelSetVTimerHandler"}, {0x53B00E9A,WrapU_UU64UU,"sceKernelSetVTimerHandlerWide"}, {0x8daff657,WrapI_CUUUUU,"ThreadManForUser_8DAFF657"}, {0x32bf938e,WrapI_I,"ThreadManForUser_32BF938E"}, // Not sure if these should be hooked up. See below. {0x0E927AED, _sceKernelReturnFromTimerHandler, "_sceKernelReturnFromTimerHandler"}, {0x532A522E, WrapV_I<_sceKernelExitThread>,"_sceKernelExitThread"}, // Shouldn't hook this up. No games should import this function manually and call it. // {0x6E9EA350, _sceKernelReturnFromCallback,"_sceKernelReturnFromCallback"}, }; void Register_ThreadManForUser() { RegisterModule("ThreadManForUser", ARRAY_SIZE(ThreadManForUser), ThreadManForUser); } const HLEFunction LoadExecForUser[] = { {0x05572A5F,&WrapV_V, "sceKernelExitGame"}, //() {0x4AC57943,&WrapU_U,"sceKernelRegisterExitCallback"}, {0xBD2F1094,&WrapI_CU,"sceKernelLoadExec"}, {0x2AC9954B,&WrapV_V,"sceKernelExitGameWithStatus"}, }; void Register_LoadExecForUser() { RegisterModule("LoadExecForUser", ARRAY_SIZE(LoadExecForUser), LoadExecForUser); } const HLEFunction ExceptionManagerForKernel[] = { {0x3FB264FC, 0, "sceKernelRegisterExceptionHandler"}, {0x5A837AD4, 0, "sceKernelRegisterPriorityExceptionHandler"}, {0x565C0B0E, sceKernelRegisterDefaultExceptionHandler, "sceKernelRegisterDefaultExceptionHandler"}, {0x1AA6CFFA, 0, "sceKernelReleaseExceptionHandler"}, {0xDF83875E, 0, "sceKernelGetActiveDefaultExceptionHandler"}, {0x291FF031, 0, "sceKernelReleaseDefaultExceptionHandler"}, {0x15ADC862, 0, "sceKernelRegisterNmiHandler"}, {0xB15357C9, 0, "sceKernelReleaseNmiHandler"}, }; void Register_ExceptionManagerForKernel() { RegisterModule("ExceptionManagerForKernel", ARRAY_SIZE(ExceptionManagerForKernel), ExceptionManagerForKernel); }