Skip to content

Commit

Permalink
Improved keyboard handling on macOS by caching key status in an inter…
Browse files Browse the repository at this point in the history
…nal buffer
  • Loading branch information
doraemoncito committed Jun 14, 2024
1 parent d4b8563 commit d93711d
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 28 deletions.
8 changes: 4 additions & 4 deletions src/emulator/common/Z80emu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,10 +220,10 @@ uint8_t Z80emu::inPort(uint16_t port) {
} else if (port == 0x011Fu) { // Kempston joystick port
// No need to do anything here at this point
} else {
#ifdef DEBUG
// Log the port number that the emulated ZX Spectrum software is trying to access
CLogger::Get()->Write(msgFromULA, LogDebug, "[PORT IN ] port 0x%04X <-- value 0x%02X", port, m_pIOPort[port]);
#endif
//#ifdef DEBUG
// // Log the port number that the emulated ZX Spectrum software is trying to access
// CLogger::Get()->Write(msgFromULA, LogDebug, "[PORT IN ] port 0x%04X <-- value 0x%02X", port, m_pIOPort[port]);
//#endif
}

return m_pIOPort[port];
Expand Down
199 changes: 179 additions & 20 deletions src/emulator/macos/zxkeyboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,30 @@
* ---------------------------------------------------------------------------
*
* The neat arrangement of ports means that the B register need only be rotated left to work up the left-hand side and
* then down the right-hand side of the keyboard. When the reset bit drops into the carry then all 8 half-rows have
* then down the right-hand side of the keyboard. When the reset bit drops into the carry, then all 8 half-rows have
* been read. Shift is the first key to be read. The lower six bits of the shifts are unambiguous.
*
* reference: https://web.archive.org/web/20150825085532/http://www.wearmouth.demon.co.uk/zx82.htm
*/

