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(®s, 0, sizeof(regs));
688 // TODO: fill the struct.
689 //if (Memory::IsValidAddress(statusPtr)) {
690 // Memory::WriteStruct(statusPtr, ®s);
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