mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Started on an attempt not to treat the various buffers as free to loop within, starting with the input texture.
This commit is contained in:
parent
3684c6404f
commit
87df57195d
@ -156,8 +156,8 @@ void Machine::get_output_pixel(uint8_t *pixel, int offset)
|
|||||||
if(playerPixels[0] || missilePixels[0]) outputColour = _playerColour[0];
|
if(playerPixels[0] || missilePixels[0]) outputColour = _playerColour[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// store colour
|
// store colour, if possible
|
||||||
pixel[0] = outputColour;
|
if(pixel) *pixel = outputColour;
|
||||||
}
|
}
|
||||||
|
|
||||||
// in imputing the knowledge that all we're dealing with is the rollover from 159 to 0,
|
// in imputing the knowledge that all we're dealing with is the rollover from 159 to 0,
|
||||||
@ -237,8 +237,7 @@ void Machine::output_pixels(unsigned int count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(_horizontalTimer < (_vBlankExtend ? 152 : 160)) {
|
if(_horizontalTimer < (_vBlankExtend ? 152 : 160)) {
|
||||||
if(_outputBuffer)
|
get_output_pixel(_outputBuffer ? &_outputBuffer[_lastOutputStateDuration] : nullptr, 159 - _horizontalTimer);
|
||||||
get_output_pixel(&_outputBuffer[_lastOutputStateDuration], 159 - _horizontalTimer);
|
|
||||||
|
|
||||||
// increment all graphics counters
|
// increment all graphics counters
|
||||||
increment_object_counter(0);
|
increment_object_counter(0);
|
||||||
|
@ -539,7 +539,7 @@ inline void Machine::start_pixel_line()
|
|||||||
}
|
}
|
||||||
_currentScreenAddress = _startLineAddress;
|
_currentScreenAddress = _startLineAddress;
|
||||||
_current_pixel_column = 0;
|
_current_pixel_column = 0;
|
||||||
_current_output_target = nullptr;
|
_initial_output_target = _current_output_target = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Machine::end_pixel_line()
|
inline void Machine::end_pixel_line()
|
||||||
@ -566,7 +566,7 @@ inline void Machine::output_pixels(unsigned int number_of_cycles)
|
|||||||
case 2: case 5: divider = 8; break;
|
case 2: case 5: divider = 8; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!_current_output_target || divider != _current_output_divider)
|
if(!_initial_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);
|
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;
|
_current_output_divider = divider;
|
||||||
@ -584,97 +584,112 @@ inline void Machine::output_pixels(unsigned int number_of_cycles)
|
|||||||
switch(_screen_mode)
|
switch(_screen_mode)
|
||||||
{
|
{
|
||||||
case 0: case 3:
|
case 0: case 3:
|
||||||
while(number_of_cycles--)
|
if(_initial_output_target)
|
||||||
{
|
{
|
||||||
get_pixel();
|
while(number_of_cycles--)
|
||||||
*(uint32_t *)_current_output_target = _paletteTables.eighty1bpp[_last_pixel_byte];
|
{
|
||||||
_current_output_target += 4;
|
get_pixel();
|
||||||
_current_pixel_column++;
|
*(uint32_t *)_current_output_target = _paletteTables.eighty1bpp[_last_pixel_byte];
|
||||||
}
|
_current_output_target += 4;
|
||||||
|
_current_pixel_column++;
|
||||||
|
}
|
||||||
|
} else _current_output_target += 4*number_of_cycles;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
while(number_of_cycles--)
|
if(_initial_output_target)
|
||||||
{
|
{
|
||||||
get_pixel();
|
while(number_of_cycles--)
|
||||||
*(uint16_t *)_current_output_target = _paletteTables.eighty2bpp[_last_pixel_byte];
|
{
|
||||||
_current_output_target += 2;
|
get_pixel();
|
||||||
_current_pixel_column++;
|
*(uint16_t *)_current_output_target = _paletteTables.eighty2bpp[_last_pixel_byte];
|
||||||
}
|
_current_output_target += 2;
|
||||||
|
_current_pixel_column++;
|
||||||
|
}
|
||||||
|
} else _current_output_target += 2*number_of_cycles;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
while(number_of_cycles--)
|
if(_initial_output_target)
|
||||||
{
|
{
|
||||||
get_pixel();
|
while(number_of_cycles--)
|
||||||
*_current_output_target = _paletteTables.eighty4bpp[_last_pixel_byte];
|
{
|
||||||
_current_output_target += 1;
|
get_pixel();
|
||||||
_current_pixel_column++;
|
*_current_output_target = _paletteTables.eighty4bpp[_last_pixel_byte];
|
||||||
}
|
_current_output_target += 1;
|
||||||
|
_current_pixel_column++;
|
||||||
|
}
|
||||||
|
} else _current_output_target += number_of_cycles;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4: case 6:
|
case 4: case 6:
|
||||||
if(_current_pixel_column&1)
|
if(_initial_output_target)
|
||||||
{
|
{
|
||||||
_last_pixel_byte <<= 4;
|
if(_current_pixel_column&1)
|
||||||
*(uint16_t *)_current_output_target = _paletteTables.forty1bpp[_last_pixel_byte];
|
{
|
||||||
_current_output_target += 2;
|
_last_pixel_byte <<= 4;
|
||||||
|
*(uint16_t *)_current_output_target = _paletteTables.forty1bpp[_last_pixel_byte];
|
||||||
|
_current_output_target += 2;
|
||||||
|
|
||||||
number_of_cycles--;
|
number_of_cycles--;
|
||||||
_current_pixel_column++;
|
_current_pixel_column++;
|
||||||
}
|
}
|
||||||
while(number_of_cycles > 1)
|
while(number_of_cycles > 1)
|
||||||
{
|
{
|
||||||
get_pixel();
|
get_pixel();
|
||||||
*(uint16_t *)_current_output_target = _paletteTables.forty1bpp[_last_pixel_byte];
|
*(uint16_t *)_current_output_target = _paletteTables.forty1bpp[_last_pixel_byte];
|
||||||
_current_output_target += 2;
|
_current_output_target += 2;
|
||||||
|
|
||||||
_last_pixel_byte <<= 4;
|
_last_pixel_byte <<= 4;
|
||||||
*(uint16_t *)_current_output_target = _paletteTables.forty1bpp[_last_pixel_byte];
|
*(uint16_t *)_current_output_target = _paletteTables.forty1bpp[_last_pixel_byte];
|
||||||
_current_output_target += 2;
|
_current_output_target += 2;
|
||||||
|
|
||||||
number_of_cycles -= 2;
|
number_of_cycles -= 2;
|
||||||
_current_pixel_column+=2;
|
_current_pixel_column+=2;
|
||||||
}
|
}
|
||||||
if(number_of_cycles)
|
if(number_of_cycles)
|
||||||
{
|
{
|
||||||
get_pixel();
|
get_pixel();
|
||||||
*(uint16_t *)_current_output_target = _paletteTables.forty1bpp[_last_pixel_byte];
|
*(uint16_t *)_current_output_target = _paletteTables.forty1bpp[_last_pixel_byte];
|
||||||
_current_output_target += 2;
|
_current_output_target += 2;
|
||||||
_current_pixel_column++;
|
_current_pixel_column++;
|
||||||
}
|
}
|
||||||
|
} else _current_output_target += 2 * number_of_cycles;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
if(_current_pixel_column&1)
|
if(_initial_output_target)
|
||||||
{
|
{
|
||||||
_last_pixel_byte <<= 2;
|
if(_current_pixel_column&1)
|
||||||
*_current_output_target = _paletteTables.forty2bpp[_last_pixel_byte];
|
{
|
||||||
_current_output_target += 1;
|
_last_pixel_byte <<= 2;
|
||||||
|
*_current_output_target = _paletteTables.forty2bpp[_last_pixel_byte];
|
||||||
|
_current_output_target += 1;
|
||||||
|
|
||||||
number_of_cycles--;
|
number_of_cycles--;
|
||||||
_current_pixel_column++;
|
_current_pixel_column++;
|
||||||
}
|
}
|
||||||
while(number_of_cycles > 1)
|
while(number_of_cycles > 1)
|
||||||
{
|
{
|
||||||
get_pixel();
|
get_pixel();
|
||||||
*_current_output_target = _paletteTables.forty2bpp[_last_pixel_byte];
|
*_current_output_target = _paletteTables.forty2bpp[_last_pixel_byte];
|
||||||
_current_output_target += 1;
|
_current_output_target += 1;
|
||||||
|
|
||||||
_last_pixel_byte <<= 2;
|
_last_pixel_byte <<= 2;
|
||||||
*_current_output_target = _paletteTables.forty2bpp[_last_pixel_byte];
|
*_current_output_target = _paletteTables.forty2bpp[_last_pixel_byte];
|
||||||
_current_output_target += 1;
|
_current_output_target += 1;
|
||||||
|
|
||||||
number_of_cycles -= 2;
|
number_of_cycles -= 2;
|
||||||
_current_pixel_column+=2;
|
_current_pixel_column+=2;
|
||||||
}
|
}
|
||||||
if(number_of_cycles)
|
if(number_of_cycles)
|
||||||
{
|
{
|
||||||
get_pixel();
|
get_pixel();
|
||||||
*_current_output_target = _paletteTables.forty2bpp[_last_pixel_byte];
|
*_current_output_target = _paletteTables.forty2bpp[_last_pixel_byte];
|
||||||
_current_output_target += 1;
|
_current_output_target += 1;
|
||||||
_current_pixel_column++;
|
_current_pixel_column++;
|
||||||
}
|
}
|
||||||
|
} else _current_output_target += number_of_cycles;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,15 +312,21 @@ void CRT::output_colour_burst(unsigned int number_of_cycles, uint8_t phase, uint
|
|||||||
|
|
||||||
void CRT::output_data(unsigned int number_of_cycles, unsigned int source_divider)
|
void CRT::output_data(unsigned int number_of_cycles, unsigned int source_divider)
|
||||||
{
|
{
|
||||||
_openGL_output_builder->reduce_previous_allocation_to(number_of_cycles / source_divider);
|
if(_openGL_output_builder->reduce_previous_allocation_to(number_of_cycles / source_divider))
|
||||||
Scan scan {
|
{
|
||||||
.type = Scan::Type::Data,
|
Scan scan {
|
||||||
.number_of_cycles = number_of_cycles,
|
.type = Scan::Type::Data,
|
||||||
.tex_x = _openGL_output_builder->get_last_write_x_posititon(),
|
.number_of_cycles = number_of_cycles,
|
||||||
.tex_y = _openGL_output_builder->get_last_write_y_posititon(),
|
.tex_x = _openGL_output_builder->get_last_write_x_posititon(),
|
||||||
.source_divider = source_divider
|
.tex_y = _openGL_output_builder->get_last_write_y_posititon(),
|
||||||
};
|
.source_divider = source_divider
|
||||||
output_scan(&scan);
|
};
|
||||||
|
output_scan(&scan);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
output_blank(number_of_cycles);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Outputs::CRT::Rect CRT::get_rect_for_area(int first_line_after_sync, int number_of_lines, int first_cycle_after_sync, int number_of_cycles, float aspect_ratio)
|
Outputs::CRT::Rect CRT::get_rect_for_area(int first_line_after_sync, int number_of_lines, int first_cycle_after_sync, int number_of_cycles, float aspect_ratio)
|
||||||
|
@ -176,14 +176,16 @@ class CRT {
|
|||||||
*/
|
*/
|
||||||
void output_colour_burst(unsigned int number_of_cycles, uint8_t phase, uint8_t amplitude);
|
void output_colour_burst(unsigned int number_of_cycles, uint8_t phase, uint8_t amplitude);
|
||||||
|
|
||||||
/*! Ensures that the given number of output samples are allocated for writing.
|
/*! Attempts to allocate the given number of output samples for writing.
|
||||||
|
|
||||||
The beginning of the most recently allocated area is used as the start
|
The beginning of the most recently allocated area is used as the start
|
||||||
of data written by a call to @c output_data; it is acceptable to write and to
|
of data written by a call to @c output_data; it is acceptable to write and to
|
||||||
output less data than the amount requested but that may be less efficient.
|
output less data than the amount requested but that may be less efficient.
|
||||||
|
|
||||||
|
Allocation should fail only if emulation is running significantly below real speed.
|
||||||
|
|
||||||
@param required_length The number of samples to allocate.
|
@param required_length The number of samples to allocate.
|
||||||
@returns A pointer to the allocated area.
|
@returns A pointer to the allocated area if room is available; @c nullptr otherwise.
|
||||||
*/
|
*/
|
||||||
inline uint8_t *allocate_write_area(size_t required_length)
|
inline uint8_t *allocate_write_area(size_t required_length)
|
||||||
{
|
{
|
||||||
|
@ -13,44 +13,51 @@
|
|||||||
using namespace Outputs::CRT;
|
using namespace Outputs::CRT;
|
||||||
|
|
||||||
CRTInputBufferBuilder::CRTInputBufferBuilder(size_t bytes_per_pixel) :
|
CRTInputBufferBuilder::CRTInputBufferBuilder(size_t bytes_per_pixel) :
|
||||||
bytes_per_pixel(bytes_per_pixel),
|
_bytes_per_pixel(bytes_per_pixel),
|
||||||
_next_write_x_position(0),
|
_next_write_x_position(0),
|
||||||
_next_write_y_position(0),
|
_next_write_y_position(0),
|
||||||
last_uploaded_line(0)
|
_last_uploaded_line(0),
|
||||||
|
_is_full(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
CRTInputBufferBuilder::~CRTInputBufferBuilder()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRTInputBufferBuilder::allocate_write_area(size_t required_length)
|
void CRTInputBufferBuilder::allocate_write_area(size_t required_length)
|
||||||
{
|
{
|
||||||
_last_allocation_amount = required_length;
|
if (!_is_full)
|
||||||
|
|
||||||
if(_next_write_x_position + required_length + 2 > InputBufferBuilderWidth)
|
|
||||||
{
|
{
|
||||||
_next_write_x_position = 0;
|
_last_allocation_amount = required_length;
|
||||||
_next_write_y_position++;
|
|
||||||
}
|
|
||||||
|
|
||||||
_write_x_position = _next_write_x_position + 1;
|
if(_next_write_x_position + required_length + 2 > InputBufferBuilderWidth)
|
||||||
_write_y_position = _next_write_y_position;
|
{
|
||||||
_write_target_pointer = ((_write_y_position % InputBufferBuilderHeight) * InputBufferBuilderWidth) + _write_x_position;
|
_next_write_x_position = 0;
|
||||||
_next_write_x_position += required_length + 2;
|
_next_write_y_position++;
|
||||||
|
|
||||||
|
_is_full = (_next_write_y_position == _last_uploaded_line + InputBufferBuilderHeight);
|
||||||
|
if(_is_full) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_write_x_position = _next_write_x_position + 1;
|
||||||
|
_write_y_position = _next_write_y_position;
|
||||||
|
_write_target_pointer = ((_write_y_position % InputBufferBuilderHeight) * InputBufferBuilderWidth) + _write_x_position;
|
||||||
|
_next_write_x_position += required_length + 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRTInputBufferBuilder::reduce_previous_allocation_to(size_t actual_length, uint8_t *buffer)
|
bool CRTInputBufferBuilder::reduce_previous_allocation_to(size_t actual_length, uint8_t *buffer)
|
||||||
{
|
{
|
||||||
|
if(_is_full) return false;
|
||||||
|
|
||||||
// book end the allocation with duplicates of the first and last pixel, to protect
|
// book end the allocation with duplicates of the first and last pixel, to protect
|
||||||
// against rounding errors when this run is drawn
|
// against rounding errors when this run is drawn
|
||||||
memcpy( &buffer[(_write_target_pointer - 1) * bytes_per_pixel],
|
memcpy( &buffer[(_write_target_pointer - 1) * _bytes_per_pixel],
|
||||||
&buffer[_write_target_pointer * bytes_per_pixel],
|
&buffer[_write_target_pointer * _bytes_per_pixel],
|
||||||
bytes_per_pixel);
|
_bytes_per_pixel);
|
||||||
|
|
||||||
memcpy( &buffer[(_write_target_pointer + actual_length) * bytes_per_pixel],
|
memcpy( &buffer[(_write_target_pointer + actual_length) * _bytes_per_pixel],
|
||||||
&buffer[(_write_target_pointer + actual_length - 1) * bytes_per_pixel],
|
&buffer[(_write_target_pointer + actual_length - 1) * _bytes_per_pixel],
|
||||||
bytes_per_pixel);
|
_bytes_per_pixel);
|
||||||
|
|
||||||
// return any allocated length that wasn't actually used to the available pool
|
// return any allocated length that wasn't actually used to the available pool
|
||||||
_next_write_x_position -= (_last_allocation_amount - actual_length);
|
_next_write_x_position -= (_last_allocation_amount - actual_length);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -20,23 +20,26 @@ namespace CRT {
|
|||||||
|
|
||||||
struct CRTInputBufferBuilder {
|
struct CRTInputBufferBuilder {
|
||||||
CRTInputBufferBuilder(size_t bytes_per_pixel);
|
CRTInputBufferBuilder(size_t bytes_per_pixel);
|
||||||
~CRTInputBufferBuilder();
|
|
||||||
|
|
||||||
void allocate_write_area(size_t required_length);
|
void allocate_write_area(size_t required_length);
|
||||||
void reduce_previous_allocation_to(size_t actual_length, uint8_t *buffer);
|
bool reduce_previous_allocation_to(size_t actual_length, uint8_t *buffer);
|
||||||
|
|
||||||
inline uint16_t get_and_finalise_current_line()
|
inline uint16_t get_and_finalise_current_line()
|
||||||
{
|
{
|
||||||
uint16_t result = _write_y_position;
|
uint16_t result = _write_y_position;
|
||||||
_next_write_x_position = 0;
|
if(!_is_full)
|
||||||
_next_write_y_position++;
|
{
|
||||||
|
_next_write_x_position = 0;
|
||||||
|
_next_write_y_position++;
|
||||||
|
}
|
||||||
_next_write_y_position %= InputBufferBuilderHeight;
|
_next_write_y_position %= InputBufferBuilderHeight;
|
||||||
|
_is_full = false;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint8_t *get_write_target(uint8_t *buffer)
|
inline uint8_t *get_write_target(uint8_t *buffer)
|
||||||
{
|
{
|
||||||
return &buffer[_write_target_pointer * bytes_per_pixel];
|
return _is_full ? nullptr : &buffer[_write_target_pointer * _bytes_per_pixel];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint16_t get_last_write_x_position()
|
inline uint16_t get_last_write_x_position()
|
||||||
@ -51,7 +54,7 @@ struct CRTInputBufferBuilder {
|
|||||||
|
|
||||||
inline size_t get_bytes_per_pixel()
|
inline size_t get_bytes_per_pixel()
|
||||||
{
|
{
|
||||||
return bytes_per_pixel;
|
return _bytes_per_pixel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -66,11 +69,12 @@ struct CRTInputBufferBuilder {
|
|||||||
size_t _last_allocation_amount;
|
size_t _last_allocation_amount;
|
||||||
|
|
||||||
// the buffer size
|
// the buffer size
|
||||||
size_t bytes_per_pixel;
|
size_t _bytes_per_pixel;
|
||||||
|
|
||||||
// Storage for the amount of buffer uploaded so far; initialised correctly by the buffer
|
// Storage for the amount of buffer uploaded so far; initialised correctly by the buffer
|
||||||
// builder but otherwise entrusted to the CRT to update.
|
// builder but otherwise entrusted to the CRT to update.
|
||||||
unsigned int last_uploaded_line;
|
unsigned int _last_uploaded_line;
|
||||||
|
bool _is_full;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -152,9 +152,9 @@ class OpenGLOutputBuilder {
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void reduce_previous_allocation_to(size_t actual_length)
|
inline bool reduce_previous_allocation_to(size_t actual_length)
|
||||||
{
|
{
|
||||||
_buffer_builder->reduce_previous_allocation_to(actual_length, _input_texture_data);
|
return _buffer_builder->reduce_previous_allocation_to(actual_length, _input_texture_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint16_t get_last_write_x_posititon()
|
inline uint16_t get_last_write_x_posititon()
|
||||||
|
Loading…
Reference in New Issue
Block a user