diff --git a/Analyser/Static/Enterprise/Target.hpp b/Analyser/Static/Enterprise/Target.hpp index 9200a3ce5..71805a10f 100644 --- a/Analyser/Static/Enterprise/Target.hpp +++ b/Analyser/Static/Enterprise/Target.hpp @@ -13,6 +13,8 @@ #include "../../../Reflection/Struct.hpp" #include "../StaticAnalyser.hpp" +#include + namespace Analyser { namespace Static { namespace Enterprise { @@ -27,6 +29,7 @@ struct Target: public Analyser::Static::Target, public Reflection::StructImpl class ConcreteMachine: // Pass on any media. insert_media(target.media); + if(!target.loading_command.empty()) { + type_string(target.loading_command); + } } ~ConcreteMachine() { @@ -312,7 +315,6 @@ template class ConcreteMachine: if(dave_timer_ += full_length) { set_interrupts(dave_timer_.last_valid()->get_new_interrupts(), dave_timer_.last_sequence_point_overrun()); } - if(typer_) typer_->run_for(cycle.length); // The WD/etc runs at a nominal 8Mhz. if constexpr (has_disk_controller) { @@ -428,6 +430,39 @@ template class ConcreteMachine: update_interrupts(); break; case 0xb5: + // Logic here: the ROM scans the keyboard by checking ascending + // lines. It also seems to provide a line of 0 when using port B5 + // for non-keyboard uses. + // + // So: use the rollover from line 9 back to line 0 as a trigger to + // spot that a scan of the keyboard just finished. Which makes it + // time to enqueue the next keypress. + // + // Re: is_past_splash_screen_ and typer_delay_, assume that a + // single keypress is necessary to get past the Enterprise splash + // screen, then a pause in keypressing while BASIC or whatever + // starts up, then presses can resume. + if(typer_ && active_key_line_ == 9 && !(*cycle.value & 0xf)) { + if(!is_past_splash_screen_) { + set_key_state(uint16_t(Key::Space), typer_delay_); + if(typer_delay_) { + --typer_delay_; + } else { + typer_delay_ = 60; + is_past_splash_screen_ = true; + } + } else { + if(!typer_delay_) { + if(!typer_->type_next_character()) { + clear_all_keys(); + typer_ = nullptr; + } + } else { + --typer_delay_; + } + } + } + active_key_line_ = *cycle.value & 0xf; // TODO: // @@ -582,25 +617,20 @@ template class ConcreteMachine: } // MARK: - Utility::TypeRecipient - HalfCycles get_typer_delay(const std::string &) const final { - if(!z80_.get_is_resetting()) { - return Cycles(0); - } - return HalfCycles(1'000'000); - } - - HalfCycles get_typer_frequency() const final { - return HalfCycles(80'000); - } - void type_string(const std::string &string) final { Utility::TypeRecipient::add_typer(string); + + is_past_splash_screen_ = !z80_.get_is_resetting(); + typer_delay_ = !is_past_splash_screen_; } bool can_type(char c) const final { return Utility::TypeRecipient::can_type(c); } + bool is_past_splash_screen_ = false; + int typer_delay_ = 30; + // MARK: - MediaTarget bool insert_media(const Analyser::Static::Media &media) final { if constexpr (has_disk_controller) {