From add6b4515206d5973ec7e3e30012a469fecc49bb Mon Sep 17 00:00:00 2001 From: cracyc Date: Tue, 15 Oct 2024 20:15:25 -0500 Subject: [PATCH] 86f_dsk: add read 86f image support --- scripts/src/formats.lua | 2 + src/devices/imagedev/floppy.cpp | 2 + src/lib/formats/86f_dsk.cpp | 241 ++++++++++++++++++++++++++++++++ src/lib/formats/86f_dsk.h | 62 ++++++++ 4 files changed, 307 insertions(+) create mode 100644 src/lib/formats/86f_dsk.cpp create mode 100644 src/lib/formats/86f_dsk.h diff --git a/scripts/src/formats.lua b/scripts/src/formats.lua index c1f9c86d15c..320f2123674 100644 --- a/scripts/src/formats.lua +++ b/scripts/src/formats.lua @@ -75,6 +75,8 @@ project "formats" MAME_DIR .. "src/lib/formats/fdi_dsk.cpp", MAME_DIR .. "src/lib/formats/rpk.cpp", MAME_DIR .. "src/lib/formats/rpk.h", + MAME_DIR .. "src/lib/formats/86f_dsk.cpp", + MAME_DIR .. "src/lib/formats/86f_dsk.h", MAME_DIR .. "src/lib/formats/fsmgr.h", MAME_DIR .. "src/lib/formats/fsmgr.cpp", diff --git a/src/devices/imagedev/floppy.cpp b/src/devices/imagedev/floppy.cpp index c37183aa303..e350ac100f3 100644 --- a/src/devices/imagedev/floppy.cpp +++ b/src/devices/imagedev/floppy.cpp @@ -20,6 +20,7 @@ #include "formats/dsk_dsk.h" #include "formats/pc_dsk.h" #include "formats/ipf_dsk.h" +#include "formats/86f_dsk.h" #include "formats/fs_unformatted.h" #include "formats/fsblk_vec.h" @@ -164,6 +165,7 @@ void format_registration::add_fm_containers() add(FLOPPY_MFM_FORMAT); add(FLOPPY_TD0_FORMAT); add(FLOPPY_IMD_FORMAT); + add(FLOPPY_86F_FORMAT); } void format_registration::add_mfm_containers() diff --git a/src/lib/formats/86f_dsk.cpp b/src/lib/formats/86f_dsk.cpp new file mode 100644 index 00000000000..97ad3429f62 --- /dev/null +++ b/src/lib/formats/86f_dsk.cpp @@ -0,0 +1,241 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert, Carl + +#include "86f_dsk.h" + +#include "ioprocs.h" + +#include +#include + + +#define _86F_FORMAT_HEADER "86BF" + +#pragma pack(1) + +struct _86FIMG +{ + uint8_t headername[4]; + uint8_t minor_version; + uint8_t major_version; + uint16_t flags; + uint32_t firsttrackoffs; +}; + +#pragma pack() + +_86f_format::_86f_format() : floppy_image_format_t() +{ +} + +const char *_86f_format::name() const noexcept +{ + return "86f"; +} + +const char *_86f_format::description() const noexcept +{ + return "86f floppy image"; +} + +const char *_86f_format::extensions() const noexcept +{ + return "86f"; +} + +bool _86f_format::supports_save() const noexcept +{ + return false; +} + +int _86f_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) const +{ + uint8_t header[4]; + auto const [err, actual] = read_at(io, 0, &header, sizeof(header)); + if (err) { + return 0; + } + if (!memcmp(header, _86F_FORMAT_HEADER, 4)) { + return FIFID_SIGN; + } + return 0; +} + +void _86f_format::generate_track_from_bitstream_with_weak(int track, int head, const uint8_t *trackbuf, const uint8_t *weak, int index_cell, int track_size, floppy_image &image) const +{ + int j = 0; + std::vector &dest = image.get_buffer(track, head); + dest.clear(); + + for(int i=index_cell; i != track_size; i++, j++) { + int databit = trackbuf[i >> 3] & (0x80 >> (i & 7)); + int weakbit = weak ? weak[i >> 3] & (0x80 >> (i & 7)) : 0; + if(weakbit && databit) + dest.push_back(floppy_image::MG_D | (j*2+1)); + else if(weakbit && !databit) + dest.push_back(floppy_image::MG_N | (j*2+1)); + else if(databit) + dest.push_back(floppy_image::MG_F | (j*2+1)); + } + for(int i=0; i != index_cell; i++, j++) { + int databit = trackbuf[i >> 3] & (0x80 >> (i & 7)); + int weakbit = weak ? weak[i >> 3] & (0x80 >> (i & 7)) : 0; + if(weakbit && databit) + dest.push_back(floppy_image::MG_D | (j*2+1)); + else if(weakbit && !databit) + dest.push_back(floppy_image::MG_N | (j*2+1)); + else if(databit) + dest.push_back(floppy_image::MG_F | (j*2+1)); + } + + normalize_times(dest, track_size*2); + image.set_write_splice_position(track, head, 0, 0); +} + +bool _86f_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image &image) const +{ + std::error_condition err; + size_t actual; + _86FIMG header; + + // read header + std::tie(err, actual) = read_at(io, 0, &header, sizeof(header)); + if(err || (actual != sizeof(header))) + return false; + + int drivecyl, driveheads; + image.get_maximal_geometry(drivecyl, driveheads); + bool skip_odd = drivecyl < 50; + int imagesides = header.flags & TWO_SIDES ? 2 : 1; + int sides = (imagesides == 2) && (driveheads == 2) ? 2 : 1; + + std::vector tracklist; + int tracklistsize = header.firsttrackoffs - 8; + tracklist.resize(tracklistsize / 4); + std::tie(err, actual) = read_at(io, 8, &tracklist[0], tracklistsize); + if(err || (actual != tracklistsize)) + return false; + + uint32_t tracklen = 0; + if((header.flags & (TOTAL_BC | EXTRA_BC | RPM_MASK)) != (TOTAL_BC | EXTRA_BC)) { + switch(header.flags & (RPM_MASK | RPM_FAST | TYPE_MASK)) { + case TYPE_DD | RPM_2: + case TYPE_HD | RPM_2: + tracklen = 12750; + break; + case TYPE_DD | RPM_15: + case TYPE_HD | RPM_15: + tracklen = 12687; + break; + case TYPE_DD | RPM_1: + case TYPE_HD | RPM_1: + tracklen = 12625; + break; + case TYPE_DD | RPM_0: + case TYPE_HD | RPM_0: + tracklen = 12500; + break; + case TYPE_DD | RPM_1 | RPM_FAST: + case TYPE_HD | RPM_1 | RPM_FAST: + tracklen = 12376; + break; + case TYPE_DD | RPM_15 | RPM_FAST: + case TYPE_HD | RPM_15 | RPM_FAST: + tracklen = 12315; + break; + case TYPE_DD | RPM_2 | RPM_FAST: + case TYPE_HD | RPM_2 | RPM_FAST: + tracklen = 12254; + break; + + case TYPE_ED | RPM_2: + tracklen = 25500; + break; + case TYPE_ED | RPM_15: + tracklen = 25375; + break; + case TYPE_ED | RPM_1: + tracklen = 25250; + break; + case TYPE_ED | RPM_0: + tracklen = 25000; + break; + case TYPE_ED | RPM_1 | RPM_FAST: + tracklen = 25752; + break; + case TYPE_ED | RPM_15 | RPM_FAST: + tracklen = 24630; + break; + case TYPE_ED | RPM_2 | RPM_FAST: + tracklen = 24509; + break; + } + } + uint32_t trackoff; + int trackinfolen = header.flags & EXTRA_BC ? 10 : 6; + if(skip_odd) + drivecyl *= 2; + std::vector trackbuf; + std::vector weakbuf; + int track; + for(track=0; (track < (tracklistsize / 4)) && (track < drivecyl); track++) { + for(int side=0; side < sides; side++) { + trackoff = tracklist[(track * imagesides) + side]; + if(!trackoff) break; + if(!skip_odd || track%2 == 0) { + char trackinfo[10]; + std::tie(err, actual) = read_at(io, trackoff, &trackinfo, trackinfolen); // FIXME: check for errors and premature EOF + if(err || (actual != trackinfolen)) + return false; + uint32_t bitcells = tracklen << 4; + uint32_t index_cell; + if(header.flags & EXTRA_BC) + { + uint32_t extra = *(uint32_t *)(trackinfo + 2); + index_cell = *(uint32_t *)(trackinfo + 6); + if((header.flags & TOTAL_BC) && !tracklen) + bitcells = extra; + else + bitcells += (int32_t)extra; + } + else + index_cell = *(uint32_t *)(trackinfo + 2); + uint32_t fulltracklen = (bitcells >> 3) + (bitcells & 7 ? 1 : 0); + uint8_t *weak = nullptr; + trackbuf.resize(fulltracklen); + std::tie(err, actual) = read_at(io, trackoff + trackinfolen, &trackbuf[0], fulltracklen); + if(err || (actual != fulltracklen)) + return false; + if(header.flags & SURFACE_DESC) + { + weakbuf.resize(fulltracklen); + std::tie(err, actual) = read_at(io, trackoff + trackinfolen + fulltracklen, &weakbuf[0], fulltracklen); + if(err || (actual != fulltracklen)) + return false; + weak = &weakbuf[0]; + } + if(skip_odd) { + generate_track_from_bitstream_with_weak(track/2, side, &trackbuf[0], weak, index_cell, bitcells, image); + } + else { + generate_track_from_bitstream_with_weak(track, side, &trackbuf[0], weak, index_cell, bitcells, image); + } + } + } + if(!trackoff) break; + } + + if(imagesides == 2) + image.set_variant(track > 50 ? floppy_image::DSHD : floppy_image::DSDD); + else + image.set_variant(floppy_image::SSDD); + return true; +} + +/* +bool _86f_format::save(util::random_read_write &io, const std::vector &variants, const floppy_image &image) const +{ + return true; +} +*/ +const _86f_format FLOPPY_86F_FORMAT; diff --git a/src/lib/formats/86f_dsk.h b/src/lib/formats/86f_dsk.h new file mode 100644 index 00000000000..097ff68e576 --- /dev/null +++ b/src/lib/formats/86f_dsk.h @@ -0,0 +1,62 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert, Carl +/********************************************************************* + + formats/86f_dsk.h + + 86f disk images + +*********************************************************************/ +#ifndef MAME_FORMATS_86F_DSK_H +#define MAME_FORMATS_86F_DSK_H + +#pragma once + +#include "flopimg.h" + +class _86f_format : public floppy_image_format_t +{ +public: + _86f_format(); + + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) const override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image &image) const override; + //virtual bool save(util::random_read_write &io, const std::vector &variants, const floppy_image &image) const override; + + virtual const char *name() const noexcept override; + virtual const char *description() const noexcept override; + virtual const char *extensions() const noexcept override; + virtual bool supports_save() const noexcept override; + +private: + void generate_track_from_bitstream_with_weak(int track, int head, const uint8_t *trackbuf, const uint8_t *weak, int index_cell, int track_size, floppy_image &image) const; + enum + { + SURFACE_DESC = 1, + TYPE_MASK = 6, + TYPE_DD = 0, + TYPE_HD = 2, + TYPE_ED = 4, + TYPE_ED2000 = 6, + TWO_SIDES = 8, + WRITE_PROTECT = 0x10, + RPM_MASK = 0x60, + RPM_0 = 0, + RPM_1 = 0x20, + RPM_15 = 0x40, + RPM_2 = 0x60, + EXTRA_BC = 0x80, + ZONED_RPM = 0x100, + ZONE_PREA2_1 = 0, + ZONE_PREA2_2 = 0x200, + ZONE_A2 = 0x400, + ZONE_C64 = 0x600, + BIG_ENDIAN = 0x800, + RPM_FAST = 0x1000, + TOTAL_BC = 0x1000 + }; +}; + +extern const _86f_format FLOPPY_86F_FORMAT; + +#endif // MAME_FORMATS_86F_DSK_H