mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Implement a factory for kernel objects.
Couldn't think of a better way to do this, maybe there's some fancy one I don't know about. Also finished up a couple left over kernel objects. Maybe a quarter the way there?
This commit is contained in:
parent
d9efdf548b
commit
595759ef78
26 changed files with 304 additions and 17 deletions
|
@ -32,6 +32,7 @@
|
|||
#include <deque>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <set>
|
||||
|
||||
#include "Common.h"
|
||||
#include "FileUtil.h"
|
||||
|
@ -147,6 +148,7 @@ public:
|
|||
void Do(std::list<T> &x, T &default_val)
|
||||
{
|
||||
u32 list_size = (u32)x.size();
|
||||
Do(list_size);
|
||||
x.resize(list_size, default_val);
|
||||
|
||||
typename std::list<T>::iterator itr, end;
|
||||
|
@ -154,6 +156,41 @@ public:
|
|||
Do(*itr);
|
||||
}
|
||||
|
||||
// Store STL sets.
|
||||
template <class T>
|
||||
void Do(std::set<T> &x)
|
||||
{
|
||||
unsigned int number = (unsigned int)x.size();
|
||||
Do(number);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case MODE_READ:
|
||||
{
|
||||
x.clear();
|
||||
while (number-- > 0)
|
||||
{
|
||||
T it;
|
||||
Do(it);
|
||||
x.insert(it);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MODE_WRITE:
|
||||
case MODE_MEASURE:
|
||||
case MODE_VERIFY:
|
||||
{
|
||||
typename std::set<T>::iterator itr = x.begin();
|
||||
while (number-- > 0)
|
||||
Do(*itr++);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR_LOG(COMMON, "Savestate error: invalid mode %d.", mode);
|
||||
}
|
||||
}
|
||||
|
||||
// Store strings.
|
||||
void Do(std::string &x)
|
||||
{
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../Globals.h"
|
||||
#include "../../Common/ChunkFile.h"
|
||||
#include <string>
|
||||
|
||||
enum FileAccess
|
||||
|
@ -56,6 +57,20 @@ struct PSPFileInfo
|
|||
PSPFileInfo()
|
||||
: size(0), access(0), exists(false), type(FILETYPE_NORMAL), isOnSectorSystem(false), startSector(0), numSectors(0) {}
|
||||
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(name);
|
||||
p.Do(size);
|
||||
p.Do(access);
|
||||
p.Do(exists);
|
||||
p.Do(type);
|
||||
p.Do(mtime);
|
||||
p.Do(isOnSectorSystem);
|
||||
p.Do(startSector);
|
||||
p.Do(numSectors);
|
||||
p.DoMarker("PSPFileInfo");
|
||||
}
|
||||
|
||||
std::string name;
|
||||
s64 size;
|
||||
u32 access; //unix 777
|
||||
|
|
|
@ -137,7 +137,18 @@ public:
|
|||
sprintf(ptr, "Seekpos: %08x", (u32)pspFileSystem.GetSeekPos(handle));
|
||||
}
|
||||
static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_BADF; }
|
||||
int GetIDType() const { return 0; }
|
||||
int GetIDType() const { return PPSSPP_KERNEL_TMID_File; }
|
||||
|
||||
virtual void DoState(PointerWrap &p) {
|
||||
p.Do(fullpath);
|
||||
p.Do(handle);
|
||||
p.Do(callbackID);
|
||||
p.Do(callbackArg);
|
||||
p.Do(asyncResult);
|
||||
p.Do(pendingAsyncResult);
|
||||
p.Do(sectorBlockMode);
|
||||
p.DoMarker("File");
|
||||
}
|
||||
|
||||
std::string fullpath;
|
||||
u32 handle;
|
||||
|
@ -836,7 +847,18 @@ public:
|
|||
const char *GetName() {return name.c_str();}
|
||||
const char *GetTypeName() {return "DirListing";}
|
||||
static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_BADF; }
|
||||
int GetIDType() const { return 0; }
|
||||
int GetIDType() const { return PPSSPP_KERNEL_TMID_DirList; }
|
||||
|
||||
virtual void DoState(PointerWrap &p) {
|
||||
p.Do(name);
|
||||
|
||||
// TODO: Is this the right way for it to wake up?
|
||||
size_t count = listing.size();
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
listing[i].DoState(p);
|
||||
}
|
||||
p.DoMarker("DirListing");
|
||||
}
|
||||
|
||||
std::string name;
|
||||
std::vector<PSPFileInfo> listing;
|
||||
|
@ -920,6 +942,14 @@ u32 sceIoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 ou
|
|||
return 0;
|
||||
}
|
||||
|
||||
KernelObject *__KernelFileNodeObject() {
|
||||
return new FileNode;
|
||||
}
|
||||
|
||||
KernelObject *__KernelDirListingObject() {
|
||||
return new DirListing;
|
||||
}
|
||||
|
||||
const HLEFunction IoFileMgrForUser[] = {
|
||||
{ 0xb29ddf9c, &WrapU_C<sceIoDopen>, "sceIoDopen" },
|
||||
{ 0xe3eb004c, &WrapU_IU<sceIoDread>, "sceIoDread" },
|
||||
|
|
|
@ -19,9 +19,12 @@
|
|||
|
||||
#include <string>
|
||||
#include "HLE.h"
|
||||
#include "sceKernel.h"
|
||||
|
||||
void __IoInit();
|
||||
void __IoShutdown();
|
||||
KernelObject *__KernelFileNodeObject();
|
||||
KernelObject *__KernelDirListingObject();
|
||||
|
||||
void Register_IoFileMgrForUser();
|
||||
void Register_StdioForUser();
|
||||
|
|
|
@ -320,25 +320,76 @@ void KernelObjectPool::DoState(PointerWrap &p)
|
|||
{
|
||||
int _maxCount = maxCount;
|
||||
p.Do(_maxCount);
|
||||
|
||||
if (_maxCount != maxCount)
|
||||
ERROR_LOG(HLE, "Unable to load state: different kernel object storage.");
|
||||
|
||||
// Assumption: on load, we've already cleared.
|
||||
p.DoArray(occupied, maxCount);
|
||||
for (int i = 0; i < maxCount; ++i)
|
||||
{
|
||||
if (!occupied[i])
|
||||
continue;
|
||||
|
||||
KernelObject *t = pool[i];
|
||||
if (!t)
|
||||
int type;
|
||||
if (p.mode == p.MODE_READ)
|
||||
{
|
||||
// TODO: Pass down error?
|
||||
ERROR_LOG(HLE, "Unable to save state: inconsistent kernel object pool.");
|
||||
return;
|
||||
p.Do(type);
|
||||
pool[i] = CreateByIDType(type);
|
||||
}
|
||||
|
||||
t->DoState(p);
|
||||
else
|
||||
{
|
||||
type = pool[i]->GetIDType();
|
||||
p.Do(type);
|
||||
}
|
||||
pool[i]->DoState(p);
|
||||
}
|
||||
p.DoMarker("KernelObjectPool");
|
||||
}
|
||||
|
||||
KernelObject *KernelObjectPool::CreateByIDType(int type)
|
||||
{
|
||||
// Used for save states. This is ugly, but what other way is there?
|
||||
switch (type)
|
||||
{
|
||||
case SCE_KERNEL_TMID_Alarm:
|
||||
return __KernelAlarmObject();
|
||||
case SCE_KERNEL_TMID_EventFlag:
|
||||
return __KernelEventFlagObject();
|
||||
case SCE_KERNEL_TMID_Mbox:
|
||||
return __KernelMbxObject();
|
||||
case SCE_KERNEL_TMID_Fpl:
|
||||
return __KernelMemoryFPLObject();
|
||||
case SCE_KERNEL_TMID_Vpl:
|
||||
return __KernelMemoryVPLObject();
|
||||
case PPSSPP_KERNEL_TMID_PMB:
|
||||
return __KernelMemoryPMBObject();
|
||||
case PPSSPP_KERNEL_TMID_Module:
|
||||
return __KernelModuleObject();
|
||||
case SCE_KERNEL_TMID_Mpipe:
|
||||
return __KernelMsgPipeObject();
|
||||
case SCE_KERNEL_TMID_Mutex:
|
||||
return __KernelMutexObject();
|
||||
case SCE_KERNEL_TMID_LwMutex:
|
||||
return __KernelLwMutexObject();
|
||||
case SCE_KERNEL_TMID_Semaphore:
|
||||
return __KernelSemaphoreObject();
|
||||
case SCE_KERNEL_TMID_Callback:
|
||||
return __KernelCallbackObject();
|
||||
case SCE_KERNEL_TMID_Thread:
|
||||
return __KernelThreadObject();
|
||||
case SCE_KERNEL_TMID_VTimer:
|
||||
return __KernelVTimerObject();
|
||||
case PPSSPP_KERNEL_TMID_File:
|
||||
return __KernelFileNodeObject();
|
||||
case PPSSPP_KERNEL_TMID_DirList:
|
||||
return __KernelDirListingObject();
|
||||
|
||||
default:
|
||||
ERROR_LOG(COMMON, "Unable to load state: could not find object type %d.", type);
|
||||
}
|
||||
}
|
||||
|
||||
void sceKernelIcacheInvalidateAll()
|
||||
{
|
||||
DEBUG_LOG(CPU, "Icache invalidated - should clear JIT someday");
|
||||
|
|
|
@ -224,6 +224,7 @@ enum
|
|||
SCE_KERNEL_ERROR_ERRORMAX = 0x8002044d,
|
||||
};
|
||||
|
||||
// If you add to this, make sure to check KernelObjectPool::CreateByIDType().
|
||||
enum TMIDPurpose
|
||||
{
|
||||
SCE_KERNEL_TMID_Thread = 1,
|
||||
|
@ -243,6 +244,12 @@ enum TMIDPurpose
|
|||
SCE_KERNEL_TMID_DelayThread = 65,
|
||||
SCE_KERNEL_TMID_SuspendThread = 66,
|
||||
SCE_KERNEL_TMID_DormantThread = 67,
|
||||
|
||||
// Not official, but need ids for save states.
|
||||
PPSSPP_KERNEL_TMID_Module = 0x100001,
|
||||
PPSSPP_KERNEL_TMID_PMB = 0x100002,
|
||||
PPSSPP_KERNEL_TMID_File = 0x100003,
|
||||
PPSSPP_KERNEL_TMID_DirList = 0x100004,
|
||||
};
|
||||
|
||||
typedef int SceUID;
|
||||
|
@ -329,6 +336,7 @@ public:
|
|||
SceUID Create(KernelObject *obj, int rangeBottom = 16, int rangeTop = 0x7fffffff);
|
||||
|
||||
void DoState(PointerWrap &p);
|
||||
static KernelObject *CreateByIDType(int type);
|
||||
|
||||
template <class T>
|
||||
u32 Destroy(SceUID handle)
|
||||
|
|
|
@ -111,6 +111,12 @@ void __KernelAlarmInit()
|
|||
alarmTimer = CoreTiming::RegisterEvent("Alarm", __KernelTriggerAlarm);
|
||||
}
|
||||
|
||||
KernelObject *__KernelAlarmObject()
|
||||
{
|
||||
// Default object to load from state.
|
||||
return new Alarm;
|
||||
}
|
||||
|
||||
void __KernelScheduleAlarm(Alarm *alarm, u64 ticks)
|
||||
{
|
||||
alarm->alm.schedule = (CoreTiming::GetTicks() + ticks) / (u64) CoreTiming::GetClockFrequencyMHz();
|
||||
|
|
|
@ -23,3 +23,4 @@ int sceKernelCancelAlarm(SceUID uid);
|
|||
int sceKernelReferAlarmStatus(SceUID uid, u32 infoPtr);
|
||||
|
||||
void __KernelAlarmInit();
|
||||
KernelObject *__KernelAlarmObject();
|
||||
|
|
|
@ -104,6 +104,12 @@ void __KernelEventFlagInit()
|
|||
eventFlagWaitTimer = CoreTiming::RegisterEvent("EventFlagTimeout", &__KernelEventFlagTimeout);
|
||||
}
|
||||
|
||||
KernelObject *__KernelEventFlagObject()
|
||||
{
|
||||
// Default object to load from state.
|
||||
return new EventFlag;
|
||||
}
|
||||
|
||||
bool __KernelEventFlagMatches(u32 *pattern, u32 bits, u8 wait, u32 outAddr)
|
||||
{
|
||||
if ((wait & PSP_EVENT_WAITOR)
|
||||
|
|
|
@ -28,3 +28,4 @@ u32 sceKernelReferEventFlagStatus(SceUID id, u32 statusPtr);
|
|||
u32 sceKernelCancelEventFlag(SceUID uid, u32 pattern, u32 numWaitThreadsPtr);
|
||||
|
||||
void __KernelEventFlagInit();
|
||||
KernelObject *__KernelEventFlagObject();
|
||||
|
|
|
@ -170,6 +170,11 @@ void __KernelMbxInit()
|
|||
mbxWaitTimer = CoreTiming::RegisterEvent("MbxTimeout", &__KernelMbxTimeout);
|
||||
}
|
||||
|
||||
KernelObject *__KernelMbxObject()
|
||||
{
|
||||
return new Mbx;
|
||||
}
|
||||
|
||||
bool __KernelUnlockMbxForThread(Mbx *m, MbxWaitingThread &th, u32 &error, int result, bool &wokeThreads)
|
||||
{
|
||||
SceUID waitID = __KernelGetWaitID(th.first, WAITTYPE_MBX, error);
|
||||
|
|
|
@ -34,3 +34,4 @@ int sceKernelCancelReceiveMbx(SceUID id, u32 numWaitingThreadsAddr);
|
|||
int sceKernelReferMbxStatus(SceUID id, u32 infoAddr);
|
||||
|
||||
void __KernelMbxInit();
|
||||
KernelObject *__KernelMbxObject();
|
||||
|
|
|
@ -53,7 +53,7 @@ struct NativeFPL
|
|||
};
|
||||
|
||||
//FPL - Fixed Length Dynamic Memory Pool - every item has the same length
|
||||
struct FPL : KernelObject
|
||||
struct FPL : public KernelObject
|
||||
{
|
||||
const char *GetName() {return nf.name;}
|
||||
const char *GetTypeName() {return "FPL";}
|
||||
|
@ -106,7 +106,7 @@ struct SceKernelVplInfo
|
|||
int numWaitThreads;
|
||||
};
|
||||
|
||||
struct VPL : KernelObject
|
||||
struct VPL : public KernelObject
|
||||
{
|
||||
const char *GetName() {return nv.name;}
|
||||
const char *GetTypeName() {return "VPL";}
|
||||
|
@ -368,13 +368,18 @@ public:
|
|||
sprintf(ptr, "MemPart: %08x - %08x size: %08x", address, address + sz, sz);
|
||||
}
|
||||
static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_MPPID; } /// ????
|
||||
int GetIDType() const { return 0; }
|
||||
int GetIDType() const { return PPSSPP_KERNEL_TMID_PMB; }
|
||||
|
||||
PartitionMemoryBlock(BlockAllocator *_alloc, u32 size, bool fromEnd)
|
||||
{
|
||||
alloc = _alloc;
|
||||
address = alloc->Alloc(size, fromEnd, "PMB");
|
||||
alloc->ListBlocks();
|
||||
|
||||
// 0 is used for save states to wake up.
|
||||
if (size != 0)
|
||||
{
|
||||
address = alloc->Alloc(size, fromEnd, "PMB");
|
||||
alloc->ListBlocks();
|
||||
}
|
||||
}
|
||||
~PartitionMemoryBlock()
|
||||
{
|
||||
|
@ -620,6 +625,22 @@ void sceKernelSetCompilerVersion(int version)
|
|||
flags_ |= SCE_KERNEL_HASCOMPILERVERSION;
|
||||
}
|
||||
|
||||
KernelObject *__KernelMemoryFPLObject()
|
||||
{
|
||||
return new FPL;
|
||||
}
|
||||
|
||||
KernelObject *__KernelMemoryVPLObject()
|
||||
{
|
||||
return new VPL;
|
||||
}
|
||||
|
||||
KernelObject *__KernelMemoryPMBObject()
|
||||
{
|
||||
// TODO: We could theoretically handle kernelMemory too, but we don't support that now anyway.
|
||||
return new PartitionMemoryBlock(&userMemory, 0, true);
|
||||
}
|
||||
|
||||
// VPL = variable length memory pool
|
||||
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Util/BlockAllocator.h"
|
||||
#include "sceKernel.h"
|
||||
|
||||
|
||||
//todo: "real" memory block allocator,
|
||||
|
@ -30,6 +31,9 @@ extern BlockAllocator kernelMemory;
|
|||
|
||||
void __KernelMemoryInit();
|
||||
void __KernelMemoryShutdown();
|
||||
KernelObject *__KernelMemoryFPLObject();
|
||||
KernelObject *__KernelMemoryVPLObject();
|
||||
KernelObject *__KernelMemoryPMBObject();
|
||||
|
||||
void sceKernelCreateVpl();
|
||||
void sceKernelDeleteVpl();
|
||||
|
|
|
@ -117,13 +117,25 @@ public:
|
|||
nm.entry_addr);
|
||||
}
|
||||
static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_MODULE; }
|
||||
int GetIDType() const { return 0; }
|
||||
int GetIDType() const { return PPSSPP_KERNEL_TMID_Module; }
|
||||
|
||||
virtual void DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(nm);
|
||||
p.Do(memoryBlockAddr);
|
||||
p.DoMarker("Module");
|
||||
}
|
||||
|
||||
NativeModule nm;
|
||||
|
||||
u32 memoryBlockAddr;
|
||||
};
|
||||
|
||||
KernelObject *__KernelModuleObject()
|
||||
{
|
||||
return new Module;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MODULES
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -642,7 +654,7 @@ u32 sceKernelLoadModule(const char *name, u32 flags)
|
|||
class AfterModuleEntryCall : public Action {
|
||||
public:
|
||||
AfterModuleEntryCall() {}
|
||||
Module *module_;
|
||||
SceUID moduleID_;
|
||||
u32 retValAddr;
|
||||
virtual void run();
|
||||
};
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include "sceKernel.h"
|
||||
#include "HLE.h"
|
||||
|
||||
KernelObject *__KernelModuleObject();
|
||||
|
||||
u32 __KernelGetModuleGP(SceUID module);
|
||||
bool __KernelLoadExec(const char *filename, SceKernelLoadExecParam *param, std::string *error_string);
|
||||
|
||||
|
|
|
@ -162,6 +162,11 @@ struct MsgPipe : public KernelObject
|
|||
u8 *buffer;
|
||||
};
|
||||
|
||||
KernelObject *__KernelMsgPipeObject()
|
||||
{
|
||||
return new MsgPipe;
|
||||
}
|
||||
|
||||
void sceKernelCreateMsgPipe()
|
||||
{
|
||||
const char *name = Memory::GetCharPointer(PARAM(0));
|
||||
|
|
|
@ -26,4 +26,6 @@ void sceKernelReceiveMsgPipe();
|
|||
void sceKernelReceiveMsgPipeCB();
|
||||
void sceKernelTryReceiveMsgPipe();
|
||||
void sceKernelCancelMsgPipe();
|
||||
void sceKernelReferMsgPipeStatus();
|
||||
void sceKernelReferMsgPipeStatus();
|
||||
|
||||
KernelObject *__KernelMsgPipeObject();
|
||||
|
|
|
@ -137,6 +137,16 @@ void __KernelMutexInit()
|
|||
__KernelListenThreadEnd(&__KernelMutexThreadEnd);
|
||||
}
|
||||
|
||||
KernelObject *__KernelMutexObject()
|
||||
{
|
||||
return new Mutex;
|
||||
}
|
||||
|
||||
KernelObject *__KernelLwMutexObject()
|
||||
{
|
||||
return new LwMutex;
|
||||
}
|
||||
|
||||
void __KernelMutexShutdown()
|
||||
{
|
||||
mutexHeldLocks.clear();
|
||||
|
|
|
@ -38,3 +38,5 @@ void __KernelMutexThreadEnd(SceUID thread);
|
|||
|
||||
void __KernelMutexInit();
|
||||
void __KernelMutexShutdown();
|
||||
KernelObject *__KernelMutexObject();
|
||||
KernelObject *__KernelLwMutexObject();
|
||||
|
|
|
@ -75,6 +75,11 @@ void __KernelSemaInit()
|
|||
semaWaitTimer = CoreTiming::RegisterEvent("SemaphoreTimeout", &__KernelSemaTimeout);
|
||||
}
|
||||
|
||||
KernelObject *__KernelSemaphoreObject()
|
||||
{
|
||||
return new Semaphore;
|
||||
}
|
||||
|
||||
// Returns whether the thread should be removed.
|
||||
bool __KernelUnlockSemaForThread(Semaphore *s, SceUID threadID, u32 &error, int result, bool &wokeThreads)
|
||||
{
|
||||
|
|
|
@ -29,3 +29,4 @@ int sceKernelWaitSemaCB(SceUID semaid, int signal, u32 timeoutPtr);
|
|||
void __KernelSemaTimeout(u64 userdata, int cycleslate);
|
||||
|
||||
void __KernelSemaInit();
|
||||
KernelObject *__KernelSemaphoreObject();
|
||||
|
|
|
@ -113,6 +113,18 @@ public:
|
|||
static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_CBID; }
|
||||
int GetIDType() const { return SCE_KERNEL_TMID_Callback; }
|
||||
|
||||
virtual void DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(nc);
|
||||
p.Do(savedPC);
|
||||
p.Do(savedRA);
|
||||
p.Do(savedV0);
|
||||
p.Do(savedV1);
|
||||
p.Do(savedIdRegister);
|
||||
p.Do(forceDelete);
|
||||
p.DoMarker("Callback");
|
||||
}
|
||||
|
||||
NativeCallback nc;
|
||||
|
||||
u32 savedPC;
|
||||
|
@ -297,6 +309,34 @@ public:
|
|||
bool isWaiting() const { return (nt.status & THREADSTATUS_WAIT) != 0; }
|
||||
bool isSuspended() const { return (nt.status & THREADSTATUS_SUSPEND) != 0; }
|
||||
|
||||
virtual void DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(nt);
|
||||
p.Do(waitInfo);
|
||||
p.Do(sleeping);
|
||||
p.Do(moduleId);
|
||||
p.Do(isProcessingCallbacks);
|
||||
p.Do(currentCallbackId);
|
||||
p.Do(context);
|
||||
|
||||
u32 numCallbacks = THREAD_CALLBACK_NUM_TYPES;
|
||||
p.Do(numCallbacks);
|
||||
if (numCallbacks != THREAD_CALLBACK_NUM_TYPES)
|
||||
ERROR_LOG(HLE, "Unable to load state: different kernel object storage.");
|
||||
|
||||
for (size_t i = 0; i < THREAD_CALLBACK_NUM_TYPES; ++i)
|
||||
{
|
||||
std::set<SceUID>::iterator it, end;
|
||||
p.Do(registeredCallbacks[i]);
|
||||
p.Do(readyCallbacks[i]);
|
||||
}
|
||||
|
||||
p.Do(pendingMipsCalls);
|
||||
p.Do(stackBlock);
|
||||
|
||||
p.DoMarker("Thread");
|
||||
}
|
||||
|
||||
NativeThread nt;
|
||||
|
||||
ThreadWaitInfo waitInfo;
|
||||
|
@ -409,6 +449,16 @@ void __KernelThreadingInit()
|
|||
__KernelListenThreadEnd(__KernelCancelWakeup);
|
||||
}
|
||||
|
||||
KernelObject *__KernelThreadObject()
|
||||
{
|
||||
return new Thread;
|
||||
}
|
||||
|
||||
KernelObject *__KernelCallbackObject()
|
||||
{
|
||||
return new Callback;
|
||||
}
|
||||
|
||||
void __KernelListenThreadEnd(ThreadCallback callback)
|
||||
{
|
||||
threadEndListeners.push_back(callback);
|
||||
|
|
|
@ -98,6 +98,8 @@ struct ThreadContext
|
|||
|
||||
void __KernelThreadingInit();
|
||||
void __KernelThreadingShutdown();
|
||||
KernelObject *__KernelThreadObject();
|
||||
KernelObject *__KernelCallbackObject();
|
||||
|
||||
void __KernelScheduleWakeup(int usFromNow, int threadnumber);
|
||||
SceUID __KernelGetCurThread();
|
||||
|
|
|
@ -51,6 +51,11 @@ struct VTimer : public KernelObject
|
|||
u32 argument;
|
||||
};
|
||||
|
||||
KernelObject *__KernelVTimerObject()
|
||||
{
|
||||
return new VTimer;
|
||||
}
|
||||
|
||||
void sceKernelCreateVTimer()
|
||||
{
|
||||
DEBUG_LOG(HLE,"sceKernelCreateVTimer");
|
||||
|
|
|
@ -23,3 +23,5 @@ void sceKernelSetVTimerHandler();
|
|||
|
||||
// TODO
|
||||
void _sceKernelReturnFromTimerHandler();
|
||||
|
||||
KernelObject *__KernelVTimerObject();
|
||||
|
|
Loading…
Add table
Reference in a new issue