diff --git a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.h b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.h index 97c237738..5ffaf2ed6 100644 --- a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.h +++ b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.h @@ -7,6 +7,25 @@ // #import +#import + +@class CSTestMachineZ80; + +@protocol CSTestMachineTrapHandler +- (void)testMachine:(CSTestMachineZ80 *)testMachine didTrapAtAddress:(uint16_t)address; +@end + +typedef NS_ENUM(NSInteger, CSTestMachineZ80BusOperationCaptureOperation) { + CSTestMachineZ80BusOperationCaptureOperationRead, + CSTestMachineZ80BusOperationCaptureOperationWrite +}; + +@interface CSTestMachineZ80BusOperationCapture: NSObject +@property(nonatomic, assign) CSTestMachineZ80BusOperationCaptureOperation operation; +@property(nonatomic, assign) uint16_t address; +@property(nonatomic, assign) uint8_t value; +@property(nonatomic, assign) int timeStamp; +@end typedef NS_ENUM(NSInteger, CSTestMachineZ80Register) { CSTestMachineZ80RegisterProgramCounter, @@ -25,18 +44,14 @@ typedef NS_ENUM(NSInteger, CSTestMachineZ80Register) { CSTestMachineZ80RegisterIFF1, CSTestMachineZ80RegisterIFF2, CSTestMachineZ80RegisterIM }; -@class CSTestMachineZ80; - -@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)runToNextInstruction; - (void)setValue:(uint16_t)value forRegister:(CSTestMachineZ80Register)reg; - (uint16_t)valueForRegister:(CSTestMachineZ80Register)reg; @@ -44,4 +59,7 @@ typedef NS_ENUM(NSInteger, CSTestMachineZ80Register) { @property(nonatomic, weak) id trapHandler; - (void)addTrapAddress:(uint16_t)trapAddress; +@property(nonatomic, assign) BOOL captureBusActivity; +@property(nonatomic, readonly) NSArray *busOperationCaptures; + @end diff --git a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.mm b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.mm index af4ee7964..225e7ac32 100644 --- a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.mm +++ b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.mm @@ -11,9 +11,10 @@ @interface CSTestMachineZ80 () - (void)testMachineDidTrapAtAddress:(uint16_t)address; +- (void)testMachineDidPerformBusOperation:(CPU::Z80::BusOperation)operation address:(uint16_t)address value:(uint8_t)value timeStamp:(int)time_stamp; @end -#pragma mark - C++ trap handler +#pragma mark - C++ delegate handlers class MachineTrapHandler: public CPU::AllRAMProcessor::TrapHandler { public: @@ -27,6 +28,18 @@ class MachineTrapHandler: public CPU::AllRAMProcessor::TrapHandler { CSTestMachineZ80 *target_; }; +class BusOperationHandler: public CPU::Z80::AllRAMProcessor::MemoryAccessDelegate { + public: + BusOperationHandler(CSTestMachineZ80 *targetMachine) : target_(targetMachine) {} + + void z80_all_ram_processor_did_perform_bus_operation(CPU::Z80::AllRAMProcessor &processor, CPU::Z80::BusOperation operation, uint16_t address, uint8_t value, int time_stamp) { + [target_ testMachineDidPerformBusOperation:operation address:address value:value timeStamp:time_stamp]; + } + + private: + CSTestMachineZ80 *target_; +}; + #pragma mark - Register enum map static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) { @@ -64,11 +77,20 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) { } } +#pragma mark - Capture class + +@implementation CSTestMachineZ80BusOperationCapture +@end + #pragma mark - Test class @implementation CSTestMachineZ80 { CPU::Z80::AllRAMProcessor _processor; MachineTrapHandler *_cppTrapHandler; + BusOperationHandler *_busOperationHandler; + + NSMutableArray *_busOperationCaptures; + BOOL _isAtReadOpcode; } #pragma mark - Lifecycle @@ -76,13 +98,17 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) { - (instancetype)init { if(self = [super init]) { _cppTrapHandler = new MachineTrapHandler(self); + _busOperationHandler = new BusOperationHandler(self); + _processor.set_trap_handler(_cppTrapHandler); + _processor.set_memory_access_delegate(_busOperationHandler); } return self; } - (void)dealloc { delete _cppTrapHandler; + delete _busOperationHandler; } #pragma mark - Accessors @@ -121,4 +147,37 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) { [self.trapHandler testMachine:self didTrapAtAddress:address]; } +#pragma mark - Z80-specific Runner + +- (void)runToNextInstruction { + _isAtReadOpcode = false; + while(!_isAtReadOpcode) { + _processor.run_for_cycles(1); + } +} + +#pragma mark - Bus operation accumulation + +- (void)testMachineDidPerformBusOperation:(CPU::Z80::BusOperation)operation address:(uint16_t)address value:(uint8_t)value timeStamp:(int)time_stamp { + _isAtReadOpcode |= (operation == CPU::Z80::BusOperation::ReadOpcode); + + if(self.captureBusActivity) { + if(!_busOperationCaptures) _busOperationCaptures = [[NSMutableArray alloc] init]; + + if(operation == CPU::Z80::BusOperation::Read || operation == CPU::Z80::BusOperation::ReadOpcode || operation == CPU::Z80::BusOperation::Write) { + CSTestMachineZ80BusOperationCapture *capture = [[CSTestMachineZ80BusOperationCapture alloc] init]; + capture.operation = (operation == CPU::Z80::BusOperation::Write) ? CSTestMachineZ80BusOperationCaptureOperationWrite : CSTestMachineZ80BusOperationCaptureOperationRead; + capture.address = address; + capture.value = value; + capture.timeStamp = time_stamp; + + [_busOperationCaptures addObject:capture]; + } + } +} + +- (NSArray *)busOperationCaptures { + return [_busOperationCaptures copy]; +} + @end diff --git a/OSBindings/Mac/Clock SignalTests/FUSETests.swift b/OSBindings/Mac/Clock SignalTests/FUSETests.swift index 76fc0626a..01448f450 100644 --- a/OSBindings/Mac/Clock SignalTests/FUSETests.swift +++ b/OSBindings/Mac/Clock SignalTests/FUSETests.swift @@ -70,7 +70,6 @@ class FUSETests: XCTestCase { machine.setValue(UInt16(iff1), for: .IFF1) machine.setValue(UInt16(iff2), for: .IFF2) machine.setValue(UInt16(interruptMode), for: .IM) - // TODO: isHalted while true { @@ -93,7 +92,11 @@ class FUSETests: XCTestCase { } } + machine.captureBusActivity = true machine.runForNumber(ofCycles: Int32(tStates)) + machine.runToNextInstruction() + + print("\(machine.busOperationCaptures)") } } } diff --git a/Processors/Z80/Z80AllRAM.hpp b/Processors/Z80/Z80AllRAM.hpp index 04775ba96..4afe0a6bd 100644 --- a/Processors/Z80/Z80AllRAM.hpp +++ b/Processors/Z80/Z80AllRAM.hpp @@ -25,7 +25,7 @@ class AllRAMProcessor: int perform_machine_cycle(const MachineCycle *cycle); struct MemoryAccessDelegate { - virtual void z80_all_ram_processor_did_perform_bus_operation(AllRAMProcessor &processor, BusOperation operation, uint16_t address, uint8_t value, int time_stamp); + virtual void z80_all_ram_processor_did_perform_bus_operation(AllRAMProcessor &processor, BusOperation operation, uint16_t address, uint8_t value, int time_stamp) = 0; }; void set_memory_access_delegate(MemoryAccessDelegate *delegate) { delegate_ = delegate;