#include #include using namespace icsneo; #pragma pack(push, 2) struct DISK_STATUS { uint16_t status; uint64_t sectors; uint32_t bytesPerSector; }; struct DISK_DETAILS { DISK_SETTINGS settings; uint16_t options; DISK_STATUS status[12]; }; #pragma pack(pop) static constexpr uint8_t DISK_FORMAT_FAT32 = 0x01u; static constexpr uint8_t DISK_STATUS_PRESENT = 0x01u; static constexpr uint8_t DISK_STATUS_INITIALIZED = 0x02u; static constexpr uint16_t DISK_DETAILS_FULL_FORMAT = 0x01u; std::vector DiskDetails::Encode(const DiskDetails& config) { std::vector result(sizeof(DISK_DETAILS), 0); DISK_DETAILS* details = reinterpret_cast(result.data()); details->settings.disk_layout = static_cast(config.layout); details->settings.disk_format = DISK_FORMAT_FAT32; // Always FAT32 details->options = config.fullFormat ? DISK_DETAILS_FULL_FORMAT : 0; uint32_t& enables = details->settings.disk_enables; enables = 0u; for(size_t i = 0; i < config.disks.size(); i++) { auto& disk = config.disks[i]; details->status[i].sectors = disk.sectors; details->status[i].bytesPerSector = disk.bytesPerSector; uint16_t& status = details->status[i].status; status = 0u; if(disk.initialized) { status |= DISK_STATUS_INITIALIZED; } if(disk.present) { status |= DISK_STATUS_PRESENT; } if(disk.formatted) { enables |= (1u << i); } } return result; } std::shared_ptr DiskDetails::Decode(const std::vector& bytes, size_t diskCount, device_eventhandler_t report) { if(bytes.size() < sizeof(DISK_DETAILS)) { report(APIEvent::Type::BufferInsufficient, APIEvent::Severity::Error); return nullptr; } auto result = std::make_shared(); const DISK_DETAILS* details = reinterpret_cast(bytes.data()); result->layout = static_cast(details->settings.disk_layout); result->fullFormat = details->options & DISK_DETAILS_FULL_FORMAT; result->disks.reserve(diskCount); for(size_t i = 0; i < diskCount; i++) { auto& disk = details->status[i]; result->disks.emplace_back(); auto& info = result->disks.back(); info.present = static_cast(disk.status & DISK_STATUS_PRESENT); info.initialized = static_cast(disk.status & DISK_STATUS_INITIALIZED); info.formatted = static_cast(details->settings.disk_enables & (1u << i)); info.sectors = disk.sectors; info.bytesPerSector = disk.bytesPerSector; } return result; }