1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-04 18:29:40 +00:00

Merge pull request #905 from TomHarte/JustInTimeOric

Adopts JustInTimeActor in the Oric.
This commit is contained in:
Thomas Harte 2021-04-04 20:57:52 -04:00 committed by GitHub
commit 27eddf6dff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 47 deletions

View File

@ -136,6 +136,11 @@ template <class T, class LocalTimeScale = HalfCycles, int multiplier = 1, int di
return &object_; return &object_;
} }
/// @returns a const pointer to the included object, without flushing time.
[[nodiscard]] forceinline const T *last_valid() const {
return &object_;
}
/// @returns the amount of time since the object was last flushed, in the target time scale. /// @returns the amount of time since the object was last flushed, in the target time scale.
[[nodiscard]] forceinline TargetTimeScale time_since_flush() const { [[nodiscard]] forceinline TargetTimeScale time_since_flush() const {
// TODO: does this handle conversions properly where TargetTimeScale != LocalTimeScale? // TODO: does this handle conversions properly where TargetTimeScale != LocalTimeScale?
@ -191,6 +196,11 @@ template <class T, class LocalTimeScale = HalfCycles, int multiplier = 1, int di
} }
} }
/// @returns A cached copy of the object's clocking preference.
ClockingHint::Preference clocking_preference() const {
return clocking_preference_;
}
private: private:
T object_; T object_;
LocalTimeScale time_since_update_, time_until_event_; LocalTimeScale time_since_update_, time_until_event_;

View File

