mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-25 16:31:42 +00:00
Seeks to introduce MSX interrupts.
This commit is contained in:
parent
69ec8a362e
commit
aa4eef41d8
@ -66,11 +66,15 @@ void TMS9918::run_for(const HalfCycles cycles) {
|
||||
// PAL output is 313 lines total. NTSC output is 262 lines total.
|
||||
// Interrupt is signalled upon entering the lower border.
|
||||
|
||||
// Keep a count of cycles separate from internal counts to avoid
|
||||
// potential errors mapping back and forth.
|
||||
half_cycles_into_frame_ = (half_cycles_into_frame_ + cycles) % HalfCycles(frame_lines_ * 228 * 2);
|
||||
|
||||
// Convert to 342 cycles per line; the internal clock is 1.5 times the
|
||||
// nominal 3.579545 Mhz that I've advertised for this part.
|
||||
int int_cycles = (cycles.as_int() * 3) + cycles_error_;
|
||||
cycles_error_ = int_cycles & 3;
|
||||
int_cycles >>= 2;
|
||||
cycles_error_ = int_cycles & 7;
|
||||
int_cycles >>= 3;
|
||||
if(!int_cycles) return;
|
||||
|
||||
//
|
||||
@ -296,3 +300,16 @@ uint8_t TMS9918::get_register(int address) {
|
||||
void TMS9918::reevaluate_interrupts() {
|
||||
|
||||
}
|
||||
|
||||
HalfCycles TMS9918::get_time_until_interrupt() {
|
||||
if(!generate_interrupts_) return HalfCycles(-1);
|
||||
if(get_interrupt_line()) return HalfCycles(-1);
|
||||
|
||||
const int half_cycles_per_frame = frame_lines_ * 228 * 2;
|
||||
int half_cycles_remaining = (192 * 228 * 2 + half_cycles_per_frame - half_cycles_into_frame_.as_int()) % half_cycles_per_frame;
|
||||
return HalfCycles(half_cycles_remaining);
|
||||
}
|
||||
|
||||
bool TMS9918::get_interrupt_line() {
|
||||
return (status_ & 0x80) && generate_interrupts_;
|
||||
}
|
||||
|
@ -44,6 +44,9 @@ class TMS9918 {
|
||||
void set_register(int address, uint8_t value);
|
||||
uint8_t get_register(int address);
|
||||
|
||||
HalfCycles get_time_until_interrupt();
|
||||
bool get_interrupt_line();
|
||||
|
||||
private:
|
||||
std::shared_ptr<Outputs::CRT::CRT> crt_;
|
||||
|
||||
@ -73,6 +76,7 @@ class TMS9918 {
|
||||
|
||||
void reevaluate_interrupts();
|
||||
|
||||
HalfCycles half_cycles_into_frame_;
|
||||
int column_ = 0, row_ = 0, output_column_ = 0;
|
||||
int cycles_error_ = 0;
|
||||
uint32_t *pixel_target_ = nullptr;
|
||||
@ -93,7 +97,7 @@ class TMS9918 {
|
||||
uint8_t pattern_buffer_[40];
|
||||
uint8_t colour_buffer_[32];
|
||||
int access_pointer_ = 0;
|
||||
uint8_t pattern_name_;
|
||||
uint8_t pattern_name_ = 0;
|
||||
};
|
||||
|
||||
};
|
||||
|
@ -20,7 +20,15 @@
|
||||
|
||||
namespace MSX {
|
||||
|
||||
class AYPortHandler: public GI::AY38910::PortHandler {
|
||||
struct AYPortHandler: public GI::AY38910::PortHandler {
|
||||
void set_port_output(bool port_b, uint8_t value) {
|
||||
printf("AY port %c output: %02x\n", port_b ? 'b' : 'a', value);
|
||||
}
|
||||
|
||||
uint8_t get_port_input(bool port_b) {
|
||||
printf("AY port %c input\n", port_b ? 'b' : 'a');
|
||||
return 0xff;
|
||||
}
|
||||
};
|
||||
|
||||
class ConcreteMachine:
|
||||
@ -65,6 +73,7 @@ class ConcreteMachine:
|
||||
}
|
||||
|
||||
void page_memory(uint8_t value) {
|
||||
printf("Page %02x\n", value);
|
||||
for(int c = 0; c < 4; ++c) {
|
||||
read_pointers_[c] = unpopulated_;
|
||||
write_pointers_[c] = scratch_;
|
||||
@ -87,6 +96,13 @@ class ConcreteMachine:
|
||||
}
|
||||
|
||||
HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) {
|
||||
if(time_until_interrupt_ > 0) {
|
||||
time_until_interrupt_ -= cycle.length;
|
||||
if(time_until_interrupt_ <= HalfCycles(0)) {
|
||||
z80_.set_interrupt_line(true, time_until_interrupt_);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t address = cycle.address ? *cycle.address : 0x0000;
|
||||
switch(cycle.operation) {
|
||||
case CPU::Z80::PartialMachineCycle::ReadOpcode:
|
||||
@ -104,6 +120,8 @@ class ConcreteMachine:
|
||||
vdp_->run_for(time_since_vdp_update_);
|
||||
time_since_vdp_update_ = 0;
|
||||
*cycle.value = vdp_->get_register(address);
|
||||
z80_.set_interrupt_line(vdp_->get_interrupt_line());
|
||||
time_until_interrupt_ = vdp_->get_time_until_interrupt();
|
||||
break;
|
||||
|
||||
case 0xa2:
|
||||
@ -124,6 +142,8 @@ class ConcreteMachine:
|
||||
vdp_->run_for(time_since_vdp_update_);
|
||||
time_since_vdp_update_ = 0;
|
||||
vdp_->set_register(address, *cycle.value);
|
||||
z80_.set_interrupt_line(vdp_->get_interrupt_line());
|
||||
time_until_interrupt_ = vdp_->get_time_until_interrupt();
|
||||
break;
|
||||
|
||||
case 0xa0:
|
||||
@ -205,7 +225,7 @@ class ConcreteMachine:
|
||||
uint8_t get_value(int port) {
|
||||
if(port == 1) {
|
||||
printf("?? Read keyboard\n");
|
||||
}
|
||||
} else printf("What what?\n");
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
@ -229,6 +249,7 @@ class ConcreteMachine:
|
||||
std::vector<uint8_t> basic_, main_;
|
||||
|
||||
HalfCycles time_since_vdp_update_;
|
||||
HalfCycles time_until_interrupt_;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user