diff --git a/Components/68901/MFP68901.cpp b/Components/68901/MFP68901.cpp index 5466ad959..7d17b4dcb 100644 --- a/Components/68901/MFP68901.cpp +++ b/Components/68901/MFP68901.cpp @@ -123,11 +123,7 @@ void MFP68901::run_for(HalfCycles time) { --timers_[c].divisor; if(!timers_[c].divisor) { timers_[c].divisor = timers_[c].prescale; - - --timers_[c].value; - if(!timers_[c].value) { - // TODO: interrupt. - } + decrement_timer(c); } } } @@ -159,3 +155,19 @@ void MFP68901::set_timer_data(int timer, uint8_t value) { uint8_t MFP68901::get_timer_data(int timer) { return timers_[timer].value; } + +void MFP68901::set_timer_event_input(int channel, bool value) { + if(timers_[channel].event_input == value) return; + + timers_[channel].event_input = value; + if(timers_[channel].mode == TimerMode::EventCount && !value) { /* TODO: which edge is counted? "as defined by the associated Interrupt Channel’s edge bit"? */ + decrement_timer(channel); + } +} + +void MFP68901::decrement_timer(int timer) { + --timers_[timer].value; + if(!timers_[timer].value) { + // TODO: interrupt. Reload, possibly. + } +} diff --git a/Components/68901/MFP68901.hpp b/Components/68901/MFP68901.hpp index d94cc04c5..13d5f0b1c 100644 --- a/Components/68901/MFP68901.hpp +++ b/Components/68901/MFP68901.hpp @@ -23,6 +23,8 @@ class MFP68901 { void run_for(HalfCycles); HalfCycles get_next_sequence_point(); + void set_timer_event_input(int channel, bool value); + private: // MARK: - Timers enum class TimerMode { @@ -31,6 +33,7 @@ class MFP68901 { void set_timer_mode(int timer, TimerMode, int prescale, bool reset_timer); void set_timer_data(int timer, uint8_t); uint8_t get_timer_data(int timer); + void decrement_timer(int timer); struct Timer { TimerMode mode = TimerMode::Stopped; @@ -38,6 +41,7 @@ class MFP68901 { uint8_t reload_value = 0; int prescale = 1; int divisor = 0; + bool event_input = false; } timers_[4]; HalfCycles cycles_left_; diff --git a/Machines/AtariST/AtariST.cpp b/Machines/AtariST/AtariST.cpp index cfb29d714..d2bec7bbc 100644 --- a/Machines/AtariST/AtariST.cpp +++ b/Machines/AtariST/AtariST.cpp @@ -115,6 +115,8 @@ class ConcreteMachine: address %= rom_.size(); break; + case BusDevice::Unassigned: + // TODO: figure out the rules about bus errors. case BusDevice::Cartridge: /* TOS 1.0 appears to attempt to read from the catridge before it has setup @@ -131,10 +133,6 @@ class ConcreteMachine: } return HalfCycles(0); - case BusDevice::Unassigned: - assert(false); - return HalfCycles(0); - case BusDevice::IO: switch(address) { default: @@ -236,6 +234,39 @@ class ConcreteMachine: GPIP 0: centronics busy */ break; + + // Video controls. + case 0x7fc100: case 0x7fc101: case 0x7fc102: case 0x7fc103: + case 0x7fc104: case 0x7fc105: case 0x7fc106: case 0x7fc107: + case 0x7fc108: case 0x7fc109: case 0x7fc10a: case 0x7fc10b: + case 0x7fc10c: case 0x7fc10d: case 0x7fc10e: case 0x7fc10f: + case 0x7fc110: case 0x7fc111: case 0x7fc112: case 0x7fc113: + case 0x7fc114: case 0x7fc115: case 0x7fc116: case 0x7fc117: + case 0x7fc118: case 0x7fc119: case 0x7fc11a: case 0x7fc11b: + case 0x7fc11c: case 0x7fc11d: case 0x7fc11e: case 0x7fc11f: + case 0x7fc120: case 0x7fc121: case 0x7fc122: case 0x7fc123: + case 0x7fc124: case 0x7fc125: case 0x7fc126: case 0x7fc127: + case 0x7fc128: case 0x7fc129: case 0x7fc12a: case 0x7fc12b: + case 0x7fc12c: case 0x7fc12d: case 0x7fc12e: case 0x7fc12f: + case 0x7fc130: case 0x7fc131: + if(!cycle.data_select_active()) return HalfCycles(0); + + if(cycle.operation & Microcycle::Read) { + const uint8_t value = video_->read(int(address)); + if(cycle.operation & Microcycle::SelectByte) { + cycle.value->halves.low = value; + } else { + cycle.value->halves.high = value; + cycle.value->halves.low = 0xff; + } + } else { + if(cycle.operation & Microcycle::SelectByte) { + video_->write(int(address), cycle.value->halves.low); + } else { + video_->write(int(address), cycle.value->halves.high); + } + } + break; } return HalfCycles(0); } @@ -281,6 +312,8 @@ class ConcreteMachine: cycles_until_video_event_ = video_->get_next_sequence_point(); // TODO: push v/hsync/display_enable elsewhere. + mfp_->set_timer_event_input(1, video_->display_enabled()); +// printf("%c%c%c\n", video_->display_enabled() ? 'e' : '-', video_->hsync() ? 'h' : '-', video_->vsync() ? 'v' : '-'); } cycles_until_video_event_ -= length; video_ += length; diff --git a/Machines/AtariST/Video.cpp b/Machines/AtariST/Video.cpp index 976e8e5c6..99bf8efc1 100644 --- a/Machines/AtariST/Video.cpp +++ b/Machines/AtariST/Video.cpp @@ -8,6 +8,8 @@ #include "Video.hpp" +#include "../../Outputs/Log.hpp" + #include using namespace Atari::ST; @@ -66,6 +68,9 @@ void Video::run_for(HalfCycles duration) { x = target; \ } + // TODO: the below is **way off**. The real hardware does what you'd expect with ongoing state and + // exact equality tests. Fixes to come. + while(integer_duration) { const int final_x = std::min(x + integer_duration, mode_params.line_length); integer_duration -= (final_x - x); @@ -117,7 +122,7 @@ void Video::run_for(HalfCycles duration) { void Video::output_border(int duration) { uint16_t *colour_pointer = reinterpret_cast(crt_.begin_data(1)); - if(colour_pointer) *colour_pointer = 0x333; + if(colour_pointer) *colour_pointer = palette_[0]; crt_.output_level(duration); } @@ -178,3 +183,26 @@ HalfCycles Video::get_next_sequence_point() { return (cycles_until_vsync < cycles_until_display_enable) ? cycles_until_vsync : cycles_until_display_enable; } } + +// MARK: - IO dispatch + +uint8_t Video::read(int address) { + LOG("[Video] read " << (address & 0x3f)); + return 0xff; +} + +void Video::write(int address, uint8_t value) { + LOG("[Video] write " << PADHEX(2) << int(value) << " to " << PADHEX(2) << (address & 0x3f)); + address &= 0x3f; + switch(address) { + default: break; + + // Palette. + case 0x20: case 0x21: case 0x22: case 0x23: + case 0x24: case 0x25: case 0x26: case 0x27: + case 0x28: case 0x29: case 0x2a: case 0x2b: + case 0x2c: case 0x2d: case 0x2e: case 0x2f: + palette_[address - 0x20] = uint16_t((value & 0x777) << 5); + break; + } +} diff --git a/Machines/AtariST/Video.hpp b/Machines/AtariST/Video.hpp index d27dd5b3b..e825ff1da 100644 --- a/Machines/AtariST/Video.hpp +++ b/Machines/AtariST/Video.hpp @@ -39,9 +39,14 @@ class Video { bool vsync(); bool display_enabled(); + uint8_t read(int address); + void write(int address, uint8_t value); + private: Outputs::CRT::CRT crt_; + uint16_t palette_[16]; + int x = 0, y = 0; void output_border(int duration); };