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 <Foundation/Foundation.h>
+#import <stdint.h>
+
+@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<CSTestMachineTrapHandler> trapHandler;
 - (void)addTrapAddress:(uint16_t)trapAddress;
 
+@property(nonatomic, assign) BOOL captureBusActivity;
+@property(nonatomic, readonly) NSArray<CSTestMachineZ80BusOperationCapture *> *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<CSTestMachineZ80BusOperationCapture *> *_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<CSTestMachineZ80BusOperationCapture *> *)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;