summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/formats/imd_dsk.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/formats/imd_dsk.cpp')
-rw-r--r--src/lib/formats/imd_dsk.cpp318
1 files changed, 162 insertions, 156 deletions
diff --git a/src/lib/formats/imd_dsk.cpp b/src/lib/formats/imd_dsk.cpp
index 631eac9b297..907440dc922 100644
--- a/src/lib/formats/imd_dsk.cpp
+++ b/src/lib/formats/imd_dsk.cpp
@@ -2,15 +2,19 @@
// copyright-holders:Miodrag Milanovic
/*********************************************************************
- formats/imd_dsk.c
+ formats/imd_dsk.cpp
IMD disk images
*********************************************************************/
#include "imd_dsk.h"
+#include "flopimg_legacy.h"
+
+#include "ioprocs.h"
+
+#include "osdcore.h" // osd_printf_*
-#include <cassert>
#include <cstring>
@@ -19,6 +23,7 @@ struct imddsk_tag
{
int heads;
int tracks;
+ int track_sectors[84*2]; /* number of sectors for each track */
int sector_size;
uint64_t track_offsets[84*2]; /* offset within data for each track */
};
@@ -56,6 +61,11 @@ static int imd_get_tracks_per_disk(floppy_image_legacy *floppy)
return get_tag(floppy)->tracks;
}
+static int imd_get_sectors_per_track(floppy_image_legacy *floppy, int head, int track)
+{
+ return get_tag(floppy)->track_sectors[(track<<1) + head];
+}
+
static uint64_t imd_get_track_offset(floppy_image_legacy *floppy, int head, int track)
{
return get_tag(floppy)->track_offsets[(track<<1) + head];
@@ -208,7 +218,7 @@ static floperr_t imd_write_indexed_sector(floppy_image_legacy *floppy, int head,
if (err) {
return err;
}
- // Fall through!
+ [[fallthrough]];
case 1:
case 3:
@@ -330,9 +340,11 @@ FLOPPY_CONSTRUCT( imd_dsk_construct )
tag->heads = 1;
do {
floppy_image_read(floppy, header, pos, 5);
- if ((header[2] & 1)==1) tag->heads = 2;
- tag->track_offsets[(header[1]<<1) + (header[2] & 1)] = pos;
sector_num = header[3];
+ int track = (header[1]<<1) + (header[2] & 1);
+ if ((header[2] & 1)==1) tag->heads = 2;
+ tag->track_offsets[track] = pos;
+ tag->track_sectors[track] = sector_num;
pos += 5 + sector_num; // skip header and sector numbering map
if(header[2] & 0x80) pos += sector_num; // skip cylinder numbering map
if(header[2] & 0x40) pos += sector_num; // skip head numbering map
@@ -361,6 +373,7 @@ FLOPPY_CONSTRUCT( imd_dsk_construct )
callbacks->get_heads_per_disk = imd_get_heads_per_disk;
callbacks->get_tracks_per_disk = imd_get_tracks_per_disk;
callbacks->get_indexed_sector_info = imd_get_indexed_sector_info;
+ callbacks->get_sectors_per_track = imd_get_sectors_per_track;
return FLOPPY_ERROR_SUCCESS;
}
@@ -370,7 +383,7 @@ FLOPPY_CONSTRUCT( imd_dsk_construct )
// copyright-holders:Olivier Galibert
/*********************************************************************
- formats/imd_dsk.c
+ formats/imd_dsk.cpp
IMD disk images
@@ -380,17 +393,17 @@ imd_format::imd_format()
{
}
-const char *imd_format::name() const
+const char *imd_format::name() const noexcept
{
return "imd";
}
-const char *imd_format::description() const
+const char *imd_format::description() const noexcept
{
return "IMD disk image";
}
-const char *imd_format::extensions() const
+const char *imd_format::extensions() const noexcept
{
return "imd";
}
@@ -409,116 +422,199 @@ void imd_format::fixnum(char *start, char *end) const
};
}
-int imd_format::identify(io_generic *io, uint32_t form_factor)
+int imd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
char h[4];
+ auto const [err, actual] = read_at(io, 0, h, 4);
+ if(err || (4 != actual))
+ return 0;
- io_generic_read(io, h, 0, 4);
if(!memcmp(h, "IMD ", 4))
- return 100;
+ return FIFID_SIGN;
return 0;
}
-bool imd_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
+bool imd_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
- uint64_t size = io_generic_size(io);
- std::vector<uint8_t> img(size);
- io_generic_read(io, &img[0], 0, size);
+ std::vector<uint8_t> comment;
+ std::vector<std::vector<uint8_t> > snum;
+ std::vector<std::vector<uint8_t> > tnum;
+ std::vector<std::vector<uint8_t> > hnum;
+
+ std::vector<uint8_t> mode;
+ std::vector<uint8_t> track;
+ std::vector<uint8_t> head;
+ std::vector<uint8_t> sector_count;
+ std::vector<uint8_t> ssize;
+
+ int trackmult;
+ uint64_t size;
+ if(io.length(size))
+ return false;
+ auto const [err, img, actual] = read_at(io, 0, size);
+ if(err || (actual != size))
+ return false;
- uint64_t pos;
- for(pos=0; pos < size && img[pos] != 0x1a; pos++) {};
+ uint64_t pos, savepos;
+ for(pos=0; pos < size && img[pos] != 0x1a; pos++) { }
pos++;
- m_comment.resize(pos);
- memcpy(&m_comment[0], &img[0], pos);
+ comment.resize(pos);
+ memcpy(&comment[0], &img[0], pos);
if(pos >= size)
return false;
int tracks, heads;
- image->get_maximal_geometry(tracks, heads);
+ image.get_maximal_geometry(tracks, heads);
+
+ mode.clear();
+ track.clear();
+ head.clear();
+ sector_count.clear();
+ ssize.clear();
+ trackmult = 1;
+
+ // we have to walk the whole file to find out the number of tracks
+ savepos = pos;
+ uint8_t maxtrack = 0;
+ while(pos < size)
+ {
+ pos++; // skip mode
+ uint8_t track = img[pos++];
+ uint8_t head = img[pos++];
+ uint8_t sector_count = img[pos++];
+ uint8_t sector_size = img[pos++];
+ int actual_size = sector_size < 7 ? 128 << sector_size : 8192;
+
+ if (track > maxtrack)
+ {
+ maxtrack = track;
+ }
+
+ pos += sector_count;
+ if (head & 0x80)
+ {
+ pos += sector_count;
+ }
+ if (head & 0x40)
+ {
+ pos += sector_count;
+ }
+
+ for (int i = 0; i < sector_count; i++)
+ {
+ uint8_t stype = img[pos++];
+ if (stype == 0 || stype > 8)
+ {
+ }
+ else
+ {
+ if (stype == 2 || stype == 4 || stype == 6 || stype == 8)
+ {
+ pos++;
+ }
+ else
+ {
+ pos += actual_size;
+ }
+ }
+ }
+ }
- m_mode.clear();
- m_track.clear();
- m_head.clear();
- m_sector_count.clear();
- m_ssize.clear();
+ if(form_factor == floppy_image::FF_525)
+ {
+ // On 5.25, check if the drive is QD or HD but we're a 40 track
+ // image. If so, put the image on even tracks.
+ if ((has_variant(variants, floppy_image::DSQD)) ||
+ (has_variant(variants, floppy_image::DSHD)))
+ {
+ if (maxtrack <= 39)
+ trackmult = 2;
+ }
+ else
+ {
+ if (maxtrack > 42)
+ return false;
+ }
+ }
+ pos = savepos;
while(pos < size) {
- m_mode.push_back(img[pos++]);
- m_track.push_back(img[pos++]);
- m_head.push_back(img[pos++]);
- m_sector_count.push_back(img[pos++]);
- m_ssize.push_back(img[pos++]);
+ mode.push_back(img[pos++]);
+ track.push_back(img[pos++]);
+ head.push_back(img[pos++]);
+ sector_count.push_back(img[pos++]);
+ ssize.push_back(img[pos++]);
- if(m_track.back() >= tracks)
+ if(track.back() >= tracks)
{
- osd_printf_error("imd_format: Track %d exceeds maximum of %d\n", m_track.back(), tracks);
+ osd_printf_error("imd_format: Track %d exceeds maximum of %d\n", track.back(), tracks);
return false;
}
- if((m_head.back() & 0x3f) >= heads)
+ if((head.back() & 0x3f) >= heads)
{
- osd_printf_error("imd_format: Head %d exceeds maximum of %d\n", m_head.back() & 0x3f, heads);
+ osd_printf_error("imd_format: Head %d exceeds maximum of %d\n", head.back() & 0x3f, heads);
return false;
}
- if(m_ssize.back() == 0xff)
+ if(ssize.back() == 0xff)
{
- osd_printf_error("imd_format: Unsupported variable sector size on track %d head %d", m_track.back(), m_head.back() & 0x3f);
+ osd_printf_error("imd_format: Unsupported variable sector size on track %d head %d", track.back(), head.back() & 0x3f);
return false;
}
- uint32_t actual_size = m_ssize.back() < 7 ? 128 << m_ssize.back() : 8192;
+ uint32_t actual_size = ssize.back() < 7 ? 128 << ssize.back() : 8192;
static const int rates[3] = { 500000, 300000, 250000 };
- bool fm = m_mode.back() < 3;
- int rate = rates[m_mode.back() % 3];
+ bool fm = mode.back() < 3;
+ int rate = rates[mode.back() % 3];
int rpm = form_factor == floppy_image::FF_8 || (form_factor == floppy_image::FF_525 && rate >= 300000) ? 360 : 300;
int cell_count = (fm ? 1 : 2)*rate*60/rpm;
//const uint8_t *snum = &img[pos];
- m_snum.push_back(std::vector<uint8_t>(m_sector_count.back()));
- memcpy(&m_snum.back()[0], &img[pos], m_sector_count.back());
- pos += m_sector_count.back();
+ snum.push_back(std::vector<uint8_t>(sector_count.back()));
+ memcpy(&snum.back()[0], &img[pos], sector_count.back());
+ pos += sector_count.back();
//const uint8_t *tnum = head & 0x80 ? &img[pos] : nullptr;
- if (m_head.back() & 0x80)
+ if (head.back() & 0x80)
{
- m_tnum.push_back(std::vector<uint8_t>(m_sector_count.back()));
- memcpy(&m_tnum.back()[0], &img[pos], m_sector_count.back());
- pos += m_sector_count.back();
+ tnum.push_back(std::vector<uint8_t>(sector_count.back()));
+ memcpy(&tnum.back()[0], &img[pos], sector_count.back());
+ pos += sector_count.back();
}
else
{
- m_tnum.push_back(std::vector<uint8_t>(0));
+ tnum.push_back(std::vector<uint8_t>(0));
}
//const uint8_t *hnum = head & 0x40 ? &img[pos] : nullptr;
- if (m_head.back() & 0x40)
+ if (head.back() & 0x40)
{
- m_hnum.push_back(std::vector<uint8_t>(m_sector_count.back()));
- memcpy(&m_hnum.back()[0], &img[pos], m_sector_count.back());
- pos += m_sector_count.back();
+ hnum.push_back(std::vector<uint8_t>(sector_count.back()));
+ memcpy(&hnum.back()[0], &img[pos], sector_count.back());
+ pos += sector_count.back();
}
else
{
- m_hnum.push_back(std::vector<uint8_t>(0));
+ hnum.push_back(std::vector<uint8_t>(0));
}
- uint8_t head = m_head.back() & 0x3f;
+ uint8_t chead = head.back() & 0x3f;
int gap_3 = calc_default_pc_gap3_size(form_factor, actual_size);
desc_pc_sector sects[256];
- for(int i=0; i<m_sector_count.back(); i++) {
+ for(int i=0; i<sector_count.back(); i++) {
uint8_t stype = img[pos++];
- sects[i].track = m_tnum.back().size() ? m_tnum.back()[i] : m_track.back();
- sects[i].head = m_hnum.back().size() ? m_hnum.back()[i] : m_head.back();
- sects[i].sector = m_snum.back()[i];
- sects[i].size = m_ssize.back();
+ sects[i].track = tnum.back().size() ? tnum.back()[i] : track.back();
+ sects[i].head = hnum.back().size() ? hnum.back()[i] : head.back();
+ sects[i].sector = snum.back()[i];
+ sects[i].size = ssize.back();
sects[i].actual_size = actual_size;
if(stype == 0 || stype > 8) {
@@ -537,15 +633,15 @@ bool imd_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
}
}
- if(m_sector_count.back()) {
+ if(sector_count.back()) {
if(fm) {
- build_pc_track_fm(m_track.back(), head, image, cell_count, m_sector_count.back(), sects, gap_3);
+ build_pc_track_fm(track.back()*trackmult, chead, image, cell_count, sector_count.back(), sects, gap_3);
} else {
- build_pc_track_mfm(m_track.back(), head, image, cell_count, m_sector_count.back(), sects, gap_3);
+ build_pc_track_mfm(track.back()*trackmult, chead, image, cell_count, sector_count.back(), sects, gap_3);
}
}
- for(int i=0; i< m_sector_count.back(); i++)
+ for(int i=0; i< sector_count.back(); i++)
if(sects[i].data && (sects[i].data < &img[0] || sects[i].data >= (&img[0] + size)))
delete [] sects[i].data;
}
@@ -553,99 +649,9 @@ bool imd_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
return true;
}
-bool can_compress(const uint8_t* buffer, uint8_t ptrn, uint64_t size)
-{
- for (; size > 0; size--)
- if (*buffer++ != ptrn)
- return false;
- return true;
-}
-
-bool imd_format::save(io_generic* io, floppy_image* image)
-{
- uint64_t pos = 0;
- io_generic_write(io, &m_comment[0], pos, m_comment.size());
- pos += m_comment.size();
-
- for (int i = 0; i < m_mode.size(); i++)
- {
- io_generic_write(io, &m_mode[i], pos++, 1);
- io_generic_write(io, &m_track[i], pos++, 1);
- io_generic_write(io, &m_head[i], pos++, 1);
- io_generic_write(io, &m_sector_count[i], pos++, 1);
- io_generic_write(io, &m_ssize[i], pos++, 1);
-
- io_generic_write(io, &m_snum[i][0], pos, m_sector_count[i]);
- pos += m_sector_count[i];
-
- if (m_tnum[i].size())
- {
- io_generic_write(io, &m_tnum[i][0], pos, m_sector_count[i]);
- pos += m_sector_count[i];
- }
-
- if (m_hnum[i].size())
- {
- io_generic_write(io, &m_hnum[i][0], pos, m_sector_count[i]);
- pos += m_sector_count[i];
- }
-
- uint32_t actual_size = m_ssize[i] < 7 ? 128 << m_ssize[i] : 8192;
- uint8_t head = m_head[i] & 0x3f;
-
- bool fm = m_mode[i]< 3;
-
- uint8_t bitstream[500000 / 8];
- uint8_t sector_data[50000];
- desc_xs sectors[256];
- int track_size;
- generate_bitstream_from_track(m_track[i], head, 2000, bitstream, track_size, image);
- if (fm)
- extract_sectors_from_bitstream_fm_pc(bitstream, track_size, sectors, sector_data, sizeof(sector_data));
- else
- extract_sectors_from_bitstream_mfm_pc(bitstream, track_size, sectors, sector_data, sizeof(sector_data));
-
- uint8_t sdata[8192];
- for (int j = 0; j < m_sector_count[i]; j++) {
-
- desc_xs& xs = sectors[m_snum[i][j]];
-
- uint8_t mode;
- if (!xs.data)
- {
- mode = 0;
- io_generic_write(io, &mode, pos++, 1);
- continue;
- }
- else if (xs.size < actual_size) {
- memcpy((void*)sdata, xs.data, xs.size);
- memset((uint8_t*)sdata + xs.size, 0, xs.size - actual_size);
- }
- else
- memcpy((void*)sdata, xs.data, actual_size);
-
- if (can_compress(sdata, sdata[0], actual_size))
- {
- mode = 2;
- io_generic_write(io, &mode, pos++, 1);
- io_generic_write(io, &sdata[0], pos++, 1);
- }
- else
- {
- mode = 1;
- io_generic_write(io, &mode, pos++, 1);
- io_generic_write(io, &sdata, pos, actual_size);
- pos += actual_size;
- }
- }
- }
-
- return true;
-}
-
-bool imd_format::supports_save() const
+bool imd_format::supports_save() const noexcept
{
- return true;
+ return false;
}
-const floppy_format_type FLOPPY_IMD_FORMAT = &floppy_image_format_creator<imd_format>;
+const imd_format FLOPPY_IMD_FORMAT;