From a617f7305adc85dd5dc4b4b157953ea44843a7d3 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 27 Dec 2023 16:15:52 -0500 Subject: [PATCH] Move personality into type. --- Components/6845/CRTC6845.hpp | 42 +++++++++++++++--------------- Machines/AmstradCPC/AmstradCPC.cpp | 7 +++-- Machines/PCCompatible/CGA.hpp | 7 +++-- Machines/PCCompatible/MDA.hpp | 7 +++-- 4 files changed, 36 insertions(+), 27 deletions(-) diff --git a/Components/6845/CRTC6845.hpp b/Components/6845/CRTC6845.hpp index 8c39cdbee..63ed6471e 100644 --- a/Components/6845/CRTC6845.hpp +++ b/Components/6845/CRTC6845.hpp @@ -46,19 +46,21 @@ class BusHandler { void perform_bus_cycle_phase2(const BusState &) {} }; -enum Personality { +enum class Personality { HD6845S, // Type 0 in CPC parlance. Zero-width HSYNC available, no status, programmable VSYNC length. // Considered exactly identical to the UM6845, so this enum covers both. UM6845R, // Type 1 in CPC parlance. Status register, fixed-length VSYNC. MC6845, // Type 2. No status register, fixed-length VSYNC, no zero-length HSYNC. - AMS40226 // Type 3. Status is get register, fixed-length VSYNC, no zero-length HSYNC. + AMS40226, // Type 3. Status is get register, fixed-length VSYNC, no zero-length HSYNC. + + EGA, // Extended EGA-style CRTC; uses 16-bit addressing throughout. }; // https://www.pcjs.org/blog/2018/03/20/ advises that "the behavior of bits 5 and 6 [of register 10, the cursor start // register is really card specific". // // This enum captures those specifics. -enum CursorType { +enum class CursorType { /// No cursor signal is generated. None, /// MDA style: 00 => symmetric blinking; 01 or 10 => no blinking; 11 => short on, long off. @@ -69,20 +71,19 @@ enum CursorType { // TODO UM6845R and R12/R13; see http://www.cpcwiki.eu/index.php/CRTC#CRTC_Differences -template class CRTC6845 { +template class CRTC6845 { public: - - CRTC6845(Personality p, T &bus_handler) noexcept : - personality_(p), bus_handler_(bus_handler), status_(0) {} + CRTC6845(BusHandlerT &bus_handler) noexcept : + bus_handler_(bus_handler), status_(0) {} void select_register(uint8_t r) { selected_register_ = r; } uint8_t get_status() { - switch(personality_) { - case UM6845R: return status_ | (bus_state_.vsync ? 0x20 : 0x00); - case AMS40226: return get_register(); + switch(personality) { + case Personality::UM6845R: return status_ | (bus_state_.vsync ? 0x20 : 0x00); + case Personality::AMS40226: return get_register(); default: return 0xff; } return 0xff; @@ -92,7 +93,7 @@ template class CRTC6845 { if(selected_register_ == 31) status_ &= ~0x80; if(selected_register_ == 16 || selected_register_ == 17) status_ &= ~0x40; - if(personality_ == UM6845R && selected_register_ == 31) return dummy_register_; + if(personality == Personality::UM6845R && selected_register_ == 31) return dummy_register_; if(selected_register_ < 12 || selected_register_ > 17) return 0xff; return registers_[selected_register_]; } @@ -104,7 +105,7 @@ template class CRTC6845 { }; // Per CPC documentation, skew doesn't work on a "type 1 or 2", i.e. an MC6845 or a UM6845R. - if(selected_register_ == 8 && personality_ != UM6845R && personality_ != MC6845) { + if(selected_register_ == 8 && personality != Personality::UM6845R && personality != Personality::MC6845) { switch((value >> 4)&3) { default: display_skew_mask_ = 1; break; case 1: display_skew_mask_ = 2; break; @@ -115,7 +116,7 @@ template class CRTC6845 { if(selected_register_ < 16) { registers_[selected_register_] = value & masks[selected_register_]; } - if(selected_register_ == 31 && personality_ == UM6845R) { + if(selected_register_ == 31 && personality == Personality::UM6845R) { dummy_register_ = value; } } @@ -162,9 +163,9 @@ template class CRTC6845 { // cancellation of the plan to perform sync if this is an HD6845S or UM6845R; otherwise zero // will end up counting as 16 as it won't be checked until after overflow. if(bus_state_.hsync) { - switch(personality_) { - case HD6845S: - case UM6845R: + switch(personality) { + case Personality::HD6845S: + case Personality::UM6845R: bus_state_.hsync = hsync_counter_ != (registers_[3] & 15); hsync_counter_ = (hsync_counter_ + 1) & 15; break; @@ -207,9 +208,9 @@ template class CRTC6845 { vsync_counter_ = (vsync_counter_ + 1) & 15; // On the UM6845R and AMS40226, honour the programmed vertical sync time; on the other CRTCs // always use a vertical sync count of 16. - switch(personality_) { - case HD6845S: - case AMS40226: + switch(personality) { + case Personality::HD6845S: + case Personality::AMS40226: bus_state_.vsync = vsync_counter_ != (registers_[3] >> 4); break; default: @@ -290,8 +291,7 @@ template class CRTC6845 { ++bus_state_.field_count; } - Personality personality_; - T &bus_handler_; + BusHandlerT &bus_handler_; BusState bus_state_; uint8_t registers_[18] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; diff --git a/Machines/AmstradCPC/AmstradCPC.cpp b/Machines/AmstradCPC/AmstradCPC.cpp index bb2d6d24b..60b2e048e 100644 --- a/Machines/AmstradCPC/AmstradCPC.cpp +++ b/Machines/AmstradCPC/AmstradCPC.cpp @@ -583,7 +583,10 @@ class CRTCBusHandler { InterruptTimer &interrupt_timer_; }; -using CRTC = Motorola::CRTC::CRTC6845; +using CRTC = Motorola::CRTC::CRTC6845< + CRTCBusHandler, + Motorola::CRTC::Personality::HD6845S, + Motorola::CRTC::CursorType::None>; /*! Holds and vends the current keyboard state, acting as the AY's port handler. @@ -766,7 +769,7 @@ template class ConcreteMachine: ConcreteMachine(const Analyser::Static::AmstradCPC::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) : z80_(*this), crtc_bus_handler_(ram_, interrupt_timer_), - crtc_(Motorola::CRTC::HD6845S, crtc_bus_handler_), + crtc_(crtc_bus_handler_), i8255_port_handler_(key_state_, crtc_, ay_, tape_player_), i8255_(i8255_port_handler_), tape_player_(8000000), diff --git a/Machines/PCCompatible/CGA.hpp b/Machines/PCCompatible/CGA.hpp index 4d0742b70..f2e82155f 100644 --- a/Machines/PCCompatible/CGA.hpp +++ b/Machines/PCCompatible/CGA.hpp @@ -17,7 +17,7 @@ namespace PCCompatible { class CGA { public: - CGA() : crtc_(Motorola::CRTC::Personality::HD6845S, outputter_) {} + CGA() : crtc_(outputter_) {} static constexpr uint32_t BaseAddress = 0xb'8000; static constexpr auto FontROM = ROM::Name::PCCompatibleCGAFont; @@ -439,7 +439,10 @@ class CGA { return (source & 0x10) ? bright(result) : yellow_to_brown(result); } } outputter_; - Motorola::CRTC::CRTC6845 crtc_; + Motorola::CRTC::CRTC6845< + CRTCOutputter, + Motorola::CRTC::Personality::HD6845S, + Motorola::CRTC::CursorType::MDA> crtc_; int full_clock_ = 0; diff --git a/Machines/PCCompatible/MDA.hpp b/Machines/PCCompatible/MDA.hpp index 72a0a5a36..cc48d26c7 100644 --- a/Machines/PCCompatible/MDA.hpp +++ b/Machines/PCCompatible/MDA.hpp @@ -17,7 +17,7 @@ namespace PCCompatible { class MDA { public: - MDA() : crtc_(Motorola::CRTC::Personality::HD6845S, outputter_) {} + MDA() : crtc_(outputter_) {} static constexpr uint32_t BaseAddress = 0xb'0000; static constexpr auto FontROM = ROM::Name::PCCompatibleMDAFont; @@ -226,7 +226,10 @@ class MDA { uint8_t control_ = 0; } outputter_; - Motorola::CRTC::CRTC6845 crtc_; + Motorola::CRTC::CRTC6845< + CRTCOutputter, + Motorola::CRTC::Personality::HD6845S, + Motorola::CRTC::CursorType::MDA> crtc_; int full_clock_ = 0; };