diff --git a/Intel8080/inc/Intel8080.h b/Intel8080/inc/Intel8080.h index 380e69b..369e162 100644 --- a/Intel8080/inc/Intel8080.h +++ b/Intel8080/inc/Intel8080.h @@ -16,7 +16,7 @@ namespace EightBit { CF = Bit0, }; - Intel8080(Memory& memory, InputOutput& ports); + Intel8080(Bus& bus, InputOutput& ports); Signal ExecutingInstruction; diff --git a/Intel8080/src/Disassembler.cpp b/Intel8080/src/Disassembler.cpp index c5747a0..9b5537f 100644 --- a/Intel8080/src/Disassembler.cpp +++ b/Intel8080/src/Disassembler.cpp @@ -168,8 +168,8 @@ std::string EightBit::Disassembler::disassemble(Intel8080& cpu) { void EightBit::Disassembler::disassemble(std::ostringstream& output, Intel8080& cpu, uint16_t pc) { - auto& memory = cpu.getMemory(); - auto opcode = memory.peek(pc); + auto& bus = cpu.BUS(); + auto opcode = bus.peek(pc); output << hex(opcode); @@ -180,11 +180,11 @@ void EightBit::Disassembler::disassemble(std::ostringstream& output, Intel8080& auto p = (y & 0b110) >> 1; auto q = (y & 1); - auto immediate = memory.peek(pc + 1); - auto absolute = memory.peekWord(pc + 1); + auto immediate = bus.peek(pc + 1); + auto absolute = bus.peekWord(pc + 1); auto displacement = (int8_t)immediate; auto relative = pc + displacement + 2; - auto indexedImmediate = memory.peek(pc + 1); + auto indexedImmediate = bus.peek(pc + 1); auto dumpCount = 0; @@ -196,7 +196,7 @@ void EightBit::Disassembler::disassemble(std::ostringstream& output, Intel8080& x, y, z, p, q); for (int i = 0; i < dumpCount; ++i) - output << hex(memory.peek(pc + i + 1)); + output << hex(bus.peek(pc + i + 1)); output << '\t'; m_formatter.parse(specification); diff --git a/Intel8080/src/Intel8080.cpp b/Intel8080/src/Intel8080.cpp index 1933724..6a288fa 100644 --- a/Intel8080/src/Intel8080.cpp +++ b/Intel8080/src/Intel8080.cpp @@ -1,8 +1,8 @@ #include "stdafx.h" #include "Intel8080.h" -EightBit::Intel8080::Intel8080(Memory& memory, InputOutput& ports) -: IntelProcessor(memory), +EightBit::Intel8080::Intel8080(Bus& bus, InputOutput& ports) +: IntelProcessor(bus), m_interrupt(false), m_ports(ports) { bc.word = de.word = hl.word = Mask16; @@ -225,7 +225,7 @@ void EightBit::Intel8080::xhtl() { MEMPTR().low = getByte(SP()); setByte(L()); L() = MEMPTR().low; - m_memory.ADDRESS().word++; + BUS().ADDRESS().word++; MEMPTR().high = getByte(); setByte(H()); H() = MEMPTR().high; diff --git a/inc/Bus.h b/inc/Bus.h new file mode 100644 index 0000000..bca7255 --- /dev/null +++ b/inc/Bus.h @@ -0,0 +1,101 @@ +#pragma once + +#include + +#include "Signal.h" +#include "AddressEventArgs.h" +#include "Register.h" + +namespace EightBit { + class Bus { + public: + Bus() {} + + Signal WrittenByte; + Signal ReadByte; + + register16_t& ADDRESS() { return m_address; } + uint8_t& DATA() { return *m_data; } + + uint8_t& placeDATA(uint8_t value) { + m_temporary = value; + m_data = &m_temporary; + return DATA(); + } + + uint8_t& referenceDATA(uint8_t& value) { + m_data = &value; + return DATA(); + } + + uint8_t peek(uint16_t address) { + bool rom; + return reference(address, rom); + } + + void poke(uint16_t address, uint8_t value) { + bool rom; + reference(address, rom) = value; + } + + uint16_t peekWord(uint16_t address) { + register16_t returned; + returned.low = peek(address); + returned.high = peek(address + 1); + return returned.word; + } + + uint8_t read() { + auto content = reference(); + fireReadBusEvent(); + return content; + } + + uint8_t read(uint16_t offset) { + ADDRESS().word = offset; + return read(); + } + + uint8_t read(register16_t address) { + ADDRESS() = address; + return read(); + } + + void write(uint8_t value) { + reference() = value; + fireWriteBusEvent(); + } + + void write(uint16_t offset, uint8_t value) { + ADDRESS().word = offset; + write(value); + } + + void write(register16_t address, uint8_t value) { + ADDRESS() = address; + write(value); + } + + protected: + void fireReadBusEvent() { + ReadByte.fire(AddressEventArgs(ADDRESS().word, DATA())); + } + + void fireWriteBusEvent() { + WrittenByte.fire(AddressEventArgs(ADDRESS().word, DATA())); + } + + virtual uint8_t& reference(uint16_t address, bool& rom) = 0; + + uint8_t& reference() { + bool rom; + auto& value = reference(ADDRESS().word, rom); + return rom ? placeDATA(value) : referenceDATA(value); + } + + private: + uint8_t m_temporary; // Used to simulate ROM + register16_t m_address; + uint8_t* m_data; + }; +} \ No newline at end of file diff --git a/inc/IntelProcessor.h b/inc/IntelProcessor.h index 48d9be2..b2e90ed 100644 --- a/inc/IntelProcessor.h +++ b/inc/IntelProcessor.h @@ -56,7 +56,7 @@ namespace EightBit { uint8_t& L() { return HL().low; } protected: - IntelProcessor(Memory& memory); + IntelProcessor(Bus& bus); template static void adjustSign(uint8_t& f, uint8_t value) { setFlag(f, T::SF, value & T::SF); @@ -124,21 +124,21 @@ namespace EightBit { // void memptrReference() { - m_memory.ADDRESS() = MEMPTR(); + BUS().ADDRESS() = MEMPTR(); MEMPTR().word++; } virtual void getWordViaMemptr(register16_t& value) { memptrReference(); value.low = getByte(); - m_memory.ADDRESS().word++; + BUS().ADDRESS().word++; value.high = getByte(); } virtual void setWordViaMemptr(register16_t value) { memptrReference(); setByte(value.low); - m_memory.ADDRESS().word++; + BUS().ADDRESS().word++; setByte(value.high); } diff --git a/inc/Memory.h b/inc/Memory.h index 3356889..dbf0079 100644 --- a/inc/Memory.h +++ b/inc/Memory.h @@ -1,143 +1,31 @@ #pragma once -#include #include -#include - -#include "Signal.h" -#include "AddressEventArgs.h" - -#ifdef __BYTE_ORDER__ -# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -# define HOST_LITTLE_ENDIAN -# endif -# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -# define HOST_BIG_ENDIAN -# endif -#else -# if defined(_M_X64) || defined(_M_IX86) -# define HOST_LITTLE_ENDIAN -# else -# define HOST_BIG_ENDIAN -# endif -#endif +#include namespace EightBit { - - typedef union { - struct { -#ifdef HOST_LITTLE_ENDIAN - uint8_t low; - uint8_t high; -#endif -#ifdef HOST_BIG_ENDIAN - uint8_t high; - uint8_t low; -#endif - }; - uint16_t word; - } register16_t; - class Memory { public: - Memory(uint16_t addressMask); - - // Only fired with read/write methods - Signal WrittenByte; - Signal ReadByte; - - register16_t& ADDRESS() { return m_address; } - uint8_t& DATA() { return *m_data; } - - uint8_t& placeDATA(uint8_t value) { - m_temporary = value; - m_data = &m_temporary; - return DATA(); + Memory(size_t size) + : m_bytes(size) { } - uint8_t& referenceDATA(uint8_t& value) { - m_data = &value; - return DATA(); - } - - uint8_t peek(uint16_t address); - void poke(uint16_t address, uint8_t value); - - uint16_t peekWord(uint16_t address); - - virtual int effectiveAddress(int address) const { - return address & m_addressMask; - } - - uint8_t read() { - auto content = reference(); - fireReadBusEvent(); - return content; - } - - uint8_t read(uint16_t offset) { - ADDRESS().word = offset; - return read(); - } - - uint8_t read(register16_t address) { - ADDRESS() = address; - return read(); - } - - void write(uint8_t value) { - reference() = value; - fireWriteBusEvent(); - } - - void write(uint16_t offset, uint8_t value) { - ADDRESS().word = offset; - write(value); - } - - void write(register16_t address, uint8_t value) { - ADDRESS() = address; - write(value); - } - - virtual void clear(); - void loadRom(const std::string& path, uint16_t offset); - void loadRam(const std::string& path, uint16_t offset); - - void lock(int address, int size) { - std::fill(m_locked.begin() + address, m_locked.begin() + address + size, true); + void load(const std::string& path, uint16_t offset = 0) { + loadBinary(path, m_bytes, offset, m_bytes.size() - offset); } protected: - std::vector m_bus; - std::vector m_locked; + std::vector m_bytes; - uint16_t m_addressMask; // Mirror - uint8_t m_temporary; // Used to simulate ROM - register16_t m_address; - uint8_t* m_data; + uint8_t read(uint16_t address) const { + return m_bytes[address]; + } + void write(uint16_t address, uint8_t value) { + m_bytes[address] = value; + } + + private: static int loadBinary(const std::string& path, std::vector& output, int offset = 0, int maximumSize = -1); - - void fireReadBusEvent() { - ReadByte.fire(AddressEventArgs(ADDRESS().word, DATA())); - } - - void fireWriteBusEvent() { - WrittenByte.fire(AddressEventArgs(ADDRESS().word, DATA())); - } - - virtual uint8_t& reference(uint16_t address, bool& rom) { - rom = m_locked[address]; - return m_bus[address]; - } - - uint8_t& reference() { - bool rom; - auto& value = reference(ADDRESS().word, rom); - return rom ? placeDATA(value) : referenceDATA(value); - } - - int loadMemory(const std::string& path, uint16_t offset); }; } \ No newline at end of file diff --git a/inc/Processor.h b/inc/Processor.h index 574a488..c6e7713 100644 --- a/inc/Processor.h +++ b/inc/Processor.h @@ -2,7 +2,8 @@ #include -#include "Memory.h" +#include "Bus.h" +#include "Register.h" #ifdef _MSC_VER # define UNREACHABLE __assume(0) @@ -61,7 +62,7 @@ namespace EightBit { static int promoteNibble(int value) { return value << 4; } static int demoteNibble(int value) { return highNibble(value); } - Memory& getMemory() { return m_memory; } + Bus& BUS() { return m_bus; } register16_t& PC() { return pc; } register16_t& MEMPTR() { return m_memptr; } @@ -95,9 +96,9 @@ namespace EightBit { static void clearFlag(uint8_t& f, int flag, uint32_t condition) { clearFlag(f, flag, condition != 0); } static void clearFlag(uint8_t& f, int flag, bool condition) { condition ? clearFlag(f, flag) : setFlag(f, flag); } - Processor(Memory& memory); + Processor(Bus& memory); - Memory& m_memory; + Bus& m_bus; int cycles; virtual uint8_t fetchByte() { @@ -119,11 +120,11 @@ namespace EightBit { return execute(fetchByte()); } - uint8_t getByte() { return m_memory.read(); } - template uint8_t getByte(T offset) { return m_memory.read(offset); } + uint8_t getByte() { return BUS().read(); } + template uint8_t getByte(T offset) { return BUS().read(offset); } - void setByte(uint8_t value) { m_memory.write(value); } - template void setByte(T offset, uint8_t value) { m_memory.write(offset, value); } + void setByte(uint8_t value) { BUS().write(value); } + template void setByte(T offset, uint8_t value) { BUS().write(offset, value); } virtual void push(uint8_t value) = 0; virtual uint8_t pop() = 0; diff --git a/inc/Ram.h b/inc/Ram.h new file mode 100644 index 0000000..0a01af0 --- /dev/null +++ b/inc/Ram.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include "Memory.h" + +namespace EightBit { + class Ram : public Memory { + public: + Ram(size_t size) + : Memory(size) { + } + + uint8_t peek(uint16_t address) const { + return read(address); + } + + void poke(uint16_t address, uint8_t value) { + write(address, value); + } + + uint8_t& reference(uint16_t address) { + return m_bytes[address]; + } + }; +} diff --git a/inc/Register.h b/inc/Register.h new file mode 100644 index 0000000..81c5056 --- /dev/null +++ b/inc/Register.h @@ -0,0 +1,34 @@ +#pragma once + +#include + +#ifdef __BYTE_ORDER__ +# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define HOST_LITTLE_ENDIAN +# endif +# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define HOST_BIG_ENDIAN +# endif +#else +# if defined(_M_X64) || defined(_M_IX86) +# define HOST_LITTLE_ENDIAN +# else +# define HOST_BIG_ENDIAN +# endif +#endif + +namespace EightBit { + typedef union { + struct { +#ifdef HOST_LITTLE_ENDIAN + uint8_t low; + uint8_t high; +#endif +#ifdef HOST_BIG_ENDIAN + uint8_t high; + uint8_t low; +#endif + }; + uint16_t word; + } register16_t; +} \ No newline at end of file diff --git a/inc/Rom.h b/inc/Rom.h new file mode 100644 index 0000000..e6235f9 --- /dev/null +++ b/inc/Rom.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include "Memory.h" + +namespace EightBit { + class Rom : public Memory { + public: + Rom(size_t size) + : Memory(size) { + } + + uint8_t peek(uint16_t address) const { + return read(address); + } + + uint8_t& reference(uint16_t address) { + return m_bytes[address]; + } + }; +} \ No newline at end of file diff --git a/src/EightBit.vcxproj b/src/EightBit.vcxproj index 5c212fd..d1e4274 100644 --- a/src/EightBit.vcxproj +++ b/src/EightBit.vcxproj @@ -139,12 +139,16 @@ + + + + diff --git a/src/EightBit.vcxproj.filters b/src/EightBit.vcxproj.filters index f123331..609f9b4 100644 --- a/src/EightBit.vcxproj.filters +++ b/src/EightBit.vcxproj.filters @@ -41,6 +41,18 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + diff --git a/src/IntelProcessor.cpp b/src/IntelProcessor.cpp index 005a81a..dbc7767 100644 --- a/src/IntelProcessor.cpp +++ b/src/IntelProcessor.cpp @@ -1,8 +1,8 @@ #include "stdafx.h" #include "IntelProcessor.h" -EightBit::IntelProcessor::IntelProcessor(Memory& memory) -: Processor(memory) { +EightBit::IntelProcessor::IntelProcessor(Bus& bus) +: Processor(bus) { SP().word = Mask16; } diff --git a/src/Memory.cpp b/src/Memory.cpp index 4ec6eeb..3542922 100644 --- a/src/Memory.cpp +++ b/src/Memory.cpp @@ -1,55 +1,8 @@ #include "stdafx.h" #include "Memory.h" -#include "Processor.h" #include #include -#include - -EightBit::Memory::Memory(uint16_t addressMask) -: m_addressMask(addressMask), - m_temporary(0), - m_data(nullptr) { - clear(); - m_address.word = 0; - m_bus.resize(0x10000); - m_locked.resize(0x10000); -} - -uint8_t EightBit::Memory::peek(uint16_t address) { - bool rom; - return reference(address, rom); -} - -void EightBit::Memory::poke(uint16_t address, uint8_t value) { - bool rom; - reference(address, rom) = value; -} - -uint16_t EightBit::Memory::peekWord(uint16_t address) { - register16_t returned; - returned.low = peek(address); - returned.high = peek(address + 1); - return returned.word; -} - -void EightBit::Memory::clear() { - std::fill(m_bus.begin(), m_bus.end(), 0); - std::fill(m_locked.begin(), m_locked.end(), false); -} - -void EightBit::Memory::loadRom(const std::string& path, uint16_t offset) { - auto size = loadMemory(path, offset); - lock(offset, size); -} - -void EightBit::Memory::loadRam(const std::string& path, uint16_t offset) { - loadMemory(path, offset); -} - -int EightBit::Memory::loadMemory(const std::string& path, uint16_t offset) { - return loadBinary(path, m_bus, offset, 0x10000 - offset); -} int EightBit::Memory::loadBinary(const std::string& path, std::vector& output, int offset, int maximumSize) { std::ifstream file; diff --git a/src/Processor.cpp b/src/Processor.cpp index 23b2a18..b9ffdbb 100644 --- a/src/Processor.cpp +++ b/src/Processor.cpp @@ -1,8 +1,8 @@ #include "stdafx.h" #include "Processor.h" -EightBit::Processor::Processor(Memory& memory) -: m_memory(memory), +EightBit::Processor::Processor(Bus& bus) +: m_bus(bus), cycles(0), m_halted(false), m_power(false) {