mirror of
https://github.com/JorjBauer/aiie.git
synced 2024-10-31 09:15:51 +00:00
205 lines
4.0 KiB
C++
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;
|
|
}
|
|
}
|
|
}
|