1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 23:52:26 +00:00

Merge pull request #1153 from TomHarte/IIgsInterrupts

IIgS: abstract VGC interrupt register; fix clearing bug.
This commit is contained in:
Thomas Harte 2023-08-18 22:14:13 -04:00 committed by GitHub
commit 222f6e92fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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. // Post an interrupt if requested.
if(line_control_ & 0x40) { if(line_control_ & 0x40) {
set_interrupts(0x20); interrupts_.add(0x20);
} }
// Set up appropriately for fill mode (or not). // 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) { void Video::clear_interrupts(uint8_t mask) {
set_interrupts(interrupts_ & ~(mask & 0x60)); interrupts_.clear(mask);
} }
void Video::set_interrupt_register(uint8_t mask) { void Video::set_interrupt_register(uint8_t mask) {
set_interrupts(interrupts_ | (mask & 0x6)); interrupts_.set_control(mask);
} }
uint8_t Video::get_interrupt_register() { uint8_t Video::get_interrupt_register() {
return interrupts_; return interrupts_.status();
} }
bool Video::get_interrupt_line() { 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) { void Video::set_megaii_interrupts_enabled(uint8_t mask) {
@ -526,13 +526,7 @@ void Video::clear_megaii_interrupts() {
} }
void Video::notify_clock_tick() { void Video::notify_clock_tick() {
set_interrupts(interrupts_ | 0x40); interrupts_.add(0x40);
}
void Video::set_interrupts(uint8_t new_value) {
interrupts_ = new_value & 0x7f;
if((interrupts_ >> 4) & interrupts_ & 0x6)
interrupts_ |= 0x80;
} }
void Video::set_border_colour(uint8_t colour) { void Video::set_border_colour(uint8_t colour) {

View File

@ -123,8 +123,56 @@ class Video: public Apple::II::VideoSwitches<Cycles> {
void advance(Cycles); void advance(Cycles);
uint8_t new_video_ = 0x01; 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; int cycles_into_frame_ = 0;
const uint8_t *ram_ = nullptr; const uint8_t *ram_ = nullptr;