diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 1cc8e6880..5a1ab50bb 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 4B018B89211930DE002A3937 /* 65C02_extended_opcodes_test.bin in Resources */ = {isa = PBXBuildFile; fileRef = 4B018B88211930DE002A3937 /* 65C02_extended_opcodes_test.bin */; }; 4B01A6881F22F0DB001FD6E3 /* Z80MemptrTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B01A6871F22F0DB001FD6E3 /* Z80MemptrTests.swift */; }; 4B0333AF2094081A0050B93D /* AppleDSK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0333AD2094081A0050B93D /* AppleDSK.cpp */; }; 4B0333B02094081A0050B93D /* AppleDSK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0333AD2094081A0050B93D /* AppleDSK.cpp */; }; @@ -690,6 +691,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 4B018B88211930DE002A3937 /* 65C02_extended_opcodes_test.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; name = 65C02_extended_opcodes_test.bin; path = "Klaus Dormann/65C02_extended_opcodes_test.bin"; sourceTree = ""; }; 4B01A6871F22F0DB001FD6E3 /* Z80MemptrTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80MemptrTests.swift; sourceTree = ""; }; 4B0333AD2094081A0050B93D /* AppleDSK.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AppleDSK.cpp; sourceTree = ""; }; 4B0333AE2094081A0050B93D /* AppleDSK.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = AppleDSK.hpp; sourceTree = ""; }; @@ -1545,14 +1547,15 @@ 4B1414631B588A1100E04248 /* Test Binaries */ = { isa = PBXGroup; children = ( - 4B98A1CD1FFADEC400ADF63B /* MSX ROMs */, 4B9252CD1E74D28200B76AF1 /* Atari ROMs */, 4B44EBF81DC9898E00A7820C /* BCDTEST_beeb */, + 4B98A1CD1FFADEC400ADF63B /* MSX ROMs */, + 4B018B88211930DE002A3937 /* 65C02_extended_opcodes_test.bin */, 4B44EBF61DC9883B00A7820C /* 6502_functional_test.bin */, 4B44EBF41DC987AE00A7820C /* AllSuiteA.bin */, - 4BE9A6B21EDE294200CBCB47 /* Zexall */, 4BBF49B41ED2881600AB3669 /* FUSE */, 4BB297E41B587D8300A49093 /* Wolfgang Lorenz 6502 test suite */, + 4BE9A6B21EDE294200CBCB47 /* Zexall */, ); name = "Test Binaries"; sourceTree = ""; @@ -3330,6 +3333,7 @@ 4BB2998A1B587D8400A49093 /* lseix in Resources */, 4BB2994E1B587D8400A49093 /* dexn in Resources */, 4BB299971B587D8400A49093 /* nopa in Resources */, + 4B018B89211930DE002A3937 /* 65C02_extended_opcodes_test.bin in Resources */, 4BFCA1291ECBE7A700AC40C1 /* zexall.com in Resources */, 4BB299521B587D8400A49093 /* eoray in Resources */, 4BB299411B587D8400A49093 /* cpyb in Resources */, diff --git a/OSBindings/Mac/Clock SignalTests/6502InterruptTests.swift b/OSBindings/Mac/Clock SignalTests/6502InterruptTests.swift index 98c9c6b8c..a6c0def50 100644 --- a/OSBindings/Mac/Clock SignalTests/6502InterruptTests.swift +++ b/OSBindings/Mac/Clock SignalTests/6502InterruptTests.swift @@ -15,7 +15,7 @@ class MOS6502InterruptTests: XCTestCase { super.setUp() // create a machine full of NOPs - machine = CSTestMachine6502() + machine = CSTestMachine6502(is65C02: false) for c in 0...65535 { machine.setValue(0xea, forAddress: UInt16(c)) } diff --git a/OSBindings/Mac/Clock SignalTests/6502TimingTests.swift b/OSBindings/Mac/Clock SignalTests/6502TimingTests.swift index fdccca3a7..514b41413 100644 --- a/OSBindings/Mac/Clock SignalTests/6502TimingTests.swift +++ b/OSBindings/Mac/Clock SignalTests/6502TimingTests.swift @@ -12,7 +12,7 @@ import XCTest class MOS6502TimingTests: XCTestCase, CSTestMachineTrapHandler { private var endTime: UInt32 = 0 - private let machine = CSTestMachine6502() + private let machine = CSTestMachine6502(is65C02: false) func testImplied() { let code: [UInt8] = [ diff --git a/OSBindings/Mac/Clock SignalTests/AllSuiteATests.swift b/OSBindings/Mac/Clock SignalTests/AllSuiteATests.swift index 2aa7f992a..5c0a13607 100644 --- a/OSBindings/Mac/Clock SignalTests/AllSuiteATests.swift +++ b/OSBindings/Mac/Clock SignalTests/AllSuiteATests.swift @@ -13,7 +13,7 @@ class AllSuiteATests: XCTestCase { func testAllSuiteA() { if let filename = Bundle(for: type(of: self)).path(forResource: "AllSuiteA", ofType: "bin") { if let allSuiteA = try? Data(contentsOf: URL(fileURLWithPath: filename)) { - let machine = CSTestMachine6502() + let machine = CSTestMachine6502(is65C02: false) machine.setData(allSuiteA, atAddress: 0x4000) machine.setValue(CSTestMachine6502JamOpcode, forAddress:0x45c0); // end diff --git a/OSBindings/Mac/Clock SignalTests/BCDTest.swift b/OSBindings/Mac/Clock SignalTests/BCDTest.swift index 7dbcfa435..6eb9850b0 100644 --- a/OSBindings/Mac/Clock SignalTests/BCDTest.swift +++ b/OSBindings/Mac/Clock SignalTests/BCDTest.swift @@ -14,7 +14,7 @@ class BCDTest: XCTestCase, CSTestMachineTrapHandler { func testBCD() { if let filename = Bundle(for: type(of: self)).path(forResource: "BCDTEST_beeb", ofType: nil) { if let bcdTest = try? Data(contentsOf: URL(fileURLWithPath: filename)) { - let machine = CSTestMachine6502() + let machine = CSTestMachine6502(is65C02: false) machine.trapHandler = self machine.setData(bcdTest, atAddress: 0x2900) diff --git a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.h b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.h index 5d78b5306..59b5f0aed 100644 --- a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.h +++ b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.h @@ -23,7 +23,11 @@ extern const uint8_t CSTestMachine6502JamOpcode; @interface CSTestMachine6502 : CSTestMachine -- (void)setData:(NSData *)data atAddress:(uint16_t)startAddress; +- (nonnull instancetype)init NS_UNAVAILABLE; + +- (nonnull instancetype)initIs65C02:(BOOL)is65C02; + +- (void)setData:(nonnull NSData *)data atAddress:(uint16_t)startAddress; - (void)runForNumberOfCycles:(int)cycles; - (void)setValue:(uint8_t)value forAddress:(uint16_t)address; diff --git a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.mm b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.mm index 7477a0370..d5a7787e9 100644 --- a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.mm +++ b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.mm @@ -35,11 +35,12 @@ static CPU::MOS6502::Register registerForRegister(CSTestMachine6502Register reg) #pragma mark - Lifecycle -- (instancetype)init { +- (instancetype)initIs65C02:(BOOL)is65C02 { self = [super init]; if(self) { - _processor = CPU::MOS6502::AllRAMProcessor::Processor(CPU::MOS6502::Personality::P6502); + _processor = CPU::MOS6502::AllRAMProcessor::Processor( + is65C02 ? CPU::MOS6502::Personality::P65C02 : CPU::MOS6502::Personality::P6502); } return self; diff --git a/OSBindings/Mac/Clock SignalTests/Klaus Dormann/65C02_extended_opcodes_test.bin b/OSBindings/Mac/Clock SignalTests/Klaus Dormann/65C02_extended_opcodes_test.bin new file mode 100644 index 000000000..b1ea946a1 Binary files /dev/null and b/OSBindings/Mac/Clock SignalTests/Klaus Dormann/65C02_extended_opcodes_test.bin differ diff --git a/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift b/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift index 118a7cac7..f884413d2 100644 --- a/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift +++ b/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift @@ -11,10 +11,32 @@ import XCTest class KlausDormannTests: XCTestCase { - func testKlausDormann() { + fileprivate func runTest(resource: String, is65C02: Bool) -> UInt16 { + if let filename = Bundle(for: type(of: self)).path(forResource: resource, ofType: "bin") { + if let functionalTest = try? Data(contentsOf: URL(fileURLWithPath: filename)) { + let machine = CSTestMachine6502(is65C02: is65C02) + machine.setData(functionalTest, atAddress: 0) + machine.setValue(0x400, for: .programCounter) + + while true { + let oldPC = machine.value(for: .lastOperationAddress) + machine.runForNumber(ofCycles: 1000) + let newPC = machine.value(for: .lastOperationAddress) + + if newPC == oldPC { + return newPC + } + } + } + } + + return 0 + } + + /// Runs Klaus Dorman's 6502 tests. + func test6502() { func errorForTrapAddress(_ address: UInt16) -> String? { - let hexAddress = String(format:"%04x", address) switch address { case 0x3399: return nil // success! @@ -28,29 +50,35 @@ class KlausDormannTests: XCTestCase { case 0x26d2: return "ASL zpg,x produced incorrect flags" case 0x36c6: return "Unexpected RESET" - default: return "Unknown error at \(hexAddress)" + case 0: return "Didn't find tests" + + default: return "Unknown error at \(String(format:"%04x", address))" } } - if let filename = Bundle(for: type(of: self)).path(forResource: "6502_functional_test", ofType: "bin") { - if let functionalTest = try? Data(contentsOf: URL(fileURLWithPath: filename)) { - let machine = CSTestMachine6502() + let destination = runTest(resource: "6502_functional_test", is65C02: false) + let error = errorForTrapAddress(destination) + XCTAssert(error == nil, "Failed with error \(error!)") + } - machine.setData(functionalTest, atAddress: 0) - machine.setValue(0x400, for: .programCounter) + /// Runs Klaus Dorman's 65C02 tests. + func test65C02() { + func errorForTrapAddress(_ address: UInt16) -> String? { + switch address { + case 0x0423: return "PHX: value of X not on stack page" + case 0x0428: return "PHX: stack pointer not decremented" + case 0x042d: return "PLY: didn't acquire value 0xaa from stack" + case 0x0432: return "PLY: didn't acquire value 0x55 from stack" + case 0x0437: return "PLY: stack pointer not incremented" + case 0x043c: return "PLY: stack pointer not incremented" - while true { - let oldPC = machine.value(for: .lastOperationAddress) - machine.runForNumber(ofCycles: 1000) - let newPC = machine.value(for: .lastOperationAddress) - - if newPC == oldPC { - let error = errorForTrapAddress(oldPC) - XCTAssert(error == nil, "Failed with error \(error!)") - return - } - } + case 0: return "Didn't find tests" + default: return "Unknown error at \(String(format:"%04x", address))" } } + + let destination = runTest(resource: "65C02_extended_opcodes_test", is65C02: true) + let error = errorForTrapAddress(destination) + XCTAssert(error == nil, "Failed with error \(error!)") } } diff --git a/OSBindings/Mac/Clock SignalTests/WolfgangLorenzTests.swift b/OSBindings/Mac/Clock SignalTests/WolfgangLorenzTests.swift index 9f0660853..4ec9be87b 100644 --- a/OSBindings/Mac/Clock SignalTests/WolfgangLorenzTests.swift +++ b/OSBindings/Mac/Clock SignalTests/WolfgangLorenzTests.swift @@ -200,7 +200,7 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachineTrapHandler { if let filename = Bundle(for: type(of: self)).path(forResource: name, ofType: nil) { if let testData = try? Data(contentsOf: URL(fileURLWithPath: filename)) { - machine = CSTestMachine6502() + machine = CSTestMachine6502(is65C02: false) machine.trapHandler = self // machine.logActivity = true output = "" diff --git a/Processors/6502/Implementation/6502Storage.cpp b/Processors/6502/Implementation/6502Storage.cpp index c6a916b22..6dd33f569 100644 --- a/Processors/6502/Implementation/6502Storage.cpp +++ b/Processors/6502/Implementation/6502Storage.cpp @@ -69,7 +69,7 @@ using namespace CPU::MOS6502; #define JAM {CycleFetchOperand, CycleScheduleJam} -ProcessorStorage::ProcessorStorage(Personality) { +ProcessorStorage::ProcessorStorage(Personality personality) { // only the interrupt flag is defined upon reset but get_flags isn't going to // mask the other flags so we need to do that, at least carry_flag_ &= Flag::Carry; @@ -214,7 +214,13 @@ ProcessorStorage::ProcessorStorage(Personality) { /* 0xfe INC abs, x */ AbsoluteXReadModifyWrite(OperationINC), /* 0xff INS abs, x */ AbsoluteXReadModifyWrite(OperationINS), }; + // Install the basic 6502 table. memcpy(operations_, operations_6502, sizeof(operations_)); + + // Patch the table according to the chip's personality. + switch(personality) { + default: break; + } } #undef Program