diff --git a/Components/9918/9918.cpp b/Components/9918/9918.cpp index 7343aebf9..ec90b91c3 100644 --- a/Components/9918/9918.cpp +++ b/Components/9918/9918.cpp @@ -486,7 +486,7 @@ void TMS9918::set_register(int address, uint8_t value) { case 10: if(is_sega_vdp(personality_)) { - line_interrupt_target = value; + line_interrupt_target = low_write_; } break; @@ -559,8 +559,12 @@ uint8_t TMS9918::get_register(int address) { return generate_interrupts_ ? time_until_frame_interrupt : HalfCycles(-1); } - // Figure out the number of internal cycles until the next line interrupt. - int local_cycles_until_line_interrupt = ((mode_timing_.line_interrupt_position - column_ + 342) % 342) + (next_line_interrupt_row - row_) * 342; + // Figure out the number of internal cycles until the next line interrupt, which is the amount + // of time to the next tick over and then next_line_interrupt_row - row_ lines further. + int local_cycles_until_next_tick = (mode_timing_.line_interrupt_position - column_ + 342) % 342; + if(!local_cycles_until_next_tick) local_cycles_until_next_tick += 342; + + int local_cycles_until_line_interrupt = local_cycles_until_next_tick + (next_line_interrupt_row - row_) * 342; local_cycles_until_line_interrupt <<= 2; local_cycles_until_line_interrupt -= cycles_error_; diff --git a/OSBindings/Mac/Clock SignalTests/MasterSystemVDPTests.mm b/OSBindings/Mac/Clock SignalTests/MasterSystemVDPTests.mm index 0047ac20b..ec5c36587 100644 --- a/OSBindings/Mac/Clock SignalTests/MasterSystemVDPTests.mm +++ b/OSBindings/Mac/Clock SignalTests/MasterSystemVDPTests.mm @@ -59,11 +59,24 @@ // Check interrupt flag isn't set prior to the reported time. vdp.run_for(HalfCycles(time_until_interrupt)); - NSAssert(!vdp.get_interrupt_line(), @"Interrupt line went active early"); + NSAssert(!vdp.get_interrupt_line(), @"Interrupt line went active early [1]"); // Check interrupt flag is set at the reported time. vdp.run_for(HalfCycles(1)); - NSAssert(vdp.get_interrupt_line(), @"Interrupt line wasn't set when promised"); + NSAssert(vdp.get_interrupt_line(), @"Interrupt line wasn't set when promised [1]"); + + // Read the status register to clear interrupt status. + vdp.get_register(1); + NSAssert(!vdp.get_interrupt_line(), @"Interrupt wasn't reset by status read"); + + // Check interrupt flag isn't set prior to the reported time. + time_until_interrupt = vdp.get_time_until_interrupt().as_int() - 1; + vdp.run_for(HalfCycles(time_until_interrupt)); + NSAssert(!vdp.get_interrupt_line(), @"Interrupt line went active early [2]"); + + // Check interrupt flag is set at the reported time. + vdp.run_for(HalfCycles(1)); + NSAssert(vdp.get_interrupt_line(), @"Interrupt line wasn't set when promised [2]"); } @end