summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Olivier Galibert <galibert@pobox.com>2021-02-15 23:43:32 +0100
committer Olivier Galibert <galibert@pobox.com>2021-02-15 23:45:00 +0100
commit26bf6638a994a9fd5d4c980575d1a7e0c018a51f (patch)
tree9e36db81035ff0429d623752d6e3530b9f889819
parent6cd00933275eed572a92f4c92226b75fc3d0ee61 (diff)
woz: Add write
some formats: Correct setting up of form factor and variant
-rw-r--r--src/lib/formats/ap2_dsk.cpp146
-rw-r--r--src/lib/formats/ap2_dsk.h3
-rw-r--r--src/lib/formats/flopimg.cpp15
-rw-r--r--src/lib/formats/flopimg.h5
-rw-r--r--src/lib/formats/mfi_dsk.cpp2
-rw-r--r--src/lib/formats/upd765_dsk.cpp2
-rw-r--r--src/lib/formats/wd177x_dsk.cpp2
7 files changed, 170 insertions, 5 deletions
diff --git a/src/lib/formats/ap2_dsk.cpp b/src/lib/formats/ap2_dsk.cpp
index 3af006fcfc7..082c263c569 100644
--- a/src/lib/formats/ap2_dsk.cpp
+++ b/src/lib/formats/ap2_dsk.cpp
@@ -578,6 +578,8 @@ bool a2_16sect_format::load(io_generic *io, uint32_t form_factor, const std::vec
{
uint64_t size = io_generic_size(io);
+ image->set_form_variant(floppy_image::FF_525, floppy_image::SSSD);
+
m_prodos_order = false;
m_tracks = (size == (40 * 16 * 256)) ? 40 : 35;
@@ -768,6 +770,9 @@ bool a2_16sect_format::save(io_generic *io, const std::vector<uint32_t> &variant
}
image->get_actual_geometry(g_tracks, g_heads);
+ if(!m_tracks)
+ m_tracks = g_tracks;
+
int head = 0;
int pos_data = 0;
@@ -1586,6 +1591,9 @@ bool a2_edd_format::load(io_generic *io, uint32_t form_factor, const std::vector
image->set_write_splice_position(i >> 2, 0, uint32_t(uint64_t(200'000'000)*splice/len), i & 3);
}
free(img);
+
+ image->set_form_variant(floppy_image::FF_525, floppy_image::SSSD);
+
return true;
}
@@ -1613,7 +1621,7 @@ const char *a2_woz_format::extensions() const
bool a2_woz_format::supports_save() const
{
- return false;
+ return true;
}
const uint8_t a2_woz_format::signature[8] = { 0x57, 0x4f, 0x5a, 0x31, 0xff, 0x0a, 0x0d, 0x0a };
@@ -1664,7 +1672,13 @@ bool a2_woz_format::load(io_generic *io, uint32_t form_factor, const std::vector
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;
@@ -1676,6 +1690,8 @@ bool a2_woz_format::load(io_generic *io, uint32_t form_factor, const std::vector
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) {
@@ -1693,8 +1709,10 @@ bool a2_woz_format::load(io_generic *io, uint32_t form_factor, const std::vector
if (r32(img, trks_off + 4) == 0)
return false;
- // TODO: when write capability is added, use the WRIT chunk data if it's present
generate_track_from_bitstream(track, head, &img[boff], r32(img, trks_off + 4), image, subtrack, 0xffff);
+
+ if(is_35 && !track && head)
+ image->set_variant(r32(img, trks_off + 4) >= 90000 ? floppy_image::DSHD : floppy_image::DSDD);
}
}
}
@@ -1703,6 +1721,113 @@ bool a2_woz_format::load(io_generic *io, uint32_t form_factor, const std::vector
return true;
}
+bool a2_woz_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+{
+ 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 != 160; 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, 8*tcount); // 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));
+
+ io_generic_write(io, data.data(), 0, data.size());
+ return true;
+}
+
+
uint32_t a2_woz_format::find_tag(const std::vector<uint8_t> &data, uint32_t tag)
{
uint32_t offset = 12;
@@ -1729,6 +1854,20 @@ uint8_t a2_woz_format::r8(const std::vector<uint8_t> &data, uint32_t offset)
return data[offset];
}
+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;
+}
+
uint32_t a2_woz_format::crc32r(const uint8_t *data, uint32_t size)
{
// Reversed crc32
@@ -1909,6 +2048,9 @@ bool a2_nib_format::load(io_generic *io, uint32_t form_factor, const std::vector
levels,
0, image);
}
+
+ image->set_form_variant(floppy_image::FF_525, floppy_image::SSSD);
+
return true;
}
diff --git a/src/lib/formats/ap2_dsk.h b/src/lib/formats/ap2_dsk.h
index 15b41503ce9..7420d72d818 100644
--- a/src/lib/formats/ap2_dsk.h
+++ b/src/lib/formats/ap2_dsk.h
@@ -113,6 +113,7 @@ public:
virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual bool supports_save() const override;
virtual const char *name() const override;
@@ -126,6 +127,8 @@ private:
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);
};
diff --git a/src/lib/formats/flopimg.cpp b/src/lib/formats/flopimg.cpp
index cb8d6ca1300..595332571ec 100644
--- a/src/lib/formats/flopimg.cpp
+++ b/src/lib/formats/flopimg.cpp
@@ -955,6 +955,21 @@ int floppy_image::get_resolution() const
return 0;
}
+bool floppy_image::track_is_formatted(int track, int head, int subtrack)
+{
+ int idx = track*4 + subtrack;
+ if(int(track_array.size()) <= idx)
+ return false;
+ if(int(track_array[idx].size()) <= head)
+ return false;
+ const auto &data = track_array[idx][head].cell_data;
+ if(data.empty())
+ return false;
+ if(data.size() == 1 && (data[0] & MG_MASK) == MG_N)
+ return false;
+ return true;
+}
+
const char *floppy_image::get_variant_name(uint32_t form_factor, uint32_t variant)
{
switch(variant) {
diff --git a/src/lib/formats/flopimg.h b/src/lib/formats/flopimg.h
index a471167dbfe..661ce4b2ac5 100644
--- a/src/lib/formats/flopimg.h
+++ b/src/lib/formats/flopimg.h
@@ -750,6 +750,8 @@ public:
uint32_t get_variant() const { return variant; }
//! @param v the variant.
void set_variant(uint32_t v) { variant = v; }
+ //! @param v the variant.
+ void set_form_variant(uint32_t f, uint32_t v) { if(form_factor == FF_UNKNOWN) form_factor = f, variant = v; }
/*!
@param track
@@ -783,6 +785,9 @@ public:
//! @return the track resolution (0=full track, 1 = half-track, 2 = quarter track)
int get_resolution() const;
+ //! @return whether a given track is formatted
+ bool track_is_formatted(int track, int head, int subtrack = 0);
+
//! Returns the variant name for the particular disk form factor/variant
//! @param form_factor
//! @param variant
diff --git a/src/lib/formats/mfi_dsk.cpp b/src/lib/formats/mfi_dsk.cpp
index dc6c320042f..df60e5aeec0 100644
--- a/src/lib/formats/mfi_dsk.cpp
+++ b/src/lib/formats/mfi_dsk.cpp
@@ -117,7 +117,7 @@ bool mfi_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
h.cyl_count &= CYLINDER_MASK;
io_generic_read(io, &entries, sizeof(header), (h.cyl_count << resolution)*h.head_count*sizeof(entry));
- image->set_variant(h.variant);
+ image->set_form_variant(h.form_factor, h.variant);
std::vector<uint8_t> compressed;
diff --git a/src/lib/formats/upd765_dsk.cpp b/src/lib/formats/upd765_dsk.cpp
index ce17bd1c4f2..0538dc58010 100644
--- a/src/lib/formats/upd765_dsk.cpp
+++ b/src/lib/formats/upd765_dsk.cpp
@@ -224,7 +224,7 @@ bool upd765_format::load(io_generic *io, uint32_t form_factor, const std::vector
generate_track(desc, track, head, sectors, f.sector_count, total_size, image);
}
- image->set_variant(f.variant);
+ image->set_form_variant(f.form_factor, f.variant);
return true;
}
diff --git a/src/lib/formats/wd177x_dsk.cpp b/src/lib/formats/wd177x_dsk.cpp
index 5a83da6a473..e89fe9b3f6e 100644
--- a/src/lib/formats/wd177x_dsk.cpp
+++ b/src/lib/formats/wd177x_dsk.cpp
@@ -247,7 +247,7 @@ bool wd177x_format::load(io_generic *io, uint32_t form_factor, const std::vector
generate_track(desc, track, head, sectors, tf.sector_count, total_size, image);
}
- image->set_variant(f.variant);
+ image->set_form_variant(f.form_factor, f.variant);
return true;
}