diff options
author | 2021-08-22 09:06:15 +1000 | |
---|---|---|
committer | 2021-08-22 09:06:15 +1000 | |
commit | e8bbea1fc6e94e14768509d322f6c624403ffb36 (patch) | |
tree | 74dd1606a900d83de8aecff17a6737af4113308d /src/lib/formats/acorn_dsk.cpp | |
parent | e319bde5fc3696d7f48f62b15b6366c4377fe5d1 (diff) |
formats, osd, util: Started refactoring file I/O stuff. (#8456)
Added more modern generic I/O interfaces with implementation backed by stdio, osd_file and core_file, replacing io_generic. Also replaced core_file's build-in zlib compression with a filter.
unzip.cpp, un7z.cpp: Added option to supply abstract I/O interface rather than filename.
Converted osd_file, core_file, archive_file, chd_file and device_image_interface to use std::error_condition rather than their own error enums.
Allow mounting TI-99 RPK from inside archives.
Diffstat (limited to 'src/lib/formats/acorn_dsk.cpp')
-rw-r--r-- | src/lib/formats/acorn_dsk.cpp | 216 |
1 files changed, 143 insertions, 73 deletions
diff --git a/src/lib/formats/acorn_dsk.cpp b/src/lib/formats/acorn_dsk.cpp index c4668478b05..40ab6eb1029 100644 --- a/src/lib/formats/acorn_dsk.cpp +++ b/src/lib/formats/acorn_dsk.cpp @@ -10,6 +10,9 @@ #include "acorn_dsk.h" +#include "ioprocs.h" + + acorn_ssd_format::acorn_ssd_format() : wd177x_format(formats) { } @@ -29,29 +32,36 @@ const char *acorn_ssd_format::extensions() const return "ssd,bbc,img"; } -int acorn_ssd_format::find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) +int acorn_ssd_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) { uint8_t cat[8]; uint32_t sectors0, sectors2; - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + { + LOG_FORMATS("ssd: error getting image size\n"); + return -1; + } - for(int i=0; formats[i].form_factor; i++) { + for (int i=0; formats[i].form_factor; i++) + { + size_t actual; const format &f = formats[i]; - if(form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) + if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) continue; // test for Torch CPN - test pattern at sector &0018 - io_generic_read(io, cat, 0x32800, 8); + io.read_at(0x32800, cat, 8, actual); if (memcmp(cat, "\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd", 4) == 0 && size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count) return i; // test for HADFS - test pattern at sector 70 - io_generic_read(io, cat, 0x04610, 8); + io.read_at(0x04610, cat, 8, actual); if (memcmp(cat, "\x00\x28\x43\x29\x4a\x47\x48\x00", 4) == 0 && size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count) return i; // test for Kenda SD - offset &0962 = 0 SD/1 DD, offset &0963 = disk size blocks / 4 (block size = 1K, ie. 0x400 bytes), reserved tracks = 3, ie. 0x1e00 bytes, soft stagger = 2 sectors, ie. 0x200 bytes - io_generic_read(io, cat, 0x0960, 8); + io.read_at(0x0960, cat, 8, actual); if (cat[2] == 0 && ((uint64_t)cat[3] * 4 * 0x400 + 0x2000) == size && size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count) { // valid blocks for single sided @@ -63,20 +73,22 @@ int acorn_ssd_format::find_size(io_generic *io, uint32_t form_factor, const std: } // read sector count from side 0 catalogue - io_generic_read(io, cat, 0x100, 8); + io.read_at(0x100, cat, 8, actual); sectors0 = ((cat[6] & 3) << 8) + cat[7]; LOG_FORMATS("ssd: sector count 0: %d %s\n", sectors0, sectors0 % 10 != 0 ? "invalid" : ""); - if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (sectors0 <= f.track_count * f.sector_count)) { + if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (sectors0 <= f.track_count * f.sector_count)) + { if (f.head_count == 2) { // read sector count from side 2 catalogue - io_generic_read(io, cat, (uint64_t)compute_track_size(f) * f.track_count + 0x100, 8); // sequential + io.read_at((uint64_t)compute_track_size(f) * f.track_count + 0x100, cat, 8, actual); // sequential sectors2 = ((cat[6] & 3) << 8) + cat[7]; // exception case for Acorn CP/M System Disc 1 - io_generic_read(io, cat, 0x367ec, 8); - if (memcmp(cat, "/M ", 4) == 0) sectors2 = ((cat[6] & 3) << 8) + cat[7]; + io.read_at(0x367ec, cat, 8, actual); + if (memcmp(cat, "/M ", 4) == 0) + sectors2 = ((cat[6] & 3) << 8) + cat[7]; LOG_FORMATS("ssd: sector count 2: %d %s\n", sectors2, sectors2 % 10 != 0 ? "invalid" : ""); } @@ -93,12 +105,13 @@ int acorn_ssd_format::find_size(io_generic *io, uint32_t form_factor, const std: return -1; } -int acorn_ssd_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) +int acorn_ssd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) { int type = find_size(io, form_factor, variants); - if(type != -1) + if (type != -1) return 90; + return 0; } @@ -171,40 +184,49 @@ const char *acorn_dsd_format::extensions() const return "dsd"; } -int acorn_dsd_format::find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) +int acorn_dsd_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) { uint8_t cat[8]; uint32_t sectors0, sectors2; - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + { + LOG_FORMATS("dsd: error getting image size\n"); + return -1; + } - for (int i = 0; formats[i].form_factor; i++) { + for (int i = 0; formats[i].form_factor; i++) + { + size_t actual; const format &f = formats[i]; if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) continue; // test for Torch CPN - test pattern at sector &0018 - io_generic_read(io, cat, 0x1200, 8); + io.read_at(0x1200, cat, 8, actual); if (memcmp(cat, "\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd", 4) == 0 && size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count) return i; // test for HADFS - test pattern at sector 70 - io_generic_read(io, cat, 0x08c10, 8); + io.read_at(0x08c10, cat, 8, actual); if (memcmp(cat, "\x00\x28\x43\x29\x4a\x47\x48\x00", 4) == 0 && size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count) return i; // read sector count from side 0 catalogue - io_generic_read(io, cat, 0x100, 8); + io.read_at(0x100, cat, 8, actual); sectors0 = ((cat[6] & 3) << 8) + cat[7]; LOG_FORMATS("dsd: sector count 0: %d %s\n", sectors0, sectors0 % 10 != 0 ? "invalid" : ""); - if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (sectors0 <= f.track_count * f.sector_count)) { + if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (sectors0 <= f.track_count * f.sector_count)) + { // read sector count from side 2 catalogue - io_generic_read(io, cat, 0xb00, 8); // interleaved + io.read_at(0xb00, cat, 8, actual); // interleaved sectors2 = ((cat[6] & 3) << 8) + cat[7]; // exception case for Acorn CP/M System Disc 1 - io_generic_read(io, cat, 0x97ec, 8); - if (memcmp(cat, "/M ", 4) == 0) sectors2 = ((cat[6] & 3) << 8) + cat[7]; + io.read_at(0x97ec, cat, 8, actual); + if (memcmp(cat, "/M ", 4) == 0) + sectors2 = ((cat[6] & 3) << 8) + cat[7]; LOG_FORMATS("dsd: sector count 2: %d %s\n", sectors2, sectors2 % 10 != 0 ? "invalid" : ""); @@ -216,12 +238,13 @@ int acorn_dsd_format::find_size(io_generic *io, uint32_t form_factor, const std: return -1; } -int acorn_dsd_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) +int acorn_dsd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) { int type = find_size(io, form_factor, variants); if (type != -1) return 90; + return 0; } @@ -274,27 +297,36 @@ const char *opus_ddos_format::extensions() const return "dds"; } -int opus_ddos_format::find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) +int opus_ddos_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) { + size_t actual; uint8_t cat[8]; uint32_t sectors0, sectors2; // read sector count from side 0 catalogue - io_generic_read(io, cat, 0x1000, 8); + io.read_at(0x1000, cat, 8, actual); sectors0 = (cat[1] << 8) + cat[2]; LOG_FORMATS("ddos: sector count 0: %d %s\n", sectors0, sectors0 % 18 != 0 ? "invalid" : ""); - uint64_t size = io_generic_size(io); - for (int i = 0; formats[i].form_factor; i++) { + uint64_t size; + if (io.length(size)) + { + LOG_FORMATS("ddos: error getting image size\n"); + return -1; + } + + for (int i = 0; formats[i].form_factor; i++) + { const format &f = formats[i]; if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) continue; - if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (sectors0 <= f.track_count * f.sector_count)) { + if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (sectors0 <= f.track_count * f.sector_count)) + { if (f.head_count == 2) { // read sector count from side 2 catalogue - io_generic_read(io, cat, (uint64_t)compute_track_size(f) * f.track_count + 0x1000, 8); // sequential + io.read_at((uint64_t)compute_track_size(f) * f.track_count + 0x1000, cat, 8, actual); // sequential sectors2 = (cat[1] << 8) + cat[2]; LOG_FORMATS("ddos: sector count 2: %d %s\n", sectors2, sectors2 % 18 != 0 ? "invalid" : ""); } @@ -311,12 +343,13 @@ int opus_ddos_format::find_size(io_generic *io, uint32_t form_factor, const std: return -1; } -int opus_ddos_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) +int opus_ddos_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) { int type = find_size(io, form_factor, variants); if (type != -1) return 90; + return 0; } @@ -369,25 +402,33 @@ const char *acorn_adfs_old_format::extensions() const return "adf,ads,adm,adl"; } -int acorn_adfs_old_format::find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) +int acorn_adfs_old_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) { + size_t actual; uint8_t map[3]; uint32_t sectors; uint8_t oldmap[4]; // read sector count from free space map - io_generic_read(io, map, 0xfc, 3); + io.read_at(0xfc, map, 3, actual); sectors = map[0] + (map[1] << 8) + (map[2] << 16); LOG_FORMATS("adfs_o: sector count %d %s\n", sectors, sectors % 16 != 0 ? "invalid" : ""); // read map identifier - io_generic_read(io, oldmap, 0x201, 4); + io.read_at(0x201, oldmap, 4, actual); LOG_FORMATS("adfs_o: map identifier %s %s\n", oldmap, memcmp(oldmap, "Hugo", 4) != 0 ? "invalid" : ""); - uint64_t size = io_generic_size(io); - for(int i=0; formats[i].form_factor; i++) { + uint64_t size; + if (io.length(size)) + { + LOG_FORMATS("adfs_o: error getting image size\n"); + return -1; + } + + for (int i=0; formats[i].form_factor; i++) + { const format &f = formats[i]; - if(form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) + if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) continue; // valid images will have map identifier 'Hugo' and sector counts adfs-s = 0x280; adfs-m = 0x500; adfs-l = 0xa00; adfs-dos = 0xaa0; though many adfs-s images are incorrect @@ -399,12 +440,13 @@ int acorn_adfs_old_format::find_size(io_generic *io, uint32_t form_factor, const return -1; } -int acorn_adfs_old_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) +int acorn_adfs_old_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) { int type = find_size(io, form_factor, variants); if(type != -1) return 100; + return 0; } @@ -465,43 +507,50 @@ const char *acorn_adfs_new_format::extensions() const return "adf"; } -int acorn_adfs_new_format::find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) +int acorn_adfs_new_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) { + size_t actual; uint8_t dform[4]; uint8_t eform[4]; // read map identifiers for D and E formats - io_generic_read(io, dform, 0x401, 4); + io.read_at(0x401, dform, 4, actual); LOG_FORMATS("adfs_n: map identifier (D format) %s %s\n", dform, (memcmp(dform, "Hugo", 4) != 0 && memcmp(dform, "Nick", 4) != 0) ? "invalid" : ""); - io_generic_read(io, eform, 0x801, 4); + io.read_at(0x801, eform, 4, actual); LOG_FORMATS("adfs_n: map identifier (E format) %s %s\n", eform, memcmp(eform, "Nick", 4) != 0 ? "invalid" : ""); - uint64_t size = io_generic_size(io); - for (int i = 0; formats[i].form_factor; i++) { + uint64_t size; + if (io.length(size)) + { + LOG_FORMATS("adfs_n: error getting image size\n"); + return -1; + } + + for (int i = 0; formats[i].form_factor; i++) + { const format &f = formats[i]; if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) continue; // no further checks for 1600K images - if ((size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && size == 0x190000) { + if ((size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && size == 0x190000) return i; - } // valid 800K images will have map identifier Nick, Arthur D format still use Hugo - if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (memcmp(dform, "Hugo", 4) == 0 || memcmp(dform, "Nick", 4) == 0 || memcmp(eform, "Nick", 4) == 0)) { + if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (memcmp(dform, "Hugo", 4) == 0 || memcmp(dform, "Nick", 4) == 0 || memcmp(eform, "Nick", 4) == 0)) return i; - } } LOG_FORMATS("adfs_n: no match\n"); return -1; } -int acorn_adfs_new_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) +int acorn_adfs_new_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) { int type = find_size(io, form_factor, variants); if (type != -1) return 100; + return 0; } @@ -546,33 +595,43 @@ const char *acorn_dos_format::extensions() const return "img"; } -int acorn_dos_format::find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) +int acorn_dos_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) { - uint8_t type; + uint64_t size; + if (io.length(size)) + { + LOG_FORMATS("dos: error getting image size\n"); + return -1; + } - uint64_t size = io_generic_size(io); - for(int i=0; formats[i].form_factor; i++) { + for (int i=0; formats[i].form_factor; i++) + { const format &f = formats[i]; - if(form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) + if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) continue; - if (size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count) { + if (size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count) + { // read media type ID from FAT - Acorn DOS = 0xfd - io_generic_read(io, &type, 0, 1); + size_t actual; + uint8_t type; + io.read_at(0, &type, 1, actual); LOG_FORMATS("dos: 800k media type id %02X %s\n", type, type != 0xfd ? "invalid" : ""); - if (type == 0xfd) return i; + if (type == 0xfd) + return i; } } LOG_FORMATS("dos: no match\n"); return -1; } -int acorn_dos_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) +int acorn_dos_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) { int type = find_size(io, form_factor, variants); - if(type != -1) + if (type != -1) return 90; + return 0; } @@ -618,19 +677,28 @@ bool opus_ddcpm_format::supports_save() const return false; } -int opus_ddcpm_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) +int opus_ddcpm_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) { + size_t actual; uint8_t h[8]; - io_generic_read(io, h, 0, 8); + io.read_at(0, h, 8, actual); + + uint64_t size; + if (io.length(size)) + { + LOG_FORMATS("ddcpm: error getting image size\n"); + return -1; + } - if (io_generic_size(io) == 819200 && memcmp(h, "Slogger ", 8) == 0) + if (size == 819200 && memcmp(h, "Slogger ", 8) == 0) return 100; + LOG_FORMATS("ddcpm: no match\n"); return 0; } -bool opus_ddcpm_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) +bool opus_ddcpm_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) { // Double density discs formatted with DDCPM : // @@ -644,19 +712,21 @@ bool opus_ddcpm_format::load(io_generic *io, uint32_t form_factor, const std::ve // Sector skew of 1 // Sector interleave of 2 // - int spt, bps; - - for (int head = 0; head < 2; head++) { - for (int track = 0; track < 80; track++) { - bool mfm = track > 2 || head; - bps = mfm ? 512 : 256; - spt = 10; + for (int head = 0; head < 2; head++) + { + for (int track = 0; track < 80; track++) + { + bool const mfm = track > 2 || head; + int const bps = mfm ? 512 : 256; + int const spt = 10; desc_pc_sector sects[10]; uint8_t sectdata[10*512]; - io_generic_read(io, sectdata, head * 80 * spt * 512 + track * spt * 512, spt * 512); + size_t actual; + io.read_at(head * 80 * spt * 512 + track * spt * 512, sectdata, spt * 512, actual); - for (int i = 0; i < spt; i++) { + for (int i = 0; i < spt; i++) + { sects[i].track = track; sects[i].head = head; sects[i].sector = i; @@ -677,7 +747,7 @@ bool opus_ddcpm_format::load(io_generic *io, uint32_t form_factor, const std::ve return true; } -bool opus_ddcpm_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) +bool opus_ddcpm_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) { return false; } |