From f576baf2141f3525d942bf90e2b5baea953164e1 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 30 Jul 2021 21:21:16 -0400 Subject: [PATCH] I'm not yet sure this is the best approach, but starts trying to make use of Lorenz's 6526 tests. --- .../Bridges/TestMachine6502.h | 1 + .../Bridges/TestMachine6502.mm | 12 +++-- .../WolfgangLorenzTests.swift | 27 +++++++++-- Processors/6502/AllRAM/6502AllRAM.cpp | 47 +++++++++++++++++-- Processors/6502/AllRAM/6502AllRAM.hpp | 4 +- 5 files changed, 78 insertions(+), 13 deletions(-) diff --git a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.h b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.h index 4302e91d7..af729db05 100644 --- a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.h +++ b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.h @@ -35,6 +35,7 @@ extern const uint8_t CSTestMachine6502JamOpcode; - (nonnull instancetype)init NS_UNAVAILABLE; +- (nonnull instancetype)initWithProcessor:(CSTestMachine6502Processor)processor hasCIAs:(BOOL)hasCIAs; - (nonnull instancetype)initWithProcessor:(CSTestMachine6502Processor)processor; - (void)setData:(nonnull NSData *)data atAddress:(uint32_t)startAddress; diff --git a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.mm b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.mm index 4a2885cdd..5ced2a41b 100644 --- a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.mm +++ b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.mm @@ -39,25 +39,29 @@ static CPU::MOS6502::Register registerForRegister(CSTestMachine6502Register reg) #pragma mark - Lifecycle -- (instancetype)initWithProcessor:(CSTestMachine6502Processor)processor { +- (instancetype)initWithProcessor:(CSTestMachine6502Processor)processor hasCIAs:(BOOL)hasCIAs { self = [super init]; if(self) { switch(processor) { case CSTestMachine6502Processor6502: - _processor = CPU::MOS6502::AllRAMProcessor::Processor(CPU::MOS6502Esque::Type::T6502); + _processor = CPU::MOS6502::AllRAMProcessor::Processor(CPU::MOS6502Esque::Type::T6502, hasCIAs); break; case CSTestMachine6502Processor65C02: - _processor = CPU::MOS6502::AllRAMProcessor::Processor(CPU::MOS6502Esque::Type::TWDC65C02); + _processor = CPU::MOS6502::AllRAMProcessor::Processor(CPU::MOS6502Esque::Type::TWDC65C02, hasCIAs); break; case CSTestMachine6502Processor65816: - _processor = CPU::MOS6502::AllRAMProcessor::Processor(CPU::MOS6502Esque::Type::TWDC65816); + _processor = CPU::MOS6502::AllRAMProcessor::Processor(CPU::MOS6502Esque::Type::TWDC65816, hasCIAs); } } return self; } +- (nonnull instancetype)initWithProcessor:(CSTestMachine6502Processor)processor { + return [self initWithProcessor:processor hasCIAs:NO]; +} + - (void)dealloc { delete _processor; } diff --git a/OSBindings/Mac/Clock SignalTests/WolfgangLorenzTests.swift b/OSBindings/Mac/Clock SignalTests/WolfgangLorenzTests.swift index d29b0dc9b..9e6466923 100644 --- a/OSBindings/Mac/Clock SignalTests/WolfgangLorenzTests.swift +++ b/OSBindings/Mac/Clock SignalTests/WolfgangLorenzTests.swift @@ -226,6 +226,13 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachineTrapHandler { /* The NOP tests also don't apply; the 65816 has only one, well-defined NOP. */ + // MARK: - CIA Tests + + func testCIA1TA() { + runTest("cia1ta", suffixes: [""], processor: .processor6502) + } + + // MARK: - Collections func testTransfers(processor: CSTestMachine6502Processor) { @@ -284,10 +291,13 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachineTrapHandler { fileprivate func runTest(_ name: String, processor: CSTestMachine6502Processor) { var machine: CSTestMachine6502! - if let filename = Bundle(for: type(of: self)).path(forResource: name, ofType: nil) { - if let testData = try? Data(contentsOf: URL(fileURLWithPath: filename)) { + let bundle = Bundle(for: type(of: self)) + let mainBundle = Bundle.main + if let testFilename = bundle.url(forResource: name, withExtension: nil), + let kernelFilename = mainBundle.url(forResource: "kernal.901227-02", withExtension: "bin", subdirectory: "ROMImages/Commodore64") { + if let testData = try? Data(contentsOf: testFilename), let kernelData = try? Data(contentsOf: kernelFilename) { - machine = CSTestMachine6502(processor: processor) + machine = CSTestMachine6502(processor: processor, hasCIAs: true) machine.trapHandler = self output = "" @@ -296,9 +306,18 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachineTrapHandler { let contents = testData.subdata(in: 2 ..< testData.count) machine.setData(contents, atAddress: loadAddress) + machine.setData(kernelData, atAddress: 0xe000) // Cf. http://www.softwolves.com/arkiv/cbm-hackers/7/7114.html for the steps being taken here. + // Signal in-border, set up NMI and IRQ vectors as defaults. + machine.setValue(0xff, forAddress: 0xd011) + + machine.setValue(0x66, forAddress: 0x0316) + machine.setValue(0xfe, forAddress: 0x0317) + machine.setValue(0x31, forAddress: 0x0314) + machine.setValue(0xea, forAddress: 0x0315) + // Initialise memory locations as instructed. machine.setValue(0x00, forAddress: 0x0002) machine.setValue(0x00, forAddress: 0xa002) @@ -345,7 +364,7 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachineTrapHandler { } if machine == nil { - NSException(name: NSExceptionName(rawValue: "Failed Test"), reason: "Couldn't load file \(name)", userInfo: nil).raise() + NSException(name: NSExceptionName(rawValue: "Failed Test"), reason: "Couldn't load kernel, or file \(name)", userInfo: nil).raise() } while machine.value(for: .lastOperationAddress) != 0xe16f && !machine.isJammed { diff --git a/Processors/6502/AllRAM/6502AllRAM.cpp b/Processors/6502/AllRAM/6502AllRAM.cpp index 81cd4d2bd..8825893e0 100644 --- a/Processors/6502/AllRAM/6502AllRAM.cpp +++ b/Processors/6502/AllRAM/6502AllRAM.cpp @@ -11,6 +11,8 @@ #include #include +#include "../../../Components/6526/6526.hpp" + //#define BE_NOISY using namespace CPU::MOS6502; @@ -19,17 +21,24 @@ namespace { using Type = CPU::MOS6502Esque::Type; -template class ConcreteAllRAMProcessor: public AllRAMProcessor, public BusHandler { +template class ConcreteAllRAMProcessor: public AllRAMProcessor, public BusHandler { public: ConcreteAllRAMProcessor(size_t memory_size) : AllRAMProcessor(memory_size), - mos6502_(*this) { + mos6502_(*this), + cia1_(cia1_handler_), + cia2_(cia2_handler_) { mos6502_.set_power_on(false); } inline Cycles perform_bus_operation(BusOperation operation, uint32_t address, uint8_t *value) { timestamp_ += Cycles(1); + if constexpr (has_cias) { + cia1_.run_for(HalfCycles(2)); + cia2_.run_for(HalfCycles(2)); + } + if(isAccessOperation(operation)) { if(operation == BusOperation::ReadOpcode) { #ifdef BE_NOISY @@ -46,6 +55,16 @@ template class ConcreteAllRAMProcessor: public AllRAMProcessor, publ if(isReadOperation(operation)) { *value = memory_[address]; + + if constexpr (has_cias) { + if((address & 0xff00) == 0xdc00) { + *value = cia1_.read(address); + } else if((address & 0xff00) == 0xdd00) { + *value = cia2_.read(address); + } + + } + #ifdef BE_NOISY // if((address&0xff00) == 0x100) { printf("%04x -> %02x\n", address, *value); @@ -53,6 +72,14 @@ template class ConcreteAllRAMProcessor: public AllRAMProcessor, publ #endif } else { memory_[address] = *value; + + if constexpr (has_cias) { + if((address & 0xff00) == 0xdc00) { + cia1_.write(address, *value); + } else if((address & 0xff00) == 0xdd00) { + cia2_.write(address, *value); + } + } #ifdef BE_NOISY // if((address&0xff00) == 0x100) { printf("%04x <- %02x\n", address, *value); @@ -61,6 +88,9 @@ template class ConcreteAllRAMProcessor: public AllRAMProcessor, publ } } + mos6502_.set_irq_line(cia1_.get_interrupt_line()); + mos6502_.set_nmi_line(cia2_.get_interrupt_line()); + return Cycles(1); } @@ -98,12 +128,21 @@ template class ConcreteAllRAMProcessor: public AllRAMProcessor, publ private: CPU::MOS6502Esque::Processor mos6502_; int instructions_ = 0; + + class PortHandler: public MOS::MOS6526::PortHandler {}; + PortHandler cia1_handler_, cia2_handler_; + + MOS::MOS6526::MOS6526 cia1_, cia2_; }; } -AllRAMProcessor *AllRAMProcessor::Processor(Type type) { -#define Bind(p) case p: return new ConcreteAllRAMProcessor

