diff --git a/sdl_handmade.c b/sdl_handmade.c index 84b4d08..85e8539 100644 --- a/sdl_handmade.c +++ b/sdl_handmade.c @@ -13,7 +13,7 @@ #include /* fstat */ #include /* open */ -#include /* close, write, read, readlink */ +#include /* close, write, read, readlink, unlink */ #include /* dlopen */ #include /* stat */ #if __APPLE__ && __MACH__ @@ -35,13 +35,21 @@ SDL_GameController *ControllerHandles[MAX_CONTROLLERS]; static offscreen_buffer GlobalBackbuffer; +static S32 str_len(char *str) +{ + S32 count = 0; + while(*str++) + count++; + return count; +} + static U32 SafeTruncateUInt64(U64 Value) { U32 Result; Assert(Value <= 0xFFFFFFFF); Result = (U32)Value; - return Result; + return Result; } debug_read_file_result DEBUGPlatformReadEntireFile(const char *Filename) @@ -165,11 +173,20 @@ static void SDLDisplayBufferInWindow(offscreen_buffer Buffer, SDL_Window *Window, SDL_Renderer *Renderer) { + SDL_Rect dest_rect; + if(SDL_UpdateTexture(Buffer.Texture, 0, Buffer.Memory, Buffer.Pitch)) { /* TODO: Do something about this error! */ } - SDL_RenderCopy(Renderer, Buffer.Texture, 0, 0); + /* TODO: We temporarily introduce the target rectangle to avoid + * stretching the canvas. */ + /* SDL_RenderCopy(Renderer, Buffer.Texture, 0, 0); */ + dest_rect.x = 0; + dest_rect.y = 0; + dest_rect.w = 500; + dest_rect.h = 500; + SDL_RenderCopy(Renderer, Buffer.Texture, 0, (const SDL_Rect *)(&dest_rect)); SDL_RenderPresent(Renderer); } @@ -268,13 +285,18 @@ static void HandleEvent(SDL_Event *Event) case SDL_WINDOWEVENT: { switch(Event->window.event) { + /* TODO: We temporarily disable for ease of writing the + * rendering code. */ +#if 0 case SDL_WINDOWEVENT_SIZE_CHANGED: { sdl_window_dimension Dimension; Dimension = SDLGetWindowDimension(Window); + /* TODO: For now we fix the width and height. */ SDLResizeTexture(&GlobalBackbuffer, Renderer, Dimension.Width, Dimension.Height); } break; +#endif case SDL_WINDOWEVENT_EXPOSED: { } break; @@ -295,15 +317,32 @@ static void HandleEvent(SDL_Event *Event) } } +static void SDLGetInputFileLocation(sdl_state *SDLState, char *path, + size_t path_size, S32 SlotIndex) +{ + const char *file_name = "loop.hmi"; + + Assert(SlotIndex == 1); + + snprintf(path, path_size, "%s%s", SDLState->EXEDirPath, file_name); +} + static void SDLBeginRecordingInput(sdl_state *SDLState, S32 InputRecordingIndex) { - char *FileName; + char FileName[SDL_STATE_PATH_SIZE]; + + SDLGetInputFileLocation(SDLState, FileName, sizeof(FileName), + InputRecordingIndex); SDLState->InputRecordingIndex = InputRecordingIndex; - FileName = "foo.hmi"; + + if(unlink(FileName) != 0) { + /* TODO: Diagnostics . . . */ + } + SDLState->RecordingHandle = - open((const char *)FileName, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | + open(FileName, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); write(SDLState->RecordingHandle, SDLState->GameMmemoryBlock, (size_t)(SDLState->TotalSize)); @@ -318,13 +357,15 @@ static void SDLEndRecordingInput(sdl_state *SDLState) static void SDLBeginInputPlayback(sdl_state *SDLState, S32 InputPlayingIndex) { + char FileName[SDL_STATE_PATH_SIZE]; ssize_t size; - char *FileName; + + SDLGetInputFileLocation(SDLState, FileName, sizeof(FileName), + InputPlayingIndex); SDLState->InputPlayingIndex = InputPlayingIndex; - FileName = "foo.hmi"; SDLState->PlaybackHandle = - open((const char *)FileName, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | + open(FileName, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); size = read(SDLState->PlaybackHandle, SDLState->GameMmemoryBlock, (size_t)(SDLState->TotalSize)); @@ -352,6 +393,7 @@ static void SDLPlaybackInput(sdl_state *SDLState, game_input *NewInput) PlayingIndex = SDLState->InputPlayingIndex; SDLEndInputPlayback(SDLState); SDLBeginInputPlayback(SDLState, PlayingIndex); + size = read(SDLState->PlaybackHandle, NewInput, sizeof(*NewInput)); } } @@ -522,6 +564,7 @@ static U32 GetLastWriteTime(const char *FileName) memset(&file_info, 0, sizeof(file_info)); if(stat(FileName, &file_info) != 0) { /* TODO: Diagnostic. perror("stat failed"); */ + perror("stat failed"); } return (U32)file_info.st_mtime; @@ -566,56 +609,63 @@ static void SDLUnloadGameCode(sdl_game_code *GameCode) GameCode->UpdateAndRender = NULL; } -char *GetExecutablePath() +void GetExecutablePath(char *path, size_t path_size) { - static char path[1024]; - size_t path_size; #if __APPLE__ && __MACH__ U32 size; #else ssize_t size; #endif - /* NOTE: We choose 1024 only because MacOS's MAXPATHLEN says such a - * value. For example, linux/limits.h PATH_MAX says 4096. */ - path[0] = '\0'; - path_size = sizeof(path); + if(path_size > 0) { + path[0] = '\0'; #if __APPLE__ && __MACH__ - size = path_size; - if(_NSGetExecutablePath(path, &size) != 0) { /* NOTE: Not an absolute - path. */ - /* TODO: Diagnostics. */ - } + size = path_size; + if(_NSGetExecutablePath(path, &size) != 0) { /* NOTE: Not an + absolute + path. */ + /* TODO: Diagnostics. */ + } #else - size = readlink("/proc/self/exe", path, path_size - 1); - if(size != -1) { - path[size] = '\0'; - } else { - /* TODO: Diagnostics. */ - } + size = readlink("/proc/self/exe", path, path_size - 1); + if(size != -1) { + path[size] = '\0'; + } else { + /* TODO: Diagnostics. */ + } #endif - - return path; + } } -S32 main(S32 argc, char *argv[]) +static void SDLGetEXEDirPath(char *path, size_t path_size) { - char *path; U32 len, i; - char game_dll_path[1024]; - SDL_Window *Window; - path = GetExecutablePath(); - len = strlen(path); + GetExecutablePath(path, path_size); + len = str_len(path); i = len; while(path[i] != '/' || i == 0) { i--; } path[i+1] = '\0'; +} - snprintf(game_dll_path, sizeof(game_dll_path), "%s%s", path, - GAME_DLL_NAME); +static void SDLGetDLLPath(char *path, size_t path_size, char *exe_path) +{ + snprintf(path, path_size, "%s%s", exe_path, GAME_DLL_NAME); +} + +S32 main(S32 argc, char *argv[]) +{ + sdl_state SDLState; + SDL_Window *Window; + + memset(&SDLState, 0, sizeof(SDLState)); + + SDLGetEXEDirPath(SDLState.EXEDirPath, sizeof(SDLState.EXEDirPath)); + SDLGetDLLPath(SDLState.DLLPath, sizeof(SDLState.DLLPath), + SDLState.EXEDirPath); if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER | SDL_INIT_AUDIO)) @@ -629,7 +679,7 @@ S32 main(S32 argc, char *argv[]) * 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, 700, 500, + SDL_WINDOWPOS_UNDEFINED, 500, 500, SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALWAYS_ON_TOP); if(Window) { @@ -643,7 +693,6 @@ S32 main(S32 argc, char *argv[]) * its actual size. */ /* SDL_RenderPresent(Renderer) is enough to display the window. */ if(Renderer) { - sdl_state SDLState; sdl_window_dimension Dimension; sdl_sound_output SoundOutput; game_memory GameMemory; @@ -654,7 +703,6 @@ S32 main(S32 argc, char *argv[]) void *BaseAddress = (void *)(0); #endif - memset(&SDLState, 0, sizeof(SDLState)); GlobalRunning = TRUE; Dimension = SDLGetWindowDimension(Window); @@ -685,7 +733,7 @@ S32 main(S32 argc, char *argv[]) memset(&GameMemory, 0, sizeof(GameMemory)); GameMemory.PermanentStorageSize = MB(64); - GameMemory.TransientStorageSize = GB(4); + GameMemory.TransientStorageSize = GB(1); GameMemory.DEBUGPlatformReadEntireFile = &DEBUGPlatformReadEntireFile; GameMemory.DEBUGPlatformWriteEntireFile = @@ -724,7 +772,7 @@ S32 main(S32 argc, char *argv[]) GlobalPerfCountFrequency = SDL_GetPerformanceFrequency(); - Game = SDLLoadGameCode(game_dll_path); + Game = SDLLoadGameCode(SDLState.DLLPath); while(GlobalRunning) { S32 MonitorRefreshHz, GameUpdateHz; @@ -759,10 +807,10 @@ S32 main(S32 argc, char *argv[]) GameUpdateHz = MonitorRefreshHz; TargetSecondsPerFrame = 1.0f / (F32)GameUpdateHz; - NewDLLWriteTime = GetLastWriteTime(game_dll_path); + NewDLLWriteTime = GetLastWriteTime(SDLState.DLLPath); if(NewDLLWriteTime > Game.DLLLastWriteTime) { SDLUnloadGameCode(&Game); - Game = SDLLoadGameCode(game_dll_path); + Game = SDLLoadGameCode(SDLState.DLLPath); } OldKeyboardController = GetController(OldInput, 0); @@ -803,6 +851,8 @@ S32 main(S32 argc, char *argv[]) S16 StickX, StickY; float Threshold; + NewController->IsAnalog = + OldController->IsAnalog; NewController->IsConnected = TRUE; StickX = diff --git a/sdl_handmade.h b/sdl_handmade.h index 77e6554..aa5a89d 100644 --- a/sdl_handmade.h +++ b/sdl_handmade.h @@ -30,6 +30,9 @@ typedef struct sdl_sound_output { void *Samples; } sdl_sound_output; +/* NOTE: We choose 1024 only because MacOS's MAXPATHLEN says such a value. + * For example, linux/limits.h PATH_MAX says 4096. */ +#define SDL_STATE_PATH_SIZE 1024 typedef struct sdl_state { U64 TotalSize; void *GameMmemoryBlock; @@ -37,8 +40,12 @@ typedef struct sdl_state { S32 RecordingHandle; S32 InputRecordingIndex; + // NOTE: These functions might be NULL. Check before calling them! S32 PlaybackHandle; S32 InputPlayingIndex; + + char EXEDirPath[SDL_STATE_PATH_SIZE]; + char DLLPath[SDL_STATE_PATH_SIZE]; } sdl_state; #endif