1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-02-16 18:30:32 +00:00

Break assumption that cycles = pixels; fix pixel clocking.

This commit is contained in:
Thomas Harte 2023-01-08 21:25:22 -05:00
parent 8cc20844a9
commit 794adf470b
3 changed files with 32 additions and 11 deletions

View File

@ -417,23 +417,25 @@ void TMS9918<personality>::run_for(const HalfCycles cycles) {
line_buffer.next_border_column, line_buffer.next_border_column,
if(!this->asked_for_write_area_) { if(!this->asked_for_write_area_) {
this->asked_for_write_area_ = true; this->asked_for_write_area_ = true;
// TODO: how many pixels across is this mode?
this->pixel_origin_ = this->pixel_target_ = reinterpret_cast<uint32_t *>( this->pixel_origin_ = this->pixel_target_ = reinterpret_cast<uint32_t *>(
this->crt_.begin_data(size_t(line_buffer.next_border_column - line_buffer.first_pixel_output_column)) this->crt_.begin_data(256)
); );
} }
if(this->pixel_target_) { if(this->pixel_target_) {
switch(line_buffer.line_mode) { switch(line_buffer.line_mode) {
case LineMode::SMS: draw(draw_sms(relative_start, relative_end, cram_value), to_tms_access_clock); break; case LineMode::SMS: draw(draw_sms(relative_start, relative_end, cram_value), to_tms_pixel_clock); break;
case LineMode::Character: draw(draw_tms_character(relative_start, relative_end), to_tms_access_clock); break; case LineMode::Character: draw(draw_tms_character(relative_start, relative_end), to_tms_pixel_clock); break;
case LineMode::Text: draw(draw_tms_text(relative_start, relative_end), to_tms_access_clock); break; case LineMode::Text: draw(draw_tms_text(relative_start, relative_end), to_tms_pixel_clock); break;
case LineMode::Refresh: break; /* Dealt with elsewhere. */ case LineMode::Refresh: break; /* Dealt with elsewhere. */
} }
} }
if(end == line_buffer.next_border_column) { if(end == line_buffer.next_border_column) {
const int length = line_buffer.next_border_column - line_buffer.first_pixel_output_column; const int length = 256;//line_buffer.next_border_column - line_buffer.first_pixel_output_column; // TODO: proper number of pixels, as above.
this->crt_.output_data(this->clock_converter_.to_crt_clock(length), size_t(length)); this->crt_.output_data(this->clock_converter_.to_crt_clock(length), size_t(length));
this->pixel_origin_ = this->pixel_target_ = nullptr; this->pixel_origin_ = this->pixel_target_ = nullptr;
this->asked_for_write_area_ = false; this->asked_for_write_area_ = false;
@ -713,7 +715,9 @@ HalfCycles TMS9918<personality>::get_next_sequence_point() const {
) % frame_length; ) % frame_length;
if(!time_until_frame_interrupt) time_until_frame_interrupt = frame_length; if(!time_until_frame_interrupt) time_until_frame_interrupt = frame_length;
if(!this->enable_line_interrupts_) return this->clock_converter_.half_cycles_before_internal_cycles(time_until_frame_interrupt); if(!this->enable_line_interrupts_) {
return this->clock_converter_.half_cycles_before_internal_cycles(time_until_frame_interrupt);
}
// Calculate when the next line interrupt will occur. // Calculate when the next line interrupt will occur.
int next_line_interrupt_row = -1; int next_line_interrupt_row = -1;

View File

@ -155,7 +155,7 @@ template <Personality personality> class ClockConverter {
case Personality::V9938: case Personality::V9938:
case Personality::V9958: case Personality::V9958:
return HalfCycles(internal_cycles / 3); return HalfCycles((internal_cycles + 2) / 3);
case Personality::MDVDP: case Personality::MDVDP:
return HalfCycles( return HalfCycles(
@ -166,8 +166,7 @@ template <Personality personality> class ClockConverter {
/*! /*!
Converts a position in internal cycles to its corresponding position Converts a position in internal cycles to its corresponding position
on the TMS memory-access clock, i.e. scales down to 171 clocks on the TMS memory-access clock, i.e. scales to 171 clocks per line.
per line
*/ */
static constexpr int to_tms_access_clock(int source) { static constexpr int to_tms_access_clock(int source) {
switch(personality) { switch(personality) {
@ -183,6 +182,24 @@ template <Personality personality> class ClockConverter {
} }
} }
/*!
Converts a position in internal cycles to its corresponding position
on the TMS pixel clock, i.e. scales to 342 clocks per line.
*/
static constexpr int to_tms_pixel_clock(int source) {
switch(personality) {
default:
return source;
case Personality::V9938:
case Personality::V9958:
return source >> 2;
case Personality::MDVDP:
return source / 10;
}
}
/*! /*!
Convers a position in internal cycles to its corresponding position Convers a position in internal cycles to its corresponding position
on the CRT's output clock, which [TODO] is clocked so that on the CRT's output clock, which [TODO] is clocked so that
@ -191,7 +208,7 @@ template <Personality personality> class ClockConverter {
static constexpr int to_crt_clock(int source) { static constexpr int to_crt_clock(int source) {
switch(personality) { switch(personality) {
default: default:
return source * 4; return source << 2;
case Personality::V9938: case Personality::V9938:
case Personality::V9958: case Personality::V9958:

View File

@ -743,7 +743,7 @@ class ConcreteMachine:
}; };
CPU::Z80::Processor<ConcreteMachine, false, false> z80_; CPU::Z80::Processor<ConcreteMachine, false, false> z80_;
JustInTimeActor<TI::TMS::TMS9918<TI::TMS::Personality::TMS9918A>> vdp_; JustInTimeActor<TI::TMS::TMS9918<TI::TMS::Personality::V9938>> vdp_;
Intel::i8255::i8255<i8255PortHandler> i8255_; Intel::i8255::i8255<i8255PortHandler> i8255_;
Concurrency::AsyncTaskQueue<false> audio_queue_; Concurrency::AsyncTaskQueue<false> audio_queue_;