mirror of
https://github.com/TomHarte/CLK.git
synced 2026-01-24 08:16:12 +00:00
Introduce the concept of a 'skip range' and spot one type of loader.
This commit is contained in:
@@ -238,30 +238,33 @@ public:
|
||||
audio_queue_.lock_flush();
|
||||
}
|
||||
|
||||
// HACK. NOCOMMIT.
|
||||
// int pulse_num_ = 0;
|
||||
|
||||
template <CPU::MOS6502Mk2::BusOperation operation, typename AddressT>
|
||||
Cycles perform(const AddressT address, CPU::MOS6502Mk2::data_t<operation> value) {
|
||||
// Determine from the TED video subsystem the length of this clock cycle as perceived by the 6502,
|
||||
// relative to the master clock.
|
||||
const auto length = video_.cycle_length(operation == CPU::MOS6502Mk2::BusOperation::Ready);
|
||||
auto length = video_.cycle_length(operation == CPU::MOS6502Mk2::BusOperation::Ready);
|
||||
|
||||
// Update other subsystems.
|
||||
timers_subcycles_ += length;
|
||||
const auto timers_cycles = timers_subcycles_.divide(video_.timer_cycle_length());
|
||||
timers_.tick(timers_cycles.as<int>());
|
||||
advance_timers_and_tape(length);
|
||||
if(operation != CPU::MOS6502Mk2::BusOperation::Ready && skip_range_) {
|
||||
if(
|
||||
operation == CPU::MOS6502Mk2::BusOperation::ReadOpcode &&
|
||||
(address < skip_range_->low || address >= skip_range_->high)
|
||||
) {
|
||||
skip_range_ = std::nullopt;
|
||||
}
|
||||
length = Cycles(0);
|
||||
} else {
|
||||
video_.run_for(length);
|
||||
|
||||
tape_handler_.run_for(length);
|
||||
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::MOS6502Mk2::BusOperation::Ready) {
|
||||
return length;
|
||||
}
|
||||
@@ -284,6 +287,12 @@ public:
|
||||
value = io_direction_;
|
||||
} else {
|
||||
value = io_input();
|
||||
|
||||
if(!skip_range_) {
|
||||
if(const auto pc = m6502_.registers().pc; pc >= 0x333 && pc < 0x3f2 ) {
|
||||
skip_range_ = tape_handler_.skip_range(pc.full, m6502_, map_);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(!address) {
|
||||
@@ -676,7 +685,15 @@ private:
|
||||
Serial::Bus serial_bus_;
|
||||
SerialPort serial_port_;
|
||||
|
||||
void advance_timers_and_tape(const Cycles length) {
|
||||
timers_subcycles_ += length;
|
||||
const auto timers_cycles = timers_subcycles_.divide(video_.timer_cycle_length());
|
||||
timers_.tick(timers_cycles.as<int>());
|
||||
|
||||
tape_handler_.run_for(length);
|
||||
}
|
||||
TapeHandler tape_handler_;
|
||||
std::optional<SkipRange> skip_range_;
|
||||
|
||||
uint8_t io_direction_ = 0x00, io_output_ = 0x00;
|
||||
uint8_t io_input() const {
|
||||
|
||||
@@ -13,9 +13,14 @@
|
||||
#include "Storage/Tape/Parsers/Commodore.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
namespace Commodore::Plus4 {
|
||||
|
||||
struct SkipRange {
|
||||
uint16_t low, high;
|
||||
};
|
||||
|
||||
/*!
|
||||
All tape assistance, bundled into a single place, including:
|
||||
|
||||
@@ -181,6 +186,28 @@ struct TapeHandler: public ClockingHint::Observer {
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename M6502T, typename MemoryT>
|
||||
std::optional<SkipRange> skip_range(const uint16_t pc, M6502T &, MemoryT &map) {
|
||||
|
||||
// Check for sequence:
|
||||
//
|
||||
// 24 01 BIT 01
|
||||
// d0 fc BNE 3c8 <- PC will be here; trigger is the BIT operation above.
|
||||
// 24 01 BIT 01
|
||||
// f0 fc BEQ 3cc
|
||||
|
||||
if(
|
||||
map.read(pc) == 0xd0 && map.read(pc+1) == 0xfc &&
|
||||
map.read(pc-2) == 0x24 && map.read(pc-1) == 0x01 &&
|
||||
map.read(pc+2) == 0x24 && map.read(pc+3) == 0x01 &&
|
||||
map.read(pc+4) == 0xf0 && map.read(pc+5) == 0xfc
|
||||
) {
|
||||
return SkipRange{uint16_t(pc - 2), uint16_t(pc + 6)};
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Storage::Tape::BinaryTapePlayer> tape_player_;
|
||||
bool play_button_ = false;
|
||||
|
||||
Reference in New Issue
Block a user