libicsneo/disk/diskdetails.cpp

82 lines
2.5 KiB
C++

#include <icsneo/disk/diskdetails.h>
#include <icsneo/device/idevicesettings.h>
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<uint8_t> DiskDetails::Encode(const DiskDetails& config) {
std::vector<uint8_t> result(sizeof(DISK_DETAILS), 0);
DISK_DETAILS* details = reinterpret_cast<DISK_DETAILS*>(result.data());
details->settings.disk_layout = static_cast<uint8_t>(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> DiskDetails::Decode(const std::vector<uint8_t>& 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<DiskDetails>();
const DISK_DETAILS* details = reinterpret_cast<const DISK_DETAILS*>(bytes.data());
result->layout = static_cast<DiskLayout>(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<bool>(disk.status & DISK_STATUS_PRESENT);
info.initialized = static_cast<bool>(disk.status & DISK_STATUS_INITIALIZED);
info.formatted = static_cast<bool>(details->settings.disk_enables & (1u << i));
info.sectors = disk.sectors;
info.bytesPerSector = disk.bytesPerSector;
}
return result;
}