(type == Type::TWDC65816 ? 16*1024*1024 : 64*1024); +AllRAMProcessor *AllRAMProcessor::Processor(Type type, bool has_cias) { +#define Bind(p) \ + case p: \ + if(has_cias) return new ConcreteAllRAMProcessor(type == Type::TWDC65816 ? 16*1024*1024 : 64*1024); \ + else return new ConcreteAllRAMProcessor(type == Type::TWDC65816 ? 16*1024*1024 : 64*1024); \ + switch(type) { default: Bind(Type::T6502) diff --git a/Processors/6502/AllRAM/6502AllRAM.hpp b/Processors/6502/AllRAM/6502AllRAM.hpp index e397896ff..848d4e7de 100644 --- a/Processors/6502/AllRAM/6502AllRAM.hpp +++ b/Processors/6502/AllRAM/6502AllRAM.hpp @@ -18,7 +18,7 @@ namespace MOS6502 { class AllRAMProcessor: public ::CPU::AllRAMProcessor { public: - static AllRAMProcessor *Processor(CPU::MOS6502Esque::Type type); + static AllRAMProcessor *Processor(CPU::MOS6502Esque::Type type, bool has_cias = false); virtual ~AllRAMProcessor() {} virtual void run_for(const Cycles cycles) = 0; @@ -29,6 +29,8 @@ class AllRAMProcessor: virtual uint16_t get_value_of_register(Register r) = 0; virtual void set_value_of_register(Register r, uint16_t value) = 0; + + protected: AllRAMProcessor(size_t memory_size) : ::CPU::AllRAMProcessor(memory_size) {} };