Day 36. 25:01. Need to draw assets.

This commit is contained in:
igor
2026-04-16 22:18:24 -07:00
parent dea811e073
commit a8a3b57f8a
6 changed files with 269 additions and 362 deletions
+81 -153
View File
@@ -50,10 +50,8 @@ static S32 str_len(char *str)
static U32 SafeTruncateUInt64(U64 Value)
{
U32 Result;
ASSERT(Value <= 0xFFFFFFFF);
Result = (U32)Value;
U32 Result = (U32)Value;
return Result;
}
@@ -61,17 +59,14 @@ debug_read_file_result DEBUGPlatformReadEntireFile(thread_context *Thread,
const char *Filename)
{
debug_read_file_result Result;
S32 FileHandle;
struct stat FileStatus;
U32 BytesToRead;
U8 *NextByteLocation;
memset(&Result, 0, sizeof(Result));
FileHandle = open(Filename, O_RDONLY);
S32 FileHandle = open(Filename, O_RDONLY);
if(FileHandle == -1) {
return Result;
}
struct stat FileStatus;
if(fstat(FileHandle, &FileStatus) == -1) {
close(FileHandle);
return Result;
@@ -85,12 +80,10 @@ debug_read_file_result DEBUGPlatformReadEntireFile(thread_context *Thread,
return Result;
}
BytesToRead = Result.ContentsSize;
NextByteLocation = (U8 *)Result.Contents;
U32 BytesToRead = Result.ContentsSize;
U8 *NextByteLocation = (U8 *)Result.Contents;
while(BytesToRead) {
U32 BytesRead;
BytesRead = read(FileHandle, NextByteLocation, BytesToRead);
U32 BytesRead = read(FileHandle, NextByteLocation, BytesToRead);
if(BytesRead == (U32)-1) {
free(Result.Contents);
Result.Contents = 0;
@@ -111,17 +104,13 @@ B32 DEBUGPlatformWriteEntireFile(thread_context *Thread,
const char *Filename, U32 MemorySize,
void *Memory)
{
S32 FileHandle;
U32 BytesToWrite;
U8 *NextByteLocation;
FileHandle = open(Filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR |
S_IRGRP | S_IROTH);
S32 FileHandle = open(Filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR |
S_IRGRP | S_IROTH);
if(FileHandle == -1)
return FALSE;
BytesToWrite = MemorySize;
NextByteLocation = (U8*)Memory;
U32 BytesToWrite = MemorySize;
U8 *NextByteLocation = (U8*)Memory;
while(BytesToWrite) {
U32 BytesWritten;
@@ -155,15 +144,13 @@ static sdl_window_dimension SDLGetWindowDimension(SDL_Window *Window)
static void SDLResizeTexture(offscreen_buffer *Buffer,
SDL_Renderer *Renderer, int Width, int Height)
{
S32 BytesPerPixel;
if(Buffer->Texture)
SDL_DestroyTexture(Buffer->Texture);
if(Buffer->Memory)
free(Buffer->Memory);
BytesPerPixel = 4;
S32 BytesPerPixel = 4;
Buffer->Texture = SDL_CreateTexture(Renderer, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING,
@@ -179,7 +166,6 @@ static void SDLDisplayBufferInWindow(offscreen_buffer Buffer,
SDL_Window *Window,
SDL_Renderer *Renderer)
{
SDL_Rect dest_rect;
S32 OffsetX = 10;
S32 OffsetY = 10;
@@ -193,21 +179,17 @@ static void SDLDisplayBufferInWindow(offscreen_buffer Buffer,
/* TODO: We temporarily introduce the target rectangle to avoid
* stretching the canvas. */
/* SDL_RenderCopy(Renderer, Buffer.Texture, 0, 0); */
dest_rect.x = OffsetX;
dest_rect.y = OffsetY;
dest_rect.w = RESOLUTION_WIDTH;
dest_rect.h = RESOLUTION_HEIGHT;
SDL_Rect dest_rect = { OffsetX, OffsetY,
RESOLUTION_WIDTH, RESOLUTION_HEIGHT };
SDL_RenderCopy(Renderer, Buffer.Texture, 0, (const SDL_Rect *)(&dest_rect));
SDL_RenderPresent(Renderer);
}
static void SDLInitControllers()
{
S32 MaxJoysticks, ControllerIndex, JoystickIndex;
MaxJoysticks = SDL_NumJoysticks();
ControllerIndex = 0;
for(JoystickIndex = 0; JoystickIndex < MaxJoysticks; JoystickIndex++) {
S32 MaxJoysticks = SDL_NumJoysticks();
S32 ControllerIndex = 0;
for(S32 JoystickIndex = 0; JoystickIndex < MaxJoysticks; JoystickIndex++) {
if(!SDL_IsGameController(JoystickIndex))
continue;
if(ControllerIndex >= MAX_CONTROLLERS)
@@ -221,9 +203,7 @@ static void SDLInitControllers()
/*
static void SDLDeinitControllers()
{
S32 ControllerIndex;
for(ControllerIndex = 0;
for(S32 ControllerIndex = 0;
ControllerIndex < MAX_CONTROLLERS;
ControllerIndex++)
{
@@ -236,7 +216,6 @@ static void SDLDeinitControllers()
static void SDLInitSound(S32 SamplesPerSecond, S32 BufferSize)
{
SDL_AudioSpec AudioSettings;
memset(&AudioSettings, 0, sizeof(AudioSettings));
AudioSettings.freq = SamplesPerSecond;
@@ -283,12 +262,8 @@ static void SDLProcessInputDigitalButton(SDL_GameController *Controller,
static void HandleEvent(SDL_Event *Event)
{
/* TODO: Should this be below scopes? */
SDL_Window *Window;
SDL_Renderer *Renderer;
Window = SDL_GetWindowFromID(Event->window.windowID);
Renderer = SDL_GetRenderer(Window);
SDL_Window *Window = SDL_GetWindowFromID(Event->window.windowID);
SDL_Renderer *Renderer = SDL_GetRenderer(Window);
switch(Event->type) {
case SDL_QUIT: {
@@ -404,13 +379,11 @@ static void SDLProcessMessages(sdl_state *SDLState,
}
if(WasDown) {
B32 AltKeyWasDown;
/* NOTE: If your window manager already uses an Alt+F4
* keybind to close programs, then we are likely
* to see SDL_QUIT event occur before our
* keybind. */
AltKeyWasDown = (Event.key.keysym.mod & KMOD_ALT);
B32 AltKeyWasDown = (Event.key.keysym.mod & KMOD_ALT);
if(KeyCode == SDLK_F4 && AltKeyWasDown)
GlobalRunning = FALSE;
#if BUILD_INTERNAL
@@ -429,9 +402,7 @@ static void SDLProcessMessages(sdl_state *SDLState,
static F32 SDLProcessInputStickValue(F32 Value, S32 DeadZoneThreshold)
{
F32 Result;
Result = 0.0f;
F32 Result = 0.0f;
if(Value < -(F32)DeadZoneThreshold)
Result = ((Value + (F32)DeadZoneThreshold) /
(32768.0f - (F32)DeadZoneThreshold));
@@ -445,11 +416,9 @@ static F32 SDLProcessInputStickValue(F32 Value, S32 DeadZoneThreshold)
#define DEFAULT_REFRESH_RATE 60
static S32 SDLGetWindowRefreshRate(SDL_Window *Window)
{
S32 DisplayIndex;
S32 DisplayIndex = SDL_GetWindowDisplayIndex(Window);
SDL_DisplayMode Mode;
DisplayIndex = SDL_GetWindowDisplayIndex(Window);
if(SDL_GetDesktopDisplayMode(DisplayIndex, &Mode) != 0)
return DEFAULT_REFRESH_RATE;
if(Mode.refresh_rate == 0)
@@ -482,7 +451,6 @@ typedef struct sdl_game_code {
static U32 GetLastWriteTime(const char *FileName)
{
struct stat file_info;
memset(&file_info, 0, sizeof(file_info));
if(stat(FileName, &file_info) != 0) {
/* TODO: Diagnostic. perror("stat failed"); */
@@ -561,11 +529,9 @@ void GetExecutablePath(char *path, size_t path_size)
static void SDLGetEXEDirPath(char *path, size_t path_size)
{
U32 len, i;
GetExecutablePath(path, path_size);
len = str_len(path);
i = len;
U32 len = str_len(path);
U32 i = len;
while(path[i] != '/' || i == 0) {
i--;
}
@@ -590,8 +556,6 @@ U64 __rdtsc()
* drawing into a bitmap. */
void SDLSetProgramIcon(SDL_Window *Window)
{
SDL_Surface *icon;
U32 Rmask, Gmask, Bmask, Amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
S32 shift_by = (program_icon.bytes_per_pixel == 3) ? 8 : 0;
@@ -606,12 +570,12 @@ void SDLSetProgramIcon(SDL_Window *Window)
Amask = (program_icon.bytes_per_pixel == 3) ? 0 : 0xff000000;
#endif
icon = SDL_CreateRGBSurfaceFrom(
(void *)program_icon.pixel_data,
program_icon.width, program_icon.height,
program_icon.bytes_per_pixel * 8,
program_icon.bytes_per_pixel * program_icon.width,
Rmask, Gmask, Bmask, Amask);
SDL_Surface * icon = SDL_CreateRGBSurfaceFrom(
(void *)program_icon.pixel_data,
program_icon.width, program_icon.height,
program_icon.bytes_per_pixel * 8,
program_icon.bytes_per_pixel * program_icon.width,
Rmask, Gmask, Bmask, Amask);
if(icon) {
SDL_SetWindowIcon(Window, icon);
SDL_FreeSurface(icon);
@@ -623,8 +587,6 @@ void SDLSetProgramIcon(SDL_Window *Window)
S32 main(S32 argc, char *argv[])
{
sdl_state SDLState;
SDL_Window *Window;
memset(&SDLState, 0, sizeof(SDLState));
SDLGetEXEDirPath(SDLState.EXEDirPath, sizeof(SDLState.EXEDirPath));
@@ -642,20 +604,20 @@ S32 main(S32 argc, char *argv[])
/* NOTE: Floating windows are not supported oficially by Wayland
* protocol. However, SDL_WINDOW_ALWAYS_ON_TOP does work on KDE
* under Wayland. I have not tested GNOME. */
Window = SDL_CreateWindow("Handmade Hero", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
RESOLUTION_WIDTH, RESOLUTION_HEIGHT,
SDL_WINDOW_RESIZABLE);
SDL_Window *Window = SDL_CreateWindow("Handmade Hero",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
RESOLUTION_WIDTH, RESOLUTION_HEIGHT,
SDL_WINDOW_RESIZABLE);
/*SDL_WINDOW_RESIZABLE |
SDL_WINDOW_ALWAYS_ON_TOP);*/
if(Window) {
SDL_Renderer *Renderer;
SDL_DisplayMode display_mode;
SDL_GetCurrentDisplayMode(0, &display_mode);
Renderer = SDL_CreateRenderer(Window, -1, SDL_RENDERER_PRESENTVSYNC);
SDL_Renderer *Renderer =
SDL_CreateRenderer(Window, -1, SDL_RENDERER_PRESENTVSYNC);
SDL_SetWindowPosition(Window, (display_mode.w - RESOLUTION_WIDTH),
(display_mode.h - RESOLUTION_HEIGHT));
@@ -666,11 +628,6 @@ S32 main(S32 argc, char *argv[])
* its actual size. */
/* SDL_RenderPresent(Renderer) is enough to display the window. */
if(Renderer) {
sdl_window_dimension Dimension;
sdl_sound_output SoundOutput;
game_memory GameMemory;
S32 ReplayIndex;
#if BUILD_DEBUG
void *BaseAddress = (void *)TB(2);
#else
@@ -686,10 +643,11 @@ S32 main(S32 argc, char *argv[])
GlobalRunning = TRUE;
Dimension = SDLGetWindowDimension(Window);
sdl_window_dimension Dimension = SDLGetWindowDimension(Window);
SDLResizeTexture(&GlobalBackbuffer, Renderer, Dimension.Width,
Dimension.Height);
sdl_sound_output SoundOutput;
memset(&SoundOutput, 0, sizeof(SoundOutput));
SoundOutput.SamplesPerSecond = 48000;
SoundOutput.BytesPerSample = sizeof(S16) * 2;
@@ -712,6 +670,7 @@ S32 main(S32 argc, char *argv[])
/* NOTE: calloc auto clears to zero */
/* SDLClearSoundBuffer(&SoundOutput); */
game_memory GameMemory;
memset(&GameMemory, 0, sizeof(GameMemory));
GameMemory.PermanentStorageSize = MB(64);
GameMemory.TransientStorageSize = GB(1);
@@ -735,65 +694,29 @@ S32 main(S32 argc, char *argv[])
(U8 *)(GameMemory.PermanentStorage) +
GameMemory.PermanentStorageSize;
for(ReplayIndex = 0;
ReplayIndex < (S32)ARRAY_SIZE(SDLState.ReplayBuffers);
ReplayIndex++)
{
sdl_replay_buffer *ReplayBuffer =
&SDLState.ReplayBuffers[ReplayIndex];
ReplayBuffer->MemoryBlock = mmap(NULL,
(size_t)SDLState.TotalSize,
PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE,
-1, 0);
if(ReplayBuffer->MemoryBlock) {
} else {
/* TODO: Change this to log message. */
}
}
if(SoundOutput.Samples &&
GameMemory.PermanentStorage &&
GameMemory.TransientStorage)
{
game_input Input[2];
game_input *NewInput, *OldInput;
sdl_game_code Game;
F32 TargetSecondsPerFrame;
S32 MonitorRefreshHz, GameUpdateHz;
U64 LastCounter;
U64 LastCycleCount;
MonitorRefreshHz = SDLGetWindowRefreshRate(Window);
S32 MonitorRefreshHz = SDLGetWindowRefreshRate(Window);
/*GameUpdateHz = MonitorRefreshHz;*/
GameUpdateHz = 30; /* NOTE: Temporarily target 30 FPS. */
TargetSecondsPerFrame = 1.0f / (F32)GameUpdateHz;
S32 GameUpdateHz = 30; /* NOTE: Temporarily target 30 FPS. */
F32 TargetSecondsPerFrame = 1.0f / (F32)GameUpdateHz;
NewInput = &Input[0];
OldInput = &Input[1];
game_input *NewInput = &Input[0];
game_input *OldInput = &Input[1];
memset(&Input, 0, sizeof(Input));
GlobalPerfCountFrequency = SDL_GetPerformanceFrequency();
Game = SDLLoadGameCode(SDLState.DLLPath);
sdl_game_code Game = SDLLoadGameCode(SDLState.DLLPath);
while(GlobalRunning) {
thread_context Context;
U32 NewDLLWriteTime, ButtonIndex, ControllerIndex,
SDLMouseButtons;
game_controller_input *OldKeyboardController,
*NewKeyboardController;
game_controller_input ZeroController;
S32 TargetQueueBytes, BytesToWrite;
game_sound_output_buffer SoundBuffer;
game_offscreen_buffer Buffer;
U64 WorkCounter, EndCounter;
F32 WorkSecondsElapsed, SecondsElapsedForFrame;
F64 MSPerFrame, FPS;
U64 EndCycleCount, CyclesElapsed;
F64 MCPF;
NewInput->dtForFrame = TargetSecondsPerFrame;
LastCounter = SDLGetWallClock();
@@ -805,14 +728,15 @@ S32 main(S32 argc, char *argv[])
* have not checked MacOS x64. */
LastCycleCount = __rdtsc();
NewDLLWriteTime = GetLastWriteTime(SDLState.DLLPath);
U32 NewDLLWriteTime = GetLastWriteTime(SDLState.DLLPath);
if(NewDLLWriteTime > Game.DLLLastWriteTime) {
SDLUnloadGameCode(&Game);
Game = SDLLoadGameCode(SDLState.DLLPath);
}
SDLMouseButtons = SDL_GetMouseState(&(NewInput->MouseX),
&(NewInput->MouseY));
U32 SDLMouseButtons =
SDL_GetMouseState(&(NewInput->MouseX),
&(NewInput->MouseY));
NewInput->MouseZ = 0; /* TODO: Support mouse wheel? */
SDLProcessKeyboardMessage(&(NewInput->MouseButtons[0]),
SDL_BUTTON_LMASK & SDLMouseButtons);
@@ -828,13 +752,16 @@ S32 main(S32 argc, char *argv[])
SDLProcessKeyboardMessage(&(NewInput->MouseButtons[4]),
SDL_BUTTON_X2MASK & SDLMouseButtons);
OldKeyboardController = GetController(OldInput, 0);
NewKeyboardController = GetController(NewInput, 0);
game_controller_input *OldKeyboardController =
GetController(OldInput, 0);
game_controller_input *NewKeyboardController =
GetController(NewInput, 0);
game_controller_input ZeroController;
memset(&ZeroController, 0, sizeof(ZeroController));
*NewKeyboardController = ZeroController;
NewKeyboardController->IsConnected = TRUE;
for(ButtonIndex = 0;
for(U32 ButtonIndex = 0;
ButtonIndex < ARRAY_SIZE(
NewKeyboardController->u.Buttons);
ButtonIndex++)
@@ -848,11 +775,12 @@ S32 main(S32 argc, char *argv[])
SDLProcessMessages(&SDLState, NewKeyboardController);
for(ControllerIndex = 0;
for(U32 ControllerIndex = 0;
ControllerIndex < MAX_CONTROLLERS;
ControllerIndex++)
{
game_controller_input *OldController, *NewController;
game_controller_input *OldController,
*NewController;
OldController =
GetController(OldInput, ControllerIndex+1);
@@ -863,18 +791,15 @@ S32 main(S32 argc, char *argv[])
SDL_GameControllerGetAttached(
ControllerHandles[ControllerIndex]))
{
S16 StickX, StickY;
float Threshold;
NewController->IsAnalog =
OldController->IsAnalog;
NewController->IsConnected = TRUE;
StickX =
S16 StickX =
SDL_GameControllerGetAxis(
ControllerHandles[ControllerIndex],
SDL_CONTROLLER_AXIS_LEFTX);
StickY =
S16 StickY =
SDL_GameControllerGetAxis(
ControllerHandles[ControllerIndex],
SDL_CONTROLLER_AXIS_LEFTY);
@@ -925,7 +850,7 @@ S32 main(S32 argc, char *argv[])
NewController->IsAnalog = FALSE;
}
Threshold = 0.5f;
F32 Threshold = 0.5f;
SDLProcessInputDigitalButton(
ControllerHandles[
(NewController->StickAverageY <
@@ -1002,18 +927,21 @@ S32 main(S32 argc, char *argv[])
}
}
TargetQueueBytes = SoundOutput.LatencySampleCount *
SoundOutput.BytesPerSample;
BytesToWrite =
S32 TargetQueueBytes = SoundOutput.LatencySampleCount *
SoundOutput.BytesPerSample;
S32 BytesToWrite =
TargetQueueBytes - SDL_GetQueuedAudioSize(1);
game_sound_output_buffer SoundBuffer;
SoundBuffer.SamplesPerSecond =
SoundOutput.SamplesPerSecond;
SoundBuffer.SampleCount =
BytesToWrite / SoundOutput.BytesPerSample;
SoundBuffer.Samples = (short *)SoundOutput.Samples;
thread_context Context;
memset(&Context, 0, sizeof(Context));
game_offscreen_buffer Buffer;
Buffer.Memory = GlobalBackbuffer.Memory;
Buffer.Width = GlobalBackbuffer.Width;
Buffer.Height = GlobalBackbuffer.Height;
@@ -1028,11 +956,11 @@ S32 main(S32 argc, char *argv[])
SDLFillSoundBuffer(&SoundOutput, BytesToWrite);
WorkCounter = SDLGetWallClock();
WorkSecondsElapsed = SDLGetSecondsElapsed(LastCounter,
WorkCounter);
U64 WorkCounter = SDLGetWallClock();
F32 WorkSecondsElapsed =
SDLGetSecondsElapsed(LastCounter, WorkCounter);
SecondsElapsedForFrame = WorkSecondsElapsed;
F32 SecondsElapsedForFrame = WorkSecondsElapsed;
if(SecondsElapsedForFrame < TargetSecondsPerFrame) {
while(SecondsElapsedForFrame < TargetSecondsPerFrame) {
SecondsElapsedForFrame =
@@ -1046,21 +974,21 @@ S32 main(S32 argc, char *argv[])
/* TODO: Logging. */
}
EndCounter = SDLGetWallClock();
U64 EndCounter = SDLGetWallClock();
SDLDisplayBufferInWindow(GlobalBackbuffer, Window,
Renderer);
MSPerFrame = 1000.0 * SDLGetSecondsElapsed(LastCounter,
EndCounter);
FPS = 0.0;
F64 MSPerFrame = 1000.0 *
SDLGetSecondsElapsed(LastCounter, EndCounter);
F64 FPS = 0.0;
LastCounter = EndCounter;
#if 0
EndCycleCount = __rdtsc();
CyclesElapsed = EndCycleCount - LastCycleCount;
MCPF = ((double)CyclesElapsed / (1000.0 * 1000.0));
U64 EndCycleCount = __rdtsc();
U64 CyclesElapsed = EndCycleCount - LastCycleCount;
F64 MCPF = ((double)CyclesElapsed / (1000.0 * 1000.0));
fprintf(stderr, "%.02f ms/f, %.02f/s, %.02f mc/f\n",
MSPerFrame, FPS, MCPF);
LastCycleCount = EndCycleCount;