DqnTimer unix implementation

This commit is contained in:
Doyle Thai 2017-06-22 18:10:44 +10:00
parent f464e869ec
commit 187fc14d02
2 changed files with 462 additions and 369 deletions

179
dqn.h
View File

@ -18,7 +18,7 @@
// You can search by #<entry> to jump straight to the section. // You can search by #<entry> to jump straight to the section.
// The first match is the public API, the next matche(s) are the implementation // The first match is the public API, the next matche(s) are the implementation
// API > Portable Code // #Portable Code
// #DqnAssert Assertions // #DqnAssert Assertions
// #DqnMem Memory Allocation // #DqnMem Memory Allocation
// #DqnMemStack Memory Allocator, Push, Pop Style // #DqnMemStack Memory Allocator, Push, Pop Style
@ -36,18 +36,19 @@
// #DqnWStr WStr Operations (WStr_Len() etc) // #DqnWStr WStr Operations (WStr_Len() etc)
// #DqnRnd Random Number Generator (ints and floats) // #DqnRnd Random Number Generator (ints and floats)
// API > Cross Platform Code // #XPlatform (Win32 & Unix)
// #DqnFile File I/O (Read, Write, Delete) // #DqnFile File I/O (Read, Write, Delete)
// #DqnDir Directory Querying // #DqnDir Directory Querying
// #DqnTimer High Resolution Timer
// API > Win32 Only // #Platform
// #DqnTime Platform High Resolution Timer // - #Win32Platform
// #DqnLock Mutex Synchronisation // - #DqnLock Mutex Synchronisation
// #DqnAtomic Interlocks/Atomic Operations // - #DqnAtomic Interlocks/Atomic Operations
// #DqnJobQueue Multithreaded Job Queue // - #DqnJobQueue Multithreaded Job Queue
// #DqnWin32 Common Win32 API Helpers // - #DqnWin32 Common Win32 API Helpers
// API > External Code // #External Code
// #DqnIni Simple INI Config File API (Public Domain lib by Mattias Gustavsson) // #DqnIni Simple INI Config File API (Public Domain lib by Mattias Gustavsson)
// #DqnSprintf Cross-platform Sprintf Implementation (Public Domain lib stb_sprintf) // #DqnSprintf Cross-platform Sprintf Implementation (Public Domain lib stb_sprintf)
@ -58,15 +59,15 @@
// a platform implementation, platform specific implementations in the portable // a platform implementation, platform specific implementations in the portable
// layer will get activated. // layer will get activated.
#if (defined(_WIN32) || defined(_WIN64)) && defined(DQN_WIN32_IMPLEMENTATION) #if (defined(_WIN32) || defined(_WIN64)) && defined(DQN_WIN32_IMPLEMENTATION)
#define DQN_PLATFORM_LAYER #define DQN_XPLATFORM_LAYER
#define DQN_WIN32_PLATFORM #define DQN_WIN32_PLATFORM
#elif defined(__linux__) && defined(DQN_UNIX_IMPLEMENTATION) #elif defined(__linux__) && defined(DQN_UNIX_IMPLEMENTATION)
#define DQN_PLATFORM_LAYER #define DQN_XPLATFORM_LAYER
#define DQN_UNIX_PLATFORM #define DQN_UNIX_PLATFORM
#endif #endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Portable Layer // #Portable Code
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#ifndef DQN_H #ifndef DQN_H
#define DQN_H #define DQN_H
@ -893,26 +894,13 @@ DQN_FILE_SCOPE i32 DqnRnd_PCGRange(DqnRandPCGState *pcg, i32 min, i32 max);
#endif /* DQN_H */ #endif /* DQN_H */
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Cross-Platform Layer // #XPlatform (Win32 & Unix) Public API
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Functions in the Cross Platform are guaranteed to be supported in both Unix // Functions in the Cross Platform are guaranteed to be supported in both Unix
// and Win32 // and Win32
#ifdef DQN_PLATFORM_LAYER #ifdef DQN_XPLATFORM_LAYER
#ifdef DQN_WIN32_PLATFORM
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#endif
#ifdef DQN_UNIX_PLATFORM
#include <sys/stat.h>
#include <stdio.h> // Basic File I/O // TODO(doyle): Syscall versions
#include <unistd.h> // unlink()
#include <dirent.h> // readdir()/opendir()/closedir()
#endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Cross-Platform > #DqnFile Public API - File I/O // XPlatform > #DqnFile Public API - File I/O
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
enum DqnFilePermissionFlag enum DqnFilePermissionFlag
{ {
@ -964,6 +952,9 @@ DQN_FILE_SCOPE void DqnFile_Close(DqnFile *const file);
DQN_FILE_SCOPE bool DqnFile_Delete (const char *const path); DQN_FILE_SCOPE bool DqnFile_Delete (const char *const path);
DQN_FILE_SCOPE bool DqnFile_DeleteW(const wchar_t *const path); DQN_FILE_SCOPE bool DqnFile_DeleteW(const wchar_t *const path);
////////////////////////////////////////////////////////////////////////////////
// XPlatform > #DqnDir Public API - Directory Querying
////////////////////////////////////////////////////////////////////////////////
// numFiles: Pass in a pointer to a u32. The function fills it out with the number of entries. // numFiles: Pass in a pointer to a u32. The function fills it out with the number of entries.
// return: An array of strings of the files in the directory in UTF-8. The directory lisiting is // return: An array of strings of the files in the directory in UTF-8. The directory lisiting is
// allocated with malloc and must be freed using free() or the helper function DqnDir_ReadFree() // allocated with malloc and must be freed using free() or the helper function DqnDir_ReadFree()
@ -971,20 +962,27 @@ DQN_FILE_SCOPE char **DqnDir_Read (const char *const dir, u32 *const numFiles
DQN_FILE_SCOPE void DqnDir_ReadFree(char **fileList, u32 numFiles); DQN_FILE_SCOPE void DqnDir_ReadFree(char **fileList, u32 numFiles);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Platform Layer // XPlatform > #DqnTimer Public API - High Resolution Timer
////////////////////////////////////////////////////////////////////////////////
DQN_FILE_SCOPE f64 DqnTimer_NowInMs();
DQN_FILE_SCOPE f64 DqnTimer_NowInS ();
#endif // DQN_XPLATFORM_LAYER
////////////////////////////////////////////////////////////////////////////////
// #Platform Public API
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Functions here are only available for the #defined sections (i.e. all functions in // Functions here are only available for the #defined sections (i.e. all functions in
// DQN_WIN32_PLATFORM only have a valid implementation in Win32. // DQN_WIN32_PLATFORM only have a valid implementation in Win32.
////////////////////////////////////////////////////////////////////////////////
// #Win32Platform Public API
////////////////////////////////////////////////////////////////////////////////
#ifdef DQN_WIN32_PLATFORM #ifdef DQN_WIN32_PLATFORM
//////////////////////////////////////////////////////////////////////////////// #define WIN32_LEAN_AND_MEAN
// Platform > Win32 > #DqnTimer Public API - High Resolution Timer #include <Windows.h>
////////////////////////////////////////////////////////////////////////////////
DQN_FILE_SCOPE f64 DqnTime_NowInS();
DQN_FILE_SCOPE f64 DqnTime_NowInMs();
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Platform > Win32 > #DqnLock Public API - Mutex Synchronisation // Win32Platform > #DqnLock Public API - Mutex Synchronisation
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
typedef struct DqnLock typedef struct DqnLock
{ {
@ -997,14 +995,14 @@ DQN_FILE_SCOPE void DqnLock_Release(DqnLock *const lock);
DQN_FILE_SCOPE void DqnLock_Delete (DqnLock *const lock); DQN_FILE_SCOPE void DqnLock_Delete (DqnLock *const lock);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Platform > Win32 > #DqnAtomic Public API - Interlocks/Atomic Operations // Win32Platform > #DqnAtomic Public API - Interlocks/Atomic Operations
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
DQN_FILE_SCOPE u32 DqnAtomic_CompareSwap32(u32 volatile *dest, u32 swapVal, u32 compareVal); DQN_FILE_SCOPE u32 DqnAtomic_CompareSwap32(u32 volatile *dest, u32 swapVal, u32 compareVal);
DQN_FILE_SCOPE u32 DqnAtomic_Add32 (u32 volatile *src); DQN_FILE_SCOPE u32 DqnAtomic_Add32 (u32 volatile *src);
DQN_FILE_SCOPE u32 DqnAtomic_Sub32 (u32 volatile *src); DQN_FILE_SCOPE u32 DqnAtomic_Sub32 (u32 volatile *src);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Platform > Win32 > #DqnJobQueue Public API - Multithreaded Job Queue // Win32Platform > #DqnJobQueue Public API - Multithreaded Job Queue
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// DqnJobQueue is a platform abstracted "lockless" multithreaded work queue. It will create threads // DqnJobQueue is a platform abstracted "lockless" multithreaded work queue. It will create threads
// and assign threads to complete the job via the job "callback" using the "userData" supplied. // and assign threads to complete the job via the job "callback" using the "userData" supplied.
@ -1082,14 +1080,9 @@ DQN_FILE_SCOPE i32 DqnWin32_GetEXEDirectory(char *const buf, const u32 bufLen);
DQN_FILE_SCOPE void DqnWin32_GetNumThreadsAndCores(i32 *const numCores, i32 *const numThreadsPerCore); DQN_FILE_SCOPE void DqnWin32_GetNumThreadsAndCores(i32 *const numCores, i32 *const numThreadsPerCore);
#endif // DQN_WIN32_PLATFORM #endif // DQN_WIN32_PLATFORM
#ifdef DQN_UNIX_PLATFORM
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Platform > Unix // #External Code
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#endif
#endif // DQN_PLATFORM_LAYER
#ifndef DQN_INI_H #ifndef DQN_INI_H
#define DQN_INI_H #define DQN_INI_H
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -3657,6 +3650,9 @@ DQN_FILE_SCOPE i32 DqnRnd_PCGRange(DqnRandPCGState *pcg, i32 min, i32 max)
return min + value; return min + value;
} }
////////////////////////////////////////////////////////////////////////////////
// #External Code
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// #DqnSprintf Implementation - STB_Sprintf // #DqnSprintf Implementation - STB_Sprintf
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -5349,14 +5345,24 @@ void DqnIni_PropertyValueSet(DqnIni *ini, int section, int property,
#endif #endif
#endif // DQN_IMPLEMENTATION #endif // DQN_IMPLEMENTATION
#if defined(DQN_XPLATFORM_LAYER)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Cross-Platform Layer // #XPlatform (Win32 & Unix) Implementation
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Functions in the Cross Platform are guaranteed to be supported in both Unix // Functions in the Cross Platform are guaranteed to be supported in both Unix
// and Win32 // and Win32
#ifdef DQN_UNIX_PLATFORM
#include <sys/stat.h>
#include <sys/time.h>
#include <time.h>
#include <stdio.h> // Basic File I/O // TODO(doyle): Syscall versions
#include <unistd.h> // unlink()
#include <dirent.h> // readdir()/opendir()/closedir()
#endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Cross-Platform > #DqnFileInternal Implementation // XPlatform > #DqnFileInternal Implementation
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#ifdef DQN_WIN32_PLATFORM #ifdef DQN_WIN32_PLATFORM
FILE_SCOPE bool DqnFileInternal_Win32OpenW(const wchar_t *const path, FILE_SCOPE bool DqnFileInternal_Win32OpenW(const wchar_t *const path,
@ -5645,7 +5651,7 @@ DQN_FILE_SCOPE char **DqnDirInternal_PlatformRead(const char *const dir,
#endif // DQN_UNIX_PLATFORM #endif // DQN_UNIX_PLATFORM
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Cross-Platform > #DqnFile Implementation // XPlatform > #DqnFile Implementation
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
DQN_FILE_SCOPE DQN_FILE_SCOPE
bool DqnFile_Open(const char *const path, DqnFile *const file, bool DqnFile_Open(const char *const path, DqnFile *const file,
@ -5674,7 +5680,7 @@ bool DqnFile_OpenW(const wchar_t *const path, DqnFile *const file, const u32 per
{ {
if (!file || !path) return false; if (!file || !path) return false;
#ifdef DQN_WIN32_PLATFORM #if defined(DQN_WIN32_PLATFORM)
return DqnFileInternal_Win32OpenW(path, file, permissionFlags, action); return DqnFileInternal_Win32OpenW(path, file, permissionFlags, action);
#else #else
DQN_ASSERT(DQN_INVALID_CODE_PATH); DQN_ASSERT(DQN_INVALID_CODE_PATH);
@ -5780,7 +5786,7 @@ DQN_FILE_SCOPE bool DqnFile_Delete(const char *const path)
// TODO(doyle): Logging // TODO(doyle): Logging
#if defined(DQN_WIN32_PLATFORM) #if defined(DQN_WIN32_PLATFORM)
return DeleteFile(path); return DeleteFileA(path);
#elif defined(DQN_UNIX_PLATFORM) #elif defined(DQN_UNIX_PLATFORM)
i32 result = unlink(path); i32 result = unlink(path);
@ -5791,6 +5797,9 @@ DQN_FILE_SCOPE bool DqnFile_Delete(const char *const path)
#endif #endif
} }
////////////////////////////////////////////////////////////////////////////////
// XPlatform > #DqnDir Implementation
////////////////////////////////////////////////////////////////////////////////
DQN_FILE_SCOPE char **DqnDir_Read(const char *const dir, u32 *const numFiles) DQN_FILE_SCOPE char **DqnDir_Read(const char *const dir, u32 *const numFiles)
{ {
char **result = DqnDirInternal_PlatformRead(dir, numFiles); char **result = DqnDirInternal_PlatformRead(dir, numFiles);
@ -5812,13 +5821,10 @@ DQN_FILE_SCOPE void DqnDir_ReadFree(char **fileList, u32 numFiles)
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Platform Layer // XPlatform > #DqnTimer Implementation
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#ifdef DQN_WIN32_PLATFORM #if defined (DQN_WIN32_PLATFORM)
//////////////////////////////////////////////////////////////////////////////// FILE_SCOPE f64 DqnTimerInternal_Win32QueryPerfCounterTimeInMs()
// Platform > Win32 > #DqnTimer Implementation
////////////////////////////////////////////////////////////////////////////////
FILE_SCOPE f64 DqnTimeInternal_Win32QueryPerfCounterTimeInS()
{ {
LOCAL_PERSIST LARGE_INTEGER queryPerformanceFrequency = {0}; LOCAL_PERSIST LARGE_INTEGER queryPerformanceFrequency = {0};
if (queryPerformanceFrequency.QuadPart == 0) if (queryPerformanceFrequency.QuadPart == 0)
@ -5830,28 +5836,53 @@ FILE_SCOPE f64 DqnTimeInternal_Win32QueryPerfCounterTimeInS()
LARGE_INTEGER qpcResult; LARGE_INTEGER qpcResult;
QueryPerformanceCounter(&qpcResult); QueryPerformanceCounter(&qpcResult);
// Convert to ms // Convert to microseconds first then divide by ticks per second then to milliseconds
f64 timestamp = qpcResult.QuadPart *= 1000000;
qpcResult.QuadPart / (f64)queryPerformanceFrequency.QuadPart; f64 timestamp = qpcResult.QuadPart / (f64)queryPerformanceFrequency.QuadPart;
timestamp /= 1000.0f;
return timestamp; return timestamp;
} }
#endif
f64 DqnTime_NowInS() DQN_FILE_SCOPE f64 DqnTimer_NowInMs()
{ {
f64 result; f64 result = 0;
#ifdef DQN_WIN32_PLATFORM #if defined(DQN_WIN32_PLATFORM)
result = DQN_MAX(DqnTimeInternal_Win32QueryPerfCounterTimeInS(), 0); result = DQN_MAX(DqnTimerInternal_Win32QueryPerfCounterTimeInMs(), 0);
#elif defined(DQN_UNIX_PLATFORM)
struct timespec timeSpec = {0};
if (clock_gettime(CLOCK_MONOTONIC, &timeSpec))
{
// TODO(doyle): Failed logging
DQN_ASSERT_HARD(DQN_INVALID_CODE_PATH);
}
else
{
printf("tv_nsec: %ld\n", timeSpec.tv_nsec);
result = ((f64)timeSpec.tv_sec * 1000.0f) + ((f64)timeSpec.tv_nsec / 100000.0f);
}
#else #else
result = 0; DQN_ASSERT_MSG(DQN_INVALID_CODE_PATH, "Non Unix/Win32 path not implemented yet");
DQN_ASSERT_MSG(DQN_INVALID_CODE_PATH, "Non Win32 path not implemented yet");
#endif #endif
return result; return result;
}; };
f64 DqnTime_NowInMs() { return DqnTime_NowInS() * 1000.0f; } DQN_FILE_SCOPE f64 DqnTimer_NowInS() { return DqnTimer_NowInMs() / 1000.0f; }
#endif // DQN_XPLATFORM_LAYER
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Platform > Win32 > #DqnLock Implementation // #Platform Implementation
////////////////////////////////////////////////////////////////////////////////
#ifdef DQN_WIN32_PLATFORM
////////////////////////////////////////////////////////////////////////////////
// #Win32Platform Implementation
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Win32Platform > #DqnLock Implementation
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool DqnLock_Init(DqnLock *const lock, const u32 spinCount) bool DqnLock_Init(DqnLock *const lock, const u32 spinCount)
{ {
@ -5896,7 +5927,7 @@ void DqnLock_Delete(DqnLock *const lock)
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Platform > Win32 > #DqnAtomic Implementation // Win32Platform > #DqnAtomic Implementation
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
DQN_FILE_SCOPE u32 DqnAtomic_CompareSwap32(u32 volatile *dest, u32 swapVal, u32 compareVal) DQN_FILE_SCOPE u32 DqnAtomic_CompareSwap32(u32 volatile *dest, u32 swapVal, u32 compareVal)
{ {
@ -5936,7 +5967,7 @@ DQN_FILE_SCOPE u32 DqnAtomic_Sub32(u32 volatile *src)
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Platform > Win32 > #DqnJobQueue Implementation // Win32Platform > #DqnJobQueue Implementation
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
typedef struct DqnJobQueue typedef struct DqnJobQueue
{ {
@ -5953,7 +5984,7 @@ typedef struct DqnJobQueue
} DqnJobQueue; } DqnJobQueue;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Platform > Win32 > #DqnJobQueueInternal Implementation // Win32Platform > #DqnJobQueueInternal Implementation
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
size_t DQN_JOB_QUEUE_INTERNAL_THREAD_DEFAULT_STACK_SIZE = 0; size_t DQN_JOB_QUEUE_INTERNAL_THREAD_DEFAULT_STACK_SIZE = 0;
FILE_SCOPE u32 DqnJobQueueInternal_ThreadCreate(const size_t stackSize, void *threadCallback, FILE_SCOPE u32 DqnJobQueueInternal_ThreadCreate(const size_t stackSize, void *threadCallback,
@ -5998,7 +6029,7 @@ FILE_SCOPE u32 DqnJobQueueInternal_ThreadCallback(void *threadParam)
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Platform > Win32 > #DqnJobQueue Implementation // Win32Platform > #DqnJobQueue Implementation
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
DQN_FILE_SCOPE DqnJobQueue *DqnJobQueue_InitWithMem(const void *const mem, size_t *const memSize, DQN_FILE_SCOPE DqnJobQueue *DqnJobQueue_InitWithMem(const void *const mem, size_t *const memSize,
const u32 queueSize, const u32 numThreads) const u32 queueSize, const u32 numThreads)
@ -6095,7 +6126,7 @@ DQN_FILE_SCOPE bool DqnJobQueue_AllJobsComplete(DqnJobQueue *const queue)
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Platform > Win32 > #DqnWin32 Implementation // Win32Platform > #DqnWin32 Implementation
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
DQN_FILE_SCOPE bool DqnWin32_UTF8ToWChar(const char *const in, DQN_FILE_SCOPE bool DqnWin32_UTF8ToWChar(const char *const in,
wchar_t *const out, const i32 outLen) wchar_t *const out, const i32 outLen)
@ -6182,13 +6213,13 @@ DQN_FILE_SCOPE void DqnWin32_OutputDebugString(const char *const formatStr, ...)
} }
va_end(argList); va_end(argList);
OutputDebugString(str); OutputDebugStringA(str);
} }
DQN_FILE_SCOPE i32 DqnWin32_GetEXEDirectory(char *const buf, const u32 bufLen) DQN_FILE_SCOPE i32 DqnWin32_GetEXEDirectory(char *const buf, const u32 bufLen)
{ {
if (!buf || bufLen == 0) return 0; if (!buf || bufLen == 0) return 0;
u32 copiedLen = GetModuleFileName(NULL, buf, bufLen); u32 copiedLen = GetModuleFileNameA(NULL, buf, bufLen);
if (copiedLen == bufLen) return -1; if (copiedLen == bufLen) return -1;
// NOTE: Should always work if GetModuleFileName works and we're running an // NOTE: Should always work if GetModuleFileName works and we're running an

File diff suppressed because it is too large Load Diff