diff --git a/Machines/ZX8081/ZX8081.cpp b/Machines/ZX8081/ZX8081.cpp index 3d955c268..cf3c24ed0 100644 --- a/Machines/ZX8081/ZX8081.cpp +++ b/Machines/ZX8081/ZX8081.cpp @@ -22,7 +22,8 @@ Machine::Machine() : hsync_(false), nmi_is_enabled_(false), tape_player_(ZX8081ClockRate), - use_fast_tape_hack_(false) { + use_fast_tape_hack_(false), + tape_advance_delay_(0) { set_clock_rate(ZX8081ClockRate); tape_player_.set_motor_control(true); clear_all_keys(); @@ -53,7 +54,11 @@ int Machine::perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) { } if(is_zx81_) horizontal_counter_ %= 207; - tape_player_.run_for_cycles(cycle.length); + if(!tape_advance_delay_) { + tape_player_.run_for_cycles(cycle.length); + } else { + tape_advance_delay_ = std::max(tape_advance_delay_ - cycle.length, 0); + } if(nmi_is_enabled_ && !get_halt_line() && get_non_maskable_interrupt_line()) { set_wait_line(true); @@ -124,14 +129,22 @@ int Machine::perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) { case CPU::Z80::PartialMachineCycle::ReadOpcodeStart: case CPU::Z80::PartialMachineCycle::ReadOpcodeWait: // Check for use of the fast tape hack. - if(use_fast_tape_hack_ && address == tape_trap_address_) { + if(use_fast_tape_hack_ && address == tape_trap_address_ && tape_player_.has_tape()) { + Storage::Time time = tape_player_.get_tape()->get_current_time(); int next_byte = parser_.get_next_byte(tape_player_.get_tape()); if(next_byte != -1) { uint16_t hl = get_value_of_register(CPU::Z80::Register::HL); ram_[hl & ram_mask_] = (uint8_t)next_byte; *cycle.value = 0x00; set_value_of_register(CPU::Z80::Register::ProgramCounter, tape_return_address_ - 1); + + // Assume that having read one byte quickly, we're probably going to be asked to read + // another shortly. Therefore, temporarily disable the tape motor for 1000 cycles in order + // to avoid fighting with real time. This is a stop-gap fix. + tape_advance_delay_ = 1000; return 0; + } else { + tape_player_.get_tape()->seek(time); } } is_opcode_read = true; diff --git a/Machines/ZX8081/ZX8081.hpp b/Machines/ZX8081/ZX8081.hpp index 9bd9044a5..d07ed461a 100644 --- a/Machines/ZX8081/ZX8081.hpp +++ b/Machines/ZX8081/ZX8081.hpp @@ -94,6 +94,7 @@ class Machine: uint8_t latched_video_byte_; bool use_fast_tape_hack_; + int tape_advance_delay_; }; } diff --git a/Storage/Tape/Formats/ZX80O81P.cpp b/Storage/Tape/Formats/ZX80O81P.cpp index 53b64222b..e1f969217 100644 --- a/Storage/Tape/Formats/ZX80O81P.cpp +++ b/Storage/Tape/Formats/ZX80O81P.cpp @@ -54,7 +54,7 @@ Tape::Pulse ZX80O81P::virtual_get_next_pulse() { // Start with 1 second of silence. if(!is_past_silence_ || has_finished_data()) { pulse.type = Pulse::Type::Low; - pulse.length.length = 5; + pulse.length.length = 10; pulse.length.clock_rate = 1; is_past_silence_ = true; has_ended_final_byte_ = has_finished_data(); diff --git a/Storage/Tape/Parsers/ZX8081.cpp b/Storage/Tape/Parsers/ZX8081.cpp index dba32dc28..f4678dc6f 100644 --- a/Storage/Tape/Parsers/ZX8081.cpp +++ b/Storage/Tape/Parsers/ZX8081.cpp @@ -79,10 +79,10 @@ void Parser::inspect_waves(const std::vector &waves) { // the gap that follows the bit due to the simplified "high is high, everything else is low" // logic applied to pulse detection. So those two things will merge. Meaning we're looking for // 17 and/or 7 pulses. - int gaps_to_swallow = (int)wave_offset + ((waves[number_of_pulses + wave_offset] == WaveType::Gap) ? 1 : 0); + size_t gaps_to_swallow = wave_offset + ((waves[number_of_pulses + wave_offset] == WaveType::Gap) ? 1 : 0); switch(number_of_pulses) { - case 17: push_symbol(SymbolType::One, 17 + gaps_to_swallow); break; - case 7: push_symbol(SymbolType::Zero, 7 + gaps_to_swallow); break; + case 18: case 17: push_symbol(SymbolType::One, (int)(number_of_pulses + gaps_to_swallow)); break; + case 8: case 7: push_symbol(SymbolType::Zero, (int)(number_of_pulses + gaps_to_swallow)); break; default: push_symbol(SymbolType::Unrecognised, 1); break; } } diff --git a/Storage/Tape/Tape.cpp b/Storage/Tape/Tape.cpp index b5907a078..3fef2973e 100644 --- a/Storage/Tape/Tape.cpp +++ b/Storage/Tape/Tape.cpp @@ -22,7 +22,7 @@ TapePlayer::TapePlayer(unsigned int input_clock_rate) : void Storage::Tape::Tape::seek(Time &seek_time) { current_time_.set_zero(); next_time_.set_zero(); - while(next_time_ < seek_time) get_next_pulse(); + while(next_time_ <= seek_time) get_next_pulse(); } void Storage::Tape::Tape::reset() {