diff --git a/Components/9918/9918.cpp b/Components/9918/9918.cpp index 33fcfe0c0..50ab24e15 100644 --- a/Components/9918/9918.cpp +++ b/Components/9918/9918.cpp @@ -110,7 +110,8 @@ Base::Base(Personality p) : write_pointer_.column = read_pointer_.column + output_lag; } -TMS9918::TMS9918(Personality p): +template +TMS9918::TMS9918(Personality p): Base(p) { crt_.set_display_type(Outputs::Display::DisplayType::RGB); crt_.set_visible_area(Outputs::Display::Rect(0.07f, 0.0375f, 0.875f, 0.875f)); @@ -122,7 +123,8 @@ TMS9918::TMS9918(Personality p): crt_.set_immediate_default_phase(0.85f); } -void TMS9918::set_tv_standard(TVStandard standard) { +template +void TMS9918::set_tv_standard(TVStandard standard) { tv_standard_ = standard; switch(standard) { case TVStandard::PAL: @@ -138,11 +140,13 @@ void TMS9918::set_tv_standard(TVStandard standard) { } } -void TMS9918::set_scan_target(Outputs::Display::ScanTarget *scan_target) { +template +void TMS9918::set_scan_target(Outputs::Display::ScanTarget *scan_target) { crt_.set_scan_target(scan_target); } -Outputs::Display::ScanStatus TMS9918::get_scaled_scan_status() const { +template +Outputs::Display::ScanStatus TMS9918::get_scaled_scan_status() const { // The input was scaled by 3/4 to convert half cycles to internal ticks, // so undo that and also allow for: (i) the multiply by 4 that it takes // to reach the CRT; and (ii) the fact that the half-cycles value was scaled, @@ -150,11 +154,13 @@ Outputs::Display::ScanStatus TMS9918::get_scaled_scan_status() const { return crt_.get_scaled_scan_status() * (4.0f / (3.0f * 8.0f)); } -void TMS9918::set_display_type(Outputs::Display::DisplayType display_type) { +template +void TMS9918::set_display_type(Outputs::Display::DisplayType display_type) { crt_.set_display_type(display_type); } -Outputs::Display::DisplayType TMS9918::get_display_type() const { +template +Outputs::Display::DisplayType TMS9918::get_display_type() const { return crt_.get_display_type(); } @@ -193,7 +199,8 @@ void Base::posit_sprite(LineBuffer &buffer, int sprite_number, int sprite_positi ++buffer.active_sprite_slot; } -void TMS9918::run_for(const HalfCycles cycles) { +template +void TMS9918::run_for(const HalfCycles cycles) { // As specific as I've been able to get: // Scanline time is always 228 cycles. // PAL output is 313 lines total. NTSC output is 262 lines total. @@ -532,7 +539,8 @@ void Base::output_border(int cycles, uint32_t cram_dot) { } } -void TMS9918::write(int address, uint8_t value) { +template +void TMS9918::write(int address, uint8_t value) { // Writes to address 0 are writes to the video RAM. Store // the value and return. if(!(address & 1)) { @@ -662,7 +670,8 @@ void TMS9918::write(int address, uint8_t value) { } } -uint8_t TMS9918::get_current_line() { +template +uint8_t TMS9918::get_current_line() { // Determine the row to return. constexpr int row_change_position = 63; // This is the proper Master System value; substitute if any other VDPs turn out to have this functionality. int source_row = @@ -696,7 +705,8 @@ uint8_t TMS9918::get_current_line() { return uint8_t(source_row); } -uint8_t TMS9918::get_latched_horizontal_counter() { +template +uint8_t TMS9918::get_latched_horizontal_counter() { // Translate from internal numbering, which puts pixel output // in the final 256 pixels of 342, to the public numbering, // which makes the 256 pixels the first 256 spots, but starts @@ -706,11 +716,13 @@ uint8_t TMS9918::get_latched_horizontal_counter() { return uint8_t(public_counter >> 1); } -void TMS9918::latch_horizontal_counter() { +template +void TMS9918::latch_horizontal_counter() { latched_column_ = write_pointer_.column; } -uint8_t TMS9918::read(int address) { +template +uint8_t TMS9918::read(int address) { write_phase_ = false; // Reads from address 0 read video RAM, via the read-ahead buffer. @@ -732,7 +744,8 @@ HalfCycles Base::half_cycles_before_internal_cycles(int internal_cycles) { return HalfCycles(((internal_cycles << 2) + (2 - cycles_error_)) / 3); } -HalfCycles TMS9918::get_next_sequence_point() { +template +HalfCycles TMS9918::get_next_sequence_point() { if(!generate_interrupts_ && !enable_line_interrupts_) return HalfCycles::max(); if(get_interrupt_line()) return HalfCycles::max(); @@ -786,7 +799,8 @@ HalfCycles TMS9918::get_next_sequence_point() { return half_cycles_before_internal_cycles(std::min(local_cycles_until_line_interrupt, time_until_frame_interrupt)); } -HalfCycles TMS9918::get_time_until_line(int line) { +template +HalfCycles TMS9918::get_time_until_line(int line) { if(line < 0) line += mode_timing_.total_lines; int cycles_to_next_interrupt_threshold = mode_timing_.line_interrupt_position - write_pointer_.column; @@ -803,7 +817,8 @@ HalfCycles TMS9918::get_time_until_line(int line) { return half_cycles_before_internal_cycles(cycles_to_next_interrupt_threshold + (line - line_of_next_interrupt_threshold)*342); } -bool TMS9918::get_interrupt_line() { +template +bool TMS9918::get_interrupt_line() { return ((status_ & StatusInterrupt) && generate_interrupts_) || (enable_line_interrupts_ && line_interrupt_pending_); } @@ -1074,3 +1089,11 @@ void Base::draw_sms(int start, int end, uint32_t cram_dot) { } } } + +template class TI::TMS::TMS9918; +template class TI::TMS::TMS9918; +template class TI::TMS::TMS9918; +template class TI::TMS::TMS9918; +template class TI::TMS::TMS9918; +template class TI::TMS::TMS9918; +template class TI::TMS::TMS9918; diff --git a/Components/9918/9918.hpp b/Components/9918/9918.hpp index c019077c2..fe885d4b6 100644 --- a/Components/9918/9918.hpp +++ b/Components/9918/9918.hpp @@ -48,7 +48,7 @@ namespace TMS { These chips have only one non-on-demand interaction with the outside world: an interrupt line. See get_time_until_interrupt and get_interrupt_line for asynchronous operation options. */ -class TMS9918: public Base { +template class TMS9918: public Base { public: /*! Constructs an instance of the drive controller that behaves according to personality @c p. diff --git a/Machines/ColecoVision/ColecoVision.cpp b/Machines/ColecoVision/ColecoVision.cpp index 2138528a9..1b6cec505 100644 --- a/Machines/ColecoVision/ColecoVision.cpp +++ b/Machines/ColecoVision/ColecoVision.cpp @@ -379,7 +379,7 @@ class ConcreteMachine: } CPU::Z80::Processor z80_; - JustInTimeActor vdp_; + JustInTimeActor> vdp_; Concurrency::AsyncTaskQueue audio_queue_; TI::SN76489 sn76489_; diff --git a/Machines/MSX/MSX.cpp b/Machines/MSX/MSX.cpp index 88e879601..16752fdcf 100644 --- a/Machines/MSX/MSX.cpp +++ b/Machines/MSX/MSX.cpp @@ -744,7 +744,7 @@ class ConcreteMachine: }; CPU::Z80::Processor z80_; - JustInTimeActor vdp_; + JustInTimeActor> vdp_; Intel::i8255::i8255 i8255_; Concurrency::AsyncTaskQueue audio_queue_; diff --git a/Machines/MasterSystem/MasterSystem.cpp b/Machines/MasterSystem/MasterSystem.cpp index da26f9775..5b233b7a2 100644 --- a/Machines/MasterSystem/MasterSystem.cpp +++ b/Machines/MasterSystem/MasterSystem.cpp @@ -431,6 +431,7 @@ class ConcreteMachine: } private: + // TODO: incorporate this into the VDP declaration. static TI::TMS::Personality tms_personality_for_model(Analyser::Static::Sega::Target::Model model) { switch(model) { default: @@ -485,7 +486,7 @@ class ConcreteMachine: const Target::Region region_; const Target::PagingScheme paging_scheme_; CPU::Z80::Processor z80_; - JustInTimeActor vdp_; + JustInTimeActor> vdp_; // TODO. Concurrency::AsyncTaskQueue audio_queue_; TI::SN76489 sn76489_;