mirror of
https://github.com/TomHarte/CLK.git
synced 2026-03-12 10:42:14 +00:00
Add VIA instances, flesh out 1Mhz space.
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
#include "Machines/MachineTypes.hpp"
|
||||
|
||||
#include "Processors/6502/6502.hpp"
|
||||
#include "Components/6522/6522.hpp"
|
||||
|
||||
#include "Analyser/Static/Acorn/Target.hpp"
|
||||
#include "Outputs/Log.hpp"
|
||||
@@ -22,20 +23,36 @@
|
||||
|
||||
namespace BBCMicro {
|
||||
|
||||
namespace {
|
||||
|
||||
struct UserVIAPortHandler: public MOS::MOS6522::IRQDelegatePortHandler {
|
||||
};
|
||||
|
||||
struct SystemVIAPortHandler: public MOS::MOS6522::IRQDelegatePortHandler {
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
class ConcreteMachine:
|
||||
public Machine,
|
||||
public MachineTypes::ScanProducer,
|
||||
public MachineTypes::TimedMachine
|
||||
public MachineTypes::TimedMachine,
|
||||
public MOS::MOS6522::IRQDelegatePortHandler::Delegate
|
||||
{
|
||||
public:
|
||||
ConcreteMachine(
|
||||
const Analyser::Static::Acorn::BBCMicroTarget &target,
|
||||
const ROMMachine::ROMFetcher &rom_fetcher
|
||||
) :
|
||||
m6502_(*this)
|
||||
m6502_(*this),
|
||||
user_via_(user_via_port_handler_),
|
||||
system_via_(system_via_port_handler_)
|
||||
{
|
||||
set_clock_rate(2'000'000);
|
||||
|
||||
system_via_port_handler_.set_interrupt_delegate(this);
|
||||
user_via_port_handler_.set_interrupt_delegate(this);
|
||||
|
||||
// Grab ROMs.
|
||||
using Request = ::ROM::Request;
|
||||
using Name = ::ROM::Name;
|
||||
@@ -65,27 +82,63 @@ public:
|
||||
const uint16_t address,
|
||||
uint8_t *const value
|
||||
) {
|
||||
// Returns @c true if @c address is a device on the 1Mhz bus; @c false otherwise.
|
||||
static constexpr auto is_1mhz = [](const uint16_t address) {
|
||||
if(address < 0xfe00 || address >= 0xff00) return false;
|
||||
// TODO: 1Mhz should apply only for "most of the SHEILA ($FExx) devices, except for the Econet, floppy,
|
||||
// Tube, VIDPROC, and memory mapping registers."
|
||||
return true;
|
||||
// Fast exit if outside the IO space.
|
||||
if(address < 0xfc00) return false;
|
||||
if(address >= 0xff00) return false;
|
||||
|
||||
// Pages FC ('Fred'), FD ('Jim').
|
||||
if(address < 0xfe00) return true;
|
||||
|
||||
// The 6845, 6850 and serial ULA.
|
||||
if(address < 0xfe18) return true;
|
||||
|
||||
// The two VIAs.
|
||||
if(address >= 0xfe40 && address < 0xfe80) return true;
|
||||
|
||||
// The ADC.
|
||||
if(address >= 0xfec0 && address < 0xfee0) return true;
|
||||
|
||||
// Otherwise: in IO space, but not a 1Mhz device.
|
||||
return false;
|
||||
};
|
||||
|
||||
// Determine whether this access hits the 1Mhz bus; if so then apply appropriate penalty,
|
||||
// and update phase.
|
||||
// Determine whether this access hits the 1Mhz bus; if so then apply appropriate penalty, and update phase.
|
||||
const auto duration = is_1mhz(address) ? Cycles(2 + (phase_&1)) : Cycles(1);
|
||||
phase_ += duration.as<int>();
|
||||
|
||||
// TODO: advance subsystems.
|
||||
|
||||
//
|
||||
// Dependent device updates.
|
||||
//
|
||||
const auto half_cycles = HalfCycles(duration.as_integral());
|
||||
system_via_.run_for(half_cycles);
|
||||
user_via_.run_for(half_cycles);
|
||||
|
||||
|
||||
//
|
||||
// Check for an IO access; if found then perform that and exit.
|
||||
//
|
||||
if(address >= 0xfc00 && address < 0xff00) {
|
||||
|
||||
// TODO:
|
||||
//
|
||||
// fe00 - CRTC select register/read from status.
|
||||
// fe01 - CRTC write/read register.
|
||||
// (mirrored up to fe08)
|
||||
//
|
||||
// fe08 - 6850 read/write.
|
||||
// (mirrored up to fe10)
|
||||
//
|
||||
|
||||
Logger::error().append("Unhandled IO access at %04x", address);
|
||||
return duration;
|
||||
}
|
||||
|
||||
//
|
||||
// ROM or RAM access.
|
||||
//
|
||||
if(is_read(operation)) {
|
||||
*value = memory_[address >> 14][address];
|
||||
} else {
|
||||
@@ -111,6 +164,11 @@ private:
|
||||
m6502_.run_for(cycles);
|
||||
}
|
||||
|
||||
// MARK: - IRQDelegatePortHandler::Delegate.
|
||||
void mos6522_did_change_interrupt_status(void *) override {
|
||||
update_irq_line();
|
||||
}
|
||||
|
||||
// MARK: - Clock phase.
|
||||
int phase_ = 0;
|
||||
|
||||
@@ -145,6 +203,18 @@ private:
|
||||
|
||||
// MARK: - Components.
|
||||
CPU::MOS6502::Processor<CPU::MOS6502::Personality::P6502, ConcreteMachine, false> m6502_;
|
||||
|
||||
UserVIAPortHandler user_via_port_handler_;
|
||||
SystemVIAPortHandler system_via_port_handler_;
|
||||
MOS::MOS6522::MOS6522<UserVIAPortHandler> user_via_;
|
||||
MOS::MOS6522::MOS6522<SystemVIAPortHandler> system_via_;
|
||||
|
||||
void update_irq_line() {
|
||||
m6502_.set_irq_line(
|
||||
user_via_.get_interrupt_line() ||
|
||||
system_via_.get_interrupt_line()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user