aiie/apple/applekeyboard.cpp
2021-12-12 12:10:49 -05:00

205 lines
4.0 KiB
C++

#include "applekeyboard.h"
#include "physicalkeyboard.h" // for LA/RA constants
#include "applemmu.h"
#include "globals.h"
// How many CPU cycles before we begin repeating a key?
#define STARTREPEAT 700000
// How many CPU cycles between repeats of a key?
#define REPEATAGAIN 66667
AppleKeyboard::AppleKeyboard(AppleMMU *m)
{
this->mmu = m;
for (uint16_t i=0; i<sizeof(keysDown); i++) {
keysDown[i] = false;
}
anyKeyIsDown = false;
startRepeatTimer = 0;
repeatTimer = 0;
capsLockEnabled = true;
}
AppleKeyboard::~AppleKeyboard()
{
}
bool AppleKeyboard::isVirtualKey(uint8_t kc)
{
if (kc >= 0x81 && kc <= 0x86) {
return true;
}
return false;
}
// apply the apple keymap.
// FIXME: easier with an array, but is that better?
uint8_t AppleKeyboard::translateKeyWithModifiers(uint8_t k)
{
// tolower, so we know what we're working with...
if (k >= 'A' && k <= 'Z') {
k = k - 'A' + 'a';
}
if (keysDown[PK_CTRL]) {
if (k >= 'a' && k <= 'z') {
return k - 'a' + 1;
}
// FIXME: any other control keys honored on the //e keyboard?
}
if (capsLockEnabled && k >= 'a' && k <= 'z') {
return k - 'a' + 'A';
}
if (keysDown[PK_LSHFT] || keysDown[PK_RSHFT]) {
if (k >= 'a' && k <= 'z') {
return k - 'a' + 'A';
}
switch (k) {
case '1':
return '!';
case '2':
return '@';
case '3':
return '#';
case '4':
return '$';
case '5':
return '%';
case '6':
return '^';
case '7':
return '&';
case '8':
return '*';
case '9':
return '(';
case '0':
return ')';
case '-':
return '_';
case '=':
return '+';
case '[':
return '{';
case ']':
return '}';
case '\\':
return '|';
case '`':
return '~';
case ';':
return ':';
case '\'':
return '"';
case ',':
return '<';
case '.':
return '>';
case '/':
return '?';
}
// FIXME: what the heck is it? I guess we don't need to shift it?
}
// And if we fall through, then just return it as-is
return k;
}
void AppleKeyboard::keyDepressed(uint8_t k)
{
if (k >= 'A' && k <= 'Z') {
k = k - 'A' + 'a';
}
keysDown[k] = true;
// If it's not a virtual key, then set the anyKeyDown flag
// (the VM will see this as a keyboard key)
if (!isVirtualKey(k)) {
if (!anyKeyIsDown) {
mmu->setKeyDown(true);
anyKeyIsDown = true;
}
keyThatIsRepeating = translateKeyWithModifiers(k);
startRepeatTimer = g_cpu->cycles + STARTREPEAT;
mmu->keyboardInput(keyThatIsRepeating);
} else if (k == PK_LA) {
// Special handling: apple keys
mmu->setAppleKey(0, true);
return;
} else if (k == PK_RA) {
// Special handling: apple keys
mmu->setAppleKey(1, true);
return;
} else if (k == PK_LOCK) {
// Special handling: caps lock
capsLockEnabled = !capsLockEnabled;
return;
}
}
void AppleKeyboard::keyReleased(uint8_t k)
{
if (k >= 'A' && k <= 'Z') {
k = k - 'A' + 'a';
}
keysDown[k] = false;
// Special handling: apple keys
if (k == PK_LA) {
mmu->setAppleKey(0, false);
return;
}
if (k == PK_RA) {
mmu->setAppleKey(1, false);
return;
}
if (k == PK_LOCK) {
// Nothing to do when the caps lock key is released.
return;
}
if (anyKeyIsDown) {
anyKeyIsDown = false;
for (int i=0; i<sizeof(keysDown); i++) {
if (keysDown[i] && !isVirtualKey(i)) {
anyKeyIsDown = true;
break;
}
}
if (!anyKeyIsDown) {
mmu->setKeyDown(false);
}
}
}
void AppleKeyboard::maintainKeyboard(int64_t cycleCount)
{
if (anyKeyIsDown) {
if (startRepeatTimer) {
if (cycleCount >= startRepeatTimer) {
// waiting to start repeating
startRepeatTimer = 0;
repeatTimer = 0;
// Will fall through...
} else {
// Don't fall through; not time to start repeating yet
return;
}
}
// already repeating; keep it up
if (cycleCount >= repeatTimer) {
mmu->keyboardInput(keyThatIsRepeating);
repeatTimer = cycleCount + REPEATAGAIN;
}
}
}