c3ab4004ad
Signed-off-by: Gwenhael Le Moine <gwenhael.le.moine@gmail.com>
896 lines
26 KiB
C
896 lines
26 KiB
C
/*
|
||
* Copyright (C) 1995 Sebastien Carlier
|
||
*/
|
||
|
||
#define NEW 1
|
||
#define WIN32_LEAN_AND_MEAN
|
||
#include <windows.h>
|
||
#undef IN
|
||
#undef OUT
|
||
#include <stdlib.h>
|
||
#include <memory.h>
|
||
#include "emu48.h"
|
||
#include "resource.h"
|
||
#include <stdio.h>
|
||
#include <stdarg.h>
|
||
|
||
#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 (x<KBD_LEFT) break;
|
||
if (x>KBD_RIGHT) break;
|
||
if (y<KBD_UP) break;
|
||
if (y>KBD_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 (x<KBD_LEFT) break;
|
||
if (x>KBD_RIGHT) break;
|
||
if (y<KBD_UP) break;
|
||
if (y>KBD_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_<79>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;
|
||
*/
|
||
}
|