Day 1
This commit is contained in:
parent
5838345c09
commit
56518bdd66
|
@ -1,6 +1,10 @@
|
||||||
app_run_tree/
|
app_run_tree/
|
||||||
meta_run_tree/
|
meta_run_tree/
|
||||||
|
*.exe
|
||||||
|
*.pdb
|
||||||
|
*.o
|
||||||
process/
|
process/
|
||||||
reference/
|
reference/
|
||||||
working_data/
|
working_data/
|
||||||
nssm_log.log
|
nssm_log.log
|
||||||
|
sysroot/
|
|
@ -0,0 +1,294 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
print_usage () {
|
||||||
|
echo
|
||||||
|
echo Build Command Syntax:
|
||||||
|
echo " $0 [mode] [platform] [arch]"
|
||||||
|
echo
|
||||||
|
echo "Release Mode Options:"
|
||||||
|
echo " debug"
|
||||||
|
echo " prod"
|
||||||
|
echo
|
||||||
|
echo "Platform Options:"
|
||||||
|
echo " win32"
|
||||||
|
echo " osx"
|
||||||
|
echo " webgl"
|
||||||
|
echo
|
||||||
|
echo "Arch Options: (architecture)"
|
||||||
|
echo " intel (valid with Platform Win32 and OSX) (default)"
|
||||||
|
echo " arm64 (only valid for Platform OSX)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# Arguments
|
||||||
|
MODE=$1
|
||||||
|
PLATFORM=$2
|
||||||
|
ARCH=$3
|
||||||
|
PACKAGE=$4
|
||||||
|
|
||||||
|
if [ "${MODE}" == "" ] | [ "${PLATFORM}" == "" ]
|
||||||
|
then
|
||||||
|
print_usage
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Default to Intel architecture if none provided
|
||||||
|
if [ "${ARCH}" == "" ]
|
||||||
|
then
|
||||||
|
ARCH="intel"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${ARCH}" != "intel" ] && [ "${ARCH}" != "arm64" ]
|
||||||
|
then
|
||||||
|
echo "Uknown target architecture: ${ARCH}"
|
||||||
|
print_usage
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# Utilities
|
||||||
|
|
||||||
|
pushdir () {
|
||||||
|
command pushd "$@" > /dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
popdir () {
|
||||||
|
command popd "$@" > /dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# Getting Project Path
|
||||||
|
#
|
||||||
|
# Project is stored in PROJECT_PATH
|
||||||
|
|
||||||
|
SCRIPT_REL_DIR=$(dirname "${BASH_SOURCE[0]}")
|
||||||
|
pushdir $SCRIPT_REL_DIR
|
||||||
|
pushdir ..
|
||||||
|
PROJECT_PATH=$(pwd)
|
||||||
|
popdir
|
||||||
|
popdir
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# Platform/Mode Specific Variables
|
||||||
|
|
||||||
|
# Compiler Selection
|
||||||
|
|
||||||
|
Compiler_win32="cl"
|
||||||
|
Compiler_osx="clang++"
|
||||||
|
WasiSdk="/c/drive/apps/wasi-sdk"
|
||||||
|
Compiler_webgl="$WasiSdk/bin/clang++"
|
||||||
|
Compiler_linux="clang++"
|
||||||
|
|
||||||
|
# Platform Entry Points
|
||||||
|
|
||||||
|
PlatformEntry_win32="src_v2/platform/win32/lumenarium_first_win32.cpp"
|
||||||
|
PlatformEntry_osx="src_v2/platform/osx/lumenarium_first_osx.cpp"
|
||||||
|
PlatformEntry_webgl="src_v2/platform/webgl/lumenarium_first_webgl.cpp"
|
||||||
|
PlatformEntry_linux="src_v2/platform/linux/lumenarium_first_linux.cpp"
|
||||||
|
|
||||||
|
# Intermediate Outputs
|
||||||
|
|
||||||
|
CompilerOutput_win32="lumenarium.o"
|
||||||
|
CompilerOutput_osx="lumenarium"
|
||||||
|
CompilerOutput_webgl="lumenarium.wasm"
|
||||||
|
CompilerOutput_linux=""
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
|
||||||
|
LinkerOutput_win32="lumenarium.exe"
|
||||||
|
LinkerOutput_osx="lumenarium"
|
||||||
|
LinkerOutput_webgl="lumenarium.wasm"
|
||||||
|
LinkerOutput_linux=""
|
||||||
|
|
||||||
|
# Wasm Sys Root
|
||||||
|
WasmSysRoot="${PROJECT_PATH}/src_v2/platform/webgl/sysroot/"
|
||||||
|
|
||||||
|
# Compiler Flags
|
||||||
|
|
||||||
|
CompilerFlags_win32="-nologo -FC -WX -W4 -Z7 -Oi -MTd -fp:fast"
|
||||||
|
CompilerFlags_win32="$CompilerFlags_win32 -wd4505 -wd4100 -wd4189"
|
||||||
|
|
||||||
|
CompilerFlags_osx=""
|
||||||
|
|
||||||
|
CompilerFlags_webgl="-target wasm32 --sysroot ${WasmSysRoot} -s -fvisibility=hidden -fno-builtin -fno-exceptions -fno-threadsafe-statics"
|
||||||
|
|
||||||
|
# CompilerFlags_webgl="-nostartfiles -fno-exceptions -fno-entry -strip-all -s -import-memory -fvisibility=hidden --sysroot ${WasmSysRoot}"
|
||||||
|
|
||||||
|
CompilerFlags_linux=""
|
||||||
|
|
||||||
|
CompilerFlags_DEBUG_win32="-Od -Zi -DDEBUG"
|
||||||
|
CompilerFlags_DEBUG="-O0 -g -DDEBUG"
|
||||||
|
CompilerFlags_PROD="-O3"
|
||||||
|
|
||||||
|
# Compiler flags that no matter what, we want to define
|
||||||
|
# for the most part these pass the build parameters into the executable
|
||||||
|
CompilerFlags_common="-DPLATFORM=${PLATFORM} -DMODE=${MODE} -DARCH=${ARCH}"
|
||||||
|
|
||||||
|
# Linker Flags
|
||||||
|
|
||||||
|
LinkerFlags_win32="-NOLOGO -incremental:no -subsystem:windows -entry:WinMain -opt:ref"
|
||||||
|
LinkerFlags_osx=""
|
||||||
|
# LinkerFlags_webgl="--no-entry --export-dynamic -allow-undefined -import-memory -export=__wasm_call_ctors -export=malloc -export=free -export=main"
|
||||||
|
LinkerFlags_webgl="--no-entry --export-dynamic --unresolved-symbols=import-functions"
|
||||||
|
LinkerFlags_linux=""
|
||||||
|
|
||||||
|
LinkerFlags_DEBUG="-debug"
|
||||||
|
LinkerFlags_PROD=""
|
||||||
|
|
||||||
|
# Linker Libs
|
||||||
|
|
||||||
|
LinkerLibs_win32="user32.lib kernel32.lib gdi32.lib opengl32.lib"
|
||||||
|
# winmm.lib gdi32.lib dsound.lib Ws2_32.lib Comdlg32.lib Winspool.lib"
|
||||||
|
LinkerLibs_osx="-framework OpenGL -framework Cocoa"
|
||||||
|
LinkerLibs_webgl=""
|
||||||
|
LinkerLibs_linux=""
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# Varible Selection
|
||||||
|
|
||||||
|
# Select Platform Variables
|
||||||
|
|
||||||
|
if [ "${PLATFORM}" == "win32" ]
|
||||||
|
then
|
||||||
|
Compiler=$Compiler_win32
|
||||||
|
PlatformEntry=$PlatformEntry_win32
|
||||||
|
CompilerFlags=$CompilerFlags_win32
|
||||||
|
CompilerOutput=$CompilerOutput_win32
|
||||||
|
LinkerOutput=$LinkerOutput_win32
|
||||||
|
LinkerFlags=$LinkerFlags_win32
|
||||||
|
LinkerLibs=$LinkerLibs_win32
|
||||||
|
|
||||||
|
elif [ "${PLATFORM}" == "osx" ]
|
||||||
|
then
|
||||||
|
Compiler=$Compiler_osx
|
||||||
|
PlatformEntry=$PlatformEntry_osx
|
||||||
|
CompilerFlags=$CompilerFlags_osx
|
||||||
|
CompilerOutput=$CompilerOutput_osx
|
||||||
|
LinkerOutput=$LinkerOutput_osx
|
||||||
|
LinkerFlags=$LinkerFlags_osx
|
||||||
|
LinkerLibs=$LinkerLibs_osx
|
||||||
|
|
||||||
|
elif [ "${PLATFORM}" == "webgl" ]
|
||||||
|
then
|
||||||
|
Compiler=$Compiler_webgl
|
||||||
|
PlatformEntry=$PlatformEntry_webgl
|
||||||
|
CompilerFlags=$CompilerFlags_webgl
|
||||||
|
CompilerOutput=$CompilerOutput_webgl
|
||||||
|
LinkerOutput=$LinkerOutput_webgl
|
||||||
|
LinkerFlags=$LinkerFlags_webgl
|
||||||
|
LinkerLibs=$LinkerLibs_webgl
|
||||||
|
|
||||||
|
elif [ "${PLATFORM}" == "linux" ]
|
||||||
|
then
|
||||||
|
Compiler=$Compiler_linux
|
||||||
|
PlatformEntry=$PlatformEntry_linux
|
||||||
|
CompilerFlags=$CompilerFlags_linux
|
||||||
|
CompilerOutput=$CompilerOutput_linux
|
||||||
|
LinkerOutput=$LinkerOutput_linux
|
||||||
|
LinkerFlags=$LinkerFlags_linux
|
||||||
|
LinkerLibs=$LinkerLibs_linux
|
||||||
|
|
||||||
|
else
|
||||||
|
echo "Attempting to build for an unknown platform: ${PLATFORM}"
|
||||||
|
print_usage
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Select Release Mode Variables
|
||||||
|
|
||||||
|
if [ "${MODE}" == "debug" ]
|
||||||
|
then
|
||||||
|
if [ $PLATFORM == "win32" ]
|
||||||
|
then
|
||||||
|
CompilerFlags="${CompilerFlags} ${CompilerFlags_DEBUG_win32}"
|
||||||
|
else
|
||||||
|
CompilerFlags="${CompilerFlags} ${CompilerFlags_DEBUG}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
LinkerFlags="${LinkerFlags} ${LinkerFlags_DEBUG}"
|
||||||
|
|
||||||
|
elif [ "${MODE}" == "prod" ]
|
||||||
|
then
|
||||||
|
CompilerFlags="${CompilerFlags} ${CompilerFlags_PROD}"
|
||||||
|
LinkerFlags="${LinkerFlags} ${LinkerFlags_PROD}"
|
||||||
|
|
||||||
|
else
|
||||||
|
echo "Attempting to build for an unknown release mode: ${MODE}"
|
||||||
|
print_usage
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Common Flags
|
||||||
|
CompilerFlags="${CompilerFlags} ${CompilerFlags_common}"
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# Build Path Construction
|
||||||
|
#
|
||||||
|
# This determines where the generated executable will
|
||||||
|
# be located. In general, it can be found at
|
||||||
|
# project_path/run_tree/platform/arch/release_mode/lumenarium.exe
|
||||||
|
#
|
||||||
|
# This section also ensures that the path requested actually exists
|
||||||
|
|
||||||
|
BuildDir="${PROJECT_PATH}/run_tree/${PLATFORM}/${ARCH}/${MODE}"
|
||||||
|
EntryPath="${PROJECT_PATH}/${PlatformEntry}"
|
||||||
|
|
||||||
|
# Exception for webgl, which doesn't care about cpu architecture
|
||||||
|
if [ $PLATFORM == "webgl" ]
|
||||||
|
then
|
||||||
|
BuildDir="${PROJECT_PATH}/run_tree/${PLATFORM}/${MODE}"
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make the build directory,
|
||||||
|
# "-p" flag makes it make the entire tree, and not emit errors if it
|
||||||
|
# exists.
|
||||||
|
mkdir -p "${BuildDir}"
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# Compilation
|
||||||
|
|
||||||
|
echo "Building To: ${BuildDir}/${LinkerOutput}"
|
||||||
|
echo
|
||||||
|
pushdir $BuildDir
|
||||||
|
|
||||||
|
rm ${CompilerOutput} 2> /dev/null
|
||||||
|
rm ${LinkerOutput} 2> /dev/null
|
||||||
|
|
||||||
|
echo "COMPILING..."
|
||||||
|
if [ $PLATFORM == "win32" ]
|
||||||
|
then
|
||||||
|
$Compiler $CompilerFlags $EntryPath \
|
||||||
|
-link $LinkerFlags $LinkerLibs -OUT:${LinkerOutput}
|
||||||
|
|
||||||
|
elif [ $PLATFORM == "webgl" ]
|
||||||
|
then
|
||||||
|
|
||||||
|
LD="$WasiSdk/bin/wasm-ld"
|
||||||
|
echo $Compiler
|
||||||
|
CFlags="-O3 -flto --target=wasm32-unknown-wasi"
|
||||||
|
LDFlags="--no-entry --export-dynamic --allow-undefined --lto-O3 --import-memory"
|
||||||
|
|
||||||
|
$Compiler \
|
||||||
|
-Wno-writable-strings \
|
||||||
|
--target=wasm32 \
|
||||||
|
-nostdlib \
|
||||||
|
-Wl,--export-all \
|
||||||
|
-Wl,--no-entry \
|
||||||
|
-Wl,--allow-undefined \
|
||||||
|
-o lumenarium.wasm \
|
||||||
|
$EntryPath \
|
||||||
|
|
||||||
|
else
|
||||||
|
$Compiler -o $LinkerOutput $CompilerFlags $EntryPath $LinkerLibs
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Finished..."
|
||||||
|
popdir
|
|
@ -20,7 +20,7 @@ del *.pdb > NUL 2> NUL
|
||||||
|
|
||||||
echo WAITING FOR PDB TO WRITE > lock.tmp
|
echo WAITING FOR PDB TO WRITE > lock.tmp
|
||||||
|
|
||||||
cl %CommonCompilerFlags% %SourceCodePath%\foldhaus_app.cpp /Fefoldhaus.dll /LD /link %CommonLinkerFlags% %DLLExports%
|
cl %CommonCompilerFlags% %SourceCodePath%\foldhaus_app.cpp /Fefoldhaus.dll /LD /link %CommoLinkerFlags% %DLLExports%
|
||||||
SET LastError=%ERRORLEVEL%
|
SET LastError=%ERRORLEVEL%
|
||||||
|
|
||||||
del lock.tmp
|
del lock.tmp
|
||||||
|
|
|
@ -14,6 +14,7 @@ blacklist_patterns = {
|
||||||
};
|
};
|
||||||
load_paths_base = {
|
load_paths_base = {
|
||||||
{ "src", .relative = true, .recursive = true, },
|
{ "src", .relative = true, .recursive = true, },
|
||||||
|
{ "src_v2", .relative = true, .recursive = true, },
|
||||||
{ "meta", .relative = true, .recursive = true, },
|
{ "meta", .relative = true, .recursive = true, },
|
||||||
{ "gs_libs", .relative = true, .recursive = true, },
|
{ "gs_libs", .relative = true, .recursive = true, },
|
||||||
};
|
};
|
||||||
|
@ -22,6 +23,7 @@ load_paths = {
|
||||||
{ load_paths_base, .os = "linux", },
|
{ load_paths_base, .os = "linux", },
|
||||||
{ load_paths_base, .os = "mac", },
|
{ load_paths_base, .os = "mac", },
|
||||||
};
|
};
|
||||||
|
enable_virtual_whitespace=true;
|
||||||
|
|
||||||
command_list = {
|
command_list = {
|
||||||
{ .name = "build_application",
|
{ .name = "build_application",
|
||||||
|
@ -34,6 +36,11 @@ command_list = {
|
||||||
.cmd = { { "build\build_meta_msvc_win32_debug.bat" , .os = "win" },
|
.cmd = { { "build\build_meta_msvc_win32_debug.bat" , .os = "win" },
|
||||||
{ "./build_meta.sh", .os = "linux" },
|
{ "./build_meta.sh", .os = "linux" },
|
||||||
{ "./build_meta.sh", .os = "mac" }, }, },
|
{ "./build_meta.sh", .os = "mac" }, }, },
|
||||||
|
{ .name = "build_v2",
|
||||||
|
.out = "*compilation*", .footer_panel = true, .save_dirty_files = true,
|
||||||
|
.cmd = { { "bash build\build.sh debug win32 intel" , .os = "win" },
|
||||||
|
{ "./build_meta.sh", .os = "linux" },
|
||||||
|
{ "./build_meta.sh", .os = "mac" }, }, },
|
||||||
};
|
};
|
||||||
fkey_command[1] = "build_application";
|
fkey_command[1] = "build_v2";
|
||||||
fkey_command[2] = "build_meta";
|
fkey_command[2] = "build_meta";
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,9 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en-us">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script type="text/javascript" src="loader.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,130 @@
|
||||||
|
|
||||||
|
let memory = null;
|
||||||
|
let memory_u8 = null;
|
||||||
|
|
||||||
|
// TODO(PS): you need to figure out how to get text to convert to a string
|
||||||
|
function print (text)
|
||||||
|
{
|
||||||
|
console.log(i, memory_u8.length, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function load_webassembly_module ()
|
||||||
|
{
|
||||||
|
const path = "lumenarium.wasm";
|
||||||
|
const promise = fetch(path);
|
||||||
|
const module = await WebAssembly.compileStreaming(promise);
|
||||||
|
memory = new WebAssembly.Memory({ initial: 2 });
|
||||||
|
memory_u8 = new Uint8Array(memory.buffer);
|
||||||
|
const env = {
|
||||||
|
memory,
|
||||||
|
print,
|
||||||
|
};
|
||||||
|
const result = await WebAssembly.instantiate(module, { env });
|
||||||
|
console.log(result);
|
||||||
|
|
||||||
|
result.exports.main();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("load", load_webassembly_module)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
function load_webassembly_module (wa)
|
||||||
|
{
|
||||||
|
fetch(wa.module)
|
||||||
|
.then(res => res.arrayBuffer())
|
||||||
|
.then((wasm_bytes) => {
|
||||||
|
"use strict";
|
||||||
|
wasm_bytes = new Uint8Array(wasm_bytes);
|
||||||
|
|
||||||
|
// find start of heap and calc initial mem requirements
|
||||||
|
var wasm_heap_base = 65536;
|
||||||
|
|
||||||
|
// see https://webassembly.org/docs/binary-encoding/
|
||||||
|
for (let i = 8, section_end, type, length;
|
||||||
|
i < wasm_bytes.length;
|
||||||
|
i = section_end
|
||||||
|
){
|
||||||
|
|
||||||
|
function get_b8()
|
||||||
|
{
|
||||||
|
return wasm_bytes[i++];
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_leb()
|
||||||
|
{
|
||||||
|
for (var s = i, r = 0, n = 128; n & 128; i++)
|
||||||
|
{
|
||||||
|
r |= ((n = wasm_bytes[i]) & 127) << ((i - s) * 7);
|
||||||
|
}
|
||||||
|
return r; // TODO(PS): this might belong in the for loop?
|
||||||
|
}
|
||||||
|
|
||||||
|
type = get_leb();
|
||||||
|
length = get_leb();
|
||||||
|
section_end = i + length;
|
||||||
|
|
||||||
|
if (type < 0 || type > 11 || length <= 0 || section_end > wasm_bytes.length)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == 6)
|
||||||
|
{
|
||||||
|
//Section 6 'Globals', llvm places the heap base pointer into the first value here
|
||||||
|
let count = get_leb();
|
||||||
|
let gtype = get_b8();
|
||||||
|
let mutable = get_b8();
|
||||||
|
let opcode = get_leb();
|
||||||
|
let offset = get_leb();
|
||||||
|
let endcode = get_leb();
|
||||||
|
wasm_heap_base = offset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the wasm memory size to [DATA] + [STACK] + [256KB HEAP]
|
||||||
|
// (This loader does not support memory growing so it stays at this size)
|
||||||
|
var wasm_mem_init = ((wasm_heap_base + 65535) >> 16 << 16) + (256 * 1024);
|
||||||
|
var env = {
|
||||||
|
env: {
|
||||||
|
memory: new WebAssembly.Memory(
|
||||||
|
{
|
||||||
|
initial: wasm_mem_init >> 16
|
||||||
|
}
|
||||||
|
),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Instantiate the wasm module by passing the prepared environment
|
||||||
|
WebAssembly.instantiate(wasm_bytes, env)
|
||||||
|
.then(function (output)
|
||||||
|
{
|
||||||
|
// Store the list of the functions exported by the wasm module in WA.asm
|
||||||
|
wa.asm = output.instance.exports;
|
||||||
|
|
||||||
|
// If function '__wasm_call_ctors' (global C++ constructors) exists, call it
|
||||||
|
if (wa.asm.__wasm_call_ctors) wa.asm.__wasm_call_ctors();
|
||||||
|
|
||||||
|
// If function 'main' exists, call it with dummy arguments
|
||||||
|
if (wa.asm.main) wa.asm.main(0, 0);
|
||||||
|
|
||||||
|
// If the outer HTML file supplied a 'started' callback, call it
|
||||||
|
if (wa.started) wa.started();
|
||||||
|
})
|
||||||
|
.catch(function (err)
|
||||||
|
{
|
||||||
|
// On an exception, if the err is 'abort' the error was already processed in the abort function above
|
||||||
|
if (err !== 'abort') {
|
||||||
|
let stack = err.stack ? "\n" + err.stack : "";
|
||||||
|
console.error('BOOT: WASM instiantate error: ' + err + stack);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
load_webassembly_module(web_assembly)
|
||||||
|
|
||||||
|
*/
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,25 @@
|
||||||
|
|
||||||
|
internal void
|
||||||
|
ed_init(App_State* state)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
ed_frame_prepare(App_State* state)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
ed_frame(App_State* state)
|
||||||
|
{
|
||||||
|
edr_render(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
ed_cleanup(App_State* state)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
internal void
|
||||||
|
edr_render(App_State* state)
|
||||||
|
{
|
||||||
|
glMatrixMode(GL_TEXTURE_2D);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
glClearColor(0.1f, 0.1f, 0.1f, 1);
|
||||||
|
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
glViewport(0, 0, 1600, 900);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthFunc(GL_LESS);
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
|
||||||
|
internal void
|
||||||
|
en_init(App_State* state)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
en_frame_prepare(App_State* state)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
en_frame(App_State* state)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
en_cleanup(App_State* state)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
/* date = March 22nd 2022 6:40 pm */
|
||||||
|
|
||||||
|
#ifndef LUMENARIUM_ENGINE_ASSEMBLY_H
|
||||||
|
#define LUMENARIUM_ENGINE_ASSEMBLY_H
|
||||||
|
|
||||||
|
struct Assembly_Handle
|
||||||
|
{
|
||||||
|
u32 value;
|
||||||
|
};
|
||||||
|
|
||||||
|
union Assembly_Pixel
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
u8 r;
|
||||||
|
u8 g;
|
||||||
|
u8 b;
|
||||||
|
};
|
||||||
|
u8 channels[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Assembly_Pixel_Buffer
|
||||||
|
{
|
||||||
|
u32 cap;
|
||||||
|
u32 len;
|
||||||
|
Assembly_Pixel* pixels;
|
||||||
|
v4* positions;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Assembly_Strip
|
||||||
|
{
|
||||||
|
u32 pixels_cap;
|
||||||
|
u32* pixels;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Assembly_Strip_Array
|
||||||
|
{
|
||||||
|
u32 cap;
|
||||||
|
Assembly_Strip* strips;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Assembly_Array
|
||||||
|
{
|
||||||
|
u32 cap;
|
||||||
|
u32 len;
|
||||||
|
String* names;
|
||||||
|
Assembly_Pixel_Buffer* pixel_buffers;
|
||||||
|
Assembly_Strip_Array* strip_arrays;
|
||||||
|
|
||||||
|
Allocator* allocator;
|
||||||
|
};
|
||||||
|
|
||||||
|
Assembly_Handle assembly_add(Assembly_Array* a, String name, u64 pixels_cap, u64 strips_cap);
|
||||||
|
void assembly_rem(Assembly_Array* a, Assembly_Handle h);
|
||||||
|
Assembly_Strip* assembly_add_strip(Assembly_Array* a, Assembly_Handle h);
|
||||||
|
void assembly_add_led(Assembly_Array* a, Assembly_Handle h, Assembly_Strip* strip, v4 position);
|
||||||
|
|
||||||
|
|
||||||
|
#endif //LUMENARIUM_ENGINE_ASSEMBLY_H
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,87 @@
|
||||||
|
#include "lumenarium_first.h"
|
||||||
|
|
||||||
|
internal App_State*
|
||||||
|
lumenarium_init()
|
||||||
|
{
|
||||||
|
permanent = bump_allocator_create_reserve(MB(64));
|
||||||
|
scratch = bump_allocator_create_reserve(MB(64));
|
||||||
|
|
||||||
|
run_tests();
|
||||||
|
|
||||||
|
App_State* state = allocator_alloc_struct(permanent, App_State);
|
||||||
|
add_flag(state->flags, AppState_IsRunning);
|
||||||
|
|
||||||
|
state->input_state = input_state_create();
|
||||||
|
|
||||||
|
en_init(state);
|
||||||
|
if (!has_flag(state->flags, AppState_NoEditor))
|
||||||
|
{
|
||||||
|
ed_init(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
lumenarium_frame_prepare(App_State* state)
|
||||||
|
{
|
||||||
|
allocator_clear(scratch);
|
||||||
|
input_state_swap_frames(&state->input_state);
|
||||||
|
|
||||||
|
en_frame_prepare(state);
|
||||||
|
if (!has_flag(state->flags, AppState_NoEditor))
|
||||||
|
{
|
||||||
|
ed_frame_prepare(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
lumenarium_frame(App_State* state)
|
||||||
|
{
|
||||||
|
en_frame(state);
|
||||||
|
if (!has_flag(state->flags, AppState_NoEditor))
|
||||||
|
{
|
||||||
|
ed_frame(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
lumenarium_event(Platform_Window_Event evt, App_State* state)
|
||||||
|
{
|
||||||
|
Input_Frame* frame = state->input_state.frame_hot;
|
||||||
|
switch (evt.kind)
|
||||||
|
{
|
||||||
|
case WindowEvent_MouseScroll:
|
||||||
|
{
|
||||||
|
frame->mouse_scroll = evt.scroll_amt;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case WindowEvent_ButtonDown:
|
||||||
|
case WindowEvent_ButtonUp:
|
||||||
|
{
|
||||||
|
frame->key_flags[evt.key_code] = evt.key_flags;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case WindowEvent_Char:
|
||||||
|
{
|
||||||
|
frame->string_input[frame->string_input_len++] = evt.char_value;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case WindowEvent_WindowClosed:
|
||||||
|
{
|
||||||
|
rem_flag(state->flags, AppState_IsRunning);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
invalid_default_case;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
lumenarium_cleanup(App_State* state)
|
||||||
|
{
|
||||||
|
en_cleanup(state);
|
||||||
|
if (!has_flag(state->flags, AppState_NoEditor))
|
||||||
|
{
|
||||||
|
ed_cleanup(state);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/* date = March 22nd 2022 2:29 am */
|
||||||
|
|
||||||
|
#ifndef LUMENARIUM_FIRST_H
|
||||||
|
#define LUMENARIUM_FIRST_H
|
||||||
|
|
||||||
|
typedef struct App_State App_State;
|
||||||
|
|
||||||
|
#include "lumenarium_memory.cpp"
|
||||||
|
#include "lumenarium_string.cpp"
|
||||||
|
#include "lumenarium_input.cpp"
|
||||||
|
|
||||||
|
#include "engine/lumenarium_engine_assembly.h"
|
||||||
|
#include "engine/lumenarium_engine.cpp"
|
||||||
|
|
||||||
|
#include "editor/lumenarium_editor_renderer.cpp"
|
||||||
|
#include "editor/lumenarium_editor.cpp"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////
|
||||||
|
// Lumenarium Runtime Environment
|
||||||
|
|
||||||
|
global Allocator* permanent;
|
||||||
|
global Allocator* scratch; // gets reset at frame boundaries
|
||||||
|
|
||||||
|
#if defined(DEBUG)
|
||||||
|
# include "lumenarium_tests.cpp"
|
||||||
|
#else
|
||||||
|
# define run_tests()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////
|
||||||
|
// Lumenarium State
|
||||||
|
|
||||||
|
typedef b32 App_State_Flags;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
AppState_None = 0,
|
||||||
|
AppState_IsRunning = 1,
|
||||||
|
AppState_NoEditor = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct App_State
|
||||||
|
{
|
||||||
|
App_State_Flags flags;
|
||||||
|
|
||||||
|
Input_State input_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //LUMENARIUM_FIRST_H
|
|
@ -0,0 +1,81 @@
|
||||||
|
|
||||||
|
#define INPUT_FRAME_STRING_LENGTH 32
|
||||||
|
struct Input_Frame
|
||||||
|
{
|
||||||
|
Platform_Key_Flags key_flags[KeyCode_Count];
|
||||||
|
|
||||||
|
char string_input[INPUT_FRAME_STRING_LENGTH];
|
||||||
|
u32 string_input_len;
|
||||||
|
|
||||||
|
v2 mouse_pos;
|
||||||
|
s32 mouse_scroll;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Input_State
|
||||||
|
{
|
||||||
|
Input_Frame frames[2];
|
||||||
|
Input_Frame* frame_hot;
|
||||||
|
Input_Frame* frame_cold;
|
||||||
|
|
||||||
|
// cross frame state tracking
|
||||||
|
v2 mouse_pos_delta;
|
||||||
|
v2 mouse_pos_down;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define key_was_down(key_flags) has_flag((key_flags), KeyFlag_State_WasDown)
|
||||||
|
#define key_is_down(key_flags) has_flag((key_flags), KeyFlag_State_IsDown)
|
||||||
|
#define key_was_up(key_flags) (!has_flag((key_flags), KeyFlag_State_WasDown)
|
||||||
|
#define key_is_up(key_flags) (!has_flag((key_flags), KeyFlag_State_IsDown)
|
||||||
|
|
||||||
|
internal Input_State
|
||||||
|
input_state_create()
|
||||||
|
{
|
||||||
|
Input_State result = {};
|
||||||
|
result.frame_hot = result.frames + 0;
|
||||||
|
result.frame_cold = result.frames + 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
input_state_swap_frames(Input_State* input_state)
|
||||||
|
{
|
||||||
|
Input_Frame* next_hot = input_state->frame_cold;
|
||||||
|
input_state->frame_cold = input_state->frame_hot;
|
||||||
|
input_state->frame_hot = next_hot;
|
||||||
|
|
||||||
|
// Clear the new hot input frame
|
||||||
|
Platform_Key_Flags* hot_key_flags = input_state->frame_hot->key_flags;
|
||||||
|
Platform_Key_Flags* cold_key_flags = input_state->frame_cold->key_flags;
|
||||||
|
for (u32 i = 0; i < KeyCode_Count; i++) hot_key_flags[i] = cold_key_flags[i];
|
||||||
|
input_state->frame_hot->string_input_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key State Queries
|
||||||
|
|
||||||
|
internal bool
|
||||||
|
input_key_is_down(Input_State* input_state, Platform_Key_Code key)
|
||||||
|
{
|
||||||
|
Platform_Key_Flags flags = input_state->frame_hot->key_flags[key];
|
||||||
|
return key_is_down(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool
|
||||||
|
input_key_went_down(Input_State* input_state, Platform_Key_Code key)
|
||||||
|
{
|
||||||
|
Platform_Key_Flags flags = input_state->frame_hot->key_flags[key];
|
||||||
|
return key_is_down(flags) && !key_was_down(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool
|
||||||
|
input_key_is_up(Input_State* input_state, Platform_Key_Code key)
|
||||||
|
{
|
||||||
|
Platform_Key_Flags flags = input_state->frame_hot->key_flags[key];
|
||||||
|
return !key_is_down(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool
|
||||||
|
input_key_went_up(Input_State* input_state, Platform_Key_Code key)
|
||||||
|
{
|
||||||
|
Platform_Key_Flags flags = input_state->frame_hot->key_flags[key];
|
||||||
|
return !key_is_down(flags) && key_was_down(flags);
|
||||||
|
}
|
|
@ -0,0 +1,226 @@
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
// Memory Functions
|
||||||
|
|
||||||
|
void
|
||||||
|
memory_zero_no_simd(u8* base, u64 size)
|
||||||
|
{
|
||||||
|
for (u64 i = 0; i < size; i++) base[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
memory_copy_no_simd(u8* from, u8* to, u64 size)
|
||||||
|
{
|
||||||
|
for (u64 i = 0; i < size; i++) to[i] = from[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(PLATFORM_HAS_SIMD)
|
||||||
|
|
||||||
|
// TODO(PS):
|
||||||
|
// TODO(PS):
|
||||||
|
// TODO(PS):
|
||||||
|
|
||||||
|
void
|
||||||
|
memory_zero_simd(u8* base, u64 size)
|
||||||
|
{
|
||||||
|
memory_zero_no_simd(base, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
memory_copy_simd(u8* from, u8* to, u64 size)
|
||||||
|
{
|
||||||
|
memory_copy_no_simd(from, to, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
# define memory_zero(b,s) memory_zero_simd((b),(s))
|
||||||
|
# define memory_copy(f,t,s) memory_copy_simd((f),(t),(s))
|
||||||
|
|
||||||
|
#else
|
||||||
|
# define memory_zero(b,s) memory_zero_no_simd((b),(s))
|
||||||
|
# define memory_copy(f,t,s) memory_copy_no_simd((f),(t),(s))
|
||||||
|
|
||||||
|
#endif // defined(PLATFORM_HAS_SIMD)
|
||||||
|
|
||||||
|
#define zero_struct(s) memory_zero((u8*)(&s), sizeof(s))
|
||||||
|
|
||||||
|
u64
|
||||||
|
size_to_pages(u64 size)
|
||||||
|
{
|
||||||
|
u64 page_size = platform_page_size();
|
||||||
|
u64 rem = size % page_size;
|
||||||
|
if (rem != 0 || size < page_size)
|
||||||
|
{
|
||||||
|
u64 grow = page_size - rem;
|
||||||
|
size += grow;
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
// Allocator
|
||||||
|
//
|
||||||
|
// A generic interface for any memory-providing construct
|
||||||
|
//
|
||||||
|
// To implement a complete allocator, all that is really required
|
||||||
|
// is to create its Allocator_Alloc function
|
||||||
|
|
||||||
|
typedef struct Allocator Allocator;
|
||||||
|
|
||||||
|
typedef u8* Allocator_Alloc(Allocator* allocator, u64 size);
|
||||||
|
typedef void Allocator_Free(Allocator* allocator, u8* base, u64 size);
|
||||||
|
typedef u8* Allocator_Realloc(Allocator* allocator, u8* base, u64 old_size, u64 new_size);
|
||||||
|
typedef void Allocator_Clear(Allocator* allocator);
|
||||||
|
|
||||||
|
struct Allocator
|
||||||
|
{
|
||||||
|
Allocator_Alloc* alloc;
|
||||||
|
Allocator_Free* free;
|
||||||
|
Allocator_Realloc* realloc;
|
||||||
|
Allocator_Clear* clear;
|
||||||
|
|
||||||
|
Allocator* parent;
|
||||||
|
|
||||||
|
u8* allocator_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define allocator_alloc(a,s) (a)->alloc((a),(s))
|
||||||
|
#define allocator_alloc_struct(a,t) (t*)(a)->alloc((a),sizeof(t))
|
||||||
|
#define allocator_alloc_array(a,t,c) (t*)(a)->alloc((a),sizeof(t)*(c))
|
||||||
|
|
||||||
|
#define allocator_free(a,b,s) (a)->free((a),(b),(s))
|
||||||
|
#define allocator_free_struct(a,b,t) (a)->free((a),(b),sizeof(t))
|
||||||
|
#define allocator_free_array(a,b,t,c) (a)->free((a),(b),sizeof(t)*(c))
|
||||||
|
|
||||||
|
#define allocator_realloc(a,b,os,ns) (a)->realloc((a),(b),(os),(ns))
|
||||||
|
#define allocator_realloc_array(a,b,t,oc,nc) (t*)(a)->realloc((a),(b),sizeof(t)*(oc),sizeof(t)*(nc))
|
||||||
|
|
||||||
|
#define allocator_clear(a) (a)->clear(a)
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
// Bump Allocator
|
||||||
|
|
||||||
|
struct Allocator_Bump
|
||||||
|
{
|
||||||
|
u8* base;
|
||||||
|
u64 at;
|
||||||
|
u64 size_committed;
|
||||||
|
u64 size_reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
internal u8*
|
||||||
|
bump_allocator_alloc(Allocator* allocator, u64 size)
|
||||||
|
{
|
||||||
|
Allocator_Bump* bump = (Allocator_Bump*)allocator->allocator_data;
|
||||||
|
|
||||||
|
u64 at_after = bump->at + size;
|
||||||
|
// TODO(PS): align up to 8 bytes
|
||||||
|
|
||||||
|
if (at_after >= bump->size_committed)
|
||||||
|
{
|
||||||
|
// determine new size of the arena
|
||||||
|
u64 new_size = bump->size_committed * 2;
|
||||||
|
if (new_size == 0) new_size = platform_page_size();
|
||||||
|
if (new_size < at_after) new_size = size_to_pages(at_after);
|
||||||
|
|
||||||
|
if (allocator->parent)
|
||||||
|
{
|
||||||
|
bump->base = allocator_realloc(
|
||||||
|
allocator->parent,
|
||||||
|
bump->base,
|
||||||
|
bump->size_committed,
|
||||||
|
new_size
|
||||||
|
);
|
||||||
|
if (bump->base != 0)
|
||||||
|
{
|
||||||
|
bump->size_reserved = new_size;
|
||||||
|
bump->size_committed = new_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (new_size < bump->size_reserved)
|
||||||
|
{
|
||||||
|
u64 next_page = size_to_pages(bump->at);
|
||||||
|
u64 commit_amt = new_size - next_page;
|
||||||
|
bump->base = platform_mem_commit(bump->base + next_page, commit_amt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
invalid_code_path; // out of reserved memory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u8* result = bump->base;
|
||||||
|
bump->at = at_after;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal u8*
|
||||||
|
bump_allocator_realloc(Allocator* allocator, u8* base, u64 old_size, u64 new_size)
|
||||||
|
{
|
||||||
|
u8* result = bump_allocator_alloc(allocator, new_size);
|
||||||
|
memory_copy(base, result, old_size);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
bump_allocator_clear(Allocator* allocator)
|
||||||
|
{
|
||||||
|
if (!allocator->allocator_data) return;
|
||||||
|
Allocator_Bump* bump = (Allocator_Bump*)allocator->allocator_data;
|
||||||
|
bump->at = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Allocator*
|
||||||
|
bump_allocator_create_()
|
||||||
|
{
|
||||||
|
u64 size_needed = sizeof(Allocator) + sizeof(Allocator_Bump);
|
||||||
|
|
||||||
|
u8* base = platform_mem_reserve(size_needed);
|
||||||
|
base = platform_mem_commit(base, size_needed);
|
||||||
|
|
||||||
|
Allocator* result = (Allocator*)base;
|
||||||
|
zero_struct(*result);
|
||||||
|
|
||||||
|
Allocator_Bump* bump = (Allocator_Bump*)base + sizeof(Allocator);
|
||||||
|
zero_struct(*bump);
|
||||||
|
|
||||||
|
result->alloc = bump_allocator_alloc;
|
||||||
|
result->realloc = bump_allocator_realloc;
|
||||||
|
result->clear = bump_allocator_clear;
|
||||||
|
result->allocator_data = (u8*)bump;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Allocator*
|
||||||
|
bump_allocator_create_reserve(u64 reserve_size)
|
||||||
|
{
|
||||||
|
Allocator* result = bump_allocator_create_();
|
||||||
|
Allocator_Bump* bump = (Allocator_Bump*)result->allocator_data;
|
||||||
|
|
||||||
|
u64 reserve_pages = size_to_pages(reserve_size);
|
||||||
|
bump->base = platform_mem_reserve(reserve_pages);
|
||||||
|
if (bump->base != 0) bump->size_reserved = reserve_pages;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Allocator*
|
||||||
|
bump_allocator_create_child(Allocator* parent, u64 init_size)
|
||||||
|
{
|
||||||
|
Allocator* result = bump_allocator_create_();
|
||||||
|
result->parent = parent;
|
||||||
|
|
||||||
|
Allocator_Bump* bump = (Allocator_Bump*)result->allocator_data;
|
||||||
|
bump->base = allocator_alloc(result->parent, init_size);
|
||||||
|
if (bump->base != 0)
|
||||||
|
{
|
||||||
|
bump->size_reserved = init_size;
|
||||||
|
bump->size_committed = init_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,226 @@
|
||||||
|
|
||||||
|
internal u64
|
||||||
|
c_str_len(char* s)
|
||||||
|
{
|
||||||
|
u64 result = 0;
|
||||||
|
for (; s[result] != 0; result++) {}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define str_varg(str) (int)(str).len, (char*)(str).str
|
||||||
|
#define lit_str(s) String{ (u8*)(s), (u64)sizeof(s)-1, (u64)sizeof(s)-1 }
|
||||||
|
|
||||||
|
internal String
|
||||||
|
allocator_alloc_string(Allocator* a, u64 cap)
|
||||||
|
{
|
||||||
|
String result = {};
|
||||||
|
result.str = allocator_alloc_array(a, u8, cap);
|
||||||
|
result.cap = cap;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////
|
||||||
|
// Char Operations
|
||||||
|
|
||||||
|
bool
|
||||||
|
char_is_space(u8 c)
|
||||||
|
{
|
||||||
|
return c == ' ' || c == '\r' || c == '\t' || c == '\f' || c == '\v' || c == '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
u8
|
||||||
|
char_to_upper(u8 c)
|
||||||
|
{
|
||||||
|
return (c >= 'a' && c <= 'z') ? ('A' + (c - 'a')) : c;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8
|
||||||
|
char_to_lower(u8 c)
|
||||||
|
{
|
||||||
|
return (c >= 'A' && c <= 'Z') ? ('a' + (c - 'A')) : c;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8
|
||||||
|
char_to_forward_slash(u8 c)
|
||||||
|
{
|
||||||
|
return (c == '\\' ? '/' : c);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////
|
||||||
|
// String Operations
|
||||||
|
//
|
||||||
|
// Note that these don't actually modify any memory
|
||||||
|
// just return structures that let you view it differently
|
||||||
|
|
||||||
|
internal String
|
||||||
|
string_substring(String s, u64 min, u64 max)
|
||||||
|
{
|
||||||
|
if (max > s.len) max = s.len;
|
||||||
|
if (min > s.len) min = s.len;
|
||||||
|
if (min > max) {
|
||||||
|
u64 t = min;
|
||||||
|
min = max;
|
||||||
|
max = min;
|
||||||
|
}
|
||||||
|
String result = {};
|
||||||
|
result.str = s.str + min;
|
||||||
|
result.len = max - min;
|
||||||
|
result.cap = result.len;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal String
|
||||||
|
string_skip(String s, u64 min)
|
||||||
|
{
|
||||||
|
return string_substring(s, min, s.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal String
|
||||||
|
string_chop(String s, u64 nmax)
|
||||||
|
{
|
||||||
|
return string_substring(s, 0, s.len - nmax);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal String
|
||||||
|
string_get_prefix(String s, u64 max)
|
||||||
|
{
|
||||||
|
return string_substring(s, 0, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal String
|
||||||
|
string_get_suffix(String s, u64 nmax)
|
||||||
|
{
|
||||||
|
return string_substring(s, s.len - nmax, s.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef u32 String_Match_Flags;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
StringMatch_FindLast = 1,
|
||||||
|
StringMatch_CaseInsensitive = 2,
|
||||||
|
StringMatch_SlashInsensitive = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
internal bool
|
||||||
|
string_match(String a, String b, String_Match_Flags flags)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
if (a.len == b.len)
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
for (u64 i = 0; i < a.len; i++)
|
||||||
|
{
|
||||||
|
bool match = a.str[i] == b.str[i];
|
||||||
|
if(flags & StringMatch_CaseInsensitive)
|
||||||
|
{
|
||||||
|
match |= (char_to_lower(a.str[i]) == char_to_lower(b.str[i]));
|
||||||
|
}
|
||||||
|
if(flags & StringMatch_SlashInsensitive)
|
||||||
|
{
|
||||||
|
match |= (char_to_forward_slash(a.str[i]) == char_to_forward_slash(b.str[i]));
|
||||||
|
}
|
||||||
|
if(match == 0)
|
||||||
|
{
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal u64
|
||||||
|
string_find_substring(String s, String substr, u64 start_pos, String_Match_Flags flags)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
u64 found_i = s.len;
|
||||||
|
for (u64 i = start_pos; i < s.len; i++)
|
||||||
|
{
|
||||||
|
if (i + substr.len <= s.len)
|
||||||
|
{
|
||||||
|
String at = string_substring(s, i, i + substr.len);
|
||||||
|
if (string_match(at, substr, flags))
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
found_i = i;
|
||||||
|
if (!(flags & StringMatch_FindLast)) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found_i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////
|
||||||
|
// Path Operations
|
||||||
|
|
||||||
|
// good for removing extensions
|
||||||
|
internal String
|
||||||
|
string_chop_last_period(String s)
|
||||||
|
{
|
||||||
|
u64 period_pos = string_find_substring(s, lit_str("."), 0, StringMatch_FindLast);
|
||||||
|
if(period_pos < s.len)
|
||||||
|
{
|
||||||
|
s.len = period_pos;
|
||||||
|
s.cap = s.len;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the filename
|
||||||
|
internal String
|
||||||
|
string_skip_last_slash(String s)
|
||||||
|
{
|
||||||
|
u64 slash_pos = string_find_substring(s, lit_str("/"), 0, StringMatch_FindLast | StringMatch_SlashInsensitive);
|
||||||
|
if(slash_pos < s.len)
|
||||||
|
{
|
||||||
|
s.str += slash_pos + 1;
|
||||||
|
s.len -= slash_pos + 1;
|
||||||
|
s.cap = s.len;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the extension
|
||||||
|
internal String
|
||||||
|
string_skip_last_period(String s)
|
||||||
|
{
|
||||||
|
u64 period_pos = string_find_substring(s, lit_str("."), 0, StringMatch_FindLast);
|
||||||
|
if(period_pos < s.len)
|
||||||
|
{
|
||||||
|
s.str += period_pos + 1;
|
||||||
|
s.len -= period_pos + 1;
|
||||||
|
s.cap = s.len;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// good for getting the path to a file
|
||||||
|
internal String
|
||||||
|
string_chop_last_slash(String s)
|
||||||
|
{
|
||||||
|
u64 slash_pos = string_find_substring(s, lit_str("/"), 0, StringMatch_FindLast | StringMatch_SlashInsensitive);
|
||||||
|
if(slash_pos < s.len)
|
||||||
|
{
|
||||||
|
s.len = slash_pos;
|
||||||
|
s.cap = s.len;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////
|
||||||
|
// String Modifications
|
||||||
|
|
||||||
|
internal String
|
||||||
|
string_copy(String s, Allocator* a)
|
||||||
|
{
|
||||||
|
u64 size = s.cap;
|
||||||
|
if (s.str[s.cap] != 0) size += 1;
|
||||||
|
String result = allocator_alloc_string(a, size);
|
||||||
|
memory_copy(s.str, result.str, s.cap);
|
||||||
|
result.str[size] = 0;
|
||||||
|
result.len = size;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
|
||||||
|
Platform_Thread_Result
|
||||||
|
thread_proc(Platform_Thread_Data* td)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
run_tests()
|
||||||
|
{
|
||||||
|
// testing strings and exe path
|
||||||
|
String exe_file_path = platform_get_exe_path(scratch);
|
||||||
|
assert(exe_file_path.str != 0);
|
||||||
|
u64 run_tree_start = string_find_substring(exe_file_path, lit_str("run_tree"), 0, StringMatch_FindLast);
|
||||||
|
u64 run_tree_end = run_tree_start + lit_str("run_tree").len;
|
||||||
|
assert(run_tree_start < exe_file_path.len);
|
||||||
|
String run_tree_path = string_get_prefix(exe_file_path, run_tree_end);
|
||||||
|
String run_tree_path_nullterm = string_copy(run_tree_path, scratch);
|
||||||
|
assert(run_tree_path_nullterm.len > 0);
|
||||||
|
assert(platform_pwd_set(run_tree_path_nullterm));
|
||||||
|
|
||||||
|
// testing file io
|
||||||
|
Platform_File_Handle f = platform_file_open(lit_str("text.txt"), FileAccess_Read | FileAccess_Write, FileCreate_OpenExisting);
|
||||||
|
Platform_File_Info i = platform_file_get_info(f, scratch);
|
||||||
|
|
||||||
|
Data d0 = platform_file_read_all(f, scratch);
|
||||||
|
assert(d0.size > 0);
|
||||||
|
|
||||||
|
String s = lit_str("foooooooooobbbbbbaaaarrrrrr");
|
||||||
|
Data d1 = { s.str, s.len };
|
||||||
|
bool r = platform_file_write_all(f, d1);
|
||||||
|
assert(r);
|
||||||
|
|
||||||
|
// testing threads
|
||||||
|
Platform_Thread_Handle threads[8];
|
||||||
|
for (u32 j = 0; j < 8; j++)
|
||||||
|
{
|
||||||
|
threads[j] = platform_thread_begin(thread_proc, 0);
|
||||||
|
}
|
||||||
|
for (u32 j = 0; j < 8; j++)
|
||||||
|
{
|
||||||
|
platform_thread_end(threads[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
allocator_clear(scratch);
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
/* date = March 22nd 2022 2:08 am */
|
||||||
|
|
||||||
|
#ifndef LUMENARIUM_TYPES_H
|
||||||
|
#define LUMENARIUM_TYPES_H
|
||||||
|
|
||||||
|
#define internal static
|
||||||
|
#define local_persist static
|
||||||
|
#define global static
|
||||||
|
#define local_const static const
|
||||||
|
#define global_const static const
|
||||||
|
#define external extern "C"
|
||||||
|
|
||||||
|
#if defined(GUESS_INTS)
|
||||||
|
typedef signed char s8;
|
||||||
|
typedef signed short s16;
|
||||||
|
typedef signed int s32;
|
||||||
|
typedef signed long long s64;
|
||||||
|
typedef unsigned char u8;
|
||||||
|
typedef unsigned short u16;
|
||||||
|
typedef unsigned int u32;
|
||||||
|
typedef unsigned long long u64;
|
||||||
|
#else
|
||||||
|
typedef int8_t s8;
|
||||||
|
typedef int16_t s16;
|
||||||
|
typedef int32_t s32;
|
||||||
|
typedef int64_t s64;
|
||||||
|
typedef uint8_t u8;
|
||||||
|
typedef uint16_t u16;
|
||||||
|
typedef uint32_t u32;
|
||||||
|
typedef uint64_t u64;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef s8 b8;
|
||||||
|
typedef s32 b32;
|
||||||
|
typedef s64 b64;
|
||||||
|
|
||||||
|
typedef float r32;
|
||||||
|
typedef double r64;
|
||||||
|
|
||||||
|
struct Data
|
||||||
|
{
|
||||||
|
u8* base;
|
||||||
|
u64 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define Bytes(x) (x)
|
||||||
|
#define KB(x) ((x) << 10)
|
||||||
|
#define MB(x) ((x) << 20)
|
||||||
|
#define GB(x) ((x) << 30)
|
||||||
|
#define TB(x) (((u64)x) << 40)
|
||||||
|
|
||||||
|
#define has_flag(data, flag) (((data) & (flag)) != 0)
|
||||||
|
#define has_flag_only(data, flag) (((data) & (flag)) == (data))
|
||||||
|
#define add_flag(data, flag) ((data) |= (flag))
|
||||||
|
#define rem_flag(data, flag) ((data) &= (~(flag)))
|
||||||
|
|
||||||
|
//////////////////////////////////////////////
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
// this assert works by simply trying to write to an invalid address
|
||||||
|
// (in this case, 0x0), which will crash in most debuggers
|
||||||
|
#define assert_always (*((volatile s32*)0) = 0xFFFF)
|
||||||
|
|
||||||
|
#ifdef USE_ASSERTS
|
||||||
|
# define assert(c) if (!(c)) { assert_always; }
|
||||||
|
|
||||||
|
// useful for catching cases that you aren't sure you'll hit, but
|
||||||
|
// want to be alerted when they happen
|
||||||
|
# define invalid_code_path assert_always
|
||||||
|
|
||||||
|
// useful for switch statements on enums that might grow. You'll
|
||||||
|
// break in the debugger the first time the default case is hit
|
||||||
|
// with a new enum value
|
||||||
|
# define invalid_default_case default: { assert_always; } break;
|
||||||
|
|
||||||
|
#else
|
||||||
|
# define assert(c)
|
||||||
|
# define invalid_code_path
|
||||||
|
# define invalid_default_case default: { } break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////
|
||||||
|
// List Helper Macros
|
||||||
|
|
||||||
|
#define sll_push(first,last,ele) \
|
||||||
|
if (!(first)) { (first) = (ele); }\
|
||||||
|
else { (last)->next = (ele); } \
|
||||||
|
(last) = (ele); (ele)->next = 0;
|
||||||
|
|
||||||
|
// TODO(PS): Stack, Queue, DLL ops
|
||||||
|
|
||||||
|
//////////////////////////////////////////////
|
||||||
|
// String
|
||||||
|
|
||||||
|
// NOTE(PS): even though this has a len and cap, it should always be
|
||||||
|
// null terminated
|
||||||
|
struct String
|
||||||
|
{
|
||||||
|
u8* str;
|
||||||
|
u64 len;
|
||||||
|
u64 cap;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Allocator Allocator;
|
||||||
|
|
||||||
|
#endif //LUMENARIUM_TYPES_H
|
|
@ -0,0 +1,17 @@
|
||||||
|
/* date = March 22nd 2022 2:09 am */
|
||||||
|
|
||||||
|
#ifndef LUMENARIUM_COMPILER_FLAGS_H
|
||||||
|
#define LUMENARIUM_COMPILER_FLAGS_H
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
# pragma GCC diagnostic ignored "-Wunused-value"
|
||||||
|
# pragma GCC diagnostic ignored "-Wvarargs"
|
||||||
|
# pragma GCC diagnostic ignored "-Wwritable-strings"
|
||||||
|
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
# define USE_ASSERTS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //LUMENARIUM_COMPILER_FLAGS_H
|
|
@ -0,0 +1,294 @@
|
||||||
|
/* date = March 22nd 2022 2:05 am */
|
||||||
|
|
||||||
|
#ifndef LUMENARIUM_PLATFORM_H
|
||||||
|
#define LUMENARIUM_PLATFORM_H
|
||||||
|
|
||||||
|
// This is a file that defines the things that every platform
|
||||||
|
// must expose to the entire program
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Memory
|
||||||
|
|
||||||
|
u64 platform_page_size();
|
||||||
|
|
||||||
|
u8* platform_mem_reserve(u64 size);
|
||||||
|
u8* platform_mem_commit(u8* base, u64 size);
|
||||||
|
bool platform_mem_decommit(u8* base, u64 size);
|
||||||
|
bool platform_mem_release(u8* base, u64 size);
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// File I/O
|
||||||
|
|
||||||
|
struct Platform_File_Handle
|
||||||
|
{
|
||||||
|
u64 value;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef u32 Platform_File_Access_Flags;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
FileAccess_None = 0,
|
||||||
|
FileAccess_Read = 1,
|
||||||
|
FileAccess_Write = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef u32 Platform_File_Create_Flags;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
// these match https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
|
||||||
|
FileCreate_None = 0,
|
||||||
|
FileCreate_New = 1,
|
||||||
|
FileCreate_CreateAlways = 2,
|
||||||
|
FileCreate_OpenExisting = 3,
|
||||||
|
FileCreate_OpenAlways = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef u32 Platform_File_Flags;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
FileFlag_IsFile = 0,
|
||||||
|
FileFlag_IsDir = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Platform_File_Info
|
||||||
|
{
|
||||||
|
String path;
|
||||||
|
String path_abs;
|
||||||
|
u64 size;
|
||||||
|
u64 time_created;
|
||||||
|
u64 time_last_write;
|
||||||
|
Platform_File_Flags flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Platform_File_Info_List_Ele
|
||||||
|
{
|
||||||
|
Platform_File_Info info;
|
||||||
|
Platform_File_Info_List_Ele* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Platform_File_Info_List
|
||||||
|
{
|
||||||
|
Platform_File_Info_List_Ele* first;
|
||||||
|
Platform_File_Info_List_Ele* last;
|
||||||
|
};
|
||||||
|
|
||||||
|
Platform_File_Handle platform_file_open(String path, Platform_File_Access_Flags flags_access, Platform_File_Create_Flags flags_create);
|
||||||
|
void platform_file_close(Platform_File_Handle file_handle);
|
||||||
|
Platform_File_Info platform_file_get_info(Platform_File_Handle file_handle, Allocator* allocator);
|
||||||
|
Data platform_file_read_all(Platform_File_Handle file_handle, Allocator* allocator);
|
||||||
|
bool platform_file_write_all(Platform_File_Handle file_handle, Data file_data);
|
||||||
|
|
||||||
|
typedef u32 Platform_Enum_Dir_Flags;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
EnumDir_Recursive = 1,
|
||||||
|
EnumDir_IncludeDirectories = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
Platform_File_Info_List platform_dir_enum(String path, Platform_Enum_Dir_Flags flags, Allocator* allocator);
|
||||||
|
|
||||||
|
String platform_get_exe_path(Allocator* allocator);
|
||||||
|
bool platform_pwd_set(String path);
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Windows & Events
|
||||||
|
|
||||||
|
enum Platform_Window_Event_Kind
|
||||||
|
{
|
||||||
|
WindowEvent_Invalid = 0,
|
||||||
|
|
||||||
|
WindowEvent_MouseScroll,
|
||||||
|
WindowEvent_ButtonDown,
|
||||||
|
WindowEvent_ButtonUp,
|
||||||
|
WindowEvent_Char,
|
||||||
|
WindowEvent_WindowClosed,
|
||||||
|
|
||||||
|
WindowEvent_Count,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef u32 Platform_Key_Code;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
KeyCode_Invalid = 0,
|
||||||
|
|
||||||
|
KeyCode_Esc,
|
||||||
|
|
||||||
|
KeyCode_Space,
|
||||||
|
KeyCode_Tab,
|
||||||
|
KeyCode_CapsLock,
|
||||||
|
KeyCode_LeftShift, KeyCode_RightShift,
|
||||||
|
KeyCode_LeftCtrl, KeyCode_RightCtrl,
|
||||||
|
KeyCode_Fn,
|
||||||
|
KeyCode_Alt,
|
||||||
|
KeyCode_PageUp, KeyCode_PageDown,
|
||||||
|
KeyCode_Backspace, KeyCode_Delete,
|
||||||
|
KeyCode_Enter,
|
||||||
|
|
||||||
|
// Function Keys
|
||||||
|
KeyCode_F0, KeyCode_F1, KeyCode_F2, KeyCode_F3, KeyCode_F4, KeyCode_F5, KeyCode_F6, KeyCode_F7,
|
||||||
|
KeyCode_F8, KeyCode_F9, KeyCode_F10, KeyCode_F11, KeyCode_F12,
|
||||||
|
|
||||||
|
// Letters
|
||||||
|
KeyCode_a, KeyCode_b, KeyCode_c, KeyCode_d, KeyCode_e, KeyCode_f, KeyCode_g, KeyCode_h,
|
||||||
|
KeyCode_i, KeyCode_j, KeyCode_k, KeyCode_l, KeyCode_m, KeyCode_n, KeyCode_o, KeyCode_p,
|
||||||
|
KeyCode_q, KeyCode_r, KeyCode_s, KeyCode_t, KeyCode_u, KeyCode_v, KeyCode_w, KeyCode_x,
|
||||||
|
KeyCode_y, KeyCode_z,
|
||||||
|
|
||||||
|
KeyCode_A, KeyCode_B, KeyCode_C, KeyCode_D, KeyCode_E, KeyCode_F, KeyCode_G, KeyCode_H,
|
||||||
|
KeyCode_I, KeyCode_J, KeyCode_K, KeyCode_L, KeyCode_M, KeyCode_N, KeyCode_O, KeyCode_P,
|
||||||
|
KeyCode_Q, KeyCode_R, KeyCode_S, KeyCode_T, KeyCode_U, KeyCode_V, KeyCode_W, KeyCode_X,
|
||||||
|
KeyCode_Y, KeyCode_Z,
|
||||||
|
|
||||||
|
// Numbers
|
||||||
|
KeyCode_0, KeyCode_1, KeyCode_2, KeyCode_3, KeyCode_4, KeyCode_5, KeyCode_6, KeyCode_7,
|
||||||
|
KeyCode_8, KeyCode_9,
|
||||||
|
|
||||||
|
KeyCode_Num0, KeyCode_Num1, KeyCode_Num2, KeyCode_Num3, KeyCode_Num4, KeyCode_Num5,
|
||||||
|
KeyCode_Num6, KeyCode_Num7, KeyCode_Num8, KeyCode_Num9,
|
||||||
|
|
||||||
|
// Symbols
|
||||||
|
KeyCode_Bang, KeyCode_At, KeyCode_Pound, KeyCode_Dollar, KeyCode_Percent, KeyCode_Carrot,
|
||||||
|
KeyCode_Ampersand, KeyCode_Star, KeyCode_LeftParen, KeyCode_RightParen, KeyCode_Minus, KeyCode_Plus,
|
||||||
|
KeyCode_Equals, KeyCode_Underscore, KeyCode_LeftBrace, KeyCode_RightBrace, KeyCode_LeftBracket,
|
||||||
|
KeyCode_RightBracket, KeyCode_Colon, KeyCode_SemiColon, KeyCode_SingleQuote, KeyCode_DoubleQuote,
|
||||||
|
KeyCode_ForwardSlash, KeyCode_Backslash, KeyCode_Pipe, KeyCode_Comma, KeyCode_Period,
|
||||||
|
KeyCode_QuestionMark, KeyCode_LessThan, KeyCode_GreaterThan, KeyCode_Tilde, KeyCode_BackQuote,
|
||||||
|
|
||||||
|
// Arrows
|
||||||
|
KeyCode_UpArrow,
|
||||||
|
KeyCode_DownArrow,
|
||||||
|
KeyCode_LeftArrow,
|
||||||
|
KeyCode_RightArrow,
|
||||||
|
|
||||||
|
// Mouse
|
||||||
|
// NOTE(Peter): Including this here so we can utilize the same KeyDown, KeyUp etc. functions
|
||||||
|
KeyCode_MouseLeftButton,
|
||||||
|
KeyCode_MouseMiddleButton,
|
||||||
|
KeyCode_MouseRightButton,
|
||||||
|
|
||||||
|
KeyCode_Count,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef u8 Platform_Key_Flags;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
KeyFlag_None = 0,
|
||||||
|
|
||||||
|
KeyFlag_Mod_Shift = 1,
|
||||||
|
KeyFlag_Mod_Ctrl = 2,
|
||||||
|
KeyFlag_Mod_Alt = 4,
|
||||||
|
KeyFlag_Mod_Sys = 8,
|
||||||
|
|
||||||
|
KeyFlag_State_WasDown = 16,
|
||||||
|
KeyFlag_State_IsDown = 32,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Platform_Window_Event
|
||||||
|
{
|
||||||
|
Platform_Window_Event_Kind kind;
|
||||||
|
Platform_Key_Code key_code;
|
||||||
|
Platform_Key_Flags key_flags;
|
||||||
|
s32 mouse_x;
|
||||||
|
s32 mouse_y;
|
||||||
|
s32 scroll_amt;
|
||||||
|
char char_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Platform_Cursor_Kind
|
||||||
|
{
|
||||||
|
Cursor_Arrow,
|
||||||
|
Cursor_Pointer,
|
||||||
|
Cursor_Loading,
|
||||||
|
Cursor_HArrows,
|
||||||
|
Cursor_VArrows,
|
||||||
|
Cursor_DTopLeftArrows,
|
||||||
|
Cursor_DTopRightArrows,
|
||||||
|
Cursor_Count,
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Time
|
||||||
|
|
||||||
|
global r64 target_seconds_per_frame = 1.0 / 30.0f;
|
||||||
|
|
||||||
|
struct Platform_Ticks
|
||||||
|
{
|
||||||
|
s64 value;
|
||||||
|
};
|
||||||
|
|
||||||
|
Platform_Ticks platform_get_ticks();
|
||||||
|
r64 platform_ticks_to_seconds(Platform_Ticks ticks);
|
||||||
|
|
||||||
|
Platform_Ticks
|
||||||
|
get_ticks_elapsed(Platform_Ticks start, Platform_Ticks end)
|
||||||
|
{
|
||||||
|
Platform_Ticks result = {};
|
||||||
|
result.value = end.value - start.value;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
r64
|
||||||
|
get_seconds_elapsed(Platform_Ticks start, Platform_Ticks end)
|
||||||
|
{
|
||||||
|
Platform_Ticks diff = get_ticks_elapsed(start, end);
|
||||||
|
return platform_ticks_to_seconds(diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(PS): we have some stuff in v1 around system time, probably
|
||||||
|
// for timestamps etc.
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Threads
|
||||||
|
|
||||||
|
struct Platform_Thread_Handle
|
||||||
|
{
|
||||||
|
u64 value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Platform_Thread_Result
|
||||||
|
{
|
||||||
|
u32 code;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Platform_Thread_Data Platform_Thread_Data;
|
||||||
|
typedef Platform_Thread_Result Platform_Thread_Proc(Platform_Thread_Data* thread_data);
|
||||||
|
|
||||||
|
struct Platform_Thread_Data
|
||||||
|
{
|
||||||
|
Platform_Thread_Handle thread_handle;
|
||||||
|
u32 thread_id;
|
||||||
|
Platform_Thread_Proc* thread_proc;
|
||||||
|
Allocator* thread_memory;
|
||||||
|
u8* user_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
Platform_Thread_Handle platform_thread_begin(Platform_Thread_Proc* proc, u8* user_data);
|
||||||
|
void platform_thread_end(Platform_Thread_Handle thread_handle);
|
||||||
|
|
||||||
|
u32 platform_interlocked_increment(volatile u32* value);
|
||||||
|
u32 platform_interlocked_cmp_exchg(volatile u32* dest, u32 new_value, u32 old_value);
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Network Access
|
||||||
|
|
||||||
|
// TODO(PS):
|
||||||
|
|
||||||
|
struct Platform_Socket_Handle
|
||||||
|
{
|
||||||
|
u64 value;
|
||||||
|
};
|
||||||
|
|
||||||
|
Platform_Socket_Handle platform_socket_create();
|
||||||
|
bool platform_socket_bind();
|
||||||
|
bool platform_socket_connect();
|
||||||
|
bool platform_socket_close();
|
||||||
|
Data platform_socket_recv();
|
||||||
|
s32 platform_Socket_set_listening();
|
||||||
|
s32 platform_Socket_send();
|
||||||
|
s32 platform_Socket_send_to();
|
||||||
|
s32 platform_Socket_set_opt();
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// Graphics Integration
|
||||||
|
|
||||||
|
#endif //LUMENARIUM_PLATFORM_H
|
|
@ -0,0 +1,36 @@
|
||||||
|
/* date = March 22nd 2022 2:12 am */
|
||||||
|
|
||||||
|
#ifndef LUMENARIUM_PLATFORM_COMMON_INCLUDES_H
|
||||||
|
#define LUMENARIUM_PLATFORM_COMMON_INCLUDES_H
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#if !defined(GUESS_INTS)
|
||||||
|
# include <stdint.h>
|
||||||
|
#endif // !defined(GUESS_INTS)
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#define HMM_SINF sin
|
||||||
|
#define HMM_COSF cos
|
||||||
|
#define HMM_TANF tan
|
||||||
|
#define HMM_SQRTF sqrt
|
||||||
|
#define HMM_EXPF exp
|
||||||
|
#define HMM_LOGF log
|
||||||
|
#define HMM_ACOSF acos
|
||||||
|
#define HMM_ATANF atan
|
||||||
|
#define HMM_ATAN2F atan2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define HANDMADE_MATH_IMPLEMENTATION
|
||||||
|
#define HANDMADE_MATH_CPP_MODE
|
||||||
|
#define HANDMADE_MATH_STATIC
|
||||||
|
#include "../libs/HandmadeMath.h"
|
||||||
|
|
||||||
|
typedef hmm_v2 v2;
|
||||||
|
typedef hmm_v3 v3;
|
||||||
|
typedef hmm_v4 v4;
|
||||||
|
typedef hmm_mat4 m44;
|
||||||
|
|
||||||
|
#endif //LUMENARIUM_PLATFORM_COMMON_INCLUDES_H
|
|
@ -0,0 +1,28 @@
|
||||||
|
|
||||||
|
#include "../lumenarium_compiler_flags.h"
|
||||||
|
#include "../lumenarium_platform_common_includes.h"
|
||||||
|
|
||||||
|
#include "../../lumenarium_types.h"
|
||||||
|
#include "../lumenarium_platform.h"
|
||||||
|
#include "../../lumenarium_first.cpp"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "lumenarium_osx_memory.cpp"
|
||||||
|
|
||||||
|
int main (int arg_count, char** args)
|
||||||
|
{
|
||||||
|
App_State* state = lumenarium_init();
|
||||||
|
|
||||||
|
while (has_flag(state->flags, AppState_IsRunning))
|
||||||
|
{
|
||||||
|
// TODO(PS): event processing
|
||||||
|
|
||||||
|
lumenarium_update(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
lumenarium_cleanup(state);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
#define OSX_PAGE_SIZE KB(4) // TODO(PS): look this up
|
||||||
|
|
||||||
|
u64 platform_page_size() { return OSX_PAGE_SIZE; }
|
||||||
|
|
||||||
|
u8*
|
||||||
|
platform_mem_reserve(u64 size)
|
||||||
|
{
|
||||||
|
size_t size_cvt = (size_t)size_to_pages(size);
|
||||||
|
u8* result = (u8*)malloc(size);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8*
|
||||||
|
platform_mem_commit(u8* base, u64 size)
|
||||||
|
{
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
platform_mem_decommit(u8* base, u64 size)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
platform_mem_release(u8* base, u64 size)
|
||||||
|
{
|
||||||
|
free(base);
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
#define WEBGL_EXPORT __attribute__((visibility("default")))
|
||||||
|
#define WEBGL_EXTERN extern "C"
|
||||||
|
|
||||||
|
#define EXTERN_C_BEGIN extern "C" {
|
||||||
|
#define EXTERN_C_END }
|
||||||
|
|
||||||
|
WEBGL_EXTERN void print(char* text);
|
||||||
|
|
||||||
|
EXTERN_C_BEGIN;
|
||||||
|
|
||||||
|
WEBGL_EXPORT int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
print("Hi there!\n");
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXTERN_C_END;
|
|
@ -0,0 +1,249 @@
|
||||||
|
|
||||||
|
#include "../lumenarium_compiler_flags.h"
|
||||||
|
#include "../lumenarium_platform_common_includes.h"
|
||||||
|
|
||||||
|
#include "windows.h"
|
||||||
|
#include <gl/gl.h>
|
||||||
|
|
||||||
|
#include "../../lumenarium_types.h"
|
||||||
|
#include "../lumenarium_platform.h"
|
||||||
|
#include "../../lumenarium_first.cpp"
|
||||||
|
|
||||||
|
global DWORD win32_last_error = 0;
|
||||||
|
void
|
||||||
|
win32_get_last_error()
|
||||||
|
{
|
||||||
|
win32_last_error = GetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "lumenarium_win32_memory.cpp"
|
||||||
|
#include "lumenarium_win32_window.cpp"
|
||||||
|
#include "lumenarium_win32_time.cpp"
|
||||||
|
#include "lumenarium_win32_file.cpp"
|
||||||
|
#include "lumenarium_win32_thread.cpp"
|
||||||
|
|
||||||
|
internal Platform_Key_Flags
|
||||||
|
win32_get_key_flags_mod()
|
||||||
|
{
|
||||||
|
Platform_Key_Flags result = 0;
|
||||||
|
if (GetKeyState(VK_SHIFT) & 0x8000) add_flag(result, KeyFlag_Mod_Shift);
|
||||||
|
if (GetKeyState(VK_MENU) & 0x8000) add_flag(result, KeyFlag_Mod_Alt);
|
||||||
|
if (GetKeyState(VK_CONTROL) & 0x8000) add_flag(result, KeyFlag_Mod_Ctrl);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
win32_mouse_capture(Win32_Window* win)
|
||||||
|
{
|
||||||
|
// NOTE(Peter): We capture events when the mouse goes down so that
|
||||||
|
// if the user drags outside the window, we still get the mouse up
|
||||||
|
// event and can process it. Otherwise, we can get into cases where
|
||||||
|
// an event was started, didn't end, but the user can click again and
|
||||||
|
// try to start the event again.
|
||||||
|
// We relase event capture on mouse up.
|
||||||
|
SetCapture(win->window_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
win32_mouse_release(Win32_Window* win)
|
||||||
|
{
|
||||||
|
ReleaseCapture();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Platform_Window_Event
|
||||||
|
win32_button_event(Platform_Key_Code key, bool is_down, bool was_down)
|
||||||
|
{
|
||||||
|
Platform_Window_Event evt = {};
|
||||||
|
evt.kind = WindowEvent_ButtonDown;
|
||||||
|
evt.key_code = key;
|
||||||
|
evt.key_flags = win32_get_key_flags_mod();
|
||||||
|
if (is_down) add_flag(evt.key_flags, KeyFlag_State_IsDown);
|
||||||
|
if (was_down) add_flag(evt.key_flags, KeyFlag_State_WasDown);
|
||||||
|
return evt;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
win32_window_handle_event(MSG msg, Win32_Window* win, App_State* state)
|
||||||
|
{
|
||||||
|
switch (msg.message)
|
||||||
|
{
|
||||||
|
case WM_MOUSEWHEEL:
|
||||||
|
{
|
||||||
|
Platform_Window_Event evt = {};
|
||||||
|
evt.kind = WindowEvent_MouseScroll;
|
||||||
|
evt.scroll_amt = GET_WHEEL_DELTA_WPARAM(msg.wParam);
|
||||||
|
lumenarium_event(evt, state);
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case WM_LBUTTONDOWN:
|
||||||
|
{
|
||||||
|
Platform_Window_Event evt = win32_button_event(
|
||||||
|
KeyCode_MouseLeftButton,
|
||||||
|
true, false
|
||||||
|
);
|
||||||
|
lumenarium_event(evt, state);
|
||||||
|
win32_mouse_capture(win);
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case WM_MBUTTONDOWN:
|
||||||
|
{
|
||||||
|
Platform_Window_Event evt = win32_button_event(
|
||||||
|
KeyCode_MouseMiddleButton,
|
||||||
|
true, false
|
||||||
|
);
|
||||||
|
lumenarium_event(evt, state);
|
||||||
|
win32_mouse_capture(win);
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case WM_RBUTTONDOWN:
|
||||||
|
{
|
||||||
|
Platform_Window_Event evt = win32_button_event(
|
||||||
|
KeyCode_MouseRightButton,
|
||||||
|
true, false
|
||||||
|
);
|
||||||
|
lumenarium_event(evt, state);
|
||||||
|
win32_mouse_capture(win);
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case WM_LBUTTONUP:
|
||||||
|
{
|
||||||
|
Platform_Window_Event evt = win32_button_event(
|
||||||
|
KeyCode_MouseLeftButton,
|
||||||
|
false, true
|
||||||
|
);
|
||||||
|
lumenarium_event(evt, state);
|
||||||
|
win32_mouse_release(win);
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case WM_MBUTTONUP:
|
||||||
|
{
|
||||||
|
Platform_Window_Event evt = win32_button_event(
|
||||||
|
KeyCode_MouseMiddleButton,
|
||||||
|
false, true
|
||||||
|
);
|
||||||
|
lumenarium_event(evt, state);
|
||||||
|
win32_mouse_release(win);
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case WM_RBUTTONUP:
|
||||||
|
{
|
||||||
|
Platform_Window_Event evt = win32_button_event(
|
||||||
|
KeyCode_MouseRightButton,
|
||||||
|
false, true
|
||||||
|
);
|
||||||
|
lumenarium_event(evt, state);
|
||||||
|
win32_mouse_release(win);
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case WM_SYSKEYDOWN:
|
||||||
|
case WM_SYSKEYUP:
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
case WM_KEYUP:
|
||||||
|
{
|
||||||
|
Platform_Key_Code key = 0;
|
||||||
|
b32 was_down = (msg.lParam & (1 << 30)) != 0;
|
||||||
|
b32 is_down = (msg.lParam & (1 << 31)) == 0;
|
||||||
|
Platform_Window_Event evt = win32_button_event(key, is_down, was_down);
|
||||||
|
lumenarium_event(evt, state);
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case WM_CHAR:
|
||||||
|
{
|
||||||
|
Platform_Window_Event evt = {};
|
||||||
|
evt.kind = WindowEvent_Char;
|
||||||
|
evt.char_value = (char)msg.wParam;
|
||||||
|
lumenarium_event(evt, state);
|
||||||
|
}break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
INT WINAPI
|
||||||
|
WinMain(
|
||||||
|
HINSTANCE hInstance,
|
||||||
|
HINSTANCE hPrevInstance,
|
||||||
|
PSTR lpCmdLine,
|
||||||
|
INT nCmdShow)
|
||||||
|
{
|
||||||
|
|
||||||
|
App_State* state = lumenarium_init();
|
||||||
|
if (!has_flag(state->flags, AppState_IsRunning)) return 0;
|
||||||
|
|
||||||
|
// Window Setup
|
||||||
|
win32_main_window = win32_window_create(
|
||||||
|
hInstance, "Lumenarium", 1600, 900, win32_window_event_handler
|
||||||
|
);
|
||||||
|
win32_window_opengl_ctx_create(&win32_main_window, { 32, 8, 0 });
|
||||||
|
|
||||||
|
win32_time_init();
|
||||||
|
win32_files_init();
|
||||||
|
win32_threads_init();
|
||||||
|
|
||||||
|
Platform_Ticks ticks_start = platform_get_ticks();
|
||||||
|
while (has_flag(state->flags, AppState_IsRunning))
|
||||||
|
{
|
||||||
|
win32_threads_reclaim();
|
||||||
|
lumenarium_frame_prepare(state);
|
||||||
|
|
||||||
|
// Potentially pass the window closed event to the runtime
|
||||||
|
if (win32_window_event_flags & WindowEventFlag_CloseRequested)
|
||||||
|
{
|
||||||
|
Platform_Window_Event evt = {
|
||||||
|
WindowEvent_WindowClosed,
|
||||||
|
};
|
||||||
|
lumenarium_event(evt, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pass Window Events to the runtime
|
||||||
|
MSG window_msg;
|
||||||
|
while (PeekMessageA(
|
||||||
|
&window_msg,
|
||||||
|
win32_main_window.window_handle,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
PM_REMOVE)
|
||||||
|
){
|
||||||
|
win32_window_handle_event(window_msg, &win32_main_window, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
lumenarium_frame(state);
|
||||||
|
|
||||||
|
// Swap Render Buffers
|
||||||
|
SwapBuffers(win32_main_window.dc);
|
||||||
|
|
||||||
|
////////////////////////////////////////
|
||||||
|
// Maintain Frame Rate
|
||||||
|
|
||||||
|
Platform_Ticks ticks_end = platform_get_ticks();
|
||||||
|
r64 seconds_elapsed = get_seconds_elapsed(ticks_start, ticks_end);
|
||||||
|
while (seconds_elapsed < target_seconds_per_frame)
|
||||||
|
{
|
||||||
|
u32 sleep_time = (u32)(1000.0f * (target_seconds_per_frame - seconds_elapsed));
|
||||||
|
Sleep(sleep_time);
|
||||||
|
|
||||||
|
ticks_end = platform_get_ticks();
|
||||||
|
seconds_elapsed = get_seconds_elapsed(ticks_start, ticks_end);
|
||||||
|
}
|
||||||
|
ticks_start = ticks_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
lumenarium_cleanup(state);
|
||||||
|
|
||||||
|
|
||||||
|
// threads cleanup
|
||||||
|
for (u32 i = 1; i < win32_threads_cap; i++)
|
||||||
|
{
|
||||||
|
if (win32_threads[i] == INVALID_HANDLE_VALUE) continue;
|
||||||
|
TerminateThread(win32_threads[i], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExitProcess(0);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,258 @@
|
||||||
|
#define win32_open_files_cap 32
|
||||||
|
char win32_open_file_paths[win32_open_files_cap][MAX_PATH];
|
||||||
|
u64 win32_open_files_len = 1; // zero is invalid
|
||||||
|
HANDLE win32_open_files[win32_open_files_cap];
|
||||||
|
|
||||||
|
void
|
||||||
|
win32_files_init()
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < win32_open_files_cap; i++)
|
||||||
|
{
|
||||||
|
win32_open_files[i] = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE
|
||||||
|
win32_get_open_file_handle(Platform_File_Handle file)
|
||||||
|
{
|
||||||
|
return win32_open_files[file.value];
|
||||||
|
}
|
||||||
|
|
||||||
|
internal u64
|
||||||
|
win32_high_low_to_u64(u32 low_part, u32 high_part)
|
||||||
|
{
|
||||||
|
ULARGE_INTEGER Time = {};
|
||||||
|
Time.LowPart = low_part;
|
||||||
|
Time.HighPart = high_part;
|
||||||
|
u64 result = Time.QuadPart;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal u64
|
||||||
|
win32_file_time_to_u64(FILETIME file_time)
|
||||||
|
{
|
||||||
|
return win32_high_low_to_u64(file_time.dwLowDateTime, file_time.dwHighDateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
Platform_File_Handle
|
||||||
|
platform_file_open(String path, Platform_File_Access_Flags flags_access, Platform_File_Create_Flags flags_create)
|
||||||
|
{
|
||||||
|
Platform_File_Handle result = {};
|
||||||
|
|
||||||
|
DWORD flags_create_ = OPEN_EXISTING;
|
||||||
|
|
||||||
|
HANDLE file_handle = CreateFileA(
|
||||||
|
(char*)path.str,
|
||||||
|
(DWORD)flags_access,
|
||||||
|
0, // share mode
|
||||||
|
NULL, // security attributes
|
||||||
|
(DWORD)flags_create,
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
if (file_handle != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
if (win32_open_files_len < win32_open_files_cap)
|
||||||
|
{
|
||||||
|
result.value = win32_open_files_len++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// search for emtpy index
|
||||||
|
for (u32 i = 1; i < win32_open_files_cap; i++)
|
||||||
|
{
|
||||||
|
if (win32_open_files[i] == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
result.value = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(result.value != 0);
|
||||||
|
win32_open_files[result.value] = file_handle;
|
||||||
|
|
||||||
|
memory_copy(path.str, (u8*)win32_open_file_paths[result.value], path.len);
|
||||||
|
win32_open_file_paths[result.value][path.len] = 0; // null term
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
win32_get_last_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
platform_file_close(Platform_File_Handle file_handle)
|
||||||
|
{
|
||||||
|
assert(file_handle.value < win32_open_files_len);
|
||||||
|
CloseHandle(win32_get_open_file_handle(file_handle));
|
||||||
|
win32_open_files[file_handle.value] = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64
|
||||||
|
win32_get_file_size(HANDLE h)
|
||||||
|
{
|
||||||
|
DWORD size_low, size_high;
|
||||||
|
size_low = GetFileSize(h, &size_high);
|
||||||
|
if (size_low == INVALID_FILE_SIZE)
|
||||||
|
{
|
||||||
|
win32_get_last_error();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
LARGE_INTEGER win32_size;
|
||||||
|
win32_size.LowPart = size_low;
|
||||||
|
win32_size.HighPart = size_high;
|
||||||
|
return (u64)win32_size.QuadPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
Platform_File_Info
|
||||||
|
platform_file_get_info(Platform_File_Handle file_handle, Allocator* allocator)
|
||||||
|
{
|
||||||
|
Platform_File_Info result = {};
|
||||||
|
HANDLE h = win32_get_open_file_handle(file_handle);
|
||||||
|
if (h == INVALID_HANDLE_VALUE) return result;
|
||||||
|
|
||||||
|
// File Size
|
||||||
|
u64 win32_size = win32_get_file_size(h);
|
||||||
|
if (win32_size == 0 && win32_last_error != 0) return result;
|
||||||
|
|
||||||
|
// File Times
|
||||||
|
FILETIME time_created, time_last_write;
|
||||||
|
if (!GetFileTime(h, &time_created, (LPFILETIME)0, &time_last_write))
|
||||||
|
{
|
||||||
|
win32_get_last_error();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// File Path
|
||||||
|
// call GetFullPathName with empty dest just to get the length needed
|
||||||
|
DWORD file_name_len_needed = GetFullPathName(
|
||||||
|
win32_open_file_paths[file_handle.value], 0, 0, 0
|
||||||
|
);
|
||||||
|
if (!file_name_len_needed)
|
||||||
|
{
|
||||||
|
win32_get_last_error();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.path = allocator_alloc_string(allocator, (u64)file_name_len_needed);
|
||||||
|
result.path.len = (u64)GetFullPathName(
|
||||||
|
win32_open_file_paths[file_handle.value],
|
||||||
|
(DWORD)result.path.cap,
|
||||||
|
(char*)result.path.str,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
result.path_abs = result.path;
|
||||||
|
|
||||||
|
// File Attributes
|
||||||
|
DWORD file_attrs = GetFileAttributesA((char*)result.path.str);
|
||||||
|
if (!file_attrs)
|
||||||
|
{
|
||||||
|
win32_get_last_error();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.size = win32_size;
|
||||||
|
result.time_created = win32_file_time_to_u64(time_created);
|
||||||
|
result.time_last_write = win32_file_time_to_u64(time_last_write);
|
||||||
|
|
||||||
|
if (has_flag(file_attrs, FILE_ATTRIBUTE_DIRECTORY))
|
||||||
|
{
|
||||||
|
add_flag(result.flags, FileFlag_IsDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Data
|
||||||
|
platform_file_read_all(Platform_File_Handle file_handle, Allocator* allocator)
|
||||||
|
{
|
||||||
|
Data result = {};
|
||||||
|
|
||||||
|
HANDLE h = win32_get_open_file_handle(file_handle);
|
||||||
|
if (h == INVALID_HANDLE_VALUE) return result;
|
||||||
|
|
||||||
|
u64 file_size = win32_get_file_size(h);
|
||||||
|
if (file_size == 0 && win32_last_error != 0) return result;
|
||||||
|
|
||||||
|
result.base = allocator_alloc(allocator, file_size + 1);
|
||||||
|
result.size = file_size + 1;
|
||||||
|
|
||||||
|
DWORD bytes_read = 0;
|
||||||
|
if (ReadFile(h, (void*)result.base, (DWORD)result.size, &bytes_read, NULL))
|
||||||
|
{
|
||||||
|
result.base[result.size - 1] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
win32_get_last_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
platform_file_write_all(Platform_File_Handle file_handle, Data file_data)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
HANDLE h = win32_get_open_file_handle(file_handle);
|
||||||
|
if (h == INVALID_HANDLE_VALUE) return result;
|
||||||
|
|
||||||
|
// Set file pointer to beginning
|
||||||
|
SetFilePointer(h, 0, 0, FILE_BEGIN);
|
||||||
|
|
||||||
|
DWORD bytes_written = 0;
|
||||||
|
if (WriteFile(h, file_data.base, (DWORD)file_data.size, &bytes_written, NULL))
|
||||||
|
{
|
||||||
|
result = (bytes_written == file_data.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
platform_dir_enum_(String path, Platform_Enum_Dir_Flags flags, Allocator* allocator, Platform_File_Info_List* list)
|
||||||
|
{
|
||||||
|
WIN32_FIND_DATA ffd;
|
||||||
|
HANDLE search_handle = FindFirstFile((char*)path.str, &ffd);
|
||||||
|
if (search_handle != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Platform_File_Info_List_Ele* ele = allocator_alloc_struct(
|
||||||
|
allocator, Platform_File_Info_List_Ele
|
||||||
|
);
|
||||||
|
|
||||||
|
sll_push(list->first, list->last, ele);
|
||||||
|
} while (FindNextFile(search_handle, &ffd));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Platform_File_Info_List
|
||||||
|
platform_dir_enum(String path, Platform_Enum_Dir_Flags flags, Allocator* allocator)
|
||||||
|
{
|
||||||
|
Platform_File_Info_List result = {};
|
||||||
|
platform_dir_enum_(path, flags, allocator, &result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String
|
||||||
|
platform_get_exe_path(Allocator* allocator)
|
||||||
|
{
|
||||||
|
String result = allocator_alloc_string(allocator, (u64)MAX_PATH);
|
||||||
|
result.len = (u64)GetModuleFileName(NULL, (char*)result.str, (DWORD)result.cap);
|
||||||
|
if (!result.len) return result;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
platform_pwd_set(String path)
|
||||||
|
{
|
||||||
|
bool result = SetCurrentDirectory((char*)path.str);
|
||||||
|
if (!result) win32_get_last_error();
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
#define WIN32_PAGE_SIZE KB(4)
|
||||||
|
|
||||||
|
u64 platform_page_size() { return WIN32_PAGE_SIZE; }
|
||||||
|
|
||||||
|
u8*
|
||||||
|
platform_mem_reserve(u64 size)
|
||||||
|
{
|
||||||
|
size_t size_cvt = (size_t)size_to_pages(size);
|
||||||
|
DWORD alloc_type = MEM_RESERVE;
|
||||||
|
DWORD protection = PAGE_READWRITE;
|
||||||
|
u8* result = (u8*)VirtualAlloc(0, size_cvt, alloc_type, protection);
|
||||||
|
if (!result) win32_get_last_error();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8*
|
||||||
|
platform_mem_commit(u8* base, u64 size)
|
||||||
|
{
|
||||||
|
size_t size_cvt = (size_t)size_to_pages(size);
|
||||||
|
DWORD alloc_type = MEM_COMMIT;
|
||||||
|
DWORD protection = PAGE_READWRITE;
|
||||||
|
u8* result = (u8*)VirtualAlloc(base, size_cvt, alloc_type, protection);
|
||||||
|
if (!result) win32_get_last_error();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
platform_mem_decommit(u8* base, u64 size)
|
||||||
|
{
|
||||||
|
DWORD free_type = MEM_DECOMMIT;
|
||||||
|
bool result = VirtualFree(base, (size_t)size, free_type);
|
||||||
|
if (!result) win32_get_last_error();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
platform_mem_release(u8* base, u64 size)
|
||||||
|
{
|
||||||
|
DWORD free_type = MEM_RELEASE;
|
||||||
|
bool result = VirtualFree(base, size, free_type);
|
||||||
|
if (!result) win32_get_last_error();
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
|
||||||
|
#define win32_threads_cap 9
|
||||||
|
global u32 win32_threads_len = 1;
|
||||||
|
global HANDLE win32_threads[win32_threads_cap];
|
||||||
|
global Platform_Thread_Data win32_threads_data[win32_threads_cap];
|
||||||
|
|
||||||
|
DWORD WINAPI
|
||||||
|
win32_thread_wrapper(void* d)
|
||||||
|
{
|
||||||
|
Platform_Thread_Result result = {};
|
||||||
|
Platform_Thread_Data* thread_data = (Platform_Thread_Data*)d;
|
||||||
|
thread_data->thread_id = GetCurrentThreadId();
|
||||||
|
if (thread_data->thread_proc)
|
||||||
|
{
|
||||||
|
result = thread_data->thread_proc(thread_data);
|
||||||
|
}
|
||||||
|
return result.code;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
win32_threads_init()
|
||||||
|
{
|
||||||
|
for (u32 i = 1; i < win32_threads_cap; i++) win32_threads[i] = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
win32_threads_reclaim()
|
||||||
|
{
|
||||||
|
u32 highest_valid = 0;
|
||||||
|
for (u32 i = 1; i < win32_threads_cap; i++)
|
||||||
|
{
|
||||||
|
if (win32_threads[i] != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
highest_valid = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
win32_threads_len = highest_valid + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Platform_Thread_Handle
|
||||||
|
platform_thread_begin(Platform_Thread_Proc* proc, u8* user_data)
|
||||||
|
{
|
||||||
|
Platform_Thread_Handle result = {};
|
||||||
|
if (win32_threads_len < win32_threads_cap)
|
||||||
|
{
|
||||||
|
result.value = win32_threads_len++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (u32 i = 1; i < win32_threads_cap; i++)
|
||||||
|
{
|
||||||
|
if (win32_threads[i] == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
result.value = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(result.value != 0);
|
||||||
|
|
||||||
|
Platform_Thread_Data* thread_data = &win32_threads_data[result.value];
|
||||||
|
thread_data->thread_handle = result;
|
||||||
|
thread_data->thread_proc = proc;
|
||||||
|
thread_data->user_data = user_data;
|
||||||
|
|
||||||
|
HANDLE thread_handle = CreateThread(
|
||||||
|
0, 0, win32_thread_wrapper, (void*)thread_data, 0, 0
|
||||||
|
);
|
||||||
|
win32_threads[result.value] = thread_handle;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
platform_thread_end(Platform_Thread_Handle thread)
|
||||||
|
{
|
||||||
|
HANDLE thread_handle = win32_threads[thread.value];
|
||||||
|
TerminateThread(thread_handle, 0);
|
||||||
|
win32_threads[thread.value] = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32
|
||||||
|
platform_interlocked_increment(volatile u32* value)
|
||||||
|
{
|
||||||
|
return InterlockedIncrement((LONG volatile*)value);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32
|
||||||
|
platform_interlocked_cmp_exchg(volatile u32* dest, u32 new_value, u32 old_value)
|
||||||
|
{
|
||||||
|
return InterlockedCompareExchange((LONG volatile*)dest, new_value, old_value);
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
|
||||||
|
// set by calling win32_get_performance_frequency()
|
||||||
|
global s64 win32_performance_counter_freq_s64 = 0;
|
||||||
|
global r64 win32_performance_counter_freq_r64 = 0;
|
||||||
|
|
||||||
|
s64
|
||||||
|
win32_get_performance_frequency()
|
||||||
|
{
|
||||||
|
LARGE_INTEGER freq;
|
||||||
|
if (!QueryPerformanceFrequency(&freq))
|
||||||
|
{
|
||||||
|
win32_get_last_error();
|
||||||
|
// TODO(Peter): I'm waiting to see an error actually occur here
|
||||||
|
// to know what it could possibly be.
|
||||||
|
invalid_code_path;
|
||||||
|
}
|
||||||
|
return (s64)freq.QuadPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
win32_time_init()
|
||||||
|
{
|
||||||
|
win32_performance_counter_freq_s64 = win32_get_performance_frequency();
|
||||||
|
win32_performance_counter_freq_r64 = (r64)win32_performance_counter_freq_s64;
|
||||||
|
}
|
||||||
|
|
||||||
|
Platform_Ticks
|
||||||
|
platform_get_ticks()
|
||||||
|
{
|
||||||
|
Platform_Ticks result = {};
|
||||||
|
LARGE_INTEGER time;
|
||||||
|
if (!QueryPerformanceCounter(&time))
|
||||||
|
{
|
||||||
|
win32_get_last_error();
|
||||||
|
// TODO(Peter): I'm waiting to see an error actually occur here
|
||||||
|
// to know what it could possibly be.
|
||||||
|
invalid_code_path;
|
||||||
|
}
|
||||||
|
result.value = (s64)time.QuadPart;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
r64
|
||||||
|
platform_ticks_to_seconds(Platform_Ticks ticks)
|
||||||
|
{
|
||||||
|
r64 result = (r64)ticks.value / win32_performance_counter_freq_r64;
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,203 @@
|
||||||
|
typedef u32 Win32_Window_Event_Flags;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
WindowEventFlag_None = 0,
|
||||||
|
WindowEventFlag_CloseRequested = 1,
|
||||||
|
WindowEventFlag_WindowIsActive = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Win32_Window_OpenGL_Info
|
||||||
|
{
|
||||||
|
BYTE bits_color;
|
||||||
|
BYTE bits_alpha;
|
||||||
|
BYTE bits_depth;
|
||||||
|
|
||||||
|
HGLRC rc;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Win32_Window
|
||||||
|
{
|
||||||
|
char* name;
|
||||||
|
char* class_name;
|
||||||
|
s32 width;
|
||||||
|
s32 height;
|
||||||
|
|
||||||
|
WNDCLASS window_class;
|
||||||
|
WNDPROC window_event_handler;
|
||||||
|
HWND window_handle;
|
||||||
|
HDC dc;
|
||||||
|
|
||||||
|
Win32_Window_OpenGL_Info opengl_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////
|
||||||
|
// Main Window
|
||||||
|
//
|
||||||
|
// At the moment, we only need one window, so this is easier to
|
||||||
|
// track globally. Replace this if we need more windows
|
||||||
|
|
||||||
|
global Win32_Window_Event_Flags win32_window_event_flags = 0;
|
||||||
|
global Win32_Window win32_main_window = {};
|
||||||
|
|
||||||
|
//////////////////////////////////////////
|
||||||
|
//
|
||||||
|
|
||||||
|
internal Win32_Window
|
||||||
|
win32_window_create(
|
||||||
|
HINSTANCE hinstance,
|
||||||
|
char* window_name,
|
||||||
|
s32 width,
|
||||||
|
s32 height,
|
||||||
|
WNDPROC window_event_handler
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Win32_Window result = {};
|
||||||
|
result.name = window_name;
|
||||||
|
result.class_name = window_name;
|
||||||
|
result.width = width;
|
||||||
|
result.height = height;
|
||||||
|
result.window_event_handler = window_event_handler;
|
||||||
|
|
||||||
|
result.window_class = {};
|
||||||
|
result.window_class.style = CS_HREDRAW | CS_VREDRAW;
|
||||||
|
result.window_class.lpfnWndProc = window_event_handler;
|
||||||
|
result.window_class.hInstance = hinstance;
|
||||||
|
result.window_class.lpszClassName = window_name;
|
||||||
|
|
||||||
|
if (RegisterClass(&result.window_class))
|
||||||
|
{
|
||||||
|
result.window_handle = CreateWindowEx(
|
||||||
|
0,
|
||||||
|
result.window_class.lpszClassName,
|
||||||
|
window_name,
|
||||||
|
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
|
||||||
|
CW_USEDEFAULT,
|
||||||
|
CW_USEDEFAULT,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
hinstance,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
result.dc = GetDC(result.window_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
win32_window_update_dim(Win32_Window* win)
|
||||||
|
{
|
||||||
|
RECT client_rect;
|
||||||
|
GetClientRect(win->window_handle, &client_rect);
|
||||||
|
win->width = client_rect.right - client_rect.left;
|
||||||
|
win->height = client_rect.bottom - client_rect.top;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT CALLBACK
|
||||||
|
win32_window_event_handler(HWND window_handle, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||||
|
{
|
||||||
|
LRESULT result = 0;
|
||||||
|
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
case WM_SIZE:
|
||||||
|
{
|
||||||
|
win32_window_update_dim(&win32_main_window);
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case WM_CLOSE:
|
||||||
|
{
|
||||||
|
result = DefWindowProc(window_handle, msg, wparam, lparam);
|
||||||
|
add_flag(win32_window_event_flags, WindowEventFlag_CloseRequested);
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case WM_DESTROY:
|
||||||
|
{
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case WM_PAINT:
|
||||||
|
{
|
||||||
|
PAINTSTRUCT paint_struct;
|
||||||
|
HDC device_ctx;
|
||||||
|
b32 paint_result;
|
||||||
|
|
||||||
|
device_ctx = BeginPaint(window_handle, &paint_struct);
|
||||||
|
paint_result = EndPaint(window_handle, &paint_struct);
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case WM_ACTIVATE:
|
||||||
|
{
|
||||||
|
bool WindowIsActive = (
|
||||||
|
LOWORD(wparam) == WA_ACTIVE || LOWORD(wparam) == WA_CLICKACTIVE
|
||||||
|
);
|
||||||
|
if (WindowIsActive)
|
||||||
|
{
|
||||||
|
add_flag(win32_window_event_flags, WindowEventFlag_WindowIsActive);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rem_flag(win32_window_event_flags, WindowEventFlag_WindowIsActive);
|
||||||
|
}
|
||||||
|
}break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
result = DefWindowProc(window_handle, msg, wparam, lparam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
win32_window_opengl_ctx_create(Win32_Window* win, Win32_Window_OpenGL_Info info)
|
||||||
|
{
|
||||||
|
// Setup pixel format
|
||||||
|
{
|
||||||
|
PIXELFORMATDESCRIPTOR pixel_format_desc = { 0 };
|
||||||
|
// TODO: Program seems to work perfectly fine without all other params except dwFlags.
|
||||||
|
// Can we skip other params for the sake of brevity?
|
||||||
|
pixel_format_desc.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
||||||
|
pixel_format_desc.nVersion = 1;
|
||||||
|
pixel_format_desc.dwFlags = (
|
||||||
|
PFD_SUPPORT_OPENGL |
|
||||||
|
PFD_DRAW_TO_WINDOW |
|
||||||
|
PFD_DOUBLEBUFFER
|
||||||
|
);
|
||||||
|
pixel_format_desc.cColorBits = info.bits_color;
|
||||||
|
pixel_format_desc.cAlphaBits = info.bits_alpha;
|
||||||
|
pixel_format_desc.cDepthBits = info.bits_depth;
|
||||||
|
|
||||||
|
// TODO(Peter): include these in win32_opengl_window_info?
|
||||||
|
pixel_format_desc.iPixelType = PFD_TYPE_RGBA;
|
||||||
|
pixel_format_desc.dwLayerMask = PFD_MAIN_PLANE;
|
||||||
|
|
||||||
|
s32 pixel_fmt = ChoosePixelFormat(win->dc, &pixel_format_desc);
|
||||||
|
if (!pixel_fmt) { invalid_code_path; }
|
||||||
|
if (!SetPixelFormat(win->dc, pixel_fmt, &pixel_format_desc))
|
||||||
|
{
|
||||||
|
invalid_code_path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create rendering context
|
||||||
|
{
|
||||||
|
// TODO: Create "proper" context?
|
||||||
|
// https://www.opengl.org/wiki/Creating_an_OpenGL_Context_(WGL)#Proper_Context_Creation
|
||||||
|
|
||||||
|
info.rc = wglCreateContext(win->dc);
|
||||||
|
wglMakeCurrent(win->dc, info.rc);
|
||||||
|
|
||||||
|
// TODO(Peter): do we want this?
|
||||||
|
/*
|
||||||
|
glGetIntegerv(GL_MAJOR_VERSION, );
|
||||||
|
glGetIntegerv(GL_MINOR_VERSION, );
|
||||||
|
(char*)glGetString(GL_VENDOR);
|
||||||
|
(char*)glGetString(GL_RENDERER);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
win->opengl_info = info;
|
||||||
|
}
|
Loading…
Reference in New Issue