diff --git a/Machines/Electron/Electron.cpp b/Machines/Electron/Electron.cpp index a3f16da98..35dfaf718 100644 --- a/Machines/Electron/Electron.cpp +++ b/Machines/Electron/Electron.cpp @@ -504,16 +504,12 @@ inline void Machine::start_pixel_line() } _currentScreenAddress = _startLineAddress; _current_pixel_column = 0; - - if(!_isBlankLine) - { - _currentLine = _crt->allocate_write_area(640); - } + _current_output_target = nullptr; } inline void Machine::end_pixel_line() { - if(!_isBlankLine) _crt->output_data(640, 1); + if(_current_output_target) _crt->output_data((unsigned int)((_current_output_target - _initial_output_target) * _current_output_divider), _current_output_divider); _current_character_row++; } @@ -525,6 +521,21 @@ inline void Machine::output_pixels(unsigned int number_of_cycles) } else { + unsigned int divider = 0; + switch(_screen_mode) + { + case 0: case 3: divider = 1; break; + case 1: case 4: case 6: divider = 2; break; + case 2: case 5: divider = 4; break; + } + + if(!_current_output_target || divider != _current_output_divider) + { + if(_current_output_target) _crt->output_data((unsigned int)((_current_output_target - _initial_output_target) * _current_output_divider), _current_output_divider); + _current_output_divider = divider; + _initial_output_target = _current_output_target = _crt->allocate_write_area(640 / _current_output_divider); + } + while(number_of_cycles--) { if(!(_current_pixel_column&1) || _screen_mode < 4) @@ -543,40 +554,33 @@ inline void Machine::output_pixels(unsigned int number_of_cycles) case 3: case 0: { - _currentLine[0] = _palette[(_last_pixel_byte&0x80) >> 4]; - _currentLine[1] = _palette[(_last_pixel_byte&0x40) >> 3]; - _currentLine[2] = _palette[(_last_pixel_byte&0x20) >> 2]; - _currentLine[3] = _palette[(_last_pixel_byte&0x10) >> 1]; - _currentLine[4] = _palette[(_last_pixel_byte&0x08) >> 0]; - _currentLine[5] = _palette[(_last_pixel_byte&0x04) << 1]; - _currentLine[6] = _palette[(_last_pixel_byte&0x02) << 2]; - _currentLine[7] = _palette[(_last_pixel_byte&0x01) << 3]; + _current_output_target[0] = _palette[(_last_pixel_byte&0x80) >> 4]; + _current_output_target[1] = _palette[(_last_pixel_byte&0x40) >> 3]; + _current_output_target[2] = _palette[(_last_pixel_byte&0x20) >> 2]; + _current_output_target[3] = _palette[(_last_pixel_byte&0x10) >> 1]; + _current_output_target[4] = _palette[(_last_pixel_byte&0x08) >> 0]; + _current_output_target[5] = _palette[(_last_pixel_byte&0x04) << 1]; + _current_output_target[6] = _palette[(_last_pixel_byte&0x02) << 2]; + _current_output_target[7] = _palette[(_last_pixel_byte&0x01) << 3]; + _current_output_target += 8; } break; case 1: { - _currentLine[0] = - _currentLine[1] = _palette[((_last_pixel_byte&0x80) >> 4) | ((_last_pixel_byte&0x08) >> 2)]; - _currentLine[2] = - _currentLine[3] = _palette[((_last_pixel_byte&0x40) >> 3) | ((_last_pixel_byte&0x04) >> 1)]; - _currentLine[4] = - _currentLine[5] = _palette[((_last_pixel_byte&0x20) >> 2) | ((_last_pixel_byte&0x02) >> 0)]; - _currentLine[6] = - _currentLine[7] = _palette[((_last_pixel_byte&0x10) >> 1) | ((_last_pixel_byte&0x01) << 1)]; + _current_output_target[0] = _palette[((_last_pixel_byte&0x80) >> 4) | ((_last_pixel_byte&0x08) >> 2)]; + _current_output_target[1] = _palette[((_last_pixel_byte&0x40) >> 3) | ((_last_pixel_byte&0x04) >> 1)]; + _current_output_target[2] = _palette[((_last_pixel_byte&0x20) >> 2) | ((_last_pixel_byte&0x02) >> 0)]; + _current_output_target[3] = _palette[((_last_pixel_byte&0x10) >> 1) | ((_last_pixel_byte&0x01) << 1)]; + _current_output_target += 4; } break; case 2: { - _currentLine[0] = - _currentLine[1] = - _currentLine[2] = - _currentLine[3] = _palette[((_last_pixel_byte&0x80) >> 4) | ((_last_pixel_byte&0x20) >> 3) | ((_last_pixel_byte&0x08) >> 2) | ((_last_pixel_byte&0x02) >> 1)]; - _currentLine[4] = - _currentLine[5] = - _currentLine[6] = - _currentLine[7] = _palette[((_last_pixel_byte&0x40) >> 3) | ((_last_pixel_byte&0x10) >> 2) | ((_last_pixel_byte&0x04) >> 1) | ((_last_pixel_byte&0x01) >> 0)]; + _current_output_target[0] = _palette[((_last_pixel_byte&0x80) >> 4) | ((_last_pixel_byte&0x20) >> 3) | ((_last_pixel_byte&0x08) >> 2) | ((_last_pixel_byte&0x02) >> 1)]; + _current_output_target[1] = _palette[((_last_pixel_byte&0x40) >> 3) | ((_last_pixel_byte&0x10) >> 2) | ((_last_pixel_byte&0x04) >> 1) | ((_last_pixel_byte&0x01) >> 0)]; + _current_output_target += 2; } break; @@ -585,26 +589,19 @@ inline void Machine::output_pixels(unsigned int number_of_cycles) { if(_current_pixel_column&1) { - _currentLine[0] = - _currentLine[1] = _palette[(_last_pixel_byte&0x08) >> 0]; - _currentLine[2] = - _currentLine[3] = _palette[(_last_pixel_byte&0x04) << 1]; - _currentLine[4] = - _currentLine[5] = _palette[(_last_pixel_byte&0x02) << 2]; - _currentLine[6] = - _currentLine[7] = _palette[(_last_pixel_byte&0x01) << 3]; + _current_output_target[0] = _palette[(_last_pixel_byte&0x08) >> 0]; + _current_output_target[1] = _palette[(_last_pixel_byte&0x04) << 1]; + _current_output_target[2] = _palette[(_last_pixel_byte&0x02) << 2]; + _current_output_target[3] = _palette[(_last_pixel_byte&0x01) << 3]; } else { - _currentLine[0] = - _currentLine[1] = _palette[(_last_pixel_byte&0x80) >> 4]; - _currentLine[2] = - _currentLine[3] = _palette[(_last_pixel_byte&0x40) >> 3]; - _currentLine[4] = - _currentLine[5] = _palette[(_last_pixel_byte&0x20) >> 2]; - _currentLine[6] = - _currentLine[7] = _palette[(_last_pixel_byte&0x10) >> 1]; + _current_output_target[0] = _palette[(_last_pixel_byte&0x80) >> 4]; + _current_output_target[1] = _palette[(_last_pixel_byte&0x40) >> 3]; + _current_output_target[2] = _palette[(_last_pixel_byte&0x20) >> 2]; + _current_output_target[3] = _palette[(_last_pixel_byte&0x10) >> 1]; } + _current_output_target += 4; } break; @@ -612,32 +609,20 @@ inline void Machine::output_pixels(unsigned int number_of_cycles) { if(_current_pixel_column&1) { - _currentLine[0] = - _currentLine[1] = - _currentLine[2] = - _currentLine[3] = _palette[((_last_pixel_byte&0x20) >> 2) | ((_last_pixel_byte&0x02) >> 0)]; - _currentLine[4] = - _currentLine[5] = - _currentLine[6] = - _currentLine[7] = _palette[((_last_pixel_byte&0x10) >> 1) | ((_last_pixel_byte&0x01) << 1)]; + _current_output_target[0] = _palette[((_last_pixel_byte&0x20) >> 2) | ((_last_pixel_byte&0x02) >> 0)]; + _current_output_target[1] = _palette[((_last_pixel_byte&0x10) >> 1) | ((_last_pixel_byte&0x01) << 1)]; } else { - _currentLine[0] = - _currentLine[1] = - _currentLine[2] = - _currentLine[3] = _palette[((_last_pixel_byte&0x80) >> 4) | ((_last_pixel_byte&0x08) >> 2)]; - _currentLine[4] = - _currentLine[5] = - _currentLine[6] = - _currentLine[7] = _palette[((_last_pixel_byte&0x40) >> 3) | ((_last_pixel_byte&0x04) >> 1)]; + _current_output_target[0] = _palette[((_last_pixel_byte&0x80) >> 4) | ((_last_pixel_byte&0x08) >> 2)]; + _current_output_target[1] = _palette[((_last_pixel_byte&0x40) >> 3) | ((_last_pixel_byte&0x04) >> 1)]; } + _current_output_target += 2; } break; } _current_pixel_column++; - _currentLine += 8; } } } diff --git a/Machines/Electron/Electron.hpp b/Machines/Electron/Electron.hpp index 304e7fc81..6148cfbab 100644 --- a/Machines/Electron/Electron.hpp +++ b/Machines/Electron/Electron.hpp @@ -197,7 +197,8 @@ class Machine: public CPU6502::Processor, Tape::Delegate { bool _isBlankLine; // CRT output - uint8_t *_currentLine; + uint8_t *_current_output_target, *_initial_output_target; + unsigned int _current_output_divider; // Tape. Tape _tape; diff --git a/Outputs/CRT/Internals/CRTConstants.hpp b/Outputs/CRT/Internals/CRTConstants.hpp index f8480d437..46d4d7209 100644 --- a/Outputs/CRT/Internals/CRTConstants.hpp +++ b/Outputs/CRT/Internals/CRTConstants.hpp @@ -43,7 +43,6 @@ const int IntermediateBufferHeight = 2048; // Some internal const GLsizeiptr InputVertexBufferDataSize = 262080; // a multiple of 6 * OutputVertexSize -const GLsizeiptr InputTextureBufferDataSize = InputBufferBuilderWidth*InputBufferBuilderHeight; // Runs are divided discretely by vertical syncs in order to put a usable bounds on the uniform used to track diff --git a/Outputs/CRT/Internals/CRTOpenGL.cpp b/Outputs/CRT/Internals/CRTOpenGL.cpp index 29d6b4f07..c6c73a6dd 100644 --- a/Outputs/CRT/Internals/CRTOpenGL.cpp +++ b/Outputs/CRT/Internals/CRTOpenGL.cpp @@ -87,7 +87,8 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out GLenum format = formatForDepth(_buffer_builder->bytes_per_pixel); glGenBuffers(1, &_input_texture_array); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _input_texture_array); - glBufferData(GL_PIXEL_UNPACK_BUFFER, InputTextureBufferDataSize, NULL, GL_STREAM_DRAW); + _input_texture_array_size = (GLsizeiptr)(InputBufferBuilderWidth * InputBufferBuilderHeight * _buffer_builder->bytes_per_pixel); + glBufferData(GL_PIXEL_UNPACK_BUFFER, _input_texture_array_size, NULL, GL_STREAM_DRAW); glTexImage2D(GL_TEXTURE_2D, 0, (GLint)format, InputBufferBuilderWidth, InputBufferBuilderHeight, 0, format, GL_UNSIGNED_BYTE, nullptr); @@ -219,7 +220,7 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out // drawing commands having been issued, reclaim the array buffer pointer _buffer_builder->move_to_new_line(); _output_buffer_data = (uint8_t *)glMapBufferRange(GL_ARRAY_BUFFER, 0, InputVertexBufferDataSize, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); - _input_texture_data = (uint8_t *)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, InputTextureBufferDataSize, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); + _input_texture_data = (uint8_t *)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, _input_texture_array_size, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); _output_mutex->unlock(); } diff --git a/Outputs/CRT/Internals/CRTOpenGL.hpp b/Outputs/CRT/Internals/CRTOpenGL.hpp index 52ebc154a..c68402267 100644 --- a/Outputs/CRT/Internals/CRTOpenGL.hpp +++ b/Outputs/CRT/Internals/CRTOpenGL.hpp @@ -207,6 +207,7 @@ class OpenGLOutputBuilder { uint8_t *_input_texture_data; GLuint _input_texture_array; GLsync _input_texture_sync; + GLsizeiptr _input_texture_array_size; uint8_t *_output_buffer_data; size_t _output_buffer_data_pointer;