diff --git a/src/client/Client.cpp b/src/client/Client.cpp index 1c3b92c..ba2275a 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -97,8 +97,6 @@ void ClientRegisterConsoleCommands() { ConsoleCommandRegister("reloadUI", CCommand_ReloadUI, GRAPHICS, nullptr); ConsoleCommandRegister("perf", CCommand_Perf, DEBUG, nullptr); - const auto game = CATEGORY::GAME; - Client::g_accountNameVar = CVar::Register( "accountName", "Saved account name", @@ -180,7 +178,6 @@ void ClientPostClose(int32_t a1) { int32_t DestroyEngineCallback(const void* a1, void* a2) { // TODO - return 1; } @@ -625,6 +622,17 @@ int32_t InitializeGlobal() { return 1; } +void DestroyGlobal() { + // TODO + + OsTimeShutdown(); + EventDestroy(); + ConsoleDeviceDestroy(); + CVar::Destroy(); + + // TODO +} + void CommonMain() { StormInitialize(); @@ -659,7 +667,7 @@ void CommonMain() { if (InitializeGlobal()) { EventDoMessageLoop(); - // TODO: DestroyGlobal(); + DestroyGlobal(); } // TODO: diff --git a/src/console/CVar.cpp b/src/console/CVar.cpp index bd39313..490741c 100644 --- a/src/console/CVar.cpp +++ b/src/console/CVar.cpp @@ -8,6 +8,7 @@ const char* s_filename = nullptr; bool CVar::m_needsSave; +bool CVar::m_initialized; TSHashTable CVar::s_registeredCVars; CVar* CVar::Lookup(const char* name) { @@ -34,6 +35,10 @@ CVar* CVar::LookupRegistered(const char* name) { } CVar* CVar::Register(const char* name, const char* help, uint32_t flags, const char* value, HANDLER_FUNC fcn, uint32_t category, bool a7, void* arg, bool a9) { + if (!name || !*name || !value) { + return nullptr; + } + auto cv = s_registeredCVars.Ptr(name); if (cv) { @@ -280,6 +285,7 @@ int32_t CVar::Load(const char* filename) { void CVar::Initialize(const char* filename) { STORM_ASSERT(filename); s_filename = filename; + m_initialized = 1; // Get data path char path[STORM_MAX_PATH] = {0}; @@ -296,6 +302,72 @@ void CVar::Initialize(const char* filename) { CVar::Load(s_filename); } +int32_t CVar::IterateForArchive(uint32_t a1, uint32_t a2, ITERATE_FUNC cb, void* param) { + auto cvar = s_registeredCVars.Head(); + + while (cvar) { + if (cvar->m_flags & 0x1) { + if (!(cvar->m_flags & 0x80) && (cvar->m_flags & 0x30) == a1 && (cvar->m_flags & a2) == 0) { + const char* value; + if ((value = cvar->m_latchedValue.GetString()) || + (value = cvar->m_stringValue.GetString()) || + (value = cvar->m_defaultValue.GetString())) { + auto defaultvalue = cvar->m_defaultValue.GetString(); + if (!defaultvalue || SStrCmp(value, defaultvalue, STORM_MAX_STR)) { + if (!cb(cvar->m_key.m_str, value, param)) { + return 0; + } + } + } + } + } + + cvar = s_registeredCVars.Next(cvar); + } + + return 1; +} + +bool CVar::SaveCvar(const char* key, const char* value, void* param) { + char buffer[STORM_MAX_PATH]; + SStrPrintf(buffer, sizeof(buffer), "SET %s \"%s\"\n", key, value); + uint32_t byteswritten = 0; + OsWriteFile(static_cast(param), buffer, SStrLen(buffer), &byteswritten); + return byteswritten != 0; +} + +int32_t CVarSaveFile() { + if (!CVar::m_needsSave) { + return 1; + } + + char name[STORM_MAX_PATH]; + + CVar::m_needsSave = false; + SStrCopy(name, "WTF\\", sizeof(name)); + SStrPack(name, s_filename, sizeof(name)); + + int32_t result = 0; + + auto file = OsCreateFile(name, OS_GENERIC_WRITE, 0, OS_CREATE_ALWAYS, OS_FILE_ATTRIBUTE_NORMAL, OS_FILE_TYPE_DEFAULT); + if (file != HOSFILE_INVALID) { + result = CVar::IterateForArchive(0, 0, CVar::SaveCvar, file); + OsCloseFile(file); + } + + return result; +} + +void CVar::Destroy() { + m_initialized = 0; + CVarSaveFile(); + ConsoleCommandUnregister("set"); + ConsoleCommandUnregister("cvar_reset"); + ConsoleCommandUnregister("cvar_default"); + ConsoleCommandUnregister("cvarlist"); + s_registeredCVars.Clear(); +} + int32_t CvarResetCommandHandler(const char* command, const char* arguments) { char cvarName[256] = {0}; auto string = arguments; @@ -395,7 +467,7 @@ int32_t SetCommandHandler(const char* command, const char* arguments) { } cvar->m_modified++; - if (!(cvar->m_flags & 0x2)) { + if ((cvar->m_flags & 0x2)) { cvar->m_latchedValue.Copy(cvarValue); CVar::m_needsSave = true; } else if (!(cvar->m_flags & 0x4)) { diff --git a/src/console/CVar.hpp b/src/console/CVar.hpp index 6f87974..6b4b709 100644 --- a/src/console/CVar.hpp +++ b/src/console/CVar.hpp @@ -1,32 +1,36 @@ #ifndef CONSOLE_CVAR_HPP #define CONSOLE_CVAR_HPP -#include -#include -#include #include +#include +#include +#include #define CONSOLE_CVAR_MAX_LINE 2048 - class CVar : public TSHashObject { public: + typedef bool (*ITERATE_FUNC)(const char*, const char*, void*); typedef bool (*HANDLER_FUNC)(CVar*, const char*, const char*, void*); // Static variables static TSHashTable s_registeredCVars; static bool m_needsSave; + static bool m_initialized; // Static functions static CVar* Lookup(const char* name); static CVar* LookupRegistered(const char* name); static CVar* Register(const char* name, const char* help, uint32_t flags, const char* value, HANDLER_FUNC fcn, uint32_t category, bool a7, void* arg, bool a9); - static void Initialize(const char* filename); + static void Initialize(const char* filename); + static int32_t IterateForArchive(uint32_t a1, uint32_t a2, ITERATE_FUNC cb, void* param); + static void Destroy(); static int32_t Load(const char* filename); static int32_t Load(HOSFILE fileHandle); + static bool SaveCvar(const char* key, const char* value, void* param); // Member variables uint32_t m_category = 0; - uint32_t m_flags = 0; + uint32_t m_flags = 0; RCString m_stringValue; float m_floatValue = 0.0; int32_t m_intValue = 0; @@ -36,7 +40,7 @@ class CVar : public TSHashObject { RCString m_latchedValue; RCString m_help; bool (*m_callback)(CVar*, const char*, const char*, void*) = nullptr; - void* m_arg = nullptr; + void* m_arg = nullptr; // Member functions CVar(); @@ -50,7 +54,6 @@ class CVar : public TSHashObject { int32_t Update(); }; - int32_t SetCommandHandler(const char* command, const char* arguments); int32_t CvarResetCommandHandler(const char* command, const char* arguments); int32_t CvarDefaultCommandHandler(const char* command, const char* arguments); diff --git a/src/console/Command.hpp b/src/console/Command.hpp index 7e92571..97bab43 100644 --- a/src/console/Command.hpp +++ b/src/console/Command.hpp @@ -31,8 +31,6 @@ const char* ConsoleCommandHistory(uint32_t index); uint32_t ConsoleCommandHistoryDepth(); -int32_t ConsoleCommandRegister(const char* command, COMMANDHANDLER handler, CATEGORY category, const char* helpText); - void ConsoleInitializeCommonCommand(); void ConsoleInitializeDebugCommand(); diff --git a/src/console/Console.cpp b/src/console/Console.cpp index fe1943b..6a279ab 100644 --- a/src/console/Console.cpp +++ b/src/console/Console.cpp @@ -35,5 +35,5 @@ void ConsoleSetHotKey(KEY hotkey) { } void ConsolePostClose() { - EventPostCloseEx(EventGetCurrentContext()); + EventPostClose(); } diff --git a/src/event/Context.cpp b/src/event/Context.cpp index 7d0e005..5bf6823 100644 --- a/src/event/Context.cpp +++ b/src/event/Context.cpp @@ -1,4 +1,5 @@ #include "event/Context.hpp" +#include "Event.hpp" #include "event/Event.hpp" #include "event/EvtThread.hpp" #include @@ -53,8 +54,32 @@ HEVENTCONTEXT AttachContextToThread(EvtContext* context) { return context; } -void DetachContextFromThread(uint32_t a1, EvtContext* a2) { - // TODO +void DetachContextFromThread(uint32_t hThread, EvtContext* context) { + SInterlockedIncrement(&Event::s_threadListContention); + Event::s_threadListCritsect.Enter(); + + auto threadSlot = Event::s_threadSlots[hThread]; + if (threadSlot) { + threadSlot->m_weightTotal -= context->m_schedWeight; + threadSlot->m_contextCount--; + + threadSlot->m_weightAvg = threadSlot->m_contextCount ? threadSlot->m_weightTotal / threadSlot->m_contextCount : 0; + + auto thread = Event::s_threadList.Head(); + while (thread) { + if (thread != threadSlot && thread->m_weightAvg) { + if ((thread->m_weightAvg + threadSlot->m_weightTotal) <= thread->m_weightTotal) { + thread->m_rebalance += (thread->m_weightTotal - threadSlot->m_weightTotal) / thread->m_weightAvg; + } + thread->m_rebalance = std::min(thread->m_rebalance, thread->m_contextCount); + } + + thread = thread->Next(); + } + } + + Event::s_threadListCritsect.Leave(); + SInterlockedDecrement(&Event::s_threadListContention); } EvtContext* GetNextContext(uint32_t hThread) { diff --git a/src/event/Event.cpp b/src/event/Event.cpp index d4ea245..12396fd 100644 --- a/src/event/Event.cpp +++ b/src/event/Event.cpp @@ -86,6 +86,10 @@ HEVENTCONTEXT EventCreateContextEx(int32_t interactive, int32_t (*initializeHand return IEvtSchedulerCreateContext(interactive, initializeHandler, destroyHandler, idleTime, debugFlags); } +void EventDestroy() { + // TODO +} + void EventDoMessageLoop() { IEvtSchedulerProcess(); } diff --git a/src/event/Event.hpp b/src/event/Event.hpp index 4d9e628..2f838cf 100644 --- a/src/event/Event.hpp +++ b/src/event/Event.hpp @@ -35,6 +35,8 @@ namespace Event { HEVENTCONTEXT EventCreateContextEx(int32_t interactive, int32_t (*initializeHandler)(const void*, void*), int32_t (*destroyHandler)(const void*, void*), uint32_t idleTime, uint32_t debugFlags); +void EventDestroy(); + void EventDoMessageLoop(); HEVENTCONTEXT EventGetCurrentContext(); diff --git a/src/event/Queue.cpp b/src/event/Queue.cpp index 7aae11d..fa88e2e 100644 --- a/src/event/Queue.cpp +++ b/src/event/Queue.cpp @@ -51,7 +51,7 @@ void ResetSyncState(EvtContext* context) { auto list = &context->m_queueSyncKeyDownList; - while (node = list->Head()) { + while ((node = list->Head())) { list->UnlinkNode(node); list->DeleteNode(node); } diff --git a/src/event/Scheduler.cpp b/src/event/Scheduler.cpp index c7f1b17..71f98f6 100644 --- a/src/event/Scheduler.cpp +++ b/src/event/Scheduler.cpp @@ -1,4 +1,5 @@ #include "event/Scheduler.hpp" +#include "Event.hpp" #include "event/Context.hpp" #include "event/Event.hpp" #include "event/EvtContext.hpp" @@ -149,6 +150,18 @@ void IEvtSchedulerProcess() { void IEvtSchedulerShutdown() { // TODO + Event::s_shutdownEvent.Set(); + if (Event::s_netServer) { + return; + } + + Event::s_threadListCritsect.Enter(); + for (uint32_t i = 0; i < Event::s_threadSlotCount; i++) { + if (Event::s_threadSlots[i]) { + Event::s_threadSlots[i]->m_wakeEvent.Set(); + } + } + Event::s_threadListCritsect.Leave(); } uint32_t InitializeSchedulerThread() { diff --git a/src/event/Synthesize.cpp b/src/event/Synthesize.cpp index 59345cb..0e10c1f 100644 --- a/src/event/Synthesize.cpp +++ b/src/event/Synthesize.cpp @@ -1,19 +1,55 @@ #include "event/Synthesize.hpp" +#include "event/Event.hpp" +#include "event/Queue.hpp" +#include "event/Types.hpp" +#include "event/Scheduler.hpp" #include "event/EvtContext.hpp" #include "event/Queue.hpp" #include +#include #if defined(WHOA_SYSTEM_WIN) #include #endif void SynthesizeDestroy(EvtContext* context) { - // TODO -#if defined(WHOA_SYSTEM_WIN) - ExitProcess(0); -#else - exit(0); -#endif + if (!(context->m_schedFlags & 0x1)) { + context->m_schedFlags |= 0x1; + context->m_schedLastIdle = OsGetAsyncTimeMs(); + IEvtQueueDispatch(context, EVENT_ID_INITIALIZE, nullptr); + } + + if (context->m_schedFlags & 0x2) { + SInterlockedDecrement(&Event::s_interactiveCount); + if (!Event::s_interactiveCount) { + IEvtSchedulerShutdown(); + } + } + + IEvtQueueDispatch(context, EVENT_ID_3, nullptr); + context->m_critsect.Enter(); + context->m_schedState = EvtContext::SCHEDSTATE_DESTROYED; + context->m_critsect.Leave(); + IEvtQueueDispatchAll(context); + IEvtQueueDispatch(context, EVENT_ID_DESTROY, nullptr); + + OsCallResetContext(context->m_callContext); + PropSelectContext(0); + + int32_t findMask; + TSingletonInstanceId::s_idTable.Ptr( + context->m_id, + 1, + &findMask); + + DEL(context); + + if (findMask != -1) { + TSingletonInstanceId::s_idTable.Unlock( + findMask & (INSTANCE_TABLE_SLOT_COUNT - 1), + findMask >= INSTANCE_TABLE_SLOT_COUNT + ); + } } void SynthesizeIdle(EvtContext* context, uint32_t currTime, float elapsedSec) {