Created
February 11, 2018 14:49
-
-
Save dwilliamson/2262f68021cb71ef37530c5e8678f39f to your computer and use it in GitHub Desktop.
Old K-Libs game engine snippet
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
=============================================================================================== | |
K-Libs, Kernel, WINMAIN.C | |
------------------------------------- | |
by Don Williamson, 1999 | |
=============================================================================================== | |
*/ | |
#include <windows.h> | |
#include "types.h" | |
#include "resource.h" | |
#include "utility.h" | |
#include "memory.h" | |
#include "timing.h" | |
#define kMSGLOOP_THREAD 1 | |
#define kMSGLOOP_NORMAL 2 | |
#define kMSGLOOP_POLLED 4 | |
extern uBYTE kSetupMessageLoop(void); | |
/* --- Private variables --- */ | |
static uBYTE message_loop; | |
static LPSTR lpCmdGlobal; | |
static int nShowGlobal; | |
static HANDLE hThread; | |
static DWORD nThreadId; | |
static volatile uBYTE ThreadReady = 0; | |
/* --- Global variables --- */ | |
HINSTANCE kInstance = 0; | |
HWND khWnd = 0; | |
LPSTR kClassName = "K-Lib Class"; | |
int (*main_function)(int argc, char **argv) = NULL; | |
long (*message_handler)(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) = NULL; | |
int (*main_loop)(void) = NULL; | |
void (*abnormal_exit)(void) = NULL; | |
void (*normal_exit)(void) = NULL; | |
int (*main_init)(void) = NULL; | |
/* | |
================================================================================================== | |
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Globally used functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
================================================================================================== | |
*/ | |
long WINAPI MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) | |
{ | |
// Check to see if there is a user-defined message handling function | |
if (message_handler) | |
{ | |
long retval; | |
// The function should return TRUE if the message was processed | |
retval = message_handler(hWnd, message, wParam, lParam); | |
if (retval) return (0L); | |
} | |
// Decide what to do with the message | |
switch (message) | |
{ | |
case (WM_COMMAND): | |
return (0L); | |
// Handle the X click to close a window | |
case (WM_CLOSE): | |
SendMessage(khWnd, WM_DESTROY, 0, 0); | |
return (0L); | |
// Return 0 to the message loop to terminate it | |
case (WM_DESTROY): | |
PostQuitMessage(0); | |
return (0L); | |
} | |
// Message has not been catered for so pass onto the default window procedure | |
return (DefWindowProc(hWnd, message, wParam, lParam)); | |
} | |
static int InitApplication(void) | |
{ | |
WNDCLASS wc; | |
// Setup the needed window class | |
wc.cbClsExtra = 0; | |
wc.cbWndExtra = 0; | |
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW); | |
wc.hCursor = LoadCursor(NULL, IDC_ARROW); | |
wc.hIcon = LoadIcon(kInstance, NULL); | |
wc.hInstance = kInstance; | |
wc.lpfnWndProc = MainWndProc; | |
wc.lpszClassName = kClassName; | |
wc.lpszMenuName = NULL; | |
wc.style = CS_HREDRAW | CS_VREDRAW; | |
// Attempt to register the class with windows | |
if (!RegisterClass(&wc)) return (kFALSE); | |
// Create the application window | |
khWnd = CreateWindowEx(0, kClassName, kClassName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, | |
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, kInstance, NULL); | |
if (khWnd == NULL) return (kFALSE); | |
// Update the window | |
UpdateWindow(khWnd); | |
ShowWindow(khWnd, nShowGlobal); | |
return (kTRUE); | |
} | |
/* | |
================================================================================================== | |
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Thread message loop functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
================================================================================================== | |
*/ | |
DWORD WINAPI ThreadMessageLoop(LPVOID parameter) | |
{ | |
MSG message; | |
// Create the window in this thread and continue if successful | |
if (InitApplication()) | |
{ | |
// Flag that the application can continue processing | |
ThreadReady = 1; | |
// Loop infinitely | |
while (1) | |
{ | |
// Check to see if there is a message in the queue | |
if (PeekMessage(&message, NULL, 0, 0, PM_NOREMOVE)) | |
{ | |
// Terminate thread if application message queue terminates | |
if (!GetMessage(&message, NULL, 0, 0)) return (kTRUE); | |
// Translate accelerators and pass everything onto the message loop | |
TranslateMessage(&message); | |
DispatchMessage(&message); | |
} | |
// If not, sit idle until one occurs | |
else | |
{ | |
WaitMessage(); | |
} | |
} | |
} | |
// Even though it is not ready, avoid a crashing infinite loop | |
ThreadReady = 1; | |
return (kFALSE); | |
} | |
int ExecuteApplication_Thread(void) | |
{ | |
int retval = kFALSE; | |
// Create the message loop's host thread | |
hThread = CreateThread(NULL, 0, (LPVOID)&ThreadMessageLoop, NULL, 0, &nThreadId); | |
if (hThread == NULL) return (kFALSE); | |
// Wait until the thread creates the application window | |
while (!ThreadReady) { } | |
// If a "main" function exists, call it to enter the application | |
if (main_function) | |
retval = main_function(__argc, __argv); | |
// Tell the thread message loop to destroy itself and the window | |
SendMessage(khWnd, WM_DESTROY, 0, 0); | |
CloseHandle(hThread); | |
return (retval); | |
} | |
/* | |
================================================================================================== | |
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Normal message loop functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
================================================================================================== | |
*/ | |
int ExecuteApplication_Normal(void) | |
{ | |
MSG message; | |
int retval = kFALSE; | |
// Create the window | |
if (!InitApplication()) return (kFALSE); | |
// Execute the init function if one exists | |
if (main_init) | |
if (!main_init()) SendMessage(khWnd, WM_DESTROY, 0, 0); | |
// Loop infinitely | |
while (1) | |
{ | |
// Check to see if there are any messages waiting in the queue | |
if (PeekMessage(&message, NULL, 0, 0, PM_NOREMOVE)) | |
{ | |
// Terminate loop if application message queue terminates | |
if (!GetMessage(&message, NULL, 0, 0)) return (kTRUE); | |
// Translate accelerators and pass everything onto the message loop | |
TranslateMessage(&message); | |
DispatchMessage(&message); | |
} | |
else | |
{ | |
// If there is a "main_loop" function, call it | |
if (main_loop) | |
{ | |
// The "main_loop" function should return FALSE to abort the application | |
retval = main_loop(); | |
if (retval == 0) SendMessage(khWnd, WM_DESTROY, 0, 0); | |
} | |
} | |
} | |
return (retval); | |
} | |
/* | |
================================================================================================== | |
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Polled message loop functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
================================================================================================== | |
*/ | |
void kPollMessageQueue(void) | |
{ | |
MSG message; | |
// Continuously remove all messages until there are none left | |
while (PeekMessage(&message, khWnd, 0, 0, PM_REMOVE)) | |
{ | |
// Translate accelerators and pass everything onto the message handler | |
TranslateMessage(&message); | |
DispatchMessage(&message); | |
} | |
} | |
int ExecuteApplication_Polled(void) | |
{ | |
int retval = kFALSE; | |
// Create the application window | |
if (!InitApplication()) return (kFALSE); | |
// If a main function exists, call it to enter the application | |
if (main_function) | |
retval = main_function(__argc, __argv); | |
// Destroy the application window | |
SendMessage(khWnd, WM_DESTROY, 0, 0); | |
kPollMessageQueue(); | |
return (retval); | |
} | |
/* | |
================================================================================================== | |
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> WINMAIN <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
================================================================================================== | |
*/ | |
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) | |
{ | |
int retval = kFALSE; | |
// Initialise the K-Lib memory sub-system | |
if (kInitAllMemory() == kFALSE) | |
return (kFALSE); | |
// Obtain the message loop type and quit if required | |
if ((message_loop = kSetupMessageLoop()) == 0) | |
{ | |
kCloseAllMemory(); | |
return (kFALSE); | |
} | |
// Setup the needed global variables | |
lpCmdGlobal = lpCmdLine; | |
nShowGlobal = nCmdShow; | |
kInstance = hInstance; | |
// Execute the first block of code unconditionally | |
__try | |
{ | |
// Decide where to further the application and it's resources | |
if (message_loop == kMSGLOOP_THREAD) retval = ExecuteApplication_Thread(); | |
if (message_loop == kMSGLOOP_NORMAL) retval = ExecuteApplication_Normal(); | |
if (message_loop == kMSGLOOP_POLLED) retval = ExecuteApplication_Polled(); | |
} | |
// The next block is called normally or if an exception occurs | |
__finally | |
{ | |
if (AbnormalTermination()) | |
{ | |
// Call the user defined abnormal termination function if one exists | |
if (abnormal_exit) | |
abnormal_exit(); | |
} | |
// Call the user defined normal termination function if one exists | |
if (normal_exit) | |
normal_exit(); | |
// Shut down all resources | |
CloseUtil(); | |
} | |
// Destroy all created timers | |
kDestroyAllTimers(); | |
// Shutdown the K-Lib memory sub-system | |
kCloseAllMemory(); | |
return (retval); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment