Sync with MESS (no whatsnew)

This commit is contained in:
Miodrag Milanovic 2012-04-24 07:13:24 +00:00
parent f5ffd68141
commit e18eceb3f1
2 changed files with 194 additions and 58 deletions

View File

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

View File

@ -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 <zlib.h>
#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<tsize; i++) {
UINT8 v = data[i];
if (v == 0xFF) { fprintf(stderr,"DFI stream contained a 0xFF at t%d, position%d, THIS SHOULD NEVER HAPPEN!\n", track, i); exit(1); }
if((v & 0x7f) == 0x7f)
total_time += 0x7f;
else {
total_time += v & 0x7f;
if((v & 0x80) && (index_count<NUMBER_OF_MULTIREADS)) {
index_time = total_time;///NUMBER_OF_MULTIREADS;
if((v & 0x80)==0) total_time += v & 0x7f;
if(v & 0x80) {
index_time = total_time;
if (onerev_time == 0) onerev_time = total_time;
//index_polarity ^= 1;
//index_count =+ index_polarity;
index_count++;
}
}
@ -117,6 +153,32 @@ bool dfi_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
if(!track && !head)
fprintf(stderr, "%02d:%d tt=%10d it=%10d\n", track, head, total_time, index_time);
if(!track && !head) {
fprintf(stderr, "index_count: %d, onerev_time: %d\n", index_count, onerev_time);
if ((onerev_time > 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<tsize; i++) {
UINT8 v = data[i];
if((v & 0x7f) == 0x7f) // 0x7F or 0xFF: no transition, but a carry
cur_time += 0x7f;
if((v & 0x7f) == 0x7f) {// 0x7F or 0xFF: no transition, but a carry
cur_time += 0x7f; // should this be done if v&80 is also set?
if(v & 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;
}
}
else if((v & 0x80) == 0) { // 0x00-0x7E: not an index or carry, add the number and store transition
cur_time += v & 0x7f;
mg = mg == floppy_image::MG_A ? floppy_image::MG_B : floppy_image::MG_A;
buf[tpos++] = mg | UINT32(200000000ULL*cur_time/index_time);
int trans_time = cur_time - prev_time;
#ifdef TRACK_HISTOGRAM
time_buckets[(trans_time<4096)?trans_time:4095]++;
#endif
// cur_time and onerev_time need to be converted to something standard, so we'll stick with 300rpm at the standard 200mhz rate that mfi uses internally
// TODO for 4/22/2012: ACTUALLY DO THIS RESCALING STEP
// filter out spurious crap
//if (trans_time <= MIN_THRESH) fprintf(stderr, "DFI: Throwing out short transition of length %d\n", trans_time);
//if ((prev_time == 0) || ((trans_time > 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);
}