Day 24 done.
This commit is contained in:
+94
-44
@@ -13,7 +13,7 @@
|
||||
|
||||
#include <sys/stat.h> /* fstat */
|
||||
#include <fcntl.h> /* open */
|
||||
#include <unistd.h> /* close, write, read, readlink */
|
||||
#include <unistd.h> /* close, write, read, readlink, unlink */
|
||||
#include <dlfcn.h> /* dlopen */
|
||||
#include <sys/stat.h> /* 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 =
|
||||
|
||||
Reference in New Issue
Block a user