From c81d2dcfeabeff4c897d1b2b7a90afa52b58bb4d Mon Sep 17 00:00:00 2001 From: OmniaX-Dev Date: Mon, 8 Jun 2026 06:26:14 +0200 Subject: [PATCH] Restored legacy ostd SerialIO class --- CMakeLists.txt | 4 + extra/dragon/disk1.dr | Bin 4194304 -> 4194304 bytes extra/dss/sdk/bios_api.dss | 2 +- other/build.nr | 2 +- src/assembler/Assembler.cpp | 96 +++--- src/debugger/DisassemblyLoader.cpp | 2 +- src/hardware/BUS.cpp | 143 --------- src/hardware/BUS.hpp | 142 --------- src/hardware/MemoryMapper.cpp | 1 - src/hardware/RAM.cpp | 172 ----------- src/hardware/RAM.hpp | 51 ---- src/hardware/VirtualIODevices.hpp | 2 +- src/hardware/VirtualMMU.hpp | 2 +- src/hardware/VirtualRAM.hpp | 2 +- src/tools/GlobalData.hpp | 57 ---- src/tools/LegacyOstdSerial.cpp | 457 +++++++++++++++++++++++++++++ src/tools/LegacyOstdSerial.hpp | 92 ++++++ src/tools/Tools.cpp | 2 +- src/tools/Utils.cpp | 1 - 19 files changed, 608 insertions(+), 622 deletions(-) delete mode 100644 src/hardware/BUS.cpp delete mode 100644 src/hardware/BUS.hpp delete mode 100644 src/hardware/RAM.cpp delete mode 100644 src/hardware/RAM.hpp create mode 100644 src/tools/LegacyOstdSerial.cpp create mode 100644 src/tools/LegacyOstdSerial.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0eec9cd..63482ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,6 +44,7 @@ list(APPEND RUNTIME_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/src/tools/Utils.cpp ${CMAKE_CURRENT_LIST_DIR}/src/tools/GlobalData.cpp + ${CMAKE_CURRENT_LIST_DIR}/src/tools/LegacyOstdSerial.cpp ) list(APPEND DEBUGGER_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/src/debugger/debugger_main.cpp @@ -69,6 +70,7 @@ list(APPEND DEBUGGER_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/src/tools/Utils.cpp ${CMAKE_CURRENT_LIST_DIR}/src/tools/GlobalData.cpp + ${CMAKE_CURRENT_LIST_DIR}/src/tools/LegacyOstdSerial.cpp ) list(APPEND ASSEMBLER_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/src/assembler/assembler_main.cpp @@ -79,11 +81,13 @@ list(APPEND ASSEMBLER_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualHardDrive.cpp ${CMAKE_CURRENT_LIST_DIR}/src/tools/Utils.cpp + ${CMAKE_CURRENT_LIST_DIR}/src/tools/LegacyOstdSerial.cpp ) list(APPEND TOOLS_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/src/tools/tools_main.cpp ${CMAKE_CURRENT_LIST_DIR}/src/tools/Utils.cpp ${CMAKE_CURRENT_LIST_DIR}/src/tools/Tools.cpp + ${CMAKE_CURRENT_LIST_DIR}/src/tools/LegacyOstdSerial.cpp ${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualHardDrive.cpp diff --git a/extra/dragon/disk1.dr b/extra/dragon/disk1.dr index 3bbe04af26d7345a849fcc8b969a969494fa7552..08a43553ae09f020453b3162bfa2908ba09a8619 100644 GIT binary patch delta 404 zcmW;ESx$p+6vg37sc69}g*xIu)jIxBoM-A1AOzipi7^^&A~8)|i7U`VH{d?pgAc|R z^#>2%J-O%MN^%KRqtK(_2-(-qisn2DhSQQEc&3+ zF!akH5-l-ZOL>V!8;c%GHC4A~mZLnY8${)-?MnMM7cL9OqrAzC$5fYS>j@f6}wv7snFGdtI@w z?dYJJDJ$O5!CSc}bA@2McRW%2Ep>HpbL;Z$Kk9bWPY=31==9`!?A7l}L>|q}Y8V5K; d31w7JMGZ$d#tBYwhC0r1flFKs{C;Ef{13hYa25an diff --git a/extra/dss/sdk/bios_api.dss b/extra/dss/sdk/bios_api.dss index 6847cdf..a780608 100644 --- a/extra/dss/sdk/bios_api.dss +++ b/extra/dss/sdk/bios_api.dss @@ -1,5 +1,5 @@ ## -- -## -- This file is automatically generated by the DragonAssembler (version 0.4.1646) +## -- This file is automatically generated by the DragonAssembler (version 0.4.1649) ## -- Please do not modify this file in any way. ## -- diff --git a/other/build.nr b/other/build.nr index 8f8453a..712cd79 100644 --- a/other/build.nr +++ b/other/build.nr @@ -1 +1 @@ -1648 +1650 diff --git a/src/assembler/Assembler.cpp b/src/assembler/Assembler.cpp index 3372386..bfa70ef 100644 --- a/src/assembler/Assembler.cpp +++ b/src/assembler/Assembler.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include "../tools/LegacyOstdSerial.hpp" #include #include #include @@ -36,7 +36,7 @@ namespace dragon if (m_lines.size() == 0) return { }; //TODO: Error // for (auto& line : m_lines) - // std::cout << line << "\n"; + // std::cout << line << "\n"; removeComments(); parseExportSpecifications(); createExports(); @@ -70,7 +70,7 @@ namespace dragon { assembleFromFile(sourceFileName); if (m_code.size() == 0) return { }; - ostd::Memory::saveByteStreamToFile(m_code, binaryFileName); + ostd::Memory::saveByteStreamToFile(m_code, binaryFileName); return m_code; } @@ -223,7 +223,7 @@ namespace dragon return false; }; // auto exportExists = [](const std::unordered_map& exports, const ostd::String& name) -> bool { - // return exports.count(name) > 0; + // return exports.count(name) > 0; // }; std::vector defines; std::vector newLines; @@ -237,27 +237,27 @@ namespace dragon // ostd::String export_name = ""; // if (tmpLineEdit.toLower().startsWith("@export_comment ")) // { - // lineEdit.substr(16).trim(); - // if (!lineEdit.startsWith("/") || !lineEdit.contains(" ")) - // { - // std::cout << "Invalid @export_comment directive: export specification not found: " << line << "\n"; - // return; - // } - // export_name = lineEdit.new_substr(1, lineEdit.indexOf(" ")).trim(); - // lineEdit.substr(lineEdit.indexOf(" ") + 1).trim(); - // if (!lineEdit.startsWith("\"") || !lineEdit.endsWith("\"")) - // { - // std::cout << "Invalid @export_comment directive: comment not found: " << line << "\n"; - // return; - // } - // lineEdit.substr(1, lineEdit.len() - 1); - // if (!exportExists(m_exportSpecifications, export_name)) - // { - // std::cout << "Invalid export specification: " << line << "\n"; - // return; - // } - // m_exportSpecifications[export_name].content.push_back({ "## -- ", lineEdit }); - // continue; + // lineEdit.substr(16).trim(); + // if (!lineEdit.startsWith("/") || !lineEdit.contains(" ")) + // { + // std::cout << "Invalid @export_comment directive: export specification not found: " << line << "\n"; + // return; + // } + // export_name = lineEdit.new_substr(1, lineEdit.indexOf(" ")).trim(); + // lineEdit.substr(lineEdit.indexOf(" ") + 1).trim(); + // if (!lineEdit.startsWith("\"") || !lineEdit.endsWith("\"")) + // { + // std::cout << "Invalid @export_comment directive: comment not found: " << line << "\n"; + // return; + // } + // lineEdit.substr(1, lineEdit.len() - 1); + // if (!exportExists(m_exportSpecifications, export_name)) + // { + // std::cout << "Invalid export specification: " << line << "\n"; + // return; + // } + // m_exportSpecifications[export_name].content.push_back({ "## -- ", lineEdit }); + // continue; // } else if (tmpLineEdit.toLower().startsWith("@define ")) { @@ -287,12 +287,12 @@ namespace dragon defines.push_back({ define_name, define_value }); // if (export_name != "") // { - // if (!exportExists(m_exportSpecifications, export_name)) - // { - // std::cout << "Invalid export specification: " << line << "\n"; - // return; - // } - // m_exportSpecifications[export_name].content.push_back({ define_name, define_value }); + // if (!exportExists(m_exportSpecifications, export_name)) + // { + // std::cout << "Invalid export specification: " << line << "\n"; + // return; + // } + // m_exportSpecifications[export_name].content.push_back({ define_name, define_value }); // } continue; } @@ -307,11 +307,11 @@ namespace dragon } // for (auto& exp : m_exportSpecifications) // { - // for (auto& def : exp.second.content) - // { - // for (int32_t i = defines.size() - 1; i >= 0; i--) - // def.value.replaceAll(defines[i].name, defines[i].value.new_trim()); - // } + // for (auto& def : exp.second.content) + // { + // for (int32_t i = defines.size() - 1; i >= 0; i--) + // def.value.replaceAll(defines[i].name, defines[i].value.new_trim()); + // } // } m_lines.clear(); m_lines = newLines; @@ -525,14 +525,14 @@ namespace dragon // for (auto& str : m_structDefs) // { - // std::cout << str.name << "\n"; - // for(auto& d : str.memberData) - // { - // std::cout << " " << d.first << " "; - // for (auto& b : d.second) - // std::cout << ostd::String::getHexStr(b) << " "; - // } - // std::cout << "\n"; + // std::cout << str.name << "\n"; + // for(auto& d : str.memberData) + // { + // std::cout << " " << d.first << " "; + // for (auto& b : d.second) + // std::cout << ostd::String::getHexStr(b) << " "; + // } + // std::cout << "\n"; // } // std::cin.get(); } @@ -901,7 +901,7 @@ namespace dragon void Assembler::parseDataSection(void) { // for (auto& line : m_rawDataSection) - // std::cout << line << "\n"; + // std::cout << line << "\n"; for (auto& line : m_rawDataSection) { ostd::String lineEdit(line); @@ -970,8 +970,8 @@ namespace dragon if (lineEdit.isNumeric()) { // union valueSplit { - // uint16_t value; - // uint8_t bytes[2]; + // uint16_t value; + // uint8_t bytes[2]; // } split; // split.value = lineEdit.toInt(); // symbol.bytes.push_back(split.bytes[0]); @@ -1302,7 +1302,7 @@ namespace dragon if (opType == eOperandType::Immediate || opType == eOperandType::Label) { // if (opType == eOperandType::Label) - // std::cout << ostd::String::getHexStr(word, true, 2) << "\n"; + // std::cout << ostd::String::getHexStr(word, true, 2) << "\n"; m_code[m_code.size() - 1] = data::OpCodes::PushImm; // m_code.push_back(data::OpCodes::PushImm); m_code.push_back((uint8_t)((word & 0xFF00) >> 8)); diff --git a/src/debugger/DisassemblyLoader.cpp b/src/debugger/DisassemblyLoader.cpp index f464413..853704f 100644 --- a/src/debugger/DisassemblyLoader.cpp +++ b/src/debugger/DisassemblyLoader.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include "../tools/LegacyOstdSerial.hpp" #include #include diff --git a/src/hardware/BUS.cpp b/src/hardware/BUS.cpp deleted file mode 100644 index 6b3eb40..0000000 --- a/src/hardware/BUS.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - DragonV2 - A collection of useful functionality - Copyright (C) 2026 OmniaX-Dev - - This file is part of DragonV2. - - DragonV2 is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - DragonV2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with DragonV2. If not, see . -*/ - -#include "BUS.hpp" - -namespace dragon -{ - AtomicStorageMemoryDevice::AtomicStorageMemoryDevice(u64 size) - { - if (size == 0) // Special case, for classes like BUS, that are MemoryDevices but don't own any data - { - m_wordCount = 0; - m_size = 0; - m_words = nullptr; - return; - } - m_wordCount = (size + 7) / 8; // Round up to multiple of 8 bytes for the word-granular backing - m_size = size; - m_words = new std::atomic[m_wordCount]; - for (u64 i = 0; i < m_wordCount; ++i) - m_words[i].store(0, std::memory_order_relaxed); - } - - AtomicStorageMemoryDevice::~AtomicStorageMemoryDevice(void) - { - delete[] m_words; - } - - bool MemoryDevice::guest_cas_u32(AddressType addr, u32 expected, u32& actual, u32 desired) - { - data::ErrorHandler::pushError(data::ErrorCodes::MM_AtomicNotSupported, "MemoryDevice::guest_cas_u32: atomic not supported: "); - fault(addr, data::ExceptionCause::AtomicNotSupported, "MemoryDevice::guest_cas_u32"); - return false; - } - - - - - - namespace hw - { - bool BUS::guest_cas_u32(AddressType addr, u32 expected, u32& actual, u32 desired) - { - auto region = findRegion(addr); - if (!region) { /* fault */ return false; } - AddressType finalAddr = (region->remap ? addr - region->startAddress : addr); - return region->device->guest_cas_u32(finalAddr, expected, actual, desired); - } - - u8 BUS::load_u8(AddressType addr) const - { - auto region = findRegion(addr); - if (region == nullptr) return 0x00; //TODO: Error - AddressType finalAddr = (region->remap ? addr - region->startAddress : addr); - return region->device->load_u8(finalAddr); - } - - u16 BUS::load_u16(AddressType addr) const - { - auto region = findRegion(addr); - if (region == nullptr) return 0x0000; //TODO: Error - AddressType finalAddr = (region->remap ? addr - region->startAddress : addr); - return region->device->load_u16(finalAddr); - } - - u32 BUS::load_u32(AddressType addr) const - { - auto region = findRegion(addr); - if (region == nullptr) return 0x0000'0000; //TODO: Error - AddressType finalAddr = (region->remap ? addr - region->startAddress : addr); - return region->device->load_u32(finalAddr); - } - - u64 BUS::load_u64(AddressType addr) const - { - auto region = findRegion(addr); - if (region == nullptr) return 0x0000'0000'0000'0000; //TODO: Error - AddressType finalAddr = (region->remap ? addr - region->startAddress : addr); - return region->device->load_u64(finalAddr); - } - - bool BUS::store_u8(AddressType addr, u8 value) - { - auto region = findRegion(addr); - if (region == nullptr) return false; - AddressType finalAddr = (region->remap ? addr - region->startAddress : addr); - return region->device->store_u8(finalAddr, value); - } - - bool BUS::store_u16(AddressType addr, u16 value) - { - auto region = findRegion(addr); - if (region == nullptr) return false; - AddressType finalAddr = (region->remap ? addr - region->startAddress : addr); - return region->device->store_u16(finalAddr, value); - } - - bool BUS::store_u32(AddressType addr, u32 value) - { - auto region = findRegion(addr); - if (region == nullptr) return false; - AddressType finalAddr = (region->remap ? addr - region->startAddress : addr); - return region->device->store_u32(finalAddr, value); - } - - bool BUS::store_u64(AddressType addr, u64 value) - { - auto region = findRegion(addr); - if (region == nullptr) return false; - AddressType finalAddr = (region->remap ? addr - region->startAddress : addr); - return region->device->store_u64(finalAddr, value); - } - - void BUS::mapDevice(MemoryDevice& device, AddressType startAddr, AddressType endAddr, bool remap, ostd::String name) - { - m_regions.push_back({ &device, startAddr, endAddr, remap, name }); - } - - ostd::String BUS::getMemoryRegionName(AddressType address) - { - tMemoryRegion* region = findRegion(address); - if (region == nullptr) return "Invalid"; - return region->name; - } - } -} diff --git a/src/hardware/BUS.hpp b/src/hardware/BUS.hpp deleted file mode 100644 index b28b4f2..0000000 --- a/src/hardware/BUS.hpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - DragonV2 - A collection of useful functionality - Copyright (C) 2026 OmniaX-Dev - - This file is part of DragonV2. - - DragonV2 is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - DragonV2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with DragonV2. If not, see . -*/ - -#include -#include -#include -#include "../tools/GlobalData.hpp" - -#pragma once - -namespace dragon -{ - class MemoryDevice : public ostd::BaseObject - { - public: - MemoryDevice(void) = default; - MemoryDevice(const MemoryDevice&) = delete; - MemoryDevice& operator=(const MemoryDevice&) = delete; - MemoryDevice(MemoryDevice&&) = delete; - MemoryDevice& operator=(MemoryDevice&&) = delete; - virtual ~MemoryDevice() = default; - - virtual bool guest_cas_u32(AddressType addr, u32 expected, u32& actual, u32 desired); - - // ---- Aligned loads ---- - virtual u64 load_u64(AddressType addr) const = 0; - virtual u32 load_u32(AddressType addr) const = 0; - virtual u16 load_u16(AddressType addr) const = 0; - virtual u8 load_u8 (AddressType addr) const = 0; - - inline i64 load_i64(AddressType addr) const { return cast(load_u64(addr)); } - inline i32 load_i32(AddressType addr) const { return cast(load_u32(addr)); } - inline i16 load_i16(AddressType addr) const { return cast(load_u16(addr)); } - inline i8 load_i8 (AddressType addr) const { return cast(load_u8 (addr)); } - - // ---- Aligned stores ---- - virtual bool store_u64(AddressType addr, u64 value) = 0; - virtual bool store_u32(AddressType addr, u32 value) = 0; - virtual bool store_u16(AddressType addr, u16 value) = 0; - virtual bool store_u8 (AddressType addr, u8 value) = 0; - - inline bool store_i64(AddressType addr, u64 value) { return store_u64(addr, cast(value)); } - inline bool store_i32(AddressType addr, u32 value) { return store_u32(addr, cast(value)); } - inline bool store_i16(AddressType addr, u16 value) { return store_u16(addr, cast(value)); } - inline bool store_i8 (AddressType addr, u8 value) { return store_u8 (addr, cast(value)); } - - [[noreturn]] virtual void fault(AddressType addr, data::ExceptionCause cause, const String& msg = "") const { throw data::GuestException{ cause, addr, msg }; }; // Message can be useful for debugging - }; - - class AtomicStorageMemoryDevice : public MemoryDevice - { - public: - explicit AtomicStorageMemoryDevice(u64 size); - virtual ~AtomicStorageMemoryDevice(void); - AtomicStorageMemoryDevice(const AtomicStorageMemoryDevice&) = delete; - AtomicStorageMemoryDevice& operator=(const AtomicStorageMemoryDevice&) = delete; - AtomicStorageMemoryDevice(AtomicStorageMemoryDevice&&) = delete; - AtomicStorageMemoryDevice& operator=(AtomicStorageMemoryDevice&&) = delete; - - // ---- Helpers ---- - inline u64 getWordCount(void) const { return m_wordCount; } - inline u64 getSize(void) const { return m_size; } - inline virtual std::span> getRawData(void) { return { m_words, m_size }; } - inline virtual std::span> getRawData(void) const { return { m_words, m_size }; } - // Both getRawData() can be overridden to return empty spans for devices where internal memory shouldn't be exposed - - protected: - std::atomic* m_words; - u64 m_wordCount; - u64 m_size; - }; - namespace hw - { - class BUS : public MemoryDevice - { - public: - private: struct tMemoryRegion - { - MemoryDevice* device { nullptr }; - AddressType startAddress { 0x0000'0000 }; - AddressType endAddress { 0x0000'0000 }; - bool remap { false }; - ostd::String name { "" }; - }; - - public: - BUS(void) = default; - - bool guest_cas_u32(AddressType addr, u32 expected, u32& actual, u32 desired) override; - - // ---- Aligned loads ---- - u64 load_u64(AddressType addr) const override; - u32 load_u32(AddressType addr) const override; - u16 load_u16(AddressType addr) const override; - u8 load_u8 (AddressType addr) const override; - - // ---- Aligned stores ---- - bool store_u64(AddressType addr, u64 value) override; - bool store_u32(AddressType addr, u32 value) override; - bool store_u16(AddressType addr, u16 value) override; - bool store_u8 (AddressType addr, u8 value) override; - - void mapDevice(MemoryDevice& device, AddressType startAddr, AddressType endAddr, bool remap = false, ostd::String name = ""); - ostd::String getMemoryRegionName(AddressType address); - - private: - template - auto findRegion(this Self&& self, AddressType address) - { - for (auto& region : self.m_regions) - { // works whether self is const or not - if (address >= region.startAddress && address <= region.endAddress) - return ®ion; - } - data::ErrorHandler::pushError(data::ErrorCodes::MM_RegionNotFound, "Memory device not found"); - return decltype(&self.m_regions[0]){nullptr}; - } - - private: - std::vector m_regions; - - private: - }; - } -} diff --git a/src/hardware/MemoryMapper.cpp b/src/hardware/MemoryMapper.cpp index a5feb9a..7e18e1f 100644 --- a/src/hardware/MemoryMapper.cpp +++ b/src/hardware/MemoryMapper.cpp @@ -1,5 +1,4 @@ #include "MemoryMapper.hpp" -#include #include #include "../tools/GlobalData.hpp" diff --git a/src/hardware/RAM.cpp b/src/hardware/RAM.cpp deleted file mode 100644 index 055acca..0000000 --- a/src/hardware/RAM.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* - DragonV2 - A collection of useful functionality - Copyright (C) 2026 OmniaX-Dev - - This file is part of DragonV2. - - DragonV2 is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - DragonV2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with DragonV2. If not, see . -*/ - -#include "RAM.hpp" -#include - -#define DRAGON_TEST_FOR_MISALIGNED_OR_BOUNDS_FAULT_R(size, msg) \ - if (addr + size > m_size) \ - { \ - fault(addr, data::ExceptionCause::LoadBounds, msg); \ - return 0; \ - } \ - if (addr & (size - 1)) \ - { \ - fault(addr, data::ExceptionCause::MisalignedLoad, msg); \ - return 0; \ - } \ - -#define DRAGON_TEST_FOR_MISALIGNED_OR_BOUNDS_FAULT_W(size, msg) \ - if (addr + size > m_size) \ - { \ - fault(addr, data::ExceptionCause::StoreBounds, msg); \ - return false; \ - } \ - if (addr & (size - 1)) \ - { \ - fault(addr, data::ExceptionCause::MisalignedStore, msg); \ - return false; \ - } \ - -namespace dragon -{ - namespace hw - { - bool RAM::guest_cas_u32(AddressType addr, u32 expected, u32& actual, u32 desired) - { - DRAGON_TEST_FOR_MISALIGNED_OR_BOUNDS_FAULT_R(4, "RAM::guest_cas_u32"); - - u32 shift = (addr & 4) * 8; - u64 mask = u64(0xFFFFFFFFu) << shift; - std::atomic& word = m_words[addr >> 3]; - - u64 word_expected = word.load(std::memory_order_seq_cst); - while (true) - { - u32 current_in_slot = static_cast(word_expected >> shift); - if (current_in_slot != expected) - { - // CAS fails: report what we saw, don't modify - actual = current_in_slot; - return false; - } - // CAS could succeed: try to update - u64 word_desired = (word_expected & ~mask) | (u64(desired) << shift); - if (word.compare_exchange_weak(word_expected, word_desired, std::memory_order_seq_cst, std::memory_order_seq_cst)) - { - actual = expected; // tell caller we succeeded - return true; - } - // CAS spuriously failed or someone else changed the word; word_expected - // is updated. Loop and re-check. - } - } - - u64 RAM::load_u64(AddressType addr) const - { - DRAGON_TEST_FOR_MISALIGNED_OR_BOUNDS_FAULT_R(8, "RAM::load_u64"); - return m_words[addr >> 3].load(std::memory_order_seq_cst); - } - - u32 RAM::load_u32(AddressType addr) const - { - DRAGON_TEST_FOR_MISALIGNED_OR_BOUNDS_FAULT_R(4, "RAM::load_u32"); - u64 word = m_words[addr >> 3].load(std::memory_order_seq_cst); - u32 shift = (addr & 4) * 8; // 0 or 32 - return static_cast(word >> shift); - } - - u16 RAM::load_u16(AddressType addr) const - { - DRAGON_TEST_FOR_MISALIGNED_OR_BOUNDS_FAULT_R(2, "RAM::load_u16"); - u64 word = m_words[addr >> 3].load(std::memory_order_seq_cst); - u32 shift = (addr & 6) * 8; // 0, 16, 32, or 48 - return static_cast(word >> shift); - } - - u8 RAM::load_u8(AddressType addr) const - { - if (addr >= m_size) - { - fault(addr, data::ExceptionCause::LoadBounds, "RAM::load_u8"); - return 0; - } - u64 word = m_words[addr >> 3].load(std::memory_order_seq_cst); - u32 shift = (addr & 7) * 8; - return static_cast(word >> shift); - } - - bool RAM::store_u64(AddressType addr, u64 value) - { - DRAGON_TEST_FOR_MISALIGNED_OR_BOUNDS_FAULT_W(8, "RAM::store_u64"); - m_words[addr >> 3].store(value, std::memory_order_seq_cst); - return true; - } - - bool RAM::store_u32(AddressType addr, u32 value) - { - DRAGON_TEST_FOR_MISALIGNED_OR_BOUNDS_FAULT_W(4, "RAM::store_u32"); - u32 shift = (addr & 4) * 8; - u64 mask = u64(0xFFFFFFFFu) << shift; - std::atomic& word = m_words[addr >> 3]; - u64 expected = word.load(std::memory_order_relaxed); - u64 desired; - do - { - desired = (expected & ~mask) | (u64(value) << shift); - } while (!word.compare_exchange_weak(expected, desired, std::memory_order_seq_cst, std::memory_order_relaxed)); - return true; - } - - bool RAM::store_u16(AddressType addr, u16 value) - { - DRAGON_TEST_FOR_MISALIGNED_OR_BOUNDS_FAULT_W(2, "RAM::store_u16"); - u32 shift = (addr & 6) * 8; - u64 mask = u64(0xFFFFu) << shift; - std::atomic& word = m_words[addr >> 3]; - u64 expected = word.load(std::memory_order_relaxed); - u64 desired; - do - { - desired = (expected & ~mask) | (u64(value) << shift); - } while (!word.compare_exchange_weak(expected, desired, std::memory_order_seq_cst, std::memory_order_relaxed)); - return true; - } - - bool RAM::store_u8(AddressType addr, u8 value) - { - if (addr >= m_size) - { - fault(addr, data::ExceptionCause::StoreBounds, "RAM::store_u8"); - return false; - } - u32 shift = (addr & 7) * 8; - u64 mask = u64(0xFFu) << shift; - std::atomic& word = m_words[addr >> 3]; - u64 expected = word.load(std::memory_order_relaxed); - u64 desired; - do - { - desired = (expected & ~mask) | (u64(value) << shift); - } while (!word.compare_exchange_weak(expected, desired, std::memory_order_seq_cst, std::memory_order_relaxed)); - return true; - } - } -} diff --git a/src/hardware/RAM.hpp b/src/hardware/RAM.hpp deleted file mode 100644 index de4ff22..0000000 --- a/src/hardware/RAM.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - DragonV2 - A collection of useful functionality - Copyright (C) 2026 OmniaX-Dev - - This file is part of DragonV2. - - DragonV2 is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - DragonV2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with DragonV2. If not, see . -*/ - -#pragma once - -#include - -#include "BUS.hpp" - -namespace dragon -{ - namespace hw - { - class RAM : public AtomicStorageMemoryDevice - { - public: - explicit RAM(u64 size) : AtomicStorageMemoryDevice(size) { } - - bool guest_cas_u32(AddressType addr, u32 expected, u32& actual, u32 desired) override; - - // ---- Aligned loads ---- - u64 load_u64(AddressType addr) const override; - u32 load_u32(AddressType addr) const override; - u16 load_u16(AddressType addr) const override; - u8 load_u8 (AddressType addr) const override; - - // ---- Aligned stores ---- - bool store_u64(AddressType addr, u64 value) override; - bool store_u32(AddressType addr, u32 value) override; - bool store_u16(AddressType addr, u16 value) override; - bool store_u8 (AddressType addr, u8 value) override; - }; - } -} diff --git a/src/hardware/VirtualIODevices.hpp b/src/hardware/VirtualIODevices.hpp index a323217..b06162d 100644 --- a/src/hardware/VirtualIODevices.hpp +++ b/src/hardware/VirtualIODevices.hpp @@ -2,7 +2,7 @@ #include "IMemoryDevice.hpp" #include "../tools/GlobalData.hpp" -#include +#include "../tools/LegacyOstdSerial.hpp" #include #include diff --git a/src/hardware/VirtualMMU.hpp b/src/hardware/VirtualMMU.hpp index d307c58..ac073e4 100644 --- a/src/hardware/VirtualMMU.hpp +++ b/src/hardware/VirtualMMU.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include "../tools/LegacyOstdSerial.hpp" namespace dragon { diff --git a/src/hardware/VirtualRAM.hpp b/src/hardware/VirtualRAM.hpp index b75f563..ab8f2c9 100644 --- a/src/hardware/VirtualRAM.hpp +++ b/src/hardware/VirtualRAM.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include "../tools/LegacyOstdSerial.hpp" #include "IMemoryDevice.hpp" namespace dragon diff --git a/src/tools/GlobalData.hpp b/src/tools/GlobalData.hpp index fe673b7..1b1e5c1 100644 --- a/src/tools/GlobalData.hpp +++ b/src/tools/GlobalData.hpp @@ -60,63 +60,6 @@ namespace dragon }; - enum class ExceptionCause : u32 - { - // === Instruction fetch faults === - MisalignedFetch = 0x0000'0000, // PC not aligned to instruction boundary - InstructionBounds = 0x0000'0001, // PC outside any mapped region - InstructionPageFault = 0x0000'0002, // virt page not mapped (MMU on) or no X permission - InstructionPrivPageFault = 0x0000'0003, // privileged virt page not mapped (MMU on) or no X permission - UnknownInstruction = 0x0000'0004, // decoded opcode is not valid - - // === Privilege === - PrivilegeViolation = 0x0000'1000, // user mode executed a [PRIV] instruction - - // === Memory access faults (loads) === - MisalignedLoad = 0x0000'2000, // load address not naturally aligned - LoadBounds = 0x0000'2001, // load address outside mapped region - LoadPageFault = 0x0000'2002, // virt page not mapped or no R permission - LoadPrivPageFault = 0x0000'2003, // virt page not mapped or no R permission - - // === Memory access faults (stores) === - MisalignedStore = 0x0000'3000, - StoreBounds = 0x0000'3001, - StorePageFault = 0x0000'3002, // virt page not mapped or no W permission - StorePrivPageFault = 0x0000'3003, // virt page not mapped or no W permission - - // === Atomic op faults === - AtomicNotSupported = 0x0000'4000, // CAS/XADD/XCHG on a device that can't (ROM, MMIO) - - // === Arithmetic === - DivideByZero = 0x0000'5000, - - // === MMIO === - BusUnmapped = 0x0000'6000, - ReadOnlyViolation = 0x0000'6001, - - // === Deliberate guest-initiated traps === - Syscall = 0x0000'7000, // syscall instruction - SoftwareInt = 0x0000'7001, // int N instruction - TrapInstruction = 0x0000'7002, // explicit trap instr - Breakpoint = 0x0000'7003, // brk for debugger - - // === Asynchronous (external) === - HardwareInterrupt = 0x0000'F000, // generic external IRQ; details in INT controller - - // === Catastrophic === - DoubleFault = 0x000F'FFFF, // exception while handling exception - - // Just in case - NoFault = 0xFFFF'FFFF, - }; - - struct GuestException - { - ExceptionCause cause; - AddressType fault_addr; // VA for translation faults, PA for bus faults, 0 otherwise - String msg; // For debug - }; - class ErrorHandler { public: struct tError diff --git a/src/tools/LegacyOstdSerial.cpp b/src/tools/LegacyOstdSerial.cpp new file mode 100644 index 0000000..aa8352d --- /dev/null +++ b/src/tools/LegacyOstdSerial.cpp @@ -0,0 +1,457 @@ +#include "LegacyOstdSerial.hpp" +#include + +namespace ostd +{ + namespace serial + { + bool SerialIO::init(u64 size, u8 endianness) + { + if (size < 1) return false; + for (u64 i = 0; i < size; i++) + m_data.push_back(0); + m_endianness = endianness; + return true; + } + + + bool SerialIO::r_QWord(StreamIndex addr, QWord& outVal) + { + if (!is_validAddr(addr, tTypeSize::QWORD)) return false; + if (isLittleEndian()) + { + outVal = ( m_data[addr + 7] & 0x00000000000000FFU) + | (( m_data[addr + 6] << 8) & 0x000000000000FF00U) + | (( m_data[addr + 5] << 16) & 0x0000000000FF0000U) + | (( m_data[addr + 4] << 24) & 0x00000000FF000000U) + | (((QWord)m_data[addr + 3] << 32) & 0x000000FF00000000U) + | (((QWord)m_data[addr + 2] << 40) & 0x0000FF0000000000U) + | (((QWord)m_data[addr + 1] << 48) & 0x00FF000000000000U) + | (((QWord)m_data[addr + 0] << 56) & 0xFF00000000000000U); + } + else if (isBigEndian()) + { + outVal = (((QWord)m_data[addr + 0] << 56) & 0xFF00000000000000U) + | (((QWord)m_data[addr + 1] << 48) & 0x00FF000000000000U) + | (((QWord)m_data[addr + 2] << 40) & 0x0000FF0000000000U) + | (((QWord)m_data[addr + 3] << 32) & 0x000000FF00000000U) + | (( m_data[addr + 4] << 24) & 0x00000000FF000000U) + | (( m_data[addr + 5] << 16) & 0x0000000000FF0000U) + | (( m_data[addr + 6] << 8) & 0x000000000000FF00U) + | ( m_data[addr + 7] & 0x00000000000000FFU); + } + else return false; + return true; + } + + bool SerialIO::r_DWord(StreamIndex addr, DWord& outVal) + { + if (!is_validAddr(addr, tTypeSize::DWORD)) return false; + if (isLittleEndian()) + { + outVal = ((m_data[addr + 0] ) & 0x000000FF) + | ((m_data[addr + 1] << 8) & 0x0000FF00) + | ((m_data[addr + 2] << 16) & 0x00FF0000) + | ((m_data[addr + 3] << 24) & 0xFF000000); + } + else if (isBigEndian()) + { + outVal = ((m_data[addr + 0] << 24) & 0xFF000000U) + | ((m_data[addr + 1] << 16) & 0x00FF0000U) + | ((m_data[addr + 2] << 8) & 0x0000FF00U) + | ( m_data[addr + 3] & 0x000000FFU); + } + else return false; + return true; + } + + bool SerialIO::r_Word(StreamIndex addr, Word& outVal) + { + if (!is_validAddr(addr, tTypeSize::WORD)) return false; + if (isLittleEndian()) + { + outVal = ((m_data[addr + 0] ) & 0x00FFU) + | ((m_data[addr + 1] << 8) & 0xFF00U); + } + else if (isBigEndian()) + { + outVal = ((m_data[addr + 0] << 8) & 0xFF00U) + | ( m_data[addr + 1] & 0x00FFU); + } + else return false; + return true; + } + + bool SerialIO::r_Byte(StreamIndex addr, Byte& outVal) + { + if (!is_validAddr(addr, tTypeSize::BYTE)) return false; + outVal = m_data[addr]; + return true; + } + + bool SerialIO::r_Addr(StreamIndex addr, StreamIndex& outVal) + { + if (!is_validAddr(addr, tTypeSize::ADDR)) return false; + if (isLittleEndian()) + { + outVal = ((m_data[addr + 0] ) & 0x000000FF) + | ((m_data[addr + 1] << 8) & 0x0000FF00) + | ((m_data[addr + 2] << 16) & 0x00FF0000) + | ((m_data[addr + 3] << 24) & 0xFF000000); + } + else if (isBigEndian()) + { + outVal = ((m_data[addr + 0] << 24) & 0xFF000000U) + | ((m_data[addr + 1] << 16) & 0x00FF0000U) + | ((m_data[addr + 2] << 8) & 0x0000FF00U) + | ( m_data[addr + 3] & 0x000000FFU); + } + else return false; + return true; + } + + bool SerialIO::r_Float(StreamIndex addr, f32& outVal) + { + if (!is_validAddr(addr, tTypeSize::FLOAT)) return false; + __float_parser fp; + if (isLittleEndian()) + { + fp.data[3] = m_data[addr + 0]; + fp.data[2] = m_data[addr + 1]; + fp.data[1] = m_data[addr + 2]; + fp.data[0] = m_data[addr + 3]; + } + else if (isBigEndian()) + { + fp.data[0] = m_data[addr + 0]; + fp.data[1] = m_data[addr + 1]; + fp.data[2] = m_data[addr + 2]; + fp.data[3] = m_data[addr + 3]; + } + else return false; + outVal = fp.val; + return true; + } + + bool SerialIO::r_Double(StreamIndex addr, f64& outVal) + { + if (!is_validAddr(addr, tTypeSize::DOUBLE)) return false; + __double_parser dp; + if (isLittleEndian()) + { + dp.data[7] = m_data[addr++]; + dp.data[6] = m_data[addr++]; + dp.data[5] = m_data[addr++]; + dp.data[4] = m_data[addr++]; + dp.data[3] = m_data[addr++]; + dp.data[2] = m_data[addr++]; + dp.data[1] = m_data[addr++]; + dp.data[0] = m_data[addr ]; + } + else if (isBigEndian()) + { + dp.data[0] = m_data[addr++]; + dp.data[1] = m_data[addr++]; + dp.data[2] = m_data[addr++]; + dp.data[3] = m_data[addr++]; + dp.data[4] = m_data[addr++]; + dp.data[5] = m_data[addr++]; + dp.data[6] = m_data[addr++]; + dp.data[7] = m_data[addr ]; + } + else return false; + outVal = dp.val; + return true; + } + + bool SerialIO::r_ByteStream(StreamIndex addr, ByteStream& outStream) + { + if (!is_validAddr(addr, tTypeSize::ADDR)) return false; + u32 stream_size; + if (!r_Addr(addr, stream_size)) return false; + addr += tTypeSize::ADDR; + if (!is_validAddr(addr, stream_size)) return false; + outStream.clear(); + outStream.reserve(stream_size); + for (StreamIndex j = addr; j < addr + stream_size; j++) + outStream.push_back(m_data[j]); + return true; + } + + bool SerialIO::r_ByteStream(StreamIndex addr, ByteStream& outStream, u32 size) + { + if (!is_validAddr(addr, size)) return false; + outStream.clear(); + outStream.reserve(size); + for (StreamIndex j = addr; j < addr + size; j++) + outStream.push_back(m_data[j]); + return true; + } + + bool SerialIO::r_String(StreamIndex addr, String& outString) + { + if (!is_validAddr(addr, tTypeSize::ADDR)) return false; + u32 stream_size; + if (!r_Addr(addr, stream_size)) return false; + addr += tTypeSize::ADDR; + if (!is_validAddr(addr, stream_size)) return false; + outString = ""; + for (StreamIndex j = addr; j < addr + stream_size; j++) + outString += (char)(m_data[j]); + return true; + } + + bool SerialIO::r_String(StreamIndex addr, String& outString, u32 size) + { + if (!is_validAddr(addr, size)) return false; + outString = ""; + for (StreamIndex j = addr; j < addr + size; j++) + outString += (char)(m_data[j]); + return true; + } + + bool SerialIO::r_NullTerminatedString(StreamIndex addr, String& outString) + { + outString = ""; + i8 c = 0; + if (!r_Byte(addr, c)) return false; + addr += tTypeSize::BYTE; + while (c != 0) + { + outString += (char)c; + if (!r_Byte(addr, c)) return false; + addr += tTypeSize::BYTE; + } + return true; + } + + + bool SerialIO::w_QWord(StreamIndex addr, QWord val) + { + m_statuWriting = true; + if (!is_validAddr(addr, tTypeSize::QWORD)) return false; + if (isLittleEndian()) + { + m_data[addr + 0] = val & 0xFF; + m_data[addr + 1] = (val >> 8) & 0xFF; + m_data[addr + 2] = (val >> 16) & 0xFF; + m_data[addr + 3] = (val >> 24) & 0xFF; + m_data[addr + 4] = (val >> 32) & 0xFF; + m_data[addr + 5] = (val >> 40) & 0xFF; + m_data[addr + 6] = (val >> 48) & 0xFF; + m_data[addr + 7] = (val >> 56) & 0xFF; + } + else if (isBigEndian()) + { + m_data[addr + 0] = (val >> 56) & 0xFF; + m_data[addr + 1] = (val >> 48) & 0xFF; + m_data[addr + 2] = (val >> 40) & 0xFF; + m_data[addr + 3] = (val >> 32) & 0xFF; + m_data[addr + 4] = (val >> 24) & 0xFF; + m_data[addr + 5] = (val >> 16) & 0xFF; + m_data[addr + 6] = (val >> 8) & 0xFF; + m_data[addr + 7] = val & 0xFF; + } + else return false; + return true; + } + + bool SerialIO::w_DWord(StreamIndex addr, DWord val) + { + m_statuWriting = true; + if (!is_validAddr(addr, tTypeSize::DWORD)) return false; + if (isLittleEndian()) + { + m_data[addr + 0] = val & 0xFF; + m_data[addr + 1] = (val >> 8) & 0xFF; + m_data[addr + 2] = (val >> 16) & 0xFF; + m_data[addr + 3] = (val >> 24) & 0xFF; + } + else if (isBigEndian()) + { + m_data[addr + 0] = (val >> 24) & 0xFF; + m_data[addr + 1] = (val >> 16) & 0xFF; + m_data[addr + 2] = (val >> 8) & 0xFF; + m_data[addr + 3] = val & 0xFF; + } + else return false; + return true; + } + + bool SerialIO::w_Word(StreamIndex addr, Word val) + { + m_statuWriting = true; + if (!is_validAddr(addr, tTypeSize::WORD)) return false; + if (isLittleEndian()) + { + m_data[addr + 0] = val & 0xFF; + m_data[addr + 1] = (val >> 8) & 0xFF; + } + else if (isBigEndian()) + { + m_data[addr + 0] = (val >> 8) & 0xFF; + m_data[addr + 1] = val & 0xFF; + } + else return false; + return true; + } + + bool SerialIO::w_Byte(StreamIndex addr, Byte val) + { + m_statuWriting = true; + if (!is_validAddr(addr, tTypeSize::BYTE)) return false; + m_data[addr] = val; + return true; + } + + bool SerialIO::w_Addr(StreamIndex addr, StreamIndex val) + { + m_statuWriting = true; + if (!is_validAddr(addr, tTypeSize::ADDR)) return false; + if (isLittleEndian()) + { + m_data[addr + 0] = val & 0xFF; + m_data[addr + 1] = (val >> 8) & 0xFF; + m_data[addr + 2] = (val >> 16) & 0xFF; + m_data[addr + 3] = (val >> 24) & 0xFF; + } + else if (isBigEndian()) + { + m_data[addr + 0] = (val >> 24) & 0xFF; + m_data[addr + 1] = (val >> 16) & 0xFF; + m_data[addr + 2] = (val >> 8) & 0xFF; + m_data[addr + 3] = val & 0xFF; + } + else return false; + return true; + } + + bool SerialIO::w_Float(StreamIndex addr, f32 val) + { + m_statuWriting = true; + if (!is_validAddr(addr, tTypeSize::FLOAT)) return false; + __float_parser fp; + fp.val = val; + if (isLittleEndian()) + { + m_data[addr + 0] = fp.data[3]; + m_data[addr + 1] = fp.data[2]; + m_data[addr + 2] = fp.data[1]; + m_data[addr + 3] = fp.data[0]; + } + else if (isBigEndian()) + { + m_data[addr + 0] = fp.data[0]; + m_data[addr + 1] = fp.data[1]; + m_data[addr + 2] = fp.data[2]; + m_data[addr + 3] = fp.data[3]; + } + else return false; + return true; + } + + bool SerialIO::w_Double(StreamIndex addr, f64 val) + { + m_statuWriting = true; + if (!is_validAddr(addr, tTypeSize::DOUBLE)) return false; + __double_parser dp; + dp.val = val; + if (isLittleEndian()) + { + m_data[addr++] = dp.data[7]; + m_data[addr++] = dp.data[6]; + m_data[addr++] = dp.data[5]; + m_data[addr++] = dp.data[4]; + m_data[addr++] = dp.data[3]; + m_data[addr++] = dp.data[2]; + m_data[addr++] = dp.data[1]; + m_data[addr ] = dp.data[0]; + } + else if (isBigEndian()) + { + m_data[addr++] = dp.data[0]; + m_data[addr++] = dp.data[1]; + m_data[addr++] = dp.data[2]; + m_data[addr++] = dp.data[3]; + m_data[addr++] = dp.data[4]; + m_data[addr++] = dp.data[5]; + m_data[addr++] = dp.data[6]; + m_data[addr ] = dp.data[7]; + } + else return false; + return true; + } + + bool SerialIO::w_ByteStream(StreamIndex addr, const ByteStream& stream, bool store_size) + { + m_statuWriting = true; + u32 stream_size = stream.size(); + if (store_size) + { + if (!is_validAddr(addr, tTypeSize::ADDR + stream_size)) return false; + if (!w_Addr(addr, stream_size)) return false; + addr += tTypeSize::ADDR; + } + else if (!is_validAddr(addr, stream_size)) return false; + for (StreamIndex j = addr; j < addr + stream_size; j++) + m_data[j] = stream[j - addr]; + return true; + } + + bool SerialIO::w_String(StreamIndex addr, const String& str, bool store_size, bool null_terminate) + { + m_statuWriting = true; + auto stream = Memory::stringToByteStream(str); + u32 stream_size = stream.size(); + if (store_size && !null_terminate) + { + if (!is_validAddr(addr, tTypeSize::ADDR + stream_size)) return false; + if (!w_Addr(addr, stream_size)) return false; + addr += tTypeSize::ADDR; + } + else if (!is_validAddr(addr, stream_size)) return false; + for (StreamIndex j = addr; j < addr + stream_size; j++) + m_data[j] = stream[j - addr]; + addr += str.len() * tTypeSize::BYTE; + if (null_terminate) + if (!w_Byte(addr, 0x00)) return false; + return true; + } + + + bool SerialIO::is_validAddr(StreamIndex addr, StreamIndex offset) + { + if ((addr + offset - 1) >= m_data.size()) + { + if (isAutoResizeEnabled() && m_statuWriting) + { + for (u32 i = 0; i <= m_resizeAmount; i++) + m_data.push_back(0); + m_statuWriting = false; + return true; + } + else + { + m_statuWriting = false; + return false; + } + } + m_statuWriting = false; + return true; + } + + void SerialIO::print(StreamIndex start, OutputHandlerBase& out) + { + u32 line_len = 32; + u64 power = 1; + while(power < size()) + power *= 2; + Memory::printByteStream(m_data, start, line_len, power / line_len, out); + } + + bool SerialIO::saveToFile(const String& filePath) + { + return Memory::saveByteStreamToFile(getData(), filePath); + } + } +} diff --git a/src/tools/LegacyOstdSerial.hpp b/src/tools/LegacyOstdSerial.hpp new file mode 100644 index 0000000..3347e64 --- /dev/null +++ b/src/tools/LegacyOstdSerial.hpp @@ -0,0 +1,92 @@ +/* + OmniaFramework - A collection of useful functionality + Copyright (C) 2026 OmniaX-Dev + + This file is part of OmniaFramework. + + OmniaFramework is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OmniaFramework is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OmniaFramework. If not, see . +*/ + +#pragma once + +#include +#include +#include + +namespace ostd +{ + class OutputHandlerBase; + + namespace serial + { + class SerialIO + { + public: struct tEndianness { + inline static constexpr u8 LittleEndian = 0x00; + inline static constexpr u8 BigEndian = 0x01; + }; + + public: + inline SerialIO(void) { init(); } + inline SerialIO(u64 size, u8 endianness = tEndianness::BigEndian) { init(size, endianness); } + inline SerialIO(ByteStream& data, u8 endianness = tEndianness::BigEndian) { m_data = data; m_endianness = endianness; } + bool init(u64 size = SerialIO::DefaultMaxSize, u8 endianness = tEndianness::BigEndian); + bool r_QWord(StreamIndex addr, QWord& outVal); + bool r_DWord(StreamIndex addr, DWord& outVal); + bool r_Word(StreamIndex addr, Word& outVal); + bool r_Byte(StreamIndex addr, Byte& outVal); + bool r_Addr(StreamIndex addr, StreamIndex& outVal); + bool r_Float(StreamIndex addr, f32& outVal); + bool r_Double(StreamIndex addr, f64& outVal); + bool r_ByteStream(StreamIndex addr, ByteStream& outStream); + bool r_ByteStream(StreamIndex addr, ByteStream& outStream, u32 size); + bool r_String(StreamIndex addr, String& outString); + bool r_String(StreamIndex addr, String& outString, u32 size); + bool r_NullTerminatedString(StreamIndex addr, String& outString); + + bool w_QWord(StreamIndex addr, QWord val); + bool w_DWord(StreamIndex addr, DWord val); + bool w_Word(StreamIndex addr, Word val); + bool w_Byte(StreamIndex addr, Byte val); + bool w_Addr(StreamIndex addr, StreamIndex val); + bool w_Float(StreamIndex addr, f32 val); + bool w_Double(StreamIndex addr, f64 val); + bool w_ByteStream(StreamIndex addr, const ByteStream& stream, bool store_size = true); + bool w_String(StreamIndex addr, const String& str, bool store_size = false, bool null_terminate = true); + bool is_validAddr(StreamIndex addr, StreamIndex offset = 1); + inline u64 size(void) { return m_data.size(); } + inline ByteStream& getData(void) { return m_data; } + + void print(StreamIndex start, OutputHandlerBase& out); + bool saveToFile(const String& filePath); + + inline u8 getEndianness(void) const { return m_endianness; } + inline bool isLittleEndian(void) const { return m_endianness == tEndianness::LittleEndian; } + inline bool isBigEndian(void) const { return m_endianness == tEndianness::BigEndian; } + + inline bool isAutoResizeEnabled(void) const { return m_autoResize; } + inline void enableAutoResize(bool val = true, i32 resizeAmount = 1024) { m_autoResize = val; if (!val) return; m_resizeAmount = resizeAmount; } + + private: + ByteStream m_data; + u8 m_endianness { tEndianness::BigEndian }; + bool m_autoResize { true }; + i32 m_resizeAmount { 1024 }; + bool m_statuWriting { false }; + + public: + inline static constexpr u64 DefaultMaxSize = 512; + }; + } +} diff --git a/src/tools/Tools.cpp b/src/tools/Tools.cpp index 39f2e22..21b4e8a 100644 --- a/src/tools/Tools.cpp +++ b/src/tools/Tools.cpp @@ -7,7 +7,7 @@ #include "GlobalData.hpp" #include "../debugger/DisassemblyLoader.hpp" #include -#include +#include "../tools/LegacyOstdSerial.hpp" namespace dragon { diff --git a/src/tools/Utils.cpp b/src/tools/Utils.cpp index ff1627a..59e9d8d 100644 --- a/src/tools/Utils.cpp +++ b/src/tools/Utils.cpp @@ -1,5 +1,4 @@ #include "Utils.hpp" -#include #include namespace dragon