mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-23 20:29:42 +00:00
With the provision of an extra hint to the CRT and, finally, the realisation about why my scans weren't exactly joining up, improved output precision.
This commit is contained in:
parent
1c6de7692d
commit
7839d93344
@ -24,7 +24,7 @@ Machine::Machine() :
|
||||
_piaDataValue{0xff, 0xff},
|
||||
_tiaInputValue{0xff, 0xff}
|
||||
{
|
||||
_crt = new Outputs::CRT(228, Outputs::CRT::DisplayType::NTSC60, 1, 2);
|
||||
_crt = new Outputs::CRT(228, 1, Outputs::CRT::DisplayType::NTSC60, 1, 2);
|
||||
_crt->set_composite_sampling_function(
|
||||
"float sample(vec2 coordinate, float phase)\n"
|
||||
"{\n"
|
||||
|
@ -32,7 +32,7 @@ Machine::Machine() :
|
||||
_audioOutputPositionError(0),
|
||||
_currentOutputLine(0),
|
||||
_is_odd_field(false),
|
||||
_crt(std::unique_ptr<Outputs::CRT>(new Outputs::CRT(crt_cycles_per_line, Outputs::CRT::DisplayType::PAL50, 1, 1)))
|
||||
_crt(std::unique_ptr<Outputs::CRT>(new Outputs::CRT(crt_cycles_per_line, 8, Outputs::CRT::DisplayType::PAL50, 1, 1)))
|
||||
{
|
||||
_crt->set_rgb_sampling_function(
|
||||
"vec3 rgb_sample(vec2 coordinate)"
|
||||
|
@ -43,7 +43,8 @@ void CRT::set_new_timing(unsigned int cycles_per_line, unsigned int height_of_di
|
||||
_vertical_flywheel = std::unique_ptr<Outputs::Flywheel>(new Outputs::Flywheel(_cycles_per_line * height_of_display, scanlinesVerticalRetraceTime * _cycles_per_line));
|
||||
|
||||
// figure out the divisor necessary to get the horizontal flywheel into a 16-bit range
|
||||
_vertical_flywheel_output_divider = (uint16_t)ceilf(_vertical_flywheel->get_scan_period() / 65536.0f);
|
||||
unsigned int real_clock_scan_period = (_cycles_per_line * height_of_display) / (_time_multiplier * _common_output_divisor);
|
||||
_vertical_flywheel_output_divider = (uint16_t)(ceilf(real_clock_scan_period / 65536.0f) * (_time_multiplier * _common_output_divisor));
|
||||
}
|
||||
|
||||
void CRT::set_new_display_type(unsigned int cycles_per_line, DisplayType displayType)
|
||||
@ -74,14 +75,15 @@ void CRT::allocate_buffers(unsigned int number, va_list sizes)
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
CRT::CRT() :
|
||||
CRT::CRT(unsigned int common_output_divisor) :
|
||||
_next_scan(0),
|
||||
_run_write_pointer(0),
|
||||
_sync_capacitor_charge_level(0),
|
||||
_is_receiving_sync(false),
|
||||
_output_mutex(new std::mutex),
|
||||
_visible_area(Rect(0, 0, 1, 1)),
|
||||
_sync_period(0)
|
||||
_sync_period(0),
|
||||
_common_output_divisor(common_output_divisor)
|
||||
{
|
||||
construct_openGL();
|
||||
}
|
||||
@ -96,7 +98,7 @@ CRT::~CRT()
|
||||
destruct_openGL();
|
||||
}
|
||||
|
||||
CRT::CRT(unsigned int cycles_per_line, unsigned int height_of_display, ColourSpace colour_space, unsigned int colour_cycle_numerator, unsigned int colour_cycle_denominator, unsigned int number_of_buffers, ...) : CRT()
|
||||
CRT::CRT(unsigned int cycles_per_line, unsigned int common_output_divisor, unsigned int height_of_display, ColourSpace colour_space, unsigned int colour_cycle_numerator, unsigned int colour_cycle_denominator, unsigned int number_of_buffers, ...) : CRT(common_output_divisor)
|
||||
{
|
||||
set_new_timing(cycles_per_line, height_of_display, colour_space, colour_cycle_numerator, colour_cycle_denominator);
|
||||
|
||||
@ -106,7 +108,7 @@ CRT::CRT(unsigned int cycles_per_line, unsigned int height_of_display, ColourSpa
|
||||
va_end(buffer_sizes);
|
||||
}
|
||||
|
||||
CRT::CRT(unsigned int cycles_per_line, DisplayType displayType, unsigned int number_of_buffers, ...) : CRT()
|
||||
CRT::CRT(unsigned int cycles_per_line, unsigned int common_output_divisor, DisplayType displayType, unsigned int number_of_buffers, ...) : CRT(common_output_divisor)
|
||||
{
|
||||
set_new_display_type(cycles_per_line, displayType);
|
||||
|
||||
|
@ -58,6 +58,11 @@ class CRT {
|
||||
|
||||
@param cycles_per_line The clock rate at which this CRT will be driven, specified as the number
|
||||
of cycles expected to take up one whole scanline of the display.
|
||||
|
||||
@param common_output_divisor The greatest a priori common divisor of all cycle counts that will be
|
||||
supplied to @c output_sync, @c output_data, etc; supply 1 if no greater divisor is known. For many
|
||||
machines output will run at a fixed multiple of the clock rate; knowing this divisor can improve
|
||||
internal precision.
|
||||
|
||||
@param height_of_dispaly The number of lines that nominally form one field of the display, rounded
|
||||
up to the next whole integer.
|
||||
@ -79,7 +84,7 @@ class CRT {
|
||||
|
||||
@see @c set_rgb_sampling_function , @c set_composite_sampling_function
|
||||
*/
|
||||
CRT(unsigned int cycles_per_line, unsigned int height_of_display, ColourSpace colour_space, unsigned int colour_cycle_numerator, unsigned int colour_cycle_denominator, unsigned int number_of_buffers, ...);
|
||||
CRT(unsigned int cycles_per_line, unsigned int common_output_divisor, unsigned int height_of_display, ColourSpace colour_space, unsigned int colour_cycle_numerator, unsigned int colour_cycle_denominator, unsigned int number_of_buffers, ...);
|
||||
|
||||
/*! Constructs the CRT with the specified clock rate, with the display height and colour
|
||||
subcarrier frequency dictated by a standard display type and with the requested number of
|
||||
@ -88,7 +93,7 @@ class CRT {
|
||||
Exactly identical to calling the designated constructor with colour subcarrier information
|
||||
looked up by display type.
|
||||
*/
|
||||
CRT(unsigned int cycles_per_line, DisplayType displayType, unsigned int number_of_buffers, ...);
|
||||
CRT(unsigned int cycles_per_line, unsigned int common_output_divisor, DisplayType displayType, unsigned int number_of_buffers, ...);
|
||||
|
||||
/*! Resets the CRT with new timing information. The CRT then continues as though the new timing had
|
||||
been provided at construction. */
|
||||
@ -232,12 +237,13 @@ class CRT {
|
||||
#endif
|
||||
|
||||
private:
|
||||
CRT();
|
||||
CRT(unsigned int common_output_divisor);
|
||||
void allocate_buffers(unsigned int number, va_list sizes);
|
||||
|
||||
// the incoming clock lengths will be multiplied by something to give at least 1000
|
||||
// sample points per line
|
||||
unsigned int _time_multiplier;
|
||||
const unsigned int _common_output_divisor;
|
||||
|
||||
// fundamental creator-specified properties
|
||||
unsigned int _cycles_per_line;
|
||||
|
@ -375,9 +375,10 @@ void CRT::prepare_shader()
|
||||
glUniform2f(positionConversionUniform, _horizontal_flywheel->get_scan_period(), _vertical_flywheel->get_scan_period() / (unsigned int)_vertical_flywheel_output_divider);
|
||||
|
||||
float scan_angle = atan2f(1.0f / (float)_height_of_display, 1.0f);
|
||||
float scan_normal[] = { sinf(scan_angle), cosf(scan_angle)};
|
||||
scan_normal[0] /= (float)_height_of_display;
|
||||
scan_normal[1] /= (float)_height_of_display;
|
||||
float scan_normal[] = { sinf(scan_angle), -cosf(scan_angle)};
|
||||
float multiplier = (float)_horizontal_flywheel->get_standard_period() / ((float)_height_of_display * (float)_horizontal_flywheel->get_scan_period());
|
||||
scan_normal[0] *= multiplier;
|
||||
scan_normal[1] *= multiplier;
|
||||
glUniform2f(scanNormalUniform, scan_normal[0], scan_normal[1]);
|
||||
}
|
||||
|
||||
|
@ -160,13 +160,21 @@ struct Flywheel
|
||||
}
|
||||
|
||||
/*!
|
||||
@returns the expected length of the scan period.
|
||||
@returns the expected length of the scan period (excluding retrace).
|
||||
*/
|
||||
inline unsigned int get_scan_period()
|
||||
{
|
||||
return _standard_period - _retrace_time;
|
||||
}
|
||||
|
||||
/*!
|
||||
@returns the expected length of a complete scan and retrace cycle.
|
||||
*/
|
||||
inline unsigned int get_standard_period()
|
||||
{
|
||||
return _standard_period;
|
||||
}
|
||||
|
||||
/*!
|
||||
@returns the number of synchronisation events that have seemed surprising since the last time this method was called;
|
||||
a low number indicates good synchronisation.
|
||||
|
Loading…
Reference in New Issue
Block a user