From 1f5dc54c404daef9ea3d5f0a290161e3138ee194 Mon Sep 17 00:00:00 2001
From: Adrian Conlon <adrian.conlon@gmail.com>
Date: Mon, 27 Dec 2021 22:07:30 +0000
Subject: [PATCH] Copy constructor and equality operations added.

---
 Z80/inc/Z80.h                 |  1 +
 Z80/src/Z80.cpp               | 70 ++++++++++++++++++++++++++++-------
 inc/Chip.h                    |  3 ++
 inc/ClockedChip.h             |  1 +
 inc/Device.h                  |  1 +
 inc/IntelProcessor.h          |  1 +
 inc/LittleEndianProcessor.h   |  1 +
 inc/Processor.h               |  1 +
 src/ClockedChip.cpp           |  5 +++
 src/Device.cpp                |  4 ++
 src/IntelProcessor.cpp        |  9 +++++
 src/LittleEndianProcessor.cpp |  3 ++
 src/Processor.cpp             |  8 ++++
 13 files changed, 95 insertions(+), 13 deletions(-)

diff --git a/Z80/inc/Z80.h b/Z80/inc/Z80.h
index 5264f03..8d6b6a8 100644
--- a/Z80/inc/Z80.h
+++ b/Z80/inc/Z80.h
@@ -71,6 +71,7 @@ namespace EightBit {
 
 		Z80(Bus& bus);
 
+		Z80(const Z80& rhs);
 		bool operator==(const Z80& rhs) const;
 
 		Signal<Z80> ExecutingInstruction;
diff --git a/Z80/src/Z80.cpp b/Z80/src/Z80.cpp
index 898f34a..21e7137 100644
--- a/Z80/src/Z80.cpp
+++ b/Z80/src/Z80.cpp
@@ -34,33 +34,77 @@ EightBit::Z80::Z80(Bus& bus)
 	});
 }
 
+EightBit::Z80::Z80(const Z80& rhs)
+: IntelProcessor(rhs) {
+
+	m_registers = rhs.m_registers;
+	m_registerSet = rhs.m_registerSet;
+
+	m_accumulatorFlags = rhs.m_accumulatorFlags;
+	m_accumulatorFlagsSet = rhs.m_accumulatorFlagsSet;
+
+	m_ix = rhs.m_ix;
+	m_iy = rhs.m_iy;
+
+	m_refresh = rhs.m_refresh;
+
+	iv = rhs.iv;
+	m_interruptMode = rhs.m_interruptMode;
+	m_iff1 = rhs.m_iff1;
+	m_iff2 = rhs.m_iff2;
+
+	RFSH() = rhs.RFSH();
+	NMI() = rhs.NMI();
+	M1() = rhs.M1();
+	MREQ() = rhs.MREQ();
+	IORQ() = rhs.IORQ();
+	RD() = rhs.RD();
+	WR() = rhs.WR();
+}
+
 bool EightBit::Z80::operator==(const EightBit::Z80& rhs) const {
 
 	const auto base = IntelProcessor::operator==(rhs);
 
-	auto* z80 = const_cast<Z80*>(this);
-	z80->exxAF();
-	z80->exx();
-
-	return base
-		&& RFSH() == rhs.RFSH()
+	const auto pins =
+		RFSH() == rhs.RFSH()
 		&& NMI() == rhs.NMI()
 		&& M1() == rhs.M1()
 		&& MREQ() == rhs.MREQ()
 		&& IORQ() == rhs.IORQ()
 		&& RD() == rhs.RD()
-		&& WR() == rhs.WR()
-		&& AF() == rhs.AF()
-		&& BC() == rhs.BC()
+		&& WR() == rhs.WR();
+
+	auto* z80 = const_cast<Z80*>(this);
+	auto& z80_rhs = const_cast<Z80&>(rhs);
+
+	z80->exxAF();
+	z80_rhs.exxAF();
+	const auto af = AF() == rhs.AF();
+	z80->exxAF();
+	z80_rhs.exxAF();
+
+	z80->exx();
+	z80_rhs.exx();
+	const auto pairs =
+		BC() == rhs.BC()
 		&& DE() == rhs.DE()
-		&& HL() == rhs.HL()
-		&& IX() == rhs.IX()
-		&& IY() == rhs.IY()
-		&& REFRESH() == rhs.REFRESH()
+		&& HL() == rhs.HL();
+	z80->exx();
+	z80_rhs.exx();
+
+	const auto indices =
+		IX() == rhs.IX()
+		&& IY() == rhs.IY();
+
+	const auto miscellaneous =
+		REFRESH() == rhs.REFRESH()
 		&& IV() == rhs.IV()
 		&& IM() == rhs.IM()
 		&& IFF1() == rhs.IFF1()
 		&& IFF2() == rhs.IFF2();
+
+	return base && pins && af && pairs && indices && miscellaneous;
 }
 
 DEFINE_PIN_LEVEL_CHANGERS(NMI, Z80);
diff --git a/inc/Chip.h b/inc/Chip.h
index 87ae113..a361ebe 100644
--- a/inc/Chip.h
+++ b/inc/Chip.h
@@ -68,6 +68,9 @@ namespace EightBit {
 
 		virtual ~Chip() {}
 
+		Chip(const Chip& rhs)
+		: Device(rhs) {}
+
 	protected:
 		Chip() noexcept = default;
 	};
