}
+
uint32_t Emulator::readReg8(uint32_t reg) {
if (reg == PADR) {
- return readKeyboard(kScan);
+ return ((portValues >> 24) & 0x80) | (readKeyboard() & 0x7F);
} else if (reg == PBDR) {
- return (portValues >> 16) & 0xFF;
+ return ((portValues >> 16) & 0x0F) | (keyboardExtra << 4);
} else if (reg == PDDR) {
return (portValues >> 8) & 0xFF;
} else if (reg == PEDR) {
if (changes & 0x400000) log("PRT B6: %d", newval&0x400000);
if (changes & 0x800000) log("PRT B7: %d", newval&0x800000);
}
+
+
+uint32_t Emulator::readKeyboard() const {
+ if (kScan & 8) {
+ // Select one keyboard
+ if ((kScan & 7) < 7)
+ return keyboardColumns[kScan & 7];
+ else
+ return 0;
+ } else if (kScan == 0) {
+ // Report all columns combined
+ uint8_t val = 0;
+ for (int i = 0; i < 7; i++)
+ val |= keyboardColumns[i];
+ return val;
+ } else {
+ return 0;
+ }
+}
+
+void Emulator::setKeyboardKey(EpocKey key, bool value) {
+ int idx = -1;
+#define KEY(column, bit) idx = (column << 8) | (1 << bit); break
+
+ switch ((int)key) {
+ case '1': KEY(0, 0);
+ case '2': KEY(1, 0);
+ case '3': KEY(2, 0);
+ case '4': KEY(3, 0);
+ case '5': KEY(4, 0);
+ case '6': KEY(5, 0);
+ case '7': KEY(6, 0);
+
+ case '8': KEY(0, 1);
+ case '9': KEY(1, 1);
+ case '0': KEY(2, 1);
+ case 'P': KEY(3, 1);
+ case EStdKeySingleQuote: KEY(4, 1);
+ case EStdKeyEnter: KEY(5, 1);
+ case EStdKeyBackspace: KEY(6, 1);
+
+ case EStdKeyEscape: KEY(0, 2);
+ case 'Q': KEY(1, 2);
+ case 'W': KEY(2, 2);
+ case 'E': KEY(3, 2);
+ case 'R': KEY(4, 2);
+ case 'T': KEY(5, 2);
+ case 'Y': KEY(6, 2);
+
+ case 'U': KEY(0, 3);
+ case 'J': KEY(1, 3);
+ case 'I': KEY(2, 3);
+ case 'K': KEY(3, 3);
+ case 'O': KEY(4, 3);
+ case 'L': KEY(5, 3);
+ case EStdKeyUpArrow: KEY(6, 3);
+
+ case EStdKeyTab: KEY(0, 4);
+ case 'A': KEY(1, 4);
+ case 'S': KEY(2, 4);
+ case 'D': KEY(3, 4);
+ case 'F': KEY(4, 4);
+ case 'G': KEY(5, 4);
+ case 'H': KEY(6, 4);
+
+ case EStdKeySpace: KEY(0, 5);
+ case EStdKeyComma: KEY(1, 5);
+ case 'M': KEY(2, 5);
+ case EStdKeyFullStop: KEY(3, 5);
+ case EStdKeyLeftArrow: KEY(4, 5);
+ case EStdKeyDownArrow: KEY(5, 5);
+ case EStdKeyRightArrow: KEY(6, 5);
+
+ case 'Z': KEY(0, 6);
+ case 'X': KEY(1, 6);
+ case EStdKeyMenu: KEY(2, 6);
+ case 'C': KEY(3, 6);
+ case 'V': KEY(4, 6);
+ case 'B': KEY(5, 6);
+ case 'N': KEY(6, 6);
+
+ case EStdKeyLeftShift: KEY(8, 0);
+ case EStdKeyRightShift: KEY(8, 1);
+ case EStdKeyLeftCtrl: KEY(8, 2);
+ case EStdKeyLeftFunc: KEY(8, 3);
+ }
+
+ if (idx >= 0x800) {
+ if (value)
+ keyboardExtra |= (idx & 0xFF);
+ else
+ keyboardExtra &= ~(idx & 0xFF);
+ } else if (idx >= 0) {
+ if (value)
+ keyboardColumns[idx >> 8] |= (idx & 0xFF);
+ else
+ keyboardColumns[idx >> 8] &= ~(idx & 0xFF);
+ }
+}
+
}
uint32_t sysFlg1 = 0x20008000; // constant CL-PS7111 flag and cold start flag
uint32_t lcdControl = 0;
uint32_t lcdAddress = 0xC0000000;
- uint32_t kScan = 0;
uint32_t rtc = 0;
uint32_t rtcDiv = 0;
uint64_t lcdPalette = 0;
+ uint32_t kScan = 0;
+ uint8_t keyboardColumns[7] = {0,0,0,0,0,0,0};
+ uint8_t keyboardExtra = 0;
+
Timer tc1, tc2;
CLPS7600 pcCardController;
bool halted = false, asleep = false;
void fetchProcessFilename(uint32_t obj, char *buf);
void debugPC(uint32_t pc);
void diffPorts(uint32_t oldval, uint32_t newval);
+ uint32_t readKeyboard() const;
public:
Emulator();
int getLCDWidth() const override;
int getLCDHeight() const override;
void readLCDIntoBuffer(uint8_t **lines) const override;
+ void setKeyboardKey(EpocKey key, bool value) override;
};
}
#include "emubase.h"
-
-uint8_t EmuBase::readKeyboard(int kScan) {
- uint8_t val = 0;
- if (kScan & 8) {
- // Select one keyboard
- int whichColumn = kScan & 7;
- for (int i = 0; i < 7; i++)
- if (keyboardKeys[whichColumn * 7 + i])
- val |= (1 << i);
- } else if (kScan == 0) {
- // Report all columns combined
- // EPOC's keyboard driver relies on this...
- for (int i = 0; i < 8*7; i++)
- if (keyboardKeys[i])
- val |= (1 << (i % 7));
- }
- return val;
-}
#include "arm710.h"
#include <unordered_set>
+enum EpocKey {
+ EStdKeyDial = 161,
+ EStdKeyOff = 160,
+ EStdKeyHelp = 159,
+ EStdKeyDictaphoneRecord = 158,
+ EStdKeyDictaphoneStop = 157,
+ EStdKeyDictaphonePlay = 156,
+ EStdKeySliderUp = 155,
+ EStdKeySliderDown = 154,
+ EStdKeyDecContrast = 153,
+ EStdKeyIncContrast = 152,
+ EStdKeyBacklightToggle = 151,
+ EStdKeyBacklightOff = 150,
+ EStdKeyBacklightOn = 149,
+ EStdKeyMenu = 148,
+ EStdKeyNkpFullStop = 147,
+ EStdKeyNkp0 = 146,
+ EStdKeyNkp9 = 145,
+ EStdKeyNkp8 = 144,
+ EStdKeyNkp7 = 143,
+ EStdKeyNkp6 = 142,
+ EStdKeyNkp5 = 141,
+ EStdKeyNkp4 = 140,
+ EStdKeyNkp3 = 139,
+ EStdKeyNkp2 = 138,
+ EStdKeyNkp1 = 137,
+ EStdKeyNkpEnter = 136,
+ EStdKeyNkpPlus = 135,
+ EStdKeyNkpMinus = 134,
+ EStdKeyNkpAsterisk = 133,
+ EStdKeyNkpForwardSlash = 132,
+ EStdKeyEquals = 131,
+ EStdKeyMinus = 130,
+ EStdKeySquareBracketRight = 129,
+ EStdKeySquareBracketLeft = 128,
+ EStdKeyHash = 127,
+ EStdKeySingleQuote = 126,
+ EStdKeySemiColon = 125,
+ EStdKeyBackSlash = 124,
+ EStdKeyForwardSlash = 123,
+ EStdKeyFullStop = 122,
+ EStdKeyComma = 121,
+ EStdKeyXXX = 120,
+ EStdKeyF24 = 119,
+ EStdKeyF23 = 118,
+ EStdKeyF22 = 117,
+ EStdKeyF21 = 116,
+ EStdKeyF20 = 115,
+ EStdKeyF19 = 114,
+ EStdKeyF18 = 113,
+ EStdKeyF17 = 112,
+ EStdKeyF16 = 111,
+ EStdKeyF15 = 110,
+ EStdKeyF14 = 109,
+ EStdKeyF13 = 108,
+ EStdKeyF12 = 107,
+ EStdKeyF11 = 106,
+ EStdKeyF10 = 105,
+ EStdKeyF9 = 104,
+ EStdKeyF8 = 103,
+ EStdKeyF7 = 102,
+ EStdKeyF6 = 101,
+ EStdKeyF5 = 100,
+ EStdKeyF4 = 99,
+ EStdKeyF3 = 98,
+ EStdKeyF2 = 97,
+ EStdKeyF1 = 96,
+ EStdKeyScrollLock = 28,
+ EStdKeyNumLock = 27,
+ EStdKeyCapsLock = 26,
+ EStdKeyRightFunc = 25,
+ EStdKeyLeftFunc = 24,
+ EStdKeyRightCtrl = 23,
+ EStdKeyLeftCtrl = 22,
+ EStdKeyRightAlt = 21,
+ EStdKeyLeftAlt = 20,
+ EStdKeyRightShift = 19,
+ EStdKeyLeftShift = 18,
+ EStdKeyDownArrow = 17,
+ EStdKeyUpArrow = 16,
+ EStdKeyRightArrow = 15,
+ EStdKeyLeftArrow = 14,
+ EStdKeyDelete = 13,
+ EStdKeyInsert = 12,
+ EStdKeyPageDown = 11,
+ EStdKeyPageUp = 10,
+ EStdKeyEnd = 9,
+ EStdKeyHome = 8,
+ EStdKeyPause = 7,
+ EStdKeyPrintScreen = 6,
+ EStdKeySpace = 5,
+ EStdKeyEscape = 4,
+ EStdKeyEnter = 3,
+ EStdKeyTab = 2,
+ EStdKeyBackspace = 1,
+ EStdKeyNull = 0
+};
+
class EmuBase : public ARM710
{
protected:
virtual int getLCDWidth() const = 0;
virtual int getLCDHeight() const = 0;
virtual void readLCDIntoBuffer(uint8_t **lines) const = 0;
+ virtual void setKeyboardKey(EpocKey key, bool value) = 0;
std::unordered_set<uint32_t> &breakpoints() { return _breakpoints; }
uint64_t currentCycles() const { return passedCycles; }
-
- bool keyboardKeys[8*7] = {0};
};
} else if (reg == TC2CTRL) {
return tc2.config;
} else if (reg == PADR) {
- return readKeyboard(kScan);
+ return readKeyboard();
} else if (reg == PBDR) {
return (portValues >> 16) & 0xFF;
} else if (reg == PCDR) {
if (changes & 0x4000) log("INTCHG lcd=%d", newval & 0x4000);
if (changes & 0x8000) log("INTCHG spi=%d", newval & 0x8000);
}
+
+
+uint32_t Emulator::readKeyboard() {
+ if (kScan & 8) {
+ // Select one keyboard
+ return keyboardColumns[kScan & 7];
+ } else if (kScan == 0) {
+ // Report all columns combined
+ uint8_t val = 0;
+ for (int i = 0; i < 8; i++)
+ val |= keyboardColumns[i];
+ return val;
+ } else {
+ return 0;
+ }
+}
+
+void Emulator::setKeyboardKey(EpocKey key, bool value) {
+ int idx = -1;
+#define KEY(column, bit) idx = (column << 8) | (1 << bit); break
+
+ switch ((int)key) {
+ case EStdKeyDictaphoneRecord: KEY(0, 6);
+ case '1': KEY(0, 5);
+ case '2': KEY(0, 4);
+ case '3': KEY(0, 3);
+ case '4': KEY(0, 2);
+ case '5': KEY(0, 1);
+ case '6': KEY(0, 0);
+
+ case EStdKeyDictaphonePlay: KEY(1, 6);
+ case '7': KEY(1, 5);
+ case '8': KEY(1, 4);
+ case '9': KEY(1, 3);
+ case '0': KEY(1, 2);
+ case EStdKeyBackspace: KEY(1, 1);
+ case EStdKeySingleQuote: KEY(1, 0);
+
+ case EStdKeyEscape: KEY(2, 6);
+ case 'Q': KEY(2, 5);
+ case 'W': KEY(2, 4);
+ case 'E': KEY(2, 3);
+ case 'R': KEY(2, 2);
+ case 'T': KEY(2, 1);
+ case 'Y': KEY(2, 0);
+
+ case EStdKeyMenu: KEY(3, 6);
+ case 'U': KEY(3, 5);
+ case 'I': KEY(3, 4);
+ case 'O': KEY(3, 3);
+ case 'P': KEY(3, 2);
+ case 'L': KEY(3, 1);
+ case EStdKeyEnter: KEY(3, 0);
+
+ case EStdKeyLeftCtrl: KEY(4, 6);
+ case EStdKeyTab: KEY(4, 5);
+ case 'A': KEY(4, 4);
+ case 'S': KEY(4, 3);
+ case 'D': KEY(4, 2);
+ case 'F': KEY(4, 1);
+ case 'G': KEY(4, 0);
+
+ case EStdKeyLeftFunc: KEY(5, 6);
+ case 'H': KEY(5, 5);
+ case 'J': KEY(5, 4);
+ case 'K': KEY(5, 3);
+ case 'M': KEY(5, 2);
+ case EStdKeyFullStop: KEY(5, 1);
+ case EStdKeyDownArrow: KEY(5, 0);
+
+ case EStdKeyRightShift: KEY(6, 6);
+ case 'Z': KEY(6, 5);
+ case 'X': KEY(6, 4);
+ case 'C': KEY(6, 3);
+ case 'V': KEY(6, 2);
+ case 'B': KEY(6, 1);
+ case 'N': KEY(6, 0);
+
+ case EStdKeyLeftShift: KEY(7, 6);
+ case EStdKeyDictaphoneStop: KEY(7, 5);
+ case EStdKeySpace: KEY(7, 4);
+ case EStdKeyUpArrow: KEY(7, 3);
+ case EStdKeyComma: KEY(7, 2);
+ case EStdKeyLeftArrow: KEY(7, 1);
+ case EStdKeyRightArrow: KEY(7, 0);
+ }
+
+ if (idx >= 0) {
+ if (value)
+ keyboardColumns[idx >> 8] |= (idx & 0xFF);
+ else
+ keyboardColumns[idx >> 8] &= ~(idx & 0xFF);
+ }
+}
+
}
uint32_t pwrsr = 0x00002000; // cold start flag
uint32_t lcdControl = 0;
uint32_t lcdAddress = 0;
- uint32_t kScan = 0;
uint32_t rtc = 0;
+ uint32_t kScan = 0;
+ uint8_t keyboardColumns[8] = {0,0,0,0,0,0,0};
+
Timer tc1, tc2;
UART uart1, uart2;
Etna etna;
void debugPC(uint32_t pc);
void diffPorts(uint32_t oldval, uint32_t newval);
void diffInterrupts(uint16_t oldval, uint16_t newval);
+ uint32_t readKeyboard();
public:
Emulator();
int getLCDWidth() const override;
int getLCDHeight() const override;
void readLCDIntoBuffer(uint8_t **lines) const override;
+ void setKeyboardKey(EpocKey key, bool value) override;
};
}
}
-static int resolveKey(int key) {
+static EpocKey resolveKey(int key) {
switch (key) {
- case Qt::Key_6: return 0;
- case Qt::Key_5: return 1;
- case Qt::Key_4: return 2;
- case Qt::Key_3: return 3;
- case Qt::Key_2: return 4;
- case Qt::Key_1: return 5;
- // missing 6: F13/rec
-
- case Qt::Key_Apostrophe: return 7;
- case Qt::Key_Backspace: return 8;
- case Qt::Key_0: return 9;
- case Qt::Key_9: return 10;
- case Qt::Key_8: return 11;
- case Qt::Key_7: return 12;
- // missing 13: F15/play
-
- case Qt::Key_Y: return 14;
- case Qt::Key_T: return 15;
- case Qt::Key_R: return 16;
- case Qt::Key_E: return 17;
- case Qt::Key_W: return 18;
- case Qt::Key_Q: return 19;
- case Qt::Key_Escape: return 20;
-
- case Qt::Key_Enter: return 21;
- case Qt::Key_Return: return 21;
- case Qt::Key_L: return 22;
- case Qt::Key_P: return 23;
- case Qt::Key_O: return 24;
- case Qt::Key_I: return 25;
- case Qt::Key_U: return 26;
- case Qt::Key_Alt: return 27; // actually Menu
-
- case Qt::Key_G: return 28;
- case Qt::Key_F: return 29;
- case Qt::Key_D: return 30;
- case Qt::Key_S: return 31;
- case Qt::Key_A: return 32;
- case Qt::Key_Tab: return 33;
+ case Qt::Key_Apostrophe: return EStdKeySingleQuote;
+ case Qt::Key_Backspace: return EStdKeyBackspace;
+ case Qt::Key_Escape: return EStdKeyEscape;
+ case Qt::Key_Enter: return EStdKeyEnter;
+ case Qt::Key_Return: return EStdKeyEnter;
+ case Qt::Key_Alt: return EStdKeyMenu;
+ case Qt::Key_Tab: return EStdKeyTab;
#ifdef Q_OS_MAC
- case Qt::Key_Meta: return 34; // Control -> Control
+ case Qt::Key_Meta: return EStdKeyLeftCtrl;
#else
- case Qt::Key_Control: return 34; // Control -> Control
+ case Qt::Key_Control: return EStdKeyLeftCtrl;
#endif
-
- case Qt::Key_Down: return 35;
- case Qt::Key_Period: return 36;
- case Qt::Key_M: return 37;
- case Qt::Key_K: return 38;
- case Qt::Key_J: return 39;
- case Qt::Key_H: return 40;
+ case Qt::Key_Down: return EStdKeyDownArrow;
+ case Qt::Key_Period: return EStdKeyFullStop;
#ifdef Q_OS_MAC
- case Qt::Key_Control: return 41; // Command -> Fn
+ case Qt::Key_Control: return EStdKeyLeftFunc;
#else
- case Qt::Key_Meta: return 41; // Super -> Fn
+ case Qt::Key_Meta: return EStdKeyLeftFunc;
#endif
-
- case Qt::Key_N: return 42;
- case Qt::Key_B: return 43;
- case Qt::Key_V: return 44;
- case Qt::Key_C: return 45;
- case Qt::Key_X: return 46;
- case Qt::Key_Z: return 47;
- case Qt::Key_Shift: return 48;
-
- case Qt::Key_Right: return 49;
- case Qt::Key_Left: return 50;
- case Qt::Key_Comma: return 51;
- case Qt::Key_Up: return 52;
- case Qt::Key_Space: return 53;
- // missing 54: F14/stop
- // missing 55: another Shift
+ case Qt::Key_Shift: return EStdKeyLeftShift;
+ case Qt::Key_Right: return EStdKeyRightArrow;
+ case Qt::Key_Left: return EStdKeyLeftArrow;
+ case Qt::Key_Comma: return EStdKeyComma;
+ case Qt::Key_Up: return EStdKeyUpArrow;
+ case Qt::Key_Space: return EStdKeySpace;
}
- return -1;
+
+ if (key >= '0' && key <= '9') return (EpocKey)key;
+ if (key >= 'A' && key <= 'Z') return (EpocKey)key;
+ return EStdKeyNull;
}
void MainWindow::keyPressEvent(QKeyEvent *event)
{
- int k = resolveKey(event->key());
- if (k >= 0)
- emu->keyboardKeys[k] = true;
+ EpocKey k = resolveKey(event->key());
+ if (k != EStdKeyNull)
+ emu->setKeyboardKey(k, true);
}
void MainWindow::keyReleaseEvent(QKeyEvent *event)
{
- int k = resolveKey(event->key());
- if (k >= 0)
- emu->keyboardKeys[k] = false;
+ EpocKey k = resolveKey(event->key());
+ if (k != EStdKeyNull)
+ emu->setKeyboardKey(k, false);
}