diff --git a/src/lib/formats/as_dsk.cpp b/src/lib/formats/as_dsk.cpp index 38f2544386c..99fdd06c418 100644 --- a/src/lib/formats/as_dsk.cpp +++ b/src/lib/formats/as_dsk.cpp @@ -120,134 +120,6 @@ void as_format::load_flux_track(const std::vector &img, floppy_image *i } - -woz_format::woz_format() : as_format() -{ -} - -const char *woz_format::name() const -{ - return "woz"; -} - -const char *woz_format::description() const -{ - return "Apple II WOZ Image"; -} - -const char *woz_format::extensions() const -{ - return "woz"; -} - -bool woz_format::supports_save() const -{ - return true; -} - -const uint8_t woz_format::signature[8] = { 0x57, 0x4f, 0x5a, 0x31, 0xff, 0x0a, 0x0d, 0x0a }; -const uint8_t woz_format::signature2[8] = { 0x57, 0x4f, 0x5a, 0x32, 0xff, 0x0a, 0x0d, 0x0a }; - -int woz_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) const -{ - uint8_t header[8]; - size_t actual; - io.read_at(0, header, 8, actual); - if (!memcmp(header, signature, 8)) return FIFID_SIGN; - if (!memcmp(header, signature2, 8)) return FIFID_SIGN; - return 0; -} - -bool woz_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) const -{ - uint64_t image_size; - if(io.length(image_size)) - return false; - std::vector img(image_size); - size_t actual; - io.read_at(0, &img[0], img.size(), actual); - - // Check signature - if((memcmp(&img[0], signature, 8)) && (memcmp(&img[0], signature2, 8))) - return false; - - uint32_t woz_vers = 1; - if(!memcmp(&img[0], signature2, 8)) woz_vers = 2; - - // Check integrity - uint32_t crc = crc32r(&img[12], img.size() - 12); - if(crc != r32(img, 8)) - return false; - - uint32_t off_info = find_tag(img, 0x4f464e49); - uint32_t off_tmap = find_tag(img, 0x50414d54); - uint32_t off_trks = find_tag(img, 0x534b5254); -// uint32_t off_writ = find_tag(img, 0x54495257); - - if(!off_info || !off_tmap || !off_trks) - return false; - - uint32_t info_vers = r8(img, off_info + 0); - if(info_vers < 1 || info_vers > 3) - return false; - - uint16_t off_flux = info_vers < 3 ? 0 : r16(img, off_info + 46); - uint16_t flux_size = info_vers < 3 ? 0 : r16(img, off_info + 48); - - if(!flux_size) - off_flux = 0; - - bool is_35 = r8(img, off_info + 1) == 2; - - if((form_factor == floppy_image::FF_35 && !is_35) || (form_factor == floppy_image::FF_525 && is_35)) - return false; - - unsigned int limit = is_35 ? 160 : 141; - - if(is_35) - image->set_form_variant(floppy_image::FF_35, floppy_image::SSDD); - else - image->set_form_variant(floppy_image::FF_525, floppy_image::SSSD); - - if (woz_vers == 1) { - for (unsigned int trkid = 0; trkid != limit; trkid++) { - int head = is_35 && trkid >= 80 ? 1 : 0; - int track = is_35 ? trkid % 80 : trkid / 4; - int subtrack = is_35 ? 0 : trkid & 3; - - uint8_t idx = r8(img, off_tmap + trkid); - if(idx != 0xff) { - uint32_t boff = off_trks + 6656*idx; - if (r16(img, boff + 6648) == 0) - return false; - generate_track_from_bitstream(track, head, &img[boff], r16(img, boff + 6648), image, subtrack, r16(img, boff + 6650)); - if(is_35 && !track && head) - image->set_variant(floppy_image::DSDD); - } - } - } else if (woz_vers == 2) { - for (unsigned int trkid = 0; trkid != limit; trkid++) { - int head = is_35 && trkid & 1 ? 1 : 0; - int track = is_35 ? trkid >> 1 : trkid / 4; - int subtrack = is_35 ? 0 : trkid & 3; - - uint8_t idx = r8(img, off_tmap + trkid); - uint8_t fidx = off_flux ? r8(img, off_flux*512 + 8 + trkid) : 0xff; - - if(fidx != 0xff) - load_flux_track(img, image, head, track, subtrack, fidx, off_trks); - - else if(idx != 0xff) { - if(!load_bitstream_track(img, image, head, track, subtrack, idx, off_trks, !is_35, is_35 && !track && head)) - return false; - } - } - } - else return false; - - return true; -} - as_format::tdata as_format::analyze_for_save(floppy_image *image, int head, int track, int subtrack, int speed_zone) { // 200000000 / 60.0 * 1.979e-6 ~= 6.5967 @@ -413,6 +285,135 @@ void as_format::save_tracks(std::vector &data, const std::vector } + +woz_format::woz_format() : as_format() +{ +} + +const char *woz_format::name() const +{ + return "woz"; +} + +const char *woz_format::description() const +{ + return "Apple II WOZ Image"; +} + +const char *woz_format::extensions() const +{ + return "woz"; +} + +bool woz_format::supports_save() const +{ + return true; +} + +const uint8_t woz_format::signature[8] = { 0x57, 0x4f, 0x5a, 0x31, 0xff, 0x0a, 0x0d, 0x0a }; +const uint8_t woz_format::signature2[8] = { 0x57, 0x4f, 0x5a, 0x32, 0xff, 0x0a, 0x0d, 0x0a }; + +int woz_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) const +{ + uint8_t header[8]; + size_t actual; + io.read_at(0, header, 8, actual); + if (!memcmp(header, signature, 8)) return FIFID_SIGN; + if (!memcmp(header, signature2, 8)) return FIFID_SIGN; + return 0; +} + +bool woz_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) const +{ + uint64_t image_size; + if(io.length(image_size)) + return false; + std::vector img(image_size); + size_t actual; + io.read_at(0, &img[0], img.size(), actual); + + // Check signature + if((memcmp(&img[0], signature, 8)) && (memcmp(&img[0], signature2, 8))) + return false; + + uint32_t woz_vers = 1; + if(!memcmp(&img[0], signature2, 8)) woz_vers = 2; + + // Check integrity + uint32_t crc = crc32r(&img[12], img.size() - 12); + if(crc != r32(img, 8)) + return false; + + uint32_t off_info = find_tag(img, 0x4f464e49); + uint32_t off_tmap = find_tag(img, 0x50414d54); + uint32_t off_trks = find_tag(img, 0x534b5254); +// uint32_t off_writ = find_tag(img, 0x54495257); + + if(!off_info || !off_tmap || !off_trks) + return false; + + uint32_t info_vers = r8(img, off_info + 0); + if(info_vers < 1 || info_vers > 3) + return false; + + uint16_t off_flux = info_vers < 3 ? 0 : r16(img, off_info + 46); + uint16_t flux_size = info_vers < 3 ? 0 : r16(img, off_info + 48); + + if(!flux_size) + off_flux = 0; + + bool is_35 = r8(img, off_info + 1) == 2; + + if((form_factor == floppy_image::FF_35 && !is_35) || (form_factor == floppy_image::FF_525 && is_35)) + return false; + + unsigned int limit = is_35 ? 160 : 141; + + if(is_35) + image->set_form_variant(floppy_image::FF_35, floppy_image::SSDD); + else + image->set_form_variant(floppy_image::FF_525, floppy_image::SSSD); + + if (woz_vers == 1) { + for (unsigned int trkid = 0; trkid != limit; trkid++) { + int head = is_35 && trkid >= 80 ? 1 : 0; + int track = is_35 ? trkid % 80 : trkid / 4; + int subtrack = is_35 ? 0 : trkid & 3; + + uint8_t idx = r8(img, off_tmap + trkid); + if(idx != 0xff) { + uint32_t boff = off_trks + 6656*idx; + if (r16(img, boff + 6648) == 0) + return false; + generate_track_from_bitstream(track, head, &img[boff], r16(img, boff + 6648), image, subtrack, r16(img, boff + 6650)); + if(is_35 && !track && head) + image->set_variant(floppy_image::DSDD); + } + } + } else if (woz_vers == 2) { + for (unsigned int trkid = 0; trkid != limit; trkid++) { + int head = is_35 && trkid & 1 ? 1 : 0; + int track = is_35 ? trkid >> 1 : trkid / 4; + int subtrack = is_35 ? 0 : trkid & 3; + + uint8_t idx = r8(img, off_tmap + trkid); + uint8_t fidx = off_flux ? r8(img, off_flux*512 + 8 + trkid) : 0xff; + + if(fidx != 0xff) + load_flux_track(img, image, head, track, subtrack, fidx, off_trks); + + else if(idx != 0xff) { + if(!load_bitstream_track(img, image, head, track, subtrack, idx, off_trks, !is_35, is_35 && !track && head)) + return false; + } + } + } + else return false; + + return true; +} + + bool woz_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) const { std::vector tracks(160); @@ -496,7 +497,7 @@ const char *moof_format::extensions() const bool moof_format::supports_save() const { - return false; + return true; } const uint8_t moof_format::signature[8] = { 0x4d, 0x4f, 0x4f, 0x46, 0xff, 0x0a, 0x0d, 0x0a }; @@ -578,4 +579,55 @@ bool moof_format::load(util::random_read &io, uint32_t form_factor, const std::v return true; } +bool moof_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) const +{ + std::vector tracks(160); + bool twosided = false; + bool is_hd = false; + + if(image->get_variant() == floppy_image::DSHD) { + twosided = true; + is_hd = true; + for(unsigned int i=0; i != 160; i++) + tracks[i] = analyze_for_save(image, i & 1, i >> 1, 0, 6); + + } else { + for(unsigned int i=0; i != 160; i++) { + tracks[i] = analyze_for_save(image, i & 1, i >> 1, 0, i / (2*16)); + if((i & 1) && tracks[i].track_size) + twosided = true; + } + } + + auto [total_blocks, max_blocks] = count_blocks(tracks); + bool has_flux = test_flux(tracks); + + std::vector data(1536 + total_blocks*512 + (has_flux ? 512 : 0), 0); + + memcpy(&data[0], signature, 8); + + w32(data, 12, 0x4F464E49); // INFO + w32(data, 16, 60); // size + data[20] = 1; // chunk version + data[21] = is_hd ? 3 : twosided ? 2 : 1; // variant + data[22] = 0; // not write protected + data[23] = 1; // synchronized, since our internal format is + data[24] = is_hd ? 8 : 16; // optimal timing + data[25] = 'M'; + data[26] = 'A'; + data[27] = 'M'; + data[28] = 'E'; + memset(&data[29], ' ', 32-4); + data[57] = 0; // pad + w16(data, 58, max_blocks); + w16(data, 60, has_flux ? total_blocks+3 : 0); + w16(data, 62, max_blocks); + + save_tracks(data, tracks, total_blocks, has_flux); + + size_t actual; + io.write_at(0, data.data(), data.size(), actual); + return true; +} + const moof_format FLOPPY_MOOF_FORMAT; diff --git a/src/lib/formats/as_dsk.h b/src/lib/formats/as_dsk.h index 82091f1d1d7..74582836721 100644 --- a/src/lib/formats/as_dsk.h +++ b/src/lib/formats/as_dsk.h @@ -67,6 +67,7 @@ public: virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) const override; virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) const override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) const override; virtual bool supports_save() const override; virtual const char *name() const override;