public virtual void reset() { status = PSP_THREAD_STOPPED; int k0 = stackAddr + stackSize - 0x100; // setup k0 Memory mem = Memory.Instance; if (stackAddr != 0 && stackSize > 0 && !preserveStack) { // set stack to 0xFF if ((attr & PSP_THREAD_ATTR_NO_FILLSTACK) != PSP_THREAD_ATTR_NO_FILLSTACK) { mem.memset(stackAddr, unchecked ((sbyte)0xFF), stackSize); } // setup k0 mem.memset(k0, (sbyte)0x0, 0x100); mem.write32(k0 + 0xc0, stackAddr); mem.write32(k0 + 0xca, uid); mem.write32(k0 + 0xf8, unchecked ((int)0xffffffff)); mem.write32(k0 + 0xfc, unchecked ((int)0xffffffff)); mem.write32(stackAddr, uid); } currentPriority = initPriority; waitType = PSP_WAIT_NONE; waitId = 0; wakeupCount = 0; exitStatus = ERROR_KERNEL_THREAD_ALREADY_DORMANT; // Threads start with DORMANT and not NOT_DORMANT (tested and checked). exitStatusAddr = null; runClocks = 0; intrPreemptCount = 0; threadPreemptCount = 0; releaseCount = 0; notifyCallback = 0; // Thread specific registers cpuContext.pc = entry_addr; cpuContext.npc = entry_addr; // + 4; // Reset all the registers to DEADBEEF value for (int i = _ra; i > _zr; i--) { cpuContext.setRegister(i, unchecked ((int)0xDEADBEEF)); } cpuContext._k0 = 0; cpuContext._k1 = 0; if (UserMode) { cpuContext._k1 |= 0x100000; } cpuContext._k1 |= 0x100000; int intNanValue = 0x7F800001; float nanValue = Float.intBitsToFloat(intNanValue); for (int i = Common._f31; i >= Common._f0; i--) { cpuContext.fpr[i] = nanValue; } cpuContext.hilo = unchecked ((long)0xDEADBEEFDEADBEEFL); if ((attr & PSP_THREAD_ATTR_VFPU) != 0) { // Reset the VFPU context for (int m = 0; m < 8; m++) { for (int c = 0; c < 4; c++) { for (int r = 0; r < 4; r++) { cpuContext.setVprInt(m, c, r, intNanValue); } } } for (int i = 0; i < cpuContext.vcr.cc.Length; i++) { cpuContext.vcr.cc[i] = true; } cpuContext.vcr.pfxs.reset(); cpuContext.vcr.pfxt.reset(); cpuContext.vcr.pfxd.reset(); } // sp, 512 byte padding at the top for user data, this will get re-jigged when we call start thread cpuContext._sp = stackAddr + stackSize - 512; cpuContext._k0 = k0; // We'll hook "jr $ra" where $ra == address of HLE syscall hleKernelExitThread // when the thread is exiting cpuContext._ra = pspsharp.HLE.modules.ThreadManForUser.THREAD_EXIT_HANDLER_ADDRESS; doDelete = false; doCallbacks = false; registeredCallbacks = new RegisteredCallbacks[THREAD_CALLBACK_SIZE]; for (int i = 0; i < registeredCallbacks.Length; i++) { registeredCallbacks[i] = new RegisteredCallbacks(i); } // The UMD callback registers only the last callback. registeredCallbacks[THREAD_CALLBACK_UMD].setRegisterOnlyLastCallback(); }