Clear some state between runs. Tabs fixing.

This commit is contained in:
Henrik Rydgård 2012-12-23 11:16:32 +01:00
parent ce214b3943
commit 862a11e7be
2 changed files with 224 additions and 221 deletions

View file

@ -63,12 +63,12 @@ static bool framebufIsLatched;
static int enterVblankEvent = -1;
static int leaveVblankEvent = -1;
static int hCount = 0;
static int hCountTotal = 0; //unused
static int vCount = 0;
static int isVblank = 0;
static bool hasSetMode = false;
double lastFrameTime = 0;
static int hCount;
static int hCountTotal; //unused
static int vCount;
static int isVblank;
static bool hasSetMode;
double lastFrameTime;
// STATE END
@ -110,12 +110,18 @@ void __DisplayInit()
CoreTiming::ScheduleEvent(msToCycles(frameMs - vblankMs), enterVblankEvent, 0);
isVblank = 0;
vCount = 0;
hCount = 0;
hCountTotal = 0;
hasSetMode = false;
lastFrameTime = 0;
InitGfxState();
}
void __DisplayShutdown()
{
vblankListeners.clear();
vblankWaitingThreads.clear();
ShutdownGfxState();
}

View file

@ -37,43 +37,42 @@
enum {
ERROR_KERNEL_THREAD_ALREADY_DORMANT = 0x800201a2,
ERROR_KERNEL_THREAD_ALREADY_SUSPEND = 0x800201a3,
ERROR_KERNEL_THREAD_IS_NOT_DORMANT = 0x800201a4,
ERROR_KERNEL_THREAD_IS_NOT_SUSPEND = 0x800201a5,
ERROR_KERNEL_THREAD_IS_NOT_WAIT = 0x800201a6,
ERROR_KERNEL_THREAD_ALREADY_DORMANT = 0x800201a2,
ERROR_KERNEL_THREAD_ALREADY_SUSPEND = 0x800201a3,
ERROR_KERNEL_THREAD_IS_NOT_DORMANT = 0x800201a4,
ERROR_KERNEL_THREAD_IS_NOT_SUSPEND = 0x800201a5,
ERROR_KERNEL_THREAD_IS_NOT_WAIT = 0x800201a6,
};
enum
{
PSP_THREAD_ATTR_USER = 0x80000000,
PSP_THREAD_ATTR_USBWLAN = 0xa0000000,
PSP_THREAD_ATTR_VSH = 0xc0000000,
PSP_THREAD_ATTR_KERNEL = 0x00001000,
PSP_THREAD_ATTR_VFPU = 0x00004000, // TODO: Should not bother saving VFPU context except when switching between two thread that has this attribute
PSP_THREAD_ATTR_SCRATCH_SRAM = 0x00008000, // Save/restore scratch as part of context???
PSP_THREAD_ATTR_NO_FILLSTACK = 0x00100000, // TODO: No filling of 0xff
PSP_THREAD_ATTR_CLEAR_STACK = 0x00200000, // TODO: Clear thread stack when deleted
PSP_THREAD_ATTR_USER = 0x80000000,
PSP_THREAD_ATTR_USBWLAN = 0xa0000000,
PSP_THREAD_ATTR_VSH = 0xc0000000,
PSP_THREAD_ATTR_KERNEL = 0x00001000,
PSP_THREAD_ATTR_VFPU = 0x00004000, // TODO: Should not bother saving VFPU context except when switching between two thread that has this attribute
PSP_THREAD_ATTR_SCRATCH_SRAM = 0x00008000, // Save/restore scratch as part of context???
PSP_THREAD_ATTR_NO_FILLSTACK = 0x00100000, // TODO: No filling of 0xff
PSP_THREAD_ATTR_CLEAR_STACK = 0x00200000, // TODO: Clear thread stack when deleted
};
const char *waitTypeStrings[] =
{
"NONE",
"Sleep",
"Delay",
"Sema",
"EventFlag",
"Mbx",
"Vpl",
"Fpl",
"",
"ThreadEnd", // These are nonstandard wait types
"AudioChannel",
"Umd",
"Vblank",
"Mutex",
"LwMutex",
"Ctrl",
const char *waitTypeStrings[] = {
"NONE",
"Sleep",
"Delay",
"Sema",
"EventFlag",
"Mbx",
"Vpl",
"Fpl",
"",
"ThreadEnd", // These are nonstandard wait types
"AudioChannel",
"Umd",
"Vblank",
"Mutex",
"LwMutex",
"Ctrl",
};
struct SceKernelSysClock {
@ -81,7 +80,6 @@ struct SceKernelSysClock {
u32 hi;
};
struct NativeCallback
{
SceUInt size;
@ -185,9 +183,9 @@ public:
nt.waitID,
waitInfo.waitValue);
}
static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_THID; }
int GetIDType() const { return SCE_KERNEL_TMID_Thread; }
bool AllocateStack(u32 &stackSize)
@ -255,7 +253,7 @@ public:
bool isReady() const { return (nt.status & THREADSTATUS_DORMANT) != 0; }
bool isWaiting() const { return (nt.status & THREADSTATUS_WAIT) != 0; }
bool isSuspended() const { return (nt.status & THREADSTATUS_SUSPEND) != 0; }
NativeThread nt;
ThreadWaitInfo waitInfo;
@ -269,7 +267,7 @@ public:
std::set<SceUID> registeredCallbacks[THREAD_CALLBACK_NUM_TYPES];
std::list<SceUID> readyCallbacks[THREAD_CALLBACK_NUM_TYPES];
std::list<int> pendingMipsCalls;
u32 stackBlock;
@ -319,52 +317,53 @@ Thread *__GetCurrentThread() {
u32 __KernelMipsCallReturnAddress()
{
return cbReturnHackAddr;
return cbReturnHackAddr;
}
u32 __KernelInterruptReturnAddress()
{
return intReturnHackAddr;
return intReturnHackAddr;
}
void hleScheduledWakeup(u64 userdata, int cyclesLate);
void __KernelThreadingInit()
{
u32 blockSize = 4 * 4 + 4 * 2 * 3; // One 16-byte thread plus 3 8-byte "hacks"
u32 blockSize = 4 * 4 + 4 * 2 * 3; // One 16-byte thread plus 3 8-byte "hacks"
dispatchEnabled = true;
g_inCbCount = 0;
idleThreadHackAddr = kernelMemory.Alloc(blockSize, false, "threadrethack");
// Make sure it got allocated where we expect it... at the very start of kernel RAM
//CHECK_EQ(idleThreadHackAddr & 0x3FFFFFFF, 0x08000000);
// Make sure it got allocated where we expect it... at the very start of kernel RAM
//CHECK_EQ(idleThreadHackAddr & 0x3FFFFFFF, 0x08000000);
// Yeah, this is straight out of JPCSP, I should be ashamed.
Memory::Write_U32(MIPS_MAKE_ADDIU(MIPS_REG_A0, MIPS_REG_ZERO, 0), idleThreadHackAddr);
Memory::Write_U32(MIPS_MAKE_LUI(MIPS_REG_RA, 0x0800), idleThreadHackAddr + 4);
Memory::Write_U32(MIPS_MAKE_JR_RA(), idleThreadHackAddr + 8);
//Memory::Write_U32(MIPS_MAKE_SYSCALL("ThreadManForUser", "sceKernelDelayThread"), idleThreadHackAddr + 12);
Memory::Write_U32(MIPS_MAKE_SYSCALL("FakeSysCalls", "_sceKernelIdle"), idleThreadHackAddr + 12);
Memory::Write_U32(MIPS_MAKE_BREAK(), idleThreadHackAddr + 16);
// Yeah, this is straight out of JPCSP, I should be ashamed.
Memory::Write_U32(MIPS_MAKE_ADDIU(MIPS_REG_A0, MIPS_REG_ZERO, 0), idleThreadHackAddr);
Memory::Write_U32(MIPS_MAKE_LUI(MIPS_REG_RA, 0x0800), idleThreadHackAddr + 4);
Memory::Write_U32(MIPS_MAKE_JR_RA(), idleThreadHackAddr + 8);
//Memory::Write_U32(MIPS_MAKE_SYSCALL("ThreadManForUser", "sceKernelDelayThread"), idleThreadHackAddr + 12);
Memory::Write_U32(MIPS_MAKE_SYSCALL("FakeSysCalls", "_sceKernelIdle"), idleThreadHackAddr + 12);
Memory::Write_U32(MIPS_MAKE_BREAK(), idleThreadHackAddr + 16);
threadReturnHackAddr = idleThreadHackAddr + 20;
threadReturnHackAddr = idleThreadHackAddr + 20;
WriteSyscall("FakeSysCalls", NID_THREADRETURN, threadReturnHackAddr);
cbReturnHackAddr = threadReturnHackAddr + 8;
WriteSyscall("FakeSysCalls", NID_CALLBACKRETURN, cbReturnHackAddr);
cbReturnHackAddr = threadReturnHackAddr + 8;
WriteSyscall("FakeSysCalls", NID_CALLBACKRETURN, cbReturnHackAddr);
intReturnHackAddr = cbReturnHackAddr + 8;
WriteSyscall("FakeSysCalls", NID_INTERRUPTRETURN, intReturnHackAddr);
intReturnHackAddr = cbReturnHackAddr + 8;
WriteSyscall("FakeSysCalls", NID_INTERRUPTRETURN, intReturnHackAddr);
eventScheduledWakeup = CoreTiming::RegisterEvent("ScheduledWakeup", &hleScheduledWakeup);
// Create the two idle threads, as well. With the absolute minimal possible priority.
// 4096 stack size - don't know what the right value is. Hm, if callbacks are ever to run on these threads...
__KernelResetThread(__KernelCreateThread(threadIdleID[0], 0, "idle0", idleThreadHackAddr, 0x7f, 4096, PSP_THREAD_ATTR_KERNEL));
__KernelResetThread(__KernelCreateThread(threadIdleID[1], 0, "idle1", idleThreadHackAddr, 0x7f, 4096, PSP_THREAD_ATTR_KERNEL));
// These idle threads are later started in LoadExec, which calls __KernelStartIdleThreads below.
// Create the two idle threads, as well. With the absolute minimal possible priority.
// 4096 stack size - don't know what the right value is. Hm, if callbacks are ever to run on these threads...
__KernelResetThread(__KernelCreateThread(threadIdleID[0], 0, "idle0", idleThreadHackAddr, 0x7f, 4096, PSP_THREAD_ATTR_KERNEL));
__KernelResetThread(__KernelCreateThread(threadIdleID[1], 0, "idle1", idleThreadHackAddr, 0x7f, 4096, PSP_THREAD_ATTR_KERNEL));
// These idle threads are later started in LoadExec, which calls __KernelStartIdleThreads below.
__KernelListenThreadEnd(__KernelCancelWakeup);
__KernelListenThreadEnd(__KernelCancelWakeup);
}
void __KernelListenThreadEnd(ThreadCallback callback)
@ -384,15 +383,15 @@ void __KernelFireThreadEnd(Thread *thread)
void __KernelStartIdleThreads()
{
for (int i = 0; i < 2; i++)
{
u32 error;
Thread *t = kernelObjects.Get<Thread>(threadIdleID[i], error);
t->nt.gpreg = __KernelGetModuleGP(curModule);
t->context.r[MIPS_REG_GP] = t->nt.gpreg;
//t->context.pc += 4; // ADJUSTPC
t->nt.status = THREADSTATUS_READY;
}
for (int i = 0; i < 2; i++)
{
u32 error;
Thread *t = kernelObjects.Get<Thread>(threadIdleID[i], error);
t->nt.gpreg = __KernelGetModuleGP(curModule);
t->context.r[MIPS_REG_GP] = t->nt.gpreg;
//t->context.pc += 4; // ADJUSTPC
t->nt.status = THREADSTATUS_READY;
}
}
bool __KernelSwitchOffThread(const char *reason)
@ -421,25 +420,25 @@ bool __KernelSwitchOffThread(const char *reason)
void __KernelIdle()
{
CoreTiming::Idle();
// Advance must happen between Idle and Reschedule, so that threads that were waiting for something
// that was triggered at the end of the Idle period must get a chance to be scheduled.
CoreTiming::Advance();
CoreTiming::Idle();
// Advance must happen between Idle and Reschedule, so that threads that were waiting for something
// that was triggered at the end of the Idle period must get a chance to be scheduled.
CoreTiming::Advance();
// In Advance, we might trigger an interrupt such as vblank.
// If we end up in an interrupt, we don't want to reschedule.
// However, we have to reschedule... damn.
__KernelReSchedule("idle");
// In Advance, we might trigger an interrupt such as vblank.
// If we end up in an interrupt, we don't want to reschedule.
// However, we have to reschedule... damn.
__KernelReSchedule("idle");
}
void __KernelThreadingShutdown()
{
kernelMemory.Free(threadReturnHackAddr);
threadqueue.clear();
threadReturnHackAddr = 0;
cbReturnHackAddr = 0;
cbReturnHackAddr = 0;
currentThread = 0;
intReturnHackAddr = 0;
threadqueue.clear();
}
const char *__KernelGetThreadName(SceUID threadID)
@ -521,29 +520,29 @@ void sceKernelReferThreadStatus()
void sceKernelGetThreadExitStatus()
{
SceUID threadID = PARAM(0);
if (threadID == 0)
threadID = __KernelGetCurThread();
SceUID threadID = PARAM(0);
if (threadID == 0)
threadID = __KernelGetCurThread();
u32 error;
Thread *t = kernelObjects.Get<Thread>(threadID, error);
if (t)
{
if (t->nt.status == THREADSTATUS_DORMANT) // TODO: can be dormant before starting, too, need to avoid that
{
DEBUG_LOG(HLE,"sceKernelGetThreadExitStatus(%i)", threadID);
RETURN(t->nt.exitStatus);
}
else
{
RETURN(SCE_KERNEL_ERROR_NOT_DORMANT);
}
}
else
{
ERROR_LOG(HLE,"sceKernelGetThreadExitStatus Error %08x", error);
RETURN(SCE_KERNEL_ERROR_UNKNOWN_THID);
}
u32 error;
Thread *t = kernelObjects.Get<Thread>(threadID, error);
if (t)
{
if (t->nt.status == THREADSTATUS_DORMANT) // TODO: can be dormant before starting, too, need to avoid that
{
DEBUG_LOG(HLE,"sceKernelGetThreadExitStatus(%i)", threadID);
RETURN(t->nt.exitStatus);
}
else
{
RETURN(SCE_KERNEL_ERROR_NOT_DORMANT);
}
}
else
{
ERROR_LOG(HLE,"sceKernelGetThreadExitStatus Error %08x", error);
RETURN(SCE_KERNEL_ERROR_UNKNOWN_THID);
}
}
u32 sceKernelGetThreadmanIdType(u32 uid) {
@ -597,10 +596,10 @@ void __KernelSaveContext(ThreadContext *ctx)
ctx->lo = currentMIPS->lo;
ctx->pc = currentMIPS->pc;
ctx->fpcond = currentMIPS->fpcond;
// ctx->fcr0 = currentMIPS->fcr0;
// ctx->fcr31 = currentMIPS->fcr31;
// ctx->fcr0 = currentMIPS->fcr0;
// ctx->fcr31 = currentMIPS->fcr31;
// TODO: Make VFPU saving optional/delayed, only necessary between VFPU-attr-marked threads
// TODO: Make VFPU saving optional/delayed, only necessary between VFPU-attr-marked threads
}
// Loads a CPU context
@ -623,8 +622,8 @@ void __KernelLoadContext(ThreadContext *ctx)
currentMIPS->lo = ctx->lo;
currentMIPS->pc = ctx->pc;
currentMIPS->fpcond = ctx->fpcond;
// currentMIPS->fcr0 = ctx->fcr0;
// currentMIPS->fcr31 = ctx->fcr31;
// currentMIPS->fcr0 = ctx->fcr0;
// currentMIPS->fcr31 = ctx->fcr31;
}
u32 __KernelResumeThreadFromWait(SceUID threadID)
@ -723,7 +722,7 @@ void __KernelWaitCurThread(WaitType type, SceUID waitID, u32 waitValue, u32 time
// TODO: time waster
char temp[256];
sprintf(temp, "started wait %s", waitTypeStrings[(int)type]);
hleReSchedule(processCallbacks, temp);
// TODO: Remove thread from Ready queue?
}
@ -746,21 +745,21 @@ void __KernelCancelWakeup(SceUID threadID)
void __KernelRemoveFromThreadQueue(Thread *t)
{
for (size_t i = 0; i < threadqueue.size(); i++)
{
if (threadqueue[i] == t)
{
for (size_t i = 0; i < threadqueue.size(); i++)
{
if (threadqueue[i] == t)
{
DEBUG_LOG(HLE, "Deleted thread %p (%i) from thread queue", t, t->GetUID());
threadqueue.erase(threadqueue.begin() + i);
return;
}
}
threadqueue.erase(threadqueue.begin() + i);
return;
}
}
}
Thread *__KernelNextThread() {
// round-robin scheduler
// seems to work ?
// not accurate!
// not accurate!
int bestthread = -1;
int prio = 0xffffff;
@ -852,53 +851,51 @@ void __KernelReSchedule(bool doCallbacks, const char *reason)
}
}
//////////////////////////////////////////////////////////////////////////
// Thread Management
//////////////////////////////////////////////////////////////////////////
void sceKernelCheckThreadStack()
{
u32 error;
Thread *t = kernelObjects.Get<Thread>(__KernelGetCurThread(), error);
u32 diff = abs((long)((s64)t->stackBlock - (s64)currentMIPS->r[MIPS_REG_SP]));
ERROR_LOG(HLE, "%i=sceKernelCheckThreadStack()", diff);
u32 error;
Thread *t = kernelObjects.Get<Thread>(__KernelGetCurThread(), error);
u32 diff = abs((long)((s64)t->stackBlock - (s64)currentMIPS->r[MIPS_REG_SP]));
ERROR_LOG(HLE, "%i=sceKernelCheckThreadStack()", diff);
RETURN(diff); //Blatant lie
}
void ThreadContext::reset()
{
for (int i = 0; i<32; i++)
{
r[i] = 0;
f[i] = 0.0f;
}
for (int i = 0; i<128; i++)
{
v[i] = 0.0f;
}
for (int i = 0; i<15; i++)
{
vfpuCtrl[i] = 0x00000000;
}
vfpuCtrl[VFPU_CTRL_SPREFIX] = 0xe4; // neutral
vfpuCtrl[VFPU_CTRL_TPREFIX] = 0xe4; // neutral
vfpuCtrl[VFPU_CTRL_DPREFIX] = 0x0; // neutral
vfpuCtrl[VFPU_CTRL_CC] = 0x3f;
vfpuCtrl[VFPU_CTRL_INF4] = 0;
vfpuCtrl[VFPU_CTRL_RCX0] = 0x3f800001;
vfpuCtrl[VFPU_CTRL_RCX1] = 0x3f800002;
vfpuCtrl[VFPU_CTRL_RCX2] = 0x3f800004;
vfpuCtrl[VFPU_CTRL_RCX3] = 0x3f800008;
vfpuCtrl[VFPU_CTRL_RCX4] = 0x3f800000;
vfpuCtrl[VFPU_CTRL_RCX5] = 0x3f800000;
vfpuCtrl[VFPU_CTRL_RCX6] = 0x3f800000;
vfpuCtrl[VFPU_CTRL_RCX7] = 0x3f800000;
fpcond = 0;
fcr0 = 0;
fcr31 = 0;
hi = 0;
lo = 0;
for (int i = 0; i<32; i++)
{
r[i] = 0;
f[i] = 0.0f;
}
for (int i = 0; i<128; i++)
{
v[i] = 0.0f;
}
for (int i = 0; i<15; i++)
{
vfpuCtrl[i] = 0x00000000;
}
vfpuCtrl[VFPU_CTRL_SPREFIX] = 0xe4; // neutral
vfpuCtrl[VFPU_CTRL_TPREFIX] = 0xe4; // neutral
vfpuCtrl[VFPU_CTRL_DPREFIX] = 0x0; // neutral
vfpuCtrl[VFPU_CTRL_CC] = 0x3f;
vfpuCtrl[VFPU_CTRL_INF4] = 0;
vfpuCtrl[VFPU_CTRL_RCX0] = 0x3f800001;
vfpuCtrl[VFPU_CTRL_RCX1] = 0x3f800002;
vfpuCtrl[VFPU_CTRL_RCX2] = 0x3f800004;
vfpuCtrl[VFPU_CTRL_RCX3] = 0x3f800008;
vfpuCtrl[VFPU_CTRL_RCX4] = 0x3f800000;
vfpuCtrl[VFPU_CTRL_RCX5] = 0x3f800000;
vfpuCtrl[VFPU_CTRL_RCX6] = 0x3f800000;
vfpuCtrl[VFPU_CTRL_RCX7] = 0x3f800000;
fpcond = 0;
fcr0 = 0;
fcr31 = 0;
hi = 0;
lo = 0;
}
void __KernelResetThread(Thread *t)
@ -971,7 +968,7 @@ void __KernelSetupRootThread(SceUID moduleID, int args, const char *argp, int pr
u32 location = mipsr4k.r[MIPS_REG_SP];
mipsr4k.r[MIPS_REG_A1] = location;
for (int i = 0; i < args; i++)
Memory::Write_U8(argp[i], location + i);
Memory::Write_U8(argp[i], location + i);
}
@ -1016,12 +1013,12 @@ int sceKernelStartThread(SceUID threadToStartID, u32 argSize, u32 argBlockPtr)
if (argBlockPtr && argSize > 0)
{
startThread->context.r[MIPS_REG_A0] = argSize;
startThread->context.r[MIPS_REG_A1] = sp;
startThread->context.r[MIPS_REG_A1] = sp;
}
else
{
startThread->context.r[MIPS_REG_A0] = 0;
startThread->context.r[MIPS_REG_A1] = 0;
startThread->context.r[MIPS_REG_A1] = 0;
}
startThread->context.r[MIPS_REG_GP] = startThread->nt.gpreg;
@ -1064,16 +1061,16 @@ void sceKernelGetThreadStackFreeSize()
}
}
// Scan the stack for 0xFF
int sz = 0;
for (u32 addr = thread->stackBlock; addr < thread->stackBlock + thread->nt.stackSize; addr++)
{
if (Memory::Read_U8(addr) != 0xFF)
break;
sz++;
}
// Scan the stack for 0xFF
int sz = 0;
for (u32 addr = thread->stackBlock; addr < thread->stackBlock + thread->nt.stackSize; addr++)
{
if (Memory::Read_U8(addr) != 0xFF)
break;
sz++;
}
RETURN(sz & ~3);
RETURN(sz & ~3);
}
// Internal function
@ -1116,46 +1113,46 @@ void sceKernelExitThread()
void _sceKernelExitThread()
{
ERROR_LOG(HLE,"_sceKernelExitThread FAKED");
currentThread->nt.status = THREADSTATUS_DORMANT;
currentThread->nt.exitStatus = PARAM(0);
__KernelFireThreadEnd(currentThread);
ERROR_LOG(HLE,"_sceKernelExitThread FAKED");
currentThread->nt.status = THREADSTATUS_DORMANT;
currentThread->nt.exitStatus = PARAM(0);
__KernelFireThreadEnd(currentThread);
//Find threads that waited for this one
// Wake them
if (!__KernelTriggerWait(WAITTYPE_THREADEND, __KernelGetCurThread()))
hleReSchedule("exit-deleted thread");
//Find threads that waited for this one
// Wake them
if (!__KernelTriggerWait(WAITTYPE_THREADEND, __KernelGetCurThread()))
hleReSchedule("exit-deleted thread");
// The stack will be deallocated when the thread is deleted.
}
void sceKernelExitDeleteThread()
{
int threadHandle = __KernelGetCurThread();
u32 error;
Thread *t = kernelObjects.Get<Thread>(threadHandle, error);
if (t)
{
INFO_LOG(HLE,"sceKernelExitDeleteThread()");
currentThread->nt.status = THREADSTATUS_DORMANT;
currentThread->nt.exitStatus = PARAM(0);
int threadHandle = __KernelGetCurThread();
u32 error;
Thread *t = kernelObjects.Get<Thread>(threadHandle, error);
if (t)
{
INFO_LOG(HLE,"sceKernelExitDeleteThread()");
currentThread->nt.status = THREADSTATUS_DORMANT;
currentThread->nt.exitStatus = PARAM(0);
__KernelFireThreadEnd(currentThread);
//userMemory.Free(currentThread->stackBlock);
currentThread->stackBlock = 0;
__KernelRemoveFromThreadQueue(t);
currentThread = 0;
__KernelRemoveFromThreadQueue(t);
currentThread = 0;
RETURN(kernelObjects.Destroy<Thread>(threadHandle));
RETURN(kernelObjects.Destroy<Thread>(threadHandle));
__KernelTriggerWait(WAITTYPE_THREADEND, threadHandle);
}
else
{
ERROR_LOG(HLE,"sceKernelExitDeleteThread() ERROR - could not find myself!");
RETURN(error);
}
}
__KernelTriggerWait(WAITTYPE_THREADEND, threadHandle);
}
else
{
ERROR_LOG(HLE,"sceKernelExitDeleteThread() ERROR - could not find myself!");
RETURN(error);
}
}
u32 sceKernelSuspendDispatchThread()
{
@ -1185,7 +1182,7 @@ int sceKernelDeleteThread(int threadHandle)
{
//TODO: remove from threadqueue!
DEBUG_LOG(HLE,"sceKernelDeleteThread(%i)",threadHandle);
u32 error;
Thread *t = kernelObjects.Get<Thread>(threadHandle, error);
if (t)
@ -1375,7 +1372,7 @@ void sceKernelCancelWakeupThread()
t->nt.wakeupCount = 0;
DEBUG_LOG(HLE,"sceKernelCancelWakeupThread(%i) - wakeupCount reset from %i", uid, wCount);
RETURN(wCount);
}
}
else {
ERROR_LOG(HLE,"sceKernelCancelWakeupThread(%i) - bad thread id", uid);
RETURN(error);
@ -1429,24 +1426,24 @@ void sceKernelWaitThreadEnd()
void sceKernelWaitThreadEndCB()
{
SceUID id = PARAM(0);
DEBUG_LOG(HLE,"sceKernelWaitThreadEnd(%i)",id);
u32 error;
Thread *t = kernelObjects.Get<Thread>(id, error);
if (t)
{
if (t->nt.status != THREADSTATUS_DORMANT) {
__KernelWaitCurThread(WAITTYPE_THREADEND, id, 0, 0, true);
} else {
SceUID id = PARAM(0);
DEBUG_LOG(HLE,"sceKernelWaitThreadEnd(%i)",id);
u32 error;
Thread *t = kernelObjects.Get<Thread>(id, error);
if (t)
{
if (t->nt.status != THREADSTATUS_DORMANT) {
__KernelWaitCurThread(WAITTYPE_THREADEND, id, 0, 0, true);
} else {
DEBUG_LOG(HLE,"sceKernelWaitThreadEnd - thread %i already ended. Doing nothing.", id);
}
__KernelCheckCallbacks();
}
else
{
ERROR_LOG(HLE,"sceKernelWaitThreadEnd - bad thread %i", id);
}
RETURN(0);
}
else
{
ERROR_LOG(HLE,"sceKernelWaitThreadEnd - bad thread %i", id);
}
RETURN(0);
}
void sceKernelSuspendThread()
@ -1475,14 +1472,14 @@ u32 __KernelCreateCallback(const char *name, u32 entrypoint, u32 commonArg)
SceUID id = kernelObjects.Create(cb);
cb->nc.size = sizeof(NativeCallback);
strncpy(cb->nc.name, name, 32);
strncpy(cb->nc.name, name, 32);
cb->nc.entrypoint = entrypoint;
cb->nc.threadId = __KernelGetCurThread();
cb->nc.commonArgument = commonArg;
cb->nc.notifyCount = 0;
cb->nc.notifyArg = 0;
cb->forceDelete = false;
return id;
@ -1531,7 +1528,7 @@ void sceKernelCancelCallback()
Callback *cb = kernelObjects.Get<Callback>(cbId, error);
if (cb) {
// This is what JPCSP does. Huh?
cb->nc.notifyArg = 0;
cb->nc.notifyArg = 0;
RETURN(0);
} else {
ERROR_LOG(HLE,"sceKernelCancelCallback(%i) - bad cbId", cbId);
@ -1819,7 +1816,7 @@ void __KernelCallAddress(Thread *thread, u32 entryPoint, Action *afterAction, bo
call->numArgs = args.size();
call->doAfter = afterAction;
call->tag = "callAddress";
int callId = mipsCalls.add(call);
bool called = false;
@ -1841,7 +1838,7 @@ void __KernelCallAddress(Thread *thread, u32 entryPoint, Action *afterAction, bo
}
}
}
void __KernelExecuteMipsCallOnCurrentThread(int callId, bool reschedAfter)
{
if (g_inCbCount > 0) {
@ -1849,7 +1846,7 @@ void __KernelExecuteMipsCallOnCurrentThread(int callId, bool reschedAfter)
}
DEBUG_LOG(HLE, "Executing mipscall %i", callId);
MipsCall *call = mipsCalls.get(callId);
// Save the few regs that need saving
call->savedPc = currentMIPS->pc;
call->savedRa = currentMIPS->r[MIPS_REG_RA];