some simulator improvements

This commit is contained in:
Christian Kroll 2012-10-20 01:56:36 +00:00
parent c36917bb24
commit 17dc32acc6
1 changed files with 87 additions and 40 deletions

View File

@ -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
return msg.wParam; {
MessageBoxA(HWND_DESKTOP, g_strErrorCreateEvent,
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; DestroyWindow(hWnd);
}
else
{
MessageBoxA(HWND_DESKTOP, g_strErrorCreateWindow,
g_strError, MB_OK | MB_ICONERROR);
}
UnregisterClassA(g_strWindowClass, hInstance);
}
else
{
MessageBoxA(HWND_DESKTOP, g_strErrorRegisterWindow,
g_strError, MB_OK | MB_ICONERROR);
}
return nExitCode;
} }
/*@}*/ /*@}*/