1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-09-25 08:25:09 +00:00

Merge pull request #1568 from TomHarte/BBC1770

Add 1770 DFS support.
This commit is contained in:
Thomas Harte
2025-09-19 23:20:29 -04:00
committed by GitHub
10 changed files with 88 additions and 18 deletions

View File

@@ -38,12 +38,15 @@ private:
struct BBCMicroTarget: public ::Analyser::Static::Target, public Reflection::StructImpl<BBCMicroTarget> {
std::string loading_command;
bool has_1770dfs = false;
BBCMicroTarget() : Analyser::Static::Target(Machine::BBCMicro) {}
private:
friend Reflection::StructImpl<BBCMicroTarget>;
void declare_fields() {}
void declare_fields() {
DeclareField(has_1770dfs);
}
};
struct ArchimedesTarget: public ::Analyser::Static::Target, public Reflection::StructImpl<ArchimedesTarget> {

View File

@@ -114,6 +114,7 @@ uint8_t WD1770::read(const int address) {
update_status([] (Status &status) {
status.data_request = false;
});
// Logger::info().append("Returned data %02x; [drq:%d]", data_, status_.data_request);
return data_;
}
}
@@ -486,8 +487,12 @@ void WD1770::posit_event(const int new_event_type) {
WAIT_FOR_EVENT(Event::Token);
if(get_latest_token().type != Token::Byte) goto type2_read_byte;
data_ = get_latest_token().byte_value;
// Logger::info().append("Posting %02x", data_);
update_status([] (Status &status) {
status.lost_data |= status.data_request;
// if(status.lost_data) {
// Logger::info().append("Lost data");
// }
status.data_request = true;
});
distance_into_section_++;

View File

@@ -20,6 +20,9 @@
#include "Components/6850/6850.hpp"
#include "Components/uPD7002/uPD7002.hpp"
// TODO: factor this more appropriately.
#include "Machines/Acorn/Electron/Plus3.hpp"
#include "Analyser/Static/Acorn/Target.hpp"
#include "Outputs/Log.hpp"
@@ -457,14 +460,17 @@ using CRTC = Motorola::CRTC::CRTC6845<
Motorola::CRTC::CursorType::None>;
}
template <bool has_1770>
class ConcreteMachine:
public Machine,
public MachineTypes::AudioProducer,
public MachineTypes::MappedKeyboardMachine,
public MachineTypes::MediaTarget,
public MachineTypes::ScanProducer,
public MachineTypes::TimedMachine,
public MOS::MOS6522::IRQDelegatePortHandler::Delegate,
public NEC::uPD7002::Delegate
public NEC::uPD7002::Delegate,
public WD::WD1770::Delegate
{
public:
ConcreteMachine(
@@ -488,7 +494,12 @@ public:
// Grab ROMs.
using Request = ::ROM::Request;
using Name = ::ROM::Name;
const auto request = Request(Name::AcornBASICII) && Request(Name::BBCMicroMOS12);
auto request = Request(Name::AcornBASICII) && Request(Name::BBCMicroMOS12);
if(target.has_1770dfs) {
request = request && Request(Name::AcornDFS226);
}
auto roms = rom_fetcher(request);
if(!request.validate(roms)) {
throw ROMMachine::Error::MissingROMs;
@@ -498,6 +509,9 @@ public:
std::copy(os_data.begin(), os_data.end(), os_.begin());
install_sideways(15, roms.find(Name::AcornBASICII)->second, false);
if(target.has_1770dfs) {
install_sideways(14, roms.find(Name::AcornDFS226)->second, false);
}
// Setup fixed parts of memory map.
page(0, &ram_[0], true);
@@ -506,7 +520,11 @@ public:
page(3, os_.data(), false);
Memory::Fuzz(ram_);
(void)target;
if constexpr (has_1770) {
wd1770_.set_delegate(this);
}
insert_media(target.media);
}
// MARK: - 6502 bus.
@@ -538,7 +556,7 @@ public:
};
// 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);
const auto duration = Cycles(is_1mhz(address) ? 2 + (phase_&1) : 1);
phase_ += duration.as<int>();
@@ -565,6 +583,11 @@ public:
adc_.run_for(duration);
if constexpr (has_1770) {
// The WD1770 is nominally clocked at 8Mhz.
wd1770_.run_for(duration * 4);
}
//
// Questionably-clocked devices.
//
@@ -642,6 +665,21 @@ public:
} else {
adc_.write(address, *value);
}
} else if(has_1770 && address >= 0xfe80 && address < 0xfe88) {
switch(address) {
case 0xfe80:
if(!is_read(operation)) {
wd1770_.set_control_register(*value);
}
break;
default:
if(is_read(operation)) {
*value = wd1770_.read(address);
} else {
wd1770_.write(address, *value);
}
break;
}
}
else {
Logger::error()
@@ -720,6 +758,15 @@ private:
update_irq_line();
}
// MARK: - MediaTarget.
bool insert_media(const Analyser::Static::Media &media) override {
if(!media.disks.empty() && has_1770) {
wd1770_.set_disk(media.disks.front(), 0);
}
return !media.disks.empty();
}
// MARK: - Clock phase.
int phase_ = 0;
@@ -778,6 +825,12 @@ private:
Motorola::ACIA::ACIA acia_;
NEC::uPD7002 adc_;
// MARK: - WD1770.
Electron::Plus3 wd1770_;
void wd1770_did_change_output(WD::WD1770 &) override {
m6502_.set_nmi_line(wd1770_.get_interrupt_request_line() || wd1770_.get_data_request_line());
}
};
}
@@ -790,5 +843,9 @@ std::unique_ptr<Machine> Machine::BBCMicro(
) {
using Target = Analyser::Static::Acorn::BBCMicroTarget;
const Target *const acorn_target = dynamic_cast<const Target *>(target);
return std::make_unique<BBCMicro::ConcreteMachine>(*acorn_target, rom_fetcher);
if(acorn_target->has_1770dfs) {
return std::make_unique<BBCMicro::ConcreteMachine<true>>(*acorn_target, rom_fetcher);
} else {
return std::make_unique<BBCMicro::ConcreteMachine<false>>(*acorn_target, rom_fetcher);
}
}

