diff --git a/Machines/Apple/AppleII/AppleII.cpp b/Machines/Apple/AppleII/AppleII.cpp index 3a2f99b05..06044b807 100644 --- a/Machines/Apple/AppleII/AppleII.cpp +++ b/Machines/Apple/AppleII/AppleII.cpp @@ -48,7 +48,6 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine: public MachineTypes::MappedKeyboardMachine, public MachineTypes::JoystickMachine, public CPU::MOS6502::BusHandler, - public Inputs::Keyboard, public Configurable::Device, public Activity::Source, public Apple::II::Card::Delegate { @@ -66,7 +65,11 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine: uint8_t *ram_, *aux_ram_; }; - CPU::MOS6502::Processor<(model == Analyser::Static::AppleII::Target::Model::EnhancedIIe) ? CPU::MOS6502::Personality::PSynertek65C02 : CPU::MOS6502::Personality::P6502, ConcreteMachine, false> m6502_; + using Processor = CPU::MOS6502::Processor< + (model == Analyser::Static::AppleII::Target::Model::EnhancedIIe) ? CPU::MOS6502::Personality::PSynertek65C02 : CPU::MOS6502::Personality::P6502, + ConcreteMachine, + false>; + Processor m6502_; VideoBusHandler video_bus_handler_; Apple::II::Video::Video<VideoBusHandler, is_iie()> video_; int cycles_into_current_line_ = 0; @@ -91,16 +94,6 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine: uint8_t ram_[65536], aux_ram_[65536]; std::vector<uint8_t> rom_; - uint8_t keyboard_input_ = 0x00; - bool key_is_down_ = false; - - uint8_t get_keyboard_input() { - if(string_serialiser_) { - return string_serialiser_->head() | 0x80; - } else { - return keyboard_input_; - } - } Concurrency::DeferringAsyncTaskQueue audio_queue_; Audio::Toggle audio_toggle_; @@ -258,16 +251,99 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine: state.region_20_40.write ? &aux_ram_[0x2000] : &ram_[0x2000]); } - // MARK - typing - std::unique_ptr<Utility::StringSerialiser> string_serialiser_; + // MARK: - Keyboard and typing. - // MARK - Joysticks. + struct Keyboard: public Inputs::Keyboard { + Keyboard(Processor *m6502) : m6502_(m6502) {} + + void reset_all_keys() final { + open_apple_is_pressed = closed_apple_is_pressed = key_is_down = false; + } + + bool set_key_pressed(Key key, char value, bool is_pressed) final { + // If no ASCII value is supplied, look for a few special cases. + switch(key) { + case Key::Left: value = 0x08; break; + case Key::Right: value = 0x15; break; + case Key::Down: value = 0x0a; break; + case Key::Up: value = 0x0b; break; + case Key::Backspace: value = 0x7f; break; + case Key::Enter: value = 0x0d; break; + case Key::Tab: value = '\t'; break; + case Key::Escape: value = 0x1b; break; + + case Key::LeftOption: + case Key::RightMeta: + open_apple_is_pressed = is_pressed; + return true; + + case Key::RightOption: + case Key::LeftMeta: + closed_apple_is_pressed = is_pressed; + return true; + + case Key::F1: case Key::F2: case Key::F3: case Key::F4: + case Key::F5: case Key::F6: case Key::F7: case Key::F8: + case Key::F9: case Key::F10: case Key::F11: case Key::F12: + case Key::PrintScreen: + case Key::ScrollLock: + case Key::Pause: + case Key::Insert: + case Key::Home: + case Key::PageUp: + case Key::PageDown: + case Key::End: + // Accept a bunch non-symbolic other keys, as + // reset, in the hope that the user can find + // at least one usable key. + m6502_->set_reset_line(is_pressed); + return true; + + default: + if(!value) { + return false; + } + + // Prior to the IIe, the keyboard could produce uppercase only. + if(!is_iie()) value = char(toupper(value)); + break; + } + + if(is_pressed) { + keyboard_input = uint8_t(value | 0x80); + key_is_down = true; + } else { + if((keyboard_input & 0x7f) == value) { + key_is_down = false; + } + } + + return true; + } + + uint8_t get_keyboard_input() { + if(string_serialiser) { + return string_serialiser->head() | 0x80; + } else { + return keyboard_input; + } + } + + // The IIe has three keys that are wired directly to the same input as the joystick buttons. + bool open_apple_is_pressed = false; + bool closed_apple_is_pressed = false; + uint8_t keyboard_input = 0x00; + bool key_is_down = false; + std::unique_ptr<Utility::StringSerialiser> string_serialiser; + + private: + Processor *const m6502_; + }; + Keyboard keyboard_; + + // MARK: - Joysticks. JoystickPair joysticks_; - // The IIe has three keys that are wired directly to the same input as the joystick buttons. - bool open_apple_is_pressed_ = false; - bool closed_apple_is_pressed_ = false; - public: ConcreteMachine(const Analyser::Static::AppleII::Target &target, const ROMMachine::ROMFetcher &rom_fetcher): m6502_(*this), @@ -276,7 +352,8 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine: audio_toggle_(audio_queue_), speaker_(audio_toggle_), language_card_(*this), - auxiliary_switches_(*this) { + auxiliary_switches_(*this), + keyboard_(&m6502_) { // The system's master clock rate. constexpr float master_clock = 14318180.0; @@ -435,18 +512,18 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine: default: break; case 0xc000: - *value = get_keyboard_input(); + *value = keyboard_.get_keyboard_input(); break; case 0xc001: case 0xc002: case 0xc003: case 0xc004: case 0xc005: case 0xc006: case 0xc007: case 0xc008: case 0xc009: case 0xc00a: case 0xc00b: case 0xc00c: case 0xc00d: case 0xc00e: case 0xc00f: - *value = (*value & 0x80) | (get_keyboard_input() & 0x7f); + *value = (*value & 0x80) | (keyboard_.get_keyboard_input() & 0x7f); break; case 0xc061: // Switch input 0. *value &= 0x7f; if( joysticks_.button(0) || - (is_iie() && open_apple_is_pressed_) + (is_iie() && keyboard_.open_apple_is_pressed) ) *value |= 0x80; break; @@ -454,7 +531,7 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine: *value &= 0x7f; if( joysticks_.button(1) || - (is_iie() && closed_apple_is_pressed_) + (is_iie() && keyboard_.closed_apple_is_pressed) ) *value |= 0x80; break; @@ -476,7 +553,7 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine: } break; // The IIe-only state reads follow... -#define IIeSwitchRead(s) *value = get_keyboard_input(); if(is_iie()) *value = (*value & 0x7f) | (s ? 0x80 : 0x00); +#define IIeSwitchRead(s) *value = keyboard_.get_keyboard_input(); if(is_iie()) *value = (*value & 0x7f) | (s ? 0x80 : 0x00); case 0xc011: IIeSwitchRead(language_card_.state().bank2); break; case 0xc012: IIeSwitchRead(language_card_.state().read); break; case 0xc013: IIeSwitchRead(auxiliary_switches_.switches().read_auxiliary_memory); break; @@ -559,15 +636,15 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine: break; case 0xc010: - keyboard_input_ &= 0x7f; - if(string_serialiser_) { - if(!string_serialiser_->advance()) - string_serialiser_.reset(); + keyboard_.keyboard_input &= 0x7f; + if(keyboard_.string_serialiser) { + if(!keyboard_.string_serialiser->advance()) + keyboard_.string_serialiser.reset(); } // On the IIe, reading C010 returns additional key info. if(is_iie() && isReadOperation(operation)) { - *value = (key_is_down_ ? 0x80 : 0x00) | (keyboard_input_ & 0x7f); + *value = (keyboard_.key_is_down ? 0x80 : 0x00) | (keyboard_.keyboard_input & 0x7f); } break; @@ -683,81 +760,16 @@ template <Analyser::Static::AppleII::Target::Model model> class ConcreteMachine: m6502_.run_for(cycles); } - void reset_all_keys() final { - open_apple_is_pressed_ = closed_apple_is_pressed_ = key_is_down_ = false; - } - bool prefers_logical_input() final { return true; } - bool set_key_pressed(Key key, char value, bool is_pressed) final { - // If no ASCII value is supplied, look for a few special cases. - switch(key) { - case Key::Left: value = 0x08; break; - case Key::Right: value = 0x15; break; - case Key::Down: value = 0x0a; break; - case Key::Up: value = 0x0b; break; - case Key::Backspace: value = 0x7f; break; - case Key::Enter: value = 0x0d; break; - case Key::Tab: value = '\t'; break; - case Key::Escape: value = 0x1b; break; - - case Key::LeftOption: - case Key::RightMeta: - open_apple_is_pressed_ = is_pressed; - return true; - - case Key::RightOption: - case Key::LeftMeta: - closed_apple_is_pressed_ = is_pressed; - return true; - - case Key::F1: case Key::F2: case Key::F3: case Key::F4: - case Key::F5: case Key::F6: case Key::F7: case Key::F8: - case Key::F9: case Key::F10: case Key::F11: case Key::F12: - case Key::PrintScreen: - case Key::ScrollLock: - case Key::Pause: - case Key::Insert: - case Key::Home: - case Key::PageUp: - case Key::PageDown: - case Key::End: - // Accept a bunch non-symbolic other keys, as - // reset, in the hope that the user can find - // at least one usable key. - m6502_.set_reset_line(is_pressed); - return true; - - default: - if(!value) { - return false; - } - - // Prior to the IIe, the keyboard could produce uppercase only. - if(!is_iie()) value = char(toupper(value)); - break; - } - - if(is_pressed) { - keyboard_input_ = uint8_t(value | 0x80); - key_is_down_ = true; - } else { - if((keyboard_input_ & 0x7f) == value) { - key_is_down_ = false; - } - } - - return true; - } - Inputs::Keyboard &get_keyboard() final { - return *this; + return keyboard_; } void type_string(const std::string &string) final { - string_serialiser_ = std::make_unique<Utility::StringSerialiser>(string, true); + keyboard_.string_serialiser = std::make_unique<Utility::StringSerialiser>(string, true); } bool can_type(char c) const final { diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 7f256a459..01eddfd55 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -4656,7 +4656,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 1200; + LastUpgradeCheck = 1240; ORGANIZATIONNAME = "Thomas Harte"; TargetAttributes = { 4B055A691FAE763F0060FFFF = { @@ -5980,6 +5980,7 @@ CLANG_WARN_SEMICOLON_BEFORE_METHOD_BODY = YES; CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; CODE_SIGN_ENTITLEMENTS = "Clock Signal/Clock Signal.entitlements"; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = DV3346VVUN; ENABLE_HARDENED_RUNTIME = YES; @@ -6026,6 +6027,7 @@ CLANG_WARN_SEMICOLON_BEFORE_METHOD_BODY = YES; CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; CODE_SIGN_ENTITLEMENTS = "Clock Signal/Clock Signal.entitlements"; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = DV3346VVUN; ENABLE_HARDENED_RUNTIME = YES; diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal Kiosk.xcscheme b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal Kiosk.xcscheme index 6560dd001..0d593f776 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal Kiosk.xcscheme +++ b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal Kiosk.xcscheme @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme - LastUpgradeVersion = "1200" + LastUpgradeVersion = "1240" version = "1.3"> <BuildAction parallelizeBuildables = "YES" diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme index 01069c685..54b355ae8 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme +++ b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme - LastUpgradeVersion = "1200" + LastUpgradeVersion = "1240" version = "1.3"> <BuildAction parallelizeBuildables = "YES" diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock SignalTests.xcscheme b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock SignalTests.xcscheme index 446760744..cd858da79 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock SignalTests.xcscheme +++ b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock SignalTests.xcscheme @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme - LastUpgradeVersion = "1200" + LastUpgradeVersion = "1240" version = "1.3"> <BuildAction parallelizeBuildables = "YES"