EightBit/inc/Bus.h
Adrian.Conlon b445457b37 Fire pre/post memory read/write events
Signed-off-by: Adrian.Conlon <adrian.conlon@gmail.com>
2017-09-14 15:00:57 +01:00

100 lines
1.9 KiB
C++

#pragma once
#include <cstdint>
#include "Signal.h"
#include "Register.h"
namespace EightBit {
class Bus {
public:
Bus()
: m_temporary(0xff), m_data(nullptr) {
m_address.word = 0xffff;
}
Signal<uint16_t> WritingByte;
Signal<uint16_t> WrittenByte;
Signal<uint16_t> ReadingByte;
Signal<uint16_t> 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() {
ReadingByte.fire(ADDRESS().word);
auto content = reference();
ReadByte.fire(ADDRESS().word);
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) {
WritingByte.fire(ADDRESS().word);
reference() = value;
WrittenByte.fire(ADDRESS().word);
}
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:
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;
};
}