diff options
author | 2021-05-02 21:10:57 +0200 | |
---|---|---|
committer | 2021-05-02 21:24:45 +0200 | |
commit | ba6e0b72a7908309ce8c428ddbe59bf1f5f1ac52 (patch) | |
tree | 29b40fe78b76ff5e1dd85bdfcfb1a23602931171 /src/tools/floptool.cpp | |
parent | 0a8757673ff571dd6e47d9ee5b95c3745078b2db (diff) |
prodos: Start of read support
Diffstat (limited to 'src/tools/floptool.cpp')
-rw-r--r-- | src/tools/floptool.cpp | 199 |
1 files changed, 124 insertions, 75 deletions
diff --git a/src/tools/floptool.cpp b/src/tools/floptool.cpp index bc86393dc5e..0204feb0607 100644 --- a/src/tools/floptool.cpp +++ b/src/tools/floptool.cpp @@ -1,12 +1,8 @@ // license:BSD-3-Clause -// copyright-holders:Miodrag Milanovic +// copyright-holders:Olivier Galibert /*************************************************************************** - main.c - - Floptool command line front end - - 20/07/2011 Initial version by Miodrag Milanovic + (Floppy) image command-line manager ***************************************************************************/ @@ -274,11 +270,11 @@ static const fs_info *find_fs_by_name(const char *name) static void display_usage() { fprintf(stderr, "Usage: \n"); - 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 <image>\n"); - fprintf(stderr, " floptool.exe read input_format filesystem <image> <path> <outputfile>\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 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"); } static void display_formats() @@ -295,7 +291,7 @@ static void display_formats() sk = sz; } - fprintf(stderr, "Supported formats:\n\n"); + fprintf(stderr, "Supported floppy formats:\n\n"); for(const auto &e : formats_by_category) if(!e.second.empty()) { fprintf(stderr, "%s:\n", e.first.c_str()); @@ -304,7 +300,7 @@ static void display_formats() } fprintf(stderr, "\n\n"); - fprintf(stderr, "Supported filesystems:\n\n"); + fprintf(stderr, "Supported floppy filesystems:\n\n"); for(const auto &e : fs_by_category) if(!e.second.empty()) { fprintf(stderr, "%s:\n", e.first.c_str()); @@ -548,7 +544,63 @@ static void dir_scan(u32 depth, filesystem_t::dir_t dir, std::vector<std::vector } } -static int dir(int argc, char *argv[]) +static int generic_dir(const filesystem_manager_t *fm, fsblk_t &blockdev) +{ + 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 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\n", vinf.c_str()); + } + + std::vector<fs_meta_name> names; + names.push_back(fs_meta_name::name); + for(const auto &e : fmetad) + if(e.m_name != fs_meta_name::name) + names.push_back(e.m_name); + for(const auto &e : dmetad) + if(std::find(names.begin(), names.end(), e.m_name) == names.end()) + names.push_back(e.m_name); + + 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(); + std::vector<std::vector<std::string>> entries; + + entries.resize(1); + for(fs_meta_name n : names) + entries[0].push_back(fs_meta_get_name(n)); + + dir_scan(0, root, entries, nmap, names.size(), dmetad, fmetad); + + std::vector<u32> sizes(names.size()); + + for(const auto &e : entries) + for(unsigned int i=0; i != names.size(); i++) + sizes[i] = std::max<u32>(sizes[i], e[i].size()); + + for(const auto &e : entries) { + std::string l; + for(unsigned int i=0; i != names.size(); i++) { + if(i) + l += ' '; + l += util::string_format("%-*s", sizes[i], e[i]); + } + printf("%s\n", l.c_str()); + } + + return 0; +} + +static int flopdir(int argc, char *argv[]) { if (argc!=5) { fprintf(stderr, "Incorrect number of arguments.\n\n"); @@ -599,62 +651,52 @@ static int dir(int argc, char *argv[]) delete iog; fsblk_vec_t blockdev(img); - auto load_fs = fs->m_manager->mount(blockdev); - auto vmetad = fs->m_manager->volume_meta_description(); - auto fmetad = fs->m_manager->file_meta_description(); - auto dmetad = fs->m_manager->directory_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\n", vinf.c_str()); - } - - std::vector<fs_meta_name> names; - names.push_back(fs_meta_name::name); - for(const auto &e : fmetad) - if(e.m_name != fs_meta_name::name) - names.push_back(e.m_name); - for(const auto &e : dmetad) - if(std::find(names.begin(), names.end(), e.m_name) == names.end()) - names.push_back(e.m_name); - - std::unordered_map<fs_meta_name, size_t> nmap; - for(size_t i = 0; i != names.size(); i++) - nmap[names[i]] = i; + return generic_dir(fs->m_manager, blockdev); - auto root = load_fs->root(); - std::vector<std::vector<std::string>> entries; + return 0; +} - entries.resize(1); - for(fs_meta_name n : names) - entries[0].push_back(fs_meta_get_name(n)); +// Should use chd&friends instead, but one thing at a time - dir_scan(0, root, entries, nmap, names.size(), dmetad, fmetad); +static int hddir(int argc, char *argv[]) +{ + if (argc!=4) { + fprintf(stderr, "Incorrect number of arguments.\n\n"); + display_usage(); + return 1; + } - std::vector<u32> sizes(names.size()); + auto fs = find_fs_by_name(argv[2]); + if(!fs) { + fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[2]); + return 1; + } - for(const auto &e : entries) - for(unsigned int i=0; i != names.size(); i++) - sizes[i] = std::max<u32>(sizes[i], e[i].size()); + if(!fs->m_manager || !fs->m_manager->can_read()) { + fprintf(stderr, "Error: Filesystem '%s' does not implement reading\n", argv[2]); + return 1; + } - for(const auto &e : entries) { - std::string l; - for(unsigned int i=0; i != names.size(); i++) { - if(i) - l += ' '; - l += util::string_format("%-*s", sizes[i], e[i]); - } - printf("%s\n", l.c_str()); + char msg[4096]; + sprintf(msg, "Error opening %s for reading", argv[3]); + FILE *f = fopen(argv[3], "rb"); + if (!f) { + perror(msg); + return 1; } - - return 0; + 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 int doread(int argc, char *argv[]) +static int flopread(int argc, char *argv[]) { if (argc!=7) { fprintf(stderr, "Incorrect number of arguments.\n\n"); @@ -664,13 +706,13 @@ static int doread(int argc, char *argv[]) auto format = find_format_by_name(argv[2]); if(!format) { - fprintf(stderr, "Error: Format '%s' unknown\n", argv[3]); + fprintf(stderr, "Error: Format '%s' unknown\n", argv[2]); return 1; } auto fs = find_fs_by_name(argv[3]); if(!fs) { - fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[2]); + fprintf(stderr, "Error: Filesystem '%s' unknown\n", argv[3]); return 1; } @@ -777,19 +819,26 @@ int CLIB_DECL main(int argc, char *argv[]) return 0; } - 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("create", argv[1])) - return create(argc, argv); - else if (!core_stricmp("dir", argv[1])) - return dir(argc, argv); - else if (!core_stricmp("read", argv[1])) - return doread(argc, argv); - else { - fprintf(stderr, "Unknown command '%s'\n\n", argv[1]); - display_usage(); + try { + 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("create", argv[1])) + return create(argc, argv); + else if (!core_stricmp("flopdir", argv[1])) + return flopdir(argc, argv); + else if (!core_stricmp("flopread", argv[1])) + return flopread(argc, argv); + else if (!core_stricmp("hddir", argv[1])) + return hddir(argc, argv); + else { + fprintf(stderr, "Unknown command '%s'\n\n", argv[1]); + display_usage(); + return 1; + } + } catch(const emu_fatalerror &err) { + fprintf(stderr, "Error: %s", err.what()); return 1; } } |