1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-03 11:30:02 +00:00

Chopped time accumulation out of the default Tape process because it's proving to be sufficiently expensive for a TZX as not to be worthwhile. Introduced a cheaper position capturing/restoring method.

This commit is contained in:
Thomas Harte 2017-07-21 18:55:03 -04:00
parent d9a2c32aca
commit a3e0024980
3 changed files with 53 additions and 15 deletions

View File

@ -130,7 +130,7 @@ int Machine::perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) {
case CPU::Z80::PartialMachineCycle::ReadOpcodeWait:
// Check for use of the fast tape hack.
if(use_fast_tape_hack_ && address == tape_trap_address_ && tape_player_.has_tape()) {
Storage::Time time = tape_player_.get_tape()->get_current_time();
uint64_t prior_offset = tape_player_.get_tape()->get_offset();
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);
@ -144,7 +144,7 @@ int Machine::perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) {
tape_advance_delay_ = 1000;
return 0;
} else {
tape_player_.get_tape()->seek(time);
tape_player_.get_tape()->set_offset(prior_offset);
}
}

View File

@ -20,22 +20,43 @@ TapePlayer::TapePlayer(unsigned int input_clock_rate) :
#pragma mark - Seeking
void Storage::Tape::Tape::seek(Time &seek_time) {
current_time_.set_zero();
next_time_.set_zero();
while(next_time_ <= seek_time) get_next_pulse();
Time next_time(0);
reset();
while(next_time <= seek_time) {
get_next_pulse();
next_time += pulse_.length;
}
}
Storage::Time Tape::get_current_time() {
Time time(0);
uint64_t steps = get_offset();
reset();
while(steps--) {
get_next_pulse();
time += pulse_.length;
}
return time;
}
void Storage::Tape::Tape::reset() {
current_time_.set_zero();
next_time_.set_zero();
offset_ = 0;
virtual_reset();
}
Tape::Pulse Tape::get_next_pulse() {
Tape::Pulse pulse = virtual_get_next_pulse();
current_time_ = next_time_;
next_time_ += pulse.length;
return pulse;
pulse_ = virtual_get_next_pulse();
offset_++;
return pulse_;
}
uint64_t Tape::get_offset() {
return offset_;
}
void Tape::set_offset(uint64_t offset) {
reset();
while(offset--) get_next_pulse();
}
#pragma mark - Player

View File

@ -52,16 +52,33 @@ class Tape {
/// @returns @c true if the tape has progressed beyond all recorded content; @c false otherwise.
virtual bool is_at_end() = 0;
/// @returns the amount of time preceeding the most recently-returned pulse.
virtual Time get_current_time() { return current_time_; }
/*!
Returns a numerical representation of progression into the tape. Precision is arbitrary but
required to be at least to the whole pulse. Greater numbers are later than earlier numbers,
but not necessarily continuous.
*/
virtual uint64_t get_offset();
/// Advances or reverses the tape to the last time before or at @c time from which a pulse starts.
/*!
Moves the tape to the first time at which the specified offset would be returned by get_offset.
*/
virtual void set_offset(uint64_t);
/*!
Calculates and returns the amount of time that has elapsed since the time began. Potentially expensive.
*/
virtual Time get_current_time();
/*!
Seeks to @c time. Potentially expensive.
*/
virtual void seek(Time &time);
virtual ~Tape() {};
private:
Time current_time_, next_time_;
uint64_t offset_;
Tape::Pulse pulse_;
virtual Pulse virtual_get_next_pulse() = 0;
virtual void virtual_reset() = 0;