View File

@@ -36,6 +36,7 @@ void Plus3::set_control_register(uint8_t control) {
// bit 1 => enable or disable drive 2
// bit 2 => side select
// bit 3 => single density select
// bit 5 => reset?
uint8_t changes = control ^ last_control_;
last_control_ = control;

View File

@@ -429,6 +429,14 @@ const std::vector<Description> &Description::all_roms() {
16_kb,
0x3c14fc70u
},
{
AcornDFS226,
"BBCMicro",
"the Acorn 1770 DFS 2.26 ROM",
"dfs-2.26.rom",
16_kb,
0x5ae33e94u
},
//
// ColecoVision.

View File

@@ -82,6 +82,7 @@ enum Name {
// BBC Micro.
BBCMicroMOS12,
AcornDFS226,
// ColecoVision.
ColecoVisionBIOS,

View File

@@ -165,10 +165,9 @@
if(self) {
auto target = std::make_unique<Analyser::Static::Acorn::BBCMicroTarget>();
// TODO.
(void)dfs;
(void)adfs;
(void)sidewaysRAM;
// target->has_dfs = dfs;
target->has_1770dfs = dfs;
// target->has_pres_adfs = adfs;
// target->has_ap6_rom = ap6;
// target->has_sideways_ram = sidewaysRAM;

View File

@@ -194,13 +194,10 @@ void Processor<personality, T, uses_ready_line>::run_for(const Cycles cycles) {
case OperationRSTPickVector: next_address_.full = 0xfffc; continue;
case CycleReadVectorLow: read_mem(pc_.halves.low, next_address_.full); break;
case CycleReadVectorHigh: read_mem(pc_.halves.high, next_address_.full+1); break;
case OperationSetIRQFlags:
case OperationSetInterruptFlags:
flags_.inverse_interrupt = 0;
if(is_65c02(personality)) flags_.decimal = 0;
continue;
case OperationSetNMIRSTFlags:
if(is_65c02(personality)) flags_.decimal = 0;
continue;
case CyclePullPCL: s_++; read_mem(pc_.halves.low, s_ | 0x100); break;
case CyclePullPCH: s_++; read_mem(pc_.halves.high, s_ | 0x100); break;

View File

@@ -77,7 +77,7 @@ using namespace CPU::MOS6502;
ProcessorStorage::ProcessorStorage(Personality personality) {
const InstructionList operations_6502[] = {
/* 0x00 BRK */ Program(CycleIncPCPushPCH, CyclePushPCL, OperationBRKPickVector, OperationSetOperandFromFlagsWithBRKSet, CyclePushOperand, OperationSetIRQFlags, CycleReadVectorLow, CycleReadVectorHigh),
/* 0x00 BRK */ Program(CycleIncPCPushPCH, CyclePushPCL, OperationBRKPickVector, OperationSetOperandFromFlagsWithBRKSet, CyclePushOperand, OperationSetInterruptFlags, CycleReadVectorLow, CycleReadVectorHigh),
/* 0x01 ORA x, ind */ IndexedIndirectRead(OperationORA),
/* 0x02 JAM */ JAM, /* 0x03 ASO x, ind */ IndexedIndirectReadModifyWrite(OperationASO),
/* 0x04 NOP zpg */ ZeroNop(), /* 0x05 ORA zpg */ ZeroRead(OperationORA),
@@ -228,7 +228,7 @@ ProcessorStorage::ProcessorStorage(Personality personality) {
CycleNoWritePush,
OperationRSTPickVector,
CycleNoWritePush,
OperationSetNMIRSTFlags,
OperationSetInterruptFlags,
CycleReadVectorLow,
CycleReadVectorHigh
),
@@ -242,7 +242,7 @@ ProcessorStorage::ProcessorStorage(Personality personality) {
OperationBRKPickVector,
OperationSetOperandFromFlags,
CyclePushOperand,
OperationSetIRQFlags,
OperationSetInterruptFlags,
CycleReadVectorLow,
CycleReadVectorHigh
),
@@ -256,7 +256,7 @@ ProcessorStorage::ProcessorStorage(Personality personality) {
OperationNMIPickVector,
OperationSetOperandFromFlags,
CyclePushOperand,
OperationSetNMIRSTFlags,
OperationSetInterruptFlags,
CycleReadVectorLow,
CycleReadVectorHigh
),

View File

@@ -35,8 +35,7 @@ class ProcessorStorage {
CyclePushY, // pushes Y to the stack
CyclePushOperand, // pushes operand_ to the stack
OperationSetIRQFlags, // 6502: sets I; 65C02: sets I and resets D
OperationSetNMIRSTFlags, // 6502: no-op. 65C02: resets D
OperationSetInterruptFlags, // 6502: sets I; 65C02: sets I and resets D
OperationBRKPickVector, // 65C02: sets next_address_ to the BRK vector location; 6502: as 65C02 if no NMI is pending; otherwise sets next_address_ to the NMI address and resets the internal NMI-pending flag
OperationNMIPickVector, // sets next_address_ to the NMI vector