mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-12 00:30:31 +00:00
I'm not yet sure this is the best approach, but starts trying to make use of Lorenz's 6526 tests.
This commit is contained in:
parent
5c1ac05170
commit
f576baf214
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
#include "../../../Components/6526/6526.hpp"
|
||||
|
||||
//#define BE_NOISY
|
||||
|
||||
using namespace CPU::MOS6502;
|
||||
@ -19,17 +21,24 @@ namespace {
|
||||
|
||||
using Type = CPU::MOS6502Esque::Type;
|
||||
|
||||
template <Type type> class ConcreteAllRAMProcessor: public AllRAMProcessor, public BusHandler {
|
||||
template <Type type, bool has_cias> 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 <Type type> 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 <Type type> 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 <Type type> 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 <Type type> class ConcreteAllRAMProcessor: public AllRAMProcessor, publ
|
||||
private:
|
||||
CPU::MOS6502Esque::Processor<type, ConcreteAllRAMProcessor, false> mos6502_;
|
||||
int instructions_ = 0;
|
||||
|
||||
class PortHandler: public MOS::MOS6526::PortHandler {};
|
||||
PortHandler cia1_handler_, cia2_handler_;
|
||||
|
||||
MOS::MOS6526::MOS6526<PortHandler, MOS::MOS6526::Personality::P6526> cia1_, cia2_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
AllRAMProcessor *AllRAMProcessor::Processor(Type type) {
|
||||
#define Bind(p) case p: return new ConcreteAllRAMProcessor<p>(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<p, true>(type == Type::TWDC65816 ? 16*1024*1024 : 64*1024); \
|
||||
else return new ConcreteAllRAMProcessor<p, false>(type == Type::TWDC65816 ? 16*1024*1024 : 64*1024); \
|
||||
|
||||
switch(type) {
|
||||
default:
|
||||
Bind(Type::T6502)
|
||||
|
@ -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) {}
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user