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>
|
<ShowEmptyFolders>true</ShowEmptyFolders>
|
||||||
<IsVirtual>false</IsVirtual>
|
<IsVirtual>false</IsVirtual>
|
||||||
<IsFolder>false</IsFolder>
|
<IsFolder>false</IsFolder>
|
||||||
<BuildCommand>pwsh $(WorkspaceDirectory)/scripts/build.ps1 msvc dev debug</BuildCommand>
|
<BuildCommand>pwsh -ExecutionPolicy Bypass -NoProfile -NonInteractive -File $(WorkspaceDirectory)/scripts/build.ps1 msvc dev optimized</BuildCommand>
|
||||||
<RebuildCommand>pwsh $(WorkspaceDirectory)/scripts/clean.ps1; $(WorkspaceDirectory)scripts/build.ps1 msvc dev debug</RebuildCommand>
|
<RebuildCommand></RebuildCommand>
|
||||||
<BuildFileCommand></BuildFileCommand>
|
<BuildFileCommand></BuildFileCommand>
|
||||||
<CleanCommand>pwsh $(WorkspaceDirectory)/scripts/clean.ps1</CleanCommand>
|
<CleanCommand>pwsh -ExecutionPolicy Bypass -NoProfile -NonInteractive -File $(WorkspaceDirectory)/scripts/clean.ps1</CleanCommand>
|
||||||
<BuildWorkingDirectory></BuildWorkingDirectory>
|
<BuildWorkingDirectory></BuildWorkingDirectory>
|
||||||
<CancelBuild></CancelBuild>
|
<CancelBuild></CancelBuild>
|
||||||
<RunCommand>$(WorkspaceDirectory)/build/handmade_win32.exe</RunCommand>
|
<RunCommand>$(WorkspaceDirectory)/build/handmade_win32.exe</RunCommand>
|
||||||
@ -19,10 +19,10 @@
|
|||||||
<DebugCommand>$(WorkspaceDirectory)/build/handmade_win32.exe</DebugCommand>
|
<DebugCommand>$(WorkspaceDirectory)/build/handmade_win32.exe</DebugCommand>
|
||||||
<ExePathCommand>$(WorkspaceDirectory)/build/handmade_win32.exe</ExePathCommand>
|
<ExePathCommand>$(WorkspaceDirectory)/build/handmade_win32.exe</ExePathCommand>
|
||||||
<DebugSln></DebugSln>
|
<DebugSln></DebugSln>
|
||||||
<UseVisualStudioEnvBat>false</UseVisualStudioEnvBat>
|
<UseVisualStudioEnvBat>true</UseVisualStudioEnvBat>
|
||||||
<Configurations>
|
<Configurations>
|
||||||
<Configuration>Dev Optimzied</Configuration>
|
<Configuration>Dev Optimzied</Configuration>
|
||||||
<Configuration>Dev </Configuration>
|
<Configuration>Dev</Configuration>
|
||||||
<Configuration>Optimized</Configuration>
|
<Configuration>Optimized</Configuration>
|
||||||
</Configurations>
|
</Configurations>
|
||||||
<Platforms>
|
<Platforms>
|
||||||
@ -31,11 +31,11 @@
|
|||||||
<AdditionalIncludePaths>
|
<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\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\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.19041.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.19041.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.19041.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.19041..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\\cppwinrt</AdditionalIncludePath>
|
||||||
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um</AdditionalIncludePath>
|
<AdditionalIncludePath>C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um</AdditionalIncludePath>
|
||||||
</AdditionalIncludePaths>
|
</AdditionalIncludePaths>
|
||||||
<Defines>
|
<Defines>
|
||||||
@ -51,10 +51,28 @@
|
|||||||
<Defines></Defines>
|
<Defines></Defines>
|
||||||
<ForceIncludes></ForceIncludes>
|
<ForceIncludes></ForceIncludes>
|
||||||
</ConfigAndPlatform>
|
</ConfigAndPlatform>
|
||||||
|
<ConfigAndPlatform>
|
||||||
|
<Name>Dev :x64</Name>
|
||||||
|
<Defines></Defines>
|
||||||
|
<ForceIncludes></ForceIncludes>
|
||||||
|
</ConfigAndPlatform>
|
||||||
|
<ConfigAndPlatform>
|
||||||
|
<Name>Dev Optimzied:x64</Name>
|
||||||
|
<Defines></Defines>
|
||||||
|
<ForceIncludes></ForceIncludes>
|
||||||
|
</ConfigAndPlatform>
|
||||||
<Config>
|
<Config>
|
||||||
<Name>Debug</Name>
|
<Name>Debug</Name>
|
||||||
<Defines></Defines>
|
<Defines></Defines>
|
||||||
</Config>
|
</Config>
|
||||||
|
<Config>
|
||||||
|
<Name>Dev</Name>
|
||||||
|
<Defines></Defines>
|
||||||
|
</Config>
|
||||||
|
<Config>
|
||||||
|
<Name>Dev Optimzied</Name>
|
||||||
|
<Defines></Defines>
|
||||||
|
</Config>
|
||||||
<Platform>
|
<Platform>
|
||||||
<Name>x64</Name>
|
<Name>x64</Name>
|
||||||
<Defines></Defines>
|
<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
|
## Gallery
|
||||||
|
|
||||||
![img](https://files.catbox.moe/fwjm1m.png)
|
![img](https://files.catbox.moe/xyh7u7.png)
|
||||||
![img](https://files.catbox.moe/b7ifa8.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
|
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] >> 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] >> 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] >> 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] >> 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] >> 7) << JSOFFSET_RCLICK) & JSMASK_RCLICK;
|
||||||
jc->simple_state.buttons |= ((int) (packet[indexOffset + 8] >> 5) << JSOFFSET_OPTIONS) & JSMASK_OPTIONS;
|
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 + 8]) << JSOFFSET_L) & JSMASK_L;
|
||||||
jc->simple_state.buttons |= ((int) (packet[indexOffset + 9]) << JSOFFSET_PS) & JSMASK_PS;
|
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.
|
// 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] >> 2) << JSOFFSET_MIC) & JSMASK_MIC;
|
||||||
jc->simple_state.buttons |=
|
jc->simple_state.buttons |= ((int)(packet[indexOffset + 9] >> 4) << JSOFFSET_FNL) & JSMASK_FNL;
|
||||||
((int) (packet[indexOffset + 9] >> 1) << JSOFFSET_TOUCHPAD_CLICK) & JSMASK_TOUCHPAD_CLICK;
|
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.zr = (packet[indexOffset+6] >> 3) & 1;
|
||||||
//jc->btns.zl = (packet[indexOffset+6] >> 2) & 1;
|
//jc->btns.zl = (packet[indexOffset+6] >> 2) & 1;
|
||||||
jc->simple_state.rTrigger = packet[indexOffset + 5] / 255.0f;
|
jc->simple_state.rTrigger = packet[indexOffset + 5] / 255.0f;
|
||||||
|
@ -17,31 +17,33 @@
|
|||||||
#define JS_SPLIT_TYPE_RIGHT 2
|
#define JS_SPLIT_TYPE_RIGHT 2
|
||||||
#define JS_SPLIT_TYPE_FULL 3
|
#define JS_SPLIT_TYPE_FULL 3
|
||||||
|
|
||||||
#define JSMASK_UP 0x00001
|
#define JSMASK_UP 0x000001
|
||||||
#define JSMASK_DOWN 0x00002
|
#define JSMASK_DOWN 0x000002
|
||||||
#define JSMASK_LEFT 0x00004
|
#define JSMASK_LEFT 0x000004
|
||||||
#define JSMASK_RIGHT 0x00008
|
#define JSMASK_RIGHT 0x000008
|
||||||
#define JSMASK_PLUS 0x00010
|
#define JSMASK_PLUS 0x000010
|
||||||
#define JSMASK_OPTIONS 0x00010
|
#define JSMASK_OPTIONS 0x000010
|
||||||
#define JSMASK_MINUS 0x00020
|
#define JSMASK_MINUS 0x000020
|
||||||
#define JSMASK_SHARE 0x00020
|
#define JSMASK_SHARE 0x000020
|
||||||
#define JSMASK_LCLICK 0x00040
|
#define JSMASK_LCLICK 0x000040
|
||||||
#define JSMASK_RCLICK 0x00080
|
#define JSMASK_RCLICK 0x000080
|
||||||
#define JSMASK_L 0x00100
|
#define JSMASK_L 0x000100
|
||||||
#define JSMASK_R 0x00200
|
#define JSMASK_R 0x000200
|
||||||
#define JSMASK_ZL 0x00400
|
#define JSMASK_ZL 0x000400
|
||||||
#define JSMASK_ZR 0x00800
|
#define JSMASK_ZR 0x000800
|
||||||
#define JSMASK_S 0x01000
|
#define JSMASK_S 0x001000
|
||||||
#define JSMASK_E 0x02000
|
#define JSMASK_E 0x002000
|
||||||
#define JSMASK_W 0x04000
|
#define JSMASK_W 0x004000
|
||||||
#define JSMASK_N 0x08000
|
#define JSMASK_N 0x008000
|
||||||
#define JSMASK_HOME 0x10000
|
#define JSMASK_HOME 0x010000
|
||||||
#define JSMASK_PS 0x10000
|
#define JSMASK_PS 0x010000
|
||||||
#define JSMASK_CAPTURE 0x20000
|
#define JSMASK_CAPTURE 0x020000
|
||||||
#define JSMASK_TOUCHPAD_CLICK 0x20000
|
#define JSMASK_TOUCHPAD_CLICK 0x020000
|
||||||
#define JSMASK_MIC 0x40000
|
#define JSMASK_MIC 0x040000
|
||||||
#define JSMASK_SL 0x40000
|
#define JSMASK_SL 0x080000
|
||||||
#define JSMASK_SR 0x80000
|
#define JSMASK_SR 0x100000
|
||||||
|
#define JSMASK_FNL 0x200000
|
||||||
|
#define JSMASK_FNR 0x400000
|
||||||
|
|
||||||
#define JSOFFSET_UP 0
|
#define JSOFFSET_UP 0
|
||||||
#define JSOFFSET_DOWN 1
|
#define JSOFFSET_DOWN 1
|
||||||
@ -66,8 +68,10 @@
|
|||||||
#define JSOFFSET_CAPTURE 17
|
#define JSOFFSET_CAPTURE 17
|
||||||
#define JSOFFSET_TOUCHPAD_CLICK 17
|
#define JSOFFSET_TOUCHPAD_CLICK 17
|
||||||
#define JSOFFSET_MIC 18
|
#define JSOFFSET_MIC 18
|
||||||
#define JSOFFSET_SL 18
|
#define JSOFFSET_SL 19
|
||||||
#define JSOFFSET_SR 19
|
#define JSOFFSET_SR 20
|
||||||
|
#define JSOFFSET_FNL 21
|
||||||
|
#define JSOFFSET_FNR 22
|
||||||
|
|
||||||
// PS5 Player maps for the DS Player Lightbar
|
// PS5 Player maps for the DS Player Lightbar
|
||||||
#define DS5_PLAYER_1 4
|
#define DS5_PLAYER_1 4
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
#include "win32.h"
|
//#include "win32.h"
|
||||||
|
|
||||||
NS_ENGINE_BEGIN
|
NS_ENGINE_BEGIN
|
||||||
|
|
||||||
@ -109,13 +109,11 @@ b32 input_using_analog()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
void startup()
|
||||||
startup()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
void shutdown()
|
||||||
shutdown()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,17 +144,17 @@ void update_and_render( InputState* input, OffscreenBuffer* back_buffer, SoundBu
|
|||||||
assert( sizeof(EngineState) <= memory->PersistentSize );
|
assert( sizeof(EngineState) <= memory->PersistentSize );
|
||||||
|
|
||||||
state->ToneVolume = 1000;
|
state->ToneVolume = 1000;
|
||||||
state->WaveToneHz = 262;
|
state->WaveToneHz = 120;
|
||||||
state->WavePeriod = sound_buffer->SamplesPerSecond / state->WaveToneHz;
|
state->WavePeriod = sound_buffer->SamplesPerSecond / state->WaveToneHz;
|
||||||
|
|
||||||
state->XOffset = 0;
|
state->XOffset = 0;
|
||||||
state->YOffset = 0;
|
state->YOffset = 0;
|
||||||
|
|
||||||
#if Build_Debug
|
#if Build_Debug && 0
|
||||||
{
|
{
|
||||||
using namespace platform;
|
using namespace platform;
|
||||||
|
|
||||||
char* file_path = __FILE__;
|
char const* file_path = __FILE__;
|
||||||
Debug_FileContent file_content = debug_file_read_content( file_path );
|
Debug_FileContent file_content = debug_file_read_content( file_path );
|
||||||
if ( file_content.Size )
|
if ( file_content.Size )
|
||||||
{
|
{
|
||||||
@ -282,3 +280,4 @@ void update_and_render( InputState* input, OffscreenBuffer* back_buffer, SoundBu
|
|||||||
}
|
}
|
||||||
|
|
||||||
NS_ENGINE_END
|
NS_ENGINE_END
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "platform.h"
|
#include "platform/platform.h"
|
||||||
|
|
||||||
#define NS_ENGINE_BEGIN namespace engine {
|
#define NS_ENGINE_BEGIN namespace engine {
|
||||||
#define NS_ENGINE_END }
|
#define NS_ENGINE_END }
|
||||||
@ -58,8 +58,6 @@ struct DigitalBtn
|
|||||||
s32 HalfTransitions;
|
s32 HalfTransitions;
|
||||||
b32 EndedDown;
|
b32 EndedDown;
|
||||||
};
|
};
|
||||||
#define DigitalBtn_Up 0
|
|
||||||
#define DigitalBtn_Down 1
|
|
||||||
|
|
||||||
struct AnalogAxis
|
struct AnalogAxis
|
||||||
{
|
{
|
||||||
@ -197,10 +195,6 @@ struct InputMode
|
|||||||
void input_mode_pop( InputMode* mode );
|
void input_mode_pop( InputMode* mode );
|
||||||
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
|
NS_ENGINE_END
|
||||||
|
|
||||||
// TODO(Ed) : Move this to handmade game layer later.
|
// 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 )
|
# pragma warning( disable: 4820 )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "JoyShockLibrary/JoyShockLibrary.h"
|
#include "dependencies/JoyShockLibrary/JoyShockLibrary.h"
|
||||||
|
|
||||||
#ifdef COMPILER_CLANG
|
#ifdef COMPILER_CLANG
|
||||||
# pragma clang diagnostic pop
|
# pragma clang diagnostic pop
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
Platform abstraction layer for the project.
|
Platform abstraction layer for the project.
|
||||||
Services the platform provides to the engine & game.
|
Services the platform provides to the engine & game.
|
||||||
|
|
||||||
|
This should be the only file the engine or game layer can include
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -14,6 +16,10 @@
|
|||||||
#pragma warning( disable: 4505 ) // Support for unused static functions
|
#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
|
#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 "grime.h"
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
#include "generics.h"
|
#include "generics.h"
|
||||||
@ -38,8 +44,29 @@ struct Debug_FileContent
|
|||||||
};
|
};
|
||||||
|
|
||||||
void debug_file_free_content ( Debug_FileContent* file_content );
|
void debug_file_free_content ( Debug_FileContent* file_content );
|
||||||
Debug_FileContent debug_file_read_content ( char* file_path );
|
Debug_FileContent debug_file_read_content ( char const* file_path );
|
||||||
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 );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NS_PLATFORM_END
|
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)
|
- 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
|
// Platform Layer headers
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "jsl.h" // Using this to get dualsense controllers
|
#include "jsl.h" // Using this to get dualsense controllers
|
||||||
@ -41,10 +25,12 @@
|
|||||||
|
|
||||||
// Engine layer headers
|
// Engine layer headers
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
|
#include "platform_engine_api.h"
|
||||||
|
|
||||||
|
|
||||||
// TOOD(Ed): Redo these macros properly later.
|
// TOOD(Ed): Redo these macros properly later.
|
||||||
|
|
||||||
|
#if 1
|
||||||
#define congrats( message ) do { \
|
#define congrats( message ) do { \
|
||||||
JslSetLightColour( 0, (255 << 16) | (215 << 8) ); \
|
JslSetLightColour( 0, (255 << 16) | (215 << 8) ); \
|
||||||
MessageBoxA( 0, message, "Congratulations!", MB_OK | MB_ICONEXCLAMATION ); \
|
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 ); \
|
MessageBoxA( 0, message, "Fatal Error", MB_OK | MB_ICONERROR ); \
|
||||||
JslSetLightColour( 0, (255 << 8 ) ); \
|
JslSetLightColour( 0, (255 << 8 ) ); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
NS_PLATFORM_BEGIN
|
NS_PLATFORM_BEGIN
|
||||||
using namespace win32;
|
using namespace win32;
|
||||||
|
|
||||||
// TODO(Ed) : This is a global for now.
|
|
||||||
global bool Running;
|
|
||||||
|
|
||||||
|
|
||||||
struct OffscreenBuffer
|
struct OffscreenBuffer
|
||||||
{
|
{
|
||||||
BITMAPINFO Info;
|
BITMAPINFO Info;
|
||||||
@ -93,33 +76,57 @@ struct WinDimensions
|
|||||||
};
|
};
|
||||||
|
|
||||||
// TODO : This will def need to be looked over.
|
// 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;
|
DWORD IsPlaying;
|
||||||
u32 RunningSampleIndex;
|
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 );
|
using DirectSoundCreateFn = HRESULT WINAPI (LPGUID lpGuid, LPDIRECTSOUND* ppDS, LPUNKNOWN pUnkOuter );
|
||||||
global DirectSoundCreateFn* direct_sound_create;
|
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_Millisecond = 1000;
|
||||||
constexpr u64 Tick_To_Microsecond = 1000 * 1000;
|
constexpr u64 Tick_To_Microsecond = 1000 * 1000;
|
||||||
|
|
||||||
global u64 Performance_Counter_Frequency;
|
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
|
#if Build_Debug
|
||||||
|
struct DebugTimeMarker
|
||||||
|
{
|
||||||
|
DWORD PlayCursor;
|
||||||
|
DWORD WriteCursor;
|
||||||
|
};
|
||||||
|
|
||||||
void debug_file_free_content( Debug_FileContent* content )
|
void debug_file_free_content( Debug_FileContent* content )
|
||||||
{
|
{
|
||||||
if ( content->Data)
|
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 {};
|
Debug_FileContent result {};
|
||||||
|
|
||||||
@ -168,7 +175,7 @@ Debug_FileContent debug_file_read_content( char* file_path )
|
|||||||
return result;
|
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
|
HANDLE file_handle = CreateFileA( file_path
|
||||||
, GENERIC_WRITE, 0, 0
|
, 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 );
|
CloseHandle( file_handle );
|
||||||
return true;
|
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
|
#endif
|
||||||
|
|
||||||
inline u64
|
inline u64
|
||||||
@ -205,6 +260,7 @@ timing_get_seconds_elapsed( u64 start, u64 end )
|
|||||||
{
|
{
|
||||||
u64 delta = end - start;
|
u64 delta = end - start;
|
||||||
f32 result = scast(f32, delta) / scast(f32, Performance_Counter_Frequency);
|
f32 result = scast(f32, delta) / scast(f32, Performance_Counter_Frequency);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline f32
|
inline f32
|
||||||
@ -269,16 +325,13 @@ input_process_axis_value( f32 value, f32 deadzone_threshold )
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
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
|
internal void
|
||||||
init_sound(HWND window_handle, s32 samples_per_second, s32 buffer_size )
|
init_sound(HWND window_handle, DirectSoundBuffer* sound_buffer )
|
||||||
{
|
{
|
||||||
// Load library
|
// Load library
|
||||||
HMODULE sound_library = LoadLibraryA( "dsound.dll" );
|
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 {};
|
||||||
wave_format.wFormatTag = WAVE_FORMAT_PCM; /* format type */
|
wave_format.wFormatTag = WAVE_FORMAT_PCM; /* format type */
|
||||||
wave_format.nChannels = 2; /* number of channels (i.e. mono, stereo...) */
|
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.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.nBlockAlign = wave_format.nChannels * wave_format.wBitsPerSample / 8 ; /* block size of data */
|
||||||
wave_format.nAvgBytesPerSec = wave_format.nSamplesPerSec * wave_format.nBlockAlign; /* for buffer estimation */
|
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
|
DSBUFFERDESC
|
||||||
buffer_description { sizeof(buffer_description) };
|
buffer_description { sizeof(buffer_description) };
|
||||||
buffer_description.dwFlags = 0;
|
buffer_description.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
|
||||||
buffer_description.dwBufferBytes = buffer_size;
|
buffer_description.dwBufferBytes = sound_buffer->SecondaryBufferSize;
|
||||||
buffer_description.lpwfxFormat = & wave_format;
|
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
|
// TODO : Diagnostic
|
||||||
}
|
}
|
||||||
if ( ! SUCCEEDED( DS_SecondaryBuffer->SetFormat( & wave_format ) ) )
|
if ( ! SUCCEEDED( sound_buffer->SecondaryBuffer->SetFormat( & wave_format ) ) )
|
||||||
{
|
{
|
||||||
// TODO : Diagnostic
|
// TODO : Diagnostic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
ds_clear_sound_buffer( SoundOutput* sound_output )
|
ds_clear_sound_buffer( DirectSoundBuffer* sound_buffer )
|
||||||
{
|
{
|
||||||
LPVOID region_1;
|
LPVOID region_1;
|
||||||
DWORD region_1_size;
|
DWORD region_1_size;
|
||||||
LPVOID region_2;
|
LPVOID region_2;
|
||||||
DWORD region_2_size;
|
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_1, & region_1_size
|
||||||
, & region_2, & region_2_size
|
, & region_2, & region_2_size
|
||||||
, 0 );
|
, 0 );
|
||||||
@ -383,21 +436,21 @@ ds_clear_sound_buffer( SoundOutput* sound_output )
|
|||||||
++ sample_out;
|
++ 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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
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;
|
LPVOID region_1;
|
||||||
DWORD region_1_size;
|
DWORD region_1_size;
|
||||||
LPVOID region_2;
|
LPVOID region_2;
|
||||||
DWORD region_2_size;
|
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_1, & region_1_size
|
||||||
, & region_2, & region_2_size
|
, & region_2, & region_2_size
|
||||||
, 0 );
|
, 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
|
// 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_out = rcast( s16*, region_1 );
|
||||||
s16* sample_in = sound_buffer->Samples;
|
s16* sample_in = sound_buffer->Samples;
|
||||||
for ( DWORD sample_index = 0; sample_index < region_1_sample_count; ++ sample_index )
|
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_out;
|
||||||
++ sample_in;
|
++ 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 );
|
sample_out = rcast( s16*, region_2 );
|
||||||
for ( DWORD sample_index = 0; sample_index < region_2_sample_count; ++ sample_index )
|
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_out;
|
||||||
++ sample_in;
|
++ 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;
|
return;
|
||||||
}
|
}
|
||||||
@ -512,12 +565,10 @@ display_buffer_in_window( HDC device_context, u32 window_width, u32 window_heigh
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal LRESULT CALLBACK
|
internal LRESULT CALLBACK
|
||||||
main_window_callback(
|
main_window_callback( HWND handle
|
||||||
HWND handle,
|
, UINT system_messages
|
||||||
UINT system_messages,
|
, WPARAM w_param
|
||||||
WPARAM w_param,
|
, LPARAM l_param )
|
||||||
LPARAM l_param
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
LRESULT result = 0;
|
LRESULT result = 0;
|
||||||
|
|
||||||
@ -554,7 +605,7 @@ main_window_callback(
|
|||||||
|
|
||||||
WinDimensions dimensions = get_window_dimensions( handle );
|
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
|
, x, y
|
||||||
, width, height );
|
, width, height );
|
||||||
EndPaint( handle, & info );
|
EndPaint( handle, & info );
|
||||||
@ -617,16 +668,10 @@ process_pending_window_messages( engine::KeyboardState* keyboard )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_PLATFORM_END
|
NS_PLATFORM_END
|
||||||
|
|
||||||
int CALLBACK
|
int CALLBACK
|
||||||
WinMain(
|
WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR commandline, int show_command )
|
||||||
HINSTANCE instance,
|
|
||||||
HINSTANCE prev_instance,
|
|
||||||
LPSTR commandline,
|
|
||||||
int show_command
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
using namespace win32;
|
using namespace win32;
|
||||||
using namespace platform;
|
using namespace platform;
|
||||||
@ -637,20 +682,12 @@ WinMain(
|
|||||||
u64 launch_cycle = __rdtsc();
|
u64 launch_cycle = __rdtsc();
|
||||||
#endif
|
#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
|
// 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 );
|
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.
|
// 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)
|
||||||
f32 high_perf_frametime_ms = 1000.f / 120.f;
|
b32 sub_ms_granularity_required = scast(f32, Engine_Refresh_Hz) <= High_Perf_Frametime_MS;
|
||||||
b32 sub_ms_granularity_required = engine_frame_target_ms <= high_perf_frametime_ms;
|
|
||||||
|
|
||||||
QueryPerformanceFrequency( rcast(LARGE_INTEGER*, & Performance_Counter_Frequency) );
|
QueryPerformanceFrequency( rcast(LARGE_INTEGER*, & Performance_Counter_Frequency) );
|
||||||
|
|
||||||
@ -666,13 +703,12 @@ WinMain(
|
|||||||
+ engine_memory.TransientSize;
|
+ engine_memory.TransientSize;
|
||||||
|
|
||||||
#if Build_Debug
|
#if Build_Debug
|
||||||
void* Base_Address = rcast(void*, terabytes( 1 ));
|
void* base_address = rcast(void*, terabytes( 1 ));
|
||||||
#else
|
#else
|
||||||
void* Base_Address = 0;
|
void* base_address = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
engine_memory.Persistent = VirtualAlloc( Base_Address, total_size
|
engine_memory.Persistent = VirtualAlloc( base_address, total_size , MEM_Commit_Zeroed | MEM_Reserve, Page_Read_Write );
|
||||||
, MEM_Commit_Zeroed | MEM_Reserve, Page_Read_Write );
|
|
||||||
engine_memory.Transient = rcast( u8*, engine_memory.Persistent ) + engine_memory.PersistentSize;
|
engine_memory.Transient = rcast( u8*, engine_memory.Persistent ) + engine_memory.PersistentSize;
|
||||||
|
|
||||||
if ( engine_memory.Persistent == nullptr
|
if ( engine_memory.Persistent == nullptr
|
||||||
@ -721,33 +757,49 @@ WinMain(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// WinDimensions dimensions = get_window_dimensions( window_handle );
|
// 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_sound_buffer.IsPlaying = 0;
|
||||||
DS_SecondaryBuffer_SamplesPerSecond = 48000;
|
ds_sound_buffer.SamplesPerSecond = 48000;
|
||||||
DS_SecondaryBuffer_BytesPerSample = sizeof(s16) * 2;
|
ds_sound_buffer.BytesPerSample = sizeof(s16) * 2;
|
||||||
|
|
||||||
DS_SecondaryBuffer_Size = DS_SecondaryBuffer_SamplesPerSecond * DS_SecondaryBuffer_BytesPerSample;
|
ds_sound_buffer.SecondaryBufferSize = ds_sound_buffer.SamplesPerSecond * ds_sound_buffer.BytesPerSample;
|
||||||
init_sound( window_handle, DS_SecondaryBuffer_SamplesPerSecond, DS_SecondaryBuffer_Size );
|
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 ));
|
, MEM_Commit_Zeroed | MEM_Reserve, Page_Read_Write ));
|
||||||
|
|
||||||
assert( SoundBufferSamples );
|
assert( ds_sound_buffer.Samples );
|
||||||
|
ds_sound_buffer.RunningSampleIndex = 0;
|
||||||
sound_output.RunningSampleIndex = 0;
|
|
||||||
sound_output.LatencySampleCount = DS_SecondaryBuffer_SamplesPerSecond / 15;
|
|
||||||
// ds_clear_sound_buffer( & sound_output );
|
// 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;
|
// Direct sound requires 3 frames of audio latency for no bugs to show u
|
||||||
// Max controllers for the platform layer and thus for all other layers is 4. (Sanity and xinput limit)
|
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 {};
|
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 keyboard_states[2] {};
|
||||||
engine::KeyboardState* old_keyboard = & keyboard_states[0];
|
engine::KeyboardState* old_keyboard = & keyboard_states[0];
|
||||||
engine::KeyboardState* new_keyboard = & keyboard_states[1];
|
engine::KeyboardState* new_keyboard = & keyboard_states[1];
|
||||||
@ -801,14 +853,37 @@ WinMain(
|
|||||||
f32 startup_ms = timing_get_ms_elapsed( launch_clock, last_frame_clock );
|
f32 startup_ms = timing_get_ms_elapsed( launch_clock, last_frame_clock );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
Running = true;
|
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 )
|
while( Running )
|
||||||
{
|
{
|
||||||
process_pending_window_messages( new_keyboard );
|
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
|
// 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.
|
// Swapping at the beginning of the input frame instead of the end.
|
||||||
swap( old_keyboard, new_keyboard );
|
swap( old_keyboard, new_keyboard );
|
||||||
swap( old_xpads, new_xpads );
|
swap( old_xpads, new_xpads );
|
||||||
@ -941,21 +1016,21 @@ WinMain(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pain...
|
// Pain...
|
||||||
b32 sound_is_valid = false;
|
// DWORD ds_play_cursor;
|
||||||
DWORD ds_play_cursor;
|
// DWORD ds_write_cursor;
|
||||||
DWORD ds_write_cursor;
|
|
||||||
DWORD byte_to_lock = 0;
|
DWORD byte_to_lock = 0;
|
||||||
DWORD bytes_to_write = 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 = (ds_sound_buffer.RunningSampleIndex * ds_sound_buffer.BytesPerSample) % ds_sound_buffer.SecondaryBufferSize;
|
||||||
byte_to_lock = (sound_output.RunningSampleIndex * DS_SecondaryBuffer_BytesPerSample) % DS_SecondaryBuffer_Size;
|
target_cursor = (last_play_cursor + (ds_sound_buffer.LatencySampleCount * ds_sound_buffer.BytesPerSample)) % ds_sound_buffer.SecondaryBufferSize;
|
||||||
DWORD target_cursor = (ds_play_cursor + (sound_output.LatencySampleCount * DS_SecondaryBuffer_BytesPerSample)) % DS_SecondaryBuffer_Size;
|
|
||||||
|
|
||||||
if ( byte_to_lock > target_cursor)
|
if ( byte_to_lock > target_cursor)
|
||||||
{
|
{
|
||||||
// Infront of play cursor |--play--byte_to_write-->--|
|
// 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;
|
bytes_to_write += target_cursor;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -963,40 +1038,72 @@ WinMain(
|
|||||||
// Behind play cursor |--byte_to_write-->--play--|
|
// Behind play cursor |--byte_to_write-->--play--|
|
||||||
bytes_to_write = target_cursor - byte_to_lock;
|
bytes_to_write = target_cursor - byte_to_lock;
|
||||||
}
|
}
|
||||||
|
// sound_is_valid = true;
|
||||||
sound_is_valid = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// s16 samples[ 48000 * 2 ];
|
// s16 samples[ 48000 * 2 ];
|
||||||
engine::SoundBuffer sound_buffer {};
|
engine::SoundBuffer sound_buffer {};
|
||||||
sound_buffer.NumSamples = bytes_to_write / DS_SecondaryBuffer_BytesPerSample;
|
sound_buffer.NumSamples = bytes_to_write / ds_sound_buffer.BytesPerSample;
|
||||||
sound_buffer.RunningSampleIndex = sound_output.RunningSampleIndex;
|
sound_buffer.RunningSampleIndex = ds_sound_buffer.RunningSampleIndex;
|
||||||
sound_buffer.SamplesPerSecond = DS_SecondaryBuffer_SamplesPerSecond;
|
sound_buffer.SamplesPerSecond = ds_sound_buffer.SamplesPerSecond;
|
||||||
sound_buffer.Samples = SoundBufferSamples;
|
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_cycle = __rdtsc();
|
||||||
u64 work_frame_end_clock = timing_get_wall_clock();
|
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 work_cycles = timing_get_ms_elapsed( last_frame_cycle, work_frame_end_cycle );
|
||||||
|
|
||||||
f32 frame_elapsed_ms = work_frame_ms;
|
f32 frame_elapsed_ms = work_frame_ms; // SecondsElapsedForFrame
|
||||||
if ( frame_elapsed_ms < engine_frame_target_ms )
|
if ( frame_elapsed_ms < Engine_Frame_Target_MS )
|
||||||
{
|
{
|
||||||
|
s32 sleep_ms = scast(DWORD, (Engine_Frame_Target_MS - frame_elapsed_ms)) - 1;
|
||||||
DWORD sleep_ms = scast(DWORD, (engine_frame_target_ms - frame_elapsed_ms)) - 1;
|
if ( sleep_ms > 0 && ! sub_ms_granularity_required && sleep_is_granular )
|
||||||
if ( ! sub_ms_granularity_required && sleep_is_granular )
|
|
||||||
{
|
{
|
||||||
Sleep( sleep_ms );
|
Sleep( scast(DWORD, sleep_ms) );
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 frame_clock = timing_get_wall_clock();
|
u64 frame_clock = timing_get_wall_clock();
|
||||||
frame_elapsed_ms = timing_get_ms_elapsed( last_frame_clock, frame_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 );
|
assert( frame_elapsed_ms < Engine_Frame_Target_MS );
|
||||||
while ( frame_elapsed_ms < engine_frame_target_ms )
|
while ( frame_elapsed_ms < Engine_Frame_Target_MS )
|
||||||
{
|
{
|
||||||
frame_clock = timing_get_wall_clock();
|
frame_clock = timing_get_wall_clock();
|
||||||
frame_elapsed_ms = timing_get_ms_elapsed( last_frame_clock, frame_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!
|
// TODO(Ed) : Missed the display sync window!
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update audio buffer
|
last_frame_clock = timing_get_wall_clock(); // LastCouner
|
||||||
do {
|
last_frame_cycle = __rdtsc();
|
||||||
DWORD ds_status = 0;
|
|
||||||
if ( SUCCEEDED( DS_SecondaryBuffer->GetStatus( & ds_status ) ) )
|
|
||||||
{
|
|
||||||
sound_output.IsPlaying = ds_status & DSBSTATUS_PLAYING;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! sound_is_valid )
|
// Update surface back buffer
|
||||||
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
|
|
||||||
{
|
{
|
||||||
WinDimensions dimensions = get_window_dimensions( window_handle );
|
WinDimensions dimensions = get_window_dimensions( window_handle );
|
||||||
HDC device_context = GetDC( 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
|
, 0, 0
|
||||||
, dimensions.Width, dimensions.Height );
|
, 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();
|
if ( SUCCEEDED( ds_sound_buffer.SecondaryBuffer->GetCurrentPosition( & play_cursor, & write_cursor ) ) )
|
||||||
last_frame_cycle = __rdtsc();
|
{
|
||||||
|
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 )
|
if ( jsl_num_devices > 0 )
|
||||||
{
|
{
|
@ -1,9 +1,11 @@
|
|||||||
Clear-Host
|
Clear-Host
|
||||||
|
|
||||||
Import-Module ./helpers/target_arch.psm1
|
$target_arch = Join-Path $PSScriptRoot 'helpers/target_arch.psm1'
|
||||||
$devshell = Join-Path $PSScriptRoot 'helpers/devshell.ps1'
|
$devshell = Join-Path $PSScriptRoot 'helpers/devshell.ps1'
|
||||||
$path_root = git rev-parse --show-toplevel
|
$path_root = git rev-parse --show-toplevel
|
||||||
|
|
||||||
|
Import-Module $target_arch
|
||||||
|
|
||||||
Push-Location $path_root
|
Push-Location $path_root
|
||||||
|
|
||||||
#region Arguments
|
#region Arguments
|
||||||
@ -30,8 +32,7 @@ if ( $args ) { $args | ForEach-Object {
|
|||||||
|
|
||||||
#region Configuration
|
#region Configuration
|
||||||
if ($IsWindows) {
|
if ($IsWindows) {
|
||||||
# This library was really designed to only run on 64-bit systems.
|
# This HandmadeHero implementation is only designed for 64-bit systems
|
||||||
# (Its a development tool after all)
|
|
||||||
& $devshell -arch amd64
|
& $devshell -arch amd64
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,11 +156,13 @@ if ( $vendor -match "clang" )
|
|||||||
$flag_win_nologo = '/nologo'
|
$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
|
$target_arch = Get-TargetArchClang
|
||||||
|
|
||||||
$warning_ignores = @(
|
$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
|
# 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 ) {
|
if ( $debug ) {
|
||||||
$linker_args += $flag_link_win_debug
|
$linker_args += $flag_link_win_debug
|
||||||
$linker_args += $flag_link_win_pdb + $pdb
|
$linker_args += $flag_link_win_pdb + $pdb
|
||||||
$linker_args += $flag_link_mapfile + $map
|
# $linker_args += $flag_link_mapfile + $map
|
||||||
}
|
}
|
||||||
|
|
||||||
$libraries | ForEach-Object {
|
$libraries | ForEach-Object {
|
||||||
@ -338,7 +341,7 @@ if ( $vendor -match "msvc" )
|
|||||||
if ( $debug ) {
|
if ( $debug ) {
|
||||||
$linker_args += $flag_link_win_debug
|
$linker_args += $flag_link_win_debug
|
||||||
$linker_args += $flag_link_win_pdb + $pdb
|
$linker_args += $flag_link_win_pdb + $pdb
|
||||||
$linker_args += $flag_link_mapfile + $map
|
# $linker_args += $flag_link_mapfile + $map
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
}
|
}
|
||||||
@ -376,7 +379,7 @@ if ( (Test-Path $path_deps) -eq $false ) {
|
|||||||
$includes = @(
|
$includes = @(
|
||||||
$path_project,
|
$path_project,
|
||||||
$path_gen,
|
$path_gen,
|
||||||
$path_deps,
|
# $path_deps,
|
||||||
$path_platform
|
$path_platform
|
||||||
)
|
)
|
||||||
$compiler_args = @()
|
$compiler_args = @()
|
||||||
@ -420,7 +423,7 @@ $lib_winmm = 'Winmm.lib'
|
|||||||
# Github
|
# Github
|
||||||
$lib_jsl = Join-Path $path_deps 'JoyShockLibrary/x64/JoyShockLibrary.lib'
|
$lib_jsl = Join-Path $path_deps 'JoyShockLibrary/x64/JoyShockLibrary.lib'
|
||||||
|
|
||||||
$unit = Join-Path $path_platform 'handmade_win32.cpp'
|
$unit = Join-Path $path_project 'handmade_win32.cpp'
|
||||||
$executable = Join-Path $path_build 'handmade_win32.exe'
|
$executable = Join-Path $path_build 'handmade_win32.exe'
|
||||||
|
|
||||||
$stack_size = 1024 * 1024 * 4
|
$stack_size = 1024 * 1024 * 4
|
||||||
@ -434,6 +437,9 @@ $compiler_args = @(
|
|||||||
$flag_optimize_intrinsics
|
$flag_optimize_intrinsics
|
||||||
|
|
||||||
($flag_define + 'Build_DLL=0' )
|
($flag_define + 'Build_DLL=0' )
|
||||||
|
|
||||||
|
# For now this script only supports unity builds... (for the full binary)
|
||||||
|
($flag_define + 'Build_Unity=1' )
|
||||||
)
|
)
|
||||||
|
|
||||||
if ( $dev ) {
|
if ( $dev ) {
|
||||||
|
@ -5,6 +5,6 @@ $path_project = join-path $path_root "project"
|
|||||||
$path_build = join-path $path_root "build"
|
$path_build = join-path $path_root "build"
|
||||||
$path_dependencies = join-path $path_project "dependencies"
|
$path_dependencies = join-path $path_project "dependencies"
|
||||||
|
|
||||||
if ( Test-Path $path_project ) {
|
if ( Test-Path $path_build ) {
|
||||||
Remove-Item $path_build -Recurse
|
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