diff options
Diffstat (limited to 'src/lib/formats/flopimg.h')
-rw-r--r-- | src/lib/formats/flopimg.h | 544 |
1 files changed, 208 insertions, 336 deletions
diff --git a/src/lib/formats/flopimg.h b/src/lib/formats/flopimg.h index d5edd6b0315..18cc17ea73b 100644 --- a/src/lib/formats/flopimg.h +++ b/src/lib/formats/flopimg.h @@ -7,211 +7,20 @@ Floppy disk image abstraction code *********************************************************************/ + #ifndef MAME_FORMATS_FLOPIMG_H #define MAME_FORMATS_FLOPIMG_H #pragma once -#include "osdcore.h" -#include "ioprocs.h" -#include "opresolv.h" -#include "coretmpl.h" +#include "utilfwd.h" +#include <memory> #include <vector> -#ifndef LOG_FORMATS -#define LOG_FORMATS if (0) printf -#endif - - -/*************************************************************************** - - Constants - -***************************************************************************/ - -#define FLOPPY_FLAGS_READWRITE 0 -#define FLOPPY_FLAGS_READONLY 1 - -/* sector has a deleted data address mark */ -#define ID_FLAG_DELETED_DATA 0x0001 -/* CRC error in id field */ -#define ID_FLAG_CRC_ERROR_IN_ID_FIELD 0x0002 -/* CRC error in data field */ -#define ID_FLAG_CRC_ERROR_IN_DATA_FIELD 0x0004 - - -/*************************************************************************** - - Type definitions - -***************************************************************************/ - -enum floperr_t -{ - FLOPPY_ERROR_SUCCESS, /* no error */ - FLOPPY_ERROR_INTERNAL, /* fatal internal error */ - FLOPPY_ERROR_UNSUPPORTED, /* this operation is unsupported */ - FLOPPY_ERROR_OUTOFMEMORY, /* ran out of memory */ - FLOPPY_ERROR_SEEKERROR, /* attempted to seek to nonexistent location */ - FLOPPY_ERROR_INVALIDIMAGE, /* this image in invalid */ - FLOPPY_ERROR_READONLY, /* attempt to write to read-only image */ - FLOPPY_ERROR_NOSPACE, - FLOPPY_ERROR_PARAMOUTOFRANGE, - FLOPPY_ERROR_PARAMNOTSPECIFIED -}; - -struct floppy_image_legacy; - -struct FloppyCallbacks -{ - floperr_t (*read_sector)(floppy_image_legacy *floppy, int head, int track, int sector, void *buffer, size_t buflen); - floperr_t (*write_sector)(floppy_image_legacy *floppy, int head, int track, int sector, const void *buffer, size_t buflen, int ddam); - floperr_t (*read_indexed_sector)(floppy_image_legacy *floppy, int head, int track, int sector_index, void *buffer, size_t buflen); - floperr_t (*write_indexed_sector)(floppy_image_legacy *floppy, int head, int track, int sector_index, const void *buffer, size_t buflen, int ddam); - floperr_t (*read_track)(floppy_image_legacy *floppy, int head, int track, uint64_t offset, void *buffer, size_t buflen); - floperr_t (*write_track)(floppy_image_legacy *floppy, int head, int track, uint64_t offset, const void *buffer, size_t buflen); - floperr_t (*format_track)(floppy_image_legacy *floppy, int head, int track, util::option_resolution *params); - floperr_t (*post_format)(floppy_image_legacy *floppy, util::option_resolution *params); - int (*get_heads_per_disk)(floppy_image_legacy *floppy); - int (*get_tracks_per_disk)(floppy_image_legacy *floppy); - int (*get_sectors_per_track)(floppy_image_legacy *floppy, int head, int track); - uint32_t (*get_track_size)(floppy_image_legacy *floppy, int head, int track); - floperr_t (*get_sector_length)(floppy_image_legacy *floppy, int head, int track, int sector, uint32_t *sector_length); - floperr_t (*get_indexed_sector_info)(floppy_image_legacy *floppy, int head, int track, int sector_index, int *cylinder, int *side, int *sector, uint32_t *sector_length, unsigned long *flags); - floperr_t (*get_track_data_offset)(floppy_image_legacy *floppy, int head, int track, uint64_t *offset); -}; - - - -struct FloppyFormat -{ - const char *name; - const char *extensions; - const char *description; - floperr_t (*identify)(floppy_image_legacy *floppy, const struct FloppyFormat *format, int *vote); - floperr_t (*construct)(floppy_image_legacy *floppy, const struct FloppyFormat *format, util::option_resolution *params); - floperr_t (*destruct)(floppy_image_legacy *floppy, const struct FloppyFormat *format); - const char *param_guidelines; -}; - -#define FLOPPY_IDENTIFY(name) floperr_t name(floppy_image_legacy *floppy, const struct FloppyFormat *format, int *vote) -#define FLOPPY_CONSTRUCT(name) floperr_t name(floppy_image_legacy *floppy, const struct FloppyFormat *format, util::option_resolution *params) -#define FLOPPY_DESTRUCT(name) floperr_t name(floppy_image_legacy *floppy, const struct FloppyFormat *format) - -FLOPPY_IDENTIFY(td0_dsk_identify); -FLOPPY_CONSTRUCT(td0_dsk_construct); -FLOPPY_DESTRUCT(td0_dsk_destruct); - -FLOPPY_IDENTIFY(imd_dsk_identify); -FLOPPY_CONSTRUCT(imd_dsk_construct); - -FLOPPY_IDENTIFY(cqm_dsk_identify); -FLOPPY_CONSTRUCT(cqm_dsk_construct); - -FLOPPY_IDENTIFY(dsk_dsk_identify); -FLOPPY_CONSTRUCT(dsk_dsk_construct); - -FLOPPY_IDENTIFY(d88_dsk_identify); -FLOPPY_CONSTRUCT(d88_dsk_construct); - -FLOPPY_IDENTIFY(fdi_dsk_identify); -FLOPPY_CONSTRUCT(fdi_dsk_construct); - -#define LEGACY_FLOPPY_OPTIONS_NAME(name) floppyoptions_##name - -#define LEGACY_FLOPPY_OPTIONS_START(name) \ - const struct FloppyFormat floppyoptions_##name[] = \ - { -#define LEGACY_FLOPPY_OPTIONS_END0 \ - { nullptr } \ - }; - -#define LEGACY_FLOPPY_OPTIONS_EXTERN(name) \ - extern const struct FloppyFormat floppyoptions_##name[] -#define LEGACY_FLOPPY_OPTION(name, extensions_, description_, identify_, construct_, destruct_, ranges_)\ - { #name, extensions_, description_, identify_, construct_, destruct_, ranges_ }, -#define LEGACY_FLOPPY_OPTIONS_END \ - LEGACY_FLOPPY_OPTION( fdi, "fdi", "Formatted Disk Image", fdi_dsk_identify, fdi_dsk_construct, nullptr, nullptr) \ - LEGACY_FLOPPY_OPTION( td0, "td0", "Teledisk floppy disk image", td0_dsk_identify, td0_dsk_construct, td0_dsk_destruct, nullptr) \ - LEGACY_FLOPPY_OPTION( imd, "imd", "IMD floppy disk image", imd_dsk_identify, imd_dsk_construct, nullptr, nullptr) \ - LEGACY_FLOPPY_OPTION( cqm, "cqm,dsk", "CopyQM floppy disk image", cqm_dsk_identify, cqm_dsk_construct, nullptr, nullptr) \ - LEGACY_FLOPPY_OPTION( dsk, "dsk", "DSK floppy disk image", dsk_dsk_identify, dsk_dsk_construct, nullptr, nullptr) \ - LEGACY_FLOPPY_OPTION( d88, "d77,d88,1dd", "D88 Floppy Disk image", d88_dsk_identify, d88_dsk_construct, nullptr, nullptr) \ - LEGACY_FLOPPY_OPTIONS_END0 - -LEGACY_FLOPPY_OPTIONS_EXTERN(default); - -#define PARAM_END '\0' -#define PARAM_HEADS 'H' -#define PARAM_TRACKS 'T' -#define PARAM_SECTORS 'S' -#define PARAM_SECTOR_LENGTH 'L' -#define PARAM_INTERLEAVE 'I' -#define PARAM_FIRST_SECTOR_ID 'F' - -#define HEADS(range) "H" #range -#define TRACKS(range) "T" #range -#define SECTORS(range) "S" #range -#define SECTOR_LENGTH(range) "L" #range -#define INTERLEAVE(range) "I" #range -#define FIRST_SECTOR_ID(range) "F" #range - -/*************************************************************************** - - Prototypes - -***************************************************************************/ - -OPTION_GUIDE_EXTERN(floppy_option_guide); - -/* opening, closing and creating of floppy images */ -floperr_t floppy_open(void *fp, const struct io_procs *procs, const std::string &extension, const struct FloppyFormat *format, int flags, floppy_image_legacy **outfloppy); -floperr_t floppy_open_choices(void *fp, const struct io_procs *procs, const std::string &extension, const struct FloppyFormat *formats, int flags, floppy_image_legacy **outfloppy); -floperr_t floppy_create(void *fp, const struct io_procs *procs, const struct FloppyFormat *format, util::option_resolution *parameters, floppy_image_legacy **outfloppy); -void floppy_close(floppy_image_legacy *floppy); - -/* useful for identifying a floppy image */ -floperr_t floppy_identify(void *fp, const struct io_procs *procs, const char *extension, const struct FloppyFormat *formats, int *identified_format); - -/* functions useful within format constructors */ -void *floppy_tag(floppy_image_legacy *floppy); -void *floppy_create_tag(floppy_image_legacy *floppy, size_t tagsize); -struct FloppyCallbacks *floppy_callbacks(floppy_image_legacy *floppy); -uint8_t floppy_get_filler(floppy_image_legacy *floppy); -void floppy_set_filler(floppy_image_legacy *floppy, uint8_t filler); - -/* calls for accessing disk image data */ -floperr_t floppy_read_sector(floppy_image_legacy *floppy, int head, int track, int sector, int offset, void *buffer, size_t buffer_len); -floperr_t floppy_write_sector(floppy_image_legacy *floppy, int head, int track, int sector, int offset, const void *buffer, size_t buffer_len, int ddam); -floperr_t floppy_read_indexed_sector(floppy_image_legacy *floppy, int head, int track, int sector_index, int offset, void *buffer, size_t buffer_len); -floperr_t floppy_write_indexed_sector(floppy_image_legacy *floppy, int head, int track, int sector_index, int offset, const void *buffer, size_t buffer_len, int ddam); -floperr_t floppy_read_track(floppy_image_legacy *floppy, int head, int track, void *buffer, size_t buffer_len); -floperr_t floppy_write_track(floppy_image_legacy *floppy, int head, int track, const void *buffer, size_t buffer_len); -floperr_t floppy_read_track_data(floppy_image_legacy *floppy, int head, int track, void *buffer, size_t buffer_len); -floperr_t floppy_write_track_data(floppy_image_legacy *floppy, int head, int track, const void *buffer, size_t buffer_len); -floperr_t floppy_format_track(floppy_image_legacy *floppy, int head, int track, util::option_resolution *params); -int floppy_get_tracks_per_disk(floppy_image_legacy *floppy); -int floppy_get_heads_per_disk(floppy_image_legacy *floppy); -uint32_t floppy_get_track_size(floppy_image_legacy *floppy, int head, int track); -floperr_t floppy_get_sector_length(floppy_image_legacy *floppy, int head, int track, int sector, uint32_t *sector_length); -floperr_t floppy_get_indexed_sector_info(floppy_image_legacy *floppy, int head, int track, int sector_index, int *cylinder, int *side, int *sector, uint32_t *sector_length, unsigned long *flags); -floperr_t floppy_get_sector_count(floppy_image_legacy *floppy, int head, int track, int *sector_count); -floperr_t floppy_load_track(floppy_image_legacy *floppy, int head, int track, int dirtify, void **track_data, size_t *track_length); -int floppy_is_read_only(floppy_image_legacy *floppy); -uint8_t floppy_random_byte(floppy_image_legacy *floppy); - -/* accessors for meta information about the image */ -const char *floppy_format_description(floppy_image_legacy *floppy); - -/* calls for accessing the raw disk image */ -void floppy_image_read(floppy_image_legacy *floppy, void *buffer, uint64_t offset, size_t length); -void floppy_image_write(floppy_image_legacy *floppy, const void *buffer, uint64_t offset, size_t length); -void floppy_image_write_filler(floppy_image_legacy *floppy, uint8_t filler, uint64_t offset, size_t length); -uint64_t floppy_image_size(floppy_image_legacy *floppy); - -/* misc */ -const char *floppy_error(floperr_t err); +#include <cassert> +#include <cstddef> +#include <cstdint> ////////////////////////////////////////////////////////// @@ -224,8 +33,19 @@ class floppy_image; class floppy_image_format_t { public: - floppy_image_format_t(); - virtual ~floppy_image_format_t(); + virtual ~floppy_image_format_t() = default; + + // The result of identify is a binary or of these flags, comparison afterwards is numerical. + // If a match is incorrect (bad signature for instance), result must be 0. The non-zero + // result helps to decide how reliable the identification is, for choice classification. + + enum { + FIFID_HINT = 0x01, // All other things being equal, favorise this format + FIFID_EXT = 0x02, // Extension matches one of the list (set outside of identify) + FIFID_SIZE = 0x04, // File size matches what is expected + FIFID_SIGN = 0x08, // The file signature matches + FIFID_STRUCT = 0x10, // Some file internal structure aspects have been verified + }; /*! @brief Identify an image. The identify function tests if the image is valid @@ -233,44 +53,43 @@ public: @param io buffer containing the image data. @param form_factor Physical form factor of disk, from the enum in floppy_image - @return 1 if image valid, 0 otherwise. + @param variants the variants from floppy_image the drive can handle + @return Binary or of FIFID flags, 0 if invalid for that format */ - virtual int identify(io_generic *io, uint32_t form_factor) = 0; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const = 0; /*! @brief Load an image. The load function opens an image file and converts it to the - internal MESS floppy representation. + internal MAME floppy representation. @param io source buffer containing the image data. @param form_factor Physical form factor of disk, from the enum in floppy_image - @param image output buffer for data in MESS internal format. + @param variants the variants from floppy_image the drive can handle + @param image output buffer for data in MAME internal format. @return true on success, false otherwise. */ - virtual bool load(io_generic *io, uint32_t form_factor, floppy_image *image) = 0; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const = 0; /*! @brief Save an image. - The save function writes back an image from the MESS internal + The save function writes back an image from the MAME internal floppy representation to the appropriate format on disk. @param io output buffer for the data in the on-disk format. - @param image source buffer containing data in MESS internal format. + @param variants the variants from floppy_image the drive can handle + @param image source buffer containing data in MAME internal format. @return true on success, false otherwise. */ - virtual bool save(io_generic *io, floppy_image *image); + virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, const floppy_image &image) const; //! @returns string containing name of format. - virtual const char *name() const = 0; + virtual const char *name() const noexcept = 0; //! @returns string containing description of format. - virtual const char *description() const = 0; + virtual const char *description() const noexcept = 0; //! @returns string containing comma-separated list of file //! extensions the format may use. - virtual const char *extensions() const = 0; + virtual const char *extensions() const noexcept = 0; //! @returns true if format supports saving. - virtual bool supports_save() const = 0; + virtual bool supports_save() const noexcept = 0; - //! Used if a linked list of formats is needed - floppy_image_format_t *next; - //! This appends a format to the linked list of formats, needed for floppy_image_device(). - void append(floppy_image_format_t *_next); //! This checks if the file has the proper extension for this format. //! @param file_name //! @returns true if file matches the extension. @@ -366,6 +185,14 @@ protected: SECTOR_INTERLEAVE_SKEW //!< Defines interleave and skew for sector counting }; + + /*! @brief Test if a variant is present in the variant vector + @param variants the variant vector + @param variant the variant to test + @result true if variant is in variants + */ + static bool has_variant(const std::vector<uint32_t> &variants, uint32_t variant) noexcept; + //! Sector data description struct desc_s { @@ -385,7 +212,7 @@ protected: @param track_size in _cells_, i.e. 100000 for a usual 2us-per-cell track at 300rpm. @param image */ - void generate_track(const desc_e *desc, int track, int head, const desc_s *sect, int sect_count, int track_size, floppy_image *image); + static void generate_track(const desc_e *desc, int track, int head, const desc_s *sect, int sect_count, int track_size, floppy_image &image); /*! @brief Generate a track from cell binary values, MSB-first. @param track @@ -396,7 +223,7 @@ protected: @param subtrack subtrack index, 0-3 @param splice write splice position */ - void generate_track_from_bitstream(int track, int head, const uint8_t *trackbuf, int track_size, floppy_image *image, int subtrack = 0, int splice = 0); + static void generate_track_from_bitstream(int track, int head, const uint8_t *trackbuf, int track_size, floppy_image &image, int subtrack = 0, int splice = 0); //! @brief Generate a track from cell level values (0/1/W/D/N). @@ -413,10 +240,11 @@ protected: know. trackbuf may be modified at that position or after. @param image */ - void generate_track_from_levels(int track, int head, std::vector<uint32_t> &trackbuf, int splice_pos, floppy_image *image); + static void generate_track_from_levels(int track, int head, const std::vector<uint32_t> &trackbuf, int splice_pos, floppy_image &image); - //! Normalize the times in a cell buffer to sum up to 200000000 - 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]; @@ -493,16 +321,8 @@ protected: @endverbatim */ - void generate_bitstream_from_track(int track, int head, int cell_size, uint8_t *trackbuf, int &track_size, floppy_image *image, int subtrack = 0); - - //! Defines a standard sector for extracting. - struct desc_xs - { - int track, //!< Track for this sector - head, //!< Head for this sector - size; //!< Size of this sector - const uint8_t *data; //!< Data within this sector - }; + static std::vector<bool> generate_bitstream_from_track(int track, int head, int cell_size, const floppy_image &image, int subtrack = 0, int *max_delta = nullptr); + static std::vector<uint8_t> generate_nibbles_from_bitstream(const std::vector<bool> &bitstream); struct desc_pc_sector { @@ -513,84 +333,91 @@ protected: bool bad_crc; }; - int calc_default_pc_gap3_size(uint32_t form_factor, int sector_size); - void build_wd_track_fm(int track, int head, floppy_image *image, int cell_count, int sector_count, const desc_pc_sector *sects, int gap_3, int gap_1, int gap_2); - void build_wd_track_mfm(int track, int head, floppy_image *image, int cell_count, int sector_count, const desc_pc_sector *sects, int gap_3, int gap_1, int gap_2=22); - void build_pc_track_fm(int track, int head, floppy_image *image, int cell_count, int sector_count, const desc_pc_sector *sects, int gap_3, int gap_4a=40, int gap_1=26, int gap_2=11); - void build_pc_track_mfm(int track, int head, floppy_image *image, int cell_count, int sector_count, const desc_pc_sector *sects, int gap_3, int gap_4a=80, int gap_1=50, int gap_2=22); + struct desc_gcr_sector + { + uint8_t track, head, sector, info; + uint8_t *tag; + uint8_t *data; + }; + static int calc_default_pc_gap3_size(uint32_t form_factor, int sector_size); + static void build_wd_track_fm(int track, int head, floppy_image &image, int cell_count, int sector_count, const desc_pc_sector *sects, int gap_3, int gap_1, int gap_2); + static void build_wd_track_mfm(int track, int head, floppy_image &image, int cell_count, int sector_count, const desc_pc_sector *sects, int gap_3, int gap_1, int gap_2=22); + static void build_pc_track_fm(int track, int head, floppy_image &image, int cell_count, int sector_count, const desc_pc_sector *sects, int gap_3, int gap_4a=40, int gap_1=26, int gap_2=11); + static void build_pc_track_mfm(int track, int head, floppy_image &image, int cell_count, int sector_count, const desc_pc_sector *sects, int gap_3, int gap_4a=80, int gap_1=50, int gap_2=22); + static void build_mac_track_gcr(int track, int head, floppy_image &image, const desc_gcr_sector *sects); //! @brief Extract standard sectors from a regenerated bitstream. - //! Sectors must point to an array of 256 desc_xs. - - //! An existing sector is recognizable by having ->data non-null. - //! Sector data is written in sectdata up to sectdata_size bytes. - - //! The ones implemented here are the ones used by multiple - //! systems. + //! Returns a vector of the vector contents, indexed by the sector id. Missing sectors have size zero. //! PC-type sectors with MFM encoding, sector size can go from 128 bytes to 16K. - void extract_sectors_from_bitstream_mfm_pc(const uint8_t *bitstream, int track_size, desc_xs *sectors, uint8_t *sectdata, int sectdata_size); + static std::vector<std::vector<uint8_t>> extract_sectors_from_bitstream_mfm_pc(const std::vector<bool> &bitstream); + //! PC-type sectors with FM encoding - void extract_sectors_from_bitstream_fm_pc(const uint8_t *bitstream, int track_size, desc_xs *sectors, uint8_t *sectdata, int sectdata_size); + static std::vector<std::vector<uint8_t>> extract_sectors_from_bitstream_fm_pc(const std::vector<bool> &bitstream); + //! Commodore type sectors with GCR5 encoding - void extract_sectors_from_bitstream_gcr5(const uint8_t *bitstream, int track_size, desc_xs *sectors, uint8_t *sectdata, int sectdata_size, int head, int tracks); + static std::vector<std::vector<uint8_t>> extract_sectors_from_bitstream_gcr5(const std::vector<bool> &bitstream, int head, int tracks); + //! Victor 9000 type sectors with GCR5 encoding - void extract_sectors_from_bitstream_victor_gcr5(const uint8_t *bitstream, int track_size, desc_xs *sectors, uint8_t *sectdata, int sectdata_size); + static std::vector<std::vector<uint8_t>> extract_sectors_from_bitstream_victor_gcr5(const std::vector<bool> &bitstream); + + //! Mac type sectors with GCR6 encoding + static std::vector<std::vector<uint8_t>> extract_sectors_from_track_mac_gcr6(int head, int track, const floppy_image &image); //! @brief Get a geometry (including sectors) from an image. //! PC-type sectors with MFM encoding - void get_geometry_mfm_pc(floppy_image *image, int cell_size, int &track_count, int &head_count, int §or_count); + static void get_geometry_mfm_pc(const floppy_image &image, int cell_size, int &track_count, int &head_count, int §or_count); //! PC-type sectors with FM encoding - void get_geometry_fm_pc(floppy_image *image, int cell_size, int &track_count, int &head_count, int §or_count); + static void get_geometry_fm_pc(const floppy_image &image, int cell_size, int &track_count, int &head_count, int §or_count); //! Regenerate the data for a full track. //! PC-type sectors with MFM encoding and fixed-size. - void get_track_data_mfm_pc(int track, int head, floppy_image *image, int cell_size, int sector_size, int sector_count, uint8_t *sectdata); + static void get_track_data_mfm_pc(int track, int head, const floppy_image &image, int cell_size, int sector_size, int sector_count, uint8_t *sectdata); //! Regenerate the data for a full track. //! PC-type sectors with FM encoding and fixed-size. - void get_track_data_fm_pc(int track, int head, floppy_image *image, int cell_size, int sector_size, int sector_count, uint8_t *sectdata); + static void get_track_data_fm_pc(int track, int head, const floppy_image &image, int cell_size, int sector_size, int sector_count, uint8_t *sectdata); //! Look up a bit in a level-type stream. - bool bit_r(const std::vector<uint32_t> &buffer, int offset); + static bool bit_r(const std::vector<uint32_t> &buffer, int offset); //! Look up multiple bits - uint32_t bitn_r(const std::vector<uint32_t> &buffer, int offset, int count); + static uint32_t bitn_r(const std::vector<uint32_t> &buffer, int offset, int count); //! Write a bit with a given size. - void bit_w(std::vector<uint32_t> &buffer, bool val, uint32_t size = 1000); - void bit_w(std::vector<uint32_t> &buffer, bool val, uint32_t size, int offset); + static void bit_w(std::vector<uint32_t> &buffer, bool val, uint32_t size = 1000); + static void bit_w(std::vector<uint32_t> &buffer, bool val, uint32_t size, int offset); //! Calculate a CCITT-type CRC. - uint16_t calc_crc_ccitt(const std::vector<uint32_t> &buffer, int start, int end); + static uint16_t calc_crc_ccitt(const std::vector<uint32_t> &buffer, int start, int end); //! Write a series of (raw) bits - void raw_w(std::vector<uint32_t> &buffer, int n, uint32_t val, uint32_t size = 1000); - void raw_w(std::vector<uint32_t> &buffer, int n, uint32_t val, uint32_t size, int offset); + static void raw_w(std::vector<uint32_t> &buffer, int n, uint32_t val, uint32_t size = 1000); + static void raw_w(std::vector<uint32_t> &buffer, int n, uint32_t val, uint32_t size, int offset); //! FM-encode and write a series of bits - void fm_w(std::vector<uint32_t> &buffer, int n, uint32_t val, uint32_t size = 1000); - void fm_w(std::vector<uint32_t> &buffer, int n, uint32_t val, uint32_t size, int offset); + static void fm_w(std::vector<uint32_t> &buffer, int n, uint32_t val, uint32_t size = 1000); + static void fm_w(std::vector<uint32_t> &buffer, int n, uint32_t val, uint32_t size, int offset); //! MFM-encode and write a series of bits - void mfm_w(std::vector<uint32_t> &buffer, int n, uint32_t val, uint32_t size = 1000); - void mfm_w(std::vector<uint32_t> &buffer, int n, uint32_t val, uint32_t size, int offset); + static void mfm_w(std::vector<uint32_t> &buffer, int n, uint32_t val, uint32_t size = 1000); + static void mfm_w(std::vector<uint32_t> &buffer, int n, uint32_t val, uint32_t size, int offset); //! MFM-encode every two bits and write - void mfm_half_w(std::vector<uint32_t> &buffer, int start_bit, uint32_t val, uint32_t size = 1000); + static void mfm_half_w(std::vector<uint32_t> &buffer, int start_bit, uint32_t val, uint32_t size = 1000); //! GCR5-encode and write a series of bits - void gcr5_w(std::vector<uint32_t> &buffer, uint8_t val, uint32_t size = 1000); - void gcr5_w(std::vector<uint32_t> &buffer, uint8_t val, uint32_t size, int offset); + static void gcr5_w(std::vector<uint32_t> &buffer, uint8_t val, uint32_t size = 1000); + static void gcr5_w(std::vector<uint32_t> &buffer, uint8_t val, uint32_t size, int offset); //! 8N1-encode and write a series of bits - void _8n1_w(std::vector<uint32_t> &buffer, int n, uint32_t val, uint32_t size = 1000); + static void _8n1_w(std::vector<uint32_t> &buffer, int n, uint32_t val, uint32_t size = 1000); //! GCR4 encode (Apple II sector header) - uint16_t gcr4_encode(uint8_t va); + static uint16_t gcr4_encode(uint8_t va); //! GCR4 decode - uint8_t gcr4_decode(uint8_t e0, uint8_t e1); + static uint8_t gcr4_decode(uint8_t e0, uint8_t e1); //! GCR6 encode (Apple II 16-sector and Mac-style GCR) - uint32_t gcr6_encode(uint8_t va, uint8_t vb, uint8_t vc); + static uint32_t gcr6_encode(uint8_t va, uint8_t vb, uint8_t vc); //! GCR6 decode - void gcr6_decode(uint8_t e0, uint8_t e1, uint8_t e2, uint8_t e3, uint8_t &va, uint8_t &vb, uint8_t &vc); + static void gcr6_decode(uint8_t e0, uint8_t e1, uint8_t e2, uint8_t e3, uint8_t &va, uint8_t &vb, uint8_t &vc); - uint8_t sbyte_mfm_r(const uint8_t *bitstream, int &pos, int track_size); - uint8_t sbyte_gcr5_r(const uint8_t *bitstream, int &pos, int track_size); + static uint8_t sbyte_mfm_r(const std::vector<bool> &bitstream, uint32_t &pos); + static uint8_t sbyte_gcr5_r(const std::vector<bool> &bitstream, uint32_t &pos); //! Max number of excess tracks to be discarded from disk image to fit floppy drive enum { DUMP_THRESHOLD = 2 }; @@ -609,36 +436,25 @@ private: bool fixup_mfm_clock; //!< would the MFM clock bit after the CRC need to be fixed? }; - bool type_no_data(int type) const; - bool type_data_mfm(int type, int p1, const gen_crc_info *crcs) const; - - int crc_cells_size(int type) const; - void fixup_crc_amiga(std::vector<uint32_t> &buffer, const gen_crc_info *crc); - void fixup_crc_cbm(std::vector<uint32_t> &buffer, const gen_crc_info *crc); - void fixup_crc_ccitt(std::vector<uint32_t> &buffer, const gen_crc_info *crc); - void fixup_crc_ccitt_fm(std::vector<uint32_t> &buffer, const gen_crc_info *crc); - void fixup_crc_machead(std::vector<uint32_t> &buffer, const gen_crc_info *crc); - void fixup_crc_fcs(std::vector<uint32_t> &buffer, const gen_crc_info *crc); - void fixup_crc_victor_header(std::vector<uint32_t> &buffer, const gen_crc_info *crc); - void fixup_crc_victor_data(std::vector<uint32_t> &buffer, const gen_crc_info *crc); - void fixup_crcs(std::vector<uint32_t> &buffer, gen_crc_info *crcs); - void collect_crcs(const desc_e *desc, gen_crc_info *crcs) const; - - int sbit_r(const uint8_t *bitstream, int pos); - int sbit_rp(const uint8_t *bitstream, int &pos, int track_size); - - int calc_sector_index(int num, int interleave, int skew, int total_sectors, int track_head); -}; + static bool type_no_data(int type); + static bool type_data_mfm(int type, int p1, const gen_crc_info *crcs); -// a dce_type is simply a pointer to its alloc function -typedef floppy_image_format_t *(*floppy_format_type)(); + static int crc_cells_size(int type); + static void fixup_crc_amiga(std::vector<uint32_t> &buffer, const gen_crc_info *crc); + static void fixup_crc_cbm(std::vector<uint32_t> &buffer, const gen_crc_info *crc); + static void fixup_crc_ccitt(std::vector<uint32_t> &buffer, const gen_crc_info *crc); + static void fixup_crc_ccitt_fm(std::vector<uint32_t> &buffer, const gen_crc_info *crc); + static void fixup_crc_machead(std::vector<uint32_t> &buffer, const gen_crc_info *crc); + static void fixup_crc_fcs(std::vector<uint32_t> &buffer, const gen_crc_info *crc); + static void fixup_crc_victor_header(std::vector<uint32_t> &buffer, const gen_crc_info *crc); + static void fixup_crc_victor_data(std::vector<uint32_t> &buffer, const gen_crc_info *crc); + static void fixup_crcs(std::vector<uint32_t> &buffer, gen_crc_info *crcs); + static void collect_crcs(const desc_e *desc, gen_crc_info *crcs); -// this template function creates a stub which constructs a image format -template<class _FormatClass> -floppy_image_format_t *floppy_image_format_creator() -{ - return new _FormatClass(); -} + static int sbit_rp(const std::vector<bool> &bitstream, uint32_t &pos); + + static int calc_sector_index(int num, int interleave, int skew, int total_sectors, int track_head); +}; // ======================> floppy_image @@ -647,19 +463,22 @@ floppy_image_format_t *floppy_image_format_creator() //! 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 @@ -688,10 +507,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 }; @@ -706,14 +525,30 @@ public: //! Variants enum { - SSSD = 0x44535353, //!< "SSSD", Single-sided single-density - SSDD = 0x44445353, //!< "SSDD", Single-sided double-density - SSQD = 0x44515353, //!< "SSQD", Single-sided quad-density - DSSD = 0x44535344, //!< "DSSD", Double-sided single-density - DSDD = 0x44445344, //!< "DSDD", Double-sided double-density (720K in 3.5, 360K in 5.25) - DSQD = 0x44515344, //!< "DSQD", Double-sided quad-density (720K in 5.25, means DD+80 tracks) - DSHD = 0x44485344, //!< "DSHD", Double-sided high-density (1440K) - DSED = 0x44455344 //!< "DSED", Double-sided extra-density (2880K) + SSSD = 0x44535353, //!< "SSSD", Single-sided single-density + SSSD10 = 0x30315353, //!< "SS10", Single-sided single-density 10 hard sector + SSSD16 = 0x36315353, //!< "SS16", Single-sided single-density 16 hard sector + SSSD32 = 0x32335353, //!< "SS32", Single-sided single-density 32 hard sector + SSDD = 0x44445353, //!< "SSDD", Single-sided double-density + SSDD10 = 0x30314453, //!< "SD10", Single-sided double-density 10 hard sector + SSDD16 = 0x36314453, //!< "SD16", Single-sided double-density 16 hard sector + SSDD32 = 0x32334453, //!< "SD32", Single-sided double-density 32 hard sector + SSQD = 0x44515353, //!< "SSQD", Single-sided quad-density + SSQD10 = 0x30315153, //!< "SQ10", Single-sided quad-density 10 hard sector + SSQD16 = 0x36315153, //!< "SQ16", Single-sided quad-density 16 hard sector + DSSD = 0x44535344, //!< "DSSD", Double-sided single-density + DSSD10 = 0x30315344, //!< "DS10", Double-sided single-density 10 hard sector + DSSD16 = 0x36315344, //!< "DS16", Double-sided single-density 16 hard sector + DSSD32 = 0x32335344, //!< "DS32", Double-sided single-density 32 hard sector + DSDD = 0x44445344, //!< "DSDD", Double-sided double-density (720K in 3.5, 360K in 5.25) + DSDD10 = 0x30314444, //!< "DD10", Double-sided double-density 10 hard sector + DSDD16 = 0x36314444, //!< "DD16", Double-sided double-density 16 hard sector (360K in 5.25) + DSDD32 = 0x32334444, //!< "DD32", Double-sided double-density 32 hard sector + DSQD = 0x44515344, //!< "DSQD", Double-sided quad-density (720K in 5.25, means DD+80 tracks) + DSQD10 = 0x30315144, //!< "DQ10", Double-sided quad-density 10 hard sector + DSQD16 = 0x36315144, //!< "DQ16", Double-sided quad-density 16 hard sector (720K in 5.25, means DD+80 tracks) + DSHD = 0x44485344, //!< "DSHD", Double-sided high-density (1440K) + DSED = 0x44455344 //!< "DSED", Double-sided extra-density (2880K) }; //! Encodings @@ -723,24 +558,49 @@ public: M2FM = 0x4D32464D //!< "M2FM", modified modified frequency modulation }; + //! Sectoring + enum { + SOFT = 0x54464F53, //!< "SOFT", Soft-sectored + H10 = 0x20303148, //!< "H10 ", Hard 10-sectored + H16 = 0x20363148, //!< "H16 ", Hard 16-sectored + H32 = 0x20323348 //!< "H32 ", Hard 32-sectored (8 inch disk) + }; + // construction/destruction //! floppy_image constructor /*! - @param _tracks number of tracks. - @param _heads number of heads. - @param _form_factor form factor of drive (from enum) + @param tracks number of tracks. + @param heads number of heads. + @param form_factor form factor of drive (from enum) */ floppy_image(int tracks, int heads, uint32_t form_factor); - virtual ~floppy_image(); + ~floppy_image(); //! @return the form factor. - uint32_t get_form_factor() const { return form_factor; } + uint32_t get_form_factor() const noexcept { return form_factor; } //! @return the variant. - uint32_t get_variant() const { return variant; } + uint32_t get_variant() const noexcept { return variant; } + //! @return the disk sectoring. + uint32_t get_sectoring() const noexcept { return sectoring; } //! @param v the variant. - void set_variant(uint32_t v) { variant = v; } + void set_variant(uint32_t v); + //! @param v the variant. + void set_form_variant(uint32_t f, uint32_t v) { if(form_factor == FF_UNKNOWN) form_factor = f; set_variant(v); } + //! @param s the sectoring. + void set_sectoring(uint32_t s) { sectoring = s; } + + //! Find most recent and next index hole for provided angular position. + //! The most recent hole may be equal to provided position. The next + //! hole will be 200000000 if all holes of the current rotation are in + //! the past. + + /*! @param pos angular position + @param last most recent index hole + @param next next index hole + */ + void find_index_hole(uint32_t pos, uint32_t &last, uint32_t &next) const; /*! @param track @@ -748,7 +608,8 @@ public: @param head head number @return a pointer to the data buffer for this track and head */ - std::vector<uint32_t> &get_buffer(int track, int head, int subtrack = 0) { assert(track < tracks && head < heads); return track_array[track*4+subtrack][head].cell_data; } + std::vector<uint32_t> &get_buffer(int track, int head, int subtrack = 0) noexcept { assert(track < tracks && head < heads); return track_array[track*4+subtrack][head].cell_data; } + const std::vector<uint32_t> &get_buffer(int track, int head, int subtrack = 0) const noexcept { assert(track < tracks && head < heads); return track_array[track*4+subtrack][head].cell_data; } //! Sets the write splice position. //! The "track splice" information indicates where to start writing @@ -762,28 +623,31 @@ public: @param head @param pos the position */ - void set_write_splice_position(int track, int head, uint32_t pos, int subtrack = 0) { assert(track < tracks && head < heads); track_array[track*4+subtrack][head].write_splice = pos; } + void set_write_splice_position(int track, int head, uint32_t pos, int subtrack = 0) noexcept { assert(track < tracks && head < heads); track_array[track*4+subtrack][head].write_splice = pos; } //! @return the current write splice position. - uint32_t get_write_splice_position(int track, int head, int subtrack = 0) const { assert(track < tracks && head < heads); return track_array[track*4+subtrack][head].write_splice; } + uint32_t get_write_splice_position(int track, int head, int subtrack = 0) const noexcept { assert(track < tracks && head < heads); return track_array[track*4+subtrack][head].write_splice; } //! @return the maximal geometry supported by this format. - void get_maximal_geometry(int &tracks, int &heads) const; + void get_maximal_geometry(int &tracks, int &heads) const noexcept; //! @return the current geometry of the loaded image. - void get_actual_geometry(int &tracks, int &heads); + void get_actual_geometry(int &tracks, int &heads) const noexcept; //! @return the track resolution (0=full track, 1 = half-track, 2 = quarter track) - int get_resolution() const; + int get_resolution() const noexcept; + + //! @return whether a given track is formatted + bool track_is_formatted(int track, int head, int subtrack = 0) const noexcept; //! Returns the variant name for the particular disk form factor/variant //! @param form_factor //! @param variant - //! @param returns a string containing the variant name. - static const char *get_variant_name(uint32_t form_factor, uint32_t variant); + //! @return a string containing the variant name. + static const char *get_variant_name(uint32_t form_factor, uint32_t variant) noexcept; private: int tracks, heads; - uint32_t form_factor, variant; + uint32_t form_factor, variant, sectoring; struct track_info { @@ -796,6 +660,14 @@ private: // track number multiplied by 4 then head // last array size may be bigger than actual track size std::vector<std::vector<track_info> > track_array; + + // Additional index holes in increasing order. Entries are absolute + // positions of index holes in the same units as cell_data. The + // positions are the start of the hole, not the center of the hole. The + // hole at angular position 0 is implicit, so an empty list encodes a + // regular soft-sectored disk. Additional holes are found on + // hard-sectored disks. + std::vector<uint32_t> index_array; }; #endif // MAME_FORMATS_FLOPIMG_H |