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

Made an attempt to be more rigorous in display generation on the Electron, to make sure I deal with mid-line changes to/from blank line mode. Even if it turns out that they generate pixels.

This commit is contained in:
Thomas Harte 2016-01-29 21:14:13 -05:00
parent adc6838ba0
commit 4554abb755
5 changed files with 76 additions and 53 deletions

View File

@ -379,12 +379,19 @@ inline void Machine::update_display()
{
const int current_line = _displayOutputPosition >> 7;
const int line_position = _displayOutputPosition & 127;
const int cycles_left = _frameCycles - _displayOutputPosition;
// all lines then start with 9 cycles of sync
if(!line_position)
if(line_position < 9)
{
_crt.output_sync(9 * crt_cycles_multiplier);
_displayOutputPosition += 9;
int remaining_period = std::min(9 - line_position, cycles_left);
_displayOutputPosition += remaining_period;
if(line_position + remaining_period == 9)
{
// printf("!%d!", 9);
_crt.output_sync(9 * crt_cycles_multiplier);
}
}
else
{
@ -395,33 +402,37 @@ inline void Machine::update_display()
if(isBlankLine)
{
if(line_position == 9)
{
_crt.output_blank(119 * crt_cycles_multiplier);
_displayOutputPosition += 119;
}
int remaining_period = std::min(128 - line_position, cycles_left);
_crt.output_blank((unsigned int)remaining_period * crt_cycles_multiplier);
// printf(".[%d]", remaining_period);
_displayOutputPosition += remaining_period;
}
else
{
// there are then 15 cycles of blank, 80 cycles of pixels, and 24 further cycles of blank
if(line_position == 9)
if(line_position < 24)
{
_crt.output_blank(15 * crt_cycles_multiplier);
_displayOutputPosition += 15;
int remaining_period = std::min(24 - line_position, cycles_left);
_crt.output_blank((unsigned int)remaining_period * crt_cycles_multiplier);
// printf("/(%d)(%d)[%d]", 24 - line_position, cycles_left, remaining_period);
_displayOutputPosition += remaining_period;
switch(_screenMode)
if(line_position + remaining_period == 24)
{
case 0: case 3: _currentOutputDivider = 1; break;
case 1: case 4: case 6: _currentOutputDivider = 2; break;
case 2: case 5: _currentOutputDivider = 4; break;
switch(_screenMode)
{
case 0: case 3: _currentOutputDivider = 1; break;
case 1: case 4: case 6: _currentOutputDivider = 2; break;
case 2: case 5: _currentOutputDivider = 4; break;
}
_crt.allocate_write_area(80 * crt_cycles_multiplier / _currentOutputDivider);
_currentLine = _writePointer = (uint8_t *)_crt.get_write_target_for_buffer(0);
if(current_line == first_graphics_line)
_startLineAddress = _startScreenAddress;
_currentScreenAddress = _startLineAddress;
}
_crt.allocate_write_area(80 * crt_cycles_multiplier / _currentOutputDivider);
_currentLine = _writePointer = (uint8_t *)_crt.get_write_target_for_buffer(0);
if(current_line == first_graphics_line)
_startLineAddress = _startScreenAddress;
_currentScreenAddress = _startLineAddress;
}
if(line_position >= 24 && line_position < 104)
@ -446,6 +457,7 @@ inline void Machine::update_display()
int pixels_to_output = std::min(_frameCycles - _displayOutputPosition, 104 - line_position);
_displayOutputPosition += pixels_to_output;
// printf("<- %d ->", pixels_to_output);
if(_screenMode >= 4)
{
// just shifting wouldn't be enough if both
@ -514,23 +526,29 @@ inline void Machine::update_display()
#undef GetNextPixels
if(line_position == 104)
if(line_position >= 104)
{
_currentOutputLine++;
if(!(_currentOutputLine&7))
{
_startLineAddress += ((_screenMode < 4) ? 80 : 40)*8 - 7;
}
else
_startLineAddress++;
int pixels_to_output = std::min(_frameCycles - _displayOutputPosition, 128 - line_position);
_crt.output_blank((unsigned int)pixels_to_output * crt_cycles_multiplier);
_displayOutputPosition += pixels_to_output;
if(_writePointer)
_crt.output_data((unsigned int)((_writePointer - _currentLine) * _currentOutputDivider), _currentOutputDivider);
else
_crt.output_data(80 * crt_cycles_multiplier, _currentOutputDivider);
_crt.output_blank(24 * crt_cycles_multiplier);
_displayOutputPosition += 24;
_currentLine = nullptr;
if(line_position + pixels_to_output == 128)
{
_currentOutputLine++;
// printf("\n%d: ", _currentOutputLine);
if(!(_currentOutputLine&7))
{
_startLineAddress += ((_screenMode < 4) ? 80 : 40)*8 - 7;
}
else
_startLineAddress++;
if(_writePointer)
_crt.output_data((unsigned int)((_writePointer - _currentLine) * _currentOutputDivider), _currentOutputDivider);
else
_crt.output_data(80 * crt_cycles_multiplier, _currentOutputDivider);
_currentLine = nullptr;
}
}
}
}
@ -708,6 +726,12 @@ inline void Tape::set_data_register(uint8_t value)
_output_bits_remaining = 9;
}
inline uint8_t Tape::get_data_register()
{
int shift = std::max(_bits_since_start - 7, 0);
return (uint8_t)(_data_register >> shift);
}
inline void Tape::run_for_cycles(unsigned int number_of_cycles)
{
if(_is_enabled)

View File

@ -63,7 +63,7 @@ class Tape {
void set_tape(std::shared_ptr<Storage::Tape> tape);
inline uint8_t get_data_register() { return (uint8_t)(_data_register >> 2); }
inline uint8_t get_data_register();
inline void set_data_register(uint8_t value);
inline void set_counter(uint8_t value);

View File

@ -28,7 +28,7 @@ class ElectronDocument: MachineDocument {
super.windowControllerDidLoadNib(aController)
electron.view = openGLView
electron.audioQueue = self.audioQueue
openGLView.frameBounds = CGRectMake(0.0225, 0.0625, 0.75, 0.75)
// openGLView.frameBounds = CGRectMake(0.0225, 0.0625, 0.75, 0.75)
}
override var windowNibName: String? {

View File

@ -302,10 +302,8 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
@"phase = srcCoordinates.x * 6.283185308;\n"
"\n"
"srcCoordinatesVarying[0] = vec2(srcCoordinates.x / textureSize.x, (srcCoordinates.y + 0.5) / textureSize.y);\n"
"srcCoordinatesVarying[3] = srcCoordinatesVarying[0] + vec2(0.375 / textureSize.x, 0.0);\n"
"srcCoordinatesVarying[2] = srcCoordinatesVarying[0] + vec2(0.125 / textureSize.x, 0.0);\n"
"srcCoordinatesVarying[1] = srcCoordinatesVarying[0] - vec2(0.125 / textureSize.x, 0.0);\n"
"srcCoordinatesVarying[0] = srcCoordinatesVarying[0] - vec2(0.325 / textureSize.x, 0.0);\n";
"srcCoordinatesVarying[1] = srcCoordinatesVarying[0] - vec2(0.5 / textureSize.x, 0.0);\n"
"srcCoordinatesVarying[2] = srcCoordinatesVarying[0] - vec2(0.25 / textureSize.x, 0.0);\n";
NSString *const rgbVertexShaderGlobals =
@"out vec2 srcCoordinatesVarying[5];\n";
@ -385,21 +383,22 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
"const mat3 yiqToRGB = mat3(1.0, 1.0, 1.0, 1.1389784, -0.3240608, -1.3176884, 0.6490692, -0.6762444, 1.7799756);\n";
NSString *const ntscFragmentShaderBody =
@"vec4 angles = vec4(phase) + vec4(-2.35619449019234, -0.78539816339745, 0.78539816339745, 2.35619449019234);\n"
"vec4 samples = vec4("
@"vec3 angles = vec3(phase) + vec3(0.0, -3.141592654, -1.570796327);\n"
"vec3 samples = vec3("
" sample(srcCoordinatesVarying[0], angles.x),"
" sample(srcCoordinatesVarying[1], angles.y),"
" sample(srcCoordinatesVarying[2], angles.z),"
" sample(srcCoordinatesVarying[3], angles.w)"
" sample(srcCoordinatesVarying[2], angles.z)"
");\n"
"\n"
"float y = dot(vec4(0.25), samples);\n"
"samples -= vec4(y);\n"
"float y = dot(vec2(0.5), samples.xy);\n"
"samples -= vec3(y);\n"
"\n"
"float i = dot(cos(angles), samples);\n"
"float q = dot(sin(angles), samples);\n"
"float i = dot(vec3(0.75), cos(angles) * samples);\n"
"float q = dot(vec3(0.75), sin(angles) * samples);\n"
"\n"
"fragColour = 5.0 * texture(shadowMaskTexID, shadowMaskCoordinates) * vec4(yiqToRGB * vec3(y, i, q), 1.0);//sin(lateralVarying));\n";
"fragColour = vec4(yiqToRGB * vec3(y, i, q), 1.0);\n"; //sin(lateralVarying));
// 5.0 * texture(shadowMaskTexID, shadowMaskCoordinates) *
// "float y2 = dot(vec2(0.5), samples.zw);\n"
NSString *const rgbFragmentShaderGlobals =
@"in vec2 srcCoordinatesVarying[5];\n"; // texture(shadowMaskTexID, shadowMaskCoordinates) *

View File

@ -275,7 +275,7 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi
position_y(5) = InternalToUInt16(kCRTFixedPointOffset + _rasterPosition.y + _beamWidth[lengthMask].y);
// if this is a data run then advance the buffer pointer
if(type == Type::Data) tex_x += next_run_length / (_time_multiplier * source_divider);
if(type == Type::Data && source_divider) tex_x += next_run_length / (_time_multiplier * source_divider);
// if this is a data or level run then store the end point
tex_x(2) = tex_x(3) = tex_x(5) = tex_x;