1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-02 20:30:00 +00:00

Factored interrupt counting out of the CRTCBusHandler.

This commit is contained in:
Thomas Harte 2017-08-01 22:15:39 -04:00
parent 6ca07f1e28
commit 587eb3a67c

View File

@ -16,9 +16,55 @@
using namespace AmstradCPC;
class InterruptTimer {
public:
InterruptTimer() : timer_(0), interrupt_request_(false) {}
inline void increment() {
timer_++;
if(timer_ == 52) {
timer_ = 0;
interrupt_request_ = true;
}
if(reset_counter_) {
reset_counter_--;
if(!reset_counter_) {
if(timer_ < 32) {
interrupt_request_ = true;
}
timer_ = 0;
}
}
}
inline void signal_vsync() {
reset_counter_ = 2;
}
inline void reset_request() {
interrupt_request_ = false;
timer_ &= ~32;
}
inline bool get_request() {
return interrupt_request_;
}
inline void reset_count() {
timer_ = 0;
}
private:
int reset_counter_;
bool interrupt_request_;
int timer_;
};
class CRTCBusHandler {
public:
CRTCBusHandler(uint8_t *ram) :
CRTCBusHandler(uint8_t *ram, InterruptTimer &interrupt_timer) :
cycles_(0),
was_enabled_(false),
was_sync_(false),
@ -26,8 +72,7 @@ class CRTCBusHandler {
pixel_pointer_(nullptr),
was_hsync_(false),
ram_(ram),
interrupt_counter_(0),
interrupt_request_(false),
interrupt_timer_(interrupt_timer),
pixel_divider_(1) {}
inline void perform_bus_cycle(const Motorola::CRTC::BusState &state) {
@ -121,40 +166,17 @@ class CRTCBusHandler {
}
}
interrupt_counter_++;
if(interrupt_counter_ == 52) {
interrupt_request_ = true;
interrupt_counter_ = false;
}
if(interrupt_reset_counter_) {
interrupt_reset_counter_--;
if(!interrupt_reset_counter_) {
if(interrupt_counter_ < 32) {
interrupt_request_ = true;
}
interrupt_counter_ = 0;
}
}
interrupt_timer_.increment();
}
if(!was_vsync_ && state.vsync) {
interrupt_reset_counter_ = 2;
interrupt_timer_.signal_vsync();
}
was_vsync_ = state.vsync;
was_hsync_ = state.hsync;
}
bool get_interrupt_request() {
return interrupt_request_;
}
void reset_interrupt_request() {
interrupt_request_ = false;
interrupt_counter_ &= ~32;
}
void setup_output(float aspect_ratio) {
crt_.reset(new Outputs::CRT::CRT(1024, 16, Outputs::CRT::DisplayType::PAL50, 1));
crt_->set_rgb_sampling_function(
@ -226,10 +248,6 @@ class CRTCBusHandler {
}
}
void reset_interrupt_counter() {
interrupt_counter_ = 0;
}
private:
uint8_t mapped_palette_value(uint8_t colour) {
#define COL(r, g, b) (r << 4) | (g << 2) | b
@ -266,9 +284,7 @@ class CRTCBusHandler {
uint8_t palette_[16];
uint8_t border_;
int interrupt_counter_;
bool interrupt_request_;
int interrupt_reset_counter_;
InterruptTimer &interrupt_timer_;
};
struct KeyboardState {
@ -337,7 +353,7 @@ class ConcreteMachine:
ConcreteMachine() :
crtc_counter_(HalfCycles(4)), // This starts the CRTC exactly out of phase with the memory accesses
crtc_(crtc_bus_handler_),
crtc_bus_handler_(ram_),
crtc_bus_handler_(ram_, interrupt_timer_),
i8255_(i8255_port_handler_),
i8255_port_handler_(key_state_, crtc_bus_handler_) {
// primary clock is 4Mhz
@ -356,7 +372,7 @@ class ConcreteMachine:
crtc_counter_ += cycle.length;
int crtc_cycles = crtc_counter_.divide(HalfCycles(8)).as_int();
if(crtc_cycles) crtc_.run_for(Cycles(1));
set_interrupt_line(crtc_bus_handler_.get_interrupt_request());
set_interrupt_line(interrupt_timer_.get_request());
// Stop now if no action is strictly required.
if(!cycle.is_terminal()) return HalfCycles(0);
@ -381,7 +397,7 @@ class ConcreteMachine:
case 2:
read_pointers_[0] = (*cycle.value & 4) ? &ram_[0] : os_.data();
read_pointers_[3] = (*cycle.value & 8) ? &ram_[49152] : basic_.data();
if(*cycle.value & 15) crtc_bus_handler_.reset_interrupt_counter();
if(*cycle.value & 15) interrupt_timer_.reset_count();
crtc_bus_handler_.set_next_mode(*cycle.value & 3);
break;
case 3: printf("RAM paging?\n"); break;
@ -422,7 +438,7 @@ class ConcreteMachine:
case CPU::Z80::PartialMachineCycle::Interrupt:
*cycle.value = 0xff;
crtc_bus_handler_.reset_interrupt_request();
interrupt_timer_.reset_request();
break;
default: break;
@ -498,6 +514,8 @@ class ConcreteMachine:
i8255PortHandler i8255_port_handler_;
Intel::i8255::i8255<i8255PortHandler> i8255_;
InterruptTimer interrupt_timer_;
HalfCycles clock_offset_;
HalfCycles crtc_counter_;
HalfCycles half_cycles_since_ay_update_;