mirror of
https://github.com/Ed94/HandmadeHero.git
synced 2024-12-21 22:14:43 -08:00
Day 19 complete
This commit is contained in:
parent
e0463670c9
commit
5cfbc204a7
@ -8,10 +8,10 @@
|
||||
<ShowEmptyFolders>true</ShowEmptyFolders>
|
||||
<IsVirtual>false</IsVirtual>
|
||||
<IsFolder>false</IsFolder>
|
||||
<BuildCommand>pwsh $(WorkspaceDirectory)/scripts/build.ps1 msvc dev debug</BuildCommand>
|
||||
<RebuildCommand>pwsh $(WorkspaceDirectory)/scripts/clean.ps1; $(WorkspaceDirectory)scripts/build.ps1 msvc dev debug</RebuildCommand>
|
||||
<BuildCommand>pwsh -ExecutionPolicy Bypass -NoProfile -NonInteractive -File $(WorkspaceDirectory)/scripts/build.ps1 msvc dev optimized</BuildCommand>
|
||||
<RebuildCommand></RebuildCommand>
|
||||
<BuildFileCommand></BuildFileCommand>
|
||||
<CleanCommand>pwsh $(WorkspaceDirectory)/scripts/clean.ps1</CleanCommand>
|
||||
<CleanCommand>pwsh -ExecutionPolicy Bypass -NoProfile -NonInteractive -File $(WorkspaceDirectory)/scripts/clean.ps1</CleanCommand>
|
||||
<BuildWorkingDirectory></BuildWorkingDirectory>
|
||||
<CancelBuild></CancelBuild>
|
||||
<RunCommand>$(WorkspaceDirectory)/build/handmade_win32.exe</RunCommand>
|
||||
@ -19,7 +19,7 @@
|
||||
<DebugCommand>$(WorkspaceDirectory)/build/handmade_win32.exe</DebugCommand>
|
||||
<ExePathCommand>$(WorkspaceDirectory)/build/handmade_win32.exe</ExePathCommand>
|
||||
<DebugSln></DebugSln>
|
||||
<UseVisualStudioEnvBat>false</UseVisualStudioEnvBat>
|
||||
<UseVisualStudioEnvBat>true</UseVisualStudioEnvBat>
|
||||
<Configurations>
|
||||
<Configuration>Dev Optimzied</Configuration>
|
||||
<Configuration>Dev</Configuration>
|
||||
@ -31,11 +31,11 @@
|
||||
<AdditionalIncludePaths>
|
||||
<AdditionalIncludePath>C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.34.31933\include</AdditionalIncludePath>
|
||||
<AdditionalIncludePath>C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\VS\include</AdditionalIncludePath>
|
||||
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\ucrt</AdditionalIncludePath>
|
||||
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\um</AdditionalIncludePath>
|
||||
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\shared</AdditionalIncludePath>
|
||||
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\winrt</AdditionalIncludePath>
|
||||
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\cppwinrt</AdditionalIncludePath>
|
||||
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt</AdditionalIncludePath>
|
||||
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\um</AdditionalIncludePath>
|
||||
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\shared</AdditionalIncludePath>
|
||||
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.19041..0\\winrt</AdditionalIncludePath>
|
||||
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\cppwinrt</AdditionalIncludePath>
|
||||
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um</AdditionalIncludePath>
|
||||
</AdditionalIncludePaths>
|
||||
<Defines>
|
||||
@ -51,10 +51,28 @@
|
||||
<Defines></Defines>
|
||||
<ForceIncludes></ForceIncludes>
|
||||
</ConfigAndPlatform>
|
||||
<ConfigAndPlatform>
|
||||
<Name>Dev :x64</Name>
|
||||
<Defines></Defines>
|
||||
<ForceIncludes></ForceIncludes>
|
||||
</ConfigAndPlatform>
|
||||
<ConfigAndPlatform>
|
||||
<Name>Dev Optimzied:x64</Name>
|
||||
<Defines></Defines>
|
||||
<ForceIncludes></ForceIncludes>
|
||||
</ConfigAndPlatform>
|
||||
<Config>
|
||||
<Name>Debug</Name>
|
||||
<Defines></Defines>
|
||||
</Config>
|
||||
<Config>
|
||||
<Name>Dev</Name>
|
||||
<Defines></Defines>
|
||||
</Config>
|
||||
<Config>
|
||||
<Name>Dev Optimzied</Name>
|
||||
<Defines></Defines>
|
||||
</Config>
|
||||
<Platform>
|
||||
<Name>x64</Name>
|
||||
<Defines></Defines>
|
||||
|
20
HandmadeHero.sln
Normal file
20
HandmadeHero.sln
Normal file
@ -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
|
70
HandmadeHero.vcxproj
Normal file
70
HandmadeHero.vcxproj
Normal file
@ -0,0 +1,70 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="17.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{E1CF01B8-BB9F-42F4-9EDB-9F1274D3685A}</ProjectGuid>
|
||||
<RootNamespace>HandmadeHero</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
<ProjectName>HandmadeHero</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<!-- Development Configuration for x64 -->
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Development|x64">
|
||||
<Configuration>Development</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Development|x64'">
|
||||
<IncludePath>$(ProjectDir)project;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>$(ProjectDir)data;$(windir)System32;$(LibraryPath)</LibraryPath>
|
||||
<NMakeBuildCommandLine>pwsh -ExecutionPolicy Bypass -NoProfile -NonInteractive -File $(ProjectDir)scripts\build.ps1 msvc dev</NMakeBuildCommandLine>
|
||||
<NMakeCleanCommandLine>pwsh ExecutionPolicy Bypass -NoProfile -NonInteractive -File $(ProjectDir)scripts\clean.ps1</NMakeCleanCommandLine>
|
||||
<NMakePreprocessorDefinitions>GEN_TIME;Build_Development;Build_Debug;$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
|
||||
<ExternalIncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath)</ExternalIncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="project\engine.h" />
|
||||
<ClInclude Include="project\platform\generics.h" />
|
||||
<ClInclude Include="project\platform\grime.h" />
|
||||
<ClInclude Include="project\platform\jsl.h" />
|
||||
<ClInclude Include="project\platform\macros.h" />
|
||||
<ClInclude Include="project\platform\math_constants.h" />
|
||||
<ClInclude Include="project\platform\platform.h" />
|
||||
<ClInclude Include="project\platform\platform_engine_api.h" />
|
||||
<ClInclude Include="project\platform\types.h" />
|
||||
<ClInclude Include="project\platform\win32.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="project\engine.cpp" />
|
||||
<ClCompile Include="project\handmade.cpp" />
|
||||
<ClCompile Include="project\handmade_win32.cpp" />
|
||||
<ClCompile Include="project\platform\platform_win32.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="docs\Day 001.md" />
|
||||
<None Include="docs\Day 002.md" />
|
||||
<None Include="docs\Day 003.md" />
|
||||
<None Include="docs\Day 004.md" />
|
||||
<None Include="docs\Day 011.md" />
|
||||
<None Include="docs\Day 012.md" />
|
||||
<None Include="docs\Day 013.md" />
|
||||
<None Include="docs\Day 014.md" />
|
||||
<None Include="docs\Day 015.md" />
|
||||
<None Include="docs\Day 016.md" />
|
||||
<None Include="docs\Day 017.md" />
|
||||
<None Include="docs\Day 019.md" />
|
||||
<None Include="scripts\build.ps1" />
|
||||
<None Include="scripts\clean.ps1" />
|
||||
<None Include="scripts\helpers\devshell.ps1" />
|
||||
<None Include="scripts\helpers\target_arch.psm1" />
|
||||
<None Include="scripts\update_deps.ps1" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Development|x64'" Label="Configuration">
|
||||
<ConfigurationType>Makefile</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Targets" />
|
||||
</Project>
|
11
HandmadeHero.vcxproj.user
Normal file
11
HandmadeHero.vcxproj.user
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ShowAllFiles>true</ShowAllFiles>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Development|x64'">
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)data</LocalDebuggerWorkingDirectory>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LocalDebuggerCommand>$(ProjectDir)build\handmade_win32.exe</LocalDebuggerCommand>
|
||||
</PropertyGroup>
|
||||
</Project>
|
@ -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)
|
||||
|
20
docs/Day 019.md
Normal file
20
docs/Day 019.md
Normal file
@ -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"
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
16
project/handmade_win32.cpp
Normal file
16
project/handmade_win32.cpp
Normal file
@ -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
|
@ -10,7 +10,7 @@
|
||||
# pragma warning( disable: 4820 )
|
||||
#endif
|
||||
|
||||
#include "JoyShockLibrary/JoyShockLibrary.h"
|
||||
#include "dependencies/JoyShockLibrary/JoyShockLibrary.h"
|
||||
|
||||
#ifdef COMPILER_CLANG
|
||||
# pragma clang diagnostic pop
|
||||
|
@ -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 <math.h> // TODO : Implement math ourselves
|
||||
#include <stdio.h> // 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
|
||||
|
16
project/platform/platform_engine_api.h
Normal file
16
project/platform/platform_engine_api.h
Normal file
@ -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
|
@ -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 <math.h> // TODO : Implement math ourselves
|
||||
#include <stdio.h> // 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
|
||||
{
|
||||
LPDIRECTSOUNDBUFFER SecondaryBuffer;
|
||||
s16* Samples;
|
||||
u32 SecondaryBufferSize;
|
||||
u32 SamplesPerSecond;
|
||||
u32 BytesPerSample;
|
||||
|
||||
DWORD IsPlaying;
|
||||
u32 RunningSampleIndex;
|
||||
s32 LatencySampleCount;
|
||||
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 );
|
||||
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 )
|
||||
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,39 +1114,53 @@ 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 )
|
||||
{
|
@ -1,9 +1,11 @@
|
||||
Clear-Host
|
||||
|
||||
Import-Module ./helpers/target_arch.psm1
|
||||
$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
|
||||
|
||||
#region Arguments
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -155,11 +156,13 @@ if ( $vendor -match "clang" )
|
||||
$flag_win_nologo = '/nologo'
|
||||
|
||||
$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,7 +423,7 @@ $lib_winmm = 'Winmm.lib'
|
||||
# Github
|
||||
$lib_jsl = Join-Path $path_deps 'JoyShockLibrary/x64/JoyShockLibrary.lib'
|
||||
|
||||
$unit = Join-Path $path_platform 'handmade_win32.cpp'
|
||||
$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 ) {
|
||||
|
@ -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
|
||||
}
|
||||
|
Binary file not shown.
1
scripts/rebuild.ps1
Normal file
1
scripts/rebuild.ps1
Normal file
@ -0,0 +1 @@
|
||||
Clear-Host
|
Loading…
Reference in New Issue
Block a user