diff --git a/.gitignore b/.gitignore index e87fa4a..da7c10a 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ build **/*.hmi **/*.symbols +**/*.hm_* data/test.out data/handmade_engine.symbols diff --git a/.vscode/bookmarks.json b/.vscode/bookmarks.json index 91597bc..63127c5 100644 --- a/.vscode/bookmarks.json +++ b/.vscode/bookmarks.json @@ -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" } diff --git a/docs/Day 025.md b/docs/Day 025.md index ff70a62..2b36fff 100644 --- a/docs/Day 025.md +++ b/docs/Day 025.md @@ -1,12 +1,13 @@ # Day 25 -Him doing replay save states at the platform layer is causing issues for me... - +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. +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!!! diff --git a/project/engine/engine.cpp b/project/engine/engine.cpp index ce8f22d..9fbe9fd 100644 --- a/project/engine/engine.cpp +++ b/project/engine/engine.cpp @@ -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 ); diff --git a/project/engine/engine.hpp b/project/engine/engine.hpp index 93d6e9b..1caf252 100644 --- a/project/engine/engine.hpp +++ b/project/engine/engine.hpp @@ -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; }; diff --git a/project/platform/win32_platform.cpp b/project/platform/win32_platform.cpp index a92158c..3c0bae8 100644 --- a/project/platform/win32_platform.cpp +++ b/project/platform/win32_platform.cpp @@ -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