1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-17 21:30:14 +00:00

Rephrased the CRT as owning an arbitrary number of buffers and vending storage space for pixel output. That much better maps to potential implementations of this thing in GLSL, with ES 2.0's limitations kept in mind.

This commit is contained in:
Thomas Harte 2015-07-19 21:21:34 -04:00
parent 7df5025eef
commit 4a1e9fe2a8
4 changed files with 89 additions and 15 deletions

View File

@ -14,12 +14,13 @@ using namespace Atari2600;
Machine::Machine()
{
reset();
_timestamp = 0;
_horizontalTimer = 0;
_lastOutputStateDuration = 0;
_lastOutputState = OutputState::Sync;
_crt = new Outputs::CRT(228);
_crt = new Outputs::CRT(228, 1, 4);
reset();
}
void Machine::get_output_pixel(uint8_t *pixel, int offset)
@ -76,22 +77,34 @@ void Machine::output_state(OutputState state, uint8_t *pixel)
_lastOutputStateDuration++;
if(state != _lastOutputState)
{
static uint8_t blankingLevel[3] = {0, 0, 0};
switch(_lastOutputState)
{
case OutputState::Blank: _crt->output_level(_lastOutputStateDuration, blankingLevel, "Atari2600"); break;
case OutputState::Blank: {
_crt->allocate_write_area(1);
_outputBuffer = _crt->get_write_target_for_buffer(0);
_outputBuffer[0] = _outputBuffer[1] = _outputBuffer[2] = 0;
_outputBuffer[3] = 0xff;
_crt->output_level(_lastOutputStateDuration, "Atari2600");
} break;
case OutputState::Sync: _crt->output_sync(_lastOutputStateDuration); break;
case OutputState::Pixel: _crt->output_data(_lastOutputStateDuration, _outPixels, "Atari2600"); break;
case OutputState::Pixel: _crt->output_data(_lastOutputStateDuration, "Atari2600"); break;
}
_lastOutputStateDuration = 0;
_lastOutputState = state;
if(state == OutputState::Pixel)
{
_crt->allocate_write_area(160);
_outputBuffer = _crt->get_write_target_for_buffer(0);
}
}
if(state == OutputState::Pixel)
{
_outPixels[(_lastOutputStateDuration * 3) + 0] = pixel[0];
_outPixels[(_lastOutputStateDuration * 3) + 1] = pixel[1];
_outPixels[(_lastOutputStateDuration * 3) + 2] = pixel[2];
_outputBuffer[(_lastOutputStateDuration * 4) + 0] = pixel[0];
_outputBuffer[(_lastOutputStateDuration * 4) + 1] = pixel[1];
_outputBuffer[(_lastOutputStateDuration * 4) + 2] = pixel[2];
_outputBuffer[(_lastOutputStateDuration * 4) + 3] = 0xff;
}
}

View File

@ -53,9 +53,9 @@ class Machine: public CPU6502::Processor<Machine> {
Outputs::CRT *_crt;
// latched output state
uint8_t _outPixels[480];
int _lastOutputStateDuration;
OutputState _lastOutputState;
uint8_t *_outputBuffer;
};
}

View File

@ -7,13 +7,42 @@
//
#include "CRT.hpp"
#include <stdarg.h>
static const int bufferWidth = 512;
static const int bufferHeight = 512;
using namespace Outputs;
CRT::CRT(int cycles_per_line)
CRT::CRT(int cycles_per_line, int number_of_buffers, ...)
{
_horizontalOffset = 0.0f;
_verticalOffset = 0.0f;
_numberOfBuffers = number_of_buffers;
_bufferSizes = new int[_numberOfBuffers];
_buffers = new uint8_t *[_numberOfBuffers];
va_list va;
va_start(va, number_of_buffers);
for(int c = 0; c < _numberOfBuffers; c++)
{
_bufferSizes[c] = va_arg(va, int);
_buffers[c] = new uint8_t[bufferHeight * bufferWidth * _bufferSizes[c]];
}
va_end(va);
_write_allocation_pointer = 0;
}
CRT::~CRT()
{
delete[] _bufferSizes;
for(int c = 0; c < _numberOfBuffers; c++)
{
delete[] _buffers[c];
}
delete[] _buffers;
}
void CRT::output_sync(int number_of_cycles)
@ -22,12 +51,32 @@ void CRT::output_sync(int number_of_cycles)
_syncCapacitorChargeLevel += number_of_cycles;
}
void CRT::output_level(int number_of_cycles, uint8_t *level, std::string type)
void CRT::output_level(int number_of_cycles, std::string type)
{
_syncCapacitorChargeLevel -= number_of_cycles;
}
void CRT::output_data(int number_of_cycles, uint8_t *data, std::string type)
void CRT::output_data(int number_of_cycles, std::string type)
{
_syncCapacitorChargeLevel -= number_of_cycles;
}
#pragma mark - Buffer supplying
void CRT::allocate_write_area(int required_length)
{
int xPos = _write_allocation_pointer & (bufferWidth - 1);
if (xPos + required_length > bufferWidth)
{
_write_allocation_pointer &= ~(bufferWidth - 1);
_write_allocation_pointer = (_write_allocation_pointer + bufferWidth) & ((bufferHeight-1) * bufferWidth);
}
_write_target_pointer = _write_allocation_pointer;
_write_allocation_pointer += required_length;
}
uint8_t *CRT::get_write_target_for_buffer(int buffer)
{
return &_buffers[buffer][_write_target_pointer * _bufferSizes[buffer]];
}

View File

@ -16,10 +16,12 @@ namespace Outputs {
class CRT {
public:
CRT(int cycles_per_line);
CRT(int cycles_per_line, int number_of_buffers, ...);
~CRT();
void output_sync(int number_of_cycles);
void output_level(int number_of_cycles, uint8_t *level, std::string type);
void output_data(int number_of_cycles, uint8_t *data, std::string type);
void output_level(int number_of_cycles, std::string type);
void output_data(int number_of_cycles, std::string type);
struct CRTRun {
struct Point {
@ -30,6 +32,7 @@ class CRT {
Sync, Level, Data
} type;
std::string data_type;
uint8_t *data;
};
@ -39,11 +42,20 @@ class CRT {
};
void set_crt_delegate(CRTDelegate *);
void allocate_write_area(int required_length);
uint8_t *get_write_target_for_buffer(int buffer);
private:
CRTDelegate *_delegate;
int _syncCapacitorChargeLevel;
float _horizontalOffset, _verticalOffset;
uint8_t **_buffers;
int *_bufferSizes;
int _numberOfBuffers;
int _write_allocation_pointer, _write_target_pointer;
};
}