mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 23:52:26 +00:00
Adds a first attempt at CRAM dot output. With a TODO.
This commit is contained in:
parent
916710353a
commit
521d603902
@ -93,7 +93,6 @@ TMS9918::TMS9918(Personality p):
|
|||||||
"}");
|
"}");
|
||||||
crt_->set_video_signal(Outputs::CRT::VideoSignal::RGB);
|
crt_->set_video_signal(Outputs::CRT::VideoSignal::RGB);
|
||||||
crt_->set_visible_area(Outputs::CRT::Rect(0.055f, 0.025f, 0.9f, 0.9f));
|
crt_->set_visible_area(Outputs::CRT::Rect(0.055f, 0.025f, 0.9f, 0.9f));
|
||||||
crt_->set_input_gamma(2.8f);
|
|
||||||
|
|
||||||
// The TMS remains in-phase with the NTSC colour clock; this is an empirical measurement
|
// The TMS remains in-phase with the NTSC colour clock; this is an empirical measurement
|
||||||
// intended to produce the correct relationship between the hard edges between pixels and
|
// intended to produce the correct relationship between the hard edges between pixels and
|
||||||
@ -321,16 +320,31 @@ void TMS9918::run_for(const HalfCycles cycles) {
|
|||||||
|
|
||||||
if(read_cycles_pool) {
|
if(read_cycles_pool) {
|
||||||
// Determine how much time has passed in the remainder of this line, and proceed.
|
// Determine how much time has passed in the remainder of this line, and proceed.
|
||||||
const int read_cycles = std::min(342 - read_pointer_.column, read_cycles_pool);
|
const int target_read_cycles = std::min(342 - read_pointer_.column, read_cycles_pool);
|
||||||
|
int read_cycles_performed = 0;
|
||||||
|
uint32_t next_cram_value = 0;
|
||||||
|
|
||||||
|
while(read_cycles_performed < target_read_cycles) {
|
||||||
|
const uint32_t cram_value = next_cram_value;
|
||||||
|
next_cram_value = 0;
|
||||||
|
int read_cycles = target_read_cycles - read_cycles_performed;
|
||||||
|
if(!upcoming_cram_dots_.empty() && upcoming_cram_dots_.front().location.row == read_pointer_.row) {
|
||||||
|
int time_until_dot = upcoming_cram_dots_.front().location.column - read_pointer_.column;
|
||||||
|
|
||||||
|
if(time_until_dot < read_cycles) {
|
||||||
|
read_cycles = time_until_dot;
|
||||||
|
next_cram_value = upcoming_cram_dots_.front().value;
|
||||||
|
upcoming_cram_dots_.erase(upcoming_cram_dots_.begin());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!read_cycles) continue;
|
||||||
|
read_cycles_performed += read_cycles;
|
||||||
|
|
||||||
const int end_column = read_pointer_.column + read_cycles;
|
const int end_column = read_pointer_.column + read_cycles;
|
||||||
LineBuffer &line_buffer = line_buffers_[read_pointer_.row];
|
LineBuffer &line_buffer = line_buffers_[read_pointer_.row];
|
||||||
|
|
||||||
|
|
||||||
// TODO: actually perform these dots, at least in part by further subdividing
|
|
||||||
// the period to run for.
|
|
||||||
upcoming_cram_dots_.clear();
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------
|
// --------------------
|
||||||
// Output video stream.
|
// Output video stream.
|
||||||
// --------------------
|
// --------------------
|
||||||
@ -344,7 +358,7 @@ void TMS9918::run_for(const HalfCycles cycles) {
|
|||||||
}\
|
}\
|
||||||
}
|
}
|
||||||
|
|
||||||
#define border(left, right) intersect(left, right, output_border(end - start))
|
#define border(left, right) intersect(left, right, output_border(end - start, cram_value))
|
||||||
|
|
||||||
if(line_buffer.line_mode == LineMode::Refresh || read_pointer_.row > mode_timing_.pixel_lines) {
|
if(line_buffer.line_mode == LineMode::Refresh || read_pointer_.row > mode_timing_.pixel_lines) {
|
||||||
if(read_pointer_.row >= mode_timing_.first_vsync_line && read_pointer_.row < mode_timing_.first_vsync_line+4) {
|
if(read_pointer_.row >= mode_timing_.first_vsync_line && read_pointer_.row < mode_timing_.first_vsync_line+4) {
|
||||||
@ -401,7 +415,7 @@ void TMS9918::run_for(const HalfCycles cycles) {
|
|||||||
const int relative_start = start - line_buffer.first_pixel_output_column;
|
const int relative_start = start - line_buffer.first_pixel_output_column;
|
||||||
const int relative_end = end - line_buffer.first_pixel_output_column;
|
const int relative_end = end - line_buffer.first_pixel_output_column;
|
||||||
switch(line_buffer.line_mode) {
|
switch(line_buffer.line_mode) {
|
||||||
case LineMode::SMS: draw_sms(relative_start, relative_end, 0); break;
|
case LineMode::SMS: draw_sms(relative_start, relative_end, cram_value); break;
|
||||||
case LineMode::Character: draw_tms_character(relative_start, relative_end); break;
|
case LineMode::Character: draw_tms_character(relative_start, relative_end); break;
|
||||||
case LineMode::Text: draw_tms_text(relative_start, relative_end); break;
|
case LineMode::Text: draw_tms_text(relative_start, relative_end); break;
|
||||||
|
|
||||||
@ -432,8 +446,9 @@ void TMS9918::run_for(const HalfCycles cycles) {
|
|||||||
// Advance time.
|
// Advance time.
|
||||||
// -------------
|
// -------------
|
||||||
read_pointer_.column = end_column;
|
read_pointer_.column = end_column;
|
||||||
read_cycles_pool -= read_cycles;
|
}
|
||||||
|
|
||||||
|
read_cycles_pool -= target_read_cycles;
|
||||||
if(read_pointer_.column == 342) {
|
if(read_pointer_.column == 342) {
|
||||||
read_pointer_.column = 0;
|
read_pointer_.column = 0;
|
||||||
read_pointer_.row = (read_pointer_.row + 1) % mode_timing_.total_lines;
|
read_pointer_.row = (read_pointer_.row + 1) % mode_timing_.total_lines;
|
||||||
@ -444,16 +459,25 @@ void TMS9918::run_for(const HalfCycles cycles) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Base::output_border(int cycles) {
|
void Base::output_border(int cycles, uint32_t cram_dot) {
|
||||||
|
cycles *= 4;
|
||||||
|
uint32_t border_colour =
|
||||||
|
is_sega_vdp(personality_) ?
|
||||||
|
master_system_.colour_ram[16 + background_colour_] :
|
||||||
|
palette[background_colour_];
|
||||||
|
|
||||||
|
if(cram_dot) {
|
||||||
uint32_t *const pixel_target = reinterpret_cast<uint32_t *>(crt_->allocate_write_area(1));
|
uint32_t *const pixel_target = reinterpret_cast<uint32_t *>(crt_->allocate_write_area(1));
|
||||||
if(pixel_target) {
|
*pixel_target = border_colour | cram_dot;
|
||||||
if(is_sega_vdp(personality_)) {
|
crt_->output_level(4);
|
||||||
*pixel_target = master_system_.colour_ram[16 + background_colour_];
|
cycles -= 4;
|
||||||
} else {
|
|
||||||
*pixel_target = palette[background_colour_];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(cycles) {
|
||||||
|
uint32_t *const pixel_target = reinterpret_cast<uint32_t *>(crt_->allocate_write_area(1));
|
||||||
|
*pixel_target = border_colour;
|
||||||
|
crt_->output_level(static_cast<unsigned int>(cycles));
|
||||||
}
|
}
|
||||||
crt_->output_level(static_cast<unsigned int>(cycles) * 4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TMS9918::set_register(int address, uint8_t value) {
|
void TMS9918::set_register(int address, uint8_t value) {
|
||||||
|
@ -127,7 +127,7 @@ class Base {
|
|||||||
|
|
||||||
// A helper function to output the current border colour for
|
// A helper function to output the current border colour for
|
||||||
// the number of cycles supplied.
|
// the number of cycles supplied.
|
||||||
void output_border(int cycles);
|
void output_border(int cycles, uint32_t cram_dot);
|
||||||
|
|
||||||
// A struct to contain timing information for the current mode.
|
// A struct to contain timing information for the current mode.
|
||||||
struct {
|
struct {
|
||||||
@ -343,9 +343,13 @@ class Base {
|
|||||||
// Schedule a CRAM dot.
|
// Schedule a CRAM dot.
|
||||||
upcoming_cram_dots_.emplace_back();
|
upcoming_cram_dots_.emplace_back();
|
||||||
CRAMDot &dot = upcoming_cram_dots_.back();
|
CRAMDot &dot = upcoming_cram_dots_.back();
|
||||||
dot.location.row = write_pointer_.row;
|
dot.location.row = write_pointer_.row + (access_column / 342);
|
||||||
dot.location.column = access_column;
|
dot.location.column = access_column % 342;
|
||||||
dot.value = master_system_.colour_ram[ram_pointer_ & 0x1f];
|
dot.value = master_system_.colour_ram[ram_pointer_ & 0x1f];
|
||||||
|
|
||||||
|
// TODO: the location should actually be slightly in the past, as
|
||||||
|
// output trails memory reading; expose the length of that gap
|
||||||
|
// somewhere that makes it visible to here and adjust.
|
||||||
} else {
|
} else {
|
||||||
ram_[ram_pointer_ & 16383] = read_ahead_buffer_;
|
ram_[ram_pointer_ & 16383] = read_ahead_buffer_;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user