summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Olivier Galibert <galibert@pobox.com>2011-09-03 20:51:10 +0000
committer Olivier Galibert <galibert@pobox.com>2011-09-03 20:51:10 +0000
commit19b0135c3019e14d1ee7948ebf3f9abd485bb24c (patch)
treea350c8d38040f57aa9c058f97865d811efcad663
parent45ca5483743452764f948db66d1d646e283181ed (diff)
floppy: Change the internal format to use magnetic cells. Temporarily
move the full-track pll bit extraction in the amiga fdc. [O. Galibert]
-rw-r--r--src/emu/imagedev/floppy.h3
-rw-r--r--src/lib/formats/ami_dsk.c8
-rw-r--r--src/lib/formats/flopimg.c76
-rw-r--r--src/lib/formats/flopimg.h64
-rw-r--r--src/lib/formats/hxcmfm_dsk.c21
-rw-r--r--src/lib/formats/mfi_dsk.c99
-rw-r--r--src/lib/formats/mfi_dsk.h3
7 files changed, 147 insertions, 127 deletions
diff --git a/src/emu/imagedev/floppy.h b/src/emu/imagedev/floppy.h
index 487bfd47930..a06a4375c30 100644
--- a/src/emu/imagedev/floppy.h
+++ b/src/emu/imagedev/floppy.h
@@ -61,7 +61,8 @@ public:
void setup_unload_cb(unload_cb cb);
void setup_index_pulse_cb(index_pulse_cb cb);
- UINT8* get_buffer() { return m_image->get_buffer(m_cyl,m_ss ^ 1); }
+ UINT32* get_buffer() { return m_image->get_buffer(m_cyl,m_ss ^ 1); }
+ UINT32 get_len() { return m_image->get_track_size(m_cyl,m_ss ^ 1); }
void mon_w(int state);
void index_func();
diff --git a/src/lib/formats/ami_dsk.c b/src/lib/formats/ami_dsk.c
index b12b561d780..df04c178b68 100644
--- a/src/lib/formats/ami_dsk.c
+++ b/src/lib/formats/ami_dsk.c
@@ -37,7 +37,7 @@ int adf_format::identify(floppy_image *image)
UINT64 size = image->image_size();
if ((size == 901120) || (size == 1802240))
{
- return 100;
+ return 50;
}
return 0;
}
@@ -78,13 +78,11 @@ bool adf_format::load(floppy_image *image)
}
UINT8 *mfm = NULL;
- image->set_meta_data(80,2,300,(UINT16)253360);
+ image->set_meta_data(80, 2);
for(int track=0; track < 80; track++) {
for(int side=0; side < 2; side++) {
- mfm = image->get_buffer(track,side);
- image->set_track_size(track, side, 16384);
image->image_read(sectdata, (track*2 + side)*512*11, 512*11);
- generate_track(desc, track, side, sectors, 11, 100000, mfm);
+ generate_track(desc, track, side, sectors, 11, 100000, image);
}
}
diff --git a/src/lib/formats/flopimg.c b/src/lib/formats/flopimg.c
index 66150e44295..c9eccef5881 100644
--- a/src/lib/formats/flopimg.c
+++ b/src/lib/formats/flopimg.c
@@ -13,6 +13,7 @@
#include <assert.h>
#include <limits.h>
+#include "emu.h"
#include "osdcore.h"
#include "ioprocs.h"
#include "flopimg.h"
@@ -955,15 +956,32 @@ floppy_image::floppy_image(void *fp, const struct io_procs *procs, const floppy_
else
m_formats = fif;
}
+
+ memset(cell_data, 0, sizeof(cell_data));
+ memset(track_size, 0, sizeof(track_size));
+ memset(track_alloc_size, 0, sizeof(track_alloc_size));
}
floppy_image::~floppy_image()
{
- if(m_formats)
- delete m_formats;
close();
}
+void floppy_image::ensure_alloc(UINT16 track, UINT8 side)
+{
+ int idx = (track << 1) + side;
+ if(track_size[idx] > track_alloc_size[idx]) {
+ UINT32 new_size = track_size[idx]*11/10;
+ UINT32 *new_array = global_alloc_array(UINT32, new_size);
+ if(track_alloc_size[idx]) {
+ memcpy(new_array, cell_data[idx], track_alloc_size[idx]*4);
+ global_free(cell_data[idx]);
+ }
+ cell_data[idx] = new_array;
+ track_alloc_size[idx] = new_size;
+ }
+}
+
void floppy_image::image_read(void *buffer, UINT64 offset, size_t length)
{
io_generic_read(&m_io, buffer, offset, length);
@@ -995,12 +1013,10 @@ void floppy_image::close()
close_internal(TRUE);
}
-void floppy_image::set_meta_data(UINT16 tracks, UINT8 sides, UINT16 rpm, UINT16 bitrate)
+void floppy_image::set_meta_data(UINT16 _tracks, UINT8 _sides)
{
- m_tracks = tracks;
- m_sides = sides;
- m_rpm = rpm;
- m_bitrate= bitrate;
+ tracks = _tracks;
+ sides = _sides;
}
floppy_image_format_t *floppy_image::identify(int *best)
@@ -1181,9 +1197,9 @@ void floppy_image_format_t::fixup_crcs(UINT8 *buffer, gen_crc_info *crcs)
}
}
-void floppy_image_format_t::generate_track(const desc_e *desc, UINT8 track, UINT8 head, const desc_s *sect, int sect_count, int track_size, UINT8 *buffer)
+void floppy_image_format_t::generate_track(const desc_e *desc, UINT8 track, UINT8 head, const desc_s *sect, int sect_count, int track_size, floppy_image *image)
{
- memset(buffer, 0, (track_size+7)/8);
+ UINT8 *buffer = global_alloc_array_clear(UINT8, (track_size+7)/8);
gen_crc_info crcs[MAX_CRC_COUNT];
collect_crcs(desc, crcs);
@@ -1317,5 +1333,47 @@ void floppy_image_format_t::generate_track(const desc_e *desc, UINT8 track, UINT
}
fixup_crcs(buffer, crcs);
+
+ generate_track_from_bitstream(track, head, buffer, track_size, image);
+ global_free(buffer);
+}
+
+void floppy_image_format_t::normalize_times(UINT32 *buffer, int bitlen)
+{
+ unsigned int total_sum = 0;
+ for(int i=0; i != bitlen; i++)
+ total_sum += buffer[i] & floppy_image::TIME_MASK;
+
+ unsigned int current_sum = 0;
+ for(int i=0; i != bitlen; i++) {
+ UINT32 time = buffer[i] & floppy_image::TIME_MASK;
+ buffer[i] = (buffer[i] & floppy_image::MG_MASK) | (200000000ULL * current_sum / total_sum);
+ current_sum += time;
+ }
+}
+
+void floppy_image_format_t::generate_track_from_bitstream(UINT8 track, UINT8 head, const UINT8 *trackbuf, int track_size, floppy_image *image)
+{
+ // Maximal number of cells which happens when the buffer is all 1
+ image->set_track_size(track, head, track_size+1);
+ UINT32 *dest = image->get_buffer(track, head);
+ UINT32 *base = dest;
+
+ UINT32 cbit = floppy_image::MG_A;
+ UINT32 count = 0;
+ for(int i=0; i != track_size; i++)
+ if(trackbuf[i >> 3] & (0x80 >> (i & 7))) {
+ *dest++ = cbit | (count+1);
+ cbit = cbit == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
+ count = 1;
+ } else
+ count += 2;
+
+ if(count)
+ *dest++ = cbit | count;
+
+ int size = dest - base;
+ normalize_times(base, size);
+ image->set_track_size(track, head, size);
}
diff --git a/src/lib/formats/flopimg.h b/src/lib/formats/flopimg.h
index 5a2dff6616c..2827e67ba76 100644
--- a/src/lib/formats/flopimg.h
+++ b/src/lib/formats/flopimg.h
@@ -287,7 +287,9 @@ protected:
// "sect" is a vector indexed by sector id
// "track_size" is in _cells_, i.e. 100000 for a usual 2us-per-cell track at 300rpm
- void generate_track(const desc_e *desc, UINT8 track, UINT8 head, const desc_s *sect, int sect_count, int track_size, UINT8 *buffer);
+ void generate_track(const desc_e *desc, UINT8 track, UINT8 head, const desc_s *sect, int sect_count, int track_size, floppy_image *image);
+ void generate_track_from_bitstream(UINT8 track, UINT8 head, const UINT8 *trackbuf, int track_size, floppy_image *image);
+ void normalize_times(UINT32 *buffer, int bitlen);
private:
enum { CRC_NONE, CRC_AMIGA, CRC_CCITT };
@@ -325,14 +327,38 @@ floppy_image_format_t *floppy_image_format_creator()
// ======================> floppy_image
-#define MAX_FLOPPY_SIDES 2
-#define MAX_FLOPPY_TRACKS 84
-#define MAX_TRACK_DATA 16384
-
// class representing floppy image
class floppy_image
{
public:
+ // 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
+ //
+ // 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.
+ //
+ // Unformatted tracks are encoded as zero-size.
+
+ enum {
+ TIME_MASK = 0x0fffffff,
+ MG_MASK = 0xf0000000,
+ MG_SHIFT = 28,
+
+ MG_A = (0 << MG_SHIFT),
+ MG_B = (1 << MG_SHIFT),
+ MG_N = (2 << MG_SHIFT),
+ MG_D = (3 << MG_SHIFT)
+ };
+
// construction/destruction
floppy_image(void *fp, const struct io_procs *procs, const floppy_format_type *formats);
virtual ~floppy_image();
@@ -343,23 +369,31 @@ public:
UINT64 image_size();
void close();
- void set_meta_data(UINT16 tracks, UINT8 sides, UINT16 rpm, UINT16 bitrate);
- void set_track_size(UINT16 track, UINT8 side, UINT16 size) { m_track_size[(track << 1) + side] = size; }
+ void set_meta_data(UINT16 tracks, UINT8 sides);
+ void set_track_size(UINT16 track, UINT8 side, UINT32 size) { track_size[(track << 1) + side] = size; ensure_alloc(track, side); }
floppy_image_format_t *identify(int *best);
- UINT8* get_buffer(UINT16 track, UINT8 side) { return m_native_data[(track << 1) + side]; }
- UINT16 get_track_size(UINT16 track, UINT8 side) { return m_track_size[(track << 1) + side]; }
+ UINT32 *get_buffer(UINT16 track, UINT8 side) { return cell_data[(track << 1) + side]; }
+ UINT32 get_track_size(UINT16 track, UINT8 side) { return track_size[(track << 1) + side]; }
private:
+ enum {
+ MAX_FLOPPY_SIDES = 2,
+ MAX_FLOPPY_TRACKS = 84
+ };
+
void close_internal(bool close_file);
struct io_generic m_io;
floppy_image_format_t *m_formats;
- UINT16 m_tracks;
- UINT8 m_sides;
- UINT16 m_rpm;
- UINT16 m_bitrate;
- UINT8 m_native_data[MAX_FLOPPY_SIDES * MAX_FLOPPY_TRACKS][MAX_TRACK_DATA];
- UINT16 m_track_size[MAX_FLOPPY_SIDES * MAX_FLOPPY_TRACKS];
+ UINT16 tracks;
+ UINT8 sides;
+ UINT16 rpm;
+
+ UINT32 *cell_data[MAX_FLOPPY_SIDES * MAX_FLOPPY_TRACKS];
+ UINT32 track_size[MAX_FLOPPY_SIDES * MAX_FLOPPY_TRACKS];
+ UINT32 track_alloc_size[MAX_FLOPPY_SIDES * MAX_FLOPPY_TRACKS];
+
+ void ensure_alloc(UINT16 track, UINT8 side);
};
#endif /* FLOPIMG_H */
diff --git a/src/lib/formats/hxcmfm_dsk.c b/src/lib/formats/hxcmfm_dsk.c
index f1b7a2c3195..f2ef79ba901 100644
--- a/src/lib/formats/hxcmfm_dsk.c
+++ b/src/lib/formats/hxcmfm_dsk.c
@@ -1,3 +1,5 @@
+#include "emu.h"
+
#include "hxcmfm_dsk.h"
#define MFM_FORMAT_HEADER "HXCMFM"
@@ -67,22 +69,35 @@ bool mfm_format::load(floppy_image *image)
{
MFMIMG header;
MFMTRACKIMG trackdesc;
+ UINT8 *trackbuf = 0;
+ int trackbuf_size = 0;
// read header
image->image_read(&header,0, sizeof(header));
- image->set_meta_data(header.number_of_track,header.number_of_side,header.floppyRPM,header.floppyBitRate);
+ image->set_meta_data(header.number_of_track, header.number_of_side);
for(int track=0; track < header.number_of_track; track++) {
for(int side=0; side < header.number_of_side; side++) {
// read location of
image->image_read(&trackdesc,(header.mfmtracklistoffset)+((( track << 1 ) + side)*sizeof(trackdesc)),sizeof(trackdesc));
- image->set_track_size(track, side, trackdesc.mfmtracksize);
+ if(trackdesc.mfmtracksize > trackbuf_size) {
+ if(trackbuf)
+ global_free(trackbuf);
+ trackbuf_size = trackdesc.mfmtracksize;
+ trackbuf = global_alloc_array(UINT8, trackbuf_size);
+ }
+
// actual data read
- image->image_read(image->get_buffer(track,side), trackdesc.mfmtrackoffset, trackdesc.mfmtracksize);
+ image->image_read(trackbuf, trackdesc.mfmtrackoffset, trackdesc.mfmtracksize);
+
+ generate_track_from_bitstream(track, side, trackbuf, trackdesc.mfmtracksize*8, image);
}
}
+ if(trackbuf)
+ global_free(trackbuf);
+
return FALSE;
}
diff --git a/src/lib/formats/mfi_dsk.c b/src/lib/formats/mfi_dsk.c
index 7f55fa68748..6b631a70978 100644
--- a/src/lib/formats/mfi_dsk.c
+++ b/src/lib/formats/mfi_dsk.c
@@ -89,41 +89,14 @@ int mfi_format::identify(floppy_image *image)
return 0;
}
-void mfi_format::advance(const UINT32 *trackbuf, UINT32 &cur_cell, UINT32 cell_count, UINT32 time)
-{
- if(time >= 200000000) {
- cur_cell = cell_count;
- return;
- }
-
- while(cur_cell != cell_count-1 && (trackbuf[cur_cell+1] & TIME_MASK) < time)
- cur_cell++;
-}
-
-UINT32 mfi_format::get_next_edge(const UINT32 *trackbuf, UINT32 cur_cell, UINT32 cell_count)
-{
- if(cur_cell == cell_count)
- return 200000000;
- UINT32 cur_bit = trackbuf[cur_cell] & MG_MASK;
- cur_cell++;
- while(cur_cell != cell_count) {
- UINT32 next_bit = trackbuf[cur_cell] & MG_MASK;
- if(next_bit != cur_bit)
- break;
- }
- return cur_cell == cell_count ? 200000000 : trackbuf[cur_cell] & TIME_MASK;
-}
-
bool mfi_format::load(floppy_image *image)
{
header h;
entry entries[84*2];
image->image_read(&h, 0, sizeof(header));
image->image_read(&entries, sizeof(header), h.cyl_count*h.head_count*sizeof(entry));
- image->set_meta_data(h.cyl_count, h.head_count, 300, (UINT16)253360);
+ image->set_meta_data(h.cyl_count, h.head_count);
- UINT32 *trackbuf = 0;
- int trackbuf_size = 0;
UINT8 *compressed = 0;
int compressed_size = 0;
@@ -143,34 +116,16 @@ bool mfi_format::load(floppy_image *image)
compressed = global_alloc_array(UINT8, compressed_size);
}
- if(ent->uncompressed_size > trackbuf_size) {
- if(trackbuf)
- global_free(trackbuf);
- trackbuf_size = ent->uncompressed_size;
- trackbuf = global_alloc_array(UINT32, trackbuf_size/4);
- }
-
image->image_read(compressed, ent->offset, ent->compressed_size);
+ unsigned int cell_count = ent->uncompressed_size/4;
+ image->set_track_size(cyl, head, cell_count);
+ UINT32 *trackbuf = image->get_buffer(cyl, head);
+
uLongf size = ent->uncompressed_size;
if(uncompress((Bytef *)trackbuf, &size, compressed, ent->compressed_size) != Z_OK)
return true;
- UINT8 *mfm = image->get_buffer(cyl, head);
- image->set_track_size(cyl, head, 16384);
- memset(mfm, 0, 16384);
- int bit = 0;
-
- // Extract the bits using a quick-n-dirty software pll
- // expecting mfm 2us data. Eventually the plls will end
- // up in the fdc simulations themselves.
-
- // Neutral/damaged bits are not really taken into account
-
- // Start by turning the cell times into absolute
- // positions, it's easier to use that way.
-
- unsigned int cell_count = ent->uncompressed_size/4;
UINT32 cur_time = 0;
for(unsigned int i=0; i != cell_count; i++) {
UINT32 next_cur_time = cur_time + (trackbuf[i] & TIME_MASK);
@@ -180,50 +135,12 @@ bool mfi_format::load(floppy_image *image)
if(cur_time != 200000000)
return true;
- // Then pll the hell out of the bits
-
- UINT32 cur_cell = 0;
- UINT32 pll_period = 2000;
- UINT32 pll_phase = 0;
- for(;;) {
- advance(trackbuf, cur_cell, cell_count, pll_phase);
- if(cur_cell == cell_count)
- break;
-
-#if 0
- printf("%09d: (%d, %09d) - (%d, %09d) - (%d, %09d)\n",
- pll_phase,
- trackbuf[cur_cell] >> MG_SHIFT, trackbuf[cur_cell] & TIME_MASK,
- trackbuf[cur_cell+1] >> MG_SHIFT, trackbuf[cur_cell+1] & TIME_MASK,
- trackbuf[cur_cell+2] >> MG_SHIFT, trackbuf[cur_cell+2] & TIME_MASK);
-#endif
-
- UINT32 next_edge = get_next_edge(trackbuf, cur_cell, cell_count);
-
- if(next_edge > pll_phase + pll_period) {
- // free run, zero bit
- // printf("%09d: %4d - Free run\n", pll_phase, pll_period);
- pll_phase += pll_period;
- } else {
- // Transition in the window, one bit, adjust the period
-
- mfm[bit >> 3] |= 0x80 >> (bit & 7);
-
- INT32 delta = next_edge - (pll_phase + pll_period/2);
- // printf("%09d: %4d - Delta = %d\n", pll_phase, pll_period, delta);
-
- // The deltas should be lowpassed, the amplification factor tuned...
- pll_period += delta/2;
- pll_phase += pll_period;
- }
-
- bit++;
- }
- image->set_track_size(cyl, head, (bit+7)/8);
-
ent++;
}
+ if(compressed)
+ global_free(compressed);
+
return false;
}
diff --git a/src/lib/formats/mfi_dsk.h b/src/lib/formats/mfi_dsk.h
index 3983b8aead6..797b662f46d 100644
--- a/src/lib/formats/mfi_dsk.h
+++ b/src/lib/formats/mfi_dsk.h
@@ -38,9 +38,6 @@ private:
struct entry {
unsigned int offset, compressed_size, uncompressed_size;
};
-
- void advance(const UINT32 *trackbuf, UINT32 &cur_cell, UINT32 cell_count, UINT32 time);
- UINT32 get_next_edge(const UINT32 *trackbuf, UINT32 cur_cell, UINT32 cell_count);
};
extern const floppy_format_type FLOPPY_MFI_FORMAT;