mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-12 15:31:09 +00:00
Edges to within millimetres of CRAM dots.
... but all the way up to bedtime.
This commit is contained in:
parent
9621ba59ae
commit
0587b9f257
@ -326,6 +326,10 @@ void TMS9918::run_for(const HalfCycles cycles) {
|
||||
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.
|
||||
@ -340,6 +344,8 @@ void TMS9918::run_for(const HalfCycles cycles) {
|
||||
}\
|
||||
}
|
||||
|
||||
#define border(left, right) intersect(left, right, output_border(end - start))
|
||||
|
||||
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) {
|
||||
// Vertical sync.
|
||||
@ -348,7 +354,7 @@ void TMS9918::run_for(const HalfCycles cycles) {
|
||||
}
|
||||
} else {
|
||||
// Right border.
|
||||
intersect(0, 15, output_border(end - start));
|
||||
border(0, 15);
|
||||
|
||||
// Blanking region; total length is 58 cycles,
|
||||
// and 58+15 = 73. So output the lot when the
|
||||
@ -362,11 +368,11 @@ void TMS9918::run_for(const HalfCycles cycles) {
|
||||
}
|
||||
|
||||
// Border colour for the rest of the line.
|
||||
intersect(73, 342, output_border(end - start));
|
||||
border(73, 342);
|
||||
}
|
||||
} else {
|
||||
// Right border.
|
||||
intersect(0, 15, output_border(end - start));
|
||||
border(0, 15);
|
||||
|
||||
// Blanking region.
|
||||
if(read_pointer_.column < 73 && end_column >= 73) {
|
||||
@ -378,7 +384,7 @@ void TMS9918::run_for(const HalfCycles cycles) {
|
||||
}
|
||||
|
||||
// Left border.
|
||||
intersect(73, line_buffer.first_pixel_output_column, output_border(end - start));
|
||||
border(73, line_buffer.first_pixel_output_column);
|
||||
|
||||
// Pixel region.
|
||||
intersect(
|
||||
@ -395,7 +401,7 @@ void TMS9918::run_for(const HalfCycles cycles) {
|
||||
const int relative_start = start - line_buffer.first_pixel_output_column;
|
||||
const int relative_end = end - line_buffer.first_pixel_output_column;
|
||||
switch(line_buffer.line_mode) {
|
||||
case LineMode::SMS: draw_sms(relative_start, relative_end); break;
|
||||
case LineMode::SMS: draw_sms(relative_start, relative_end, 0); break;
|
||||
case LineMode::Character: draw_tms_character(relative_start, relative_end); break;
|
||||
case LineMode::Text: draw_tms_text(relative_start, relative_end); break;
|
||||
|
||||
@ -413,11 +419,12 @@ void TMS9918::run_for(const HalfCycles cycles) {
|
||||
|
||||
// Additional right border, if called for.
|
||||
if(line_buffer.next_border_column != 342) {
|
||||
intersect(line_buffer.next_border_column, 342, output_border(end - start));
|
||||
border(line_buffer.next_border_column, 342);
|
||||
}
|
||||
}
|
||||
|
||||
#undef intersect
|
||||
#undef border
|
||||
#undef intersect
|
||||
|
||||
|
||||
|
||||
@ -841,7 +848,7 @@ void Base::draw_tms_text(int start, int end) {
|
||||
}
|
||||
}
|
||||
|
||||
void Base::draw_sms(int start, int end) {
|
||||
void Base::draw_sms(int start, int end, uint32_t cram_dot) {
|
||||
LineBuffer &line_buffer = line_buffers_[read_pointer_.row];
|
||||
int colour_buffer[256];
|
||||
|
||||
@ -974,8 +981,9 @@ void Base::draw_sms(int start, int end) {
|
||||
status_ |= StatusSpriteCollision;
|
||||
}
|
||||
|
||||
// Map from the 32-colour buffer to real output pixels.
|
||||
for(int c = start; c < end; ++c) {
|
||||
// Map from the 32-colour buffer to real output pixels, applying the specific CRAM dot if any.
|
||||
pixel_target_[start] = master_system_.colour_ram[colour_buffer[start] & 0x1f] | cram_dot;
|
||||
for(int c = start+1; c < end; ++c) {
|
||||
pixel_target_[c] = master_system_.colour_ram[colour_buffer[c] & 0x1f];
|
||||
}
|
||||
|
||||
|
@ -253,6 +253,16 @@ class Base {
|
||||
int row, column;
|
||||
} read_pointer_, write_pointer_;
|
||||
|
||||
// The SMS VDP has a programmer-set colour palette, with a dedicated patch of RAM. But the RAM is only exactly
|
||||
// fast enough for the pixel clock. So when the programmer writes to it, that causes a one-pixel glitch; there
|
||||
// isn't the bandwidth for the read both write to occur simultaneously. The following buffer therefore keeps
|
||||
// track of pending collisions, for visual reproduction.
|
||||
struct CRAMDot {
|
||||
LineBufferPointer location;
|
||||
uint32_t value;
|
||||
};
|
||||
std::vector<CRAMDot> upcoming_cram_dots_;
|
||||
|
||||
// Extra information that affects the Master System output mode.
|
||||
struct {
|
||||
// Programmer-set flags.
|
||||
@ -314,17 +324,27 @@ class Base {
|
||||
screen_mode_ = ScreenMode::Blank;
|
||||
}
|
||||
|
||||
void do_external_slot() {
|
||||
void do_external_slot(int access_column) {
|
||||
// TODO: is queued access ready yet?
|
||||
|
||||
switch(queued_access_) {
|
||||
default: return;
|
||||
|
||||
case MemoryAccess::Write:
|
||||
if(master_system_.cram_is_selected) {
|
||||
// Adjust the palette.
|
||||
master_system_.colour_ram[ram_pointer_ & 0x1f] = palette_pack(
|
||||
static_cast<uint8_t>(((read_ahead_buffer_ >> 0) & 3) * 255 / 3),
|
||||
static_cast<uint8_t>(((read_ahead_buffer_ >> 2) & 3) * 255 / 3),
|
||||
static_cast<uint8_t>(((read_ahead_buffer_ >> 4) & 3) * 255 / 3)
|
||||
);
|
||||
|
||||
// Schedule a CRAM dot.
|
||||
upcoming_cram_dots_.emplace_back();
|
||||
auto dot = upcoming_cram_dots_.back();
|
||||
dot.location.row = write_pointer_.row;
|
||||
dot.location.column = access_column;
|
||||
dot.value = master_system_.colour_ram[ram_pointer_ & 0x1f];
|
||||
} else {
|
||||
ram_[ram_pointer_ & 16383] = read_ahead_buffer_;
|
||||
}
|
||||
@ -374,7 +394,7 @@ class Base {
|
||||
case n
|
||||
|
||||
#define external_slot(n) \
|
||||
slot(n): do_external_slot();
|
||||
slot(n): do_external_slot((n)*2);
|
||||
|
||||
#define external_slots_2(n) \
|
||||
external_slot(n); \
|
||||
@ -606,7 +626,7 @@ class Base {
|
||||
|
||||
slot(31):
|
||||
sprite_selection_buffer.reset_sprite_collection();
|
||||
do_external_slot();
|
||||
do_external_slot(31*2);
|
||||
external_slots_2(32);
|
||||
external_slot(34);
|
||||
|
||||
@ -758,7 +778,7 @@ class Base {
|
||||
|
||||
slot(29):
|
||||
sprite_selection_buffer.reset_sprite_collection();
|
||||
do_external_slot();
|
||||
do_external_slot(29*2);
|
||||
external_slot(30);
|
||||
|
||||
sprite_y_read(31, 0);
|
||||
@ -799,7 +819,7 @@ class Base {
|
||||
bool asked_for_write_area_ = false;
|
||||
void draw_tms_character(int start, int end);
|
||||
void draw_tms_text(int start, int end);
|
||||
void draw_sms(int start, int end);
|
||||
void draw_sms(int start, int end, uint32_t cram_dot);
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user