diff --git a/Machines/Electron/Electron.cpp b/Machines/Electron/Electron.cpp index af60bb8de..9932d5537 100644 --- a/Machines/Electron/Electron.cpp +++ b/Machines/Electron/Electron.cpp @@ -447,6 +447,8 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin update_audio(); _tape.run_for_cycles(cycles); + if(_typer) _typer->update(cycles); + return cycles; } @@ -1051,3 +1053,98 @@ inline void Tape::run_for_cycles(unsigned int number_of_cycles) } } } + +#pragma mark - Typer + +int Machine::get_typer_delay() +{ + return get_reset_line() ? 625*25*128 : 0; // wait one second if resetting +} + +int Machine::get_typer_frequency() +{ + return 625*128; // accept a new character every frame +} + +bool Machine::typer_set_next_character(::Utility::Typer *typer, char character, int phase) +{ + if(!phase) clear_all_keys(); + + // The following table is arranged in ASCII order + Key key_sequences[][3] = { + {NotMapped}, {NotMapped}, {NotMapped}, {NotMapped}, {NotMapped}, {NotMapped}, {NotMapped}, {NotMapped}, + {KeyDelete, TerminateSequence}, + {NotMapped}, + {KeyReturn, TerminateSequence}, + {NotMapped}, {NotMapped}, {NotMapped}, {NotMapped}, {NotMapped}, + {NotMapped}, {NotMapped}, {NotMapped}, {NotMapped}, + {NotMapped}, {NotMapped}, {NotMapped}, {NotMapped}, + {NotMapped}, {NotMapped}, {NotMapped}, {NotMapped}, + {NotMapped}, {NotMapped}, {NotMapped}, {NotMapped}, + + {KeySpace, TerminateSequence}, // space + + {KeyShift, Key1, TerminateSequence}, {KeyShift, Key2, TerminateSequence}, // !, " + {KeyShift, Key3, TerminateSequence}, {KeyShift, Key4, TerminateSequence}, // #, $ + {KeyShift, Key5, TerminateSequence}, {KeyShift, Key6, TerminateSequence}, // %, & + {KeyShift, Key7, TerminateSequence}, {KeyShift, Key8, TerminateSequence}, // ', ( + {KeyShift, Key9, TerminateSequence}, {KeyShift, KeyColon, TerminateSequence}, // ), * + {KeyShift, KeySemiColon, TerminateSequence}, {KeyComma, TerminateSequence}, // +, , + {KeyMinus, TerminateSequence}, {KeyFullStop, TerminateSequence}, // -, . + {KeySlash, TerminateSequence}, // / + + {Key0, TerminateSequence}, {Key1, TerminateSequence}, // 0, 1 + {Key2, TerminateSequence}, {Key3, TerminateSequence}, // 2, 3 + {Key4, TerminateSequence}, {Key5, TerminateSequence}, // 4, 5 + {Key6, TerminateSequence}, {Key7, TerminateSequence}, // 6, 7 + {Key8, TerminateSequence}, {Key9, TerminateSequence}, // 8, 9 + + {KeyColon, TerminateSequence}, {KeySemiColon, TerminateSequence}, // :, ; + {KeyShift, KeyComma, TerminateSequence}, {KeyShift, KeyMinus, TerminateSequence}, // <, = + {KeyShift, KeyFullStop, TerminateSequence}, {KeyShift, KeySlash, TerminateSequence}, // >, ? + {NotMapped}, // @ + + {KeyA, TerminateSequence}, {KeyB, TerminateSequence}, {KeyC, TerminateSequence}, {KeyD, TerminateSequence}, // A, B, C, D + {KeyE, TerminateSequence}, {KeyF, TerminateSequence}, {KeyG, TerminateSequence}, {KeyH, TerminateSequence}, // E, F, G, H + {KeyI, TerminateSequence}, {KeyJ, TerminateSequence}, {KeyK, TerminateSequence}, {KeyL, TerminateSequence}, // I, J, K L + {KeyM, TerminateSequence}, {KeyN, TerminateSequence}, {KeyO, TerminateSequence}, {KeyP, TerminateSequence}, // M, N, O, P + {KeyQ, TerminateSequence}, {KeyR, TerminateSequence}, {KeyS, TerminateSequence}, {KeyT, TerminateSequence}, // Q, R, S, T + {KeyU, TerminateSequence}, {KeyV, TerminateSequence}, {KeyW, TerminateSequence}, {KeyX, TerminateSequence}, // U, V, W X + {KeyY, TerminateSequence}, {KeyZ, TerminateSequence}, // Y, Z + + {NotMapped}, {KeyControl, KeyRight, TerminateSequence}, // [, '\' + {NotMapped}, {KeyShift, KeyLeft, TerminateSequence}, // ], ^ + {KeyShift, KeyDown, TerminateSequence}, {NotMapped}, // _, ` + + {KeyShift, KeyA, TerminateSequence}, {KeyShift, KeyB, TerminateSequence}, {KeyShift, KeyC, TerminateSequence}, {KeyShift, KeyD, TerminateSequence}, // a, b, c, d + {KeyShift, KeyE, TerminateSequence}, {KeyShift, KeyF, TerminateSequence}, {KeyShift, KeyG, TerminateSequence}, {KeyShift, KeyH, TerminateSequence}, // e, f, g, h + {KeyShift, KeyI, TerminateSequence}, {KeyShift, KeyJ, TerminateSequence}, {KeyShift, KeyK, TerminateSequence}, {KeyShift, KeyL, TerminateSequence}, // i, j, k, l + {KeyShift, KeyM, TerminateSequence}, {KeyShift, KeyN, TerminateSequence}, {KeyShift, KeyO, TerminateSequence}, {KeyShift, KeyP, TerminateSequence}, // m, n, o, p + {KeyShift, KeyQ, TerminateSequence}, {KeyShift, KeyR, TerminateSequence}, {KeyShift, KeyS, TerminateSequence}, {KeyShift, KeyT, TerminateSequence}, // q, r, s, t + {KeyShift, KeyU, TerminateSequence}, {KeyShift, KeyV, TerminateSequence}, {KeyShift, KeyW, TerminateSequence}, {KeyShift, KeyX, TerminateSequence}, // u, v, w, x + {KeyShift, KeyY, TerminateSequence}, {KeyShift, KeyZ, TerminateSequence}, // y, z + + {KeyControl, KeyUp, TerminateSequence}, {KeyShift, KeyRight, TerminateSequence}, // {, | + {KeyControl, KeyDown, TerminateSequence}, {KeyControl, KeyLeft, TerminateSequence}, // }, ~ + }; + Key *key_sequence = nullptr; + + character &= 0x7f; + if(character < sizeof(key_sequences) / sizeof(*key_sequences)) + { + key_sequence = key_sequences[character]; + + if(key_sequence[0] != NotMapped) + { + if(phase > 0) + { + set_key_state(key_sequence[phase-1], true); + return key_sequence[phase] == TerminateSequence; + } + else + return false; + } + } + + return true; +} diff --git a/Machines/Electron/Electron.hpp b/Machines/Electron/Electron.hpp index f1ba9a312..6fe964641 100644 --- a/Machines/Electron/Electron.hpp +++ b/Machines/Electron/Electron.hpp @@ -11,8 +11,11 @@ #include "../../Processors/6502/CPU6502.hpp" #include "../../Storage/Tape/Tape.hpp" + #include "../CRTMachine.hpp" -#include +#include "../Typer.hpp" + +#include namespace Electron { @@ -54,7 +57,9 @@ enum Key: uint16_t { KeyZ = 0x00c0 | 0x08, KeyA = 0x00c0 | 0x04, KeyQ = 0x00c0 | 0x02, Key1 = 0x00c0 | 0x01, KeyShift = 0x00d0 | 0x08, KeyControl = 0x00d0 | 0x04, KeyFunc = 0x00d0 | 0x02, KeyEscape = 0x00d0 | 0x01, - KeyBreak = 0xffff + KeyBreak = 0xffff, + + TerminateSequence = 0, NotMapped = 0xfffe, }; class Tape { @@ -141,10 +146,13 @@ class Speaker: public ::Outputs::Filter { @discussion An instance of Electron::Machine represents the current state of an Acorn Electron. */ -class Machine: public CPU6502::Processor, public CRTMachine::Machine, Tape::Delegate { +class Machine: + public CPU6502::Processor, + public CRTMachine::Machine, + Tape::Delegate, + public Utility::TypeRecipient { public: - Machine(); void set_rom(ROMSlot slot, size_t length, const uint8_t *data); @@ -170,6 +178,11 @@ class Machine: public CPU6502::Processor, public CRTMachine::Machine, T // to satisfy Tape::Delegate virtual void tape_did_change_interrupt_status(Tape *tape); + // for Utility::TypeRecipient + virtual int get_typer_delay(); + virtual int get_typer_frequency(); + virtual bool typer_set_next_character(Utility::Typer *typer, char character, int phase); + private: inline void update_display();