mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Merge branch 'master' into DesktopScreenshots
This commit is contained in:
commit
c88abed2dc
@ -167,6 +167,8 @@ template <VideoTiming timing> class Video {
|
|||||||
last_fetches_[1] = memory_[attribute_address_];
|
last_fetches_[1] = memory_[attribute_address_];
|
||||||
last_fetches_[2] = memory_[pixel_address_+1];
|
last_fetches_[2] = memory_[pixel_address_+1];
|
||||||
last_fetches_[3] = memory_[attribute_address_+1];
|
last_fetches_[3] = memory_[attribute_address_+1];
|
||||||
|
set_last_contended_area_access(last_fetches_[3]);
|
||||||
|
|
||||||
pixel_address_ += 2;
|
pixel_address_ += 2;
|
||||||
attribute_address_ += 2;
|
attribute_address_ += 2;
|
||||||
|
|
||||||
@ -315,21 +317,37 @@ template <VideoTiming timing> class Video {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@returns Whatever the ULA or gate array has fetched this cycle, or 0xff if it has fetched nothing.
|
@returns Whatever the ULA or gate array would expose via the floating bus, this cycle.
|
||||||
*/
|
*/
|
||||||
uint8_t get_current_fetch() const {
|
uint8_t get_floating_value() const {
|
||||||
constexpr auto timings = get_timings();
|
constexpr auto timings = get_timings();
|
||||||
const int line = time_into_frame_ / timings.cycles_per_line;
|
const int line = time_into_frame_ / timings.cycles_per_line;
|
||||||
if(line >= 192) return 0xff;
|
if(line >= 192) return 0xff;
|
||||||
|
|
||||||
const int time_into_line = time_into_frame_ % timings.cycles_per_line;
|
const int time_into_line = time_into_frame_ % timings.cycles_per_line;
|
||||||
if(time_into_line >= 256 || (time_into_line&8)) {
|
if(time_into_line >= 256 || (time_into_line&8)) {
|
||||||
return 0xff;
|
return last_contended_access_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The +2a and +3 always return the low bit as set.
|
||||||
|
if constexpr (timing == VideoTiming::Plus3) {
|
||||||
|
return last_fetches_[(time_into_line >> 1) & 3] | 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return last_fetches_[(time_into_line >> 1) & 3];
|
return last_fetches_[(time_into_line >> 1) & 3];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Relevant to the +2a and +3 only, sets the most recent value read from or
|
||||||
|
written to contended memory. This is what will be returned if the floating
|
||||||
|
bus is accessed when the gate array isn't currently reading.
|
||||||
|
*/
|
||||||
|
void set_last_contended_area_access([[maybe_unused]] uint8_t value) {
|
||||||
|
if constexpr (timing == VideoTiming::Plus3) {
|
||||||
|
last_contended_access_ = value | 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Sets the current border colour.
|
Sets the current border colour.
|
||||||
*/
|
*/
|
||||||
@ -367,6 +385,7 @@ template <VideoTiming timing> class Video {
|
|||||||
bool is_alternate_line_ = false;
|
bool is_alternate_line_ = false;
|
||||||
|
|
||||||
uint8_t last_fetches_[4] = {0xff, 0xff, 0xff, 0xff};
|
uint8_t last_fetches_[4] = {0xff, 0xff, 0xff, 0xff};
|
||||||
|
uint8_t last_contended_access_ = 0xff;
|
||||||
|
|
||||||
#define RGB(r, g, b) (r << 4) | (g << 2) | b
|
#define RGB(r, g, b) (r << 4) | (g << 2) | b
|
||||||
static constexpr uint8_t palette[] = {
|
static constexpr uint8_t palette[] = {
|
||||||
|
@ -223,6 +223,10 @@ template<Model model> class ConcreteMachine:
|
|||||||
|
|
||||||
case PartialMachineCycle::Read:
|
case PartialMachineCycle::Read:
|
||||||
*cycle.value = read_pointers_[address >> 14][address];
|
*cycle.value = read_pointers_[address >> 14][address];
|
||||||
|
|
||||||
|
if(is_contended_[address >> 14]) {
|
||||||
|
video_.last_valid()->set_last_contended_area_access(*cycle.value);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PartialMachineCycle::Write:
|
case PartialMachineCycle::Write:
|
||||||
@ -230,7 +234,13 @@ template<Model model> class ConcreteMachine:
|
|||||||
if(is_video_[address >> 14] && (address & 0x3fff) < 6912) {
|
if(is_video_[address >> 14] && (address & 0x3fff) < 6912) {
|
||||||
video_.flush();
|
video_.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
write_pointers_[address >> 14][address] = *cycle.value;
|
write_pointers_[address >> 14][address] = *cycle.value;
|
||||||
|
|
||||||
|
// Fill the floating bus buffer if this write is within the contended area.
|
||||||
|
if(is_contended_[address >> 14]) {
|
||||||
|
video_.last_valid()->set_last_contended_area_access(*cycle.value);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PartialMachineCycle::Output:
|
case PartialMachineCycle::Output:
|
||||||
@ -331,8 +341,9 @@ template<Model model> class ConcreteMachine:
|
|||||||
|
|
||||||
// Check for a floating bus read; these are particularly arcane
|
// Check for a floating bus read; these are particularly arcane
|
||||||
// on the +2a/+3. See footnote to https://spectrumforeveryone.com/technical/memory-contention-floating-bus/
|
// on the +2a/+3. See footnote to https://spectrumforeveryone.com/technical/memory-contention-floating-bus/
|
||||||
if((address & 0xf003) == 0x0001) {
|
// and, much more rigorously, http://sky.relative-path.com/zx/floating_bus.html
|
||||||
*cycle.value &= video_->get_current_fetch();
|
if(!disable_paging_ && (address & 0xf003) == 0x0001) {
|
||||||
|
*cycle.value &= video_->get_floating_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (model == Model::Plus3) {
|
if constexpr (model == Model::Plus3) {
|
||||||
|
Loading…
Reference in New Issue
Block a user