Day 25 complete!!!

This commit is contained in:
Edward R. Gonzalez 2023-09-30 15:40:27 -04:00
parent dc43db117c
commit 4599ca1167
6 changed files with 234 additions and 183 deletions

1
.gitignore vendored
View File

@ -26,6 +26,7 @@ build
**/*.hmi
**/*.symbols
**/*.hm_*
data/test.out
data/handmade_engine.symbols

View File

@ -14,22 +14,22 @@
"label": "Static Data"
},
{
"line": 655,
"line": 661,
"column": 0,
"label": "Timing"
},
{
"line": 1575,
"line": 1591,
"column": 4,
"label": "Main Loop : Audio Processing"
},
{
"line": 1694,
"line": 1710,
"column": 2,
"label": "Main Loop : Timing Update"
},
{
"line": 1778,
"line": 1794,
"column": 0,
"label": "Main Loop : End"
}

View File

@ -1,12 +1,13 @@
# Day 25
Him doing replay save states at the platform layer is causing issues for me...
I'm going to most likely end up doing two categories of save states, one for engine level and one for platform level.
The engine level can just store it in the memory struct, and the game memory can just stay where it is.
I want to use the same "save state" slots for both engine and game since there is no need different memory buckets for that. They will at worst case be ofcourse the size of engine's memory block.
So if there is 4, we are looking at 5x the actual memory size. This is fine for now since the engine block is 2 gigs.
Snapshots of of memory are are handled using take and load snapshot functions. They can be used separate from the replay looping functionality.
Replay looping however is dependent on snapshots so if a replay is save/loaded it will use the same snapshot slot of memory to do that state management.
Since engine manages the memory of game and editor (when editor exists), restoring its state will also restore the game and editor state.
Feels great to be past the platform layer bulk!!!

View File

@ -29,6 +29,11 @@ struct EngineActions
#if Build_Development
b32 pause_renderer;
b32 set_snapshot_slot_1;
b32 set_snapshot_slot_2;
b32 set_snapshot_slot_3;
b32 set_snapshot_slot_4;
#endif
};
@ -181,17 +186,20 @@ render_player( OffscreenBuffer* buffer, s32 pos_x, s32 pos_y )
}
}
using SnapshotFn = void ( s32 slot, Memory* memory, platform::ModuleAPI* platform_api );
#if Build_Development
using SnapshotFn = void ( Memory* memory, platform::ModuleAPI* platform_api );
internal
void load_engine_snapshot( s32 slot, Memory* memory, platform::ModuleAPI* platform_api )
void load_engine_snapshot( Memory* memory, platform::ModuleAPI* platform_api )
{
platform_api->memory_copy( memory->persistent, memory->total_size(), memory->snapshots[ slot ].memory );
platform_api->memory_copy( memory->persistent, memory->total_size()
, memory->snapshots[ memory->active_snapshot_slot ].memory );
}
internal
void load_game_snapshot( s32 slot, Memory* memory, platform::ModuleAPI* platform_api )
void load_game_snapshot( Memory* memory, platform::ModuleAPI* platform_api )
{
s32 slot = memory->active_snapshot_slot;
EngineState* state = rcast( EngineState*, memory->persistent );
void* persistent_slot = memory->snapshots[ slot ].memory;
@ -202,14 +210,15 @@ void load_game_snapshot( s32 slot, Memory* memory, platform::ModuleAPI* platform
}
internal
void take_engine_snapshot( s32 slot, Memory* memory, platform::ModuleAPI* platform_api )
void take_engine_snapshot( Memory* memory, platform::ModuleAPI* platform_api )
{
platform_api->memory_copy( memory->snapshots[ slot ].memory, memory->total_size(), memory->persistent );
platform_api->memory_copy( memory->snapshots[ memory->active_snapshot_slot ].memory, memory->total_size(), memory->persistent );
}
internal
void take_game_snapshot( s32 slot, Memory* memory, platform::ModuleAPI* platform_api )
void take_game_snapshot( Memory* memory, platform::ModuleAPI* platform_api )
{
s32 slot = memory->active_snapshot_slot;
EngineState* state = rcast( EngineState*, memory->persistent );
void* persistent_slot = memory->snapshots[ slot ].memory;
@ -219,64 +228,54 @@ void take_game_snapshot( s32 slot, Memory* memory, platform::ModuleAPI* platform
platform_api->memory_copy( transient_slot, state->game_memory.transient_size, state->game_memory.transient );
}
#define Snapshot_New_Way 1
internal
void begin_recording_input( Memory* memory, InputState* input, platform::ModuleAPI* platform_api )
{
Str file_name = str_ascii("test_input.hmi");
Str file_name = str_ascii("test_input_");
StrPath file_path = {};
file_path.concat( platform_api->path_scratch, file_name );
snprintf( file_path.ptr, file_path.len, "%s%d.hm_replay", file_name.ptr, memory->active_snapshot_slot );
memory->active_recording_file.path = file_path;
memory->input_recording_index = 1;
#if Snapshot_New_Way
platform_api->file_delete( memory->active_recording_file.path );
#else
platform_api->file_write_content( & state->ActiveInputRecordingFile, scast(u32, state->game_memory.PersistentSize), state->game_memory.Persistent );
#endif
platform_api->file_delete( memory->active_input_replay_file.path );
memory->active_input_replay_file.path = file_path;
memory->replay_mode = ReplayMode_Record;
}
internal
void end_recording_input( Memory* memory, InputState* input, platform::ModuleAPI* platform_api )
{
memory->input_recording_index = 0;
platform_api->file_close( & memory->active_recording_file );
memory->replay_mode = ReplayMode_Off;
platform_api->file_close( & memory->active_input_replay_file );
}
internal
void begin_playback_input( Memory* memory, InputState* input, platform::ModuleAPI* platform_api )
{
Str file_name = str_ascii("test_input.hmi");
Str file_name = str_ascii("test_input_");
StrPath file_path = {};
file_path.concat( platform_api->path_scratch, file_name );
snprintf( file_path.ptr, file_path.len, "%s%d.hm_replay", file_name.ptr, memory->active_snapshot_slot );
// TODO(Ed - From Casey): Recording system still seems to take too long
// on record start - find out what Windows is doing and if
// we can speed up / defer some of that processing.
if ( platform_api->file_check_exists( file_path ) )
{
memory->active_playback_file.path = file_path;
memory->input_playback_index = 1;
memory->active_input_replay_file.path = file_path;
memory->replay_mode = ReplayMode_Playback;
}
#if Snapshot_New_Way
#else
if ( state->ActiveInputRecordingFile.OpaqueHandle == nullptr )
else
{
platform_api->file_read_stream( & state->ActivePlaybackFile, scast(u32, state->game_memory.PersistentSize), state->game_memory.Persistent );
// TODO(Ed) : Logging
}
#endif
}
internal
void end_playback_input( Memory* memory, InputState* input, platform::ModuleAPI* platform_api )
{
memory->input_playback_index = 0;
#if Snapshot_New_Way
#else
platform_api->file_rewind( & state->ActivePlaybackFile );
platform_api->file_read_stream( & state->ActivePlaybackFile, scast(u32, state->game_memory.PersistentSize), state->game_memory.Persistent );
#endif
platform_api->file_close( & memory->active_playback_file );
memory->replay_mode = ReplayMode_Off;
platform_api->file_close( & memory->active_input_replay_file );
}
InputStateSnapshot input_state_snapshot( InputState* input )
@ -309,7 +308,7 @@ internal
void record_input( Memory* memory, InputState* input, platform::ModuleAPI* platform_api )
{
InputStateSnapshot snapshot = input_state_snapshot( input );
if ( platform_api->file_write_stream( & memory->active_recording_file, sizeof(snapshot), &snapshot ) == 0 )
if ( platform_api->file_write_stream( & memory->active_input_replay_file, sizeof(snapshot), &snapshot ) == 0 )
{
// TODO(Ed) : Logging
}
@ -319,11 +318,10 @@ internal
void play_input( SnapshotFn* load_snapshot, Memory* memory, InputState* input, platform::ModuleAPI* platform_api )
{
InputStateSnapshot new_input;
if ( platform_api->file_read_stream( & memory->active_playback_file, sizeof(InputStateSnapshot), & new_input ) == 0 )
if ( platform_api->file_read_stream( & memory->active_input_replay_file, sizeof(InputStateSnapshot), & new_input ) == 0 )
{
end_playback_input( memory, input, platform_api );
load_snapshot( memory->active_snapshot_slot, memory, platform_api );
begin_playback_input( memory, input, platform_api );
load_snapshot( memory, platform_api );
platform_api->file_rewind( & memory->active_input_replay_file );
return;
}
@ -352,24 +350,25 @@ void play_input( SnapshotFn* load_snapshot, Memory* memory, InputState* input, p
void process_loop_mode( SnapshotFn* take_snapshot, SnapshotFn* load_snapshot
, Memory* memory, EngineState* state, InputState* input, platform::ModuleAPI* platform_api )
{
if ( memory->input_recording_index == 0 && memory->input_playback_index == 0 )
if ( memory->replay_mode == ReplayMode_Off )
{
take_snapshot( 0, memory, platform_api );
memory->active_snapshot_slot = 0;
take_snapshot( memory, platform_api );
begin_recording_input( memory, input, platform_api );
}
else if ( memory->input_playback_index )
else if ( memory->replay_mode == ReplayMode_Playback )
{
end_playback_input( memory, input, platform_api );
load_snapshot( memory->active_snapshot_slot, memory, platform_api );
load_snapshot( memory, platform_api );
}
else if ( memory->input_recording_index )
else if ( memory->replay_mode == ReplayMode_Record )
{
end_recording_input( memory, input, platform_api );
load_snapshot( memory->active_snapshot_slot, memory, platform_api );
load_snapshot( memory, platform_api );
begin_playback_input( memory, input, platform_api );
}
}
// Build_Development
#endif
internal
void input_poll_engine_actions( InputState* input, EngineActions* actions )
@ -390,6 +389,11 @@ void input_poll_engine_actions( InputState* input, EngineActions* actions )
#if Build_Development
actions->pause_renderer |= pressed( keyboard->pause );
actions->set_snapshot_slot_1 |= pressed( keyboard->_1 ) && keyboard->right_alt.ended_down;
actions->set_snapshot_slot_2 |= pressed( keyboard->_2 ) && keyboard->right_alt.ended_down;
actions->set_snapshot_slot_3 |= pressed( keyboard->_3 ) && keyboard->right_alt.ended_down;
actions->set_snapshot_slot_4 |= pressed( keyboard->_4 ) && keyboard->right_alt.ended_down;
#endif
actions->toggle_wave_tone |= pressed( keyboard->Q );
@ -404,6 +408,7 @@ void input_poll_engine_actions( InputState* input, EngineActions* actions )
actions->move_up = (mouse->vertical_wheel.end > 0.f) * 10;
actions->move_down = (mouse->vertical_wheel.end < 0.f) * 10;
}
internal
@ -454,13 +459,13 @@ void on_module_reload( Memory* memory, platform::ModuleAPI* platfom_api )
Engine_API
void startup( Memory* memory, platform::ModuleAPI* platform_api )
{
memory->active_snapshot_slot = -1;
memory->input_recording_index = 0;
memory->input_playback_index = 0;
memory->active_recording_file = {};
memory->active_playback_file = {};
memory->engine_loop_active = false;
memory->game_loop_active = false;
#if Build_Development
memory->active_snapshot_slot = 1;
memory->replay_mode = ReplayMode_Off;
memory->active_input_replay_file = {};
memory->engine_loop_active = false;
memory->game_loop_active = false;
#endif
for ( s32 slot = 0; slot < memory->Num_Snapshot_Slots; ++ slot )
{
@ -513,27 +518,29 @@ void update_and_render( InputState* input, OffscreenBuffer* back_buffer, Memory*
input_poll_engine_actions( input, & engine_actions );
#if Build_Development
// Ease of use: Allow user to press L key without shift if engine loop recording is active.
engine_actions.loop_mode_engine |= engine_actions.loop_mode_game && memory->engine_loop_active;
if ( engine_actions.loop_mode_engine && ! memory->game_loop_active )
{
process_loop_mode( & take_engine_snapshot, & load_engine_snapshot, memory, state, input, platform_api );
memory->engine_loop_active = memory->input_playback_index || memory->input_recording_index;
memory->engine_loop_active = memory->replay_mode > ReplayMode_Off;
}
// Input recording and playback for engine state
if ( memory->engine_loop_active )
{
if ( memory->input_recording_index )
if ( memory->replay_mode == ReplayMode_Record )
{
record_input( memory, input, platform_api );
}
if ( memory->input_playback_index )
if ( memory->replay_mode == ReplayMode_Playback )
{
play_input( & load_engine_snapshot, memory, input, platform_api );
}
}
#endif
// Process Engine Actions
{
@ -572,7 +579,7 @@ void update_and_render( InputState* input, OffscreenBuffer* back_buffer, Memory*
if ( engine_actions.loop_mode_game && ! memory->engine_loop_active )
{
process_loop_mode( & take_game_snapshot, & load_game_snapshot, memory, state, input, platform_api );
memory->game_loop_active = memory->input_playback_index || memory->input_recording_index;
memory->game_loop_active = memory->replay_mode > ReplayMode_Off;
}
#if Build_Development
@ -589,21 +596,31 @@ void update_and_render( InputState* input, OffscreenBuffer* back_buffer, Memory*
state->renderer_paused = true;
}
}
if ( ! memory->game_loop_active )
{
if ( engine_actions.set_snapshot_slot_1 ) memory->active_snapshot_slot = 0;
if ( engine_actions.set_snapshot_slot_2 ) memory->active_snapshot_slot = 1;
if ( engine_actions.set_snapshot_slot_3 ) memory->active_snapshot_slot = 2;
if ( engine_actions.set_snapshot_slot_4 ) memory->active_snapshot_slot = 3;
}
#endif
}
#if Build_Development
if ( ! memory->engine_loop_active )
{
// Input recording and playback for game state
if ( memory->input_recording_index )
if ( memory->replay_mode == ReplayMode_Record )
{
record_input( memory, input, platform_api );
}
if ( memory->input_playback_index )
if ( memory->replay_mode == ReplayMode_Playback )
{
play_input( & load_game_snapshot, memory, input, platform_api );
}
}
#endif
hh::PlayerState* player = rcast( hh::PlayerState*, state->game_memory.persistent );
assert( sizeof(hh::PlayerState) <= state->game_memory.persistent_size );
@ -622,21 +639,23 @@ void update_and_render( InputState* input, OffscreenBuffer* back_buffer, Memory*
else
{
player->jump_time = 0.f;
player->mid_jump = false;
player->mid_jump = false;
}
if ( ! player->mid_jump && player_actions.jump )
{
player->jump_time = 1.f;
player->mid_jump = true;
player->mid_jump = true;
}
}
render_weird_graident( back_buffer, state->x_offset, state->y_offset );
render_player( back_buffer, player->pos_x, player->pos_y );
if ( memory->input_recording_index )
#if Build_Development
if ( memory->replay_mode == ReplayMode_Record )
render_player( back_buffer, player->pos_x + 20, player->pos_y - 20 );
#endif
render_player( back_buffer, (s32)input->controllers[0].mouse->X.end, (s32)input->controllers[0].mouse->Y.end );

View File

@ -11,6 +11,13 @@
NS_ENGINE_BEGIN
enum ReplayMode : s32
{
ReplayMode_Off,
ReplayMode_Record,
ReplayMode_Playback
};
struct Clocks
{
// TODO(Ed) : Clock values...
@ -24,8 +31,10 @@ struct ThreadContext
struct MemorySnapshot
{
Str file_path;
void* memory;
StrPath file_path;
void* opaque_handle;
void* opaque_handle_2;
void* memory;
};
struct Memory
@ -45,23 +54,22 @@ struct Memory
u64 transient_size;
// TODO(Ed) : Move this crap to state & replay archive definitions?
#if Build_Development
static constexpr
s32 Num_Snapshot_Slots = 4;
s32 Num_Snapshot_Slots = 2;
// Abuse RAM to store snapshots of the Engine or Game state.
MemorySnapshot snapshots[ Num_Snapshot_Slots ];
s32 active_snapshot_slot;
// Recording and playback info is the same for either engine or game.
s32 input_recording_index;
s32 input_playback_index;
platform::File active_recording_file;
platform::File active_playback_file;
ReplayMode replay_mode;
platform::File active_input_replay_file;
// Engine-wide recording & playback loop.
s32 engine_loop_active;
s32 game_loop_active;
#endif
u64 total_size()
{
@ -114,7 +122,11 @@ union KeyboardState
{
DigitalBtn keys[12];
struct {
DigitalBtn row_1;
DigitalBtn _1;
DigitalBtn _2;
DigitalBtn _3;
DigitalBtn _4;
DigitalBtn Q;
DigitalBtn E;
DigitalBtn W;
@ -131,6 +143,8 @@ union KeyboardState
DigitalBtn right;
DigitalBtn space;
DigitalBtn pause;
DigitalBtn left_alt;
DigitalBtn right_alt;
DigitalBtn right_shift;
DigitalBtn left_shift;
};

View File

@ -504,6 +504,10 @@ poll_input( HWND window_handle, engine::InputState* input, u32 jsl_num_devices,
// Keyboards are unified for now.
{
constexpr u32 is_down = 0x80000000;
input_process_digital_btn( & old_keyboard->_1, & new_keyboard->_1, GetAsyncKeyState( '1' ), is_down );
input_process_digital_btn( & old_keyboard->_2, & new_keyboard->_2, GetAsyncKeyState( '2' ), is_down );
input_process_digital_btn( & old_keyboard->_3, & new_keyboard->_3, GetAsyncKeyState( '3' ), is_down );
input_process_digital_btn( & old_keyboard->_4, & new_keyboard->_4, GetAsyncKeyState( '4' ), is_down );
input_process_digital_btn( & old_keyboard->Q, & new_keyboard->Q, GetAsyncKeyState( 'Q' ), is_down );
input_process_digital_btn( & old_keyboard->E, & new_keyboard->E, GetAsyncKeyState( 'E' ), is_down );
input_process_digital_btn( & old_keyboard->W, & new_keyboard->W, GetAsyncKeyState( 'W' ), is_down );
@ -520,8 +524,10 @@ poll_input( HWND window_handle, engine::InputState* input, u32 jsl_num_devices,
input_process_digital_btn( & old_keyboard->right, & new_keyboard->right, GetAsyncKeyState( VK_RIGHT ), is_down );
input_process_digital_btn( & old_keyboard->space, & new_keyboard->space, GetAsyncKeyState( VK_SPACE ), is_down );
input_process_digital_btn( & old_keyboard->pause, & new_keyboard->pause, GetAsyncKeyState( VK_PAUSE ), is_down );
input_process_digital_btn( & old_keyboard->right_shift, & new_keyboard->right_shift, GetAsyncKeyState( VK_RSHIFT ), is_down );
input_process_digital_btn( & old_keyboard->left_alt, & new_keyboard->left_alt, GetAsyncKeyState( VK_LMENU ), is_down );
input_process_digital_btn( & old_keyboard->right_alt, & new_keyboard->right_alt, GetAsyncKeyState( VK_RMENU ), is_down );
input_process_digital_btn( & old_keyboard->left_shift, & new_keyboard->left_shift, GetAsyncKeyState( VK_LSHIFT ), is_down );
input_process_digital_btn( & old_keyboard->right_shift, & new_keyboard->right_shift, GetAsyncKeyState( VK_RSHIFT ), is_down );
input->controllers[0].keyboard = new_keyboard;
}
@ -1209,105 +1215,6 @@ WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR commandline, int sho
QueryPerformanceFrequency( rcast(LARGE_INTEGER*, & Performance_Counter_Frequency) );
// Memory
engine::Memory engine_memory {};
{
engine_memory.persistent_size = megabytes( 128 );
// engine_memory.FrameSize = megabytes( 64 );
engine_memory.transient_size = gigabytes( 2 );
u64 total_size = engine_memory.persistent_size
// + engine_memory.FrameSize
+ engine_memory.transient_size;
#if Build_Debug
void* base_address = rcast(void*, terabytes( 1 ));
#else
void* base_address = 0;
#endif
engine_memory.persistent = VirtualAlloc( base_address, total_size , MEM_Commit_Zeroed | MEM_Reserve, Page_Read_Write );
engine_memory.transient = rcast( u8*, engine_memory.persistent ) + engine_memory.persistent_size;
Byte* snapshot_address = rcast(Byte*, NULL) + terabytes(2);
void* snapshots_memory = VirtualAlloc( snapshot_address, total_size * engine_memory.Num_Snapshot_Slots, MEM_Commit_Zeroed | MEM_Reserve, Page_Read_Write );
if ( snapshots_memory == nullptr )
{
// TODO : Diagnostic Logging
return -1;
}
for (u32 slot = 0; slot < engine_memory.Num_Snapshot_Slots; ++slot)
{
engine::MemorySnapshot& snapshot = engine_memory.snapshots[ slot ];
Byte* address = rcast(Byte*, snapshots_memory) + total_size * slot;
snapshot.memory = address;
}
if ( engine_memory.persistent == nullptr
|| engine_memory.transient == nullptr )
{
// TODO : Diagnostic Logging
return -1;
}
}
WNDCLASSW window_class {};
HWND window_handle = nullptr;
{
window_class.style = CS_Horizontal_Redraw | CS_Vertical_Redraw;
window_class.lpfnWndProc = main_window_callback;
// window_class.cbClsExtra = ;
// window_class.cbWndExtra = ;
window_class.hInstance = instance;
// window_class.hIcon = ;
// window_class.hCursor = ;
// window_class.hbrBackground = ;
window_class.lpszMenuName = L"Handmade Hero!";
window_class.lpszClassName = L"HandmadeHeroWindowClass";
if ( ! RegisterClassW( & window_class ) )
{
// TODO : Diagnostic Logging
return 0;
}
window_handle = CreateWindowExW(
// WS_EX_LAYERED | WS_EX_TOPMOST,
WS_EX_LAYERED,
window_class.lpszClassName,
L"Handmade Hero",
WS_Overlapped_Window | WS_Initially_Visible,
CW_Use_Default, CW_Use_Default, // x, y
CW_Use_Default, CW_Use_Default, // width, height
0, 0, // parent, menu
instance, 0 // instance, param
);
if ( ! window_handle )
{
// TODO : Diagnostic Logging
return 0;
}
// WinDimensions dimensions = get_window_dimensions( window_handle );
resize_dib_section( &Surface_Back_Buffer, 1920, 1080 );
// Setup monitor refresh and associated timers
HDC refresh_dc = GetDC( window_handle );
u32 monitor_refresh_hz = GetDeviceCaps( refresh_dc, VREFRESH );
if ( monitor_refresh_hz > 1 )
{
Monitor_Refresh_Hz = monitor_refresh_hz;
}
ReleaseDC( window_handle, refresh_dc );
Engine_Refresh_Hz = 60;
Engine_Frame_Target_MS = 1000.f / scast(f32, Engine_Refresh_Hz);
}
// Setup pathing
StrFixed< S16_MAX > path_pdb_lock {};
{
@ -1349,6 +1256,115 @@ WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR commandline, int sho
CreateDirectoryA( Path_Scratch, 0 );
}
// Memory
engine::Memory engine_memory {};
{
engine_memory.persistent_size = megabytes( 128 );
// engine_memory.FrameSize = megabytes( 64 );
engine_memory.transient_size = gigabytes( 2 );
u64 total_size = engine_memory.persistent_size
// + engine_memory.FrameSize
+ engine_memory.transient_size;
#if Build_Debug
void* base_address = rcast(void*, terabytes( 1 ));
#else
void* base_address = 0;
#endif
engine_memory.persistent = VirtualAlloc( base_address, total_size , MEM_Commit_Zeroed | MEM_Reserve, Page_Read_Write );
engine_memory.transient = rcast( u8*, engine_memory.persistent ) + engine_memory.persistent_size;
#if Build_Development
for (u32 slot = 0; slot < engine_memory.Num_Snapshot_Slots; ++slot)
{
engine::MemorySnapshot& snapshot = engine_memory.snapshots[ slot ];
snapshot.file_path.concat( Path_Scratch, str_ascii("snapshot_") );
wsprintfA( snapshot.file_path.ptr, "%s%d.hm_snapshot", snapshot.file_path.ptr, slot );
HANDLE snapshot_file = CreateFileA( snapshot.file_path
, GENERIC_READ | GENERIC_WRITE, 0, 0
, CREATE_ALWAYS, 0, 0 );
LARGE_INTEGER file_size {};
file_size.QuadPart = total_size;
HANDLE snapshot_mapping = CreateFileMappingA( snapshot_file, 0
, Page_Read_Write
, file_size.HighPart, file_size.LowPart
, 0 );
snapshot.memory = MapViewOfFile( snapshot_mapping, FILE_MAP_ALL_ACCESS, 0, 0, total_size );
snapshot.opaque_handle = snapshot_file;
snapshot.opaque_handle_2 = snapshot_mapping;
}
#endif
if ( engine_memory.persistent == nullptr
|| engine_memory.transient == nullptr )
{
// TODO : Diagnostic Logging
return -1;
}
}
WNDCLASSW window_class {};
HWND window_handle = nullptr;
{
window_class.style = CS_Horizontal_Redraw | CS_Vertical_Redraw;
window_class.lpfnWndProc = main_window_callback;
// window_class.cbClsExtra = ;
// window_class.cbWndExtra = ;
window_class.hInstance = instance;
// window_class.hIcon = ;
// window_class.hCursor = ;
// window_class.hbrBackground = ;
window_class.lpszMenuName = L"Handmade Hero!";
window_class.lpszClassName = L"HandmadeHeroWindowClass";
if ( ! RegisterClassW( & window_class ) )
{
// TODO : Diagnostic Logging
return 0;
}
window_handle = CreateWindowExW(
WS_EX_LAYERED | WS_EX_TOPMOST,
// WS_EX_LAYERED,
window_class.lpszClassName,
L"Handmade Hero",
WS_Overlapped_Window | WS_Initially_Visible,
CW_Use_Default, CW_Use_Default, // x, y
CW_Use_Default, CW_Use_Default, // width, height
0, 0, // parent, menu
instance, 0 // instance, param
);
if ( ! window_handle )
{
// TODO : Diagnostic Logging
return 0;
}
// WinDimensions dimensions = get_window_dimensions( window_handle );
resize_dib_section( &Surface_Back_Buffer, 1920, 1080 );
// Setup monitor refresh and associated timers
HDC refresh_dc = GetDC( window_handle );
u32 monitor_refresh_hz = GetDeviceCaps( refresh_dc, VREFRESH );
if ( monitor_refresh_hz > 1 )
{
Monitor_Refresh_Hz = monitor_refresh_hz;
}
ReleaseDC( window_handle, refresh_dc );
Engine_Refresh_Hz = 60;
Engine_Frame_Target_MS = 1000.f / scast(f32, Engine_Refresh_Hz);
}
// Prepare platform API
ModuleAPI platform_api {};
{
@ -1735,7 +1751,7 @@ WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR commandline, int sho
WinDimensions dimensions = get_window_dimensions( window_handle );
HDC device_context = GetDC( window_handle );
#if Build_Development
#if Build_Development && 0
// Note: debug_marker_index is wrong for the 0th index
debug_sync_display( & ds_sound_buffer
, audio_time_markers_size, audio_time_markers, audio_marker_index - 1