mirror of
https://github.com/TomHarte/CLK.git
synced 2024-09-07 12:54:34 +00:00
139 lines
4.0 KiB
C++
139 lines
4.0 KiB
C++
//
|
|
// AppleIIgs.cpp
|
|
// Clock Signal
|
|
//
|
|
// Created by Thomas Harte on 20/10/2020.
|
|
// Copyright 2020 Thomas Harte. All rights reserved.
|
|
//
|
|
|
|
#include "AppleIIgs.hpp"
|
|
|
|
#include "../../MachineTypes.hpp"
|
|
#include "../../../Processors/65816/65816.hpp"
|
|
|
|
#include "../../../Analyser/Static/AppleIIgs/Target.hpp"
|
|
#include "MemoryMap.hpp"
|
|
|
|
#include <cassert>
|
|
#include <array>
|
|
|
|
namespace Apple {
|
|
namespace IIgs {
|
|
|
|
class ConcreteMachine:
|
|
public Apple::IIgs::Machine,
|
|
public MachineTypes::TimedMachine,
|
|
public MachineTypes::ScanProducer,
|
|
public CPU::MOS6502Esque::BusHandler<uint32_t> {
|
|
|
|
public:
|
|
ConcreteMachine(const Analyser::Static::AppleIIgs::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) :
|
|
m65816_(*this) {
|
|
|
|
set_clock_rate(14318180.0);
|
|
|
|
using Target = Analyser::Static::AppleIIgs::Target;
|
|
std::vector<ROMMachine::ROM> rom_descriptions;
|
|
const std::string machine_name = "AppleIIgs";
|
|
switch(target.model) {
|
|
case Target::Model::ROM00:
|
|
/* TODO */
|
|
case Target::Model::ROM01:
|
|
rom_descriptions.emplace_back(machine_name, "the Apple IIgs ROM01", "apple2gs.rom", 128*1024, 0x42f124b0);
|
|
break;
|
|
|
|
case Target::Model::ROM03:
|
|
rom_descriptions.emplace_back(machine_name, "the Apple IIgs ROM03", "apple2gs.rom2", 256*1024, 0xde7ddf29);
|
|
break;
|
|
}
|
|
const auto roms = rom_fetcher(rom_descriptions);
|
|
if(!roms[0]) {
|
|
throw ROMMachine::Error::MissingROMs;
|
|
}
|
|
rom_ = *roms[0];
|
|
|
|
size_t ram_size = 0;
|
|
switch(target.memory_model) {
|
|
case Target::MemoryModel::TwoHundredAndFiftySixKB:
|
|
ram_size = 256;
|
|
break;
|
|
|
|
case Target::MemoryModel::OneMB:
|
|
ram_size = 128 + 1024;
|
|
break;
|
|
|
|
case Target::MemoryModel::EightMB:
|
|
ram_size = 128 + 8 * 1024;
|
|
break;
|
|
}
|
|
ram_.resize(ram_size * 1024);
|
|
|
|
memory_.set_storage(ram_, rom_);
|
|
}
|
|
|
|
void run_for(const Cycles cycles) override {
|
|
m65816_.run_for(cycles);
|
|
}
|
|
|
|
void set_scan_target(Outputs::Display::ScanTarget *) override {
|
|
}
|
|
|
|
Outputs::Display::ScanStatus get_scaled_scan_status() const override {
|
|
return Outputs::Display::ScanStatus();
|
|
}
|
|
|
|
forceinline Cycles perform_bus_operation(const CPU::WDC65816::BusOperation operation, const uint32_t address, uint8_t *const value) {
|
|
const auto ®ion = MemoryMapRegion(memory_, address);
|
|
|
|
if(region.flags & MemoryMap::Region::IsIO) {
|
|
// TODO: all IO accesses.
|
|
} else {
|
|
// TODO: branching below is predicated on the idea that an extra 64kb of scratch write area
|
|
// and 64kb of 0xffs would be worse than branching due to the data set increase. Verify that?
|
|
if(isReadOperation(operation)) {
|
|
MemoryMapRead(region, address, value);
|
|
} else {
|
|
MemoryMapWrite(memory_, region, address, value);
|
|
}
|
|
}
|
|
|
|
Cycles duration = Cycles(5);
|
|
|
|
// TODO: determine the cost of this access.
|
|
// if((mapping.flags & BankMapping::Is1Mhz) || ((mapping.flags & BankMapping::IsShadowed) && !isReadOperation(operation))) {
|
|
// // TODO: (i) get into phase; (ii) allow for the 1Mhz bus length being sporadically 16 rather than 14.
|
|
// duration = Cycles(14);
|
|
// } else {
|
|
// // TODO: (i) get into phase; (ii) allow for collisions with the refresh cycle.
|
|
// duration = Cycles(5);
|
|
// }
|
|
fast_access_phase_ = (fast_access_phase_ + duration.as<int>()) % 5; // TODO: modulo something else, to allow for refresh.
|
|
slow_access_phase_ = (slow_access_phase_ + duration.as<int>()) % 14; // TODO: modulo something else, to allow for stretched cycles.
|
|
return duration;
|
|
}
|
|
|
|
private:
|
|
CPU::WDC65816::Processor<ConcreteMachine, false> m65816_;
|
|
MemoryMap memory_;
|
|
|
|
int fast_access_phase_ = 0;
|
|
int slow_access_phase_ = 0;
|
|
|
|
// MARK: - Memory storage.
|
|
|
|
// Actual memory storage.
|
|
std::vector<uint8_t> ram_;
|
|
std::vector<uint8_t> rom_;
|
|
};
|
|
|
|
}
|
|
}
|
|
|
|
using namespace Apple::IIgs;
|
|
|
|
Machine *Machine::AppleIIgs(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher) {
|
|
return new ConcreteMachine(*dynamic_cast<const Analyser::Static::AppleIIgs::Target *>(target), rom_fetcher);
|
|
}
|
|
|
|
Machine::~Machine() {}
|