summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/formats
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/formats')
-rw-r--r--src/lib/formats/all.cpp10
-rw-r--r--src/lib/formats/ap2_dsk.cpp508
-rw-r--r--src/lib/formats/ap2_dsk.h55
-rw-r--r--src/lib/formats/as_dsk.cpp464
-rw-r--r--src/lib/formats/as_dsk.h71
5 files changed, 543 insertions, 565 deletions
diff --git a/src/lib/formats/all.cpp b/src/lib/formats/all.cpp
index 5bae7c54707..30a1e103fc2 100644
--- a/src/lib/formats/all.cpp
+++ b/src/lib/formats/all.cpp
@@ -104,6 +104,10 @@
#include "asst128_dsk.h"
#endif
+#ifdef HAS_FORMATS_AS_DSK
+#include "as_dsk.h"
+#endif
+
#ifdef HAS_FORMATS_ATARI_DSK
#include "atari_dsk.h"
#endif
@@ -753,10 +757,12 @@ void mame_formats_full_list(mame_formats_enumerator &en)
en.add(FLOPPY_A216S_PRODOS_FORMAT); // ap2_dsk.h
en.add(FLOPPY_RWTS18_FORMAT); // ap2_dsk.h
en.add(FLOPPY_EDD_FORMAT); // ap2_dsk.h
- en.add(FLOPPY_WOZ_FORMAT); // ap2_dsk.h
- en.add(FLOPPY_MOOF_FORMAT); // ap2_dsk.h
en.add(FLOPPY_NIB_FORMAT); // ap2_dsk.h
#endif
+#ifdef HAS_FORMATS_AS_DSK
+ en.add(FLOPPY_WOZ_FORMAT); // as_dsk.h
+ en.add(FLOPPY_MOOF_FORMAT); // as_dsk.h
+#endif
#ifdef HAS_FORMATS_AIM_DSK
en.add(FLOPPY_AIM_FORMAT); // aim_dsk.h
#endif
diff --git a/src/lib/formats/ap2_dsk.cpp b/src/lib/formats/ap2_dsk.cpp
index 6cb22219b93..192a1dd3252 100644
--- a/src/lib/formats/ap2_dsk.cpp
+++ b/src/lib/formats/ap2_dsk.cpp
@@ -1130,514 +1130,6 @@ bool a2_edd_format::load(util::random_read &io, uint32_t form_factor, const std:
const a2_edd_format FLOPPY_EDD_FORMAT;
-a2_woz_format::a2_woz_format() : floppy_image_format_t()
-{
-}
-
-const char *a2_woz_format::name() const
-{
- return "a2_woz";
-}
-
-const char *a2_woz_format::description() const
-{
- return "Apple II WOZ Image";
-}
-
-const char *a2_woz_format::extensions() const
-{
- return "woz";
-}
-
-bool a2_woz_format::supports_save() const
-{
- return true;
-}
-
-const uint8_t a2_woz_format::signature[8] = { 0x57, 0x4f, 0x5a, 0x31, 0xff, 0x0a, 0x0d, 0x0a };
-const uint8_t a2_woz_format::signature2[8] = { 0x57, 0x4f, 0x5a, 0x32, 0xff, 0x0a, 0x0d, 0x0a };
-
-int a2_woz_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &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 a2_woz_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) const
-{
- uint64_t image_size;
- if(io.length(image_size))
- return false;
- std::vector<uint8_t> 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) {
- uint32_t trks_off = off_trks + (fidx * 8);
- uint32_t boff = (uint32_t)r16(img, trks_off + 0) * 512;
- uint32_t track_size = r32(img, trks_off + 4);
-
- uint32_t total_ticks = 0;
- for(uint32_t i=0; i != track_size; i++)
- total_ticks += img[boff+i];
-
- // Assume there is always a pulse at index, and it's
- // the last one in the stream
- std::vector<uint32_t> &buf = image->get_buffer(track, head, subtrack);
- buf.push_back(floppy_image::MG_F | 0);
- uint32_t cpos = 0;
- for(uint32_t i=0; i != track_size; i++) {
- uint8_t step = img[boff+i];
- cpos += step;
- if(step != 0xff && i != track_size-1)
- buf.push_back(floppy_image::MG_F | uint64_t(cpos)*200000000/total_ticks);
- }
-
- } else if(idx != 0xff) {
- uint32_t trks_off = off_trks + (idx * 8);
-
- uint32_t boff = (uint32_t)r16(img, trks_off + 0) * 512;
-
- if (r32(img, trks_off + 4) == 0)
- return false;
-
- uint32_t track_size = r32(img, trks_off + 4);
-
- // With 5.25 floppies the end-of-track may be missing
- // if unformatted. Accept track length down to 95% of
- // 51090, otherwise pad it
-
- bool short_track = !is_35 && track_size < 48535;
-
- if(short_track) {
- std::vector<uint8_t> buffer(6387, 0);
- memcpy(buffer.data(), &img[boff], (track_size + 7) / 8);
- generate_track_from_bitstream(track, head, buffer.data(), 51090, image, subtrack, 0xffff);
-
- } else
- generate_track_from_bitstream(track, head, &img[boff], track_size, image, subtrack, 0xffff);
-
- if(is_35 && !track && head)
- image->set_variant(r32(img, trks_off + 4) >= 90000 ? floppy_image::DSHD : floppy_image::DSDD);
- }
- }
- }
- else return false;
-
- return true;
-}
-
-bool a2_woz_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) const
-{
- std::vector<std::vector<bool>> tracks(160);
- bool twosided = false;
-
- if(image->get_form_factor() == floppy_image::FF_525) {
- for(unsigned int i=0; i != 141; i++)
- if(image->track_is_formatted(i >> 2, 0, i & 3))
- tracks[i] = generate_bitstream_from_track(i >> 2, 0, 3915, image, i & 3);
-
- } else if(image->get_variant() == floppy_image::DSHD) {
- for(unsigned int i=0; i != 160; i++)
- if(image->track_is_formatted(i >> 1, i & 1)) {
- tracks[i] = generate_bitstream_from_track(i >> 1, i & 1, 1000, image);
- if(i & 1)
- twosided = true;
- }
-
- } else {
- // 200000000 / 60.0 * 1.979e-6 ~= 6.5967
- static const int cell_size_per_speed_zone[5] = {
- 394 * 65967 / 10000,
- 429 * 65967 / 10000,
- 472 * 65967 / 10000,
- 525 * 65967 / 10000,
- 590 * 65967 / 10000
- };
-
- for(unsigned int i=0; i != 160; i++)
- if(image->track_is_formatted(i >> 1, i & 1)) {
- tracks[i] = generate_bitstream_from_track(i >> 1, i & 1, cell_size_per_speed_zone[i / (2*16)], image);
- if(i & 1)
- twosided = true;
- }
- }
-
- int max_blocks = 0;
- int total_blocks = 0;
- for(const auto &t : tracks) {
- int blocks = (t.size() + 4095) / 4096;
- total_blocks += blocks;
- if(max_blocks < blocks)
- max_blocks = blocks;
- }
-
- std::vector<uint8_t> data(1536 + total_blocks*512, 0);
-
- memcpy(&data[0], signature2, 8);
-
- w32(data, 12, 0x4F464E49); // INFO
- w32(data, 16, 60); // size
- data[20] = 2; // chunk version
- data[21] = image->get_form_factor() == floppy_image::FF_525 ? 1 : 2;
- data[22] = 0; // not write protected
- data[23] = 1; // synchronized, since our internal format is
- data[24] = 1; // weak bits are generated, not stored
- data[25] = 'M';
- data[26] = 'A';
- data[27] = 'M';
- data[28] = 'E';
- memset(&data[29], ' ', 32-4);
- data[57] = twosided ? 2 : 1;
- data[58] = 0; // boot sector unknown
- data[59] = image->get_form_factor() == floppy_image::FF_525 ? 32 : image->get_variant() == floppy_image::DSHD ? 8 : 16;
- w16(data, 60, 0); // compatibility unknown
- w16(data, 62, 0); // needed ram unknown
- w16(data, 64, max_blocks);
- w32(data, 80, 0x50414D54); // TMAP
- w32(data, 84, 160); // size
-
- uint8_t tcount = 0;
- for(int i=0; i != 160 ; i++)
- data[88 + i] = tracks[i].empty() ? 0xff : tcount++;
-
- w32(data, 248, 0x534B5254); // TRKS
- w32(data, 252, 1280 + total_blocks*512); // size
-
- uint8_t tid = 0;
- uint16_t tb = 3;
- for(int i=0; i != 160 ; i++)
- if(!tracks[i].empty()) {
- int blocks = (tracks[i].size() + 4095) / 4096;
- w16(data, 256 + tid*8, tb);
- w16(data, 256 + tid*8 + 2, blocks);
- w32(data, 256 + tid*8 + 4, tracks[i].size());
- tb += blocks;
- tid ++;
- }
-
- tb = 3;
- for(int i=0; i != 160 ; i++)
- if(!tracks[i].empty()) {
- int off = tb * 512;
- int size = tracks[i].size();
- for(int j=0; j != size; j++)
- if(tracks[i][j])
- data[off + (j >> 3)] |= 0x80 >> (j & 7);
- tb += (size + 4095) / 4096;
- }
-
- w32(data, 8, crc32r(&data[12], data.size() - 12));
-
- size_t actual;
- io.write_at(0, data.data(), data.size(), actual);
- return true;
-}
-
-uint32_t a2_woz_format::find_tag(const std::vector<uint8_t> &data, uint32_t tag)
-{
- uint32_t offset = 12;
- do {
- if(r32(data, offset) == tag)
- return offset + 8;
- offset += r32(data, offset+4) + 8;
- } while(offset < data.size() - 8);
- return 0;
-}
-
-uint32_t a2_woz_format::r32(const std::vector<uint8_t> &data, uint32_t offset)
-{
- return data[offset] | (data[offset+1] << 8) | (data[offset+2] << 16) | (data[offset+3] << 24);
-}
-
-uint16_t a2_woz_format::r16(const std::vector<uint8_t> &data, uint32_t offset)
-{
- return data[offset] | (data[offset+1] << 8);
-}
-
-void a2_woz_format::w32(std::vector<uint8_t> &data, int offset, uint32_t value)
-{
- data[offset] = value;
- data[offset+1] = value >> 8;
- data[offset+2] = value >> 16;
- data[offset+3] = value >> 24;
-}
-
-void a2_woz_format::w16(std::vector<uint8_t> &data, int offset, uint16_t value)
-{
- data[offset] = value;
- data[offset+1] = value >> 8;
-}
-
-uint8_t a2_woz_format::r8(const std::vector<uint8_t> &data, uint32_t offset)
-{
- return data[offset];
-}
-
-uint32_t a2_woz_format::crc32r(const uint8_t *data, uint32_t size)
-{
- // Reversed crc32
- uint32_t crc = 0xffffffff;
- for(uint32_t i=0; i != size; i++) {
- crc = crc ^ data[i];
- for(int j=0; j<8; j++)
- if(crc & 1)
- crc = (crc >> 1) ^ 0xedb88320;
- else
- crc = crc >> 1;
- }
- return ~crc;
-}
-
-
-const a2_woz_format FLOPPY_WOZ_FORMAT;
-
-
-moof_format::moof_format() : floppy_image_format_t()
-{
-}
-
-const char *moof_format::name() const
-{
- return "moof";
-}
-
-const char *moof_format::description() const
-{
- return "Macintosh MOOF Image";
-}
-
-const char *moof_format::extensions() const
-{
- return "moof";
-}
-
-bool moof_format::supports_save() const
-{
- return false;
-}
-
-const uint8_t moof_format::signature[8] = { 0x4d, 0x4f, 0x4f, 0x46, 0xff, 0x0a, 0x0d, 0x0a };
-
-int moof_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
-{
- uint8_t header[8];
- size_t actual;
- io.read_at(0, header, 8, actual);
- if (!memcmp(header, signature, 8)) return FIFID_SIGN;
- return 0;
-}
-
-bool moof_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) const
-{
- uint64_t image_size;
- if(io.length(image_size))
- return false;
- std::vector<uint8_t> img(image_size);
- size_t actual;
- io.read_at(0, &img[0], img.size(), actual);
-
- // Check signature
- if(memcmp(&img[0], signature, 8))
- return false;
-
- // 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);
-
- if(!off_info || !off_tmap || !off_trks)
- return false;
-
- uint32_t info_vers = r8(img, off_info + 0);
- if(info_vers != 1)
- return false;
-
- uint16_t off_flux = r16(img, off_info + 40);
- uint16_t flux_size = r16(img, off_info + 42);
-
- if(!flux_size)
- off_flux = 0;
-
- switch(r8(img, off_info + 1)) {
- case 1:
- image->set_form_variant(floppy_image::FF_35, floppy_image::SSDD);
- break;
- case 2:
- image->set_form_variant(floppy_image::FF_35, floppy_image::DSDD);
- break;
- case 3:
- image->set_form_variant(floppy_image::FF_35, floppy_image::DSHD);
- break;
- default:
- return false;
- }
-
- for (unsigned int trkid = 0; trkid != 160; trkid++) {
- int head = trkid & 1;
- int track = trkid >> 1;
-
- uint8_t idx = r8(img, off_tmap + trkid);
- uint8_t fidx = off_flux ? r8(img, off_flux*512 + 8 + trkid) : 0xff;
-
- if(fidx != 0xff) {
- uint32_t trks_off = off_trks + (fidx * 8);
- uint32_t boff = (uint32_t)r16(img, trks_off + 0) * 512;
- uint32_t track_size = r32(img, trks_off + 4);
-
- uint32_t total_ticks = 0;
- for(uint32_t i=0; i != track_size; i++)
- total_ticks += img[boff+i];
-
- // Assume there is always a pulse at index, and it's
- // the last one in the stream
- std::vector<uint32_t> &buf = image->get_buffer(track, head);
- buf.push_back(floppy_image::MG_F | 0);
- uint32_t cpos = 0;
- for(uint32_t i=0; i != track_size; i++) {
- uint8_t step = img[boff+i];
- cpos += step;
- if(step != 0xff && i != track_size-1)
- buf.push_back(floppy_image::MG_F | uint64_t(cpos)*200000000/total_ticks);
- }
-
- } else if(idx != 0xff) {
- uint32_t trks_off = off_trks + (idx * 8);
-
- uint32_t boff = (uint32_t)r16(img, trks_off + 0) * 512;
-
- uint32_t track_size = r32(img, trks_off + 4);
-
- if (track_size == 0)
- return false;
-
- generate_track_from_bitstream(track, head, &img[boff], track_size, image, 0, 0xffff);
- }
- }
-
- return true;
-}
-
-uint32_t moof_format::find_tag(const std::vector<uint8_t> &data, uint32_t tag)
-{
- uint32_t offset = 12;
- do {
- if(r32(data, offset) == tag)
- return offset + 8;
- offset += r32(data, offset+4) + 8;
- } while(offset < data.size() - 8);
- return 0;
-}
-
-uint32_t moof_format::r32(const std::vector<uint8_t> &data, uint32_t offset)
-{
- return data[offset] | (data[offset+1] << 8) | (data[offset+2] << 16) | (data[offset+3] << 24);
-}
-
-uint16_t moof_format::r16(const std::vector<uint8_t> &data, uint32_t offset)
-{
- return data[offset] | (data[offset+1] << 8);
-}
-
-uint8_t moof_format::r8(const std::vector<uint8_t> &data, uint32_t offset)
-{
- return data[offset];
-}
-
-uint32_t moof_format::crc32r(const uint8_t *data, uint32_t size)
-{
- // Reversed crc32
- uint32_t crc = 0xffffffff;
- for(uint32_t i=0; i != size; i++) {
- crc = crc ^ data[i];
- for(int j=0; j<8; j++)
- if(crc & 1)
- crc = (crc >> 1) ^ 0xedb88320;
- else
- crc = crc >> 1;
- }
- return ~crc;
-}
-
-
-const moof_format FLOPPY_MOOF_FORMAT;
-
-
a2_nib_format::a2_nib_format() : floppy_image_format_t()
{
}
diff --git a/src/lib/formats/ap2_dsk.h b/src/lib/formats/ap2_dsk.h
index c5503133295..607d2d9568c 100644
--- a/src/lib/formats/ap2_dsk.h
+++ b/src/lib/formats/ap2_dsk.h
@@ -109,61 +109,6 @@ private:
extern const a2_edd_format FLOPPY_EDD_FORMAT;
-class a2_woz_format : public floppy_image_format_t
-{
-public:
- a2_woz_format();
-
- virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const override;
- virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) const override;
- virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) const override;
- virtual bool supports_save() const override;
-
- virtual const char *name() const override;
- virtual const char *description() const override;
- virtual const char *extensions() const override;
-
-private:
- static const uint8_t signature[8];
- static const uint8_t signature2[8];
-
- static uint32_t r32(const std::vector<uint8_t> &data, uint32_t offset);
- static uint16_t r16(const std::vector<uint8_t> &data, uint32_t offset);
- static uint8_t r8(const std::vector<uint8_t> &data, uint32_t offset);
- static void w32(std::vector<uint8_t> &data, int offset, uint32_t value);
- static void w16(std::vector<uint8_t> &data, int offset, uint16_t value);
- static uint32_t crc32r(const uint8_t *data, uint32_t size);
- static uint32_t find_tag(const std::vector<uint8_t> &data, uint32_t tag);
-};
-
-extern const a2_woz_format FLOPPY_WOZ_FORMAT;
-
-class moof_format : public floppy_image_format_t
-{
-public:
- moof_format();
-
- virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const override;
- virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) const override;
- virtual bool supports_save() const override;
-
- virtual const char *name() const override;
- virtual const char *description() const override;
- virtual const char *extensions() const override;
-
-private:
- static const uint8_t signature[8];
-
- static uint32_t r32(const std::vector<uint8_t> &data, uint32_t offset);
- static uint16_t r16(const std::vector<uint8_t> &data, uint32_t offset);
- static uint8_t r8(const std::vector<uint8_t> &data, uint32_t offset);
- static uint32_t crc32r(const uint8_t *data, uint32_t size);
- static uint32_t find_tag(const std::vector<uint8_t> &data, uint32_t tag);
-};
-
-extern const moof_format FLOPPY_MOOF_FORMAT;
-
-
class a2_nib_format : public floppy_image_format_t
{
public:
diff --git a/src/lib/formats/as_dsk.cpp b/src/lib/formats/as_dsk.cpp
new file mode 100644
index 00000000000..eef5bb6dc80
--- /dev/null
+++ b/src/lib/formats/as_dsk.cpp
@@ -0,0 +1,464 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// Applesauce solved output formats
+
+#include "as_dsk.h"
+#include "ioprocs.h"
+
+#include <string.h>
+
+as_format::as_format() : floppy_image_format_t()
+{
+}
+
+uint32_t as_format::find_tag(const std::vector<uint8_t> &data, uint32_t tag)
+{
+ uint32_t offset = 12;
+ do {
+ if(r32(data, offset) == tag)
+ return offset + 8;
+ offset += r32(data, offset+4) + 8;
+ } while(offset < data.size() - 8);
+ return 0;
+}
+
+uint32_t as_format::r32(const std::vector<uint8_t> &data, uint32_t offset)
+{
+ return data[offset] | (data[offset+1] << 8) | (data[offset+2] << 16) | (data[offset+3] << 24);
+}
+
+uint16_t as_format::r16(const std::vector<uint8_t> &data, uint32_t offset)
+{
+ return data[offset] | (data[offset+1] << 8);
+}
+
+void as_format::w32(std::vector<uint8_t> &data, int offset, uint32_t value)
+{
+ data[offset] = value;
+ data[offset+1] = value >> 8;
+ data[offset+2] = value >> 16;
+ data[offset+3] = value >> 24;
+}
+
+void as_format::w16(std::vector<uint8_t> &data, int offset, uint16_t value)
+{
+ data[offset] = value;
+ data[offset+1] = value >> 8;
+}
+
+uint8_t as_format::r8(const std::vector<uint8_t> &data, uint32_t offset)
+{
+ return data[offset];
+}
+
+uint32_t as_format::crc32r(const uint8_t *data, uint32_t size)
+{
+ // Reversed crc32
+ uint32_t crc = 0xffffffff;
+ for(uint32_t i=0; i != size; i++) {
+ crc = crc ^ data[i];
+ for(int j=0; j<8; j++)
+ if(crc & 1)
+ crc = (crc >> 1) ^ 0xedb88320;
+ else
+ crc = crc >> 1;
+ }
+ return ~crc;
+}
+
+bool as_format::load_bitstream_track(const std::vector<uint8_t> &img, floppy_image *image, int head, int track, int subtrack, uint8_t idx, uint32_t off_trks, bool may_be_short, bool set_variant)
+{
+ uint32_t trks_off = off_trks + (idx * 8);
+
+ uint32_t track_size = r32(img, trks_off + 4);
+ if (track_size == 0)
+ return false;
+
+ uint32_t boff = (uint32_t)r16(img, trks_off + 0) * 512;
+
+ // With 5.25 floppies the end-of-track may be missing
+ // if unformatted. Accept track length down to 95% of
+ // 51090, otherwise pad it
+
+ bool short_track = may_be_short && track_size < 48535;
+
+ if(short_track) {
+ std::vector<uint8_t> buffer(6387, 0);
+ memcpy(buffer.data(), &img[boff], (track_size + 7) / 8);
+ generate_track_from_bitstream(track, head, buffer.data(), 51090, image, subtrack, 0xffff);
+
+ } else
+ generate_track_from_bitstream(track, head, &img[boff], track_size, image, subtrack, 0xffff);
+
+ if(set_variant)
+ image->set_variant(r32(img, trks_off + 4) >= 90000 ? floppy_image::DSHD : floppy_image::DSDD);
+ return true;
+}
+
+void as_format::load_flux_track(const std::vector<uint8_t> &img, floppy_image *image, int head, int track, int subtrack, uint8_t fidx, uint32_t off_trks)
+{
+ uint32_t trks_off = off_trks + (fidx * 8);
+ uint32_t boff = (uint32_t)r16(img, trks_off + 0) * 512;
+ uint32_t track_size = r32(img, trks_off + 4);
+
+ uint32_t total_ticks = 0;
+ for(uint32_t i=0; i != track_size; i++)
+ total_ticks += img[boff+i];
+
+ // There is always a pulse at index, and it's
+ // the last one in the stream
+ std::vector<uint32_t> &buf = image->get_buffer(track, head, subtrack);
+ buf.push_back(floppy_image::MG_F | 0);
+ uint32_t cpos = 0;
+ for(uint32_t i=0; i != track_size; i++) {
+ uint8_t step = img[boff+i];
+ cpos += step;
+ if(step != 0xff && i != track_size-1)
+ buf.push_back(floppy_image::MG_F | uint64_t(cpos)*200000000/total_ticks);
+ }
+}
+
+
+
+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<uint32_t> &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<uint32_t> &variants, floppy_image *image) const
+{
+ uint64_t image_size;
+ if(io.length(image_size))
+ return false;
+ std::vector<uint8_t> 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<uint32_t> &variants, floppy_image *image) const
+{
+ std::vector<std::vector<bool>> tracks(160);
+ bool twosided = false;
+
+ if(image->get_form_factor() == floppy_image::FF_525) {
+ for(unsigned int i=0; i != 141; i++)
+ if(image->track_is_formatted(i >> 2, 0, i & 3))
+ tracks[i] = generate_bitstream_from_track(i >> 2, 0, 3915, image, i & 3);
+
+ } else if(image->get_variant() == floppy_image::DSHD) {
+ for(unsigned int i=0; i != 160; i++)
+ if(image->track_is_formatted(i >> 1, i & 1)) {
+ tracks[i] = generate_bitstream_from_track(i >> 1, i & 1, 1000, image);
+ if(i & 1)
+ twosided = true;
+ }
+
+ } else {
+ // 200000000 / 60.0 * 1.979e-6 ~= 6.5967
+ static const int cell_size_per_speed_zone[5] = {
+ 394 * 65967 / 10000,
+ 429 * 65967 / 10000,
+ 472 * 65967 / 10000,
+ 525 * 65967 / 10000,
+ 590 * 65967 / 10000
+ };
+
+ for(unsigned int i=0; i != 160; i++)
+ if(image->track_is_formatted(i >> 1, i & 1)) {
+ tracks[i] = generate_bitstream_from_track(i >> 1, i & 1, cell_size_per_speed_zone[i / (2*16)], image);
+ if(i & 1)
+ twosided = true;
+ }
+ }
+
+ int max_blocks = 0;
+ int total_blocks = 0;
+ for(const auto &t : tracks) {
+ int blocks = (t.size() + 4095) / 4096;
+ total_blocks += blocks;
+ if(max_blocks < blocks)
+ max_blocks = blocks;
+ }
+
+ std::vector<uint8_t> data(1536 + total_blocks*512, 0);
+
+ memcpy(&data[0], signature2, 8);
+
+ w32(data, 12, 0x4F464E49); // INFO
+ w32(data, 16, 60); // size
+ data[20] = 2; // chunk version
+ data[21] = image->get_form_factor() == floppy_image::FF_525 ? 1 : 2;
+ data[22] = 0; // not write protected
+ data[23] = 1; // synchronized, since our internal format is
+ data[24] = 1; // weak bits are generated, not stored
+ data[25] = 'M';
+ data[26] = 'A';
+ data[27] = 'M';
+ data[28] = 'E';
+ memset(&data[29], ' ', 32-4);
+ data[57] = twosided ? 2 : 1;
+ data[58] = 0; // boot sector unknown
+ data[59] = image->get_form_factor() == floppy_image::FF_525 ? 32 : image->get_variant() == floppy_image::DSHD ? 8 : 16;
+ w16(data, 60, 0); // compatibility unknown
+ w16(data, 62, 0); // needed ram unknown
+ w16(data, 64, max_blocks);
+ w32(data, 80, 0x50414D54); // TMAP
+ w32(data, 84, 160); // size
+
+ uint8_t tcount = 0;
+ for(int i=0; i != 160 ; i++)
+ data[88 + i] = tracks[i].empty() ? 0xff : tcount++;
+
+ w32(data, 248, 0x534B5254); // TRKS
+ w32(data, 252, 1280 + total_blocks*512); // size
+
+ uint8_t tid = 0;
+ uint16_t tb = 3;
+ for(int i=0; i != 160 ; i++)
+ if(!tracks[i].empty()) {
+ int blocks = (tracks[i].size() + 4095) / 4096;
+ w16(data, 256 + tid*8, tb);
+ w16(data, 256 + tid*8 + 2, blocks);
+ w32(data, 256 + tid*8 + 4, tracks[i].size());
+ tb += blocks;
+ tid ++;
+ }
+
+ tb = 3;
+ for(int i=0; i != 160 ; i++)
+ if(!tracks[i].empty()) {
+ int off = tb * 512;
+ int size = tracks[i].size();
+ for(int j=0; j != size; j++)
+ if(tracks[i][j])
+ data[off + (j >> 3)] |= 0x80 >> (j & 7);
+ tb += (size + 4095) / 4096;
+ }
+
+ w32(data, 8, crc32r(&data[12], data.size() - 12));
+
+ size_t actual;
+ io.write_at(0, data.data(), data.size(), actual);
+ return true;
+}
+
+const woz_format FLOPPY_WOZ_FORMAT;
+
+
+moof_format::moof_format() : as_format()
+{
+}
+
+const char *moof_format::name() const
+{
+ return "moof";
+}
+
+const char *moof_format::description() const
+{
+ return "Macintosh MOOF Image";
+}
+
+const char *moof_format::extensions() const
+{
+ return "moof";
+}
+
+bool moof_format::supports_save() const
+{
+ return false;
+}
+
+const uint8_t moof_format::signature[8] = { 0x4d, 0x4f, 0x4f, 0x46, 0xff, 0x0a, 0x0d, 0x0a };
+
+int moof_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
+{
+ uint8_t header[8];
+ size_t actual;
+ io.read_at(0, header, 8, actual);
+ if (!memcmp(header, signature, 8)) return FIFID_SIGN;
+ return 0;
+}
+
+bool moof_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) const
+{
+ uint64_t image_size;
+ if(io.length(image_size))
+ return false;
+ std::vector<uint8_t> img(image_size);
+ size_t actual;
+ io.read_at(0, &img[0], img.size(), actual);
+
+ // Check signature
+ if(memcmp(&img[0], signature, 8))
+ return false;
+
+ // 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);
+
+ if(!off_info || !off_tmap || !off_trks)
+ return false;
+
+ uint32_t info_vers = r8(img, off_info + 0);
+ if(info_vers != 1)
+ return false;
+
+ uint16_t off_flux = r16(img, off_info + 40);
+ uint16_t flux_size = r16(img, off_info + 42);
+
+ if(!flux_size)
+ off_flux = 0;
+
+ switch(r8(img, off_info + 1)) {
+ case 1:
+ image->set_form_variant(floppy_image::FF_35, floppy_image::SSDD);
+ break;
+ case 2:
+ image->set_form_variant(floppy_image::FF_35, floppy_image::DSDD);
+ break;
+ case 3:
+ image->set_form_variant(floppy_image::FF_35, floppy_image::DSHD);
+ break;
+ default:
+ return false;
+ }
+
+ for (unsigned int trkid = 0; trkid != 160; trkid++) {
+ int head = trkid & 1;
+ int track = trkid >> 1;
+
+ 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, track, head, 0, fidx, off_trks);
+
+ else if(idx != 0xff) {
+ if(!load_bitstream_track(img, image, head, track, 0, idx, off_trks, false, false))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+const moof_format FLOPPY_MOOF_FORMAT;
diff --git a/src/lib/formats/as_dsk.h b/src/lib/formats/as_dsk.h
new file mode 100644
index 00000000000..b33252a4c77
--- /dev/null
+++ b/src/lib/formats/as_dsk.h
@@ -0,0 +1,71 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// Applesauce solved output formats
+
+#ifndef MAME_FORMATS_AS_DSK_H
+#define MAME_FORMATS_AS_DSK_H
+
+#pragma once
+
+#include "flopimg.h"
+
+class as_format : public floppy_image_format_t
+{
+public:
+ as_format();
+
+protected:
+ static uint32_t r32(const std::vector<uint8_t> &data, uint32_t offset);
+ static uint16_t r16(const std::vector<uint8_t> &data, uint32_t offset);
+ static uint8_t r8(const std::vector<uint8_t> &data, uint32_t offset);
+ static void w32(std::vector<uint8_t> &data, int offset, uint32_t value);
+ static void w16(std::vector<uint8_t> &data, int offset, uint16_t value);
+ static uint32_t crc32r(const uint8_t *data, uint32_t size);
+ static uint32_t find_tag(const std::vector<uint8_t> &data, uint32_t tag);
+
+ static bool load_bitstream_track(const std::vector<uint8_t> &img, floppy_image *image, int head, int track, int subtrack, uint8_t idx, uint32_t off_trks, bool may_be_short, bool set_variant);
+ static void load_flux_track(const std::vector<uint8_t> &img, floppy_image *image, int head, int track, int subtrack, uint8_t fidx, uint32_t off_trks);
+};
+
+class woz_format : public as_format
+{
+public:
+ woz_format();
+
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) const override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) const override;
+ virtual bool supports_save() const override;
+
+ virtual const char *name() const override;
+ virtual const char *description() const override;
+ virtual const char *extensions() const override;
+
+private:
+ static const uint8_t signature[8];
+ static const uint8_t signature2[8];
+};
+
+extern const woz_format FLOPPY_WOZ_FORMAT;
+
+class moof_format : public as_format
+{
+public:
+ moof_format();
+
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) const override;
+ virtual bool supports_save() const override;
+
+ virtual const char *name() const override;
+ virtual const char *description() const override;
+ virtual const char *extensions() const override;
+
+private:
+ static const uint8_t signature[8];
+};
+
+extern const moof_format FLOPPY_MOOF_FORMAT;
+
+#endif