mirror of
https://github.com/TomHarte/CLK.git
synced 2024-10-04 17:56:29 +00:00
Minimises video flushing, moves it to the proper time.
This commit is contained in:
parent
7965772745
commit
42a9dc7c2b
@ -152,15 +152,13 @@ template<Model model> class ConcreteMachine:
|
|||||||
case PartialMachineCycle::ReadStart:
|
case PartialMachineCycle::ReadStart:
|
||||||
case PartialMachineCycle::WriteStart:
|
case PartialMachineCycle::WriteStart:
|
||||||
// Apply contention if necessary.
|
// Apply contention if necessary.
|
||||||
// For now this causes a video sync up every time any contended area is written to.
|
|
||||||
// TODO: flush only upon a video-area write.
|
|
||||||
//
|
//
|
||||||
// Assumption here: the trigger for the ULA inserting a delay is the falling edge
|
// Assumption here: the trigger for the ULA inserting a delay is the falling edge
|
||||||
// of MREQ, which is always half a cycle into a read or write.
|
// of MREQ, which is always half a cycle into a read or write.
|
||||||
//
|
//
|
||||||
// TODO: somehow provide that information in the PartialMachineCycle?
|
// TODO: somehow provide that information in the PartialMachineCycle?
|
||||||
if(is_contended_[address >> 14]) {
|
if(is_contended_[address >> 14]) {
|
||||||
delay = video_->access_delay(HalfCycles(1));
|
delay = video_.last_valid()->access_delay(video_.time_since_flush() + HalfCycles(1));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -170,6 +168,10 @@ template<Model model> class ConcreteMachine:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PartialMachineCycle::Write:
|
case PartialMachineCycle::Write:
|
||||||
|
// Flush video if this access modifies screen contents.
|
||||||
|
if(address >= video_base_ && address < video_base_ + 6912) {
|
||||||
|
video_.flush();
|
||||||
|
}
|
||||||
write_pointers_[address >> 14][address] = *cycle.value;
|
write_pointers_[address >> 14][address] = *cycle.value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -188,12 +190,12 @@ template<Model model> class ConcreteMachine:
|
|||||||
|
|
||||||
// Test for classic 128kb paging register.
|
// Test for classic 128kb paging register.
|
||||||
if((address & 0xc002) == 0x4000) {
|
if((address & 0xc002) == 0x4000) {
|
||||||
// Set the proper video base pointer.
|
|
||||||
set_video_address();
|
|
||||||
|
|
||||||
port7ffd_ = *cycle.value;
|
port7ffd_ = *cycle.value;
|
||||||
update_memory_map();
|
update_memory_map();
|
||||||
|
|
||||||
|
// Set the proper video base pointer.
|
||||||
|
set_video_address();
|
||||||
|
|
||||||
// Potentially lock paging, _after_ the current
|
// Potentially lock paging, _after_ the current
|
||||||
// port values have taken effect.
|
// port values have taken effect.
|
||||||
disable_paging_ |= *cycle.value & 0x20;
|
disable_paging_ |= *cycle.value & 0x20;
|
||||||
@ -203,6 +205,7 @@ template<Model model> class ConcreteMachine:
|
|||||||
if((address & 0xf002) == 0x1000) {
|
if((address & 0xf002) == 0x1000) {
|
||||||
port1ffd_ = *cycle.value;
|
port1ffd_ = *cycle.value;
|
||||||
update_memory_map();
|
update_memory_map();
|
||||||
|
update_video_base();
|
||||||
}
|
}
|
||||||
|
|
||||||
if((address & 0xc002) == 0xc000) {
|
if((address & 0xc002) == 0xc000) {
|
||||||
@ -369,7 +372,9 @@ template<Model model> class ConcreteMachine:
|
|||||||
std::array<uint8_t, 16*1024> scratch_;
|
std::array<uint8_t, 16*1024> scratch_;
|
||||||
const uint8_t *read_pointers_[4];
|
const uint8_t *read_pointers_[4];
|
||||||
uint8_t *write_pointers_[4];
|
uint8_t *write_pointers_[4];
|
||||||
|
uint8_t pages_[4];
|
||||||
bool is_contended_[4];
|
bool is_contended_[4];
|
||||||
|
int video_base_ = 0x4000;
|
||||||
|
|
||||||
uint8_t port1ffd_ = 0;
|
uint8_t port1ffd_ = 0;
|
||||||
uint8_t port7ffd_ = 0;
|
uint8_t port7ffd_ = 0;
|
||||||
@ -388,56 +393,66 @@ template<Model model> class ConcreteMachine:
|
|||||||
switch(port1ffd_ & 0x06) {
|
switch(port1ffd_ & 0x06) {
|
||||||
default:
|
default:
|
||||||
case 0x00:
|
case 0x00:
|
||||||
set_memory(0, &ram_[0 * 16384], &ram_[0 * 16384], false);
|
set_memory(0, 0);
|
||||||
set_memory(1, &ram_[1 * 16384], &ram_[1 * 16384], false);
|
set_memory(1, 1);
|
||||||
set_memory(2, &ram_[2 * 16384], &ram_[2 * 16384], false);
|
set_memory(2, 2);
|
||||||
set_memory(3, &ram_[3 * 16384], &ram_[3 * 16384], false);
|
set_memory(3, 3);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x02:
|
case 0x02:
|
||||||
set_memory(0, &ram_[4 * 16384], &ram_[4 * 16384], true);
|
set_memory(0, 4);
|
||||||
set_memory(1, &ram_[5 * 16384], &ram_[5 * 16384], true);
|
set_memory(1, 5);
|
||||||
set_memory(2, &ram_[6 * 16384], &ram_[6 * 16384], true);
|
set_memory(2, 6);
|
||||||
set_memory(3, &ram_[7 * 16384], &ram_[7 * 16384], true);
|
set_memory(3, 7);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x04:
|
case 0x04:
|
||||||
set_memory(0, &ram_[4 * 16384], &ram_[4 * 16384], true);
|
set_memory(0, 4);
|
||||||
set_memory(1, &ram_[5 * 16384], &ram_[5 * 16384], true);
|
set_memory(1, 5);
|
||||||
set_memory(2, &ram_[6 * 16384], &ram_[6 * 16384], true);
|
set_memory(2, 6);
|
||||||
set_memory(3, &ram_[3 * 16384], &ram_[3 * 16384], false);
|
set_memory(3, 3);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x06:
|
case 0x06:
|
||||||
set_memory(0, &ram_[4 * 16384], &ram_[4 * 16384], true);
|
set_memory(0, 4);
|
||||||
set_memory(1, &ram_[7 * 16384], &ram_[7 * 16384], true);
|
set_memory(1, 7);
|
||||||
set_memory(2, &ram_[6 * 16384], &ram_[6 * 16384], true);
|
set_memory(2, 6);
|
||||||
set_memory(3, &ram_[3 * 16384], &ram_[3 * 16384], false);
|
set_memory(3, 3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
return;
|
// Apply standard 128kb-esque mapping (albeit with extra ROM to pick from).
|
||||||
|
set_memory(0, 0x80 | ((port1ffd_ >> 1) & 2) | ((port7ffd_ >> 4) & 1));
|
||||||
|
set_memory(1, 5);
|
||||||
|
set_memory(2, 2);
|
||||||
|
set_memory(3, port7ffd_ & 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply standard 128kb-esque mapping (albeit with extra ROM to pick from).
|
|
||||||
const auto rom = &rom_[ (((port1ffd_ >> 1) & 2) | ((port7ffd_ >> 4) & 1)) * 16384];
|
|
||||||
set_memory(0, rom, nullptr, false);
|
|
||||||
|
|
||||||
set_memory(1, &ram_[5 * 16384], &ram_[5 * 16384], true);
|
|
||||||
set_memory(2, &ram_[2 * 16384], &ram_[2 * 16384], false);
|
|
||||||
|
|
||||||
const auto high_ram = &ram_[(port7ffd_ & 7) * 16384];
|
|
||||||
set_memory(3, high_ram, high_ram, (port7ffd_ & 7) >= 4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_memory(int bank, const uint8_t *read, uint8_t *write, bool is_contended) {
|
void set_memory(int bank, uint8_t source) {
|
||||||
is_contended_[bank] = is_contended;
|
is_contended_[bank] = (source >= 4 && source < 8);
|
||||||
read_pointers_[bank] = read - bank*16384;
|
pages_[bank] = source;
|
||||||
write_pointers_[bank] = (write ? write : scratch_.data()) - bank*16384;
|
|
||||||
|
uint8_t *read = (source < 0x80) ? &ram_[source * 16384] : &rom_[(source & 0x7f) * 16384];
|
||||||
|
const auto offset = bank*16384;
|
||||||
|
|
||||||
|
read_pointers_[bank] = read - offset;
|
||||||
|
write_pointers_[bank] = ((source < 0x80) ? read : scratch_.data()) - offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_video_address() {
|
void set_video_address() {
|
||||||
video_->set_video_source(&ram_[((port7ffd_ & 0x08) ? 7 : 5) * 16384]);
|
video_->set_video_source(&ram_[((port7ffd_ & 0x08) ? 7 : 5) * 16384]);
|
||||||
|
update_video_base();
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_video_base() {
|
||||||
|
const uint8_t video_page = (port7ffd_ & 0x08) ? 7 : 5;
|
||||||
|
video_base_ = 0x1'0000; // i.e. not in memory.
|
||||||
|
|
||||||
|
if(pages_[0] == video_page) video_base_ = 0x0000;
|
||||||
|
else if(pages_[1] == video_page) video_base_ = 0x4000;
|
||||||
|
else if(pages_[2] == video_page) video_base_ = 0x8000;
|
||||||
|
else if(pages_[3] == video_page) video_base_ = 0xc000;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Audio.
|
// MARK: - Audio.
|
||||||
|
Loading…
Reference in New Issue
Block a user