diff --git a/Machines/Sinclair/ZX8081/Keyboard.cpp b/Machines/Sinclair/Keyboard/Keyboard.cpp similarity index 94% rename from Machines/Sinclair/ZX8081/Keyboard.cpp rename to Machines/Sinclair/Keyboard/Keyboard.cpp index 198210fa3..48bc24fca 100644 --- a/Machines/Sinclair/ZX8081/Keyboard.cpp +++ b/Machines/Sinclair/Keyboard/Keyboard.cpp @@ -10,10 +10,12 @@ #include -using namespace Sinclair::ZX8081; +using namespace Sinclair::ZX::Keyboard; + +KeyboardMapper::KeyboardMapper(Machine machine) : machine_(machine) {} uint16_t KeyboardMapper::mapped_key_for_key(Inputs::Keyboard::Key key) const { -#define BIND(source, dest) case Inputs::Keyboard::Key::source: return ZX8081::dest +#define BIND(source, dest) case Inputs::Keyboard::Key::source: return dest switch(key) { default: break; @@ -44,7 +46,7 @@ uint16_t KeyboardMapper::mapped_key_for_key(Inputs::Keyboard::Key key) const { return MachineTypes::MappedKeyboardMachine::KeyNotMapped; } -CharacterMapper::CharacterMapper(bool is_zx81) : is_zx81_(is_zx81) {} +CharacterMapper::CharacterMapper(Machine machine) : machine_(machine) {} const uint16_t *CharacterMapper::sequence_for_character(char character) const { #define KEYS(...) {__VA_ARGS__, MachineTypes::MappedKeyboardMachine::KeyEndSequence} @@ -185,17 +187,21 @@ const uint16_t *CharacterMapper::sequence_for_character(char character) const { #undef SHIFT #undef X - if(is_zx81_) + switch(machine_) { + case Machine::ZX81: + case Machine::ZXSpectrum: // TODO: some differences exist for the Spectrum. return table_lookup_sequence_for_character(zx81_key_sequences, sizeof(zx81_key_sequences), character); - else + + case Machine::ZX80: return table_lookup_sequence_for_character(zx80_key_sequences, sizeof(zx80_key_sequences), character); + } } bool CharacterMapper::needs_pause_after_key(uint16_t key) const { return key != KeyShift; } -Keyboard::Keyboard(bool is_zx81) : is_zx81_(is_zx81) { +Keyboard::Keyboard(Machine machine) : machine_(machine) { clear_all_keys(); } @@ -217,7 +223,7 @@ void Keyboard::set_key_state(uint16_t key, bool is_pressed) { ShiftedKey(KeyDown, Key6); ShiftedKey(KeyLeft, Key5); ShiftedKey(KeyRight, Key8); - ShiftedKey(KeyEdit, is_zx81_ ? Key1 : KeyEnter); + ShiftedKey(KeyEdit, (machine_ == Machine::ZX80) ? KeyEnter : Key1); #undef ShiftedKey } diff --git a/Machines/Sinclair/ZX8081/Keyboard.hpp b/Machines/Sinclair/Keyboard/Keyboard.hpp similarity index 59% rename from Machines/Sinclair/ZX8081/Keyboard.hpp rename to Machines/Sinclair/Keyboard/Keyboard.hpp index 8f52e701a..1f3ec2bae 100644 --- a/Machines/Sinclair/ZX8081/Keyboard.hpp +++ b/Machines/Sinclair/Keyboard/Keyboard.hpp @@ -13,7 +13,12 @@ #include "../../Utility/Typer.hpp" namespace Sinclair { -namespace ZX8081 { +namespace ZX { +namespace Keyboard { + +enum class Machine { + ZX80, ZX81, ZXSpectrum +}; enum Key: uint16_t { KeyShift = 0x0000 | 0x01, KeyZ = 0x0000 | 0x02, KeyX = 0x0000 | 0x04, KeyC = 0x0000 | 0x08, KeyV = 0x0000 | 0x10, @@ -23,41 +28,53 @@ enum Key: uint16_t { Key0 = 0x0400 | 0x01, Key9 = 0x0400 | 0x02, Key8 = 0x0400 | 0x04, Key7 = 0x0400 | 0x08, Key6 = 0x0400 | 0x10, KeyP = 0x0500 | 0x01, KeyO = 0x0500 | 0x02, KeyI = 0x0500 | 0x04, KeyU = 0x0500 | 0x08, KeyY = 0x0500 | 0x10, KeyEnter = 0x0600 | 0x01, KeyL = 0x0600 | 0x02, KeyK = 0x0600 | 0x04, KeyJ = 0x0600 | 0x08, KeyH = 0x0600 | 0x10, - KeySpace = 0x0700 | 0x01, KeyDot = 0x0700 | 0x02, KeyM = 0x0700 | 0x04, KeyN = 0x0700 | 0x08, KeyB = 0x0700 | 0x10, + KeySpace = 0x0700 | 0x01, KeyM = 0x0700 | 0x04, KeyN = 0x0700 | 0x08, KeyB = 0x0700 | 0x10, - // Add some virtual keys; these do not exist on a real ZX80 or ZX81. They're just a convenience. + // The ZX80 and ZX81 keyboards have a full stop; the ZX Spectrum replaces that key with symbol shift. + KeyDot = 0x0700 | 0x02, KeySymbolShift = KeyDot, + + // Add some virtual keys; these do not exist on a real ZX80, ZX81 or early Spectrum, those all were added to the 128kb Spectrums. + // Either way, they're a convenience. KeyDelete = 0x0801, KeyBreak, KeyLeft, KeyRight, KeyUp, KeyDown, KeyEdit }; -struct Keyboard { - Keyboard(bool is_zx81); +class Keyboard { + public: + Keyboard(Machine machine); - void set_key_state(uint16_t key, bool is_pressed); - void clear_all_keys(); + void set_key_state(uint16_t key, bool is_pressed); + void clear_all_keys(); - uint8_t read(uint16_t address); + uint8_t read(uint16_t address); private: uint8_t key_states_[8]; - const bool is_zx81_; + const Machine machine_; }; -struct KeyboardMapper: public MachineTypes::MappedKeyboardMachine::KeyboardMapper { - uint16_t mapped_key_for_key(Inputs::Keyboard::Key key) const override; +class KeyboardMapper: public MachineTypes::MappedKeyboardMachine::KeyboardMapper { + public: + KeyboardMapper(Machine machine); + + uint16_t mapped_key_for_key(Inputs::Keyboard::Key key) const override; + + private: + const Machine machine_; }; class CharacterMapper: public ::Utility::CharacterMapper { public: - CharacterMapper(bool is_zx81); + CharacterMapper(Machine machine); const uint16_t *sequence_for_character(char character) const override; bool needs_pause_after_key(uint16_t key) const override; private: - bool is_zx81_; + const Machine machine_; }; +} } } diff --git a/Machines/Sinclair/ZX8081/ZX8081.cpp b/Machines/Sinclair/ZX8081/ZX8081.cpp index c1749fdbb..48455a880 100644 --- a/Machines/Sinclair/ZX8081/ZX8081.cpp +++ b/Machines/Sinclair/ZX8081/ZX8081.cpp @@ -24,7 +24,7 @@ #include "../../../Analyser/Static/ZX8081/Target.hpp" -#include "Keyboard.hpp" +#include "../Keyboard/Keyboard.hpp" #include "Video.hpp" #include @@ -49,6 +49,8 @@ enum ROMType: uint8_t { ZX80 = 0, ZX81 }; +using CharacterMapper = Sinclair::ZX::Keyboard::CharacterMapper; + template class ConcreteMachine: public MachineTypes::TimedMachine, public MachineTypes::ScanProducer, @@ -61,9 +63,10 @@ template class ConcreteMachine: public Machine { public: ConcreteMachine(const Analyser::Static::ZX8081::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) : - Utility::TypeRecipient(is_zx81), + Utility::TypeRecipient(keyboard_machine()), z80_(*this), - keyboard_(is_zx81), + keyboard_(keyboard_machine()), + keyboard_mapper_(keyboard_machine()), tape_player_(ZX8081ClockRate), ay_(GI::AY38910::Personality::AY38910, audio_queue_), speaker_(ay_) { @@ -341,6 +344,10 @@ template class ConcreteMachine: keyboard_.clear_all_keys(); } + static constexpr Sinclair::ZX::Keyboard::Machine keyboard_machine() { + return is_zx81 ? Sinclair::ZX::Keyboard::Machine::ZX81 : Sinclair::ZX::Keyboard::Machine::ZX80; + } + // MARK: - Tape control void set_use_automatic_tape_motor_control(bool enabled) { @@ -418,8 +425,8 @@ template class ConcreteMachine: bool vsync_ = false, hsync_ = false; int line_counter_ = 0; - Keyboard keyboard_; - ZX8081::KeyboardMapper keyboard_mapper_; + Sinclair::ZX::Keyboard::Keyboard keyboard_; + Sinclair::ZX::Keyboard::KeyboardMapper keyboard_mapper_; HalfClockReceiver tape_player_; Storage::Tape::ZX8081::Parser parser_; diff --git a/Machines/Sinclair/ZXSpectrum/ZXSpectrum.cpp b/Machines/Sinclair/ZXSpectrum/ZXSpectrum.cpp index 69af74b2f..d1c84ed27 100644 --- a/Machines/Sinclair/ZXSpectrum/ZXSpectrum.cpp +++ b/Machines/Sinclair/ZXSpectrum/ZXSpectrum.cpp @@ -30,8 +30,7 @@ #include "../../../ClockReceiver/JustInTime.hpp" -// TODO: Factor this file into an appropriate place and namespace. -#include "../ZX8081/Keyboard.hpp" +#include "../Keyboard/Keyboard.hpp" #include @@ -52,7 +51,8 @@ template class ConcreteMachine: audio_toggle_(audio_queue_), mixer_(ay_, audio_toggle_), speaker_(mixer_), - keyboard_(true) + keyboard_(Sinclair::ZX::Keyboard::Machine::ZXSpectrum), + keyboard_mapper_(Sinclair::ZX::Keyboard::Machine::ZXSpectrum) { set_clock_rate(clock_rate()); speaker_.set_input_rate(float(clock_rate()) / 2.0f); @@ -355,8 +355,8 @@ template class ConcreteMachine: JustInTimeActor> video_; // MARK: - Keyboard. - Sinclair::ZX8081::Keyboard keyboard_; - ZX8081::KeyboardMapper keyboard_mapper_; + Sinclair::ZX::Keyboard::Keyboard keyboard_; + Sinclair::ZX::Keyboard::KeyboardMapper keyboard_mapper_; }; diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index f02baa208..98375593d 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -128,10 +128,10 @@ 4B0F1BDE2602FF9900B85C66 /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0F1BCD2602F17B00B85C66 /* Video.cpp */; }; 4B0F1BE22602FF9C00B85C66 /* ZX8081.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0F1BCC2602F17B00B85C66 /* ZX8081.cpp */; }; 4B0F1BE62602FF9D00B85C66 /* ZX8081.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0F1BCC2602F17B00B85C66 /* ZX8081.cpp */; }; - 4B0F1BEA2602FFA000B85C66 /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0F1BCF2602F17B00B85C66 /* Keyboard.cpp */; }; - 4B0F1BEB2602FFA100B85C66 /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0F1BCF2602F17B00B85C66 /* Keyboard.cpp */; }; 4B0F1BFC260300D900B85C66 /* ZXSpectrum.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0F1BFA260300D900B85C66 /* ZXSpectrum.cpp */; }; 4B0F1BFD260300D900B85C66 /* ZXSpectrum.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0F1BFA260300D900B85C66 /* ZXSpectrum.cpp */; }; + 4B0F1C1C2604EA1000B85C66 /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0F1C1B2604EA1000B85C66 /* Keyboard.cpp */; }; + 4B0F1C1D2604EA1000B85C66 /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0F1C1B2604EA1000B85C66 /* Keyboard.cpp */; }; 4B0F94FE208C1A1600FE41D9 /* NIB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0F94FC208C1A1600FE41D9 /* NIB.cpp */; }; 4B0F94FF208C1A1600FE41D9 /* NIB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0F94FC208C1A1600FE41D9 /* NIB.cpp */; }; 4B121F9B1E06293F00BFDA12 /* PCMSegmentEventSourceTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B121F9A1E06293F00BFDA12 /* PCMSegmentEventSourceTests.mm */; }; @@ -1061,16 +1061,16 @@ 4B0E61061FF34737002A9DBD /* MSX.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = MSX.hpp; path = Parsers/MSX.hpp; sourceTree = ""; }; 4B0F1BB02602645900B85C66 /* StaticAnalyser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StaticAnalyser.cpp; sourceTree = ""; }; 4B0F1BB12602645900B85C66 /* StaticAnalyser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StaticAnalyser.hpp; sourceTree = ""; }; - 4B0F1BCB2602F17B00B85C66 /* Keyboard.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Keyboard.hpp; sourceTree = ""; }; 4B0F1BCC2602F17B00B85C66 /* ZX8081.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ZX8081.cpp; sourceTree = ""; }; 4B0F1BCD2602F17B00B85C66 /* Video.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Video.cpp; sourceTree = ""; }; 4B0F1BCE2602F17B00B85C66 /* Video.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Video.hpp; sourceTree = ""; }; - 4B0F1BCF2602F17B00B85C66 /* Keyboard.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Keyboard.cpp; sourceTree = ""; }; 4B0F1BD02602F17B00B85C66 /* ZX8081.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ZX8081.hpp; sourceTree = ""; }; 4B0F1BFA260300D900B85C66 /* ZXSpectrum.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ZXSpectrum.cpp; sourceTree = ""; }; 4B0F1BFB260300D900B85C66 /* ZXSpectrum.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ZXSpectrum.hpp; sourceTree = ""; }; 4B0F1C04260391F100B85C66 /* Target.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Target.hpp; sourceTree = ""; }; 4B0F1C092603BA5F00B85C66 /* Video.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Video.hpp; sourceTree = ""; }; + 4B0F1C1A2604EA1000B85C66 /* Keyboard.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Keyboard.hpp; sourceTree = ""; }; + 4B0F1C1B2604EA1000B85C66 /* Keyboard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Keyboard.cpp; sourceTree = ""; }; 4B0F94FC208C1A1600FE41D9 /* NIB.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = NIB.cpp; sourceTree = ""; }; 4B0F94FD208C1A1600FE41D9 /* NIB.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = NIB.hpp; sourceTree = ""; }; 4B0F9500208C42A300FE41D9 /* Target.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = Target.hpp; path = AppleII/Target.hpp; sourceTree = ""; }; @@ -2177,6 +2177,7 @@ 4B0F1BC92602F17B00B85C66 /* Sinclair */ = { isa = PBXGroup; children = ( + 4B0F1C192604EA1000B85C66 /* Keyboard */, 4B0F1BCA2602F17B00B85C66 /* ZX8081 */, 4B0F1BF9260300D900B85C66 /* ZXSpectrum */, ); @@ -2186,11 +2187,9 @@ 4B0F1BCA2602F17B00B85C66 /* ZX8081 */ = { isa = PBXGroup; children = ( - 4B0F1BCB2602F17B00B85C66 /* Keyboard.hpp */, 4B0F1BCC2602F17B00B85C66 /* ZX8081.cpp */, 4B0F1BCD2602F17B00B85C66 /* Video.cpp */, 4B0F1BCE2602F17B00B85C66 /* Video.hpp */, - 4B0F1BCF2602F17B00B85C66 /* Keyboard.cpp */, 4B0F1BD02602F17B00B85C66 /* ZX8081.hpp */, ); path = ZX8081; @@ -2206,6 +2205,15 @@ path = ZXSpectrum; sourceTree = ""; }; + 4B0F1C192604EA1000B85C66 /* Keyboard */ = { + isa = PBXGroup; + children = ( + 4B0F1C1A2604EA1000B85C66 /* Keyboard.hpp */, + 4B0F1C1B2604EA1000B85C66 /* Keyboard.cpp */, + ); + path = Keyboard; + sourceTree = ""; + }; 4B1414561B58879D00E04248 /* 6502 */ = { isa = PBXGroup; children = ( @@ -5094,7 +5102,6 @@ 4B65086122F4CFE0009C1100 /* Keyboard.cpp in Sources */, 4BBB70A9202014E2002FE009 /* MultiProducer.cpp in Sources */, 4B2E86BF25D74F160024F1E9 /* Mouse.cpp in Sources */, - 4B0F1BEB2602FFA100B85C66 /* Keyboard.cpp in Sources */, 4B6ED2F1208E2F8A0047B343 /* WOZ.cpp in Sources */, 4B5D5C9825F56FC7001B4623 /* Spectrum.cpp in Sources */, 4B2E86D025D8D8C70024F1E9 /* Keyboard.cpp in Sources */, @@ -5141,6 +5148,7 @@ 4B055A9E1FAE85DA0060FFFF /* G64.cpp in Sources */, 4B055AB81FAE860F0060FFFF /* ZX80O81P.cpp in Sources */, 4B055AB01FAE86070060FFFF /* PulseQueuedTape.cpp in Sources */, + 4B0F1C1D2604EA1000B85C66 /* Keyboard.cpp in Sources */, 4B055AAC1FAE85FD0060FFFF /* PCMSegment.cpp in Sources */, 4BB307BC235001C300457D33 /* 6850.cpp in Sources */, 4B055AB31FAE860F0060FFFF /* CSW.cpp in Sources */, @@ -5291,6 +5299,7 @@ 4B0E04EA1FC9E5DA00F43484 /* CAS.cpp in Sources */, 4B7A90ED20410A85008514A2 /* StaticAnalyser.cpp in Sources */, 4B58601E1F806AB200AEE2E3 /* MFMSectorDump.cpp in Sources */, + 4B0F1C1C2604EA1000B85C66 /* Keyboard.cpp in Sources */, 4B228CD924DA12C60077EF25 /* CSScanTargetView.m in Sources */, 4B6AAEAD230E40250078E864 /* Target.cpp in Sources */, 4B448E841F1C4C480009ABD6 /* PulseQueuedTape.cpp in Sources */, @@ -5436,7 +5445,6 @@ 4B0ACC02237756ED008902D0 /* Line.cpp in Sources */, 4B89453A201967B4007DE474 /* StaticAnalyser.cpp in Sources */, 4BB697CB1D4B6D3E00248BDF /* TimedEventLoop.cpp in Sources */, - 4B0F1BEA2602FFA000B85C66 /* Keyboard.cpp in Sources */, 4BDACBEC22FFA5D20045EF7E /* ncr5380.cpp in Sources */, 4B54C0C21F8D91CD0050900F /* Keyboard.cpp in Sources */, 4BD0FBC3233706A200148981 /* CSApplication.m in Sources */,