summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/formats/flopimg.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/formats/flopimg.h')
-rw-r--r--src/lib/formats/flopimg.h544
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 &sector_count);
+ static void get_geometry_mfm_pc(const floppy_image &image, int cell_size, int &track_count, int &head_count, int &sector_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 &sector_count);
+ static void get_geometry_fm_pc(const floppy_image &image, int cell_size, int &track_count, int &head_count, int &sector_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