mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Merge pull request #892 from TomHarte/FixedFloatingBus
Attempts to implement proper floating bus behaviour.
This commit is contained in:
commit
e42b6cb3c8
@ -167,6 +167,8 @@ template <VideoTiming timing> class Video {
|
||||
last_fetches_[1] = memory_[attribute_address_];
|
||||
last_fetches_[2] = memory_[pixel_address_+1];
|
||||
last_fetches_[3] = memory_[attribute_address_+1];
|
||||
set_last_contended_area_access(last_fetches_[3]);
|
||||
|
||||
pixel_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();
|
||||
const int line = time_into_frame_ / timings.cycles_per_line;
|
||||
if(line >= 192) return 0xff;
|
||||
|
||||
const int time_into_line = time_into_frame_ % timings.cycles_per_line;
|
||||
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];
|
||||
}
|
||||
|
||||
/*!
|
||||
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.
|
||||
*/
|
||||
@ -367,6 +385,7 @@ template <VideoTiming timing> class Video {
|
||||
bool is_alternate_line_ = false;
|
||||
|
||||
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
|
||||
static constexpr uint8_t palette[] = {
|
||||
|
@ -223,6 +223,10 @@ template<Model model> class ConcreteMachine:
|
||||
|
||||
case PartialMachineCycle::Read:
|
||||
*cycle.value = read_pointers_[address >> 14][address];
|
||||
|
||||
if(is_contended_[address >> 14]) {
|
||||
video_.last_valid()->set_last_contended_area_access(*cycle.value);
|
||||
}
|
||||
break;
|
||||
|
||||
case PartialMachineCycle::Write:
|
||||
@ -230,7 +234,13 @@ template<Model model> class ConcreteMachine:
|
||||
if(is_video_[address >> 14] && (address & 0x3fff) < 6912) {
|
||||
video_.flush();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
case PartialMachineCycle::Output:
|
||||
@ -331,8 +341,9 @@ template<Model model> class ConcreteMachine:
|
||||
|
||||
// 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/
|
||||
if((address & 0xf003) == 0x0001) {
|
||||
*cycle.value &= video_->get_current_fetch();
|
||||
// and, much more rigorously, http://sky.relative-path.com/zx/floating_bus.html
|
||||
if(!disable_paging_ && (address & 0xf003) == 0x0001) {
|
||||
*cycle.value &= video_->get_floating_value();
|
||||
}
|
||||
|
||||
if constexpr (model == Model::Plus3) {
|
||||
|
Loading…
Reference in New Issue
Block a user