220 lines
8.8 KiB
C++
Executable File
220 lines
8.8 KiB
C++
Executable File
/*
|
|
* (C) 2006 Dirk W. Hoffmann. All rights reserved.
|
|
*
|
|
* This program 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.
|
|
*
|
|
* This program 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 this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#include "C64.h"
|
|
|
|
#define SHIFT_FLAG 0x1000
|
|
|
|
Keyboard::Keyboard()
|
|
{
|
|
name = "Keyboard";
|
|
debug(2, "Creating keyboard at address %p...\n", this);
|
|
|
|
for (int i = 0; i < 256; i++) {
|
|
rowcolmap[i] = 0xFFFF;
|
|
}
|
|
|
|
// 0 1 2 3 4 5 6 7
|
|
//
|
|
// 0 DEL RETURN CUR LR F7 F1 F3 F5 CUR UD
|
|
// 1 3 W A 4 Z S E LSHIFT
|
|
// 2 5 R D 6 C F T X
|
|
// 3 7 Y G 8 B H U V
|
|
// 4 9 I J 0 M K O N
|
|
// 5 + P L - . : @ ,
|
|
// 6 LIRA * ; HOME RSHIFT = ^ /
|
|
// 7 1 <- CTRL 2 SPACE C= Q STOP
|
|
rowcolmap[(unsigned char)'\n'] = 0x0001;
|
|
rowcolmap[(unsigned char)' '] = 0x0704;
|
|
rowcolmap[(unsigned char)'*'] = 0x0601;
|
|
rowcolmap[(unsigned char)'+'] = 0x0500;
|
|
rowcolmap[(unsigned char)','] = 0x0507; rowcolmap[(unsigned char)'<'] = 0x0507 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'-'] = 0x0503;
|
|
rowcolmap[(unsigned char)'.'] = 0x0504; rowcolmap[(unsigned char)'>'] = 0x0504 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'/'] = 0x0607; rowcolmap[(unsigned char)'?'] = 0x0607 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'^'] = 0x0701;
|
|
rowcolmap[(unsigned char)'~'] = 0x0701;
|
|
rowcolmap[C64KEY_ARROW] = 0x0701;
|
|
rowcolmap[(unsigned char)'0'] = 0x0403;
|
|
rowcolmap[(unsigned char)'1'] = 0x0700; rowcolmap[(unsigned char)'!'] = 0x0700 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'2'] = 0x0703; rowcolmap[(unsigned char)'"'] = 0x0703 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'3'] = 0x0100; rowcolmap[(unsigned char)'#'] = 0x0100 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'4'] = 0x0103; rowcolmap[(unsigned char)'$'] = 0x0103 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'5'] = 0x0200; rowcolmap[(unsigned char)'%'] = 0x0200 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'6'] = 0x0203; rowcolmap[(unsigned char)'&'] = 0x0203 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'7'] = 0x0300; rowcolmap[(unsigned char)'\'']= 0x0300 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'8'] = 0x0303; rowcolmap[(unsigned char)'('] = 0x0303 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'9'] = 0x0400; rowcolmap[(unsigned char)')'] = 0x0400 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)':'] = 0x0505; rowcolmap[(unsigned char)'['] = 0x0505 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)';'] = 0x0602; rowcolmap[(unsigned char)']'] = 0x0602 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'='] = 0x0605;
|
|
rowcolmap[(unsigned char)'@'] = 0x0506;
|
|
rowcolmap[(unsigned char)'a'] = 0x0102; rowcolmap[(unsigned char)'A'] = 0x0102 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'b'] = 0x0304; rowcolmap[(unsigned char)'B'] = 0x0304 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'c'] = 0x0204; rowcolmap[(unsigned char)'C'] = 0x0204 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'d'] = 0x0202; rowcolmap[(unsigned char)'D'] = 0x0202 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'e'] = 0x0106; rowcolmap[(unsigned char)'E'] = 0x0106 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'f'] = 0x0205; rowcolmap[(unsigned char)'F'] = 0x0205 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'g'] = 0x0302; rowcolmap[(unsigned char)'G'] = 0x0302 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'h'] = 0x0305; rowcolmap[(unsigned char)'H'] = 0x0305 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'i'] = 0x0401; rowcolmap[(unsigned char)'I'] = 0x0401 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'j'] = 0x0402; rowcolmap[(unsigned char)'J'] = 0x0402 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'k'] = 0x0405; rowcolmap[(unsigned char)'K'] = 0x0405 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'l'] = 0x0502; rowcolmap[(unsigned char)'L'] = 0x0502 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'m'] = 0x0404; rowcolmap[(unsigned char)'M'] = 0x0404 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'n'] = 0x0407; rowcolmap[(unsigned char)'N'] = 0x0407 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'o'] = 0x0406; rowcolmap[(unsigned char)'O'] = 0x0406 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'p'] = 0x0501; rowcolmap[(unsigned char)'P'] = 0x0501 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'q'] = 0x0706; rowcolmap[(unsigned char)'Q'] = 0x0706 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'r'] = 0x0201; rowcolmap[(unsigned char)'R'] = 0x0201 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'s'] = 0x0105; rowcolmap[(unsigned char)'S'] = 0x0105 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'t'] = 0x0206; rowcolmap[(unsigned char)'T'] = 0x0206 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'u'] = 0x0306; rowcolmap[(unsigned char)'U'] = 0x0306 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'v'] = 0x0307; rowcolmap[(unsigned char)'V'] = 0x0307 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'w'] = 0x0101; rowcolmap[(unsigned char)'W'] = 0x0101 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'x'] = 0x0207; rowcolmap[(unsigned char)'X'] = 0x0207 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'y'] = 0x0301; rowcolmap[(unsigned char)'Y'] = 0x0301 | SHIFT_FLAG;
|
|
rowcolmap[(unsigned char)'z'] = 0x0104; rowcolmap[(unsigned char)'Z'] = 0x0104 | SHIFT_FLAG;
|
|
rowcolmap[C64KEY_F1] = 0x0004; rowcolmap[C64KEY_F2] = 0x0004 | SHIFT_FLAG;
|
|
rowcolmap[C64KEY_F3] = 0x0005; rowcolmap[C64KEY_F4] = 0x0005 | SHIFT_FLAG;
|
|
rowcolmap[C64KEY_F5] = 0x0006; rowcolmap[C64KEY_F6] = 0x0006 | SHIFT_FLAG;
|
|
rowcolmap[C64KEY_F7] = 0x0003; rowcolmap[C64KEY_F8] = 0x0003 | SHIFT_FLAG;
|
|
rowcolmap[C64KEY_DEL] = 0x0000;
|
|
rowcolmap[C64KEY_INS] = 0x0000 | SHIFT_FLAG;
|
|
rowcolmap[C64KEY_RET] = 0x0001;
|
|
rowcolmap[C64KEY_CL] = 0x0002 | SHIFT_FLAG;
|
|
rowcolmap[C64KEY_CR] = 0x0002;
|
|
rowcolmap[C64KEY_CU] = 0x0007 | SHIFT_FLAG;
|
|
rowcolmap[C64KEY_CD] = 0x0007;
|
|
|
|
// Register snapshot items
|
|
SnapshotItem items[] = {
|
|
|
|
{ &kbMatrix, sizeof(kbMatrix), CLEAR_ON_RESET | BYTE_FORMAT },
|
|
{ NULL, 0, 0 }};
|
|
|
|
registerSnapshotItems(items, sizeof(items));
|
|
|
|
}
|
|
|
|
Keyboard::~Keyboard()
|
|
{
|
|
}
|
|
|
|
void
|
|
Keyboard::reset()
|
|
{
|
|
VirtualComponent::reset();
|
|
|
|
// Reset keyboard matrix (0 = pressed, 1 = not pressed)
|
|
for (int i = 0; i < 8; i++) {
|
|
kbMatrix[i] = 0xff;
|
|
}
|
|
}
|
|
|
|
void
|
|
Keyboard::dumpState()
|
|
{
|
|
msg("Keyboard:\n");
|
|
msg("---------\n\n");
|
|
msg("Keyboard matrix: ");
|
|
for (int i = 0; i < 8; i++) {
|
|
msg("%d %d %d %d %d %d %d %d\n ",
|
|
(kbMatrix[i] & 0x01) != 0, (kbMatrix[i] & 0x02) != 0, (kbMatrix[i] & 0x04) != 0, (kbMatrix[i] & 0x08) != 0,
|
|
(kbMatrix[i] & 0x10) != 0, (kbMatrix[i] & 0x20) != 0, (kbMatrix[i] & 0x40) != 0, (kbMatrix[i] & 0x80) != 0);
|
|
}
|
|
msg("\n");
|
|
}
|
|
|
|
uint8_t Keyboard::getRowValues(uint8_t columnMask)
|
|
{
|
|
uint8_t result = 0xff;
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
if ((columnMask & (1 << i)) == 0) {
|
|
result &= kbMatrix[i];
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void Keyboard::pressKey(uint8_t row, uint8_t col)
|
|
{
|
|
if (row < 8 && col < 8)
|
|
kbMatrix[row] &= 255 - (1 << col);
|
|
}
|
|
|
|
void Keyboard::pressKey(int c)
|
|
{
|
|
// Check for commodore key flag
|
|
if (c & C64KEY_COMMODORE) {
|
|
pressCommodoreKey();
|
|
}
|
|
|
|
c &= 0xFF;
|
|
|
|
// Only proceed if key is known and mapped
|
|
if (rowcolmap[c] == 0xFFFF)
|
|
return;
|
|
|
|
uint8_t row = (rowcolmap[c] & 0x0F00) >> 8;
|
|
uint8_t col = (rowcolmap[c] & 0x000F);
|
|
|
|
if (rowcolmap[c] & SHIFT_FLAG) {
|
|
pressShiftKey();
|
|
}
|
|
|
|
// debug("Pressing (%ld,%ld)\n", (long)(row), (long)(col));
|
|
pressKey(row, col);
|
|
}
|
|
|
|
void Keyboard::releaseKey(uint8_t row, uint8_t col)
|
|
{
|
|
if (row < 8 && col < 8) {
|
|
kbMatrix[row] |= (1 << col);
|
|
}
|
|
}
|
|
|
|
void Keyboard::releaseKey(int c)
|
|
{
|
|
// Check for commodore key flag
|
|
if (c & C64KEY_COMMODORE) {
|
|
releaseCommodoreKey();
|
|
}
|
|
|
|
c &= 0xFF;
|
|
|
|
// Only proceed if key is known and mapped
|
|
if (rowcolmap[c] == 0xFFFF)
|
|
return;
|
|
|
|
uint8_t row = (rowcolmap[c] & 0x0F00) >> 8;
|
|
uint8_t col = (rowcolmap[c] & 0x000F);
|
|
|
|
if (rowcolmap[c] & SHIFT_FLAG) {
|
|
releaseShiftKey();
|
|
}
|
|
|
|
// debug("Releasing (%ld,%ld)\n", (long)(row), (long)(col));
|
|
releaseKey(row, col);
|
|
}
|
|
|
|
#undef SHIFT_FLAG
|
|
|