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:
parent
adc6838ba0
commit
4554abb755
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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? {
|
||||
|
@ -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) *
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user