1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-02-02 16:38:51 +00:00

Added enough infrastructure to be able to react to the two CP/M calls this cares about.

This commit is contained in:
Thomas Harte 2017-05-19 21:53:39 -04:00
parent 62b432c046
commit d910405648
5 changed files with 57 additions and 4 deletions

View File

@ -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;

View File

@ -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));
}

View File

@ -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))))
}
}
}

View File

@ -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_;
}

View File

@ -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: