diff --git a/ClockReceiver/ForceInline.hpp b/ClockReceiver/ForceInline.hpp index 2b6cf5589..df486d14c 100644 --- a/ClockReceiver/ForceInline.hpp +++ b/ClockReceiver/ForceInline.hpp @@ -9,10 +9,18 @@ #ifndef ForceInline_hpp #define ForceInline_hpp +#ifdef DEBUG + +#define forceinline + +#else + #ifdef __GNUC__ #define forceinline __attribute__((always_inline)) inline #elif _MSC_VER #define forceinline __forceinline #endif +#endif + #endif /* ForceInline_h */ diff --git a/Machines/AmstradCPC/AmstradCPC.cpp b/Machines/AmstradCPC/AmstradCPC.cpp index a704ee549..40b4515ed 100644 --- a/Machines/AmstradCPC/AmstradCPC.cpp +++ b/Machines/AmstradCPC/AmstradCPC.cpp @@ -22,6 +22,8 @@ #include "../../Storage/Tape/Tape.hpp" +#include "../../ClockReceiver/ForceInline.hpp" + namespace AmstradCPC { /*! @@ -173,7 +175,7 @@ class CRTCBusHandler { The CRTC entry function; takes the current bus state and determines what output to produce based on the current palette and mode. */ - inline void perform_bus_cycle(const Motorola::CRTC::BusState &state) { + forceinline void perform_bus_cycle(const Motorola::CRTC::BusState &state) { // The gate array waits 2µs to react to the CRTC's vsync signal, and then // caps output at 4µs. Since the clock rate is 1Mhz, that's 2 and 4 cycles, // respectively. @@ -691,7 +693,7 @@ class ConcreteMachine: } /// The entry point for performing a partial Z80 machine cycle. - inline HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) { + forceinline HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) { // Amstrad CPC timing scheme: assert WAIT for three out of four cycles clock_offset_ = (clock_offset_ + cycle.length) & HalfCycles(7); z80_.set_wait_line(clock_offset_ >= HalfCycles(2)); @@ -825,35 +827,35 @@ class ConcreteMachine: } /// A CRTMachine function; indicates that outputs should be created now. - void setup_output(float aspect_ratio) { + void setup_output(float aspect_ratio) override final { crtc_bus_handler_.setup_output(aspect_ratio); ay_.setup_output(); ay_.ay()->set_port_handler(&key_state_); } /// A CRTMachine function; indicates that outputs should be destroyed now. - void close_output() { + void close_output() override final { crtc_bus_handler_.close_output(); ay_.close_output(); } /// @returns the CRT in use. - std::shared_ptr get_crt() { + std::shared_ptr get_crt() override final { return crtc_bus_handler_.get_crt(); } /// @returns the speaker in use. - std::shared_ptr get_speaker() { + std::shared_ptr get_speaker() override final { return ay_.get_speaker(); } /// Wires virtual-dispatched CRTMachine run_for requests to the static Z80 method. - void run_for(const Cycles cycles) { + void run_for(const Cycles cycles) override final { z80_.run_for(cycles); } /// The ConfigurationTarget entry point; should configure this meachine as described by @c target. - void configure_as_target(const StaticAnalyser::Target &target) { + void configure_as_target(const StaticAnalyser::Target &target) override final { switch(target.amstradcpc.model) { case StaticAnalyser::AmstradCPCModel::CPC464: rom_model_ = ROMType::OS464; @@ -894,7 +896,7 @@ class ConcreteMachine: insert_media(target.media); } - bool insert_media(const StaticAnalyser::Media &media) { + bool insert_media(const StaticAnalyser::Media &media) override final { // If there are any tapes supplied, use the first of them. if(!media.tapes.empty()) { tape_player_.set_tape(media.tapes.front()); @@ -912,37 +914,37 @@ class ConcreteMachine: } // See header; provides the system ROMs. - void set_rom(ROMType type, std::vector data) { + void set_rom(ROMType type, std::vector data) override final { roms_[(int)type] = data; } - void set_component_is_sleeping(void *component, bool is_sleeping) { + void set_component_is_sleeping(void *component, bool is_sleeping) override final { fdc_is_sleeping_ = fdc_.is_sleeping(); tape_player_is_sleeping_ = tape_player_.is_sleeping(); } #pragma mark - Keyboard - void set_typer_for_string(const char *string) { + void set_typer_for_string(const char *string) override final { std::unique_ptr mapper(new CharacterMapper()); Utility::TypeRecipient::set_typer_for_string(string, std::move(mapper)); } - HalfCycles get_typer_delay() { + HalfCycles get_typer_delay() override final { return Cycles(4000000); // Wait 1 second before typing. } - HalfCycles get_typer_frequency() { + HalfCycles get_typer_frequency() override final { return Cycles(160000); // Type one character per frame. } // See header; sets a key as either pressed or released. - void set_key_state(uint16_t key, bool isPressed) { + void set_key_state(uint16_t key, bool isPressed) override final { key_state_.set_is_pressed(isPressed, key >> 4, key & 7); } // See header; sets all keys to released. - void clear_all_keys() { + void clear_all_keys() override final { key_state_.clear_all_keys(); } @@ -992,7 +994,7 @@ class ConcreteMachine: } } - CPU::Z80::Processor z80_; + CPU::Z80::Processor z80_; CRTCBusHandler crtc_bus_handler_; Motorola::CRTC::CRTC6845 crtc_; diff --git a/Machines/Atari2600/Cartridges/Cartridge.hpp b/Machines/Atari2600/Cartridges/Cartridge.hpp index 20f52c9a9..2580244e5 100644 --- a/Machines/Atari2600/Cartridges/Cartridge.hpp +++ b/Machines/Atari2600/Cartridges/Cartridge.hpp @@ -184,7 +184,7 @@ template class Cartridge: } protected: - CPU::MOS6502::Processor> m6502_; + CPU::MOS6502::Processor, true> m6502_; std::vector rom_; private: diff --git a/Machines/Commodore/1540/C1540.hpp b/Machines/Commodore/1540/C1540.hpp index 59b1ba745..f1fe08a68 100644 --- a/Machines/Commodore/1540/C1540.hpp +++ b/Machines/Commodore/1540/C1540.hpp @@ -152,7 +152,7 @@ class Machine: void drive_via_did_set_data_density(void *driveVIA, int density); private: - CPU::MOS6502::Processor m6502_; + CPU::MOS6502::Processor m6502_; uint8_t ram_[0x800]; uint8_t rom_[0x4000]; diff --git a/Machines/Commodore/Vic-20/Vic20.cpp b/Machines/Commodore/Vic-20/Vic20.cpp index 7095f4138..8bb641c0a 100644 --- a/Machines/Commodore/Vic-20/Vic20.cpp +++ b/Machines/Commodore/Vic-20/Vic20.cpp @@ -14,6 +14,8 @@ #include "../../../Components/6560/6560.hpp" #include "../../../Components/6522/6522.hpp" +#include "../../../ClockReceiver/ForceInline.hpp" + #include "../../../Storage/Tape/Parsers/Commodore.hpp" #include "../SerialBus.hpp" @@ -253,7 +255,7 @@ class ConcreteMachine: delete[] rom_; } - void set_rom(ROMSlot slot, size_t length, const uint8_t *data) { + void set_rom(ROMSlot slot, size_t length, const uint8_t *data) override final { uint8_t *target = nullptr; size_t max_length = 0x2000; switch(slot) { @@ -273,7 +275,7 @@ class ConcreteMachine: } } - void configure_as_target(const StaticAnalyser::Target &target) { + void configure_as_target(const StaticAnalyser::Target &target) override final { if(target.loadingCommand.length()) { set_typer_for_string(target.loadingCommand.c_str()); } @@ -304,7 +306,7 @@ class ConcreteMachine: insert_media(target.media); } - bool insert_media(const StaticAnalyser::Media &media) { + bool insert_media(const StaticAnalyser::Media &media) override final { if(!media.tapes.empty()) { tape_->set_tape(media.tapes.front()); } @@ -326,20 +328,20 @@ class ConcreteMachine: return !media.tapes.empty() || (!media.disks.empty() && c1540_ != nullptr) || !media.cartridges.empty(); } - void set_key_state(uint16_t key, bool isPressed) { + void set_key_state(uint16_t key, bool isPressed) override final { keyboard_via_->set_key_state(key, isPressed); } - void clear_all_keys() { + void clear_all_keys() override final { keyboard_via_->clear_all_keys(); } - void set_joystick_state(JoystickInput input, bool isPressed) { + void set_joystick_state(JoystickInput input, bool isPressed) override final { user_port_via_->set_joystick_state(input, isPressed); keyboard_via_->set_joystick_state(input, isPressed); } - void set_memory_size(MemorySize size) { + void set_memory_size(MemorySize size) override final { memset(processor_read_memory_map_, 0, sizeof(processor_read_memory_map_)); memset(processor_write_memory_map_, 0, sizeof(processor_write_memory_map_)); @@ -373,7 +375,7 @@ class ConcreteMachine: } } - void set_region(Region region) { + void set_region(Region region) override final { region_ = region; switch(region) { case PAL: @@ -393,12 +395,12 @@ class ConcreteMachine: } } - void set_use_fast_tape_hack(bool activate) { + void set_use_fast_tape_hack(bool activate) override final { use_fast_tape_hack_ = activate; } // to satisfy CPU::MOS6502::Processor - Cycles perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) { + forceinline Cycles perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) { // run the phase-1 part of this cycle, in which the VIC accesses memory if(!is_running_at_zero_cost_) mos6560_->run_for(Cycles(1)); @@ -494,15 +496,15 @@ class ConcreteMachine: return Cycles(1); } - void flush() { + forceinline void flush() { mos6560_->flush(); } - void run_for(const Cycles cycles) { + void run_for(const Cycles cycles) override final { m6502_.run_for(cycles); } - void setup_output(float aspect_ratio) { + void setup_output(float aspect_ratio) override final { mos6560_.reset(new Vic6560()); mos6560_->get_speaker()->set_high_frequency_cut_off(1600); // There is a 1.6Khz low-pass filter in the Vic-20. set_region(region_); @@ -514,34 +516,34 @@ class ConcreteMachine: mos6560_->colour_memory = colour_memory_; } - void close_output() { + void close_output() override final { mos6560_ = nullptr; } - std::shared_ptr get_crt() { + std::shared_ptr get_crt() override final { return mos6560_->get_crt(); } - std::shared_ptr get_speaker() { + std::shared_ptr get_speaker() override final { return mos6560_->get_speaker(); } - void mos6522_did_change_interrupt_status(void *mos6522) { + void mos6522_did_change_interrupt_status(void *mos6522) override final { m6502_.set_nmi_line(user_port_via_->get_interrupt_line()); m6502_.set_irq_line(keyboard_via_->get_interrupt_line()); } - void set_typer_for_string(const char *string) { + void set_typer_for_string(const char *string) override final { std::unique_ptr mapper(new CharacterMapper()); Utility::TypeRecipient::set_typer_for_string(string, std::move(mapper)); } - void tape_did_change_input(Storage::Tape::BinaryTapePlayer *tape) { + void tape_did_change_input(Storage::Tape::BinaryTapePlayer *tape) override final { keyboard_via_->set_control_line_input(KeyboardVIA::Port::A, KeyboardVIA::Line::One, !tape->get_input()); } private: - CPU::MOS6502::Processor m6502_; + CPU::MOS6502::Processor m6502_; uint8_t character_rom_[0x1000]; uint8_t basic_rom_[0x2000]; diff --git a/Machines/Electron/Electron.cpp b/Machines/Electron/Electron.cpp index c4072061a..9fef59337 100644 --- a/Machines/Electron/Electron.cpp +++ b/Machines/Electron/Electron.cpp @@ -11,6 +11,7 @@ #include "../../Processors/6502/6502.hpp" #include "../../Storage/Tape/Tape.hpp" #include "../../ClockReceiver/ClockReceiver.hpp" +#include "../../ClockReceiver/ForceInline.hpp" #include "../Typer.hpp" @@ -44,7 +45,7 @@ class ConcreteMachine: set_clock_rate(2000000); } - void set_rom(ROMSlot slot, std::vector data, bool is_writeable) { + void set_rom(ROMSlot slot, std::vector data, bool is_writeable) override final { uint8_t *target = nullptr; switch(slot) { case ROMSlotDFS: dfs_ = data; return; @@ -60,7 +61,7 @@ class ConcreteMachine: memcpy(target, &data[0], std::min((size_t)16384, data.size())); } - void set_key_state(uint16_t key, bool isPressed) { + void set_key_state(uint16_t key, bool isPressed) override final { if(key == KeyBreak) { m6502_.set_reset_line(isPressed); } else { @@ -71,16 +72,16 @@ class ConcreteMachine: } } - void clear_all_keys() { + void clear_all_keys() override final { memset(key_states_, 0, sizeof(key_states_)); if(is_holding_shift_) set_key_state(KeyShift, true); } - void set_use_fast_tape_hack(bool activate) { + void set_use_fast_tape_hack(bool activate) override final { use_fast_tape_hack_ = activate; } - void configure_as_target(const StaticAnalyser::Target &target) { + void configure_as_target(const StaticAnalyser::Target &target) override final { if(target.loadingCommand.length()) { set_typer_for_string(target.loadingCommand.c_str()); } @@ -104,7 +105,7 @@ class ConcreteMachine: insert_media(target.media); } - bool insert_media(const StaticAnalyser::Media &media) { + bool insert_media(const StaticAnalyser::Media &media) override final { if(!media.tapes.empty()) { tape_.set_tape(media.tapes.front()); } @@ -122,7 +123,7 @@ class ConcreteMachine: return !media.tapes.empty() || !media.disks.empty() || !media.cartridges.empty(); } - Cycles perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) { + forceinline Cycles perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) { unsigned int cycles = 1; if(address < 0x8000) { @@ -342,13 +343,13 @@ class ConcreteMachine: return Cycles((int)cycles); } - void flush() { + forceinline void flush() { update_display(); update_audio(); speaker_->flush(); } - void setup_output(float aspect_ratio) { + void setup_output(float aspect_ratio) override final { video_output_.reset(new VideoOutput(ram_)); // The maximum output frequency is 62500Hz and all other permitted output frequencies are integral divisions of that; @@ -358,36 +359,36 @@ class ConcreteMachine: speaker_->set_input_rate(2000000 / Speaker::clock_rate_divider); } - void close_output() { + void close_output() override final { video_output_.reset(); } - std::shared_ptr get_crt() { + std::shared_ptr get_crt() override final { return video_output_->get_crt(); } - std::shared_ptr get_speaker() { + std::shared_ptr get_speaker() override final { return speaker_; } - virtual void run_for(const Cycles cycles) { + void run_for(const Cycles cycles) override final { m6502_.run_for(cycles); } - void tape_did_change_interrupt_status(Tape *tape) { + void tape_did_change_interrupt_status(Tape *tape) override final { interrupt_status_ = (interrupt_status_ & ~(Interrupt::TransmitDataEmpty | Interrupt::ReceiveDataFull | Interrupt::HighToneDetect)) | tape_.get_interrupt_status(); evaluate_interrupts(); } - HalfCycles get_typer_delay() { + HalfCycles get_typer_delay() override final { return m6502_.get_is_resetting() ? Cycles(625*25*128) : Cycles(0); // wait one second if resetting } - HalfCycles get_typer_frequency() { + HalfCycles get_typer_frequency() override final { return Cycles(625*128*2); // accept a new character every two frames } - void set_typer_for_string(const char *string) { + void set_typer_for_string(const char *string) override final { std::unique_ptr mapper(new CharacterMapper()); Utility::TypeRecipient::set_typer_for_string(string, std::move(mapper)); } @@ -430,7 +431,7 @@ class ConcreteMachine: m6502_.set_irq_line(interrupt_status_ & 1); } - CPU::MOS6502::Processor m6502_; + CPU::MOS6502::Processor m6502_; // Things that directly constitute the memory map. uint8_t roms_[16][16384]; diff --git a/Machines/Oric/Oric.cpp b/Machines/Oric/Oric.cpp index 0df5d8be0..ce1978954 100644 --- a/Machines/Oric/Oric.cpp +++ b/Machines/Oric/Oric.cpp @@ -22,6 +22,8 @@ #include "../../Storage/Tape/Tape.hpp" #include "../../Storage/Tape/Parsers/Oric.hpp" +#include "../../ClockReceiver/ForceInline.hpp" + #include #include #include @@ -54,7 +56,7 @@ class ConcreteMachine: Memory::Fuzz(ram_, sizeof(ram_)); } - void set_rom(ROM rom, const std::vector &data) { + void set_rom(ROM rom, const std::vector &data) override final { switch(rom) { case BASIC11: basic11_rom_ = std::move(data); break; case BASIC10: basic10_rom_ = std::move(data); break; @@ -66,7 +68,7 @@ class ConcreteMachine: } } - void set_key_state(uint16_t key, bool isPressed) { + void set_key_state(uint16_t key, bool isPressed) override final { if(key == KeyNMI) { m6502_.set_nmi_line(isPressed); } else { @@ -77,20 +79,20 @@ class ConcreteMachine: } } - void clear_all_keys() { + void clear_all_keys() override final { memset(keyboard_->rows, 0, sizeof(keyboard_->rows)); } - void set_use_fast_tape_hack(bool activate) { + void set_use_fast_tape_hack(bool activate) override final { use_fast_tape_hack_ = activate; } - void set_output_device(Outputs::CRT::OutputDevice output_device) { + void set_output_device(Outputs::CRT::OutputDevice output_device) override final { video_output_->set_output_device(output_device); } // to satisfy ConfigurationTarget::Machine - void configure_as_target(const StaticAnalyser::Target &target) { + void configure_as_target(const StaticAnalyser::Target &target) override final { if(target.oric.has_microdisc) { microdisc_is_enabled_ = true; microdisc_did_change_paging_flags(µdisc_); @@ -120,7 +122,7 @@ class ConcreteMachine: insert_media(target.media); } - bool insert_media(const StaticAnalyser::Media &media) { + bool insert_media(const StaticAnalyser::Media &media) override final { if(media.tapes.size()) { via_.tape->set_tape(media.tapes.front()); } @@ -135,7 +137,7 @@ class ConcreteMachine: } // to satisfy CPU::MOS6502::BusHandler - Cycles perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) { + forceinline Cycles perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) { if(address > ram_top_) { if(isReadOperation(operation)) *value = paged_rom_[address - ram_top_ - 1]; @@ -193,55 +195,55 @@ class ConcreteMachine: return Cycles(1); } - void flush() { + forceinline void flush() { update_video(); via_.flush(); } // to satisfy CRTMachine::Machine - void setup_output(float aspect_ratio) { + void setup_output(float aspect_ratio) override final { via_.ay8910.reset(new GI::AY38910::AY38910()); via_.ay8910->set_clock_rate(1000000); video_output_.reset(new VideoOutput(ram_)); if(!colour_rom_.empty()) video_output_->set_colour_rom(colour_rom_); } - void close_output() { + void close_output() override final { video_output_.reset(); via_.ay8910.reset(); } - std::shared_ptr get_crt() { + std::shared_ptr get_crt() override final { return video_output_->get_crt(); } - std::shared_ptr get_speaker() { + std::shared_ptr get_speaker() override final { return via_.ay8910; } - void run_for(const Cycles cycles) { + void run_for(const Cycles cycles) override final { m6502_.run_for(cycles); } // to satisfy MOS::MOS6522IRQDelegate::Delegate - void mos6522_did_change_interrupt_status(void *mos6522) { + void mos6522_did_change_interrupt_status(void *mos6522) override final { set_interrupt_line(); } // to satisfy Storage::Tape::BinaryTapePlayer::Delegate - void tape_did_change_input(Storage::Tape::BinaryTapePlayer *tape_player) { + void tape_did_change_input(Storage::Tape::BinaryTapePlayer *tape_player) override final { // set CB1 via_.set_control_line_input(VIA::Port::B, VIA::Line::One, !tape_player->get_input()); } // for Utility::TypeRecipient::Delegate - void set_typer_for_string(const char *string) { + void set_typer_for_string(const char *string) override final { std::unique_ptr mapper(new CharacterMapper); Utility::TypeRecipient::set_typer_for_string(string, std::move(mapper)); } // for Microdisc::Delegate - void microdisc_did_change_paging_flags(class Microdisc *microdisc) { + void microdisc_did_change_paging_flags(class Microdisc *microdisc) override final { int flags = microdisc->get_paging_flags(); if(!(flags&Microdisc::PagingFlags::BASICDisable)) { ram_top_ = 0xbfff; @@ -256,12 +258,12 @@ class ConcreteMachine: } } - void wd1770_did_change_output(WD::WD1770 *wd1770) { + void wd1770_did_change_output(WD::WD1770 *wd1770) override final { set_interrupt_line(); } private: - CPU::MOS6502::Processor m6502_; + CPU::MOS6502::Processor m6502_; // RAM and ROM std::vector basic11_rom_, basic10_rom_, microdisc_rom_, colour_rom_; @@ -292,7 +294,7 @@ class ConcreteMachine: public: TapePlayer() : Storage::Tape::BinaryTapePlayer(1000000) {} - uint8_t get_next_byte(bool fast) { + inline uint8_t get_next_byte(bool fast) { return (uint8_t)parser_.get_next_byte(get_tape(), fast); } diff --git a/Machines/ZX8081/ZX8081.cpp b/Machines/ZX8081/ZX8081.cpp index c79b9e58a..fab9c8986 100644 --- a/Machines/ZX8081/ZX8081.cpp +++ b/Machines/ZX8081/ZX8081.cpp @@ -12,6 +12,8 @@ #include "../../Storage/Tape/Tape.hpp" #include "../../Storage/Tape/Parsers/ZX8081.hpp" +#include "../../ClockReceiver/ForceInline.hpp" + #include "../MemoryFuzzer.hpp" #include "../Typer.hpp" @@ -45,7 +47,7 @@ class ConcreteMachine: clear_all_keys(); } - HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) { + forceinline HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) { HalfCycles previous_counter = horizontal_counter_; horizontal_counter_ += cycle.length; @@ -204,31 +206,31 @@ class ConcreteMachine: return HalfCycles(0); } - void flush() { + forceinline void flush() { video_->flush(); } - void setup_output(float aspect_ratio) { + void setup_output(float aspect_ratio) override final { video_.reset(new Video); } - void close_output() { + void close_output() override final { video_.reset(); } - std::shared_ptr get_crt() { + std::shared_ptr get_crt() override final { return video_->get_crt(); } - std::shared_ptr get_speaker() { + std::shared_ptr get_speaker() override final { return nullptr; } - void run_for(const Cycles cycles) { + void run_for(const Cycles cycles) override final { z80_.run_for(cycles); } - void configure_as_target(const StaticAnalyser::Target &target) { + void configure_as_target(const StaticAnalyser::Target &target) override final { is_zx81_ = target.zx8081.isZX81; if(is_zx81_) { rom_ = zx81_rom_; @@ -275,7 +277,7 @@ class ConcreteMachine: insert_media(target.media); } - bool insert_media(const StaticAnalyser::Media &media) { + bool insert_media(const StaticAnalyser::Media &media) override final { if(!media.tapes.empty()) { tape_player_.set_tape(media.tapes.front()); } @@ -283,12 +285,12 @@ class ConcreteMachine: return !media.tapes.empty(); } - void set_typer_for_string(const char *string) { + void set_typer_for_string(const char *string) override final { std::unique_ptr mapper(new CharacterMapper(is_zx81_)); Utility::TypeRecipient::set_typer_for_string(string, std::move(mapper)); } - void set_rom(ROMType type, std::vector data) { + void set_rom(ROMType type, std::vector data) override final { switch(type) { case ZX80: zx80_rom_ = data; break; case ZX81: zx81_rom_ = data; break; @@ -297,40 +299,40 @@ class ConcreteMachine: #pragma mark - Keyboard - void set_key_state(uint16_t key, bool isPressed) { + void set_key_state(uint16_t key, bool isPressed) override final { if(isPressed) key_states_[key >> 8] &= (uint8_t)(~key); else key_states_[key >> 8] |= (uint8_t)key; } - void clear_all_keys() { + void clear_all_keys() override final { memset(key_states_, 0xff, 8); } #pragma mark - Tape control - void set_use_fast_tape_hack(bool activate) { + void set_use_fast_tape_hack(bool activate) override final { use_fast_tape_hack_ = activate; } - void set_use_automatic_tape_motor_control(bool enabled) { + void set_use_automatic_tape_motor_control(bool enabled) override final { use_automatic_tape_motor_control_ = enabled; if(!enabled) { tape_player_.set_motor_control(false); } } - void set_tape_is_playing(bool is_playing) { + void set_tape_is_playing(bool is_playing) override final { tape_player_.set_motor_control(is_playing); } #pragma mark - Typer timing - HalfCycles get_typer_delay() { return Cycles(7000000); } - HalfCycles get_typer_frequency() { return Cycles(390000); } + HalfCycles get_typer_delay() override final { return Cycles(7000000); } + HalfCycles get_typer_frequency() override final { return Cycles(390000); } private: - CPU::Z80::Processor z80_; + CPU::Z80::Processor z80_; std::shared_ptr