1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-06 01:28:57 +00:00

Got back to a stable image, at least when staying in a mode. Which is what I was trying to fix. Hmmm.

This commit is contained in:
Thomas Harte 2016-02-19 23:41:09 -05:00
parent dce1649fc5
commit 1954f7bcbd
4 changed files with 87 additions and 15 deletions

View File

@ -38,7 +38,7 @@ Machine::Machine() :
"float texValue = texture(texID, coordinate).r;"
"return vec3(step(4.0/256.0, mod(texValue, 8.0/256.0)), step(2.0/256.0, mod(texValue, 4.0/256.0)), step(1.0/256.0, mod(texValue, 2.0/256.0)));"
"}");
_crt->set_visible_area(Outputs::Rect(0.23108f, 0.0f, 0.8125f, 0.98f)); //1875
// _crt->set_visible_area(Outputs::Rect(0.23108f, 0.0f, 0.8125f, 0.98f)); //1875
memset(_key_states, 0, sizeof(_key_states));
memset(_palette, 0xf, sizeof(_palette));
@ -388,16 +388,67 @@ inline void Machine::reset_pixel_output()
_startLineAddress = _startScreenAddress;
}
inline void Machine::output_pixels(int number_of_pixels)
inline void Machine::output_pixels(int start_x, int number_of_pixels)
{
if(number_of_pixels)
{
_crt->output_blank((unsigned int)number_of_pixels * crt_cycles_multiplier);
unsigned int newDivider = 0;
switch(_screen_mode)
{
case 0: case 3: newDivider = 1; break;
case 1: case 4: case 6: newDivider = 2; break;
case 2: case 5: newDivider = 4; break;
}
bool is40Column = (_screen_mode > 3);
if(!_writePointer || newDivider != _currentOutputDivider)
{
_currentOutputDivider = newDivider;
end_pixel_output();
_crt->allocate_write_area(640 / newDivider);
_currentLine = _writePointer = _crt->get_write_target_for_buffer(0);
}
if(is40Column)
{
number_of_pixels = ((start_x + number_of_pixels) >> 1) - (start_x >> 1);
}
switch(_screen_mode)
{
default:
case 0: case 3: case 4: case 6:
while(number_of_pixels--)
{
_writePointer[0] = 7;
_writePointer += 8;
}
break;
case 1: case 5:
while(number_of_pixels--)
{
_writePointer += 4;
}
break;
case 2:
while(number_of_pixels--)
{
_writePointer += 2;
}
break;
}
}
}
inline void Machine::end_pixel_output()
{
if(_currentLine != nullptr)
{
_crt->output_data((unsigned int)((_writePointer - _currentLine) * _currentOutputDivider), _currentOutputDivider);
_writePointer = _currentLine = nullptr;
}
}
inline void Machine::update_pixels_to_position(int x, int y)
@ -419,11 +470,13 @@ inline void Machine::update_pixels_to_position(int x, int y)
if(display_x < first_graphics_cycle+80)
{
int cycles_to_output = (display_y < y) ? 80 + first_graphics_cycle - display_x : std::min(80, x - display_x);
output_pixels(cycles_to_output);
output_pixels(display_x, cycles_to_output);
display_x += cycles_to_output;
if(display_x == first_graphics_cycle+80)
{
end_pixel_output();
}
continue;
}
@ -475,13 +528,13 @@ inline void Machine::update_display()
|--B--|
|--P--|
|--B--|
|-B-
(2.5 lines of sync; half a line of blank; full blanks; pixels; full blanks; half blank)
Even field:
-S-|
|-B-S-|
|--S--|
|--S--|
|--B--|
@ -493,13 +546,13 @@ inline void Machine::update_display()
So:
Top:
if even then half a line of blank
2.5 lines of sync
if odd then half a line of blank
full blanks
Pixels
Bottom:
full blanks
if odd then half a line of blank
*/
@ -509,6 +562,8 @@ inline void Machine::update_display()
// does the top region need to be output?
if(_displayOutputPosition < end_of_top && _fieldCycles >= end_of_top)
{
// printf("[1] %d / %d\n", _crt->get_field_cycle() >> 10, (_crt->get_field_cycle() >> 3)&127);
if(!_is_odd_field) _crt->output_blank(64 * crt_cycles_multiplier);
_crt->output_sync(320 * crt_cycles_multiplier);
if(_is_odd_field) _crt->output_blank(64 * crt_cycles_multiplier);
@ -517,6 +572,7 @@ inline void Machine::update_display()
_crt->output_sync(9 * crt_cycles_multiplier);
_crt->output_blank(119 * crt_cycles_multiplier);
}
// printf("[2] %d / %d\n", _crt->get_field_cycle() >> 10, (_crt->get_field_cycle() >> 3)&127);
_displayOutputPosition = end_of_top;
@ -534,17 +590,17 @@ inline void Machine::update_display()
}
// is this the bottom region?
if(_displayOutputPosition < end_of_graphics && _fieldCycles > end_of_graphics)
if(_displayOutputPosition >= end_of_graphics && _displayOutputPosition < cycles_per_frame)
{
// printf("[3] %d / %d\n", _crt->get_field_cycle() >> 10, (_crt->get_field_cycle() >> 3)&127);
for(int y = first_graphics_line+256; y < 312; y++)
{
_crt->output_sync(9 * crt_cycles_multiplier);
_crt->output_blank(119 * crt_cycles_multiplier);
}
_displayOutputPosition = end_of_graphics;
if(_is_odd_field) _crt->output_blank(64 * crt_cycles_multiplier);
_displayOutputPosition = cycles_per_frame;
// printf("[4] %d / %d\n", _crt->get_field_cycle() >> 10, (_crt->get_field_cycle() >> 3)&127);
_is_odd_field ^= true;
}

