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:
Unknown W. Brackets 2012-12-26 22:45:19 -08:00
parent d9efdf548b
commit 595759ef78
26 changed files with 304 additions and 17 deletions

View file

@ -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)
{

View file

@ -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

View file

@ -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" },

View file

@ -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();

View file

@ -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");

View file

@ -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)

View file

@ -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();

View file

@ -23,3 +23,4 @@ int sceKernelCancelAlarm(SceUID uid);
int sceKernelReferAlarmStatus(SceUID uid, u32 infoPtr);
void __KernelAlarmInit();
KernelObject *__KernelAlarmObject();

View file

@ -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)

View file

@ -28,3 +28,4 @@ u32 sceKernelReferEventFlagStatus(SceUID id, u32 statusPtr);
u32 sceKernelCancelEventFlag(SceUID uid, u32 pattern, u32 numWaitThreadsPtr);
void __KernelEventFlagInit();
KernelObject *__KernelEventFlagObject();

View file

@ -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);

View file

@ -34,3 +34,4 @@ int sceKernelCancelReceiveMbx(SceUID id, u32 numWaitingThreadsAddr);
int sceKernelReferMbxStatus(SceUID id, u32 infoAddr);
void __KernelMbxInit();
KernelObject *__KernelMbxObject();

View file

@ -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

View file

@ -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();

View file

@ -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();
};

View file

@ -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);

View file

@ -162,6 +162,11 @@ struct MsgPipe : public KernelObject
u8 *buffer;
};
KernelObject *__KernelMsgPipeObject()
{
return new MsgPipe;
}
void sceKernelCreateMsgPipe()
{
const char *name = Memory::GetCharPointer(PARAM(0));

View file

@ -26,4 +26,6 @@ void sceKernelReceiveMsgPipe();
void sceKernelReceiveMsgPipeCB();
void sceKernelTryReceiveMsgPipe();
void sceKernelCancelMsgPipe();
void sceKernelReferMsgPipeStatus();
void sceKernelReferMsgPipeStatus();
KernelObject *__KernelMsgPipeObject();

View file

@ -137,6 +137,16 @@ void __KernelMutexInit()
__KernelListenThreadEnd(&__KernelMutexThreadEnd);
}
KernelObject *__KernelMutexObject()
{
return new Mutex;
}
KernelObject *__KernelLwMutexObject()
{
return new LwMutex;
}
void __KernelMutexShutdown()
{
mutexHeldLocks.clear();

View file

@ -38,3 +38,5 @@ void __KernelMutexThreadEnd(SceUID thread);
void __KernelMutexInit();
void __KernelMutexShutdown();
KernelObject *__KernelMutexObject();
KernelObject *__KernelLwMutexObject();

View file

@ -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)
{

View file

@ -29,3 +29,4 @@ int sceKernelWaitSemaCB(SceUID semaid, int signal, u32 timeoutPtr);
void __KernelSemaTimeout(u64 userdata, int cycleslate);
void __KernelSemaInit();
KernelObject *__KernelSemaphoreObject();

View file

@ -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);

View file

@ -98,6 +98,8 @@ struct ThreadContext
void __KernelThreadingInit();
void __KernelThreadingShutdown();
KernelObject *__KernelThreadObject();
KernelObject *__KernelCallbackObject();
void __KernelScheduleWakeup(int usFromNow, int threadnumber);
SceUID __KernelGetCurThread();

View file

@ -51,6 +51,11 @@ struct VTimer : public KernelObject
u32 argument;
};
KernelObject *__KernelVTimerObject()
{
return new VTimer;
}
void sceKernelCreateVTimer()
{
DEBUG_LOG(HLE,"sceKernelCreateVTimer");

View file

@ -23,3 +23,5 @@ void sceKernelSetVTimerHandler();
// TODO
void _sceKernelReturnFromTimerHandler();
KernelObject *__KernelVTimerObject();