1 // Copyright (c) 2012- PPSSPP Project.
2 
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.
6 
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.
11 
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
14 
15 // Official git repository and contact information can be found at
16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17 
18 #include "Common/Serialize/SerializeFuncs.h"
19 #include "Common/LogManager.h"
20 #include "Core/Core.h"
21 #include "Core/Config.h"
22 #include "Core/CwCheat.h"
23 #include "Core/MemMapHelpers.h"
24 #include "Core/HLE/HLE.h"
25 #include "Core/HLE/FunctionWrappers.h"
26 #include "Core/MIPS/MIPS.h"
27 #include "Core/MIPS/MIPSCodeUtils.h"
28 #include "Core/MIPS/MIPSInt.h"
29 #include "Core/MIPS/JitCommon/JitCommon.h"
30 
31 #include "Core/FileSystems/FileSystem.h"
32 #include "Core/FileSystems/MetaFileSystem.h"
33 #include "Core/PSPLoaders.h"
34 #include "Core/CoreTiming.h"
35 #include "Core/Reporting.h"
36 #include "Core/SaveState.h"
37 #include "Core/System.h"
38 #include "GPU/GPUInterface.h"
39 #include "GPU/GPUState.h"
40 
41 #include "__sceAudio.h"
42 #include "sceAtrac.h"
43 #include "sceAudio.h"
44 #include "sceAudiocodec.h"
45 #include "sceCcc.h"
46 #include "sceCtrl.h"
47 #include "sceDisplay.h"
48 #include "sceFont.h"
49 #include "sceGe.h"
50 #include "sceIo.h"
51 #include "sceJpeg.h"
52 #include "sceKernel.h"
53 #include "sceKernelAlarm.h"
54 #include "sceKernelHeap.h"
55 #include "sceKernelInterrupt.h"
56 #include "sceKernelThread.h"
57 #include "sceKernelMemory.h"
58 #include "sceKernelModule.h"
59 #include "sceKernelMutex.h"
60 #include "sceKernelMbx.h"
61 #include "sceKernelMsgPipe.h"
62 #include "sceKernelInterrupt.h"
63 #include "sceKernelSemaphore.h"
64 #include "sceKernelEventFlag.h"
65 #include "sceKernelVTimer.h"
66 #include "sceKernelTime.h"
67 #include "sceMp3.h"
68 #include "sceMpeg.h"
69 #include "sceNet.h"
70 #include "sceNetAdhoc.h"
71 #include "scePower.h"
72 #include "sceUtility.h"
73 #include "sceUmd.h"
74 #include "sceRtc.h"
75 #include "sceSsl.h"
76 #include "sceSas.h"
77 #include "scePsmf.h"
78 #include "sceImpose.h"
79 #include "sceUsb.h"
80 #include "sceUsbGps.h"
81 #include "sceUsbCam.h"
82 #include "sceUsbMic.h"
83 #include "scePspNpDrm_user.h"
84 #include "sceVaudio.h"
85 #include "sceHeap.h"
86 #include "sceDmac.h"
87 #include "sceMp4.h"
88 #include "sceOpenPSID.h"
89 
90 #include "../Util/PPGeDraw.h"
91 
92 /*
93 17: [MIPS32 R4K 00000000 ]: Loader: Type: 1 Vaddr: 00000000 Filesz: 2856816 Memsz: 2856816
94 18: [MIPS32 R4K 00000000 ]: Loader: Loadable Segment Copied to 0898dab0, size 002b9770
95 19: [MIPS32 R4K 00000000 ]: Loader: Type: 1 Vaddr: 002b9770 Filesz: 14964 Memsz: 733156
96 20: [MIPS32 R4K 00000000 ]: Loader: Loadable Segment Copied to 08c47220, size 000b2fe4
97 */
98 
99 static bool kernelRunning = false;
100 KernelObjectPool kernelObjects;
101 KernelStats kernelStats;
102 u32 registeredExitCbId;
103 
__KernelInit()104 void __KernelInit()
105 {
106 	if (kernelRunning)
107 	{
108 		ERROR_LOG(SCEKERNEL, "Can't init kernel when kernel is running");
109 		return;
110 	}
111 	INFO_LOG(SCEKERNEL, "Initializing kernel...");
112 
113 	__KernelTimeInit();
114 	__InterruptsInit();
115 	__KernelMemoryInit();
116 	__KernelThreadingInit();
117 	__KernelAlarmInit();
118 	__KernelVTimerInit();
119 	__KernelEventFlagInit();
120 	__KernelMbxInit();
121 	__KernelMutexInit();
122 	__KernelSemaInit();
123 	__KernelMsgPipeInit();
124 	__IoInit();
125 	__JpegInit();
126 	__AudioInit();
127 	__SasInit();
128 	__AtracInit();
129 	__CccInit();
130 	__DisplayInit();
131 	__GeInit();
132 	__PowerInit();
133 	__UtilityInit();
134 	__UmdInit();
135 	__MpegInit();
136 	__PsmfInit();
137 	__CtrlInit();
138 	__RtcInit();
139 	__SslInit();
140 	__ImposeInit();
141 	__UsbInit();
142 	__FontInit();
143 	__NetInit();
144 	__NetAdhocInit();
145 	__VaudioInit();
146 	__CheatInit();
147 	__HeapInit();
148 	__DmacInit();
149 	__AudioCodecInit();
150 	__VideoPmpInit();
151 	__UsbGpsInit();
152 	__UsbCamInit();
153 	__UsbMicInit();
154 	__OpenPSIDInit();
155 
156 	SaveState::Init();  // Must be after IO, as it may create a directory
157 	Reporting::Init();
158 
159 	// "Internal" PSP libraries
160 	__PPGeInit();
161 
162 	kernelRunning = true;
163 	INFO_LOG(SCEKERNEL, "Kernel initialized.");
164 }
165 
__KernelShutdown()166 void __KernelShutdown()
167 {
168 	if (!kernelRunning)
169 	{
170 		ERROR_LOG(SCEKERNEL, "Can't shut down kernel - not running");
171 		return;
172 	}
173 	kernelObjects.List();
174 	INFO_LOG(SCEKERNEL, "Shutting down kernel - %i kernel objects alive", kernelObjects.GetCount());
175 	hleCurrentThreadName = NULL;
176 	kernelObjects.Clear();
177 
178 	__OpenPSIDShutdown();
179 	__UsbCamShutdown();
180 	__UsbMicShutdown();
181 	__UsbGpsShutdown();
182 
183 	__AudioCodecShutdown();
184 	__VideoPmpShutdown();
185 	__AACShutdown();
186 	__NetAdhocShutdown();
187 	__NetShutdown();
188 	__FontShutdown();
189 
190 	__Mp3Shutdown();
191 	__MpegShutdown();
192 	__PsmfShutdown();
193 	__PPGeShutdown();
194 
195 	__CtrlShutdown();
196 	__UtilityShutdown();
197 	__GeShutdown();
198 	__SasShutdown();
199 	__DisplayShutdown();
200 	__AtracShutdown();
201 	__AudioShutdown();
202 	__IoShutdown();
203 	__KernelMutexShutdown();
204 	__KernelThreadingShutdown();
205 	__KernelMemoryShutdown();
206 	__InterruptsShutdown();
207 	__CheatShutdown();
208 	__KernelModuleShutdown();
209 
210 	CoreTiming::ClearPendingEvents();
211 	CoreTiming::UnregisterAllEvents();
212 	Reporting::Shutdown();
213 	SaveState::Shutdown();
214 
215 	kernelRunning = false;
216 }
217 
__KernelDoState(PointerWrap & p)218 void __KernelDoState(PointerWrap &p)
219 {
220 	{
221 		auto s = p.Section("Kernel", 1, 2);
222 		if (!s)
223 			return;
224 
225 		Do(p, kernelRunning);
226 		kernelObjects.DoState(p);
227 
228 		if (s >= 2)
229 			Do(p, registeredExitCbId);
230 	}
231 
232 	{
233 		auto s = p.Section("Kernel Modules", 1);
234 		if (!s)
235 			return;
236 
237 		__InterruptsDoState(p);
238 		// Memory needs to be after kernel objects, which may free kernel memory.
239 		__KernelMemoryDoState(p);
240 		__KernelThreadingDoState(p);
241 		__KernelAlarmDoState(p);
242 		__KernelVTimerDoState(p);
243 		__KernelEventFlagDoState(p);
244 		__KernelMbxDoState(p);
245 		__KernelModuleDoState(p);
246 		__KernelMsgPipeDoState(p);
247 		__KernelMutexDoState(p);
248 		__KernelSemaDoState(p);
249 		__KernelTimeDoState(p);
250 	}
251 
252 	{
253 		auto s = p.Section("HLE Modules", 1);
254 		if (!s)
255 			return;
256 
257 		__AtracDoState(p);
258 		__AudioDoState(p);
259 		__CccDoState(p);
260 		__CtrlDoState(p);
261 		__DisplayDoState(p);
262 		__FontDoState(p);
263 		__GeDoState(p);
264 		__ImposeDoState(p);
265 		__IoDoState(p);
266 		__JpegDoState(p);
267 		__Mp3DoState(p);
268 		__MpegDoState(p);
269 		__NetDoState(p);
270 		__NetAdhocDoState(p);
271 		__PowerDoState(p);
272 		__PsmfDoState(p);
273 		__PsmfPlayerDoState(p);
274 		__RtcDoState(p);
275 		__SasDoState(p);
276 		__SslDoState(p);
277 		__UmdDoState(p);
278 		__UtilityDoState(p);
279 		__UsbDoState(p);
280 		__VaudioDoState(p);
281 		__HeapDoState(p);
282 
283 		__PPGeDoState(p);
284 		__CheatDoState(p);
285 		__sceAudiocodecDoState(p);
286 		__VideoPmpDoState(p);
287 		__AACDoState(p);
288 		__UsbGpsDoState(p);
289 		__UsbMicDoState(p);
290 
291 		// IMPORTANT! Add new sections last!
292 	}
293 
294 	{
295 		auto s = p.Section("Kernel Cleanup", 1);
296 		if (!s)
297 			return;
298 
299 		__InterruptsDoStateLate(p);
300 		__KernelThreadingDoStateLate(p);
301 		Reporting::DoState(p);
302 	}
303 }
304 
__KernelIsRunning()305 bool __KernelIsRunning() {
306 	return kernelRunning;
307 }
308 
__KernelStateSummary()309 std::string __KernelStateSummary() {
310 	std::string threadSummary = __KernelThreadingSummary();
311 	return StringFromFormat("%s", threadSummary.c_str());
312 }
313 
314 
sceKernelExitGame()315 void sceKernelExitGame()
316 {
317 	INFO_LOG(SCEKERNEL, "sceKernelExitGame");
318 	__KernelSwitchOffThread("game exited");
319 	Core_Stop();
320 }
321 
sceKernelExitGameWithStatus()322 void sceKernelExitGameWithStatus()
323 {
324 	INFO_LOG(SCEKERNEL, "sceKernelExitGameWithStatus");
325 	__KernelSwitchOffThread("game exited");
326 	Core_Stop();
327 }
328 
sceKernelDevkitVersion()329 u32 sceKernelDevkitVersion()
330 {
331 	int firmwareVersion = g_Config.iFirmwareVersion;
332 	int major = firmwareVersion / 100;
333 	int minor = (firmwareVersion / 10) % 10;
334 	int revision = firmwareVersion % 10;
335 	int devkitVersion = (major << 24) | (minor << 16) | (revision << 8) | 0x10;
336 
337 	DEBUG_LOG(SCEKERNEL, "%08x=sceKernelDevkitVersion()", devkitVersion);
338 	return devkitVersion;
339 }
340 
sceKernelRegisterKprintfHandler()341 u32 sceKernelRegisterKprintfHandler()
342 {
343 	ERROR_LOG(SCEKERNEL, "UNIMPL sceKernelRegisterKprintfHandler()");
344 	return 0;
345 }
346 
sceKernelRegisterDefaultExceptionHandler()347 int sceKernelRegisterDefaultExceptionHandler()
348 {
349 	ERROR_LOG(SCEKERNEL, "UNIMPL sceKernelRegisterDefaultExceptionHandler()");
350 	return 0;
351 }
352 
sceKernelSetGPO(u32 ledAddr)353 void sceKernelSetGPO(u32 ledAddr)
354 {
355 	// Sets debug LEDs.
356 	DEBUG_LOG(SCEKERNEL, "sceKernelSetGPO(%02x)", ledAddr);
357 }
358 
sceKernelGetGPI()359 u32 sceKernelGetGPI()
360 {
361 	// Always returns 0 on production systems.
362 	DEBUG_LOG(SCEKERNEL, "0=sceKernelGetGPI()");
363 	return 0;
364 }
365 
366 // #define LOG_CACHE
367 
368 // Don't even log these by default, they're spammy and we probably won't
369 // need to emulate them. Useful for invalidating cached textures though,
370 // and in the future display lists (although hashing takes care of those
371 // for now).
sceKernelDcacheInvalidateRange(u32 addr,int size)372 int sceKernelDcacheInvalidateRange(u32 addr, int size)
373 {
374 #ifdef LOG_CACHE
375 	NOTICE_LOG(CPU,"sceKernelDcacheInvalidateRange(%08x, %i)", addr, size);
376 #endif
377 	if (size < 0 || (int) addr + size < 0)
378 		return SCE_KERNEL_ERROR_ILLEGAL_ADDR;
379 
380 	if (size > 0)
381 	{
382 		if ((addr % 64) != 0 || (size % 64) != 0)
383 			return SCE_KERNEL_ERROR_CACHE_ALIGNMENT;
384 
385 		if (addr != 0)
386 			gpu->InvalidateCache(addr, size, GPU_INVALIDATE_HINT);
387 	}
388 	hleEatCycles(190);
389 	return 0;
390 }
391 
sceKernelIcacheInvalidateRange(u32 addr,int size)392 int sceKernelIcacheInvalidateRange(u32 addr, int size) {
393 	DEBUG_LOG(CPU, "sceKernelIcacheInvalidateRange(%08x, %i)", addr, size);
394 	currentMIPS->InvalidateICache(addr, size);
395 	return 0;
396 }
397 
sceKernelDcacheWritebackAll()398 int sceKernelDcacheWritebackAll()
399 {
400 #ifdef LOG_CACHE
401 	NOTICE_LOG(CPU,"sceKernelDcacheWritebackAll()");
402 #endif
403 	// Some games seem to use this a lot, it doesn't make sense
404 	// to zap the whole texture cache.
405 	gpu->InvalidateCache(0, -1, GPU_INVALIDATE_ALL);
406 	hleEatCycles(3524);
407 	hleReSchedule("dcache writeback all");
408 	return 0;
409 }
410 
sceKernelDcacheWritebackRange(u32 addr,int size)411 int sceKernelDcacheWritebackRange(u32 addr, int size)
412 {
413 #ifdef LOG_CACHE
414 	NOTICE_LOG(CPU,"sceKernelDcacheWritebackRange(%08x, %i)", addr, size);
415 #endif
416 	if (size < 0)
417 		return SCE_KERNEL_ERROR_INVALID_SIZE;
418 
419 	if (size > 0 && addr != 0) {
420 		gpu->InvalidateCache(addr, size, GPU_INVALIDATE_HINT);
421 	}
422 	hleEatCycles(165);
423 	return 0;
424 }
425 
sceKernelDcacheWritebackInvalidateRange(u32 addr,int size)426 int sceKernelDcacheWritebackInvalidateRange(u32 addr, int size)
427 {
428 #ifdef LOG_CACHE
429 	NOTICE_LOG(CPU,"sceKernelDcacheInvalidateRange(%08x, %i)", addr, size);
430 #endif
431 	if (size < 0)
432 		return SCE_KERNEL_ERROR_INVALID_SIZE;
433 
434 	if (size > 0 && addr != 0) {
435 		gpu->InvalidateCache(addr, size, GPU_INVALIDATE_HINT);
436 	}
437 	hleEatCycles(165);
438 	return 0;
439 }
440 
sceKernelDcacheWritebackInvalidateAll()441 int sceKernelDcacheWritebackInvalidateAll()
442 {
443 #ifdef LOG_CACHE
444 	NOTICE_LOG(CPU,"sceKernelDcacheInvalidateAll()");
445 #endif
446 	gpu->InvalidateCache(0, -1, GPU_INVALIDATE_ALL);
447 	hleEatCycles(1165);
448 	hleReSchedule("dcache invalidate all");
449 	return 0;
450 }
451 
sceKernelIcacheInvalidateAll()452 u32 sceKernelIcacheInvalidateAll()
453 {
454 #ifdef LOG_CACHE
455 	NOTICE_LOG(CPU, "Icache invalidated - should clear JIT someday");
456 #endif
457 	// Note that this doesn't actually fully invalidate all with such a large range.
458 	currentMIPS->InvalidateICache(0, 0x3FFFFFFF);
459 	return 0;
460 }
461 
sceKernelIcacheClearAll()462 u32 sceKernelIcacheClearAll()
463 {
464 #ifdef LOG_CACHE
465 	NOTICE_LOG(CPU, "Icache cleared - should clear JIT someday");
466 #endif
467 	DEBUG_LOG(CPU, "Icache cleared - should clear JIT someday");
468 	// Note that this doesn't actually fully invalidate all with such a large range.
469 	currentMIPS->InvalidateICache(0, 0x3FFFFFFF);
470 	return 0;
471 }
472 
GetQuickInfo(char * ptr,int size)473 void KernelObject::GetQuickInfo(char *ptr, int size)
474 {
475 	strcpy(ptr, "-");
476 }
477 
KernelObjectPool()478 KernelObjectPool::KernelObjectPool() {
479 	memset(occupied, 0, sizeof(bool)*maxCount);
480 	nextID = initialNextID;
481 }
482 
Create(KernelObject * obj,int rangeBottom,int rangeTop)483 SceUID KernelObjectPool::Create(KernelObject *obj, int rangeBottom, int rangeTop) {
484 	if (rangeTop > maxCount)
485 		rangeTop = maxCount;
486 	if (nextID >= rangeBottom && nextID < rangeTop)
487 		rangeBottom = nextID++;
488 
489 	for (int i = rangeBottom; i < rangeTop; i++) {
490 		if (!occupied[i]) {
491 			occupied[i] = true;
492 			pool[i] = obj;
493 			pool[i]->uid = i + handleOffset;
494 			return i + handleOffset;
495 		}
496 	}
497 
498 	ERROR_LOG_REPORT(SCEKERNEL, "Unable to allocate kernel object, too many objects slots in use.");
499 	return 0;
500 }
501 
IsValid(SceUID handle) const502 bool KernelObjectPool::IsValid(SceUID handle) const {
503 	int index = handle - handleOffset;
504 	if (index < 0 || index >= maxCount)
505 		return false;
506 	else
507 		return occupied[index];
508 }
509 
Clear()510 void KernelObjectPool::Clear() {
511 	for (int i = 0; i < maxCount; i++) {
512 		// brutally clear everything, no validation
513 		if (occupied[i])
514 			delete pool[i];
515 		pool[i] = nullptr;
516 		occupied[i] = false;
517 	}
518 	nextID = initialNextID;
519 }
520 
List()521 void KernelObjectPool::List() {
522 	for (int i = 0; i < maxCount; i++) {
523 		if (occupied[i]) {
524 			char buffer[256];
525 			if (pool[i]) {
526 				pool[i]->GetQuickInfo(buffer, 256);
527 				INFO_LOG(SCEKERNEL, "KO %i: %s \"%s\": %s", i + handleOffset, pool[i]->GetTypeName(), pool[i]->GetName(), buffer);
528 			} else {
529 				strcpy(buffer, "WTF? Zero Pointer");
530 			}
531 		}
532 	}
533 }
534 
GetCount() const535 int KernelObjectPool::GetCount() const {
536 	int count = 0;
537 	for (int i = 0; i < maxCount; i++) {
538 		if (occupied[i])
539 			count++;
540 	}
541 	return count;
542 }
543 
DoState(PointerWrap & p)544 void KernelObjectPool::DoState(PointerWrap &p) {
545 	auto s = p.Section("KernelObjectPool", 1);
546 	if (!s)
547 		return;
548 
549 	int _maxCount = maxCount;
550 	Do(p, _maxCount);
551 
552 	if (_maxCount != maxCount) {
553 		p.SetError(p.ERROR_FAILURE);
554 		ERROR_LOG(SCEKERNEL, "Unable to load state: different kernel object storage.");
555 		return;
556 	}
557 
558 	if (p.mode == p.MODE_READ) {
559 		hleCurrentThreadName = nullptr;
560 		kernelObjects.Clear();
561 	}
562 
563 	Do(p, nextID);
564 	DoArray(p, occupied, maxCount);
565 	for (int i = 0; i < maxCount; ++i) {
566 		if (!occupied[i])
567 			continue;
568 
569 		int type;
570 		if (p.mode == p.MODE_READ) {
571 			Do(p, type);
572 			pool[i] = CreateByIDType(type);
573 
574 			// Already logged an error.
575 			if (pool[i] == nullptr)
576 				return;
577 
578 			pool[i]->uid = i + handleOffset;
579 		} else {
580 			type = pool[i]->GetIDType();
581 			Do(p, type);
582 		}
583 		pool[i]->DoState(p);
584 		if (p.error >= p.ERROR_FAILURE)
585 			break;
586 	}
587 }
588 
CreateByIDType(int type)589 KernelObject *KernelObjectPool::CreateByIDType(int type) {
590 	// Used for save states.  This is ugly, but what other way is there?
591 	switch (type) {
592 	case SCE_KERNEL_TMID_Alarm:
593 		return __KernelAlarmObject();
594 	case SCE_KERNEL_TMID_EventFlag:
595 		return __KernelEventFlagObject();
596 	case SCE_KERNEL_TMID_Mbox:
597 		return __KernelMbxObject();
598 	case SCE_KERNEL_TMID_Fpl:
599 		return __KernelMemoryFPLObject();
600 	case SCE_KERNEL_TMID_Vpl:
601 		return __KernelMemoryVPLObject();
602 	case PPSSPP_KERNEL_TMID_PMB:
603 		return __KernelMemoryPMBObject();
604 	case PPSSPP_KERNEL_TMID_Module:
605 		return __KernelModuleObject();
606 	case SCE_KERNEL_TMID_Mpipe:
607 		return __KernelMsgPipeObject();
608 	case SCE_KERNEL_TMID_Mutex:
609 		return __KernelMutexObject();
610 	case SCE_KERNEL_TMID_LwMutex:
611 		return __KernelLwMutexObject();
612 	case SCE_KERNEL_TMID_Semaphore:
613 		return __KernelSemaphoreObject();
614 	case SCE_KERNEL_TMID_Callback:
615 		return __KernelCallbackObject();
616 	case SCE_KERNEL_TMID_Thread:
617 		return __KernelThreadObject();
618 	case SCE_KERNEL_TMID_VTimer:
619 		return __KernelVTimerObject();
620 	case SCE_KERNEL_TMID_Tlspl:
621 	case SCE_KERNEL_TMID_Tlspl_v0:
622 		return __KernelTlsplObject();
623 	case PPSSPP_KERNEL_TMID_File:
624 		return __KernelFileNodeObject();
625 	case PPSSPP_KERNEL_TMID_DirList:
626 		return __KernelDirListingObject();
627 	case SCE_KERNEL_TMID_ThreadEventHandler:
628 		return __KernelThreadEventHandlerObject();
629 
630 	default:
631 		ERROR_LOG(SAVESTATE, "Unable to load state: could not find object type %d.", type);
632 		return NULL;
633 	}
634 }
635 
636 struct SystemStatus {
637 	SceSize_le size;
638 	SceUInt_le status;
639 	SceUInt_le clockPart1;
640 	SceUInt_le clockPart2;
641 	SceUInt_le perfcounter1;
642 	SceUInt_le perfcounter2;
643 	SceUInt_le perfcounter3;
644 };
645 
sceKernelReferSystemStatus(u32 statusPtr)646 static int sceKernelReferSystemStatus(u32 statusPtr) {
647 	DEBUG_LOG(SCEKERNEL, "sceKernelReferSystemStatus(%08x)", statusPtr);
648 	if (Memory::IsValidAddress(statusPtr)) {
649 		SystemStatus status;
650 		memset(&status, 0, sizeof(SystemStatus));
651 		status.size = sizeof(SystemStatus);
652 		// TODO: Fill in the struct!
653 		Memory::WriteStruct(statusPtr, &status);
654 	}
655 	return 0;
656 }
657 
658 struct DebugProfilerRegs {
659 	u32 enable;
660 	u32 systemck;
661 	u32 cpuck;
662 	u32 internal;
663 	u32 memory;
664 	u32 copz;
665 	u32 vfpu;
666 	u32 sleep;
667 	u32 bus_access;
668 	u32 uncached_load;
669 	u32 uncached_store;
670 	u32 cached_load;
671 	u32 cached_store;
672 	u32 i_miss;
673 	u32 d_miss;
674 	u32 d_writeback;
675 	u32 cop0_inst;
676 	u32 fpu_inst;
677 	u32 vfpu_inst;
678 	u32 local_bus;
679 };
680 
sceKernelReferThreadProfiler(u32 statusPtr)681 static u32 sceKernelReferThreadProfiler(u32 statusPtr) {
682 	ERROR_LOG(SCEKERNEL, "FAKE sceKernelReferThreadProfiler()");
683 
684 	// Can we confirm that the struct above is the right struct?
685 	// If so, re-enable this code.
686 	//DebugProfilerRegs regs;
687 	//memset(&regs, 0, sizeof(regs));
688 	// TODO: fill the struct.
689 	//if (Memory::IsValidAddress(statusPtr)) {
690 	//	Memory::WriteStruct(statusPtr, &regs);
691 	//}
692 	return 0;
693 }
694 
sceKernelReferGlobalProfiler(u32 statusPtr)695 static int sceKernelReferGlobalProfiler(u32 statusPtr) {
696 	ERROR_LOG(SCEKERNEL, "UNIMPL sceKernelReferGlobalProfiler(%08x)", statusPtr);
697 	// Ignore for now
698 	return 0;
699 }
700 
701 const HLEFunction ThreadManForUser[] =
702 {
703 	{0X55C20A00, &WrapI_CUUU<sceKernelCreateEventFlag>,              "sceKernelCreateEventFlag",                  'i', "sxxx"    },
704 	{0X812346E4, &WrapU_IU<sceKernelClearEventFlag>,                 "sceKernelClearEventFlag",                   'x', "ix"      },
705 	{0XEF9E4C70, &WrapU_I<sceKernelDeleteEventFlag>,                 "sceKernelDeleteEventFlag",                  'x', "i"       },
706 	{0X1FB15A32, &WrapU_IU<sceKernelSetEventFlag>,                   "sceKernelSetEventFlag",                     'x', "ix"      },
707 	{0X402FCF22, &WrapI_IUUUU<sceKernelWaitEventFlag>,               "sceKernelWaitEventFlag",                    'i', "ixxpp",  HLE_NOT_IN_INTERRUPT },
708 	{0X328C546A, &WrapI_IUUUU<sceKernelWaitEventFlagCB>,             "sceKernelWaitEventFlagCB",                  'i', "ixxpp",  HLE_NOT_IN_INTERRUPT },
709 	{0X30FD48F0, &WrapI_IUUU<sceKernelPollEventFlag>,                "sceKernelPollEventFlag",                    'i', "ixxp"    },
710 	{0XCD203292, &WrapU_IUU<sceKernelCancelEventFlag>,               "sceKernelCancelEventFlag",                  'x', "ixp"     },
711 	{0XA66B0120, &WrapU_IU<sceKernelReferEventFlagStatus>,           "sceKernelReferEventFlagStatus",             'x', "ix"      },
712 
713 	{0X8FFDF9A2, &WrapI_IIU<sceKernelCancelSema>,                    "sceKernelCancelSema",                       'i', "iix"     },
714 	{0XD6DA4BA1, &WrapI_CUIIU<sceKernelCreateSema>,                  "sceKernelCreateSema",                       'i', "sxiix"   },
715 	{0X28B6489C, &WrapI_I<sceKernelDeleteSema>,                      "sceKernelDeleteSema",                       'i', "i"       },
716 	{0X58B1F937, &WrapI_II<sceKernelPollSema>,                       "sceKernelPollSema",                         'i', "ii"      },
717 	{0XBC6FEBC5, &WrapI_IU<sceKernelReferSemaStatus>,                "sceKernelReferSemaStatus",                  'i', "ix"      },
718 	{0X3F53E640, &WrapI_II<sceKernelSignalSema>,                     "sceKernelSignalSema",                       'i', "ii"      },
719 	{0X4E3A1105, &WrapI_IIU<sceKernelWaitSema>,                      "sceKernelWaitSema",                         'i', "iix",    HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
720 	{0X6D212BAC, &WrapI_IIU<sceKernelWaitSemaCB>,                    "sceKernelWaitSemaCB",                       'i', "iix",    HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
721 
722 	{0X60107536, &WrapI_U<sceKernelDeleteLwMutex>,                   "sceKernelDeleteLwMutex",                    'i', "x"       },
723 	{0X19CFF145, &WrapI_UCUIU<sceKernelCreateLwMutex>,               "sceKernelCreateLwMutex",                    'i', "xsxix"   },
724 	{0X4C145944, &WrapI_IU<sceKernelReferLwMutexStatusByID>,         "sceKernelReferLwMutexStatusByID",           'i', "ix"      },
725 	// NOTE: LockLwMutex, UnlockLwMutex, and ReferLwMutexStatus are in Kernel_Library, see sceKernelInterrupt.cpp.
726 	// The below should not be called directly.
727 	//{0x71040D5C, nullptr,                                            "_sceKernelTryLockLwMutex",                  '?', ""        },
728 	//{0x7CFF8CF3, nullptr,                                            "_sceKernelLockLwMutex",                     '?', ""        },
729 	//{0x31327F19, nullptr,                                            "_sceKernelLockLwMutexCB",                   '?', ""        },
730 	//{0xBEED3A47, nullptr,                                            "_sceKernelUnlockLwMutex",                   '?', ""        },
731 
732 	{0XF8170FBE, &WrapI_I<sceKernelDeleteMutex>,                     "sceKernelDeleteMutex",                      'i', "i"       },
733 	{0XB011B11F, &WrapI_IIU<sceKernelLockMutex>,                     "sceKernelLockMutex",                        'i', "iix",    HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
734 	{0X5BF4DD27, &WrapI_IIU<sceKernelLockMutexCB>,                   "sceKernelLockMutexCB",                      'i', "iix",    HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
735 	{0X6B30100F, &WrapI_II<sceKernelUnlockMutex>,                    "sceKernelUnlockMutex",                      'i', "ii"      },
736 	{0XB7D098C6, &WrapI_CUIU<sceKernelCreateMutex>,                  "sceKernelCreateMutex",                      'i', "sxix"    },
737 	{0X0DDCD2C9, &WrapI_II<sceKernelTryLockMutex>,                   "sceKernelTryLockMutex",                     'i', "ii"      },
738 	{0XA9C2CB9A, &WrapI_IU<sceKernelReferMutexStatus>,               "sceKernelReferMutexStatus",                 'i', "ix"      },
739 	{0X87D9223C, &WrapI_IIU<sceKernelCancelMutex>,                   "sceKernelCancelMutex",                      'i', "iix"     },
740 
741 	{0XFCCFAD26, &WrapI_I<sceKernelCancelWakeupThread>,              "sceKernelCancelWakeupThread",               'i', "i"       },
742 	{0X1AF94D03, nullptr,                                            "sceKernelDonateWakeupThread",               '?', ""        },
743 	{0XEA748E31, &WrapI_UU<sceKernelChangeCurrentThreadAttr>,        "sceKernelChangeCurrentThreadAttr",          'i', "xx"      },
744 	{0X71BC9871, &WrapI_II<sceKernelChangeThreadPriority>,           "sceKernelChangeThreadPriority",             'i', "ii"      },
745 	{0X446D8DE6, &WrapI_CUUIUU<sceKernelCreateThread>,               "sceKernelCreateThread",                     'i', "sxxixx", HLE_NOT_IN_INTERRUPT },
746 	{0X9FA03CD3, &WrapI_I<sceKernelDeleteThread>,                    "sceKernelDeleteThread",                     'i', "i"       },
747 	{0XBD123D9E, &WrapI_U<sceKernelDelaySysClockThread>,             "sceKernelDelaySysClockThread",              'i', "P",      HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
748 	{0X1181E963, &WrapI_U<sceKernelDelaySysClockThreadCB>,           "sceKernelDelaySysClockThreadCB",            'i', "P",      HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
749 	{0XCEADEB47, &WrapI_U<sceKernelDelayThread>,                     "sceKernelDelayThread",                      'i', "x",      HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
750 	{0X68DA9E36, &WrapI_U<sceKernelDelayThreadCB>,                   "sceKernelDelayThreadCB",                    'i', "x",      HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
751 	{0XAA73C935, &WrapI_I<sceKernelExitThread>,                      "sceKernelExitThread",                       'i', "i"       },
752 	{0X809CE29B, &WrapI_I<sceKernelExitDeleteThread>,                "sceKernelExitDeleteThread",                 'i', "i"       },
753 	{0x94aa61ee, &WrapI_V<sceKernelGetThreadCurrentPriority>,        "sceKernelGetThreadCurrentPriority",         'i', ""        },
754 	{0X293B45B8, &WrapI_V<sceKernelGetThreadId>,                     "sceKernelGetThreadId",                      'i', "",       HLE_NOT_IN_INTERRUPT },
755 	{0X3B183E26, &WrapI_I<sceKernelGetThreadExitStatus>,             "sceKernelGetThreadExitStatus",              'i', "i"       },
756 	{0X52089CA1, &WrapI_I<sceKernelGetThreadStackFreeSize>,          "sceKernelGetThreadStackFreeSize",           'i', "i"       },
757 	{0XFFC36A14, &WrapU_UU<sceKernelReferThreadRunStatus>,           "sceKernelReferThreadRunStatus",             'x', "xx"      },
758 	{0X17C1684E, &WrapU_UU<sceKernelReferThreadStatus>,              "sceKernelReferThreadStatus",                'i', "xp"      },
759 	{0X2C34E053, &WrapI_I<sceKernelReleaseWaitThread>,               "sceKernelReleaseWaitThread",                'i', "i"       },
760 	{0X75156E8F, &WrapI_I<sceKernelResumeThread>,                    "sceKernelResumeThread",                     'i', "i"       },
761 	{0X3AD58B8C, &WrapU_V<sceKernelSuspendDispatchThread>,           "sceKernelSuspendDispatchThread",            'x', "",       HLE_NOT_IN_INTERRUPT },
762 	{0X27E22EC2, &WrapU_U<sceKernelResumeDispatchThread>,            "sceKernelResumeDispatchThread",             'x', "x",      HLE_NOT_IN_INTERRUPT },
763 	{0X912354A7, &WrapI_I<sceKernelRotateThreadReadyQueue>,          "sceKernelRotateThreadReadyQueue",           'i', "i"       },
764 	{0X9ACE131E, &WrapI_V<sceKernelSleepThread>,                     "sceKernelSleepThread",                      'i', "",       HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
765 	{0X82826F70, &WrapI_V<sceKernelSleepThreadCB>,                   "sceKernelSleepThreadCB",                    'i', "",       HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
766 	{0XF475845D, &WrapI_IIU<sceKernelStartThread>,                   "sceKernelStartThread",                      'i', "iix",    HLE_NOT_IN_INTERRUPT },
767 	{0X9944F31F, &WrapI_I<sceKernelSuspendThread>,                   "sceKernelSuspendThread",                    'i', "i"       },
768 	{0X616403BA, &WrapI_I<sceKernelTerminateThread>,                 "sceKernelTerminateThread",                  'i', "i"       },
769 	{0X383F7BCC, &WrapI_I<sceKernelTerminateDeleteThread>,           "sceKernelTerminateDeleteThread",            'i', "i"       },
770 	{0X840E8133, &WrapI_IU<sceKernelWaitThreadEndCB>,                "sceKernelWaitThreadEndCB",                  'i', "ix"      },
771 	{0XD13BDE95, &WrapI_V<sceKernelCheckThreadStack>,                "sceKernelCheckThreadStack",                 'i', ""        },
772 
773 	{0X94416130, &WrapU_UUUU<sceKernelGetThreadmanIdList>,           "sceKernelGetThreadmanIdList",               'x', "xxxx"    },
774 	{0X57CF62DD, &WrapU_U<sceKernelGetThreadmanIdType>,              "sceKernelGetThreadmanIdType",               'x', "x"       },
775 	{0XBC80EC7C, &WrapU_UUU<sceKernelExtendThreadStack>,             "sceKernelExtendThreadStack",                'x', "xxx"     },
776 	// NOTE: Takes a UID from sceKernelMemory's AllocMemoryBlock and seems thread stack related.
777 	//{0x28BFD974, nullptr,                                           "ThreadManForUser_28BFD974",                  '?', ""        },
778 
779 	{0X82BC5777, &WrapU64_V<sceKernelGetSystemTimeWide>,             "sceKernelGetSystemTimeWide",                'X', ""        },
780 	{0XDB738F35, &WrapI_U<sceKernelGetSystemTime>,                   "sceKernelGetSystemTime",                    'i', "x"       },
781 	{0X369ED59D, &WrapU_V<sceKernelGetSystemTimeLow>,                "sceKernelGetSystemTimeLow",                 'x', ""        },
782 
783 	{0X8218B4DD, &WrapI_U<sceKernelReferGlobalProfiler>,             "sceKernelReferGlobalProfiler",              'i', "x"       },
784 	{0X627E6F3A, &WrapI_U<sceKernelReferSystemStatus>,               "sceKernelReferSystemStatus",                'i', "x"       },
785 	{0X64D4540E, &WrapU_U<sceKernelReferThreadProfiler>,             "sceKernelReferThreadProfiler",              'x', "x"       },
786 
787 	//Fifa Street 2 uses alarms
788 	{0X6652B8CA, &WrapI_UUU<sceKernelSetAlarm>,                      "sceKernelSetAlarm",                         'i', "xxx"     },
789 	{0XB2C25152, &WrapI_UUU<sceKernelSetSysClockAlarm>,              "sceKernelSetSysClockAlarm",                 'i', "xxx"     },
790 	{0X7E65B999, &WrapI_I<sceKernelCancelAlarm>,                     "sceKernelCancelAlarm",                      'i', "i"       },
791 	{0XDAA3F564, &WrapI_IU<sceKernelReferAlarmStatus>,               "sceKernelReferAlarmStatus",                 'i', "ix"      },
792 
793 	{0XBA6B92E2, &WrapI_UUU<sceKernelSysClock2USec>,                 "sceKernelSysClock2USec",                    'i', "xxx"     },
794 	{0X110DEC9A, &WrapI_UU<sceKernelUSec2SysClock>,                  "sceKernelUSec2SysClock",                    'i', "xx"      },
795 	{0XC8CD158C, &WrapU64_U<sceKernelUSec2SysClockWide>,             "sceKernelUSec2SysClockWide",                'X', "x"       },
796 	{0XE1619D7C, &WrapI_UUUU<sceKernelSysClock2USecWide>,            "sceKernelSysClock2USecWide",                'i', "xxxx"    },
797 
798 	{0X278C0DF5, &WrapI_IU<sceKernelWaitThreadEnd>,                  "sceKernelWaitThreadEnd",                    'i', "ix"      },
799 	{0XD59EAD2F, &WrapI_I<sceKernelWakeupThread>,                    "sceKernelWakeupThread",                     'i', "i"       }, //AI Go, audio?
800 
801 	{0x0C106E53, &WrapI_CIUUU<sceKernelRegisterThreadEventHandler>,  "sceKernelRegisterThreadEventHandler",       'i', "sixxx",  },
802 	{0x72F3C145, &WrapI_I<sceKernelReleaseThreadEventHandler>,       "sceKernelReleaseThreadEventHandler",        'i', "i"       },
803 	{0x369EEB6B, &WrapI_IU<sceKernelReferThreadEventHandlerStatus>,  "sceKernelReferThreadEventHandlerStatus",    'i', "ip"      },
804 
805 	{0x349d6d6c, &sceKernelCheckCallback,                            "sceKernelCheckCallback",                    'i', ""        },
806 	{0XE81CAF8F, &WrapI_CUU<sceKernelCreateCallback>,                "sceKernelCreateCallback",                   'i', "sxx"     },
807 	{0XEDBA5844, &WrapI_I<sceKernelDeleteCallback>,                  "sceKernelDeleteCallback",                   'i', "i"       },
808 	{0XC11BA8C4, &WrapI_II<sceKernelNotifyCallback>,                 "sceKernelNotifyCallback",                   'i', "ii"      },
809 	{0XBA4051D6, &WrapI_I<sceKernelCancelCallback>,                  "sceKernelCancelCallback",                   'i', "i"       },
810 	{0X2A3D44FF, &WrapI_I<sceKernelGetCallbackCount>,                "sceKernelGetCallbackCount",                 'i', "i"       },
811 	{0X730ED8BC, &WrapI_IU<sceKernelReferCallbackStatus>,            "sceKernelReferCallbackStatus",              'i', "ip"      },
812 
813 	{0X8125221D, &WrapI_CUU<sceKernelCreateMbx>,                     "sceKernelCreateMbx",                        'i', "sxx"     },
814 	{0X86255ADA, &WrapI_I<sceKernelDeleteMbx>,                       "sceKernelDeleteMbx",                        'i', "i"       },
815 	{0XE9B3061E, &WrapI_IU<sceKernelSendMbx>,                        "sceKernelSendMbx",                          'i', "ix"      },
816 	{0X18260574, &WrapI_IUU<sceKernelReceiveMbx>,                    "sceKernelReceiveMbx",                       'i', "ixx",    HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
817 	{0XF3986382, &WrapI_IUU<sceKernelReceiveMbxCB>,                  "sceKernelReceiveMbxCB",                     'i', "ixx",    HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
818 	{0X0D81716A, &WrapI_IU<sceKernelPollMbx>,                        "sceKernelPollMbx",                          'i', "ix"      },
819 	{0X87D4DD36, &WrapI_IU<sceKernelCancelReceiveMbx>,               "sceKernelCancelReceiveMbx",                 'i', "ix"      },
820 	{0XA8E8C846, &WrapI_IU<sceKernelReferMbxStatus>,                 "sceKernelReferMbxStatus",                   'i', "ix"      },
821 
822 	{0X7C0DC2A0, &WrapI_CIUUU<sceKernelCreateMsgPipe>,               "sceKernelCreateMsgPipe",                    'i', "sixxx"   },
823 	{0XF0B7DA1C, &WrapI_I<sceKernelDeleteMsgPipe>,                   "sceKernelDeleteMsgPipe",                    'i', "i"       },
824 	{0X876DBFAD, &WrapI_IUUUUU<sceKernelSendMsgPipe>,                "sceKernelSendMsgPipe",                      'i', "ixxxxx"  },
825 	{0X7C41F2C2, &WrapI_IUUUUU<sceKernelSendMsgPipeCB>,              "sceKernelSendMsgPipeCB",                    'i', "ixxxxx"  },
826 	{0X884C9F90, &WrapI_IUUUU<sceKernelTrySendMsgPipe>,              "sceKernelTrySendMsgPipe",                   'i', "ixxxx"   },
827 	{0X74829B76, &WrapI_IUUUUU<sceKernelReceiveMsgPipe>,             "sceKernelReceiveMsgPipe",                   'i', "ixxxxx"  },
828 	{0XFBFA697D, &WrapI_IUUUUU<sceKernelReceiveMsgPipeCB>,           "sceKernelReceiveMsgPipeCB",                 'i', "ixxxxx"  },
829 	{0XDF52098F, &WrapI_IUUUU<sceKernelTryReceiveMsgPipe>,           "sceKernelTryReceiveMsgPipe",                'i', "ixxxx"   },
830 	{0X349B864D, &WrapI_IUU<sceKernelCancelMsgPipe>,                 "sceKernelCancelMsgPipe",                    'i', "ixx"     },
831 	{0X33BE4024, &WrapI_IU<sceKernelReferMsgPipeStatus>,             "sceKernelReferMsgPipeStatus",               'i', "ix"      },
832 
833 	{0X56C039B5, &WrapI_CIUUU<sceKernelCreateVpl>,                   "sceKernelCreateVpl",                        'i', "sixxx"   },
834 	{0X89B3D48C, &WrapI_I<sceKernelDeleteVpl>,                       "sceKernelDeleteVpl",                        'i', "i"       },
835 	{0XBED27435, &WrapI_IUUU<sceKernelAllocateVpl>,                  "sceKernelAllocateVpl",                      'i', "ixxx",   HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
836 	{0XEC0A693F, &WrapI_IUUU<sceKernelAllocateVplCB>,                "sceKernelAllocateVplCB",                    'i', "ixxx",   HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
837 	{0XAF36D708, &WrapI_IUU<sceKernelTryAllocateVpl>,                "sceKernelTryAllocateVpl",                   'i', "ixx"     },
838 	{0XB736E9FF, &WrapI_IU<sceKernelFreeVpl>,                        "sceKernelFreeVpl",                          'i', "ix"      },
839 	{0X1D371B8A, &WrapI_IU<sceKernelCancelVpl>,                      "sceKernelCancelVpl",                        'i', "ix"      },
840 	{0X39810265, &WrapI_IU<sceKernelReferVplStatus>,                 "sceKernelReferVplStatus",                   'i', "ix"      },
841 
842 	{0XC07BB470, &WrapI_CUUUUU<sceKernelCreateFpl>,                  "sceKernelCreateFpl",                        'i', "sxxxxx"  },
843 	{0XED1410E0, &WrapI_I<sceKernelDeleteFpl>,                       "sceKernelDeleteFpl",                        'i', "i"       },
844 	{0XD979E9BF, &WrapI_IUU<sceKernelAllocateFpl>,                   "sceKernelAllocateFpl",                      'i', "ixx",    HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
845 	{0XE7282CB6, &WrapI_IUU<sceKernelAllocateFplCB>,                 "sceKernelAllocateFplCB",                    'i', "ixx",    HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
846 	{0X623AE665, &WrapI_IU<sceKernelTryAllocateFpl>,                 "sceKernelTryAllocateFpl",                   'i', "ix"      },
847 	{0XF6414A71, &WrapI_IU<sceKernelFreeFpl>,                        "sceKernelFreeFpl",                          'i', "ix"      },
848 	{0XA8AA591F, &WrapI_IU<sceKernelCancelFpl>,                      "sceKernelCancelFpl",                        'i', "ix"      },
849 	{0XD8199E4C, &WrapI_IU<sceKernelReferFplStatus>,                 "sceKernelReferFplStatus",                   'i', "ix"      },
850 
851 	{0X20FFF560, &WrapU_CU<sceKernelCreateVTimer>,                   "sceKernelCreateVTimer",                     'x', "sx",     HLE_NOT_IN_INTERRUPT },
852 	{0X328F9E52, &WrapU_I<sceKernelDeleteVTimer>,                    "sceKernelDeleteVTimer",                     'x', "i",      HLE_NOT_IN_INTERRUPT },
853 	{0XC68D9437, &WrapU_I<sceKernelStartVTimer>,                     "sceKernelStartVTimer",                      'x', "i"       },
854 	{0XD0AEEE87, &WrapU_I<sceKernelStopVTimer>,                      "sceKernelStopVTimer",                       'x', "i"       },
855 	{0XD2D615EF, &WrapU_I<sceKernelCancelVTimerHandler>,             "sceKernelCancelVTimerHandler",              'x', "i"       },
856 	{0XB3A59970, &WrapU_IU<sceKernelGetVTimerBase>,                  "sceKernelGetVTimerBase",                    'x', "ix"      },
857 	{0XB7C18B77, &WrapU64_I<sceKernelGetVTimerBaseWide>,             "sceKernelGetVTimerBaseWide",                'X', "i"       },
858 	{0X034A921F, &WrapU_IU<sceKernelGetVTimerTime>,                  "sceKernelGetVTimerTime",                    'x', "ix"      },
859 	{0XC0B3FFD2, &WrapU64_I<sceKernelGetVTimerTimeWide>,             "sceKernelGetVTimerTimeWide",                'X', "i"       },
860 	{0X5F32BEAA, &WrapU_IU<sceKernelReferVTimerStatus>,              "sceKernelReferVTimerStatus",                'x', "ix"      },
861 	{0X542AD630, &WrapU_IU<sceKernelSetVTimerTime>,                  "sceKernelSetVTimerTime",                    'x', "ix"      },
862 	{0XFB6425C3, &WrapU64_IU64<sceKernelSetVTimerTimeWide>,          "sceKernelSetVTimerTimeWide",                'X', "iX"      },
863 	{0XD8B299AE, &WrapU_IUUU<sceKernelSetVTimerHandler>,             "sceKernelSetVTimerHandler",                 'x', "ixxx"    },
864 	{0X53B00E9A, &WrapU_IU64UU<sceKernelSetVTimerHandlerWide>,       "sceKernelSetVTimerHandlerWide",             'x', "iXxx"    },
865 
866 	{0X8DAFF657, &WrapI_CUUUUU<sceKernelCreateTlspl>,                "sceKernelCreateTlspl",                      'i', "sxxxxx"  },
867 	{0X32BF938E, &WrapI_I<sceKernelDeleteTlspl>,                     "sceKernelDeleteTlspl",                      'i', "i"       },
868 	{0X721067F3, &WrapI_IU<sceKernelReferTlsplStatus>,               "sceKernelReferTlsplStatus",                 'i', "ix"      },
869 	// Not completely certain about args.
870 	{0X4A719FB2, &WrapI_I<sceKernelFreeTlspl>,                       "sceKernelFreeTlspl",                        'i', "i"       },
871 	// Internal.  Takes (uid, &addr) as parameters... probably.
872 	//{0x65F54FFB, nullptr,                                            "_sceKernelAllocateTlspl",                   'v', ""        },
873 	// NOTE: sceKernelGetTlsAddr is in Kernel_Library, see sceKernelInterrupt.cpp.
874 
875 	// Not sure if these should be hooked up. See below.
876 	{0x0E927AED, &_sceKernelReturnFromTimerHandler,                  "_sceKernelReturnFromTimerHandler",          'v', ""        },
877 	{0X532A522E, &WrapV_I<_sceKernelExitThread>,                     "_sceKernelExitThread",                      'v', "i"       },
878 
879 	// Shouldn't hook this up. No games should import this function manually and call it.
880 	// {0x6E9EA350, _sceKernelReturnFromCallback,"_sceKernelReturnFromCallback"},
881 	{0X71EC4271, &WrapU_UU<sceKernelLibcGettimeofday>,               "sceKernelLibcGettimeofday",               'x', "xx" },
882 	{0X79D1C3FA, &WrapI_V<sceKernelDcacheWritebackAll>,              "sceKernelDcacheWritebackAll",             'i', "" },
883 	{0X91E4F6A7, &WrapU_V<sceKernelLibcClock>,                       "sceKernelLibcClock",                      'x', "" },
884 	{0XB435DEC5, &WrapI_V<sceKernelDcacheWritebackInvalidateAll>,    "sceKernelDcacheWritebackInvalidateAll",   'i', "" },
885 
886 };
887 
888 const HLEFunction ThreadManForKernel[] =
889 {
890 	{0xCEADEB47, &WrapI_U<sceKernelDelayThread>,                     "sceKernelDelayThread",                      'i', "x",      HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED | HLE_KERNEL_SYSCALL },
891 	{0x446D8DE6, &WrapI_CUUIUU<sceKernelCreateThread>,               "sceKernelCreateThread",                     'i', "sxxixx", HLE_NOT_IN_INTERRUPT | HLE_KERNEL_SYSCALL },
892 	{0xF475845D, &WrapI_IIU<sceKernelStartThread>,                   "sceKernelStartThread",                      'i', "iix",    HLE_NOT_IN_INTERRUPT | HLE_KERNEL_SYSCALL },
893 	{0X9FA03CD3, &WrapI_I<sceKernelDeleteThread>,                    "sceKernelDeleteThread",                     'i', "i",      HLE_KERNEL_SYSCALL },
894 	{0XAA73C935, &WrapI_I<sceKernelExitThread>,                      "sceKernelExitThread",                       'i', "i",      HLE_KERNEL_SYSCALL },
895 	{0X809CE29B, &WrapI_I<sceKernelExitDeleteThread>,                "sceKernelExitDeleteThread",                 'i', "i",      HLE_KERNEL_SYSCALL },
896 	{0X9944F31F, &WrapI_I<sceKernelSuspendThread>,                   "sceKernelSuspendThread",                    'i', "i",      HLE_KERNEL_SYSCALL },
897 	{0X75156E8F, &WrapI_I<sceKernelResumeThread>,                    "sceKernelResumeThread",                     'i', "i",      HLE_KERNEL_SYSCALL },
898 	{0X94416130, &WrapU_UUUU<sceKernelGetThreadmanIdList>,           "sceKernelGetThreadmanIdList",               'x', "xxxx",   HLE_KERNEL_SYSCALL },
899 	{0x278c0df5, &WrapI_IU<sceKernelWaitThreadEnd>,                  "sceKernelWaitThreadEnd",                    'i', "ix",     HLE_KERNEL_SYSCALL },
900 	{0xd6da4ba1, &WrapI_CUIIU<sceKernelCreateSema>,                  "sceKernelCreateSema",                       'i', "sxiix",  HLE_KERNEL_SYSCALL },
901 	{0x28b6489c, &WrapI_I<sceKernelDeleteSema>,                      "sceKernelDeleteSema",                       'i', "i",      HLE_KERNEL_SYSCALL },
902 	{0x3f53e640, &WrapI_II<sceKernelSignalSema>,                     "sceKernelSignalSema",                       'i', "ii",     HLE_KERNEL_SYSCALL },
903 	{0x4e3a1105, &WrapI_IIU<sceKernelWaitSema>,                      "sceKernelWaitSema",                         'i', "iix",    HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED | HLE_KERNEL_SYSCALL},
904 	{0x58b1f937, &WrapI_II<sceKernelPollSema>,                       "sceKernelPollSema",                         'i', "ii",     HLE_KERNEL_SYSCALL },
905 	{0x55c20a00, &WrapI_CUUU<sceKernelCreateEventFlag>,              "sceKernelCreateEventFlag",                  'i', "sxxx",   HLE_KERNEL_SYSCALL },
906 	{0xef9e4c70, &WrapU_I<sceKernelDeleteEventFlag>,                 "sceKernelDeleteEventFlag",                  'x', "i",      HLE_KERNEL_SYSCALL },
907 	{0x1fb15a32, &WrapU_IU<sceKernelSetEventFlag>,                   "sceKernelSetEventFlag",                     'x', "ix",     HLE_KERNEL_SYSCALL },
908 	{0x812346e4, &WrapU_IU<sceKernelClearEventFlag>,                 "sceKernelClearEventFlag",                   'x', "ix",     HLE_KERNEL_SYSCALL },
909 	{0x402fcf22, &WrapI_IUUUU<sceKernelWaitEventFlag>,               "sceKernelWaitEventFlag",                    'i', "ixxpp",  HLE_NOT_IN_INTERRUPT | HLE_KERNEL_SYSCALL},
910 	{0xc07bb470, &WrapI_CUUUUU<sceKernelCreateFpl>,                  "sceKernelCreateFpl",                        'i', "sxxxxx" ,HLE_KERNEL_SYSCALL },
911 	{0xed1410e0, &WrapI_I<sceKernelDeleteFpl>,                       "sceKernelDeleteFpl",                        'i', "i"      ,HLE_KERNEL_SYSCALL },
912 	{0x623ae665, &WrapI_IU<sceKernelTryAllocateFpl>,                 "sceKernelTryAllocateFpl",                   'i', "ix"     ,HLE_KERNEL_SYSCALL },
913 	{0x616403ba, &WrapI_I<sceKernelTerminateThread>,                 "sceKernelTerminateThread",                  'i', "i"      ,HLE_KERNEL_SYSCALL },
914 	{0x383f7bcc, &WrapI_I<sceKernelTerminateDeleteThread>,           "sceKernelTerminateDeleteThread",            'i', "i"      ,HLE_KERNEL_SYSCALL },
915 	{0x57cf62dd, &WrapU_U<sceKernelGetThreadmanIdType>,              "sceKernelGetThreadmanIdType",               'x', "x"      ,HLE_KERNEL_SYSCALL },
916 	{0x94aa61ee, &WrapI_V<sceKernelGetThreadCurrentPriority>,        "sceKernelGetThreadCurrentPriority",         'i', "",       HLE_KERNEL_SYSCALL },
917 	{0x293B45B8, &WrapI_V<sceKernelGetThreadId>,                     "sceKernelGetThreadId",                      'i', "",       HLE_KERNEL_SYSCALL | HLE_NOT_IN_INTERRUPT },
918 	{0x3B183E26, &WrapI_I<sceKernelGetThreadExitStatus>,             "sceKernelGetThreadExitStatus",              'i', "i",      HLE_KERNEL_SYSCALL },
919 	{0x82BC5777, &WrapU64_V<sceKernelGetSystemTimeWide>,             "sceKernelGetSystemTimeWide",                'X', "",       HLE_KERNEL_SYSCALL },
920 	{0xDB738F35, &WrapI_U<sceKernelGetSystemTime>,                   "sceKernelGetSystemTime",                    'i', "x",      HLE_KERNEL_SYSCALL },
921 	{0x369ED59D, &WrapU_V<sceKernelGetSystemTimeLow>,                "sceKernelGetSystemTimeLow",                 'x', "",       HLE_KERNEL_SYSCALL },
922 	{0x6652B8CA, &WrapI_UUU<sceKernelSetAlarm>,                      "sceKernelSetAlarm",                         'i', "xxx",    HLE_KERNEL_SYSCALL },
923 	{0xB2C25152, &WrapI_UUU<sceKernelSetSysClockAlarm>,              "sceKernelSetSysClockAlarm",                 'i', "xxx",    HLE_KERNEL_SYSCALL },
924 	{0x7E65B999, &WrapI_I<sceKernelCancelAlarm>,                     "sceKernelCancelAlarm",                      'i', "i",      HLE_KERNEL_SYSCALL },
925 	{0xDAA3F564, &WrapI_IU<sceKernelReferAlarmStatus>,               "sceKernelReferAlarmStatus",                 'i', "ix",     HLE_KERNEL_SYSCALL },
926 	{0x8125221D, &WrapI_CUU<sceKernelCreateMbx>,                     "sceKernelCreateMbx",                        'i', "sxx",    HLE_KERNEL_SYSCALL },
927 	{0x86255ADA, &WrapI_I<sceKernelDeleteMbx>,                       "sceKernelDeleteMbx",                        'i', "i",      HLE_KERNEL_SYSCALL },
928 	{0xE9B3061E, &WrapI_IU<sceKernelSendMbx>,                        "sceKernelSendMbx",                          'i', "ix",     HLE_KERNEL_SYSCALL },
929 	{0x18260574, &WrapI_IUU<sceKernelReceiveMbx>,                    "sceKernelReceiveMbx",                       'i', "ixx",    HLE_KERNEL_SYSCALL | HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
930 	{0xF3986382, &WrapI_IUU<sceKernelReceiveMbxCB>,                  "sceKernelReceiveMbxCB",                     'i', "ixx",    HLE_KERNEL_SYSCALL | HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
931 	{0x0D81716A, &WrapI_IU<sceKernelPollMbx>,                        "sceKernelPollMbx",                          'i', "ix",     HLE_KERNEL_SYSCALL },
932 	{0x87D4DD36, &WrapI_IU<sceKernelCancelReceiveMbx>,               "sceKernelCancelReceiveMbx",                 'i', "ix",     HLE_KERNEL_SYSCALL },
933 	{0xA8E8C846, &WrapI_IU<sceKernelReferMbxStatus>,                 "sceKernelReferMbxStatus",                   'i', "ix",     HLE_KERNEL_SYSCALL },
934 	{0x56C039B5, &WrapI_CIUUU<sceKernelCreateVpl>,                   "sceKernelCreateVpl",                        'i', "sixxx",  HLE_KERNEL_SYSCALL },
935 	{0x89B3D48C, &WrapI_I<sceKernelDeleteVpl>,                       "sceKernelDeleteVpl",                        'i', "i",      HLE_KERNEL_SYSCALL },
936 	{0xBED27435, &WrapI_IUUU<sceKernelAllocateVpl>,                  "sceKernelAllocateVpl",                      'i', "ixxx",   HLE_KERNEL_SYSCALL | HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
937 	{0xEC0A693F, &WrapI_IUUU<sceKernelAllocateVplCB>,                "sceKernelAllocateVplCB",                    'i', "ixxx",   HLE_KERNEL_SYSCALL | HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
938 	{0xAF36D708, &WrapI_IUU<sceKernelTryAllocateVpl>,                "sceKernelTryAllocateVpl",                   'i', "ixx",    HLE_KERNEL_SYSCALL },
939 	{0xB736E9FF, &WrapI_IU<sceKernelFreeVpl>,                        "sceKernelFreeVpl",                          'i', "ix",     HLE_KERNEL_SYSCALL },
940 	{0x1D371B8A, &WrapI_IU<sceKernelCancelVpl>,                      "sceKernelCancelVpl",                        'i', "ix",     HLE_KERNEL_SYSCALL },
941 	{0x39810265, &WrapI_IU<sceKernelReferVplStatus>,                 "sceKernelReferVplStatus",                   'i', "ix",     HLE_KERNEL_SYSCALL },
942 };
943 
Register_ThreadManForUser()944 void Register_ThreadManForUser()
945 {
946 	RegisterModule("ThreadManForUser", ARRAY_SIZE(ThreadManForUser), ThreadManForUser);
947 }
948 
949 
950 const HLEFunction LoadExecForUser[] =
951 {
952 	{0X05572A5F, &WrapV_V<sceKernelExitGame>,                        "sceKernelExitGame",                         'v', ""        },
953 	{0X4AC57943, &WrapI_I<sceKernelRegisterExitCallback>,            "sceKernelRegisterExitCallback",             'i', "i"       },
954 	{0XBD2F1094, &WrapI_CU<sceKernelLoadExec>,                       "sceKernelLoadExec",                         'i', "sx"      },
955 	{0X2AC9954B, &WrapV_V<sceKernelExitGameWithStatus>,              "sceKernelExitGameWithStatus",               'v', ""        },
956 	{0X362A956B, &WrapI_V<LoadExecForUser_362A956B>,                 "LoadExecForUser_362A956B",                  'i', ""        },
957 	{0X8ADA38D3, nullptr,                                            "LoadExecForUser_8ADA38D3",                  '?', ""        },
958 };
959 
Register_LoadExecForUser()960 void Register_LoadExecForUser()
961 {
962 	RegisterModule("LoadExecForUser", ARRAY_SIZE(LoadExecForUser), LoadExecForUser);
963 }
964 
965 const HLEFunction LoadExecForKernel[] =
966 {
967 	{0x4AC57943, &WrapI_I<sceKernelRegisterExitCallback>,            "sceKernelRegisterExitCallback",             'i', "i",      HLE_KERNEL_SYSCALL },
968 	{0XA3D5E142, nullptr,                                            "LoadExecForKernel_a3d5e142",                '?', ""        },
969 	{0X28D0D249, &WrapI_CU<sceKernelLoadExec>,                       "sceKernelLoadExec_28D0D249",                'i', "sx"      },
970 	{0x6D302D3D, &WrapV_V<sceKernelExitGame>,                        "sceKernelExitVSHKernel",                    'v', "x", HLE_KERNEL_SYSCALL },// when called in game mode it will have the same effect that sceKernelExitGame
971 };
972 
Register_LoadExecForKernel()973 void Register_LoadExecForKernel()
974 {
975 	RegisterModule("LoadExecForKernel", ARRAY_SIZE(LoadExecForKernel), LoadExecForKernel);
976 }
977 
978 const HLEFunction ExceptionManagerForKernel[] =
979 {
980 	{0X3FB264FC, nullptr,                                            "sceKernelRegisterExceptionHandler",         '?', ""        },
981 	{0X5A837AD4, nullptr,                                            "sceKernelRegisterPriorityExceptionHandler", '?', ""        },
982 	{0x565C0B0E, &WrapI_V<sceKernelRegisterDefaultExceptionHandler>, "sceKernelRegisterDefaultExceptionHandler",  'i', "",       HLE_KERNEL_SYSCALL },
983 	{0X1AA6CFFA, nullptr,                                            "sceKernelReleaseExceptionHandler",          '?', ""        },
984 	{0XDF83875E, nullptr,                                            "sceKernelGetActiveDefaultExceptionHandler", '?', ""        },
985 	{0X291FF031, nullptr,                                            "sceKernelReleaseDefaultExceptionHandler",   '?', ""        },
986 	{0X15ADC862, nullptr,                                            "sceKernelRegisterNmiHandler",               '?', ""        },
987 	{0XB15357C9, nullptr,                                            "sceKernelReleaseNmiHandler",                '?', ""        },
988 };
989 
Register_ExceptionManagerForKernel()990 void Register_ExceptionManagerForKernel()
991 {
992 	RegisterModule("ExceptionManagerForKernel", ARRAY_SIZE(ExceptionManagerForKernel), ExceptionManagerForKernel);
993 }
994 
995 // Seen in some homebrew
996 const HLEFunction UtilsForKernel[] = {
997 	{0xC2DF770E, WrapI_UI<sceKernelIcacheInvalidateRange>,           "sceKernelIcacheInvalidateRange",            '?', "",       HLE_KERNEL_SYSCALL },
998 	{0X78934841, nullptr,                                            "sceKernelGzipDecompress",                   '?', ""        },
999 	{0XE8DB3CE6, nullptr,                                            "sceKernelDeflateDecompress",                '?', ""        },
1000 	{0X840259F1, nullptr,                                            "sceKernelUtilsSha1Digest",                  '?', ""        },
1001 	{0X9E5C5086, nullptr,                                            "sceKernelUtilsMd5BlockInit",                '?', ""        },
1002 	{0X61E1E525, nullptr,                                            "sceKernelUtilsMd5BlockUpdate",              '?', ""        },
1003 	{0XB8D24E78, nullptr,                                            "sceKernelUtilsMd5BlockResult",              '?', ""        },
1004 	{0XC8186A58, nullptr,                                            "sceKernelUtilsMd5Digest",                   '?', ""        },
1005 	{0X6C6887EE, nullptr,                                            "UtilsForKernel_6C6887EE",                   '?', ""        },
1006 	{0X91E4F6A7, nullptr,                                            "sceKernelLibcClock",                        '?', ""        },
1007 	{0X27CC57F0, nullptr,                                            "sceKernelLibcTime",                         '?', ""        },
1008 	{0X79D1C3FA, nullptr,                                            "sceKernelDcacheWritebackAll",               '?', ""        },
1009 	{0X3EE30821, nullptr,                                            "sceKernelDcacheWritebackRange",             '?', ""        },
1010 	{0X34B9FA9E, nullptr,                                            "sceKernelDcacheWritebackInvalidateRange",   '?', ""        },
1011 	{0XB435DEC5, nullptr,                                            "sceKernelDcacheWritebackInvalidateAll",     '?', ""        },
1012 	{0XBFA98062, nullptr,                                            "sceKernelDcacheInvalidateRange",            '?', ""        },
1013 	{0X920F104A, nullptr,                                            "sceKernelIcacheInvalidateAll",              '?', ""        },
1014 	{0XE860E75E, nullptr,                                            "sceKernelUtilsMt19937Init",                 '?', ""        },
1015 	{0X06FB8A63, nullptr,                                            "sceKernelUtilsMt19937UInt",                 '?', ""        },
1016 };
1017 
1018 
Register_UtilsForKernel()1019 void Register_UtilsForKernel()
1020 {
1021 	RegisterModule("UtilsForKernel", ARRAY_SIZE(UtilsForKernel), UtilsForKernel);
1022 }
1023 
Register_ThreadManForKernel()1024 void Register_ThreadManForKernel()
1025 {
1026 	RegisterModule("ThreadManForKernel", ARRAY_SIZE(ThreadManForKernel), ThreadManForKernel);
1027 }
1028