mirror of
https://github.com/TomHarte/CLK.git
synced 2025-08-08 14:25:05 +00:00
Implement much of Yamaha line interrupts.
This commit is contained in:
@@ -37,6 +37,11 @@ Base<personality>::Base() :
|
|||||||
mode_timing_.end_of_frame_interrupt_position.row = 193;
|
mode_timing_.end_of_frame_interrupt_position.row = 193;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if constexpr (is_yamaha_vdp(personality)) {
|
||||||
|
// TODO: start of sync, or end of sync?
|
||||||
|
mode_timing_.line_interrupt_position = Timing<personality>::StartOfSync;
|
||||||
|
}
|
||||||
|
|
||||||
// Establish that output is delayed after reading by `output_lag` cycles; start
|
// Establish that output is delayed after reading by `output_lag` cycles; start
|
||||||
// at a random position.
|
// at a random position.
|
||||||
fetch_pointer_.row = rand() % 262;
|
fetch_pointer_.row = rand() % 262;
|
||||||
@@ -255,6 +260,12 @@ void TMS9918<personality>::run_for(const HalfCycles cycles) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if constexpr (is_yamaha_vdp(personality)) {
|
||||||
|
if(this->fetch_pointer_.row == this->line_interrupt_target_) {
|
||||||
|
this->line_interrupt_pending_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: the V9938 provides line interrupts from direct specification of the target line.
|
// TODO: the V9938 provides line interrupts from direct specification of the target line.
|
||||||
// So life is easy.
|
// So life is easy.
|
||||||
}
|
}
|
||||||
@@ -723,6 +734,7 @@ void Base<personality>::commit_register(int reg, uint8_t value) {
|
|||||||
(Storage<personality>::mode_ & 3) |
|
(Storage<personality>::mode_ & 3) |
|
||||||
((value & 0xe) << 1)
|
((value & 0xe) << 1)
|
||||||
);
|
);
|
||||||
|
enable_line_interrupts_ = value & 0x10;
|
||||||
|
|
||||||
LOG("TODO: Yamaha additional mode selection; " << PADHEX(2) << +value);
|
LOG("TODO: Yamaha additional mode selection; " << PADHEX(2) << +value);
|
||||||
// b1–b3: M3–M5
|
// b1–b3: M3–M5
|
||||||
@@ -819,7 +831,7 @@ void Base<personality>::commit_register(int reg, uint8_t value) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 19:
|
case 19:
|
||||||
LOG("TODO: Yamaha interrupt line; " << PADHEX(2) << +value);
|
line_interrupt_target_ = value;
|
||||||
// b0–b7: line to match for interrupts (if eabled)
|
// b0–b7: line to match for interrupts (if eabled)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1020,16 +1032,20 @@ uint8_t Base<personality>::read_register() {
|
|||||||
default:
|
default:
|
||||||
case 0: break;
|
case 0: break;
|
||||||
|
|
||||||
case 1:
|
case 1: {
|
||||||
// b7 = light pen; set when light is detected, reset on read;
|
// b7 = light pen; set when light is detected, reset on read;
|
||||||
// or: mouse button 2 currently down.
|
// or: mouse button 2 currently down.
|
||||||
// b6 = light pen button or mouse button 1.
|
// b6 = light pen button or mouse button 1.
|
||||||
// b5–b1 = VDP identification (1 = 9938; 2 = 9958)
|
// b5–b1 = VDP identification (1 = 9938; 2 = 9958)
|
||||||
// b0 = set when the VDP reaches the line provided in the line interrupt register.
|
// b0 = set when the VDP reaches the line provided in the line interrupt register.
|
||||||
// Reset upon read.
|
// Reset upon read.
|
||||||
return
|
const uint8_t result =
|
||||||
personality == Personality::V9938 ? 0x2 : 0x4;
|
(personality == Personality::V9938 ? 0x2 : 0x4) |
|
||||||
break;
|
(line_interrupt_pending_ ? 0x01 : 0x00);
|
||||||
|
|
||||||
|
line_interrupt_pending_ = false;
|
||||||
|
return result;
|
||||||
|
} break;
|
||||||
|
|
||||||
case 2: {
|
case 2: {
|
||||||
// b7 = transfer ready flag (i.e. VDP ready for next transfer)
|
// b7 = transfer ready flag (i.e. VDP ready for next transfer)
|
||||||
@@ -1189,6 +1205,10 @@ HalfCycles TMS9918<personality>::get_next_sequence_point() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if constexpr (is_yamaha_vdp(personality)) {
|
||||||
|
// TODO: time to next retrace interrupt.
|
||||||
|
}
|
||||||
|
|
||||||
// If there's actually no interrupt upcoming, despite being enabled, either return
|
// If there's actually no interrupt upcoming, despite being enabled, either return
|
||||||
// the frame end interrupt or no interrupt pending as appropriate.
|
// the frame end interrupt or no interrupt pending as appropriate.
|
||||||
if(next_line_interrupt_row == -1) {
|
if(next_line_interrupt_row == -1) {
|
||||||
|
Reference in New Issue
Block a user