floppy: Change the internal format to use magnetic cells. Temporarily

move the full-track pll bit extraction in the amiga fdc. [O. Galibert]
This commit is contained in:
Olivier Galibert 2011-09-03 20:51:10 +00:00
parent 45ca548374
commit 19b0135c30
7 changed files with 147 additions and 127 deletions

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;