summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Olivier Galibert <galibert@pobox.com>2021-04-28 22:58:51 +0200
committer Olivier Galibert <galibert@pobox.com>2021-04-28 22:58:57 +0200
commit18d1768325a37b3496a55a84698e7c7dc789e14c (patch)
treecdcbf932a7e76af7160b491ea050e39bc340228f
parent67d7e16274f71ab6fefeeedcaab12066d2a12668 (diff)
floppy: first steps on metadata, and hopefully make gcc happier on enumerate
-rw-r--r--src/devices/imagedev/floppy.cpp6
-rw-r--r--src/devices/imagedev/floppy.h2
-rw-r--r--src/frontend/mame/ui/floppycntrl.cpp12
-rw-r--r--src/lib/formats/fs_oric_jasmin.cpp55
-rw-r--r--src/lib/formats/fs_oric_jasmin.h13
-rw-r--r--src/lib/formats/fs_prodos.cpp32
-rw-r--r--src/lib/formats/fs_prodos.h11
-rw-r--r--src/lib/formats/fs_unformatted.cpp7
-rw-r--r--src/lib/formats/fs_unformatted.h3
-rw-r--r--src/lib/formats/fsmgr.cpp76
-rw-r--r--src/lib/formats/fsmgr.h70
-rw-r--r--src/tools/floptool.cpp91
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();