1
// Copyright (c) 2012- PPSSPP Project.
3
// This program is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, version 2.0 or later versions.
7
// This program is distributed in the hope that it will be useful,
8
// but WITHOUT ANY WARRANTY; without even the implied warranty of
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
// GNU General Public License 2.0 for more details.
12
// A copy of the GPL 2.0 should have been included with the program.
13
// If not, see http://www.gnu.org/licenses/
15
// Official git repository and contact information can be found at
16
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
18
#include "Core/Core.h"
19
#include "Core/Config.h"
20
#include "Core/CwCheat.h"
21
#include "Core/MemMapHelpers.h"
22
#include "Core/HLE/HLE.h"
23
#include "Core/HLE/FunctionWrappers.h"
24
#include "Core/MIPS/MIPS.h"
25
#include "Core/MIPS/MIPSCodeUtils.h"
26
#include "Core/MIPS/MIPSInt.h"
27
#include "Core/MIPS/JitCommon/JitCommon.h"
29
#include "Common/LogManager.h"
30
#include "Core/FileSystems/FileSystem.h"
31
#include "Core/FileSystems/MetaFileSystem.h"
32
#include "Core/PSPLoaders.h"
33
#include "Core/CoreTiming.h"
34
#include "Core/Reporting.h"
35
#include "Core/SaveState.h"
36
#include "Core/System.h"
37
#include "GPU/GPUInterface.h"
38
#include "GPU/GPUState.h"
40
#include "__sceAudio.h"
43
#include "sceAudiocodec.h"
46
#include "sceDisplay.h"
51
#include "sceKernel.h"
52
#include "sceKernelAlarm.h"
53
#include "sceKernelInterrupt.h"
54
#include "sceKernelThread.h"
55
#include "sceKernelMemory.h"
56
#include "sceKernelModule.h"
57
#include "sceKernelMutex.h"
58
#include "sceKernelMbx.h"
59
#include "sceKernelMsgPipe.h"
60
#include "sceKernelInterrupt.h"
61
#include "sceKernelSemaphore.h"
62
#include "sceKernelEventFlag.h"
63
#include "sceKernelVTimer.h"
64
#include "sceKernelTime.h"
68
#include "sceNetAdhoc.h"
70
#include "sceUtility.h"
76
#include "sceImpose.h"
78
#include "scePspNpDrm_user.h"
79
#include "sceVaudio.h"
84
#include "../Util/PPGeDraw.h"
87
17: [MIPS32 R4K 00000000 ]: Loader: Type: 1 Vaddr: 00000000 Filesz: 2856816 Memsz: 2856816
88
18: [MIPS32 R4K 00000000 ]: Loader: Loadable Segment Copied to 0898dab0, size 002b9770
89
19: [MIPS32 R4K 00000000 ]: Loader: Type: 1 Vaddr: 002b9770 Filesz: 14964 Memsz: 733156
90
20: [MIPS32 R4K 00000000 ]: Loader: Loadable Segment Copied to 08c47220, size 000b2fe4
93
static bool kernelRunning = false;
94
KernelObjectPool kernelObjects;
95
KernelStats kernelStats;
96
u32 registeredExitCbId;
102
ERROR_LOG(SCEKERNEL, "Can't init kernel when kernel is running");
108
__KernelMemoryInit();
109
__KernelThreadingInit();
111
__KernelVTimerInit();
112
__KernelEventFlagInit();
116
__KernelMsgPipeInit();
145
SaveState::Init(); // Must be after IO, as it may create a directory
148
// "Internal" PSP libraries
151
kernelRunning = true;
152
INFO_LOG(SCEKERNEL, "Kernel initialized.");
155
void __KernelShutdown()
159
ERROR_LOG(SCEKERNEL, "Can't shut down kernel - not running");
162
kernelObjects.List();
163
INFO_LOG(SCEKERNEL, "Shutting down kernel - %i kernel objects alive", kernelObjects.GetCount());
164
hleCurrentThreadName = NULL;
165
kernelObjects.Clear();
167
__AudioCodecShutdown();
168
__VideoPmpShutdown();
170
__NetAdhocShutdown();
187
__KernelMutexShutdown();
188
__KernelThreadingShutdown();
189
__KernelMemoryShutdown();
190
__InterruptsShutdown();
192
__KernelModuleShutdown();
194
CoreTiming::ClearPendingEvents();
195
CoreTiming::UnregisterAllEvents();
196
Reporting::Shutdown();
198
kernelRunning = false;
201
void __KernelDoState(PointerWrap &p)
204
auto s = p.Section("Kernel", 1, 2);
209
kernelObjects.DoState(p);
212
p.Do(registeredExitCbId);
216
auto s = p.Section("Kernel Modules", 1);
220
__InterruptsDoState(p);
221
// Memory needs to be after kernel objects, which may free kernel memory.
222
__KernelMemoryDoState(p);
223
__KernelThreadingDoState(p);
224
__KernelAlarmDoState(p);
225
__KernelVTimerDoState(p);
226
__KernelEventFlagDoState(p);
227
__KernelMbxDoState(p);
228
__KernelModuleDoState(p);
229
__KernelMsgPipeDoState(p);
230
__KernelMutexDoState(p);
231
__KernelSemaDoState(p);
232
__KernelTimeDoState(p);
236
auto s = p.Section("HLE Modules", 1);
253
__NetAdhocDoState(p);
256
__PsmfPlayerDoState(p);
268
__sceAudiocodecDoState(p);
269
__VideoPmpDoState(p);
274
auto s = p.Section("Kernel Cleanup", 1);
278
__InterruptsDoStateLate(p);
279
__KernelThreadingDoStateLate(p);
280
Reporting::DoState(p);
284
bool __KernelIsRunning() {
285
return kernelRunning;
288
void sceKernelExitGame()
290
INFO_LOG(SCEKERNEL, "sceKernelExitGame");
291
__KernelSwitchOffThread("game exited");
295
void sceKernelExitGameWithStatus()
297
INFO_LOG(SCEKERNEL, "sceKernelExitGameWithStatus");
298
__KernelSwitchOffThread("game exited");
302
u32 sceKernelDevkitVersion()
304
int firmwareVersion = g_Config.iFirmwareVersion;
305
int major = firmwareVersion / 100;
306
int minor = (firmwareVersion / 10) % 10;
307
int revision = firmwareVersion % 10;
308
int devkitVersion = (major << 24) | (minor << 16) | (revision << 8) | 0x10;
310
DEBUG_LOG_REPORT_ONCE(devkitVer, SCEKERNEL, "%08x=sceKernelDevkitVersion()", devkitVersion);
311
return devkitVersion;
314
u32 sceKernelRegisterKprintfHandler()
316
ERROR_LOG(SCEKERNEL, "UNIMPL sceKernelRegisterKprintfHandler()");
320
int sceKernelRegisterDefaultExceptionHandler()
322
ERROR_LOG(SCEKERNEL, "UNIMPL sceKernelRegisterDefaultExceptionHandler()");
326
void sceKernelSetGPO(u32 ledAddr)
329
DEBUG_LOG(SCEKERNEL, "sceKernelSetGPO(%02x)", ledAddr);
332
u32 sceKernelGetGPI()
334
// Always returns 0 on production systems.
335
DEBUG_LOG(SCEKERNEL, "0=sceKernelGetGPI()");
341
// Don't even log these by default, they're spammy and we probably won't
342
// need to emulate them. Useful for invalidating cached textures though,
343
// and in the future display lists (although hashing takes care of those
345
int sceKernelDcacheInvalidateRange(u32 addr, int size)
348
NOTICE_LOG(CPU,"sceKernelDcacheInvalidateRange(%08x, %i)", addr, size);
350
if (size < 0 || (int) addr + size < 0)
351
return SCE_KERNEL_ERROR_ILLEGAL_ADDR;
355
if ((addr % 64) != 0 || (size % 64) != 0)
356
return SCE_KERNEL_ERROR_CACHE_ALIGNMENT;
359
gpu->InvalidateCache(addr, size, GPU_INVALIDATE_HINT);
365
int sceKernelIcacheInvalidateRange(u32 addr, int size) {
366
DEBUG_LOG(CPU, "sceKernelIcacheInvalidateRange(%08x, %i)", addr, size);
367
currentMIPS->InvalidateICache(addr, size);
371
int sceKernelDcacheWritebackAll()
374
NOTICE_LOG(CPU,"sceKernelDcacheWritebackAll()");
376
// Some games seem to use this a lot, it doesn't make sense
377
// to zap the whole texture cache.
378
gpu->InvalidateCache(0, -1, GPU_INVALIDATE_ALL);
380
hleReSchedule("dcache writeback all");
384
int sceKernelDcacheWritebackRange(u32 addr, int size)
387
NOTICE_LOG(CPU,"sceKernelDcacheWritebackRange(%08x, %i)", addr, size);
390
return SCE_KERNEL_ERROR_INVALID_SIZE;
392
if (size > 0 && addr != 0) {
393
gpu->InvalidateCache(addr, size, GPU_INVALIDATE_HINT);
399
int sceKernelDcacheWritebackInvalidateRange(u32 addr, int size)
402
NOTICE_LOG(CPU,"sceKernelDcacheInvalidateRange(%08x, %i)", addr, size);
405
return SCE_KERNEL_ERROR_INVALID_SIZE;
407
if (size > 0 && addr != 0) {
408
gpu->InvalidateCache(addr, size, GPU_INVALIDATE_HINT);
414
int sceKernelDcacheWritebackInvalidateAll()
417
NOTICE_LOG(CPU,"sceKernelDcacheInvalidateAll()");
419
gpu->InvalidateCache(0, -1, GPU_INVALIDATE_ALL);
421
hleReSchedule("dcache invalidate all");
425
u32 sceKernelIcacheInvalidateAll()
428
NOTICE_LOG(CPU, "Icache invalidated - should clear JIT someday");
430
// Note that this doesn't actually fully invalidate all with such a large range.
431
currentMIPS->InvalidateICache(0, 0x3FFFFFFF);
435
u32 sceKernelIcacheClearAll()
438
NOTICE_LOG(CPU, "Icache cleared - should clear JIT someday");
440
DEBUG_LOG(CPU, "Icache cleared - should clear JIT someday");
441
// Note that this doesn't actually fully invalidate all with such a large range.
442
currentMIPS->InvalidateICache(0, 0x3FFFFFFF);
446
void KernelObject::GetQuickInfo(char *ptr, int size)
451
KernelObjectPool::KernelObjectPool() {
452
memset(occupied, 0, sizeof(bool)*maxCount);
453
nextID = initialNextID;
456
SceUID KernelObjectPool::Create(KernelObject *obj, int rangeBottom, int rangeTop) {
457
if (rangeTop > maxCount)
459
if (nextID >= rangeBottom && nextID < rangeTop)
460
rangeBottom = nextID++;
462
for (int i = rangeBottom; i < rangeTop; i++) {
466
pool[i]->uid = i + handleOffset;
467
return i + handleOffset;
471
ERROR_LOG_REPORT(SCEKERNEL, "Unable to allocate kernel object, too many objects slots in use.");
475
bool KernelObjectPool::IsValid(SceUID handle) const {
476
int index = handle - handleOffset;
477
if (index < 0 || index >= maxCount)
480
return occupied[index];
483
void KernelObjectPool::Clear() {
484
for (int i = 0; i < maxCount; i++) {
485
// brutally clear everything, no validation
491
nextID = initialNextID;
494
void KernelObjectPool::List() {
495
for (int i = 0; i < maxCount; i++) {
499
pool[i]->GetQuickInfo(buffer, 256);
500
INFO_LOG(SCEKERNEL, "KO %i: %s \"%s\": %s", i + handleOffset, pool[i]->GetTypeName(), pool[i]->GetName(), buffer);
502
strcpy(buffer, "WTF? Zero Pointer");
508
int KernelObjectPool::GetCount() const {
510
for (int i = 0; i < maxCount; i++) {
517
void KernelObjectPool::DoState(PointerWrap &p) {
518
auto s = p.Section("KernelObjectPool", 1);
522
int _maxCount = maxCount;
525
if (_maxCount != maxCount) {
526
p.SetError(p.ERROR_FAILURE);
527
ERROR_LOG(SCEKERNEL, "Unable to load state: different kernel object storage.");
531
if (p.mode == p.MODE_READ) {
532
hleCurrentThreadName = nullptr;
533
kernelObjects.Clear();
537
p.DoArray(occupied, maxCount);
538
for (int i = 0; i < maxCount; ++i) {
543
if (p.mode == p.MODE_READ) {
545
pool[i] = CreateByIDType(type);
547
// Already logged an error.
548
if (pool[i] == nullptr)
551
pool[i]->uid = i + handleOffset;
553
type = pool[i]->GetIDType();
557
if (p.error >= p.ERROR_FAILURE)
562
KernelObject *KernelObjectPool::CreateByIDType(int type) {
563
// Used for save states. This is ugly, but what other way is there?
565
case SCE_KERNEL_TMID_Alarm:
566
return __KernelAlarmObject();
567
case SCE_KERNEL_TMID_EventFlag:
568
return __KernelEventFlagObject();
569
case SCE_KERNEL_TMID_Mbox:
570
return __KernelMbxObject();
571
case SCE_KERNEL_TMID_Fpl:
572
return __KernelMemoryFPLObject();
573
case SCE_KERNEL_TMID_Vpl:
574
return __KernelMemoryVPLObject();
575
case PPSSPP_KERNEL_TMID_PMB:
576
return __KernelMemoryPMBObject();
577
case PPSSPP_KERNEL_TMID_Module:
578
return __KernelModuleObject();
579
case SCE_KERNEL_TMID_Mpipe:
580
return __KernelMsgPipeObject();
581
case SCE_KERNEL_TMID_Mutex:
582
return __KernelMutexObject();
583
case SCE_KERNEL_TMID_LwMutex:
584
return __KernelLwMutexObject();
585
case SCE_KERNEL_TMID_Semaphore:
586
return __KernelSemaphoreObject();
587
case SCE_KERNEL_TMID_Callback:
588
return __KernelCallbackObject();
589
case SCE_KERNEL_TMID_Thread:
590
return __KernelThreadObject();
591
case SCE_KERNEL_TMID_VTimer:
592
return __KernelVTimerObject();
593
case SCE_KERNEL_TMID_Tlspl:
594
case SCE_KERNEL_TMID_Tlspl_v0:
595
return __KernelTlsplObject();
596
case PPSSPP_KERNEL_TMID_File:
597
return __KernelFileNodeObject();
598
case PPSSPP_KERNEL_TMID_DirList:
599
return __KernelDirListingObject();
600
case SCE_KERNEL_TMID_ThreadEventHandler:
601
return __KernelThreadEventHandlerObject();
604
ERROR_LOG(COMMON, "Unable to load state: could not find object type %d.", type);
609
struct SystemStatus {
612
SceUInt_le clockPart1;
613
SceUInt_le clockPart2;
614
SceUInt_le perfcounter1;
615
SceUInt_le perfcounter2;
616
SceUInt_le perfcounter3;
619
static int sceKernelReferSystemStatus(u32 statusPtr) {
620
DEBUG_LOG(SCEKERNEL, "sceKernelReferSystemStatus(%08x)", statusPtr);
621
if (Memory::IsValidAddress(statusPtr)) {
623
memset(&status, 0, sizeof(SystemStatus));
624
status.size = sizeof(SystemStatus);
625
// TODO: Fill in the struct!
626
Memory::WriteStruct(statusPtr, &status);
631
struct DebugProfilerRegs {
654
static u32 sceKernelReferThreadProfiler(u32 statusPtr) {
655
ERROR_LOG(SCEKERNEL, "FAKE sceKernelReferThreadProfiler()");
657
// Can we confirm that the struct above is the right struct?
658
// If so, re-enable this code.
659
//DebugProfilerRegs regs;
660
//memset(®s, 0, sizeof(regs));
661
// TODO: fill the struct.
662
//if (Memory::IsValidAddress(statusPtr)) {
663
// Memory::WriteStruct(statusPtr, ®s);
668
static int sceKernelReferGlobalProfiler(u32 statusPtr) {
669
ERROR_LOG(SCEKERNEL, "UNIMPL sceKernelReferGlobalProfiler(%08x)", statusPtr);
674
const HLEFunction ThreadManForUser[] =
676
{0X55C20A00, &WrapI_CUUU<sceKernelCreateEventFlag>, "sceKernelCreateEventFlag", 'i', "sxxx" },
677
{0X812346E4, &WrapU_IU<sceKernelClearEventFlag>, "sceKernelClearEventFlag", 'x', "ix" },
678
{0XEF9E4C70, &WrapU_I<sceKernelDeleteEventFlag>, "sceKernelDeleteEventFlag", 'x', "i" },
679
{0X1FB15A32, &WrapU_IU<sceKernelSetEventFlag>, "sceKernelSetEventFlag", 'x', "ix" },
680
{0X402FCF22, &WrapI_IUUUU<sceKernelWaitEventFlag>, "sceKernelWaitEventFlag", 'i', "ixxpp", HLE_NOT_IN_INTERRUPT },
681
{0X328C546A, &WrapI_IUUUU<sceKernelWaitEventFlagCB>, "sceKernelWaitEventFlagCB", 'i', "ixxpp", HLE_NOT_IN_INTERRUPT },
682
{0X30FD48F0, &WrapI_IUUU<sceKernelPollEventFlag>, "sceKernelPollEventFlag", 'i', "ixxp" },
683
{0XCD203292, &WrapU_IUU<sceKernelCancelEventFlag>, "sceKernelCancelEventFlag", 'x', "ixp" },
684
{0XA66B0120, &WrapU_IU<sceKernelReferEventFlagStatus>, "sceKernelReferEventFlagStatus", 'x', "ix" },
686
{0X8FFDF9A2, &WrapI_IIU<sceKernelCancelSema>, "sceKernelCancelSema", 'i', "iix" },
687
{0XD6DA4BA1, &WrapI_CUIIU<sceKernelCreateSema>, "sceKernelCreateSema", 'i', "sxiix" },
688
{0X28B6489C, &WrapI_I<sceKernelDeleteSema>, "sceKernelDeleteSema", 'i', "i" },
689
{0X58B1F937, &WrapI_II<sceKernelPollSema>, "sceKernelPollSema", 'i', "ii" },
690
{0XBC6FEBC5, &WrapI_IU<sceKernelReferSemaStatus>, "sceKernelReferSemaStatus", 'i', "ix" },
691
{0X3F53E640, &WrapI_II<sceKernelSignalSema>, "sceKernelSignalSema", 'i', "ii" },
692
{0X4E3A1105, &WrapI_IIU<sceKernelWaitSema>, "sceKernelWaitSema", 'i', "iix", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
693
{0X6D212BAC, &WrapI_IIU<sceKernelWaitSemaCB>, "sceKernelWaitSemaCB", 'i', "iix", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
695
{0X60107536, &WrapI_U<sceKernelDeleteLwMutex>, "sceKernelDeleteLwMutex", 'i', "x" },
696
{0X19CFF145, &WrapI_UCUIU<sceKernelCreateLwMutex>, "sceKernelCreateLwMutex", 'i', "xsxix" },
697
{0X4C145944, &WrapI_IU<sceKernelReferLwMutexStatusByID>, "sceKernelReferLwMutexStatusByID", 'i', "ix" },
698
// NOTE: LockLwMutex, UnlockLwMutex, and ReferLwMutexStatus are in Kernel_Library, see sceKernelInterrupt.cpp.
699
// The below should not be called directly.
700
//{0x71040D5C, nullptr, "_sceKernelTryLockLwMutex", '?', "" },
701
//{0x7CFF8CF3, nullptr, "_sceKernelLockLwMutex", '?', "" },
702
//{0x31327F19, nullptr, "_sceKernelLockLwMutexCB", '?', "" },
703
//{0xBEED3A47, nullptr, "_sceKernelUnlockLwMutex", '?', "" },
705
{0XF8170FBE, &WrapI_I<sceKernelDeleteMutex>, "sceKernelDeleteMutex", 'i', "i" },
706
{0XB011B11F, &WrapI_IIU<sceKernelLockMutex>, "sceKernelLockMutex", 'i', "iix", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
707
{0X5BF4DD27, &WrapI_IIU<sceKernelLockMutexCB>, "sceKernelLockMutexCB", 'i', "iix", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
708
{0X6B30100F, &WrapI_II<sceKernelUnlockMutex>, "sceKernelUnlockMutex", 'i', "ii" },
709
{0XB7D098C6, &WrapI_CUIU<sceKernelCreateMutex>, "sceKernelCreateMutex", 'i', "sxix" },
710
{0X0DDCD2C9, &WrapI_II<sceKernelTryLockMutex>, "sceKernelTryLockMutex", 'i', "ii" },
711
{0XA9C2CB9A, &WrapI_IU<sceKernelReferMutexStatus>, "sceKernelReferMutexStatus", 'i', "ix" },
712
{0X87D9223C, &WrapI_IIU<sceKernelCancelMutex>, "sceKernelCancelMutex", 'i', "iix" },
714
{0XFCCFAD26, &WrapI_I<sceKernelCancelWakeupThread>, "sceKernelCancelWakeupThread", 'i', "i" },
715
{0X1AF94D03, nullptr, "sceKernelDonateWakeupThread", '?', "" },
716
{0XEA748E31, &WrapI_UU<sceKernelChangeCurrentThreadAttr>, "sceKernelChangeCurrentThreadAttr", 'i', "xx" },
717
{0X71BC9871, &WrapI_II<sceKernelChangeThreadPriority>, "sceKernelChangeThreadPriority", 'i', "ii" },
718
{0X446D8DE6, &WrapI_CUUIUU<sceKernelCreateThread>, "sceKernelCreateThread", 'i', "sxxixx", HLE_NOT_IN_INTERRUPT },
719
{0X9FA03CD3, &WrapI_I<sceKernelDeleteThread>, "sceKernelDeleteThread", 'i', "i" },
720
{0XBD123D9E, &WrapI_U<sceKernelDelaySysClockThread>, "sceKernelDelaySysClockThread", 'i', "P", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
721
{0X1181E963, &WrapI_U<sceKernelDelaySysClockThreadCB>, "sceKernelDelaySysClockThreadCB", 'i', "P", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
722
{0XCEADEB47, &WrapI_U<sceKernelDelayThread>, "sceKernelDelayThread", 'i', "x", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
723
{0X68DA9E36, &WrapI_U<sceKernelDelayThreadCB>, "sceKernelDelayThreadCB", 'i', "x", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
724
{0XAA73C935, &WrapV_I<sceKernelExitThread>, "sceKernelExitThread", 'v', "i" },
725
{0X809CE29B, &WrapV_I<sceKernelExitDeleteThread>, "sceKernelExitDeleteThread", 'v', "i" },
726
{0x94aa61ee, &WrapI_V<sceKernelGetThreadCurrentPriority>, "sceKernelGetThreadCurrentPriority", 'i', "" },
727
{0X293B45B8, &WrapI_V<sceKernelGetThreadId>, "sceKernelGetThreadId", 'i', "", HLE_NOT_IN_INTERRUPT },
728
{0X3B183E26, &WrapI_I<sceKernelGetThreadExitStatus>, "sceKernelGetThreadExitStatus", 'i', "i" },
729
{0X52089CA1, &WrapI_I<sceKernelGetThreadStackFreeSize>, "sceKernelGetThreadStackFreeSize", 'i', "i" },
730
{0XFFC36A14, &WrapU_UU<sceKernelReferThreadRunStatus>, "sceKernelReferThreadRunStatus", 'x', "xx" },
731
{0X17C1684E, &WrapU_UU<sceKernelReferThreadStatus>, "sceKernelReferThreadStatus", 'x', "xx" },
732
{0X2C34E053, &WrapI_I<sceKernelReleaseWaitThread>, "sceKernelReleaseWaitThread", 'i', "i" },
733
{0X75156E8F, &WrapI_I<sceKernelResumeThread>, "sceKernelResumeThread", 'i', "i" },
734
{0X3AD58B8C, &WrapU_V<sceKernelSuspendDispatchThread>, "sceKernelSuspendDispatchThread", 'x', "", HLE_NOT_IN_INTERRUPT },
735
{0X27E22EC2, &WrapU_U<sceKernelResumeDispatchThread>, "sceKernelResumeDispatchThread", 'x', "x", HLE_NOT_IN_INTERRUPT },
736
{0X912354A7, &WrapI_I<sceKernelRotateThreadReadyQueue>, "sceKernelRotateThreadReadyQueue", 'i', "i" },
737
{0X9ACE131E, &WrapI_V<sceKernelSleepThread>, "sceKernelSleepThread", 'i', "", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
738
{0X82826F70, &WrapI_V<sceKernelSleepThreadCB>, "sceKernelSleepThreadCB", 'i', "", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
739
{0XF475845D, &WrapI_IIU<sceKernelStartThread>, "sceKernelStartThread", 'i', "iix", HLE_NOT_IN_INTERRUPT },
740
{0X9944F31F, &WrapI_I<sceKernelSuspendThread>, "sceKernelSuspendThread", 'i', "i" },
741
{0X616403BA, &WrapI_I<sceKernelTerminateThread>, "sceKernelTerminateThread", 'i', "i" },
742
{0X383F7BCC, &WrapI_I<sceKernelTerminateDeleteThread>, "sceKernelTerminateDeleteThread", 'i', "i" },
743
{0X840E8133, &WrapI_IU<sceKernelWaitThreadEndCB>, "sceKernelWaitThreadEndCB", 'i', "ix" },
744
{0XD13BDE95, &WrapI_V<sceKernelCheckThreadStack>, "sceKernelCheckThreadStack", 'i', "" },
746
{0X94416130, &WrapU_UUUU<sceKernelGetThreadmanIdList>, "sceKernelGetThreadmanIdList", 'x', "xxxx" },
747
{0X57CF62DD, &WrapU_U<sceKernelGetThreadmanIdType>, "sceKernelGetThreadmanIdType", 'x', "x" },
748
{0XBC80EC7C, &WrapU_UUU<sceKernelExtendThreadStack>, "sceKernelExtendThreadStack", 'x', "xxx" },
749
// NOTE: Takes a UID from sceKernelMemory's AllocMemoryBlock and seems thread stack related.
750
//{0x28BFD974, nullptr, "ThreadManForUser_28BFD974", '?', "" },
752
{0X82BC5777, &WrapU64_V<sceKernelGetSystemTimeWide>, "sceKernelGetSystemTimeWide", 'X', "" },
753
{0XDB738F35, &WrapI_U<sceKernelGetSystemTime>, "sceKernelGetSystemTime", 'i', "x" },
754
{0X369ED59D, &WrapU_V<sceKernelGetSystemTimeLow>, "sceKernelGetSystemTimeLow", 'x', "" },
756
{0X8218B4DD, &WrapI_U<sceKernelReferGlobalProfiler>, "sceKernelReferGlobalProfiler", 'i', "x" },
757
{0X627E6F3A, &WrapI_U<sceKernelReferSystemStatus>, "sceKernelReferSystemStatus", 'i', "x" },
758
{0X64D4540E, &WrapU_U<sceKernelReferThreadProfiler>, "sceKernelReferThreadProfiler", 'x', "x" },
760
//Fifa Street 2 uses alarms
761
{0X6652B8CA, &WrapI_UUU<sceKernelSetAlarm>, "sceKernelSetAlarm", 'i', "xxx" },
762
{0XB2C25152, &WrapI_UUU<sceKernelSetSysClockAlarm>, "sceKernelSetSysClockAlarm", 'i', "xxx" },
763
{0X7E65B999, &WrapI_I<sceKernelCancelAlarm>, "sceKernelCancelAlarm", 'i', "i" },
764
{0XDAA3F564, &WrapI_IU<sceKernelReferAlarmStatus>, "sceKernelReferAlarmStatus", 'i', "ix" },
766
{0XBA6B92E2, &WrapI_UUU<sceKernelSysClock2USec>, "sceKernelSysClock2USec", 'i', "xxx" },
767
{0X110DEC9A, &WrapI_UU<sceKernelUSec2SysClock>, "sceKernelUSec2SysClock", 'i', "xx" },
768
{0XC8CD158C, &WrapU64_U<sceKernelUSec2SysClockWide>, "sceKernelUSec2SysClockWide", 'X', "x" },
769
{0XE1619D7C, &WrapI_UUUU<sceKernelSysClock2USecWide>, "sceKernelSysClock2USecWide", 'i', "xxxx" },
771
{0X278C0DF5, &WrapI_IU<sceKernelWaitThreadEnd>, "sceKernelWaitThreadEnd", 'i', "ix" },
772
{0XD59EAD2F, &WrapI_I<sceKernelWakeupThread>, "sceKernelWakeupThread", 'i', "i" }, //AI Go, audio?
774
{0x0C106E53, &WrapI_CIUUU<sceKernelRegisterThreadEventHandler>, "sceKernelRegisterThreadEventHandler", 'i', "sixxx", },
775
{0x72F3C145, &WrapI_I<sceKernelReleaseThreadEventHandler>, "sceKernelReleaseThreadEventHandler", 'i', "i" },
776
{0x369EEB6B, &WrapI_IU<sceKernelReferThreadEventHandlerStatus>, "sceKernelReferThreadEventHandlerStatus", 'i', "ip" },
778
{0x349d6d6c, &sceKernelCheckCallback, "sceKernelCheckCallback", 'i', "" },
779
{0XE81CAF8F, &WrapI_CUU<sceKernelCreateCallback>, "sceKernelCreateCallback", 'i', "sxx" },
780
{0XEDBA5844, &WrapI_I<sceKernelDeleteCallback>, "sceKernelDeleteCallback", 'i', "i" },
781
{0XC11BA8C4, &WrapI_II<sceKernelNotifyCallback>, "sceKernelNotifyCallback", 'i', "ii" },
782
{0XBA4051D6, &WrapI_I<sceKernelCancelCallback>, "sceKernelCancelCallback", 'i', "i" },
783
{0X2A3D44FF, &WrapI_I<sceKernelGetCallbackCount>, "sceKernelGetCallbackCount", 'i', "i" },
784
{0X730ED8BC, &WrapI_IU<sceKernelReferCallbackStatus>, "sceKernelReferCallbackStatus", 'i', "ip" },
786
{0X8125221D, &WrapI_CUU<sceKernelCreateMbx>, "sceKernelCreateMbx", 'i', "sxx" },
787
{0X86255ADA, &WrapI_I<sceKernelDeleteMbx>, "sceKernelDeleteMbx", 'i', "i" },
788
{0XE9B3061E, &WrapI_IU<sceKernelSendMbx>, "sceKernelSendMbx", 'i', "ix" },
789
{0X18260574, &WrapI_IUU<sceKernelReceiveMbx>, "sceKernelReceiveMbx", 'i', "ixx", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
790
{0XF3986382, &WrapI_IUU<sceKernelReceiveMbxCB>, "sceKernelReceiveMbxCB", 'i', "ixx", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
791
{0X0D81716A, &WrapI_IU<sceKernelPollMbx>, "sceKernelPollMbx", 'i', "ix" },
792
{0X87D4DD36, &WrapI_IU<sceKernelCancelReceiveMbx>, "sceKernelCancelReceiveMbx", 'i', "ix" },
793
{0XA8E8C846, &WrapI_IU<sceKernelReferMbxStatus>, "sceKernelReferMbxStatus", 'i', "ix" },
795
{0X7C0DC2A0, &WrapI_CIUUU<sceKernelCreateMsgPipe>, "sceKernelCreateMsgPipe", 'i', "sixxx" },
796
{0XF0B7DA1C, &WrapI_I<sceKernelDeleteMsgPipe>, "sceKernelDeleteMsgPipe", 'i', "i" },
797
{0X876DBFAD, &WrapI_IUUUUU<sceKernelSendMsgPipe>, "sceKernelSendMsgPipe", 'i', "ixxxxx" },
798
{0X7C41F2C2, &WrapI_IUUUUU<sceKernelSendMsgPipeCB>, "sceKernelSendMsgPipeCB", 'i', "ixxxxx" },
799
{0X884C9F90, &WrapI_IUUUU<sceKernelTrySendMsgPipe>, "sceKernelTrySendMsgPipe", 'i', "ixxxx" },
800
{0X74829B76, &WrapI_IUUUUU<sceKernelReceiveMsgPipe>, "sceKernelReceiveMsgPipe", 'i', "ixxxxx" },
801
{0XFBFA697D, &WrapI_IUUUUU<sceKernelReceiveMsgPipeCB>, "sceKernelReceiveMsgPipeCB", 'i', "ixxxxx" },
802
{0XDF52098F, &WrapI_IUUUU<sceKernelTryReceiveMsgPipe>, "sceKernelTryReceiveMsgPipe", 'i', "ixxxx" },
803
{0X349B864D, &WrapI_IUU<sceKernelCancelMsgPipe>, "sceKernelCancelMsgPipe", 'i', "ixx" },
804
{0X33BE4024, &WrapI_IU<sceKernelReferMsgPipeStatus>, "sceKernelReferMsgPipeStatus", 'i', "ix" },
806
{0X56C039B5, &WrapI_CIUUU<sceKernelCreateVpl>, "sceKernelCreateVpl", 'i', "sixxx" },
807
{0X89B3D48C, &WrapI_I<sceKernelDeleteVpl>, "sceKernelDeleteVpl", 'i', "i" },
808
{0XBED27435, &WrapI_IUUU<sceKernelAllocateVpl>, "sceKernelAllocateVpl", 'i', "ixxx", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
809
{0XEC0A693F, &WrapI_IUUU<sceKernelAllocateVplCB>, "sceKernelAllocateVplCB", 'i', "ixxx", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
810
{0XAF36D708, &WrapI_IUU<sceKernelTryAllocateVpl>, "sceKernelTryAllocateVpl", 'i', "ixx" },
811
{0XB736E9FF, &WrapI_IU<sceKernelFreeVpl>, "sceKernelFreeVpl", 'i', "ix" },
812
{0X1D371B8A, &WrapI_IU<sceKernelCancelVpl>, "sceKernelCancelVpl", 'i', "ix" },
813
{0X39810265, &WrapI_IU<sceKernelReferVplStatus>, "sceKernelReferVplStatus", 'i', "ix" },
815
{0XC07BB470, &WrapI_CUUUUU<sceKernelCreateFpl>, "sceKernelCreateFpl", 'i', "sxxxxx" },
816
{0XED1410E0, &WrapI_I<sceKernelDeleteFpl>, "sceKernelDeleteFpl", 'i', "i" },
817
{0XD979E9BF, &WrapI_IUU<sceKernelAllocateFpl>, "sceKernelAllocateFpl", 'i', "ixx", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
818
{0XE7282CB6, &WrapI_IUU<sceKernelAllocateFplCB>, "sceKernelAllocateFplCB", 'i', "ixx", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
819
{0X623AE665, &WrapI_IU<sceKernelTryAllocateFpl>, "sceKernelTryAllocateFpl", 'i', "ix" },
820
{0XF6414A71, &WrapI_IU<sceKernelFreeFpl>, "sceKernelFreeFpl", 'i', "ix" },
821
{0XA8AA591F, &WrapI_IU<sceKernelCancelFpl>, "sceKernelCancelFpl", 'i', "ix" },
822
{0XD8199E4C, &WrapI_IU<sceKernelReferFplStatus>, "sceKernelReferFplStatus", 'i', "ix" },
824
{0X20FFF560, &WrapU_CU<sceKernelCreateVTimer>, "sceKernelCreateVTimer", 'x', "sx", HLE_NOT_IN_INTERRUPT },
825
{0X328F9E52, &WrapU_I<sceKernelDeleteVTimer>, "sceKernelDeleteVTimer", 'x', "i", HLE_NOT_IN_INTERRUPT },
826
{0XC68D9437, &WrapU_I<sceKernelStartVTimer>, "sceKernelStartVTimer", 'x', "i" },
827
{0XD0AEEE87, &WrapU_I<sceKernelStopVTimer>, "sceKernelStopVTimer", 'x', "i" },
828
{0XD2D615EF, &WrapU_I<sceKernelCancelVTimerHandler>, "sceKernelCancelVTimerHandler", 'x', "i" },
829
{0XB3A59970, &WrapU_IU<sceKernelGetVTimerBase>, "sceKernelGetVTimerBase", 'x', "ix" },
830
{0XB7C18B77, &WrapU64_I<sceKernelGetVTimerBaseWide>, "sceKernelGetVTimerBaseWide", 'X', "i" },
831
{0X034A921F, &WrapU_IU<sceKernelGetVTimerTime>, "sceKernelGetVTimerTime", 'x', "ix" },
832
{0XC0B3FFD2, &WrapU64_I<sceKernelGetVTimerTimeWide>, "sceKernelGetVTimerTimeWide", 'X', "i" },
833
{0X5F32BEAA, &WrapU_IU<sceKernelReferVTimerStatus>, "sceKernelReferVTimerStatus", 'x', "ix" },
834
{0X542AD630, &WrapU_IU<sceKernelSetVTimerTime>, "sceKernelSetVTimerTime", 'x', "ix" },
835
{0XFB6425C3, &WrapU64_IU64<sceKernelSetVTimerTimeWide>, "sceKernelSetVTimerTimeWide", 'X', "iX" },
836
{0XD8B299AE, &WrapU_IUUU<sceKernelSetVTimerHandler>, "sceKernelSetVTimerHandler", 'x', "ixxx" },
837
{0X53B00E9A, &WrapU_IU64UU<sceKernelSetVTimerHandlerWide>, "sceKernelSetVTimerHandlerWide", 'x', "iXxx" },
839
{0X8DAFF657, &WrapI_CUUUUU<sceKernelCreateTlspl>, "sceKernelCreateTlspl", 'i', "sxxxxx" },
840
{0X32BF938E, &WrapI_I<sceKernelDeleteTlspl>, "sceKernelDeleteTlspl", 'i', "i" },
841
{0X721067F3, &WrapI_IU<sceKernelReferTlsplStatus>, "sceKernelReferTlsplStatus", 'i', "ix" },
842
// Not completely certain about args.
843
{0X4A719FB2, &WrapI_I<sceKernelFreeTlspl>, "sceKernelFreeTlspl", 'i', "i" },
844
// Internal. Takes (uid, &addr) as parameters... probably.
845
//{0x65F54FFB, nullptr, "_sceKernelAllocateTlspl", 'v', "" },
846
// NOTE: sceKernelGetTlsAddr is in Kernel_Library, see sceKernelInterrupt.cpp.
848
// Not sure if these should be hooked up. See below.
849
{0x0E927AED, &_sceKernelReturnFromTimerHandler, "_sceKernelReturnFromTimerHandler", 'v', "" },
850
{0X532A522E, &WrapV_I<_sceKernelExitThread>, "_sceKernelExitThread", 'v', "i" },
852
// Shouldn't hook this up. No games should import this function manually and call it.
853
// {0x6E9EA350, _sceKernelReturnFromCallback,"_sceKernelReturnFromCallback"},
856
const HLEFunction ThreadManForKernel[] =
858
{0xCEADEB47, &WrapI_U<sceKernelDelayThread>, "sceKernelDelayThread", 'i', "x", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED | HLE_KERNEL_SYSCALL },
859
{0x446D8DE6, &WrapI_CUUIUU<sceKernelCreateThread>, "sceKernelCreateThread", 'i', "sxxixx", HLE_NOT_IN_INTERRUPT | HLE_KERNEL_SYSCALL },
860
{0xF475845D, &WrapI_IIU<sceKernelStartThread>, "sceKernelStartThread", 'i', "iix", HLE_NOT_IN_INTERRUPT | HLE_KERNEL_SYSCALL },
863
void Register_ThreadManForUser()
865
RegisterModule("ThreadManForUser", ARRAY_SIZE(ThreadManForUser), ThreadManForUser);
869
const HLEFunction LoadExecForUser[] =
871
{0X05572A5F, &WrapV_V<sceKernelExitGame>, "sceKernelExitGame", 'v', "" },
872
{0X4AC57943, &WrapI_I<sceKernelRegisterExitCallback>, "sceKernelRegisterExitCallback", 'i', "i" },
873
{0XBD2F1094, &WrapI_CU<sceKernelLoadExec>, "sceKernelLoadExec", 'i', "sx" },
874
{0X2AC9954B, &WrapV_V<sceKernelExitGameWithStatus>, "sceKernelExitGameWithStatus", 'v', "" },
875
{0X362A956B, &WrapI_V<LoadExecForUser_362A956B>, "LoadExecForUser_362A956B", 'i', "" },
876
{0X8ADA38D3, nullptr, "LoadExecForUser_8ADA38D3", '?', "" },
879
void Register_LoadExecForUser()
881
RegisterModule("LoadExecForUser", ARRAY_SIZE(LoadExecForUser), LoadExecForUser);
884
const HLEFunction LoadExecForKernel[] =
886
{0x4AC57943, &WrapI_I<sceKernelRegisterExitCallback>, "sceKernelRegisterExitCallback", 'i', "i", HLE_KERNEL_SYSCALL },
887
{0XA3D5E142, nullptr, "LoadExecForKernel_a3d5e142", '?', "" },
890
void Register_LoadExecForKernel()
892
RegisterModule("LoadExecForKernel", ARRAY_SIZE(LoadExecForKernel), LoadExecForKernel);
895
const HLEFunction ExceptionManagerForKernel[] =
897
{0X3FB264FC, nullptr, "sceKernelRegisterExceptionHandler", '?', "" },
898
{0X5A837AD4, nullptr, "sceKernelRegisterPriorityExceptionHandler", '?', "" },
899
{0x565C0B0E, &WrapI_V<sceKernelRegisterDefaultExceptionHandler>, "sceKernelRegisterDefaultExceptionHandler", 'i', "", HLE_KERNEL_SYSCALL },
900
{0X1AA6CFFA, nullptr, "sceKernelReleaseExceptionHandler", '?', "" },
901
{0XDF83875E, nullptr, "sceKernelGetActiveDefaultExceptionHandler", '?', "" },
902
{0X291FF031, nullptr, "sceKernelReleaseDefaultExceptionHandler", '?', "" },
903
{0X15ADC862, nullptr, "sceKernelRegisterNmiHandler", '?', "" },
904
{0XB15357C9, nullptr, "sceKernelReleaseNmiHandler", '?', "" },
907
void Register_ExceptionManagerForKernel()
909
RegisterModule("ExceptionManagerForKernel", ARRAY_SIZE(ExceptionManagerForKernel), ExceptionManagerForKernel);
912
// Seen in some homebrew
913
const HLEFunction UtilsForKernel[] = {
914
{0xC2DF770E, WrapI_UI<sceKernelIcacheInvalidateRange>, "sceKernelIcacheInvalidateRange", '?', "", HLE_KERNEL_SYSCALL },
915
{0X78934841, nullptr, "sceKernelGzipDecompress", '?', "" },
916
{0XE8DB3CE6, nullptr, "sceKernelDeflateDecompress", '?', "" },
917
{0X840259F1, nullptr, "sceKernelUtilsSha1Digest", '?', "" },
918
{0X9E5C5086, nullptr, "sceKernelUtilsMd5BlockInit", '?', "" },
919
{0X61E1E525, nullptr, "sceKernelUtilsMd5BlockUpdate", '?', "" },
920
{0XB8D24E78, nullptr, "sceKernelUtilsMd5BlockResult", '?', "" },
921
{0XC8186A58, nullptr, "sceKernelUtilsMd5Digest", '?', "" },
922
{0X6C6887EE, nullptr, "UtilsForKernel_6C6887EE", '?', "" },
923
{0X91E4F6A7, nullptr, "sceKernelLibcClock", '?', "" },
924
{0X27CC57F0, nullptr, "sceKernelLibcTime", '?', "" },
925
{0X79D1C3FA, nullptr, "sceKernelDcacheWritebackAll", '?', "" },
926
{0X3EE30821, nullptr, "sceKernelDcacheWritebackRange", '?', "" },
927
{0X34B9FA9E, nullptr, "sceKernelDcacheWritebackInvalidateRange", '?', "" },
928
{0XB435DEC5, nullptr, "sceKernelDcacheWritebackInvalidateAll", '?', "" },
929
{0XBFA98062, nullptr, "sceKernelDcacheInvalidateRange", '?', "" },
930
{0X920F104A, nullptr, "sceKernelIcacheInvalidateAll", '?', "" },
931
{0XE860E75E, nullptr, "sceKernelUtilsMt19937Init", '?', "" },
932
{0X06FB8A63, nullptr, "sceKernelUtilsMt19937UInt", '?', "" },
936
void Register_UtilsForKernel()
938
RegisterModule("UtilsForKernel", ARRAY_SIZE(UtilsForKernel), UtilsForKernel);
941
void Register_ThreadManForKernel()
943
RegisterModule("ThreadManForKernel", ARRAY_SIZE(ThreadManForKernel), ThreadManForKernel);