You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
677 lines
17 KiB
C
677 lines
17 KiB
C
// The Digital Grove Codebase
|
|
// Copyright (c) Ryan Fleury. All rights reserved.
|
|
|
|
#ifndef BASE_H
|
|
#define BASE_H
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Context Cracking
|
|
|
|
//- rjf: MSVC Extraction
|
|
|
|
#if defined(_MSC_VER)
|
|
|
|
# define COMPILER_MSVC 1
|
|
|
|
# if defined(_WIN32)
|
|
# define PLATFORM_WINDOWS 1
|
|
# else
|
|
# error _MSC_VER is defined, but _WIN32 is not. This setup is not supported.
|
|
# endif
|
|
|
|
# if defined(_M_AMD64)
|
|
# define ARCH_X64 1
|
|
# elif defined(_M_IX86)
|
|
# define ARCH_X86 1
|
|
# elif defined(_M_ARM64)
|
|
# define ARCH_ARM64 1
|
|
# elif defined(_M_ARM)
|
|
# define ARCH_ARM32 1
|
|
# else
|
|
# error Target architecture is not supported. _MSC_VER is defined, but one of {_M_AMD64, _M_IX86, _M_ARM64, _M_ARM} is not.
|
|
# endif
|
|
|
|
#if _MSC_VER >= 1920
|
|
# define COMPILER_MSVC_YEAR 2019
|
|
#elif _MSC_VER >= 1910
|
|
# define COMPILER_MSVC_YEAR 2017
|
|
#elif _MSC_VER >= 1900
|
|
# define COMPILER_MSVC_YEAR 2015
|
|
#elif _MSC_VER >= 1800
|
|
# define COMPILER_MSVC_YEAR 2013
|
|
#elif _MSC_VER >= 1700
|
|
# define COMPILER_MSVC_YEAR 2012
|
|
#elif _MSC_VER >= 1600
|
|
# define COMPILER_MSVC_YEAR 2010
|
|
#elif _MSC_VER >= 1500
|
|
# define COMPILER_MSVC_YEAR 2008
|
|
#elif _MSC_VER >= 1400
|
|
# define COMPILER_MSVC_YEAR 2005
|
|
#else
|
|
# define COMPILER_MSVC_YEAR 0
|
|
#endif
|
|
|
|
//- rjf: Clang Extraction
|
|
|
|
#elif defined(__clang__)
|
|
|
|
# define COMPILER_CLANG 1
|
|
|
|
# if defined(__APPLE__) && defined(__MACH__)
|
|
# define PLATFORM_MAC 1
|
|
# elif defined(__gnu_linux__)
|
|
# define PLATFORM_LINUX 1
|
|
# elif defined(N64)
|
|
# define PLATFORM_N64 1
|
|
# else
|
|
# error __clang__ is defined, but one of {__APPLE__, __gnu_linux__, N64} is not. This setup is not supported.
|
|
# endif
|
|
|
|
# if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
|
|
# define ARCH_X64 1
|
|
# elif defined(i386) || defined(__i386) || defined(__i386__)
|
|
# define ARCH_X86 1
|
|
# elif defined(__aarch64__)
|
|
# define ARCH_ARM64 1
|
|
# elif defined(__arm__)
|
|
# define ARCH_ARM32 1
|
|
# elif defined(__mips) && defined(__mips64)
|
|
# define ARCH_MIPS64 1
|
|
# elif defined(__mips) && !defined(__mips64)
|
|
# define ARCH_MIPS32 1
|
|
# else
|
|
# error Target architecture is not supported. __clang__ is defined, but one of {__amd64__, __amd64, __x86_64__, __x86_64, i386, __i386, __i386__, __aarch64__, __arm__, __mips} is not.
|
|
# endif
|
|
|
|
//- rjf: GCC Extraction
|
|
|
|
#elif defined(__GNUC__) || defined(__GNUG__)
|
|
|
|
# define COMPILER_GCC 1
|
|
|
|
# if defined(__gnu_linux__)
|
|
# define PLATFORM_LINUX 1
|
|
# else
|
|
# error __GNUC__ or __GNUG__ is defined, but __gnu_linux__ is not. This setup is not supported.
|
|
# endif
|
|
|
|
# if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
|
|
# define ARCH_X64 1
|
|
# elif defined(i386) || defined(__i386) || defined(__i386__)
|
|
# define ARCH_X86 1
|
|
# elif defined(__aarch64__)
|
|
# define ARCH_ARM64 1
|
|
# elif defined(__arm__)
|
|
# define ARCH_ARM32 1
|
|
# else
|
|
# error Target architecture is not supported. __GNU_C__ or __GNUG__ is defined, but one of {__amd64__, __amd64, __x86_64__, __x86_64, i386, __i386, __i386__, __aarch64__, __arm__} is not.
|
|
# endif
|
|
|
|
#else
|
|
# error Compiler is not supported. _MSC_VER, __clang__, __GNUC__, or __GNUG__ must be defined.
|
|
#endif
|
|
|
|
#if ARCH_X64 || ARCH_ARM64 || ARCH_MIPS64
|
|
# define ARCH_64BIT 1
|
|
#elif ARCH_X86 || ARCH_ARM32 || ARCH_MIPS32
|
|
# define ARCH_32BIT 1
|
|
#endif
|
|
|
|
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
|
# define LITTLE_ENDIAN 0
|
|
# define BIG_ENDIAN 1
|
|
#else
|
|
# define LITTLE_ENDIAN 1
|
|
# define BIG_ENDIAN 0
|
|
#endif
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Variadic Arguments
|
|
|
|
#define VariadicS64(args) va_arg(args, S64)
|
|
#define VariadicU64(args) va_arg(args, U64)
|
|
#if ARCH_X64 || ARCH_ARM64
|
|
# define VariadicS32(args) va_arg(args, S32)
|
|
# define VariadicU32(args) va_arg(args, U32)
|
|
# define VariadicInt(args) va_arg(args, int)
|
|
# define VariadicAddr(args) va_arg(args, UAddr)
|
|
#elif ARCH_MIPS32 || ARCH_MIPS64
|
|
# define VariadicS32(args) (S32)(va_arg(args, U64) & 0xffffffff)
|
|
# define VariadicU32(args) (U64)(va_arg(args, U64) & 0xffffffff)
|
|
# define VariadicInt(args) (int)(va_arg(args, U64) & 0xffffffff)
|
|
# define VariadicAddr(args) (UAddr)(va_arg(args, U64) & 0xffffffff)
|
|
#endif
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Keywords
|
|
|
|
#define function static
|
|
#define global static
|
|
#define local_persist static
|
|
#define align(n) __attribute__((aligned(n)))
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Preprocessor Operations
|
|
|
|
#define Glue_(A, B) A##B
|
|
#define Glue(A, B) Glue_(A, B)
|
|
#define Stringify_(S) #S
|
|
#define Stringify(S) Stringify_(S)
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Static Assertions
|
|
|
|
#define StaticAssert(C, ID) global U8 Glue(ID, __LINE__)[(C)?1:-1]
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
//~ rjf: Clamps, Mins, Maxes
|
|
|
|
#define Min(a, b) (((a)<(b)) ? (a) : (b))
|
|
#define Max(a, b) (((a)>(b)) ? (a) : (b))
|
|
#define ClampTop(x, a) Min(x,a)
|
|
#define ClampBot(a, x) Max(a,x)
|
|
#define Clamp(a, x, b) (((a)>(x))?(a):((b)<(x))?(b):(x))
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
//~ rjf: Swaps
|
|
|
|
#define Swap(T, a, b) do{T c = (a); (a) = (b); (b) = c;}while(0)
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
//~ rjf: Array Counts
|
|
|
|
#define ArrayCount(a) ((sizeof(a)) / sizeof((a)[0]))
|
|
#define ArrayAndCount(a) (a), ArrayCount(a)
|
|
#define CountAndArray(a) ArrayCount(a), (a)
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
//~ rjf: Loop Helpers
|
|
|
|
#define EachIndex(idx, count) (UAddr idx = 0; idx < (count); idx += 1)
|
|
#define EachElement(idx, array) (UAddr idx = 0; idx < ArrayCount(array); idx += 1)
|
|
|
|
#define DeferLoop(start, end) for(int _i_ = ((start), 0); _i_ == 0; (_i_ += 1, (end)))
|
|
#define DeferLoopChecked(begin, end) for(int _i_ = 2 * !(begin); (_i_ == 2 ? ((end), 0) : !_i_); _i_ += 1, (end))
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
//~ rjf: Bit Arrays
|
|
|
|
#define BitArrayDecl(type, name, count) type name[(count + sizeof(type)*8-1) / sizeof(type)*8]
|
|
#define BitArrayAdd(arr, bit) ((arr)[(bit) / (sizeof((arr)[0])*8)] |= (((U64)1) << ((bit) % (sizeof((arr)[0])*8))))
|
|
#define BitArrayRemove(arr, bit) ((arr)[(bit) / (sizeof((arr)[0])*8)] &= ~(((U64)1) << ((bit) % (sizeof((arr)[0])*8))))
|
|
#define BitArrayGet(arr, bit) (!!((arr)[(bit) / (sizeof((arr)[0])*8)] & (((U64)1) << ((bit) % (sizeof((arr)[0])*8)))))
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Masks
|
|
|
|
#define Lower16(x) (((x)&0x0000ffff) >> 0)
|
|
#define Upper16(x) (((x)&0xffff0000) >> 16)
|
|
#define Lower32(x) (((x)&0x00000000ffffffffull) >> 0)
|
|
#define Upper32(x) (((x)&0xffffffff00000000ull) >> 32)
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Units
|
|
|
|
#define KiB(x) ((x)*1024)
|
|
#define MiB(x) (KiB(x)*1024)
|
|
#define GiB(x) (MiB(x)*1024)
|
|
#define TiB(x) (GiB(x)*1024)
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
//~ rjf: Structure Packing Marker Macros
|
|
|
|
#define pack_begin _Pragma("pack(push, 1)")
|
|
#define pack_end _Pragma("pack(pop)")
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
//~ rjf: Type -> Alignment
|
|
|
|
#if COMPILER_MSVC
|
|
# define AlignOf(T) __alignof(T)
|
|
#elif COMPILER_CLANG
|
|
# define AlignOf(T) __alignof(T)
|
|
#elif COMPILER_GCC
|
|
# define AlignOf(T) __alignof__(T)
|
|
#else
|
|
# error AlignOf not defined for this compiler.
|
|
#endif
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Basic Types
|
|
|
|
#include <stdint.h>
|
|
|
|
typedef int8_t S8;
|
|
typedef int16_t S16;
|
|
typedef int32_t S32;
|
|
typedef int64_t S64;
|
|
typedef uint8_t U8;
|
|
typedef uint16_t U16;
|
|
typedef uint32_t U32;
|
|
typedef uint64_t U64;
|
|
typedef S8 B8;
|
|
typedef S16 B16;
|
|
typedef S32 B32;
|
|
typedef S64 B64;
|
|
typedef float F32;
|
|
typedef double F64;
|
|
typedef void VoidFunction(void);
|
|
|
|
#if ARCH_32BIT
|
|
typedef S32 SAddr;
|
|
typedef U32 UAddr;
|
|
#elif ARCH_64BIT
|
|
typedef S64 SAddr;
|
|
typedef U64 UAddr;
|
|
#endif
|
|
|
|
////////////////////////////////
|
|
//~ rjf: C Runtime Implementations
|
|
|
|
void *memset(void *buffer, int c, UAddr n);
|
|
void *memcpy(void *dest, void *src, UAddr n);
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Memory Operations
|
|
|
|
#define MemoryZero(ptr, size) memset((ptr), 0, (size))
|
|
#define MemoryZeroStruct(ptr) MemoryZero((ptr), sizeof(*(ptr)))
|
|
#define MemoryCopy(dst, src, size) memcpy((dst), (src), (size))
|
|
#define MemoryCopyStruct(dst, src) memcpy((dst), (src), Min(sizeof(*(dst)), sizeof(*(src))))
|
|
|
|
function inline void
|
|
WriteAndInc(void *buffer, void *src, UAddr size, UAddr *cursor)
|
|
{
|
|
MemoryCopy((U8 *)buffer + *cursor, src, size);
|
|
*cursor += size;
|
|
}
|
|
|
|
function inline void
|
|
ReadAndInc(void *buffer, void *dst, UAddr size, UAddr *cursor)
|
|
{
|
|
MemoryCopy(dst, (U8 *)buffer + *cursor, size);
|
|
*cursor += size;
|
|
}
|
|
|
|
#define WriteStructAndInc(buffer, ptr, cursor_ptr) WriteAndInc((buffer), (ptr), sizeof(*(ptr)), (cursor_ptr))
|
|
#define ReadStructAndInc(buffer, ptr, cursor_ptr) ReadAndInc((buffer), (ptr), sizeof(*(ptr)), (cursor_ptr))
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Float Operations
|
|
|
|
function inline F32
|
|
TruncF32(F32 f)
|
|
{
|
|
#if ARCH_MIPS32
|
|
F32 result_int;
|
|
F32 result;
|
|
__asm("trunc.w.s %0,%1" : "=f"(result_int) : "f"(f));
|
|
__asm("cvt.s.w %0,%1" : "=f"(result) : "f"(result_int));
|
|
return result;
|
|
#else
|
|
# error TruncF32 not implemented for this architecture.
|
|
#endif
|
|
}
|
|
|
|
function inline F32
|
|
FloorF32(F32 f)
|
|
{
|
|
#if ARCH_MIPS32
|
|
F32 result_int;
|
|
F32 result;
|
|
__asm("floor.w.s %0,%1" : "=f"(result_int) : "f"(f));
|
|
__asm("cvt.s.w %0,%1" : "=f"(result) : "f"(result_int));
|
|
return result;
|
|
#else
|
|
# error FloorF32 not implemented for this architecture.
|
|
#endif
|
|
}
|
|
|
|
function inline F32
|
|
ModF32(F32 f, F32 d)
|
|
{
|
|
F32 result = f - TruncF32(f/d)*d;
|
|
return result;
|
|
}
|
|
|
|
function inline S32
|
|
Fixed112FromF32(F32 f)
|
|
{
|
|
S32 result = (S32)(f*4.f);
|
|
result = Clamp(-4096*4, result, +4095*4);
|
|
return result;
|
|
}
|
|
|
|
function inline S32
|
|
Fixed1616FromF32(F32 f)
|
|
{
|
|
S32 result;
|
|
if(f >= 32768.f)
|
|
{
|
|
result = 0x7fffffff;
|
|
}
|
|
else if(f < -32768.f)
|
|
{
|
|
result = 0x80000000;
|
|
}
|
|
else
|
|
{
|
|
result = (S32)FloorF32(f*65536.f);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Scalar Math Functions
|
|
|
|
function F32 inline
|
|
SquareRootF32(F32 v)
|
|
{
|
|
#if ARCH_MIPS32
|
|
F32 result;
|
|
__asm("sqrt.s %0,%1" : "=f"(result) : "f"(v));
|
|
return result;
|
|
#else
|
|
# error SquareRootF32 not implemented for this architecture.
|
|
#endif
|
|
}
|
|
|
|
function F32 SinF32(F32 turns);
|
|
|
|
function F32 inline
|
|
CosF32(F32 turns)
|
|
{
|
|
F32 result = SinF32(turns + 0.25f);
|
|
return result;
|
|
}
|
|
|
|
function F32 inline
|
|
TanF32(F32 turns)
|
|
{
|
|
F32 result = SinF32(turns) / CosF32(turns);
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Vector / Matrix Types
|
|
|
|
typedef union Vec2U32 Vec2U32;
|
|
union Vec2U32
|
|
{
|
|
struct
|
|
{
|
|
U32 x;
|
|
U32 y;
|
|
};
|
|
U32 v[2];
|
|
};
|
|
|
|
typedef union Vec2F32 Vec2F32;
|
|
union Vec2F32
|
|
{
|
|
struct
|
|
{
|
|
F32 x;
|
|
F32 y;
|
|
};
|
|
F32 v[2];
|
|
};
|
|
|
|
typedef union Vec3F32 Vec3F32;
|
|
union Vec3F32
|
|
{
|
|
struct
|
|
{
|
|
F32 x;
|
|
F32 y;
|
|
F32 z;
|
|
};
|
|
struct
|
|
{
|
|
Vec2F32 xy;
|
|
F32 z_;
|
|
};
|
|
struct
|
|
{
|
|
F32 x_;
|
|
Vec2F32 yz;
|
|
};
|
|
F32 v[3];
|
|
};
|
|
|
|
typedef union Vec4F32 Vec4F32;
|
|
union Vec4F32
|
|
{
|
|
struct
|
|
{
|
|
F32 x;
|
|
F32 y;
|
|
F32 z;
|
|
F32 w;
|
|
};
|
|
struct
|
|
{
|
|
Vec2F32 xy;
|
|
Vec2F32 zw;
|
|
};
|
|
struct
|
|
{
|
|
Vec3F32 xyz;
|
|
F32 w_;
|
|
};
|
|
struct
|
|
{
|
|
F32 x_;
|
|
Vec3F32 yzw;
|
|
};
|
|
F32 v[4];
|
|
};
|
|
|
|
typedef struct Mat3x3F32 Mat3x3F32;
|
|
struct Mat3x3F32
|
|
{
|
|
F32 v[3][3];
|
|
};
|
|
|
|
typedef struct Mat4x4F32 Mat4x4F32;
|
|
struct Mat4x4F32
|
|
{
|
|
F32 v[4][4];
|
|
};
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Vector Functions
|
|
|
|
//- rjf: constructors
|
|
function Vec2U32 V2U32(U32 x, U32 y);
|
|
function Vec2F32 V2F32(F32 x, F32 y);
|
|
function Vec3F32 V3F32(F32 x, F32 y, F32 z);
|
|
function Vec4F32 V4F32(F32 x, F32 y, F32 z, F32 w);
|
|
|
|
//- rjf: 2-vector ops
|
|
function Vec2F32 Add2F32(Vec2F32 l, Vec2F32 r);
|
|
function Vec2F32 Sub2F32(Vec2F32 l, Vec2F32 r);
|
|
function Vec2F32 Mul2F32(Vec2F32 l, Vec2F32 r);
|
|
function Vec2F32 Div2F32(Vec2F32 l, Vec2F32 r);
|
|
function F32 LengthSquared2F32(Vec2F32 v);
|
|
function F32 Length2F32(Vec2F32 v);
|
|
function Vec2F32 Scale2F32(Vec2F32 v, F32 s);
|
|
function Vec2F32 Normalize2F32(Vec2F32 v);
|
|
function F32 Dot2F32(Vec2F32 l, Vec2F32 r);
|
|
|
|
//- rjf: 3-vector ops
|
|
function Vec3F32 Add3F32(Vec3F32 l, Vec3F32 r);
|
|
function Vec3F32 Sub3F32(Vec3F32 l, Vec3F32 r);
|
|
function Vec3F32 Mul3F32(Vec3F32 l, Vec3F32 r);
|
|
function Vec3F32 Div3F32(Vec3F32 l, Vec3F32 r);
|
|
function F32 LengthSquared3F32(Vec3F32 v);
|
|
function F32 Length3F32(Vec3F32 v);
|
|
function Vec3F32 Scale3F32(Vec3F32 v, F32 s);
|
|
function Vec3F32 Normalize3F32(Vec3F32 v);
|
|
function F32 Dot3F32(Vec3F32 l, Vec3F32 r);
|
|
function Vec3F32 Cross3F32(Vec3F32 l, Vec3F32 r);
|
|
|
|
//- rjf: 4-vector ops
|
|
function Vec4F32 Add4F32(Vec4F32 l, Vec4F32 r);
|
|
function Vec4F32 Sub4F32(Vec4F32 l, Vec4F32 r);
|
|
function Vec4F32 Mul4F32(Vec4F32 l, Vec4F32 r);
|
|
function Vec4F32 Div4F32(Vec4F32 l, Vec4F32 r);
|
|
function F32 LengthSquared4F32(Vec4F32 v);
|
|
function F32 Length4F32(Vec4F32 v);
|
|
function Vec4F32 Scale4F32(Vec4F32 v, F32 s);
|
|
function Vec4F32 Normalize4F32(Vec4F32 v);
|
|
function F32 Dot4F32(Vec4F32 l, Vec4F32 r);
|
|
function Vec4F32 XForm4F32(Mat4x4F32 m, Vec4F32 v);
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Matrix Functions
|
|
|
|
//- rjf: constructors
|
|
function Mat3x3F32 MakeMat3x3F32(F32 d);
|
|
function Mat3x3F32 MakeTranslate3x3F32(Vec2F32 translation);
|
|
function Mat3x3F32 MakeScale3x3F32(Vec2F32 scale);
|
|
function Mat3x3F32 MakeRotate3x3F32(F32 turns);
|
|
function Mat4x4F32 MakeMat4x4F32(F32 d);
|
|
function Mat4x4F32 MakeTranslate4x4F32(Vec3F32 translation);
|
|
function Mat4x4F32 MakeScale4x4F32(Vec3F32 scale);
|
|
function Mat4x4F32 MakePerspective4x4F32(F32 fov, F32 aspect_ratio, F32 near_z, F32 far_z);
|
|
function Mat4x4F32 MakeOrthographic4x4F32(F32 left, F32 right, F32 bottom, F32 top, F32 near_z, F32 far_z);
|
|
function Mat4x4F32 MakeLookAt4x4F32(Vec3F32 eye, Vec3F32 center, Vec3F32 up);
|
|
function Mat4x4F32 MakeRotate4x4F32(Vec3F32 axis, F32 turns);
|
|
|
|
//- rjf: ops
|
|
function Mat3x3F32 Mul3x3F32(Mat3x3F32 a, Mat3x3F32 b);
|
|
function Mat3x3F32 Scale3x3F32(Mat3x3F32 m, F32 scale);
|
|
function Mat4x4F32 Mul4x4F32(Mat4x4F32 a, Mat4x4F32 b);
|
|
function Mat4x4F32 Scale4x4F32(Mat4x4F32 m, F32 scale);
|
|
function Mat4x4F32 Inverse4x4F32(Mat4x4F32 m);
|
|
function Mat4x4F32 RemoveRotation4x4F32(Mat4x4F32 mat);
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Arenas
|
|
|
|
typedef struct Arena Arena;
|
|
struct Arena
|
|
{
|
|
UAddr pos;
|
|
UAddr cap;
|
|
};
|
|
|
|
function Arena *ArenaMakeStatic(U8 *buffer, UAddr buffer_size);
|
|
function void *ArenaPush(Arena *arena, UAddr size, UAddr align);
|
|
function UAddr ArenaPos(Arena *arena);
|
|
function void ArenaPopTo(Arena *arena, UAddr pos);
|
|
function void ArenaClear(Arena *arena);
|
|
function void ArenaPop(Arena *arena, UAddr amt);
|
|
#define PushArrayNoZeroAligned(a, T, c, align) (T *)ArenaPush((a), sizeof(T)*(c), (align))
|
|
#define PushArrayAligned(a, T, c, align) (T *)MemoryZero(PushArrayNoZeroAligned(a, T, c, align), sizeof(T)*(c))
|
|
#define PushArrayNoZero(a, T, c) PushArrayNoZeroAligned(a, T, c, AlignOf(T))
|
|
#define PushArray(a, T, c) PushArrayAligned(a, T, c, AlignOf(T))
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Arena Temporary Scopes
|
|
|
|
typedef struct Temp Temp;
|
|
struct Temp
|
|
{
|
|
Arena *arena;
|
|
UAddr pos;
|
|
};
|
|
|
|
function Temp TempBegin(Arena *arena);
|
|
function void TempEnd(Temp temp);
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Thread Context
|
|
|
|
typedef struct ThreadCtx ThreadCtx;
|
|
struct ThreadCtx
|
|
{
|
|
Arena *scratch_arenas[2];
|
|
};
|
|
|
|
//- rjf: @per_platform Thread Context Functions
|
|
function ThreadCtx *GetThreadCtx(void);
|
|
|
|
//- rjf: Thread Context Helpers
|
|
function Arena *GetScratch(Arena *conflict);
|
|
#define ScratchBegin(result_arena) TempBegin(GetScratch(result_arena))
|
|
#define ScratchEnd(temp) TempEnd(temp)
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Strings
|
|
|
|
#include <stdarg.h>
|
|
|
|
typedef struct String8 String8;
|
|
struct String8
|
|
{
|
|
U8 *str;
|
|
UAddr size;
|
|
};
|
|
|
|
function UAddr CStr8Size(char *cstr);
|
|
function String8 Str8(U8 *str, UAddr size);
|
|
#define Str8Lit(s) Str8((U8 *)(s), sizeof(s)-1)
|
|
#define Str8LitComp(s) {(U8 *)(s), sizeof(s)-1}
|
|
#define S(s) Str8Lit(s)
|
|
function String8 Str8FV(Arena *arena, char *fmt, va_list args);
|
|
function String8 Str8F(Arena *arena, char *fmt, ...);
|
|
#define SF(...) Str8F(scratch.arena, __VA_ARGS__)
|
|
function String8 ByteStringFromData(Arena *arena, String8 data);
|
|
|
|
global U8 dec_chars[] = "0123456789";
|
|
global U8 hex_chars_lower[] = "0123456789abcdef";
|
|
global U8 hex_chars_upper[] = "0123456789ABCDEF";
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Colors
|
|
|
|
function U16 RGBA5551From4F32(Vec4F32 rgba);
|
|
function U32 RGBA32From4F32(Vec4F32 rgba);
|
|
function Vec4F32 RGBA4F32From32(U32 rgba);
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Game Pads
|
|
|
|
typedef enum GamePadButtonKind
|
|
{
|
|
GamePadButtonKind_Null,
|
|
GamePadButtonKind_A,
|
|
GamePadButtonKind_B,
|
|
GamePadButtonKind_CLeft,
|
|
GamePadButtonKind_CUp,
|
|
GamePadButtonKind_CRight,
|
|
GamePadButtonKind_CDown,
|
|
GamePadButtonKind_Start,
|
|
GamePadButtonKind_DLeft,
|
|
GamePadButtonKind_DUp,
|
|
GamePadButtonKind_DRight,
|
|
GamePadButtonKind_DDown,
|
|
GamePadButtonKind_Z,
|
|
GamePadButtonKind_LeftBumper,
|
|
GamePadButtonKind_RightBumper,
|
|
GamePadButtonKind_COUNT
|
|
}
|
|
GamePadButtonKind;
|
|
|
|
typedef struct GamePad GamePad;
|
|
struct GamePad
|
|
{
|
|
U32 connect_gen; // incremented on every connection change
|
|
BitArrayDecl(U32, last_buttons, GamePadButtonKind_COUNT);
|
|
BitArrayDecl(U32, buttons, GamePadButtonKind_COUNT);
|
|
F32 left_trigger;
|
|
F32 right_trigger;
|
|
Vec2F32 sticks[2];
|
|
};
|
|
|
|
#define GAME_PAD_SLOT_COUNT 4
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Program Tick Entry Point
|
|
|
|
function B32 Run(U64 tick_idx, Arena *permanent_arena, GamePad game_pads[GAME_PAD_SLOT_COUNT]);
|
|
|
|
#endif // BASE_H
|