mirror of
https://github.com/Ed94/HandmadeHero.git
synced 2025-06-16 11:41:47 -07:00
Day 22 complete
This commit is contained in:
@ -110,7 +110,7 @@ render_weird_graident(OffscreenBuffer* buffer, u32 x_offset, u32 y_offset )
|
||||
u8 red = 0;
|
||||
#endif
|
||||
|
||||
*pixel++ = u32(red << 16) | u32(green << 8) | blue;
|
||||
*pixel++ = u32(red << 16) | u32(green/2 << 16) | blue/2 << 0;
|
||||
}
|
||||
wildcard += 0.5375f;
|
||||
row += buffer->Pitch;
|
||||
|
@ -50,7 +50,6 @@ struct AudioBuffer
|
||||
u32 RunningSampleIndex;
|
||||
s32 SamplesPerSecond;
|
||||
s32 NumSamples;
|
||||
char _PAD_[4];
|
||||
};
|
||||
|
||||
struct DigitalBtn
|
||||
@ -190,7 +189,6 @@ struct InputMode
|
||||
{
|
||||
InputBindCallback* Binds;
|
||||
s32 NumBinds;
|
||||
char _PAD_[4];
|
||||
};
|
||||
|
||||
void input_mode_pop( InputMode* mode );
|
||||
|
3
project/engine/engine_game_api.hpp
Normal file
3
project/engine/engine_game_api.hpp
Normal file
@ -0,0 +1,3 @@
|
||||
/*
|
||||
This represents the API only accessible to the engine to fullfill for the game module.
|
||||
*/
|
@ -1,11 +0,0 @@
|
||||
#include "platform/win32.hpp"
|
||||
#include "engine.hpp"
|
||||
|
||||
b32 WINAPI DllMain(
|
||||
HINSTANCE instance,
|
||||
DWORD reason_for_call,
|
||||
LPVOID reserved
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
@ -27,7 +27,6 @@ struct Actionable
|
||||
char const* Name;
|
||||
engine::InputBindCallback* Binds;
|
||||
s32 NumBinds;
|
||||
char _PAD_[4];
|
||||
};
|
||||
|
||||
struct ActionableMode
|
||||
|
@ -13,7 +13,4 @@
|
||||
|
||||
#if Build_Unity
|
||||
# include "engine/engine.cpp"
|
||||
# if SYSTEM_WINDOWS
|
||||
# include "engine/win32_engine.cpp"
|
||||
# endif
|
||||
#endif
|
||||
|
@ -16,6 +16,8 @@
|
||||
#pragma warning( disable: 4514 ) // Support for unused inline functions
|
||||
#pragma warning( disable: 4505 ) // Support for unused static functions
|
||||
#pragma warning( disable: 5045 ) // Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified
|
||||
#pragma warning( disable: 5264 ) // Support for 'const' variables unused
|
||||
#pragma warning( disable: 4820 ) // Support auto-adding padding to structs
|
||||
|
||||
// TODO(Ed) : REMOVE THESE WHEN HE GETS TO THEM
|
||||
#include <math.h> // TODO : Implement math ourselves
|
||||
@ -26,6 +28,7 @@
|
||||
#include "generics.hpp"
|
||||
#include "math_constants.hpp"
|
||||
#include "types.hpp"
|
||||
#include "strings.hpp"
|
||||
|
||||
#define NS_PLATFORM_BEGIN namespace platform {
|
||||
#define NS_PLATFORM_END }
|
||||
@ -45,7 +48,12 @@ struct Debug_FileContent
|
||||
{
|
||||
void* Data;
|
||||
u32 Size;
|
||||
char _PAD_[4];
|
||||
Byte _PAD_[4];
|
||||
};
|
||||
|
||||
struct BinaryModule
|
||||
{
|
||||
void* OpaqueHandle;
|
||||
};
|
||||
|
||||
using DebugFileFreeContentFn = void ( Debug_FileContent* file_content );
|
||||
@ -53,9 +61,54 @@ using DebugFileReadContentFn = Debug_FileContent ( char const* file_path );
|
||||
using DebugFileWriteContentFn = b32 ( char const* file_path, u32 content_size, void* content_memory );
|
||||
|
||||
using DebugSetPauseRenderingFn = void (b32 value);
|
||||
|
||||
// TODO(Ed): This also assumes the symbol name is always within size of the provided buffer, needs to fail if not.
|
||||
// Note: This is a temporary solution until there is more infrastructure for the engine to use.
|
||||
void get_symbol_from_module_table( Debug_FileContent symbol_table, u32 symbol_ID, char* symbol_name )
|
||||
{
|
||||
struct Token
|
||||
{
|
||||
char const* Ptr;
|
||||
u32 Len;
|
||||
char _PAD_[4];
|
||||
};
|
||||
|
||||
Token tokens[256] = {};
|
||||
s32 idx = 0;
|
||||
|
||||
char const* scanner = rcast( char const*, symbol_table.Data );
|
||||
u32 left = symbol_table.Size;
|
||||
while ( left )
|
||||
{
|
||||
if ( *scanner == '\n' || *scanner == '\r' )
|
||||
{
|
||||
++ scanner;
|
||||
-- left;
|
||||
}
|
||||
else
|
||||
{
|
||||
tokens[idx].Ptr = scanner;
|
||||
while ( left && *scanner != '\r' && *scanner != '\n' )
|
||||
{
|
||||
-- left;
|
||||
++ scanner;
|
||||
++ tokens[idx].Len;
|
||||
}
|
||||
++ idx;
|
||||
}
|
||||
}
|
||||
|
||||
Token& token = tokens[symbol_ID];
|
||||
while ( token.Len -- )
|
||||
{
|
||||
*symbol_name = *token.Ptr;
|
||||
++ symbol_name;
|
||||
++ token.Ptr;
|
||||
}
|
||||
*symbol_name = '\0';
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO(Ed) : Implement this later when settings UI is setup.
|
||||
#pragma region Settings Exposure
|
||||
// Exposing specific properties for user configuration in settings
|
||||
|
||||
@ -68,6 +121,13 @@ using SetMonitorRefreshRateFn = void ( u32 rate_in_hz );
|
||||
using GetEngineFrameTargetFn = u32 ();
|
||||
using SetEngineFrameTargetFn = void ( u32 rate_in_hz );
|
||||
|
||||
// This module api will be used to manage the editor and game modules from the engine side,
|
||||
// without the platform layer needing to know about it.
|
||||
|
||||
using LoadBinaryModuleFn = BinaryModule ( char const* module_path );
|
||||
using UnloadBinaryModuleFn = void ( BinaryModule* module );
|
||||
using GetModuleProcedureFn = void* ( BinaryModule module, char const* symbol );
|
||||
|
||||
struct ModuleAPI
|
||||
{
|
||||
#if Build_Development
|
||||
@ -83,6 +143,10 @@ struct ModuleAPI
|
||||
|
||||
GetEngineFrameTargetFn* get_engine_frame_target;
|
||||
SetEngineFrameTargetFn* set_engine_frame_target;
|
||||
|
||||
LoadBinaryModuleFn* load_binary_module;
|
||||
UnloadBinaryModuleFn* unload_binary_module;
|
||||
GetModuleProcedureFn* get_module_procedure;
|
||||
};
|
||||
|
||||
#pragma endregion Settings Exposure
|
||||
|
@ -42,7 +42,6 @@ struct ModuleAPI
|
||||
UpdateAudioFn* update_audio;
|
||||
|
||||
b32 IsValid;
|
||||
char _PAD_[4];
|
||||
};
|
||||
|
||||
NS_ENGINE_END
|
||||
|
@ -1,3 +0,0 @@
|
||||
/*
|
||||
This represents the API only accessible to the platform layer to fullfill for the game layer.
|
||||
*/
|
190
project/platform/strings.hpp
Normal file
190
project/platform/strings.hpp
Normal file
@ -0,0 +1,190 @@
|
||||
#include "macros.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
void str_append( u32 dest_len, char* dest, u32 src_len, char const* src );
|
||||
void str_concat( u32 dest_size, char* dest
|
||||
, u32 str_a_len, char const* str_a
|
||||
, u32 str_b_len, char const* str_b );
|
||||
u32 str_length( char const* str );
|
||||
|
||||
#define str_ascii( str ) { sizeof( str ) - 1, str }
|
||||
|
||||
// Length tracked raw strings.
|
||||
struct Str
|
||||
{
|
||||
u32 Len;
|
||||
char* Data;
|
||||
|
||||
void append( u32 src_len, char const* src ) {
|
||||
str_append( Len, Data, src_len, src );
|
||||
}
|
||||
void append( Str const src ) {
|
||||
str_append( Len, Data, src.Len, src.Data );
|
||||
}
|
||||
|
||||
static
|
||||
void concast( u32 dest_size, Str* dest, Str const str_a, Str const str_b )
|
||||
{
|
||||
str_concat( dest_size, dest->Data
|
||||
, str_a.Len, str_a.Data
|
||||
, str_b.Len, str_b.Data );
|
||||
dest->Len = str_a.Len + str_b.Len;
|
||||
}
|
||||
|
||||
operator char*() const {
|
||||
return Data;
|
||||
}
|
||||
char& operator []( u32 idx ) {
|
||||
return Data[idx];
|
||||
}
|
||||
char const& operator []( u32 idx ) const {
|
||||
return Data[idx];
|
||||
}
|
||||
};
|
||||
|
||||
template< u32 capacity >
|
||||
// Fixed length raw strings.
|
||||
struct StrFixed
|
||||
{
|
||||
constexpr static u32 Capacity = capacity;
|
||||
|
||||
u32 Len;
|
||||
char Data[capacity];
|
||||
|
||||
void append( u32 src_len, char const* src ) {
|
||||
str_append( Len, Data, src_len, src );
|
||||
}
|
||||
void append( Str const src ) {
|
||||
str_append( Len, Data, src.Len, src.Data );
|
||||
}
|
||||
|
||||
void concat( Str const str_a, Str const str_b )
|
||||
{
|
||||
str_concat( Capacity, Data
|
||||
, str_a.Len, str_a.Data
|
||||
, str_b.Len, str_b.Data );
|
||||
Len = str_a.Len + str_b.Len;
|
||||
}
|
||||
|
||||
operator char*() { return Data;}
|
||||
operator char const*() { return Data; }
|
||||
operator Str() { return { Len, Data }; }
|
||||
operator Str const() const { return { Len, Data }; }
|
||||
char& operator []( u32 idx ) {
|
||||
assert( idx < Capacity );
|
||||
return Data[idx];
|
||||
}
|
||||
char const& operator []( u32 idx ) const {
|
||||
assert( idx < Capacity );
|
||||
return Data[idx];
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
void str_append( u32 dest_len, char* dest, u32 src_len, char const* src )
|
||||
{
|
||||
assert( dest_len > 0 );
|
||||
assert( dest != nullptr );
|
||||
assert( src_len > 0 );
|
||||
assert( src != nullptr );
|
||||
assert( dest_len >= src_len );
|
||||
|
||||
char* dest_end = dest + dest_len;
|
||||
assert( *dest_end == '\0' );
|
||||
|
||||
u32 left = src_len;
|
||||
while ( left-- )
|
||||
{
|
||||
*dest = *src;
|
||||
++ dest;
|
||||
++ src;
|
||||
}
|
||||
}
|
||||
|
||||
void str_concat( u32 dest_size, char* dest
|
||||
, u32 str_a_len, char const* str_a
|
||||
, u32 str_b_len, char const* str_b )
|
||||
{
|
||||
assert( dest_size > 0 );
|
||||
assert( dest != nullptr );
|
||||
assert( *dest == '\0' );
|
||||
assert( str_a_len > 0 );
|
||||
assert( str_a != nullptr );
|
||||
assert( str_b_len > 0 );
|
||||
assert( str_b != nullptr );
|
||||
assert( str_a_len + str_b_len < dest_size );
|
||||
|
||||
char* dest_a = dest;
|
||||
char* dest_b = dest + str_a_len;
|
||||
if ( str_a_len > str_b_len )
|
||||
{
|
||||
u32 left = str_a_len;
|
||||
while ( left-- )
|
||||
{
|
||||
*dest_a = *str_a;
|
||||
*dest_b = *str_b;
|
||||
|
||||
++ dest_a;
|
||||
++ dest_b;
|
||||
++ str_a;
|
||||
++ str_b;
|
||||
}
|
||||
|
||||
left = str_a_len - str_b_len;
|
||||
while ( left-- )
|
||||
{
|
||||
*dest_b = *str_b;
|
||||
++ dest_b;
|
||||
++ str_b;
|
||||
}
|
||||
}
|
||||
else if ( str_a_len < str_b_len )
|
||||
{
|
||||
u32 left = str_b_len;
|
||||
while ( left-- )
|
||||
{
|
||||
*dest_a = *str_a;
|
||||
*dest_b = *str_b;
|
||||
++ dest_a;
|
||||
++ dest_b;
|
||||
++ str_a;
|
||||
++ str_b;
|
||||
}
|
||||
|
||||
left = str_b_len - str_a_len;
|
||||
while ( left-- )
|
||||
{
|
||||
*dest_a = *str_a;
|
||||
++ dest_a;
|
||||
++ str_a;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 left = str_a_len;
|
||||
while ( left-- )
|
||||
{
|
||||
*dest_a = *str_a;
|
||||
*dest_b = *str_b;
|
||||
++ dest_a;
|
||||
++ str_a;
|
||||
++ dest_b;
|
||||
++ str_b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
u32 str_length( char const* str )
|
||||
{
|
||||
assert( str != nullptr );
|
||||
|
||||
u32 result = 0;
|
||||
while ( *str != '\0' )
|
||||
{
|
||||
++ result;
|
||||
++ str;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
@ -97,6 +97,9 @@ static_assert( sizeof( uptr ) == sizeof( sptr ), "sizeof(uptr) != sizeof(sptr)"
|
||||
typedef float f32;
|
||||
typedef double f64;
|
||||
|
||||
struct Byte {};
|
||||
static_assert( sizeof( Byte ) == 1, "Unit type must be 1 byte in size" );
|
||||
|
||||
static_assert( sizeof( f32 ) == 4, "sizeof(f32) != 4" );
|
||||
static_assert( sizeof( f64 ) == 8, "sizeof(f64) != 8" );
|
||||
|
||||
|
@ -101,6 +101,16 @@ struct DirectSoundBuffer
|
||||
|
||||
|
||||
#pragma region Static Data
|
||||
|
||||
global StrFixed< S16_MAX > Path_Root;
|
||||
global StrFixed< S16_MAX > Path_Binaries;
|
||||
|
||||
constexpr Str FName_Engine_DLL = str_ascii("handmade_engine.dll");
|
||||
constexpr Str FName_Engine_DLL_InUse = str_ascii("handmade_engine_in_use.dll");
|
||||
|
||||
global StrFixed< S16_MAX > Path_Engine_DLL;
|
||||
global StrFixed< S16_MAX > Path_Engine_DLL_InUse;
|
||||
|
||||
// TODO(Ed) : This is a global for now.
|
||||
global b32 Running = false;
|
||||
global b32 Pause_Rendering = false;
|
||||
@ -130,7 +140,7 @@ global u32 Engine_Refresh_Hz = Monitor_Refresh_Hz / 2;
|
||||
global f32 Engine_Frame_Target_MS = 1000.f / scast(f32, Engine_Refresh_Hz);
|
||||
#pragma endregion Static Data
|
||||
|
||||
|
||||
#pragma region Internal
|
||||
#if Build_Debug
|
||||
struct DebugTimeMarker
|
||||
{
|
||||
@ -145,82 +155,6 @@ struct DebugTimeMarker
|
||||
DWORD ExpectedFlipCursor;
|
||||
};
|
||||
|
||||
void debug_file_free_content( Debug_FileContent* content )
|
||||
{
|
||||
if ( content->Data)
|
||||
{
|
||||
VirtualFree( content->Data, 0, MEM_Release);
|
||||
*content = {};
|
||||
}
|
||||
}
|
||||
|
||||
Debug_FileContent debug_file_read_content( char const* file_path )
|
||||
{
|
||||
Debug_FileContent result {};
|
||||
|
||||
HANDLE file_handle = CreateFileA( file_path
|
||||
, GENERIC_READ, FILE_SHARE_READ, 0
|
||||
, OPEN_EXISTING, 0, 0
|
||||
);
|
||||
if ( file_handle == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
// TODO(Ed) : Logging
|
||||
return result;
|
||||
}
|
||||
|
||||
GetFileSizeEx( file_handle, rcast(LARGE_INTEGER*, &result.Size) );
|
||||
if ( result.Size == 0 )
|
||||
{
|
||||
// TODO(Ed) : Logging
|
||||
return result;
|
||||
}
|
||||
result.Data = VirtualAlloc( 0, result.Size, MEM_Commit_Zeroed | MEM_Reserve, Page_Read_Write );
|
||||
|
||||
u32 bytes_read;
|
||||
if ( ReadFile( file_handle, result.Data, result.Size, rcast(LPDWORD, &bytes_read), 0 ) == false )
|
||||
{
|
||||
// TODO(Ed) : Logging
|
||||
return {};
|
||||
}
|
||||
|
||||
if ( bytes_read != result.Size )
|
||||
{
|
||||
// TODO : Logging
|
||||
return {};
|
||||
}
|
||||
|
||||
CloseHandle( file_handle );
|
||||
return result;
|
||||
}
|
||||
|
||||
b32 debug_file_write_content( char const* file_path, u32 content_size, void* content_memory )
|
||||
{
|
||||
HANDLE file_handle = CreateFileA( file_path
|
||||
, GENERIC_WRITE, 0, 0
|
||||
, CREATE_ALWAYS, 0, 0
|
||||
);
|
||||
if ( file_handle == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
// TODO : Logging
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD bytes_written;
|
||||
if ( WriteFile( file_handle, content_memory, content_size, & bytes_written, 0 ) == false )
|
||||
{
|
||||
// TODO : Logging
|
||||
return false;
|
||||
}
|
||||
|
||||
CloseHandle( file_handle );
|
||||
return true;
|
||||
}
|
||||
|
||||
void debug_set_pause_rendering( b32 value )
|
||||
{
|
||||
Pause_Rendering = value;
|
||||
}
|
||||
|
||||
internal void
|
||||
debug_draw_vertical( s32 x_pos, s32 top, s32 bottom, s32 color )
|
||||
{
|
||||
@ -748,84 +682,144 @@ process_pending_window_messages( engine::KeyboardState* keyboard )
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma endregion Internal
|
||||
|
||||
#pragma region Platfom API
|
||||
u32 get_monitor_refresh_rate();
|
||||
|
||||
#pragma endregion Platform API
|
||||
|
||||
// TODO(Ed): This also assumes the symbol name is always within size of the provided buffer, needs to fail if not.
|
||||
void get_symbol_from_module_table( Debug_FileContent symbol_table, u32 symbol_ID, char* symbol_name )
|
||||
#if Build_Development
|
||||
void debug_file_free_content( Debug_FileContent* content )
|
||||
{
|
||||
struct Token
|
||||
if ( content->Data)
|
||||
{
|
||||
char const* Ptr;
|
||||
u32 Len;
|
||||
char _PAD_[4];
|
||||
};
|
||||
|
||||
Token tokens[256] = {};
|
||||
s32 idx = 0;
|
||||
|
||||
char const* scanner = rcast( char const*, symbol_table.Data );
|
||||
u32 left = symbol_table.Size;
|
||||
while ( left )
|
||||
{
|
||||
if ( *scanner == '\n' || *scanner == '\r' )
|
||||
{
|
||||
++ scanner;
|
||||
-- left;
|
||||
}
|
||||
else
|
||||
{
|
||||
tokens[idx].Ptr = scanner;
|
||||
while ( left && *scanner != '\r' && *scanner != '\n' )
|
||||
{
|
||||
-- left;
|
||||
++ scanner;
|
||||
++ tokens[idx].Len;
|
||||
}
|
||||
++ idx;
|
||||
}
|
||||
VirtualFree( content->Data, 0, MEM_Release);
|
||||
*content = {};
|
||||
}
|
||||
|
||||
Token& token = tokens[symbol_ID];
|
||||
while ( token.Len -- )
|
||||
{
|
||||
*symbol_name = *token.Ptr;
|
||||
++ symbol_name;
|
||||
++ token.Ptr;
|
||||
}
|
||||
*symbol_name = '\0';
|
||||
}
|
||||
|
||||
// Right now they are just the data directory
|
||||
#define Path_To_Symbol_Tables
|
||||
Debug_FileContent debug_file_read_content( char const* file_path )
|
||||
{
|
||||
Debug_FileContent result {};
|
||||
|
||||
HANDLE file_handle = CreateFileA( file_path
|
||||
, GENERIC_READ, FILE_SHARE_READ, 0
|
||||
, OPEN_EXISTING, 0, 0
|
||||
);
|
||||
if ( file_handle == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
// TODO(Ed) : Logging
|
||||
return result;
|
||||
}
|
||||
|
||||
GetFileSizeEx( file_handle, rcast(LARGE_INTEGER*, &result.Size) );
|
||||
if ( result.Size == 0 )
|
||||
{
|
||||
// TODO(Ed) : Logging
|
||||
return result;
|
||||
}
|
||||
result.Data = VirtualAlloc( 0, result.Size, MEM_Commit_Zeroed | MEM_Reserve, Page_Read_Write );
|
||||
|
||||
u32 bytes_read;
|
||||
if ( ReadFile( file_handle, result.Data, result.Size, rcast(LPDWORD, &bytes_read), 0 ) == false )
|
||||
{
|
||||
// TODO(Ed) : Logging
|
||||
return {};
|
||||
}
|
||||
|
||||
if ( bytes_read != result.Size )
|
||||
{
|
||||
// TODO : Logging
|
||||
return {};
|
||||
}
|
||||
|
||||
CloseHandle( file_handle );
|
||||
return result;
|
||||
}
|
||||
|
||||
b32 debug_file_write_content( char const* file_path, u32 content_size, void* content_memory )
|
||||
{
|
||||
HANDLE file_handle = CreateFileA( file_path
|
||||
, GENERIC_WRITE, 0, 0
|
||||
, CREATE_ALWAYS, 0, 0
|
||||
);
|
||||
if ( file_handle == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
// TODO : Logging
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD bytes_written;
|
||||
if ( WriteFile( file_handle, content_memory, content_size, & bytes_written, 0 ) == false )
|
||||
{
|
||||
// TODO : Logging
|
||||
return false;
|
||||
}
|
||||
|
||||
CloseHandle( file_handle );
|
||||
return true;
|
||||
}
|
||||
|
||||
void debug_set_pause_rendering( b32 value )
|
||||
{
|
||||
Pause_Rendering = value;
|
||||
}
|
||||
#endif
|
||||
|
||||
u32 get_monitor_refresh_rate();
|
||||
|
||||
BinaryModule load_binary_module( char const* module_path )
|
||||
{
|
||||
HMODULE lib = LoadLibraryA( module_path );
|
||||
return BinaryModule { scast(void*, lib) };
|
||||
}
|
||||
|
||||
void unload_binary_module( BinaryModule* module )
|
||||
{
|
||||
FreeLibrary( scast(HMODULE, module->OpaqueHandle) );
|
||||
*module = {};
|
||||
}
|
||||
|
||||
void* get_binary_module_symbol( BinaryModule module, char const* symbol_name )
|
||||
{
|
||||
return rcast(void*, GetProcAddress( scast(HMODULE, module.OpaqueHandle), symbol_name ));
|
||||
}
|
||||
#pragma endregion Platform API
|
||||
|
||||
FILETIME file_get_last_write_time( char const* path )
|
||||
{
|
||||
WIN32_FIND_DATAA dll_file_info = {};
|
||||
HANDLE dll_file_handle = FindFirstFileA( path, & dll_file_info );
|
||||
if ( dll_file_handle == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
FindClose( dll_file_handle );
|
||||
}
|
||||
|
||||
return dll_file_info.ftLastWriteTime;
|
||||
}
|
||||
|
||||
#pragma region Engine Module API
|
||||
global HMODULE Lib_Handmade_Engine = nullptr;
|
||||
|
||||
engine::ModuleAPI load_engine_module_api()
|
||||
{
|
||||
using ModuleAPI = engine::ModuleAPI;
|
||||
|
||||
// TODO(Ed) : Need proper paything to the dll (not assume is in the base directory).
|
||||
|
||||
CopyFileA( "handmade_engine.dll", "handmade_engine_temp.dll", FALSE );
|
||||
CopyFileA( Path_Engine_DLL, Path_Engine_DLL_InUse, FALSE );
|
||||
|
||||
// Engine
|
||||
Lib_Handmade_Engine = LoadLibraryA( "handmade_engine_temp.dll" );
|
||||
Lib_Handmade_Engine = LoadLibraryA( Path_Engine_DLL_InUse );
|
||||
if ( ! Lib_Handmade_Engine )
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
constexpr char const*
|
||||
handmade_engine_symbols = Path_To_Symbol_Tables "handmade_engine.symbols";
|
||||
constexpr Str fname_handmade_engine_symbols = str_ascii("handmade_engine.symbols");
|
||||
|
||||
Debug_FileContent symbol_table = debug_file_read_content( handmade_engine_symbols );
|
||||
StrFixed< S16_MAX > path_handmade_engine_symbols { 0, {} };
|
||||
path_handmade_engine_symbols.concat( Path_Binaries, fname_handmade_engine_symbols );
|
||||
|
||||
Debug_FileContent symbol_table = debug_file_read_content( path_handmade_engine_symbols );
|
||||
if ( symbol_table.Size == 0 )
|
||||
{
|
||||
fatal( "Failed to laod symbol table for handmade engine module!" );
|
||||
fatal( "Failed to load symbol table for handmade engine module!" );
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -872,6 +866,7 @@ void unload_engine_module_api( engine::ModuleAPI* engine_api )
|
||||
OutputDebugStringA( "Unloaded engine module API\n" );
|
||||
}
|
||||
}
|
||||
#pragma endregion Engine Module API
|
||||
|
||||
NS_PLATFORM_END
|
||||
|
||||
@ -910,6 +905,10 @@ WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR commandline, int sho
|
||||
platform_api.set_monitor_refresh_rate = nullptr;
|
||||
platform_api.get_engine_frame_target = nullptr;
|
||||
platform_api.set_engine_frame_target = nullptr;
|
||||
|
||||
platform_api.load_binary_module = & load_binary_module;
|
||||
platform_api.unload_binary_module = & unload_binary_module;
|
||||
platform_api.get_module_procedure = & get_binary_module_symbol;
|
||||
}
|
||||
|
||||
// Memory
|
||||
@ -940,9 +939,6 @@ WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR commandline, int sho
|
||||
}
|
||||
}
|
||||
|
||||
// Load engine module
|
||||
engine::ModuleAPI engine_api = load_engine_module_api();
|
||||
|
||||
WNDCLASSW window_class {};
|
||||
HWND window_handle = nullptr;
|
||||
{
|
||||
@ -983,6 +979,41 @@ WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR commandline, int sho
|
||||
// WinDimensions dimensions = get_window_dimensions( window_handle );
|
||||
resize_dib_section( &Surface_Back_Buffer, 1280, 720 );
|
||||
|
||||
// Setup pathing
|
||||
// TODO(Ed): This will not support long paths, NEEDS to be changed to support long paths.
|
||||
{
|
||||
char path_buffer[S16_MAX];
|
||||
GetModuleFileNameA( 0, path_buffer, sizeof(path_buffer) );
|
||||
|
||||
if ( GetCurrentDirectoryA( S16_MAX, Path_Binaries ) == 0 )
|
||||
{
|
||||
fatal( "Failed to get the root directory!" );
|
||||
}
|
||||
Path_Binaries.Len = str_length( Path_Binaries );
|
||||
Path_Binaries[ Path_Binaries.Len ] = '\\';
|
||||
++ Path_Binaries.Len;
|
||||
|
||||
if ( SetCurrentDirectoryA( ".." ) == 0 )
|
||||
{
|
||||
fatal( "Failed to set current directory to root!");
|
||||
}
|
||||
|
||||
if ( GetCurrentDirectoryA( S16_MAX, Path_Root.Data ) == 0 )
|
||||
{
|
||||
fatal( "Failed to get the root directory!" );
|
||||
}
|
||||
Path_Root.Len = str_length(Path_Root.Data);
|
||||
Path_Root.Data[ Path_Root.Len ] = '\\';
|
||||
++ Path_Root.Len;
|
||||
|
||||
Path_Engine_DLL. concat( Path_Binaries, FName_Engine_DLL );
|
||||
Path_Engine_DLL_InUse.concat( Path_Binaries, FName_Engine_DLL_InUse );
|
||||
}
|
||||
|
||||
// Load engine module
|
||||
FILETIME engine_api_load_time = file_get_last_write_time( Path_Engine_DLL );
|
||||
engine::ModuleAPI engine_api = load_engine_module_api();
|
||||
|
||||
b32 sound_is_valid = false;
|
||||
DWORD ds_cursor_byte_delta = 0;
|
||||
f32 ds_latency_ms = 0;
|
||||
@ -1091,8 +1122,6 @@ WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR commandline, int sho
|
||||
OutputDebugStringA( text_buffer );
|
||||
#endif
|
||||
|
||||
u64 module_reload_counter = 0;
|
||||
|
||||
Running = true;
|
||||
#if 0
|
||||
// This tests the play & write cursor update frequency.
|
||||
@ -1109,13 +1138,13 @@ WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR commandline, int sho
|
||||
#endif
|
||||
while( Running )
|
||||
{
|
||||
if ( module_reload_counter > 120 )
|
||||
FILETIME engine_api_current_time = file_get_last_write_time( Path_Engine_DLL );
|
||||
if ( CompareFileTime( & engine_api_load_time, & engine_api_current_time ) != 0 )
|
||||
{
|
||||
engine_api_load_time = engine_api_current_time;
|
||||
unload_engine_module_api( & engine_api );
|
||||
engine_api = load_engine_module_api();
|
||||
module_reload_counter = 0;
|
||||
}
|
||||
++ module_reload_counter;
|
||||
|
||||
process_pending_window_messages( new_keyboard );
|
||||
|
||||
@ -1490,6 +1519,9 @@ WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR commandline, int sho
|
||||
|
||||
engine_api.shutdown( & engine_memory, & platform_api );
|
||||
|
||||
unload_engine_module_api( & engine_api );
|
||||
DeleteFileA( Path_Engine_DLL_InUse );
|
||||
|
||||
if ( jsl_num_devices > 0 )
|
||||
{
|
||||
for ( u32 jsl_device_index = 0; jsl_device_index < jsl_num_devices; ++ jsl_device_index )
|
||||
|
Reference in New Issue
Block a user