mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2025-04-09 17:37:45 +00:00
Start adding comparison operations to EightBit classes
This commit is contained in:
parent
af7679505c
commit
945fcefb36
@ -35,10 +35,14 @@ namespace EightBit {
|
||||
virtual int execute() final;
|
||||
virtual int step() final;
|
||||
|
||||
[[nodiscard]] virtual register16_t& AF() noexcept final;
|
||||
[[nodiscard]] virtual register16_t& BC() noexcept final;
|
||||
[[nodiscard]] virtual register16_t& DE() noexcept final;
|
||||
[[nodiscard]] virtual register16_t& HL() noexcept final;
|
||||
[[nodiscard]] const register16_t& AF() const noexcept final;
|
||||
[[nodiscard]] auto& AF() noexcept { return IntelProcessor::AF(); }
|
||||
[[nodiscard]] const register16_t& BC() const noexcept final;
|
||||
[[nodiscard]] auto& BC() noexcept { return IntelProcessor::BC(); }
|
||||
[[nodiscard]] const register16_t& DE() const noexcept final;
|
||||
[[nodiscard]] auto& DE() noexcept { return IntelProcessor::DE(); }
|
||||
[[nodiscard]] const register16_t& HL() const noexcept final;
|
||||
[[nodiscard]] auto& HL() noexcept { return IntelProcessor::HL(); }
|
||||
|
||||
[[nodiscard]] bool requestingIO() noexcept { return m_requestIO; }
|
||||
[[nodiscard]] bool requestingMemory() noexcept { return m_requestMemory; }
|
||||
|
@ -19,20 +19,21 @@ EightBit::Intel8080::Intel8080(Bus& bus)
|
||||
DEFINE_PIN_LEVEL_CHANGERS(DBIN, Intel8080);
|
||||
DEFINE_PIN_LEVEL_CHANGERS(WR, Intel8080);
|
||||
|
||||
EightBit::register16_t& EightBit::Intel8080::AF() noexcept {
|
||||
af.low = (af.low | Bit1) & ~(Bit5 | Bit3);
|
||||
const EightBit::register16_t& EightBit::Intel8080::AF() const noexcept {
|
||||
auto* processor = const_cast<Intel8080*>(this);
|
||||
processor->af.low = (af.low | Bit1) & ~(Bit5 | Bit3);
|
||||
return af;
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::Intel8080::BC() noexcept {
|
||||
const EightBit::register16_t& EightBit::Intel8080::BC() const noexcept {
|
||||
return bc;
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::Intel8080::DE() noexcept {
|
||||
const EightBit::register16_t& EightBit::Intel8080::DE() const noexcept {
|
||||
return de;
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::Intel8080::HL() noexcept {
|
||||
const EightBit::register16_t& EightBit::Intel8080::HL() const noexcept {
|
||||
return hl;
|
||||
}
|
||||
|
||||
|
@ -26,10 +26,14 @@ namespace EightBit {
|
||||
Signal<LR35902> ExecutingInstruction;
|
||||
Signal<LR35902> ExecutedInstruction;
|
||||
|
||||
[[nodiscard]] register16_t& AF() noexcept final;
|
||||
[[nodiscard]] register16_t& BC() noexcept final;
|
||||
[[nodiscard]] register16_t& DE() noexcept final;
|
||||
[[nodiscard]] register16_t& HL() noexcept final;
|
||||
[[nodiscard]] const register16_t& AF() const noexcept final;
|
||||
[[nodiscard]] auto& AF() noexcept { return IntelProcessor::AF(); }
|
||||
[[nodiscard]] const register16_t& BC() const noexcept final;
|
||||
[[nodiscard]] auto& BC() noexcept { return IntelProcessor::BC(); }
|
||||
[[nodiscard]] const register16_t& DE() const noexcept final;
|
||||
[[nodiscard]] auto& DE() noexcept { return IntelProcessor::DE(); }
|
||||
[[nodiscard]] const register16_t& HL() const noexcept final;
|
||||
[[nodiscard]] auto& HL() noexcept { return IntelProcessor::HL(); }
|
||||
|
||||
bool& IME() noexcept { return m_ime; }
|
||||
|
||||
|
@ -13,20 +13,21 @@ EightBit::GameBoy::LR35902::LR35902(Bus& memory)
|
||||
});
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::GameBoy::LR35902::AF() noexcept {
|
||||
af.low = higherNibble(af.low);
|
||||
const EightBit::register16_t& EightBit::GameBoy::LR35902::AF() const noexcept {
|
||||
auto* gb = const_cast<LR35902*>(this);
|
||||
gb->af.low = higherNibble(af.low);
|
||||
return af;
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::GameBoy::LR35902::BC() noexcept {
|
||||
const EightBit::register16_t& EightBit::GameBoy::LR35902::BC() const noexcept {
|
||||
return bc;
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::GameBoy::LR35902::DE() noexcept {
|
||||
const EightBit::register16_t& EightBit::GameBoy::LR35902::DE() const noexcept {
|
||||
return de;
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::GameBoy::LR35902::HL() noexcept {
|
||||
const EightBit::register16_t& EightBit::GameBoy::LR35902::HL() const noexcept {
|
||||
return hl;
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,8 @@ namespace EightBit {
|
||||
|
||||
Z80(Bus& bus);
|
||||
|
||||
bool operator==(const Z80& rhs) const;
|
||||
|
||||
Signal<Z80> ExecutingInstruction;
|
||||
Signal<Z80> ExecutedInstruction;
|
||||
|
||||
@ -89,16 +91,22 @@ namespace EightBit {
|
||||
int execute() final;
|
||||
int step() final;
|
||||
|
||||
[[nodiscard]] register16_t& AF() noexcept final;
|
||||
[[nodiscard]] register16_t& BC() noexcept final;
|
||||
[[nodiscard]] register16_t& DE() noexcept final;
|
||||
[[nodiscard]] register16_t& HL() noexcept final;
|
||||
[[nodiscard]] const register16_t& AF() const noexcept final;
|
||||
[[nodiscard]] auto& AF() noexcept { return IntelProcessor::AF(); }
|
||||
[[nodiscard]] const register16_t& BC() const noexcept final;
|
||||
[[nodiscard]] auto& BC() noexcept { return IntelProcessor::BC(); }
|
||||
[[nodiscard]] const register16_t& DE() const noexcept final;
|
||||
[[nodiscard]] auto& DE() noexcept { return IntelProcessor::DE(); }
|
||||
[[nodiscard]] const register16_t& HL() const noexcept final;
|
||||
[[nodiscard]] auto& HL() noexcept { return IntelProcessor::HL(); }
|
||||
|
||||
[[nodiscard]] auto& IX() noexcept { return m_ix; }
|
||||
[[nodiscard]] const auto& IX() const noexcept { return m_ix; }
|
||||
NON_CONST_REGISTOR_ACCESSOR(IX);
|
||||
[[nodiscard]] auto& IXH() noexcept { return IX().high; }
|
||||
[[nodiscard]] auto& IXL() noexcept { return IX().low; }
|
||||
|
||||
[[nodiscard]] auto& IY() noexcept { return m_iy; }
|
||||
[[nodiscard]] const auto& IY() const noexcept { return m_iy; }
|
||||
NON_CONST_REGISTOR_ACCESSOR(IY);
|
||||
[[nodiscard]] auto& IYH() noexcept { return IY().high; }
|
||||
[[nodiscard]] auto& IYL() noexcept { return IY().low; }
|
||||
|
||||
@ -114,11 +122,16 @@ namespace EightBit {
|
||||
// programmer. During refresh, the contents of the I Register are placed on the upper eight
|
||||
// bits of the address bus.
|
||||
[[nodiscard]] constexpr auto& REFRESH() noexcept { return m_refresh; }
|
||||
[[nodiscard]] constexpr auto REFRESH() const noexcept { return m_refresh; }
|
||||
|
||||
[[nodiscard]] constexpr auto& IV() noexcept { return iv; }
|
||||
[[nodiscard]] constexpr auto IV() const noexcept { return iv; }
|
||||
[[nodiscard]] constexpr auto& IM() noexcept { return m_interruptMode; }
|
||||
[[nodiscard]] constexpr auto IM() const noexcept { return m_interruptMode; }
|
||||
[[nodiscard]] constexpr auto& IFF1() noexcept { return m_iff1; }
|
||||
[[nodiscard]] constexpr auto IFF1() const noexcept { return m_iff1; }
|
||||
[[nodiscard]] constexpr auto& IFF2() noexcept { return m_iff2; }
|
||||
[[nodiscard]] constexpr auto IFF2() const noexcept { return m_iff2; }
|
||||
|
||||
constexpr void exx() noexcept { m_registerSet ^= 1; }
|
||||
constexpr void exxAF() noexcept { m_accumulatorFlagsSet ^= 1; }
|
||||
|
@ -23,7 +23,8 @@ EightBit::Z80::Z80(Bus& bus)
|
||||
exxAF();
|
||||
exx();
|
||||
|
||||
AF() = IX() = IY() = BC() = DE() = HL() = Mask16;
|
||||
IX() = IY() = Mask16;
|
||||
resetWorkingRegisters();
|
||||
|
||||
resetPrefixes();
|
||||
});
|
||||
@ -33,6 +34,35 @@ EightBit::Z80::Z80(Bus& bus)
|
||||
});
|
||||
}
|
||||
|
||||
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()
|
||||
&& NMI() == rhs.NMI()
|
||||
&& M1() == rhs.M1()
|
||||
&& MREQ() == rhs.MREQ()
|
||||
&& IORQ() == rhs.IORQ()
|
||||
&& RD() == rhs.RD()
|
||||
&& WR() == rhs.WR()
|
||||
&& AF() == rhs.AF()
|
||||
&& BC() == rhs.BC()
|
||||
&& DE() == rhs.DE()
|
||||
&& HL() == rhs.HL()
|
||||
&& IX() == rhs.IX()
|
||||
&& IY() == rhs.IY()
|
||||
&& REFRESH() == rhs.REFRESH()
|
||||
&& IV() == rhs.IV()
|
||||
&& IM() == rhs.IM()
|
||||
&& IFF1() == rhs.IFF1()
|
||||
&& IFF2() == rhs.IFF2();
|
||||
}
|
||||
|
||||
DEFINE_PIN_LEVEL_CHANGERS(NMI, Z80);
|
||||
DEFINE_PIN_LEVEL_CHANGERS(M1, Z80);
|
||||
DEFINE_PIN_LEVEL_CHANGERS(RFSH, Z80);
|
||||
@ -41,19 +71,19 @@ DEFINE_PIN_LEVEL_CHANGERS(IORQ, Z80);
|
||||
DEFINE_PIN_LEVEL_CHANGERS(RD, Z80);
|
||||
DEFINE_PIN_LEVEL_CHANGERS(WR, Z80);
|
||||
|
||||
EightBit::register16_t& EightBit::Z80::AF() noexcept {
|
||||
const EightBit::register16_t& EightBit::Z80::AF() const noexcept {
|
||||
return m_accumulatorFlags[m_accumulatorFlagsSet];
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::Z80::BC() noexcept {
|
||||
const EightBit::register16_t& EightBit::Z80::BC() const noexcept {
|
||||
return m_registers[m_registerSet][BC_IDX];
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::Z80::DE() noexcept {
|
||||
const EightBit::register16_t& EightBit::Z80::DE() const noexcept {
|
||||
return m_registers[m_registerSet][DE_IDX];
|
||||
}
|
||||
|
||||
EightBit::register16_t& EightBit::Z80::HL() noexcept {
|
||||
const EightBit::register16_t& EightBit::Z80::HL() const noexcept {
|
||||
return m_registers[m_registerSet][HL_IDX];
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,8 @@ namespace EightBit {
|
||||
public:
|
||||
virtual ~ClockedChip() noexcept {};
|
||||
|
||||
bool operator==(const ClockedChip& rhs) const;
|
||||
|
||||
Signal<EventArgs> Ticked;
|
||||
|
||||
[[nodiscard]] constexpr auto cycles() const noexcept { return m_cycles; }
|
||||
|
@ -108,6 +108,8 @@ namespace EightBit {
|
||||
|
||||
virtual ~Device() noexcept {};
|
||||
|
||||
bool operator==(const Device& rhs) const;
|
||||
|
||||
[[nodiscard]] constexpr bool powered() const noexcept { return raised(POWER()); }
|
||||
|
||||
protected:
|
||||
|
@ -9,6 +9,16 @@
|
||||
#include "Signal.h"
|
||||
#include "EightBitCompilerDefinitions.h"
|
||||
|
||||
#define NON_CONST_ACCESSOR(accessor, type) \
|
||||
[[nodiscard]] auto& accessor() noexcept { \
|
||||
const auto& consted = *this; \
|
||||
const auto& reference = consted.accessor(); \
|
||||
return const_cast<type&>(reference); \
|
||||
}
|
||||
|
||||
#define NON_CONST_REGISTOR_ACCESSOR(accessor) \
|
||||
NON_CONST_ACCESSOR(accessor, register16_t)
|
||||
|
||||
namespace EightBit {
|
||||
|
||||
class Bus;
|
||||
@ -36,27 +46,35 @@ namespace EightBit {
|
||||
|
||||
virtual ~IntelProcessor() {};
|
||||
|
||||
bool operator==(const IntelProcessor& rhs) const;
|
||||
|
||||
[[nodiscard]] constexpr const auto& getDecodedOpcode(const size_t i) const noexcept {
|
||||
return m_decodedOpcodes[i];
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto& MEMPTR() noexcept { return m_memptr; }
|
||||
[[nodiscard]] constexpr auto MEMPTR() const noexcept { return m_memptr; }
|
||||
|
||||
[[nodiscard]] constexpr auto& SP() noexcept { return m_sp; }
|
||||
[[nodiscard]] register16_t SP() const noexcept { return m_sp; }
|
||||
|
||||
[[nodiscard]] virtual register16_t& AF() noexcept = 0;
|
||||
[[nodiscard]] virtual const register16_t& AF() const noexcept = 0;
|
||||
NON_CONST_REGISTOR_ACCESSOR(AF);
|
||||
[[nodiscard]] auto& A() noexcept { return AF().high; }
|
||||
[[nodiscard]] auto& F() noexcept { return AF().low; }
|
||||
|
||||
[[nodiscard]] virtual register16_t& BC() noexcept = 0;
|
||||
[[nodiscard]] virtual const register16_t& BC() const noexcept = 0;
|
||||
NON_CONST_REGISTOR_ACCESSOR(BC);
|
||||
[[nodiscard]] auto& B() noexcept { return BC().high; }
|
||||
[[nodiscard]] auto& C() noexcept { return BC().low; }
|
||||
|
||||
[[nodiscard]] virtual register16_t& DE() noexcept = 0;
|
||||
[[nodiscard]] virtual const register16_t& DE() const noexcept = 0;
|
||||
NON_CONST_REGISTOR_ACCESSOR(DE);
|
||||
[[nodiscard]] auto& D() noexcept { return DE().high; }
|
||||
[[nodiscard]] auto& E() noexcept { return DE().low; }
|
||||
|
||||
[[nodiscard]] virtual register16_t& HL() noexcept = 0;
|
||||
[[nodiscard]] virtual const register16_t& HL() const noexcept = 0;
|
||||
NON_CONST_REGISTOR_ACCESSOR(HL);
|
||||
[[nodiscard]] auto& H() noexcept { return HL().high; }
|
||||
[[nodiscard]] auto& L() noexcept { return HL().low; }
|
||||
|
||||
@ -141,6 +159,8 @@ namespace EightBit {
|
||||
virtual int jrConditional(int condition);
|
||||
void ret() override;
|
||||
|
||||
void resetWorkingRegisters();
|
||||
|
||||
private:
|
||||
static std::array<int, 8> m_halfCarryTableAdd;
|
||||
static std::array<int, 8> m_halfCarryTableSub;
|
||||
|
@ -23,7 +23,10 @@ namespace EightBit {
|
||||
|
||||
virtual ~Processor() noexcept {}
|
||||
|
||||
bool operator==(const Processor& rhs) const;
|
||||
|
||||
[[nodiscard]] constexpr auto& PC() noexcept { return m_pc; }
|
||||
[[nodiscard]] constexpr const auto& PC() const noexcept { return m_pc; }
|
||||
|
||||
int run(int limit);
|
||||
virtual int step() = 0;
|
||||
|
@ -28,6 +28,7 @@ namespace EightBit {
|
||||
Rom(size_t size = 0) noexcept;
|
||||
Rom(const Rom& rhs);
|
||||
Rom& operator=(const Rom& rhs);
|
||||
bool operator==(const Rom& rhs) const;
|
||||
|
||||
[[nodiscard]] size_t size() const noexcept final;
|
||||
|
||||
|
@ -14,3 +14,9 @@ void EightBit::ClockedChip::tick() {
|
||||
void EightBit::ClockedChip::resetCycles() noexcept {
|
||||
m_cycles = 0;
|
||||
}
|
||||
|
||||
bool EightBit::ClockedChip::operator==(const EightBit::ClockedChip& rhs) const {
|
||||
return
|
||||
Device::operator==(rhs)
|
||||
&& cycles() == rhs.cycles();
|
||||
}
|
||||
|
@ -2,3 +2,7 @@
|
||||
#include "../inc/Device.h"
|
||||
|
||||
DEFINE_PIN_LEVEL_CHANGERS(POWER, Device);
|
||||
|
||||
bool EightBit::Device::operator==(const EightBit::Device& rhs) const {
|
||||
return POWER() == rhs.POWER();
|
||||
}
|
||||
|
@ -13,11 +13,16 @@ EightBit::IntelProcessor::IntelProcessor(Bus& bus)
|
||||
RaisedHALT.connect([this](EventArgs) noexcept { ++PC(); });
|
||||
|
||||
RaisedPOWER.connect([this](EventArgs) {
|
||||
PC() = SP() = AF() = BC() = DE() = HL() = Mask16;
|
||||
PC() = SP() = Mask16;
|
||||
resetWorkingRegisters();
|
||||
raiseHALT();
|
||||
});
|
||||
}
|
||||
|
||||
void EightBit::IntelProcessor::resetWorkingRegisters() {
|
||||
AF() = BC() = DE() = HL() = Mask16;
|
||||
}
|
||||
|
||||
DEFINE_PIN_LEVEL_CHANGERS(HALT, IntelProcessor);
|
||||
|
||||
void EightBit::IntelProcessor::handleRESET() {
|
||||
@ -85,3 +90,15 @@ void EightBit::IntelProcessor::ret() {
|
||||
Processor::ret();
|
||||
MEMPTR() = PC();
|
||||
}
|
||||
|
||||
bool EightBit::IntelProcessor::operator==(const EightBit::IntelProcessor& rhs) const {
|
||||
return
|
||||
Processor::operator==(rhs)
|
||||
&& HALT() == rhs.HALT()
|
||||
&& MEMPTR() == rhs.MEMPTR()
|
||||
&& SP() == rhs.SP()
|
||||
&& AF() == rhs.AF()
|
||||
&& BC() == rhs.BC()
|
||||
&& DE() == rhs.DE()
|
||||
&& HL() == rhs.HL();
|
||||
}
|
||||
|
@ -98,3 +98,11 @@ void EightBit::Processor::call(const register16_t destination) {
|
||||
void EightBit::Processor::ret() {
|
||||
jump(popWord());
|
||||
}
|
||||
|
||||
bool EightBit::Processor::operator==(const EightBit::Processor& rhs) const {
|
||||
return
|
||||
ClockedChip::operator==(rhs)
|
||||
&& RESET() == rhs.RESET()
|
||||
&& INT() == rhs.INT()
|
||||
&& PC() == rhs.PC();
|
||||
}
|
||||
|
@ -3,6 +3,10 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
bool EightBit::Rom::operator==(const Rom& rhs) const {
|
||||
return BYTES() == rhs.BYTES();
|
||||
}
|
||||
|
||||
int EightBit::Rom::load(std::ifstream& file, std::vector<uint8_t>& output, const int writeOffset, const int readOffset, int limit, const int maximumSize) {
|
||||
|
||||
file.seekg(0, std::ios::end);
|
||||
|
Loading…
x
Reference in New Issue
Block a user