Clear some state between runs. Tabs fixing.
This commit is contained in:
parent
ce214b3943
commit
862a11e7be
2 changed files with 224 additions and 221 deletions
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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,45 +1113,45 @@ 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()
|
||||
|
@ -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()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue