diff options
Diffstat (limited to 'src/lib/formats/imd_dsk.cpp')
-rw-r--r-- | src/lib/formats/imd_dsk.cpp | 318 |
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; |