mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-11 08:30:55 +00:00
Added a two-slot buffer of scans and a comon dispatch mechanism.
This commit is contained in:
parent
f4cd0aa38e
commit
20cab08f8f
@ -64,7 +64,16 @@ void CRT::set_new_timing(unsigned int cycles_per_line, unsigned int height_of_di
|
||||
}
|
||||
}
|
||||
|
||||
CRT::CRT(unsigned int cycles_per_line, unsigned int height_of_display, unsigned int number_of_buffers, ...)
|
||||
CRT::CRT(unsigned int cycles_per_line, unsigned int height_of_display, unsigned int number_of_buffers, ...) :
|
||||
_next_scan(0),
|
||||
_frames_with_delegate(0),
|
||||
_frame_read_pointer(0),
|
||||
_horizontal_counter(0),
|
||||
_sync_capacitor_charge_level(0),
|
||||
_is_receiving_sync(false),
|
||||
_is_in_hsync(false),
|
||||
_is_in_vsync(false),
|
||||
_rasterPosition({.x = 0, .y = 0})
|
||||
{
|
||||
set_new_timing(cycles_per_line, height_of_display);
|
||||
|
||||
@ -79,24 +88,10 @@ CRT::CRT(unsigned int cycles_per_line, unsigned int height_of_display, unsigned
|
||||
_frame_builders[frame] = new CRTFrameBuilder(bufferWidth, bufferHeight, number_of_buffers, va);
|
||||
va_end(va);
|
||||
}
|
||||
_frames_with_delegate = 0;
|
||||
_frame_read_pointer = 0;
|
||||
_current_frame_builder = _frame_builders[0];
|
||||
|
||||
// reset raster position
|
||||
_rasterPosition.x = _rasterPosition.y = 0;
|
||||
|
||||
// reset flywheel sync
|
||||
_expected_next_hsync = _cycles_per_line;
|
||||
_horizontal_counter = 0;
|
||||
|
||||
// reset the vertical charge capacitor
|
||||
_sync_capacitor_charge_level = 0;
|
||||
|
||||
// start off not in horizontal sync, not receiving a sync signal
|
||||
_is_receiving_sync = false;
|
||||
_is_in_hsync = false;
|
||||
_is_in_vsync = false;
|
||||
}
|
||||
|
||||
CRT::~CRT()
|
||||
@ -349,35 +344,61 @@ void CRT::set_delegate(Delegate *delegate)
|
||||
|
||||
#pragma mark - stream feeding methods
|
||||
|
||||
void CRT::output_scan(Scan *scan)
|
||||
{
|
||||
bool this_is_sync = (scan->type == Type::Sync);
|
||||
bool hsync_requested = !_is_receiving_sync && this_is_sync;
|
||||
bool vsync_requested = _is_receiving_sync;
|
||||
_is_receiving_sync = this_is_sync;
|
||||
|
||||
advance_cycles(scan->number_of_cycles, scan->source_divider, hsync_requested, vsync_requested, this_is_sync, scan->type);
|
||||
|
||||
_next_scan ^= 1;
|
||||
}
|
||||
|
||||
/*
|
||||
These all merely channel into advance_cycles, supplying appropriate arguments
|
||||
*/
|
||||
void CRT::output_sync(unsigned int number_of_cycles)
|
||||
{
|
||||
bool _hsync_requested = !_is_receiving_sync; // ensure this really is edge triggered; someone calling output_sync twice in succession shouldn't trigger it twice
|
||||
_is_receiving_sync = true;
|
||||
advance_cycles(number_of_cycles, 1, _hsync_requested, false, true, Type::Sync);
|
||||
_scans[_next_scan].type = Type::Sync;
|
||||
_scans[_next_scan].number_of_cycles = number_of_cycles;
|
||||
output_scan(&_scans[_next_scan]);
|
||||
}
|
||||
|
||||
void CRT::output_blank(unsigned int number_of_cycles)
|
||||
{
|
||||
bool _vsync_requested = _is_receiving_sync;
|
||||
_is_receiving_sync = false;
|
||||
advance_cycles(number_of_cycles, 1, false, _vsync_requested, false, Type::Blank);
|
||||
_scans[_next_scan].type = Type::Blank;
|
||||
_scans[_next_scan].number_of_cycles = number_of_cycles;
|
||||
output_scan(&_scans[_next_scan]);
|
||||
}
|
||||
|
||||
void CRT::output_level(unsigned int number_of_cycles)
|
||||
{
|
||||
bool _vsync_requested = _is_receiving_sync;
|
||||
_is_receiving_sync = false;
|
||||
advance_cycles(number_of_cycles, 1, false, _vsync_requested, false, Type::Level);
|
||||
_scans[_next_scan].type = Type::Level;
|
||||
_scans[_next_scan].number_of_cycles = number_of_cycles;
|
||||
_scans[_next_scan].tex_x = _current_frame_builder ? _current_frame_builder->_write_x_position : 0;
|
||||
_scans[_next_scan].tex_y = _current_frame_builder ? _current_frame_builder->_write_y_position : 0;
|
||||
output_scan(&_scans[_next_scan]);
|
||||
}
|
||||
|
||||
void CRT::output_colour_burst(unsigned int number_of_cycles, uint8_t phase, uint8_t magnitude)
|
||||
{
|
||||
_scans[_next_scan].type = Type::ColourBurst;
|
||||
_scans[_next_scan].number_of_cycles = number_of_cycles;
|
||||
_scans[_next_scan].phase = phase;
|
||||
_scans[_next_scan].magnitude = magnitude;
|
||||
output_scan(&_scans[_next_scan]);
|
||||
}
|
||||
|
||||
void CRT::output_data(unsigned int number_of_cycles, unsigned int source_divider)
|
||||
{
|
||||
bool _vsync_requested = _is_receiving_sync;
|
||||
_is_receiving_sync = false;
|
||||
advance_cycles(number_of_cycles, source_divider, false, _vsync_requested, false, Type::Data);
|
||||
_scans[_next_scan].type = Type::Data;
|
||||
_scans[_next_scan].number_of_cycles = number_of_cycles;
|
||||
_scans[_next_scan].tex_x = _current_frame_builder ? _current_frame_builder->_write_x_position : 0;
|
||||
_scans[_next_scan].tex_y = _current_frame_builder ? _current_frame_builder->_write_y_position : 0;
|
||||
_scans[_next_scan].source_divider = source_divider;
|
||||
output_scan(&_scans[_next_scan]);
|
||||
}
|
||||
|
||||
#pragma mark - Buffer supply
|
||||
|
@ -144,7 +144,7 @@ class CRT {
|
||||
|
||||
// the outer entry point for dispatching output_sync, output_blank, output_level and output_data
|
||||
enum Type {
|
||||
Sync, Level, Data, Blank
|
||||
Sync, Level, Data, Blank, ColourBurst
|
||||
} type;
|
||||
void advance_cycles(unsigned int number_of_cycles, unsigned int source_divider, bool hsync_requested, bool vsync_requested, bool vsync_charging, Type type);
|
||||
|
||||
@ -157,6 +157,23 @@ class CRT {
|
||||
};
|
||||
SyncEvent get_next_vertical_sync_event(bool vsync_is_requested, unsigned int cycles_to_run_for, unsigned int *cycles_advanced);
|
||||
SyncEvent get_next_horizontal_sync_event(bool hsync_is_requested, unsigned int cycles_to_run_for, unsigned int *cycles_advanced);
|
||||
|
||||
// each call to output_* generates a scan. A two-slot queue for scans allows edge extensions.
|
||||
struct Scan {
|
||||
Type type;
|
||||
unsigned int number_of_cycles;
|
||||
union {
|
||||
struct {
|
||||
unsigned int source_divider;
|
||||
uint16_t tex_x, tex_y;
|
||||
};
|
||||
struct {
|
||||
uint8_t phase, magnitude;
|
||||
};
|
||||
};
|
||||
} _scans[2];
|
||||
int _next_scan;
|
||||
void output_scan(Scan *scan);
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user