diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index f4f13cf..5375bbf 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -10,6 +10,7 @@ "UNICODE", "_UNICODE", "GEN_TIME", + "Build_Debug", ], "windowsSdkVersion": "10.0.22621.0", "compilerPath": "cl.exe", diff --git a/HandmadeHero.10x b/HandmadeHero.10x index 610cfe0..6bdde83 100644 --- a/HandmadeHero.10x +++ b/HandmadeHero.10x @@ -38,6 +38,8 @@ C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um + UNICODE + _UNICODE GEN_TIME diff --git a/handmade-hero-notes b/handmade-hero-notes index 0a6995a..6b43c05 160000 --- a/handmade-hero-notes +++ b/handmade-hero-notes @@ -1 +1 @@ -Subproject commit 0a6995a2cb6217d01b463bb4416c5d30c075333b +Subproject commit 6b43c05d4800c498eb3c9b24e976f9a7eddf3301 diff --git a/project/handmade_win32.cpp b/project/handmade_win32.cpp index 8b25d37..a08e7db 100644 --- a/project/handmade_win32.cpp +++ b/project/handmade_win32.cpp @@ -1,13 +1,172 @@ -#include "win32.h" +#if __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" +#endif -int CALLBACK WinMain( - HINSTANCE hInstance, - HINSTANCE hPrevInstance, - LPSTR lpCmdLine, - int nShowCmd +#include "grime.h" +#include "macros.h" +#include "types.h" + +#include "win32.h" +// using namespace win32; + +// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nc-winuser-wndproc +// https://learn.microsoft.com/en-us/windows/win32/winmsg/about-messages-and-message-queues#system-defined-messages +LRESULT CALLBACK MainWindowCallback( + HWND handle, + UINT system_messages, + WPARAM w_param, + LPARAM l_param ) { - MessageBox( 0, L"First message!", L"Handmade Hero", MB_OK | MB_ICONINFORMATION ); + LRESULT result; + + // https://learn.microsoft.com/en-us/windows/win32/winmsg/window-notifications + switch ( system_messages ) + { + case WM_ACTIVATEAPP: + { + OutputDebugStringA( "WM_ACTIVATEAPP\n" ); + } + break; + + case WM_CLOSE: + { + OutputDebugStringA( "WM_CLOSE\n" ); + } + break; + + case WM_DESTROY: + { + OutputDebugStringA( "WM_DESTROY\n" ); + } + break; + + case WM_PAINT: + { + PAINTSTRUCT info; + HDC device_context = BeginPaint( handle, & info ); + + u32 x = info.rcPaint.left; + u32 y = info.rcPaint.top; + u32 height = info.rcPaint.bottom - info.rcPaint.top; + u32 width = info.rcPaint.right - info.rcPaint.left; + + global DWORD operation = RO_Whiteness; + + PatBlt( device_context + , x, y + , width, height + , operation ); + + operation == RO_Whiteness ? + operation = RO_Blackness + : operation = RO_Whiteness; + + EndPaint( handle, & info ); + } + break; + + case WM_SIZE: + { + OutputDebugStringA( "WM_SIZE\n" ); + } + break; + + default: + { + OutputDebugStringA( "default\n" ); + result = DefWindowProc( handle, system_messages, w_param, l_param ); + } + } + + return result; +} + +int CALLBACK WinMain( + HINSTANCE instance, + HINSTANCE prev_instance, + LPSTR commandline, + int show_command +) +{ + // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox + // MessageBox( 0, L"First message!", L"Handmade Hero", MB_Ok_Btn | MB_Icon_Information ); + + // https://en.wikibooks.org/wiki/Windows_Programming/Window_Creation + // https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-wndclassa + WNDCLASS window_class {}; + // window_class.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; + window_class.style = CS_Own_Device_Context | CS_Horizontal_Redraw | CS_Vertical_Redraw; + window_class.lpfnWndProc = MainWindowCallback; + // window_class.cbClsExtra = ; + // window_class.cbWndExtra = ; + window_class.hInstance = instance; + // window_class.hIcon = ; + // window_class.hCursor = ; + // window_class.hbrBackground = ; + window_class.lpszMenuName = L"Handmade Hero!"; + window_class.lpszClassName = L"HandmadeHeroWindowClass"; + + if ( RegisterClassW( &window_class ) ) + { + // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexa + // https://learn.microsoft.com/en-us/windows/win32/winmsg/window-styles + HWND window_handle = CreateWindowExW( + 0, + window_class.lpszClassName, + L"Handmade Hero", + // WS_OVERLAPPEDWINDOW | WS_VISIBLE, + WS_Overlapped_Window | WS_Initially_Visible, + CW_USEDEFAULT, CW_USEDEFAULT, // x, y + CW_USEDEFAULT, CW_USEDEFAULT, // width, height + 0, 0, // parent, menu + instance, 0 // instance, param + ); + + if ( window_handle ) + { + // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow + // ShowWindow( window_handle, show_command ); + + // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-updatewindow + // UpdateWindow( window_handle ); + + // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmessage + MSG message; + for (;;) + { + BOOL msg_result = GetMessage( & message, 0, 0, 0 ); + if ( msg_result > 0 ) + { + // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-translatemessage + TranslateMessage( & message ); + + // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-dispatchmessage + DispatchMessage( & message ); + // break; + } + else + { + // TODO (Ed) : Logging + break; + } + } + } + else + { + // TODO (Ed) : Logging + } + } + else + { + // TODO(Ed) : Logging + } return 0; } diff --git a/project/platform/grime.h b/project/platform/grime.h new file mode 100644 index 0000000..77f1c17 --- /dev/null +++ b/project/platform/grime.h @@ -0,0 +1,111 @@ +#pragma region Platform Detection + +/* Platform architecture */ + +#if defined( _WIN64 ) || defined( __x86_64__ ) || defined( _M_X64 ) || defined( __64BIT__ ) || defined( __powerpc64__ ) || defined( __ppc64__ ) || defined( __aarch64__ ) +# ifndef GEN_ARCH_64_BIT +# define GEN_ARCH_64_BIT 1 +# endif +#else +# ifndef GEN_ARCH_32_BItxt_StrCaT +# define GEN_ARCH_32_BIT 1 +# endif +#endif + +/* Platform OS */ + +#if defined( _WIN32 ) || defined( _WIN64 ) +# ifndef GEN_SYSTEM_WINDOWS +# define GEN_SYSTEM_WINDOWS 1 +# endif +#elif defined( __APPLE__ ) && defined( __MACH__ ) +# ifndef GEN_SYSTEM_OSX +# define GEN_SYSTEM_OSX 1 +# endif +# ifndef GEN_SYSTEM_MACOS +# define GEN_SYSTEM_MACOS 1 +# endif +# include +# if TARGET_IPHONE_SIMULATOR == 1 || TARGET_OS_IPHONE == 1 +# ifndef GEN_SYSTEM_IOS +# define GEN_SYSTEM_IOS 1 +# endif +# endif +#elif defined( __unix__ ) +# ifndef GEN_SYSTEM_UNIX +# define GEN_SYSTEM_UNIX 1 +# endif +# if defined( ANDROID ) || defined( __ANDROID__ ) +# ifndef GEN_SYSTEM_ANDROID +# define GEN_SYSTEM_ANDROID 1 +# endif +# ifndef GEN_SYSTEM_LINUX +# define GEN_SYSTEM_LINUX 1 +# endif +# elif defined( __linux__ ) +# ifndef GEN_SYSTEM_LINUX +# define GEN_SYSTEM_LINUX 1 +# endif +# elif defined( __FreeBSD__ ) || defined( __FreeBSD_kernel__ ) +# ifndef GEN_SYSTEM_FREEBSD +# define GEN_SYSTEM_FREEBSD 1 +# endif +# elif defined( __OpenBSD__ ) +# ifndef GEN_SYSTEM_OPENBSD +# define GEN_SYSTEM_OPENBSD 1 +# endif +# elif defined( __EMSCRIPTEN__ ) +# ifndef GEN_SYSTEM_EMSCRIPTEN +# define GEN_SYSTEM_EMSCRIPTEN 1 +# endif +# elif defined( __CYGWIN__ ) +# ifndef GEN_SYSTEM_CYGWIN +# define GEN_SYSTEM_CYGWIN 1 +# endif +# else +# error This UNIX operating system is not supported +# endif +#else +# error This operating system is not supported +#endif + +/* Platform compiler */ + +#if defined( _MSC_VER ) +# define GEN_COMPILER_MSVC 1 +#elif defined( __GNUC__ ) +# define GEN_COMPILER_GCC 1 +#elif defined( __clang__ ) +# define GEN_COMPILER_CLANG 1 +#elif defined( __MINGW32__ ) +# define GEN_COMPILER_MINGW 1 +# error Unknown compiler +#endif + +#if defined( __has_attribute ) +# define GEN_HAS_ATTRIBUTE( attribute ) __has_attribute( attribute ) +#else +# define GEN_HAS_ATTRIBUTE( attribute ) ( 0 ) +#endif + +#if defined(GEN_GCC_VERSION_CHECK) +# undef GEN_GCC_VERSION_CHECK +#endif +#if defined(GEN_GCC_VERSION) +# define GEN_GCC_VERSION_CHECK(major,minor,patch) (GEN_GCC_VERSION >= GEN_VERSION_ENCODE(major, minor, patch)) +#else +# define GEN_GCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#pragma endregion Platform Detection + +#pragma region Mandatory Includes + +# include +# include + +# if defined( GEN_SYSTEM_WINDOWS ) +# include +# endif + +#pragma endregion Mandatory Includes diff --git a/project/platform/macros.h b/project/platform/macros.h new file mode 100644 index 0000000..faace17 --- /dev/null +++ b/project/platform/macros.h @@ -0,0 +1,5 @@ +// Keywords + +#define global static // Global variables +#define internal static // Internal linkage +#define local_persist static // Local Persisting variables diff --git a/project/platform/types.h b/project/platform/types.h new file mode 100644 index 0000000..693db15 --- /dev/null +++ b/project/platform/types.h @@ -0,0 +1,120 @@ +#pragma region Basic Types + +#define U8_MIN 0u +#define U8_MAX 0xffu +#define I8_MIN ( -0x7f - 1 ) +#define I8_MAX 0x7f + +#define U16_MIN 0u +#define U16_MAX 0xffffu +#define I16_MIN ( -0x7fff - 1 ) +#define I16_MAX 0x7fff + +#define U32_MIN 0u +#define U32_MAX 0xffffffffu +#define I32_MIN ( -0x7fffffff - 1 ) +#define I32_MAX 0x7fffffff + +#define U64_MIN 0ull +#define U64_MAX 0xffffffffffffffffull +#define I64_MIN ( -0x7fffffffffffffffll - 1 ) +#define I64_MAX 0x7fffffffffffffffll + +#if defined( GEN_ARCH_32_BIT ) +# define USIZE_MIN GEN_U32_MIN +# define USIZE_MAX GEN_U32_MAX +# define ISIZE_MIN GEN_S32_MIN +# define ISIZE_MAX GEN_S32_MAX +#elif defined( GEN_ARCH_64_BIT ) +# define USIZE_MIN GEN_U64_MIN +# define USIZE_MAX GEN_U64_MAX +# define ISIZE_MIN GEN_I64_MIN +# define ISIZE_MAX GEN_I64_MAX +#else +# error Unknown architecture size. This library only supports 32 bit and 64 bit architectures. +#endif + +#define F32_MIN 1.17549435e-38f +#define F32_MAX 3.40282347e+38f +#define F64_MIN 2.2250738585072014e-308 +#define F64_MAX 1.7976931348623157e+308 + +#if defined( GEN_COMPILER_MSVC ) +# if _MSC_VER < 1300 +typedef unsigned char u8; +typedef signed char s8; +typedef unsigned short u16; +typedef signed short s16; +typedef unsigned int u32; +typedef signed int s32; +# else +typedef unsigned __int8 u8; +typedef signed __int8 s8; +typedef unsigned __int16 u16; +typedef signed __int16 s16; +typedef unsigned __int32 u32; +typedef signed __int32 s32; +# endif +typedef unsigned __int64 u64; +typedef signed __int64 s64; +#else +# include + +typedef uint8_t u8; +typedef int8_t s8; +typedef uint16_t u16; +typedef int16_t s16; +typedef uint32_t u32; +typedef int32_t s32; +typedef uint64_t u64; +typedef int64_t s64; +#endif + +static_assert( sizeof( u8 ) == sizeof( s8 ), "sizeof(u8) != sizeof(s8)" ); +static_assert( sizeof( u16 ) == sizeof( s16 ), "sizeof(u16) != sizeof(s16)" ); +static_assert( sizeof( u32 ) == sizeof( s32 ), "sizeof(u32) != sizeof(s32)" ); +static_assert( sizeof( u64 ) == sizeof( s64 ), "sizeof(u64) != sizeof(s64)" ); + +static_assert( sizeof( u8 ) == 1, "sizeof(u8) != 1" ); +static_assert( sizeof( u16 ) == 2, "sizeof(u16) != 2" ); +static_assert( sizeof( u32 ) == 4, "sizeof(u32) != 4" ); +static_assert( sizeof( u64 ) == 8, "sizeof(u64) != 8" ); + +typedef size_t uw; +typedef ptrdiff_t sw; + +static_assert( sizeof( uw ) == sizeof( sw ), "sizeof(uw) != sizeof(sw)" ); + +// NOTE: (u)zpl_intptr is only here for semantic reasons really as this library will only support 32/64 bit OSes. +#if defined( _WIN64 ) +typedef signed __int64 sptr; +typedef unsigned __int64 uptr; +#elif defined( _WIN32 ) +// NOTE; To mark types changing their size, e.g. zpl_intptr +# ifndef _W64 +# if ! defined( __midl ) && ( defined( _X86_ ) || defined( _M_IX86 ) ) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +# endif +typedef _W64 signed int sptr; +typedef _W64 unsigned int uptr; +#else +typedef uintptr_t uptr; +typedef intptr_t sptr; +#endif + +static_assert( sizeof( uptr ) == sizeof( sptr ), "sizeof(uptr) != sizeof(sptr)" ); + +typedef float f32; +typedef double f64; + +static_assert( sizeof( f32 ) == 4, "sizeof(f32) != 4" ); +static_assert( sizeof( f64 ) == 8, "sizeof(f64) != 8" ); + +typedef s8 b8; +typedef s16 b16; +typedef s32 b32; + +#pragma endregion Basic Types diff --git a/project/platform/win32.h b/project/platform/win32.h index e4c48d3..064a8e5 100644 --- a/project/platform/win32.h +++ b/project/platform/win32.h @@ -5,8 +5,121 @@ Alternative header for windows.h #include "windows/windows_base.h" #include "windows/window.h" -#ifdef UNICODE -constexpr auto MessageBox = MessageBoxW; +// #ifdef Build_Debug +# include "windows/dbghelp.h" +// #endif + +#if Build_DLL +# define WIN_LIBRARY_API extern "C" __declspec(dllexport) #else -constexpr auto MessageBox = MessageBoxA; +# define WIN_LIBRARY_API extern "C" +#endif + +#ifndef CONST +# define CONST const +#endif + +#define WM_ACTIVATEAPP 0x001C + + +// namespace win32 { + +#ifdef UNICODE + constexpr auto CreateWindowEx = CreateWindowExW; +#else + constexpr auto CreateWindowEx = CreateWindowExA; #endif // !UNICODE + +#ifdef UNICODE + constexpr auto DefWindowProc = DefWindowProcW; +#else + constexpr auto DefWindowProc = DefWindowProcA; +#endif // !UNICODE + +#ifdef UNICODE + constexpr auto DispatchMessage = DispatchMessageW; +#else + constexpr auto DispatchMessage = DispatchMessageA; +#endif // !UNICODE + +#pragma region Message Function Templates +// From WinUser.h, modular headers lib doesn't have. + +WIN_LIBRARY_API BOOL WINAPI GetMessageA( + LPMSG lpMsg, + HWND hWnd, + UINT wMsgFilterMin, + UINT wMsgFilterMax); +WIN_LIBRARY_API BOOL WINAPI GetMessageW( + LPMSG lpMsg, + HWND hWnd, + UINT wMsgFilterMin, + UINT wMsgFilterMax); +#ifdef UNICODE + constexpr auto GetMessage = GetMessageW; +#else + constexpr auto GetMessage = GetMessageA; +#endif // !UNICODE + +#ifdef UNICODE + constexpr auto MessageBox = MessageBoxW; +#else + constexpr auto MessageBox = MessageBoxA; +#endif // !UNICODE + +#ifdef UNICODE + constexpr auto RegisterClass = RegisterClassW; +#else + constexpr auto RegisterClass = RegisterClassA; +#endif // !UNICODE +#pragma endregion Message Function Templates + +#pragma region Window PAINT +typedef struct tagPAINTSTRUCT { + HDC hdc; + BOOL fErase; + RECT rcPaint; + BOOL fRestore; + BOOL fIncUpdate; + BYTE rgbReserved[32]; +} PAINTSTRUCT, *PPAINTSTRUCT, *NPPAINTSTRUCT, *LPPAINTSTRUCT; + +WIN_LIBRARY_API HDC WINAPI +BeginPaint( HWND hWnd, LPPAINTSTRUCT lpPaint ); + +WIN_LIBRARY_API BOOL WINAPI +EndPaint( HWND hWnd, CONST PAINTSTRUCT *lpPaint ); + +WIN_LIBRARY_API BOOL WINAPI PatBlt( HDC hdc, int x, int y, int w, int h, DWORD rop ); +#pragma endregion Window PAINT + +// Class Style Constants +// https://learn.microsoft.com/en-us/windows/win32/winmsg/about-window-classes +// https://learn.microsoft.com/en-us/windows/win32/winmsg/window-class-styles + +enum CS : UINT +{ + CS_Own_Device_Context = CS_OWNDC, + CS_Horizontal_Redraw = CS_HREDRAW, + CS_Vertical_Redraw = CS_VREDRAW, +}; + +enum MB : UINT +{ + MB_Ok_Btn = MB_OK, + MB_Icon_Information = MB_ICONINFORMATION, +}; + +enum WS : UINT +{ + WS_Overlapped_Window = WS_OVERLAPPEDWINDOW, + WS_Initially_Visible = WS_VISIBLE, +}; + +enum RasterOps : DWORD +{ + RO_Blackness = (DWORD)0x00000042, + RO_Whiteness = (DWORD)0x00FF0062, +}; + +// } diff --git a/scripts/build.ps1 b/scripts/build.ps1 index d67f04a..9e13bf0 100644 --- a/scripts/build.ps1 +++ b/scripts/build.ps1 @@ -319,23 +319,26 @@ $linker_args = @( ) #region Handmade Generate -$unit = Join-Path $path_gen 'handmade_gen.cpp' -$executable = Join-Path $path_build 'handmade_gen.exe' - -build-simple $includes $compiler_args $linker_args $unit $executable -write-host - -& $executable -write-host - if ( $false ) { - Remove-Item (Get-ChildItem -Path $path_build -Recurse -Force) + $unit = Join-Path $path_gen 'handmade_gen.cpp' + $executable = Join-Path $path_build 'handmade_gen.exe' + + build-simple $includes $compiler_args $linker_args $unit $executable + write-host + + & $executable + write-host + + if ( $false ) { + Remove-Item (Get-ChildItem -Path $path_build -Recurse -Force) + } } #endregion Handmade Generate #region Handmade Runtime $lib_user32 = 'User32.lib' +$lib_gdi32 = 'Gdi32.lib' $unit = Join-Path $path_project 'handmade_win32.cpp' $executable = Join-Path $path_build 'handmade_win32.exe' @@ -343,6 +346,7 @@ $executable = Join-Path $path_build 'handmade_win32.exe' $compiler_args = @() $linker_args = @( + $lib_gdi32, $lib_user32, $flag_link_win_subsystem_windows )