#pragma once #include #include #include #include #include #include #include namespace vc5 { namespace fs = std::filesystem; class BlockDevice { public: virtual ~BlockDevice() = default; static constexpr uint16_t block_size = 512; virtual auto block_count() -> uint16_t = 0; virtual void read(uint8_t* data, uint16_t block) = 0; virtual void write(const uint8_t* data, uint16_t block) = 0; }; class MemoryDisk final : public BlockDevice { public: explicit MemoryDisk(uint16_t block_count) : m_data(block_size * block_count, 0) , m_block_count(block_count) { } auto block_count() -> uint16_t override { return m_block_count; } void read(uint8_t* data, uint16_t block) override; void write(const uint8_t* data, uint16_t block) override; auto data() -> uint8_t* { return m_data.data(); } private: std::vector m_data; uint16_t m_block_count; }; class FileDisk final : public BlockDevice { public: explicit FileDisk(fs::path file_path) : m_file(file_path, std::ios_base::binary) { if (not m_file) { throw std::invalid_argument(std::format( "unable to open file '{}'", std::string(file_path))); } } auto block_count() -> uint16_t override; void read(uint8_t* data, uint16_t block) override; void write(const uint8_t* data, uint16_t block) override; private: std::fstream m_file; }; }