summaryrefslogtreecommitdiffstatshomepage
path: root/src/tools/floptool.cpp
diff options
context:
space:
mode:
author Olivier Galibert <galibert@pobox.com>2021-05-23 19:11:45 +0200
committer Olivier Galibert <galibert@pobox.com>2021-05-24 14:06:06 +0200
commitda1bd3b0ec0a1f5f5999cd8a98de0e8d76dca48b (patch)
treeb587d2b61410be84111f6e2caf7289d93560d863 /src/tools/floptool.cpp
parent9508ac0530c0638b6595fb46d04cc3d62674d0c0 (diff)
reorganize the floptool code, add some write support
Diffstat (limited to 'src/tools/floptool.cpp')
-rw-r--r--src/tools/floptool.cpp953
1 files changed, 251 insertions, 702 deletions
diff --git a/src/tools/floptool.cpp b/src/tools/floptool.cpp
index bff08afb600..7cd7c2ad7f0 100644
--- a/src/tools/floptool.cpp
+++ b/src/tools/floptool.cpp
@@ -15,263 +15,16 @@
#include <cassert>
#include <map>
-#include "../emu/emucore.h"
+#include "image_handler.h"
#include "corestr.h"
-#include "osdcomm.h"
-
-using u8 = uint8_t;
-using u16 = uint16_t;
-using u32 = uint32_t;
-
-#include "formats/all.h"
-#include "formats/fs_unformatted.h"
-#include "formats/fsblk_vec.h"
-
-emu_fatalerror::emu_fatalerror(util::format_argument_pack<std::ostream> const &args)
- : emu_fatalerror(0, args)
-{
-}
-
-emu_fatalerror::emu_fatalerror(int _exitcode, util::format_argument_pack<std::ostream> const &args)
- : m_text(util::string_format(args))
- , m_code(_exitcode)
-{
-}
-
-struct fs_info {
- const filesystem_manager_t *m_manager;
- floppy_format_type m_type;
- u32 m_image_size;
- const char *m_name;
- u32 m_key;
- const char *m_description;
-
- fs_info(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, const char *description) :
- m_manager(manager),
- m_type(type),
- m_image_size(image_size),
- m_name(name),
- m_key(0),
- m_description(description)
- {}
-
- fs_info(const char *name, u32 key, const char *description) :
- m_manager(nullptr),
- m_type(nullptr),
- m_image_size(0),
- m_name(name),
- m_key(key),
- m_description(description)
- {}
-};
-
-struct iofile_ram {
- std::vector<u8> *data;
- int64_t pos;
-};
-
-static void ram_closeproc(void *file)
-{
- auto f = (iofile_ram *)file;
- delete f;
-}
-
-static int ram_seekproc(void *file, int64_t offset, int whence)
-{
- auto f = (iofile_ram *)file;
- switch(whence) {
- case SEEK_SET: f->pos = offset; break;
- case SEEK_CUR: f->pos += offset; break;
- case SEEK_END: f->pos = f->data->size() + offset; break;
- }
-
- if(whence == SEEK_CUR)
- f->pos = std::max<int64_t>(f->pos, 0);
- else
- f->pos = std::clamp<int64_t>(f->pos, 0, f->data->size());
- return 0;
-}
-
-static size_t ram_readproc(void *file, void *buffer, size_t length)
-{
- auto f = (iofile_ram *)file;
- size_t l = std::min<std::common_type_t<size_t, int64_t> >(length, f->data->size() - f->pos);
- memcpy(buffer, f->data->data() + f->pos, l);
- return l;
-}
-
-static size_t ram_writeproc(void *file, const void *buffer, size_t length)
-{
- auto f = (iofile_ram *)file;
- size_t l = std::max<std::common_type_t<size_t, int64_t> >(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)
-{
- auto f = (iofile_ram *)file;
- return f->data->size();
-}
-
-
-static const io_procs iop_ram = {
- ram_closeproc,
- ram_seekproc,
- ram_readproc,
- ram_writeproc,
- ram_filesizeproc
-};
-
-static io_generic *ram_open(std::vector<u8> &data)
-{
- iofile_ram *f = new iofile_ram;
- f->data = &data;
- f->pos = 0;
- return new io_generic({ &iop_ram, f });
-}
-
-std::map<std::string, std::vector<floppy_image_format_t *>> formats_by_category;
-std::map<std::string, floppy_image_format_t *> formats_by_key;
-
-std::map<std::string, std::vector<fs_info>> fs_by_category;
-std::map<std::string, fs_info> fs_by_key;
-
-static std::vector<uint32_t> variants;
-
-struct enumerator;
-
-struct fs_enum : public filesystem_manager_t::floppy_enumerator {
- enumerator *m_en;
- fs_enum(enumerator *en) : filesystem_manager_t::floppy_enumerator(), m_en(en) {};
-
- void reg(const fs_info &fsi) const;
- virtual void add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, const char *description) override;
- virtual void add_raw(const char *name, u32 key, const char *description) override;
-};
-
-struct enumerator : public mame_formats_enumerator {
- fs_enum fse;
-
- enumerator() : mame_formats_enumerator(), fse(this) {}
-
- virtual ~enumerator() = default;
- virtual void add(const cassette_image::Format *const *formats) {}
-
- std::vector<floppy_image_format_t *> *cf = nullptr;
- std::vector<fs_info> *cfs = nullptr;
- virtual void category(const char *name) {
- auto i = formats_by_category.find(name);
- if(i != formats_by_category.end()) {
- fprintf(stderr, "Collision on category name %s\n", name);
- exit(1);
- }
- cf = &formats_by_category[name];
- cfs = &fs_by_category[name];
- }
-
- virtual void add(floppy_format_type format) {
- auto f = format();
- std::string key = f->name();
- auto i = formats_by_key.find(key);
- if(i != formats_by_key.end()) {
- fprintf(stderr, "Collision on format key %s between \"%s\" and \"%s\".\n",
- key.c_str(),
- i->second->description(),
- f->description());
- exit(1);
- }
- cf->push_back(f);
- formats_by_key[key] = f;
- }
-
- virtual void add(filesystem_manager_type fs) {
- auto ff = fs();
- ff->enumerate_f(fse, floppy_image::FF_UNKNOWN, variants);
- }
-};
-
-void fs_enum::reg(const fs_info &fsi) const
-{
- std::string key = fsi.m_name;
- auto i = fs_by_key.find(key);
- if(i != fs_by_key.end()) {
- fprintf(stderr, "Collision on fs key %s between \"%s\" and \"%s\".\n",
- key.c_str(),
- i->second.m_description,
- fsi.m_description);
- exit(1);
- }
- m_en->cfs->push_back(fsi);
- fs_by_key.emplace(key, fsi);
-}
-
-void fs_enum::add(const filesystem_manager_t *manager, floppy_format_type type, u32 image_size, const char *name, const char *description)
-{
- fs_info fsi(manager, type, image_size, name, description);
- reg(fsi);
-}
-
-void fs_enum::add_raw(const char *name, u32 key, const char *description)
-{
- fs_info fsi(name, key, description);
- reg(fsi);
-}
-
-void CLIB_DECL ATTR_PRINTF(1,2) logerror(const char *format, ...)
-{
- va_list arg;
- va_start(arg, format);
- vprintf(format, arg);
- va_end(arg);
-}
-
-
-static void init_formats()
-{
- enumerator en;
- mame_formats_full_list(en);
-}
-
-static floppy_image_format_t *find_format_by_name(const char *name)
-{
- auto i = formats_by_key.find(name);
- if(i == formats_by_key.end())
- return nullptr;
- return i->second;
-}
-
-static floppy_image_format_t *find_format_by_identify(io_generic *image)
-{
- int best = 0;
- floppy_image_format_t *best_fif = nullptr;
-
- for(const auto &e : formats_by_key) {
- floppy_image_format_t *fif = e.second;
- int score = fif->identify(image, floppy_image::FF_UNKNOWN, variants);
- if(score > best) {
- best = score;
- best_fif = fif;
- }
- }
- return best_fif;
-}
-
-static const fs_info *find_fs_by_name(const char *name)
-{
- auto i = fs_by_key.find(name);
- if(i == fs_by_key.end())
- return nullptr;
- return &i->second;
-}
+static formats_table formats;
static void display_usage()
{
fprintf(stderr, "Usage: \n");
- fprintf(stderr, " floptool.exe identify <inputfile> [<inputfile> ...] -- Identify a floppy image format\n");
- fprintf(stderr, " floptool.exe convert [input_format|auto] output_format <inputfile> <outputfile> -- Convert a floppy image\n");
+ fprintf(stderr, " floptool.exe identify <inputfile> [<inputfile> ...] -- Identify an image format\n");
+ fprintf(stderr, " floptool.exe flopconvert [input_format|auto] output_format <inputfile> <outputfile> -- Convert a floppy image\n");
fprintf(stderr, " floptool.exe flopcreate output_format filesystem <outputfile> -- Create a preformatted floppy image\n");
fprintf(stderr, " floptool.exe flopdir input_format filesystem <image> -- List the contents of a floppy image\n");
fprintf(stderr, " floptool.exe flopread input_format filesystem <image> <path> <outputfile> -- Extract a file from a floppy image\n");
@@ -279,40 +32,56 @@ static void display_usage()
}
static void display_formats()
-{
+{
int sk = 0;
- for(const auto &e : formats_by_key) {
+ for(const auto &e : formats.floppy_format_info_by_key) {
+ int sz = e.first.size();
+ if(sz > sk)
+ sk = sz;
+ }
+
+ for(const auto &e : formats.filesystem_format_by_key) {
int sz = e.first.size();
if(sz > sk)
sk = sz;
}
- for(const auto &e : fs_by_key) {
+
+ for(const auto &e : formats.floppy_create_info_by_key) {
int sz = e.first.size();
if(sz > sk)
sk = sz;
}
fprintf(stderr, "Supported floppy formats:\n\n");
- for(const auto &e : formats_by_category)
+ for(const auto &e : formats.floppy_format_info_by_category)
if(!e.second.empty()) {
fprintf(stderr, "%s:\n", e.first.c_str());
- for(floppy_image_format_t *fif : e.second)
- fprintf(stderr, " %-*s - %s [%s]\n", sk, fif->name(), fif->description(), fif->extensions());
+ for(auto *fif : e.second)
+ fprintf(stderr, " %-*s r%c - %s [%s]\n", sk, fif->m_format->name(), fif->m_format->supports_save() ? 'w' : '-', fif->m_format->description(), fif->m_format->extensions());
}
fprintf(stderr, "\n\n");
- fprintf(stderr, "Supported floppy filesystems:\n\n");
- for(const auto &e : fs_by_category)
+ fprintf(stderr, "Supported filesystems (with floppy formatting names):\n\n");
+ for(const auto &e : formats.filesystem_format_by_category)
if(!e.second.empty()) {
fprintf(stderr, "%s:\n", e.first.c_str());
- for(const fs_info &fs : e.second)
- fprintf(stderr, " %-*s %c%c%c - %s\n",
+ for(const auto &f : e.second) {
+ fprintf(stderr, " %-*s %c%c%c %c%c%c - %s\n",
sk,
- fs.m_name,
- !fs.m_manager || fs.m_manager->can_format() ? 'f' : '-',
- fs.m_manager && fs.m_manager->can_read() ? 'r' : '-',
- fs.m_manager && fs.m_manager->can_write() ? 'w' : '-',
- fs.m_description);
+ f->m_manager->name(),
+ f->m_floppy || f->m_floppy_raw ? 'F' : '-',
+ f->m_hd ? 'H' : '-',
+ f->m_cd ? 'C' : '-',
+ f->m_manager->can_format() || f->m_floppy_raw ? 'f' : '-',
+ f->m_manager->can_read() ? 'r' : '-',
+ f->m_manager->can_write() ? 'w' : '-',
+ f->m_manager->description());
+ for(auto &f2 : f->m_floppy_create)
+ fprintf(stderr, " %-*s - %s\n",
+ sk,
+ f2->m_name,
+ f2->m_description);
+ }
}
}
@@ -323,177 +92,157 @@ static void display_full_usage()
display_usage();
fprintf(stderr, "\n");
display_formats();
- fprintf(stderr, "\nExample usage:\n");
- fprintf(stderr, " floptool.exe identify image.dsk\n\n");
}
static int identify(int argc, char *argv[])
{
- if (argc<3) {
+ // Need to detect CHDs too
+
+ if(argc<3) {
fprintf(stderr, "Missing name of file to identify.\n\n");
display_usage();
return 1;
}
+ int sz = 0;
for(int i=2; i<argc; i++) {
- char msg[4096];
- sprintf(msg, "Error opening %s for reading", argv[i]);
- FILE *f = fopen(argv[i], "rb");
- if (!f) {
- perror(msg);
- return 1;
+ int len = strlen(argv[i]);
+ if(len > sz)
+ sz = len;
+ }
+
+ for(int i=2; i<argc; i++) {
+ image_handler ih;
+ ih.set_on_disk_path(argv[i]);
+ auto scores = ih.identify(formats);
+ if(scores.empty())
+ printf("%-*s : Unknown format\n", sz, argv[i]);
+ int sz2 = 0;
+ for(const auto &e : scores) {
+ int len = strlen(e.second->m_format->name());
+ if(len > sz2)
+ sz2 = len;
+ }
+
+ bool first = true;
+ for(const auto &e : scores) {
+ printf("%-*s %c %3d - %-*s %s\n", sz, first ? argv[i] : "", first ? ':' : ' ', e.first, sz2, e.second->m_format->name(), e.second->m_format->description());
+ first = false;
}
- io_generic io;
- io.file = f;
- io.procs = &stdio_ioprocs_noclose;
- io.filler = 0xff;
-
- floppy_image_format_t *best_fif = find_format_by_identify(&io);
- if (best_fif)
- printf("%s : %s\n", argv[i], best_fif->description());
- else
- printf("%s : Unknown format\n", argv[i]);
- fclose(f);
}
return 0;
}
-static int convert(int argc, char *argv[])
+static const floppy_format_info *find_floppy_source_format(const char *name, image_handler &ih)
{
- if (argc!=6) {
- fprintf(stderr, "Incorrect number of arguments.\n\n");
- display_usage();
- return 1;
- }
-
- floppy_image_format_t *source_format, *dest_format;
-
- 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 source_io;
- source_io.file = f;
- source_io.procs = &stdio_ioprocs_noclose;
- source_io.filler = 0xff;
-
- if(!core_stricmp(argv[2], "auto")) {
- source_format = find_format_by_identify(&source_io);
- if(!source_format) {
- fprintf(stderr, "Error: Could not identify the format of file %s\n", argv[4]);
- return 1;
+ const floppy_format_info *source_format;
+ if(!core_stricmp(name, "auto")) {
+ auto scores = ih.identify(formats);
+ if(scores.empty()) {
+ fprintf(stderr, "Error: Could not identify the format of file %s\n", ih.get_on_disk_path().c_str());
+ return nullptr;
+ }
+ if(scores.size() >= 2 && scores[0].first == scores[1].first) {
+ fprintf(stderr, "Ambiguous source format. Possible formats:\n");
+ int sz = 0;
+ for(const auto &e : scores) {
+ int len = strlen(e.second->m_format->name());
+ if(len > sz)
+ sz = len;
+ }
+
+ for(const auto &e : scores)
+ printf(" %3d - %-*s %s\n", e.first, sz, e.second->m_format->name(), e.second->m_format->description());
+ return nullptr;
}
+ source_format = scores[0].second;
} else {
- source_format = find_format_by_name(argv[2]);
+ source_format = formats.find_floppy_format_info_by_key(name);
if(!source_format) {
- fprintf(stderr, "Error: Format '%s' unknown\n", argv[2]);
- return 1;
+ fprintf(stderr, "Error: Format '%s' unknown\n", name);
+ return nullptr;
+
}
}
+ return source_format;
+}
- dest_format = find_format_by_name(argv[3]);
- if(!dest_format) {
- fprintf(stderr, "Error: Format '%s' unknown\n", argv[3]);
+static int flopconvert(int argc, char *argv[])
+{
+ if(argc!=6) {
+ fprintf(stderr, "Incorrect number of arguments.\n\n");
+ display_usage();
return 1;
}
- if(!dest_format->supports_save()) {
- fprintf(stderr, "Error: saving to format '%s' unsupported\n", argv[3]);
+
+ image_handler ih;
+ ih.set_on_disk_path(argv[4]);
+
+ const floppy_format_info *source_format = find_floppy_source_format(argv[2], ih);
+ if(!source_format)
return 1;
- }
- sprintf(msg, "Error opening %s for writing", argv[5]);
- f = fopen(argv[5], "wb");
- if (!f) {
- perror(msg);
+ const floppy_format_info *dest_format = formats.find_floppy_format_info_by_key(argv[3]);
+ if(!dest_format) {
+ fprintf(stderr, "Error: Format '%s' unknown\n", argv[3]);
return 1;
}
- io_generic dest_io;
- dest_io.file = f;
- dest_io.procs = &stdio_ioprocs_noclose;
- dest_io.filler = 0xff;
-
- floppy_image image(84, 2, floppy_image::FF_UNKNOWN);
- if(!source_format->load(&source_io, floppy_image::FF_UNKNOWN, variants, &image)) {
- fprintf(stderr, "Error: parsing input file as '%s' failed\n", source_format->name());
+ if(!dest_format->m_format->supports_save()) {
+ fprintf(stderr, "Error: Aaving to format '%s' unsupported\n", argv[3]);
return 1;
}
- if(!dest_format->save(&dest_io, variants, &image)) {
- fprintf(stderr, "Error: writing output file as '%s' failed\n", dest_format->name());
+ if(ih.floppy_load(source_format)) {
+ fprintf(stderr, "Error: Loading as format '%s' failed\n", source_format->m_format->name());
return 1;
}
- fclose((FILE *)source_io.file);
- fclose((FILE *)dest_io.file);
+ ih.set_on_disk_path(argv[5]);
+
+ if(ih.floppy_save(dest_format)) {
+ fprintf(stderr, "Error: Saving as format '%s' failed\n", dest_format->m_format->name());
+ return 1;
+ }
return 0;
}
-static int create(int argc, char *argv[])
+static int flopcreate(int argc, char *argv[])
{
- if (argc!=5) {
+ if(argc!=5) {
fprintf(stderr, "Incorrect number of arguments.\n\n");
display_usage();
return 1;
}
- auto dest_format = find_format_by_name(argv[2]);
+ auto dest_format = formats.find_floppy_format_info_by_key(argv[2]);
if(!dest_format) {
- fprintf(stderr, "Error: Format '%s' unknown\n", argv[2]);
+ fprintf(stderr, "Error: Floppy format '%s' unknown\n", argv[3]);
return 1;
}
-
- auto source_fs = find_fs_by_name(argv[3]);
- if(!source_fs) {
- fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[3]);
+ if(!dest_format->m_format->supports_save()) {
+ fprintf(stderr, "Error: Saving to format '%s' unsupported\n", argv[3]);
return 1;
}
- floppy_image image(84, 2, floppy_image::FF_UNKNOWN);
-
- if(source_fs->m_type) {
- fs_meta_data meta;
-
- std::vector<u8> img(source_fs->m_image_size);
- fsblk_vec_t blockdev(img);
- auto fs = source_fs->m_manager->mount(blockdev);
- fs->format(meta);
-
- auto iog = ram_open(img);
- auto source_format = source_fs->m_type();
- source_format->load(iog, floppy_image::FF_UNKNOWN, variants, &image);
- delete source_format;
- delete iog;
-
- } else
- fs_unformatted::format(source_fs->m_key, &image);
-
- char msg[4096];
- sprintf(msg, "Error opening %s for writing", argv[4]);
- auto f = fopen(argv[4], "wb");
- if (!f) {
- perror(msg);
+ auto create_fs = formats.find_floppy_create_info_by_key(argv[3]);
+ if(!create_fs) {
+ fprintf(stderr, "Error: Floppy creation format '%s' unknown\n", argv[3]);
return 1;
}
-
- io_generic dest_io;
- dest_io.file = f;
- dest_io.procs = &stdio_ioprocs_noclose;
- dest_io.filler = 0xff;
-
- if(!dest_format->save(&dest_io, variants, &image)) {
- fprintf(stderr, "Error: writing output file as '%s' failed\n", dest_format->name());
+ if(!create_fs->m_manager->can_format()) {
+ fprintf(stderr, "Error: Floppy creation format '%s' does not support creating new images\n", argv[3]);
return 1;
}
- fclose((FILE *)dest_io.file);
+ fs_meta_data meta;
+ image_handler ih;
+ ih.set_on_disk_path(argv[4]);
- return 0;
+ ih.floppy_create(create_fs, meta);
+ return ih.floppy_save(dest_format);
}
static void dir_scan(u32 depth, filesystem_t::dir_t dir, std::vector<std::vector<std::string>> &entries, const std::unordered_map<fs_meta_name, size_t> &nmap, size_t nc, const std::vector<fs_meta_description> &dmetad, const std::vector<fs_meta_description> &fmetad)
@@ -541,14 +290,14 @@ static void dir_scan(u32 depth, filesystem_t::dir_t dir, std::vector<std::vector
}
}
-static int generic_dir(const filesystem_manager_t *fm, fsblk_t &blockdev)
+static int generic_dir(image_handler &ih)
{
- auto load_fs = fm->mount(blockdev);
- auto vmetad = fm->volume_meta_description();
- auto fmetad = fm->file_meta_description();
- auto dmetad = fm->directory_meta_description();
+ auto [fsm, fs] = ih.get_fs();
+ auto vmetad = fsm->volume_meta_description();
+ auto fmetad = fsm->file_meta_description();
+ auto dmetad = fsm->directory_meta_description();
- auto vmeta = load_fs->metadata();
+ auto vmeta = fs->metadata();
if(!vmeta.empty()) {
std::string vinf = "Volume:";
for(const auto &e : vmetad)
@@ -568,8 +317,8 @@ static int generic_dir(const filesystem_manager_t *fm, fsblk_t &blockdev)
std::unordered_map<fs_meta_name, size_t> nmap;
for(size_t i = 0; i != names.size(); i++)
nmap[names[i]] = i;
-
- auto root = load_fs->root();
+
+ auto root = fs->root();
std::vector<std::vector<std::string>> entries;
entries.resize(1);
@@ -599,69 +348,55 @@ static int generic_dir(const filesystem_manager_t *fm, fsblk_t &blockdev)
static int flopdir(int argc, char *argv[])
{
- if (argc!=5) {
+ 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[2]);
+ image_handler ih;
+ ih.set_on_disk_path(argv[4]);
+
+ const floppy_format_info *source_format = find_floppy_source_format(argv[2], ih);
+ if(!source_format)
return 1;
- }
- auto fs = find_fs_by_name(argv[3]);
+ auto fs = formats.find_filesystem_format_by_key(argv[3]);
if(!fs) {
fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[3]);
return 1;
}
if(!fs->m_manager || !fs->m_manager->can_read()) {
- fprintf(stderr, "Error: Filesystem '%s' does not implement reading\n", argv[2]);
+ fprintf(stderr, "Error: Filesystem '%s' does not implement reading\n", argv[3]);
return 1;
}
- char msg[4096];
- sprintf(msg, "Error opening %s for reading", argv[4]);
- FILE *f = fopen(argv[4], "rb");
- if (!f) {
- perror(msg);
+ if(ih.floppy_load(source_format)) {
+ fprintf(stderr, "Error: Loading as format '%s' failed\n", source_format->m_format->name());
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());
+
+ if(ih.floppy_mount_fs(fs)) {
+ fprintf(stderr, "Error: Parsing as filesystem '%s' failed\n", fs->m_manager->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);
- return generic_dir(fs->m_manager, blockdev);
+ return generic_dir(ih);
}
-// Should use chd&friends instead, but one thing at a time
-
static int hddir(int argc, char *argv[])
{
- if (argc!=4) {
+ if(argc!=4) {
fprintf(stderr, "Incorrect number of arguments.\n\n");
display_usage();
return 1;
}
- auto fs = find_fs_by_name(argv[2]);
+ image_handler ih;
+ ih.set_on_disk_path(argv[3]);
+
+ auto fs = formats.find_filesystem_format_by_key(argv[2]);
if(!fs) {
fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[2]);
return 1;
@@ -672,114 +407,22 @@ static int hddir(int argc, char *argv[])
return 1;
}
- char msg[4096];
- sprintf(msg, "Error opening %s for reading", argv[3]);
- FILE *f = fopen(argv[3], "rb");
- if (!f) {
- perror(msg);
+ if(ih.hd_mount_fs(fs)) {
+ fprintf(stderr, "Error: Parsing as filesystem '%s' failed\n", fs->m_manager->name());
return 1;
}
- fseek(f, 0, SEEK_END);
- size_t size = ftell(f);
- rewind(f);
- std::vector<u8> img(size);
- fread(img.data(), size, 1, f);
- fclose(f);
-
- fsblk_vec_t blockdev(img);
- return generic_dir(fs->m_manager, blockdev);
-}
-
-static std::vector<std::string> path_split(const filesystem_manager_t *fm, std::string path)
-{
- std::string opath = path;
- std::vector<std::string> rpath;
- if(fm->has_subdirectories()) {
- std::string element;
- char sep = fm->directory_separator();
- for(char c : opath) {
- if(c == sep) {
- if(!element.empty()) {
- rpath.push_back(element);
- element.clear();
- }
- } else
- element += c;
- }
- if(!element.empty())
- rpath.push_back(element);
-
- } else
- rpath.push_back(opath);
-
- return rpath;
-}
-
-static std::vector<u8> fload(std::string path)
-{
- char msg[4096];
- sprintf(msg, "Error opening %s for reading", path.c_str());
- auto fi = fopen(path.c_str(), "rb");
- if (!fi) {
- perror(msg);
- exit(1);
- }
- fseek(fi, 0, SEEK_END);
- long size = ftell(fi);
- std::vector<u8> filedata(size);
- fseek(fi, 0, SEEK_SET);
- fread(filedata.data(), filedata.size(), 1, fi);
- fclose(fi);
-
- return filedata;
-}
-
-static void fsave(std::string path, const std::vector<u8> &data)
-{
- char msg[4096];
- sprintf(msg, "Error opening %s for writing", path.c_str());
- auto fo = fopen(path.c_str(), "wb");
- if (!fo) {
- perror(msg);
- exit(1);
- }
-
- fwrite(data.data(), data.size(), 1, fo);
- fclose(fo);
-}
-
-static bool fexists(std::string path)
-{
- auto f = fopen(path.c_str(), "rb");
- if(f != nullptr) {
- fclose(f);
- return true;
- }
- return false;
-}
-
-
-static std::string path_make_rsrc(std::string path)
-{
- auto p = path.end();
- while(p != path.begin() && p[-1] != '/')
- p--;
- std::string rpath(path.begin(), p);
- rpath += "._";
- rpath += std::string(p, path.end());
- return rpath;
+ return generic_dir(ih);
}
-
-static int generic_read(const filesystem_manager_t *fm, fsblk_t &blockdev, const char *srcpath, const char *dstpath)
+static int generic_read(image_handler &ih, const char *srcpath, const char *dstpath)
{
- auto load_fs = fm->mount(blockdev);
+ auto [fsm, fs] = ih.get_fs();
- std::vector<std::string> path = path_split(fm, srcpath);
+ std::vector<std::string> path = ih.path_split(srcpath);
- auto dir = load_fs->root();
+ auto dir = fs->root();
std::string apath;
for(unsigned int i = 0; i < path.size() - 1; i++) {
auto c = dir.contents();
@@ -788,15 +431,15 @@ static int generic_read(const filesystem_manager_t *fm, fsblk_t &blockdev, const
if(c[j].m_name == path[i])
break;
if(j == c.size()) {
- fprintf(stderr, "Error: directory %s%c%s not found\n", apath.c_str(), fm->directory_separator(), path[i].c_str());
+ fprintf(stderr, "Error: directory %s%c%s not found\n", apath.c_str(), fsm->directory_separator(), path[i].c_str());
return 1;
}
if(c[j].m_type != fs_dir_entry_type::dir) {
- fprintf(stderr, "Error: %s%c%s is not a directory\n", apath.c_str(), fm->directory_separator(), path[i].c_str());
+ fprintf(stderr, "Error: %s%c%s is not a directory\n", apath.c_str(), fsm->directory_separator(), path[i].c_str());
return 1;
}
dir = dir.dir_get(c[j].m_key);
- apath += fm->directory_separator() + path[i];
+ apath += fsm->directory_separator() + path[i];
}
auto c = dir.contents();
@@ -805,38 +448,23 @@ static int generic_read(const filesystem_manager_t *fm, fsblk_t &blockdev, const
if(c[j].m_name == path.back())
break;
if(j == c.size()) {
- fprintf(stderr, "Error: file %s%c%s not found\n", apath.c_str(), fm->directory_separator(), path.back().c_str());
+ fprintf(stderr, "Error: file %s%c%s not found\n", apath.c_str(), fsm->directory_separator(), path.back().c_str());
return 1;
}
auto file = dir.file_get(c[j].m_key);
auto meta = file.metadata();
if(!meta.has(fs_meta_name::length)) {
- fprintf(stderr, "Error: %s%c%s is not a readable file\n", apath.c_str(), fm->directory_separator(), path.back().c_str());
+ fprintf(stderr, "Error: %s%c%s is not a readable file\n", apath.c_str(), fsm->directory_separator(), path.back().c_str());
return 1;
}
- fsave(dstpath, file.read_all());
-
- bool has_rsrc = fm->has_rsrc() && meta.has(fs_meta_name::rsrc_length);
-
- if(has_rsrc) {
- std::string rpath = path_make_rsrc(dstpath);
-
- auto filedata = file.rsrc_read_all();
- filedata.insert(filedata.begin(), 0x2a, 0);
+ image_handler::fsave(dstpath, file.read_all());
- u8 *head = filedata.data();
- filesystem_t::w32b(head+0x00, 0x00051607); // Magic
- filesystem_t::w32b(head+0x04, 0x00020000); // Version
- filesystem_t::fill(head+0x08, 0, 16); // Filler
- filesystem_t::w16b(head+0x18, 1); // Number of entries
- filesystem_t::w32b(head+0x1a, 2); // Resource fork
- filesystem_t::w32b(head+0x22, 0x2a); // Offset in the file
- filesystem_t::w32b(head+0x26, filedata.size()); // Length
+ bool has_rsrc = fsm->has_rsrc() && meta.has(fs_meta_name::rsrc_length);
- fsave(rpath, filedata);
- }
+ if(has_rsrc)
+ image_handler::fsave_rsrc(image_handler::path_make_rsrc(dstpath), file.rsrc_read_all());
return 0;
}
@@ -844,70 +472,55 @@ static int generic_read(const filesystem_manager_t *fm, fsblk_t &blockdev, const
static int flopread(int argc, char *argv[])
{
- if (argc!=7) {
+ if(argc!=7) {
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[2]);
+ image_handler ih;
+ ih.set_on_disk_path(argv[4]);
+
+ const floppy_format_info *source_format = find_floppy_source_format(argv[2], ih);
+ if(!source_format)
return 1;
- }
- auto fs = find_fs_by_name(argv[3]);
+ auto fs = formats.find_filesystem_format_by_key(argv[3]);
if(!fs) {
fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[3]);
return 1;
}
if(!fs->m_manager || !fs->m_manager->can_read()) {
- fprintf(stderr, "Error: Filesystem '%s' does not implement reading\n", argv[2]);
+ fprintf(stderr, "Error: Filesystem '%s' does not implement reading\n", argv[3]);
return 1;
}
- char msg[4096];
- sprintf(msg, "Error opening %s for reading", argv[4]);
- FILE *f = fopen(argv[4], "rb");
- if (!f) {
- perror(msg);
+ if(ih.floppy_load(source_format)) {
+ fprintf(stderr, "Error: Loading as format '%s' failed\n", source_format->m_format->name());
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());
+
+ if(ih.floppy_mount_fs(fs)) {
+ fprintf(stderr, "Error: Parsing as filesystem '%s' failed\n", fs->m_manager->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);
- return generic_read(fs->m_manager, blockdev, argv[5], argv[6]);
+ return generic_read(ih, argv[5], argv[6]);
}
-
-// Should use chd&friends instead, but one thing at a time
-
static int hdread(int argc, char *argv[])
{
- if (argc!=6) {
+ if(argc!=6) {
fprintf(stderr, "Incorrect number of arguments.\n\n");
display_usage();
return 1;
}
- auto fs = find_fs_by_name(argv[2]);
+ image_handler ih;
+ ih.set_on_disk_path(argv[3]);
+
+ auto fs = formats.find_filesystem_format_by_key(argv[2]);
if(!fs) {
fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[2]);
return 1;
@@ -918,33 +531,23 @@ static int hdread(int argc, char *argv[])
return 1;
}
- char msg[4096];
- sprintf(msg, "Error opening %s for reading", argv[3]);
- FILE *f = fopen(argv[3], "rb");
- if (!f) {
- perror(msg);
+ if(ih.hd_mount_fs(fs)) {
+ fprintf(stderr, "Error: Parsing as filesystem '%s' failed\n", fs->m_manager->name());
return 1;
}
- fseek(f, 0, SEEK_END);
- size_t size = ftell(f);
- rewind(f);
- std::vector<u8> img(size);
- fread(img.data(), size, 1, f);
- fclose(f);
-
- fsblk_vec_t blockdev(img);
- return generic_read(fs->m_manager, blockdev, argv[4], argv[5]);
+
+ return generic_read(ih, argv[4], argv[5]);
}
-static int generic_write(const filesystem_manager_t *fm, fsblk_t &blockdev, const char *srcpath, const char *dstpath)
+static int generic_write(image_handler &ih, const char *srcpath, const char *dstpath)
{
- auto load_fs = fm->mount(blockdev);
+ auto [fsm, fs] = ih.get_fs();
- std::vector<std::string> path = path_split(fm, dstpath);
+ std::vector<std::string> path = ih.path_split(dstpath);
- auto dir = load_fs->root();
+ auto dir = fs->root();
std::string apath;
for(unsigned int i = 0; i < path.size() - 1; i++) {
auto c = dir.contents();
@@ -953,15 +556,15 @@ static int generic_write(const filesystem_manager_t *fm, fsblk_t &blockdev, cons
if(c[j].m_name == path[i])
break;
if(j == c.size()) {
- fprintf(stderr, "Error: directory %s%c%s not found\n", apath.c_str(), fm->directory_separator(), path[i].c_str());
+ fprintf(stderr, "Error: directory %s%c%s not found\n", apath.c_str(), fsm->directory_separator(), path[i].c_str());
return 1;
}
if(c[j].m_type != fs_dir_entry_type::dir) {
- fprintf(stderr, "Error: %s%c%s is not a directory\n", apath.c_str(), fm->directory_separator(), path[i].c_str());
+ fprintf(stderr, "Error: %s%c%s is not a directory\n", apath.c_str(), fsm->directory_separator(), path[i].c_str());
return 1;
}
dir = dir.dir_get(c[j].m_key);
- apath += fm->directory_separator() + path[i];
+ apath += fsm->directory_separator() + path[i];
}
@@ -969,33 +572,18 @@ static int generic_write(const filesystem_manager_t *fm, fsblk_t &blockdev, cons
meta.set(fs_meta_name::name, path.back());
auto file = dir.file_create(meta);
- auto filedata = fload(srcpath);
+ auto filedata = image_handler::fload(srcpath);
file.replace(filedata);
- bool has_rsrc = fm->has_rsrc();
+ bool has_rsrc = fsm->has_rsrc();
if(has_rsrc) {
- std::string rpath = path_make_rsrc(dstpath);
-
- if(fexists(rpath)) {
- filedata = fload(rpath);
- const u8 *head = filedata.data();
-
- if(filesystem_t::r32b(head+0x00) == 0x00051607 &&
- filesystem_t::r32b(head+0x04) == 0x00020000) {
- u16 nent = filesystem_t::r16b(head+0x18);
- for(u16 i=0; i != nent; i++) {
- const u8 *e = head + 12*i;
- if(filesystem_t::r32b(e+0) == 2) {
- u32 start = filesystem_t::r32b(e+4);
- u32 len = filesystem_t::r32b(e+8);
- filedata.erase(filedata.begin(), filedata.begin() + start);
- filedata.erase(filedata.begin() + len, filedata.end());
- file.rsrc_replace(filedata);
- break;
- }
- }
- }
+ std::string rpath = image_handler::path_make_rsrc(dstpath);
+
+ if(image_handler::fexists(rpath)) {
+ filedata = image_handler::fload_rsrc(rpath);
+ if(!filedata.empty())
+ file.rsrc_replace(filedata);
}
}
@@ -1005,92 +593,64 @@ static int generic_write(const filesystem_manager_t *fm, fsblk_t &blockdev, cons
static int flopwrite(int argc, char *argv[])
{
- if (argc!=7) {
+ if(argc!=7) {
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[2]);
+ image_handler ih;
+ ih.set_on_disk_path(argv[4]);
+
+ const floppy_format_info *source_format = find_floppy_source_format(argv[2], ih);
+ if(!source_format)
return 1;
- }
- auto fs = find_fs_by_name(argv[3]);
+ auto fs = formats.find_filesystem_format_by_key(argv[3]);
if(!fs) {
fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[3]);
return 1;
}
if(!fs->m_manager || !fs->m_manager->can_read()) {
- fprintf(stderr, "Error: Filesystem '%s' does not implement reading\n", argv[2]);
+ fprintf(stderr, "Error: Filesystem '%s' does not implement reading\n", argv[3]);
return 1;
}
- char msg[4096];
- sprintf(msg, "Error opening %s for reading", argv[4]);
- FILE *f = fopen(argv[4], "rb");
- if (!f) {
- perror(msg);
+ if(ih.floppy_load(source_format)) {
+ fprintf(stderr, "Error: Loading as format '%s' failed\n", source_format->m_format->name());
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);
- fsblk_vec_t blockdev(img);
- generic_write(fs->m_manager, blockdev, argv[5], argv[6]);
-
- load_format->load(iog, image.get_form_factor(), variants, &image);
- delete load_format;
- delete iog;
-
- sprintf(msg, "Error oapening %s for writing", argv[4]);
- f = fopen(argv[4], "wb");
- if (!f) {
- perror(msg);
+ if(ih.floppy_mount_fs(fs)) {
+ fprintf(stderr, "Error: Parsing as filesystem '%s' failed\n", fs->m_manager->name());
return 1;
}
+
+ int err = generic_write(ih, argv[5], argv[6]);
+ if(err)
+ return err;
- io_generic dest_io;
- dest_io.file = f;
- dest_io.procs = &stdio_ioprocs_noclose;
- dest_io.filler = 0xff;
-
- if(!format->save(&dest_io, variants, &image)) {
- fprintf(stderr, "Error: writing output file as '%s' failed\n", format->name());
+ ih.fs_to_floppy();
+ if(ih.floppy_save(source_format))
return 1;
- }
-
- fclose((FILE *)dest_io.file);
+
return 0;
}
-
-// Should use chd&friends instead, but one thing at a time
-
static int hdwrite(int argc, char *argv[])
{
- if (argc!=6) {
+ if(argc!=6) {
fprintf(stderr, "Incorrect number of arguments.\n\n");
display_usage();
return 1;
}
- auto fs = find_fs_by_name(argv[2]);
+
+ image_handler ih;
+ ih.set_on_disk_path(argv[3]);
+
+ auto fs = formats.find_filesystem_format_by_key(argv[2]);
if(!fs) {
fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[2]);
return 1;
@@ -1101,52 +661,41 @@ static int hdwrite(int argc, char *argv[])
return 1;
}
- char msg[4096];
- sprintf(msg, "Error opening %s for reading", argv[3]);
- FILE *f = fopen(argv[3], "rb");
- if (!f) {
- perror(msg);
+ if(ih.hd_mount_fs(fs)) {
+ fprintf(stderr, "Error: Parsing as filesystem '%s' failed\n", fs->m_manager->name());
return 1;
}
- fseek(f, 0, SEEK_END);
- size_t size = ftell(f);
- rewind(f);
- std::vector<u8> img(size);
- fread(img.data(), size, 1, f);
- fclose(f);
-
- fsblk_vec_t blockdev(img);
- return generic_write(fs->m_manager, blockdev, argv[4], argv[5]);
-}
+ return generic_write(ih, argv[4], argv[5]);
+}
int CLIB_DECL main(int argc, char *argv[])
{
- init_formats();
+ formats.init();
- if (argc == 1) {
+ if(argc == 1) {
display_full_usage();
return 0;
}
try {
- if (!core_stricmp("identify", argv[1]))
+ if(!core_stricmp("identify", argv[1]))
return identify(argc, argv);
- else if (!core_stricmp("convert", argv[1]))
- return convert(argc, argv);
- else if (!core_stricmp("flopcreate", argv[1]))
- return create(argc, argv);
- else if (!core_stricmp("flopdir", argv[1]))
+ else if(!core_stricmp("flopconvert", argv[1]))
+ return flopconvert(argc, argv);
+ else if(!core_stricmp("flopcreate", argv[1]))
+ return flopcreate(argc, argv);
+ else if(!core_stricmp("flopdir", argv[1]))
return flopdir(argc, argv);
- else if (!core_stricmp("flopread", argv[1]))
+ else if(!core_stricmp("flopread", argv[1]))
return flopread(argc, argv);
- else if (!core_stricmp("flopwrite", argv[1]))
+ else if(!core_stricmp("flopwrite", argv[1]))
return flopwrite(argc, argv);
- else if (!core_stricmp("hddir", argv[1]))
+ else if(!core_stricmp("hddir", argv[1]))
return hddir(argc, argv);
- else if (!core_stricmp("hdread", argv[1]))
+ else if(!core_stricmp("hdread", argv[1]))
return hdread(argc, argv);
- else if (!core_stricmp("hdwrite", argv[1]))
+ else if(!core_stricmp("hdwrite", argv[1]))
return hdwrite(argc, argv);
else {
fprintf(stderr, "Unknown command '%s'\n\n", argv[1]);