mirror of
https://github.com/TomHarte/CLK.git
synced 2024-07-17 13:29:02 +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;
|
static const unsigned int crt_cycles_per_line = crt_cycles_multiplier * cycles_per_line;
|
||||||
|
|
||||||
const int first_graphics_line = 28;
|
const int first_graphics_line = 28;
|
||||||
|
const int first_graphics_cycle = 33;
|
||||||
|
|
||||||
Machine::Machine() :
|
Machine::Machine() :
|
||||||
_interruptControl(0),
|
_interruptControl(0),
|
||||||
@ -27,6 +28,7 @@ Machine::Machine() :
|
|||||||
_audioOutputPosition(0),
|
_audioOutputPosition(0),
|
||||||
_audioOutputPositionError(0),
|
_audioOutputPositionError(0),
|
||||||
_currentOutputLine(0),
|
_currentOutputLine(0),
|
||||||
|
_is_odd_field(false),
|
||||||
_crt(Outputs::CRT(crt_cycles_per_line, Outputs::CRT::DisplayType::PAL50, 1, 1))
|
_crt(Outputs::CRT(crt_cycles_per_line, Outputs::CRT::DisplayType::PAL50, 1, 1))
|
||||||
{
|
{
|
||||||
_crt.set_rgb_sampling_function(
|
_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 current_line = _frameCycles >> 7;
|
||||||
const int line_position = _frameCycles & 127;
|
const int line_position = _frameCycles & 127;
|
||||||
if(current_line >= first_graphics_line && current_line < first_graphics_line+256 && line_position >= 24 && line_position < 104)
|
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)(104 - line_position);
|
cycles = (unsigned int)(80 + first_graphics_cycle - line_position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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
|
// assert sync for the first three lines of the display, with a break at the end for horizontal alignment
|
||||||
if(_displayOutputPosition < end_of_hsync)
|
if(_displayOutputPosition < end_of_hsync)
|
||||||
{
|
{
|
||||||
for(int c = 0; c < lines_of_hsync; c++)
|
// 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.
|
||||||
_crt.output_sync(119 * crt_cycles_multiplier);
|
// if (_is_odd_field)
|
||||||
_crt.output_blank(9 * crt_cycles_multiplier);
|
// {
|
||||||
}
|
_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;
|
_displayOutputPosition = end_of_hsync;
|
||||||
}
|
}
|
||||||
|
|
||||||
while(_displayOutputPosition >= end_of_hsync && _displayOutputPosition < _frameCycles)
|
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 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
|
// all lines then start with 9 cycles of sync
|
||||||
if(line_position < 9)
|
if(line_position < 9)
|
||||||
{
|
{
|
||||||
|
@ -179,6 +179,7 @@ class Machine: public CPU6502::Processor<Machine>, Tape::Delegate {
|
|||||||
int _currentOutputLine;
|
int _currentOutputLine;
|
||||||
unsigned int _currentOutputDivider;
|
unsigned int _currentOutputDivider;
|
||||||
uint8_t *_currentLine, *_writePointer;
|
uint8_t *_currentLine, *_writePointer;
|
||||||
|
bool _is_odd_field;
|
||||||
|
|
||||||
// Tape.
|
// Tape.
|
||||||
Tape _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.
|
/*! 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.
|
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
|
/*! Tells the CRT that the next call to draw_frame will occur on a different OpenGL context than
|
||||||
the previous.
|
the previous.
|
||||||
|
@ -68,7 +68,7 @@ void CRT::destruct_openGL()
|
|||||||
if(_rgb_shader) free(_rgb_shader);
|
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();
|
_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);
|
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);
|
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);
|
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);
|
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);
|
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)_current_frame->number_of_vertices);
|
||||||
|
_last_drawn_frame = _current_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
_current_frame_mutex->unlock();
|
_current_frame_mutex->unlock();
|
||||||
@ -264,7 +272,7 @@ char *CRT::get_fragment_shader()
|
|||||||
|
|
||||||
"void main(void)"
|
"void main(void)"
|
||||||
"{"
|
"{"
|
||||||
"fragColour = vec4(rgb_sample(srcCoordinatesVarying).rgb, 1.0);"
|
"fragColour = vec4(rgb_sample(srcCoordinatesVarying).rgb, alpha);"
|
||||||
"}"
|
"}"
|
||||||
, _rgb_shader);
|
, _rgb_shader);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user