1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-01 11:49:58 +00:00

Added comments.

This commit is contained in:
Thomas Harte 2017-06-06 18:01:33 -04:00
parent 8c66e1d99d
commit e3ee9604a5
2 changed files with 41 additions and 4 deletions

View File

@ -17,6 +17,8 @@ Video::Video() :
cycles_since_update_(0), cycles_since_update_(0),
sync_(false) { sync_(false) {
// Set a composite sampling function that assumes 8bpp input grayscale.
// TODO: lessen this to 1bpp.
crt_->set_composite_sampling_function( crt_->set_composite_sampling_function(
"float composite_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate, float phase, float amplitude)" "float composite_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate, float phase, float amplitude)"
"{" "{"
@ -25,22 +27,33 @@ Video::Video() :
} }
void Video::run_for_cycles(int number_of_cycles) { void Video::run_for_cycles(int number_of_cycles) {
// Just keep a running total of the amount of time that remains owed to the CRT.
cycles_since_update_ += (unsigned int)number_of_cycles << 1; cycles_since_update_ += (unsigned int)number_of_cycles << 1;
} }
void Video::flush() { void Video::flush() {
flush(sync_);
}
void Video::flush(bool next_sync) {
if(sync_) { if(sync_) {
// If in sync, that takes priority. Output the proper amount of sync.
crt_->output_sync(cycles_since_update_); crt_->output_sync(cycles_since_update_);
} else { } else {
// If not presently in sync, then...
if(line_data_) { if(line_data_) {
// If there is output data queued, output it either if it's being interrupted by
// sync, or if we're past its end anyway. Otherwise let it be.
unsigned int data_length = (unsigned int)(line_data_pointer_ - line_data_); unsigned int data_length = (unsigned int)(line_data_pointer_ - line_data_);
if(data_length < cycles_since_update_) { if(data_length < cycles_since_update_ || next_sync) {
crt_->output_data(data_length, 1); crt_->output_data(data_length, 1);
line_data_pointer_ = line_data_ = nullptr; line_data_pointer_ = line_data_ = nullptr;
cycles_since_update_ -= data_length; cycles_since_update_ -= data_length;
} else return; } else return;
} }
// Any pending pixels being dealt with, pad with the white level.
uint8_t *colour_pointer = (uint8_t *)crt_->allocate_write_area(1); uint8_t *colour_pointer = (uint8_t *)crt_->allocate_write_area(1);
if(colour_pointer) *colour_pointer = 0xff; if(colour_pointer) *colour_pointer = 0xff;
crt_->output_level(cycles_since_update_); crt_->output_level(cycles_since_update_);
@ -50,19 +63,24 @@ void Video::flush() {
} }
void Video::set_sync(bool sync) { void Video::set_sync(bool sync) {
// Do nothing if sync hasn't changed.
if(sync_ == sync) return; if(sync_ == sync) return;
flush();
// Complete whatever was being drawn, and update sync.
flush(sync);
sync_ = sync; sync_ = sync;
if(cycles_since_update_) flush();
} }
void Video::output_byte(uint8_t byte) { void Video::output_byte(uint8_t byte) {
// Complete whatever was going on.
flush(); flush();
// Grab a buffer if one isn't already available.
if(!line_data_) { if(!line_data_) {
line_data_pointer_ = line_data_ = crt_->allocate_write_area(320); line_data_pointer_ = line_data_ = crt_->allocate_write_area(320);
} }
// If a buffer was obtained, serialise the new pixels.
if(line_data_) { if(line_data_) {
uint8_t mask = 0x80; uint8_t mask = 0x80;
for(int c = 0; c < 8; c++) { for(int c = 0; c < 8; c++) {
@ -71,6 +89,7 @@ void Video::output_byte(uint8_t byte) {
} }
line_data_pointer_ += 8; line_data_pointer_ += 8;
// If that fills the buffer, output it now.
if(line_data_pointer_ - line_data_ == 320) { if(line_data_pointer_ - line_data_ == 320) {
crt_->output_data(320, 1); crt_->output_data(320, 1);
line_data_pointer_ = line_data_ = nullptr; line_data_pointer_ = line_data_ = nullptr;

View File

@ -13,15 +13,31 @@
namespace ZX8081 { namespace ZX8081 {
/*!
Packages a ZX80/81-style video feed into a CRT-compatible waveform.
While sync is active, this feed will output the sync level.
While sync is inactive, this feed will output the white level unless it is supplied
with a byte to output. When a byte is supplied for output, it will be interpreted as
a 1-bit graphic and output over the next 4 cycles, picking between the white level
and the black level.
*/
class Video { class Video {
public: public:
/// Constructs an instance of the video feed; a CRT is also created.
Video(); Video();
/// @returns The CRT this video feed is feeding.
std::shared_ptr<Outputs::CRT::CRT> get_crt(); std::shared_ptr<Outputs::CRT::CRT> get_crt();
/// Advances time by @c number_of_cycles cycles.
void run_for_cycles(int number_of_cycles); void run_for_cycles(int number_of_cycles);
/// Forces output to catch up to the current output position.
void flush(); void flush();
/// Sets the current sync output.
void set_sync(bool sync); void set_sync(bool sync);
/// Causes @c byte to be serialised into pixels and output over the next four cycles.
void output_byte(uint8_t byte); void output_byte(uint8_t byte);
private: private:
@ -29,6 +45,8 @@ class Video {
uint8_t *line_data_, *line_data_pointer_; uint8_t *line_data_, *line_data_pointer_;
unsigned int cycles_since_update_; unsigned int cycles_since_update_;
std::shared_ptr<Outputs::CRT::CRT> crt_; std::shared_ptr<Outputs::CRT::CRT> crt_;
void flush(bool next_sync);
}; };
} }