diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/devices/imagedev/floppy.cpp | 6 | ||||
-rw-r--r-- | src/devices/imagedev/floppy.h | 2 | ||||
-rw-r--r-- | src/frontend/mame/ui/floppycntrl.cpp | 12 | ||||
-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 | ||||
-rw-r--r-- | src/tools/floptool.cpp | 91 |
12 files changed, 336 insertions, 42 deletions
diff --git a/src/devices/imagedev/floppy.cpp b/src/devices/imagedev/floppy.cpp index 2decede8498..738412f5530 100644 --- a/src/devices/imagedev/floppy.cpp +++ b/src/devices/imagedev/floppy.cpp @@ -348,7 +348,7 @@ void floppy_image_device::register_formats() for(filesystem_manager_type fmt : fr.m_fs) { auto ff = fmt(); - ff->enumerate(fse, form_factor, variants); + ff->enumerate_f(fse, form_factor, variants); m_fs_managers.push_back(std::unique_ptr<filesystem_manager_t>(ff)); } } @@ -716,7 +716,7 @@ static io_generic *ram_open(std::vector<u8> &data) return new io_generic({ &iop_ram, f }); } -void floppy_image_device::init_fs(const fs_info *fs) +void floppy_image_device::init_fs(const fs_info *fs, const fs_meta_data &meta) { assert(image); if (fs->m_type) @@ -724,7 +724,7 @@ void floppy_image_device::init_fs(const fs_info *fs) std::vector<u8> img(fs->m_image_size); fsblk_vec_t blockdev(img); auto cfs = fs->m_manager->mount(blockdev); - cfs->format(); + cfs->format(meta); auto iog = ram_open(img); auto source_format = fs->m_type(); diff --git a/src/devices/imagedev/floppy.h b/src/devices/imagedev/floppy.h index 0747e1bef3a..c9fdc220ad3 100644 --- a/src/devices/imagedev/floppy.h +++ b/src/devices/imagedev/floppy.h @@ -86,7 +86,7 @@ public: floppy_image_format_t *identify(std::string filename); void set_rpm(float rpm); - void init_fs(const fs_info *fs); + void init_fs(const fs_info *fs, const fs_meta_data &meta); // image-level overrides virtual image_init_result call_load() override; diff --git a/src/frontend/mame/ui/floppycntrl.cpp b/src/frontend/mame/ui/floppycntrl.cpp index 4fadfd00cd8..f06c122280f 100644 --- a/src/frontend/mame/ui/floppycntrl.cpp +++ b/src/frontend/mame/ui/floppycntrl.cpp @@ -52,8 +52,16 @@ void menu_control_floppy_image::do_load_create() if (create_fs) { // HACK: ensure the floppy_image structure is created since device_image_interface may not otherwise do so during "init phase" err = fd.finish_load(); - if (err == image_init_result::PASS) - fd.init_fs(create_fs); + if (err == image_init_result::PASS) { + fs_meta_data meta; + if(create_fs->m_manager) { + auto metav = create_fs->m_manager->volume_meta_description(); + for(const auto &e : metav) + if(!e.m_ro) + meta[e.m_name] = e.m_default; + } + fd.init_fs(create_fs, meta); + } } } else { image_init_result err = fd.load(input_filename); 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; diff --git a/src/tools/floptool.cpp b/src/tools/floptool.cpp index 1e833a54b6b..91095f3a2b7 100644 --- a/src/tools/floptool.cpp +++ b/src/tools/floptool.cpp @@ -89,7 +89,10 @@ static int ram_seekproc(void *file, int64_t offset, int whence) case SEEK_END: f->pos = f->data->size() + offset; break; } - f->pos = std::clamp(f->pos, int64_t(0), int64_t(f->data->size())); + if(whence == SEEK_CUR) + f->pos = std::max(f->pos, int64_t(0)); + else + f->pos = std::clamp(f->pos, int64_t(0), int64_t(f->data->size())); return 0; } @@ -104,9 +107,10 @@ static size_t ram_readproc(void *file, void *buffer, size_t length) static size_t ram_writeproc(void *file, const void *buffer, size_t length) { auto f = (iofile_ram *)file; - size_t l = std::min(length, size_t(f->data->size() - f->pos)); - memcpy(f->data->data() + f->pos, buffer, l); - return l; + size_t l = std::max(f->pos + length, f->data->size()); + f->data->resize(l); + memcpy(f->data->data() + f->pos, buffer, length); + return length; } static uint64_t ram_filesizeproc(void *file) @@ -188,7 +192,7 @@ struct enumerator : public mame_formats_enumerator { virtual void add(filesystem_manager_type fs) { auto ff = fs(); - ff->enumerate(fse, floppy_image::FF_UNKNOWN, variants); + ff->enumerate_f(fse, floppy_image::FF_UNKNOWN, variants); } }; @@ -273,6 +277,7 @@ static void display_usage() fprintf(stderr, " floptool.exe identify <inputfile> [<inputfile> ...]\n"); fprintf(stderr, " floptool.exe convert [input_format|auto] output_format <inputfile> <outputfile>\n"); fprintf(stderr, " floptool.exe create output_format filesystem <outputfile>\n"); + fprintf(stderr, " floptool.exe dir input_format filesystem <inputfile>\n"); } static void display_formats() @@ -454,10 +459,16 @@ static int create(int argc, char *argv[]) floppy_image image(84, 2, floppy_image::FF_UNKNOWN); if(source_fs->m_type) { + auto metav = source_fs->m_manager->volume_meta_description(); + fs_meta_data meta; + for(const auto &e : metav) + if(!e.m_ro) + meta[e.m_name] = e.m_default; + std::vector<u8> img(source_fs->m_image_size); fsblk_vec_t blockdev(img); auto fs = source_fs->m_manager->mount(blockdev); - fs->format(); + fs->format(meta); auto iog = ram_open(img); auto source_format = source_fs->m_type(); @@ -491,6 +502,72 @@ static int create(int argc, char *argv[]) return 0; } +static int dir(int argc, char *argv[]) +{ + if (argc!=5) { + fprintf(stderr, "Incorrect number of arguments.\n\n"); + display_usage(); + return 1; + } + + auto format = find_format_by_name(argv[2]); + if(!format) { + fprintf(stderr, "Error: Format '%s' unknown\n", argv[3]); + return 1; + } + + auto fs = find_fs_by_name(argv[3]); + if(!fs) { + fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[2]); + return 1; + } + + if(!fs->m_manager || !fs->m_manager->can_read()) { + fprintf(stderr, "Error: Filesystem '%s' does not implement reading\n", argv[2]); + return 1; + } + + char msg[4096]; + sprintf(msg, "Error opening %s for reading", argv[4]); + FILE *f = fopen(argv[4], "rb"); + if (!f) { + perror(msg); + return 1; + } + io_generic io; + io.file = f; + io.procs = &stdio_ioprocs_noclose; + io.filler = 0xff; + + floppy_image image(84, 2, floppy_image::FF_UNKNOWN); + if(!format->load(&io, floppy_image::FF_UNKNOWN, variants, &image)) { + fprintf(stderr, "Error: parsing input file as '%s' failed\n", format->name()); + return 1; + } + + std::vector<u8> img; + auto iog = ram_open(img); + auto load_format = fs->m_type(); + load_format->save(iog, variants, &image); + delete load_format; + delete iog; + + fsblk_vec_t blockdev(img); + auto load_fs = fs->m_manager->mount(blockdev); + auto vmetad = fs->m_manager->volume_meta_description(); + auto vmeta = load_fs->metadata(); + + if(!vmeta.empty()) { + std::string vinf = "Volume:"; + for(const auto &e : vmetad) + vinf += util::string_format(" %s=%s", fs_meta_get_name(e.m_name), fs_meta_to_string(e.m_type, vmeta[e.m_name])); + printf("%s\n", vinf.c_str()); + } + + return 0; +} + + int CLIB_DECL main(int argc, char *argv[]) { init_formats(); @@ -506,6 +583,8 @@ int CLIB_DECL main(int argc, char *argv[]) return convert(argc, argv); else if (!core_stricmp("create", argv[1])) return create(argc, argv); + else if (!core_stricmp("dir", argv[1])) + return dir(argc, argv); else { fprintf(stderr, "Unknown command '%s'\n\n", argv[1]); display_usage(); |