1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-02 20:30:00 +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_;
}
/// @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.
[[nodiscard]] forceinline TargetTimeScale time_since_flush() const {
// 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:
T object_;
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 {
video_->set_scan_target(scan_target);
video_.last_valid()->set_scan_target(scan_target);
}
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 {
video_->set_display_type(display_type);
video_.last_valid()->set_display_type(display_type);
}
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 {

View File

@ -34,6 +34,8 @@
#include "../../Analyser/Static/Oric/Target.hpp"
#include "../../ClockReceiver/JustInTime.hpp"
#include <cstdint>
#include <memory>
#include <vector>
@ -217,7 +219,6 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface, CPU::MOS
public MOS::MOS6522::IRQDelegatePortHandler::Delegate,
public Storage::Tape::BinaryTapePlayer::Delegate,
public DiskController::Delegate,
public ClockingHint::Observer,
public Activity::Source,
public Machine,
public Keyboard::SpecialKeyHandler {
@ -225,7 +226,7 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface, CPU::MOS
public:
ConcreteMachine(const Analyser::Static::Oric::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) :
m6502_(*this),
video_output_(ram_),
video_(ram_),
ay8910_(GI::AY38910::Personality::AY38910, audio_queue_),
speaker_(ay8910_),
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;
}
if constexpr (disk_interface == DiskInterface::Pravetz) {
diskii_.set_clocking_hint_observer(this);
}
const std::string machine_name = "Oric";
std::vector<ROMMachine::ROM> rom_names = { {machine_name, "the Oric colour ROM", "colour.rom", 128, 0xd50fca65} };
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]);
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_.resize(512);
diskii_.set_state_machine(*roms[diskii_state_machine_index]);
diskii_->set_state_machine(*roms[diskii_state_machine_index]);
} 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::Jasmin: inserted |= insert_disks(media, jasmin_, 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;
}
}
@ -474,9 +471,8 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface, CPU::MOS
}
}
} else {
flush_diskii();
const int disk_value = diskii_.read_address(address);
if(!isWriteOperation(operation) && disk_value != diskii_.DidNotLoad) *value = uint8_t(disk_value);
const int disk_value = diskii_->read_address(address);
if(!isWriteOperation(operation) && disk_value != Apple::DiskII::DidNotLoad) *value = uint8_t(disk_value);
}
break;
}
@ -485,7 +481,7 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface, CPU::MOS
if(!isWriteOperation(operation))
*value = ram_[address];
else {
if(address >= 0x9800 && address <= 0xc000) update_video();
if(address >= 0x9800 && address <= 0xc000) video_.flush();
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.
break;
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
// 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;
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;
case DiskInterface::Pravetz:
if(diskii_clocking_preference_ == ClockingHint::Preference::RealTime) {
diskii_.set_data_input(*value);
diskii_.run_for(Cycles(2));; // i.e. effective clock rate of 2Mhz.
} else {
cycles_since_diskii_update_ += Cycles(2);
if(diskii_.clocking_preference() == ClockingHint::Preference::RealTime) {
diskii_->set_data_input(*value);
}
diskii_ += Cycles(2); // i.e. effective clock rate of 2Mhz.
break;
}
cycles_since_video_update_++;
video_ += Cycles(1);
return Cycles(1);
}
forceinline void flush() {
update_video();
video_.flush();
via_.flush();
flush_diskii();
diskii_.flush();
}
// to satisfy CRTMachine::Machine
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 {
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 {
video_output_.set_display_type(display_type);
video_.last_valid()->set_display_type(display_type);
}
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 {
@ -644,15 +638,11 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface, CPU::MOS
microdisc_.set_activity_observer(observer);
break;
case DiskInterface::Pravetz:
diskii_.set_activity_observer(observer);
diskii_->set_activity_observer(observer);
break;
}
}
void set_component_prefers_clocking(ClockingHint::Source *, ClockingHint::Preference) final {
diskii_clocking_preference_ = diskii_.preferred_clocking();
}
private:
const uint16_t basic_invisible_ram_top_ = 0xffff;
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
std::vector<uint8_t> rom_, disk_rom_;
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
uint16_t tape_get_byte_address_ = 0, tape_speed_address_ = 0;
int keyboard_read_count_ = 0;
// Outputs
VideoOutput video_output_;
JustInTimeActor<VideoOutput, Cycles> video_;
Concurrency::DeferringAsyncTaskQueue audio_queue_;
GI::AY38910::AY38910<false> ay8910_;
@ -700,14 +686,9 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface, CPU::MOS
BD500 bd500_;
// the Pravetz/Disk II, if in use.
Apple::DiskII diskii_;
Cycles cycles_since_diskii_update_;
void flush_diskii() {
diskii_.run_for(cycles_since_diskii_update_.flush<Cycles>());
}
JustInTimeActor<Apple::DiskII, Cycles> diskii_;
std::vector<uint8_t> pravetz_rom_;
std::size_t pravetz_rom_base_pointer_ = 0;
ClockingHint::Preference diskii_clocking_preference_ = ClockingHint::Preference::RealTime;
// Overlay RAM
uint16_t ram_top_ = basic_visible_ram_top_;