Split up Gamecube and Wii backends more

This commit is contained in:
UnknownShadow200 2025-12-12 20:45:06 +11:00
parent 1cdc87082f
commit 119cacac0d
19 changed files with 335 additions and 209 deletions

View File

@ -253,6 +253,10 @@ void Thread_Join(void* handle) {
threadFree(thread);
}
/*########################################################################################################################*
*-----------------------------------------------------Synchronisation-----------------------------------------------------*
*#########################################################################################################################*/
void* Mutex_Create(const char* name) {
LightLock* lock = (LightLock*)Mem_Alloc(1, sizeof(LightLock), "mutex");
LightLock_Init(lock);

View File

@ -60,7 +60,14 @@ void Thread_Join(void* handle) {
thread_id thread = (thread_id)handle;
wait_for_thread(thread, NULL);
}
#endif
/*########################################################################################################################*
*-----------------------------------------------------Synchronisation-----------------------------------------------------*
*#########################################################################################################################*/
// NOTE: BeOS only, as haiku uses the more efficient pthreads implementation in Platform_Posix.c
#if defined CC_BUILD_BEOS
void* Mutex_Create(const char* name) {
sem_id id = create_sem(1, name);
return (void*)id;

View File

@ -389,6 +389,10 @@ void Thread_Join(void* handle) {
Thread_Detach(handle);
}
/*########################################################################################################################*
*-----------------------------------------------------Synchronisation-----------------------------------------------------*
*#########################################################################################################################*/
void* Mutex_Create(const char* name) {
CRITICAL_SECTION* ptr = (CRITICAL_SECTION*)Mem_Alloc(1, sizeof(CRITICAL_SECTION), "mutex");
InitializeCriticalSection(ptr);

View File

@ -452,6 +452,10 @@ void Thread_Join(void* handle) {
#endif
}
/*########################################################################################################################*
*-----------------------------------------------------Synchronisation-----------------------------------------------------*
*#########################################################################################################################*/
void* Mutex_Create(const char* name) {
CRITICAL_SECTION* ptr = (CRITICAL_SECTION*)Mem_Alloc(1, sizeof(CRITICAL_SECTION), "mutex");
InitializeCriticalSection(ptr);

View File

@ -368,6 +368,10 @@ void Thread_Join(void* handle) {
Thread_Detach(handle);
}
/*########################################################################################################################*
*-----------------------------------------------------Synchronisation-----------------------------------------------------*
*#########################################################################################################################*/
void* Mutex_Create(const char* name) {
CRITICAL_SECTION* ptr = (CRITICAL_SECTION*)Mem_Alloc(1, sizeof(CRITICAL_SECTION), "mutex");
InitializeCriticalSection(ptr);

View File

@ -513,6 +513,10 @@ void Thread_Join(void* handle) {
thd_join((kthread_t*)handle, NULL);
}
/*########################################################################################################################*
*-----------------------------------------------------Synchronisation-----------------------------------------------------*
*#########################################################################################################################*/
void* Mutex_Create(const char* name) {
mutex_t* ptr = (mutex_t*)Mem_Alloc(1, sizeof(mutex_t), "mutex");
int res = mutex_init(ptr, MUTEX_TYPE_NORMAL);

View File

@ -1,73 +1,3 @@
/*########################################################################################################################*
*------------------------------------------------------Logging/Time-------------------------------------------------------*
*#########################################################################################################################*/
#ifdef HW_RVL
static void LogOverEXI(char* msg, int len) {
u32 cmd = 0x80000000 | (0x800400 << 6); // write flag, UART base address
// https://hitmen.c02.at/files/yagcd/yagcd/chap10.html
// Try to acquire "MASK ROM"/"IPL" link
// Writing to the IPL is used for debug message logging
if (EXI_Lock(EXI_CHANNEL_0, EXI_DEVICE_1, NULL) == 0) return;
if (EXI_Select(EXI_CHANNEL_0, EXI_DEVICE_1, EXI_SPEED8MHZ) == 0) {
EXI_Unlock(EXI_CHANNEL_0); return;
}
EXI_Imm( EXI_CHANNEL_0, &cmd, 4, EXI_WRITE, NULL);
EXI_Sync( EXI_CHANNEL_0);
EXI_ImmEx( EXI_CHANNEL_0, msg, len, EXI_WRITE);
EXI_Deselect(EXI_CHANNEL_0);
EXI_Unlock( EXI_CHANNEL_0);
}
void Platform_Log(const char* msg, int len) {
char tmp[256 + 1];
len = min(len, 256);
// See EXI_DeviceIPL.cpp in Dolphin, \r is what triggers buffered message to be logged
Mem_Copy(tmp, msg, len); tmp[len] = '\r';
LogOverEXI(tmp, len + 1);
}
#else
void Platform_Log(const char* msg, int len) {
SYS_Report("%.*s\n", len, msg);
}
#endif
TimeMS DateTime_CurrentUTC(void) {
struct timeval cur;
gettimeofday(&cur, NULL);
return (cc_uint64)cur.tv_sec + UNIX_EPOCH_SECONDS;
}
void DateTime_CurrentLocal(struct cc_datetime* t) {
struct timeval cur;
struct tm loc_time;
gettimeofday(&cur, NULL);
localtime_r(&cur.tv_sec, &loc_time);
t->year = loc_time.tm_year + 1900;
t->month = loc_time.tm_mon + 1;
t->day = loc_time.tm_mday;
t->hour = loc_time.tm_hour;
t->minute = loc_time.tm_min;
t->second = loc_time.tm_sec;
}
cc_uint64 Stopwatch_Measure(void) {
#ifdef HW_RVL
return SYS_Time();
#else
return __SYS_GetSystemTime();
#endif
}
cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) {
if (end < beg) return 0;
return ticks_to_microsecs(end - beg);
}
/*########################################################################################################################*
*-------------------------------------------------------Crash handling----------------------------------------------------*
*#########################################################################################################################*/
@ -246,145 +176,6 @@ void Thread_Join(void* handle) {
Mem_Free(ptr);
}
void* Mutex_Create(const char* name) {
mutex_t* ptr = (mutex_t*)Mem_Alloc(1, sizeof(mutex_t), "mutex");
int res = LWP_MutexInit(ptr, false);
if (res) Process_Abort2(res, "Creating mutex");
return ptr;
}
void Mutex_Free(void* handle) {
mutex_t* mutex = (mutex_t*)handle;
int res = LWP_MutexDestroy(*mutex);
if (res) Process_Abort2(res, "Destroying mutex");
Mem_Free(handle);
}
void Mutex_Lock(void* handle) {
mutex_t* mutex = (mutex_t*)handle;
int res = LWP_MutexLock(*mutex);
if (res) Process_Abort2(res, "Locking mutex");
}
void Mutex_Unlock(void* handle) {
mutex_t* mutex = (mutex_t*)handle;
int res = LWP_MutexUnlock(*mutex);
if (res) Process_Abort2(res, "Unlocking mutex");
}
#ifdef HW_RVL
// should really use a semaphore with max 1.. too bad no 'TimedWait' though
struct WaitData {
cond_t cond;
mutex_t mutex;
int signalled; // For when Waitable_Signal is called before Waitable_Wait
};
void* Waitable_Create(const char* name) {
struct WaitData* ptr = (struct WaitData*)Mem_Alloc(1, sizeof(struct WaitData), "waitable");
int res;
res = LWP_CondInit(&ptr->cond);
if (res) Process_Abort2(res, "Creating waitable");
res = LWP_MutexInit(&ptr->mutex, false);
if (res) Process_Abort2(res, "Creating waitable mutex");
ptr->signalled = false;
return ptr;
}
void Waitable_Free(void* handle) {
struct WaitData* ptr = (struct WaitData*)handle;
int res;
res = LWP_CondDestroy(ptr->cond);
if (res) Process_Abort2(res, "Destroying waitable");
res = LWP_MutexDestroy(ptr->mutex);
if (res) Process_Abort2(res, "Destroying waitable mutex");
Mem_Free(handle);
}
void Waitable_Signal(void* handle) {
struct WaitData* ptr = (struct WaitData*)handle;
int res;
Mutex_Lock(&ptr->mutex);
ptr->signalled = true;
Mutex_Unlock(&ptr->mutex);
res = LWP_CondSignal(ptr->cond);
if (res) Process_Abort2(res, "Signalling event");
}
void Waitable_Wait(void* handle) {
struct WaitData* ptr = (struct WaitData*)handle;
int res;
Mutex_Lock(&ptr->mutex);
if (!ptr->signalled) {
res = LWP_CondWait(ptr->cond, ptr->mutex);
if (res) Process_Abort2(res, "Waitable wait");
}
ptr->signalled = false;
Mutex_Unlock(&ptr->mutex);
}
void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
struct WaitData* ptr = (struct WaitData*)handle;
struct timespec ts;
int res;
ts.tv_sec = milliseconds / TB_MSPERSEC;
ts.tv_nsec = (milliseconds % TB_MSPERSEC) * TB_NSPERMS;
Mutex_Lock(&ptr->mutex);
if (!ptr->signalled) {
res = LWP_CondTimedWait(ptr->cond, ptr->mutex, &ts);
if (res && res != ETIMEDOUT) Process_Abort2(res, "Waitable wait for");
}
ptr->signalled = false;
Mutex_Unlock(&ptr->mutex);
}
#else
void* Waitable_Create(const char* name) {
sem_t* ptr = (sem_t*)Mem_Alloc(1, sizeof(sem_t), "waitable");
int res = LWP_SemInit(ptr, 0, 1);
if (res) Process_Abort2(res, "Creating waitable");
return ptr;
}
void Waitable_Free(void* handle) {
sem_t* ptr = (sem_t*)handle;
int res = LWP_SemDestroy(*ptr);
if (res) Process_Abort2(res, "Destroying waitable");
Mem_Free(handle);
}
void Waitable_Signal(void* handle) {
sem_t* ptr = (sem_t*)handle;
int res = LWP_SemPost(*ptr);
if (res && res != EOVERFLOW) Process_Abort2(res, "Signalling event");
}
void Waitable_Wait(void* handle) {
sem_t* ptr = (sem_t*)handle;
int res = LWP_SemWait(*ptr);
if (res) Process_Abort2(res, "Event wait");
}
void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
sem_t* ptr = (sem_t*)handle;
struct timespec ts;
int res;
ts.tv_sec = milliseconds / TB_MSPERSEC;
ts.tv_nsec = (milliseconds % TB_MSPERSEC) * TB_NSPERMS;
res = LWP_SemTimedWait(*ptr, &ts);
if (res && res != ETIMEDOUT) Process_Abort2(res, "Event timed wait");
}
#endif
/*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------*

View File

@ -59,6 +59,43 @@ int main(int argc, char** argv) {
}
/*########################################################################################################################*
*------------------------------------------------------Logging/Time-------------------------------------------------------*
*#########################################################################################################################*/
void Platform_Log(const char* msg, int len) {
SYS_Report("%.*s\n", len, msg);
}
TimeMS DateTime_CurrentUTC(void) {
struct timeval cur;
gettimeofday(&cur, NULL);
return (cc_uint64)cur.tv_sec + UNIX_EPOCH_SECONDS;
}
void DateTime_CurrentLocal(struct cc_datetime* t) {
struct timeval cur;
struct tm loc_time;
gettimeofday(&cur, NULL);
localtime_r(&cur.tv_sec, &loc_time);
t->year = loc_time.tm_year + 1900;
t->month = loc_time.tm_mon + 1;
t->day = loc_time.tm_mday;
t->hour = loc_time.tm_hour;
t->minute = loc_time.tm_min;
t->second = loc_time.tm_sec;
}
cc_uint64 Stopwatch_Measure(void) {
return __SYS_GetSystemTime();
}
cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) {
if (end < beg) return 0;
return ticks_to_microsecs(end - beg);
}
/*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/
@ -133,6 +170,74 @@ static void InitSockets(void) {
}
/*########################################################################################################################*
*-----------------------------------------------------Synchronisation-----------------------------------------------------*
*#########################################################################################################################*/
void* Mutex_Create(const char* name) {
mutex_t* ptr = (mutex_t*)Mem_Alloc(1, sizeof(mutex_t), "mutex");
int res = LWP_MutexInit(ptr, false);
if (res) Process_Abort2(res, "Creating mutex");
return ptr;
}
void Mutex_Free(void* handle) {
mutex_t* mutex = (mutex_t*)handle;
int res = LWP_MutexDestroy(*mutex);
if (res) Process_Abort2(res, "Destroying mutex");
Mem_Free(handle);
}
void Mutex_Lock(void* handle) {
mutex_t* mutex = (mutex_t*)handle;
int res = LWP_MutexLock(*mutex);
if (res) Process_Abort2(res, "Locking mutex");
}
void Mutex_Unlock(void* handle) {
mutex_t* mutex = (mutex_t*)handle;
int res = LWP_MutexUnlock(*mutex);
if (res) Process_Abort2(res, "Unlocking mutex");
}
void* Waitable_Create(const char* name) {
sem_t* ptr = (sem_t*)Mem_Alloc(1, sizeof(sem_t), "waitable");
int res = LWP_SemInit(ptr, 0, 1);
if (res) Process_Abort2(res, "Creating waitable");
return ptr;
}
void Waitable_Free(void* handle) {
sem_t* ptr = (sem_t*)handle;
int res = LWP_SemDestroy(*ptr);
if (res) Process_Abort2(res, "Destroying waitable");
Mem_Free(handle);
}
void Waitable_Signal(void* handle) {
sem_t* ptr = (sem_t*)handle;
int res = LWP_SemPost(*ptr);
if (res && res != EOVERFLOW) Process_Abort2(res, "Signalling event");
}
void Waitable_Wait(void* handle) {
sem_t* ptr = (sem_t*)handle;
int res = LWP_SemWait(*ptr);
if (res) Process_Abort2(res, "Event wait");
}
void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
sem_t* ptr = (sem_t*)handle;
struct timespec ts;
int res;
ts.tv_sec = milliseconds / TB_MSPERSEC;
ts.tv_nsec = (milliseconds % TB_MSPERSEC) * TB_NSPERMS;
res = LWP_SemTimedWait(*ptr, &ts);
if (res && res != ETIMEDOUT) Process_Abort2(res, "Event timed wait");
}
/*########################################################################################################################*
*-------------------------------------------------------Encryption--------------------------------------------------------*
*#########################################################################################################################*/

View File

@ -61,6 +61,66 @@ int main(int argc, char** argv) {
}
/*########################################################################################################################*
*------------------------------------------------------Logging/Time-------------------------------------------------------*
*#########################################################################################################################*/
static void LogOverEXI(char* msg, int len) {
u32 cmd = 0x80000000 | (0x800400 << 6); // write flag, UART base address
// https://hitmen.c02.at/files/yagcd/yagcd/chap10.html
// Try to acquire "MASK ROM"/"IPL" link
// Writing to the IPL is used for debug message logging
if (EXI_Lock(EXI_CHANNEL_0, EXI_DEVICE_1, NULL) == 0) return;
if (EXI_Select(EXI_CHANNEL_0, EXI_DEVICE_1, EXI_SPEED8MHZ) == 0) {
EXI_Unlock(EXI_CHANNEL_0); return;
}
EXI_Imm( EXI_CHANNEL_0, &cmd, 4, EXI_WRITE, NULL);
EXI_Sync( EXI_CHANNEL_0);
EXI_ImmEx( EXI_CHANNEL_0, msg, len, EXI_WRITE);
EXI_Deselect(EXI_CHANNEL_0);
EXI_Unlock( EXI_CHANNEL_0);
}
void Platform_Log(const char* msg, int len) {
char tmp[256 + 1];
len = min(len, 256);
// See EXI_DeviceIPL.cpp in Dolphin, \r is what triggers buffered message to be logged
Mem_Copy(tmp, msg, len); tmp[len] = '\r';
LogOverEXI(tmp, len + 1);
}
TimeMS DateTime_CurrentUTC(void) {
struct timeval cur;
gettimeofday(&cur, NULL);
return (cc_uint64)cur.tv_sec + UNIX_EPOCH_SECONDS;
}
void DateTime_CurrentLocal(struct cc_datetime* t) {
struct timeval cur;
struct tm loc_time;
gettimeofday(&cur, NULL);
localtime_r(&cur.tv_sec, &loc_time);
t->year = loc_time.tm_year + 1900;
t->month = loc_time.tm_mon + 1;
t->day = loc_time.tm_mday;
t->hour = loc_time.tm_hour;
t->minute = loc_time.tm_min;
t->second = loc_time.tm_sec;
}
cc_uint64 Stopwatch_Measure(void) {
return SYS_Time();
}
cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) {
if (end < beg) return 0;
return ticks_to_microsecs(end - beg);
}
/*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/
@ -119,6 +179,109 @@ static void InitSockets(void) {
}
/*########################################################################################################################*
*-----------------------------------------------------Synchronisation-----------------------------------------------------*
*#########################################################################################################################*/
void* Mutex_Create(const char* name) {
mutex_t* ptr = (mutex_t*)Mem_Alloc(1, sizeof(mutex_t), "mutex");
int res = LWP_MutexInit(ptr, false);
if (res) Process_Abort2(res, "Creating mutex");
return ptr;
}
void Mutex_Free(void* handle) {
mutex_t* mutex = (mutex_t*)handle;
int res = LWP_MutexDestroy(*mutex);
if (res) Process_Abort2(res, "Destroying mutex");
Mem_Free(handle);
}
void Mutex_Lock(void* handle) {
mutex_t* mutex = (mutex_t*)handle;
int res = LWP_MutexLock(*mutex);
if (res) Process_Abort2(res, "Locking mutex");
}
void Mutex_Unlock(void* handle) {
mutex_t* mutex = (mutex_t*)handle;
int res = LWP_MutexUnlock(*mutex);
if (res) Process_Abort2(res, "Unlocking mutex");
}
// should really use a semaphore with max 1.. too bad no 'TimedWait' though
struct WaitData {
cond_t cond;
mutex_t mutex;
int signalled; // For when Waitable_Signal is called before Waitable_Wait
};
void* Waitable_Create(const char* name) {
struct WaitData* ptr = (struct WaitData*)Mem_Alloc(1, sizeof(struct WaitData), "waitable");
int res;
res = LWP_CondInit(&ptr->cond);
if (res) Process_Abort2(res, "Creating waitable");
res = LWP_MutexInit(&ptr->mutex, false);
if (res) Process_Abort2(res, "Creating waitable mutex");
ptr->signalled = false;
return ptr;
}
void Waitable_Free(void* handle) {
struct WaitData* ptr = (struct WaitData*)handle;
int res;
res = LWP_CondDestroy(ptr->cond);
if (res) Process_Abort2(res, "Destroying waitable");
res = LWP_MutexDestroy(ptr->mutex);
if (res) Process_Abort2(res, "Destroying waitable mutex");
Mem_Free(handle);
}
void Waitable_Signal(void* handle) {
struct WaitData* ptr = (struct WaitData*)handle;
int res;
Mutex_Lock(&ptr->mutex);
ptr->signalled = true;
Mutex_Unlock(&ptr->mutex);
res = LWP_CondSignal(ptr->cond);
if (res) Process_Abort2(res, "Signalling event");
}
void Waitable_Wait(void* handle) {
struct WaitData* ptr = (struct WaitData*)handle;
int res;
Mutex_Lock(&ptr->mutex);
if (!ptr->signalled) {
res = LWP_CondWait(ptr->cond, ptr->mutex);
if (res) Process_Abort2(res, "Waitable wait");
}
ptr->signalled = false;
Mutex_Unlock(&ptr->mutex);
}
void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
struct WaitData* ptr = (struct WaitData*)handle;
struct timespec ts;
int res;
ts.tv_sec = milliseconds / TB_MSPERSEC;
ts.tv_nsec = (milliseconds % TB_MSPERSEC) * TB_NSPERMS;
Mutex_Lock(&ptr->mutex);
if (!ptr->signalled) {
res = LWP_CondTimedWait(ptr->cond, ptr->mutex, &ts);
if (res && res != ETIMEDOUT) Process_Abort2(res, "Waitable wait for");
}
ptr->signalled = false;
Mutex_Unlock(&ptr->mutex);
}
/*########################################################################################################################*
*-------------------------------------------------------Encryption--------------------------------------------------------*
*#########################################################################################################################*/

