mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-14 13:33:42 +00:00
Switched to generating an interlaced output, that apparently being correct. Enabled a poor man's version of phosphor persistence to smooth things out a little. It's not completely unconvincing.
This commit is contained in:
parent
b5bcadb8d3
commit
c66409421e
@ -19,6 +19,7 @@ static const unsigned int crt_cycles_multiplier = 8;
|
||||
static const unsigned int crt_cycles_per_line = crt_cycles_multiplier * cycles_per_line;
|
||||
|
||||
const int first_graphics_line = 28;
|
||||
const int first_graphics_cycle = 33;
|
||||
|
||||
Machine::Machine() :
|
||||
_interruptControl(0),
|
||||
@ -27,6 +28,7 @@ Machine::Machine() :
|
||||
_audioOutputPosition(0),
|
||||
_audioOutputPositionError(0),
|
||||
_currentOutputLine(0),
|
||||
_is_odd_field(false),
|
||||
_crt(Outputs::CRT(crt_cycles_per_line, Outputs::CRT::DisplayType::PAL50, 1, 1))
|
||||
{
|
||||
_crt.set_rgb_sampling_function(
|
||||
@ -84,8 +86,8 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin
|
||||
{
|
||||
const int current_line = _frameCycles >> 7;
|
||||
const int line_position = _frameCycles & 127;
|
||||
if(current_line >= first_graphics_line && current_line < first_graphics_line+256 && line_position >= 24 && line_position < 104)
|
||||
cycles = (unsigned int)(104 - line_position);
|
||||
if(current_line >= first_graphics_line && current_line < first_graphics_line+256 && line_position >= first_graphics_cycle && line_position < first_graphics_cycle + 80)
|
||||
cycles = (unsigned int)(80 + first_graphics_cycle - line_position);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -376,20 +378,31 @@ inline void Machine::update_display()
|
||||
// assert sync for the first three lines of the display, with a break at the end for horizontal alignment
|
||||
if(_displayOutputPosition < end_of_hsync)
|
||||
{
|
||||
for(int c = 0; c < lines_of_hsync; c++)
|
||||
{
|
||||
_crt.output_sync(119 * crt_cycles_multiplier);
|
||||
_crt.output_blank(9 * crt_cycles_multiplier);
|
||||
}
|
||||
// on an odd field, output a half line of level data, then 2.5 lines of sync; on an even field
|
||||
// output 2.5 lines of sync, then half a line of level.
|
||||
// if (_is_odd_field)
|
||||
// {
|
||||
_crt.output_blank(64 * crt_cycles_multiplier);
|
||||
_crt.output_sync(320 * crt_cycles_multiplier);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// _crt.output_sync(320 * crt_cycles_multiplier);
|
||||
// _crt.output_blank(64 * crt_cycles_multiplier);
|
||||
// }
|
||||
|
||||
_is_odd_field ^= true;
|
||||
_displayOutputPosition = end_of_hsync;
|
||||
}
|
||||
|
||||
while(_displayOutputPosition >= end_of_hsync && _displayOutputPosition < _frameCycles)
|
||||
{
|
||||
const int current_line = _displayOutputPosition >> 7;
|
||||
const int line_position = _displayOutputPosition & 127;
|
||||
const int cycles_left = _frameCycles - _displayOutputPosition;
|
||||
|
||||
const int fieldOutputPosition = _displayOutputPosition + (_is_odd_field ? 64 : 0);
|
||||
const int current_line = fieldOutputPosition >> 7;
|
||||
const int line_position = fieldOutputPosition & 127;
|
||||
|
||||
// all lines then start with 9 cycles of sync
|
||||
if(line_position < 9)
|
||||
{
|
||||
|
@ -179,6 +179,7 @@ class Machine: public CPU6502::Processor<Machine>, Tape::Delegate {
|
||||
int _currentOutputLine;
|
||||
unsigned int _currentOutputDivider;
|
||||
uint8_t *_currentLine, *_writePointer;
|
||||
bool _is_odd_field;
|
||||
|
||||
// Tape.
|
||||
Tape _tape;
|
||||
|
@ -164,7 +164,7 @@ class CRT {
|
||||
/*! Causes appropriate OpenGL or OpenGL ES calls to be issued in order to draw the current CRT state.
|
||||
The caller is responsible for ensuring that a valid OpenGL context exists for the duration of this call.
|
||||
*/
|
||||
void draw_frame(int output_width, int output_height, bool only_if_dirty);
|
||||
void draw_frame(unsigned int output_width, unsigned int output_height, bool only_if_dirty);
|
||||
|
||||
/*! Tells the CRT that the next call to draw_frame will occur on a different OpenGL context than
|
||||
the previous.
|
||||
|
@ -68,7 +68,7 @@ void CRT::destruct_openGL()
|
||||
if(_rgb_shader) free(_rgb_shader);
|
||||
}
|
||||
|
||||
void CRT::draw_frame(int output_width, int output_height, bool only_if_dirty)
|
||||
void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool only_if_dirty)
|
||||
{
|
||||
_current_frame_mutex->lock();
|
||||
|
||||
@ -105,6 +105,13 @@ void CRT::draw_frame(int output_width, int output_height, bool only_if_dirty)
|
||||
|
||||
push_size_uniforms(output_width, output_height);
|
||||
|
||||
if(_last_drawn_frame != nullptr)
|
||||
{
|
||||
glUniform1f(_openGL_state->alphaUniform, 0.4f);
|
||||
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)_last_drawn_frame->number_of_vertices);
|
||||
}
|
||||
glUniform1f(_openGL_state->alphaUniform, 1.0f);
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(_current_frame->number_of_vertices * _current_frame->size_per_vertex), _current_frame->vertices, GL_DYNAMIC_DRAW);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, _openGL_state->textureName);
|
||||
@ -121,6 +128,7 @@ void CRT::draw_frame(int output_width, int output_height, bool only_if_dirty)
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _current_frame->size.width, _current_frame->dirty_size.height, formatForDepth(_current_frame->buffers[0].depth), GL_UNSIGNED_BYTE, _current_frame->buffers[0].data);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)_current_frame->number_of_vertices);
|
||||
_last_drawn_frame = _current_frame;
|
||||
}
|
||||
|
||||
_current_frame_mutex->unlock();
|
||||
@ -264,7 +272,7 @@ char *CRT::get_fragment_shader()
|
||||
|
||||
"void main(void)"
|
||||
"{"
|
||||
"fragColour = vec4(rgb_sample(srcCoordinatesVarying).rgb, 1.0);"
|
||||
"fragColour = vec4(rgb_sample(srcCoordinatesVarying).rgb, alpha);"
|
||||
"}"
|
||||
, _rgb_shader);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user