1
0
mirror of https://github.com/TomHarte/CLK.git synced 2026-04-20 10:17:05 +00:00

Flail in attempt to implement fast loading.

This commit is contained in:
Thomas Harte
2025-01-21 14:13:42 -05:00
parent b67bb50f4a
commit 348a593dc1
4 changed files with 144 additions and 37 deletions
+127 -36
View File
@@ -30,6 +30,7 @@
#include "../1540/C1540.hpp"
#include <algorithm>
#include <cmath>
#include <vector>
using namespace Commodore;
@@ -248,16 +249,18 @@ public:
const auto timers_cycles = timers_subcycles_.divide(video_.timer_cycle_length());
timers_.tick(timers_cycles.as<int>());
video_.run_for(length);
tape_player_->run_for(length);
if(!is_fast_loading_) {
video_.run_for(length);
if(c1541_) {
c1541_cycles_ += length * Cycles(1'000'000);
c1541_->run_for(c1541_cycles_.divide(media_divider_));
if(c1541_) {
c1541_cycles_ += length * Cycles(1'000'000);
c1541_->run_for(c1541_cycles_.divide(media_divider_));
}
time_since_audio_update_ += length;
}
time_since_audio_update_ += length;
if(operation == CPU::MOS6502::BusOperation::Ready) {
return length;
}
@@ -301,38 +304,122 @@ public:
serial_port_.set_output(Serial::Line::Attention, Serial::LineLevel(~output & 0x04));
}
} else if(address < 0xfd00 || address >= 0xff40) {
if(use_fast_tape_hack_ && operation == CPU::MOS6502Esque::BusOperation::ReadOpcode && address == 0xe5fd) {
// TODO:
//
// ; read a dipole from tape (and then RTS)
// ;
// ; if c=1 then error
// ; else if v=1 then short
// ; else if n=0 then long
// ; else word
// ; end
// ; end
// ; end
// Compare with:
//
// dsamp1 *=*+2 ;time constant for x cell sample 07B8
// dsamp2 *=*+2 ;time constant for y cell sample
// zcell *=*+2 ;time constant for z cell verify
// const uint8_t dsamp1 = map_.read(0x7b8);
// const uint8_t dsamp2 = map_.read(0x7b9);
// const uint8_t zcell = map_.read(0x7ba);
// if(use_fast_tape_hack_ && operation == CPU::MOS6502Esque::BusOperation::ReadOpcode && address == 0xe5fd) {
// ++pulse_num;
// const bool is_interesting = pulse_num >= 15220;
//
// if(pulse_num == 15224) {
// printf("");
// }
//
// logger.info().append("rddipl: %d / %d / %d", dsamp1, dsamp2, zcell);
}
//// if(address == 0xe68a) {
//// }
//
// if(address == 0xe5fd) {
// // TODO:
// //
// // ; read a dipole from tape (and then RTS)
// // ;
// // ; if c=1 then error
// // ; else if v=1 then short
// // ; else if n=0 then long
// // ; else word
// // ; end
// // ; end
// // ; end
//
// // 76 = V, not N or C
// // b7 = N
//
// // Compare with:
// //
// // dsamp1 *=*+2 ;time constant for x cell sample 07B8
// // dsamp2 *=*+2 ;time constant for y cell sample
// // zcell *=*+2 ;time constant for z cell verify
//
// const auto read16 = [&](uint16_t address) {
// // These constants are defined in terms of the timer clocks; convert them to
// // fractions of a second.
// const auto constant = uint16_t( map_.read(address) | (map_.read(address + 1) << 8) );
// return (float(constant) * video_.timer_cycle_length().as<float>()) / float(get_clock_rate());
// };
// const auto dsamp1 = read16(0x7b8);
// const auto dsamp2 = read16(0x7ba);
// const auto zcell = read16(0x7bc);
// using Pulse = Storage::Tape::Pulse;
//
// // Wait until tape input is high (i.e. input is low).
//// while(tape_player_->current_pulse().type != Pulse::Type::Low) {
//// tape_player_->complete_pulse();
//// }
//
// // Wait until tape input is low.
// while(tape_player_->current_pulse().type != Pulse::Type::High) {
// tape_player_->complete_pulse();
// }
//
// // Count time of low high, and classify.
// const auto length1 = tape_player_->current_pulse().length.get<float>();
// tape_player_->complete_pulse(); // Consume High.
// const auto length2 = tape_player_->current_pulse().length.get<float>();
// tape_player_->complete_pulse(); // Consume Low.
//
// uint8_t flags =
// uint8_t(m6502_.value_of(CPU::MOS6502::Register::Flags)) &
// ~(CPU::MOS6502::Flag::Carry | CPU::MOS6502::Flag::Overflow | CPU::MOS6502::Flag::Sign);
//
// if(std::abs(length1 - length2) > 0.00025f) {
// // Lengths are too dissimilar; call that an error.
// flags |= CPU::MOS6502::Flag::Carry;
// }
//
//// const auto dsamp1_difference = std::abs(length1 - dsamp1);
//// const auto dsamp2_difference = std::abs(length1 - dsamp2);
//// const auto zcell_difference = std::abs(length1 - zcell);
//
// if(length2 < dsamp1) {
// flags |= CPU::MOS6502::Flag::Overflow;
// } else if(length2 > zcell) {
// flags |= CPU::MOS6502::Flag::Sign;
// }
//
// m6502_.set_value_of(CPU::MOS6502::Register::Flags, flags);
//
// if(is_interesting) {
// logger.info().append("Read: %d %d",
// int(length1 * 1'000'000),
// int(length2 * 1'000'000)
// );
// }
//
// *value = 0x60; // i.e. RTS.
// }
//
// if(is_interesting) {
// const auto flags = m6502_.value_of(CPU::MOS6502::Register::Flags);
// logger.info().append("%d @ %d dipole result: %c%c%c",
// pulse_num,
// tape_player_->event_count(),
// flags & CPU::MOS6502::Flag::Sign ? 'n' : '-',
// flags & CPU::MOS6502::Flag::Overflow ? 'v' : '-',
// flags & CPU::MOS6502::Flag::Carry ? 'c' : '-');
//}
// } else {
if(is_read(operation)) {
*value = map_.read(address);
} else {
map_.write(address) = *value;
}
if(is_read(operation)) {
*value = map_.read(address);
} else {
map_.write(address) = *value;
}
// If fast loading is enabled, zero-rate anything in the function rddipl, which reads
// dipoles from tape.
if(use_fast_tape_hack_ && operation == CPU::MOS6502Esque::BusOperation::ReadOpcode) {
is_fast_loading_ = (address >= 0xe5fd) && (address <= 0xeb71);
}
// if(is_in_rddipl) {
// return Cycles(0);
// }
// }
} else if(address < 0xff00) {
// Miscellaneous hardware. All TODO.
if(is_read(operation)) {
@@ -559,7 +646,7 @@ public:
}
}
return length;
return is_fast_loading_ ? Cycles(0) : length;
}
private:
@@ -618,6 +705,8 @@ private:
return video_.get_display_type();
}
int pulse_num = 0;
void run_for(const Cycles cycles) final {
m6502_.run_for(cycles);
@@ -704,8 +793,10 @@ private:
bool play_button_ = false;
bool allow_fast_tape_hack_ = false; // TODO: implement fast-tape hack.
bool use_fast_tape_hack_ = false;
bool is_fast_loading_ = false;
void set_use_fast_tape() {
use_fast_tape_hack_ = allow_fast_tape_hack_ && tape_player_->motor_control() && rom_is_paged_;
is_fast_loading_ &= use_fast_tape_hack_;
}
void update_tape_motor() {
const auto output = io_output_ | ~io_direction_;
+1 -1
View File
@@ -273,7 +273,7 @@ void BufferingScanTarget::will_change_owner() {
std::lock_guard lock_guard(producer_mutex_);
allocation_has_failed_ = true;
vended_scan_ = nullptr;
#ifdef DEBUG
#ifndef NDEBUG
data_is_allocated_ = false;
#endif
}
+6
View File
@@ -30,6 +30,9 @@ void TimedEventLoop::run_for(const Cycles cycles) {
advance(cycles_until_event_);
remaining_cycles -= cycles_until_event_;
cycles_until_event_ = 0;
#ifndef NDEBUG
++event_count_;
#endif
process_next_event();
}
@@ -60,6 +63,9 @@ void TimedEventLoop::reset_timer() {
void TimedEventLoop::jump_to_next_event() {
reset_timer();
#ifndef NDEBUG
++event_count_;
#endif
process_next_event();
}
+10
View File
@@ -58,6 +58,13 @@ public:
*/
Cycles::IntType get_input_clock_rate() const;
#ifndef NDEBUG
/*!
For debugging purposes only, returns the number of events that have so far passed.
*/
int event_count() { return event_count_; }
#endif
protected:
/*!
Sets the time interval, as a proportion of a second, until the next event should be triggered.
@@ -103,6 +110,9 @@ private:
Cycles::IntType input_clock_rate_ = 0;
Cycles::IntType cycles_until_event_ = 0;
float subcycles_until_event_ = 0.0f;
#ifndef NDEBUG
int event_count_ = 0;
#endif
};
}