mirror of
https://github.com/TomHarte/CLK.git
synced 2024-09-08 18:55:14 +00:00
Merge pull request #905 from TomHarte/JustInTimeOric
Adopts JustInTimeActor in the Oric.
This commit is contained in:
commit
27eddf6dff
@ -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_;
|
||||||
|
@ -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 {
|
||||||
|
@ -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_;
|
||||||
|
Loading…
Reference in New Issue
Block a user