Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Darkstalkers Chronicle: The Chaos Tower
#10
It's hitting this:

Code:
T *GetFast(SceUID handle) { const SceUID realHandle = handle - handleOffset; _dbg_assert_(SCEKERNEL, realHandle >= 0 && realHandle < maxCount && occupied[realHandle]); <-- BOOM return static_cast<T *>(pool[realHandle]); }

This means one of:

* The game is deleting a thread in a way that doesn't remove it from the thread queues.
* The game is writing somewhere that is corrupting PPSSPP's memory.
* A buffer overflow in PPSSPP is overwriting PPSSPP's memory.

But, your crash seems to indicate a crazy value of priority, which suggests one of the latter...

In sceKernelThread.cpp, find:

Code:
void __KernelChangeReadyState(Thread *thread, SceUID threadID, bool ready) { // Passing the id as a parameter is just an optimization, if it's wrong it will cause havoc. _dbg_assert_msg_(SCEKERNEL, thread->GetUID() == threadID, "Incorrect threadID"); int prio = thread->nt.currentPriority; if (thread->isReady()) { if (!ready) threadReadyQueue.remove(prio, threadID); } else if (ready) { if (thread->isRunning()) threadReadyQueue.push_front(prio, threadID); else threadReadyQueue.push_back(prio, threadID); thread->nt.status = THREADSTATUS_READY; } }

Change to:

Code:
void __KernelChangeReadyState(Thread *thread, SceUID threadID, bool ready) { // Passing the id as a parameter is just an optimization, if it's wrong it will cause havoc. _dbg_assert_msg_(SCEKERNEL, thread->GetUID() == threadID, "Incorrect threadID"); int prio = thread->nt.currentPriority; if (prio < 0 || prio > 127) { NOTICE_LOG(HLE, "Wackjob crazy priority %d for thread %d", prio, threadID); DebugBreak(); thread->nt.currentPriority = 127; return; } if (thread->isReady()) { if (!ready) threadReadyQueue.remove(prio, threadID); } else if (ready) { if (thread->isRunning()) threadReadyQueue.push_front(prio, threadID); else threadReadyQueue.push_back(prio, threadID); thread->nt.status = THREADSTATUS_READY; } }

Also:

Code:
Thread *__KernelNextThread() { SceUID bestThread; // If the current thread is running, it's a valid candidate. Thread *cur = __GetCurrentThread(); if (cur && cur->isRunning()) { bestThread = threadReadyQueue.pop_first_better(cur->nt.currentPriority); if (bestThread != 0) __KernelChangeReadyState(cur, currentThread, true); } else bestThread = threadReadyQueue.pop_first(); // Assume threadReadyQueue has not become corrupt. if (bestThread != 0) return kernelObjects.GetFast<Thread>(bestThread); else return 0; }

Change to:

Code:
Thread *__KernelNextThread() { SceUID bestThread; // If the current thread is running, it's a valid candidate. Thread *cur = __GetCurrentThread(); if (cur && cur->isRunning()) { bestThread = threadReadyQueue.pop_first_better(cur->nt.currentPriority); if (bestThread != 0) __KernelChangeReadyState(cur, currentThread, true); } else bestThread = threadReadyQueue.pop_first(); // Assume threadReadyQueue has not become corrupt. if (bestThread != 0) { u32 errorIgnored; Thread *t = kernelObjects.Get<Thread>(bestThread, errorIgnored); if (t == NULL && bestThread != 0) { NOTICE_LOG(HLE, "ACK ACK ACK ACK Invalid thread id %d on thread queue", bestThread); DebugBreak(); // Try, try again? t = __KernelNextThread(); } if (t == NULL) { NOTICE_LOG(HLE, "ACK ACK ACK ACK Thread queue empty"); DebugBreak(); // Just brute force it, hopefully... return kernelObjects.Get<Thread>(threadIdleID[0], errorIgnored); } return t; } else { return 0; } }

(and run in the debugger.)

-[Unknown]
Reply


Messages In This Thread
RE: Darkstalkers Chronicle The Chaos Tower - by [Unknown] - 01-06-2014, 01:45 AM

Forum Jump: