diff --git a/Intel8080/inc/Intel8080.h b/Intel8080/inc/Intel8080.h
index 0115222..26fa6c5 100644
--- a/Intel8080/inc/Intel8080.h
+++ b/Intel8080/inc/Intel8080.h
@@ -53,7 +53,7 @@ namespace EightBit {
 		register16_t de;
 		register16_t hl;
 
-		uint8_t R(int r) {
+		uint8_t R(int r, uint8_t a) {
 			switch (r) {
 			case 0b000:
 				return B();
@@ -70,14 +70,14 @@ namespace EightBit {
 			case 0b110:
 				return getByte(HL());
 			case 0b111:
-				return A();
+				return a;
 			default:
 				UNREACHABLE;
 			}
 			throw std::logic_error("Unhandled registry mechanism");
 		}
 
-		void R(int r, uint8_t value) {
+		void R(int r, uint8_t& a, uint8_t value) {
 			switch (r) {
 			case 0b000:
 				B() = value;
@@ -101,7 +101,7 @@ namespace EightBit {
 				setByte(HL(), value);
 				break;
 			case 0b111:
-				A() = value;
+				a = value;
 				break;
 			default:
 				UNREACHABLE;
@@ -153,6 +153,9 @@ namespace EightBit {
 		static void increment(uint8_t& f, uint8_t& operand);
 		static void decrement(uint8_t& f, uint8_t& operand);
 
+		void di();
+		void ei();
+
 		bool returnConditionalFlag(uint8_t& f, int flag);
 		bool jumpConditionalFlag(uint8_t& f, int flag);
 		bool callConditionalFlag(uint8_t& f, int flag);
@@ -178,12 +181,12 @@ namespace EightBit {
 		static void stc(uint8_t& a, uint8_t& f);
 		static void cmc(uint8_t& a, uint8_t& f);
 
-		void xhtl();
+		void xhtl(register16_t& operand);
 
-		void out();
-		void in();
+		void writePort(uint8_t port, uint8_t a);
+		void writePort();
 
-		void ei();
-		void di();
+		void readPort(uint8_t port, uint8_t& a);
+		void readPort();
 	};
 }
\ No newline at end of file
diff --git a/Intel8080/src/Intel8080.cpp b/Intel8080/src/Intel8080.cpp
index 6a288fa..b62bac6 100644
--- a/Intel8080/src/Intel8080.cpp
+++ b/Intel8080/src/Intel8080.cpp
@@ -112,8 +112,8 @@ bool EightBit::Intel8080::callConditionalFlag(uint8_t& f, int flag) {
 
 void EightBit::Intel8080::add(uint8_t& f, register16_t& operand, register16_t value) {
 	const auto result = operand.word + value.word;
-	setFlag(f, CF, result & Bit16);
 	operand.word = result;
+	setFlag(f, CF, result & Bit16);
 }
 
 void EightBit::Intel8080::add(uint8_t& f, uint8_t& operand, uint8_t value, int carry) {
@@ -221,27 +221,45 @@ void EightBit::Intel8080::cmc(uint8_t& a, uint8_t& f) {
 	clearFlag(f, CF, f & CF);
 }
 
-void EightBit::Intel8080::xhtl() {
+void EightBit::Intel8080::xhtl(register16_t& operand) {
 	MEMPTR().low = getByte(SP());
-	setByte(L());
-	L() = MEMPTR().low;
+	setByte(operand.low);
+	operand.low = MEMPTR().low;
 	BUS().ADDRESS().word++;
 	MEMPTR().high = getByte();
-	setByte(H());
-	H() = MEMPTR().high;
+	setByte(operand.high);
+	operand.high = MEMPTR().high;
 }
 
-void EightBit::Intel8080::out() {
-	m_ports.write(fetchByte(), A());
+void EightBit::Intel8080::writePort(uint8_t port, uint8_t data) {
+	BUS().ADDRESS().low = port;
+	BUS().ADDRESS().high = data;
+	MEMPTR() = BUS().ADDRESS();
+	BUS().placeDATA(data);
+	writePort();
+	MEMPTR().low++;
 }
 
-void EightBit::Intel8080::in() {
-	A() = m_ports.read(fetchByte());
+void EightBit::Intel8080::writePort() {
+	m_ports.write(BUS().ADDRESS().low, BUS().DATA());
+}
+
+void EightBit::Intel8080::readPort(uint8_t port, uint8_t& a) {
+	BUS().ADDRESS().low = port;
+	BUS().ADDRESS().high = a;
+	MEMPTR() = BUS().ADDRESS();
+	readPort();
+	a = BUS().DATA();
+	MEMPTR().low++;
+}
+
+void EightBit::Intel8080::readPort() {
+	BUS().placeDATA(m_ports.read(BUS().ADDRESS().low));
 }
 
 int EightBit::Intel8080::step() {
 	ExecutingInstruction.fire(*this);
-	cycles = 0;
+	resetCycles();
 	return fetchExecute();
 }
 
@@ -249,19 +267,19 @@ int EightBit::Intel8080::execute(uint8_t opcode) {
 
 	const auto& decoded = getDecodedOpcode(opcode);
 
-	auto x = decoded.x;
-	auto y = decoded.y;
-	auto z = decoded.z;
+	const auto x = decoded.x;
+	const auto y = decoded.y;
+	const auto z = decoded.z;
 
-	auto p = decoded.p;
-	auto q = decoded.q;
+	const auto p = decoded.p;
+	const auto q = decoded.q;
 
 	execute(x, y, z, p, q);
 
-	if (cycles == 0)
+	if (cycles() == 0)
 		throw std::logic_error("Unhandled opcode");
 
-	return cycles;
+	return cycles();
 }
 
 void EightBit::Intel8080::execute(int x, int y, int z, int p, int q) {
@@ -273,19 +291,19 @@ void EightBit::Intel8080::execute(int x, int y, int z, int p, int q) {
 		case 0:	// Relative jumps and assorted ops
 			switch (y) {
 			case 0:	// NOP
-				cycles += 4;
+				addCycles(4);
 				break;
 			}
 			break;
 		case 1:	// 16-bit load immediate/add
 			switch (q) {
 			case 0: // LD rp,nn
-				Processor::fetchWord(RP(p));
-				cycles += 10;
+				fetchWord(RP(p));
+				addCycles(10);
 				break;
 			case 1:	// ADD HL,rp
 				add(f, HL(), RP(p));
-				cycles += 11;
+				addCycles(11);
 				break;
 			}
 			break;
@@ -297,24 +315,24 @@ void EightBit::Intel8080::execute(int x, int y, int z, int p, int q) {
 					MEMPTR() = BC();
 					memptrReference();
 					setByte(MEMPTR().high = a);
-					cycles += 7;
+					addCycles(7);
 					break;
 				case 1:	// LD (DE),A
 					MEMPTR() = DE();
 					memptrReference();
 					setByte(MEMPTR().high = a);
-					cycles += 7;
+					addCycles(7);
 					break;
 				case 2:	// LD (nn),HL
 					fetchWord();
 					setWordViaMemptr(HL());
-					cycles += 16;
+					addCycles(16);
 					break;
 				case 3: // LD (nn),A
 					fetchWord();
 					memptrReference();
 					setByte(MEMPTR().high = a);
-					cycles += 13;
+					addCycles(13);
 					break;
 				default:
 					UNREACHABLE;
@@ -326,24 +344,24 @@ void EightBit::Intel8080::execute(int x, int y, int z, int p, int q) {
 					MEMPTR() = BC();
 					memptrReference();
 					a = getByte();
-					cycles += 7;
+					addCycles(7);
 					break;
 				case 1:	// LD A,(DE)
 					MEMPTR() = DE();
 					memptrReference();
 					a = getByte();
-					cycles += 7;
+					addCycles(7);
 					break;
 				case 2:	// LD HL,(nn)
 					fetchWord();
 					getWordViaMemptr(HL());
-					cycles += 16;
+					addCycles(16);
 					break;
 				case 3:	// LD A,(nn)
 					fetchWord();
 					memptrReference();
 					a = getByte();
-					cycles += 13;
+					addCycles(13);
 					break;
 				default:
 					UNREACHABLE;
@@ -364,27 +382,27 @@ void EightBit::Intel8080::execute(int x, int y, int z, int p, int q) {
 			default:
 				UNREACHABLE;
 			}
-			cycles += 6;
+			addCycles(6);
 			break;
 		case 4: { // 8-bit INC
-			auto operand = R(y);
+			auto operand = R(y, a);
 			increment(f, operand);
-			R(y, operand);
-			cycles += 4;
+			R(y, a, operand);
+			addCycles(4);
 			break;
 		} case 5: {	// 8-bit DEC
-			auto operand = R(y);
+			auto operand = R(y, a);
 			decrement(f, operand);
-			R(y, operand);
-			cycles += 4;
+			R(y, a, operand);
+			addCycles(4);
 			if (y == 6)
-				cycles += 7;
+				addCycles(7);
 			break;
 		} case 6:	// 8-bit load immediate
-			R(y, fetchByte());
-			cycles += 7;
+			R(y, a, fetchByte());
+			addCycles(7);
 			if (y == 6)
-				cycles += 3;
+				addCycles(3);
 			break;
 		case 7:	// Assorted operations on accumulator/flags
 			switch (y) {
@@ -415,7 +433,7 @@ void EightBit::Intel8080::execute(int x, int y, int z, int p, int q) {
 			default:
 				UNREACHABLE;
 			}
-			cycles += 4;
+			addCycles(4);
 			break;
 		default:
 			UNREACHABLE;
@@ -425,71 +443,71 @@ void EightBit::Intel8080::execute(int x, int y, int z, int p, int q) {
 		if (z == 6 && y == 6) { 	// Exception (replaces LD (HL), (HL))
 			halt();
 		} else {
-			R(y, R(z));
+			R(y, a, R(z, a));
 			if ((y == 6) || (z == 6))	// M operations
-				cycles += 3;
+				addCycles(3);
 		}
-		cycles += 4;
+		addCycles(4);
 		break;
 	case 2:	// Operate on accumulator and register/memory location
 		switch (y) {
 		case 0:	// ADD A,r
-			add(f, a, R(z));
+			add(f, a, R(z, a));
 			break;
 		case 1:	// ADC A,r
-			adc(f, a, R(z));
+			adc(f, a, R(z, a));
 			break;
 		case 2:	// SUB r
-			subtract(f, a, R(z));
+			subtract(f, a, R(z, a));
 			break;
 		case 3:	// SBC A,r
-			sbb(f, a, R(z));
+			sbb(f, a, R(z, a));
 			break;
 		case 4:	// AND r
-			andr(f, a, R(z));
+			andr(f, a, R(z, a));
 			break;
 		case 5:	// XOR r
-			xorr(f, a, R(z));
+			xorr(f, a, R(z, a));
 			break;
 		case 6:	// OR r
-			orr(f, a, R(z));
+			orr(f, a, R(z, a));
 			break;
 		case 7:	// CP r
-			compare(f, a, R(z));
+			compare(f, a, R(z, a));
 			break;
 		default:
 			UNREACHABLE;
 		}
-		cycles += 4;
+		addCycles(4);
 		if (z == 6)
-			cycles += 3;
+			addCycles(3);
 		break;
 	case 3:
 		switch (z) {
 		case 0:	// Conditional return
 			if (returnConditionalFlag(f, y))
-				cycles += 6;
-			cycles += 5;
+				addCycles(6);
+			addCycles(5);
 			break;
 		case 1:	// POP & various ops
 			switch (q) {
 			case 0:	// POP rp2[p]
 				popWord(RP2(p));
-				cycles += 10;
+				addCycles(10);
 				break;
 			case 1:
 				switch (p) {
 				case 0:	// RET
 					ret();
-					cycles += 10;
+					addCycles(10);
 					break;
 				case 2:	// JP HL
 					PC() = HL();
-					cycles += 4;
+					addCycles(4);
 					break;
 				case 3:	// LD SP,HL
 					SP() = HL();
-					cycles += 4;
+					addCycles(4);
 					break;
 				}
 				break;
@@ -499,58 +517,58 @@ void EightBit::Intel8080::execute(int x, int y, int z, int p, int q) {
 			break;
 		case 2:	// Conditional jump
 			jumpConditionalFlag(f, y);
-			cycles += 10;
+			addCycles(10);
 			break;
 		case 3:	// Assorted operations
 			switch (y) {
 			case 0:	// JP nn
 				fetchWord();
 				jump();
-				cycles += 10;
+				addCycles(10);
 				break;
 			case 2:	// OUT (n),A
-				out();
-				cycles += 11;
+				writePort(fetchByte(), a);
+				addCycles(11);
 				break;
 			case 3:	// IN A,(n)
-				in();
-				cycles += 11;
+				readPort(fetchByte(), a);
+				addCycles(11);
 				break;
 			case 4:	// EX (SP),HL
-				xhtl();
-				cycles += 19;
+				xhtl(HL());
+				addCycles(19);
 				break;
 			case 5:	// EX DE,HL
 				std::swap(DE(), HL());
-				cycles += 4;
+				addCycles(4);
 				break;
 			case 6:	// DI
 				di();
-				cycles += 4;
+				addCycles(4);
 				break;
 			case 7:	// EI
 				ei();
-				cycles += 4;
+				addCycles(4);
 				break;
 			}
 			break;
 		case 4:	// Conditional call: CALL cc[y], nn
 			if (callConditionalFlag(f, y))
-				cycles += 7;
-			cycles += 10;
+				addCycles(7);
+			addCycles(10);
 			break;
 		case 5:	// PUSH & various ops
 			switch (q) {
 			case 0:	// PUSH rp2[p]
 				pushWord(RP2(p));
-				cycles += 11;
+				addCycles(11);
 				break;
 			case 1:
 				switch (p) {
 				case 0:	// CALL nn
 					fetchWord();
 					call();
-					cycles += 17;
+					addCycles(17);
 					break;
 				}
 				break;
@@ -587,11 +605,11 @@ void EightBit::Intel8080::execute(int x, int y, int z, int p, int q) {
 			default:
 				UNREACHABLE;
 			}
-			cycles += 7;
+			addCycles(7);
 			break;
 		case 7:	// Restart: RST y * 8
 			restart(y << 3);
-			cycles += 11;
+			addCycles(11);
 			break;
 		default:
 			UNREACHABLE;
diff --git a/LR35902/inc/LR35902.h b/LR35902/inc/LR35902.h
index 9bd015a..2742812 100644
--- a/LR35902/inc/LR35902.h
+++ b/LR35902/inc/LR35902.h
@@ -27,7 +27,7 @@ namespace EightBit {
 			Signal<LR35902> ExecutedInstruction;
 
 			int clockCycles() const {
-				return cycles * 4;
+				return cycles() * 4;
 			}
 
 			virtual register16_t& AF() override {
diff --git a/LR35902/src/LR35902.cpp b/LR35902/src/LR35902.cpp
index 32c4cd3..930f129 100644
--- a/LR35902/src/LR35902.cpp
+++ b/LR35902/src/LR35902.cpp
@@ -301,7 +301,7 @@ int EightBit::GameBoy::LR35902::singleStep() {
 		if (ime) {
 			m_bus.IO().poke(IoRegisters::IF, 0);
 		} else {
-			if (isHalted())
+			if (halted())
 				proceed();
 		}
 	}
@@ -317,7 +317,7 @@ int EightBit::GameBoy::LR35902::singleStep() {
 	} else if (ime && (masked & IoRegisters::Interrupts::KeypadPressed)) {
 		current += interrupt(0x60);
 	} else {
-		current += isHalted() ? 1 : step();
+		current += halted() ? 1 : step();
 	}
 
 	m_bus.IO().checkTimers(current);
@@ -329,7 +329,7 @@ int EightBit::GameBoy::LR35902::singleStep() {
 int EightBit::GameBoy::LR35902::step() {
 	ExecutingInstruction.fire(*this);
 	m_prefixCB = false;
-	cycles = 0;
+	resetCycles();
 	const auto ran = fetchExecute();
 	ExecutedInstruction.fire(*this);
 	return ran;
@@ -351,7 +351,7 @@ int EightBit::GameBoy::LR35902::execute(uint8_t opcode) {
 	else
 		executeOther(x, y, z, p, q);
 
-	if (cycles == 0)
+	if (cycles() == 0)
 		throw std::logic_error("Unhandled opcode");
 
 	return clockCycles();
@@ -391,29 +391,29 @@ void EightBit::GameBoy::LR35902::executeCB(int x, int y, int z, int p, int q) {
 		default:
 			UNREACHABLE;
 		}
-		cycles += 2;
+		addCycles(2);
 		R(z, a, operand);
 		adjustZero<LR35902>(f, operand);
 		if (z == 6)
-			cycles += 2;
+			addCycles(2);
 		break;
 	} case 1:	// BIT y, r[z]
 		bit(f, y, R(z, a));
-		cycles += 2;
+		addCycles(2);
 		if (z == 6)
-			cycles += 2;
+			addCycles(2);
 		break;
 	case 2:	// RES y, r[z]
 		R(z, a, res(y, R(z, a)));
-		cycles += 2;
+		addCycles(2);
 		if (z == 6)
-			cycles += 2;
+			addCycles(2);
 		break;
 	case 3:	// SET y, r[z]
 		R(z, a, set(y, R(z, a)));
-		cycles += 2;
+		addCycles(2);
 		if (z == 6)
-			cycles += 2;
+			addCycles(2);
 		break;
 	default:
 		UNREACHABLE;
@@ -429,28 +429,28 @@ void EightBit::GameBoy::LR35902::executeOther(int x, int y, int z, int p, int q)
 		case 0:	// Relative jumps and assorted ops
 			switch (y) {
 			case 0:	// NOP
-				cycles++;
+				addCycle();
 				break;
 			case 1:	// GB: LD (nn),SP
 				fetchWord();
 				setWordViaMemptr(SP());
-				cycles += 5;
+				addCycles(5);
 				break;
 			case 2:	// GB: STOP
 				stop();
-				cycles++;
+				addCycle();
 				break;
 			case 3:	// JR d
 				jr(fetchByte());
-				cycles += 4;
+				addCycles(4);
 				break;
 			case 4: // JR cc,d
 			case 5:
 			case 6:
 			case 7:
 				if (jrConditionalFlag(f, y - 4))
-					cycles++;
-				cycles += 2;
+					addCycle();
+				addCycles(2);
 				break;
 			default:
 				UNREACHABLE;
@@ -460,11 +460,11 @@ void EightBit::GameBoy::LR35902::executeOther(int x, int y, int z, int p, int q)
 			switch (q) {
 			case 0: // LD rp,nn
 				fetchWord(RP(p));
-				cycles += 3;
+				addCycles(3);
 				break;
 			case 1:	// ADD HL,rp
 				add(f, HL(), RP(p));
-				cycles += 2;
+				addCycles(2);
 				break;
 			default:
 				UNREACHABLE;
@@ -476,19 +476,19 @@ void EightBit::GameBoy::LR35902::executeOther(int x, int y, int z, int p, int q)
 				switch (p) {
 				case 0:	// LD (BC),A
 					setByte(BC(), a);
-					cycles += 2;
+					addCycles(2);
 					break;
 				case 1:	// LD (DE),A
 					setByte(DE(), a);
-					cycles += 2;
+					addCycles(2);
 					break;
 				case 2:	// GB: LDI (HL),A
 					setByte(HL().word++, a);
-					cycles += 2;
+					addCycles(2);
 					break;
 				case 3: // GB: LDD (HL),A
 					setByte(HL().word--, a);
-					cycles += 2;
+					addCycles(2);
 					break;
 				default:
 					UNREACHABLE;
@@ -498,19 +498,19 @@ void EightBit::GameBoy::LR35902::executeOther(int x, int y, int z, int p, int q)
 				switch (p) {
 				case 0:	// LD A,(BC)
 					a = getByte(BC());
-					cycles += 2;
+					addCycles(2);
 					break;
 				case 1:	// LD A,(DE)
 					a = getByte(DE());
-					cycles += 2;
+					addCycles(2);
 					break;
 				case 2:	// GB: LDI A,(HL)
 					a = getByte(HL().word++);
-					cycles += 2;
+					addCycles(2);
 					break;
 				case 3:	// GB: LDD A,(HL)
 					a = getByte(HL().word--);
-					cycles += 2;
+					addCycles(2);
 					break;
 				default:
 					UNREACHABLE;
@@ -531,27 +531,27 @@ void EightBit::GameBoy::LR35902::executeOther(int x, int y, int z, int p, int q)
 			default:
 				UNREACHABLE;
 			}
-			cycles += 2;
+			addCycles(2);
 			break;
 		case 4: { // 8-bit INC
 			auto operand = R(y, a);
 			increment(f, operand);
 			R(y, a, operand);
-			cycles++;
+			addCycle();
 			if (y == 6)
-				cycles += 2;
+				addCycles(2);
 			break;
 		} case 5: {	// 8-bit DEC
 			auto operand = R(y, a);
 			decrement(f, operand);
 			R(y, a, operand);
-			cycles++;
+			addCycle();
 			if (y == 6)
-				cycles += 2;
+				addCycles(2);
 			break;
 		} case 6:	// 8-bit load immediate
 			R(y, a, fetchByte());	// LD r,n
-			cycles += 2;
+			addCycles(2);
 			break;
 		case 7:	// Assorted operations on accumulator/flags
 			switch (y) {
@@ -582,7 +582,7 @@ void EightBit::GameBoy::LR35902::executeOther(int x, int y, int z, int p, int q)
 			default:
 				UNREACHABLE;
 			}
-			cycles++;
+			addCycle();
 			break;
 		default:
 			UNREACHABLE;
@@ -594,9 +594,9 @@ void EightBit::GameBoy::LR35902::executeOther(int x, int y, int z, int p, int q)
 		} else {
 			R(y, a, R(z, a));
 			if ((y == 6) || (z == 6)) // M operations
-				cycles++;
+				addCycle();
 		}
-		cycles++;
+		addCycle();
 		break;
 	case 2:	// Operate on accumulator and register/memory location
 		switch (y) {
@@ -627,9 +627,9 @@ void EightBit::GameBoy::LR35902::executeOther(int x, int y, int z, int p, int q)
 		default:
 			UNREACHABLE;
 		}
-		cycles++;
+		addCycle();
 		if (z == 6)
-			cycles++;
+			addCycle();
 		break;
 	case 3:
 		switch (z) {
@@ -640,12 +640,12 @@ void EightBit::GameBoy::LR35902::executeOther(int x, int y, int z, int p, int q)
 			case 2:
 			case 3:
 				if (returnConditionalFlag(f, y))
-					cycles += 3;
-				cycles += 2;
+					addCycles(3);
+				addCycles(2);
 				break;
 			case 4:	// GB: LD (FF00 + n),A
 				m_bus.write(IoRegisters::BASE + fetchByte(), a);
-				cycles += 3;
+				addCycles(3);
 				break;
 			case 5: { // GB: ADD SP,dd
 					const auto before = SP().word;
@@ -657,11 +657,11 @@ void EightBit::GameBoy::LR35902::executeOther(int x, int y, int z, int p, int q)
 					setFlag(f, CF, carried & Bit8);
 					setFlag(f, HC, carried & Bit4);
 				}
-				cycles += 4;
+				addCycles(4);
 				break;
 			case 6:	// GB: LD A,(FF00 + n)
 				a = m_bus.read(IoRegisters::BASE + fetchByte());
-				cycles += 3;
+				addCycles(3);
 				break;
 			case 7: { // GB: LD HL,SP + dd
 					const auto before = SP().word;
@@ -673,7 +673,7 @@ void EightBit::GameBoy::LR35902::executeOther(int x, int y, int z, int p, int q)
 					setFlag(f, CF, carried & Bit8);
 					setFlag(f, HC, carried & Bit4);
 				}
-				cycles += 3;
+				addCycles(3);
 				break;
 			default:
 				UNREACHABLE;
@@ -683,25 +683,25 @@ void EightBit::GameBoy::LR35902::executeOther(int x, int y, int z, int p, int q)
 			switch (q) {
 			case 0:	// POP rp2[p]
 				popWord(RP2(p));
-				cycles += 3;
+				addCycles(3);
 				break;
 			case 1:
 				switch (p) {
 				case 0:	// RET
 					ret();
-					cycles += 4;
+					addCycles(4);
 					break;
 				case 1:	// GB: RETI
 					reti();
-					cycles += 4;
+					addCycles(4);
 					break;
 				case 2:	// JP HL
 					PC() = HL();
-					cycles++;
+					addCycle();
 					break;
 				case 3:	// LD SP,HL
 					SP() = HL();
-					cycles += 2;
+					addCycles(2);
 					break;
 				default:
 					UNREACHABLE;
@@ -718,25 +718,25 @@ void EightBit::GameBoy::LR35902::executeOther(int x, int y, int z, int p, int q)
 			case 2:
 			case 3:
 				jumpConditionalFlag(f, y);
-				cycles += 3;
+				addCycles(3);
 				break;
 			case 4:	// GB: LD (FF00 + C),A
 				m_bus.write(IoRegisters::BASE + C(), a);
-				cycles += 2;
+				addCycles(2);
 				break;
 			case 5:	// GB: LD (nn),A
 				fetchWord();
 				setByte(MEMPTR(), a);
-				cycles += 4;
+				addCycles(4);
 				break;
 			case 6:	// GB: LD A,(FF00 + C)
 				a = m_bus.read(IoRegisters::BASE + C());
-				cycles += 2;
+				addCycles(2);
 				break;
 			case 7:	// GB: LD A,(nn)
 				fetchWord();
 				a = getByte(MEMPTR());
-				cycles += 4;
+				addCycles(4);
 				break;
 			default:
 				UNREACHABLE;
@@ -747,7 +747,7 @@ void EightBit::GameBoy::LR35902::executeOther(int x, int y, int z, int p, int q)
 			case 0:	// JP nn
 				fetchWord();
 				jump();
-				cycles += 4;
+				addCycles(4);
 				break;
 			case 1:	// CB prefix
 				m_prefixCB = true;
@@ -755,31 +755,31 @@ void EightBit::GameBoy::LR35902::executeOther(int x, int y, int z, int p, int q)
 				break;
 			case 6:	// DI
 				di();
-				cycles++;
+				addCycle();
 				break;
 			case 7:	// EI
 				ei();
-				cycles++;
+				addCycle();
 				break;
 			}
 			break;
 		case 4:	// Conditional call: CALL cc[y], nn
 			if (callConditionalFlag(f, y))
-				cycles += 3;
-			cycles += 3;
+				addCycles(3);
+			addCycles(3);
 			break;
 		case 5:	// PUSH & various ops
 			switch (q) {
 			case 0:	// PUSH rp2[p]
 				pushWord(RP2(p));
-				cycles += 4;
+				addCycles(4);
 				break;
 			case 1:
 				switch (p) {
 				case 0:	// CALL nn
 					fetchWord();
 					call();
-					cycles += 6;
+					addCycles(6);
 					break;
 				}
 				break;
@@ -816,11 +816,11 @@ void EightBit::GameBoy::LR35902::executeOther(int x, int y, int z, int p, int q)
 			default:
 				UNREACHABLE;
 			}
-			cycles += 2;
+			addCycles(2);
 			break;
 		case 7:	// Restart: RST y * 8
 			restart(y << 3);
-			cycles += 4;
+			addCycles(4);
 			break;
 		default:
 			UNREACHABLE;
diff --git a/M6502/inc/mos6502.h b/M6502/inc/mos6502.h
index b1980b5..b9885a1 100644
--- a/M6502/inc/mos6502.h
+++ b/M6502/inc/mos6502.h
@@ -158,7 +158,7 @@ namespace EightBit {
 			Address_AbsoluteX();
 			BUS().ADDRESS() = MEMPTR();
 			if (BUS().ADDRESS().low == Mask8)
-				++cycles;
+				addCycle();
 			return getByte();
 		}
 
@@ -166,7 +166,7 @@ namespace EightBit {
 			Address_AbsoluteY();
 			BUS().ADDRESS() = MEMPTR();
 			if (BUS().ADDRESS().low == Mask8)
-				++cycles;
+				addCycle();
 			return getByte();
 		}
 
@@ -189,7 +189,7 @@ namespace EightBit {
 			Address_IndirectIndexedY();
 			BUS().ADDRESS() = MEMPTR();
 			if (BUS().ADDRESS().low == Mask8)
-				++cycles;
+				addCycle();
 			return getByte();
 		}
 
diff --git a/M6502/src/mos6502.cpp b/M6502/src/mos6502.cpp
index 6fb8529..f67e5a0 100644
--- a/M6502/src/mos6502.cpp
+++ b/M6502/src/mos6502.cpp
@@ -40,7 +40,7 @@ void EightBit::MOS6502::initialise() {
 
 int EightBit::MOS6502::step() {
 	ExecutingInstruction.fire(*this);
-	cycles = 0;
+	resetCycles();
 	auto returned = fetchExecute();
 	ExecutedInstruction.fire(*this);
 	return returned;
@@ -83,7 +83,7 @@ void EightBit::MOS6502::interrupt(uint16_t vector) {
 
 int EightBit::MOS6502::execute(uint8_t cell) {
 
-	cycles = m_timings[cell];
+	addCycles(m_timings[cell]);
 
 	// http://www.llx.com/~nparker/a2/opcodes.html
 
@@ -338,10 +338,10 @@ int EightBit::MOS6502::execute(uint8_t cell) {
 		__assume(0);
 	}
 
-	if (cycles == 0)
+	if (cycles() == 0)
 		throw std::logic_error("Unhandled opcode");
 
-	return cycles;
+	return cycles();
 }
 
 ////
@@ -483,8 +483,8 @@ void EightBit::MOS6502::Branch(int8_t displacement) {
 	const auto page = PC().high;
 	PC().word += displacement;
 	if (PC().high != page)
-		cycles++;
-	cycles++;
+		addCycle();
+	addCycle();
 }
 
 void EightBit::MOS6502::Branch(bool flag) {
diff --git a/Z80/inc/Signal.h b/Z80/inc/Signal.h
deleted file mode 100644
index 96a2ad4..0000000
--- a/Z80/inc/Signal.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#pragma once
-
-#include <vector>
-#include <functional>
-
-template<class T> class Signal {
-private:
-	typedef std::function<void(T&)> delegate_t;
-	typedef std::vector<delegate_t> delegates_t;
-
-	delegates_t delegates;
-
-public:
-	void connect(delegate_t functor) {
-		delegates.push_back(functor);
-	}
-
-	void fire(T& e) const {
-		if (!delegates.empty())
-			for (auto& delegate : delegates)
-				delegate(e);
-	}
-};
diff --git a/Z80/inc/Z80.h b/Z80/inc/Z80.h
index 1944085..bdbe2d2 100644
--- a/Z80/inc/Z80.h
+++ b/Z80/inc/Z80.h
@@ -2,12 +2,17 @@
 
 #include <cstdint>
 #include <cassert>
+#include <stdexcept>
 
-#include "IntelProcessor.h"
-#include "InputOutput.h"
-#include "Signal.h"
+#include <IntelProcessor.h>
+#include <Signal.h>
+#include <Register.h>
 
 namespace EightBit {
+
+	class InputOutput;
+	class Bus;
+
 	class Z80 : public IntelProcessor {
 	public:
 		struct refresh_t {
@@ -255,12 +260,16 @@ namespace EightBit {
 
 		register16_t& RP(int rp) {
 			switch (rp) {
+			case 0:
+				return BC();
+			case 1:
+				return DE();
+			case 2:
+				return HL2();
 			case 3:
 				return SP();
-			case HL_IDX:
-				return HL2();
 			default:
-				return m_registers[m_registerSet][rp];
+				UNREACHABLE;
 			}
 		}
 
@@ -275,12 +284,16 @@ namespace EightBit {
 
 		register16_t& RP2(int rp) {
 			switch (rp) {
+			case 0:
+				return BC();
+			case 1:
+				return DE();
+			case 2:
+				return HL2();
 			case 3:
 				return AF();
-			case HL_IDX:
-				return HL2();
 			default:
-				return m_registers[m_registerSet][rp];
+				UNREACHABLE;
 			}
 		}
 
diff --git a/Z80/src/Disassembler.cpp b/Z80/src/Disassembler.cpp
index 7b9ca78..03d0381 100644
--- a/Z80/src/Disassembler.cpp
+++ b/Z80/src/Disassembler.cpp
@@ -4,8 +4,10 @@
 #include <sstream>
 #include <iomanip>
 #include <bitset>
+#include <iostream>
+
+#include <Memory.h>
 
-#include "Memory.h"
 #include "Z80.h"
 
 EightBit::Disassembler::Disassembler() {
diff --git a/Z80/src/Z80.cpp b/Z80/src/Z80.cpp
index fa1365c..ca334f2 100644
--- a/Z80/src/Z80.cpp
+++ b/Z80/src/Z80.cpp
@@ -58,34 +58,34 @@ void EightBit::Z80::ei() {
 }
 
 int EightBit::Z80::interrupt(bool maskable, uint8_t value) {
-	cycles = 0;
+	resetCycles();
 	if (!maskable || (maskable && IFF1())) {
 		if (maskable) {
 			di();
 			switch (IM()) {
 			case 0:
 				M1() = true;
-				cycles += execute(value);
+				addCycles(execute(value));
 				break;
 			case 1:
 				restart(7 << 3);
-				cycles += 13;
+				addCycles(13);
 				break;
 			case 2:
 				pushWord(PC());
 				PC().low = value;
 				PC().high = IV();
-				cycles += 19;
+				addCycles(19);
 				break;
 			}
 		} else {
 			IFF1() = false;
 			restart(0x66);
-			cycles += 13;
+			addCycles(13);
 		}
 	}
 	// Could be zero for a masked interrupt...
-	return cycles;
+	return cycles();
 }
 
 void EightBit::Z80::increment(uint8_t& f, uint8_t& operand) {
@@ -679,7 +679,7 @@ void EightBit::Z80::readPort() {
 int EightBit::Z80::step() {
 	ExecutingInstruction.fire(*this);
 	m_displaced = m_prefixCB = m_prefixDD = m_prefixED = m_prefixFD = false;
-	cycles = 0;
+	resetCycles();
 	return fetchExecute();
 }
 
@@ -712,10 +712,10 @@ int EightBit::Z80::execute(uint8_t opcode) {
 			executeED(x, y, z, p, q);
 	}
 
-	if (cycles == 0)
+	if (cycles() == 0)
 		throw std::logic_error("Unhandled opcode");
 
-	return cycles;
+	return cycles();
 }
 
 void EightBit::Z80::executeCB(int x, int y, int z) {
@@ -757,56 +757,56 @@ void EightBit::Z80::executeCB(int x, int y, int z) {
 			if (z != 6)
 				R2(z, a, operand);
 			setByte(operand);
-			cycles += 15;
+			addCycles(15);
 		} else {
 			R(z, a, operand);
 			if (z == 6)
-				cycles += 7;
+				addCycles(7);
 		}
-		cycles += 8;
+		addCycles(8);
 		break;
 	} case 1:	// BIT y, r[z]
-		cycles += 8;
+		addCycles(8);
 		if (!m_displaced) {
 			auto operand = bit(f, y, R(z, a));
 			if (z == 6) {
 				adjustXY<Z80>(f, MEMPTR().high);
-				cycles += 4;
+				addCycles(4);
 			} else {
 				adjustXY<Z80>(f, operand);
 			}
 		} else {
 			bit(f, y, getByte(displacedAddress()));
 			adjustXY<Z80>(f, MEMPTR().high);
-			cycles += 12;
+			addCycles(12);
 		}
 		break;
 	case 2:	// RES y, r[z]
-		cycles += 8;
+		addCycles(8);
 		if (!m_displaced) {
 			R(z, a, res(y, R(z, a)));
 			if (z == 6)
-				cycles += 7;
+				addCycles(7);
 		} else {
 			auto operand = getByte(displacedAddress());
 			operand = res(y, operand);
 			setByte(operand);
 			R2(z, a, operand);
-			cycles += 15;
+			addCycles(15);
 		}
 		break;
 	case 3:	// SET y, r[z]
-		cycles += 8;
+		addCycles(8);
 		if (!m_displaced) {
 			R(z, a, set(y, R(z, a)));
 			if (z == 6)
-				cycles += 7;
+				addCycles(7);
 		} else {
 			auto operand = getByte(displacedAddress());
 			operand = set(y, operand);
 			setByte(operand);
 			R2(z, a, operand);
-			cycles += 15;
+			addCycles(15);
 		}
 		break;
 	default:
@@ -820,7 +820,7 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
 	switch (x) {
 	case 0:
 	case 3:	// Invalid instruction, equivalent to NONI followed by NOP
-		cycles += 8;
+		addCycles(8);
 		break;
 	case 1:
 		switch (z) {
@@ -832,7 +832,7 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
 				R(y, a, BUS().DATA());
 			adjustSZPXY<Z80>(f, BUS().DATA());
 			clearFlag(f, NF | HC);
-			cycles += 12;
+			addCycles(12);
 			break;
 		case 1:	// Output to port with 16-bit address
 			MEMPTR() = BUS().ADDRESS() = BC();
@@ -842,7 +842,7 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
 			else		// OUT (C),r[y]
 				BUS().placeDATA(R(y, a));
 			writePort();
-			cycles += 12;
+			addCycles(12);
 			break;
 		case 2:	// 16-bit add/subtract with carry
 			switch (q) {
@@ -855,7 +855,7 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
 			default:
 				UNREACHABLE;
 			}
-			cycles += 15;
+			addCycles(15);
 			break;
 		case 3:	// Retrieve/store register pair from/to immediate address
 			switch (q) {
@@ -870,11 +870,11 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
 			default:
 				UNREACHABLE;
 			}
-			cycles += 20;
+			addCycles(20);
 			break;
 		case 4:	// Negate accumulator
 			neg(a, f);
-			cycles += 8;
+			addCycles(8);
 			break;
 		case 5:	// Return from interrupt
 			switch (y) {
@@ -885,7 +885,7 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
 				retn();	// RETN
 				break;
 			}
-			cycles += 14;
+			addCycles(14);
 			break;
 		case 6:	// Set interrupt mode
 			switch (y) {
@@ -908,43 +908,43 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
 			default:
 				UNREACHABLE;
 			}
-			cycles += 8;
+			addCycles(8);
 			break;
 		case 7:	// Assorted ops
 			switch (y) {
 			case 0:	// LD I,A
 				IV() = a;
-				cycles += 9;
+				addCycles(9);
 				break;
 			case 1:	// LD R,A
 				REFRESH() = a;
-				cycles += 9;
+				addCycles(9);
 				break;
 			case 2:	// LD A,I
 				a = IV();
 				adjustSZXY<Z80>(f, a);
 				clearFlag(f, NF | HC);
 				setFlag(f, PF, IFF2());
-				cycles += 9;
+				addCycles(9);
 				break;
 			case 3:	// LD A,R
 				a = REFRESH();
 				adjustSZXY<Z80>(f, a);
 				clearFlag(f, NF | HC);
 				setFlag(f, PF, IFF2());
-				cycles += 9;
+				addCycles(9);
 				break;
 			case 4:	// RRD
 				rrd(a, f);
-				cycles += 18;
+				addCycles(18);
 				break;
 			case 5:	// RLD
 				rld(a, f);
-				cycles += 18;
+				addCycles(18);
 				break;
 			case 6:	// NOP
 			case 7:	// NOP
-				cycles += 4;
+				addCycles(4);
 				break;
 			default:
 				UNREACHABLE;
@@ -967,13 +967,13 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
 			case 6:	// LDIR
 				if (ldir(a, f)) {
 					PC().word -= 2;
-					cycles += 5;
+					addCycles(5);
 				}
 				break;
 			case 7:	// LDDR
 				if (lddr(a, f)) {
 					PC().word -= 2;
-					cycles += 5;
+					addCycles(5);
 				}
 				break;
 			}
@@ -989,13 +989,13 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
 			case 6:	// CPIR
 				if (cpir(a, f)) {
 					PC().word -= 2;
-					cycles += 5;
+					addCycles(5);
 				}
 				break;
 			case 7:	// CPDR
 				if (cpdr(a, f)) {
 					PC().word -= 2;
-					cycles += 5;
+					addCycles(5);
 				}
 				break;
 			}
@@ -1011,13 +1011,13 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
 			case 6:	// INIR
 				if (inir(f)) {
 					PC().word -= 2;
-					cycles += 5;
+					addCycles(5);
 				}
 				break;
 			case 7:	// INDR
 				if (indr(f)) {
 					PC().word -= 2;
-					cycles += 5;
+					addCycles(5);
 				}
 				break;
 			}
@@ -1033,19 +1033,19 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
 			case 6:	// OTIR
 				if (otir(f)) {
 					PC().word -= 2;
-					cycles += 5;
+					addCycles(5);
 				}
 				break;
 			case 7:	// OTDR
 				if (otdr(f)) {
 					PC().word -= 2;
-					cycles += 5;
+					addCycles(5);
 				}
 				break;
 			}
 			break;
 		}
-		cycles += 16;
+		addCycles(16);
 		break;
 	}
 }
@@ -1059,28 +1059,28 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
 		case 0:	// Relative jumps and assorted ops
 			switch (y) {
 			case 0:	// NOP
-				cycles += 4;
+				addCycles(4);
 				break;
 			case 1:	// EX AF AF'
 				exxAF();
-				cycles += 4;
+				addCycles(4);
 				break;
 			case 2:	// DJNZ d
 				if (jrConditional(--B()))
-					cycles += 5;
-				cycles += 8;
+					addCycles(5);
+				addCycles(8);
 				break;
 			case 3:	// JR d
 				jr(fetchByte());
-				cycles += 12;
+				addCycles(12);
 				break;
 			case 4: // JR cc,d
 			case 5:
 			case 6:
 			case 7:
 				if (jrConditionalFlag(f, y - 4))
-					cycles += 5;
-				cycles += 5;
+					addCycles(5);
+				addCycles(5);
 				break;
 			default:
 				UNREACHABLE;
@@ -1090,11 +1090,11 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
 			switch (q) {
 			case 0: // LD rp,nn
 				fetchWord(RP(p));
-				cycles += 10;
+				addCycles(10);
 				break;
 			case 1:	// ADD HL,rp
 				add(f, HL2(), RP(p));
-				cycles += 11;
+				addCycles(11);
 				break;
 			default:
 				UNREACHABLE;
@@ -1108,24 +1108,24 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
 					MEMPTR() = BC();
 					memptrReference();
 					setByte(MEMPTR().high = a);
-					cycles += 7;
+					addCycles(7);
 					break;
 				case 1:	// LD (DE),A
 					MEMPTR() = DE();
 					memptrReference();
 					setByte(MEMPTR().high = a);
-					cycles += 7;
+					addCycles(7);
 					break;
 				case 2:	// LD (nn),HL
 					fetchWord();
 					setWordViaMemptr(HL2());
-					cycles += 16;
+					addCycles(16);
 					break;
 				case 3: // LD (nn),A
 					fetchWord();
 					memptrReference();
 					setByte(MEMPTR().high = a);
-					cycles += 13;
+					addCycles(13);
 					break;
 				default:
 					UNREACHABLE;
@@ -1137,24 +1137,24 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
 					MEMPTR() = BC();
 					memptrReference();
 					a = getByte();
-					cycles += 7;
+					addCycles(7);
 					break;
 				case 1:	// LD A,(DE)
 					MEMPTR() = DE();
 					memptrReference();
 					a = getByte();
-					cycles += 7;
+					addCycles(7);
 					break;
 				case 2:	// LD HL,(nn)
 					fetchWord();
 					getWordViaMemptr(HL2());
-					cycles += 16;
+					addCycles(16);
 					break;
 				case 3:	// LD A,(nn)
 					fetchWord();
 					memptrReference();
 					a = getByte();
-					cycles += 13;
+					addCycles(13);
 					break;
 				default:
 					UNREACHABLE;
@@ -1175,7 +1175,7 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
 			default:
 				UNREACHABLE;
 			}
-			cycles += 6;
+			addCycles(6);
 			break;
 		case 4: { // 8-bit INC
 			if (m_displaced && (y == 6))
@@ -1183,7 +1183,7 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
 			auto operand = R(y, a);
 			increment(f, operand);
 			R(y, a, operand);
-			cycles += 4;
+			addCycles(4);
 			break;
 		} case 5: {	// 8-bit DEC
 			if (m_displaced && (y == 6))
@@ -1191,17 +1191,17 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
 			auto operand = R(y, a);
 			decrement(f, operand);
 			R(y, a, operand);
-			cycles += 4;
+			addCycles(4);
 			if (y == 6)
-				cycles += 7;
+				addCycles(7);
 			break;
 		} case 6:	// 8-bit load immediate
 			if (m_displaced && (y == 6))
 				fetchDisplacement();
 			R(y, a, fetchByte());	// LD r,n
-			cycles += 7;
+			addCycles(7);
 			if (y == 6)
-				cycles += 3;
+				addCycles(3);
 			break;
 		case 7:	// Assorted operations on accumulator/flags
 			switch (y) {
@@ -1232,7 +1232,7 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
 			default:
 				UNREACHABLE;
 			}
-			cycles += 4;
+			addCycles(4);
 			break;
 		default:
 			UNREACHABLE;
@@ -1274,9 +1274,9 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
 			if (normal)
 				R(y, a, R(z, a));
 			if ((y == 6) || (z == 6))	// M operations
-				cycles += 3;
+				addCycles(3);
 		}
-		cycles += 4;
+		addCycles(4);
 		break;
 	case 2:	// Operate on accumulator and register/memory location
 		if (m_displaced && (z == 6))
@@ -1309,40 +1309,40 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
 		default:
 			UNREACHABLE;
 		}
-		cycles += 4;
+		addCycles(4);
 		if (z == 6)
-			cycles += 3;
+			addCycles(3);
 		break;
 	case 3:
 		switch (z) {
 		case 0:	// Conditional return
 			if (returnConditionalFlag(f, y))
-				cycles += 6;
-			cycles += 5;
+				addCycles(6);
+			addCycles(5);
 			break;
 		case 1:	// POP & various ops
 			switch (q) {
 			case 0:	// POP rp2[p]
 				popWord(RP2(p));
-				cycles += 10;
+				addCycles(10);
 				break;
 			case 1:
 				switch (p) {
 				case 0:	// RET
 					ret();
-					cycles += 10;
+					addCycles(10);
 					break;
 				case 1:	// EXX
 					exx();
-					cycles += 4;
+					addCycles(4);
 					break;
 				case 2:	// JP HL
 					PC() = HL2();
-					cycles += 4;
+					addCycles(4);
 					break;
 				case 3:	// LD SP,HL
 					SP() = HL2();
-					cycles += 4;
+					addCycles(4);
 					break;
 				default:
 					UNREACHABLE;
@@ -1354,14 +1354,14 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
 			break;
 		case 2:	// Conditional jump
 			jumpConditionalFlag(f, y);
-			cycles += 10;
+			addCycles(10);
 			break;
 		case 3:	// Assorted operations
 			switch (y) {
 			case 0:	// JP nn
 				fetchWord();
 				jump();
-				cycles += 10;
+				addCycles(10);
 				break;
 			case 1:	// CB prefix
 				m_prefixCB = true;
@@ -1371,27 +1371,27 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
 				break;
 			case 2:	// OUT (n),A
 				writePort(fetchByte(), a);
-				cycles += 11;
+				addCycles(11);
 				break;
 			case 3:	// IN A,(n)
 				readPort(fetchByte(), a);
-				cycles += 11;
+				addCycles(11);
 				break;
 			case 4:	// EX (SP),HL
 				xhtl(HL2());
-				cycles += 19;
+				addCycles(19);
 				break;
 			case 5:	// EX DE,HL
 				std::swap(DE(), HL());
-				cycles += 4;
+				addCycles(4);
 				break;
 			case 6:	// DI
 				di();
-				cycles += 4;
+				addCycles(4);
 				break;
 			case 7:	// EI
 				ei();
-				cycles += 4;
+				addCycles(4);
 				break;
 			default:
 				UNREACHABLE;
@@ -1399,21 +1399,21 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
 			break;
 		case 4:	// Conditional call: CALL cc[y], nn
 			if (callConditionalFlag(f, y))
-				cycles += 7;
-			cycles += 10;
+				addCycles(7);
+			addCycles(10);
 			break;
 		case 5:	// PUSH & various ops
 			switch (q) {
 			case 0:	// PUSH rp2[p]
 				pushWord(RP2(p));
-				cycles += 11;
+				addCycles(11);
 				break;
 			case 1:
 				switch (p) {
 				case 0:	// CALL nn
 					fetchWord();
 					call();
-					cycles += 17;
+					addCycles(17);
 					break;
 				case 1:	// DD prefix
 					m_displaced = m_prefixDD = true;
@@ -1464,11 +1464,11 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
 			default:
 				UNREACHABLE;
 			}
-			cycles += 7;
+			addCycles(7);
 			break;
 		case 7:	// Restart: RST y * 8
 			restart(y << 3);
-			cycles += 11;
+			addCycles(11);
 			break;
 		default:
 			UNREACHABLE;
diff --git a/Z80/src/stdafx.h b/Z80/src/stdafx.h
index ef248a1..a8e08d0 100644
--- a/Z80/src/stdafx.h
+++ b/Z80/src/stdafx.h
@@ -5,17 +5,18 @@
 #include <string>
 #include <cstdint>
 #include <stdexcept>
-#include <functional>
-#include <algorithm>
-#include <memory>
+#include <cassert>
 
 #include <sstream>
 #include <iostream>
-#include <fstream>
 #include <iomanip>
 
 #include <array>
-#include <vector>
 #include <bitset>
 
 #include <boost/format.hpp>
+
+#include <Memory.h>
+#include <IntelProcessor.h>
+#include <InputOutput.h>
+#include <Signal.h>
diff --git a/Z80/test/Board.cpp b/Z80/test/Board.cpp
index 3136d69..1ff6f7a 100644
--- a/Z80/test/Board.cpp
+++ b/Z80/test/Board.cpp
@@ -1,6 +1,7 @@
 #include "stdafx.h"
 #include "Board.h"
-#include "Disassembler.h"
+
+#include <Disassembler.h>
 
 Board::Board(const Configuration& configuration)
 : m_configuration(configuration),
diff --git a/Z80/test/stdafx.h b/Z80/test/stdafx.h
index 0c89d25..5ec6b1f 100644
--- a/Z80/test/stdafx.h
+++ b/Z80/test/stdafx.h
@@ -3,14 +3,13 @@
 #endif
 
 #include <string>
-#include <cstdint>
-#include <stdexcept>
-#include <algorithm>
-#include <memory>
 
-#include <iostream>
-#include <chrono>
-
-#include <array>
-#include <vector>
-#include <map>
+#include <TestHarness.h>
+#include <Disassembler.h>
+#include <Register.h>
+#include <Ram.h>
+#include <Bus.h>
+#include <InputOutput.h>
+#include <Profiler.h>
+#include <EventArgs.h>
+#include <Z80.h>
diff --git a/Z80/test/test.cpp b/Z80/test/test.cpp
index 97cd46e..a44f12f 100644
--- a/Z80/test/test.cpp
+++ b/Z80/test/test.cpp
@@ -1,8 +1,9 @@
 #include "stdafx.h"
-#include "TestHarness.h"
 #include "Configuration.h"
 #include "Board.h"
 
+#include <TestHarness.h>
+
 int main(int, char*[]) {
 
 	Configuration configuration;
diff --git a/inc/InputOutput.h b/inc/InputOutput.h
index be22bd3..6696d5f 100644
--- a/inc/InputOutput.h
+++ b/inc/InputOutput.h
@@ -12,9 +12,9 @@ namespace EightBit {
 		void write(uint8_t port, uint8_t value) { return writeOutputPort(port, value); }
 
 		uint8_t readInputPort(uint8_t port);
-		void writeInputPort(uint8_t port, uint8_t value) { input[port] = value; }
+		void writeInputPort(uint8_t port, uint8_t value) { m_input[port] = value; }
 
-		uint8_t readOutputPort(uint8_t port) { return output[port]; }
+		uint8_t readOutputPort(uint8_t port) { return m_output[port]; }
 		void writeOutputPort(uint8_t port, uint8_t value);
 
 		Signal<uint8_t> ReadingPort;
@@ -31,7 +31,7 @@ namespace EightBit {
 		void OnWrittenPort(uint8_t port);
 
 	private:
-		std::array<uint8_t, 0x100> input;
-		std::array<uint8_t, 0x100> output;
+		std::array<uint8_t, 0x100> m_input;
+		std::array<uint8_t, 0x100> m_output;
 	};
 }
\ No newline at end of file
diff --git a/inc/IntelProcessor.h b/inc/IntelProcessor.h
index 5ecc6b0..73590a9 100644
--- a/inc/IntelProcessor.h
+++ b/inc/IntelProcessor.h
@@ -41,7 +41,7 @@ namespace EightBit {
 		virtual void initialise() override;
 		virtual void reset() override;
 
-		register16_t& SP() { return sp; }
+		register16_t& SP() { return m_sp; }
 
 		virtual register16_t& AF() = 0;
 		uint8_t& A() { return AF().high; }
@@ -188,6 +188,6 @@ namespace EightBit {
 
 	private:
 		std::array<opcode_decoded_t, 0x100> m_decodedOpcodes;
-		register16_t sp;
+		register16_t m_sp;
 	};
 }
\ No newline at end of file
diff --git a/inc/Memory.h b/inc/Memory.h
index 4a38a23..83921da 100644
--- a/inc/Memory.h
+++ b/inc/Memory.h
@@ -19,7 +19,7 @@ namespace EightBit {
 		}
 
 	protected:
-		std::vector<uint8_t> m_bytes;
+		std::vector<uint8_t>& BYTES() { return m_bytes; }
 
 		uint8_t read(uint16_t address) const {
 			return m_bytes[address];
@@ -30,6 +30,8 @@ namespace EightBit {
 		}
 
 	private:
+		std::vector<uint8_t> m_bytes;
+
 		static int loadBinary(
 			const std::string& path,
 			std::vector<uint8_t>& output,
diff --git a/inc/Processor.h b/inc/Processor.h
index c6e7713..f762918 100644
--- a/inc/Processor.h
+++ b/inc/Processor.h
@@ -64,10 +64,10 @@ namespace EightBit {
 
 		Bus& BUS() { return m_bus; }
 
-		register16_t& PC() { return pc; }
+		register16_t& PC() { return m_pc; }
 		register16_t& MEMPTR() { return m_memptr; }
 
-		bool isHalted() const { return m_halted; }
+		bool halted() const { return m_halted; }
 		void halt() { --PC().word;  m_halted = true; }
 		void proceed() { ++PC().word; m_halted = false; }
 
@@ -98,9 +98,6 @@ namespace EightBit {
 
 		Processor(Bus& memory);
 
-		Bus& m_bus;
-		int cycles;
-
 		virtual uint8_t fetchByte() {
 			return getByte(PC().word++);
 		}
@@ -153,8 +150,15 @@ namespace EightBit {
 			jump();
 		}
 
+		int cycles() const { return m_cycles; }
+		void resetCycles() { m_cycles = 0; }
+		void addCycles(int extra) { m_cycles += extra; }
+		void addCycle() { ++m_cycles;  }
+
 	private:
-		register16_t pc;
+		Bus& m_bus;
+		int m_cycles;
+		register16_t m_pc;
 		register16_t m_memptr;
 		bool m_halted;
 		bool m_power;
diff --git a/inc/Ram.h b/inc/Ram.h
index 45526a5..903c37d 100644
--- a/inc/Ram.h
+++ b/inc/Ram.h
@@ -19,7 +19,7 @@ namespace EightBit {
 		}
 
 		uint8_t& reference(uint16_t address) {
-			return m_bytes[address];
+			return BYTES()[address];
 		}
 	};
 }
diff --git a/inc/Rom.h b/inc/Rom.h
index 5557de1..a33e8f5 100644
--- a/inc/Rom.h
+++ b/inc/Rom.h
@@ -15,7 +15,7 @@ namespace EightBit {
 		}
 
 		uint8_t& reference(uint16_t address) {
-			return m_bytes[address];
+			return BYTES()[address];
 		}
 	};
 }
\ No newline at end of file
diff --git a/inc/Signal.h b/inc/Signal.h
index 83445ef..08c596a 100644
--- a/inc/Signal.h
+++ b/inc/Signal.h
@@ -9,16 +9,16 @@ namespace EightBit {
 		typedef std::function<void(const T&)> delegate_t;
 		typedef std::vector<delegate_t> delegates_t;
 
-		delegates_t delegates;
+		delegates_t m_delegates;
 
 	public:
 		void connect(delegate_t functor) {
-			delegates.push_back(functor);
+			m_delegates.push_back(functor);
 		}
 
 		void fire(const T& e) const {
-			if (!delegates.empty())
-				for (auto& delegate : delegates)
+			if (!m_delegates.empty())
+				for (auto& delegate : m_delegates)
 					delegate(e);
 		}
 	};
diff --git a/inc/TestHarness.h b/inc/TestHarness.h
index 1f4a388..fac13c0 100644
--- a/inc/TestHarness.h
+++ b/inc/TestHarness.h
@@ -63,7 +63,7 @@ namespace EightBit {
 			auto& cpu = m_board.CPU();
 			cpu.powerOn();
 
-			while (!cpu.isHalted()) {
+			while (!cpu.halted()) {
 				m_totalCycles += cpu.step();
 				++m_instructions;
 			}
diff --git a/src/InputOutput.cpp b/src/InputOutput.cpp
index 7ad30c7..7541b9a 100644
--- a/src/InputOutput.cpp
+++ b/src/InputOutput.cpp
@@ -3,14 +3,14 @@
 
 uint8_t EightBit::InputOutput::readInputPort(uint8_t port) {
 	OnReadingPort(port);
-	const auto value = input[port];
+	const auto value = m_input[port];
 	OnReadPort(port);
 	return value;
 }
 
 void EightBit::InputOutput::writeOutputPort(uint8_t port, uint8_t value) {
 	OnWritingPort(port);
-	output[port] = value;
+	m_output[port] = value;
 	OnWrittenPort(port);
 }
 
diff --git a/src/Processor.cpp b/src/Processor.cpp
index b9ffdbb..9555eca 100644
--- a/src/Processor.cpp
+++ b/src/Processor.cpp
@@ -3,7 +3,7 @@
 
 EightBit::Processor::Processor(Bus& bus)
 : m_bus(bus),
-  cycles(0),
+  m_cycles(0),
   m_halted(false),
   m_power(false) {
 	PC().word = MEMPTR().word = 0;