Day 18 complete

This commit is contained in:
Edward R. Gonzalez 2023-09-22 15:13:18 -04:00
parent 5902aec2bf
commit e0463670c9
5 changed files with 157 additions and 182 deletions

View File

@ -181,8 +181,6 @@ void update_and_render( InputState* input, OffscreenBuffer* back_buffer, SoundBu
b32 action_left = false; b32 action_left = false;
b32 action_right = false; b32 action_right = false;
f32 analog_threshold = 0.5f;
b32 raise_volume = false; b32 raise_volume = false;
b32 lower_volume = false; b32 lower_volume = false;
b32 raise_tone_hz = false; b32 raise_tone_hz = false;
@ -190,6 +188,8 @@ void update_and_render( InputState* input, OffscreenBuffer* back_buffer, SoundBu
b32 toggle_wave_tone = false; b32 toggle_wave_tone = false;
f32 analog_threshold = 0.5f;
if ( controller->DSPad ) if ( controller->DSPad )
{ {
DualsensePadState* pad = controller->DSPad; DualsensePadState* pad = controller->DSPad;
@ -242,10 +242,10 @@ void update_and_render( InputState* input, OffscreenBuffer* back_buffer, SoundBu
toggle_wave_tone |= keyboard->Space.EndedDown; toggle_wave_tone |= keyboard->Space.EndedDown;
} }
x_offset += move_right; x_offset += 3 * move_right;
x_offset -= move_left; x_offset -= 3 * move_left;
y_offset += move_down; y_offset += 3 * move_down;
y_offset -= move_up; y_offset -= 3 * move_up;
if ( raise_volume ) if ( raise_volume )
{ {

View File

@ -29,7 +29,7 @@
#endif #endif
#include <math.h> // TODO : Implement math ourselves #include <math.h> // TODO : Implement math ourselves
#include <stdio.h> #include <stdio.h> // TODO : Implement output logging ourselves
#include "engine.cpp" #include "engine.cpp"
@ -100,8 +100,7 @@ struct SoundOutput
s32 LatencySampleCount; s32 LatencySampleCount;
}; };
HRESULT WINAPI DirectSoundCreate(LPGUID lpGuid, LPDIRECTSOUND* ppDS, LPUNKNOWN pUnkOuter ); // HRESULT WINAPI DirectSoundCreate(LPGUID lpGuid, LPDIRECTSOUND* ppDS, LPUNKNOWN pUnkOuter );
using DirectSoundCreateFn = HRESULT WINAPI (LPGUID lpGuid, LPDIRECTSOUND* ppDS, LPUNKNOWN pUnkOuter ); using DirectSoundCreateFn = HRESULT WINAPI (LPGUID lpGuid, LPDIRECTSOUND* ppDS, LPUNKNOWN pUnkOuter );
global DirectSoundCreateFn* direct_sound_create; global DirectSoundCreateFn* direct_sound_create;
@ -115,6 +114,10 @@ global s32 DS_SecondaryBuffer_BytesPerSample;
global s16* SoundBufferSamples; global s16* SoundBufferSamples;
constexpr u64 Tick_To_Millisecond = 1000;
constexpr u64 Tick_To_Microsecond = 1000 * 1000;
global u64 Performance_Counter_Frequency;
#if Build_Debug #if Build_Debug
void debug_file_free_content( Debug_FileContent* content ) void debug_file_free_content( Debug_FileContent* content )
@ -189,6 +192,37 @@ b32 debug_file_write_content( char* file_path, u32 content_size, void* content_m
} }
#endif #endif
inline u64
timing_get_wall_clock()
{
u64 clock;
QueryPerformanceCounter( rcast( LARGE_INTEGER*, & clock) );
return clock;
}
inline f32
timing_get_seconds_elapsed( u64 start, u64 end )
{
u64 delta = end - start;
f32 result = scast(f32, delta) / scast(f32, Performance_Counter_Frequency);
}
inline f32
timing_get_ms_elapsed( u64 start, u64 end )
{
u64 delta = (end - start) * Tick_To_Millisecond;
f32 result = scast(f32, delta) / scast(f32, Performance_Counter_Frequency);
return result;
}
inline f32
timing_get_us_elapsed( u64 start, u64 end )
{
u64 delta = (end - start) * Tick_To_Microsecond;
f32 result = scast(f32, delta) / scast(f32, Performance_Counter_Frequency);
return result;
}
internal void internal void
input_process_digital_btn( engine::DigitalBtn* old_state, engine::DigitalBtn* new_state, u32 raw_btns, u32 btn_flag ) input_process_digital_btn( engine::DigitalBtn* old_state, engine::DigitalBtn* new_state, u32 raw_btns, u32 btn_flag )
{ {
@ -559,10 +593,6 @@ process_pending_window_messages( engine::KeyboardState* keyboard )
// I rather do this with GetAsyncKeyState... // I rather do this with GetAsyncKeyState...
case WM_SYSKEYDOWN: case WM_SYSKEYDOWN:
case WM_SYSKEYUP: case WM_SYSKEYUP:
#if 0
case WM_KEYDOWN:
case WM_KEYUP:
#endif
{ {
WPARAM vk_code = window_msg_info.wParam; WPARAM vk_code = window_msg_info.wParam;
b32 is_down = scast(b32, (window_msg_info.lParam >> 31) == 0 ); b32 is_down = scast(b32, (window_msg_info.lParam >> 31) == 0 );
@ -571,71 +601,6 @@ process_pending_window_messages( engine::KeyboardState* keyboard )
switch ( vk_code ) switch ( vk_code )
{ {
#if 0
case 'Q':
{
input_process_keyboard_key( & keyboard->Q, is_down );
}
break;
case 'E':
{
input_process_keyboard_key( & keyboard->E, is_down );
}
break;
case 'W':
{
input_process_keyboard_key( & keyboard->W, is_down );
}
break;
case 'A':
{
input_process_keyboard_key( & keyboard->A, is_down );
}
break;
case 'S':
{
input_process_keyboard_key( & keyboard->S, is_down );
}
break;
case 'D':
{
input_process_keyboard_key( & keyboard->D, is_down );
}
break;
case VK_ESCAPE:
{
input_process_keyboard_key( & keyboard->Escape, is_down );
}
break;
case VK_BACK:
input_process_keyboard_key( & keyboard->Backspace, is_down );
break;
case VK_UP:
{
input_process_keyboard_key( & keyboard->Up, is_down );
}
break;
case VK_DOWN:
{
input_process_keyboard_key( & keyboard->Down, is_down );
}
break;
case VK_LEFT:
{
input_process_keyboard_key( & keyboard->Left, is_down );
}
break;
case VK_RIGHT:
{
input_process_keyboard_key( & keyboard->Right, is_down );
}
break;
case VK_SPACE:
{
input_process_keyboard_key( & keyboard->Space, is_down );
}
break;
#endif
case VK_F4: case VK_F4:
{ {
if ( alt_down ) if ( alt_down )
@ -666,6 +631,29 @@ WinMain(
using namespace win32; using namespace win32;
using namespace platform; using namespace platform;
// Timing
#if Build_Development
u64 launch_clock = timing_get_wall_clock();
u64 launch_cycle = __rdtsc();
#endif
// TODO(Ed): Make this more flexible later
f32 monitor_refresh_hz = 165.f;
f32 engine_update_hz
// = monitor_refresh_hz / 2.f;
= monitor_refresh_hz;
f32 engine_frame_target_ms = 1000.f / engine_update_hz;
// Sets the windows scheduler granulaity for this process to 1 ms
u32 desired_scheduler_ms = 1;
b32 sleep_is_granular = ( timeBeginPeriod( desired_scheduler_ms ) == TIMERR_NOERROR );
// Anything at or below the high performance frame-time is too low latency to sleep against the window's scheduler.
f32 high_perf_frametime_ms = 1000.f / 120.f;
b32 sub_ms_granularity_required = engine_frame_target_ms <= high_perf_frametime_ms;
QueryPerformanceFrequency( rcast(LARGE_INTEGER*, & Performance_Counter_Frequency) );
// Memory // Memory
engine::Memory engine_memory {}; engine::Memory engine_memory {};
{ {
@ -678,38 +666,23 @@ WinMain(
+ engine_memory.TransientSize; + engine_memory.TransientSize;
#if Build_Debug #if Build_Debug
void* Base_Address = (void*) terabytes( 1 ); void* Base_Address = rcast(void*, terabytes( 1 ));
// void* Frame_Address = (void*) terabytes( 2 );
// void* Transient_Address = (void*) terabytes( 2 );
#else #else
void* Base_Address = 0; void* Base_Address = 0;
// void* Frame_Address = 0;
// void* Transient_Address = 0;
#endif #endif
engine_memory.Persistent = VirtualAlloc( Base_Address, total_size engine_memory.Persistent = VirtualAlloc( Base_Address, total_size
, MEM_Commit_Zeroed | MEM_Reserve, Page_Read_Write ); , MEM_Commit_Zeroed | MEM_Reserve, Page_Read_Write );
engine_memory.Transient = rcast( u8*, engine_memory.Persistent ) + engine_memory.PersistentSize; engine_memory.Transient = rcast( u8*, engine_memory.Persistent ) + engine_memory.PersistentSize;
#if 0 if ( engine_memory.Persistent == nullptr
engine_memory.Frame = VirtualAlloc( 0, engine_memory.FrameSize || engine_memory.Transient == nullptr )
, MEM_Commit_Zeroed | MEM_Reserve, Page_Read_Write );
engine_memory.Transient = VirtualAlloc( 0, engine_memory.TransientSize
, MEM_Commit_Zeroed | MEM_Reserve, Page_Read_Write );
#endif
if ( engine_memory.Persistent == nullptr
// || ! engine_memory.Frame
|| engine_memory.Transient == nullptr )
{ {
// TODO : Diagnostic Logging // TODO : Diagnostic Logging
return -1; return -1;
} }
} }
// MessageBox( 0, L"First message!", L"Handmade Hero", MB_Ok_Btn | MB_Icon_Information );
WNDCLASSW window_class {}; WNDCLASSW window_class {};
HWND window_handle = nullptr; HWND window_handle = nullptr;
{ {
@ -747,7 +720,6 @@ WinMain(
return 0; return 0;
} }
} }
// WinDimensions dimensions = get_window_dimensions( window_handle ); // WinDimensions dimensions = get_window_dimensions( window_handle );
resize_dib_section( &BackBuffer, 1280, 720 ); resize_dib_section( &BackBuffer, 1280, 720 );
@ -771,39 +743,28 @@ WinMain(
DS_SecondaryBuffer->Play( 0, 0, DSBPLAY_LOOPING ); DS_SecondaryBuffer->Play( 0, 0, DSBPLAY_LOOPING );
} }
// Timing
u64 perf_counter_frequency;
u64 last_frame_time;
QueryPerformanceFrequency( rcast(LARGE_INTEGER*, & perf_counter_frequency) );
QueryPerformanceCounter( rcast(LARGE_INTEGER*, & last_frame_time) );
u64 last_cycle_time = __rdtsc();
// Input shitshow
constexpr u32 Max_Controllers = 4; constexpr u32 Max_Controllers = 4;
// Max controllers for the platform layer and thus for all other layers is 4. (Sanity and xinput limit) // Max controllers for the platform layer and thus for all other layers is 4. (Sanity and xinput limit)
engine::InputState input {}; engine::InputState input {};
engine::KeyboardState keyboard_states[2] {}; engine::KeyboardState keyboard_states[2] {};
engine::KeyboardState* old_keyboard = & keyboard_states[0]; engine::KeyboardState* old_keyboard = & keyboard_states[0];
engine::KeyboardState* new_keyboard = & keyboard_states[1]; engine::KeyboardState* new_keyboard = & keyboard_states[1];
// Important: Assuming keyboard always connected for now, and assigning to first controller. // Important: Assuming keyboard always connected for now, and assigning to first controller.
using EngineXInputPadStates = engine::XInputPadState[ Max_Controllers ]; using EngineXInputPadStates = engine::XInputPadState[ Max_Controllers ];
EngineXInputPadStates xpad_states[2] {}; EngineXInputPadStates xpad_states[2] {};
EngineXInputPadStates* old_xpads = & xpad_states[0]; EngineXInputPadStates* old_xpads = & xpad_states[0];
EngineXInputPadStates* new_xpads = & xpad_states[1]; EngineXInputPadStates* new_xpads = & xpad_states[1];
using EngineDSPadStates = engine::DualsensePadState[Max_Controllers]; using EngineDSPadStates = engine::DualsensePadState[Max_Controllers];
EngineDSPadStates ds_pad_states[2] {}; EngineDSPadStates ds_pad_states[2] {};
EngineDSPadStates* old_ds_pads = & ds_pad_states[0]; EngineDSPadStates* old_ds_pads = & ds_pad_states[0];
EngineDSPadStates* new_ds_pads = & ds_pad_states[1]; EngineDSPadStates* new_ds_pads = & ds_pad_states[1];
using JSL_DeviceHandle = int; using JSL_DeviceHandle = int;
u32 jsl_num_devices u32 jsl_num_devices = JslConnectDevices();
= JslConnectDevices();
// = 0;
JSL_DeviceHandle jsl_device_handles[4] {}; JSL_DeviceHandle jsl_device_handles[4] {};
{ {
xinput_load_library_bindings(); xinput_load_library_bindings();
@ -832,28 +793,19 @@ WinMain(
} }
} }
u64 last_frame_clock = timing_get_wall_clock();
u64 last_frame_cycle = __rdtsc();
#if Build_Development
u64 startup_cycles = last_frame_cycle - launch_cycle;
f32 startup_ms = timing_get_ms_elapsed( launch_clock, last_frame_clock );
#endif
Running = true; Running = true;
while( Running ) while( Running )
{ {
// Handeled properly in the input section.
#if 0
swap( old_keyboard, new_keyboard );
*new_keyboard = {};
for ( u32 key_index = 0; key_index < array_count( new_keyboard->Keys ); ++ key_index )
{
engine::DigitalBtn* old_key = & old_keyboard->Keys[ key_index ];
engine::DigitalBtn* new_key = & new_keyboard->Keys[ key_index ];
new_key->EndedDown = old_key->EndedDown;
}
#endif
process_pending_window_messages( new_keyboard ); process_pending_window_messages( new_keyboard );
input.Controllers[0].Keyboard = new_keyboard;
// printf("Q- Old: %d, New: %d\n", old_keyboard->Q.EndedDown, new_keyboard->Q.EndedDown);
printf("Q- HTOld: %d, HTNew: %d\n", old_keyboard->Q.HalfTransitions, new_keyboard->Q.HalfTransitions);
// Input // Input
// TODO(Ed) : Setup user definable deadzones for triggers and sticks. // TODO(Ed) : Setup user definable deadzones for triggers and sticks.
{ {
@ -863,6 +815,7 @@ WinMain(
swap( old_ds_pads, new_ds_pads ); swap( old_ds_pads, new_ds_pads );
// Keyboard Polling // Keyboard Polling
// Keyboards are unified for now.
{ {
constexpr u32 is_down = 0x8000; constexpr u32 is_down = 0x8000;
input_process_digital_btn( & old_keyboard->Q, & new_keyboard->Q, GetAsyncKeyState( 'Q' ), is_down ); input_process_digital_btn( & old_keyboard->Q, & new_keyboard->Q, GetAsyncKeyState( 'Q' ), is_down );
@ -878,6 +831,8 @@ WinMain(
input_process_digital_btn( & old_keyboard->Left, & new_keyboard->Left, GetAsyncKeyState( VK_LEFT ), is_down ); input_process_digital_btn( & old_keyboard->Left, & new_keyboard->Left, GetAsyncKeyState( VK_LEFT ), is_down );
input_process_digital_btn( & old_keyboard->Right, & new_keyboard->Right, GetAsyncKeyState( VK_RIGHT ), is_down ); 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->Space, & new_keyboard->Space, GetAsyncKeyState( VK_SPACE ), is_down );
input.Controllers[0].Keyboard = new_keyboard;
} }
// XInput Polling // XInput Polling
@ -944,6 +899,9 @@ WinMain(
break; break;
JOY_SHOCK_STATE state = JslGetSimpleState( jsl_device_handles[ jsl_device_index ] ); JOY_SHOCK_STATE state = JslGetSimpleState( jsl_device_handles[ jsl_device_index ] );
// For now we're assuming anything that is detected via JSL is a dualsense pad.
// We'll eventually add support possibly for the nintendo pro controller.
engine::DualsensePadState* old_ds_pad = old_ds_pads[ jsl_device_index ]; engine::DualsensePadState* old_ds_pad = old_ds_pads[ jsl_device_index ];
engine::DualsensePadState* new_ds_pad = new_ds_pads[ jsl_device_index ]; engine::DualsensePadState* new_ds_pad = new_ds_pads[ jsl_device_index ];
@ -1018,16 +976,38 @@ WinMain(
engine::update_and_render( & input, rcast(engine::OffscreenBuffer*, & BackBuffer.Memory), & sound_buffer, & engine_memory ); engine::update_and_render( & input, rcast(engine::OffscreenBuffer*, & BackBuffer.Memory), & sound_buffer, & engine_memory );
// Rendering u64 work_frame_end_cycle = __rdtsc();
u64 work_frame_end_clock = timing_get_wall_clock();
f32 work_frame_ms = timing_get_ms_elapsed( last_frame_clock, work_frame_end_clock );
f32 work_cycles = timing_get_ms_elapsed( last_frame_cycle, work_frame_end_cycle );
f32 frame_elapsed_ms = work_frame_ms;
if ( frame_elapsed_ms < engine_frame_target_ms )
{ {
WinDimensions dimensions = get_window_dimensions( window_handle );
HDC device_context = GetDC( window_handle ); DWORD sleep_ms = scast(DWORD, (engine_frame_target_ms - frame_elapsed_ms)) - 1;
display_buffer_in_window( device_context, dimensions.Width, dimensions.Height, &BackBuffer if ( ! sub_ms_granularity_required && sleep_is_granular )
, 0, 0 {
, dimensions.Width, dimensions.Height ); Sleep( sleep_ms );
}
u64 frame_clock = timing_get_wall_clock();
frame_elapsed_ms = timing_get_ms_elapsed( last_frame_clock, frame_clock );
assert( frame_elapsed_ms < engine_frame_target_ms );
while ( frame_elapsed_ms < engine_frame_target_ms )
{
frame_clock = timing_get_wall_clock();
frame_elapsed_ms = timing_get_ms_elapsed( last_frame_clock, frame_clock );
}
}
else
{
// TODO(Ed) : Missed the display sync window!
} }
// Audio // Update audio buffer
do { do {
DWORD ds_status = 0; DWORD ds_status = 0;
if ( SUCCEEDED( DS_SecondaryBuffer->GetStatus( & ds_status ) ) ) if ( SUCCEEDED( DS_SecondaryBuffer->GetStatus( & ds_status ) ) )
@ -1046,27 +1026,19 @@ WinMain(
DS_SecondaryBuffer->Play( 0, 0, DSBPLAY_LOOPING ); DS_SecondaryBuffer->Play( 0, 0, DSBPLAY_LOOPING );
} while(0); } while(0);
u64 end_cycle_count = __rdtsc(); // Update framebuffer
{
WinDimensions dimensions = get_window_dimensions( window_handle );
HDC device_context = GetDC( window_handle );
display_buffer_in_window( device_context, dimensions.Width, dimensions.Height, &BackBuffer
, 0, 0
, dimensions.Width, dimensions.Height );
}
u64 frame_cycle_time_end; printf("%f\n", frame_elapsed_ms );
QueryPerformanceCounter( rcast( LARGE_INTEGER*, & frame_cycle_time_end) );
// TODO : Display value here last_frame_clock = timing_get_wall_clock();
last_frame_cycle = __rdtsc();
#define MS_PER_SECOND 1000
#define MegaCycles_Per_Second (1000 * 1000)
u64 cycles_elapsed = end_cycle_count - last_cycle_time;
u64 mega_cycles_elapsed = cycles_elapsed / MegaCycles_Per_Second;
u64 frame_time_elapsed = frame_cycle_time_end - last_frame_time;
u32 ms_per_frame = scast(u32, MS_PER_SECOND * frame_time_elapsed / perf_counter_frequency);
u32 fps = scast(u32, perf_counter_frequency / frame_time_elapsed);
// char ms_timing_debug[256] {};
// wsprintfA( ms_timing_debug, "%d ms\n" "FPS: %d\n" "mega cycles: %d\n", ms_per_frame, fps, mega_cycles_elapsed );
// OutputDebugStringA( ms_timing_debug );
last_cycle_time = end_cycle_count;
last_frame_time = frame_cycle_time_end;
} }
if ( jsl_num_devices > 0 ) if ( jsl_num_devices > 0 )

View File

@ -11,6 +11,7 @@
#include <xinput.h> #include <xinput.h>
#include <mmeapi.h> #include <mmeapi.h>
#include <dsound.h> #include <dsound.h>
#include <timeapi.h>
#pragma warning( pop ) #pragma warning( pop )
// #include "windows/windows_base.h" // #include "windows/windows_base.h"

View File

@ -415,6 +415,7 @@ $includes = @(
$lib_gdi32 = 'Gdi32.lib' $lib_gdi32 = 'Gdi32.lib'
$lib_xinput = 'Xinput.lib' $lib_xinput = 'Xinput.lib'
$lib_user32 = 'User32.lib' $lib_user32 = 'User32.lib'
$lib_winmm = 'Winmm.lib'
# Github # Github
$lib_jsl = Join-Path $path_deps 'JoyShockLibrary/x64/JoyShockLibrary.lib' $lib_jsl = Join-Path $path_deps 'JoyShockLibrary/x64/JoyShockLibrary.lib'
@ -446,6 +447,7 @@ $linker_args = @(
$lib_gdi32, $lib_gdi32,
# $lib_xinput, # $lib_xinput,
$lib_user32, $lib_user32,
$lib_winmm,
$lib_jsl, $lib_jsl,

Binary file not shown.