View File

@ -413,6 +413,10 @@ void Thread_Detach(void* handle) {
void Thread_Join(void* handle) {
}
/*########################################################################################################################*
*-----------------------------------------------------Synchronisation-----------------------------------------------------*
*#########################################################################################################################*/
void* Mutex_Create(const char* name) {
return NULL;
}

View File

@ -346,6 +346,10 @@ void Thread_Join(void* handle) {
}
}
/*########################################################################################################################*
*-----------------------------------------------------Synchronisation-----------------------------------------------------*
*#########################################################################################################################*/
void* Mutex_Create(const char* name) {
ee_sema_t sema = { 0 };
sema.init_count = 1;

View File

@ -294,6 +294,10 @@ void Thread_Join(void* handle) {
Mem_Free(thread);
}
/*########################################################################################################################*
*-----------------------------------------------------Synchronisation-----------------------------------------------------*
*#########################################################################################################################*/
void* Mutex_Create(const char* name) {
sys_mutex_attr_t attr;
sysMutexAttrInitialize(attr);

View File

@ -284,6 +284,10 @@ void Thread_Join(void* handle) {
Mem_Free(ptr);
}
/*########################################################################################################################*
*-----------------------------------------------------Synchronisation-----------------------------------------------------*
*#########################################################################################################################*/
void* Mutex_Create(const char* name) {
pthread_mutex_t* ptr = (pthread_mutex_t*)Mem_Alloc(1, sizeof(pthread_mutex_t), "mutex");
int res = pthread_mutex_init(ptr, NULL);

View File

@ -270,6 +270,10 @@ void Thread_Join(void* handle) {
sceKernelDeleteThread((int)handle);
}
/*########################################################################################################################*
*-----------------------------------------------------Synchronisation-----------------------------------------------------*
*#########################################################################################################################*/
void* Mutex_Create(const char* name) {
SceLwMutexWorkarea* ptr = (SceLwMutexWorkarea*)Mem_Alloc(1, sizeof(SceLwMutexWorkarea), "mutex");
int res = sceKernelCreateLwMutex(ptr, name, 0, 0, NULL);

View File

@ -250,6 +250,10 @@ void Thread_Join(void* handle) {
sceKernelDeleteThread((int)handle);
}
/*########################################################################################################################*
*-----------------------------------------------------Synchronisation-----------------------------------------------------*
*#########################################################################################################################*/
void* Mutex_Create(const char* name) {
SceKernelLwMutexWork* ptr = (SceKernelLwMutexWork*)Mem_Alloc(1, sizeof(SceKernelLwMutexWork), "mutex");
int res = sceKernelCreateLwMutex(ptr, name, 0, 0, NULL);

View File

@ -340,6 +340,10 @@ void Thread_Join(void* handle) {
Mem_Free(ptr);
}
/*########################################################################################################################*
*-----------------------------------------------------Synchronisation-----------------------------------------------------*
*#########################################################################################################################*/
void* Mutex_Create(const char* name) {
RMutex* mutex = new RMutex;
if (!mutex) Process_Abort("Creating mutex");

View File

@ -284,6 +284,10 @@ void Thread_Join(void* handle) {
OSJoinThread((OSThread*)handle, &result);
}
/*########################################################################################################################*
*-----------------------------------------------------Synchronisation-----------------------------------------------------*
*#########################################################################################################################*/
void* Mutex_Create(const char* name) {
OSFastMutex* mutex = (OSFastMutex*)Mem_Alloc(1, sizeof(OSFastMutex), "mutex");

View File

@ -284,6 +284,10 @@ void Thread_Join(void* handle) {
Thread_Detach(handle);
}
/*########################################################################################################################*
*-----------------------------------------------------Synchronisation-----------------------------------------------------*
*#########################################################################################################################*/
void* Mutex_Create(const char* name) {
CRITICAL_SECTION* ptr = (CRITICAL_SECTION*)Mem_Alloc(1, sizeof(CRITICAL_SECTION), "mutex");
RtlInitializeCriticalSection(ptr);

View File

@ -248,6 +248,10 @@ void Thread_Detach(void* handle) {// TODO
void Thread_Join(void* handle) {// TODO
}
/*########################################################################################################################*
*-----------------------------------------------------Synchronisation-----------------------------------------------------*
*#########################################################################################################################*/
void* Mutex_Create(const char* name) {
return Mem_AllocCleared(1, sizeof(int), "mutex");
}