mirror of
https://github.com/TomHarte/CLK.git
synced 2025-04-07 16:37:24 +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:
parent
7df5025eef
commit
4a1e9fe2a8
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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]];
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user