1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-27 01:31:42 +00:00

Rolls out JustInTime acting to the MSX and ColecoVision.

This commit is contained in:
Thomas Harte 2019-07-29 21:22:31 -04:00
parent 7dcad516bd
commit f3dd4b028d
2 changed files with 28 additions and 35 deletions

View File

@ -19,6 +19,7 @@
#include "../../Configurable/StandardOptions.hpp" #include "../../Configurable/StandardOptions.hpp"
#include "../../ClockReceiver/ForceInline.hpp" #include "../../ClockReceiver/ForceInline.hpp"
#include "../../ClockReceiver/JustInTime.hpp"
#include "../../Outputs/Speaker/Implementation/CompoundSource.hpp" #include "../../Outputs/Speaker/Implementation/CompoundSource.hpp"
#include "../../Outputs/Speaker/Implementation/LowpassSpeaker.hpp" #include "../../Outputs/Speaker/Implementation/LowpassSpeaker.hpp"
@ -169,7 +170,7 @@ class ConcreteMachine:
} }
// ColecoVisions have composite output only. // ColecoVisions have composite output only.
vdp_.set_display_type(Outputs::Display::DisplayType::CompositeColour); vdp_->set_display_type(Outputs::Display::DisplayType::CompositeColour);
} }
~ConcreteMachine() { ~ConcreteMachine() {
@ -181,11 +182,11 @@ class ConcreteMachine:
} }
void set_scan_target(Outputs::Display::ScanTarget *scan_target) override { void set_scan_target(Outputs::Display::ScanTarget *scan_target) override {
vdp_.set_scan_target(scan_target); vdp_->set_scan_target(scan_target);
} }
void set_display_type(Outputs::Display::DisplayType display_type) override { void set_display_type(Outputs::Display::DisplayType display_type) override {
vdp_.set_display_type(display_type); vdp_->set_display_type(display_type);
} }
Outputs::Speaker::Speaker *get_speaker() override { Outputs::Speaker::Speaker *get_speaker() override {
@ -210,7 +211,7 @@ class ConcreteMachine:
} }
const HalfCycles length = cycle.length + penalty; const HalfCycles length = cycle.length + penalty;
time_since_vdp_update_ += length; vdp_ += length;
time_since_sn76489_update_ += length; time_since_sn76489_update_ += length;
// Act only if necessary. // Act only if necessary.
@ -255,10 +256,9 @@ class ConcreteMachine:
case CPU::Z80::PartialMachineCycle::Input: case CPU::Z80::PartialMachineCycle::Input:
switch((address >> 5) & 7) { switch((address >> 5) & 7) {
case 5: case 5:
update_video(); *cycle.value = vdp_->get_register(address);
*cycle.value = vdp_.get_register(address); z80_.set_non_maskable_interrupt_line(vdp_->get_interrupt_line());
z80_.set_non_maskable_interrupt_line(vdp_.get_interrupt_line()); time_until_interrupt_ = vdp_->get_time_until_interrupt();
time_until_interrupt_ = vdp_.get_time_until_interrupt();
break; break;
case 7: { case 7: {
@ -299,10 +299,9 @@ class ConcreteMachine:
break; break;
case 5: case 5:
update_video(); vdp_->set_register(address, *cycle.value);
vdp_.set_register(address, *cycle.value); z80_.set_non_maskable_interrupt_line(vdp_->get_interrupt_line());
z80_.set_non_maskable_interrupt_line(vdp_.get_interrupt_line()); time_until_interrupt_ = vdp_->get_time_until_interrupt();
time_until_interrupt_ = vdp_.get_time_until_interrupt();
break; break;
case 7: case 7:
@ -354,7 +353,7 @@ class ConcreteMachine:
} }
void flush() { void flush() {
update_video(); vdp_.flush();
update_audio(); update_audio();
audio_queue_.perform(); audio_queue_.perform();
} }
@ -396,12 +395,9 @@ class ConcreteMachine:
inline void update_audio() { inline void update_audio() {
speaker_.run_for(audio_queue_, time_since_sn76489_update_.divide_cycles(Cycles(sn76489_divider))); speaker_.run_for(audio_queue_, time_since_sn76489_update_.divide_cycles(Cycles(sn76489_divider)));
} }
inline void update_video() {
vdp_.run_for(time_since_vdp_update_.flush<HalfCycles>());
}
CPU::Z80::Processor<ConcreteMachine, false, false> z80_; CPU::Z80::Processor<ConcreteMachine, false, false> z80_;
TI::TMS::TMS9918 vdp_; JustInTimeActor<TI::TMS::TMS9918, HalfCycles> vdp_;
Concurrency::DeferringAsyncTaskQueue audio_queue_; Concurrency::DeferringAsyncTaskQueue audio_queue_;
TI::SN76489 sn76489_; TI::SN76489 sn76489_;
@ -424,7 +420,6 @@ class ConcreteMachine:
std::vector<std::unique_ptr<Inputs::Joystick>> joysticks_; std::vector<std::unique_ptr<Inputs::Joystick>> joysticks_;
bool joysticks_in_keypad_mode_ = false; bool joysticks_in_keypad_mode_ = false;
HalfCycles time_since_vdp_update_;
HalfCycles time_since_sn76489_update_; HalfCycles time_since_sn76489_update_;
HalfCycles time_until_interrupt_; HalfCycles time_until_interrupt_;

View File

@ -45,6 +45,7 @@
#include "../../Configurable/StandardOptions.hpp" #include "../../Configurable/StandardOptions.hpp"
#include "../../ClockReceiver/ForceInline.hpp" #include "../../ClockReceiver/ForceInline.hpp"
#include "../../ClockReceiver/JustInTime.hpp"
#include "../../Analyser/Static/MSX/Target.hpp" #include "../../Analyser/Static/MSX/Target.hpp"
@ -187,7 +188,7 @@ class ConcreteMachine:
switch(target.region) { switch(target.region) {
case Target::Region::Japan: case Target::Region::Japan:
required_roms.emplace_back(machine_name, "a Japanese MSX BIOS", "msx-japanese.rom", 32*1024, 0xee229390); required_roms.emplace_back(machine_name, "a Japanese MSX BIOS", "msx-japanese.rom", 32*1024, 0xee229390);
vdp_.set_tv_standard(TI::TMS::TVStandard::NTSC); vdp_->set_tv_standard(TI::TMS::TVStandard::NTSC);
is_ntsc = true; is_ntsc = true;
character_generator = 0; character_generator = 0;
@ -195,7 +196,7 @@ class ConcreteMachine:
break; break;
case Target::Region::USA: case Target::Region::USA:
required_roms.emplace_back(machine_name, "an American MSX BIOS", "msx-american.rom", 32*1024, 0); required_roms.emplace_back(machine_name, "an American MSX BIOS", "msx-american.rom", 32*1024, 0);
vdp_.set_tv_standard(TI::TMS::TVStandard::NTSC); vdp_->set_tv_standard(TI::TMS::TVStandard::NTSC);
is_ntsc = true; is_ntsc = true;
character_generator = 1; character_generator = 1;
@ -203,7 +204,7 @@ class ConcreteMachine:
break; break;
case Target::Region::Europe: case Target::Region::Europe:
required_roms.emplace_back(machine_name, "a European MSX BIOS", "msx-european.rom", 32*1024, 0); required_roms.emplace_back(machine_name, "a European MSX BIOS", "msx-european.rom", 32*1024, 0);
vdp_.set_tv_standard(TI::TMS::TVStandard::PAL); vdp_->set_tv_standard(TI::TMS::TVStandard::PAL);
is_ntsc = false; is_ntsc = false;
character_generator = 1; character_generator = 1;
@ -278,11 +279,11 @@ class ConcreteMachine:
} }
void set_scan_target(Outputs::Display::ScanTarget *scan_target) override { void set_scan_target(Outputs::Display::ScanTarget *scan_target) override {
vdp_.set_scan_target(scan_target); vdp_->set_scan_target(scan_target);
} }
void set_display_type(Outputs::Display::DisplayType display_type) override { void set_display_type(Outputs::Display::DisplayType display_type) override {
vdp_.set_display_type(display_type); vdp_->set_display_type(display_type);
} }
Outputs::Speaker::Speaker *get_speaker() override { Outputs::Speaker::Speaker *get_speaker() override {
@ -411,7 +412,7 @@ class ConcreteMachine:
// but otherwise runs without pause. // but otherwise runs without pause.
const HalfCycles addition((cycle.operation == CPU::Z80::PartialMachineCycle::ReadOpcode) ? 2 : 0); const HalfCycles addition((cycle.operation == CPU::Z80::PartialMachineCycle::ReadOpcode) ? 2 : 0);
const HalfCycles total_length = addition + cycle.length; const HalfCycles total_length = addition + cycle.length;
time_since_vdp_update_ += total_length; vdp_ += total_length;
time_since_ay_update_ += total_length; time_since_ay_update_ += total_length;
memory_slots_[0].cycles_since_update += total_length; memory_slots_[0].cycles_since_update += total_length;
memory_slots_[1].cycles_since_update += total_length; memory_slots_[1].cycles_since_update += total_length;
@ -508,10 +509,9 @@ class ConcreteMachine:
case CPU::Z80::PartialMachineCycle::Input: case CPU::Z80::PartialMachineCycle::Input:
switch(address & 0xff) { switch(address & 0xff) {
case 0x98: case 0x99: case 0x98: case 0x99:
vdp_.run_for(time_since_vdp_update_.flush<HalfCycles>()); *cycle.value = vdp_->get_register(address);
*cycle.value = vdp_.get_register(address); z80_.set_interrupt_line(vdp_->get_interrupt_line());
z80_.set_interrupt_line(vdp_.get_interrupt_line()); time_until_interrupt_ = vdp_->get_time_until_interrupt();
time_until_interrupt_ = vdp_.get_time_until_interrupt();
break; break;
case 0xa2: case 0xa2:
@ -536,10 +536,9 @@ class ConcreteMachine:
const int port = address & 0xff; const int port = address & 0xff;
switch(port) { switch(port) {
case 0x98: case 0x99: case 0x98: case 0x99:
vdp_.run_for(time_since_vdp_update_.flush<HalfCycles>()); vdp_->set_register(address, *cycle.value);
vdp_.set_register(address, *cycle.value); z80_.set_interrupt_line(vdp_->get_interrupt_line());
z80_.set_interrupt_line(vdp_.get_interrupt_line()); time_until_interrupt_ = vdp_->get_time_until_interrupt();
time_until_interrupt_ = vdp_.get_time_until_interrupt();
break; break;
case 0xa0: case 0xa1: case 0xa0: case 0xa1:
@ -612,7 +611,7 @@ class ConcreteMachine:
} }
void flush() { void flush() {
vdp_.run_for(time_since_vdp_update_.flush<HalfCycles>()); vdp_.flush();
update_audio(); update_audio();
audio_queue_.perform(); audio_queue_.perform();
} }
@ -753,7 +752,7 @@ class ConcreteMachine:
}; };
CPU::Z80::Processor<ConcreteMachine, false, false> z80_; CPU::Z80::Processor<ConcreteMachine, false, false> z80_;
TI::TMS::TMS9918 vdp_; JustInTimeActor<TI::TMS::TMS9918, HalfCycles> vdp_;
Intel::i8255::i8255<i8255PortHandler> i8255_; Intel::i8255::i8255<i8255PortHandler> i8255_;
Concurrency::DeferringAsyncTaskQueue audio_queue_; Concurrency::DeferringAsyncTaskQueue audio_queue_;
@ -797,7 +796,6 @@ class ConcreteMachine:
uint8_t scratch_[8192]; uint8_t scratch_[8192];
uint8_t unpopulated_[8192]; uint8_t unpopulated_[8192];
HalfCycles time_since_vdp_update_;
HalfCycles time_since_ay_update_; HalfCycles time_since_ay_update_;
HalfCycles time_until_interrupt_; HalfCycles time_until_interrupt_;