mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-01 11:49:58 +00:00
Added comments.
This commit is contained in:
parent
8c66e1d99d
commit
e3ee9604a5
@ -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;
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user