1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-03 08:05:40 +00:00
CLK/Machines/Apple/AppleIIgs/AppleIIgs.cpp

140 lines
3.8 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 &region = MemoryMapRegion(memory_, address);
printf("%06x\n", address);
if(region.flags & MemoryMap::Region::IsIO) {
// TODO: all IO accesses.
assert(false);
} else {
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() {}