summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/formats/mfm_hd.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/formats/mfm_hd.h')
-rw-r--r--src/lib/formats/mfm_hd.h212
1 files changed, 212 insertions, 0 deletions
diff --git a/src/lib/formats/mfm_hd.h b/src/lib/formats/mfm_hd.h
new file mode 100644
index 00000000000..dfa4d3ffba7
--- /dev/null
+++ b/src/lib/formats/mfm_hd.h
@@ -0,0 +1,212 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/****************************************************************************
+
+ Hard disk support
+ See mfm_hd.c for documentation
+
+ Michael Zapf
+
+ February 2012: Rewritten as class
+
+*****************************************************************************/
+
+#ifndef __MFMHDFMT__
+#define __MFMHDFMT__
+
+#include "emu.h"
+#include "chd.h"
+
+const chd_metadata_tag MFM_HARD_DISK_METADATA_TAG = CHD_MAKE_TAG('G','D','D','I');
+
+extern const char *MFMHD_REC_METADATA_FORMAT;
+extern const char *MFMHD_GAP_METADATA_FORMAT;
+
+/*
+ Determine how data are passed from the hard disk to the controller. We
+ allow for different degrees of hardware emulation.
+*/
+enum mfmhd_enc_t
+{
+ MFM_BITS, // One bit at a time
+ MFM_BYTE, // One data byte with interleaved clock bits
+ SEPARATED, // 8 clock bits (most sig byte), one data byte (least sig byte)
+ SEPARATED_SIMPLE // MSB: 00/FF (standard / mark) clock, LSB: one data byte
+};
+
+class mfmhd_image_format_t;
+
+// Pointer to its alloc function
+typedef mfmhd_image_format_t *(*mfmhd_format_type)();
+
+template<class _FormatClass>
+mfmhd_image_format_t *mfmhd_image_format_creator()
+{
+ return new _FormatClass();
+}
+
+/*
+ Parameters for the track layout
+*/
+class mfmhd_layout_params
+{
+public:
+ // Geometry params. These are fixed for the device. However, sector sizes
+ // could be changed, but we do not support this (yet). These are defined
+ // in the CHD and must match those of the device. They are stored by the GDDD tag.
+ // The encoding is not stored in the CHD but is also supposed to be immutable.
+ int cylinders;
+ int heads;
+ int sectors_per_track;
+ int sector_size;
+ mfmhd_enc_t encoding;
+
+ // Parameters like interleave, precompensation, write current can be changed
+ // on every write operation. They are stored by the GDDI tag (first record).
+ int interleave;
+ int cylskew;
+ int headskew;
+ int write_precomp_cylinder; // if -1, no wpcom on the disks
+ int reduced_wcurr_cylinder; // if -1, no rwc on the disks
+
+ // Parameters for the track layout that are supposed to be the same for
+ // all tracks and that do not change (until the next reformat).
+ // Also, they do not have any influence on the CHD file.
+ // They are stored by the GDDI tag (second record).
+ int gap1;
+ int gap2;
+ int gap3;
+ int sync;
+ int headerlen;
+ int ecctype; // -1 is CRC
+
+ bool sane_rec()
+ {
+ return ((interleave > 0 && interleave < 32) && (cylskew >= 0 && cylskew < 32) && (headskew >= 0 && headskew < 32)
+ && (write_precomp_cylinder >= -1 && write_precomp_cylinder < 100000)
+ && (reduced_wcurr_cylinder >= -1 && reduced_wcurr_cylinder < 100000));
+ }
+
+ void reset_rec()
+ {
+ interleave = cylskew = headskew = 0;
+ write_precomp_cylinder = reduced_wcurr_cylinder = -1;
+ }
+
+ bool sane_gap()
+ {
+ return ((gap1 >= 1 && gap1 < 1000) && (gap2 >= 1 && gap2 < 20) && (gap3 >= 1 && gap3 < 1000)
+ && (sync >= 10 && sync < 20)
+ && (headerlen >= 4 && headerlen<=5) && (ecctype>=-1 && ecctype < 10));
+ }
+
+ void reset_gap()
+ {
+ gap1 = gap2 = gap3 = sync = headerlen = ecctype = 0;
+ }
+
+ bool equals_rec(mfmhd_layout_params* other)
+ {
+ return ((interleave == other->interleave) &&
+ (cylskew == other->cylskew) &&
+ (headskew == other->headskew) &&
+ (write_precomp_cylinder == other->write_precomp_cylinder) &&
+ (reduced_wcurr_cylinder == other->reduced_wcurr_cylinder));
+ }
+
+ bool equals_gap(mfmhd_layout_params* other)
+ {
+ return ((gap1 == other->gap1) &&
+ (gap2 == other->gap2) &&
+ (gap3 == other->gap3) &&
+ (sync == other->sync) &&
+ (headerlen == other->headerlen) &&
+ (ecctype == other->ecctype));
+ }
+};
+
+enum mfmhd_param_t
+{
+ MFMHD_IL,
+ MFMHD_HSKEW,
+ MFMHD_CSKEW,
+ MFMHD_WPCOM,
+ MFMHD_RWC,
+ MFMHD_GAP1,
+ MFMHD_GAP2,
+ MFMHD_GAP3,
+ MFMHD_SYNC,
+ MFMHD_HLEN,
+ MFMHD_ECC
+};
+
+/*
+ Hard disk format
+*/
+class mfmhd_image_format_t
+{
+public:
+ mfmhd_image_format_t() { m_devtag = std::string("mfmhd_image_format_t"); };
+ virtual ~mfmhd_image_format_t() {};
+
+ // Load the image.
+ virtual chd_error load(chd_file* chdfile, UINT16* trackimage, int tracksize, int cylinder, int head) = 0;
+
+ // Save the image.
+ virtual chd_error save(chd_file* chdfile, UINT16* trackimage, int tracksize, int cylinder, int head) = 0;
+
+ // Return the original parameters of the image
+ mfmhd_layout_params* get_initial_params() { return &m_param_old; }
+
+ // Return the recent parameters of the image
+ mfmhd_layout_params* get_current_params() { return &m_param; }
+
+ // Set the track layout parameters (and reset the skew detection values)
+ void set_layout_params(mfmhd_layout_params param);
+
+ // Concrete format shall decide whether we want to save the retrieved parameters or not.
+ virtual bool save_param(mfmhd_param_t type) =0;
+
+ // Accept a tag for log output, since this is not a device instance
+ void set_tag(std::string tag) { m_devtag = tag; }
+
+protected:
+ bool m_lastbit;
+ int m_current_crc;
+ int m_secnumber[4]; // used to determine the skew values
+ std::string m_devtag;
+
+ mfmhd_layout_params m_param, m_param_old;
+
+ void mfm_encode(UINT16* trackimage, int& position, UINT8 byte, int count=1);
+ void mfm_encode_a1(UINT16* trackimage, int& position);
+ void mfm_encode_mask(UINT16* trackimage, int& position, UINT8 byte, int count, int mask);
+ UINT8 mfm_decode(UINT16 raw);
+
+ // Deliver defaults.
+ virtual int get_default(mfmhd_param_t type) =0;
+
+ // Debugging
+ void showtrack(UINT16* enctrack, int length);
+ virtual const char* tag() { return m_devtag.c_str(); }
+};
+
+class mfmhd_generic_format : public mfmhd_image_format_t
+{
+public:
+ mfmhd_generic_format() { m_devtag = std::string("mfmhd_generic_format"); };
+ chd_error load(chd_file* chdfile, UINT16* trackimage, int tracksize, int cylinder, int head);
+ chd_error save(chd_file* chdfile, UINT16* trackimage, int tracksize, int cylinder, int head);
+
+ // Yes, we want to save all parameters
+ virtual bool save_param(mfmhd_param_t type) { return true; }
+ virtual int get_default(mfmhd_param_t type);
+
+protected:
+ virtual UINT8 cylinder_to_ident(int cylinder);
+ virtual int chs_to_lba(int cylinder, int head, int sector);
+};
+
+extern const mfmhd_format_type MFMHD_GEN_FORMAT;
+
+#endif