From e18eceb3f17dc268c7eab66dceb7836e432e1c4d Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 24 Apr 2012 07:13:24 +0000 Subject: [PATCH] Sync with MESS (no whatsnew) --- src/lib/formats/ap2_dsk.c | 114 ++++++++++++++++++++----------- src/lib/formats/dfi_dsk.c | 138 +++++++++++++++++++++++++++++++++----- 2 files changed, 194 insertions(+), 58 deletions(-) diff --git a/src/lib/formats/ap2_dsk.c b/src/lib/formats/ap2_dsk.c index d895b402b04..eed596f0883 100644 --- a/src/lib/formats/ap2_dsk.c +++ b/src/lib/formats/ap2_dsk.c @@ -613,31 +613,32 @@ const floppy_image_format_t::desc_e a2_16sect_format::mac_gcr[] = { bool a2_16sect_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) { +/* TODO: rewrite me properly + UINT8 sector_data[(256)*16]; + memset(sector_data, 0, sizeof(sector_data)); - UINT8 sector_data[(256)*16]; - memset(sector_data, 0, sizeof(sector_data)); + desc_s sectors[16]; + int format = 0; + int pos_data = 0; - desc_s sectors[16]; - int format = 0; - int pos_data = 0; + int head_count = 1; - int head_count = 1; - - for(int track=0; track < 35; track++) { - for(int head=0; head < head_count; head++) { - for(int si=0; si<16; si++) { - UINT8 *data = sector_data + (256)*si; - sectors[si].data = data; - sectors[si].size = 256; - sectors[si].sector_id = si; - sectors[si].sector_info = format; - io_generic_read(io, data, pos_data, 256); - pos_data += 256; - } - generate_track(mac_gcr, track, head, sectors, 16, 3104*16, image); - } - } - return true; + for(int track=0; track < 35; track++) { + for(int head=0; head < head_count; head++) { + for(int si=0; si<16; si++) { + UINT8 *data = sector_data + (256)*si; + sectors[si].data = data; + sectors[si].size = 256; + sectors[si].sector_id = si; + sectors[si].sector_info = format; + io_generic_read(io, data, pos_data, 256); + pos_data += 256; + } + generate_track(mac_gcr, track, head, sectors, 16, 3104*16, image); + } + } + return true;*/ + return false; // I hope that throws an error... } UINT8 a2_16sect_format::gb(const UINT8 *buf, int ts, int &pos, int &wrap) @@ -664,10 +665,15 @@ bool a2_16sect_format::save(io_generic *io, floppy_image *image) int g_tracks, g_heads; int visualgrid[16][35]; // visualizer grid, cleared/initialized below #define NOTFOUND 0 +// address mark was found #define ADDRFOUND 1 +// address checksum is good #define ADDRGOOD 2 +// data mark was found (requires addrfound and sane values) #define DATAFOUND 4 +// data checksum is good #define DATAGOOD 8 +// data postamble is good #define DATAPOST 16 for (int i = 0; i < 16; i++) { for (int j = 0; j < 35; j++) { @@ -686,12 +692,14 @@ bool a2_16sect_format::save(io_generic *io, floppy_image *image) int nsect = 16; UINT8 buf[130000]; // originally 13000, multiread dfi disks need larger int ts; -fprintf(stderr,"DEBUG: a2_16sect_format::save() about to generate bitstream from physical track %d (logical %d)...", track, track/2); - generate_bitstream_from_track(track, head, 200000000/(3104*nsect*1), buf, ts, image); // 3104 needs tweaking, *3 is 3x multiread from a dfi disk -fprintf(stderr,"done.\n"); +//fprintf(stderr,"DEBUG: a2_16sect_format::save() about to generate bitstream from physical track %d (logical %d)...", track, track/2); + //~332 samples per cell, times 3+8+3 (14) for address mark, 24 for sync, 3+343+3 (349) for data mark, 24 for sync is around 743, near 776 expected + generate_bitstream_from_track(track, head, 200000000/(3104*nsect*3), buf, ts, image); // 3104 needs tweaking, *3 is 3x multiread from a dfi disk +//fprintf(stderr,"done.\n"); int pos = 0; int wrap = 0; int hb = 0; + int dosver = 0; // apple dos version; 0 = >=3.3, 1 = <3.3 for(;;) { UINT8 v = gb(buf, ts, pos, wrap); if(v == 0xff) @@ -700,8 +708,10 @@ fprintf(stderr,"done.\n"); hb = 2; else if(hb == 2 && v == 0xaa) hb = 3; - else if(hb == 3 && v == 0x96) + else if(hb == 3 && ((v == 0x96) || (v == 0xab))) { // 0x96 = dos 3.3/16sec, 0xab = dos 3.21 and below/13sec hb = 4; + if (v == 0xab) dosver = 1; + } else hb = 0; @@ -735,9 +745,13 @@ fprintf(stderr,"done.\n"); else hb = 0; } - if(hb == 4) { + if((hb == 4)&&(dosver == 0)) { visualgrid[se][track/2] |= DATAFOUND; - UINT8 *dest = sectdata+(256)*se; + int prodos_translate[16] = { + 0x00, 0x08, 0x01, 0x09, 0x02, 0x0A, 0x03, 0x0B, + 0x04, 0x0C, 0x05, 0x0D, 0x06, 0x0E, 0x07, 0x0F + }; + UINT8 *dest = sectdata+(256)*prodos_translate[se]; UINT8 data[0x157]; UINT32 dpost = 0; UINT8 c = 0; @@ -766,22 +780,40 @@ fprintf(stderr,"done.\n"); // now decode it into 256 bytes // but only write it if the bitfield of the track shows datagood is NOT set. // if it is set we don't want to overwrite a guaranteed good read with a bad one - if ((visualgrid[se][track/2]&DATAGOOD)==0) { - // TODO: - // if the current read is good but the postamble isn't, write it in. - // if the current read isn't good but the postamble is, its better than nothing. + // if past read had a bad checksum or bad postamble... +#ifndef USE_OLD_BEST_SECTOR_PRIORITY + if (((visualgrid[se][track/2]&DATAGOOD)==0)||((visualgrid[se][track/2]&DATAPOST)==0)) { + // if the current read is good, and postamble is good, write it in, no matter what. + // if the current read is good and the current postamble is bad, write it in unless the postamble was good before + // if the current read is bad and the current postamble is good and the previous read had neither good, write it in // if the current read isn't good and neither is the postamble but nothing better // has been written before, write it anyway. - for(int i=0x56; i<0x156; i++) { - UINT8 dv = data[i]; - *dest++ = dv; + if ( ((data[0x156] == c) && (dpost&0xFFFF00)==0xDEAA00) || + (((data[0x156] == c) && (dpost&0xFFFF00)!=0xDEAA00) && ((visualgrid[se][track/2]&DATAPOST)==0)) || + (((data[0x156] != c) && (dpost&0xFFFF00)==0xDEAA00) && (((visualgrid[se][track/2]&DATAGOOD)==0)&&(visualgrid[se][track/2]&DATAPOST)==0)) || + (((data[0x156] != c) && (dpost&0xFFFF00)!=0xDEAA00) && (((visualgrid[se][track/2]&DATAGOOD)==0)&&(visualgrid[se][track/2]&DATAPOST)==0)) + ) { + for(int i=0x56; i<0x156; i++) { + UINT8 dv = data[i]; + *dest++ = dv; + } } } - // do some checking - if ((data[0x156] != c) || (dpost&0xFFFF00)!=0xDEAA00) { - printf("Data Mark:\tChecksum xpctd %d found %d: %s, Postamble %03X: %s\n", data[0x156], c, (data[0x156]==c)?"OK":"BAD", dpost, (dpost&0xFFFF00)==0xDEAA00?"OK":"BAD"); +#else + if ((visualgrid[se][track/2]&DATAGOOD)==0) { + for(int i=0x56; i<0x156; i++) { + UINT8 dv = data[i]; + *dest++ = dv; + } } - else visualgrid[se][track/2] |= DATAGOOD; +#endif + // do some checking + if ((data[0x156] != c) || (dpost&0xFFFF00)!=0xDEAA00) + fprintf(stderr,"Data Mark:\tChecksum xpctd %d found %d: %s, Postamble %03X: %s\n", data[0x156], c, (data[0x156]==c)?"OK":"BAD", dpost, (dpost&0xFFFF00)==0xDEAA00?"OK":"BAD"); + if (data[0x156] == c) visualgrid[se][track/2] |= DATAGOOD; + if ((dpost&0xFFFF00)==0xDEAA00) visualgrid[se][track/2] |= DATAPOST; + } else if ((hb == 4)&&(dosver == 1)) { + fprintf(stderr,"ERROR: We don't handle dos sectors below 3.3 yet!\n"); } else { pos = opos; wrap = owrap; @@ -804,14 +836,14 @@ fprintf(stderr,"done.\n"); for (int j = 0; j < 35; j++) { printf("T%2d: ",j); for (int i = 0; i < 16; i++) { - if (visualgrid[i][j] == NOTFOUND) printf("-NF-"); + if (visualgrid[i][j] == NOTFOUND) printf("-NF- "); else { if (visualgrid[i][j] & ADDRFOUND) printf("a"); else printf(" "); if (visualgrid[i][j] & ADDRGOOD) printf("A"); else printf(" "); if (visualgrid[i][j] & DATAFOUND) printf("d"); else printf(" "); if (visualgrid[i][j] & DATAGOOD) printf("D"); else printf(" "); + if (visualgrid[i][j] & DATAPOST) printf("."); else printf(" "); } - printf(" "); } printf("\n"); } diff --git a/src/lib/formats/dfi_dsk.c b/src/lib/formats/dfi_dsk.c index 92395d04282..2dd4af8d158 100644 --- a/src/lib/formats/dfi_dsk.c +++ b/src/lib/formats/dfi_dsk.c @@ -31,10 +31,34 @@ ****************************************************************************/ +/* DONE: + * Support auto-identification heuristics for determining disk image speed, + capture clock rate, and number of multireads per image. + * TODO: + * Scale captured data based on the guessed clock rate and samplerate to match + the internal 200mhz representation + * Handle 0xFF bytes properly + * Correctly note exact index timing. + */ + #include "emu.h" #include "dfi_dsk.h" #include -#define NUMBER_OF_MULTIREADS 1 +#define NUMBER_OF_MULTIREADS 3 +// threshholds for brickwall windowing +//define MIN_CLOCKS 65 +#define MIN_CLOCKS 40 +//define MAX_CLOCKS 260 +#define MAX_CLOCKS 270 +#define MIN_THRESH (MIN_CLOCKS*(clock_rate/25000000)) +#define MAX_THRESH (MAX_CLOCKS*(clock_rate/25000000)) +// constants to help guess clockrate and rpm +// constant is 25mhz / 6 revolutions per second (360rpm) = 4166667 +- 2.5% +#define REV25_MIN 4062500 +#define REV25_MAX 4270833 +// define the following to show a histogram per track +//define TRACK_HISTOGRAM 1 +#undef TRACK_HISTOGRAM dfi_format::dfi_format() : floppy_image_format_t() { @@ -64,6 +88,8 @@ int dfi_format::identify(io_generic *io, UINT32 form_factor) { char sign[4]; io_generic_read(io, sign, 0, 4); + if (memcmp(sign, "DFER", 4)) + fatalerror("Old type Discferret image detected; the mess Discferret decoder will not handle this properly, bailing out!\n"); return memcmp(sign, "DFE2", 4) ? 0 : 100; } @@ -72,8 +98,10 @@ bool dfi_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) int size = io_generic_size(io); int pos = 4; UINT8 *data = 0; - int data_size = 0; - + int data_size = 0; // size of currently allocated array for a track + int onerev_time = 0; // time for one revolution, used to guess clock and rpm for DFE2 files + unsigned long clock_rate = 100000000; // sample clock rate in megahertz + int rpm=360; // drive rpm while(pos < size) { UINT8 h[10]; io_generic_read(io, h, pos, 10); @@ -82,12 +110,15 @@ bool dfi_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) // Ignore sector UINT32 tsize = (h[6] << 24) | (h[7] << 16) | (h[8] << 8) | h[9]; + // if the position-so-far-in-file plus 10 (for the header) plus track size + // is larger than the size of the file, free buffers and bail out if(pos+tsize+10 > size) { if(data) global_free(data); return false; } + // reallocate the data array if it gets too small if(tsize > data_size) { if(data) global_free(data); @@ -95,21 +126,26 @@ bool dfi_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) data = global_alloc_array(UINT8, data_size); } - io_generic_read(io, data, pos+16, tsize); - pos += tsize+10; - tsize--; // Drop the extra 0x00 at the end + pos += 10; // skip the header, we already read it + io_generic_read(io, data, pos, tsize); + pos += tsize; // for next time we read, increment to the beginning of next header - int index_time = 0; - int index_count = 0; - int total_time = 0; + int index_time = 0; // what point the last index happened + int index_count = 0; // number of index pulses per track + int index_polarity = 0; // current polarity of index + int total_time = 0; // total sampled time per track for(int i=0; i REV25_MIN) && (onerev_time < REV25_MAX)) { + fprintf(stderr, "Guess: speed: 360rpm, clock 25MHz\n"); + clock_rate = 25000000; rpm = 360; + } else if ((onerev_time > REV25_MIN*1.2) && (onerev_time < REV25_MAX*1.2)) { + fprintf(stderr, "Guess: speed: 300rpm, clock 25MHz\n"); + clock_rate = 25000000; rpm = 300; + } else if ((onerev_time > REV25_MIN*2) && (onerev_time < REV25_MAX*2)) { + fprintf(stderr, "Guess: speed: 360rpm, clock 50MHz\n"); + clock_rate = 50000000; rpm = 360; + } else if ((onerev_time > (REV25_MIN*2)*1.2) && (onerev_time < (REV25_MAX*2)*1.2)) { + fprintf(stderr, "Guess: speed: 300rpm, clock 50MHz\n"); + clock_rate = 50000000; rpm = 300; + } else if ((onerev_time > REV25_MIN*4) && (onerev_time < REV25_MAX*4)) { + fprintf(stderr, "Guess: speed: 360rpm, clock 100MHz\n"); + clock_rate = 100000000; rpm = 360; + } else if ((onerev_time > (REV25_MIN*4)*1.2) && (onerev_time < (REV25_MAX*4)*1.2)) { + fprintf(stderr, "Guess: speed: 300rpm, clock 100MHz\n"); + clock_rate = 100000000; rpm = 300; + } else + fprintf(stderr, "WARNING: Cannot Guess Speed! Assuming 360rpm, 100Mhz clock!\n"); + fprintf(stderr,"Actual rpm based on index: %f\n", ((double)clock_rate/(double)onerev_time)*60); + } + + rpm += 0; // HACK: prevent GCC 4.6+ from warning "variable set but unused" if(!index_time) index_time = total_time; @@ -124,26 +186,68 @@ bool dfi_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) image->set_track_size(track, head, tsize); int cur_time = 0; + int prev_time = 0; +#ifdef TRACK_HISTOGRAM + // histogram + int time_buckets[4096]; + for (int i = 0; i < 4096; i++) + time_buckets[i] = 0; +#endif index_count = 0; - int index_polarity = 0; + index_polarity = 0; UINT32 mg = floppy_image::MG_A; UINT32 *buf = image->get_buffer(track, head); int tpos = 0; buf[tpos++] = mg; for(int i=0; i MIN_THRESH))) { + if ((prev_time == 0) || ((trans_time > MIN_THRESH) && (trans_time <= MAX_THRESH))) { + mg = mg == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A; + buf[tpos++] = mg | UINT32((200000000ULL*cur_time)/index_time); + prev_time = cur_time; + } + if (trans_time > MAX_THRESH) { // we probably missed a transition + mg = mg == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A; + if (((track%2)==0)&&(head==0)) fprintf(stderr,"missed transition, total time for transition is %d\n",trans_time); + buf[tpos++] = mg | UINT32((200000000ULL*(cur_time-(trans_time/2)))/index_time); // generate imaginary transition at half period + buf[tpos++] = mg | UINT32(200000000ULL*cur_time/index_time); // generate transition now + prev_time = cur_time; + } } else if(v & 0x80) { // 0x80-0xFF an index, note the index (TODO: actually do this!) and do not add number index_polarity ^= 1; index_count += index_polarity; if (index_count == NUMBER_OF_MULTIREADS) break; } } +#ifdef TRACK_HISTOGRAM + if (((track%2)==0)&&(head==0)) { + for (int i = 0; i < 4096; i++) { + fprintf(stderr,"%4d:%4d ", i, time_buckets[i]); + if (((i+1)%10)==0) fprintf(stderr,"\n"); + } + } + fprintf(stderr,"\n"); +#endif + index_count = 0; image->set_track_size(track, head, tpos); }