mirror of
https://github.com/Ed94/HandmadeHero.git
synced 2024-12-22 06:14:45 -08:00
Day 21 complete
This commit is contained in:
parent
1c3cf08687
commit
9220550dd4
2
.gitignore
vendored
2
.gitignore
vendored
@ -22,3 +22,5 @@ build
|
|||||||
|
|
||||||
**/*.dll
|
**/*.dll
|
||||||
data/test.out
|
data/test.out
|
||||||
|
data/handmade_engine.symbols
|
||||||
|
data/handmade_win32.exe
|
||||||
|
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@ -8,7 +8,7 @@
|
|||||||
"type":"cppvsdbg",
|
"type":"cppvsdbg",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name" : "Debug handmade win32 msvc",
|
"name" : "Debug handmade win32 msvc",
|
||||||
"program": "${workspaceFolder}/build/handmade_win32.exe",
|
"program": "${workspaceFolder}/data/handmade_win32.exe",
|
||||||
"args": [],
|
"args": [],
|
||||||
"cwd": "${workspaceFolder}/data",
|
"cwd": "${workspaceFolder}/data",
|
||||||
"visualizerFile": "${workspaceFolder}/scripts/handmade.natvis"
|
"visualizerFile": "${workspaceFolder}/scripts/handmade.natvis"
|
||||||
|
@ -8,16 +8,16 @@
|
|||||||
<ShowEmptyFolders>true</ShowEmptyFolders>
|
<ShowEmptyFolders>true</ShowEmptyFolders>
|
||||||
<IsVirtual>false</IsVirtual>
|
<IsVirtual>false</IsVirtual>
|
||||||
<IsFolder>false</IsFolder>
|
<IsFolder>false</IsFolder>
|
||||||
<BuildCommand>pwsh -ExecutionPolicy Bypass -NoProfile -NonInteractive -File $(WorkspaceDirectory)/scripts/build.ps1 msvc dev optimized</BuildCommand>
|
<BuildCommand>pwsh -ExecutionPolicy Bypass -NoProfile -NonInteractive -File $(WorkspaceDirectory)/scripts/build.ps1 msvc dev debug engine</BuildCommand>
|
||||||
<RebuildCommand></RebuildCommand>
|
<RebuildCommand>pwsh -ExecutionPolicy Bypass -NoProfile -NonInteractive -File $(WorkspaceDirectory)/scripts/build.ps1 msvc dev debug platform</RebuildCommand>
|
||||||
<BuildFileCommand></BuildFileCommand>
|
<BuildFileCommand></BuildFileCommand>
|
||||||
<CleanCommand>pwsh -ExecutionPolicy Bypass -NoProfile -NonInteractive -File $(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)/data/handmade_win32.exe</RunCommand>
|
||||||
<RunCommandWorkingDirectory>$(WorkspaceDirectory)/data</RunCommandWorkingDirectory>
|
<RunCommandWorkingDirectory>$(WorkspaceDirectory)/data</RunCommandWorkingDirectory>
|
||||||
<DebugCommand>$(WorkspaceDirectory)/build/handmade_win32.exe</DebugCommand>
|
<DebugCommand>$(WorkspaceDirectory)/data/handmade_win32.exe</DebugCommand>
|
||||||
<ExePathCommand>$(WorkspaceDirectory)/build/handmade_win32.exe</ExePathCommand>
|
<ExePathCommand>$(WorkspaceDirectory)/data/handmade_win32.exe</ExePathCommand>
|
||||||
<DebugSln></DebugSln>
|
<DebugSln></DebugSln>
|
||||||
<UseVisualStudioEnvBat>true</UseVisualStudioEnvBat>
|
<UseVisualStudioEnvBat>true</UseVisualStudioEnvBat>
|
||||||
<Configurations>
|
<Configurations>
|
||||||
|
@ -17,28 +17,43 @@
|
|||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Development|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Development|x64'">
|
||||||
<IncludePath>$(ProjectDir)project;$(IncludePath)</IncludePath>
|
<IncludePath>$(ProjectDir)project;$(IncludePath)</IncludePath>
|
||||||
<LibraryPath>$(ProjectDir)data;$(windir)System32;$(LibraryPath)</LibraryPath>
|
<LibraryPath>$(ProjectDir)data;$(windir)System32;$(LibraryPath)</LibraryPath>
|
||||||
<NMakeBuildCommandLine>pwsh -ExecutionPolicy Bypass -NoProfile -NonInteractive -File $(ProjectDir)scripts\build.ps1 msvc dev</NMakeBuildCommandLine>
|
<NMakeBuildCommandLine>pwsh -ExecutionPolicy Bypass -NoProfile -NonInteractive -File $(ProjectDir)scripts\build.ps1 msvc dev engine</NMakeBuildCommandLine>
|
||||||
<NMakeCleanCommandLine>pwsh ExecutionPolicy Bypass -NoProfile -NonInteractive -File $(ProjectDir)scripts\clean.ps1</NMakeCleanCommandLine>
|
<NMakeCleanCommandLine>pwsh ExecutionPolicy Bypass -NoProfile -NonInteractive -File $(ProjectDir)scripts\clean.ps1</NMakeCleanCommandLine>
|
||||||
<NMakePreprocessorDefinitions>GEN_TIME;Build_Development;Build_Debug;$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
|
<NMakePreprocessorDefinitions>GEN_TIME;Build_Development;Build_Debug;$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
|
||||||
<ExternalIncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath)</ExternalIncludePath>
|
<ExternalIncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath)</ExternalIncludePath>
|
||||||
|
<NMakeReBuildCommandLine>
|
||||||
|
</NMakeReBuildCommandLine>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="project\engine.h" />
|
<ClInclude Include="project\engine.h" />
|
||||||
|
<ClInclude Include="project\handmade.hpp" />
|
||||||
<ClInclude Include="project\platform\generics.h" />
|
<ClInclude Include="project\platform\generics.h" />
|
||||||
|
<ClInclude Include="project\platform\generics.hpp" />
|
||||||
<ClInclude Include="project\platform\grime.h" />
|
<ClInclude Include="project\platform\grime.h" />
|
||||||
|
<ClInclude Include="project\platform\grime.hpp" />
|
||||||
<ClInclude Include="project\platform\jsl.h" />
|
<ClInclude Include="project\platform\jsl.h" />
|
||||||
|
<ClInclude Include="project\platform\jsl.hpp" />
|
||||||
<ClInclude Include="project\platform\macros.h" />
|
<ClInclude Include="project\platform\macros.h" />
|
||||||
|
<ClInclude Include="project\platform\macros.hpp" />
|
||||||
<ClInclude Include="project\platform\math_constants.h" />
|
<ClInclude Include="project\platform\math_constants.h" />
|
||||||
|
<ClInclude Include="project\platform\math_constants.hpp" />
|
||||||
<ClInclude Include="project\platform\platform.h" />
|
<ClInclude Include="project\platform\platform.h" />
|
||||||
|
<ClInclude Include="project\platform\platform.hpp" />
|
||||||
<ClInclude Include="project\platform\platform_engine_api.h" />
|
<ClInclude Include="project\platform\platform_engine_api.h" />
|
||||||
|
<ClInclude Include="project\platform\platform_engine_api.hpp" />
|
||||||
|
<ClInclude Include="project\platform\platform_game_api.hpp" />
|
||||||
<ClInclude Include="project\platform\types.h" />
|
<ClInclude Include="project\platform\types.h" />
|
||||||
|
<ClInclude Include="project\platform\types.hpp" />
|
||||||
<ClInclude Include="project\platform\win32.h" />
|
<ClInclude Include="project\platform\win32.h" />
|
||||||
|
<ClInclude Include="project\platform\win32.hpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="project\engine.cpp" />
|
<ClCompile Include="project\engine.cpp" />
|
||||||
<ClCompile Include="project\handmade.cpp" />
|
<ClCompile Include="project\handmade.cpp" />
|
||||||
|
<ClCompile Include="project\handmade_engine.cpp" />
|
||||||
<ClCompile Include="project\handmade_win32.cpp" />
|
<ClCompile Include="project\handmade_win32.cpp" />
|
||||||
<ClCompile Include="project\platform\platform_win32.cpp" />
|
<ClCompile Include="project\platform\platform_win32.cpp" />
|
||||||
|
<ClCompile Include="project\platform\win32_platform.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="docs\Day 001.md" />
|
<None Include="docs\Day 001.md" />
|
||||||
|
@ -6,6 +6,6 @@
|
|||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Development|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Development|x64'">
|
||||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)data</LocalDebuggerWorkingDirectory>
|
<LocalDebuggerWorkingDirectory>$(ProjectDir)data</LocalDebuggerWorkingDirectory>
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||||
<LocalDebuggerCommand>$(ProjectDir)build\handmade_win32.exe</LocalDebuggerCommand>
|
<LocalDebuggerCommand>$(ProjectDir)data\handmade_win32.exe</LocalDebuggerCommand>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
15
docs/Day 021.md
Normal file
15
docs/Day 021.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Day 21
|
||||||
|
|
||||||
|
So I learned today the good reason why he doesn't use static variables; So that when he makes this library dynamically loaded we don't lose the state of the game on reload.
|
||||||
|
|
||||||
|
This day was extremely gratifying to get working.
|
||||||
|
|
||||||
|
I went the extra mile than what Casey did and allow for name mangled symbols (for both clang and msvc).
|
||||||
|
It took a few more steps than his solution but I get to keep the eronomics of namespaces.
|
||||||
|
|
||||||
|
After the linker finishes emitting, I use the build script to parse the .map file and extract the decorated symbols I need to load in the platform layer. Those are exported to a file called `handmade_engine.symbols` and then in the platform layer I load them up using an enum as the lookup table for the line the symbol will be in the file. From there its just loading up the symbol with GetProcAddress!
|
||||||
|
|
||||||
|
![img](https://files.catbox.moe/sdebtc.png)
|
||||||
|
![img](https://files.catbox.moe/ufkacl.png)
|
||||||
|
![img](https://files.catbox.moe/zr52au.png)
|
||||||
|
![img](https://files.catbox.moe/g3f1vv.png)
|
@ -1,15 +1,21 @@
|
|||||||
#include "engine.hpp"
|
|
||||||
//#include "win32.h"
|
//#include "win32.h"
|
||||||
|
#include "engine.hpp"
|
||||||
|
#include "platform/platform_engine_api.hpp"
|
||||||
|
#include "handmade.hpp"
|
||||||
|
|
||||||
NS_ENGINE_BEGIN
|
NS_ENGINE_BEGIN
|
||||||
|
|
||||||
struct EngineState
|
struct EngineState
|
||||||
{
|
{
|
||||||
s32 WaveSwitch;
|
|
||||||
s32 WaveToneHz;
|
s32 WaveToneHz;
|
||||||
s32 ToneVolume;
|
s32 ToneVolume;
|
||||||
s32 XOffset;
|
s32 XOffset;
|
||||||
s32 YOffset;
|
s32 YOffset;
|
||||||
|
|
||||||
|
b32 RendererPaused;
|
||||||
|
|
||||||
|
f32 SampleWaveSineTime;
|
||||||
|
b32 SampleWaveSwitch;
|
||||||
};
|
};
|
||||||
|
|
||||||
using GetSoundSampleValueFn = s16( EngineState* state, AudioBuffer* sound_buffer );
|
using GetSoundSampleValueFn = s16( EngineState* state, AudioBuffer* sound_buffer );
|
||||||
@ -28,7 +34,7 @@ square_wave_sample_value( EngineState* state, AudioBuffer* sound_buffer )
|
|||||||
internal s16
|
internal s16
|
||||||
sine_wave_sample_value( EngineState* state, AudioBuffer* sound_buffer )
|
sine_wave_sample_value( EngineState* state, AudioBuffer* sound_buffer )
|
||||||
{
|
{
|
||||||
local_persist f32 time = 0.f;
|
f32& time = state->SampleWaveSineTime;
|
||||||
|
|
||||||
s32 wave_period = sound_buffer->SamplesPerSecond / state->WaveToneHz;
|
s32 wave_period = sound_buffer->SamplesPerSecond / state->WaveToneHz;
|
||||||
|
|
||||||
@ -104,7 +110,6 @@ render_weird_graident(OffscreenBuffer* buffer, u32 x_offset, u32 y_offset )
|
|||||||
u8 red = 0;
|
u8 red = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
*pixel++ = u32(red << 16) | u32(green << 8) | blue;
|
*pixel++ = u32(red << 16) | u32(green << 8) | blue;
|
||||||
}
|
}
|
||||||
wildcard += 0.5375f;
|
wildcard += 0.5375f;
|
||||||
@ -112,66 +117,55 @@ render_weird_graident(OffscreenBuffer* buffer, u32 x_offset, u32 y_offset )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 input_using_analog()
|
Engine_API
|
||||||
|
void on_module_reload( Memory* memory, platform::ModuleAPI* platfom_api )
|
||||||
{
|
{
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void startup()
|
Engine_API
|
||||||
|
void startup( Memory* memory, platform::ModuleAPI* platform_api )
|
||||||
{
|
{
|
||||||
}
|
|
||||||
|
|
||||||
void shutdown()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO : I rather expose the back_buffer and sound_buffer using getters for access in any function.
|
|
||||||
void update_and_render( InputState* input, OffscreenBuffer* back_buffer, Memory* memory )
|
|
||||||
{
|
|
||||||
// Graphics & Input Test
|
|
||||||
local_persist u32 x_offset = 0;
|
|
||||||
local_persist u32 y_offset = 0;
|
|
||||||
|
|
||||||
// Wave Sound Test
|
|
||||||
local_persist bool wave_switch = false;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
if ( input_using_analog() )
|
|
||||||
{
|
|
||||||
// TODO(Ed) : Use analog movement tuning
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// TODO(Ed) : Use digital movement tuning
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
EngineState* state = rcast( EngineState*, memory->Persistent );
|
EngineState* state = rcast( EngineState*, memory->Persistent );
|
||||||
|
assert( sizeof(EngineState) <= memory->PersistentSize );
|
||||||
|
|
||||||
do_once_start
|
state->ToneVolume = 1000;
|
||||||
assert( sizeof(EngineState) <= memory->PersistentSize );
|
|
||||||
|
|
||||||
state->ToneVolume = 1000;
|
state->XOffset = 0;
|
||||||
state->WaveToneHz = 120;
|
state->YOffset = 0;
|
||||||
|
|
||||||
state->XOffset = 0;
|
state->SampleWaveSwitch = false;
|
||||||
state->YOffset = 0;
|
state->WaveToneHz = 120;
|
||||||
state->WaveSwitch = false;
|
state->SampleWaveSineTime = 0.f;
|
||||||
|
|
||||||
#if Build_Debug && 0
|
state->RendererPaused = false;
|
||||||
|
|
||||||
|
#if Build_Debug && 0
|
||||||
|
{
|
||||||
|
using namespace platform;
|
||||||
|
|
||||||
|
char const* file_path = __FILE__;
|
||||||
|
Debug_FileContent file_content = platform_api->debug_file_read_content( file_path );
|
||||||
|
if ( file_content.Size )
|
||||||
{
|
{
|
||||||
using namespace platform;
|
platform_api->debug_file_write_content( "test.out", file_content.Size, file_content.Data );
|
||||||
|
platform_api->debug_file_free_content( & file_content );
|
||||||
char const* file_path = __FILE__;
|
|
||||||
Debug_FileContent file_content = debug_file_read_content( file_path );
|
|
||||||
if ( file_content.Size )
|
|
||||||
{
|
|
||||||
debug_file_write_content( "test.out", file_content.Size, file_content.Data );
|
|
||||||
debug_file_free_content( & file_content );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
}
|
||||||
do_once_end
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Engine_API
|
||||||
|
void shutdown( Memory* memory, platform::ModuleAPI* platform_api )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Engine_API
|
||||||
|
// TODO : I rather expose the back_buffer and sound_buffer using getters for access in any function.
|
||||||
|
void update_and_render( InputState* input, OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI* platform_api )
|
||||||
|
{
|
||||||
|
EngineState* state = rcast( EngineState*, memory->Persistent );
|
||||||
|
assert( sizeof(EngineState) <= memory->PersistentSize );
|
||||||
|
|
||||||
ControllerState* controller = & input->Controllers[0];
|
ControllerState* controller = & input->Controllers[0];
|
||||||
|
|
||||||
@ -195,7 +189,6 @@ void update_and_render( InputState* input, OffscreenBuffer* back_buffer, Memory*
|
|||||||
b32 toggle_wave_tone = false;
|
b32 toggle_wave_tone = false;
|
||||||
|
|
||||||
b32 pause_renderer = false;
|
b32 pause_renderer = false;
|
||||||
local_persist b32 renderer_paused = false;
|
|
||||||
|
|
||||||
f32 analog_threshold = 0.5f;
|
f32 analog_threshold = 0.5f;
|
||||||
|
|
||||||
@ -255,10 +248,10 @@ void update_and_render( InputState* input, OffscreenBuffer* back_buffer, Memory*
|
|||||||
toggle_wave_tone |= pressed( keyboard->Space );
|
toggle_wave_tone |= pressed( keyboard->Space );
|
||||||
}
|
}
|
||||||
|
|
||||||
x_offset += 3 * move_right;
|
state->XOffset += 3 * move_right;
|
||||||
x_offset -= 3 * move_left;
|
state->XOffset -= 3 * move_left;
|
||||||
y_offset += 3 * move_down;
|
state->YOffset += 3 * move_down;
|
||||||
y_offset -= 3 * move_up;
|
state->YOffset -= 3 * move_up;
|
||||||
|
|
||||||
if ( raise_volume )
|
if ( raise_volume )
|
||||||
{
|
{
|
||||||
@ -284,26 +277,27 @@ void update_and_render( InputState* input, OffscreenBuffer* back_buffer, Memory*
|
|||||||
|
|
||||||
if ( toggle_wave_tone )
|
if ( toggle_wave_tone )
|
||||||
{
|
{
|
||||||
state->WaveSwitch ^= true;
|
state->SampleWaveSwitch ^= true;
|
||||||
}
|
}
|
||||||
render_weird_graident( back_buffer, x_offset, y_offset );
|
render_weird_graident( back_buffer, state->XOffset, state->YOffset );
|
||||||
|
|
||||||
if ( pause_renderer )
|
if ( pause_renderer )
|
||||||
{
|
{
|
||||||
if ( renderer_paused )
|
if ( state->RendererPaused )
|
||||||
{
|
{
|
||||||
platform::set_pause_rendering(false);
|
platform_api->debug_set_pause_rendering(false);
|
||||||
renderer_paused = false;
|
state->RendererPaused = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
platform::set_pause_rendering(true);
|
platform_api->debug_set_pause_rendering(true);
|
||||||
renderer_paused = true;
|
state->RendererPaused = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_audio( AudioBuffer* audio_buffer, Memory* memory )
|
Engine_API
|
||||||
|
void update_audio( AudioBuffer* audio_buffer, Memory* memory, platform::ModuleAPI* platform_api )
|
||||||
{
|
{
|
||||||
EngineState* state = rcast( EngineState*, memory->Persistent );
|
EngineState* state = rcast( EngineState*, memory->Persistent );
|
||||||
do_once_start
|
do_once_start
|
||||||
@ -311,11 +305,10 @@ void update_audio( AudioBuffer* audio_buffer, Memory* memory )
|
|||||||
do_once_end
|
do_once_end
|
||||||
|
|
||||||
// TODO(Ed) : Allow sample offsets here for more robust platform options
|
// TODO(Ed) : Allow sample offsets here for more robust platform options
|
||||||
if ( ! state->WaveSwitch )
|
if ( ! state->SampleWaveSwitch )
|
||||||
output_sound( state, audio_buffer, sine_wave_sample_value );
|
output_sound( state, audio_buffer, sine_wave_sample_value );
|
||||||
else
|
else
|
||||||
output_sound( state, audio_buffer, square_wave_sample_value );
|
output_sound( state, audio_buffer, square_wave_sample_value );
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_ENGINE_END
|
NS_ENGINE_END
|
||||||
|
|
@ -197,56 +197,3 @@ void input_mode_pop( InputMode* mode );
|
|||||||
void input_mode_pop( InputMode* mode );
|
void input_mode_pop( InputMode* mode );
|
||||||
|
|
||||||
NS_ENGINE_END
|
NS_ENGINE_END
|
||||||
|
|
||||||
// TODO(Ed) : Move this to handmade game layer later.
|
|
||||||
|
|
||||||
#define NS_HANDMADE_BEGIN namespace handmade {
|
|
||||||
#define NS_HANDMADE_END }
|
|
||||||
|
|
||||||
NS_HANDMADE_BEGIN
|
|
||||||
|
|
||||||
// We want a 'binding' to have multiple binds to active it (most likely)
|
|
||||||
struct Actionable
|
|
||||||
{
|
|
||||||
char const* Name;
|
|
||||||
engine::InputBindCallback* Binds;
|
|
||||||
s32 NumBinds;
|
|
||||||
char _PAD_[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ActionableMode
|
|
||||||
{
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Platform Layer:
|
|
||||||
|
|
||||||
Controller : Keyboard & Mouse, XPad, DSPad
|
|
||||||
|
|
||||||
---VV---
|
|
||||||
|
|
||||||
Engine Layer:
|
|
||||||
|
|
||||||
InputBinding callbacks (per-game-logic frame basis)
|
|
||||||
Push/Pop input modes (binding sets)
|
|
||||||
|
|
||||||
---VV---
|
|
||||||
|
|
||||||
Game Layer:
|
|
||||||
|
|
||||||
Actionables : Binding Sets where a raw input, or input interpretation leads to an player action.
|
|
||||||
ActionSet : Actionables.Push/Pop -> Input.Push/Pop ?
|
|
||||||
Player : Controller, Actionables, ActionSets
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct Player
|
|
||||||
{
|
|
||||||
// So far just has an assigned controller.
|
|
||||||
engine::ControllerState* Controller;
|
|
||||||
|
|
||||||
// Possilby some other stuff in the future.
|
|
||||||
};
|
|
||||||
|
|
||||||
NS_HANDMADE_END
|
|
||||||
|
|
11
project/engine/win32_engine.cpp
Normal file
11
project/engine/win32_engine.cpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include "platform/win32.hpp"
|
||||||
|
#include "engine.hpp"
|
||||||
|
|
||||||
|
b32 WINAPI DllMain(
|
||||||
|
HINSTANCE instance,
|
||||||
|
DWORD reason_for_call,
|
||||||
|
LPVOID reserved
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
@ -4,5 +4,5 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "engine.hpp"
|
#include "engine/engine.hpp"
|
||||||
|
|
||||||
|
67
project/handmade.hpp
Normal file
67
project/handmade.hpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "engine/engine.hpp"
|
||||||
|
|
||||||
|
#define NS_HANDMADE_BEGIN namespace handmade {
|
||||||
|
#define NS_HANDMADE_END }
|
||||||
|
|
||||||
|
NS_HANDMADE_BEGIN
|
||||||
|
|
||||||
|
struct Memory
|
||||||
|
{
|
||||||
|
// Subscection of engine memory for the game to use.
|
||||||
|
|
||||||
|
void* Persistent;
|
||||||
|
u64 PersistentSize;
|
||||||
|
|
||||||
|
// void* Frame;
|
||||||
|
// u64 FrameSize;
|
||||||
|
|
||||||
|
void* Transient;
|
||||||
|
u64 TransientSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
// We want a 'binding' to have multiple binds to active it (most likely)
|
||||||
|
struct Actionable
|
||||||
|
{
|
||||||
|
char const* Name;
|
||||||
|
engine::InputBindCallback* Binds;
|
||||||
|
s32 NumBinds;
|
||||||
|
char _PAD_[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ActionableMode
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Platform Layer:
|
||||||
|
|
||||||
|
Controller : Keyboard & Mouse, XPad, DSPad
|
||||||
|
|
||||||
|
---VV---
|
||||||
|
|
||||||
|
Engine Layer:
|
||||||
|
|
||||||
|
InputBinding callbacks (per-game-logic frame basis)
|
||||||
|
Push/Pop input modes (binding sets)
|
||||||
|
|
||||||
|
---VV---
|
||||||
|
|
||||||
|
Game Layer:
|
||||||
|
|
||||||
|
Actionables : Binding Sets where a raw input, or input interpretation leads to an player action.
|
||||||
|
ActionSet : Actionables.Push/Pop -> Input.Push/Pop ?
|
||||||
|
Player : Controller, Actionables, ActionSets
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct Player
|
||||||
|
{
|
||||||
|
// So far just has an assigned controller.
|
||||||
|
engine::ControllerState* Controller;
|
||||||
|
|
||||||
|
// Possilby some other stuff in the future.
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_HANDMADE_END
|
19
project/handmade_engine.cpp
Normal file
19
project/handmade_engine.cpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#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 "platform/grime.hpp"
|
||||||
|
|
||||||
|
#if Build_Unity
|
||||||
|
# include "engine/engine.cpp"
|
||||||
|
# if SYSTEM_WINDOWS
|
||||||
|
# include "engine/win32_engine.cpp"
|
||||||
|
# endif
|
||||||
|
#endif
|
@ -10,7 +10,5 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if Build_Unity
|
#if Build_Unity
|
||||||
#include "handmade.cpp"
|
|
||||||
#include "engine.cpp"
|
|
||||||
#include "platform/win32_platform.cpp"
|
#include "platform/win32_platform.cpp"
|
||||||
#endif
|
#endif
|
||||||
|
@ -61,6 +61,12 @@
|
|||||||
# define assert( expression )
|
# define assert( expression )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef COMPILER_CLANG
|
||||||
|
# define compiler_decorated_func_name __PRETTY_NAME__
|
||||||
|
#elif defined(COMPILER_MSVC)
|
||||||
|
# define compiler_decorated_func_name __FUNCDNAME__
|
||||||
|
#endif
|
||||||
|
|
||||||
// TODO(Ed) : Add this sauce later
|
// TODO(Ed) : Add this sauce later
|
||||||
#if 0
|
#if 0
|
||||||
#define congrats( message )
|
#define congrats( message )
|
||||||
|
@ -32,7 +32,11 @@
|
|||||||
|
|
||||||
NS_PLATFORM_BEGIN
|
NS_PLATFORM_BEGIN
|
||||||
|
|
||||||
#if Build_Debug
|
// 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)
|
||||||
|
|
||||||
|
#if Build_Development
|
||||||
/*
|
/*
|
||||||
IMPORTANT : These are not for shipping code - they are blocking and the write isn't protected.
|
IMPORTANT : These are not for shipping code - they are blocking and the write isn't protected.
|
||||||
*/
|
*/
|
||||||
@ -44,34 +48,42 @@ struct Debug_FileContent
|
|||||||
char _PAD_[4];
|
char _PAD_[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
void debug_file_free_content ( Debug_FileContent* file_content );
|
using DebugFileFreeContentFn = void ( Debug_FileContent* file_content );
|
||||||
Debug_FileContent debug_file_read_content ( char const* file_path );
|
using DebugFileReadContentFn = Debug_FileContent ( char const* file_path );
|
||||||
b32 debug_file_write_content( char const* file_path, u32 content_size, void* content_memory );
|
using DebugFileWriteContentFn = b32 ( char const* file_path, u32 content_size, void* content_memory );
|
||||||
|
|
||||||
// Allows the engine or game to pause the renderering of any next frames.
|
|
||||||
// ( Prevents blipping of the black buffer )
|
|
||||||
void set_pause_rendering( b32 value );
|
|
||||||
|
|
||||||
|
using DebugSetPauseRenderingFn = void (b32 value);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// 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.
|
// TODO(Ed) : Implement this later when settings UI is setup.
|
||||||
#pragma region Settings Exposure
|
#pragma region Settings Exposure
|
||||||
// Exposing specific properties for user configuration in settings
|
// Exposing specific properties for user configuration in settings
|
||||||
|
|
||||||
// Returns the current monitor refresh rate.
|
// Returns the current monitor refresh rate.
|
||||||
u32 get_monitor_refresh_rate();
|
using GetMonitorRefreshRateFn = u32();
|
||||||
|
|
||||||
// Sets the monitor refresh rate
|
// Sets the monitor refresh rate
|
||||||
// Must be of the compatiable listing for the monitor the window surface is presenting to.
|
// Must be of the compatiable listing for the monitor the window surface is presenting to
|
||||||
void set_monitor_refresh_rate( u32 rate_in_hz );
|
using SetMonitorRefreshRateFn = void ( u32 rate_in_hz );
|
||||||
|
|
||||||
u32 get_engine_frame_target();
|
using GetEngineFrameTargetFn = u32 ();
|
||||||
|
using SetEngineFrameTargetFn = void ( u32 rate_in_hz );
|
||||||
|
|
||||||
void set_engine_frame_target( u32 rate_in_hz );
|
struct ModuleAPI
|
||||||
|
{
|
||||||
|
#if Build_Development
|
||||||
|
DebugFileFreeContentFn* debug_file_free_content;
|
||||||
|
DebugFileReadContentFn* debug_file_read_content;
|
||||||
|
DebugFileWriteContentFn* debug_file_write_content;
|
||||||
|
|
||||||
|
DebugSetPauseRenderingFn* debug_set_pause_rendering;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
GetMonitorRefreshRateFn* get_monitor_refresh_rate;
|
||||||
|
SetMonitorRefreshRateFn* set_monitor_refresh_rate;
|
||||||
|
|
||||||
|
GetEngineFrameTargetFn* get_engine_frame_target;
|
||||||
|
SetEngineFrameTargetFn* set_engine_frame_target;
|
||||||
|
};
|
||||||
|
|
||||||
#pragma endregion Settings Exposure
|
#pragma endregion Settings Exposure
|
||||||
|
|
||||||
|
@ -2,20 +2,47 @@
|
|||||||
This represents the API only accessible to the platform layer to fullfill for the engine layer.
|
This represents the API only accessible to the platform layer to fullfill for the engine layer.
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "engine.hpp"
|
#include "engine/engine.hpp"
|
||||||
|
|
||||||
|
#ifndef Engine_API
|
||||||
|
# define Engine_API
|
||||||
|
#endif
|
||||||
|
|
||||||
NS_ENGINE_BEGIN
|
NS_ENGINE_BEGIN
|
||||||
|
|
||||||
void startup();
|
using OnModuleRelaodFn = void( Memory* memory, platform::ModuleAPI* platform_api );
|
||||||
void shutdown();
|
using StartupFn = void( Memory* memory, platform::ModuleAPI* platform_api );
|
||||||
|
using ShutdownFn = void( Memory* memory, platform::ModuleAPI* platform_api );
|
||||||
|
|
||||||
// Needs a contextual reference to four things:
|
// Needs a contextual reference to four things:
|
||||||
// Timing, Input, Bitmap Buffer
|
// Timing, Input, Bitmap Buffer
|
||||||
void update_and_render( InputState* input, OffscreenBuffer* back_buffer, Memory* memory );
|
using UpdateAndRenderFn = void ( InputState* input, OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI* platform_api );
|
||||||
|
|
||||||
// Audio timing is complicated, processing samples must be done at a different period from the rest of the engine's usual update.
|
// Audio timing is complicated, processing samples must be done at a different period from the rest of the engine's usual update.
|
||||||
// IMPORTANT: This has very tight timing, and cannot be more than a millisecond in execution.
|
// IMPORTANT: This has very tight timing, and cannot be more than a millisecond in execution.
|
||||||
// TODO(Ed) : Reduce timing pressure on performance by measuring it or pinging its time.
|
// TODO(Ed) : Reduce timing pressure on performance by measuring it or pinging its time.
|
||||||
void update_audio( AudioBuffer* audio_buffer, Memory* memory );
|
using UpdateAudioFn = void ( AudioBuffer* audio_buffer, Memory* memory, platform::ModuleAPI* platform_api );
|
||||||
|
|
||||||
|
struct ModuleAPI
|
||||||
|
{
|
||||||
|
enum : u32
|
||||||
|
{
|
||||||
|
Sym_OnModuleReload,
|
||||||
|
Sym_Startup,
|
||||||
|
Sym_Shutdown,
|
||||||
|
Sym_UpdateAndRender,
|
||||||
|
Sym_UpdateAudio,
|
||||||
|
};
|
||||||
|
|
||||||
|
OnModuleRelaodFn* on_module_reload;
|
||||||
|
StartupFn* startup;
|
||||||
|
ShutdownFn* shutdown;
|
||||||
|
|
||||||
|
UpdateAndRenderFn* update_and_render;
|
||||||
|
UpdateAudioFn* update_audio;
|
||||||
|
|
||||||
|
b32 IsValid;
|
||||||
|
char _PAD_[4];
|
||||||
|
};
|
||||||
|
|
||||||
NS_ENGINE_END
|
NS_ENGINE_END
|
||||||
|
3
project/platform/platform_game_api.hpp
Normal file
3
project/platform/platform_game_api.hpp
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/*
|
||||||
|
This represents the API only accessible to the platform layer to fullfill for the game layer.
|
||||||
|
*/
|
@ -113,6 +113,14 @@ enum XI_State : DWORD
|
|||||||
XI_PluggedIn = ERROR_SUCCESS,
|
XI_PluggedIn = ERROR_SUCCESS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template< typename ProcSignature >
|
||||||
|
ProcSignature* get_procedure_from_library( HMODULE library_module, char const* symbol )
|
||||||
|
{
|
||||||
|
void* address = rcast( void*, GetProcAddress( library_module, symbol ) );
|
||||||
|
return rcast( ProcSignature*, address );
|
||||||
|
}
|
||||||
|
|
||||||
#pragma region XInput
|
#pragma region XInput
|
||||||
WIN_LIB_API DWORD WINAPI XInputGetState
|
WIN_LIB_API DWORD WINAPI XInputGetState
|
||||||
(
|
(
|
||||||
@ -151,11 +159,14 @@ xinput_load_library_bindings()
|
|||||||
{
|
{
|
||||||
HMODULE xinput_lib = LoadLibraryA( XINPUT_DLL_A );
|
HMODULE xinput_lib = LoadLibraryA( XINPUT_DLL_A );
|
||||||
|
|
||||||
#pragma warning( push )
|
XInputGetStateFn* get_state = get_procedure_from_library< XInputGetStateFn >( xinput_lib, "XInputGetState" );
|
||||||
#pragma warning( disable: 4191 )
|
XInputSetStateFn* set_state = get_procedure_from_library< XInputSetStateFn >( xinput_lib, "XInputSetState" );
|
||||||
xinput_get_state = rcast( XInputGetStateFn*, GetProcAddress( xinput_lib, "XInputGetState" ));
|
|
||||||
xinput_set_state = rcast( XInputSetStateFn*, GetProcAddress( xinput_lib, "XInputSetState" ));
|
if ( get_state )
|
||||||
#pragma warning( pop )
|
xinput_get_state = get_state;
|
||||||
|
|
||||||
|
if ( set_state )
|
||||||
|
xinput_set_state = set_state;
|
||||||
}
|
}
|
||||||
#pragma endregion XInput
|
#pragma endregion XInput
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
#include "win32.hpp"
|
#include "win32.hpp"
|
||||||
|
|
||||||
// Engine layer headers
|
// Engine layer headers
|
||||||
#include "engine.hpp"
|
#include "engine/engine.hpp"
|
||||||
#include "platform_engine_api.hpp"
|
#include "platform_engine_api.hpp"
|
||||||
|
|
||||||
// Standard-Library stand-ins
|
// Standard-Library stand-ins
|
||||||
@ -216,7 +216,7 @@ b32 debug_file_write_content( char const* file_path, u32 content_size, void* con
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_pause_rendering( b32 value )
|
void debug_set_pause_rendering( b32 value )
|
||||||
{
|
{
|
||||||
Pause_Rendering = value;
|
Pause_Rendering = value;
|
||||||
}
|
}
|
||||||
@ -425,15 +425,12 @@ init_sound(HWND window_handle, DirectSoundBuffer* sound_buffer )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get direct sound object
|
// Get direct sound object
|
||||||
#pragma warning( push )
|
direct_sound_create = get_procedure_from_library< DirectSoundCreateFn >( sound_library, "DirectSoundCreate" );
|
||||||
#pragma warning( disable: 4191 )
|
|
||||||
direct_sound_create = rcast( DirectSoundCreateFn*, GetProcAddress( sound_library, "DirectSoundCreate" ));
|
|
||||||
if ( ! ensure( direct_sound_create, "Failed to get direct_sound_create_procedure" ) )
|
if ( ! ensure( direct_sound_create, "Failed to get direct_sound_create_procedure" ) )
|
||||||
{
|
{
|
||||||
// TOOD : Diagnostic
|
// TOOD : Diagnostic
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#pragma warning( pop )
|
|
||||||
|
|
||||||
LPDIRECTSOUND direct_sound;
|
LPDIRECTSOUND direct_sound;
|
||||||
if ( ! SUCCEEDED(direct_sound_create( 0, & direct_sound, 0 )) )
|
if ( ! SUCCEEDED(direct_sound_create( 0, & direct_sound, 0 )) )
|
||||||
@ -751,6 +748,131 @@ process_pending_window_messages( engine::KeyboardState* keyboard )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma region Platfom API
|
||||||
|
u32 get_monitor_refresh_rate();
|
||||||
|
|
||||||
|
#pragma endregion Platform API
|
||||||
|
|
||||||
|
// TODO(Ed): This also assumes the symbol name is always within size of the provided buffer, needs to fail if not.
|
||||||
|
void get_symbol_from_module_table( Debug_FileContent symbol_table, u32 symbol_ID, char* symbol_name )
|
||||||
|
{
|
||||||
|
struct Token
|
||||||
|
{
|
||||||
|
char const* Ptr;
|
||||||
|
u32 Len;
|
||||||
|
char _PAD_[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
Token tokens[256] = {};
|
||||||
|
s32 idx = 0;
|
||||||
|
|
||||||
|
char const* scanner = rcast( char const*, symbol_table.Data );
|
||||||
|
u32 left = symbol_table.Size;
|
||||||
|
while ( left )
|
||||||
|
{
|
||||||
|
if ( *scanner == '\n' || *scanner == '\r' )
|
||||||
|
{
|
||||||
|
++ scanner;
|
||||||
|
-- left;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tokens[idx].Ptr = scanner;
|
||||||
|
while ( left && *scanner != '\r' && *scanner != '\n' )
|
||||||
|
{
|
||||||
|
-- left;
|
||||||
|
++ scanner;
|
||||||
|
++ tokens[idx].Len;
|
||||||
|
}
|
||||||
|
++ idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Token& token = tokens[symbol_ID];
|
||||||
|
while ( token.Len -- )
|
||||||
|
{
|
||||||
|
*symbol_name = *token.Ptr;
|
||||||
|
++ symbol_name;
|
||||||
|
++ token.Ptr;
|
||||||
|
}
|
||||||
|
*symbol_name = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right now they are just the data directory
|
||||||
|
#define Path_To_Symbol_Tables
|
||||||
|
|
||||||
|
global HMODULE Lib_Handmade_Engine = nullptr;
|
||||||
|
|
||||||
|
engine::ModuleAPI load_engine_module_api()
|
||||||
|
{
|
||||||
|
using ModuleAPI = engine::ModuleAPI;
|
||||||
|
|
||||||
|
// TODO(Ed) : Need proper paything to the dll (not assume is in the base directory).
|
||||||
|
|
||||||
|
CopyFileA( "handmade_engine.dll", "handmade_engine_temp.dll", FALSE );
|
||||||
|
|
||||||
|
// Engine
|
||||||
|
Lib_Handmade_Engine = LoadLibraryA( "handmade_engine_temp.dll" );
|
||||||
|
if ( ! Lib_Handmade_Engine )
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr char const*
|
||||||
|
handmade_engine_symbols = Path_To_Symbol_Tables "handmade_engine.symbols";
|
||||||
|
|
||||||
|
Debug_FileContent symbol_table = debug_file_read_content( handmade_engine_symbols );
|
||||||
|
if ( symbol_table.Size == 0 )
|
||||||
|
{
|
||||||
|
fatal( "Failed to laod symbol table for handmade engine module!" );
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(Ed) : Clean this up later when Casey makes strings. (If he doesn't we'll do it)
|
||||||
|
char symbol_on_module_reload[256];
|
||||||
|
char symboL_startup[256];
|
||||||
|
char symboL_shutdown[256];
|
||||||
|
char symboL_update_and_render[256];
|
||||||
|
char symbol_update_audio[256];
|
||||||
|
get_symbol_from_module_table( symbol_table, ModuleAPI::Sym_OnModuleReload, symbol_on_module_reload );
|
||||||
|
get_symbol_from_module_table( symbol_table, ModuleAPI::Sym_Startup, symboL_startup );
|
||||||
|
get_symbol_from_module_table( symbol_table, ModuleAPI::Sym_Shutdown, symboL_shutdown );
|
||||||
|
get_symbol_from_module_table( symbol_table, ModuleAPI::Sym_UpdateAndRender, symboL_update_and_render );
|
||||||
|
get_symbol_from_module_table( symbol_table, ModuleAPI::Sym_UpdateAudio, symbol_update_audio );
|
||||||
|
|
||||||
|
debug_file_free_content( & symbol_table );
|
||||||
|
|
||||||
|
engine::ModuleAPI engine_api {};
|
||||||
|
engine_api.on_module_reload = get_procedure_from_library< engine::OnModuleRelaodFn > ( Lib_Handmade_Engine, symbol_on_module_reload );
|
||||||
|
engine_api.startup = get_procedure_from_library< engine::StartupFn > ( Lib_Handmade_Engine, symboL_startup );
|
||||||
|
engine_api.shutdown = get_procedure_from_library< engine::ShutdownFn > ( Lib_Handmade_Engine, symboL_shutdown );
|
||||||
|
engine_api.update_and_render = get_procedure_from_library< engine::UpdateAndRenderFn >( Lib_Handmade_Engine, symboL_update_and_render );
|
||||||
|
engine_api.update_audio = get_procedure_from_library< engine::UpdateAudioFn > ( Lib_Handmade_Engine, symbol_update_audio );
|
||||||
|
|
||||||
|
engine_api.IsValid =
|
||||||
|
engine_api.on_module_reload
|
||||||
|
&& engine_api.startup
|
||||||
|
&& engine_api.shutdown
|
||||||
|
&& engine_api.update_and_render
|
||||||
|
&& engine_api.update_audio;
|
||||||
|
if ( engine_api.IsValid )
|
||||||
|
{
|
||||||
|
OutputDebugStringA( "Loaded engine module API\n" );
|
||||||
|
}
|
||||||
|
return engine_api;
|
||||||
|
}
|
||||||
|
|
||||||
|
void unload_engine_module_api( engine::ModuleAPI* engine_api )
|
||||||
|
{
|
||||||
|
if ( engine_api->IsValid )
|
||||||
|
{
|
||||||
|
FreeLibrary( Lib_Handmade_Engine );
|
||||||
|
*engine_api = {};
|
||||||
|
OutputDebugStringA( "Unloaded engine module API\n" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NS_PLATFORM_END
|
NS_PLATFORM_END
|
||||||
|
|
||||||
int CALLBACK
|
int CALLBACK
|
||||||
@ -774,6 +896,22 @@ WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR commandline, int sho
|
|||||||
|
|
||||||
QueryPerformanceFrequency( rcast(LARGE_INTEGER*, & Performance_Counter_Frequency) );
|
QueryPerformanceFrequency( rcast(LARGE_INTEGER*, & Performance_Counter_Frequency) );
|
||||||
|
|
||||||
|
// Prepare platform API
|
||||||
|
ModuleAPI platform_api {};
|
||||||
|
{
|
||||||
|
#if Build_Development
|
||||||
|
platform_api.debug_file_free_content = & debug_file_free_content;
|
||||||
|
platform_api.debug_file_read_content = & debug_file_read_content;
|
||||||
|
platform_api.debug_file_write_content = & debug_file_write_content;
|
||||||
|
|
||||||
|
platform_api.debug_set_pause_rendering = & debug_set_pause_rendering;
|
||||||
|
#endif
|
||||||
|
platform_api.get_monitor_refresh_rate = nullptr;
|
||||||
|
platform_api.set_monitor_refresh_rate = nullptr;
|
||||||
|
platform_api.get_engine_frame_target = nullptr;
|
||||||
|
platform_api.set_engine_frame_target = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// Memory
|
// Memory
|
||||||
engine::Memory engine_memory {};
|
engine::Memory engine_memory {};
|
||||||
{
|
{
|
||||||
@ -802,6 +940,9 @@ WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR commandline, int sho
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load engine module
|
||||||
|
engine::ModuleAPI engine_api = load_engine_module_api();
|
||||||
|
|
||||||
WNDCLASSW window_class {};
|
WNDCLASSW window_class {};
|
||||||
HWND window_handle = nullptr;
|
HWND window_handle = nullptr;
|
||||||
{
|
{
|
||||||
@ -935,6 +1076,8 @@ WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR commandline, int sho
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
engine_api.startup( & engine_memory, & platform_api );
|
||||||
|
|
||||||
u64 last_frame_clock = timing_get_wall_clock();
|
u64 last_frame_clock = timing_get_wall_clock();
|
||||||
u64 last_frame_cycle = __rdtsc();
|
u64 last_frame_cycle = __rdtsc();
|
||||||
u64 flip_wall_clock = last_frame_clock;
|
u64 flip_wall_clock = last_frame_clock;
|
||||||
@ -942,8 +1085,14 @@ WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR commandline, int sho
|
|||||||
#if Build_Development
|
#if Build_Development
|
||||||
u64 startup_cycles = last_frame_cycle - launch_cycle;
|
u64 startup_cycles = last_frame_cycle - launch_cycle;
|
||||||
f32 startup_ms = timing_get_ms_elapsed( launch_clock, last_frame_clock );
|
f32 startup_ms = timing_get_ms_elapsed( launch_clock, last_frame_clock );
|
||||||
|
|
||||||
|
char text_buffer[256];
|
||||||
|
sprintf_s( text_buffer, sizeof(text_buffer), "Startup MS: %f\n", startup_ms );
|
||||||
|
OutputDebugStringA( text_buffer );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
u64 module_reload_counter = 0;
|
||||||
|
|
||||||
Running = true;
|
Running = true;
|
||||||
#if 0
|
#if 0
|
||||||
// This tests the play & write cursor update frequency.
|
// This tests the play & write cursor update frequency.
|
||||||
@ -960,6 +1109,14 @@ WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR commandline, int sho
|
|||||||
#endif
|
#endif
|
||||||
while( Running )
|
while( Running )
|
||||||
{
|
{
|
||||||
|
if ( module_reload_counter > 120 )
|
||||||
|
{
|
||||||
|
unload_engine_module_api( & engine_api );
|
||||||
|
engine_api = load_engine_module_api();
|
||||||
|
module_reload_counter = 0;
|
||||||
|
}
|
||||||
|
++ module_reload_counter;
|
||||||
|
|
||||||
process_pending_window_messages( new_keyboard );
|
process_pending_window_messages( new_keyboard );
|
||||||
|
|
||||||
// TODO(Ed): Offload polling to these functions later.
|
// TODO(Ed): Offload polling to these functions later.
|
||||||
@ -1107,7 +1264,7 @@ WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR commandline, int sho
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Engine's logical iteration and rendering process
|
// Engine's logical iteration and rendering process
|
||||||
engine::update_and_render( & input, rcast(engine::OffscreenBuffer*, & Surface_Back_Buffer.Memory), & engine_memory );
|
engine_api.update_and_render( & input, rcast(engine::OffscreenBuffer*, & Surface_Back_Buffer.Memory), & engine_memory, & platform_api );
|
||||||
|
|
||||||
u64 audio_frame_start = timing_get_wall_clock();
|
u64 audio_frame_start = timing_get_wall_clock();
|
||||||
f32 flip_to_audio_ms = timing_get_ms_elapsed( flip_wall_clock, audio_frame_start );
|
f32 flip_to_audio_ms = timing_get_ms_elapsed( flip_wall_clock, audio_frame_start );
|
||||||
@ -1194,7 +1351,7 @@ WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR commandline, int sho
|
|||||||
sound_buffer.RunningSampleIndex = ds_sound_buffer.RunningSampleIndex;
|
sound_buffer.RunningSampleIndex = ds_sound_buffer.RunningSampleIndex;
|
||||||
sound_buffer.SamplesPerSecond = ds_sound_buffer.SamplesPerSecond;
|
sound_buffer.SamplesPerSecond = ds_sound_buffer.SamplesPerSecond;
|
||||||
sound_buffer.Samples = ds_sound_buffer.Samples;
|
sound_buffer.Samples = ds_sound_buffer.Samples;
|
||||||
engine::update_audio( & sound_buffer, & engine_memory );
|
engine_api.update_audio( & sound_buffer, & engine_memory, & platform_api );
|
||||||
|
|
||||||
DebugTimeMarker* marker = & debug_markers[ debug_marker_index ];
|
DebugTimeMarker* marker = & debug_markers[ debug_marker_index ];
|
||||||
marker->OutputPlayCusror = ds_play_cursor;
|
marker->OutputPlayCusror = ds_play_cursor;
|
||||||
@ -1331,7 +1488,7 @@ WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR commandline, int sho
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
engine::shutdown();
|
engine_api.shutdown( & engine_memory, & platform_api );
|
||||||
|
|
||||||
if ( jsl_num_devices > 0 )
|
if ( jsl_num_devices > 0 )
|
||||||
{
|
{
|
||||||
|
@ -14,6 +14,9 @@ Push-Location $path_root
|
|||||||
$debug = $null
|
$debug = $null
|
||||||
$analysis = $false
|
$analysis = $false
|
||||||
$dev = $false
|
$dev = $false
|
||||||
|
$platform = $null
|
||||||
|
$engine = $null
|
||||||
|
$game = $null
|
||||||
|
|
||||||
[array] $vendors = @( "clang", "msvc" )
|
[array] $vendors = @( "clang", "msvc" )
|
||||||
|
|
||||||
@ -26,11 +29,14 @@ if ( $args ) { $args | ForEach-Object {
|
|||||||
"debug" { $debug = $true }
|
"debug" { $debug = $true }
|
||||||
"analysis" { $analysis = $true }
|
"analysis" { $analysis = $true }
|
||||||
"dev" { $dev = $true }
|
"dev" { $dev = $true }
|
||||||
|
"platform" { $platform = $true }
|
||||||
|
"engine" { $engine = $true }
|
||||||
|
"game" { $game = $true }
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
#endregion Argument
|
#endregion Argument
|
||||||
|
|
||||||
#region Configuration
|
#region Toolchain Configuration
|
||||||
if ($IsWindows) {
|
if ($IsWindows) {
|
||||||
# This HandmadeHero implementation is only designed for 64-bit systems
|
# This HandmadeHero implementation is only designed for 64-bit systems
|
||||||
& $devshell -arch amd64
|
& $devshell -arch amd64
|
||||||
@ -45,7 +51,7 @@ write-host "Building HandmadeHero with $vendor"
|
|||||||
|
|
||||||
if ( $dev ) {
|
if ( $dev ) {
|
||||||
if ( $debug -eq $null ) {
|
if ( $debug -eq $null ) {
|
||||||
$debug = $true
|
# $debug = $true
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $optimize -eq $null ) {
|
if ( $optimize -eq $null ) {
|
||||||
@ -118,42 +124,52 @@ function run-linker
|
|||||||
if ( $vendor -match "clang" )
|
if ( $vendor -match "clang" )
|
||||||
{
|
{
|
||||||
# https://clang.llvm.org/docs/ClangCommandLineReference.html
|
# https://clang.llvm.org/docs/ClangCommandLineReference.html
|
||||||
$flag_all_c = '/TC'
|
$flag_all_c = '/TC'
|
||||||
$flag_all_cpp = '/TP'
|
$flag_all_cpp = '/TP'
|
||||||
$flag_compile = '-c'
|
$flag_compile = '-c'
|
||||||
$flag_color_diagnostics = '-fcolor-diagnostics'
|
$flag_color_diagnostics = '-fcolor-diagnostics'
|
||||||
$flag_no_color_diagnostics = '-fno-color-diagnostics'
|
$flag_no_color_diagnostics = '-fno-color-diagnostics'
|
||||||
$flag_debug = '-g'
|
$flag_debug = '-g'
|
||||||
$flag_debug_codeview = '-gcodeview'
|
$flag_debug_codeview = '-gcodeview'
|
||||||
$flag_define = '-D'
|
$flag_define = '-D'
|
||||||
$flag_exceptions_disabled = '-fno-exceptions'
|
$flag_exceptions_disabled = '-fno-exceptions'
|
||||||
$flag_preprocess = '-E'
|
$flag_preprocess = '-E'
|
||||||
$flag_include = '-I'
|
$flag_include = '-I'
|
||||||
$flag_library = '-l'
|
$flag_section_data = '-fdata-sections'
|
||||||
$flag_library_path = '-L'
|
$flag_section_functions = '-ffunction-sections'
|
||||||
$flag_linker = '-Wl,'
|
$flag_library = '-l'
|
||||||
$flag_link_mapfile = '-Map'
|
$flag_library_path = '-L'
|
||||||
$flag_link_win_subsystem_console = '/SUBSYSTEM:CONSOLE'
|
$flag_linker = '-Wl,'
|
||||||
$flag_link_win_subsystem_windows = '/SUBSYSTEM:WINDOWS'
|
if ( $IsWindows ) {
|
||||||
$flag_link_win_machine_32 = '/MACHINE:X86'
|
$flag_link_dll = '/DLL'
|
||||||
$flag_link_win_machine_64 = '/MACHINE:X64'
|
$flag_link_mapfile = '/MAP:'
|
||||||
$flag_link_win_debug = '/DEBUG'
|
$flag_link_optimize_references = '/OPT:REF'
|
||||||
$flag_link_win_pdb = '/PDB:'
|
}
|
||||||
$flag_link_win_path_output = '/OUT:'
|
if ( $IsLinux ) {
|
||||||
$flag_no_optimization = '-O0'
|
$flag_link_mapfile = '--Map='
|
||||||
$flag_optimize_fast = '-O2'
|
$flag_link_optimize_references = '--gc-sections'
|
||||||
$flag_optimize_size = '-O1'
|
}
|
||||||
$flag_optimize_intrinsics = '-Oi'
|
$flag_link_win_subsystem_console = '/SUBSYSTEM:CONSOLE'
|
||||||
$flag_path_output = '-o'
|
$flag_link_win_subsystem_windows = '/SUBSYSTEM:WINDOWS'
|
||||||
$flag_preprocess_non_intergrated = '-no-integrated-cpp'
|
$flag_link_win_machine_32 = '/MACHINE:X86'
|
||||||
$flag_profiling_debug = '-fdebug-info-for-profiling'
|
$flag_link_win_machine_64 = '/MACHINE:X64'
|
||||||
$flag_set_stack_size = '-stack='
|
$flag_link_win_debug = '/DEBUG'
|
||||||
$flag_syntax_only = '-fsyntax-only'
|
$flag_link_win_pdb = '/PDB:'
|
||||||
$flag_target_arch = '-target'
|
$flag_link_win_path_output = '/OUT:'
|
||||||
$flag_wall = '-Wall'
|
$flag_no_optimization = '-O0'
|
||||||
$flag_warning = '-W'
|
$flag_optimize_fast = '-O2'
|
||||||
$flag_warnings_as_errors = '-Werror'
|
$flag_optimize_size = '-O1'
|
||||||
$flag_win_nologo = '/nologo'
|
$flag_optimize_intrinsics = '-Oi'
|
||||||
|
$flag_path_output = '-o'
|
||||||
|
$flag_preprocess_non_intergrated = '-no-integrated-cpp'
|
||||||
|
$flag_profiling_debug = '-fdebug-info-for-profiling'
|
||||||
|
$flag_set_stack_size = '-stack='
|
||||||
|
$flag_syntax_only = '-fsyntax-only'
|
||||||
|
$flag_target_arch = '-target'
|
||||||
|
$flag_wall = '-Wall'
|
||||||
|
$flag_warning = '-W'
|
||||||
|
$flag_warnings_as_errors = '-Werror'
|
||||||
|
$flag_win_nologo = '/nologo'
|
||||||
|
|
||||||
$ignore_warning_ms_include = 'no-microsoft-include'
|
$ignore_warning_ms_include = 'no-microsoft-include'
|
||||||
$ignore_warning_return_type_c_linkage = 'no-return-type-c-linkage'
|
$ignore_warning_return_type_c_linkage = 'no-return-type-c-linkage'
|
||||||
@ -175,12 +191,12 @@ if ( $vendor -match "clang" )
|
|||||||
|
|
||||||
function build-simple
|
function build-simple
|
||||||
{
|
{
|
||||||
param( [array]$includes, [array]$compiler_args, [array]$linker_args, [string]$unit, [string]$executable )
|
param( [array]$includes, [array]$compiler_args, [array]$linker_args, [string]$unit, [string]$binary )
|
||||||
Write-Host "build-simple: clang"
|
Write-Host "build-simple: clang"
|
||||||
|
|
||||||
$object = $executable -replace '\.exe', '.obj'
|
$object = $binary -replace '\.exe', '.obj'
|
||||||
$pdb = $executable -replace '\.exe', '.pdb'
|
$pdb = $binary -replace '\.exe', '.pdb'
|
||||||
$map = $executable -replace '\.exe', '.map'
|
$map = $binary -replace '\.exe', '.map'
|
||||||
|
|
||||||
$compiler_args += @(
|
$compiler_args += @(
|
||||||
$flag_no_color_diagnostics,
|
$flag_no_color_diagnostics,
|
||||||
@ -188,6 +204,8 @@ if ( $vendor -match "clang" )
|
|||||||
$flag_target_arch, $target_arch,
|
$flag_target_arch, $target_arch,
|
||||||
$flag_wall,
|
$flag_wall,
|
||||||
$flag_preprocess_non_intergrated,
|
$flag_preprocess_non_intergrated,
|
||||||
|
$flag_section_data,
|
||||||
|
$flag_section_functions,
|
||||||
( $flag_path_output + $object )
|
( $flag_path_output + $object )
|
||||||
)
|
)
|
||||||
if ( $optimized ) {
|
if ( $optimized ) {
|
||||||
@ -214,12 +232,12 @@ if ( $vendor -match "clang" )
|
|||||||
|
|
||||||
$linker_args += @(
|
$linker_args += @(
|
||||||
$flag_link_win_machine_64,
|
$flag_link_win_machine_64,
|
||||||
$( $flag_link_win_path_output + $executable )
|
$( $flag_link_win_path_output + $binary )
|
||||||
)
|
)
|
||||||
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 {
|
||||||
@ -227,7 +245,7 @@ if ( $vendor -match "clang" )
|
|||||||
}
|
}
|
||||||
|
|
||||||
$linker_args += $object
|
$linker_args += $object
|
||||||
run-linker $linker $executable $linker_args
|
run-linker $linker $binary $linker_args
|
||||||
|
|
||||||
# $compiler_args += $unit
|
# $compiler_args += $unit
|
||||||
# $linker_args | ForEach-Object {
|
# $linker_args | ForEach-Object {
|
||||||
@ -256,6 +274,7 @@ if ( $vendor -match "msvc" )
|
|||||||
$flag_dll = '/LD'
|
$flag_dll = '/LD'
|
||||||
$flag_dll_debug = '/LDd'
|
$flag_dll_debug = '/LDd'
|
||||||
$flag_linker = '/link'
|
$flag_linker = '/link'
|
||||||
|
$flag_link_dll = '/DLL'
|
||||||
$flag_link_mapfile = '/MAP:'
|
$flag_link_mapfile = '/MAP:'
|
||||||
$flag_link_optimize_references = '/OPT:REF'
|
$flag_link_optimize_references = '/OPT:REF'
|
||||||
$flag_link_win_debug = '/DEBUG'
|
$flag_link_win_debug = '/DEBUG'
|
||||||
@ -287,12 +306,12 @@ if ( $vendor -match "msvc" )
|
|||||||
# This works because this project uses a single unit to build
|
# This works because this project uses a single unit to build
|
||||||
function build-simple
|
function build-simple
|
||||||
{
|
{
|
||||||
param( [array]$includes, [array]$compiler_args, [array]$linker_args, [string]$unit, [string]$executable )
|
param( [array]$includes, [array]$compiler_args, [array]$linker_args, [string]$unit, [string]$binary )
|
||||||
Write-Host "build-simple: msvc"
|
Write-Host "build-simple: msvc"
|
||||||
|
|
||||||
$object = $executable -replace '\.exe', '.obj'
|
$object = $binary -replace '\.(exe|dll)$', '.obj'
|
||||||
$pdb = $executable -replace '\.exe', '.pdb'
|
$pdb = $binary -replace '\.(exe|dll)$', '.pdb'
|
||||||
$map = $executable -replace '\.exe', '.map'
|
$map = $binary -replace '\.(exe|dll)$', '.map'
|
||||||
|
|
||||||
$compiler_args += @(
|
$compiler_args += @(
|
||||||
$flag_nologo,
|
$flag_nologo,
|
||||||
@ -336,18 +355,18 @@ if ( $vendor -match "msvc" )
|
|||||||
$linker_args += @(
|
$linker_args += @(
|
||||||
$flag_nologo,
|
$flag_nologo,
|
||||||
$flag_link_win_machine_64,
|
$flag_link_win_machine_64,
|
||||||
( $flag_link_win_path_output + $executable )
|
( $flag_link_win_path_output + $binary )
|
||||||
)
|
)
|
||||||
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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
$linker_args += $object
|
$linker_args += $object
|
||||||
run-linker $linker $executable $linker_args
|
run-linker $linker $binary $linker_args
|
||||||
|
|
||||||
# $compiler_args += $unit
|
# $compiler_args += $unit
|
||||||
# $compiler_args += $flag_linker
|
# $compiler_args += $flag_linker
|
||||||
@ -360,11 +379,14 @@ if ( $vendor -match "msvc" )
|
|||||||
}
|
}
|
||||||
#endregion Configuration
|
#endregion Configuration
|
||||||
|
|
||||||
|
#region Building
|
||||||
$path_project = Join-Path $path_root 'project'
|
$path_project = Join-Path $path_root 'project'
|
||||||
$path_build = Join-Path $path_root 'build'
|
$path_build = Join-Path $path_root 'build'
|
||||||
|
$path_data = Join-Path $path_root 'data'
|
||||||
$path_deps = Join-Path $path_project 'dependencies'
|
$path_deps = Join-Path $path_project 'dependencies'
|
||||||
$path_gen = Join-Path $path_project 'gen'
|
$path_gen = Join-Path $path_project 'gen'
|
||||||
$path_platform = Join-Path $path_project 'platform'
|
$path_platform = Join-Path $path_project 'platform'
|
||||||
|
$path_engine = Join-Path $path_project 'engine'
|
||||||
|
|
||||||
$update_deps = Join-Path $PSScriptRoot 'update_deps.ps1'
|
$update_deps = Join-Path $PSScriptRoot 'update_deps.ps1'
|
||||||
|
|
||||||
@ -376,21 +398,21 @@ if ( (Test-Path $path_deps) -eq $false ) {
|
|||||||
& $update_deps
|
& $update_deps
|
||||||
}
|
}
|
||||||
|
|
||||||
$includes = @(
|
|
||||||
$path_project,
|
|
||||||
$path_gen,
|
|
||||||
# $path_deps,
|
|
||||||
$path_platform
|
|
||||||
)
|
|
||||||
$compiler_args = @()
|
|
||||||
$compiler_args += ( $flag_define + 'GEN_TIME' )
|
|
||||||
|
|
||||||
$linker_args = @(
|
|
||||||
$flag_link_win_subsystem_console
|
|
||||||
)
|
|
||||||
|
|
||||||
#region Handmade Generate
|
#region Handmade Generate
|
||||||
if ( $false ) {
|
if ( $false ) {
|
||||||
|
$includes = @(
|
||||||
|
$path_project,
|
||||||
|
$path_gen,
|
||||||
|
# $path_deps,
|
||||||
|
$path_platform
|
||||||
|
)
|
||||||
|
$compiler_args = @()
|
||||||
|
$compiler_args += ( $flag_define + 'GEN_TIME' )
|
||||||
|
|
||||||
|
$linker_args = @(
|
||||||
|
$flag_link_win_subsystem_console
|
||||||
|
)
|
||||||
|
|
||||||
$unit = Join-Path $path_gen 'handmade_gen.cpp'
|
$unit = Join-Path $path_gen 'handmade_gen.cpp'
|
||||||
$executable = Join-Path $path_build 'handmade_gen.exe'
|
$executable = Join-Path $path_build 'handmade_gen.exe'
|
||||||
|
|
||||||
@ -408,10 +430,7 @@ if ( $false ) {
|
|||||||
|
|
||||||
#region Handmade Runtime
|
#region Handmade Runtime
|
||||||
$includes = @(
|
$includes = @(
|
||||||
$path_project,
|
$path_project
|
||||||
$path_gen,
|
|
||||||
$path_deps,
|
|
||||||
$path_platform
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Microsoft
|
# Microsoft
|
||||||
@ -423,9 +442,6 @@ $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_project 'handmade_win32.cpp'
|
|
||||||
$executable = Join-Path $path_build 'handmade_win32.exe'
|
|
||||||
|
|
||||||
$stack_size = 1024 * 1024 * 4
|
$stack_size = 1024 * 1024 * 4
|
||||||
|
|
||||||
$compiler_args = @(
|
$compiler_args = @(
|
||||||
@ -436,9 +452,6 @@ $compiler_args = @(
|
|||||||
$flag_warnings_as_errors
|
$flag_warnings_as_errors
|
||||||
$flag_optimize_intrinsics
|
$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' )
|
($flag_define + 'Build_Unity=1' )
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -449,19 +462,108 @@ else {
|
|||||||
$compiler_args += ( $flag_define + 'Build_Development=0' )
|
$compiler_args += ( $flag_define + 'Build_Development=0' )
|
||||||
}
|
}
|
||||||
|
|
||||||
$linker_args = @(
|
if ( $engine )
|
||||||
$lib_gdi32,
|
{
|
||||||
# $lib_xinput,
|
$engine_compiler_args = $compiler_args
|
||||||
$lib_user32,
|
$engine_compiler_args += ($flag_define + 'Build_DLL=1' )
|
||||||
$lib_winmm,
|
|
||||||
|
|
||||||
$lib_jsl,
|
if ( $vendor -eq 'msvc' )
|
||||||
|
{
|
||||||
|
$engine_compiler_args += ($flag_define + 'Engine_API=__declspec(dllexport)')
|
||||||
|
}
|
||||||
|
if ( $vendor -eq 'clang' )
|
||||||
|
{
|
||||||
|
$engine_compiler_args += ($flag_define + 'Engine_API=__attribute__((visibility("default")))')
|
||||||
|
}
|
||||||
|
|
||||||
$flag_link_win_subsystem_windows
|
$linker_args = @(
|
||||||
$flag_link_optimize_references
|
$flag_link_dll,
|
||||||
)
|
$flag_link_optimize_references
|
||||||
|
)
|
||||||
|
|
||||||
build-simple $includes $compiler_args $linker_args $unit $executable
|
$unit = Join-Path $path_project 'handmade_engine.cpp'
|
||||||
|
$dynamic_library = Join-Path $path_build 'handmade_engine.dll'
|
||||||
|
|
||||||
|
build-simple $includes $engine_compiler_args $linker_args $unit $dynamic_library
|
||||||
|
|
||||||
|
if ( Test-Path $dynamic_library )
|
||||||
|
{
|
||||||
|
$data_path = Join-Path $path_data 'handmade_engine.dll'
|
||||||
|
move-item $dynamic_library $data_path -Force
|
||||||
|
|
||||||
|
# We need to generate the symbol table so that we can lookup the symbols we need when loading/reloading the library at runtime.
|
||||||
|
# This is done by sifting through the emitter.map file from the linker for the base symbol names
|
||||||
|
# and mapping them to their found decorated name
|
||||||
|
|
||||||
|
$engine_symbols = @(
|
||||||
|
'on_module_reload',
|
||||||
|
'startup',
|
||||||
|
'shutdown',
|
||||||
|
'update_and_render',
|
||||||
|
'update_audio'
|
||||||
|
)
|
||||||
|
|
||||||
|
$path_engine_map = Join-Path $path_build 'handmade_engine.map'
|
||||||
|
|
||||||
|
$engine_symbol_table = @()
|
||||||
|
$engine_symbol_list = @()
|
||||||
|
Get-Content -Path $path_engine_map | ForEach-Object {
|
||||||
|
# Split each line by whitespace
|
||||||
|
$tokens = $_ -split '\s+', 3
|
||||||
|
|
||||||
|
# Extract only the decorated name using regex for both MSVC and Clang conventions
|
||||||
|
$decoratedName = ($tokens[2] -match '(\?[\w@]+|_Z[\w@]+)' ) ? $matches[1] : $null
|
||||||
|
|
||||||
|
# Check each regular name against the current line
|
||||||
|
foreach ($name in $engine_symbols) {
|
||||||
|
if ($decoratedName -like "*$name*") {
|
||||||
|
$engine_symbol_table += $name + ', ' + $decoratedName
|
||||||
|
$engine_symbol_list += $decoratedName
|
||||||
|
$engine_symbols = $engine_symbols -ne $name # Remove the found symbol from the array
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write-host "Engine Symbol Table:" -ForegroundColor Green
|
||||||
|
$engine_symbol_table | ForEach-Object {
|
||||||
|
write-host "`t$_" -ForegroundColor Green
|
||||||
|
}
|
||||||
|
|
||||||
|
# Write the symbol table to a file
|
||||||
|
$path_engine_symbols = Join-Path $path_data 'handmade_engine.symbols'
|
||||||
|
$engine_symbol_list | Out-File -Path $path_engine_symbols
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $platform )
|
||||||
|
{
|
||||||
|
$platform_compiler_args = $compiler_args
|
||||||
|
$platform_compiler_args += ($flag_define + 'Build_DLL=0' )
|
||||||
|
|
||||||
|
$linker_args = @(
|
||||||
|
$lib_gdi32,
|
||||||
|
# $lib_xinput,
|
||||||
|
$lib_user32,
|
||||||
|
$lib_winmm,
|
||||||
|
|
||||||
|
$lib_jsl,
|
||||||
|
|
||||||
|
$flag_link_win_subsystem_windows
|
||||||
|
$flag_link_optimize_references
|
||||||
|
)
|
||||||
|
|
||||||
|
$unit = Join-Path $path_project 'handmade_win32.cpp'
|
||||||
|
$executable = Join-Path $path_build 'handmade_win32.exe'
|
||||||
|
|
||||||
|
build-simple $includes $platform_compiler_args $linker_args $unit $executable
|
||||||
|
|
||||||
|
if ( Test-Path $executable )
|
||||||
|
{
|
||||||
|
$data_path = Join-Path $path_data 'handmade_win32.exe'
|
||||||
|
move-item $executable $data_path -Force
|
||||||
|
}
|
||||||
|
}
|
||||||
#endregion Handmade Runtime
|
#endregion Handmade Runtime
|
||||||
|
|
||||||
Pop-Location
|
Pop-Location
|
||||||
|
#endregion Building
|
||||||
|
Binary file not shown.
@ -23,5 +23,6 @@ if ( -not (Test-Path $vs_devshell) ) {
|
|||||||
|
|
||||||
# Launch the Visual Studio Developer Shell
|
# Launch the Visual Studio Developer Shell
|
||||||
Push-Location
|
Push-Location
|
||||||
|
write-host @args
|
||||||
& $vs_devshell @args
|
& $vs_devshell @args
|
||||||
Pop-Location
|
Pop-Location
|
||||||
|
Loading…
Reference in New Issue
Block a user