@ -521,19 +521,19 @@ template <bool has_scsi_bus> class ConcreteMachine:
} }
void set_scan_target(Outputs::Display::ScanTarget *scan_target) final { void set_scan_target(Outputs::Display::ScanTarget *scan_target) final {
video_->set_scan_target(scan_target); video_.last_valid()->set_scan_target(scan_target);
} }
Outputs::Display::ScanStatus get_scaled_scan_status() const final { Outputs::Display::ScanStatus get_scaled_scan_status() const final {
return video_->get_scaled_scan_status(); return video_.last_valid()->get_scaled_scan_status();
} }
void set_display_type(Outputs::Display::DisplayType display_type) final { void set_display_type(Outputs::Display::DisplayType display_type) final {
video_->set_display_type(display_type); video_.last_valid()->set_display_type(display_type);
} }
Outputs::Display::DisplayType get_display_type() const final { Outputs::Display::DisplayType get_display_type() const final {
return video_->get_display_type(); return video_.last_valid()->get_display_type();
} }
Outputs::Speaker::Speaker *get_speaker() final { Outputs::Speaker::Speaker *get_speaker() final {

View File

@ -34,6 +34,8 @@
#include "../../Analyser/Static/Oric/Target.hpp" #include "../../Analyser/Static/Oric/Target.hpp"
#include "../../ClockReceiver/JustInTime.hpp"
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include <vector> #include <vector>
@ -217,7 +219,6 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface, CPU::MOS
public MOS::MOS6522::IRQDelegatePortHandler::Delegate, public MOS::MOS6522::IRQDelegatePortHandler::Delegate,
public Storage::Tape::BinaryTapePlayer::Delegate, public Storage::Tape::BinaryTapePlayer::Delegate,
public DiskController::Delegate, public DiskController::Delegate,
public ClockingHint::Observer,
public Activity::Source, public Activity::Source,
public Machine, public Machine,
public Keyboard::SpecialKeyHandler { public Keyboard::SpecialKeyHandler {
@ -225,7 +226,7 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface, CPU::MOS
public: public:
ConcreteMachine(const Analyser::Static::Oric::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) : ConcreteMachine(const Analyser::Static::Oric::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) :
m6502_(*this), m6502_(*this),
video_output_(ram_), video_(ram_),
ay8910_(GI::AY38910::Personality::AY38910, audio_queue_), ay8910_(GI::AY38910::Personality::AY38910, audio_queue_),
speaker_(ay8910_), speaker_(ay8910_),
via_port_handler_(audio_queue_, ay8910_, speaker_, tape_player_, keyboard_), via_port_handler_(audio_queue_, ay8910_, speaker_, tape_player_, keyboard_),
@ -247,10 +248,6 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface, CPU::MOS
ram_[c] |= 0x40; ram_[c] |= 0x40;
} }
if constexpr (disk_interface == DiskInterface::Pravetz) {
diskii_.set_clocking_hint_observer(this);
}
const std::string machine_name = "Oric"; const std::string machine_name = "Oric";
std::vector<ROMMachine::ROM> rom_names = { {machine_name, "the Oric colour ROM", "colour.rom", 128, 0xd50fca65} }; std::vector<ROMMachine::ROM> rom_names = { {machine_name, "the Oric colour ROM", "colour.rom", 128, 0xd50fca65} };
switch(target.rom) { switch(target.rom) {
@ -292,7 +289,7 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface, CPU::MOS
} }
} }
video_output_.set_colour_rom(*roms[0]); video_->set_colour_rom(*roms[0]);
rom_ = std::move(*roms[1]); rom_ = std::move(*roms[1]);
switch(disk_interface) { switch(disk_interface) {
@ -313,7 +310,7 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface, CPU::MOS
pravetz_rom_ = std::move(*roms[2]); pravetz_rom_ = std::move(*roms[2]);
pravetz_rom_.resize(512); pravetz_rom_.resize(512);
diskii_.set_state_machine(*roms[diskii_state_machine_index]); diskii_->set_state_machine(*roms[diskii_state_machine_index]);
} break; } break;
} }
@ -402,7 +399,7 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface, CPU::MOS
case DiskInterface::BD500: inserted |= insert_disks(media, bd500_, 4); break; case DiskInterface::BD500: inserted |= insert_disks(media, bd500_, 4); break;
case DiskInterface::Jasmin: inserted |= insert_disks(media, jasmin_, 4); break; case DiskInterface::Jasmin: inserted |= insert_disks(media, jasmin_, 4); break;
case DiskInterface::Microdisc: inserted |= insert_disks(media, microdisc_, 4); break; case DiskInterface::Microdisc: inserted |= insert_disks(media, microdisc_, 4); break;
case DiskInterface::Pravetz: inserted |= insert_disks(media, diskii_, 2); break; case DiskInterface::Pravetz: inserted |= insert_disks(media, *diskii_.last_valid(), 2); break;
default: break; default: break;
} }
} }
@ -474,9 +471,8 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface, CPU::MOS
} }
} }
} else { } else {
flush_diskii(); const int disk_value = diskii_->read_address(address);
const int disk_value = diskii_.read_address(address); if(!isWriteOperation(operation) && disk_value != Apple::DiskII::DidNotLoad) *value = uint8_t(disk_value);
if(!isWriteOperation(operation) && disk_value != diskii_.DidNotLoad) *value = uint8_t(disk_value);
} }
break; break;
} }
@ -485,7 +481,7 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface, CPU::MOS
if(!isWriteOperation(operation)) if(!isWriteOperation(operation))
*value = ram_[address]; *value = ram_[address];
else { else {
if(address >= 0x9800 && address <= 0xc000) update_video(); if(address >= 0x9800 && address <= 0xc000) video_.flush();
ram_[address] = *value; ram_[address] = *value;
} }
} }
@ -508,7 +504,7 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface, CPU::MOS
bd500_.run_for(Cycles(9)); // i.e. effective clock rate of 9Mhz. bd500_.run_for(Cycles(9)); // i.e. effective clock rate of 9Mhz.
break; break;
case DiskInterface::Jasmin: case DiskInterface::Jasmin:
jasmin_.run_for(Cycles(8));; // i.e. effective clock rate of 8Mhz. jasmin_.run_for(Cycles(8)); // i.e. effective clock rate of 8Mhz.
// Jasmin autostart hack: wait for a period, then trigger a reset, having forced // Jasmin autostart hack: wait for a period, then trigger a reset, having forced
// the Jasmin to page its ROM in first. I assume the latter being what the Jasmin's // the Jasmin to page its ROM in first. I assume the latter being what the Jasmin's
@ -521,43 +517,41 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface, CPU::MOS
} }
break; break;
case DiskInterface::Microdisc: case DiskInterface::Microdisc:
microdisc_.run_for(Cycles(8));; // i.e. effective clock rate of 8Mhz. microdisc_.run_for(Cycles(8)); // i.e. effective clock rate of 8Mhz.
break; break;
case DiskInterface::Pravetz: case DiskInterface::Pravetz:
if(diskii_clocking_preference_ == ClockingHint::Preference::RealTime) { if(diskii_.clocking_preference() == ClockingHint::Preference::RealTime) {
diskii_.set_data_input(*value); diskii_->set_data_input(*value);
diskii_.run_for(Cycles(2));; // i.e. effective clock rate of 2Mhz.
} else {
cycles_since_diskii_update_ += Cycles(2);
} }
diskii_ += Cycles(2); // i.e. effective clock rate of 2Mhz.
break; break;
} }
cycles_since_video_update_++;
video_ += Cycles(1);
return Cycles(1); return Cycles(1);
} }
forceinline void flush() { forceinline void flush() {
update_video(); video_.flush();
via_.flush(); via_.flush();
flush_diskii(); diskii_.flush();
} }
// to satisfy CRTMachine::Machine // to satisfy CRTMachine::Machine
void set_scan_target(Outputs::Display::ScanTarget *scan_target) final { void set_scan_target(Outputs::Display::ScanTarget *scan_target) final {
video_output_.set_scan_target(scan_target); video_.last_valid()->set_scan_target(scan_target);
} }
Outputs::Display::ScanStatus get_scaled_scan_status() const final { Outputs::Display::ScanStatus get_scaled_scan_status() const final {
return video_output_.get_scaled_scan_status(); return video_.last_valid()->get_scaled_scan_status();
} }
void set_display_type(Outputs::Display::DisplayType display_type) final { void set_display_type(Outputs::Display::DisplayType display_type) final {
video_output_.set_display_type(display_type); video_.last_valid()->set_display_type(display_type);
} }
Outputs::Display::DisplayType get_display_type() const final { Outputs::Display::DisplayType get_display_type() const final {
return video_output_.get_display_type(); return video_.last_valid()->get_display_type();
} }
Outputs::Speaker::Speaker *get_speaker() final { Outputs::Speaker::Speaker *get_speaker() final {
@ -644,15 +638,11 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface, CPU::MOS
microdisc_.set_activity_observer(observer); microdisc_.set_activity_observer(observer);
break; break;
case DiskInterface::Pravetz: case DiskInterface::Pravetz:
diskii_.set_activity_observer(observer); diskii_->set_activity_observer(observer);
break; break;
} }
} }
void set_component_prefers_clocking(ClockingHint::Source *, ClockingHint::Preference) final {
diskii_clocking_preference_ = diskii_.preferred_clocking();
}
private: private:
const uint16_t basic_invisible_ram_top_ = 0xffff; const uint16_t basic_invisible_ram_top_ = 0xffff;
const uint16_t basic_visible_ram_top_ = 0xbfff; const uint16_t basic_visible_ram_top_ = 0xbfff;
@ -662,17 +652,13 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface, CPU::MOS
// RAM and ROM // RAM and ROM
std::vector<uint8_t> rom_, disk_rom_; std::vector<uint8_t> rom_, disk_rom_;
uint8_t ram_[65536]; uint8_t ram_[65536];
Cycles cycles_since_video_update_;
inline void update_video() {
video_output_.run_for(cycles_since_video_update_.flush<Cycles>());
}
// ROM bookkeeping // ROM bookkeeping
uint16_t tape_get_byte_address_ = 0, tape_speed_address_ = 0; uint16_t tape_get_byte_address_ = 0, tape_speed_address_ = 0;
int keyboard_read_count_ = 0; int keyboard_read_count_ = 0;
// Outputs // Outputs
VideoOutput video_output_; JustInTimeActor<VideoOutput, Cycles> video_;
Concurrency::DeferringAsyncTaskQueue audio_queue_; Concurrency::DeferringAsyncTaskQueue audio_queue_;
GI::AY38910::AY38910<false> ay8910_; GI::AY38910::AY38910<false> ay8910_;
@ -700,14 +686,9 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface, CPU::MOS
BD500 bd500_; BD500 bd500_;
// the Pravetz/Disk II, if in use. // the Pravetz/Disk II, if in use.
Apple::DiskII diskii_; JustInTimeActor<Apple::DiskII, Cycles> diskii_;
Cycles cycles_since_diskii_update_;
void flush_diskii() {
diskii_.run_for(cycles_since_diskii_update_.flush<Cycles>());
}
std::vector<uint8_t> pravetz_rom_; std::vector<uint8_t> pravetz_rom_;
std::size_t pravetz_rom_base_pointer_ = 0; std::size_t pravetz_rom_base_pointer_ = 0;
ClockingHint::Preference diskii_clocking_preference_ = ClockingHint::Preference::RealTime;
// Overlay RAM // Overlay RAM
uint16_t ram_top_ = basic_visible_ram_top_; uint16_t ram_top_ = basic_visible_ram_top_;