/* * Copyright (C) 1995 Sebastien Carlier */ #define NEW 1 #define WIN32_LEAN_AND_MEAN #include #undef IN #undef OUT #include #include #include "emu48.h" #include "resource.h" #include #include #define DEBUG 1 #include "pcpdebug.h" DEBUG_PRINTF_FUNCDEF("emu48.log") #define W_WIDTH 264 #define W_HEIGHT 396 #define KBD_UP 144 #define KBD_DOWN 342 #define KBD_LEFT 30 #define KBD_RIGHT 234 HANDLE hInst; HANDLE hWindow; HANDLE hThreadEmulate; HANDLE hKeyboard, hPix4, hIdle; HANDLE hMemoryDC; DWORD ThreadID1; CHAR Buf[80]; display_t display; char kbd_row[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; int KDN, KDN_rising_edge, IR15X; int thread_suspended = 0; int keyprocessed = 0; LRESULT CALLBACK MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); void about_box(); /*************************************************************************\ * * FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int) * \*************************************************************************/ int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg; WNDCLASS wc; UNREFERENCED_PARAMETER( lpCmdLine ); UNREFERENCED_PARAMETER( hPrevInstance ); // check if Win32s, if so, display notice and terminate if(GetVersion()&0x80000000 && (GetVersion()&0xFF)==3) { MessageBox( NULL, "This application cannot run on Windows 3.1.\n" "This application will now terminate.", "HP48SX", MB_OK | MB_ICONSTOP | MB_SETFOREGROUND ); return 1; } hInst = hInstance; wc.style = CS_BYTEALIGNCLIENT; wc.lpfnWndProc = (WNDPROC)MainWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(hInstance, "Emu48_Icon"); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = "Emu48_Menu"; wc.lpszClassName = "Emu48Class"; RegisterClass(&wc); hWindow = CreateWindow("Emu48Class", "HP48SX", WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, W_WIDTH, W_HEIGHT, NULL, NULL, hInstance, NULL); ShowWindow(hWindow, nCmdShow); while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage (&msg); // Dispatch message to window. Sleep(0); } return msg.wParam; // Returns value from PostQuitMessage. } /*************************************************************************\ * * FUNCTION: MainWndProc (HWND, UINT, WPARAM, LPARAM) * \*************************************************************************/ LRESULT CALLBACK MainWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { short x, y; HDC hDC; switch (message) { case WM_CREATE : /* about_box(); */ hKeyboard = LoadBitmap(hInst, "Emu48_Keyboard"); hPix4 = LoadBitmap(hInst, "Emu48_Pix4"); hIdle = LoadBitmap(hInst, "Emu48_Idle"); hDC = GetDC(hwnd); hMemoryDC = CreateCompatibleDC(hDC); SelectObject(hMemoryDC, hPix4); ReleaseDC(hwnd, hDC); load(); if (display.pointer==NULL) display.pointer = rom; saturn_speed = 5000; // Create the emulator thread hThreadEmulate = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)emulate, NULL, 0, (LPDWORD)&ThreadID1); if (!hThreadEmulate) { wsprintf(Buf, "Error in creating Emulator thread: %d", GetLastError()); MessageBox (hwnd, Buf, "WM_CREATE", MB_OK); } return 0; case WM_RBUTTONDOWN: case WM_LBUTTONDOWN: // Left mouse button pressed x = ((short*)&lParam)[0]; y = ((short*)&lParam)[1]; if (xKBD_RIGHT) break; if (yKBD_DOWN) break; x = (x-KBD_LEFT)/34; y = (y-KBD_UP)/22; kbd_handler((y<<4)|x,1); return 0; #if NEW case WM_CHAR: case WM_KEYDOWN: case WM_SYSKEYDOWN: { MSG msg; int i; msg.hwnd = hwnd; msg.message = message; msg.wParam = wParam; msg.lParam = lParam; dsx(lParam); dsx(wParam); i = translatekeys(&msg); /* capture system key */ if (i && message == WM_SYSKEYDOWN) return 0; } break; #else case WM_CHAR: ds(("WM_CHAR\n")) dsx(lParam); dsx(wParam); presskeys(lParam, wParam, 1); break; case WM_KEYDOWN: ds(("WM_KEYDOWN\n")) dsx(lParam); dsx(wParam); if (lParam & 0x1000000L) presskeys(lParam, wParam, 1); break; #endif case WM_LBUTTONUP: // Left mouse button released x = ((short*)&lParam)[0]; y = ((short*)&lParam)[1]; if (xKBD_RIGHT) break; if (yKBD_DOWN) break; x = (x-KBD_LEFT)/34; y = (y-KBD_UP)/22; kbd_handler((y<<4)|x,0); return 0; case WM_ERASEBKGND: // Erase background hDC = GetDC(hwnd); PatBlt(hDC, 0, 0, W_WIDTH, W_HEIGHT, BLACKNESS); PatBlt(hDC, 0, 0, 262, 129, WHITENESS); SelectObject(hMemoryDC, hKeyboard); BitBlt(hDC, KBD_LEFT, KBD_UP, 204, 198, hMemoryDC, 0, 0, SRCCOPY); if (thread_suspended) { SelectObject(hMemoryDC, hIdle); BitBlt(hDC, 0, 0, 262, 128, hMemoryDC, 0, 0, SRCCOPY); } ReleaseDC(hwnd, hDC); SelectObject(hMemoryDC, hPix4); if (!thread_suspended) { display_redraw(); display_ann(); } return 0; case WM_CLOSE: save(); break; case WM_COMMAND: switch (LOWORD(wParam)) { case ID_SYSTEM_EXIT: DestroyWindow(hwnd); break; case ID_SAVE: save(); break; case ID_HELP_ABOUT: about_box(); break; } return 0; case WM_DESTROY: TerminateThread(hThreadEmulate, 0); DeleteDC(hMemoryDC); DeleteObject(hKeyboard); PostQuitMessage (0); return 0; } return DefWindowProc (hwnd, message, wParam, lParam); } /*************************************************************************\ * * FUNCTION: display_error() * \*************************************************************************/ void about_box() { display_warning( "Emu48 version "VERSION", Copyright (C) 1995 Sebastien Carlier\n" "This is free software, and you are welcome to redistribute it\n" "under certain conditions; see COPYING for details.\n"); return; } /*************************************************************************\ * * FUNCTION: display_error() * \*************************************************************************/ void display_error(char *s) { MessageBox(NULL,s,"Emu48",MB_OK|MB_ICONSTOP|MB_SETFOREGROUND); exit(1); } /*************************************************************************\ * * FUNCTION: display_warning() * \*************************************************************************/ void display_warning(char *s) { MessageBox(NULL,s,"Emu48",MB_OK|MB_ICONINFORMATION|MB_SETFOREGROUND); return; } /*************************************************************************\ * * FUNCTION: display_redraw() * \*************************************************************************/ void display_redraw() { int y; display.line = 0; display.lcounter = display.lcntsave; display.pointer = nibble_ptr(display.start1); display.disoffs = 0; if (display.dispon) for (y=0; y<64; y++) display_line(); else display_clear(); if (display.boffset&4) display.end1 = display.start1 + (display.lcntsave+1)*(display.loffset+36); else display.end1 = display.start1 + (display.lcntsave+1)*(display.loffset+34); if (display.end1 < display.start1) { display.start12 = display.end1; display.end1 = display.start1; } else display.start12 = display.start1; display.end2 = display.start2 + (63 - display.lcntsave)*34; display.touched = 0; return; } /*************************************************************************\ * * FUNCTION: display_line() * \*************************************************************************/ #define SET4PIXELS(x,y,m) BitBlt(hDC, 2*x, y, 8, 2, hMemoryDC,0, (m)*2, SRCCOPY); void display_line() { HDC hDC; char *ptr; int x, y; if (!display.dispon) return; // c = display.contrast; y = 2*display.line; hDC = GetDC(hWindow); if (display.disoffs) { ptr = display.pointer; for (x=0; x<128; x+=4) SET4PIXELS(x,y,*(ptr++)); SET4PIXELS(x,y,*ptr & 7); } else { if (display.boffset&4) display.pointer++; ptr = display.pointer; switch (display.boffset&3) { case 0: for (x=0; x<128; x+=4) SET4PIXELS(x,y,*(ptr++)); SET4PIXELS(x,y,*ptr & 7); break; case 1: SET4PIXELS(0,y, *(ptr++) >> 1); for (x=3; x<127; x+=4) SET4PIXELS(x,y,*(ptr++)); SET4PIXELS(x,y,*ptr); break; case 2: SET4PIXELS(0,y, *(ptr++) >> 2); for (x=2; x<130; x+=4) SET4PIXELS(x,y,*(ptr++)); SET4PIXELS(x,y,*ptr & 1); break; case 3: SET4PIXELS(0,y, *(ptr++) >> 3); for (x=1; x<129; x+=4) SET4PIXELS(x,y,*(ptr++)); SET4PIXELS(x,y,*ptr & 3); break; } } ReleaseDC(hWindow, hDC); display_next(); return; } /*************************************************************************\ * * FUNCTION: display_plot1(long d, char m) * \*************************************************************************/ void display_plot1(long d, char m) { int x, y, w; HDC hDC; d -= display.start12; w = 34 + display.loffset; if (display.boffset&4) w+=2; if (w==0) return; if (w<0) y = d / w + display.lcntsave + 1; else y = d / w; if (y<0) return; if (y>display.lcntsave) return; x = (d % w) * 4; if (display.boffset) { x -= display.boffset; if (x<0) return; } if (x>130) return; hDC = GetDC(hWindow); SET4PIXELS(x,y*2,m) ReleaseDC(hWindow, hDC); return; } /*************************************************************************\ * * FUNCTION: display_plot2(long d, char m) * \*************************************************************************/ void display_plot2(long d, char m) { int x, y; HDC hDC; d -= display.start2; y = display.lcntsave + (d / 34) + 1; x = (d % 34) * 4; if (x==128) m&=7; hDC = GetDC(hWindow); SET4PIXELS(x,y*2,m) ReleaseDC(hWindow, hDC); return; } /*************************************************************************\ * * FUNCTION: display_next() * \*************************************************************************/ void display_next() { display.line++; if (display.line >= 64) { /* new refresh cycle */ display.line = 0; display.lcounter = display.lcntsave; display.pointer = nibble_ptr(display.start1); display.disoffs = 0; return; } if (display.disoffs) { display.pointer += 34; return; } if (display.lcounter) { display.lcounter--; display.pointer += 34 + display.loffset; if (display.boffset&4) display.pointer++; return; } display.pointer = nibble_ptr(display.start2); display.disoffs = 1; return; } void init_lcd() { display.pointer = rom; return; } void exit_lcd() { return; } /*************************************************************************\ * * FUNCTION: display_çlear() * \*************************************************************************/ void display_clear() { HDC hDC; hDC = GetDC(hWindow); PatBlt(hDC, 0, 0, 262, 128, WHITENESS); ReleaseDC(hWindow, hDC); return; } /*************************************************************************\ * * FUNCTION: display_ann() * \*************************************************************************/ void display_ann() { HDC hDC; unsigned short c; hDC = GetDC(hWindow); c = *(unsigned short*)(ioram+0x0b); if (!(c&0x0800)) c=0; PatBlt(hDC, 16+32*1, 132, 4, 4, (c&0x001)?WHITENESS:BLACKNESS); PatBlt(hDC, 16+32*2, 132, 4, 4, (c&0x002)?WHITENESS:BLACKNESS); PatBlt(hDC, 16+32*3, 132, 4, 4, (c&0x004)?WHITENESS:BLACKNESS); PatBlt(hDC, 16+32*4, 132, 4, 4, (c&0x008)?WHITENESS:BLACKNESS); PatBlt(hDC, 16+32*5, 132, 4, 4, (c&0x100)?WHITENESS:BLACKNESS); PatBlt(hDC, 16+32*6, 132, 4, 4, (c&0x200)?WHITENESS:BLACKNESS); ReleaseDC(hWindow, hDC); return; } /*************************************************************************\ * * FUNCTION: keyboard_invert() * \*************************************************************************/ void kbd_invert(int x, int y) { HDC hDC; hDC = GetDC(hWindow); PatBlt(hDC, 1+KBD_LEFT+34*x, 1+KBD_UP+22*y, 33, 21, DSTINVERT); ReleaseDC(hWindow, hDC); return; } /*************************************************************************\ * * FUNCTION: keyboard_invert2() * \*************************************************************************/ void kbd_invert2(int x, int y) { HDC hDC; hDC = GetDC(hWindow); PatBlt(hDC, 1+KBD_LEFT+34*x, 1+KBD_UP+22*y, 67, 21, DSTINVERT); ReleaseDC(hWindow, hDC); return; } /*************************************************************************\ * * FUNCTION: keyboard_handler(unsigned char scancode, int press) * \*************************************************************************/ void kbd_handler(int scancode, int press) { int mask, row; dsx(scancode); if (scancode == 0x81) /*ON*/ { if (press) { if (!IR15X) { kbd_invert(scancode&0xf, scancode>>4); IR15X = 0x8000; } } else { if (IR15X) { kbd_invert(scancode&0xf, scancode>>4); IR15X = 0x0000; } } } if (ioram[0x2f]&1 == 0) return; switch (scancode) { case 0x00: row = 1; mask = 0x0010; break; case 0x01: row = 8; mask = 0x0010; break; case 0x02: row = 8; mask = 0x0008; break; case 0x03: row = 8; mask = 0x0004; break; case 0x04: row = 8; mask = 0x0002; break; case 0x05: row = 8; mask = 0x0001; break; case 0x10: row = 2; mask = 0x0010; break; case 0x11: row = 7; mask = 0x0010; break; case 0x12: row = 7; mask = 0x0008; break; case 0x13: row = 7; mask = 0x0004; break; case 0x14: row = 7; mask = 0x0002; break; case 0x15: row = 7; mask = 0x0001; break; case 0x20: row = 0; mask = 0x0010; break; case 0x21: row = 6; mask = 0x0010; break; case 0x22: row = 6; mask = 0x0008; break; case 0x23: row = 6; mask = 0x0004; break; case 0x24: row = 6; mask = 0x0002; break; case 0x25: row = 6; mask = 0x0001; break; case 0x30: row = 3; mask = 0x0010; break; case 0x31: row = 5; mask = 0x0010; break; case 0x32: row = 5; mask = 0x0008; break; case 0x33: row = 5; mask = 0x0004; break; case 0x34: row = 5; mask = 0x0002; break; case 0x35: row = 5; mask = 0x0001; break; case 0x40: row = 4; mask = 0x0010; break; case 0x41: row = 4; mask = 0x0010; break; case 0x42: row = 4; mask = 0x0008; break; case 0x43: row = 4; mask = 0x0004; break; case 0x44: row = 4; mask = 0x0002; break; case 0x45: row = 4; mask = 0x0001; break; case 0x51: row = 3; mask = 0x0020; break; case 0x52: row = 3; mask = 0x0008; break; case 0x53: row = 3; mask = 0x0004; break; case 0x54: row = 3; mask = 0x0002; break; case 0x55: row = 3; mask = 0x0001; break; case 0x61: row = 2; mask = 0x0020; break; case 0x62: row = 2; mask = 0x0008; break; case 0x63: row = 2; mask = 0x0004; break; case 0x64: row = 2; mask = 0x0002; break; case 0x65: row = 2; mask = 0x0001; break; case 0x71: row = 1; mask = 0x0020; break; case 0x72: row = 1; mask = 0x0008; break; case 0x73: row = 1; mask = 0x0004; break; case 0x74: row = 1; mask = 0x0002; break; case 0x75: row = 1; mask = 0x0001; break; case 0x82: row = 0; mask = 0x0008; break; case 0x83: row = 0; mask = 0x0004; break; case 0x84: row = 0; mask = 0x0002; break; case 0x85: row = 0; mask = 0x0001; break; case 0x50: kbd_invert(scancode&0xf, scancode>>4); if (press) { HDC hDC; SuspendThread(hThreadEmulate); thread_suspended = 1; hDC = GetDC(hWindow); SelectObject(hMemoryDC, hIdle); BitBlt(hDC, 0, 0, 262, 128, hMemoryDC, 0, 0, SRCCOPY); ReleaseDC(hWindow, hDC); SelectObject(hMemoryDC, hPix4); } return; case 0x60: kbd_invert(scancode&0xf, scancode>>4); if (press) { thread_suspended = 0; ResumeThread(hThreadEmulate); display_redraw(); display_ann(); } return; case 0x70: kbd_invert(scancode&0xf, scancode>>4); return; case 0x80: kbd_invert(scancode&0xf, scancode>>4); return; default: return; } if (press) { if ((kbd_row[row]&mask)==0) { KDN_rising_edge = 1; KDN++; if ((scancode==0x40)||(scancode==0x41)) kbd_invert2(0, 4); else kbd_invert(scancode&0xf, scancode>>4); kbd_row[row]|=mask; } } else { if (kbd_row[row]&mask) { KDN--; if ((scancode==0x40)||(scancode==0x41)) kbd_invert2(0, 4); else kbd_invert(scancode&0xf, scancode>>4); kbd_row[row]&=~mask; } } return; } void presskeys(unsigned lparam, unsigned wparam, int down) { int scancode = -1; int state=0; state = (GetKeyState(VK_LSHIFT) & 0x8000) ? 0x100 : 0; state |= (GetKeyState(VK_RSHIFT) & 0x8000) ? 0x200 : 0; state |= (GetKeyState(VK_CONTROL) & 0x8000) ? 0x400 : 0; state |= (GetKeyState(VK_MENU) & 0x8000) ? 0x800 : 0; dsx(wparam); if (isalpha(wparam)) wparam = toupper(wparam); dsx(wparam); if (wparam >= 'A' && wparam <= 'X') { int row = (wparam - 'A') / 6; int col = (wparam - 'A') % 6; scancode = row * 0x10 + col; } else if (!(lparam & 0x1000000L) ) { switch (wparam) { case '\n': case '\r': scancode = 0x41; break; case '0': scancode = 0x82; break; case '1': scancode = 0x72; break; case '2': scancode = 0x73; break; case '3': scancode = 0x74; break; case '4': scancode = 0x62; break; case '5': scancode = 0x63; break; case '6': scancode = 0x64; break; case '7': scancode = 0x52; break; case '8': scancode = 0x53; break; case '9': scancode = 0x54; break; case '.': scancode = 0x83; break; case ' ': scancode = 0x84; break; case '+': scancode = 0x85; break; case '-': scancode = 0x75; break; case '*': scancode = 0x65; break; case '/': scancode = 0x55; break; case 'Y': scancode = 0x42; break; case '\'': scancode = 0x20; break; case 'Z': scancode = 0x43; break; case 0x1B: scancode = 0x81; break; case '\b': scancode = 0x45; break; case '\t': scancode = 0x15; break; default: break; } } else if ((lparam & 0x1000000L) || (wparam >= VK_F1 && wparam <= VK_F6)) switch (wparam) { case VK_RETURN: scancode = 0x41; break; case VK_LEFT: scancode = 0x23; break; case VK_UP: scancode = 0x14; break; case VK_RIGHT: scancode = 0x25; break; case VK_DOWN: scancode = 0x24; break; case VK_CONTROL: scancode = 0x51; break; case VK_PRIOR: if (!(state & 0x300)) scancode = 0x61; break; case VK_NEXT: if (!(state & 0x300)) scancode = 0x71; break; case VK_F1: scancode = 0x00; break; case VK_F2: scancode = 0x01; break; case VK_F3: scancode = 0x02; break; case VK_F4: scancode = 0x03; break; case VK_F5: scancode = 0x04; break; case VK_F6: scancode = 0x05; break; } dsx(state); if (scancode != -1) { /* if (state & 0x100) presskeys(0x01000000, VK_PRIOR, 0); else if (state & 0x200) presskeys(0x01000000, VK_NEXT, 0); */ kbd_handler(scancode, 1); Sleep(100); kbd_handler(scancode, 0); } } void update_in() { IN = IR15X; if (OUT & 0x001) IN|=kbd_row[0]; if (OUT & 0x002) IN|=kbd_row[1]; if (OUT & 0x004) IN|=kbd_row[2]; if (OUT & 0x008) IN|=kbd_row[3]; if (OUT & 0x010) IN|=kbd_row[4]; if (OUT & 0x020) IN|=kbd_row[5]; if (OUT & 0x040) IN|=kbd_row[6]; if (OUT & 0x080) IN|=kbd_row[7]; if (OUT & 0x100) IN|=kbd_row[8]; return; } void init_keyboard() { return; } void exit_keyboard() { return; } #if NEW #define IGNORE_WM_CHAR 0x8000 int keyevent(long key) { int scancode = -1, retval = 0; dsx(key); if (key >= 'a' && key <= 'z') key = toupper(key); dsx(key); dsx(KEYC_PGDN); if (key >= 'A' && key <= 'X') { int row = (key - 'A') / 6; int col = (key - 'A') % 6; scancode = row * 0x10 + col; } else switch (key) { case '0': scancode = 0x82; break; case '1': scancode = 0x72; break; case '2': scancode = 0x73; break; case '3': scancode = 0x74; break; case '4': scancode = 0x62; break; case '5': scancode = 0x63; break; case '6': scancode = 0x64; break; case '7': scancode = 0x52; break; case '8': scancode = 0x53; break; case '9': scancode = 0x54; break; case '.': scancode = 0x83; break; case ' ': scancode = 0x84; break; case '+': scancode = 0x85; break; case '-': scancode = 0x75; break; case '*': scancode = 0x65; break; case '/': scancode = 0x55; break; case 'Y': scancode = 0x42; break; case '\'': scancode = 0x20; break; case 'Z': scancode = 0x43; break; case '`': scancode = 0x51; break; case '\n': case '\r': scancode = 0x41; retval = 1; break; case 0x1B: scancode = 0x81; retval = 1; break; case '\b': scancode = 0x45; retval = 1; break; case '\\': case '\t': scancode = 0x15; retval = 1; break; case KEYC_LEFT: scancode = 0x23; break; case KEYC_UP: scancode = 0x14; break; case KEYC_RIGHT: scancode = 0x25; break; case KEYC_DOWN: scancode = 0x24; break; case KEYC_DELETE: scancode = 0x44; break; case KEYC_PGUP: scancode = 0x61; break; case KEYC_PGDN: scancode = 0x71; break; case KEYF_FKEY+1: case KEYF_FKEY+2: case KEYF_FKEY+3: case KEYF_FKEY+4: case KEYF_FKEY+5: case KEYF_FKEY+6: scancode = key-KEYF_FKEY-1; retval = 1; break; default: break; } dsx(scancode); if (scancode != -1) { /* if (state & 0x100) presskeys(0x01000000, VK_PRIOR, 0); else if (state & 0x200) presskeys(0x01000000, VK_NEXT, 0); */ kbd_handler(scancode, 1); Sleep(100); kbd_handler(scancode, 0); } return retval; } int translatekeys(void * vmsg) { MSG *msg = (MSG*) vmsg; int state=0; switch(msg->message) { case WM_CHAR: if (keyprocessed & IGNORE_WM_CHAR) { keyprocessed &= ~IGNORE_WM_CHAR; return 1; } else return keyevent(KEYFROMASCII(msg->wParam)); case WM_SYSKEYDOWN: case WM_KEYDOWN: state = (GetKeyState(VK_SHIFT) & 0x8000) ? KEYF_SHIFT : 0; state |= (GetKeyState(VK_CONTROL) & 0x8000) ? KEYF_CTRL : 0; state |= (GetKeyState(VK_MENU) & 0x8000) ? KEYF_ALT: 0; if (msg->wParam >= VK_F1 && msg->wParam <= VK_F12) /* Return function key */ return keyevent((msg->wParam-(VK_F1-1)+KEYF_FKEY)|state); else { int i; long k; switch (msg->wParam) { case VK_PRIOR: k = (KEYC_PAGEUP|state); break; case VK_NEXT: k = (KEYC_PAGEDOWN|state); break; case VK_END: k = (KEYC_END|state); break; case VK_HOME: k = (KEYC_HOME|state); break; case VK_LEFT: k = (KEYC_LEFT|state); break; case VK_UP: k = (KEYC_UP|state); break; case VK_RIGHT: k = (KEYC_RIGHT|state); break; case VK_DOWN: k = (KEYC_DOWN|state); break; case VK_INSERT: k = (KEYC_INSERT|state); break; case VK_DELETE: k = (KEYC_DELETE|state); break; default: k = (KEYFROMSCAN(msg->wParam)|state); break; } i = keyevent(k); if (i) keyprocessed |= IGNORE_WM_CHAR; return i; } } return 0; } #endif /******** BEEP ********/ void update_out() { /* char c; __asm__("inb $0x61, %0":"=a"(c)); if (OUT&0x800) c|=0x02; else c&=0xfc; __asm__("outb %0, $0x61"::"a"(c)); return; */ }