linapple-pie/src/Keyboard.cpp

487 lines
11 KiB
C++

/*
AppleWin : An Apple //e emulator for Windows
Copyright (C) 1994-1996, Michael O'Brien
Copyright (C) 1999-2001, Oliver Schmidt
Copyright (C) 2002-2005, Tom Charlesworth
Copyright (C) 2006-2007, Tom Charlesworth, Michael Pohoreski
AppleWin is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
AppleWin is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with AppleWin; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Description: Keyboard emulation
*
* Author: Various
*/
/* Adaptation for SDL and POSIX (l) by beom beotiger, Nov-Dec 2007 */
#include "stdafx.h"
//#pragma hdrstop
static bool g_bKeybBufferEnable = false;
#define KEY_OLD
/*static BYTE asciicode[2][10] = {
{0x08,0x0D,0x15,0x2F,0x00,0x00,0x00,0x00,0x00,0x00},
{0x08,0x0B,0x15,0x0A,0x00,0x00,0x00,0x00,0x00,0x7F}
}; // Convert PC arrow keys to Apple keycodes*/
/*static*/ bool g_bShiftKey = false;
/*static*/ bool g_bCtrlKey = false;
/*static*/ bool g_bAltKey = false;
static bool g_bCapsLock = true;
static int lastvirtkey = 0; // Current PC keycode
static BYTE keycode = 0; // Current Apple keycode
static DWORD keyboardqueries = 0;
#ifdef KEY_OLD
// Original
static BOOL keywaiting = 0;
#else
// Buffered key input:
// - Needed on faster PCs where aliasing occurs during short/fast bursts of 6502 code.
// - Keyboard only sampled during 6502 execution, so if it's run too fast then key presses will be missed.
const int KEY_BUFFER_MIN_SIZE = 1;
const int KEY_BUFFER_MAX_SIZE = 2;
static int g_nKeyBufferSize = KEY_BUFFER_MAX_SIZE; // Circ key buffer size
static int g_nNextInIdx = 0;
static int g_nNextOutIdx = 0;
static int g_nKeyBufferCnt = 0;
static struct
{
int nVirtKey;
BYTE nAppleKey;
} g_nKeyBuffer[KEY_BUFFER_MAX_SIZE];
#endif
static BYTE g_nLastKey = 0x00;
//
// ----- ALL GLOBALLY ACCESSIBLE FUNCTIONS ARE BELOW THIS LINE -----
//
//===========================================================================
void KeybReset()
{
#ifdef KEY_OLD
keywaiting = 0;
#else
g_nNextInIdx = 0;
g_nNextOutIdx = 0;
g_nKeyBufferCnt = 0;
g_nLastKey = 0x00;
g_nKeyBufferSize = g_bKeybBufferEnable ? KEY_BUFFER_MAX_SIZE : KEY_BUFFER_MIN_SIZE;
#endif
}
//===========================================================================
//void KeybSetBufferMode(bool bNewKeybBufferEnable)
//{
// if(g_bKeybBufferEnable == bNewKeybBufferEnable)
// return;
//
// g_bKeybBufferEnable = bNewKeybBufferEnable;
// KeybReset();
//}
//
//bool KeybGetBufferMode()
//{
// return g_bKeybBufferEnable;
//}
//===========================================================================
bool KeybGetAltStatus ()
{
return g_bAltKey;
}
//===========================================================================
bool KeybGetCapsStatus ()
{
return g_bCapsLock;
}
//===========================================================================
bool KeybGetCtrlStatus ()
{
return g_bCtrlKey;
}
//===========================================================================
bool KeybGetShiftStatus ()
{
return g_bShiftKey;
}
//===========================================================================
void KeybUpdateCtrlShiftStatus()
{
// g_bShiftKey = (GetKeyState( VK_SHIFT ) & KF_UP) ? true : false; // 0x8000 KF_UP
// g_bCtrlKey = (GetKeyState( VK_CONTROL) & KF_UP) ? true : false;
// g_bAltKey = (GetKeyState( VK_MENU ) & KF_UP) ? true : false;
Uint8 *keys;
keys = SDL_GetKeyState(NULL);
g_bShiftKey = (keys[SDLK_LSHIFT] | keys[SDLK_RSHIFT]); // 0x8000 KF_UP SHIFT
g_bCtrlKey = (keys[SDLK_LCTRL] | keys[SDLK_RCTRL]); // CTRL
g_bAltKey = (keys[SDLK_LALT] | keys[SDLK_RALT]); // ALT
}
//===========================================================================
BYTE KeybGetKeycode() // Used by MemCheckPaging() & VideoCheckMode()
{
return keycode;
}
//===========================================================================
DWORD KeybGetNumQueries () // Used in determining 'idleness' of Apple system
{
DWORD result = keyboardqueries;
keyboardqueries = 0;
return result;
}
//===========================================================================
void KeybQueueKeypress (int key, BOOL bASCII)
{
// static bool bFreshReset; - do not use
if (bASCII == ASCII)
{
/* if (bFreshReset && key == 0x03)
{
bFreshReset = 0;
return; // Swallow spurious CTRL-C caused by CTRL-BREAK
}
bFreshReset = 0;*/
if (key > 0x7F) return;
// Conver SHIFTed keys to their secondary values
// may be this is straitfoward method, but it seems to be working. What else we need?? --bb
KeybUpdateCtrlShiftStatus();
if(g_bShiftKey) // SHIFT is pressed
switch(key) {
case '1': key = '!'; break;
case '2': key = '@'; break;
case '3': key = '#'; break;
case '4': key = '$'; break;
case '5': key = '%'; break;
case '6': key = '^'; break;
case '7': key = '&'; break;
case '8': key = '*'; break;
case '9': key = '('; break;
case '0': key = ')'; break;
case '`': key = '~'; break;
case '-': key = '_'; break;
case '=': key = '+'; break;
case '\\': key = '|'; break;
case '[': key = '{'; break;
case ']': key = '}'; break;
case ';': key = ':'; break;
case '\'': key = '"'; break;
case ',': key = '<'; break;
case '.': key = '>'; break;
case '/': key = '?'; break;
default: break;
}
else if (g_bCtrlKey) {
if(key >= SDLK_a && key <= SDLK_z) key = key - SDLK_a + 1;
else switch(key) {
case '\\': key = 28; break;
case '[' : key = 27; break;
case ']' : key = 29; break;
case SDLK_RETURN: key = 10; break;
default: break;
}
}
if (!IS_APPLE2)
{
if (g_bCapsLock && (key >= 'a') && (key <='z'))
keycode = key - 32;
else
keycode = key;
}
else
{
if (key >= '`')
keycode = key - 32;
else
keycode = key;
}
lastvirtkey = key;
}
else
{
/* if ((key == VK_CANCEL) && (GetKeyState(VK_CONTROL) < 0)) - implement in Frame.cpp
{
// Ctrl+Reset
if (!IS_APPLE2)
MemResetPaging();
DiskReset();
KeybReset();
if (!IS_APPLE2)
VideoResetState(); // Switch Alternate char set off
MB_Reset();
#ifndef KEY_OLD
g_nNextInIdx = g_nNextOutIdx = g_nKeyBufferCnt = 0;
#endif
CpuReset();
bFreshReset = 1;
return;
}
*/
/* No pasting??? Ye-e-e-e-et! */
// if ((key == VK_INSERT) && (GetKeyState(VK_SHIFT) < 0))
// {
// // Shift+Insert
// ClipboardInitiatePaste();
// return;
// }
// if (!((key >= VK_LEFT) && (key <= VK_DELETE) && asciicode[IS_APPLE2 ? 0 : 1][key - VK_LEFT]))
// return;
// keycode = asciicode[IS_APPLE2 ? 0 : 1][key - VK_LEFT]; // Convert to Apple arrow keycode
// lastvirtkey = key;
// {0x08,0x0D,0x15,0x2F,0x00,0x00,0x00,0x00,0x00,0x00}, - good old APPLE2
// {0x08,0x0B,0x15,0x0A,0x00,0x00,0x00,0x00,0x00,0x7F}
if(IS_APPLE2)
switch(key) {
case SDLK_LEFT: keycode = 0x08; break;
case SDLK_UP: keycode = 0x0D; break;
case SDLK_RIGHT:keycode = 0x15; break;
case SDLK_DOWN: keycode = 0x2F; break;
case SDLK_DELETE:keycode = 0x00;break;
default: return;
}
else
switch(key) {
case SDLK_LEFT: keycode = 0x08; break;
case SDLK_UP: keycode = 0x0B; break;
case SDLK_RIGHT:keycode = 0x15; break;
case SDLK_DOWN: keycode = 0x0A; break;
case SDLK_DELETE:keycode = 0x7F;break;
default: return;
}
lastvirtkey = key;
}
#ifdef KEY_OLD
keywaiting = 1;
#else
bool bOverflow = false;
if(g_nKeyBufferCnt < g_nKeyBufferSize)
g_nKeyBufferCnt++;
else
bOverflow = true;
g_nKeyBuffer[g_nNextInIdx].nVirtKey = lastvirtkey;
g_nKeyBuffer[g_nNextInIdx].nAppleKey = keycode;
g_nNextInIdx = (g_nNextInIdx + 1) % g_nKeyBufferSize;
if(bOverflow)
g_nNextOutIdx = (g_nNextOutIdx + 1) % g_nKeyBufferSize;
#endif
}
//===========================================================================
/*static HGLOBAL hglb = NULL;
static LPTSTR lptstr = NULL;
static bool g_bPasteFromClipboard = false;
static bool g_bClipboardActive = false;*/
/*
void ClipboardInitiatePaste()
{
if (g_bClipboardActive)
return;
g_bPasteFromClipboard = true;
}
static void ClipboardDone()
{
if (g_bClipboardActive)
{
g_bClipboardActive = false;
GlobalUnlock(hglb);
CloseClipboard();
}
}
static void ClipboardInit()
{
ClipboardDone();
if (!IsClipboardFormatAvailable(CF_TEXT))
return;
if (!OpenClipboard(g_hFrameWindow))
return;
hglb = GetClipboardData(CF_TEXT);
if (hglb == NULL)
{
CloseClipboard();
return;
}
lptstr = (char*) GlobalLock(hglb);
if (lptstr == NULL)
{
CloseClipboard();
return;
}
g_bPasteFromClipboard = false;
g_bClipboardActive = true;
}
static char ClipboardCurrChar(bool bIncPtr)
{
char nKey;
int nInc = 1;
if((lptstr[0] == 0x0D) && (lptstr[1] == 0x0A))
{
nKey = 0x0D;
nInc = 2;
}
else
{
nKey = lptstr[0];
}
if(bIncPtr)
lptstr += nInc;
return nKey;
}*/
//===========================================================================
BYTE /*__stdcall */KeybReadData (WORD, WORD, BYTE, BYTE, ULONG)
{
keyboardqueries++;
// if(g_bPasteFromClipboard)
// ClipboardInit();
//
// if(g_bClipboardActive)
// {
// if(*lptstr == 0)
// ClipboardDone();
// else
// return 0x80 | ClipboardCurrChar(false);
// }
//
#ifdef KEY_OLD
return keycode | (keywaiting ? 0x80 : 0);
#else
BYTE nKey = g_nKeyBufferCnt ? 0x80 : 0;
if(g_nKeyBufferCnt)
{
nKey |= g_nKeyBuffer[g_nNextOutIdx].nAppleKey;
g_nLastKey = g_nKeyBuffer[g_nNextOutIdx].nAppleKey;
}
else
{
nKey |= g_nLastKey;
}
return nKey;
#endif
}
//===========================================================================
BYTE /*__stdcall */KeybReadFlag (WORD, WORD, BYTE, BYTE, ULONG)
{
keyboardqueries++;
//
// if(g_bPasteFromClipboard)
// ClipboardInit();
//
// if(g_bClipboardActive)
// {
// if(*lptstr == 0)
// ClipboardDone();
// else
// return 0x80 | ClipboardCurrChar(true);
// }
//
Uint8 *keys;
keys = SDL_GetKeyState(NULL); // get current key state - thanx to SDL developers! ^_^ beom beotiger
#ifdef KEY_OLD
keywaiting = 0;
return keycode | (keys[lastvirtkey] ? 0x80 : 0);
#else
BYTE nKey = (keys[g_nKeyBuffer[g_nNextOutIdx].nVirtKey]) ? 0x80 : 0;
nKey |= g_nKeyBuffer[g_nNextOutIdx].nAppleKey;
if(g_nKeyBufferCnt)
{
g_nKeyBufferCnt--;
g_nNextOutIdx = (g_nNextOutIdx + 1) % g_nKeyBufferSize;
}
return nKey;
#endif
}
//===========================================================================
void KeybToggleCapsLock ()
{
if (!IS_APPLE2)
{
g_bCapsLock = !g_bCapsLock;// never mind real CapsLock status, heh???(GetKeyState(VK_CAPITAL) & 1);
// printf("g_bCapsLock=%d\n", g_bCapsLock);
// FrameRefreshStatus(DRAW_LEDS);
}
}
//===========================================================================
DWORD KeybGetSnapshot(SS_IO_Keyboard* pSS)
{
pSS->keyboardqueries = keyboardqueries;
pSS->nLastKey = g_nLastKey;
return 0;
}
DWORD KeybSetSnapshot(SS_IO_Keyboard* pSS)
{
keyboardqueries = pSS->keyboardqueries;
g_nLastKey = pSS->nLastKey;
return 0;
}