From 7b79c35f639b6d29fca114e29d13bbeac7d3c33b Mon Sep 17 00:00:00 2001 From: zanostro Date: Mon, 17 Nov 2025 15:21:25 +0100 Subject: [PATCH] added loading --- simulator_SIC_XE/CMakeLists.txt | 12 +++++++++ simulator_SIC_XE/Makefile | 2 +- simulator_SIC_XE/gui/qt/mainwindow.cpp | 10 ++++++- simulator_SIC_XE/include/constants.h | 9 +++++++ simulator_SIC_XE/include/loader.h | 4 +++ simulator_SIC_XE/src/loader.cpp | 37 +++++++++++++++++--------- simulator_SIC_XE/src/main.cpp | 17 ++++++++++++ test.asm | 7 +++++ 8 files changed, 84 insertions(+), 14 deletions(-) create mode 100644 test.asm diff --git a/simulator_SIC_XE/CMakeLists.txt b/simulator_SIC_XE/CMakeLists.txt index fe0a86a..c6c37e1 100644 --- a/simulator_SIC_XE/CMakeLists.txt +++ b/simulator_SIC_XE/CMakeLists.txt @@ -46,3 +46,15 @@ message(STATUS "Output directory: ${OUTPUT_DIR}") if(EXISTS "${CMAKE_SOURCE_DIR}/gui/qt/CMakeLists.txt") add_subdirectory(gui/qt) endif() + +# Copy resources directory (if present) to target/res so build output includes them +if(EXISTS "${CMAKE_SOURCE_DIR}/res") + add_custom_target(copy_resources + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_SOURCE_DIR}/target/res + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/res ${CMAKE_SOURCE_DIR}/target/res + COMMENT "Copying resources from res/ to target/res/" + ) + if(TARGET simulator_exec) + add_dependencies(simulator_exec copy_resources) + endif() +endif() diff --git a/simulator_SIC_XE/Makefile b/simulator_SIC_XE/Makefile index 6d5d9ea..92ab3cc 100644 --- a/simulator_SIC_XE/Makefile +++ b/simulator_SIC_XE/Makefile @@ -26,7 +26,7 @@ build: configure run: build @echo "Running primary target..." - # Prefer GUI if available, otherwise fall back to console executable + # Prefer GUI if avail able, otherwise fall back to console executable @if [ -x "$(GUI_TARGET)" ]; then \ echo "Launching GUI: $(GUI_TARGET)"; \ sh -c 'nohup env QT_QPA_PLATFORM=xcb ./$(GUI_TARGET) >/dev/null 2>&1 & echo $! > "$(BUILD_DIR)/simulator_qt.pid"'; \ diff --git a/simulator_SIC_XE/gui/qt/mainwindow.cpp b/simulator_SIC_XE/gui/qt/mainwindow.cpp index aba288f..afc464c 100644 --- a/simulator_SIC_XE/gui/qt/mainwindow.cpp +++ b/simulator_SIC_XE/gui/qt/mainwindow.cpp @@ -4,6 +4,8 @@ #include "../../include/machine.h" #include "../../include/instructions.h" #include "../../include/opcode.h" +#include "../../include/constants.h" +#include "../../../include/loader.h" #include #include @@ -16,6 +18,10 @@ #include #include +class Loader; + +std::shared_ptr g_loader; + MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), @@ -93,7 +99,9 @@ MainWindow::MainWindow(QWidget *parent) : setupMemoryDisplay(); setupDisassemblyDisplay(); - loadDemoProgram(); + //loadDemoProgram(); + g_loader = std::make_shared(machine(), std::string(PATH_RESOURCES) + "demo_program.obj"); + g_loader->load(); updateRegisterDisplays(); updateMemoryDisplay(); diff --git a/simulator_SIC_XE/include/constants.h b/simulator_SIC_XE/include/constants.h index 3698665..6f2195a 100644 --- a/simulator_SIC_XE/include/constants.h +++ b/simulator_SIC_XE/include/constants.h @@ -1,6 +1,7 @@ #ifndef CONSTANTS_H #define CONSTANTS_H +#include // ============================== // SIC/XE Architecture Constants // ============================== @@ -39,5 +40,13 @@ constexpr int BIT_E_MASK = 0x10; // mask for e bit in F4 and F3 instructions constexpr bool USE_EXTENDED_MODE = true; constexpr int VECTOR_REG_SIZE = 4; +/* if structure is +/target/ + |-> bin/simulator_exec + |-> res/ +*/ +// When running from project root (./target/bin/simulator_exec), resources are in ./target/res/ +constexpr char PATH_RESOURCES[] = "./target/res/"; +constexpr bool FILE_CONTAINS_WHITE_SPACES = true; #endif // CONSTANTS_H \ No newline at end of file diff --git a/simulator_SIC_XE/include/loader.h b/simulator_SIC_XE/include/loader.h index 16ffa45..41899c2 100644 --- a/simulator_SIC_XE/include/loader.h +++ b/simulator_SIC_XE/include/loader.h @@ -5,6 +5,7 @@ #include #include #include "file_reader.h" +#include class Machine; @@ -16,6 +17,9 @@ class Loader { public: Loader( shared_ptr machine, string filename) : _machine(machine), _filename(filename) { _file_reader = std::make_shared(filename, std::ios::in); + if (!_file_reader->good()) { + throw std::runtime_error("Loader: failed to open file: " + filename); + } } ~Loader(); diff --git a/simulator_SIC_XE/src/loader.cpp b/simulator_SIC_XE/src/loader.cpp index df459fa..9b3d293 100644 --- a/simulator_SIC_XE/src/loader.cpp +++ b/simulator_SIC_XE/src/loader.cpp @@ -2,6 +2,7 @@ #include "file_reader.h" #include "machine.h" #include "constants.h" +#include Loader::~Loader() { @@ -49,15 +50,22 @@ Loader::RecordType Loader::parseRecordType(char c) 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 @@ -67,35 +75,40 @@ Loader::HeaderMetadata Loader::readHeader() 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(); - // Read data bytes record.data.resize(length); - - for(int i = 0; i < length; ++i) { - unsigned char buffer[2]; - _file_reader->readBytes(buffer, 2); - record.data[i] = static_cast(std::stoi(std::string(reinterpret_cast(buffer), 2), nullptr, 16)); + 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)); } - // consume newline - _file_reader->readLine(); - + 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; // default start address + record.execution_start_address = 0; } // consume newline _file_reader->readLine(); @@ -106,8 +119,8 @@ bool Loader::load_into_memory(int start_address, const std::vector &dat { for(size_t i = 0; i < data.size(); ++i) { int addr = start_address + static_cast(i); - if (addr < 0 || addr >= MEMORY_SIZE) { // 24-bit address space - return false; // Address out of bounds + if (addr < 0 || addr >= MEMORY_SIZE) { + return false; } _machine->setByte(addr, data[i]); } diff --git a/simulator_SIC_XE/src/main.cpp b/simulator_SIC_XE/src/main.cpp index 2d9662a..bd7a9e7 100644 --- a/simulator_SIC_XE/src/main.cpp +++ b/simulator_SIC_XE/src/main.cpp @@ -5,6 +5,8 @@ #include "file_device.h" #include "opcode.h" #include "instructions.h" +#include "constants.h" +#include "loader.h" using std::cout; using std::endl; @@ -17,6 +19,7 @@ struct VectorAddProgram { int main() { + /* loadInstructionSet(); Machine machine; cout << "SIC/XE Program: Accumulator Loop" << endl; @@ -88,6 +91,20 @@ int main() int val = machine.getWord(VR_ADDR + i * 3); cout << val << (i + 1 < VECTOR_REG_SIZE ? ", " : "\n"); } + */ + + loadInstructionSet(); + std::shared_ptr machine = std::make_shared(); + Loader loader(machine, std::string(PATH_RESOURCES) + "test.obj"); + loader.load(); + machine->execute(); + machine->execute(); + machine->execute(); + machine->execute(); + machine->execute(); + machine->execute(); + cout << "Register A after execution: " << machine->getA() << endl; + return 0; } \ No newline at end of file diff --git a/test.asm b/test.asm new file mode 100644 index 0000000..e25da30 --- /dev/null +++ b/test.asm @@ -0,0 +1,7 @@ +test START 0 + LDA #1 + LDB #2 + ADDR B, A + +halt J halt + END test \ No newline at end of file