Projects/tigris
Projects
/
tigris
Archived
5
0
Fork 0
This repository has been archived on 2024-07-04. You can view files and clone it, but cannot push or open issues or pull requests.
tigris/TIKI-100_emul-src/win32.c

793 lines
26 KiB
C
Raw Permalink Normal View History

2008-09-01 12:30:26 +02:00
/* win32.c V1.1.1
*
* Win32 systemspesifikk kode for TIKI-100_emul
* Copyright (C) Asbj<EFBFBD>rn Djupdal 2000-2001
*/
#include "TIKI-100_emul.h"
#include "win32_res.h"
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#include <commctrl.h>
#define ERROR_CAPTION "TIKI-100_emul feilmelding"
#define STATUSBAR_HEIGHT 19
/* protos */
int WINAPI WinMain (HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode);
static LRESULT CALLBACK WindowFunc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
static BOOL CALLBACK DialogFunc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
static void update (int x, int y, int w, int h);
static void draw3dBox (int x, int y, int w, int h);
static void getDiskImage (int drive);
static void saveDiskImage (int drive);
static void setParam (HANDLE portHandle, struct serParams *params);
/* variabler */
static byte keyTable[256] = {
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
KEY_SLETT, KEY_BRYT, KEY_NONE, KEY_NONE, KEY_NONE, KEY_CR, KEY_NONE, KEY_NONE,
KEY_SHIFT, KEY_CTRL, KEY_NONE, KEY_NONE, KEY_LOCK, KEY_NONE, KEY_NONE, KEY_NONE,
KEY_NONE, KEY_NONE, KEY_NONE, KEY_ANGRE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
KEY_SPACE, KEY_PGUP, KEY_PGDOWN, KEY_TABRIGHT, KEY_HOME, KEY_LEFT, KEY_UP, KEY_RIGHT,
KEY_DOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_UTVID, KEY_TABLEFT, KEY_NONE,
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
KEY_NONE, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
KEY_NUM0, KEY_NUM1, KEY_NUM2, KEY_NUM3, KEY_NUM4, KEY_NUM5, KEY_NUM6, KEY_NUM7,
KEY_NUM8, KEY_NUM9, KEY_NUMMULT, KEY_NUMPLUS, KEY_NONE, KEY_NUMMINUS, KEY_NUMDOT, KEY_NUMDIV,
KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_NONE, KEY_HJELP,
KEY_ENTER, KEY_NONE, KEY_NUMPERCENT, KEY_NUMEQU, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
KEY_NONE, KEY_NONE, '^', '+', ',', '-', '.', '\'',
'<EFBFBD>', KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
KEY_NONE, KEY_NONE, KEY_NONE, '@', KEY_GRAFIKK, '<EFBFBD>', '<EFBFBD>', KEY_NONE,
KEY_NONE, KEY_NONE, '<', KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE
};
static HWND hwnd;
static HINSTANCE appInst;
static HDC memdc;
static HBITMAP hbit;
static byte screen[1024*256];
static COLORREF colors[16];
static char defaultDir[256];
static byte pressedKeys[256];
static byte *dsk[2];
static DWORD fileSize[2];
static int resolution;
static boolean slowDown = TRUE;
static boolean scanlines = FALSE;
static boolean st28b = FALSE;
static int width, height;
static int size40x = 1, size80x = 1;
static unsigned int xmin = (unsigned)~0;
static unsigned int ymin = (unsigned)~0;
static unsigned int xmax = 0;
static unsigned int ymax = 0;
static boolean updateWindow = FALSE;
static boolean lock = FALSE;
static boolean grafikk = FALSE;
static boolean disk[2] = {FALSE, FALSE};
static HANDLE port1;
static HANDLE port2;
static HANDLE port3;
static char port1Name[256] = "COM1";
static char port2Name[256] = "COM2";
static char port3Name[256] = "LPT1";
/*****************************************************************************/
int WINAPI WinMain (HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode) {
char szWinName[] = "TIKIWin";
MSG msg;
WNDCLASSEX wcl;
appInst = hThisInst;
InitCommonControls();
/* lag og registrer vindusklasse */
wcl.cbSize = sizeof (WNDCLASSEX);
wcl.hInstance = hThisInst;
wcl.lpszClassName = szWinName;
wcl.lpfnWndProc = WindowFunc;
wcl.style = 0;
wcl.hIcon = LoadIcon (appInst, "icon");
wcl.hIconSm = NULL;
wcl.hCursor = LoadCursor (NULL, IDC_ARROW);
wcl.lpszMenuName = "menu";
wcl.cbClsExtra = 0;
wcl.cbWndExtra = 0;
wcl.hbrBackground = (HBRUSH)GetStockObject (BLACK_BRUSH);
if (!RegisterClassEx (&wcl)) {
return 0;
}
/* lag vindu */
hwnd = CreateWindow (szWinName, "TIKI-100_emul", WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX & ~WS_MAXIMIZEBOX, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, hThisInst, NULL);
changeRes (MEDRES);
ShowWindow (hwnd, nWinMode);
/* initialiser arrays */
memset (pressedKeys, 1, 256);
memset (screen, 0, 1024*256);
/* finn katalog */
GetCurrentDirectory (256, defaultDir);
/* kj<6B>r emulator */
if (!runEmul()) {
MessageBox (hwnd, "Finner ikke ROM-fil!", ERROR_CAPTION, MB_OK);
}
/* avslutt */
free (dsk[0]);
free (dsk[1]);
if (port1) CloseHandle (port1);
if (port2) CloseHandle (port2);
if (port3) CloseHandle (port3);
return msg.wParam;
}
static LRESULT CALLBACK WindowFunc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CREATE:
{ /* sett opp memdc */
HDC hdc = GetDC (hwnd);
memdc = CreateCompatibleDC (hdc);
hbit = CreateCompatibleBitmap (hdc, 1024, 1024 + STATUSBAR_HEIGHT);
SelectObject (memdc, hbit);
SelectObject (memdc, GetStockObject (BLACK_BRUSH));
PatBlt (memdc, 0, 0, 1024, 1024 + STATUSBAR_HEIGHT, PATCOPY);
ReleaseDC (hwnd, hdc);
}
break;
case WM_PAINT:
{ /* kopier fra memdc til hdc */
PAINTSTRUCT ps;
HDC hdc = BeginPaint (hwnd, &ps);
BitBlt (hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left,
ps.rcPaint.bottom - ps.rcPaint.top, memdc, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
EndPaint (hwnd, &ps);
}
break;
case WM_SIZE:
/* statusbar */
SelectObject (memdc, GetSysColorBrush (COLOR_3DFACE));
PatBlt (memdc, 0, height, width, STATUSBAR_HEIGHT, PATCOPY);
/* tegn sm<73>bokser */
draw3dBox (20, height + 5, 9, 9);
draw3dBox (40, height + 5, 9, 9);
draw3dBox (60, height + 5, 9, 9);
draw3dBox (80, height + 5, 9, 9);
/* oppdater diodelys */
lockLight (lock);
grafikkLight (grafikk);
diskLight (0, disk[0]);
diskLight (1, disk[1]);
break;
case WM_DESTROY:
PostQuitMessage (0);
break;
case WM_KEYDOWN:
pressedKeys[keyTable[(byte)wParam]] = 0;
break;
case WM_KEYUP:
pressedKeys[keyTable[(byte)wParam]] = 1;
break;
case WM_COMMAND:
switch (LOWORD (wParam)) {
case IDM_RESET:
resetEmul();
break;
case IDM_INNSTILLINGER:
DialogBox (appInst, "dialog", hwnd, (DLGPROC)DialogFunc);
break;
case IDM_OM:
MessageBox (hwnd,
"TIKI-100_emul V1.1.1 - en freeware TIKI 100 Rev. C emulator.\n"
"Z80 emulering copyright (C) Marat Fayzullin 1994,1995,1996,1997.\n"
"Resten copyright (C) Asbj<62>rn Djupdal 2000-2001.",
"Om TIKI-100_emul",
MB_OK);
break;
case IDM_AVSLUTT:
PostQuitMessage (0);
break;
case IDM_HENT_A:
getDiskImage (0);
break;
case IDM_HENT_B:
getDiskImage (1);
break;
case IDM_LAGRE_A:
saveDiskImage (0);
break;
case IDM_LAGRE_B:
saveDiskImage (1);
break;
case IDM_FJERN_A:
EnableMenuItem (GetSubMenu (GetMenu (hwnd), 1), IDM_LAGRE_A, MF_BYCOMMAND | MF_GRAYED);
removeDisk (0);
break;
case IDM_FJERN_B:
EnableMenuItem (GetSubMenu (GetMenu (hwnd), 1), IDM_LAGRE_B, MF_BYCOMMAND | MF_GRAYED);
removeDisk (1);
break;
#ifdef DEBUG
case IDM_MONITOR:
trace();
break;
#endif
}
default:
return DefWindowProc (hwnd, msg, wParam, lParam);
}
return 0;
}
/* tegner en 3d-boks */
static void draw3dBox (int x, int y, int w, int h) {
HGDIOBJ obj;
HPEN pen1 = CreatePen (PS_SOLID, 0, GetSysColor (COLOR_3DDKSHADOW));
HPEN pen2 = CreatePen (PS_SOLID, 0, GetSysColor (COLOR_3DHILIGHT));
MoveToEx (memdc, x, y + h - 1, NULL);
obj = SelectObject (memdc, pen1);
LineTo (memdc, x, y);
LineTo (memdc, x + w - 1, y);
SelectObject (memdc, pen2);
LineTo (memdc, x + w - 1, y + h - 1);
LineTo (memdc, x, y + h - 1);
SelectObject (memdc, obj);
DeleteObject (pen2);
DeleteObject (pen1);
}
static BOOL CALLBACK DialogFunc (HWND hdwnd, UINT message, WPARAM wParam, LPARAM lParam) {
static HWND ud40Wnd, ud80Wnd;
switch (message) {
case WM_INITDIALOG:
/* oppdater alle felter */
ud40Wnd = CreateUpDownControl (WS_CHILD | WS_BORDER | WS_VISIBLE | UDS_SETBUDDYINT | UDS_ALIGNRIGHT,
48, 52, 11, 14, hdwnd, IDD_40SPIN, appInst, GetDlgItem (hdwnd, IDD_40EDIT),
4, 1, size40x);
ud80Wnd = CreateUpDownControl (WS_CHILD | WS_BORDER | WS_VISIBLE | UDS_SETBUDDYINT | UDS_ALIGNRIGHT,
48, 71, 11, 14, hdwnd, IDD_80SPIN, appInst, GetDlgItem (hdwnd, IDD_80EDIT),
2, 1, size80x);
if (slowDown) SendDlgItemMessage (hdwnd, IDD_HASTIGHET, BM_SETCHECK, 1, 0);
if (scanlines) SendDlgItemMessage (hdwnd, IDD_BEVARFORHOLD, BM_SETCHECK, 1, 0);
if (st28b) SendDlgItemMessage (hdwnd, IDD_ST28B, BM_SETCHECK, 1, 0);
if (port1) SendDlgItemMessage (hdwnd, IDD_P1, BM_SETCHECK, 1, 0);
if (port2) SendDlgItemMessage (hdwnd, IDD_P2, BM_SETCHECK, 1, 0);
if (port3) SendDlgItemMessage (hdwnd, IDD_P3, BM_SETCHECK, 1, 0);
SendDlgItemMessage (hdwnd, IDD_P1EDIT, WM_SETTEXT, 0, (LPARAM)port1Name);
SendDlgItemMessage (hdwnd, IDD_P2EDIT, WM_SETTEXT, 0, (LPARAM)port2Name);
SendDlgItemMessage (hdwnd, IDD_P3EDIT, WM_SETTEXT, 0, (LPARAM)port3Name);
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDD_OK: {
int s40x, s80x;
boolean sl;
boolean st;
char p1[256];
char p2[256];
char p3[256];
/* begrense hastighet */
slowDown = SendDlgItemMessage (hdwnd, IDD_HASTIGHET, BM_GETCHECK, 0, 0);
/* forandre vindus-st<73>rrelse */
s40x = SendMessage (ud40Wnd, UDM_GETPOS, 0, 0);
s80x = SendMessage (ud80Wnd, UDM_GETPOS, 0, 0);
sl = SendDlgItemMessage (hdwnd, IDD_BEVARFORHOLD, BM_GETCHECK, 0, 0);
if (s40x != size40x || s80x != size80x || sl != scanlines) {
size40x = s40x; size80x = s80x; scanlines = sl;
changeRes (resolution);
resetEmul();
}
/* sett ST 28 b */
st = SendDlgItemMessage (hdwnd, IDD_ST28B, BM_GETCHECK, 0, 0);
if (st != st28b) {
st28b = st;
setST28b (st28b);
}
/* skaff nye portnavn */
SendDlgItemMessage (hdwnd, IDD_P1EDIT, WM_GETTEXT, 256, (LPARAM)p1);
SendDlgItemMessage (hdwnd, IDD_P2EDIT, WM_GETTEXT, 256, (LPARAM)p2);
SendDlgItemMessage (hdwnd, IDD_P3EDIT, WM_GETTEXT, 256, (LPARAM)p3);
/* <20>pne/lukke porter */
if (SendDlgItemMessage (hdwnd, IDD_P1, BM_GETCHECK, 0, 0)) {
/* port 1 */
if (!port1 || strcmp (p1, port1Name)) {
if (port1) CloseHandle (port1);
SetCurrentDirectory (defaultDir);
if ((port1 = CreateFile(p1, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, 0, NULL)) ==
INVALID_HANDLE_VALUE) {
MessageBox (hwnd, "Angitt navn p<> P1 ikke tilgjengelig!", ERROR_CAPTION, MB_OK);
port1 = 0;
}
}
} else if (port1) {
CloseHandle (port1);
port1 = 0;
}
if (SendDlgItemMessage (hdwnd, IDD_P2, BM_GETCHECK, 0, 0)) {
/* port 2 */
if (!port2 || strcmp (p2, port2Name)) {
if (port2) CloseHandle (port2);
SetCurrentDirectory (defaultDir);
if ((port2 = CreateFile(p2, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, 0, NULL)) ==
INVALID_HANDLE_VALUE) {
MessageBox (hwnd, "Angitt navn p<> P2 ikke tilgjengelig!", ERROR_CAPTION, MB_OK);
port1 = 0;
}
}
} else if (port2) {
CloseHandle (port2);
port2 = 0;
}
if (SendDlgItemMessage (hdwnd, IDD_P3, BM_GETCHECK, 0, 0)) {
/* port 3 */
if (!port3 || strcmp (p3, port3Name)) {
if (port3) CloseHandle (port3);
SetCurrentDirectory (defaultDir);
if ((port3 = CreateFile(p3, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, 0, NULL)) ==
INVALID_HANDLE_VALUE) {
MessageBox (hwnd, "Angitt navn p<> P3 ikke tilgjengelig!", ERROR_CAPTION, MB_OK);
port1 = 0;
}
}
} else if (port3) {
CloseHandle (port3);
port3 = 0;
}
/* ta vare p<> portnavn */
strcpy (port1Name, p1);
strcpy (port2Name, p2);
strcpy (port3Name, p3);
}
case 2: /* lukkeknapp for dialogboks, vet ikke makronavnet for den */
case IDD_AVBRYT:
EndDialog (hdwnd, 0);
break;
}
break;
}
return 0;
}
/* hent inn diskbilde fra fil */
static void getDiskImage (int drive) {
OPENFILENAME fname;
char fn[256] = "\0";
HANDLE hFile;
memset (&fname, 0, sizeof (OPENFILENAME));
fname.lStructSize = sizeof (OPENFILENAME);
fname.hwndOwner = hwnd;
fname.lpstrFile = fn;
fname.nMaxFile = sizeof (fn);
fname.Flags = OFN_FILEMUSTEXIST;
if (GetOpenFileName (&fname)) {
if ((hFile = CreateFile (fn, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) {
fileSize[drive] = GetFileSize (hFile, NULL);
free (dsk[drive]);
if ((dsk[drive] = (byte *)malloc (fileSize[drive]))) {
DWORD dwRead;
if (ReadFile (hFile, dsk[drive], fileSize[drive], &dwRead, NULL)) {
switch (fileSize[drive]) {
case 40*1*18*128:
EnableMenuItem (GetSubMenu (GetMenu (hwnd), 1), drive == 0 ? IDM_LAGRE_A : IDM_LAGRE_B,
MF_BYCOMMAND | MF_ENABLED);
insertDisk (drive, dsk[drive], 40, 1, 18, 128);
break;
case 40*1*10*512:
EnableMenuItem (GetSubMenu (GetMenu (hwnd), 1), drive == 0 ? IDM_LAGRE_A : IDM_LAGRE_B,
MF_BYCOMMAND | MF_ENABLED);
insertDisk (drive, dsk[drive], 40, 1, 10, 512);
break;
case 40*2*10*512:
EnableMenuItem (GetSubMenu (GetMenu (hwnd), 1), drive == 0 ? IDM_LAGRE_A : IDM_LAGRE_B,
MF_BYCOMMAND | MF_ENABLED);
insertDisk (drive, dsk[drive], 40, 2, 10, 512);
break;
case 80*2*10*512:
EnableMenuItem (GetSubMenu (GetMenu (hwnd), 1), drive == 0 ? IDM_LAGRE_A : IDM_LAGRE_B,
MF_BYCOMMAND | MF_ENABLED);
insertDisk (drive, dsk[drive], 80, 2, 10, 512);
break;
default:
removeDisk (drive);
fileSize[drive] = 0;
}
}
}
CloseHandle (hFile);
}
}
}
/* lagre diskbilde til fil */
static void saveDiskImage (int drive) {
OPENFILENAME fname;
char fn[256] = "\0";
HANDLE hFile;
memset (&fname, 0, sizeof (OPENFILENAME));
fname.lStructSize = sizeof (OPENFILENAME);
fname.hwndOwner = hwnd;
fname.lpstrFile = fn;
fname.nMaxFile = sizeof (fn);
fname.Flags = OFN_HIDEREADONLY;
if (GetSaveFileName (&fname)) {
if ((hFile = CreateFile (fn, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL))
!= INVALID_HANDLE_VALUE) {
DWORD dwWritten;
WriteFile (hFile, dsk[drive], fileSize[drive], &dwWritten, NULL);
CloseHandle (hFile);
}
}
}
/* Forandre oppl<70>sning */
void changeRes (int newRes) {
RECT windowRect;
switch (newRes) {
case HIGHRES:
width = 1024;
height = 256 * (scanlines ? 4 : 1);
break;
case MEDRES:
width = 512 * size80x;
height = 256 * size80x * (scanlines ? 2 : 1);
break;
case LOWRES:
default:
width = 256 * size40x;
height = 256 * size40x;
break;
}
GetWindowRect (hwnd, &windowRect);
MoveWindow (hwnd, windowRect.left, windowRect.top, width + 2 * GetSystemMetrics (SM_CXFIXEDFRAME),
height + 2 * GetSystemMetrics (SM_CYFIXEDFRAME) + GetSystemMetrics (SM_CYCAPTION) +
GetSystemMetrics (SM_CYMENU) + STATUSBAR_HEIGHT, 1);
/* slett bakgrunn */
SelectObject (memdc, GetStockObject (BLACK_BRUSH));
PatBlt (memdc, 0, 0, width, height, PATCOPY);
if (newRes != resolution) {
memset (screen, 0, 1024*256);
resolution = newRes;
}
/* oppdater vindu */
InvalidateRect (hwnd, NULL, FALSE);
}
/* Plotter en pixel med farge tatt fra pallett */
void plotPixel (int x, int y, int color) {
screen[x+y*1024] = color;
switch (resolution) {
case HIGHRES:
y *= scanlines ? 4 : 1;
break;
case MEDRES:
x *= size80x;
y *= size80x * (scanlines ? 2 : 1);
break;
case LOWRES:
x *= size40x;
y *= size40x;
break;
}
SetPixelV (memdc, x, y, colors[color]);
update (x, y, 1, 1);
}
/* Scroller skjerm 'distance' linjer oppover */
void scrollScreen (int distance) {
/* scroll screen */
if (distance > 0) {
memmove (screen, screen + distance * 1024, (256 - distance) * 1024);
memset (screen + distance * 1024, 0, (256 - distance) * 1024);
} else {
memmove (screen + -(distance * 1024), screen, (byte)distance * 1024);
memset (screen, 0, -distance * 1024);
}
/* finn avstand */
switch (resolution) {
case HIGHRES:
distance *= scanlines ? 4 : 1;
break;
case MEDRES:
distance *= size80x * (scanlines ? 2 : 1);
break;
case LOWRES:
default:
distance *= size40x;
break;
}
/* scroll memdc */
BitBlt (memdc, 0, -distance, width, height + distance, memdc, 0, 0, SRCCOPY);
SelectObject (memdc, GetStockObject (BLACK_BRUSH));
/* slett resten */
if (distance > 0) {
PatBlt (memdc, 0, height - distance, width, distance, PATCOPY);
} else {
PatBlt (memdc, 0, 0, width, -distance, PATCOPY);
}
/* oppdater vindu */
InvalidateRect (hwnd, NULL, FALSE);
}
/* Ny farge, gitt pallett nummer og intensitet 0-255 */
void changePalette (int colornumber, byte red, byte green, byte blue) {
if (colors[colornumber] != RGB (red, green, blue)) {
int x, y;
colors[colornumber] = RGB (red, green, blue);
/* oppdater pixler med denne fargen */
for (y = 0; y < 256; y++) {
for (x = 0; x < 1024; x++) {
if (screen[x+y*1024] == colornumber) {
plotPixel (x, y, colornumber);
}
}
}
}
}
/* Kalles periodisk. Lar system kode m<>le / senke emuleringshastighet
* Kan ogs<EFBFBD> brukes til sjekk av brukeraktivitet
* ms er antall "emulerte" millisekunder siden forrige gang loopEmul ble kalt
*/
void loopEmul (int ms) {
/* senk hastigheten */
if (slowDown) {
static boolean firstTime = TRUE;
static LARGE_INTEGER lastTime;
LARGE_INTEGER currentTime;
static LARGE_INTEGER freq;
if (QueryPerformanceCounter (&currentTime)) {
if (firstTime) {
QueryPerformanceFrequency (&freq);
lastTime = currentTime;
firstTime = FALSE;
} else {
long sleepPeriod = ms - ((currentTime.QuadPart - lastTime.QuadPart) * 1000 / freq.QuadPart);
lastTime = currentTime;
if (sleepPeriod > 0) {
Sleep (sleepPeriod);
QueryPerformanceCounter (&lastTime);
}
}
}
}
/* oppdater skjerm */
if (updateWindow) {
RECT rect = {xmin, ymin, xmax, ymax};
InvalidateRect (hwnd, &rect, FALSE);
xmin = (unsigned)~0, ymin = (unsigned)~0, xmax = 0, ymax = 0;
updateWindow = FALSE;
}
/* sjekk seriekanaler */
{
DWORD error;
COMSTAT comstat;
if (port1) {
if (ClearCommError (port1, &error, &comstat)) {
if (comstat.cbInQue != 0) {
charAvailable (0);
}
}
}
if (port2) {
if (ClearCommError (port2, &error, &comstat)) {
if (comstat.cbInQue != 0) {
charAvailable (1);
}
}
}
}
/* sjekk om der er events som venter */
{
MSG msg;
while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT) {
DeleteDC (memdc);
DeleteObject (hbit);
quitEmul();
} else {
DispatchMessage (&msg);
}
}
}
}
/* Tenn/slukk lock lys */
void lockLight (boolean status) {
HBRUSH brush = (status ?
GetSysColorBrush (COLOR_HIGHLIGHT) :
GetSysColorBrush (COLOR_3DFACE));
SelectObject (memdc, brush);
PatBlt (memdc, 21, height + 6, 7, 7, PATCOPY);
update (21, height + 6, 7, 7);
lock = status;
}
/* Tenn/slukk grafikk lys */
void grafikkLight (boolean status) {
HBRUSH brush = (status ?
GetSysColorBrush (COLOR_HIGHLIGHT) :
GetSysColorBrush (COLOR_3DFACE));
SelectObject (memdc, brush);
PatBlt (memdc, 41, height + 6, 7, 7, PATCOPY);
update (41, height + 6, 7, 7);
grafikk = status;
}
/* Tenn/slukk disk lys for gitt stasjon */
void diskLight (int drive, boolean status) {
int x = (drive ? 81 : 61);
HBRUSH brush = (status ?
GetSysColorBrush (COLOR_HIGHLIGHT) :
GetSysColorBrush (COLOR_3DFACE));
SelectObject (memdc, brush);
PatBlt (memdc, x, height + 6, 7, 7, PATCOPY);
update (61, height + 6, 7, 7);
disk[drive] = status;
}
static void update (int x, int y, int w, int h) {
if (xmin > x) xmin = x;
if (ymin > y) ymin = y;
if (xmax < (x + w)) xmax = x + w;
if (ymax < (y + h)) ymax = y + h;
updateWindow = TRUE;
}
/* Sjekk status til hver av de gitte tastene
* Sett bit n i returkode hvis tast n IKKE er nedtrykt
* Taster er enten ascii-kode eller en av konstantene over
*/
byte testKey (byte keys[8]) {
return pressedKeys[keys[0]] | (pressedKeys[keys[1]] << 1) | (pressedKeys[keys[2]] << 2) |
(pressedKeys[keys[3]] << 3) | (pressedKeys[keys[4]] << 4) | (pressedKeys[keys[5]] << 5) |
(pressedKeys[keys[6]] << 6) | (pressedKeys[keys[7]] << 7);
}
/* setter seriekanalparametre */
void setParams (struct serParams *p1Params, struct serParams *p2Params) {
if (port1) setParam (port1, p1Params);
if (port2) setParam (port2, p2Params);
}
static void setParam (HANDLE portHandle, struct serParams *params) {
DCB dcb = {sizeof (DCB),
0, /* BaudRate */
TRUE, /* fBinary */
0, /* fParity */
FALSE, /* fOutxCtsFlow */
FALSE, /* fOutxDsrFlow */
DTR_CONTROL_ENABLE, /* fDtrControl */
FALSE, /* fDsrSensitivity */
TRUE, /* fTXContinueOnXoff */
FALSE, /* fOutX */
FALSE, /* fInX */
FALSE, /* fErrorChar */
FALSE, /* fNull */
RTS_CONTROL_ENABLE, /* fRtsControl */
FALSE, /* fAbortOnError */
17, /* fDummy2 */
0, /* wReserved */
0, /* XonLim */
0, /* XoffLim */
0, /* ByteSize */
0, /* Parity */
0, /* StopBits */
0, /* XonChar */
0, /* XoffChar */
0, /* ErrorChar */
-1, /* EofChar */
0, /* EvtChar */
0}; /* wReservedl */
dcb.BaudRate = params->baud;
dcb.BaudRate = dcb.BaudRate - dcb.BaudRate % 100;
dcb.ByteSize = params->sendBits; /* obs: receiveBits blir ikke tatt hensyn til */
switch (params->parity) {
case PAR_NONE:
dcb.Parity = NOPARITY;
dcb.fParity = FALSE;
break;
case PAR_EVEN:
dcb.Parity = EVENPARITY;
dcb.fParity = TRUE;
break;
case PAR_ODD:
dcb.Parity = ODDPARITY;
dcb.fParity = TRUE;
break;
}
switch (params->stopBits) {
case ONE_SB: dcb.StopBits = ONESTOPBIT; break;
case ONE_PT_FIVE_SB: dcb.StopBits = ONE5STOPBITS; break;
case TWO_SB: dcb.StopBits = TWOSTOPBITS; break;
}
if (!SetCommState(portHandle, &dcb)) {
/* ingen aksjon */
}
return;
}
/* send tegn til seriekanal */
void sendChar (int port, byte value) {
DWORD bytesWritten;
HANDLE portHandle = port ? port2 : port1;
if (portHandle) {
if (!WriteFile (portHandle, &value, 1, &bytesWritten, NULL)) {
/* kan ikke skrive til port */
}
}
}
/* hent tegn fra seriekanal */
byte getChar (int port) {
HANDLE portHandle = port ? port2 : port1;
byte value = 0;
DWORD bytesRead;
if (portHandle) {
if (!ReadFile (portHandle, &value, 1, &bytesRead, NULL)) {
/* kan ikke lese fra port */
}
/* flere tegn i buffer? */
{
DWORD error;
COMSTAT comstat;
if (ClearCommError (portHandle, &error, &comstat)) {
if (comstat.cbInQue != 0) {
charAvailable (port);
}
}
}
}
return value;
}
/* send tegn til skriver */
void printChar (byte value) {
DWORD bytesWritten;
if (port3) {
if (!WriteFile (port3, &value, 1, &bytesWritten, NULL)) {
/* kan ikke skrive til port */
}
}
}