summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/formats
diff options
context:
space:
mode:
author Olivier Galibert <galibert@pobox.com>2022-03-30 14:28:37 +0200
committer Olivier Galibert <galibert@pobox.com>2022-03-30 15:45:35 +0200
commit08f28cee11ce94e6656d4924c7a3c30614811783 (patch)
treeec993e6409ededbc8dfc38c351b92dd1eab6e35f /src/lib/formats
parent40033c809aed228af9b928747a882ee275482c38 (diff)
floppy: Change the internal format to flux changes, update the mfi format accordingly (keep read compatibility with the old mfi)
Diffstat (limited to 'src/lib/formats')
-rw-r--r--src/lib/formats/ap2_dsk.cpp16
-rw-r--r--src/lib/formats/dfi_dsk.cpp16
-rw-r--r--src/lib/formats/flopimg.cpp148
-rw-r--r--src/lib/formats/flopimg.h34
-rw-r--r--src/lib/formats/hxchfe_dsk.cpp19
-rw-r--r--src/lib/formats/mfi_dsk.cpp114
-rw-r--r--src/lib/formats/mfi_dsk.h14
-rw-r--r--src/lib/formats/vt_dsk.cpp94
-rw-r--r--src/lib/formats/vt_dsk.h4
9 files changed, 207 insertions, 252 deletions
diff --git a/src/lib/formats/ap2_dsk.cpp b/src/lib/formats/ap2_dsk.cpp
index 880ab10d092..2b6d6c07c88 100644
--- a/src/lib/formats/ap2_dsk.cpp
+++ b/src/lib/formats/ap2_dsk.cpp
@@ -1674,7 +1674,21 @@ bool a2_woz_format::load(util::random_read &io, uint32_t form_factor, const std:
if (r32(img, trks_off + 4) == 0)
return false;
- generate_track_from_bitstream(track, head, &img[boff], r32(img, trks_off + 4), image, subtrack, 0xffff);
+ 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);
diff --git a/src/lib/formats/dfi_dsk.cpp b/src/lib/formats/dfi_dsk.cpp
index c7afcb2cda0..ea6b23a43f9 100644
--- a/src/lib/formats/dfi_dsk.cpp
+++ b/src/lib/formats/dfi_dsk.cpp
@@ -177,9 +177,7 @@ bool dfi_format::load(util::random_read &io, uint32_t form_factor, const std::ve
#endif
index_count = 0;
//index_polarity = 0;
- uint32_t mg = floppy_image::MG_A;
int tpos = 0;
- buf[tpos++] = mg;
for(int i=0; i<tsize; i++) {
uint8_t v = data[i];
if((v & 0x7f) == 0x7f) // 0x7F : no transition, but a carry (FF is a board-on-fire error and is checked for above)
@@ -202,23 +200,19 @@ bool dfi_format::load(util::random_read &io, uint32_t form_factor, const std::ve
//if (trans_time <= MIN_THRESH) osd_printf_verbose("dfi_dsk: Throwing out short transition of length %d\n", trans_time);
// the normal case: write the transition at the appropriate time
if ((prev_time == 0) || ((trans_time > MIN_THRESH) && (trans_time <= MAX_THRESH))) {
- mg = mg == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
- buf[tpos++] = mg | uint32_t((200000000ULL*cur_time)/index_time);
+ buf[tpos++] = floppy_image::MG_F | uint32_t((200000000ULL*cur_time)/index_time);
prev_time = cur_time;
}
// the long case: we probably missed a transition, stuff an extra guessed one in there to see if it helps
if (trans_time > MAX_THRESH) {
- mg = mg == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
if (((track%2)==0)&&(head==0)) osd_printf_info("dfi_dsk: missed transition, total time for transition is %d\n",trans_time);
#ifndef FAKETRANS_ONE
- buf[tpos++] = mg | uint32_t((200000000ULL*(cur_time-(trans_time/2)))/index_time); // generate imaginary transition at half period
+ buf[tpos++] = floppy_image::MG_F | uint32_t((200000000ULL*(cur_time-(trans_time/2)))/index_time); // generate imaginary transition at half period
#else
- buf[tpos++] = mg | uint32_t((200000000ULL*(cur_time-((trans_time*2)/3)))/index_time);
- mg = mg == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
- buf[tpos++] = mg | uint32_t((200000000ULL*(cur_time-(trans_time/3)))/index_time);
+ buf[tpos++] = floppy_image::MG_F | uint32_t((200000000ULL*(cur_time-((trans_time*2)/3)))/index_time);
+ buf[tpos++] = floppy_image::MG_F | uint32_t((200000000ULL*(cur_time-(trans_time/3)))/index_time);
#endif
- mg = mg == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
- buf[tpos++] = mg | uint32_t(200000000ULL*cur_time/index_time); // generate transition now
+ buf[tpos++] = floppy_image::MG_F | uint32_t(200000000ULL*cur_time/index_time); // generate transition now
prev_time = cur_time;
}
}
diff --git a/src/lib/formats/flopimg.cpp b/src/lib/formats/flopimg.cpp
index 413c69f4a22..c2cb7e18b2b 100644
--- a/src/lib/formats/flopimg.cpp
+++ b/src/lib/formats/flopimg.cpp
@@ -91,9 +91,10 @@ bool floppy_image::track_is_formatted(int track, int head, int subtrack)
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;
+ for(uint32_t mg : data)
+ if((mg & floppy_image::MG_MASK) == floppy_image::MG_F)
+ return true;
+ return false;
}
const char *floppy_image::get_variant_name(uint32_t form_factor, uint32_t variant)
@@ -840,17 +841,11 @@ void floppy_image_format_t::generate_track(const desc_e *desc, int track, int he
generate_track_from_levels(track, head, buffer, 0, image);
}
-void floppy_image_format_t::normalize_times(std::vector<uint32_t> &buffer)
+void floppy_image_format_t::normalize_times(std::vector<uint32_t> &buffer, uint32_t last_position)
{
- unsigned int total_sum = 0;
- for(unsigned int i=0; i != buffer.size(); i++)
- total_sum += buffer[i] & floppy_image::TIME_MASK;
-
- unsigned int current_sum = 0;
for(unsigned int i=0; i != buffer.size(); i++) {
uint32_t time = buffer[i] & floppy_image::TIME_MASK;
- buffer[i] = (buffer[i] & floppy_image::MG_MASK) | (200000000ULL * current_sum / total_sum);
- current_sum += time;
+ buffer[i] = (buffer[i] & floppy_image::MG_MASK) | (200000000ULL * time / last_position);
}
}
@@ -859,36 +854,11 @@ void floppy_image_format_t::generate_track_from_bitstream(int track, int head, c
std::vector<uint32_t> &dest = image->get_buffer(track, head, subtrack);
dest.clear();
- // If the bitstream has an odd number of inversions, one needs to be added.
- // Put in in the middle of the half window after the center inversion, where
- // any fdc ignores it.
-
- int inversions = 0;
for(int i=0; i != track_size; i++)
if(trackbuf[i >> 3] & (0x80 >> (i & 7)))
- inversions++;
- bool need_flux = inversions & 1;
+ dest.push_back(floppy_image::MG_F | (i*2+1));
- uint32_t cbit = floppy_image::MG_A;
- uint32_t count = 0;
- for(int i=0; i != track_size; i++)
- if(trackbuf[i >> 3] & (0x80 >> (i & 7))) {
- dest.push_back(cbit | (count+2));
- cbit = cbit == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
- if(need_flux) {
- need_flux = false;
- dest.push_back(cbit | 1);
- cbit = cbit == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
- count = 1;
- } else
- count = 2;
- } else
- count += 4;
-
- if(count)
- dest.push_back(cbit | count);
-
- normalize_times(dest);
+ normalize_times(dest, track_size*2);
if(splice >= 0 || splice < track_size) {
int splpos = uint64_t(200000000) * splice / track_size;
@@ -902,81 +872,23 @@ void floppy_image_format_t::generate_track_from_levels(int track, int head, std:
splice_pos = splice_pos % trackbuf.size();
uint32_t splice_angular_pos = trackbuf[splice_pos] & floppy_image::TIME_MASK;
- // Check if we need to invert a cell to get an even number of
- // transitions on the whole track
- //
- // Also check if all MG values are valid
-
- int transition_count = 0;
- for(auto & elem : trackbuf) {
- switch(elem & floppy_image::MG_MASK) {
- case MG_1:
- transition_count++;
- break;
-
- case MG_W:
- throw std::runtime_error(util::string_format("Weak bits not yet handled, track %d head %d", track, head));
-
- case MG_0:
- case floppy_image::MG_N:
- case floppy_image::MG_D:
- break;
-
- case floppy_image::MG_A:
- case floppy_image::MG_B:
- default:
- throw std::invalid_argument(util::string_format("Incorrect MG information in generate_track_from_levels, track %d head %d", track, head));
- }
- }
-
- if(transition_count & 1) {
- int pos = splice_pos;
- while((trackbuf[pos] & floppy_image::MG_MASK) != MG_0 && (trackbuf[pos] & floppy_image::MG_MASK) != MG_1) {
- pos++;
- if(pos == int(trackbuf.size()))
- pos = 0;
- if(pos == splice_pos)
- goto meh;
- }
- if((trackbuf[pos] & floppy_image::MG_MASK) == MG_0)
- trackbuf[pos] = (trackbuf[pos] & floppy_image::TIME_MASK) | MG_1;
- else
- trackbuf[pos] = (trackbuf[pos] & floppy_image::TIME_MASK) | MG_0;
-
- meh:
- ;
-
- }
-
- // Maximal number of cells which happens when the buffer is all MG_1/MG_N alternated, which would be 3/2
std::vector<uint32_t> &dest = image->get_buffer(track, head);
dest.clear();
- uint32_t cbit = floppy_image::MG_A;
- uint32_t count = 0;
+ uint32_t total_time = 0;
for(auto & elem : trackbuf) {
uint32_t bit = elem & floppy_image::MG_MASK;
uint32_t time = elem & floppy_image::TIME_MASK;
- if(bit == MG_0) {
- count += time;
- continue;
- }
- if(bit == MG_1) {
- count += time >> 1;
- dest.push_back(cbit | count);
- cbit = cbit == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
- count = time - (time >> 1);
- continue;
- }
- dest.push_back(cbit | count);
- dest.push_back(elem);
- count = 0;
- }
+ if(bit == MG_1)
+ dest.push_back(floppy_image::MG_F | (total_time + (time >> 1)));
+
+ else if(bit != MG_0)
+ dest.push_back(bit | total_time);
- if(count)
- dest.push_back(cbit | count);
+ total_time += time;
+ }
- normalize_times(dest);
+ normalize_times(dest, total_time);
image->set_write_splice_position(track, head, splice_angular_pos);
}
@@ -1390,7 +1302,14 @@ std::vector<bool> floppy_image_format_t::generate_bitstream_from_track(int track
{
std::vector<bool> trackbuf;
std::vector<uint32_t> &tbuf = image->get_buffer(track, head, subtrack);
- if(tbuf.size() <= 1) {
+ bool track_has_info = false;
+ for(uint32_t mg : tbuf)
+ if((mg & floppy_image::MG_MASK) == floppy_image::MG_F) {
+ track_has_info = true;
+ break;
+ }
+
+ if(!track_has_info) {
// Unformatted track
int track_size = 200000000/cell_size;
trackbuf.resize(track_size, false);
@@ -1414,8 +1333,14 @@ std::vector<bool> floppy_image_format_t::generate_bitstream_from_track(int track
uint32_t scanned = 0;
while(scanned < 200000000) {
- // Note that all magnetic cell type changes are considered
- // edges. No randomness added for neutral/damaged cells
+ // Note that only MG_F edges are taken into account, the rest is ignored.
+ // The lack of MG_F has been tested for previously.
+ while((tbuf[cur_entry] & floppy_image::MG_MASK) != floppy_image::MG_F) {
+ cur_entry ++;
+ if(cur_entry == tbuf.size())
+ cur_entry = 0;
+ }
+
int edge = tbuf[cur_entry] & floppy_image::TIME_MASK;
if(edge < cur_pos)
edge += 200000000;
@@ -1474,11 +1399,8 @@ std::vector<bool> floppy_image_format_t::generate_bitstream_from_track(int track
// Wrap around
if(cur_entry == int(tbuf.size())-1 &&
- (tbuf[cur_entry] & floppy_image::TIME_MASK) < cur_pos) {
- // Wrap to index 0 or 1 depending on whether there is a transition exactly at the index hole
- cur_entry = (tbuf[int(tbuf.size())-1] & floppy_image::MG_MASK) != (tbuf[0] & floppy_image::MG_MASK) ?
- 0 : 1;
- }
+ (tbuf[cur_entry] & floppy_image::TIME_MASK) < cur_pos)
+ cur_entry = 0;
}
return trackbuf;
}
diff --git a/src/lib/formats/flopimg.h b/src/lib/formats/flopimg.h
index 2fd07c9f2a7..62daaaa2ac8 100644
--- a/src/lib/formats/flopimg.h
+++ b/src/lib/formats/flopimg.h
@@ -230,8 +230,9 @@ protected:
*/
static void generate_track_from_levels(int track, int head, std::vector<uint32_t> &trackbuf, int splice_pos, floppy_image *image);
- //! Normalize the times in a cell buffer to sum up to 200000000
- static void normalize_times(std::vector<uint32_t> &buffer);
+ //! Normalize the times in a cell buffer to bring the
+ //! 0..last_position range up to 0..200000000
+ static void normalize_times(std::vector<uint32_t> &buffer, uint32_t last_position);
// Some conversion tables for gcr
static const uint8_t gcr5fw_tb[0x10], gcr5bw_tb[0x20];
@@ -450,19 +451,22 @@ private:
//! Internal format is close but not identical to the mfi format.
//!
//!
+
//! Track data consists of a series of 32-bits lsb-first values
-//! representing magnetic cells. Bits 0-27 indicate the absolute
-//! position of the start of the cell (not the size), and bits
-//! 28-31 the type. Type can be:
-//! - 0, MG_A -> Magnetic orientation A
-//! - 1, MG_B -> Magnetic orientation B
-//! - 2, MG_N -> Non-magnetized zone (neutral)
-//! - 3, MG_D -> Damaged zone, reads as neutral but cannot be changed by writing
+//! representing the magnetic state. Bits 0-27 indicate the absolute
+//! position of encoded event, and bits ! 28-31 the type. Type can be:
+//! - 0, MG_F -> Flux orientation change
+//! - 1, MG_N -> Start of a non-magnetized zone (neutral)
+//! - 2, MG_D -> Start of a damaged zone, reads as neutral but cannot be changed by writing
+//! - 3, MG_E -> End of one of the previous zones, *inclusive*
//!
//! The position is in angular units of 1/200,000,000th of a turn.
-//! The last cell implicit end position is of course 200,000,000.
+//! A N or D zone must not wrap at the 200,000,000 position, it has to
+//! be split in two (the first finishing at 199,999,999, the second
+//! starting at 0)
//!
-//! Unformatted tracks are encoded as zero-size.
+//! Unformatted tracks are encoded as zero-size, and are strictly equivalent
+//! to (MG_N, 0), (MG_E, 199,999,999)
//!
//! The "track splice" information indicates where to start writing
//! if you try to rewrite a physical disk with the data. Some
@@ -491,10 +495,10 @@ public:
TIME_MASK = 0x0fffffff,
MG_MASK = 0xf0000000,
MG_SHIFT = 28, //!< Bitshift constant for magnetic orientation data
- MG_A = (0 << MG_SHIFT), //!< - 0, MG_A -> Magnetic orientation A
- MG_B = (1 << MG_SHIFT), //!< - 1, MG_B -> Magnetic orientation B
- MG_N = (2 << MG_SHIFT), //!< - 2, MG_N -> Non-magnetized zone (neutral)
- MG_D = (3 << MG_SHIFT) //!< - 3, MG_D -> Damaged zone, reads as neutral but cannot be changed by writing
+ MG_F = (0 << MG_SHIFT), //!< - 0, MG_F -> Flux orientation change
+ MG_N = (1 << MG_SHIFT), //!< - 1, MG_N -> Non-magnetized zone (neutral)
+ MG_D = (2 << MG_SHIFT), //!< - 2, MG_D -> Damaged zone, reads as neutral but cannot be changed by writing
+ MG_E = (3 << MG_SHIFT) //!< - 3, MG_E -> End of zone
};
diff --git a/src/lib/formats/hxchfe_dsk.cpp b/src/lib/formats/hxchfe_dsk.cpp
index ba9d877a537..9a8047816c7 100644
--- a/src/lib/formats/hxchfe_dsk.cpp
+++ b/src/lib/formats/hxchfe_dsk.cpp
@@ -316,17 +316,11 @@ void hfe_format::generate_track_from_hfe_bitstream(int cyl, int head, int sample
// HFE does not define subtracks; set to 0
// MG_1 / MG_0 are (logical) levels that indicate transition / no change
- // MG_A / MG_B are physical flux directions
- //
- // Cell: | AAAABBBB | = MG_1 = | BBBBAAAA |
- // | AAAAAAAA | = MG_0 = | BBBBBBBB |
+ // MG_F is the position of a flux transition
std::vector<uint32_t> &dest = image->get_buffer(cyl, head, 0);
dest.clear();
- // Start with MG_A
- uint32_t cbit = floppy_image::MG_A;
-
int offset = 0x100;
if (head==0)
@@ -338,10 +332,6 @@ void hfe_format::generate_track_from_hfe_bitstream(int cyl, int head, int sample
uint8_t current = 0;
int time = 0;
- dest.push_back(cbit | time);
-
- cbit = floppy_image::MG_B;
-
// Oversampled FM images (250 kbit/s) start with a 0, where a 1 is
// expected for 125 kbit/s.
// In order to make an oversampled image look like a normally sampled one,
@@ -384,13 +374,8 @@ void hfe_format::generate_track_from_hfe_bitstream(int cyl, int head, int sample
{
time += samplelength;
if ((current & 1)!=0)
- {
// Append another transition to the vector
- dest.push_back(cbit | time);
-
- // Toggle the cell level
- cbit = (cbit == floppy_image::MG_A)? floppy_image::MG_B : floppy_image::MG_A;
- }
+ dest.push_back(floppy_image::MG_F | time);
// HFE uses little-endian bit order
current >>= 1;
diff --git a/src/lib/formats/mfi_dsk.cpp b/src/lib/formats/mfi_dsk.cpp
index 59310f2bb65..b3d75a2a60e 100644
--- a/src/lib/formats/mfi_dsk.cpp
+++ b/src/lib/formats/mfi_dsk.cpp
@@ -7,6 +7,7 @@
#include <zlib.h>
#include <cstring>
+#include <functional>
/*
@@ -31,31 +32,27 @@
simple "compress" function.
Track data consists of a series of 32-bits lsb-first values
- representing magnetic cells. Bits 0-27 indicate the sizes, and bits
- 28-31 the types. Type can be:
- - 0, MG_A -> Magnetic orientation A
- - 1, MG_B -> Magnetic orientation B
- - 2, MG_N -> Non-magnetized zone (neutral)
- - 3, MG_D -> Damaged zone, reads as neutral but cannot be changed by writing
+ representing magnetic cells. Bits 0-27 indicate the position,
+ delta-packed (e.g. difference with the previous position, starts at
+ 0), and bits 28-31 the types. Type can be:
- Remember that the fdcs detect transitions, not absolute levels, so
- the actual physical significance of the orientation A and B is
- arbitrary.
+ - 0, MG_F -> Flux orientation change
+ - 1, MG_N -> Non-magnetized zone (neutral)
+ - 2, MG_D -> Damaged zone, reads as neutral but cannot be changed by writing
+ - 3, MG_E -> End of zone
Tracks data is aligned so that the index pulse is at the start,
whether the disk is hard-sectored or not.
- The size is the angular size in units of 1/200,000,000th of a turn.
- Such a size, not coincidentally at all, is also the flyover time in
- nanoseconds for a perfectly stable 300rpm drive. That makes the
- standard cell size of a MFM 3.5" DD floppy at 2000 exactly for
- instance (2us). Smallest expected cell size is 500 (ED density
- drives).
+ The position is the angular position in units of 1/200,000,000th of
+ a turn. A size in such units, not coincidentally at all, is also
+ the flyover time in nanoseconds for a perfectly stable 300rpm drive.
+ That makes the standard cell size of a MFM 3.5" DD floppy at 2000
+ exactly for instance (2us). Smallest expected cell size is 500 (ED
+ density drives).
- The sum of all sizes must of course be 200,000,000.
-
- An unformatted track is equivalent to one big MG_N cell covering a
- whole turn, but is encoded as zero-size.
+ An unformatted track is equivalent to a pair (MG_N, 0), (MG_E,
+ 199999999) but is encoded as zero-size.
The "track splice" information indicates where to start writing
if you try to rewrite a physical disk with the data. Some
@@ -72,7 +69,8 @@
TODO: big-endian support
*/
-const char mfi_format::sign[16] = "MESSFLOPPYIMAGE"; // Includes the final \0
+const char mfi_format::sign_old[16] = "MESSFLOPPYIMAGE"; // Includes the final \0
+const char mfi_format::sign[16] = "MAMEFLOPPYIMAGE"; // Includes the final \0
mfi_format::mfi_format() : floppy_image_format_t()
{
@@ -85,7 +83,7 @@ const char *mfi_format::name() const
const char *mfi_format::description() const
{
- return "MESS floppy image";
+ return "MAME floppy image";
}
const char *mfi_format::extensions() const
@@ -104,7 +102,7 @@ int mfi_format::identify(util::random_read &io, uint32_t form_factor, const std:
size_t actual;
io.read_at(0, &h, sizeof(header), actual);
- if(memcmp( h.sign, sign, 16 ) == 0 &&
+ if((memcmp( h.sign, sign, 16) == 0 || memcmp( h.sign, sign_old, 16) == 0) &&
(h.cyl_count & CYLINDER_MASK) <= 84 &&
(h.cyl_count >> RESOLUTION_SHIFT) < 3 &&
h.head_count <= 2 &&
@@ -129,7 +127,46 @@ bool mfi_format::load(util::random_read &io, uint32_t form_factor, const std::ve
if(!h.cyl_count)
return true;
+ std::function<void (const std::vector<uint32_t> &src, std::vector<uint32_t> &track)> converter;
+
+ if(!memcmp( h.sign, sign, 16)) {
+ converter = [](const std::vector<uint32_t> &src, std::vector<uint32_t> &track) -> void {
+ uint32_t ctime = 0;
+ for(uint32_t mg : src) {
+ ctime += mg & TIME_MASK;
+ track.push_back((mg & MG_MASK) | ctime);
+ }
+ };
+
+ } else {
+ converter = [](const std::vector<uint32_t> &src, std::vector<uint32_t> &track) -> void {
+ unsigned int cell_count = src.size();
+ uint32_t mg = src[0] & MG_MASK;
+ uint32_t wmg = src[cell_count - 1] & MG_MASK;
+ if(mg != wmg && (mg == OLD_MG_A || mg == OLD_MG_B) && (wmg == OLD_MG_A && wmg == OLD_MG_B))
+ // Flux change at 0, add it
+ track.push_back(MG_F | 0);
+
+ uint32_t ctime = 0;
+ for(unsigned int i=0; i != cell_count; i++) {
+ uint32_t nmg = src[i] & MG_MASK;
+ if(nmg == OLD_MG_N || nmg == OLD_MG_D) {
+ track.push_back((nmg == OLD_MG_N ? MG_N : MG_D) | ctime);
+ ctime += src[i] & TIME_MASK;
+ track.push_back(MG_E | (ctime-1));
+ nmg = 0xffffffff;
+ } else {
+ if(mg != 0xffffffff && mg != nmg)
+ track.push_back(MG_F | ctime);
+ ctime += src[i] & TIME_MASK;
+ }
+ mg = nmg;
+ }
+ };
+ }
+
std::vector<uint8_t> compressed;
+ std::vector<uint32_t> uncompressed;
entry *ent = entries;
for(unsigned int cyl=0; cyl <= (h.cyl_count - 1) << 2; cyl += 4 >> resolution)
@@ -143,31 +180,22 @@ bool mfi_format::load(util::random_read &io, uint32_t form_factor, const std::ve
continue;
}
+ unsigned int cell_count = ent->uncompressed_size/4;
compressed.resize(ent->compressed_size);
+ uncompressed.resize(cell_count);
io.read_at(ent->offset, &compressed[0], ent->compressed_size, actual);
- unsigned int cell_count = ent->uncompressed_size/4;
- std::vector<uint32_t> &trackbuf = image->get_buffer(cyl >> 2, head, cyl & 3);;
- trackbuf.resize(cell_count);
-
uLongf size = ent->uncompressed_size;
- if(uncompress((Bytef *)&trackbuf[0], &size, &compressed[0], ent->compressed_size) != Z_OK) {
+ if(uncompress((Bytef *)uncompressed.data(), &size, &compressed[0], ent->compressed_size) != Z_OK) {
fprintf(stderr, "fail1\n");
return false;
}
- uint32_t cur_time = 0;
- for(unsigned int i=0; i != cell_count; i++) {
- uint32_t next_cur_time = cur_time + (trackbuf[i] & TIME_MASK);
- trackbuf[i] = (trackbuf[i] & MG_MASK) | cur_time;
- cur_time = next_cur_time;
- }
- if(cur_time != 200000000) {
- fprintf(stderr, "fail2 %d\n", cur_time);
- return false;
- }
+ std::vector<uint32_t> &trackbuf = image->get_buffer(cyl >> 2, head, cyl & 3);;
+ trackbuf.clear();
+ converter(uncompressed, trackbuf);
ent++;
}
@@ -214,13 +242,11 @@ bool mfi_format::save(util::random_read_write &io, const std::vector<uint32_t> &
continue;
}
- memcpy(&precomp[0], &buffer[0], tsize*4);
- for(int j=0; j<tsize-1; j++)
- precomp[j] = (precomp[j] & floppy_image::MG_MASK) |
- ((precomp[j+1] & floppy_image::TIME_MASK) -
- (precomp[j] & floppy_image::TIME_MASK));
- precomp[tsize-1] = (precomp[tsize-1] & floppy_image::MG_MASK) |
- (200000000 - (precomp[tsize-1] & floppy_image::TIME_MASK));
+ uint32_t ctime = 0;
+ for(int i=0; i != tsize; i++) {
+ precomp[i] = (buffer[i] & MG_MASK) | ((buffer[i] & TIME_MASK) - ctime);
+ ctime = buffer[i] & TIME_MASK;
+ }
uLongf csize = max_track_size*4 + 1000;
if(compress(postcomp.get(), &csize, (const Bytef *)precomp.get(), tsize*4) != Z_OK)
diff --git a/src/lib/formats/mfi_dsk.h b/src/lib/formats/mfi_dsk.h
index b1c3e783044..93a95c81657 100644
--- a/src/lib/formats/mfi_dsk.h
+++ b/src/lib/formats/mfi_dsk.h
@@ -27,15 +27,21 @@ private:
MG_MASK = 0xf0000000,
MG_SHIFT = 28,
- MG_A = (0 << MG_SHIFT),
- MG_B = (1 << MG_SHIFT),
- MG_N = (2 << MG_SHIFT),
- MG_D = (3 << MG_SHIFT),
+ OLD_MG_A = (0 << MG_SHIFT),
+ OLD_MG_B = (1 << MG_SHIFT),
+ OLD_MG_N = (2 << MG_SHIFT),
+ OLD_MG_D = (3 << MG_SHIFT),
+
+ MG_F = (0 << MG_SHIFT), //!< - 0, MG_F -> Flux orientation change
+ MG_N = (1 << MG_SHIFT), //!< - 1, MG_N -> Non-magnetized zone (neutral)
+ MG_D = (2 << MG_SHIFT), //!< - 2, MG_D -> Damaged zone, reads as neutral but cannot be changed by writing
+ MG_E = (3 << MG_SHIFT), //!< - 3, MG_E -> End of zone
RESOLUTION_SHIFT = 30,
CYLINDER_MASK = 0x3fffffff
};
+ static const char sign_old[16];
static const char sign[16];
struct header {
diff --git a/src/lib/formats/vt_dsk.cpp b/src/lib/formats/vt_dsk.cpp
index c01906e7df3..957efab67ba 100644
--- a/src/lib/formats/vt_dsk.cpp
+++ b/src/lib/formats/vt_dsk.cpp
@@ -17,23 +17,20 @@
// One = | 2237 | 6950 |
// 0.5us ~= 143
-void vtech_common_format::wbit(std::vector<uint32_t> &buffer, uint32_t &pos, uint32_t &mg, bool bit)
+void vtech_common_format::wbit(std::vector<uint32_t> &buffer, uint32_t &pos, bool bit)
{
- buffer.push_back(pos | mg);
- mg = mg == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
if(bit) {
pos += 2237;
- buffer.push_back(pos | mg);
- mg = mg == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
+ buffer.push_back(pos | floppy_image::MG_F);
pos += 6950;
} else
pos += 9187;
}
-void vtech_common_format::wbyte(std::vector<uint32_t> &buffer, uint32_t &pos, uint32_t &mg, uint8_t byte)
+void vtech_common_format::wbyte(std::vector<uint32_t> &buffer, uint32_t &pos, uint8_t byte)
{
for(int i = 7; i >= 0; i--)
- wbit(buffer, pos, mg, (byte >> i) & 1);
+ wbit(buffer, pos, (byte >> i) & 1);
}
void vtech_common_format::image_to_flux(const std::vector<uint8_t> &bdata, floppy_image *image)
@@ -44,40 +41,39 @@ void vtech_common_format::image_to_flux(const std::vector<uint8_t> &bdata, flopp
for(int track = 0; track != 40; track ++) {
uint32_t pos = 0;
- uint32_t mg = floppy_image::MG_A;
std::vector<uint32_t> &buffer = image->get_buffer(track, 0);
buffer.clear();
image->set_write_splice_position(track, 0, 0);
// One window of pad at the start to avoid problems with the write splice
- wbit(buffer, pos, mg, 0);
+ wbit(buffer, pos, 0);
for(int sector = 0; sector != 16; sector ++) {
uint8_t sid = sector_map[sector];
for(int i=0; i != 7; i++)
- wbyte(buffer, pos, mg, 0x80);
- wbyte(buffer, pos, mg, 0x00);
- wbyte(buffer, pos, mg, 0xfe);
- wbyte(buffer, pos, mg, 0xe7);
- wbyte(buffer, pos, mg, 0x18);
- wbyte(buffer, pos, mg, 0xc3);
- wbyte(buffer, pos, mg, track);
- wbyte(buffer, pos, mg, sid);
- wbyte(buffer, pos, mg, track+sid);
+ wbyte(buffer, pos, 0x80);
+ wbyte(buffer, pos, 0x00);
+ wbyte(buffer, pos, 0xfe);
+ wbyte(buffer, pos, 0xe7);
+ wbyte(buffer, pos, 0x18);
+ wbyte(buffer, pos, 0xc3);
+ wbyte(buffer, pos, track);
+ wbyte(buffer, pos, sid);
+ wbyte(buffer, pos, track+sid);
for(int i=0; i != 5; i++)
- wbyte(buffer, pos, mg, 0x80);
- wbyte(buffer, pos, mg, 0x00);
- wbyte(buffer, pos, mg, 0xc3);
- wbyte(buffer, pos, mg, 0x18);
- wbyte(buffer, pos, mg, 0xe7);
- wbyte(buffer, pos, mg, 0xfe);
+ wbyte(buffer, pos, 0x80);
+ wbyte(buffer, pos, 0x00);
+ wbyte(buffer, pos, 0xc3);
+ wbyte(buffer, pos, 0x18);
+ wbyte(buffer, pos, 0xe7);
+ wbyte(buffer, pos, 0xfe);
uint16_t chk = 0;
const uint8_t *src = bdata.data() + 16*128*track + 128*sid;
for(int i=0; i != 128; i++) {
chk += src[i];
- wbyte(buffer, pos, mg, src[i]);
+ wbyte(buffer, pos, src[i]);
}
- wbyte(buffer, pos, mg, chk);
- wbyte(buffer, pos, mg, chk >> 8);
+ wbyte(buffer, pos, chk);
+ wbyte(buffer, pos, chk >> 8);
}
// Rest is just not formatted
buffer.push_back(pos | floppy_image::MG_N);
@@ -95,29 +91,37 @@ std::vector<uint8_t> vtech_common_format::flux_to_image(floppy_image *image)
continue;
std::vector<bool> bitstream;
- int lpos = -1;
- bool looped = !((buffer[sz-1] ^ buffer[0]) & floppy_image::MG_MASK);
- int cpos = looped ? sz-1 : 0;
- while(cpos != lpos) {
- int dt = looped && cpos == sz-1 ? (200000000 - (buffer[cpos] & floppy_image::TIME_MASK)) + (buffer[1] & floppy_image::TIME_MASK) :
- cpos == sz-1 ? 200000000 - (buffer[cpos] & floppy_image::TIME_MASK) :
- (buffer[cpos+1] & floppy_image::TIME_MASK) - (buffer[cpos] & floppy_image::TIME_MASK);
- int t = dt >= 9187 - 143 ? 0 :
- dt >= 2237 - 143 && dt <= 2237 + 143 ? 1 :
- 2;
- if(t <= 1) {
- if(lpos == -1)
- lpos = cpos;
- bitstream.push_back(t);
+ int cpos = 0;
+ while((buffer[cpos] & floppy_image::MG_MASK) != floppy_image::MG_F) {
+ cpos++;
+ if(cpos == sz) {
+ cpos = -1;
+ break;
}
- cpos += 1;
- if(cpos == sz)
- cpos = looped ? 1 : 0;
+ }
+ if(cpos == -1)
+ continue;
+ for(;;) {
+ int npos = cpos;
+ for(;;) {
+ npos ++;
+ if(npos == sz)
+ npos = 0;
+ if((buffer[npos] & floppy_image::MG_MASK) == floppy_image::MG_F)
+ break;
+ }
+ int dt = (buffer[npos] & floppy_image::TIME_MASK) - (buffer[cpos] & floppy_image::TIME_MASK);
+ if(dt < 0)
+ cpos += 200000000;
+ bitstream.push_back(dt < 9187 - 143);
+ if(npos <= cpos)
+ break;
+ cpos = npos;
}
int mode = 0;
- looped = false;
int pos = 0;
int count = 0;
+ bool looped = false;
uint8_t *dest = nullptr;
[[maybe_unused]] uint16_t checksum = 0;
uint64_t buf = 0;
diff --git a/src/lib/formats/vt_dsk.h b/src/lib/formats/vt_dsk.h
index dacdb19d90d..5711ae07cdb 100644
--- a/src/lib/formats/vt_dsk.h
+++ b/src/lib/formats/vt_dsk.h
@@ -22,8 +22,8 @@ protected:
static void image_to_flux(const std::vector<uint8_t> &bdata, floppy_image *image);
static std::vector<uint8_t> flux_to_image(floppy_image *image);
- static void wbit(std::vector<uint32_t> &buffer, uint32_t &pos, uint32_t &mg, bool bit);
- static void wbyte(std::vector<uint32_t> &buffer, uint32_t &pos, uint32_t &mg, uint8_t byte);
+ static void wbit(std::vector<uint32_t> &buffer, uint32_t &pos, bool bit);
+ static void wbyte(std::vector<uint32_t> &buffer, uint32_t &pos, uint8_t byte);
};
class vtech_bin_format : public vtech_common_format {