diff options
author | 2021-04-28 22:58:51 +0200 | |
---|---|---|
committer | 2021-04-28 22:58:57 +0200 | |
commit | 18d1768325a37b3496a55a84698e7c7dc789e14c (patch) | |
tree | cdcbf932a7e76af7160b491ea050e39bc340228f /src/lib/formats | |
parent | 67d7e16274f71ab6fefeeedcaab12066d2a12668 (diff) |
floppy: first steps on metadata, and hopefully make gcc happier on enumerate
Diffstat (limited to 'src/lib/formats')
-rw-r--r-- | src/lib/formats/fs_oric_jasmin.cpp | 55 | ||||
-rw-r--r-- | src/lib/formats/fs_oric_jasmin.h | 13 | ||||
-rw-r--r-- | src/lib/formats/fs_prodos.cpp | 32 | ||||
-rw-r--r-- | src/lib/formats/fs_prodos.h | 11 | ||||
-rw-r--r-- | src/lib/formats/fs_unformatted.cpp | 7 | ||||
-rw-r--r-- | src/lib/formats/fs_unformatted.h | 3 | ||||
-rw-r--r-- | src/lib/formats/fsmgr.cpp | 76 | ||||
-rw-r--r-- | src/lib/formats/fsmgr.h | 70 |
8 files changed, 237 insertions, 30 deletions
diff --git a/src/lib/formats/fs_oric_jasmin.cpp b/src/lib/formats/fs_oric_jasmin.cpp index 13f70ecc258..59ff60fd4b7 100644 --- a/src/lib/formats/fs_oric_jasmin.cpp +++ b/src/lib/formats/fs_oric_jasmin.cpp @@ -39,7 +39,7 @@ // offset 04-05: length of the file in bytes on the first sector, ffff otherwise // offset 06+ : reference to data sectors, (ff, ff) when done -void fs_oric_jasmin::enumerate(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const +void fs_oric_jasmin::enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const { if(has(form_factor, variants, floppy_image::FF_3, floppy_image::DSDD)) fe.add(this, FLOPPY_ORIC_JASMIN_FORMAT, 356864, "oric_jasmin_ds", "Oric Jasmin dual-sided"); @@ -59,7 +59,7 @@ bool fs_oric_jasmin::can_format() const bool fs_oric_jasmin::can_read() const { - return false; + return true; } bool fs_oric_jasmin::can_write() const @@ -67,11 +67,56 @@ bool fs_oric_jasmin::can_write() const return false; } +bool fs_oric_jasmin::has_subdirectories() const +{ + return false; +} + +std::vector<fs_meta_description> fs_oric_jasmin::volume_meta_description() const +{ + std::vector<fs_meta_description> res; + res.emplace_back(fs_meta_description(fs_meta_name::name, fs_meta_type::string, "UNTITLED", false, [](const fs_meta &m) { std::string n = std::get<std::string>(m); return n.size() <= 8; }, "Volume name, up to 8 characters")); + + return res; +} + +fs_meta_data fs_oric_jasmin::impl::metadata() +{ + fs_meta_data res; + auto bdir = m_blockdev.get(20*17); + int len = 8; + while(len > 0 && bdir.rodata()[0xf8 + len - 1] == ' ') + len--; + + res[fs_meta_name::name] = bdir.rstr(0xf8, len); + return res; +} + +bool fs_oric_jasmin::validate_filename(std::string name) +{ + auto pos = name.find('.'); + if(pos != std::string::npos) + return pos <= 8 && pos > 0 && name.size()-pos-1 <= 3; + else + return name.size() > 0 && name.size() <= 8; +} + +std::vector<fs_meta_description> fs_oric_jasmin::file_meta_description() const +{ + std::vector<fs_meta_description> res; + res.emplace_back(fs_meta_description(fs_meta_name::name, fs_meta_type::string, "", false, [](const fs_meta &m) { std::string n = std::get<std::string>(m); return validate_filename(n); }, "File name, 8.3")); + res.emplace_back(fs_meta_description(fs_meta_name::loading_address, fs_meta_type::number, 0x501, false, [](const fs_meta &m) { uint64_t n = std::get<uint64_t>(m); return n < 0x10000; }, "Loading address of the file")); + res.emplace_back(fs_meta_description(fs_meta_name::length, fs_meta_type::number, 0, true, nullptr, "Size of the file in bytes")); + res.emplace_back(fs_meta_description(fs_meta_name::size_in_blocks, fs_meta_type::number, 0, true, nullptr, "Number of blocks used by the file")); + res.emplace_back(fs_meta_description(fs_meta_name::locked, fs_meta_type::flag, false, false, nullptr, "File locked")); + res.emplace_back(fs_meta_description(fs_meta_name::sequential, fs_meta_type::flag, true, false, nullptr, "File sequential")); + return res; +} + -void fs_oric_jasmin::impl::format() +void fs_oric_jasmin::impl::format(const fs_meta_data &meta) { - std::string volume_name = "UNTITLED"; - m_blockdev.set_block_size(256); + std::string volume_name = std::get<std::string>(meta.find(fs_meta_name::name)->second); u32 blocks = m_blockdev.block_count(); m_blockdev.fill(0x6c); diff --git a/src/lib/formats/fs_oric_jasmin.h b/src/lib/formats/fs_oric_jasmin.h index f2f212b1065..347a23ff349 100644 --- a/src/lib/formats/fs_oric_jasmin.h +++ b/src/lib/formats/fs_oric_jasmin.h @@ -14,20 +14,27 @@ class fs_oric_jasmin : public filesystem_manager_t { public: class impl : public filesystem_t { public: - impl(fsblk_t &blockdev) : filesystem_t(blockdev) {} + impl(fsblk_t &blockdev) : filesystem_t(blockdev, 256) {} virtual ~impl() = default; - virtual void format() override; + virtual void format(const fs_meta_data &meta) override; + virtual fs_meta_data metadata() override; }; fs_oric_jasmin() : filesystem_manager_t() {} - virtual void enumerate(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const override; + virtual void enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const override; virtual std::unique_ptr<filesystem_t> mount(fsblk_t &blockdev) const override; virtual bool can_format() const override; virtual bool can_read() const override; virtual bool can_write() const override; + virtual bool has_subdirectories() const override; + + virtual std::vector<fs_meta_description> volume_meta_description() const override; + virtual std::vector<fs_meta_description> file_meta_description() const override; + + static bool validate_filename(std::string name); }; extern const filesystem_manager_type FS_ORIC_JASMIN; diff --git a/src/lib/formats/fs_prodos.cpp b/src/lib/formats/fs_prodos.cpp index 25e5cdc152f..e2908f6cebd 100644 --- a/src/lib/formats/fs_prodos.cpp +++ b/src/lib/formats/fs_prodos.cpp @@ -42,7 +42,7 @@ const u8 fs_prodos::impl::boot[512] = { 0xf0, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; -void fs_prodos::enumerate(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const +void fs_prodos::enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const { if(has(form_factor, variants, floppy_image::FF_35, floppy_image::DSDD)) fe.add(this, FLOPPY_APPLE_GCR_FORMAT, 819200, "prodos_800k", "Apple ProDOS 800K"); @@ -70,10 +70,34 @@ bool fs_prodos::can_write() const return false; } -void fs_prodos::impl::format() +bool fs_prodos::has_subdirectories() const { - std::string volume_name = "UNTITLED"; - m_blockdev.set_block_size(512); + return true; +} + +std::vector<fs_meta_description> fs_prodos::volume_meta_description() const +{ + std::vector<fs_meta_description> res; + res.emplace_back(fs_meta_description(fs_meta_name::name, fs_meta_type::string, "UNTITLED", false, [](const fs_meta &m) { std::string n = std::get<std::string>(m); return n.size() <= 15; }, "Volume name, up to 15 characters")); + + return res; +} + +std::vector<fs_meta_description> fs_prodos::file_meta_description() const +{ + std::vector<fs_meta_description> res; + return res; +} + +std::vector<fs_meta_description> fs_prodos::directory_meta_description() const +{ + std::vector<fs_meta_description> res; + return res; +} + +void fs_prodos::impl::format(const fs_meta_data &meta) +{ + std::string volume_name = std::get<std::string>(meta.find(fs_meta_name::name)->second); u32 blocks = m_blockdev.block_count(); m_blockdev.get(0).copy(0x000, boot, 0x200); // Standard ProDOS boot sector as written by a 2gs diff --git a/src/lib/formats/fs_prodos.h b/src/lib/formats/fs_prodos.h index 75cb49f2507..4ec3c8e1d4b 100644 --- a/src/lib/formats/fs_prodos.h +++ b/src/lib/formats/fs_prodos.h @@ -14,10 +14,10 @@ class fs_prodos : public filesystem_manager_t { public: class impl : public filesystem_t { public: - impl(fsblk_t &blockdev) : filesystem_t(blockdev) {} + impl(fsblk_t &blockdev) : filesystem_t(blockdev, 512) {} virtual ~impl() = default; - virtual void format() override; + virtual void format(const fs_meta_data &meta) override; private: static const u8 boot[512]; @@ -25,12 +25,17 @@ public: fs_prodos() : filesystem_manager_t() {} - virtual void enumerate(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const override; + virtual void enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const override; virtual std::unique_ptr<filesystem_t> mount(fsblk_t &blockdev) const override; virtual bool can_format() const override; virtual bool can_read() const override; virtual bool can_write() const override; + virtual bool has_subdirectories() const override; + + virtual std::vector<fs_meta_description> volume_meta_description() const override; + virtual std::vector<fs_meta_description> file_meta_description() const override; + virtual std::vector<fs_meta_description> directory_meta_description() const override; }; extern const filesystem_manager_type FS_PRODOS; diff --git a/src/lib/formats/fs_unformatted.cpp b/src/lib/formats/fs_unformatted.cpp index 01e611557b6..451cda3c84f 100644 --- a/src/lib/formats/fs_unformatted.cpp +++ b/src/lib/formats/fs_unformatted.cpp @@ -6,7 +6,7 @@ #include "emu.h" #include "fs_unformatted.h" -void fs_unformatted::enumerate(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const +void fs_unformatted::enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const { bool all = form_factor == floppy_image::FF_UNKNOWN; u32 best_8 = @@ -116,4 +116,9 @@ bool fs_unformatted::can_write() const return false; } +bool fs_unformatted::has_subdirectories() const +{ + return false; +} + const filesystem_manager_type FS_UNFORMATTED = &filesystem_manager_creator<fs_unformatted>; diff --git a/src/lib/formats/fs_unformatted.h b/src/lib/formats/fs_unformatted.h index b21ed311054..71b9bc4feb4 100644 --- a/src/lib/formats/fs_unformatted.h +++ b/src/lib/formats/fs_unformatted.h @@ -40,12 +40,13 @@ public: static void format(u32 key, floppy_image *image); - virtual void enumerate(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const override; + virtual void enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const override; virtual std::unique_ptr<filesystem_t> mount(fsblk_t &blockdev) const override; virtual bool can_format() const override; virtual bool can_read() const override; virtual bool can_write() const override; + virtual bool has_subdirectories() const override; }; extern const filesystem_manager_type FS_UNFORMATTED; diff --git a/src/lib/formats/fsmgr.cpp b/src/lib/formats/fsmgr.cpp index ec80710ac33..6423d523300 100644 --- a/src/lib/formats/fsmgr.cpp +++ b/src/lib/formats/fsmgr.cpp @@ -39,15 +39,15 @@ void fsblk_t::iblock_t::unref_weak() } -void filesystem_manager_t::enumerate(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const +void filesystem_manager_t::enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const { } -void filesystem_manager_t::enumerate(hd_enumerator &he) const +void filesystem_manager_t::enumerate_h(hd_enumerator &he) const { } -void filesystem_manager_t::enumerate(cdrom_enumerator &ce) const +void filesystem_manager_t::enumerate_c(cdrom_enumerator &ce) const { } @@ -71,14 +71,37 @@ bool filesystem_manager_t::has(uint32_t form_factor, const std::vector<uint32_t> return false; } -void filesystem_t::format() +std::vector<fs_meta_description> filesystem_manager_t::volume_meta_description() const { - fatalerror("format called on filesystem not supporting it.\n"); + std::vector<fs_meta_description> res; + return res; +} + +std::vector<fs_meta_description> filesystem_manager_t::file_meta_description() const +{ + std::vector<fs_meta_description> res; + return res; +} + +std::vector<fs_meta_description> filesystem_manager_t::directory_meta_description() const +{ + std::vector<fs_meta_description> res; + return res; +} + +void filesystem_t::format(const fs_meta_data &meta) +{ + fatalerror("format called on a filesystem not supporting it.\n"); } filesystem_t::dir_t filesystem_t::root() { - fatalerror("root called on filesystem not supporting it.\n"); + fatalerror("root called on a filesystem not supporting it.\n"); +} + +fs_meta_data filesystem_t::metadata() +{ + fatalerror("filesystem_t::metadata called on a filesystem not supporting it.\n"); } void fsblk_t::set_block_size(uint32_t block_size) @@ -94,6 +117,13 @@ uint8_t *fsblk_t::iblock_t::offset(const char *function, uint32_t off, uint32_t return data() + off; } +const uint8_t *fsblk_t::iblock_t::rooffset(const char *function, uint32_t off, uint32_t size) +{ + if(off + size > m_size) + fatalerror("block_t::%s out-of-block read access, offset=%d, size=%d, block size=%d\n", function, off, size, m_size); + return rodata() + off; +} + void fsblk_t::block_t::copy(u32 offset, const uint8_t *src, u32 size) { uint8_t *blk = m_block->offset("copy", offset, size); @@ -155,3 +185,37 @@ void fsblk_t::block_t::w32l(u32 offset, u32 data) blk[2] = data >> 16; blk[3] = data >> 24; } + +std::string fsblk_t::block_t::rstr(u32 offset, u32 size) +{ + const u8 *d = m_block->rooffset("rstr", offset, size); + std::string res; + for(u32 i=0; i != size; i++) + res += char(*d++); + return res; +} + +const char *fs_meta_get_name(fs_meta_name name) +{ + switch(name) { + case fs_meta_name::creation_date: return "creation_date"; + case fs_meta_name::length: return "length"; + case fs_meta_name::loading_address: return "loading_address"; + case fs_meta_name::locked: return "locked"; + case fs_meta_name::sequential: return "sequential"; + case fs_meta_name::modification_date: return "modification_date"; + case fs_meta_name::name: return "name"; + case fs_meta_name::size_in_blocks: return "size_in_blocks"; + } +} + +std::string fs_meta_to_string(fs_meta_type type, const fs_meta &m) +{ + switch(type) { + case fs_meta_type::string: return std::get<std::string>(m); + case fs_meta_type::number: return util::string_format("0x%x", std::get<uint64_t>(m)); + case fs_meta_type::flag: return std::get<bool>(m) ? "t" : "f"; + case fs_meta_type::date: abort(); + } +} + diff --git a/src/lib/formats/fsmgr.h b/src/lib/formats/fsmgr.h index 46a9f285c5e..dee33808388 100644 --- a/src/lib/formats/fsmgr.h +++ b/src/lib/formats/fsmgr.h @@ -10,6 +10,52 @@ #include "flopimg.h" +#include <variant> +#include <unordered_map> + +enum class fs_meta_name { + creation_date, + length, + loading_address, + locked, + sequential, + modification_date, + name, + size_in_blocks, +}; + +enum class fs_meta_type { + string, + number, + date, + flag, +}; + +using fs_meta = std::variant<std::string, uint64_t, bool>; +using fs_meta_data = std::unordered_map<fs_meta_name, fs_meta>; + +const char *fs_meta_get_name(fs_meta_name name); +std::string fs_meta_to_string(fs_meta_type type, const fs_meta &m); +fs_meta fs_meta_from_string(fs_meta_type type, std::string value); + + +struct fs_meta_description { + fs_meta_name m_name; + fs_meta_type m_type; + fs_meta m_default; + bool m_ro; + std::function<void (const fs_meta &)> m_validator; + const char *m_tooltip; + + fs_meta_description(fs_meta_name name, fs_meta_type type, int def, bool ro, std::function<void (fs_meta)> validator, const char *tooltip) : + m_name(name), m_type(type), m_default(uint64_t(def)), m_ro(ro), m_validator(validator), m_tooltip(tooltip) + {} + + template<typename T> fs_meta_description(fs_meta_name name, fs_meta_type type, T def, bool ro, std::function<void (fs_meta)> validator, const char *tooltip) : + m_name(name), m_type(type), m_default(def), m_ro(ro), m_validator(validator), m_tooltip(tooltip) + {} +}; + class fsblk_t { protected: class iblock_t { @@ -29,6 +75,7 @@ protected: virtual const uint8_t *rodata() = 0; virtual uint8_t *data() = 0; uint8_t *offset(const char *function, uint32_t off, uint32_t size); + const uint8_t *rooffset(const char *function, uint32_t off, uint32_t size); protected: uint32_t m_ref, m_weak_ref; @@ -91,6 +138,8 @@ public: void w16l(uint32_t offset, u16 data); void w32l(uint32_t offset, uint32_t data); + std::string rstr(uint32_t offset, uint32_t size); + private: iblock_t *m_block; bool m_is_weak_ref; @@ -114,7 +163,7 @@ public: } }; - fsblk_t() = default; + fsblk_t() : m_block_size(0) {} virtual ~fsblk_t() = default; virtual void set_block_size(uint32_t block_size); @@ -272,14 +321,16 @@ public: } }; - filesystem_t(fsblk_t &blockdev) : m_blockdev(blockdev) {} + filesystem_t(fsblk_t &blockdev, u32 size) : m_blockdev(blockdev) { + m_blockdev.set_block_size(size); + } virtual ~filesystem_t() = default; - virtual void format(); + virtual void format(const fs_meta_data &meta); + virtual fs_meta_data metadata(); virtual dir_t root(); - protected: fsblk_t &m_blockdev; }; @@ -310,13 +361,18 @@ public: virtual ~filesystem_manager_t() = default; - virtual void enumerate(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const; - virtual void enumerate(hd_enumerator &he) const; - virtual void enumerate(cdrom_enumerator &ce) const; + virtual void enumerate_f(floppy_enumerator &fe, uint32_t form_factor, const std::vector<uint32_t> &variants) const; + virtual void enumerate_h(hd_enumerator &he) const; + virtual void enumerate_c(cdrom_enumerator &ce) const; virtual bool can_format() const = 0; virtual bool can_read() const = 0; virtual bool can_write() const = 0; + virtual bool has_subdirectories() const = 0; + + virtual std::vector<fs_meta_description> volume_meta_description() const; + virtual std::vector<fs_meta_description> file_meta_description() const; + virtual std::vector<fs_meta_description> directory_meta_description() const; // Create a filesystem object from a block device virtual std::unique_ptr<filesystem_t> mount(fsblk_t &blockdev) const = 0; |