1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-01 22:41:32 +00:00

Reduces frequency of video flushes.

This commit is contained in:
Thomas Harte 2020-11-16 21:55:41 -05:00
parent 952891d1b6
commit bb80e53021
4 changed files with 36 additions and 16 deletions

View File

@ -81,11 +81,16 @@ template <class T, int multiplier = 1, int divider = 1, class LocalTimeScale = H
return std::unique_ptr<const T, SequencePointAwareDeleter>(&object_, SequencePointAwareDeleter(non_const_this));
}
/// Returns a pointer to the included object without flushing time.
/// @returns a pointer to the included object, without flushing time.
forceinline T *last_valid() {
return &object_;
}
/// @returns the amount of time since the object was last flushed.
forceinline LocalTimeScale time_since_flush() const {
return time_since_update_;
}
/// Flushes all accumulated time.
///
/// This does not affect this actor's record of when the next sequence point will occur.

View File

@ -279,7 +279,7 @@ class ConcreteMachine:
#define SwitchRead(s) *value = memory_.s ? 0x80 : 0x00
#define LanguageRead(s) SwitchRead(language_card_switches().state().s)
#define AuxiliaryRead(s) SwitchRead(auxiliary_switches().switches().s)
#define VideoRead(s) *value = video_->s ? 0x80 : 0x00
#define VideoRead(s) *value = video_.last_valid()->s ? 0x80 : 0x00
case Read(0xc011): LanguageRead(bank1); break;
case Read(0xc012): LanguageRead(read); break;
case Read(0xc013): AuxiliaryRead(read_auxiliary_memory); break;
@ -288,7 +288,9 @@ class ConcreteMachine:
case Read(0xc016): AuxiliaryRead(alternative_zero_page); break;
case Read(0xc017): AuxiliaryRead(slot_C3_rom); break;
case Read(0xc018): VideoRead(get_80_store()); break;
case Read(0xc019): VideoRead(get_is_vertical_blank()); break;
case Read(0xc019):
VideoRead(get_is_vertical_blank(video_.time_since_flush()));
break;
case Read(0xc01a): VideoRead(get_text()); break;
case Read(0xc01b): VideoRead(get_mixed()); break;
case Read(0xc01c): VideoRead(get_page2()); break;

View File

@ -179,9 +179,13 @@ void VideoBase::output_row(int row, int start, int end) {
if(start >= start_of_left_border && start < start_of_pixels) {
const int end_of_period = std::min(start_of_pixels, end);
uint16_t *const pixel = reinterpret_cast<uint16_t *>(crt_.begin_data(2, 2));
if(pixel) *pixel = border_colour_;
crt_.output_data((end_of_period - start) * CyclesPerTick, 1);
if(border_colour_) {
uint16_t *const pixel = reinterpret_cast<uint16_t *>(crt_.begin_data(2, 2));
if(pixel) *pixel = border_colour_;
crt_.output_data((end_of_period - start) * CyclesPerTick, 1);
} else {
crt_.output_blank((end_of_period - start) * CyclesPerTick);
}
start = end_of_period;
if(start == end) return;
@ -241,9 +245,13 @@ void VideoBase::output_row(int row, int start, int end) {
if(start >= start_of_right_border && start < start_of_sync) {
const int end_of_period = std::min(start_of_sync, end);
uint16_t *const pixel = reinterpret_cast<uint16_t *>(crt_.begin_data(2, 2));
if(pixel) *pixel = border_colour_;
crt_.output_data((end_of_period - start) * CyclesPerTick, 1);
if(border_colour_) {
uint16_t *const pixel = reinterpret_cast<uint16_t *>(crt_.begin_data(2, 2));
if(pixel) *pixel = border_colour_;
crt_.output_data((end_of_period - start) * CyclesPerTick, 1);
} else {
crt_.output_blank((end_of_period - start) * CyclesPerTick);
}
// There's no point updating start here; just fall
// through to the end == FinalColumn test.
@ -253,9 +261,13 @@ void VideoBase::output_row(int row, int start, int end) {
if(start >= start_of_left_border && start < start_of_sync) {
const int end_of_period = std::min(start_of_sync, end);
uint16_t *const pixel = reinterpret_cast<uint16_t *>(crt_.begin_data(2, 2));
if(pixel) *pixel = border_colour_;
crt_.output_data((end_of_period - start) * CyclesPerTick, 1);
if(border_colour_) {
uint16_t *const pixel = reinterpret_cast<uint16_t *>(crt_.begin_data(2, 2));
if(pixel) *pixel = border_colour_;
crt_.output_data((end_of_period - start) * CyclesPerTick, 1);
} else {
crt_.output_blank((end_of_period - start) * CyclesPerTick);
}
start = end_of_period;
if(start == end) return;
@ -268,10 +280,11 @@ void VideoBase::output_row(int row, int start, int end) {
}
}
bool VideoBase::get_is_vertical_blank() {
bool VideoBase::get_is_vertical_blank(Cycles offset) {
// Cf. http://www.1000bit.it/support/manuali/apple/technotes/iigs/tn.iigs.040.html ;
// this bit covers the entire vertical border area, not just the NTSC-sense vertical blank.
return cycles_into_frame_ >= FinalPixelLine * CyclesPerLine;
// this bit covers the entire vertical border area, not just the NTSC-sense vertical blank,
// and considers the border to begin at 192 even though Super High-res mode is 200 lines.
return (cycles_into_frame_ + offset.as<int>())%(Lines * CyclesPerLine) >= FinalPixelLine * CyclesPerLine;
}
void VideoBase::set_new_video(uint8_t new_video) {

View File

@ -27,7 +27,7 @@ class VideoBase: public Apple::II::VideoSwitches<Cycles> {
VideoBase();
void set_internal_ram(const uint8_t *);
bool get_is_vertical_blank();
bool get_is_vertical_blank(Cycles offset);
void set_new_video(uint8_t);
uint8_t get_new_video();