diff --git a/Machines/Thomson/MO5/Keyboard.hpp b/Machines/Thomson/MO5/Keyboard.hpp index 6e517a4d6..9ff7ca1c6 100644 --- a/Machines/Thomson/MO5/Keyboard.hpp +++ b/Machines/Thomson/MO5/Keyboard.hpp @@ -11,7 +11,7 @@ #include "Machines/KeyboardMachine.hpp" #include "Machines/Utility/Typer.hpp" -namespace MO5 { +namespace Thomson::MO5 { enum Key: uint16_t { Key0 = 0x1e, Key1 = 0x2f, Key2 = 0x27, Key3 = 0x1f, @@ -51,6 +51,8 @@ enum Key: uint16_t { KeyACC = 0x36, KeyStop = 0x37, + + KeyForwardSlash = 0x00, // TODO. It does exist. }; struct KeyboardMapper: public MachineTypes::MappedKeyboardMachine::KeyboardMapper { @@ -114,4 +116,81 @@ struct KeyboardMapper: public MachineTypes::MappedKeyboardMachine::KeyboardMappe } }; +struct CharacterMapper: public ::Utility::CharacterMapper { + const uint16_t *sequence_for_character(const char character) const final { + #define KEYS(...) {__VA_ARGS__, MachineTypes::MappedKeyboardMachine::KeyEndSequence} + #define SHIFT(...) {KeyShift, __VA_ARGS__, MachineTypes::MappedKeyboardMachine::KeyEndSequence} + #define X {MachineTypes::MappedKeyboardMachine::KeyNotMapped} + static constexpr KeySequence key_sequences[] = { + /* NUL */ X, /* SOH */ X, + /* STX */ X, /* ETX */ X, + /* EOT */ X, /* ENQ */ X, + /* ACK */ X, /* BEL */ X, + /* BS */ X, /* HT */ X, + /* LF */ KEYS(KeyEnter), /* VT */ X, + /* FF */ X, /* CR */ X, + /* SO */ X, /* SI */ X, + /* DLE */ X, /* DC1 */ X, + /* DC2 */ X, /* DC3 */ X, + /* DC4 */ X, /* NAK */ X, + /* SYN */ X, /* ETB */ X, + /* CAN */ X, /* EM */ X, + /* SUB */ X, /* ESC */ X, + /* FS */ X, /* GS */ X, + /* RS */ X, /* US */ X, + /* space */ KEYS(KeySpace), /* ! */ SHIFT(Key1), + /* " */ SHIFT(Key2), /* # */ SHIFT(Key3), + /* $ */ SHIFT(Key4), /* % */ SHIFT(Key5), + /* & */ SHIFT(Key6), /* ' */ SHIFT(Key7), + /* ( */ SHIFT(Key8), /* ) */ SHIFT(Key9), + /* * */ KEYS(KeyAsterisk), /* + */ SHIFT(KeyPlus), + /* , */ KEYS(KeyComma), /* - */ KEYS(KeyMinus), + /* . */ KEYS(KeyFullStop), /* / */ KEYS(KeyForwardSlash), + /* 0 */ KEYS(Key0), /* 1 */ KEYS(Key1), + /* 2 */ KEYS(Key2), /* 3 */ KEYS(Key3), + /* 4 */ KEYS(Key4), /* 5 */ KEYS(Key5), + /* 6 */ KEYS(Key6), /* 7 */ KEYS(Key7), + /* 8 */ KEYS(Key8), /* 9 */ KEYS(Key9), + /* : */ SHIFT(KeyAsterisk), /* ; */ SHIFT(KeyPlus), + /* < */ SHIFT(KeyComma), /* = */ SHIFT(KeyMinus), + /* > */ SHIFT(KeyFullStop), /* ? */ SHIFT(KeyForwardSlash), + /* @ */ KEYS(KeyAt), /* A */ SHIFT(KeyA), + /* B */ SHIFT(KeyB), /* C */ SHIFT(KeyC), + /* D */ SHIFT(KeyD), /* E */ SHIFT(KeyE), + /* F */ SHIFT(KeyF), /* G */ SHIFT(KeyG), + /* H */ SHIFT(KeyH), /* I */ SHIFT(KeyI), + /* J */ SHIFT(KeyJ), /* K */ SHIFT(KeyK), + /* L */ SHIFT(KeyL), /* M */ SHIFT(KeyM), + /* N */ SHIFT(KeyN), /* O */ SHIFT(KeyO), + /* P */ SHIFT(KeyP), /* Q */ SHIFT(KeyQ), + /* R */ SHIFT(KeyR), /* S */ SHIFT(KeyS), + /* T */ SHIFT(KeyT), /* U */ SHIFT(KeyU), + /* V */ SHIFT(KeyV), /* W */ SHIFT(KeyW), + /* X */ SHIFT(KeyX), /* Y */ SHIFT(KeyY), + /* Z */ SHIFT(KeyZ), /* [ */ X, + /* \ */ X, /* ] */ X, + /* ^ */ SHIFT(KeyAt), /* _ */ X, + /* ` */ X, /* a */ KEYS(KeyA), + /* b */ KEYS(KeyB), /* c */ KEYS(KeyC), + /* d */ KEYS(KeyD), /* e */ KEYS(KeyE), + /* f */ KEYS(KeyF), /* g */ KEYS(KeyG), + /* h */ KEYS(KeyH), /* i */ KEYS(KeyI), + /* j */ KEYS(KeyJ), /* k */ KEYS(KeyK), + /* l */ KEYS(KeyL), /* m */ KEYS(KeyM), + /* n */ KEYS(KeyN), /* o */ KEYS(KeyO), + /* p */ KEYS(KeyP), /* q */ KEYS(KeyQ), + /* r */ KEYS(KeyR), /* s */ KEYS(KeyS), + /* t */ KEYS(KeyT), /* u */ KEYS(KeyU), + /* v */ KEYS(KeyV), /* w */ KEYS(KeyW), + /* x */ KEYS(KeyX), /* y */ KEYS(KeyY), + /* z */ KEYS(KeyZ) + }; + #undef KEYS + #undef SHIFT + #undef X + + return table_lookup_sequence_for_character(key_sequences, character); + } +}; + } diff --git a/Machines/Thomson/MO5/MO5.cpp b/Machines/Thomson/MO5/MO5.cpp index c7f9f6efd..7a75af609 100644 --- a/Machines/Thomson/MO5/MO5.cpp +++ b/Machines/Thomson/MO5/MO5.cpp @@ -22,6 +22,7 @@ #include "Outputs/Speaker/Implementation/BufferSource.hpp" #include "Storage/Tape/Parsers/ThomsonMO.hpp" +#include "Analyser/Static/Thomson/Target.hpp" #include "Keyboard.hpp" @@ -40,9 +41,10 @@ struct ConcreteMachine: public MachineTypes::MediaTarget, public MachineTypes::TimedMachine, public MachineTypes::ScanProducer, - public Machine + public Machine, + public Utility::TypeRecipient { - ConcreteMachine(const Analyser::Static::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) : + ConcreteMachine(const Analyser::Static::Thomson::MOTarget &target, const ROMMachine::ROMFetcher &rom_fetcher) : m6809_(*this), system_pia_port_handler_(*this), system_pia_(system_pia_port_handler_), @@ -67,6 +69,9 @@ struct ConcreteMachine: system_pia_.refresh(); insert_media(target.media); + if(!target.loading_command.empty()) { + type_string(target.loading_command); + } } ~ConcreteMachine() { @@ -103,6 +108,9 @@ struct ConcreteMachine: } time_since_audio_update_ += duration; tape_player_.run_for(duration); + if(typer_) { + typer_->run_for(duration); + } if constexpr (read_write == CPU::M6809::ReadWrite::NoData) { return Cycles(0); @@ -334,7 +342,7 @@ private: // MARK: - MappedKeyboardMachine. - MO5::KeyboardMapper keyboard_mapper_; + Thomson::MO5::KeyboardMapper keyboard_mapper_; KeyboardMapper *get_keyboard_mapper() final { return &keyboard_mapper_; } @@ -347,6 +355,26 @@ private: system_pia_port_handler_.clear_all_keys(); } + void type_string(const std::string &string) final { + Utility::TypeRecipient::add_typer(string); + } + + bool can_type(char c) const final { + return Utility::TypeRecipient::can_type(c); + } + + HalfCycles get_typer_delay(const std::string &) const final { + if(m6809_.get()) { + return Cycles(1'000'000); + } else { + return Cycles(0); + } + } + + HalfCycles get_typer_frequency() const final { + return Cycles(20'000); + } + // MARK: - MediaTarget and MediaChangeObserver. bool insert_media(const Analyser::Static::Media &media) override { @@ -387,5 +415,7 @@ std::unique_ptr Machine::ThomsonMO( const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher ) { - return std::make_unique(*target, rom_fetcher); + using Target = Analyser::Static::Thomson::MOTarget; + const Target *const thomson_target = dynamic_cast(target); + return std::make_unique(*thomson_target, rom_fetcher); }