diff options
Diffstat (limited to 'src/lib/formats')
-rw-r--r-- | src/lib/formats/apridisk.h | 2 | ||||
-rw-r--r-- | src/lib/formats/dsk_dsk.cpp | 6 | ||||
-rw-r--r-- | src/lib/formats/hpi_dsk.cpp | 96 | ||||
-rw-r--r-- | src/lib/formats/hpi_dsk.h | 3 | ||||
-rw-r--r-- | src/lib/formats/mtx_dsk.cpp | 53 | ||||
-rw-r--r-- | src/lib/formats/mtx_dsk.h | 33 | ||||
-rw-r--r-- | src/lib/formats/opd_dsk.cpp | 61 | ||||
-rw-r--r-- | src/lib/formats/opd_dsk.h | 38 |
8 files changed, 272 insertions, 20 deletions
diff --git a/src/lib/formats/apridisk.h b/src/lib/formats/apridisk.h index 81db4b41105..1155a0b4a9a 100644 --- a/src/lib/formats/apridisk.h +++ b/src/lib/formats/apridisk.h @@ -33,7 +33,7 @@ private: static const int APR_HEADER_SIZE = 128; // sector types - enum + enum : uint32_t { APR_DELETED = 0xe31d0000, APR_SECTOR = 0xe31d0001, diff --git a/src/lib/formats/dsk_dsk.cpp b/src/lib/formats/dsk_dsk.cpp index 5b019fb53d1..c90579b68d0 100644 --- a/src/lib/formats/dsk_dsk.cpp +++ b/src/lib/formats/dsk_dsk.cpp @@ -362,6 +362,12 @@ bool dsk_format::load(io_generic *io, uint32_t form_factor, floppy_image *image) skip = 2; } int tracks = header[0x30]; + + int img_tracks, img_heads; + image->get_maximal_geometry(img_tracks, img_heads); + if (tracks > img_tracks || heads > img_heads) + return false; + uint64_t track_offsets[84*2]; int cnt =0; if (!extendformat) { diff --git a/src/lib/formats/hpi_dsk.cpp b/src/lib/formats/hpi_dsk.cpp index 8d23f151862..50d2653280d 100644 --- a/src/lib/formats/hpi_dsk.cpp +++ b/src/lib/formats/hpi_dsk.cpp @@ -4,9 +4,10 @@ hpi_dsk.cpp - HP9895A "HPI" disk images + HP9885/HP9895A "HPI" disk images - CHS = 77/2/30 + CHS = 67/1/30 (SSDD) + CHS = 77/2/30 (DSDD) Sector size 256 bytes Cell size 2 µs Gap1 = 16 x 0x00 @@ -40,7 +41,7 @@ 256 bytes per sector). There's also a "reduced" version holding just 75 cylinders. When loading, the disk image is translated to MMFM encoding so - that it can be loaded into HP9895 emulator. + that it can be loaded into HP9885/HP9895 emulator. *********************************************************************/ @@ -65,11 +66,14 @@ constexpr int ID_DATA_OFFSET = 30 * 16; // Nominal distance (in cells) between I // Size of image file (holding 77 cylinders) constexpr unsigned HPI_IMAGE_SIZE = HPI_TRACKS * HPI_HEADS * HPI_SECTORS * HPI_SECTOR_SIZE; constexpr unsigned HPI_RED_TRACKS = 75; // Reduced number of tracks +constexpr unsigned HPI_9885_TRACKS = 67; // Tracks visible to HP9885 drives // Size of reduced image file (holding 75 cylinders) constexpr unsigned HPI_RED_IMAGE_SIZE = HPI_RED_TRACKS * HPI_HEADS * HPI_SECTORS * HPI_SECTOR_SIZE; hpi_format::hpi_format() { + (void)HPI_IMAGE_SIZE; + (void)HPI_RED_IMAGE_SIZE; } int hpi_format::identify(io_generic *io, uint32_t form_factor) @@ -79,27 +83,79 @@ int hpi_format::identify(io_generic *io, uint32_t form_factor) // we try to stay back and give only 50 points, since another image // format may also have images of the same size (there is no header and no // magic number for HPI format... + unsigned dummy_heads; + unsigned dummy_tracks; if (((form_factor == floppy_image::FF_8) || (form_factor == floppy_image::FF_UNKNOWN)) && - ((size == HPI_RED_IMAGE_SIZE) || (size == HPI_IMAGE_SIZE))) { + geometry_from_size(size , dummy_heads , dummy_tracks)) { return 50; } else { return 0; } } +bool hpi_format::geometry_from_size(uint64_t image_size , unsigned& heads , unsigned& tracks) +{ + if ((image_size % HPI_SECTOR_SIZE) != 0) { + // Not a whole number of sectors + return false; + } + unsigned sectors = unsigned(image_size / HPI_SECTOR_SIZE); + if ((sectors % HPI_SECTORS) != 0) { + // Not a whole number of tracks + return false; + } + unsigned tot_tracks = sectors / HPI_SECTORS; + // Possible combinations + // + // | Tot tracks | Heads | Tracks | Format | + // |------------+-------+--------+--------| + // | 67 | 1 | 67 | SSDD | + // | 77 | 1 | 77 | SSDD | + // | 150 | 2 | 75 | DSDD | + // | 154 | 2 | 77 | DSDD | + // + switch (tot_tracks) { + case HPI_9885_TRACKS: + heads = 1; + tracks = HPI_9885_TRACKS; + return true; + + case HPI_TRACKS: + heads = 1; + tracks = HPI_TRACKS; + return true; + + case HPI_RED_TRACKS * 2: + heads = 2; + tracks = HPI_RED_TRACKS; + return true; + + case HPI_TRACKS * 2: + heads = 2; + tracks = HPI_TRACKS; + return true; + + default: + return false; + } +} + bool hpi_format::load(io_generic *io, uint32_t form_factor, floppy_image *image) { - image->set_variant(floppy_image::DSDD); // We actually need to derive the variant from the image size depending on the form factor + unsigned heads; + unsigned cylinders; uint64_t size = io_generic_size(io); - unsigned cylinders; - if (size == HPI_RED_IMAGE_SIZE) { - cylinders = HPI_RED_TRACKS; - } else if (size == HPI_IMAGE_SIZE) { - cylinders = HPI_TRACKS; - } else { + if (!geometry_from_size(size, heads, cylinders)) { + return false; + } + int max_tracks; + int max_heads; + image->get_maximal_geometry(max_tracks , max_heads); + if (cylinders > max_tracks || heads > max_heads) { return false; } + image->set_variant(heads == 2 ? floppy_image::DSDD : floppy_image::SSDD); // Suck in the whole image std::vector<uint8_t> image_data(size); @@ -118,11 +174,11 @@ bool hpi_format::load(io_generic *io, uint32_t form_factor, floppy_image *image) unsigned list_offset = 0; for (unsigned cyl = 0; cyl < cylinders; cyl++) { - for (unsigned head = 0; head < HPI_HEADS; head++) { + for (unsigned head = 0; head < heads; head++) { std::vector<uint32_t> track_data; for (unsigned sector = 0; sector < HPI_SECTORS; sector++) { unsigned real_sector = sector_list[ (sector + list_offset) % HPI_SECTORS ]; - unsigned offset_in_image = chs_to_lba(cyl, head, real_sector) * HPI_SECTOR_SIZE; + unsigned offset_in_image = chs_to_lba(cyl, head, real_sector, heads) * HPI_SECTOR_SIZE; write_sector(track_data , cyl , real_sector + (head << 7) , &image_data[ offset_in_image ]); } fill_with_gap3(track_data); @@ -135,8 +191,12 @@ bool hpi_format::load(io_generic *io, uint32_t form_factor, floppy_image *image) bool hpi_format::save(io_generic *io, floppy_image *image) { - for (unsigned cyl = 0; cyl < HPI_TRACKS; cyl++) { - for (unsigned head = 0; head < HPI_HEADS; head++) { + int tracks; + int heads; + image->get_actual_geometry(tracks, heads); + + for (int cyl = 0; cyl < tracks; cyl++) { + for (int head = 0; head < heads; head++) { uint8_t bitstream[ 21000 ]; int bitstream_size; generate_bitstream_from_track(cyl , head , CELL_SIZE , bitstream , bitstream_size , image , 0); @@ -145,7 +205,7 @@ bool hpi_format::save(io_generic *io, floppy_image *image) uint8_t sector_data[ HPI_SECTOR_SIZE ]; while (get_next_sector(bitstream , bitstream_size , pos , track_no , head_no , sector_no , sector_data)) { if (track_no == cyl && head_no == head && sector_no < HPI_SECTORS) { - unsigned offset_in_image = chs_to_lba(cyl, head, sector_no) * HPI_SECTOR_SIZE; + unsigned offset_in_image = chs_to_lba(cyl, head, sector_no, heads) * HPI_SECTOR_SIZE; io_generic_write(io, sector_data, offset_in_image, HPI_SECTOR_SIZE); } } @@ -300,9 +360,9 @@ void hpi_format::fill_with_gap3(std::vector<uint32_t> &buffer) } } -unsigned hpi_format::chs_to_lba(unsigned cylinder , unsigned head , unsigned sector) +unsigned hpi_format::chs_to_lba(unsigned cylinder , unsigned head , unsigned sector , unsigned heads) { - return sector + (head + cylinder * HPI_HEADS) * HPI_SECTORS; + return sector + (head + cylinder * heads) * HPI_SECTORS; } std::vector<uint8_t> hpi_format::get_next_id_n_block(const uint8_t *bitstream , int bitstream_size , int& pos , int& start_pos) diff --git a/src/lib/formats/hpi_dsk.h b/src/lib/formats/hpi_dsk.h index 8457db1ea24..287f37fd302 100644 --- a/src/lib/formats/hpi_dsk.h +++ b/src/lib/formats/hpi_dsk.h @@ -36,6 +36,7 @@ public: private: typedef std::array<uint8_t , HPI_SECTORS> sector_list_t; + static bool geometry_from_size(uint64_t image_size , unsigned& heads , unsigned& tracks); static void interleaved_sectors(unsigned il_factor , sector_list_t& sector_list); void write_mmfm_bit(std::vector<uint32_t> &buffer , bool data_bit , bool clock_bit); void write_mmfm_byte(std::vector<uint32_t> &buffer , uint8_t data , uint8_t clock = 0); @@ -43,7 +44,7 @@ private: void write_crc(std::vector<uint32_t> &buffer , uint16_t crc); void write_sector(std::vector<uint32_t> &buffer , uint8_t track_no , uint8_t sect_head_no , const uint8_t *sect_data); void fill_with_gap3(std::vector<uint32_t> &buffer); - static unsigned chs_to_lba(unsigned cylinder , unsigned head , unsigned sector); + static unsigned chs_to_lba(unsigned cylinder , unsigned head , unsigned sector , unsigned heads); std::vector<uint8_t> get_next_id_n_block(const uint8_t *bitstream , int bitstream_size , int& pos , int& start_pos); bool get_next_sector(const uint8_t *bitstream , int bitstream_size , int& pos , unsigned& track , unsigned& head , unsigned& sector , uint8_t *sector_data); diff --git a/src/lib/formats/mtx_dsk.cpp b/src/lib/formats/mtx_dsk.cpp new file mode 100644 index 00000000000..95420f40aab --- /dev/null +++ b/src/lib/formats/mtx_dsk.cpp @@ -0,0 +1,53 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/*************************************************************************** + + Memotech MTX + + Disk image format + +***************************************************************************/ + +#include "mtx_dsk.h" + +mtx_format::mtx_format() : wd177x_format(formats) +{ +} + +const char *mtx_format::name() const +{ + return "mtx"; +} + +const char *mtx_format::description() const +{ + return "Memotech MTX disk image"; +} + +const char *mtx_format::extensions() const +{ + return "mfloppy"; +} + +const mtx_format::format mtx_format::formats[] = +{ + { // 320k 5 1/4 inch double density single sided (Type 03) + floppy_image::FF_525, floppy_image::DSDD, floppy_image::MFM, + 2000, 16, 40, 2, 256, {}, 1, {}, 32, 22, 54 + }, + { // 640k 5 1/4 inch double density double sided (Type 07) + floppy_image::FF_525, floppy_image::DSQD, floppy_image::MFM, + 2000, 16, 80, 2, 256, {}, 1, {}, 32, 22, 54 + }, + { // 320k 3 1/2 inch double density single sided (Type 03) + floppy_image::FF_35, floppy_image::DSDD, floppy_image::MFM, + 2000, 16, 40, 2, 256, {}, 1, {}, 32, 22, 54 + }, + { // 640k 3 1/2 inch double density double sided (Type 07) + floppy_image::FF_35, floppy_image::DSQD, floppy_image::MFM, + 2000, 16, 80, 2, 256, {}, 1, {}, 32, 22, 54 + }, + {} +}; + +const floppy_format_type FLOPPY_MTX_FORMAT = &floppy_image_format_creator<mtx_format>; diff --git a/src/lib/formats/mtx_dsk.h b/src/lib/formats/mtx_dsk.h new file mode 100644 index 00000000000..86f74bccfc5 --- /dev/null +++ b/src/lib/formats/mtx_dsk.h @@ -0,0 +1,33 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/*************************************************************************** + + Memotech MTX + + Disk image format + +***************************************************************************/ + +#pragma once + +#ifndef __MTX_DSK_H__ +#define __MTX_DSK_H__ + +#include "wd177x_dsk.h" + +class mtx_format : public wd177x_format +{ +public: + mtx_format(); + + virtual const char *name() const override; + virtual const char *description() const override; + virtual const char *extensions() const override; + +private: + static const format formats[]; +}; + +extern const floppy_format_type FLOPPY_MTX_FORMAT; + +#endif // __MTX_DSK_H__ diff --git a/src/lib/formats/opd_dsk.cpp b/src/lib/formats/opd_dsk.cpp new file mode 100644 index 00000000000..b45b58762ed --- /dev/null +++ b/src/lib/formats/opd_dsk.cpp @@ -0,0 +1,61 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/*************************************************************************** + + Sinclair ZX Spectrum + + Opus Discovery disk image formats + +***************************************************************************/ + +#include "opd_dsk.h" + + +opd_format::opd_format() : wd177x_format(formats) +{ +} + +const char *opd_format::name() const +{ + return "opd"; +} + +const char *opd_format::description() const +{ + return "Opus Discovery disk image"; +} + +const char *opd_format::extensions() const +{ + return "opd,opu"; +} + +int opd_format::identify(io_generic *io, uint32_t form_factor) +{ + int type = find_size(io, form_factor); + + if (type != -1) + return 90; + return 0; +} + +int opd_format::get_image_offset(const format &f, int head, int track) +{ + return (f.track_count * head + track) * compute_track_size(f); +} + +const opd_format::format opd_format::formats[] = +{ + { // 180k 40 track single sided double density - gaps unverified + floppy_image::FF_35, floppy_image::SSSD, floppy_image::MFM, + 2000, 18, 40, 1, 256, {}, 0, {}, 36, 22, 27 + }, + { // 360k 40 track double sided double density - gaps unverified + floppy_image::FF_35, floppy_image::DSSD, floppy_image::MFM, + 2000, 18, 40, 2, 256, {}, 0, {}, 36, 22, 27 + }, + {} +}; + + +const floppy_format_type FLOPPY_OPD_FORMAT = &floppy_image_format_creator<opd_format>; diff --git a/src/lib/formats/opd_dsk.h b/src/lib/formats/opd_dsk.h new file mode 100644 index 00000000000..3eb018ca1dc --- /dev/null +++ b/src/lib/formats/opd_dsk.h @@ -0,0 +1,38 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/*************************************************************************** + + Sinclair ZX Spectrum + + Opus Discovery disk image formats + +***************************************************************************/ + +#pragma once + +#ifndef OPD_DSK_H +#define OPD_DSK_H + +#include "flopimg.h" +#include "wd177x_dsk.h" + + +class opd_format : public wd177x_format +{ +public: + opd_format(); + + virtual int identify(io_generic *io, uint32_t form_factor) override; + virtual int get_image_offset(const format &f, int head, int track) override; + virtual const char *name() const override; + virtual const char *description() const override; + virtual const char *extensions() const override; + +private: + static const format formats[]; +}; + + +extern const floppy_format_type FLOPPY_OPD_FORMAT; + +#endif // OPD_DSK_H |