From 22b4b4d4e30b740e54c3913a05c9e6453eaed696 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Tue, 9 Jan 2024 22:03:24 -0500 Subject: [PATCH] Switch to named values for everything except blink mode. --- Components/6845/CRTC6845.hpp | 54 ++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/Components/6845/CRTC6845.hpp b/Components/6845/CRTC6845.hpp index 24c30f2c1..77f7e72c7 100644 --- a/Components/6845/CRTC6845.hpp +++ b/Components/6845/CRTC6845.hpp @@ -105,6 +105,14 @@ template cl void set_register(uint8_t value) { static constexpr bool is_ega = is_egavga(personality); + auto load_low = [value](uint16_t &target) { + target = (target & 0xff00) | value; + }; + auto load_high = [value](uint16_t &target) { + constexpr uint8_t mask = RefreshMask >> 8; + target = uint16_t((target & 0x00ff) | ((value & mask) << 8)); + }; + switch(selected_register_) { case 0: layout_.horizontal.total = value; break; case 1: layout_.horizontal.displayed = value; break; @@ -127,6 +135,25 @@ template cl case 5: layout_.vertical.adjust = value & 0x1f; break; case 6: layout_.vertical.displayed = value & 0x7f; break; case 7: layout_.vertical.start_sync = value & 0x7f; break; + case 8: + switch(value & 3) { + default: layout_.interlace_mode_ = InterlaceMode::Off; break; + case 0b01: layout_.interlace_mode_ = InterlaceMode::InterlaceSync; break; + case 0b11: layout_.interlace_mode_ = InterlaceMode::InterlaceSyncAndVideo; break; + } + break; + case 9: layout_.vertical.end_row = value & 0x1f; break; + case 10: + layout_.vertical.start_cursor = value & 0x1f; + // TODO: blink mode. + break; + case 11: + layout_.vertical.end_cursor = value & 0x1f; + break; + case 12: load_high(layout_.start_address); break; + case 13: load_low(layout_.start_address); break; + case 14: load_high(layout_.cursor_address); break; + case 15: load_low(layout_.cursor_address); break; } static constexpr uint8_t masks[] = { @@ -181,7 +208,7 @@ template cl bus_state_.refresh_address = (bus_state_.refresh_address + 1) & RefreshMask; bus_state_.cursor = is_cursor_line_ && - bus_state_.refresh_address == (registers_[15] | (registers_[14] << 8)); + bus_state_.refresh_address == layout_.cursor_address; // Check for end-of-line. if(character_counter_ == layout_.horizontal.total) { @@ -242,7 +269,7 @@ template cl if constexpr (cursor_type != CursorType::None) { // Check for cursor disable. // TODO: this is handled differently on the EGA, should I ever implement that. - is_cursor_line_ &= bus_state_.row_address != (registers_[11] & 0x1f); + is_cursor_line_ &= bus_state_.row_address != layout_.vertical.end_cursor; } // Check for end of vertical sync. @@ -269,7 +296,7 @@ template cl } } else { // Advance vertical counter. - if(bus_state_.row_address == registers_[9]) { + if(bus_state_.row_address == layout_.vertical.end_row) { bus_state_.row_address = 0; line_address_ = end_of_line_address_; @@ -306,7 +333,7 @@ template cl if constexpr (cursor_type != CursorType::None) { // Check for cursor enable. - is_cursor_line_ |= bus_state_.row_address == (registers_[10] & 0x1f); + is_cursor_line_ |= bus_state_.row_address == layout_.vertical.start_cursor; switch(cursor_type) { // MDA-style blinking. @@ -328,7 +355,7 @@ template cl inline void do_end_of_frame() { line_counter_ = 0; line_is_visible_ = true; - line_address_ = uint16_t((registers_[12] << 8) | registers_[13]); + line_address_ = layout_.start_address; bus_state_.refresh_address = line_address_; ++bus_state_.field_count; } @@ -336,6 +363,14 @@ template cl BusHandlerT &bus_handler_; BusState bus_state_; + enum class InterlaceMode { + Off, + InterlaceSync, + InterlaceSyncAndVideo, + }; + enum class BlinkMode { + // TODO. + }; struct { struct { uint8_t total; @@ -350,7 +385,16 @@ template cl uint8_t start_sync; uint8_t sync_lines; uint8_t adjust; + + uint8_t end_row; + uint8_t start_cursor; + uint8_t end_cursor; } vertical; + + InterlaceMode interlace_mode_ = InterlaceMode::Off; + uint16_t start_address; + uint16_t cursor_address; + uint16_t light_pen_address; } layout_; uint8_t registers_[18]{};