Shall not pass 80 characters in width.
This commit is contained in:
+477
-178
@@ -37,20 +37,27 @@ static offscreen_buffer GlobalBackbuffer;
|
||||
|
||||
static U32 SafeTruncateUInt64(U64 Value)
|
||||
{
|
||||
U32 Result;
|
||||
|
||||
Assert(Value <= 0xFFFFFFFF);
|
||||
U32 Result = (U32)Value;
|
||||
Result = (U32)Value;
|
||||
return Result;
|
||||
}
|
||||
|
||||
debug_read_file_result DEBUGPlatformReadEntireFile(const char *Filename)
|
||||
{
|
||||
debug_read_file_result Result = {0};
|
||||
S32 FileHandle = open(Filename, O_RDONLY);
|
||||
debug_read_file_result Result;
|
||||
S32 FileHandle;
|
||||
struct stat FileStatus;
|
||||
U32 BytesToRead;
|
||||
U8 *NextByteLocation;
|
||||
|
||||
memset(&Result, 0, sizeof(Result));
|
||||
FileHandle = open(Filename, O_RDONLY);
|
||||
if(FileHandle == -1) {
|
||||
return Result;
|
||||
}
|
||||
|
||||
struct stat FileStatus;
|
||||
if(fstat(FileHandle, &FileStatus) == -1) {
|
||||
close(FileHandle);
|
||||
return Result;
|
||||
@@ -64,10 +71,12 @@ debug_read_file_result DEBUGPlatformReadEntireFile(const char *Filename)
|
||||
return Result;
|
||||
}
|
||||
|
||||
U32 BytesToRead = Result.ContentsSize;
|
||||
U8 *NextByteLocation = (U8 *)Result.Contents;
|
||||
BytesToRead = Result.ContentsSize;
|
||||
NextByteLocation = (U8 *)Result.Contents;
|
||||
while(BytesToRead) {
|
||||
U32 BytesRead = read(FileHandle, NextByteLocation, BytesToRead);
|
||||
U32 BytesRead;
|
||||
|
||||
BytesRead = read(FileHandle, NextByteLocation, BytesToRead);
|
||||
if(BytesRead == (U32)-1) {
|
||||
free(Result.Contents);
|
||||
Result.Contents = 0;
|
||||
@@ -84,16 +93,24 @@ debug_read_file_result DEBUGPlatformReadEntireFile(const char *Filename)
|
||||
return Result;
|
||||
}
|
||||
|
||||
B32 DEBUGPlatformWriteEntireFile(const char *Filename, U32 MemorySize, void *Memory)
|
||||
B32 DEBUGPlatformWriteEntireFile(const char *Filename, U32 MemorySize,
|
||||
void *Memory)
|
||||
{
|
||||
S32 FileHandle = open(Filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
S32 FileHandle;
|
||||
U32 BytesToWrite;
|
||||
U8 *NextByteLocation;
|
||||
|
||||
FileHandle = open(Filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR |
|
||||
S_IRGRP | S_IROTH);
|
||||
if(FileHandle == -1)
|
||||
return FALSE;
|
||||
|
||||
U32 BytesToWrite = MemorySize;
|
||||
U8 *NextByteLocation = (U8*)Memory;
|
||||
BytesToWrite = MemorySize;
|
||||
NextByteLocation = (U8*)Memory;
|
||||
while(BytesToWrite) {
|
||||
U32 BytesWritten = write(FileHandle, NextByteLocation, BytesToWrite);
|
||||
U32 BytesWritten;
|
||||
|
||||
BytesWritten = write(FileHandle, NextByteLocation, BytesToWrite);
|
||||
if(BytesWritten == (U32)-1) {
|
||||
close(FileHandle);
|
||||
return FALSE;
|
||||
@@ -121,17 +138,22 @@ static sdl_window_dimension SDLGetWindowDimension(SDL_Window *Window)
|
||||
return Dimension;
|
||||
}
|
||||
|
||||
static void SDLResizeTexture(offscreen_buffer *Buffer, SDL_Renderer *Renderer, int Width, int Height)
|
||||
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);
|
||||
|
||||
S32 BytesPerPixel = 4;
|
||||
BytesPerPixel = 4;
|
||||
|
||||
Buffer->Texture = SDL_CreateTexture(Renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, Width, Height);
|
||||
Buffer->Texture = SDL_CreateTexture(Renderer, SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_TEXTUREACCESS_STREAMING,
|
||||
Width, Height);
|
||||
Buffer->Memory = malloc(Width * Height * BytesPerPixel);
|
||||
|
||||
Buffer->Height = Height;
|
||||
@@ -139,7 +161,9 @@ static void SDLResizeTexture(offscreen_buffer *Buffer, SDL_Renderer *Renderer, i
|
||||
Buffer->Pitch = Width * BytesPerPixel;
|
||||
}
|
||||
|
||||
static void SDLDisplayBufferInWindow(offscreen_buffer Buffer, SDL_Window *Window, SDL_Renderer *Renderer)
|
||||
static void SDLDisplayBufferInWindow(offscreen_buffer Buffer,
|
||||
SDL_Window *Window,
|
||||
SDL_Renderer *Renderer)
|
||||
{
|
||||
if(SDL_UpdateTexture(Buffer.Texture, 0, Buffer.Memory, Buffer.Pitch)) {
|
||||
/* TODO: Do something about this error! */
|
||||
@@ -151,14 +175,17 @@ static void SDLDisplayBufferInWindow(offscreen_buffer Buffer, SDL_Window *Window
|
||||
|
||||
static void SDLInitControllers()
|
||||
{
|
||||
int MaxJoysticks = SDL_NumJoysticks();
|
||||
int ControllerIndex = 0;
|
||||
for(int JoystickIndex = 0; JoystickIndex < MaxJoysticks; JoystickIndex++) {
|
||||
S32 MaxJoysticks, ControllerIndex, JoystickIndex;
|
||||
|
||||
MaxJoysticks = SDL_NumJoysticks();
|
||||
ControllerIndex = 0;
|
||||
for(JoystickIndex = 0; JoystickIndex < MaxJoysticks; JoystickIndex++) {
|
||||
if(!SDL_IsGameController(JoystickIndex))
|
||||
continue;
|
||||
if(ControllerIndex >= MAX_CONTROLLERS)
|
||||
break;
|
||||
ControllerHandles[ControllerIndex] = SDL_GameControllerOpen(JoystickIndex);
|
||||
ControllerHandles[ControllerIndex] =
|
||||
SDL_GameControllerOpen(JoystickIndex);
|
||||
ControllerIndex++;
|
||||
}
|
||||
}
|
||||
@@ -166,17 +193,23 @@ static void SDLInitControllers()
|
||||
/*
|
||||
static void SDLDeinitControllers()
|
||||
{
|
||||
for(int ControllerIndex = 0; ControllerIndex < MAX_CONTROLLERS; ControllerIndex++) {
|
||||
if (ControllerHandles[ControllerIndex])
|
||||
S32 ControllerIndex;
|
||||
|
||||
for(ControllerIndex = 0;
|
||||
ControllerIndex < MAX_CONTROLLERS;
|
||||
ControllerIndex++)
|
||||
{
|
||||
if(ControllerHandles[ControllerIndex])
|
||||
SDL_GameControllerClose(ControllerHandles[ControllerIndex]);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
static void SDLInitSound(S32 SamplesPerSecond, S32 BufferSize)
|
||||
{
|
||||
SDL_AudioSpec AudioSettings = {0};
|
||||
SDL_AudioSpec AudioSettings;
|
||||
|
||||
memset(&AudioSettings, 0, sizeof(AudioSettings));
|
||||
|
||||
AudioSettings.freq = SamplesPerSecond;
|
||||
AudioSettings.format = AUDIO_S16LSB;
|
||||
@@ -190,7 +223,8 @@ static void SDLInitSound(S32 SamplesPerSecond, S32 BufferSize)
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLFillSoundBuffer(sdl_sound_output *SoundOutput, S32 BytesToWrite)
|
||||
static void SDLFillSoundBuffer(sdl_sound_output *SoundOutput,
|
||||
S32 BytesToWrite)
|
||||
{
|
||||
SDL_QueueAudio(1, SoundOutput->Samples, BytesToWrite);
|
||||
}
|
||||
@@ -200,18 +234,22 @@ static void SDLClearSoundBuffer(sdl_sound_output *SoundOutput)
|
||||
memset(SoundOutput->Samples, 0, SoundOutput->SecondaryBufferSize);
|
||||
}
|
||||
|
||||
static void SDLProcessKeyboardMessage(game_button_state *NewState, B32 IsDown)
|
||||
static void SDLProcessKeyboardMessage(game_button_state *NewState,
|
||||
B32 IsDown)
|
||||
{
|
||||
Assert(NewState->EndedDown != IsDown);
|
||||
NewState->EndedDown = IsDown;
|
||||
++NewState->HalfTransitionCount;
|
||||
}
|
||||
|
||||
static void SDLProcessInputDigitalButton(SDL_GameController *Controller, game_button_state *OldState,
|
||||
SDL_GameControllerButton Button, game_button_state *NewState)
|
||||
static void SDLProcessInputDigitalButton(SDL_GameController *Controller,
|
||||
game_button_state *OldState,
|
||||
SDL_GameControllerButton Button,
|
||||
game_button_state *NewState)
|
||||
{
|
||||
NewState->EndedDown = SDL_GameControllerGetButton(Controller, Button);
|
||||
NewState->HalfTransitionCount = (OldState->EndedDown != NewState->EndedDown) ? 1 : 0;
|
||||
NewState->HalfTransitionCount =
|
||||
(OldState->EndedDown != NewState->EndedDown) ? 1 : 0;
|
||||
}
|
||||
|
||||
static void HandleEvent(SDL_Event *Event)
|
||||
@@ -224,11 +262,16 @@ static void HandleEvent(SDL_Event *Event)
|
||||
case SDL_WINDOWEVENT: {
|
||||
switch(Event->window.event) {
|
||||
case SDL_WINDOWEVENT_SIZE_CHANGED: {
|
||||
SDL_Window *Window = SDL_GetWindowFromID(Event->window.windowID);
|
||||
SDL_Renderer *Renderer = SDL_GetRenderer(Window);
|
||||
SDL_Window *Window;
|
||||
SDL_Renderer *Renderer;
|
||||
sdl_window_dimension Dimension;
|
||||
|
||||
sdl_window_dimension Dimension = SDLGetWindowDimension(Window);
|
||||
SDLResizeTexture(&GlobalBackbuffer, Renderer, Dimension.Width, Dimension.Height);
|
||||
Window = SDL_GetWindowFromID(Event->window.windowID);
|
||||
Renderer = SDL_GetRenderer(Window);
|
||||
|
||||
Dimension = SDLGetWindowDimension(Window);
|
||||
SDLResizeTexture(&GlobalBackbuffer, Renderer,
|
||||
Dimension.Width, Dimension.Height);
|
||||
} break;
|
||||
|
||||
case SDL_WINDOWEVENT_EXPOSED: {
|
||||
@@ -238,12 +281,18 @@ static void HandleEvent(SDL_Event *Event)
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLBeginRecordingInput(sdl_state *SDLState, S32 InputRecordingIndex)
|
||||
static void SDLBeginRecordingInput(sdl_state *SDLState,
|
||||
S32 InputRecordingIndex)
|
||||
{
|
||||
char *FileName;
|
||||
|
||||
SDLState->InputRecordingIndex = InputRecordingIndex;
|
||||
const char *FileName = "foo.hmi";
|
||||
SDLState->RecordingHandle = open(FileName, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
write(SDLState->RecordingHandle, SDLState->GameMmemoryBlock, (size_t)(SDLState->TotalSize));
|
||||
FileName = "foo.hmi";
|
||||
SDLState->RecordingHandle =
|
||||
open((const char *)FileName, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR |
|
||||
S_IRGRP | S_IROTH);
|
||||
write(SDLState->RecordingHandle, SDLState->GameMmemoryBlock,
|
||||
(size_t)(SDLState->TotalSize));
|
||||
}
|
||||
|
||||
static void SDLEndRecordingInput(sdl_state *SDLState)
|
||||
@@ -252,11 +301,19 @@ static void SDLEndRecordingInput(sdl_state *SDLState)
|
||||
SDLState->InputRecordingIndex = 0;
|
||||
}
|
||||
|
||||
static void SDLBeginInputPlayback(sdl_state *SDLState, S32 InputPlayingIndex)
|
||||
static void SDLBeginInputPlayback(sdl_state *SDLState,
|
||||
S32 InputPlayingIndex)
|
||||
{
|
||||
ssize_t size;
|
||||
char *FileName;
|
||||
|
||||
SDLState->InputPlayingIndex = InputPlayingIndex;
|
||||
const char *FileName = "foo.hmi";
|
||||
SDLState->PlaybackHandle = open(FileName, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
FileName = "foo.hmi";
|
||||
SDLState->PlaybackHandle =
|
||||
open((const char *)FileName, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR |
|
||||
S_IRGRP | S_IROTH);
|
||||
size = read(SDLState->PlaybackHandle, SDLState->GameMmemoryBlock,
|
||||
(size_t)(SDLState->TotalSize));
|
||||
}
|
||||
|
||||
static void SDLEndInputPlayback(sdl_state *SDLState)
|
||||
@@ -272,24 +329,32 @@ static void SDLRecordInput(sdl_state *SDLState, game_input *NewInput)
|
||||
|
||||
static void SDLPlaybackInput(sdl_state *SDLState, game_input *NewInput)
|
||||
{
|
||||
ssize_t size = read(SDLState->PlaybackHandle, NewInput, sizeof(*NewInput));
|
||||
if(size == EOF || size == -1) {
|
||||
S32 PlayingIndex = SDLState->InputPlayingIndex;
|
||||
ssize_t size;
|
||||
|
||||
size = read(SDLState->PlaybackHandle, NewInput, sizeof(*NewInput));
|
||||
if(size == 0 || size == -1) {
|
||||
S32 PlayingIndex;
|
||||
|
||||
PlayingIndex = SDLState->InputPlayingIndex;
|
||||
SDLEndInputPlayback(SDLState);
|
||||
SDLBeginInputPlayback(SDLState, PlayingIndex);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLProcessMessages(sdl_state *SDLState, game_controller_input *KeyboardController)
|
||||
static void SDLProcessMessages(sdl_state *SDLState,
|
||||
game_controller_input *KeyboardController)
|
||||
{
|
||||
SDL_Event Event;
|
||||
while(SDL_PollEvent(&Event)) {
|
||||
switch(Event.type) {
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP: {
|
||||
SDL_Keycode KeyCode = Event.key.keysym.sym;
|
||||
B32 IsDown = (Event.key.state == SDL_PRESSED);
|
||||
B32 WasDown = FALSE;
|
||||
SDL_Keycode KeyCode;
|
||||
B32 IsDown, WasDown;
|
||||
|
||||
KeyCode = Event.key.keysym.sym;
|
||||
IsDown = (Event.key.state == SDL_PRESSED);
|
||||
WasDown = FALSE;
|
||||
if(Event.key.state == SDL_RELEASED) {
|
||||
WasDown = TRUE;
|
||||
} else if(Event.key.repeat != 0) {
|
||||
@@ -298,34 +363,61 @@ static void SDLProcessMessages(sdl_state *SDLState, game_controller_input *Keybo
|
||||
|
||||
if(Event.key.repeat == 0) {
|
||||
if(KeyCode == SDLK_w) {
|
||||
SDLProcessKeyboardMessage(&KeyboardController->MoveUp, IsDown);
|
||||
SDLProcessKeyboardMessage(
|
||||
&KeyboardController->u.buttons.MoveUp,
|
||||
IsDown);
|
||||
} else if(KeyCode == SDLK_s) {
|
||||
SDLProcessKeyboardMessage(&KeyboardController->MoveDown, IsDown);
|
||||
SDLProcessKeyboardMessage(
|
||||
&KeyboardController->u.buttons.MoveDown,
|
||||
IsDown);
|
||||
} else if(KeyCode == SDLK_a) {
|
||||
SDLProcessKeyboardMessage(&KeyboardController->MoveLeft, IsDown);
|
||||
SDLProcessKeyboardMessage(
|
||||
&KeyboardController->u.buttons.MoveLeft,
|
||||
IsDown);
|
||||
} else if(KeyCode == SDLK_d) {
|
||||
SDLProcessKeyboardMessage(&KeyboardController->MoveRight, IsDown);
|
||||
SDLProcessKeyboardMessage(
|
||||
&KeyboardController->u.buttons.MoveRight,
|
||||
IsDown);
|
||||
} else if(KeyCode == SDLK_q) {
|
||||
SDLProcessKeyboardMessage(&KeyboardController->LeftShoulder, IsDown);
|
||||
SDLProcessKeyboardMessage(
|
||||
&KeyboardController->u.buttons.LeftShoulder,
|
||||
IsDown);
|
||||
} else if(KeyCode == SDLK_e) {
|
||||
SDLProcessKeyboardMessage(&KeyboardController->RightShoulder, IsDown);
|
||||
SDLProcessKeyboardMessage(
|
||||
&KeyboardController->u.buttons.RightShoulder,
|
||||
IsDown);
|
||||
} else if(KeyCode == SDLK_UP) {
|
||||
SDLProcessKeyboardMessage(&KeyboardController->ActionUp, IsDown);
|
||||
SDLProcessKeyboardMessage(
|
||||
&KeyboardController->u.buttons.ActionUp,
|
||||
IsDown);
|
||||
} else if(KeyCode == SDLK_DOWN) {
|
||||
SDLProcessKeyboardMessage(&KeyboardController->ActionDown, IsDown);
|
||||
SDLProcessKeyboardMessage(
|
||||
&KeyboardController->u.buttons.ActionDown,
|
||||
IsDown);
|
||||
} else if(KeyCode == SDLK_LEFT) {
|
||||
SDLProcessKeyboardMessage(&KeyboardController->ActionLeft, IsDown);
|
||||
SDLProcessKeyboardMessage(
|
||||
&KeyboardController->u.buttons.ActionLeft,
|
||||
IsDown);
|
||||
} else if(KeyCode == SDLK_RIGHT) {
|
||||
SDLProcessKeyboardMessage(&KeyboardController->ActionRight, IsDown);
|
||||
SDLProcessKeyboardMessage(
|
||||
&KeyboardController->u.buttons.ActionRight,
|
||||
IsDown);
|
||||
} else if(KeyCode == SDLK_ESCAPE) {
|
||||
SDLProcessKeyboardMessage(&KeyboardController->Start, IsDown);
|
||||
SDLProcessKeyboardMessage(
|
||||
&KeyboardController->u.buttons.Start,
|
||||
IsDown);
|
||||
} else if(KeyCode == SDLK_SPACE) {
|
||||
SDLProcessKeyboardMessage(&KeyboardController->Back, IsDown);
|
||||
SDLProcessKeyboardMessage(
|
||||
&KeyboardController->u.buttons.Back,
|
||||
IsDown);
|
||||
}
|
||||
}
|
||||
|
||||
if(WasDown) {
|
||||
B32 AltKeyWasDown;
|
||||
|
||||
#if BUILD_INTERNAL
|
||||
|
||||
if(KeyCode == SDLK_l) {
|
||||
if(SDLState->InputRecordingIndex == 0) {
|
||||
SDLBeginRecordingInput(SDLState, 1);
|
||||
@@ -336,8 +428,11 @@ static void SDLProcessMessages(sdl_state *SDLState, game_controller_input *Keybo
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 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. */
|
||||
B32 AltKeyWasDown = (Event.key.keysym.mod & KMOD_ALT);
|
||||
/* 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);
|
||||
if(KeyCode == SDLK_F4 && AltKeyWasDown)
|
||||
GlobalRunning = FALSE;
|
||||
#if BUILD_INTERNAL
|
||||
@@ -356,24 +451,32 @@ static void SDLProcessMessages(sdl_state *SDLState, game_controller_input *Keybo
|
||||
|
||||
static F32 SDLProcessInputStickValue(F32 Value, S32 DeadZoneThreshold)
|
||||
{
|
||||
F32 Result = 0.0f;
|
||||
F32 Result;
|
||||
|
||||
Result = 0.0f;
|
||||
if(Value < -DeadZoneThreshold)
|
||||
Result = (F32)((Value + DeadZoneThreshold) / (32768.0f - DeadZoneThreshold));
|
||||
Result = (F32)((Value + DeadZoneThreshold) /
|
||||
(32768.0f - DeadZoneThreshold));
|
||||
else if(Value > DeadZoneThreshold)
|
||||
Result = (F32)((Value + DeadZoneThreshold) / (32767.0f - DeadZoneThreshold));
|
||||
Result = (F32)((Value + DeadZoneThreshold) /
|
||||
(32767.0f - DeadZoneThreshold));
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
#define DEFAULT_REFRESH_RATE 60
|
||||
static S32 SDLGetWindowRefreshRate(SDL_Window *Window)
|
||||
{
|
||||
int DisplayIndex = SDL_GetWindowDisplayIndex(Window);
|
||||
S32 DisplayIndex;
|
||||
SDL_DisplayMode Mode;
|
||||
|
||||
DisplayIndex = SDL_GetWindowDisplayIndex(Window);
|
||||
|
||||
if(SDL_GetDesktopDisplayMode(DisplayIndex, &Mode) != 0)
|
||||
return DEFAULT_REFRESH_RATE;
|
||||
if(Mode.refresh_rate == 0)
|
||||
return DEFAULT_REFRESH_RATE;
|
||||
|
||||
return Mode.refresh_rate;
|
||||
}
|
||||
|
||||
@@ -391,15 +494,18 @@ typedef struct sdl_game_code {
|
||||
void *GameCodeDLL;
|
||||
U32 DLLLastWriteTime;
|
||||
|
||||
void (*UpdateAndRender)(game_memory *, game_input *, game_offscreen_buffer *, game_sound_output_buffer *);
|
||||
void (*UpdateAndRender)(game_memory *, game_input *,
|
||||
game_offscreen_buffer *,
|
||||
game_sound_output_buffer *);
|
||||
|
||||
B32 IsValid;
|
||||
} sdl_game_code;
|
||||
|
||||
static U32 GetLastWriteTime(const char *FileName)
|
||||
{
|
||||
struct stat file_info = {0};
|
||||
struct stat file_info;
|
||||
|
||||
memset(&file_info, 0, sizeof(file_info));
|
||||
if(stat(FileName, &file_info) != 0) {
|
||||
/* TODO: Diagnostic. perror("stat failed"); */
|
||||
}
|
||||
@@ -411,13 +517,17 @@ static U32 GetLastWriteTime(const char *FileName)
|
||||
|
||||
static sdl_game_code SDLLoadGameCode(char *DLLPath)
|
||||
{
|
||||
sdl_game_code Result = {0};
|
||||
sdl_game_code Result;
|
||||
memset(&Result, 0, sizeof(Result));
|
||||
|
||||
Result.GameCodeDLL = dlopen(DLLPath, RTLD_NOW);
|
||||
if(Result.GameCodeDLL) {
|
||||
Result.DLLLastWriteTime = GetLastWriteTime(DLLPath);
|
||||
|
||||
Result.UpdateAndRender = (void(*)(game_memory *, game_input *, game_offscreen_buffer *, game_sound_output_buffer *))dlsym(Result.GameCodeDLL, "UpdateAndRender");
|
||||
Result.UpdateAndRender =
|
||||
(void(*)(game_memory *, game_input *, game_offscreen_buffer *,
|
||||
game_sound_output_buffer *))dlsym(Result.GameCodeDLL,
|
||||
"UpdateAndRender");
|
||||
if(!Result.UpdateAndRender) {
|
||||
/* TODO: Diagnostic. dlerror() */
|
||||
}
|
||||
@@ -444,16 +554,27 @@ static void SDLUnloadGameCode(sdl_game_code *GameCode)
|
||||
|
||||
char *GetExecutablePath()
|
||||
{
|
||||
static char path[1024] = ""; /* NOTE: We choose 1024 only because MacOS's MAXPATHLEN says such a value. For example, linux/limits.h PATH_MAX says 4096. */
|
||||
size_t path_size = sizeof(path);
|
||||
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 __APPLE__ && __MACH__
|
||||
U32 size = path_size;
|
||||
if(_NSGetExecutablePath(path, &size) != 0) { /* NOTE: Not an absolute path. */
|
||||
size = path_size;
|
||||
if(_NSGetExecutablePath(path, &size) != 0) { /* NOTE: Not an absolute
|
||||
path. */
|
||||
/* TODO: Diagnostics. */
|
||||
}
|
||||
#else
|
||||
ssize_t size = readlink("/proc/self/exe", path, path_size - 1);
|
||||
size = readlink("/proc/self/exe", path, path_size - 1);
|
||||
if(size != -1) {
|
||||
path[size] = '\0';
|
||||
} else {
|
||||
@@ -466,51 +587,48 @@ char *GetExecutablePath()
|
||||
|
||||
S32 main(S32 argc, char *argv[])
|
||||
{
|
||||
char *path = GetExecutablePath();
|
||||
U32 len = strlen(path);
|
||||
U32 i = len;
|
||||
char *path;
|
||||
U32 len, i;
|
||||
char game_dll_path[1024];
|
||||
SDL_Window *Window;
|
||||
|
||||
path = GetExecutablePath();
|
||||
len = strlen(path);
|
||||
i = len;
|
||||
while(path[i] != '/' || i == 0) {
|
||||
i--;
|
||||
}
|
||||
path[i+1] = '\0';
|
||||
|
||||
char game_dll_path[1024];
|
||||
snprintf(game_dll_path, sizeof(game_dll_path), "%s%s", path, GAME_DLL_NAME);
|
||||
snprintf(game_dll_path, sizeof(game_dll_path), "%s%s", path,
|
||||
GAME_DLL_NAME);
|
||||
|
||||
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER | SDL_INIT_AUDIO)) {
|
||||
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER |
|
||||
SDL_INIT_AUDIO))
|
||||
{
|
||||
/* TODO: This didn't work . . . */
|
||||
}
|
||||
|
||||
SDLInitControllers();
|
||||
|
||||
SDL_Window *Window = SDL_CreateWindow("Handmade Hero", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 700, 500, SDL_WINDOW_RESIZABLE);
|
||||
|
||||
Window = SDL_CreateWindow("Handmade Hero", SDL_WINDOWPOS_UNDEFINED,
|
||||
SDL_WINDOWPOS_UNDEFINED, 700, 500,
|
||||
SDL_WINDOW_RESIZABLE);
|
||||
if(Window) {
|
||||
/*SDL_Renderer *Renderer = SDL_CreateRenderer(Window, -1, 0); */
|
||||
SDL_Renderer *Renderer = SDL_CreateRenderer(Window, -1, SDL_RENDERER_PRESENTVSYNC);
|
||||
/* "Wayland needs an event loop and rendering or it won't function." https://github.com/libsdl-org/SDL/issues/7699#issuecomment-1545684792 */
|
||||
/* NOTE: This means that we need to readraw to even resize the window, otherwise the window frame will appear outdated to its actual size. */
|
||||
SDL_Renderer *Renderer;
|
||||
|
||||
Renderer = SDL_CreateRenderer(Window, -1, SDL_RENDERER_PRESENTVSYNC);
|
||||
/* "Wayland needs an event loop and rendering or it won't function."
|
||||
* https://github.com/libsdl-org/SDL/issues/7699#issuecomment-1545684792 */
|
||||
/* NOTE: This means that we need to readraw to even resize the
|
||||
* window, otherwise the window frame will appear outdated to
|
||||
* its actual size. */
|
||||
/* SDL_RenderPresent(Renderer) is enough to display the window. */
|
||||
if(Renderer) {
|
||||
sdl_state SDLState = {0};
|
||||
GlobalRunning = TRUE;
|
||||
|
||||
sdl_window_dimension Dimension = SDLGetWindowDimension(Window);
|
||||
SDLResizeTexture(&GlobalBackbuffer, Renderer, Dimension.Width, Dimension.Height);
|
||||
|
||||
sdl_sound_output SoundOutput = {0};
|
||||
SoundOutput.SamplesPerSecond = 48000;
|
||||
SoundOutput.BytesPerSample = sizeof(S16) * 2;
|
||||
SoundOutput.SecondaryBufferSize = SoundOutput.SamplesPerSecond * SoundOutput.BytesPerSample;
|
||||
SoundOutput.tSine = 0;
|
||||
SoundOutput.LatencySampleCount = SoundOutput.SamplesPerSecond / 15;
|
||||
|
||||
SDLInitSound(SoundOutput.SamplesPerSecond, SoundOutput.SamplesPerSecond * SoundOutput.BytesPerSample / 60);
|
||||
SDL_PauseAudio(0);
|
||||
|
||||
SoundOutput.Samples = calloc(SoundOutput.SamplesPerSecond, SoundOutput.BytesPerSample);
|
||||
/* SoundOutput.Samples = malloc(SoundOutput.SecondaryBufferSize); */
|
||||
/* SDLClearSoundBuffer(&SoundOutput); */ /* NOTE: calloc auto clears to zero */
|
||||
sdl_state SDLState;
|
||||
sdl_window_dimension Dimension;
|
||||
sdl_sound_output SoundOutput;
|
||||
game_memory GameMemory;
|
||||
|
||||
#if BUILD_DEBUG
|
||||
void *BaseAddress = (void *)TB(2);
|
||||
@@ -518,129 +636,299 @@ S32 main(S32 argc, char *argv[])
|
||||
void *BaseAddress = (void *)(0);
|
||||
#endif
|
||||
|
||||
game_memory GameMemory = {0};
|
||||
memset(&SDLState, 0, sizeof(SDLState));
|
||||
GlobalRunning = TRUE;
|
||||
|
||||
Dimension = SDLGetWindowDimension(Window);
|
||||
SDLResizeTexture(&GlobalBackbuffer, Renderer, Dimension.Width,
|
||||
Dimension.Height);
|
||||
|
||||
memset(&SoundOutput, 0, sizeof(SoundOutput));
|
||||
SoundOutput.SamplesPerSecond = 48000;
|
||||
SoundOutput.BytesPerSample = sizeof(S16) * 2;
|
||||
SoundOutput.SecondaryBufferSize =
|
||||
SoundOutput.SamplesPerSecond * SoundOutput.BytesPerSample;
|
||||
SoundOutput.tSine = 0;
|
||||
SoundOutput.LatencySampleCount =
|
||||
SoundOutput.SamplesPerSecond / 15;
|
||||
|
||||
SDLInitSound(SoundOutput.SamplesPerSecond,
|
||||
SoundOutput.SamplesPerSecond * SoundOutput.BytesPerSample /
|
||||
60);
|
||||
SDL_PauseAudio(0);
|
||||
|
||||
SoundOutput.Samples =
|
||||
calloc(SoundOutput.SamplesPerSecond,
|
||||
SoundOutput.BytesPerSample);
|
||||
/* SoundOutput.Samples =
|
||||
* malloc(SoundOutput.SecondaryBufferSize); */
|
||||
/* NOTE: calloc auto clears to zero */
|
||||
/* SDLClearSoundBuffer(&SoundOutput); */
|
||||
|
||||
memset(&GameMemory, 0, sizeof(GameMemory));
|
||||
GameMemory.PermanentStorageSize = MB(64);
|
||||
GameMemory.TransientStorageSize = GB(4);
|
||||
GameMemory.DEBUGPlatformReadEntireFile = &DEBUGPlatformReadEntireFile;
|
||||
GameMemory.DEBUGPlatformWriteEntireFile = &DEBUGPlatformWriteEntireFile;
|
||||
GameMemory.DEBUGPlatformFreeFileMemory = &DEBUGPlatformFreeFileMemory;
|
||||
GameMemory.DEBUGPlatformReadEntireFile =
|
||||
&DEBUGPlatformReadEntireFile;
|
||||
GameMemory.DEBUGPlatformWriteEntireFile =
|
||||
&DEBUGPlatformWriteEntireFile;
|
||||
GameMemory.DEBUGPlatformFreeFileMemory =
|
||||
&DEBUGPlatformFreeFileMemory;
|
||||
|
||||
SDLState.TotalSize = GameMemory.PermanentStorageSize + GameMemory.TransientStorageSize;
|
||||
SDLState.GameMmemoryBlock = mmap(BaseAddress, SDLState.TotalSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); /* NOTE: On MacOS and Linux, mmap seems to zero-fill anonymous memory as a side-effect of security. */
|
||||
SDLState.TotalSize =
|
||||
GameMemory.PermanentStorageSize +
|
||||
GameMemory.TransientStorageSize;
|
||||
/* NOTE: On MacOS and Linux, mmap seems to zero-fill anonymous
|
||||
* memory as a side-effect of security. */
|
||||
SDLState.GameMmemoryBlock =
|
||||
mmap(BaseAddress, SDLState.TotalSize, PROT_READ |
|
||||
PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
GameMemory.PermanentStorage = SDLState.GameMmemoryBlock;
|
||||
GameMemory.TransientStorage = (U8 *)(GameMemory.PermanentStorage) + GameMemory.PermanentStorageSize;
|
||||
GameMemory.TransientStorage =
|
||||
(U8 *)(GameMemory.PermanentStorage) +
|
||||
GameMemory.PermanentStorageSize;
|
||||
|
||||
if(SoundOutput.Samples && GameMemory.PermanentStorage && GameMemory.TransientStorage) {
|
||||
if(SoundOutput.Samples &&
|
||||
GameMemory.PermanentStorage &&
|
||||
GameMemory.TransientStorage)
|
||||
{
|
||||
game_input Input[2];
|
||||
game_input *NewInput = &Input[0];
|
||||
game_input *OldInput = &Input[1];
|
||||
memset(&Input, 0, sizeof(Input));
|
||||
|
||||
GlobalPerfCountFrequency = SDL_GetPerformanceFrequency();
|
||||
game_input *NewInput, *OldInput;
|
||||
sdl_game_code Game;
|
||||
|
||||
U64 LastCounter;
|
||||
#if __x86_64__ || __i386__
|
||||
U64 LastCycleCount;
|
||||
#endif
|
||||
NewInput = &Input[0];
|
||||
OldInput = &Input[1];
|
||||
memset(&Input, 0, sizeof(Input));
|
||||
|
||||
sdl_game_code Game = SDLLoadGameCode(game_dll_path);
|
||||
GlobalPerfCountFrequency = SDL_GetPerformanceFrequency();
|
||||
|
||||
Game = SDLLoadGameCode(game_dll_path);
|
||||
|
||||
while(GlobalRunning) {
|
||||
S32 MonitorRefreshHz, GameUpdateHz;
|
||||
F32 TargetSecondsPerFrame;
|
||||
U32 NewDLLWriteTime, ButtonIndex, ControllerIndex;
|
||||
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;
|
||||
#if __x86_64__ || __i386__
|
||||
U64 EndCycleCount, CyclesElapsed;
|
||||
F64 MCPF;
|
||||
#endif
|
||||
|
||||
LastCounter = SDLGetWallClock();
|
||||
|
||||
#if __x86_64__ || __i386__
|
||||
LastCycleCount = __rdtsc(); /* NOTE: rdtsc reports clock cylces, however it is not meant for really precise profiler work as the value returned is varied. */
|
||||
#endif /* Also, __rdtsc is not available on MacOS ARM; I have not checked MacOS x64. */
|
||||
/* NOTE: rdtsc reports clock cylces, however it is not
|
||||
* meant for really precise profiler work as the
|
||||
* value returned is varied. */
|
||||
/* Also, __rdtsc is not available on MacOS ARM; I
|
||||
* have not checked MacOS x64. */
|
||||
LastCycleCount = __rdtsc();
|
||||
#endif
|
||||
|
||||
S32 MonitorRefreshHz = SDLGetWindowRefreshRate(Window);
|
||||
S32 GameUpdateHz = MonitorRefreshHz;
|
||||
F32 TargetSecondsPerFrame = 1.0f / (F32)GameUpdateHz;
|
||||
MonitorRefreshHz = SDLGetWindowRefreshRate(Window);
|
||||
GameUpdateHz = MonitorRefreshHz;
|
||||
TargetSecondsPerFrame = 1.0f / (F32)GameUpdateHz;
|
||||
|
||||
U32 NewDLLWriteTime = GetLastWriteTime(game_dll_path);
|
||||
NewDLLWriteTime = GetLastWriteTime(game_dll_path);
|
||||
if(NewDLLWriteTime > Game.DLLLastWriteTime) {
|
||||
SDLUnloadGameCode(&Game);
|
||||
Game = SDLLoadGameCode(game_dll_path);
|
||||
}
|
||||
|
||||
game_controller_input *OldKeyboardController = GetController(OldInput, 0);
|
||||
game_controller_input *NewKeyboardController = GetController(NewInput, 0);
|
||||
game_controller_input ZeroController = {0};
|
||||
OldKeyboardController = GetController(OldInput, 0);
|
||||
NewKeyboardController = GetController(NewInput, 0);
|
||||
memset(&ZeroController, 0, sizeof(ZeroController));
|
||||
*NewKeyboardController = ZeroController;
|
||||
NewKeyboardController->IsConnected = TRUE;
|
||||
|
||||
for(unsigned int ButtonIndex = 0; ButtonIndex < ARRAY_SIZE(NewKeyboardController->Buttons); ButtonIndex++) {
|
||||
NewKeyboardController->Buttons[ButtonIndex].EndedDown = OldKeyboardController->Buttons[ButtonIndex].EndedDown;
|
||||
for(ButtonIndex = 0;
|
||||
ButtonIndex < ARRAY_SIZE(
|
||||
NewKeyboardController->u.Buttons);
|
||||
ButtonIndex++)
|
||||
{
|
||||
NewKeyboardController->
|
||||
u.Buttons[ButtonIndex].EndedDown =
|
||||
OldKeyboardController->
|
||||
u.Buttons[ButtonIndex].
|
||||
EndedDown;
|
||||
}
|
||||
|
||||
SDLProcessMessages(&SDLState, NewKeyboardController);
|
||||
|
||||
for(unsigned int ControllerIndex = 0; ControllerIndex < MAX_CONTROLLERS; ControllerIndex++) {
|
||||
game_controller_input *OldController = GetController(OldInput, ControllerIndex+1);
|
||||
game_controller_input *NewController = GetController(NewInput, ControllerIndex+1);
|
||||
for(ControllerIndex = 0;
|
||||
ControllerIndex < MAX_CONTROLLERS;
|
||||
ControllerIndex++)
|
||||
{
|
||||
game_controller_input *OldController, *NewController;
|
||||
|
||||
OldController =
|
||||
GetController(OldInput, ControllerIndex+1);
|
||||
NewController =
|
||||
GetController(NewInput, ControllerIndex+1);
|
||||
|
||||
if(ControllerHandles[ControllerIndex] != 0 &&
|
||||
SDL_GameControllerGetAttached(
|
||||
ControllerHandles[ControllerIndex]))
|
||||
{
|
||||
S16 StickX, StickY;
|
||||
float Threshold;
|
||||
|
||||
if(ControllerHandles[ControllerIndex] != 0 && SDL_GameControllerGetAttached(ControllerHandles[ControllerIndex])) {
|
||||
NewController->IsConnected = TRUE;
|
||||
|
||||
S16 StickX = SDL_GameControllerGetAxis(ControllerHandles[ControllerIndex], SDL_CONTROLLER_AXIS_LEFTX);
|
||||
S16 StickY = SDL_GameControllerGetAxis(ControllerHandles[ControllerIndex], SDL_CONTROLLER_AXIS_LEFTY);
|
||||
StickX =
|
||||
SDL_GameControllerGetAxis(
|
||||
ControllerHandles[ControllerIndex],
|
||||
SDL_CONTROLLER_AXIS_LEFTX);
|
||||
StickY =
|
||||
SDL_GameControllerGetAxis(
|
||||
ControllerHandles[ControllerIndex],
|
||||
SDL_CONTROLLER_AXIS_LEFTY);
|
||||
|
||||
NewController->IsAnalog = TRUE;
|
||||
NewController->StickAverageX = SDLProcessInputStickValue((F32)StickX, CONTROLLER_LEFT_THUMB_DEADZONE);
|
||||
NewController->StickAverageY = SDLProcessInputStickValue((F32)StickY, CONTROLLER_LEFT_THUMB_DEADZONE);
|
||||
NewController->StickAverageX =
|
||||
SDLProcessInputStickValue((F32)StickX,
|
||||
CONTROLLER_LEFT_THUMB_DEADZONE);
|
||||
NewController->StickAverageY =
|
||||
SDLProcessInputStickValue((F32)StickY,
|
||||
CONTROLLER_LEFT_THUMB_DEADZONE);
|
||||
|
||||
if((NewController->StickAverageX != 0.0f) || (NewController->StickAverageY != 0.0f)) {
|
||||
if((NewController->StickAverageX != 0.0f) ||
|
||||
(NewController->StickAverageY != 0.0f))
|
||||
{
|
||||
NewController->IsAnalog = TRUE;
|
||||
}
|
||||
|
||||
if(SDL_GameControllerGetButton(ControllerHandles[ControllerIndex], SDL_CONTROLLER_BUTTON_DPAD_UP)) {
|
||||
if(SDL_GameControllerGetButton(
|
||||
ControllerHandles[ControllerIndex],
|
||||
SDL_CONTROLLER_BUTTON_DPAD_UP))
|
||||
{
|
||||
NewController->StickAverageY = -1.0f;
|
||||
NewController->IsAnalog = FALSE;
|
||||
}
|
||||
|
||||
if(SDL_GameControllerGetButton(ControllerHandles[ControllerIndex], SDL_CONTROLLER_BUTTON_DPAD_DOWN)) {
|
||||
if(SDL_GameControllerGetButton(
|
||||
ControllerHandles[ControllerIndex],
|
||||
SDL_CONTROLLER_BUTTON_DPAD_DOWN))
|
||||
{
|
||||
NewController->StickAverageY = 1.0f;
|
||||
NewController->IsAnalog = FALSE;
|
||||
}
|
||||
|
||||
if(SDL_GameControllerGetButton(ControllerHandles[ControllerIndex], SDL_CONTROLLER_BUTTON_DPAD_LEFT)) {
|
||||
if(SDL_GameControllerGetButton(
|
||||
ControllerHandles[ControllerIndex],
|
||||
SDL_CONTROLLER_BUTTON_DPAD_LEFT))
|
||||
{
|
||||
NewController->StickAverageX = -1.0f;
|
||||
NewController->IsAnalog = FALSE;
|
||||
}
|
||||
|
||||
if(SDL_GameControllerGetButton(ControllerHandles[ControllerIndex], SDL_CONTROLLER_BUTTON_DPAD_RIGHT)) {
|
||||
if(SDL_GameControllerGetButton(
|
||||
ControllerHandles[ControllerIndex],
|
||||
SDL_CONTROLLER_BUTTON_DPAD_RIGHT))
|
||||
{
|
||||
NewController->StickAverageX = 1.0f;
|
||||
NewController->IsAnalog = FALSE;
|
||||
}
|
||||
|
||||
float Threshold = 0.5f;
|
||||
SDLProcessInputDigitalButton(ControllerHandles[(NewController->StickAverageY < -Threshold) ? 1 : 0], &OldController->MoveUp, SDL_CONTROLLER_BUTTON_A, &NewController->MoveUp);
|
||||
SDLProcessInputDigitalButton(ControllerHandles[(NewController->StickAverageY > Threshold) ? 1 : 0], &OldController->MoveDown, SDL_CONTROLLER_BUTTON_A, &NewController->MoveDown);
|
||||
SDLProcessInputDigitalButton(ControllerHandles[(NewController->StickAverageX < -Threshold) ? 1 : 0], &OldController->MoveLeft, SDL_CONTROLLER_BUTTON_A, &NewController->MoveLeft);
|
||||
SDLProcessInputDigitalButton(ControllerHandles[(NewController->StickAverageX > Threshold) ? 1 : 0], &OldController->MoveRight, SDL_CONTROLLER_BUTTON_A, &NewController->MoveRight);
|
||||
Threshold = 0.5f;
|
||||
SDLProcessInputDigitalButton(
|
||||
ControllerHandles[
|
||||
(NewController->StickAverageY <
|
||||
-Threshold) ? 1 : 0],
|
||||
&OldController->u.buttons.MoveUp,
|
||||
SDL_CONTROLLER_BUTTON_A,
|
||||
&NewController->u.buttons.MoveUp);
|
||||
SDLProcessInputDigitalButton(
|
||||
ControllerHandles[
|
||||
(NewController->StickAverageY >
|
||||
Threshold) ? 1 : 0],
|
||||
&OldController->u.buttons.MoveDown,
|
||||
SDL_CONTROLLER_BUTTON_A,
|
||||
&NewController->u.buttons.MoveDown);
|
||||
SDLProcessInputDigitalButton(
|
||||
ControllerHandles[
|
||||
(NewController->StickAverageX <
|
||||
-Threshold) ? 1 : 0],
|
||||
&OldController->u.buttons.MoveLeft,
|
||||
SDL_CONTROLLER_BUTTON_A,
|
||||
&NewController->u.buttons.MoveLeft);
|
||||
SDLProcessInputDigitalButton(
|
||||
ControllerHandles[
|
||||
(NewController->StickAverageX >
|
||||
Threshold) ? 1 : 0],
|
||||
&OldController->u.buttons.MoveRight,
|
||||
SDL_CONTROLLER_BUTTON_A,
|
||||
&NewController->u.buttons.MoveRight);
|
||||
|
||||
SDLProcessInputDigitalButton(ControllerHandles[ControllerIndex], &OldController->ActionDown, SDL_CONTROLLER_BUTTON_A, &NewController->ActionDown);
|
||||
SDLProcessInputDigitalButton(ControllerHandles[ControllerIndex], &OldController->ActionRight, SDL_CONTROLLER_BUTTON_B, &NewController->ActionRight);
|
||||
SDLProcessInputDigitalButton(ControllerHandles[ControllerIndex], &OldController->ActionLeft, SDL_CONTROLLER_BUTTON_X, &NewController->ActionLeft);
|
||||
SDLProcessInputDigitalButton(ControllerHandles[ControllerIndex], &OldController->ActionUp, SDL_CONTROLLER_BUTTON_Y, &NewController->ActionUp);
|
||||
SDLProcessInputDigitalButton(ControllerHandles[ControllerIndex], &OldController->LeftShoulder, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, &NewController->LeftShoulder);
|
||||
SDLProcessInputDigitalButton(ControllerHandles[ControllerIndex], &OldController->RightShoulder, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, &NewController->RightShoulder);
|
||||
SDLProcessInputDigitalButton(
|
||||
ControllerHandles[ControllerIndex],
|
||||
&OldController->u.buttons.ActionDown,
|
||||
SDL_CONTROLLER_BUTTON_A,
|
||||
&NewController->u.buttons.ActionDown);
|
||||
SDLProcessInputDigitalButton(
|
||||
ControllerHandles[ControllerIndex],
|
||||
&OldController->u.buttons.ActionRight,
|
||||
SDL_CONTROLLER_BUTTON_B,
|
||||
&NewController->u.buttons.ActionRight);
|
||||
SDLProcessInputDigitalButton(
|
||||
ControllerHandles[ControllerIndex],
|
||||
&OldController->u.buttons.ActionLeft,
|
||||
SDL_CONTROLLER_BUTTON_X,
|
||||
&NewController->u.buttons.ActionLeft);
|
||||
SDLProcessInputDigitalButton(
|
||||
ControllerHandles[ControllerIndex],
|
||||
&OldController->u.buttons.ActionUp,
|
||||
SDL_CONTROLLER_BUTTON_Y,
|
||||
&NewController->u.buttons.ActionUp);
|
||||
SDLProcessInputDigitalButton(
|
||||
ControllerHandles[ControllerIndex],
|
||||
&OldController->u.buttons.LeftShoulder,
|
||||
SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
|
||||
&NewController->u.buttons.LeftShoulder);
|
||||
SDLProcessInputDigitalButton(
|
||||
ControllerHandles[ControllerIndex],
|
||||
&OldController->u.buttons.RightShoulder,
|
||||
SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
|
||||
&NewController->u.buttons.RightShoulder);
|
||||
|
||||
SDLProcessInputDigitalButton(ControllerHandles[ControllerIndex], &OldController->Start, SDL_CONTROLLER_BUTTON_START, &NewController->Start);
|
||||
SDLProcessInputDigitalButton(ControllerHandles[ControllerIndex], &OldController->Back, SDL_CONTROLLER_BUTTON_BACK, &NewController->Back);
|
||||
SDLProcessInputDigitalButton(
|
||||
ControllerHandles[ControllerIndex],
|
||||
&OldController->u.buttons.Start,
|
||||
SDL_CONTROLLER_BUTTON_START,
|
||||
&NewController->u.buttons.Start);
|
||||
SDLProcessInputDigitalButton(
|
||||
ControllerHandles[ControllerIndex],
|
||||
&OldController->u.buttons.Back,
|
||||
SDL_CONTROLLER_BUTTON_BACK,
|
||||
&NewController->u.buttons.Back);
|
||||
} else {
|
||||
/* NOTE: This controller is not plugged in. */
|
||||
NewController->IsConnected = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
TargetQueueBytes = SoundOutput.LatencySampleCount *
|
||||
SoundOutput.BytesPerSample;
|
||||
BytesToWrite =
|
||||
TargetQueueBytes - SDL_GetQueuedAudioSize(1);
|
||||
SoundBuffer.SamplesPerSecond =
|
||||
SoundOutput.SamplesPerSecond;
|
||||
SoundBuffer.SampleCount =
|
||||
BytesToWrite / SoundOutput.BytesPerSample;
|
||||
SoundBuffer.Samples = (short *)SoundOutput.Samples;
|
||||
|
||||
game_offscreen_buffer Buffer;
|
||||
Buffer.Memory = GlobalBackbuffer.Memory;
|
||||
Buffer.Width = GlobalBackbuffer.Width;
|
||||
Buffer.Height = GlobalBackbuffer.Height;
|
||||
@@ -654,41 +942,50 @@ S32 main(S32 argc, char *argv[])
|
||||
}
|
||||
|
||||
if(Game.UpdateAndRender)
|
||||
Game.UpdateAndRender(&GameMemory, NewInput, &Buffer, &SoundBuffer);
|
||||
Game.UpdateAndRender(&GameMemory, NewInput, &Buffer,
|
||||
&SoundBuffer);
|
||||
|
||||
SDLFillSoundBuffer(&SoundOutput, BytesToWrite);
|
||||
|
||||
U64 WorkCounter = SDLGetWallClock();
|
||||
F32 WorkSecondsElapsed = SDLGetSecondsElapsed(LastCounter, WorkCounter);
|
||||
WorkCounter = SDLGetWallClock();
|
||||
WorkSecondsElapsed = SDLGetSecondsElapsed(LastCounter,
|
||||
WorkCounter);
|
||||
|
||||
F32 SecondsElapsedForFrame = WorkSecondsElapsed;
|
||||
SecondsElapsedForFrame = WorkSecondsElapsed;
|
||||
if(SecondsElapsedForFrame < TargetSecondsPerFrame) {
|
||||
while(SecondsElapsedForFrame < TargetSecondsPerFrame) {
|
||||
SecondsElapsedForFrame = SDLGetSecondsElapsed(LastCounter, SDLGetWallClock());
|
||||
SDL_Delay((unsigned int)((TargetSecondsPerFrame - SecondsElapsedForFrame) * 1000.0));
|
||||
SecondsElapsedForFrame =
|
||||
SDLGetSecondsElapsed(LastCounter,
|
||||
SDLGetWallClock());
|
||||
SDL_Delay((U32)((TargetSecondsPerFrame -
|
||||
SecondsElapsedForFrame) * 1000.0));
|
||||
}
|
||||
} else {
|
||||
/* TODO: Missed frame rate! */
|
||||
/* TODO: Logging. */
|
||||
}
|
||||
|
||||
U64 EndCounter = SDLGetWallClock();
|
||||
EndCounter = SDLGetWallClock();
|
||||
|
||||
SDLDisplayBufferInWindow(GlobalBackbuffer, Window, Renderer);
|
||||
SDLDisplayBufferInWindow(GlobalBackbuffer, Window,
|
||||
Renderer);
|
||||
|
||||
F64 MSPerFrame = 1000.0 * SDLGetSecondsElapsed(LastCounter, EndCounter);
|
||||
F64 FPS = 0.0;
|
||||
MSPerFrame = 1000.0 * SDLGetSecondsElapsed(LastCounter,
|
||||
EndCounter);
|
||||
FPS = 0.0;
|
||||
|
||||
LastCounter = EndCounter;
|
||||
|
||||
#if __x86_64__ || __i386__
|
||||
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);
|
||||
EndCycleCount = __rdtsc();
|
||||
CyclesElapsed = EndCycleCount - LastCycleCount;
|
||||
MCPF = ((double)CyclesElapsed / (1000.0 * 1000.0));
|
||||
fprintf(stderr, "%.02f ms/f, %.02f/s, %.02f mc/f\n",
|
||||
MSPerFrame, FPS, MCPF);
|
||||
LastCycleCount = EndCycleCount;
|
||||
#else
|
||||
fprintf(stderr, "%.02f ms/f, %.02f/s\n", MSPerFrame, FPS);
|
||||
fprintf(stderr, "%.02f ms/f, %.02f/s\n",
|
||||
MSPerFrame, FPS);
|
||||
#endif
|
||||
|
||||
SWAP(game_input *, NewInput, OldInput);
|
||||
@@ -704,7 +1001,9 @@ S32 main(S32 argc, char *argv[])
|
||||
}
|
||||
|
||||
/* NOTE: Let the OS clean things up. */
|
||||
/* SDLDeinitControllers(); // NOTE: This, however, might need to be closed? Is there maybe some clean up state that close communicates to the controller? */
|
||||
/* NOTE: This, however, might need to be closed? Is there maybe some
|
||||
* clean up state that close communicates to the controller? */
|
||||
/* SDLDeinitControllers(); */
|
||||
/* SDL_CloseAudio(); */
|
||||
/* SDL_DestroyRenderer(Renderer); */
|
||||
/* SDL_DestroyWindow(Window); */
|
||||
|
||||
Reference in New Issue
Block a user