diff --git a/WindCore/clps7111.cpp b/WindCore/clps7111.cpp index a007ad8..487d1b5 100644 --- a/WindCore/clps7111.cpp +++ b/WindCore/clps7111.cpp @@ -15,11 +15,12 @@ uint32_t Emulator::getRTC() { } + 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) { @@ -467,4 +468,104 @@ void Emulator::diffPorts(uint32_t oldval, uint32_t newval) { 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); + } +} + } diff --git a/WindCore/clps7111.h b/WindCore/clps7111.h index 925b405..9068062 100644 --- a/WindCore/clps7111.h +++ b/WindCore/clps7111.h @@ -21,11 +21,14 @@ private: 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; @@ -52,6 +55,7 @@ private: 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(); @@ -61,5 +65,6 @@ public: int getLCDWidth() const override; int getLCDHeight() const override; void readLCDIntoBuffer(uint8_t **lines) const override; + void setKeyboardKey(EpocKey key, bool value) override; }; } diff --git a/WindCore/emubase.cpp b/WindCore/emubase.cpp index 86574b5..33a7a3b 100644 --- a/WindCore/emubase.cpp +++ b/WindCore/emubase.cpp @@ -1,19 +1 @@ #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; -} diff --git a/WindCore/emubase.h b/WindCore/emubase.h index dba5405..a1653f0 100644 --- a/WindCore/emubase.h +++ b/WindCore/emubase.h @@ -2,6 +2,104 @@ #include "arm710.h" #include +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: @@ -19,10 +117,9 @@ public: 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 &breakpoints() { return _breakpoints; } uint64_t currentCycles() const { return passedCycles; } - - bool keyboardKeys[8*7] = {0}; }; diff --git a/WindCore/windermere.cpp b/WindCore/windermere.cpp index 7ada0c6..f781058 100644 --- a/WindCore/windermere.cpp +++ b/WindCore/windermere.cpp @@ -28,7 +28,7 @@ uint32_t Emulator::readReg8(uint32_t reg) { } 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) { @@ -562,4 +562,99 @@ void Emulator::diffInterrupts(uint16_t oldval, uint16_t newval) { 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); + } +} + } diff --git a/WindCore/windermere.h b/WindCore/windermere.h index dead660..469a929 100644 --- a/WindCore/windermere.h +++ b/WindCore/windermere.h @@ -23,9 +23,11 @@ private: 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; @@ -53,6 +55,7 @@ private: 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(); @@ -62,5 +65,6 @@ public: int getLCDWidth() const override; int getLCDHeight() const override; void readLCDIntoBuffer(uint8_t **lines) const override; + void setKeyboardKey(EpocKey key, bool value) override; }; } diff --git a/WindQt/mainwindow.cpp b/WindQt/mainwindow.cpp index 01e07a0..e1883d9 100644 --- a/WindQt/mainwindow.cpp +++ b/WindQt/mainwindow.cpp @@ -110,97 +110,53 @@ void MainWindow::updateScreen() } -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); }