void ZxKeyboard::keyPressEvent(Z80emu &zxRaspberry, QKeyEvent &event) {
ZxKeyboard::ZxKeyboard() {
}


void ZxKeyboard::reset() {

uint8_t port_F7FE = 0xFFu;
uint8_t port_FBFE = 0xFFu;
uint8_t port_FDFE = 0xFFu;
uint8_t port_FEFE = 0xFFu;
uint8_t port_EFFE = 0xFFu;
uint8_t port_DFFE = 0xFFu;
uint8_t port_BFFE = 0xFFu;
uint8_t port_7FFE = 0xFFu;
port_F7FE = 0xFFu;
port_FBFE = 0xFFu;
port_FDFE = 0xFFu;
port_FEFE = 0xFFu;
port_EFFE = 0xFFu;
port_DFFE = 0xFFu;
port_BFFE = 0xFFu;
port_7FFE = 0xFFu;
}


void ZxKeyboard::keyPressEvent(Z80emu &zxRaspberry, QKeyEvent &event) {

// qDebug() << "Received key press event" << &event;

Expand Down Expand Up @@ -235,19 +243,170 @@ void ZxKeyboard::keyPressEvent(Z80emu &zxRaspberry, QKeyEvent &event) {
}


void ZxKeyboard::keyReleaseEvent(Z80emu &zxRaspberry, QKeyEvent &) {

uint8_t port_F7FE = 0xFFu;
uint8_t port_FBFE = 0xFFu;
uint8_t port_FDFE = 0xFFu;
uint8_t port_FEFE = 0xFFu;
uint8_t port_EFFE = 0xFFu;
uint8_t port_DFFE = 0xFFu;
uint8_t port_BFFE = 0xFFu;
uint8_t port_7FFE = 0xFFu;
void ZxKeyboard::keyReleaseEvent(Z80emu &zxRaspberry, QKeyEvent &event) {

// qDebug() << "Received key release event" << &event;

// Modifier keys pressed on their own
switch (event.key()) {
case Qt::Key_Shift: // Left shift key -> CAPS SHIFT
port_FEFE |= ~KEY_PRESSED_BIT0;
break;
case Qt::Key_Control: // Command key -> SYMBOL SHIFT
case Qt::Key_Meta: // Control key -> SYMBOL SHIFT
case Qt::Key_Alt: // Option key -> SYMBOL SHIFT
case Qt::Key_AltGr: // Alt Gr -> SYMBOL SHIFT
port_7FFE |= ~KEY_PRESSED_BIT1;
break;
}

// Key modifiers when used in combination with other keys
Qt::KeyboardModifiers modifiers = event.modifiers();

if (modifiers & Qt::ShiftModifier)
port_FEFE |= ~KEY_PRESSED_BIT0;

if ((modifiers & Qt::ControlModifier) || (modifiers & Qt::AltModifier) || (modifiers & Qt::MetaModifier))
port_7FFE |= ~KEY_PRESSED_BIT1;

switch (event.key()) {
// row 0xF7FE
case Qt::Key_1: // 1
port_F7FE |= ~KEY_PRESSED_BIT0;
break;
case Qt::Key_2: // 2
port_F7FE |= ~KEY_PRESSED_BIT1;
break;
case Qt::Key_3: // 3
port_F7FE |= ~KEY_PRESSED_BIT2;
break;
case Qt::Key_4: // 4
port_F7FE |= ~KEY_PRESSED_BIT3;
break;
case Qt::Key_Left:
case Qt::Key_5: // 5 (left)
port_F7FE |= ~KEY_PRESSED_BIT4;
break;

// row 0xEFFE
case Qt::Key_Down:
case Qt::Key_6: // 6 (down)
port_EFFE |= ~KEY_PRESSED_BIT4;
break;
case Qt::Key_Up:
case Qt::Key_7: // 7 (up)
port_EFFE |= ~KEY_PRESSED_BIT3;
break;
case Qt::Key_Right:
case Qt::Key_8: // 8 (right)
port_EFFE |= ~KEY_PRESSED_BIT2;
break;
case Qt::Key_9: // 9
port_EFFE |= ~KEY_PRESSED_BIT1;
break;
case Qt::Key_0: // 0
port_EFFE |= ~KEY_PRESSED_BIT0;
break;

// row 0xFBFE
case Qt::Key_Q: // Q
port_FBFE |= ~KEY_PRESSED_BIT0;
break;
case Qt::Key_W: // W
port_FBFE |= ~KEY_PRESSED_BIT1;
break;
case Qt::Key_E: // E
port_FBFE |= ~KEY_PRESSED_BIT2;
break;
case Qt::Key_R: // R
port_FBFE |= ~KEY_PRESSED_BIT3;
break;
case Qt::Key_T: // T
port_FBFE |= ~KEY_PRESSED_BIT4;
break;

// row 0xDFFE
case Qt::Key_Y: // Y
port_DFFE |= ~KEY_PRESSED_BIT4;
break;
case Qt::Key_U: // U
port_DFFE |= ~KEY_PRESSED_BIT3;
break;
case Qt::Key_I: // I
port_DFFE |= ~KEY_PRESSED_BIT2;
break;
case Qt::Key_O: // O
port_DFFE |= ~KEY_PRESSED_BIT1;
break;
case Qt::Key_P: // P
port_DFFE |= ~KEY_PRESSED_BIT0;
break;

// row 0xFDFE
case Qt::Key_A: // A
port_FDFE |= ~KEY_PRESSED_BIT0;
break;
case Qt::Key_S: // S
port_FDFE |= ~KEY_PRESSED_BIT1;
break;
case Qt::Key_D: // D
port_FDFE |= ~KEY_PRESSED_BIT2;
break;
case Qt::Key_F: // F
port_FDFE |= ~KEY_PRESSED_BIT3;
break;
case Qt::Key_G: // G
port_FDFE |= ~KEY_PRESSED_BIT4;
break;

// row 0xBFFE
case Qt::Key_H: // H
port_BFFE |= ~KEY_PRESSED_BIT4;
break;
case Qt::Key_J: // J
port_BFFE |= ~KEY_PRESSED_BIT3;
break;
case Qt::Key_K: // K
port_BFFE |= ~KEY_PRESSED_BIT2;
break;
case Qt::Key_L: // L
port_BFFE |= ~KEY_PRESSED_BIT1;
break;
case Qt::Key_Return:
case Qt::Key_Enter: // ENTER
port_BFFE |= ~KEY_PRESSED_BIT0;
break;

// row 0xFEFE
case Qt::Key_Z: // Z
port_FEFE |= ~KEY_PRESSED_BIT1;
break;
case Qt::Key_X: // X
port_FEFE |= ~KEY_PRESSED_BIT2;
break;
case Qt::Key_C: // C
port_FEFE |= ~KEY_PRESSED_BIT3;
break;
case Qt::Key_V: // V
port_FEFE |= ~KEY_PRESSED_BIT4;
break;

// row 0x7FFE
case Qt::Key_B: // B
port_7FFE |= ~KEY_PRESSED_BIT4;
break;
case Qt::Key_N: // N
port_7FFE |= ~KEY_PRESSED_BIT3;
break;
case Qt::Key_M: // M
port_7FFE |= ~KEY_PRESSED_BIT2;
break;
// SYMBOL SHIFT is handled as a modifier. See code above.
case Qt::Key_Space: // BREAK SPACE
port_7FFE |= ~KEY_PRESSED_BIT0;
break;
}

zxRaspberry.internalOutPort(0xF7FE, port_F7FE);
zxRaspberry.internalOutPort(0xFBFE, port_FBFE);
zxRaspberry.internalOutPort(0xFDFE, port_FDFE);
Expand Down
25 changes: 25 additions & 0 deletions src/emulator/macos/zxkeyboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,34 @@ class Z80emu;
class ZxKeyboard {

public:
ZxKeyboard();
void reset();
void keyPressEvent(Z80emu &zxRaspberry, QKeyEvent &event);
void keyReleaseEvent(Z80emu &zxRaspberry, QKeyEvent &event);

private:

// uint8_t m_keyboardPort[8] = {0xFFu,0xFFu,0xFFu,0xFFu,0xFFu,0xFFu,0xFFu,0xFFu };
// enum PORT {
// PORT_F7FE = 0,
// PORT_FBFE,
// PORT_FDFE,
// PORT_FEFE,
// PORT_EFFE,
// PORT_DFFE,
// PORT_BFFE,
// PORT_7FFE
// };

uint8_t port_F7FE = 0xFFu;
uint8_t port_FBFE = 0xFFu;
uint8_t port_FDFE = 0xFFu;
uint8_t port_FEFE = 0xFFu;
uint8_t port_EFFE = 0xFFu;
uint8_t port_DFFE = 0xFFu;
uint8_t port_BFFE = 0xFFu;
uint8_t port_7FFE = 0xFFu;

};


Expand Down
8 changes: 4 additions & 4 deletions src/emulator/raspi/kernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@
#include "../include/zx48k_rom.h"
//#include "test_2scrn_y_ay8192_sna.h"
//#include "fpga48all_sna.h"
//#include "testkeys_sna.h"
#include "testkeys_sna.h"
//#include "overscan_sna.h"
#include "automania_sna.h"
//#include "automania_sna.h"
//#include "aquaplane_sna.h"
//#include "shock_sna.h"
#include "kernel.h"
Expand Down Expand Up @@ -214,8 +214,8 @@ unsigned clockTicksToMicroSeconds(unsigned ticks) {
// z80emu->loadSnapshot(aquaplane_sna, aquaplane_sna_len);
// z80emu->loadSnapshot(overscan_sna, overscan_sna_len);
// z80emu->loadSnapshot(test_2scrn_y_ay8192_sna, test_2scrn_y_ay8192_sna_len);
z80emu->loadSnapshot(automania_sna, automania_sna_len);
// z80emu->loadSnapshot(testkeys_sna, testkeys_sna_len);
// z80emu->loadSnapshot(automania_sna, automania_sna_len);
z80emu->loadSnapshot(testkeys_sna, testkeys_sna_len);
// z80emu->loadSnapshot(fpga48all_sna, fpga48all_sna_len);

CCPUThrottle *ccpuThrottle = new CCPUThrottle(CPUSpeedUnknown);
Expand Down

0 comments on commit d93711d

Please sign in to comment.