#include "stdafx.h" #include "Bus.h" #include "Ram.h" #include "EightBitCompilerDefinitions.h" #include #include #include #include uint8_t EightBit::Bus::read() { ReadingByte.fire(EventArgs::empty()); const auto returned = DATA() = reference(); ReadByte.fire(EventArgs::empty()); return returned; } void EightBit::Bus::write() { WritingByte.fire(EventArgs::empty()); reference() = DATA(); WrittenByte.fire(EventArgs::empty()); } void EightBit::Bus::write(const uint8_t value) { DATA() = value; write(); } void EightBit::Bus::loadHexFile(const std::string path) { const auto chunks = parseHexFile(path); for (const auto& chunk : chunks) { const auto address = chunk.first; const auto content = chunk.second; const auto mapped = mapping(address); const uint16_t offset = address - mapped.begin; mapped.memory.load(content, offset); } } std::map> EightBit::Bus::parseHexFile(const std::string path) { std::ifstream file; file.open(path); std::map> returned; bool eof = false; while (!file.eof() && !eof) { std::string line; std::getline(file, line); const auto colon = line.substr(0, 1); if (colon != ":") throw std::out_of_range("Invalid hex file: line does not begin with a colon"); const auto countString = line.substr(1, 2); const auto count = (uint8_t)strtoul(countString.c_str(), nullptr, 16); const auto addressString = line.substr(3, 4); const auto address = (uint16_t)strtoul(addressString.c_str(), nullptr, 16); const auto recordTypeString = line.substr(7, 2); const auto recordType = strtoul(recordTypeString.c_str(), nullptr, 16); switch (recordType) { case 0x00: { std::vector data(count); const auto requiredLength = 9 + 2 + (count * 2); if (line.length() != requiredLength) throw std::out_of_range("Invalid hex file: line is not the required length"); for (int i = 0; i < count; ++i) { const auto position = 9 + i * 2; const auto datumString = line.substr(position, 2); const auto datum = (uint8_t)strtoul(datumString.c_str(), nullptr, 16); data[i] = datum; } returned[address] = data; } break; case 0x01: eof = true; break; default: throw std::out_of_range("Unhandled hex file record."); } } return returned; } uint8_t& EightBit::Bus::reference(const uint16_t address) { const auto mapped = mapping(address); const uint16_t offset = address - mapped.begin; if (mapped.access == MemoryMapping::ReadOnly) return DATA() = mapped.memory.peek(offset); Ram& ram = (Ram&)(mapped.memory); return ram.reference(offset); }