mirror of
https://github.com/TomHarte/CLK.git
synced 2026-04-21 17:16:44 +00:00
Refactors the Z80 to separate out interface and implementation.
Following the pattern just established by the 6502, puts all implementation specifics beyond the visibility of a human reading Z80.hpp and in subfolders so as to promote the idea that they shouldn't go out of their way.
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
//
|
||||
// Z80AllRAM.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 16/05/2017.
|
||||
// Copyright © 2017 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Z80AllRAM.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace CPU::Z80;
|
||||
namespace {
|
||||
|
||||
class ConcreteAllRAMProcessor: public AllRAMProcessor, public BusHandler {
|
||||
public:
|
||||
ConcreteAllRAMProcessor() : AllRAMProcessor(), z80_(*this) {}
|
||||
|
||||
inline HalfCycles perform_machine_cycle(const PartialMachineCycle &cycle) {
|
||||
timestamp_ += cycle.length;
|
||||
if(!cycle.is_terminal()) {
|
||||
return HalfCycles(0);
|
||||
}
|
||||
|
||||
uint16_t address = cycle.address ? *cycle.address : 0x0000;
|
||||
switch(cycle.operation) {
|
||||
case PartialMachineCycle::ReadOpcode:
|
||||
check_address_for_trap(address);
|
||||
case PartialMachineCycle::Read:
|
||||
*cycle.value = memory_[address];
|
||||
break;
|
||||
case PartialMachineCycle::Write:
|
||||
memory_[address] = *cycle.value;
|
||||
break;
|
||||
|
||||
case PartialMachineCycle::Output:
|
||||
break;
|
||||
case PartialMachineCycle::Input:
|
||||
// This logic is selected specifically because it seems to match
|
||||
// the FUSE unit tests. It might need factoring out.
|
||||
*cycle.value = address >> 8;
|
||||
break;
|
||||
|
||||
case PartialMachineCycle::Internal:
|
||||
case PartialMachineCycle::Refresh:
|
||||
break;
|
||||
|
||||
case PartialMachineCycle::Interrupt:
|
||||
// A pick that means LD HL, (nn) if interpreted as an instruction but is otherwise
|
||||
// arbitrary.
|
||||
*cycle.value = 0x21;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("???\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if(delegate_ != nullptr) {
|
||||
delegate_->z80_all_ram_processor_did_perform_bus_operation(*this, cycle.operation, address, cycle.value ? *cycle.value : 0x00, timestamp_);
|
||||
}
|
||||
|
||||
return HalfCycles(0);
|
||||
}
|
||||
|
||||
void run_for(const Cycles cycles) {
|
||||
z80_.run_for(cycles);
|
||||
}
|
||||
|
||||
uint16_t get_value_of_register(Register r) {
|
||||
return z80_.get_value_of_register(r);
|
||||
}
|
||||
|
||||
void set_value_of_register(Register r, uint16_t value) {
|
||||
z80_.set_value_of_register(r, value);
|
||||
}
|
||||
|
||||
bool get_halt_line() {
|
||||
return z80_.get_halt_line();
|
||||
}
|
||||
|
||||
void reset_power_on() {
|
||||
return z80_.reset_power_on();
|
||||
}
|
||||
|
||||
void set_interrupt_line(bool value) {
|
||||
z80_.set_interrupt_line(value);
|
||||
}
|
||||
|
||||
void set_non_maskable_interrupt_line(bool value) {
|
||||
z80_.set_non_maskable_interrupt_line(value);
|
||||
}
|
||||
|
||||
void set_wait_line(bool value) {
|
||||
z80_.set_wait_line(value);
|
||||
}
|
||||
|
||||
private:
|
||||
CPU::Z80::Processor<ConcreteAllRAMProcessor, false, true> z80_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
AllRAMProcessor *AllRAMProcessor::Processor() {
|
||||
return new ConcreteAllRAMProcessor;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// Z80AllRAM.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 16/05/2017.
|
||||
// Copyright © 2017 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef Z80AllRAM_hpp
|
||||
#define Z80AllRAM_hpp
|
||||
|
||||
#include "../Z80.hpp"
|
||||
#include "../../AllRAMProcessor.hpp"
|
||||
|
||||
namespace CPU {
|
||||
namespace Z80 {
|
||||
|
||||
class AllRAMProcessor:
|
||||
public ::CPU::AllRAMProcessor {
|
||||
|
||||
public:
|
||||
static AllRAMProcessor *Processor();
|
||||
|
||||
struct MemoryAccessDelegate {
|
||||
virtual void z80_all_ram_processor_did_perform_bus_operation(CPU::Z80::AllRAMProcessor &processor, CPU::Z80::PartialMachineCycle::Operation operation, uint16_t address, uint8_t value, HalfCycles time_stamp) = 0;
|
||||
};
|
||||
inline void set_memory_access_delegate(MemoryAccessDelegate *delegate) {
|
||||
delegate_ = delegate;
|
||||
}
|
||||
|
||||
virtual void run_for(const Cycles cycles) = 0;
|
||||
virtual uint16_t get_value_of_register(Register r) = 0;
|
||||
virtual void set_value_of_register(Register r, uint16_t value) = 0;
|
||||
virtual bool get_halt_line() = 0;
|
||||
virtual void reset_power_on() = 0;
|
||||
|
||||
virtual void set_interrupt_line(bool value) = 0;
|
||||
virtual void set_non_maskable_interrupt_line(bool value) = 0;
|
||||
virtual void set_wait_line(bool value) = 0;
|
||||
|
||||
protected:
|
||||
MemoryAccessDelegate *delegate_;
|
||||
AllRAMProcessor() : ::CPU::AllRAMProcessor(65536), delegate_(nullptr) {}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* Z80AllRAM_hpp */
|
||||
Reference in New Issue
Block a user