1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-09-30 22:56:03 +00:00

Abstract out VGC interrupt register; fix clearing bug.

This commit is contained in:
Thomas Harte 2023-08-18 14:30:40 -04:00
parent 3bd931937f
commit b34403164e
2 changed files with 56 additions and 14 deletions

View File

@ -285,7 +285,7 @@ void Video::output_row(int row, int start, int end) {
// Post an interrupt if requested.
if(line_control_ & 0x40) {
set_interrupts(0x20);
interrupts_.add(0x20);
}
// Set up appropriately for fill mode (or not).
@ -498,19 +498,19 @@ uint8_t Video::get_new_video() {
}
void Video::clear_interrupts(uint8_t mask) {
set_interrupts(interrupts_ & ~(mask & 0x60));
interrupts_.clear(mask);
}
void Video::set_interrupt_register(uint8_t mask) {
set_interrupts(interrupts_ | (mask & 0x6));
interrupts_.set_control(mask);
}
uint8_t Video::get_interrupt_register() {
return interrupts_;
return interrupts_.status();
}
bool Video::get_interrupt_line() {
return (interrupts_&0x80) || (megaii_interrupt_mask_&megaii_interrupt_state_);
return interrupts_.active() || (megaii_interrupt_mask_ & megaii_interrupt_state_);
}
void Video::set_megaii_interrupts_enabled(uint8_t mask) {
@ -526,13 +526,7 @@ void Video::clear_megaii_interrupts() {
}
void Video::notify_clock_tick() {
set_interrupts(interrupts_ | 0x40);
}
void Video::set_interrupts(uint8_t new_value) {
interrupts_ = new_value & 0x7f;
if((interrupts_ >> 4) & interrupts_ & 0x6)
interrupts_ |= 0x80;
interrupts_.add(0x40);
}
void Video::set_border_colour(uint8_t colour) {

View File

@ -123,8 +123,56 @@ class Video: public Apple::II::VideoSwitches<Cycles> {
void advance(Cycles);
uint8_t new_video_ = 0x01;
uint8_t interrupts_ = 0x00;
void set_interrupts(uint8_t);
class Interrupts {
public:
void add(uint8_t value) {
// Taken literally, status accumulates regardless of being enabled,
// potentially to be polled, it simply doesn't trigger an interrupt.
value_ |= value;
test();
}
void clear(uint8_t value) {
// Zeroes in bits 5 or 6 clear the respective interrupts.
value_ &= value | ~0x60;
test();
}
void set_control(uint8_t value) {
// Ones in bits 1 or 2 enable the respective interrupts.
value_ = (value_ & ~0x6) | (value & 0x6);
test();
}
uint8_t status() const {
return value_;
}
bool active() const {
return value_ & 0x80;
}
private:
void test() {
value_ &= 0x7f;
if((value_ >> 4) & value_ & 0x6) {
value_ |= 0x80;
}
}
// Overall meaning of value is as per the VGC interrupt register, i.e.
//
// b7: interrupt status;
// b6: 1-second interrupt status;
// b5: scan-line interrupt status;
// b4: reserved;
// b3: reserved;
// b2: 1-second interrupt enable;
// b1: scan-line interrupt enable;
// b0: reserved.
uint8_t value_ = 0x00;
} interrupts_;
int cycles_into_frame_ = 0;
const uint8_t *ram_ = nullptr;