diff --git a/HandmadeHero.10x b/HandmadeHero.10x
index 40db348..e907d32 100644
--- a/HandmadeHero.10x
+++ b/HandmadeHero.10x
@@ -8,10 +8,10 @@
true
false
false
- pwsh $(WorkspaceDirectory)/scripts/build.ps1 msvc dev debug
- pwsh $(WorkspaceDirectory)/scripts/clean.ps1; $(WorkspaceDirectory)scripts/build.ps1 msvc dev debug
+ pwsh -ExecutionPolicy Bypass -NoProfile -NonInteractive -File $(WorkspaceDirectory)/scripts/build.ps1 msvc dev optimized
+
- pwsh $(WorkspaceDirectory)/scripts/clean.ps1
+ pwsh -ExecutionPolicy Bypass -NoProfile -NonInteractive -File $(WorkspaceDirectory)/scripts/clean.ps1
$(WorkspaceDirectory)/build/handmade_win32.exe
@@ -19,10 +19,10 @@
$(WorkspaceDirectory)/build/handmade_win32.exe
$(WorkspaceDirectory)/build/handmade_win32.exe
- false
+ true
Dev Optimzied
- Dev
+ Dev
Optimized
@@ -31,11 +31,11 @@
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.34.31933\include
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\VS\include
- C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\ucrt
- C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\um
- C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\shared
- C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\winrt
- C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\cppwinrt
+ C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt
+ C:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\um
+ C:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\shared
+ C:\Program Files (x86)\Windows Kits\10\\include\10.0.19041..0\\winrt
+ C:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\cppwinrt
C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um
@@ -51,10 +51,28 @@
+
+ Dev :x64
+
+
+
+
+ Dev Optimzied:x64
+
+
+
Debug
+
+ Dev
+
+
+
+ Dev Optimzied
+
+
x64
diff --git a/HandmadeHero.sln b/HandmadeHero.sln
new file mode 100644
index 0000000..7cdc0fe
--- /dev/null
+++ b/HandmadeHero.sln
@@ -0,0 +1,20 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.0
+MinimumVisualStudioVersion = 17.0.0
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HandmadeHero", "HandmadeHero.vcxproj", "{E1CF01B8-BB9F-42F4-9EDB-9F1274D3685A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Development|x64 = Development|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {E1CF01B8-BB9F-42F4-9EDB-9F1274D3685A}.Development|x64.ActiveCfg = Development|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {B3809CB4-EBEF-4551-B09E-0A1344DEB578}
+ EndGlobalSection
+EndGlobal
diff --git a/HandmadeHero.vcxproj b/HandmadeHero.vcxproj
new file mode 100644
index 0000000..f8703d3
--- /dev/null
+++ b/HandmadeHero.vcxproj
@@ -0,0 +1,70 @@
+
+
+
+ {E1CF01B8-BB9F-42F4-9EDB-9F1274D3685A}
+ HandmadeHero
+ 10.0
+ HandmadeHero
+
+
+
+
+
+ Development
+ x64
+
+
+
+ $(ProjectDir)project;$(IncludePath)
+ $(ProjectDir)data;$(windir)System32;$(LibraryPath)
+ pwsh -ExecutionPolicy Bypass -NoProfile -NonInteractive -File $(ProjectDir)scripts\build.ps1 msvc dev
+ pwsh ExecutionPolicy Bypass -NoProfile -NonInteractive -File $(ProjectDir)scripts\clean.ps1
+ GEN_TIME;Build_Development;Build_Debug;$(NMakePreprocessorDefinitions)
+ $(VC_IncludePath);$(WindowsSDK_IncludePath)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Makefile
+ true
+ v143
+ Unicode
+
+
+
+
\ No newline at end of file
diff --git a/HandmadeHero.vcxproj.user b/HandmadeHero.vcxproj.user
new file mode 100644
index 0000000..556ee01
--- /dev/null
+++ b/HandmadeHero.vcxproj.user
@@ -0,0 +1,11 @@
+
+
+
+ true
+
+
+ $(ProjectDir)data
+ WindowsLocalDebugger
+ $(ProjectDir)build\handmade_win32.exe
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 9e84aee..bed3e43 100644
--- a/README.md
+++ b/README.md
@@ -25,5 +25,5 @@ The build is done in two stages:
## Gallery
-![img](https://files.catbox.moe/fwjm1m.png)
+![img](https://files.catbox.moe/xyh7u7.png)
![img](https://files.catbox.moe/b7ifa8.png)
diff --git a/docs/Day 019.md b/docs/Day 019.md
new file mode 100644
index 0000000..5a298d4
--- /dev/null
+++ b/docs/Day 019.md
@@ -0,0 +1,20 @@
+# Day 19
+
+I started to do some cleanup while also following along.
+`handmade_win32.cpp` now just holds the cpp build order when running the build script for unity builds.
+
+I want to eventually support segemnted builds as well, that way I can make sure there isn't some unhandled usaged of a global or some other symbol in one of the source files.
+Evetually I can also use gencpp perform some static analysis to make sure differnt layers are not accessing symbols that they should not.
+
+I started to setup also pulling the polling of input out to a different function.
+There are a few routes to go about it:
+
+* Make a separate function per input type: ( poll_keyboard, poll_xinput, poll_jsl ).
+* Make a single function that handles all input polling (poll_input or process_input).
+* (problably more...)
+
+I'm gravitating toward the second option, the amount of content is not that large, and would keep the code all together along with its control flow.
+
+Overall this was pretty brutual to follow along with for the vod. Thankfully handmade-notes exists..
+Reading the end of the notes page for the episode showed a forum link to mmozeiko discussing use of the Windows Core Audio API to alleviate the large amount of latency required to operate with DirectSound.
+I'm going to wait until after day 20 since Casey has that one titled "Debugging the Aduio Sync"
diff --git a/project/dependencies/JoyShockLibrary/InputHelpers.cpp b/project/dependencies/JoyShockLibrary/InputHelpers.cpp
index 5d62b97..58a49df 100644
--- a/project/dependencies/JoyShockLibrary/InputHelpers.cpp
+++ b/project/dependencies/JoyShockLibrary/InputHelpers.cpp
@@ -224,9 +224,9 @@ bool handle_input(JoyShock *jc, uint8_t *packet, int len, bool &hasIMU) {
if ((hat > 4) & (hat < 8)) jc->simple_state.buttons |= JSMASK_LEFT; // left = SW | W | NW
jc->simple_state.buttons |= ((int) (packet[indexOffset + 7] >> 4) << JSOFFSET_W) & JSMASK_W;
- jc->simple_state.buttons |= ((int) (packet[indexOffset + 7] >> 7) << JSOFFSET_N) & JSMASK_N;
jc->simple_state.buttons |= ((int) (packet[indexOffset + 7] >> 5) << JSOFFSET_S) & JSMASK_S;
jc->simple_state.buttons |= ((int) (packet[indexOffset + 7] >> 6) << JSOFFSET_E) & JSMASK_E;
+ jc->simple_state.buttons |= ((int) (packet[indexOffset + 7] >> 7) << JSOFFSET_N) & JSMASK_N;
jc->simple_state.buttons |= ((int) (packet[indexOffset + 8] >> 6) << JSOFFSET_LCLICK) & JSMASK_LCLICK;
jc->simple_state.buttons |= ((int) (packet[indexOffset + 8] >> 7) << JSOFFSET_RCLICK) & JSMASK_RCLICK;
jc->simple_state.buttons |= ((int) (packet[indexOffset + 8] >> 5) << JSOFFSET_OPTIONS) & JSMASK_OPTIONS;
@@ -235,9 +235,12 @@ bool handle_input(JoyShock *jc, uint8_t *packet, int len, bool &hasIMU) {
jc->simple_state.buttons |= ((int) (packet[indexOffset + 8]) << JSOFFSET_L) & JSMASK_L;
jc->simple_state.buttons |= ((int) (packet[indexOffset + 9]) << JSOFFSET_PS) & JSMASK_PS;
// The DS5 has a mute button that is normally ignored on PC. We can use this.
+ jc->simple_state.buttons |= ((int) (packet[indexOffset + 9] >> 1) << JSOFFSET_TOUCHPAD_CLICK) & JSMASK_TOUCHPAD_CLICK;
jc->simple_state.buttons |= ((int) (packet[indexOffset + 9] >> 2) << JSOFFSET_MIC) & JSMASK_MIC;
- jc->simple_state.buttons |=
- ((int) (packet[indexOffset + 9] >> 1) << JSOFFSET_TOUCHPAD_CLICK) & JSMASK_TOUCHPAD_CLICK;
+ jc->simple_state.buttons |= ((int)(packet[indexOffset + 9] >> 4) << JSOFFSET_FNL) & JSMASK_FNL;
+ jc->simple_state.buttons |= ((int)(packet[indexOffset + 9] >> 5) << JSOFFSET_FNR) & JSMASK_FNR;
+ jc->simple_state.buttons |= ((int)(packet[indexOffset + 9] >> 6) << JSOFFSET_SL) & JSMASK_SL;
+ jc->simple_state.buttons |= ((int) (packet[indexOffset + 9] >> 7) << JSOFFSET_SR) & JSMASK_SR;
//jc->btns.zr = (packet[indexOffset+6] >> 3) & 1;
//jc->btns.zl = (packet[indexOffset+6] >> 2) & 1;
jc->simple_state.rTrigger = packet[indexOffset + 5] / 255.0f;
diff --git a/project/dependencies/JoyShockLibrary/JoyShockLibrary.h b/project/dependencies/JoyShockLibrary/JoyShockLibrary.h
index 101940f..cbfdeb0 100644
--- a/project/dependencies/JoyShockLibrary/JoyShockLibrary.h
+++ b/project/dependencies/JoyShockLibrary/JoyShockLibrary.h
@@ -17,31 +17,33 @@
#define JS_SPLIT_TYPE_RIGHT 2
#define JS_SPLIT_TYPE_FULL 3
-#define JSMASK_UP 0x00001
-#define JSMASK_DOWN 0x00002
-#define JSMASK_LEFT 0x00004
-#define JSMASK_RIGHT 0x00008
-#define JSMASK_PLUS 0x00010
-#define JSMASK_OPTIONS 0x00010
-#define JSMASK_MINUS 0x00020
-#define JSMASK_SHARE 0x00020
-#define JSMASK_LCLICK 0x00040
-#define JSMASK_RCLICK 0x00080
-#define JSMASK_L 0x00100
-#define JSMASK_R 0x00200
-#define JSMASK_ZL 0x00400
-#define JSMASK_ZR 0x00800
-#define JSMASK_S 0x01000
-#define JSMASK_E 0x02000
-#define JSMASK_W 0x04000
-#define JSMASK_N 0x08000
-#define JSMASK_HOME 0x10000
-#define JSMASK_PS 0x10000
-#define JSMASK_CAPTURE 0x20000
-#define JSMASK_TOUCHPAD_CLICK 0x20000
-#define JSMASK_MIC 0x40000
-#define JSMASK_SL 0x40000
-#define JSMASK_SR 0x80000
+#define JSMASK_UP 0x000001
+#define JSMASK_DOWN 0x000002
+#define JSMASK_LEFT 0x000004
+#define JSMASK_RIGHT 0x000008
+#define JSMASK_PLUS 0x000010
+#define JSMASK_OPTIONS 0x000010
+#define JSMASK_MINUS 0x000020
+#define JSMASK_SHARE 0x000020
+#define JSMASK_LCLICK 0x000040
+#define JSMASK_RCLICK 0x000080
+#define JSMASK_L 0x000100
+#define JSMASK_R 0x000200
+#define JSMASK_ZL 0x000400
+#define JSMASK_ZR 0x000800
+#define JSMASK_S 0x001000
+#define JSMASK_E 0x002000
+#define JSMASK_W 0x004000
+#define JSMASK_N 0x008000
+#define JSMASK_HOME 0x010000
+#define JSMASK_PS 0x010000
+#define JSMASK_CAPTURE 0x020000
+#define JSMASK_TOUCHPAD_CLICK 0x020000
+#define JSMASK_MIC 0x040000
+#define JSMASK_SL 0x080000
+#define JSMASK_SR 0x100000
+#define JSMASK_FNL 0x200000
+#define JSMASK_FNR 0x400000
#define JSOFFSET_UP 0
#define JSOFFSET_DOWN 1
@@ -66,8 +68,10 @@
#define JSOFFSET_CAPTURE 17
#define JSOFFSET_TOUCHPAD_CLICK 17
#define JSOFFSET_MIC 18
-#define JSOFFSET_SL 18
-#define JSOFFSET_SR 19
+#define JSOFFSET_SL 19
+#define JSOFFSET_SR 20
+#define JSOFFSET_FNL 21
+#define JSOFFSET_FNR 22
// PS5 Player maps for the DS Player Lightbar
#define DS5_PLAYER_1 4
diff --git a/project/engine.cpp b/project/engine.cpp
index b56f09c..1462479 100644
--- a/project/engine.cpp
+++ b/project/engine.cpp
@@ -1,5 +1,5 @@
#include "engine.h"
-#include "win32.h"
+//#include "win32.h"
NS_ENGINE_BEGIN
@@ -109,13 +109,11 @@ b32 input_using_analog()
return false;
}
-internal void
-startup()
+void startup()
{
}
-internal void
-shutdown()
+void shutdown()
{
}
@@ -146,17 +144,17 @@ void update_and_render( InputState* input, OffscreenBuffer* back_buffer, SoundBu
assert( sizeof(EngineState) <= memory->PersistentSize );
state->ToneVolume = 1000;
- state->WaveToneHz = 262;
+ state->WaveToneHz = 120;
state->WavePeriod = sound_buffer->SamplesPerSecond / state->WaveToneHz;
state->XOffset = 0;
state->YOffset = 0;
- #if Build_Debug
+ #if Build_Debug && 0
{
using namespace platform;
- char* file_path = __FILE__;
+ char const* file_path = __FILE__;
Debug_FileContent file_content = debug_file_read_content( file_path );
if ( file_content.Size )
{
@@ -282,3 +280,4 @@ void update_and_render( InputState* input, OffscreenBuffer* back_buffer, SoundBu
}
NS_ENGINE_END
+
diff --git a/project/engine.h b/project/engine.h
index 6aec9e6..c3623f2 100644
--- a/project/engine.h
+++ b/project/engine.h
@@ -4,7 +4,7 @@
#pragma once
-#include "platform.h"
+#include "platform/platform.h"
#define NS_ENGINE_BEGIN namespace engine {
#define NS_ENGINE_END }
@@ -58,8 +58,6 @@ struct DigitalBtn
s32 HalfTransitions;
b32 EndedDown;
};
-#define DigitalBtn_Up 0
-#define DigitalBtn_Down 1
struct AnalogAxis
{
@@ -197,10 +195,6 @@ struct InputMode
void input_mode_pop( InputMode* mode );
void input_mode_pop( InputMode* mode );
-// Needs a contextual reference to four things:
-// Timing, Input, Bitmap Buffer, Sound Buffer
-void update_and_render( InputState* input, OffscreenBuffer* back_buffer, SoundBuffer* sound_buffer, Memory* memory );
-
NS_ENGINE_END
// TODO(Ed) : Move this to handmade game layer later.
diff --git a/project/handmade_win32.cpp b/project/handmade_win32.cpp
new file mode 100644
index 0000000..8b6e08a
--- /dev/null
+++ b/project/handmade_win32.cpp
@@ -0,0 +1,16 @@
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-const-variable"
+#pragma clang diagnostic ignored "-Wswitch"
+#pragma clang diagnostic ignored "-Wunused-variable"
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wvarargs"
+#pragma clang diagnostic ignored "-Wunused-function"
+#pragma clang diagnostic ignored "-Wunused-but-set-variable"
+#endif
+
+#if Build_Unity
+#include "handmade.cpp"
+#include "engine.cpp"
+#include "platform/platform_win32.cpp"
+#endif
diff --git a/project/platform/jsl.h b/project/platform/jsl.h
index 577bc95..8e376d7 100644
--- a/project/platform/jsl.h
+++ b/project/platform/jsl.h
@@ -10,10 +10,10 @@
# pragma warning( disable: 4820 )
#endif
-#include "JoyShockLibrary/JoyShockLibrary.h"
+#include "dependencies/JoyShockLibrary/JoyShockLibrary.h"
#ifdef COMPILER_CLANG
# pragma clang diagnostic pop
#elif COMPILER_MSVC
# pragma warning( pop )
-#endif
\ No newline at end of file
+#endif
diff --git a/project/platform/memory.h b/project/platform/memory.h
deleted file mode 100644
index e69de29..0000000
diff --git a/project/platform/platform.h b/project/platform/platform.h
index 8bcb0b5..e0c529f 100644
--- a/project/platform/platform.h
+++ b/project/platform/platform.h
@@ -1,6 +1,8 @@
/*
Platform abstraction layer for the project.
Services the platform provides to the engine & game.
+
+ This should be the only file the engine or game layer can include
*/
#pragma once
@@ -14,6 +16,10 @@
#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
+// TODO(Ed) : REMOVE THESE WHEN HE GETS TO THEM
+#include // TODO : Implement math ourselves
+#include // TODO : Implement output logging ourselves
+
#include "grime.h"
#include "macros.h"
#include "generics.h"
@@ -38,8 +44,29 @@ struct Debug_FileContent
};
void debug_file_free_content ( Debug_FileContent* file_content );
-Debug_FileContent debug_file_read_content ( char* file_path );
-b32 debug_file_write_content( char* file_path, u32 content_size, void* content_memory );
+Debug_FileContent debug_file_read_content ( char const* file_path );
+b32 debug_file_write_content( char const* file_path, u32 content_size, void* content_memory );
#endif
NS_PLATFORM_END
+
+// On-Demand platform interface.
+// Everything exposed here should be based on a feature a game may want to provide a user
+// (Example: Letting the user change the refresh-rate of the monitor or the engine's target frame-rate)
+
+// TODO(Ed) : Implement this later when settings UI is setup.
+#pragma region Settings Exposure
+// Exposing specific variables for user configuration in settings
+
+// Returns the current monitor refresh rate.
+u32 const get_monitor_refresh_rate();
+
+// Sets the monitor refresh rate
+// Must be of the compatiable listing for the monitor the window surface is presenting to.
+void set_monitor_refresh_rate( u32 rate_in_hz );
+
+u32 const get_engine_frame_rate_target();
+
+void set_engine_frame_rate_target( u32 rate_in_hz );
+
+#pragma endregion Settings Exposure
diff --git a/project/platform/platform_engine_api.h b/project/platform/platform_engine_api.h
new file mode 100644
index 0000000..6e227b0
--- /dev/null
+++ b/project/platform/platform_engine_api.h
@@ -0,0 +1,16 @@
+/*
+ This represents the API only accessible to the platform layer to fullfill for the engine layer.
+*/
+#pragma once
+#include "engine.h"
+
+NS_ENGINE_BEGIN
+
+void startup();
+void shutdown();
+
+// Needs a contextual reference to four things:
+// Timing, Input, Bitmap Buffer, Sound Buffer
+void update_and_render( InputState* input, OffscreenBuffer* back_buffer, SoundBuffer* sound_buffer, Memory* memory );
+
+NS_ENGINE_END
diff --git a/project/platform/handmade_win32.cpp b/project/platform/platform_win32.cpp
similarity index 72%
rename from project/platform/handmade_win32.cpp
rename to project/platform/platform_win32.cpp
index 89aeea0..ff6159a 100644
--- a/project/platform/handmade_win32.cpp
+++ b/project/platform/platform_win32.cpp
@@ -17,22 +17,6 @@
- GetKeyboardLayout (for French keyboards, international WASD support)
*/
-#ifdef __clang__
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunused-const-variable"
-#pragma clang diagnostic ignored "-Wswitch"
-#pragma clang diagnostic ignored "-Wunused-variable"
-#pragma clang diagnostic ignored "-Wunknown-pragmas"
-#pragma clang diagnostic ignored "-Wvarargs"
-#pragma clang diagnostic ignored "-Wunused-function"
-#pragma clang diagnostic ignored "-Wunused-but-set-variable"
-#endif
-
-#include // TODO : Implement math ourselves
-#include // TODO : Implement output logging ourselves
-#include "engine.cpp"
-
-
// Platform Layer headers
#include "platform.h"
#include "jsl.h" // Using this to get dualsense controllers
@@ -41,10 +25,12 @@
// Engine layer headers
#include "engine.h"
+#include "platform_engine_api.h"
// TOOD(Ed): Redo these macros properly later.
+#if 1
#define congrats( message ) do { \
JslSetLightColour( 0, (255 << 16) | (215 << 8) ); \
MessageBoxA( 0, message, "Congratulations!", MB_OK | MB_ICONEXCLAMATION ); \
@@ -67,14 +53,11 @@ ensure_impl( bool condition, char const* message ) {
MessageBoxA( 0, message, "Fatal Error", MB_OK | MB_ICONERROR ); \
JslSetLightColour( 0, (255 << 8 ) ); \
} while (0)
+#endif
NS_PLATFORM_BEGIN
using namespace win32;
-// TODO(Ed) : This is a global for now.
-global bool Running;
-
-
struct OffscreenBuffer
{
BITMAPINFO Info;
@@ -93,33 +76,57 @@ struct WinDimensions
};
// TODO : This will def need to be looked over.
-struct SoundOutput
+struct DirectSoundBuffer
{
- DWORD IsPlaying;
- u32 RunningSampleIndex;
- s32 LatencySampleCount;
+ LPDIRECTSOUNDBUFFER SecondaryBuffer;
+ s16* Samples;
+ u32 SecondaryBufferSize;
+ u32 SamplesPerSecond;
+ u32 BytesPerSample;
+
+ DWORD IsPlaying;
+ u32 RunningSampleIndex;
+ u32 LatencySampleCount;
};
-// HRESULT WINAPI DirectSoundCreate(LPGUID lpGuid, LPDIRECTSOUND* ppDS, LPUNKNOWN pUnkOuter );
+
+#pragma region Static Data
+// TODO(Ed) : This is a global for now.
+global bool Running;
+
+// Max controllers for the platform layer and thus for all other layers is 4. (Sanity and xinput limit)
+constexpr u32 Max_Controllers = 4;
+
+global WinDimensions Window_Dimensions;
+global OffscreenBuffer Surface_Back_Buffer;
+
using DirectSoundCreateFn = HRESULT WINAPI (LPGUID lpGuid, LPDIRECTSOUND* ppDS, LPUNKNOWN pUnkOuter );
global DirectSoundCreateFn* direct_sound_create;
-global OffscreenBuffer BackBuffer;
-global WinDimensions WindowDimensions;
-
-global LPDIRECTSOUNDBUFFER DS_SecondaryBuffer;
-global s32 DS_SecondaryBuffer_Size;
-global s32 DS_SecondaryBuffer_SamplesPerSecond;
-global s32 DS_SecondaryBuffer_BytesPerSample;
-
-global s16* SoundBufferSamples;
-
constexpr u64 Tick_To_Millisecond = 1000;
constexpr u64 Tick_To_Microsecond = 1000 * 1000;
global u64 Performance_Counter_Frequency;
-
+
+// As of 2023 the highest refreshrate on the market is 500 hz. I'll just make this higher if something comes out beyond that...
+constexpr u32 Monitor_Refresh_Max_Supported = 500;
+
+// Anything at or below the high performance frame-time is too low latency to sleep against the window's scheduler.
+constexpr f32 High_Perf_Frametime_MS = 1000.f / 240.f;
+
+global u32 Monitor_Refresh_Hz = 60;
+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
+
+
#if Build_Debug
+struct DebugTimeMarker
+{
+ DWORD PlayCursor;
+ DWORD WriteCursor;
+};
+
void debug_file_free_content( Debug_FileContent* content )
{
if ( content->Data)
@@ -129,7 +136,7 @@ void debug_file_free_content( Debug_FileContent* content )
}
}
-Debug_FileContent debug_file_read_content( char* file_path )
+Debug_FileContent debug_file_read_content( char const* file_path )
{
Debug_FileContent result {};
@@ -168,7 +175,7 @@ Debug_FileContent debug_file_read_content( char* file_path )
return result;
}
-b32 debug_file_write_content( char* file_path, u32 content_size, void* content_memory )
+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
@@ -190,6 +197,54 @@ b32 debug_file_write_content( char* file_path, u32 content_size, void* content_m
CloseHandle( file_handle );
return true;
}
+
+internal void
+debug_draw_vertical( u32 x_pos, u32 top, u32 bottom, u32 color )
+{
+ u8*
+ pixel_byte = rcast(u8*, Surface_Back_Buffer.Memory);
+ pixel_byte += x_pos * Surface_Back_Buffer.BytesPerPixel;
+ pixel_byte += top * Surface_Back_Buffer.Pitch;
+
+ for ( u32 y = top; y < bottom; ++ y )
+ {
+ u32* pixel = rcast(u32*, pixel_byte);
+ *pixel = color;
+
+ pixel_byte += Surface_Back_Buffer.Pitch;
+ }
+}
+
+inline void
+debug_draw_sound_buffer_marker( DirectSoundBuffer* sound_buffer, f32 coefficient
+ , u32 pad_x, u32 pad_y
+ , u32 top, u32 bottom
+ , DWORD value, u32 color )
+{
+ assert( value < sound_buffer->SecondaryBufferSize );
+ u32 x = pad_x + scast(u32, coefficient * scast(f32, value ));
+ debug_draw_vertical( x, top, bottom, color );
+}
+
+internal void
+debug_sync_display( DirectSoundBuffer* sound_buffer
+ , u32 num_markers, DebugTimeMarker* markers
+ , f32 ms_per_frame )
+{
+ u32 pad_x = 16;
+ u32 pad_y = 16;
+ f32 coefficient = scast(f32, Surface_Back_Buffer.Width) / scast(f32, sound_buffer->SecondaryBufferSize);
+
+ u32 top = pad_y;
+ u32 bottom = Surface_Back_Buffer.Height - pad_y;
+
+ for ( u32 marker_index = 0; marker_index < num_markers; ++ marker_index )
+ {
+ DebugTimeMarker* marker = & markers[marker_index];
+ debug_draw_sound_buffer_marker( sound_buffer, coefficient, pad_x, pad_y, top, bottom, marker->PlayCursor, 0xFFFFFFFF );
+ debug_draw_sound_buffer_marker( sound_buffer, coefficient, pad_x, pad_y, top, bottom, marker->WriteCursor, 0xFFFF0000 );
+ }
+}
#endif
inline u64
@@ -205,6 +260,7 @@ timing_get_seconds_elapsed( u64 start, u64 end )
{
u64 delta = end - start;
f32 result = scast(f32, delta) / scast(f32, Performance_Counter_Frequency);
+ return result;
}
inline f32
@@ -269,16 +325,13 @@ input_process_axis_value( f32 value, f32 deadzone_threshold )
}
internal void
-input_process_keyboard_key( engine::DigitalBtn* key, b32 is_down )
+poll_input( engine::InputState* input )
{
- // This assert fails all the time, have no idea why. I'm just going to use GetAsyncKeyState instead, using the messaging events is horrible.
- // assert( key->EndedDown != is_down )
- key->EndedDown = is_down;
- key->HalfTransitions += is_down;
+
}
internal void
-init_sound(HWND window_handle, s32 samples_per_second, s32 buffer_size )
+init_sound(HWND window_handle, DirectSoundBuffer* sound_buffer )
{
// Load library
HMODULE sound_library = LoadLibraryA( "dsound.dll" );
@@ -313,7 +366,7 @@ init_sound(HWND window_handle, s32 samples_per_second, s32 buffer_size )
wave_format {};
wave_format.wFormatTag = WAVE_FORMAT_PCM; /* format type */
wave_format.nChannels = 2; /* number of channels (i.e. mono, stereo...) */
- wave_format.nSamplesPerSec = scast(u32, samples_per_second); /* sample rate */
+ wave_format.nSamplesPerSec = scast(u32, sound_buffer->SamplesPerSecond); /* sample rate */
wave_format.wBitsPerSample = 16; /* number of bits per sample of mono data */
wave_format.nBlockAlign = wave_format.nChannels * wave_format.wBitsPerSample / 8 ; /* block size of data */
wave_format.nAvgBytesPerSec = wave_format.nSamplesPerSec * wave_format.nBlockAlign; /* for buffer estimation */
@@ -338,29 +391,29 @@ init_sound(HWND window_handle, s32 samples_per_second, s32 buffer_size )
DSBUFFERDESC
buffer_description { sizeof(buffer_description) };
- buffer_description.dwFlags = 0;
- buffer_description.dwBufferBytes = buffer_size;
+ buffer_description.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
+ buffer_description.dwBufferBytes = sound_buffer->SecondaryBufferSize;
buffer_description.lpwfxFormat = & wave_format;
- if ( ! SUCCEEDED( direct_sound->CreateSoundBuffer( & buffer_description, & DS_SecondaryBuffer, 0 ) ))
+ if ( ! SUCCEEDED( direct_sound->CreateSoundBuffer( & buffer_description, & sound_buffer->SecondaryBuffer, 0 ) ))
{
// TODO : Diagnostic
}
- if ( ! SUCCEEDED( DS_SecondaryBuffer->SetFormat( & wave_format ) ) )
+ if ( ! SUCCEEDED( sound_buffer->SecondaryBuffer->SetFormat( & wave_format ) ) )
{
// TODO : Diagnostic
}
}
internal void
-ds_clear_sound_buffer( SoundOutput* sound_output )
+ds_clear_sound_buffer( DirectSoundBuffer* sound_buffer )
{
LPVOID region_1;
DWORD region_1_size;
LPVOID region_2;
DWORD region_2_size;
- HRESULT ds_lock_result = DS_SecondaryBuffer->Lock( 0, DS_SecondaryBuffer_Size
+ HRESULT ds_lock_result = sound_buffer->SecondaryBuffer->Lock( 0, sound_buffer->SecondaryBufferSize
, & region_1, & region_1_size
, & region_2, & region_2_size
, 0 );
@@ -383,21 +436,21 @@ ds_clear_sound_buffer( SoundOutput* sound_output )
++ sample_out;
}
- if ( ! SUCCEEDED( DS_SecondaryBuffer->Unlock( region_1, region_1_size, region_2, region_2_size ) ))
+ if ( ! SUCCEEDED( sound_buffer->SecondaryBuffer->Unlock( region_1, region_1_size, region_2, region_2_size ) ))
{
return;
}
}
internal void
-ds_fill_sound_buffer( SoundOutput* sound_output, DWORD byte_to_lock, DWORD bytes_to_write, engine::SoundBuffer* sound_buffer )
+ds_fill_sound_buffer( DirectSoundBuffer* sound_buffer, DWORD byte_to_lock, DWORD bytes_to_write )
{
LPVOID region_1;
DWORD region_1_size;
LPVOID region_2;
DWORD region_2_size;
- HRESULT ds_lock_result = DS_SecondaryBuffer->Lock( byte_to_lock, bytes_to_write
+ HRESULT ds_lock_result = sound_buffer->SecondaryBuffer->Lock( byte_to_lock, bytes_to_write
, & region_1, & region_1_size
, & region_2, & region_2_size
, 0 );
@@ -408,7 +461,7 @@ ds_fill_sound_buffer( SoundOutput* sound_output, DWORD byte_to_lock, DWORD bytes
// TODO : Assert that region sizes are valid
- DWORD region_1_sample_count = region_1_size / DS_SecondaryBuffer_BytesPerSample;
+ DWORD region_1_sample_count = region_1_size / sound_buffer->BytesPerSample;
s16* sample_out = rcast( s16*, region_1 );
s16* sample_in = sound_buffer->Samples;
for ( DWORD sample_index = 0; sample_index < region_1_sample_count; ++ sample_index )
@@ -421,10 +474,10 @@ ds_fill_sound_buffer( SoundOutput* sound_output, DWORD byte_to_lock, DWORD bytes
++ sample_out;
++ sample_in;
- ++ sound_output->RunningSampleIndex;
+ ++ sound_buffer->RunningSampleIndex;
}
- DWORD region_2_sample_count = region_2_size / DS_SecondaryBuffer_BytesPerSample;
+ DWORD region_2_sample_count = region_2_size / sound_buffer->BytesPerSample;
sample_out = rcast( s16*, region_2 );
for ( DWORD sample_index = 0; sample_index < region_2_sample_count; ++ sample_index )
{
@@ -436,10 +489,10 @@ ds_fill_sound_buffer( SoundOutput* sound_output, DWORD byte_to_lock, DWORD bytes
++ sample_out;
++ sample_in;
- ++ sound_output->RunningSampleIndex;
+ ++ sound_buffer->RunningSampleIndex;
}
- if ( ! SUCCEEDED( DS_SecondaryBuffer->Unlock( region_1, region_1_size, region_2, region_2_size ) ))
+ if ( ! SUCCEEDED( sound_buffer->SecondaryBuffer->Unlock( region_1, region_1_size, region_2, region_2_size ) ))
{
return;
}
@@ -512,12 +565,10 @@ display_buffer_in_window( HDC device_context, u32 window_width, u32 window_heigh
}
internal LRESULT CALLBACK
-main_window_callback(
- HWND handle,
- UINT system_messages,
- WPARAM w_param,
- LPARAM l_param
-)
+main_window_callback( HWND handle
+ , UINT system_messages
+ , WPARAM w_param
+ , LPARAM l_param )
{
LRESULT result = 0;
@@ -554,7 +605,7 @@ main_window_callback(
WinDimensions dimensions = get_window_dimensions( handle );
- display_buffer_in_window( device_context, dimensions.Width, dimensions.Height, &BackBuffer
+ display_buffer_in_window( device_context, dimensions.Width, dimensions.Height, &Surface_Back_Buffer
, x, y
, width, height );
EndPaint( handle, & info );
@@ -617,16 +668,10 @@ process_pending_window_messages( engine::KeyboardState* keyboard )
}
}
}
-
NS_PLATFORM_END
int CALLBACK
-WinMain(
- HINSTANCE instance,
- HINSTANCE prev_instance,
- LPSTR commandline,
- int show_command
-)
+WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR commandline, int show_command )
{
using namespace win32;
using namespace platform;
@@ -637,20 +682,12 @@ WinMain(
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;
+ constexpr 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;
+
+ // If its a high-perofmrance frame-time (a refresh rate that produces a target frametime at or below 4.16~ ms, we cannot allow the scheduler to mess things up)
+ b32 sub_ms_granularity_required = scast(f32, Engine_Refresh_Hz) <= High_Perf_Frametime_MS;
QueryPerformanceFrequency( rcast(LARGE_INTEGER*, & Performance_Counter_Frequency) );
@@ -666,13 +703,12 @@ WinMain(
+ engine_memory.TransientSize;
#if Build_Debug
- void* Base_Address = rcast(void*, terabytes( 1 ));
+ void* base_address = rcast(void*, terabytes( 1 ));
#else
- void* Base_Address = 0;
+ void* base_address = 0;
#endif
- engine_memory.Persistent = VirtualAlloc( Base_Address, total_size
- , MEM_Commit_Zeroed | MEM_Reserve, Page_Read_Write );
+ 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.PersistentSize;
if ( engine_memory.Persistent == nullptr
@@ -721,33 +757,49 @@ WinMain(
}
}
// WinDimensions dimensions = get_window_dimensions( window_handle );
- resize_dib_section( &BackBuffer, 1280, 720 );
+ resize_dib_section( &Surface_Back_Buffer, 1280, 720 );
- SoundOutput sound_output;
+ DWORD last_play_cursor = 0;
+ b32 sound_is_valid = false;
+ DirectSoundBuffer ds_sound_buffer;
{
- sound_output.IsPlaying = 0;
- DS_SecondaryBuffer_SamplesPerSecond = 48000;
- DS_SecondaryBuffer_BytesPerSample = sizeof(s16) * 2;
+ ds_sound_buffer.IsPlaying = 0;
+ ds_sound_buffer.SamplesPerSecond = 48000;
+ ds_sound_buffer.BytesPerSample = sizeof(s16) * 2;
- DS_SecondaryBuffer_Size = DS_SecondaryBuffer_SamplesPerSecond * DS_SecondaryBuffer_BytesPerSample;
- init_sound( window_handle, DS_SecondaryBuffer_SamplesPerSecond, DS_SecondaryBuffer_Size );
+ ds_sound_buffer.SecondaryBufferSize = ds_sound_buffer.SamplesPerSecond * ds_sound_buffer.BytesPerSample;
+ init_sound( window_handle, & ds_sound_buffer );
- SoundBufferSamples = rcast( s16*, VirtualAlloc( 0, 48000 * 2 * sizeof(s16)
+ ds_sound_buffer.Samples = rcast( s16*, VirtualAlloc( 0, 48000 * 2 * sizeof(s16)
, MEM_Commit_Zeroed | MEM_Reserve, Page_Read_Write ));
- assert( SoundBufferSamples );
-
- sound_output.RunningSampleIndex = 0;
- sound_output.LatencySampleCount = DS_SecondaryBuffer_SamplesPerSecond / 15;
+ assert( ds_sound_buffer.Samples );
+ ds_sound_buffer.RunningSampleIndex = 0;
// ds_clear_sound_buffer( & sound_output );
- DS_SecondaryBuffer->Play( 0, 0, DSBPLAY_LOOPING );
- }
+ ds_sound_buffer.SecondaryBuffer->Play( 0, 0, DSBPLAY_LOOPING );
- constexpr u32 Max_Controllers = 4;
- // Max controllers for the platform layer and thus for all other layers is 4. (Sanity and xinput limit)
+ // Direct sound requires 3 frames of audio latency for no bugs to show u
+ constexpr u32 frames_of_audio_latency = 3;
+ ds_sound_buffer.LatencySampleCount = frames_of_audio_latency * ( ds_sound_buffer.SamplesPerSecond / Engine_Refresh_Hz );
+ }
+#if Build_Development
+ u32 debug_marker_index = 0;
+ DebugTimeMarker debug_markers[ Monitor_Refresh_Max_Supported ] {};
+ u32 debug_marker_history_size = Engine_Refresh_Hz / 2;
+ assert( debug_marker_history_size <= Monitor_Refresh_Max_Supported )
+#endif
engine::InputState input {};
+ // There can be 4 of any of each input API type : KB & Mouse, XInput, JSL.
+
+#if 0
+ using EngineKeyboardStates = engine::KeyboardState[ Max_Controllers ];
+ EngineKeyboardStates keyboard_states[2] {};
+ EngineKeyboardStates* old_keyboards = & keyboard_states[0];
+ EngineKeyboardStates* new_keyboards = & keyboard_states[1];
+#endif
+
engine::KeyboardState keyboard_states[2] {};
engine::KeyboardState* old_keyboard = & keyboard_states[0];
engine::KeyboardState* new_keyboard = & keyboard_states[1];
@@ -801,14 +853,37 @@ WinMain(
f32 startup_ms = timing_get_ms_elapsed( launch_clock, last_frame_clock );
#endif
+
Running = true;
+#if 0
+// This tests the play & write cursor update frequency.
+ while ( Running )
+ {
+ DWORD play_cursor;
+ DWORD write_cursor;
+
+ ds_sound_buffer.SecondaryBuffer->GetCurrentPosition( & play_cursor, & write_cursor );
+ char text_buffer[256];
+ sprintf_s( text_buffer, sizeof(text_buffer), "PC:%u WC:%u\n", (u32)play_cursor, (u32)write_cursor );
+ OutputDebugStringA( text_buffer );
+ }
+#endif
while( Running )
{
process_pending_window_messages( new_keyboard );
+ // TODO(Ed): Offload polling to these functions later.
+ // poll_xinput( & input, old_xpads, new_xpads );
+ // poll_jsl( & input, old_jsl_pads, new_jsl_pads );
+
+ // or
+ // poll_input();
+
// Input
- // TODO(Ed) : Setup user definable deadzones for triggers and sticks.
+ // void poll_input();
{
+ // TODO(Ed) : Setup user definable deadzones for triggers and sticks.
+
// Swapping at the beginning of the input frame instead of the end.
swap( old_keyboard, new_keyboard );
swap( old_xpads, new_xpads );
@@ -941,21 +1016,21 @@ WinMain(
}
// Pain...
- b32 sound_is_valid = false;
- DWORD ds_play_cursor;
- DWORD ds_write_cursor;
+ // DWORD ds_play_cursor;
+ // DWORD ds_write_cursor;
DWORD byte_to_lock = 0;
DWORD bytes_to_write = 0;
- if ( SUCCEEDED( DS_SecondaryBuffer->GetCurrentPosition( & ds_play_cursor, & ds_write_cursor ) ))
+ DWORD target_cursor = 0;
+ // if ( SUCCEEDED( ds_sound_buffer.SecondaryBuffer->GetCurrentPosition( & ds_play_cursor, & ds_write_cursor ) ))
+ if ( sound_is_valid )
{
-
- byte_to_lock = (sound_output.RunningSampleIndex * DS_SecondaryBuffer_BytesPerSample) % DS_SecondaryBuffer_Size;
- DWORD target_cursor = (ds_play_cursor + (sound_output.LatencySampleCount * DS_SecondaryBuffer_BytesPerSample)) % DS_SecondaryBuffer_Size;
+ byte_to_lock = (ds_sound_buffer.RunningSampleIndex * ds_sound_buffer.BytesPerSample) % ds_sound_buffer.SecondaryBufferSize;
+ target_cursor = (last_play_cursor + (ds_sound_buffer.LatencySampleCount * ds_sound_buffer.BytesPerSample)) % ds_sound_buffer.SecondaryBufferSize;
if ( byte_to_lock > target_cursor)
{
// Infront of play cursor |--play--byte_to_write-->--|
- bytes_to_write = DS_SecondaryBuffer_Size - byte_to_lock;
+ bytes_to_write = ds_sound_buffer.SecondaryBufferSize - byte_to_lock;
bytes_to_write += target_cursor;
}
else
@@ -963,40 +1038,72 @@ WinMain(
// Behind play cursor |--byte_to_write-->--play--|
bytes_to_write = target_cursor - byte_to_lock;
}
-
- sound_is_valid = true;
+ // sound_is_valid = true;
}
// s16 samples[ 48000 * 2 ];
engine::SoundBuffer sound_buffer {};
- sound_buffer.NumSamples = bytes_to_write / DS_SecondaryBuffer_BytesPerSample;
- sound_buffer.RunningSampleIndex = sound_output.RunningSampleIndex;
- sound_buffer.SamplesPerSecond = DS_SecondaryBuffer_SamplesPerSecond;
- sound_buffer.Samples = SoundBufferSamples;
+ sound_buffer.NumSamples = bytes_to_write / ds_sound_buffer.BytesPerSample;
+ sound_buffer.RunningSampleIndex = ds_sound_buffer.RunningSampleIndex;
+ sound_buffer.SamplesPerSecond = ds_sound_buffer.SamplesPerSecond;
+ sound_buffer.Samples = ds_sound_buffer.Samples;
- engine::update_and_render( & input, rcast(engine::OffscreenBuffer*, & BackBuffer.Memory), & sound_buffer, & engine_memory );
+ engine::update_and_render( & input, rcast(engine::OffscreenBuffer*, & Surface_Back_Buffer.Memory), & sound_buffer, & engine_memory );
+
+ // Update audio buffer
+ do {
+ DWORD ds_status = 0;
+ if ( SUCCEEDED( ds_sound_buffer.SecondaryBuffer->GetStatus( & ds_status ) ) )
+ {
+ ds_sound_buffer.IsPlaying = ds_status & DSBSTATUS_PLAYING;
+ }
+
+ if ( ! sound_is_valid )
+ break;
+
+ ds_fill_sound_buffer( & ds_sound_buffer, byte_to_lock, bytes_to_write );
+
+ #if Build_Development && 0
+ DWORD play_cursor;
+ DWORD write_cursor;
+
+ ds_sound_buffer.SecondaryBuffer->GetCurrentPosition( & play_cursor, & write_cursor );
+ char text_buffer[256];
+ sprintf_s( text_buffer, sizeof(text_buffer), "LPC:%u BTL:%u TC:%u BTW:%u - PC:%u WC:%u\n"
+ , (u32)last_play_cursor, (u32)byte_to_lock, (u32)target_cursor, (u32)bytes_to_write, (u32)play_cursor, (u32)write_cursor );
+ OutputDebugStringA( text_buffer );
+ #endif
+
+ if ( ds_sound_buffer.IsPlaying )
+ break;
+
+ ds_sound_buffer.SecondaryBuffer->Play( 0, 0, DSBPLAY_LOOPING );
+ } while(0);
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_frame_ms = timing_get_ms_elapsed( last_frame_clock, work_frame_end_clock ); // WorkSecondsElapsed
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 )
+ f32 frame_elapsed_ms = work_frame_ms; // SecondsElapsedForFrame
+ if ( frame_elapsed_ms < Engine_Frame_Target_MS )
{
-
- DWORD sleep_ms = scast(DWORD, (engine_frame_target_ms - frame_elapsed_ms)) - 1;
- if ( ! sub_ms_granularity_required && sleep_is_granular )
+ s32 sleep_ms = scast(DWORD, (Engine_Frame_Target_MS - frame_elapsed_ms)) - 1;
+ if ( sleep_ms > 0 && ! sub_ms_granularity_required && sleep_is_granular )
{
- Sleep( sleep_ms );
+ Sleep( scast(DWORD, 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 )
+ if ( frame_elapsed_ms < Engine_Frame_Target_MS )
+ {
+ // TODO(Ed) : Log ms discrepancy here.
+ }
+
+ 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 );
@@ -1007,40 +1114,54 @@ WinMain(
// TODO(Ed) : Missed the display sync window!
}
- // Update audio buffer
- do {
- DWORD ds_status = 0;
- if ( SUCCEEDED( DS_SecondaryBuffer->GetStatus( & ds_status ) ) )
- {
- sound_output.IsPlaying = ds_status & DSBSTATUS_PLAYING;
- }
+ last_frame_clock = timing_get_wall_clock(); // LastCouner
+ last_frame_cycle = __rdtsc();
- if ( ! sound_is_valid )
- break;
-
- ds_fill_sound_buffer( & sound_output, byte_to_lock, bytes_to_write, & sound_buffer );
-
- if ( sound_output.IsPlaying )
- break;
-
- DS_SecondaryBuffer->Play( 0, 0, DSBPLAY_LOOPING );
- } while(0);
-
- // Update framebuffer
+ // Update surface back buffer
{
WinDimensions dimensions = get_window_dimensions( window_handle );
HDC device_context = GetDC( window_handle );
- display_buffer_in_window( device_context, dimensions.Width, dimensions.Height, &BackBuffer
+
+ #if Build_Development
+ debug_sync_display( & ds_sound_buffer, debug_marker_history_size, debug_markers, Engine_Frame_Target_MS );
+ #endif
+
+ display_buffer_in_window( device_context, dimensions.Width, dimensions.Height, &Surface_Back_Buffer
, 0, 0
, dimensions.Width, dimensions.Height );
}
- printf("%f\n", frame_elapsed_ms );
+ {
+ DWORD play_cursor = 0;
+ DWORD write_cursor = 0;
- last_frame_clock = timing_get_wall_clock();
- last_frame_cycle = __rdtsc();
+ if ( SUCCEEDED( ds_sound_buffer.SecondaryBuffer->GetCurrentPosition( & play_cursor, & write_cursor ) ) )
+ {
+ last_play_cursor = play_cursor;
+ if ( ! sound_is_valid )
+ {
+ ds_sound_buffer.RunningSampleIndex = write_cursor / ds_sound_buffer.BytesPerSample;
+ sound_is_valid = true;
+ }
+ }
+ else
+ {
+ sound_is_valid = false;
+ }
+
+ #if Build_Development
+ assert( debug_marker_index < debug_marker_history_size )
+ debug_markers[debug_marker_index] = { play_cursor, write_cursor };
+ debug_marker_index++;
+
+ if ( debug_marker_index >= debug_marker_history_size )
+ debug_marker_index = 0;
+ #endif
+ }
}
+ engine::shutdown();
+
if ( jsl_num_devices > 0 )
{
for ( u32 jsl_device_index = 0; jsl_device_index < jsl_num_devices; ++ jsl_device_index )
diff --git a/scripts/build.ps1 b/scripts/build.ps1
index 81dfd68..d0e33e7 100644
--- a/scripts/build.ps1
+++ b/scripts/build.ps1
@@ -1,8 +1,10 @@
Clear-Host
-Import-Module ./helpers/target_arch.psm1
-$devshell = Join-Path $PSScriptRoot 'helpers/devshell.ps1'
-$path_root = git rev-parse --show-toplevel
+$target_arch = Join-Path $PSScriptRoot 'helpers/target_arch.psm1'
+$devshell = Join-Path $PSScriptRoot 'helpers/devshell.ps1'
+$path_root = git rev-parse --show-toplevel
+
+Import-Module $target_arch
Push-Location $path_root
@@ -30,8 +32,7 @@ if ( $args ) { $args | ForEach-Object {
#region Configuration
if ($IsWindows) {
- # This library was really designed to only run on 64-bit systems.
- # (Its a development tool after all)
+ # This HandmadeHero implementation is only designed for 64-bit systems
& $devshell -arch amd64
}
@@ -154,12 +155,14 @@ if ( $vendor -match "clang" )
$flag_warnings_as_errors = '-Werror'
$flag_win_nologo = '/nologo'
- $ignore_warning_ms_include = 'no-microsoft-include'
+ $ignore_warning_ms_include = 'no-microsoft-include'
+ $ignore_warning_return_type_c_linkage = 'no-return-type-c-linkage'
$target_arch = Get-TargetArchClang
$warning_ignores = @(
- $ignore_warning_ms_include
+ $ignore_warning_ms_include,
+ $ignore_warning_return_type_c_linkage
)
# https://learn.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features?view=msvc-170
@@ -216,7 +219,7 @@ if ( $vendor -match "clang" )
if ( $debug ) {
$linker_args += $flag_link_win_debug
$linker_args += $flag_link_win_pdb + $pdb
- $linker_args += $flag_link_mapfile + $map
+ # $linker_args += $flag_link_mapfile + $map
}
$libraries | ForEach-Object {
@@ -338,7 +341,7 @@ if ( $vendor -match "msvc" )
if ( $debug ) {
$linker_args += $flag_link_win_debug
$linker_args += $flag_link_win_pdb + $pdb
- $linker_args += $flag_link_mapfile + $map
+ # $linker_args += $flag_link_mapfile + $map
}
else {
}
@@ -376,7 +379,7 @@ if ( (Test-Path $path_deps) -eq $false ) {
$includes = @(
$path_project,
$path_gen,
- $path_deps,
+ # $path_deps,
$path_platform
)
$compiler_args = @()
@@ -420,8 +423,8 @@ $lib_winmm = 'Winmm.lib'
# Github
$lib_jsl = Join-Path $path_deps 'JoyShockLibrary/x64/JoyShockLibrary.lib'
-$unit = Join-Path $path_platform 'handmade_win32.cpp'
-$executable = Join-Path $path_build 'handmade_win32.exe'
+$unit = Join-Path $path_project 'handmade_win32.cpp'
+$executable = Join-Path $path_build 'handmade_win32.exe'
$stack_size = 1024 * 1024 * 4
@@ -434,6 +437,9 @@ $compiler_args = @(
$flag_optimize_intrinsics
($flag_define + 'Build_DLL=0' )
+
+ # For now this script only supports unity builds... (for the full binary)
+ ($flag_define + 'Build_Unity=1' )
)
if ( $dev ) {
diff --git a/scripts/clean.ps1 b/scripts/clean.ps1
index 7e45057..6b3630e 100644
--- a/scripts/clean.ps1
+++ b/scripts/clean.ps1
@@ -5,6 +5,6 @@ $path_project = join-path $path_root "project"
$path_build = join-path $path_root "build"
$path_dependencies = join-path $path_project "dependencies"
-if ( Test-Path $path_project ) {
- Remove-Item $path_build -Recurse
+if ( Test-Path $path_build ) {
+ Remove-Item -verbose $path_build -Recurse
}
diff --git a/scripts/handmade.rdbg b/scripts/handmade.rdbg
index fb5812d..64c7312 100644
Binary files a/scripts/handmade.rdbg and b/scripts/handmade.rdbg differ
diff --git a/scripts/rebuild.ps1 b/scripts/rebuild.ps1
new file mode 100644
index 0000000..0ebc7b7
--- /dev/null
+++ b/scripts/rebuild.ps1
@@ -0,0 +1 @@
+Clear-Host