View File

@ -157,7 +157,7 @@ class Machine: public CPU6502::Processor<Machine>, Tape::Delegate {
inline void update_display();
inline void update_pixels_to_position(int x, int y);
inline void output_pixels(int number_of_pixels);
inline void output_pixels(int start_x, int number_of_pixels);
inline void end_pixel_output();
inline void reset_pixel_output();
@ -189,9 +189,11 @@ class Machine: public CPU6502::Processor<Machine>, Tape::Delegate {
// Display generation.
uint16_t _startLineAddress, _currentScreenAddress;
int _currentOutputLine;
bool _is_odd_field;
// CRT output
unsigned int _currentOutputDivider;
uint8_t *_currentLine, *_writePointer;
bool _is_odd_field;
// Tape.
Tape _tape;

View File

@ -165,7 +165,7 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi
hsync_requested = false;
vsync_requested = false;
uint8_t *next_run = (is_output_run && next_run_length) ? _run_builders[_run_write_pointer]->get_next_input_run() : nullptr;
uint8_t *next_run = ((is_output_run && next_run_length) && !_horizontal_flywheel->is_in_retrace() && !_vertical_flywheel->is_in_retrace()) ? _run_builders[_run_write_pointer]->get_next_input_run() : nullptr;
int lengthMask = (_horizontal_flywheel->is_in_retrace() ? kRetraceXMask : 0) | (_vertical_flywheel->is_in_retrace() ? kRetraceYMask : 0);
#define position_x(v) (*(uint16_t *)&next_run[kCRTSizeOfVertex*v + kCRTVertexOffsetOfPosition + 0])
@ -241,6 +241,13 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi
_run_write_pointer = (_run_write_pointer + 1)%kCRTNumberOfFrames;
_run_builders[_run_write_pointer]->reset();
static int fc = 0;
fc++;
if(!(fc&15))
{
printf("H misses %d; v misses %d\n", _horizontal_flywheel->get_and_reset_number_of_surprises(), _vertical_flywheel->get_and_reset_number_of_surprises());
}
}
}
}
@ -249,7 +256,7 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi
void CRT::output_scan()
{
_next_scan ^= 1;
// _next_scan ^= 1;
Scan *scan = &_scans[_next_scan];
bool this_is_sync = (scan->type == Type::Sync);

View File

@ -214,6 +214,13 @@ class CRT {
_visible_area = visible_area;
}
#ifdef DEBUG
inline uint32_t get_field_cycle()
{
return _run_builders[_run_write_pointer]->duration / _time_multiplier;
}
#endif
private:
CRT();
void allocate_buffers(unsigned int number, va_list sizes);