diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index 669414f7..81e5f50b 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -4056,8 +4056,8 @@ fn_800BD510 = .text:0x800BD510; // type:function size:0xC fn_800BD520 = .text:0x800BD520; // type:function size:0x5C fn_800BD580 = .text:0x800BD580; // type:function size:0x5C fn_800BD5E0 = .text:0x800BD5E0; // type:function size:0xC -fn_800BD5F0 = .text:0x800BD5F0; // type:function size:0x4 -fn_800BD600 = .text:0x800BD600; // type:function size:0x4 +onExit__Q23EGG6ThreadFv = .text:0x800BD5F0; // type:function size:0x4 +onEnter__Q23EGG6ThreadFv = .text:0x800BD600; // type:function size:0x4 fn_800BD610 = .text:0x800BD610; // type:function size:0x34 fn_800BD650 = .text:0x800BD650; // type:function size:0x8 fn_800BD660 = .text:0x800BD660; // type:function size:0x5C @@ -22030,11 +22030,11 @@ fn_803AC300 = .text:0x803AC300; // type:function size:0x20 __OSSystemCallVectorEnd = .text:0x803AC31C; // type:label scope:global __OSInitSystemCall = .text:0x803AC320; // type:function size:0x60 scope:global fn_803AC380 = .text:0x803AC380; // type:function size:0x4 -fn_803AC390 = .text:0x803AC390; // type:function size:0x70 +OSSetSwitchThreadCallback = .text:0x803AC390; // type:function size:0x70 __OSThreadInit = .text:0x803AC400; // type:function size:0x284 scope:global OSInitThreadQueue = .text:0x803AC690; // type:function size:0x10 scope:global -fn_803AC6A0 = .text:0x803AC6A0; // type:function size:0xC -fn_803AC6B0 = .text:0x803AC6B0; // type:function size:0x2C +OSGetCurrentThread = .text:0x803AC6A0; // type:function size:0xC +OSIsThreadTerminated = .text:0x803AC6B0; // type:function size:0x2C OSDisableScheduler = .text:0x803AC6E0; // type:function size:0x3C scope:global OSEnableScheduler = .text:0x803AC720; // type:function size:0x3C scope:global fn_803AC760 = .text:0x803AC760; // type:function size:0x68 @@ -22044,11 +22044,11 @@ fn_803AC9C0 = .text:0x803AC9C0; // type:function size:0x50 SelectThread = .text:0x803ACA10; // type:function size:0x22C scope:local __OSReschedule = .text:0x803ACC40; // type:function size:0x18 scope:global fn_803ACC60 = .text:0x803ACC60; // type:function size:0x3C -fn_803ACCA0 = .text:0x803ACCA0; // type:function size:0x26C +OSCreateThread = .text:0x803ACCA0; // type:function size:0x26C fn_803ACF10 = .text:0x803ACF10; // type:function size:0xE4 OSCancelThread = .text:0x803AD000; // type:function size:0x1D4 scope:global fn_803AD1E0 = .text:0x803AD1E0; // type:function size:0x144 -fn_803AD330 = .text:0x803AD330; // type:function size:0xA0 +OSDetachThread = .text:0x803AD330; // type:function size:0xA0 fn_803AD3D0 = .text:0x803AD3D0; // type:function size:0x29C fn_803AD670 = .text:0x803AD670; // type:function size:0x18C OSSleepThread = .text:0x803AD800; // type:function size:0xF0 scope:global @@ -26253,7 +26253,7 @@ getSize__Q23EGG10AssertHeapFv = .text:0x80496810; // type:function size:0x8 getHeapKind__Q23EGG10AssertHeapCFv = .text:0x80496820; // type:function size:0x8 __ct__Q23EGG8DisposerFv = .text:0x80496830; // type:function size:0x54 __dt__Q23EGG8DisposerFv = .text:0x80496890; // type:function size:0x74 -__ct__Q23EGG6ThreadFUliiPQ23EGG4Heap = .text:0x80496910; // type:function size:0xD0 +__ct__Q23EGG6ThreadFUiiiPQ23EGG4Heap = .text:0x80496910; // type:function size:0xD0 __ct__Q23EGG6ThreadFP8OSThreadi = .text:0x804969E0; // type:function size:0x74 __dt__Q23EGG6ThreadFv = .text:0x80496A60; // type:function size:0xBC findThread__Q23EGG6ThreadFP8OSThread = .text:0x80496B20; // type:function size:0x64 @@ -26262,7 +26262,7 @@ setThreadCurrentHeap__Q23EGG6ThreadFPQ23EGG4Heap = .text:0x80496BD0; // type:fun switchThreadCallback__Q23EGG6ThreadFP8OSThreadP8OSThread = .text:0x80496C70; // type:function size:0xEC setCommonMesgQueue__Q23EGG6ThreadFiPQ23EGG4Heap = .text:0x80496D60; // type:function size:0x5C start__Q23EGG6ThreadFPv = .text:0x80496DC0; // type:function size:0x10 -run__Q23EGG6ThreadFPv = .text:0x80496DD0; // type:function size:0x8 +run__Q23EGG6ThreadFv = .text:0x80496DD0; // type:function size:0x8 FUN_80496de0 = .text:0x80496DE0; // type:function size:0x44 FUN_80496e30 = .text:0x80496E30; // type:function size:0xD8 FUN_80496f10 = .text:0x80496F10; // type:function size:0x1CC @@ -37103,7 +37103,7 @@ lbl_8056E9A0 = .data:0x8056E9A0; // type:object size:0x30 lbl_8056E9D0 = .data:0x8056E9D0; // type:object size:0x30 lbl_8056EA00 = .data:0x8056EA00; // type:object size:0x30 lbl_8056EA30 = .data:0x8056EA30; // type:object size:0x10 -lbl_8056EA40 = .data:0x8056EA40; // type:object size:0x18 +__vt__Q23EGG6Thread = .data:0x8056EA40; // type:object size:0x18 lbl_8056EA58 = .data:0x8056EA58; // type:object size:0x70 __vt__Q23EGG7Display = .data:0x8056EAC8; // type:object size:0x20 __vt__Q23EGG10ColorFader = .data:0x8056EAE8; // type:object size:0x24 @@ -40890,7 +40890,7 @@ lbl_8057675C = .sbss:0x8057675C; // type:object size:0x4 data:4byte lbl_80576760 = .sbss:0x80576760; // type:object size:0x4 data:4byte lbl_80576764 = .sbss:0x80576764; // type:object size:0x4 data:4byte lbl_80576768 = .sbss:0x80576768; // type:object size:0x8 data:4byte -lbl_80576770 = .sbss:0x80576770; // type:object size:0x8 data:4byte +sOldSwitchThreadCallback__Q23EGG6Thread = .sbss:0x80576770; // type:object size:0x4 data:4byte lbl_80576778 = .sbss:0x80576778; // type:object size:0x8 data:4byte mConfigData__Q23EGG10BaseSystem = .sbss:0x80576780; // type:object size:0x4 data:4byte sTickPeriod__Q23EGG7Display = .sbss:0x80576788; // type:object size:0x4 data:4byte @@ -49347,7 +49347,7 @@ lbl_80673AC8 = .bss:0x80673AC8; // type:object size:0x10 lbl_80673AD8 = .bss:0x80673AD8; // type:object size:0x10 lbl_80673AE8 = .bss:0x80673AE8; // type:object size:0x10 lbl_80673AF8 = .bss:0x80673AF8; // type:object size:0x18 -lbl_80673B10 = .bss:0x80673B10; // type:object size:0x10 +sThreadList__Q23EGG6Thread = .bss:0x80673B10; // type:object size:0xC clear_z_tobj__29@unnamed@eggAsyncDisplay_cpp@ = .bss:0x80673B20; // type:object size:0x20 scope:local lbl_80673B40 = .bss:0x80673B40; // type:object size:0x10C0 data:4byte ident__Q23EGG9Matrix34f = .bss:0x80674C00; // type:object size:0x30 diff --git a/configure.py b/configure.py index 830c0c10..ad9079a4 100644 --- a/configure.py +++ b/configure.py @@ -350,7 +350,7 @@ config.libs = [ Object(NonMatching, "egg/core/eggFrmHeap.cpp"), Object(NonMatching, "egg/core/eggAssertHeap.cpp"), Object(NonMatching, "egg/core/eggDisposer.cpp"), - Object(NonMatching, "egg/core/eggThread.cpp"), + Object(Matching, "egg/core/eggThread.cpp"), Object(NonMatching, "egg/core/eggUnk.cpp"), Object(NonMatching, "egg/core/eggSystem.cpp"), Object(Matching, "egg/core/eggDisplay.cpp"), diff --git a/include/egg/core/eggThread.h b/include/egg/core/eggThread.h index 8895b95d..048cb88e 100644 --- a/include/egg/core/eggThread.h +++ b/include/egg/core/eggThread.h @@ -11,9 +11,9 @@ namespace EGG { class Thread { public: // vtable: 0x00 | 8056ea40 /* 0x08 | 80496a60 */ virtual ~Thread(); - /* 0x0C | 80496dd0 */ virtual void *run(); - /* 0x10 | 800bd600 */ virtual void onEnter(); - /* 0x14 | 800bd5f0 */ virtual void onExit(); + /* 0x0C | 80496dd0 */ virtual void *run() { return nullptr; } + /* 0x10 | 800bd600 */ virtual void onEnter() {} + /* 0x14 | 800bd5f0 */ virtual void onExit() {} public: /* 0x04 */ Heap *mContainingHeap; @@ -24,6 +24,8 @@ public: /* 0x34 */ void *mStackMemory; /* 0x38 */ u32 mStackSize; /* 0x3C */ Heap *mAllocatableHeap; + // TODO from the usage in eggThread this really looks like + // it's stashed thread that's restored when switching threads /* 0x40 */ Heap *mCurrentHeap; /* 0x44 */ nw4r::ut::Node mLink; diff --git a/include/rvl/OS/OSThread.h b/include/rvl/OS/OSThread.h index b81078b3..dfe07d5f 100644 --- a/include/rvl/OS/OSThread.h +++ b/include/rvl/OS/OSThread.h @@ -47,8 +47,8 @@ typedef struct OSThread { OSMutexQueue mutexQueue; // at 0x2F4 struct OSThread *nextActive; // at 0x2FC struct OSThread *prevActive; // at 0x300 - u32 *stackBegin; // at 0x304 - u32 *stackEnd; // at 0x308 + void *stackBegin; // at 0x304 + void *stackEnd; // at 0x308 s32 error; // at 0x30C void *specific[2]; // at 0x310 } OSThread; diff --git a/src/egg/core/eggThread.cpp b/src/egg/core/eggThread.cpp new file mode 100644 index 00000000..36f44d4d --- /dev/null +++ b/src/egg/core/eggThread.cpp @@ -0,0 +1,125 @@ +#include + +namespace EGG { + +/* 80673b10 */ nw4r::ut::List Thread::sThreadList; +/* 80576770 */ void (*Thread::sOldSwitchThreadCallback)(OSThread *, OSThread *); + + +/* 80496910 */ Thread::Thread(u32 stackSize, int msgCount, int priority, Heap *heap) { + if (heap == nullptr) { + heap = Heap::sCurrentHeap; + } + + mContainingHeap = heap; + mStackSize = ROUND_DOWN(stackSize, 0x20); + mStackMemory = Heap::alloc(ROUND_DOWN(stackSize, 0x20), 0x20, heap); + mOSThread = Heap::alloc(mContainingHeap, 0x20); + OSCreateThread(mOSThread, start, this, (char *)mStackMemory + mStackSize, mStackSize, priority, 1); + mAllocatableHeap = nullptr; + mCurrentHeap = nullptr; + setCommonMesgQueue(msgCount, mContainingHeap); +} + +/* 804969e0 */ Thread::Thread(OSThread *osThread, int msgCount) { + mContainingHeap = nullptr; + mOSThread = osThread; + mStackSize = (u8 *)osThread->stackBegin - (u8 *)osThread->stackEnd; + mStackMemory = osThread->stackEnd; + mAllocatableHeap = nullptr; + mCurrentHeap = nullptr; + setCommonMesgQueue(msgCount, Heap::sCurrentHeap); +} + +/* 80496a60 */ Thread::~Thread() { + nw4r::ut::List_Remove(&sThreadList, this); + if (mContainingHeap != nullptr) { + if (!OSIsThreadTerminated(mOSThread)) { + OSDetachThread(mOSThread); + OSCancelThread(mOSThread); + } + Heap::free(mStackMemory, mContainingHeap); + Heap::free(mOSThread, mContainingHeap); + } + Heap::free(mMesgBuffer, nullptr); +} + +/* 80496b20 */ Thread *Thread::findThread(OSThread *thread) { + Thread *ptr = nullptr; + while ((ptr = (Thread *)nw4r::ut::List_GetNext(&sThreadList, ptr)) != nullptr) { + if (ptr->mOSThread == thread) { + return ptr; + } + } + return nullptr; +} + +/* 80496b90 */ void Thread::initialize() { + // TODO offsetof + nw4r::ut::List_Init(&sThreadList, 0x44); + sOldSwitchThreadCallback = OSSetSwitchThreadCallback(switchThreadCallback); +} + +/* 80496bd0 */ void Thread::setThreadCurrentHeap(Heap *heap) { + OSDisableScheduler(); + OSThread *myThread = mOSThread; + OSThread *currentThread = OSGetCurrentThread(); + if (currentThread != myThread) { + mCurrentHeap = heap; + } else { + if (heap != nullptr) { + if (mCurrentHeap == nullptr) { + mCurrentHeap = Heap::sCurrentHeap; + } + heap->_becomeCurrentHeapWithoutLock(); + } else { + if (mCurrentHeap != nullptr) { + mCurrentHeap->_becomeCurrentHeapWithoutLock(); + mCurrentHeap = nullptr; + } + } + } + + OSEnableScheduler(); +} + +/* 80496c70 */ void Thread::switchThreadCallback(OSThread *from, OSThread *to) { + Thread *fromThread = from != nullptr ? findThread(from) : nullptr; + Thread *toThread = to != nullptr ? findThread(to) : nullptr; + + if (fromThread != nullptr) { + fromThread->onExit(); + if (fromThread->mCurrentHeap != nullptr) { + Heap *curr = Heap::sCurrentHeap; + fromThread->mCurrentHeap->_becomeCurrentHeapWithoutLock(); + fromThread->mCurrentHeap = curr; + } + } + + if (toThread != nullptr) { + if (toThread->mCurrentHeap != nullptr) { + Heap *curr = Heap::sCurrentHeap; + toThread->mCurrentHeap->_becomeCurrentHeapWithoutLock(); + toThread->mCurrentHeap = curr; + } + toThread->onEnter(); + } + + if (sOldSwitchThreadCallback != nullptr) { + (sOldSwitchThreadCallback)(from, to); + } +} + +/* 80496d60 */ void Thread::setCommonMesgQueue(int mesgCount, Heap *heap) { + mMesgCount = mesgCount; + mMesgBuffer = Heap::alloc(mesgCount, heap); + OSInitMessageQueue(&mMesgQueue, mMesgBuffer, mMesgCount); + nw4r::ut::List_Append(&sThreadList, this); +} + +/* 80496dc0 */ void *Thread::start(void *arg) { + Thread *thread = static_cast(arg); + return thread->run(); +} + +} // namespace EGG