diff --git a/inc/ClockedChip.h b/inc/ClockedChip.h
index f534d71..979579f 100644
--- a/inc/ClockedChip.h
+++ b/inc/ClockedChip.h
@@ -9,6 +9,7 @@ namespace EightBit {
 	public:
 		virtual ~ClockedChip() noexcept {};
 
+		ClockedChip(const ClockedChip& rhs);
 		bool operator==(const ClockedChip& rhs) const;
 
 		Signal<EventArgs> Ticked;
diff --git a/inc/Device.h b/inc/Device.h
index c5fd317..d9bd85b 100644
--- a/inc/Device.h
+++ b/inc/Device.h
@@ -108,6 +108,7 @@ namespace EightBit {
 
 		virtual ~Device() noexcept {};
 
+		Device(const Device& rhs);
 		bool operator==(const Device& rhs) const;
 
 		[[nodiscard]] constexpr bool powered() const noexcept { return raised(POWER()); }
diff --git a/inc/IntelProcessor.h b/inc/IntelProcessor.h
index 77e794e..4baaff7 100644
--- a/inc/IntelProcessor.h
+++ b/inc/IntelProcessor.h
@@ -46,6 +46,7 @@ namespace EightBit {
 
 		virtual ~IntelProcessor() {};
 
+		IntelProcessor(const IntelProcessor& rhs);
 		bool operator==(const IntelProcessor& rhs) const;
 
 		[[nodiscard]] constexpr const auto& getDecodedOpcode(const size_t i) const noexcept {
diff --git a/inc/LittleEndianProcessor.h b/inc/LittleEndianProcessor.h
index fbc00f3..1da3158 100644
--- a/inc/LittleEndianProcessor.h
+++ b/inc/LittleEndianProcessor.h
@@ -9,6 +9,7 @@ namespace EightBit {
 	class LittleEndianProcessor : public Processor {
 	public:
 		virtual ~LittleEndianProcessor() {};
+		LittleEndianProcessor(const LittleEndianProcessor& rhs);
 
 		[[nodiscard]] register16_t peekWord(register16_t address) noexcept final;
 		void pokeWord(register16_t address, register16_t value) noexcept final;
diff --git a/inc/Processor.h b/inc/Processor.h
index 3df6ba2..a5832c7 100644
--- a/inc/Processor.h
+++ b/inc/Processor.h
@@ -23,6 +23,7 @@ namespace EightBit {
 
 		virtual ~Processor() noexcept {}
 
+		Processor(const Processor& rhs);
 		bool operator==(const Processor& rhs) const;
 
 		[[nodiscard]] constexpr auto& PC() noexcept { return m_pc; }
diff --git a/src/ClockedChip.cpp b/src/ClockedChip.cpp
index e53a172..145d757 100644
--- a/src/ClockedChip.cpp
+++ b/src/ClockedChip.cpp
@@ -1,6 +1,11 @@
 #include "stdafx.h"
 #include "../inc/ClockedChip.h"
 
+EightBit::ClockedChip::ClockedChip(const ClockedChip& rhs)
+: Chip(rhs) {
+	m_cycles = rhs.m_cycles;
+}
+
 void EightBit::ClockedChip::tick(const int extra) {
 	for (int i = 0; i < extra; ++i)
 		tick();
diff --git a/src/Device.cpp b/src/Device.cpp
index fb57070..ba791b2 100644
--- a/src/Device.cpp
+++ b/src/Device.cpp
@@ -3,6 +3,10 @@
 
 DEFINE_PIN_LEVEL_CHANGERS(POWER, Device);
 
+EightBit::Device::Device(const Device& rhs) {
+	POWER() = rhs.POWER();
+}
+
 bool EightBit::Device::operator==(const EightBit::Device& rhs) const {
 	return POWER() == rhs.POWER();
 }
diff --git a/src/IntelProcessor.cpp b/src/IntelProcessor.cpp
index 5a193cf..b2e9baa 100644
--- a/src/IntelProcessor.cpp
+++ b/src/IntelProcessor.cpp
@@ -19,6 +19,15 @@ EightBit::IntelProcessor::IntelProcessor(Bus& bus)
 	});
 }
 
+EightBit::IntelProcessor::IntelProcessor(const IntelProcessor& rhs)
+: LittleEndianProcessor(rhs) {
+
+	m_sp = rhs.m_sp;
+	m_memptr = rhs.m_memptr;
+
+	HALT() = rhs.HALT();
+}
+
 void EightBit::IntelProcessor::resetWorkingRegisters() {
 	AF() = BC() = DE() = HL() = Mask16;
 }
diff --git a/src/LittleEndianProcessor.cpp b/src/LittleEndianProcessor.cpp
index 5084575..271778a 100644
--- a/src/LittleEndianProcessor.cpp
+++ b/src/LittleEndianProcessor.cpp
@@ -4,6 +4,9 @@
 EightBit::LittleEndianProcessor::LittleEndianProcessor(Bus& memory)
 : Processor(memory) {}
 
+EightBit::LittleEndianProcessor::LittleEndianProcessor(const LittleEndianProcessor& rhs)
+: Processor(rhs) {}
+
 EightBit::register16_t EightBit::LittleEndianProcessor::getWord() {
 	const auto low = memoryRead();
 	++BUS().ADDRESS();
diff --git a/src/Processor.cpp b/src/Processor.cpp
index df8f868..e2b21b5 100644
--- a/src/Processor.cpp
+++ b/src/Processor.cpp
@@ -5,6 +5,14 @@ EightBit::Processor::Processor(Bus& bus) noexcept
 : m_bus(bus) {
 }
 
+EightBit::Processor::Processor(const Processor& rhs)
+: ClockedChip(rhs),
+  m_bus(rhs.m_bus) {
+	RESET() = rhs.RESET();
+	INT() = rhs.INT();
+	PC() = rhs.PC();
+}
+
 DEFINE_PIN_LEVEL_CHANGERS(RESET, Processor);
 DEFINE_PIN_LEVEL_CHANGERS(INT, Processor);