1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
|
/* 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
#if HANDMADE_SLOW
// TODO(casey): Complete assertion macro - don't worry everyone!
#define Assert(Expression) if(!(Expression)) {*(int *)0 = 0;}
#else
#define Assert(Expression)
#endif
#define NullExpression { int X = 4; }
#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]))
// 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 memory_index;
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!
*/
typedef struct debug_read_file_result
{
u32 ContentsSize;
void *Contents;
} debug_read_file_result;
#define DEBUG_PLATFORM_FREE_FILE_MEMORY(name) void name(thread_context *Thread, void *Memory, u64 MemorySize)
typedef DEBUG_PLATFORM_FREE_FILE_MEMORY(debug_platform_free_file_memory);
#define DEBUG_PLATFORM_READ_ENTIRE_FILE(name) debug_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, u32 MemorySize, void *Memory)
typedef DEBUG_PLATFORM_WRITE_ENTIRE_FILE(debug_platform_write_entire_file);
#define PLATFORM_RUN_COMMAND_AND_GET_OUTPUT(name) b32 name(thread_context *Thread, char *OutputBuffer, char *Command[])
typedef PLATFORM_RUN_COMMAND_AND_GET_OUTPUT(platform_run_command_and_get_output);
/*
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
{
int SamplesPerSecond;
int SampleCount;
s16 *Samples;
} game_sound_output_buffer;
typedef struct game_text_button
{
rune Codepoint;
b32 Control;
b32 Shift;
b32 Alt;
} game_text_button;
typedef struct game_button_state
{
int HalfTransitionCount;
b32 EndedDown;
} game_button_state;
typedef struct game_controller_input
{
b32 IsConnected;
struct
{
u32 TextInputCount;
game_text_button TextInputBuffer[64];
// TODO(luca): Generate code for keys that are not characters like Return, Backspace, etc.
} Keyboard;
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
{
PlatformMouseButton_Left = 0,
PlatformMouseButton_Right,
PlatformMouseButton_Middle,
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;
}
typedef struct game_memory
{
b32 IsInitialized;
memory_index PermanentStorageSize;
void *PermanentStorage; // NOTE(casey): REQUIRED to be cleared to zero at startup
memory_index TransientStorageSize;
void *TransientStorage; // NOTE(casey): REQUIRED to be cleared to zero at startup
debug_platform_free_file_memory *DEBUGPlatformFreeFileMemory;
debug_platform_read_entire_file *DEBUGPlatformReadEntireFile;
debug_platform_write_entire_file *DEBUGPlatformWriteEntireFile;
platform_run_command_and_get_output *PlatformRunCommandAndGetOutput;
} 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, int unsigned ControllerIndex)
{
Assert(ControllerIndex < ArrayCount(Input->Controllers));
game_controller_input *Result = &Input->Controllers[ControllerIndex];
return(Result);
}
#endif //HANDMADE_PLATFORM_H
#ifdef __cplusplus
}
#endif
|