From d910405648c60dbdf38998207e5d934ef02b7de0 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 19 May 2017 21:53:39 -0400 Subject: [PATCH] Added enough infrastructure to be able to react to the two CP/M calls this cares about. --- .../Bridges/TestMachineZ80.h | 8 ++++- .../Bridges/TestMachineZ80.mm | 13 +++++++ .../Mac/Clock SignalTests/ZexallTests.swift | 34 +++++++++++++++++-- Processors/AllRAMProcessor.cpp | 5 +++ Processors/AllRAMProcessor.hpp | 1 + 5 files changed, 57 insertions(+), 4 deletions(-) diff --git a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.h b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.h index 4498db824..de0fcced6 100644 --- a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.h +++ b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.h @@ -11,17 +11,23 @@ typedef NS_ENUM(NSInteger, CSTestMachineZ80Register) { CSTestMachineZ80RegisterProgramCounter, CSTestMachineZ80RegisterStackPointer, + + CSTestMachineZ80RegisterC, + CSTestMachineZ80RegisterE, + CSTestMachineZ80RegisterDE, }; @class CSTestMachineZ80; -@interface CSTestMachineTrapHandler +@protocol CSTestMachineTrapHandler - (void)testMachine:(CSTestMachineZ80 *)testMachine didTrapAtAddress:(uint16_t)address; @end @interface CSTestMachineZ80 : NSObject - (void)setData:(NSData *)data atAddress:(uint16_t)startAddress; +- (void)setValue:(uint8_t)value atAddress:(uint16_t)address; +- (uint8_t)valueAtAddress:(uint16_t)address; - (void)runForNumberOfCycles:(int)cycles; - (void)setValue:(uint16_t)value forRegister:(CSTestMachineZ80Register)reg; diff --git a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.mm b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.mm index badcb15e7..43dc096a6 100644 --- a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.mm +++ b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.mm @@ -33,6 +33,9 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) { switch (reg) { case CSTestMachineZ80RegisterProgramCounter: return CPU::Z80::Register::ProgramCounter; case CSTestMachineZ80RegisterStackPointer: return CPU::Z80::Register::StackPointer; + case CSTestMachineZ80RegisterC: return CPU::Z80::Register::C; + case CSTestMachineZ80RegisterE: return CPU::Z80::Register::E; + case CSTestMachineZ80RegisterDE: return CPU::Z80::Register::DE; } } @@ -71,6 +74,16 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) { _processor.set_value_of_register(registerForRegister(reg), value); } +- (void)setValue:(uint8_t)value atAddress:(uint16_t)address { + _processor.set_data_at_address(address, 1, &value); +} + +- (uint8_t)valueAtAddress:(uint16_t)address { + uint8_t value; + _processor.get_data_at_address(address, 1, &value); + return value; +} + - (uint16_t)valueForRegister:(CSTestMachineZ80Register)reg { return _processor.get_value_of_register(registerForRegister(reg)); } diff --git a/OSBindings/Mac/Clock SignalTests/ZexallTests.swift b/OSBindings/Mac/Clock SignalTests/ZexallTests.swift index 0246cd4cb..415775453 100644 --- a/OSBindings/Mac/Clock SignalTests/ZexallTests.swift +++ b/OSBindings/Mac/Clock SignalTests/ZexallTests.swift @@ -9,21 +9,49 @@ import XCTest import Foundation -class ZexallTests: XCTestCase { +class ZexallTests: XCTestCase, CSTestMachineTrapHandler { func testZexall() { if let filename = Bundle(for: type(of: self)).path(forResource: "zexall", ofType: "com") { if let testData = try? Data(contentsOf: URL(fileURLWithPath: filename)) { + // install test program, at the usual CP/M place let machine = CSTestMachineZ80() machine.setData(testData, atAddress: 0x0100) - machine.setValue(0x0100, for: .programCounter) - machine.setValue(0xffff, for: .stackPointer) + // add a RET at the CP/M entry location, and establish it as a trap location + machine.setValue(0xc9, atAddress: 0x0005) + machine.addTrapAddress(0x0005); + machine.trapHandler = self + // seed execution at 0x0100 + machine.setValue(0x0100, for: .programCounter) + + // run! machine.runForNumber(ofCycles: 20) } } } + func testMachine(_ testMachine: CSTestMachineZ80!, didTrapAtAddress address: UInt16) { + // only 0x0005 was registered as a trap address, so no need further to inspect + let cRegister = testMachine.value(for: .C) + if cRegister == 9 { + var address = testMachine.value(for: .DE) + var character: Character = " " + var output = "" + while true { + character = Character(UnicodeScalar(testMachine.value(atAddress: address))) + if character == "$" { + break + } + output = output + String(character) + address = address + 1 + } + print(output) + } + if cRegister == 5 { + print(String(describing: UnicodeScalar(testMachine.value(for: .E)))) + } + } } diff --git a/Processors/AllRAMProcessor.cpp b/Processors/AllRAMProcessor.cpp index 74d49df5a..c91aa57de 100644 --- a/Processors/AllRAMProcessor.cpp +++ b/Processors/AllRAMProcessor.cpp @@ -19,6 +19,11 @@ void AllRAMProcessor::set_data_at_address(uint16_t startAddress, size_t length, memcpy(&memory_[startAddress], data, endAddress - startAddress); } +void AllRAMProcessor::get_data_at_address(uint16_t startAddress, size_t length, uint8_t *data) { + size_t endAddress = std::min(startAddress + length, (size_t)65536); + memcpy(data, &memory_[startAddress], endAddress - startAddress); +} + uint32_t AllRAMProcessor::get_timestamp() { return timestamp_; } diff --git a/Processors/AllRAMProcessor.hpp b/Processors/AllRAMProcessor.hpp index 17b69b7d6..7fcfe3f65 100644 --- a/Processors/AllRAMProcessor.hpp +++ b/Processors/AllRAMProcessor.hpp @@ -20,6 +20,7 @@ class AllRAMProcessor { AllRAMProcessor(size_t memory_size); uint32_t get_timestamp(); void set_data_at_address(uint16_t startAddress, size_t length, const uint8_t *data); + void get_data_at_address(uint16_t startAddress, size_t length, uint8_t *data); class TrapHandler { public: