some simulator improvements
This commit is contained in:
parent
c36917bb24
commit
17dc32acc6
|
@ -55,8 +55,11 @@ LPCSTR g_strWindowClass = "BorgSimulatorWindowClass";
|
||||||
LPCSTR g_strWindowTitle = "Borg Simulator";
|
LPCSTR g_strWindowTitle = "Borg Simulator";
|
||||||
|
|
||||||
LPCSTR g_strError = "Error";
|
LPCSTR g_strError = "Error";
|
||||||
LPCSTR g_strErrorRegisterWindow = "Error: Could not register window class.";
|
LPCSTR g_strErrorRegisterWindow = "Could not register window class.";
|
||||||
LPCSTR g_strErrorCreateWindow = "Error: Could not create window.";
|
LPCSTR g_strErrorCreateWindow = "Could not create window.";
|
||||||
|
LPCSTR g_strErrorCreateEvent = "Could not create wait event.";
|
||||||
|
LPCSTR g_strErrorCreateThread = "Could not create display loop thread.";
|
||||||
|
LPCSTR g_strErrorCreateUITimer = "Could not create UI Timer.";
|
||||||
|
|
||||||
|
|
||||||
/** Event object for the multimedia timer (wait() function). */
|
/** Event object for the multimedia timer (wait() function). */
|
||||||
|
@ -114,21 +117,27 @@ BOOL simCreateWindow(HWND *lphWnd,
|
||||||
HINSTANCE hInstance,
|
HINSTANCE hInstance,
|
||||||
int nCmdShow)
|
int nCmdShow)
|
||||||
{
|
{
|
||||||
|
BOOL bSuccess = FALSE;
|
||||||
|
|
||||||
|
/* ensure that the client area has the right proportions */
|
||||||
|
RECT rectMin = {0, 0, WND_X_EXTENTS * 1.5 - 1, WND_Y_EXTENTS * 1.5 - 1};
|
||||||
|
AdjustWindowRect(&rectMin, WS_OVERLAPPEDWINDOW & ~(WS_OVERLAPPED), FALSE);
|
||||||
|
|
||||||
/* create window and retrieve its handle */
|
/* create window and retrieve its handle */
|
||||||
*lphWnd = CreateWindow(g_strWindowClass, g_strWindowTitle,
|
*lphWnd = CreateWindow(g_strWindowClass, g_strWindowTitle,
|
||||||
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
|
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||||
WND_X_EXTENTS * 2, WND_Y_EXTENTS * 2, HWND_DESKTOP,
|
rectMin.right - rectMin.left, rectMin.bottom - rectMin.top,
|
||||||
NULL, hInstance, NULL);
|
HWND_DESKTOP, NULL, hInstance, NULL);
|
||||||
|
|
||||||
/* mske it visible */
|
/* make it visible */
|
||||||
if (*lphWnd != NULL)
|
if (*lphWnd != NULL)
|
||||||
{
|
{
|
||||||
ShowWindow(*lphWnd, nCmdShow);
|
ShowWindow(*lphWnd, nCmdShow);
|
||||||
UpdateWindow(*lphWnd);
|
UpdateWindow(*lphWnd);
|
||||||
return TRUE;
|
bSuccess = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
return bSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -201,8 +210,8 @@ void simDisplay(HWND hWnd)
|
||||||
/* retrieve window dimensions */
|
/* retrieve window dimensions */
|
||||||
if (GetClientRect(hWnd, &rect))
|
if (GetClientRect(hWnd, &rect))
|
||||||
{
|
{
|
||||||
int const cx = rect.right - rect.left;
|
int const cx = rect.right;
|
||||||
int const cy = rect.bottom - rect.top;
|
int const cy = rect.bottom;
|
||||||
|
|
||||||
/* retrieve device context */
|
/* retrieve device context */
|
||||||
if ((hdc = GetDC(hWnd)) != NULL)
|
if ((hdc = GetDC(hWnd)) != NULL)
|
||||||
|
@ -225,7 +234,7 @@ void simDisplay(HWND hWnd)
|
||||||
hBmp = CreateCompatibleBitmap(hdc, cx, cy);
|
hBmp = CreateCompatibleBitmap(hdc, cx, cy);
|
||||||
if (hBmp != NULL)
|
if (hBmp != NULL)
|
||||||
{
|
{
|
||||||
/* ...and selct that into that DC */
|
/* ...and select that into that DC */
|
||||||
hOldBmp = (HBITMAP)SelectObject(hMemDc, hBmp);
|
hOldBmp = (HBITMAP)SelectObject(hMemDc, hBmp);
|
||||||
|
|
||||||
/* finally *sigh* draw the LED matrix */
|
/* finally *sigh* draw the LED matrix */
|
||||||
|
@ -257,17 +266,30 @@ LRESULT CALLBACK simWndProc(HWND hWnd,
|
||||||
WPARAM wParam,
|
WPARAM wParam,
|
||||||
LPARAM lParam)
|
LPARAM lParam)
|
||||||
{
|
{
|
||||||
|
LRESULT lResult = 0;
|
||||||
PAINTSTRUCT ps;
|
PAINTSTRUCT ps;
|
||||||
HDC hdc;
|
HDC hdc;
|
||||||
LPMINMAXINFO lpminmax;
|
LPMINMAXINFO lpminmax;
|
||||||
|
|
||||||
|
/* minimum size of the window's client area */
|
||||||
|
RECT rectMin = {0, 0, WND_X_EXTENTS - 1, WND_Y_EXTENTS - 1};
|
||||||
|
|
||||||
switch (msg)
|
switch (msg)
|
||||||
{
|
{
|
||||||
/* enforce minimum window size */
|
/* enforce minimum window size */
|
||||||
case WM_GETMINMAXINFO:
|
case WM_GETMINMAXINFO:
|
||||||
|
/* minimum size applies to client area */
|
||||||
|
AdjustWindowRect(&rectMin, GetWindowLongA(hWnd, GWL_STYLE),
|
||||||
|
GetMenu(hWnd) != NULL);
|
||||||
|
|
||||||
|
/* actually set minimum and maximum size */
|
||||||
lpminmax = (LPMINMAXINFO)lParam;
|
lpminmax = (LPMINMAXINFO)lParam;
|
||||||
lpminmax->ptMinTrackSize.x = WND_X_EXTENTS * 2;
|
lpminmax->ptMinTrackSize.x = rectMin.right - rectMin.left;
|
||||||
lpminmax->ptMinTrackSize.y = WND_Y_EXTENTS * 2;
|
lpminmax->ptMinTrackSize.y = rectMin.bottom - rectMin.top;
|
||||||
|
lpminmax->ptMaxTrackSize.x = GetSystemMetrics(SM_CXMAXTRACK);
|
||||||
|
lpminmax->ptMaxTrackSize.y = GetSystemMetrics(SM_CYMAXTRACK);
|
||||||
|
lpminmax->ptMaxSize.x = GetSystemMetrics(SM_CXMAXTRACK);
|
||||||
|
lpminmax->ptMaxSize.y = GetSystemMetrics(SM_CYMAXTRACK);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* paint window contents */
|
/* paint window contents */
|
||||||
|
@ -310,7 +332,7 @@ LRESULT CALLBACK simWndProc(HWND hWnd,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return DefWindowProcA(hWnd, msg, wParam, lParam);
|
lResult = DefWindowProcA(hWnd, msg, wParam, lParam);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -340,7 +362,7 @@ LRESULT CALLBACK simWndProc(HWND hWnd,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return DefWindowProcA(hWnd, msg, wParam, lParam);
|
lResult = DefWindowProcA(hWnd, msg, wParam, lParam);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -348,6 +370,7 @@ LRESULT CALLBACK simWndProc(HWND hWnd,
|
||||||
/* refresh the LED matrix every 40 ms */
|
/* refresh the LED matrix every 40 ms */
|
||||||
case WM_TIMER:
|
case WM_TIMER:
|
||||||
simDisplay(hWnd);
|
simDisplay(hWnd);
|
||||||
|
UpdateWindow(hWnd);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* quit application */
|
/* quit application */
|
||||||
|
@ -357,11 +380,11 @@ LRESULT CALLBACK simWndProc(HWND hWnd,
|
||||||
|
|
||||||
/* Windows' default handler */
|
/* Windows' default handler */
|
||||||
default:
|
default:
|
||||||
return DefWindowProcA(hWnd, msg, wParam, lParam);
|
lResult = DefWindowProcA(hWnd, msg, wParam, lParam);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return lResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -391,8 +414,10 @@ void wait(int ms)
|
||||||
UINT uResolution;
|
UINT uResolution;
|
||||||
|
|
||||||
/* check if fire button is pressed (and if it is, jump to the menu) */
|
/* check if fire button is pressed (and if it is, jump to the menu) */
|
||||||
if (waitForFire) {
|
if (waitForFire)
|
||||||
if (fakeport & 0x01) {
|
{
|
||||||
|
if (fakeport & 0x01)
|
||||||
|
{
|
||||||
longjmp(newmode_jmpbuf, 43);
|
longjmp(newmode_jmpbuf, 43);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -407,12 +432,13 @@ void wait(int ms)
|
||||||
if (mmresult == TIMERR_NOERROR)
|
if (mmresult == TIMERR_NOERROR)
|
||||||
{
|
{
|
||||||
/* actually retrieve a multimedia timer */
|
/* actually retrieve a multimedia timer */
|
||||||
mmTimerEventId = timeSetEvent(ms, uResolution, g_hWaitEvent, NULL,
|
mmTimerEventId = timeSetEvent(ms, uResolution, g_hWaitEvent, 0,
|
||||||
TIME_ONESHOT | TIME_CALLBACK_EVENT_PULSE);
|
TIME_ONESHOT | TIME_CALLBACK_EVENT_SET);
|
||||||
if (mmTimerEventId != NULL)
|
if (mmTimerEventId != 0)
|
||||||
{
|
{
|
||||||
/* now halt until that timer pulses our wait event object */
|
/* now halt until that timer pulses our wait event object */
|
||||||
WaitForSingleObject(g_hWaitEvent, INFINITE);
|
WaitForSingleObject(g_hWaitEvent, INFINITE);
|
||||||
|
ResetEvent(g_hWaitEvent);
|
||||||
|
|
||||||
/* relieve the timer from its duties */
|
/* relieve the timer from its duties */
|
||||||
timeKillEvent(mmTimerEventId);
|
timeKillEvent(mmTimerEventId);
|
||||||
|
@ -441,58 +467,79 @@ int APIENTRY WinMain(HINSTANCE hInstance,
|
||||||
WNDCLASS wc;
|
WNDCLASS wc;
|
||||||
HWND hWnd;
|
HWND hWnd;
|
||||||
MSG msg;
|
MSG msg;
|
||||||
HANDLE hThread;
|
HANDLE hLoopThread;
|
||||||
UINT_PTR uTimerId;
|
UINT_PTR uTimerId;
|
||||||
|
int nExitCode = 0;
|
||||||
|
|
||||||
/* regster window class (with nice black background!) */
|
/* register window class (with nice black background!) and create window */
|
||||||
if (simRegisterWindowClass(&wc, hInstance))
|
if (simRegisterWindowClass(&wc, hInstance))
|
||||||
{
|
{
|
||||||
/* actually create the window and make it visible */
|
|
||||||
if (simCreateWindow(&hWnd, hInstance, nCmdShow))
|
if (simCreateWindow(&hWnd, hInstance, nCmdShow))
|
||||||
{
|
{
|
||||||
/* event handle for multimedia timer (for the wait() function) */
|
/* event handle for multimedia timer (for the wait() function) */
|
||||||
g_hWaitEvent = CreateEventA(NULL, FALSE, FALSE, "Local\\WaitEvent");
|
g_hWaitEvent = CreateEventA(NULL, TRUE, FALSE, "Local\\WaitEvent");
|
||||||
if (g_hWaitEvent != NULL)
|
if (g_hWaitEvent != NULL)
|
||||||
{
|
{
|
||||||
/* start the display loop thread */
|
/* start the display loop thread */
|
||||||
hThread = CreateThread(NULL, 0, simLoop, NULL, 0, NULL);
|
hLoopThread = CreateThread(NULL, 0, simLoop, NULL, 0, NULL);
|
||||||
if (hThread != NULL)
|
if (hLoopThread != NULL)
|
||||||
{
|
{
|
||||||
/* ensure that the display loop stays responsive */
|
SetThreadPriority(hLoopThread, THREAD_PRIORITY_HIGHEST);
|
||||||
SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);
|
|
||||||
|
|
||||||
/* issue a UI timer message every 40 ms (roughly 25 fps) */
|
/* issue a UI timer message every 40 ms (roughly 25 fps) */
|
||||||
/* NOTE: this has nothing to do with the multimedia timer */
|
|
||||||
uTimerId = SetTimer(hWnd, 23, 40, NULL);
|
uTimerId = SetTimer(hWnd, 23, 40, NULL);
|
||||||
if (uTimerId != NULL)
|
if (uTimerId != 0)
|
||||||
{
|
{
|
||||||
/* standard Windows(R) message loop */
|
/* standard Windows(R) message loop */
|
||||||
/* (runs as long as the window hasn't been closed) */
|
|
||||||
while (GetMessageA(&msg, NULL, 0, 0))
|
while (GetMessageA(&msg, NULL, 0, 0))
|
||||||
{
|
{
|
||||||
TranslateMessage(&msg);
|
TranslateMessage(&msg);
|
||||||
DispatchMessageA(&msg);
|
DispatchMessageA(&msg);
|
||||||
}
|
}
|
||||||
|
nExitCode = msg.wParam;
|
||||||
|
|
||||||
/* remove that UI timer */
|
|
||||||
KillTimer(hWnd, uTimerId);
|
KillTimer(hWnd, uTimerId);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MessageBoxA(HWND_DESKTOP, g_strErrorCreateUITimer,
|
||||||
|
g_strError, MB_OK | MB_ICONERROR);
|
||||||
|
}
|
||||||
|
|
||||||
/* stop the display loop */
|
TerminateThread(hLoopThread, 0);
|
||||||
TerminateThread(hThread, 0);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MessageBoxA(HWND_DESKTOP, g_strErrorCreateThread,
|
||||||
|
g_strError, MB_OK | MB_ICONERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* relieve wait event object from its duties */
|
/* relieve wait event object from its duties */
|
||||||
CloseHandle(g_hWaitEvent);
|
CloseHandle(g_hWaitEvent);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MessageBoxA(HWND_DESKTOP, g_strErrorCreateEvent,
|
||||||
|
g_strError, MB_OK | MB_ICONERROR);
|
||||||
|
}
|
||||||
|
|
||||||
return msg.wParam;
|
DestroyWindow(hWnd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MessageBoxA(HWND_DESKTOP, g_strErrorCreateWindow,
|
||||||
|
g_strError, MB_OK | MB_ICONERROR);
|
||||||
}
|
}
|
||||||
MessageBoxA(HWND_DESKTOP, g_strErrorCreateWindow, g_strError, MB_OK);
|
|
||||||
}
|
|
||||||
MessageBoxA(HWND_DESKTOP, g_strErrorRegisterWindow, g_strError, MB_OK);
|
|
||||||
|
|
||||||
return 0;
|
UnregisterClassA(g_strWindowClass, hInstance);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MessageBoxA(HWND_DESKTOP, g_strErrorRegisterWindow,
|
||||||
|
g_strError, MB_OK | MB_ICONERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nExitCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
|
Loading…
Reference in New Issue