#include "loader.h" #include "file_reader.h" #include "machine.h" #include "constants.h" #include Loader::~Loader() { _machine.reset(); } void Loader::load() { HeaderMetadata header = readHeader(); while(true) { RecordType type = parseRecordType(static_cast(_file_reader->readByte())); switch (type) { case RecordType::TEXT: { TextRecord textRecord = readTextRecord(); if (!load_into_memory(textRecord.start_address, textRecord.data)) { throw std::runtime_error("Failed to load text record into memory"); } break; } case RecordType::END: { EndRecord endRecord = readEndRecord(); _machine->setPC(endRecord.execution_start_address); return; // Loading complete } case RecordType::UNKNOWN: default: throw std::runtime_error("Unknown record type encountered"); } } } Loader::RecordType Loader::parseRecordType(char c) { switch (c) { case 'H': return RecordType::HEADER; case 'T': return RecordType::TEXT; case 'E': return RecordType::END; default: return RecordType::UNKNOWN; // fallback; adjust as needed } } Loader::HeaderMetadata Loader::readHeader() { RecordType type = parseRecordType(static_cast(_file_reader->readByte())); if (type != RecordType::HEADER) { throw std::runtime_error("Expected HEADER record"); } if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte(); HeaderMetadata header; // Read program name (6 bytes) header.program_name = _file_reader->readString(6); if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte(); // Read start address (6 hex digits) header.start_address = std::stoi(_file_reader->readString(6), nullptr, 16); if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte(); // Read length (6 hex digits) header.length = std::stoi(_file_reader->readString(6), nullptr, 16); // consume newline _file_reader->readLine(); return header; } Loader::TextRecord Loader::readTextRecord() { if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte(); TextRecord record; // Assume 'T' has already been read record.start_address = std::stoi(_file_reader->readString(6), nullptr, 16); if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte(); // Read length (1 byte, 2 hex digits) int length = std::stoi(_file_reader->readString(2), nullptr, 16); if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte(); record.data.resize(length); int index = 0; string byteStr = _file_reader->readLine(); // Remove spaces, newlines, and other whitespace characters byteStr.erase(std::remove_if(byteStr.begin(), byteStr.end(), ::isspace), byteStr.end()); for (int i = 0; i < length; ++i) { std::string byteHex = byteStr.substr(i * 2, 2); record.data[i] = static_cast(std::stoi(byteHex, nullptr, 16)); } return record; } Loader::EndRecord Loader::readEndRecord() { EndRecord record; if(FILE_CONTAINS_WHITE_SPACES) _file_reader->readByte(); // Assume 'E' has already been read std::string addrStr = _file_reader->readString(6); if (!addrStr.empty()) { record.execution_start_address = std::stoi(addrStr, nullptr, 16); } else { record.execution_start_address = 0; } // consume newline _file_reader->readLine(); return record; } bool Loader::load_into_memory(int start_address, const std::vector &data) { for(size_t i = 0; i < data.size(); ++i) { int addr = start_address + static_cast(i); if (addr < 0 || addr >= MEMORY_SIZE) { return false; } _machine->setByte(addr, data[i]); } return true; }