/* date = June 19th 2023 7:27 pm */ #ifndef CORE_H #define CORE_H #include //#include #include #include //- sixten: Base types typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; typedef uint64_t u64; typedef int8_t s8; typedef int16_t s16; typedef int32_t s32; typedef int64_t s64; typedef float r32; typedef double r64; typedef u8 b8; typedef u16 b16; typedef u32 b32; typedef uintptr_t umm; typedef intptr_t smm; //- sixten: Base type limits #define U8_Min 0x00 #define U8_Max 0xFF #define U16_Min 0x0000 #define U16_Max 0xFFFF #define U32_Min 0x00000000 #define U32_Max 0xFFFFFFFF #define U64_Min 0x0000000000000000 #define U64_Max 0xFFFFFFFFFFFFFFFF #define S8_Min 0x80 #define S8_Max 0x7F #define S16_Min 0x8000 #define S16_Max 0x7FFF #define S32_Min 0x80000000 #define S32_Max 0x7FFFFFFF #define S64_Min 0x8000000000000000 #define S64_Max 0x7FFFFFFFFFFFFFFF //- sixten: Keywords #define global static #define persist static #if _WIN32 # pragma section(".roglob", read) # define read_only __declspec(allocate(".roglob")) #else # define read_only #endif #if _WIN32 # define per_thread __declspec(thread) #else # define per_thread __thread #endif #define fallthrough //- sixten: Assertions & debugging #if VN_SLOW #define Assert(Statement) if(!(Statement)) { *(int *)0 = 0; } #else #define Assert(Statement) #endif #define CTAssert(Statement) static_assert(Statement) #define InvokeDebugger __debugbreak() #define UnimplementedCodepath Assert(!"Unimplemented codepath") #define InvalidCodepath Assert(!"Invalid codepath") #define InvalidDefaultCase default: { Assert(!"Invalid codepath"); } break //- sixten: Compiler warning helpers #define UnusedVariable(Var) ((void)(Var)) //- sixten: Array & pointer manipulation #define ArrayCount(Array) (sizeof(Array)/sizeof((Array)[0])) #define OffsetOf(type, Member) (umm) &(((type *)0)->Member) #define PointerToU64(x) ((u64)(void *)x) #define U64ToPointer(x) ((void *)(u64)x) #define FindIndexOfElement(Index, Array, Default, ToFind)\ Index = Default;\ for(s64 ___ = 0; ___ < ArrayCount(Array); ++___)\ {\ if(Array[___] == ToFind)\ {\ Index = ___; break;\ }\ }\ #define Bytes(n) (n) #define Kilobytes(n) (n << 10) #define Megabytes(n) (n << 20) #define Gigabytes(n) (((u64)n) << 30) #define Terabytes(n) (((u64)n) << 40) //- sixten: Min, max & clamp #define Minimum(A, B) (((A)<(B))?(A):(B)) #define Maximum(A, B) (((A)>(B))?(A):(B)) #define Clamp(Value, Min, Max) Minimum(Maximum(Value, Min), Max) #define Clamp01(Value) Clamp(Value, 0, 1) //- sixten: Linked list helpers #define IsNull(x) ((x) == 0) #define SetNull(x) ((x) = 0) #define QueuePush_N(f,l,n,next) (IsNull(f)?\ (((f)=(l)=(n)), SetNull((n)->next)):\ ((l)->next=(n),(l)=(n),SetNull((n)->next))) #define QueuePushFront_N(f,l,n,next) (IsNull(f) ? (((f) = (l) = (n)), SetNull((n)->next)) :\ ((n)->next = (f)), ((f) = (n))) #define QueuePop_N(f,l,next) ((f)==(l)?\ (SetNull(f),SetNull(l)):\ ((f)=(f)->next)) #define StackPush_N(f,n,next) ((n)->next=(f),(f)=(n)) #define StackPop_N(f,next) (IsNull(f)?0:((f)=(f)->next)) #define QueuePush(f,l,n) QueuePush_N(f,l,n,Next) #define QueuePushFront(f,l,n) QueuePushFront_N(f,l,n,Next) #define QueuePop(f,l) QueuePop_N(f,l,Next) #define StackPush(f,n) StackPush_N(f,n,Next) #define StackPop(f) StackPop_N(f,Next) #define DLLInsert_NP(f,l,p,n,next,prev) \ (IsNull(f) ? (((f) = (l) = (n)), SetNull((n)->next), SetNull((n)->prev)) :\ IsNull(p) ? (SetNull((n)->prev), (n)->next = (f), (IsNull(f) ? (0) : ((f)->prev = (n))), (f) = (n)) :\ ((IsNull((p)->next) ? (0) : (((p)->next->prev) = (n))), (n)->next = (p)->next, (n)->prev = (p), (p)->next = (n),\ ((p) == (l) ? (l) = (n) : (0)))) #define DLLInsertLast_NP(f,l,n,next,prev) DLLInsert_NP(f,l,l,n,next,prev) #define DLLInsertFirst_NP(f,l,n,next,prev) DLLInsert_NP(l,f,f,n,prev,next) #define DLLRemove_NP(f,l,n,next,prev)\ (((f)==(n))?\ ((f)=(f)->next, (IsNull(f) ? (SetNull(l)) : SetNull((f)->prev))):\ ((l)==(n))?\ ((l)=(l)->prev, (IsNull(l) ? (SetNull(f)) : SetNull((l)->next))):\ ((IsNull((n)->next) ? (0) : ((n)->next->prev=(n)->prev)),\ (IsNull((n)->prev) ? (0) : ((n)->prev->next=(n)->next)))) #define DLLInsertFirst(First, Last, Element) DLLInsertFirst_NP(First, Last, Element, Next, Prev) #define DLLInsertLast(First, Last, Element) DLLInsertLast_NP(First, Last, Element, Next, Prev) #define DLLRemove(First, Last, Element) DLLRemove_NP(First, Last, Element, Next, Prev) #define DLLIsEmpty(First) ((First) == 0) #define SenDLLInit(Sentinel)\ do { (Sentinel)->Next = (Sentinel); (Sentinel)->Prev = (Sentinel); } while(0) #define SenDLLInsertFirst(Sentinel, Element)\ (Element)->Next = (Sentinel)->Next;\ (Element)->Prev = (Sentinel);\ (Element)->Next->Prev = (Element);\ (Element)->Prev->Next = (Element); #define SenDLLInsertLast(Sentinel, Element)\ (Element)->Next = (Sentinel);\ (Element)->Prev = (Sentinel)->Prev;\ (Element)->Next->Prev = (Element);\ (Element)->Prev->Next = (Element); #define SenDLLRemove(Element)\ auto __Temp = (Element)->Next->Prev;\ (Element)->Next->Prev = (Element)->Prev->Next;\ (Element)->Prev->Next = __Temp; #define SenDLLIsEmpty(Sentinel)\ ((Sentinel)->Next==(Sentinel)) //- sixten: Stringify #define _Stringify(x) #x #define Stringify(x) _Stringify(x) //- sixten: Defer loop #define DeferLoop(Start, End) for(s32 ___ = ((Start), 0); ___ == 0; ++___, (End)) #if 0 //- sixten: Atomics inline u64 AtomicExchangeU64(u64 volatile *Value, u64 New) { u64 Result = _InterlockedExchange64((__int64 volatile *)Value, New); return(Result); } inline u64 AtomicAddU64(u64 volatile *Value, u64 Addend) { u64 Result = _InterlockedExchangeAdd64((__int64 volatile *)Value, Addend); return(Result); } // sixten: Memory mutexes struct ticket_mutex { u64 volatile Ticket; u64 volatile Serving; }; inline void BeginTicketMutex(ticket_mutex *Mutex) { u64 Ticket = AtomicAddU64(&Mutex->Ticket, 1); while(Ticket != Mutex->Serving) { _mm_pause(); } } inline void EndTicketMutex(ticket_mutex *Mutex) { AtomicAddU64(&Mutex->Serving, 1); } #endif //- sixten: Axes enum axis2 { Axis2_X = 0, Axis2_Y = 1, Axis2_Count }; inline axis2 Opposite(axis2 Axis) { axis2 Result = (axis2)(!(u32)Axis); return(Result); } //////////////////////////////// //- sixten: Corners enum corner { Corner_00 = 0, Corner_10 = (1 << Axis2_X), Corner_01 = (1 << Axis2_Y), Corner_11 = (1 << Axis2_X)|(1 << Axis2_Y), Corner_Count, }; #endif //CORE_H