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

Stumbles towards a memory map.

This commit is contained in:
Thomas Harte 2021-03-18 10:43:51 -04:00
parent 97249b0edd
commit 730bfcd1fd

View File

@ -10,6 +10,8 @@
#include "../../MachineTypes.hpp"
#include "../../../Processors/Z80/Z80.hpp"
#include "../../../Analyser/Static/ZXSpectrum/Target.hpp"
#include <array>
@ -24,11 +26,13 @@ namespace ZXSpectrum {
using Model = Analyser::Static::ZXSpectrum::Target::Model;
template<Model model> class ConcreteMachine:
public Machine,
public MachineTypes::ScanProducer,
public MachineTypes::TimedMachine,
public Machine {
public CPU::Z80::BusHandler {
public:
ConcreteMachine(const Analyser::Static::ZXSpectrum::Target &target, const ROMMachine::ROMFetcher &rom_fetcher)
ConcreteMachine(const Analyser::Static::ZXSpectrum::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) :
z80_(*this)
{
set_clock_rate(ClockRate);
@ -39,15 +43,17 @@ template<Model model> class ConcreteMachine:
if(!roms[0]) throw ROMMachine::Error::MissingROMs;
memcpy(rom_.data(), roms[0]->data(), std::min(rom_.size(), roms[0]->size()));
// TODO: insert media, set up memory map.
// Set up initial memory map.
update_memory_map();
// TODO: insert media.
(void)target;
}
// MARK: - TimedMachine
void run_for(const Cycles cycles) override {
// TODO.
(void)cycles;
z80_.run_for(cycles);
}
// MARK: - ScanProducer
@ -61,9 +67,92 @@ template<Model model> class ConcreteMachine:
return Outputs::Display::ScanStatus();
}
// MARK: - BusHandler
forceinline HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) {
(void)cycle;
return HalfCycles(0);
}
private:
CPU::Z80::Processor<ConcreteMachine, false, false> z80_;
// MARK: - Memory.
std::array<uint8_t, 64*1024> rom_;
std::array<uint8_t, 128*1024> ram_;
std::array<uint8_t, 16*1024> scratch_;
const uint8_t *read_pointers_[4];
uint8_t *write_pointers_[4];
uint8_t port1ffd_ = 0;
uint8_t port7ffd_ = 0;
bool disable_paging_ = false;
void update_memory_map() {
if(disable_paging_) {
// Set 48kb-esque memory map.
set_memory(0, rom_.data(), nullptr);
set_memory(1, &ram_[5 * 16384], &ram_[5 * 16384]);
set_memory(2, &ram_[2 * 16384], &ram_[2 * 16384]);
set_memory(3, &ram_[0 * 16384], &ram_[0 * 16384]);
return;
}
if(port1ffd_ & 1) {
// "Special paging mode", i.e. one of four fixed
// RAM configurations, port 7ffd doesn't matter.
switch(port1ffd_ & 0x6) {
default:
case 0x00:
set_memory(0, &ram_[0 * 16384], &ram_[0 * 16384]);
set_memory(1, &ram_[1 * 16384], &ram_[1 * 16384]);
set_memory(2, &ram_[2 * 16384], &ram_[2 * 16384]);
set_memory(3, &ram_[3 * 16384], &ram_[3 * 16384]);
break;
case 0x02:
set_memory(0, &ram_[4 * 16384], &ram_[4 * 16384]);
set_memory(1, &ram_[5 * 16384], &ram_[5 * 16384]);
set_memory(2, &ram_[6 * 16384], &ram_[6 * 16384]);
set_memory(3, &ram_[7 * 16384], &ram_[7 * 16384]);
break;
case 0x04:
set_memory(0, &ram_[4 * 16384], &ram_[4 * 16384]);
set_memory(1, &ram_[5 * 16384], &ram_[5 * 16384]);
set_memory(2, &ram_[6 * 16384], &ram_[6 * 16384]);
set_memory(3, &ram_[3 * 16384], &ram_[3 * 16384]);
break;
case 0x06:
set_memory(0, &ram_[4 * 16384], &ram_[4 * 16384]);
set_memory(1, &ram_[7 * 16384], &ram_[7 * 16384]);
set_memory(2, &ram_[6 * 16384], &ram_[6 * 16384]);
set_memory(3, &ram_[3 * 16384], &ram_[3 * 16384]);
break;
}
return;
}
// 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);
set_memory(1, &ram_[5 * 16384], &ram_[5 * 16384]);
set_memory(2, &ram_[2 * 16384], &ram_[2 * 16384]);
const auto high_ram = &ram_[(port7ffd_ & 7) * 16384];
set_memory(3, high_ram, high_ram);
}
void set_memory(int bank, const uint8_t *read, uint8_t *write) {
read_pointers_[bank] = read - bank*16384;
write_pointers_[bank] = (write ? write : scratch_.data()) - bank*16384;
}
};