diff options
Diffstat (limited to 'handmade_platform.h')
| -rw-r--r-- | handmade_platform.h | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/handmade_platform.h b/handmade_platform.h new file mode 100644 index 0000000..bc3f84a --- /dev/null +++ b/handmade_platform.h @@ -0,0 +1,327 @@ +/* date = May 12th 2025 10:53 am */ + +#ifndef HANDMADE_PLATFORM_H +#define HANDMADE_PLATFORM_H + +#ifdef __cplusplus +extern "C" { +#endif + + /* + NOTE(casey): + + HANDMADE_INTERNAL: + 0 - Build for public release + 1 - Build for developer only + + HANDMADE_SLOW: + 0 - Not slow code allowed! + 1 - Slow code welcome. + */ + +#include <stdint.h> +#include <stddef.h> + +#if !defined(COMPILER_MSVC) +#define COMPILER_MSVC 0 +#endif + +#if !defined(COMPILER_LLVM) +#define COMPILER_LLVM 0 +#endif + +#if !defined(COMPILER_GNU) +#define COMPILER_GNU 0 +#endif + +#if !COMPILER_MSVC && !COMPILER_LLVM && !COMPILER_GNU +#if _MSC_VER +#undef COMPILER_MSVC +#define COMPILER_MSVC 1 +#elif __GNUC__ +#undef COMPILER_GNU +#define COMPILER_GNU 1 +#else + // TODO(casey): More compilerz!!! +#endif +#endif + +#define internal static +#define local_persist static +#define global_variable static + +#define Pi32 3.14159265359f + + // TODO(casey): Complete assertion macro - don't worry everyone! +#if HANDMADE_SLOW +# if HANDMADE_INTERNAL && OS_LINUX +# define Assert(Expression) if(!(Expression)) { __asm__ volatile("int3"); } +# else +# define Assert(Expression) if(!(Expression)) {*(int *)0 = 0; } +# endif +#else +# define Assert(Expression) +#endif + +#define DebugBreakOnce do { local_persist b32 X = false; Assert(X); X = true; } while(0) + +#define NullExpression { int X = 0; } + +#define Kilobytes(Value) ((Value)*1024LL) +#define Megabytes(Value) (Kilobytes(Value)*1024LL) +#define Gigabytes(Value) (Megabytes(Value)*1024LL) +#define Terabytes(Value) (Gigabytes(Value)*1024LL) + +#define ArrayCount(Array) (sizeof(Array) / sizeof((Array)[0])) +#define Min(A, B) (((A) < (B)) ? (A) : (B)) +#define Max(A, B) (((A) > (B)) ? (A) : (B)) + + // TODO(casey): swap, min, max ... macros??? + + typedef int8_t s8; + typedef int16_t s16; + typedef int32_t s32; + typedef int64_t s64; + typedef s32 b32; + + typedef uint8_t u8; + typedef uint16_t u16; + typedef uint32_t u32; + typedef uint64_t u64; + + typedef size_t psize; + typedef s32 rune; + + typedef float r32; + typedef double r64; + + typedef struct thread_context + { + int Placeholder; + } thread_context; + + /* + NOTE(casey): Services that the platform layer provides to the game + */ + /* IMPORTANT(casey): + + These are NOT for doing anything in the shipping game - they are + blocking and the write doesn't protect against lost data! + */ + struct debug_platform_read_file_result + { + psize ContentsSize; + void *Contents; + }; + +#define DEBUG_PLATFORM_FREE_FILE_MEMORY(Name) void Name(thread_context *Thread, void *Memory, psize MemorySize) + typedef DEBUG_PLATFORM_FREE_FILE_MEMORY(debug_platform_free_file_memory); + +#define DEBUG_PLATFORM_READ_ENTIRE_FILE(Name) debug_platform_read_file_result Name(thread_context *Thread, char *FileName) + typedef DEBUG_PLATFORM_READ_ENTIRE_FILE(debug_platform_read_entire_file); + +#define DEBUG_PLATFORM_WRITE_ENTIRE_FILE(Name) b32 Name(thread_context *Thread, char *FileName, psize MemorySize, void *Memory) + typedef DEBUG_PLATFORM_WRITE_ENTIRE_FILE(debug_platform_write_entire_file); + +#define PLATFORM_RUN_COMMAND_AND_GET_OUTPUT(Name) psize Name(thread_context *Thread, char *OutputBuffer, char *Command[]) + typedef PLATFORM_RUN_COMMAND_AND_GET_OUTPUT(platform_run_command_and_get_output); + +#define PLATFORM_GET_WALL_CLOCK(Name) struct timespec Name(void) + typedef PLATFORM_GET_WALL_CLOCK(platform_get_wall_clock); + +#define PLATFORM_LOG(Name) void Name(char *Text) + typedef PLATFORM_LOG(platform_log); + +#define PLATFORM + + /* + NOTE(casey): Services that the game provides to the platform layer. + (this may expand in the future - sound on separate thread, etc.) + */ + + // FOUR THINGS - timing, controller/keyboard input, bitmap buffer to use, sound buffer to use + + // TODO(casey): In the future, rendering _specifically_ will become a three-tiered abstraction!!! + typedef struct game_offscreen_buffer + { + // NOTE(casey): Pixels are alwasy 32-bits wide, Memory Order BB GG RR XX + void *Memory; + s32 Width; + s32 Height; + s32 Pitch; + s32 BytesPerPixel; + } game_offscreen_buffer; + + typedef struct game_sound_output_buffer + { + s32 SamplesPerSecond; + s32 SampleCount; + s16 *Samples; + } game_sound_output_buffer; + + typedef struct game_text_button + { + rune Codepoint; + // TODO(luca): Use flag and bits. + b32 Control; + b32 Shift; + b32 Alt; + } game_text_button; + + typedef struct game_button_state + { + s32 HalfTransitionCount; + b32 EndedDown; + } game_button_state; + + typedef struct game_controller_input + { + b32 IsConnected; + + struct + { + u32 Count; + game_text_button Buffer[64]; + } Text; + + b32 IsAnalog; + r32 StickAverageX; + r32 StickAverageY; + + union + { + game_button_state Buttons[12]; + struct + { + game_button_state MoveUp; + game_button_state MoveDown; + game_button_state MoveLeft; + game_button_state MoveRight; + + game_button_state ActionUp; + game_button_state ActionDown; + game_button_state ActionLeft; + game_button_state ActionRight; + + game_button_state LeftShoulder; + game_button_state RightShoulder; + + game_button_state Back; + game_button_state Start; + + // NOTE(casey): All buttons must be added above this line + + game_button_state Terminator; + }; + }; + } game_controller_input; + + typedef enum + { + PlatformCursorShape_None = 0, + PlatformCursorShape_Grab, + } platform_cursor_shape; + + typedef enum + { + PlatformMouseButton_Left = 0, + PlatformMouseButton_Right, + PlatformMouseButton_Middle, + PlatformMouseButton_ScrollUp, + PlatformMouseButton_ScrollDown, + PlatformMouseButton_Count + } platform_mouse_buttons; + + typedef struct game_input + { + game_button_state MouseButtons[PlatformMouseButton_Count]; + s32 MouseX, MouseY, MouseZ; + + r32 dtForFrame; + + game_controller_input Controllers[5]; + } game_input; + + inline b32 WasPressed(game_button_state State) + { + b32 Result = ((State.HalfTransitionCount > 1) || + (State.HalfTransitionCount == 1 && State.EndedDown)); + return Result; + } + + //- Threading + typedef struct platform_work_queue platform_work_queue; + +#define PLATFORM_WORK_QUEUE_CALLBACK(Name) void Name(platform_work_queue *Queue, void *Data) + typedef PLATFORM_WORK_QUEUE_CALLBACK(platform_work_queue_callback); + struct platform_work_queue_entry + { + platform_work_queue_callback *Callback; + void *Data; + }; + + typedef void platform_add_entry(platform_work_queue *Queue, platform_work_queue_callback *CallBack, void *Data); + typedef void platform_complete_all_work(platform_work_queue *Queue); + //- + +#define PLATFORM_CHANGE_CURSOR(name) void name(platform_cursor_shape Shape) + typedef PLATFORM_CHANGE_CURSOR(platform_change_cursor); + + typedef struct game_memory + { + b32 IsInitialized; + + psize PermanentStorageSize; + void *PermanentStorage; // NOTE(casey): REQUIRED to be cleared to zero at startup + + psize TransientStorageSize; + void *TransientStorage; // NOTE(casey): REQUIRED to be cleared to zero at startup + + platform_work_queue *HighPriorityQueue; + + platform_add_entry *PlatformAddEntry; + platform_complete_all_work *PlatformCompleteAllWork; + platform_run_command_and_get_output *PlatformRunCommandAndGetOutput; + platform_log *PlatformLog; + platform_change_cursor *PlatformChangeCursor; + platform_get_wall_clock *PlatformGetWallClock; + + debug_platform_free_file_memory *DEBUGPlatformFreeFileMemory; + debug_platform_read_entire_file *DEBUGPlatformReadEntireFile; + debug_platform_write_entire_file *DEBUGPlatformWriteEntireFile; + } game_memory; + +#define GAME_UPDATE_AND_RENDER(name) void name(thread_context *Thread, game_memory *Memory, game_input *Input, game_offscreen_buffer *Buffer) + typedef GAME_UPDATE_AND_RENDER(game_update_and_render); + + // NOTE(casey): At the moment, this has to be a very fast function, it cannot be + // more than a millisecond or so. + // TODO(casey): Reduce the pressure on this function's performance by measuring it + // or asking about it, etc. +#define GAME_GET_SOUND_SAMPLES(name) void name(thread_context *Thread, game_memory *Memory, game_sound_output_buffer *SoundBuffer) + typedef GAME_GET_SOUND_SAMPLES(game_get_sound_samples); + + inline u32 + SafeTruncateUInt64(u64 Value) + { + // TODO(casey): Defines for maximum values + Assert(Value <= 0xFFFFFFFF); + u32 Result = (u32)Value; + return(Result); + } + + inline game_controller_input *GetController(game_input *Input, u32 ControllerIndex) + { + Assert(ControllerIndex < ArrayCount(Input->Controllers)); + + game_controller_input *Result = &Input->Controllers[ControllerIndex]; + return(Result); + } + + global_variable platform_log *Log; + +#ifdef __cplusplus +} +#endif + +#endif //HANDMADE_PLATFORM_H |
