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:
@@ -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_;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user