Modifying the manner in which memory is mapped, allows a fairly clean mechanism for loading Intel "hex" files.

Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
Adrian Conlon
2018-09-15 14:35:59 +01:00
parent a9adde6ea5
commit 7d840f1a42
17 changed files with 170 additions and 71 deletions
+79
View File
@@ -1,5 +1,12 @@
#include "stdafx.h"
#include "Bus.h"
#include "Ram.h"
#include "EightBitCompilerDefinitions.h"
#include <fstream>
#include <cstdlib>
#include <stdexcept>
#include <cassert>
uint8_t EightBit::Bus::read() {
ReadingByte.fire(EventArgs::empty());
@@ -18,3 +25,75 @@ 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;
for (size_t i = 0; i != content.size(); ++i)
write(address + i, content[i]);
const auto mapped = mapping(address);
mapped.memory.load(content, address - mapped.begin);
}
}
std::map<uint16_t, std::vector<uint8_t>> EightBit::Bus::parseHexFile(const std::string path) {
std::ifstream file;
file.open(path);
std::map<uint16_t, std::vector<uint8_t>> 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<uint8_t> 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(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);
}
+1
View File
@@ -144,6 +144,7 @@
<ClInclude Include="..\inc\IntelProcessor.h" />
<ClInclude Include="..\inc\LittleEndianProcessor.h" />
<ClInclude Include="..\inc\Memory.h" />
<ClInclude Include="..\inc\MemoryMapping.h" />
<ClInclude Include="..\inc\Processor.h" />
<ClInclude Include="..\inc\Ram.h" />
<ClInclude Include="..\inc\Register.h" />
+3
View File
@@ -53,6 +53,9 @@
<ClInclude Include="..\inc\BigEndianProcessor.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\MemoryMapping.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">