1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-25 18:30:21 +00:00

Switches back to whole bytes per pixel, owing to persistent precision problems at 1bpp.

Also fixes the inaccurately-named `cycles_since_update_`.
This commit is contained in:
Thomas Harte 2018-06-02 18:25:00 -04:00
parent 69dc3cc4d8
commit 80b281d9f1
2 changed files with 23 additions and 23 deletions

View File

@ -16,25 +16,20 @@ namespace {
The number of bytes of PCM data to allocate at once; if/when more are required, The number of bytes of PCM data to allocate at once; if/when more are required,
the class will simply allocate another batch. the class will simply allocate another batch.
*/ */
const std::size_t StandardAllocationSize = 40; const std::size_t StandardAllocationSize = 320;
/// The amount of time a byte takes to output.
const std::size_t HalfCyclesPerByte = 8;
} }
Video::Video() : Video::Video() :
crt_(new Outputs::CRT::CRT(207 * 2, 1, Outputs::CRT::DisplayType::PAL50, 1)) { crt_(new Outputs::CRT::CRT(207 * 2, 1, Outputs::CRT::DisplayType::PAL50, 1)) {
// Set a composite sampling function that assumes 1bpp input. // Set a composite sampling function that assumes two-level input; either a byte is 0, which is black,
// or it is non-zero, which is white.
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)"
"{" "{"
"uint texValue = texture(sampler, coordinate).r;" "return texture(sampler, coordinate).r;"
"texValue <<= int(icoordinate.x) & 7;"
"return float(texValue & 128u);"
"}"); "}");
crt_->set_integer_coordinate_multiplier(8.0f);
// Show only the centre 80% of the TV frame. // Show only the centre 80% of the TV frame.
crt_->set_video_signal(Outputs::CRT::VideoSignal::Composite); crt_->set_video_signal(Outputs::CRT::VideoSignal::Composite);
@ -43,7 +38,7 @@ Video::Video() :
void Video::run_for(const HalfCycles half_cycles) { void Video::run_for(const HalfCycles half_cycles) {
// Just keep a running total of the amount of time that remains owed to the CRT. // Just keep a running total of the amount of time that remains owed to the CRT.
cycles_since_update_ += static_cast<unsigned int>(half_cycles.as_int()); time_since_update_ += half_cycles;
} }
void Video::flush() { void Video::flush() {
@ -53,29 +48,29 @@ void Video::flush() {
void Video::flush(bool next_sync) { void Video::flush(bool next_sync) {
if(sync_) { if(sync_) {
// If in sync, that takes priority. Output the proper amount of sync. // If in sync, that takes priority. Output the proper amount of sync.
crt_->output_sync(cycles_since_update_); crt_->output_sync(static_cast<unsigned int>(time_since_update_.as_int()));
} else { } else {
// If not presently in sync, then... // 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 // 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. // sync, or if we're past its end anyway. Otherwise let it be.
unsigned int data_length = static_cast<unsigned int>(line_data_pointer_ - line_data_) * HalfCyclesPerByte; int data_length = static_cast<int>(line_data_pointer_ - line_data_);
if(data_length < cycles_since_update_ || next_sync) { if(data_length < time_since_update_.as_int() || next_sync) {
unsigned int output_length = std::min(data_length, cycles_since_update_); auto output_length = std::min(data_length, time_since_update_.as_int());
crt_->output_data(output_length, output_length / HalfCyclesPerByte); crt_->output_data(static_cast<unsigned int>(output_length), static_cast<unsigned int>(output_length));
line_data_pointer_ = line_data_ = nullptr; line_data_pointer_ = line_data_ = nullptr;
cycles_since_update_ -= output_length; time_since_update_ -= HalfCycles(output_length);
} else return; } else return;
} }
// Any pending pixels being dealt with, pad with the white level. // Any pending pixels being dealt with, pad with the white level.
uint8_t *colour_pointer = static_cast<uint8_t *>(crt_->allocate_write_area(1)); uint8_t *colour_pointer = static_cast<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(static_cast<unsigned int>(time_since_update_.as_int()));
} }
cycles_since_update_ = 0; time_since_update_ = 0;
} }
void Video::set_sync(bool sync) { void Video::set_sync(bool sync) {
@ -101,14 +96,19 @@ void Video::output_byte(uint8_t byte) {
if(line_data_) { if(line_data_) {
// If the buffer is full, output it now and obtain a new one // If the buffer is full, output it now and obtain a new one
if(line_data_pointer_ - line_data_ == StandardAllocationSize) { if(line_data_pointer_ - line_data_ == StandardAllocationSize) {
crt_->output_data(StandardAllocationSize * HalfCyclesPerByte, StandardAllocationSize); crt_->output_data(StandardAllocationSize, StandardAllocationSize);
cycles_since_update_ -= StandardAllocationSize * HalfCyclesPerByte; time_since_update_ -= StandardAllocationSize;
line_data_pointer_ = line_data_ = crt_->allocate_write_area(StandardAllocationSize); line_data_pointer_ = line_data_ = crt_->allocate_write_area(StandardAllocationSize);
if(!line_data_) return; if(!line_data_) return;
} }
line_data_pointer_[0] = byte; // Convert to one-byte-per-pixel where any non-zero value will act as white.
line_data_pointer_ ++; uint8_t mask = 0x80;
for(int c = 0; c < 8; c++) {
line_data_pointer_[c] = byte & mask;
mask >>= 1;
}
line_data_pointer_ += 8;
} }
} }

View File

@ -45,7 +45,7 @@ class Video {
bool sync_ = false; bool sync_ = false;
uint8_t *line_data_ = nullptr; uint8_t *line_data_ = nullptr;
uint8_t *line_data_pointer_ = nullptr; uint8_t *line_data_pointer_ = nullptr;
unsigned int cycles_since_update_ = 0; HalfCycles time_since_update_ = 0;
std::unique_ptr<Outputs::CRT::CRT> crt_; std::unique_ptr<Outputs::CRT::CRT> crt_;
void flush(bool next_sync); void flush(bool next_sync);