summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/formats/pasti_dsk.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/formats/pasti_dsk.cpp')
-rw-r--r--src/lib/formats/pasti_dsk.cpp607
1 files changed, 607 insertions, 0 deletions
diff --git a/src/lib/formats/pasti_dsk.cpp b/src/lib/formats/pasti_dsk.cpp
new file mode 100644
index 00000000000..6fa53b2590d
--- /dev/null
+++ b/src/lib/formats/pasti_dsk.cpp
@@ -0,0 +1,607 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+#include "emu.h" // logerror
+#include "pasti_dsk.h"
+
+// Pasti format supported using the documentation at
+// http://www.sarnau.info/atari:pasti_file_format
+
+// That format is an observational format, not a generative one. In
+// other terms, it encodes the raw responses of the WD1772 to the read
+// track, read ids and read sectors commands. So, in order to use it,
+// we have to build a physical representation which gives similar
+// enough results (read track varies even in the absence of fuzzy
+// bits).
+
+pasti_format::pasti_format()
+{
+}
+
+const char *pasti_format::name() const
+{
+ return "pasti";
+}
+
+const char *pasti_format::description() const
+{
+ return "Atari PASTI floppy disk image";
+}
+
+const char *pasti_format::extensions() const
+{
+ return "stx";
+}
+
+bool pasti_format::supports_save() const
+{
+ return false;
+}
+
+int pasti_format::identify(io_generic *io, UINT32 form_factor)
+{
+ UINT8 h[16];
+ io_generic_read(io, h, 0, 16);
+
+ if(!memcmp(h, "RSY\0\3\0", 6) &&
+ (1 || (h[10] >= 80 && h[10] <= 82) || (h[10] >= 160 && h[10] <= 164)))
+ return 100;
+
+ return 0;
+}
+
+static void hexdump(const UINT8 *d, int s)
+{
+ for(int i=0; i<s; i+=32) {
+ printf("%04x:", i);
+ for(int j=i; j<s && j<i+32; j++)
+ printf(" %02x", d[j]);
+ printf("\n");
+ }
+}
+
+bool pasti_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
+{
+ UINT8 fh[16];
+ io_generic_read(io, fh, 0, 16);
+
+ dynamic_buffer raw_track;
+
+ int tracks = fh[10];
+ int heads = 1+(tracks >= 160);
+ tracks /= heads;
+
+ int pos = 16;
+
+ wd_obs obs;
+
+ for(int track=0; track < tracks; track++) {
+ for(int head=0; head < heads; head++) {
+ UINT8 th[16];
+ io_generic_read(io, th, pos, 16);
+ int entry_len = th[0] | (th[1] << 8) | (th[2] << 16) | (th[3] << 24);
+ int fuzz_len = th[4] | (th[5] << 8) | (th[6] << 16) | (th[7] << 24);
+ int sect = th[8] | (th[9] << 8);
+ int flags = th[10] | (th[11] << 8);
+ int track_len = th[12] | (th[13] << 8);
+ int track_num = th[14];
+ int flags2 = th[15];
+
+ raw_track.resize(entry_len-16);
+
+ io_generic_read(io, &raw_track[0], pos+16, entry_len-16);
+
+ UINT8 *fuzz = fuzz_len ? &raw_track[16*sect] : 0;
+ UINT8 *bdata = fuzz ? fuzz+fuzz_len : &raw_track[16*sect];
+ UINT8 *tdata = bdata;
+
+ int syncpos = -1;
+ if(flags & 0x0080) {
+ syncpos = tdata[0] | (tdata[1] << 8);
+ tdata += 2;
+ }
+
+ int tsize = 0;
+ if(flags & 0x0040) {
+ tsize = tdata[0] | (tdata[1] << 8);
+ tdata += 2;
+ } else
+ tdata = 0;
+
+ if(0) {
+ printf("Track %2d.%d: el=%d fl=%d sect=%d flags=%04x tlen=%d/%d tnum=%d flags2=%02x sync=%x\n",
+ track, head,
+ entry_len, fuzz_len, sect, flags, track_len, tsize, track_num, flags2, syncpos);
+ hexdump(&raw_track[16*sect], entry_len-16-16*sect);
+ }
+
+ if(0 && tdata) {
+ hexdump(tdata, tsize);
+
+ for(int i=0; i<tsize-8; i++) {
+ if(tdata[i] == 0xa1 && tdata[i+1] == 0xa1 && tdata[i+2] != 0xa1)
+ printf(" header %5d: %02x %02x %02x %02x %02x %02x %02x\n",
+ i+2,
+ tdata[i+2], tdata[i+3], tdata[i+4], tdata[i+5], tdata[i+6], tdata[i+7], tdata[i+8]);
+ }
+ }
+
+ for(int s=0; s<sect; s++) {
+ UINT8 *sh = &raw_track[16*s];
+ int s_off = sh[0] | (sh[1] << 8) | (sh[2] << 16) | (sh[3] << 24);
+ int s_pos = sh[4] | (sh[5] << 8);
+ int s_time = sh[6] | (sh[7] << 8);
+ int s_flags = sh[14] | (sh[15] << 8);
+
+ obs.sectors[s].data = bdata + s_off;
+ obs.sectors[s].fuzzy_mask = 0;
+ memcpy(obs.sectors[s].id, sh+8, 6);
+ obs.sectors[s].time_ratio = s_time ? s_time / 16384.0 : 1;
+ obs.sectors[s].position = s_pos/8-12;
+ if(0) {
+ printf(" sector %2d: off=%5d pos=%5d [%02x %02x] time=%04x flags=%04x id=%02x.%02x.%02x.%02x.%02x.%02x\n",
+ s, s_off, s_pos, tdata ? tdata[s_pos/8] : 0x00, tdata ? tdata[s_pos/8+1] : 0x00, s_time, s_flags,
+ sh[8], sh[9], sh[10], sh[11], sh[12], sh[13]);
+ hexdump(bdata+s_off, 128<<(sh[11] & 3));
+ }
+ }
+
+ obs.track_data = tdata;
+ obs.track_size = tsize;
+ obs.sector_count = sect;
+
+ wd_generate_track_from_observations(track, head, image, obs);
+
+ pos += entry_len;
+ }
+ }
+
+ image->set_variant(floppy_image::DSDD);
+ return true;
+}
+
+const floppy_format_type FLOPPY_PASTI_FORMAT = &floppy_image_format_creator<pasti_format>;
+
+
+void pasti_format::wd_generate_track_from_observations(int track, int head, floppy_image *image, wd_obs &obs)
+{
+ if(!obs.track_data)
+ wd_generate_track_from_sectors_only(track, head, image, obs);
+ else
+ wd_generate_track_from_sectors_and_track(track, head, image, obs);
+}
+
+void pasti_format::wd_generate_unsynced_gap(std::vector<UINT32> &track, const wd_obs &obs, int tstart, int tend, UINT32 cell_size)
+{
+ for(int i=tstart; i != tend;) {
+ unsigned char v = obs.track_data[i];
+ int j;
+ for(j=i+1; j != tend && obs.track_data[j] == v; j++);
+ int size = j-i;
+ if(size < 4) {
+ mfm_w(track, 8, v, cell_size);
+ i++;
+ continue;
+ }
+ if(v == 0xff || v == 0x00)
+ v = 0;
+ else if(v == 0x4e || v == 0x21 || v == 0x9c || v == 0x42 || v == 0x39 || v == 0x84 || v == 0x72 || v == 0x09 ||
+ v == 0xe4 || v == 0x12 || v == 0xc9 || v == 0x24 || v == 0x93 || v == 0x48 || v == 0x27 || v == 0x90)
+ v = 0x4e;
+ // Grab the transition byte too
+ if((v == 0 || v == 0x4e) && j != tend)
+ size++;
+ for(j=0; j != size; j++)
+ mfm_w(track, 8, v, cell_size);
+ i += size;
+ }
+}
+
+void pasti_format::wd_generate_synced_gap(std::vector<UINT32> &track, const wd_obs &obs, int tstart, int tend, UINT32 cell_size)
+{
+ for(int i = tstart; i != tend; i++) {
+ unsigned char v = obs.track_data[i];
+ if((v == 0x14 || v == 0xa1 || v == 0xc2) && i+2 < tend && obs.track_data[i+1] == 0xa1 && obs.track_data[i+2] == 0xa1) {
+ raw_w(track, 16, 0x4489, cell_size);
+ raw_w(track, 16, 0x4489, cell_size);
+ raw_w(track, 16, 0x4489, cell_size);
+ i += 2;
+ } else if(!track.empty() && i != tend-1 && (((v == 0x14 || v == 0xc2) && (track.back() & 0x1f) == 10) || (v == 0xa1 && (track.back() & 0x1f) != 10)))
+ raw_w(track, 16, 0x4489, cell_size);
+ else if(i != tend-1 && (v == 0x14 || v == 0xc2))
+ raw_w(track, 16, 0x5224, cell_size);
+ else
+ mfm_w(track, 8, v, cell_size);
+ }
+}
+
+void pasti_format::wd_generate_gap(std::vector<UINT32> &track, const wd_obs &obs, int tstart, int tend, bool synced, UINT32 cell_size_start, UINT32 cell_size_end)
+{
+ unsigned int spos = track.size();
+ if(!synced) {
+ int sync = -1;
+ for(int i = tstart; sync == -1 && i != tend; i++)
+ if(obs.track_data[i] == 0x14 || obs.track_data[i] == 0xa1 || obs.track_data[i] == 0xc2)
+ sync = i;
+ if(sync == -1)
+ sync = tend;
+ wd_generate_unsynced_gap(track, obs, tstart, sync, cell_size_start);
+ tstart = sync;
+ }
+ if(tstart != tend)
+ wd_generate_synced_gap(track, obs, tstart, tend, cell_size_start);
+
+ if(cell_size_end != cell_size_start) {
+ INT32 total_size = 0;
+ for(unsigned int i=spos; i != track.size(); i++)
+ total_size += track[i] & floppy_image::TIME_MASK;
+ INT64 cur_size = 0;
+ for(unsigned int i=spos; i != track.size(); i++) {
+ cur_size += track[i] & floppy_image::TIME_MASK;
+ track[i] = (track[i] & floppy_image::MG_MASK) |
+ (cur_size*int(cell_size_end-cell_size_start)/total_size + cell_size_start);
+ }
+ }
+}
+
+void pasti_format::wd_generate_sector_header(std::vector<UINT32> &track, const wd_obs &obs, int sector, int tstart, UINT32 cell_size)
+{
+ raw_w(track, 16, 0x4489, cell_size);
+ raw_w(track, 16, 0x4489, cell_size);
+ raw_w(track, 16, 0x4489, cell_size);
+ mfm_w(track, 8, obs.track_data[tstart+3], cell_size);
+ for(int i=0; i != 6; i++)
+ mfm_w(track, 8, obs.sectors[sector].id[i], cell_size);
+}
+
+void pasti_format::wd_generate_sector_data(std::vector<UINT32> &track, const wd_obs &obs, int sector, int tstart, UINT32 cell_size)
+{
+ const wd_sect &s = obs.sectors[sector];
+ raw_w(track, 16, 0x4489, cell_size);
+ raw_w(track, 16, 0x4489, cell_size);
+ raw_w(track, 16, 0x4489, cell_size);
+ mfm_w(track, 8, obs.track_data[tstart+3], cell_size);
+ for(int i=0; i<128 << (s.id[3] & 3); i++)
+ mfm_w(track, 8, s.data[i], cell_size);
+ UINT16 crc = calc_crc_ccitt(track, track.size() - (2048 << (s.id[3] & 3)) - 16*4, track.size());
+ mfm_w(track, 8, crc >> 8, cell_size);
+ mfm_w(track, 8, crc, cell_size);
+}
+
+void pasti_format::wd_generate_track_from_sectors_and_track(int track, int head, floppy_image *image, wd_obs &obs)
+{
+ if(0)
+ printf("Track %d head %d sectors %d\n", track, head, obs.sector_count);
+ std::vector<UINT32> trackbuf;
+
+ wd_sect_info sect_infos[256];
+
+ if(0)
+ hexdump(obs.track_data, obs.track_size);
+ map_sectors_in_track(obs, sect_infos);
+
+ if(0)
+ for(int i=0; i != obs.sector_count; i++) {
+ wd_sect_info *s = sect_infos + i;
+ printf("%2d: %5d-%5d %c %02x %02x|%02x %02x %5d-%5d %c %02x %02x|%02x %02x %f\n",
+ i,
+ s->hstart, s->hend, s->hsynced ? 'S' : '-',
+ s->hstart == -1 ? 0 : obs.track_data[s->hstart],
+ s->hstart == -1 ? 0 : obs.track_data[s->hstart+1],
+ s->hend == -1 ? 0 : obs.track_data[s->hend],
+ s->hend == -1 ? 0 : obs.track_data[s->hend+1],
+
+ s->dstart, s->dend, s->dsynced ? 'S' : '-',
+ s->dstart == -1 ? 0 : obs.track_data[s->dstart],
+ s->dstart == -1 ? 0 : obs.track_data[s->dstart+1],
+ s->dend == -1 ? 0 : obs.track_data[s->dend],
+ s->dend == -1 ? 0 : obs.track_data[s->dend+1],
+
+ obs.sectors[i].time_ratio);
+ }
+
+ if(obs.sector_count) {
+ wd_sect_info *last = sect_infos + obs.sector_count-1;
+ if(last->dend != -1 && last->dend < last->hstart) {
+ osd_printf_error("pasti: Unsupported sector header/data over index, track %d head %d\n", track, head);
+ return;
+ }
+
+ UINT32 cell_size = UINT32(obs.sectors[0].time_ratio * 1000+0.5);
+ wd_generate_gap(trackbuf, obs, 0, sect_infos[0].hstart, false, cell_size, cell_size);
+
+ for(int i=0; i != obs.sector_count; i++) {
+ wd_sect_info *s = sect_infos + i;
+ if(i+1 != obs.sector_count) {
+ if(s->dstart != -1 && s[1].hstart < s->dend) {
+ osd_printf_error("pasti: Unsupported sector overlap, track %d head %d\n", track, head);
+ return;
+ }
+ }
+
+ UINT32 ncell_size = UINT32(obs.sectors[i+1 != obs.sector_count ? i+1 : 0].time_ratio * 1000+0.5);
+
+ wd_generate_sector_header(trackbuf, obs, i, s->hstart, cell_size);
+
+ if(s->dstart == -1) {
+ if(i == obs.sector_count-1)
+ wd_generate_gap(trackbuf, obs, s->hend, obs.track_size, s->hsynced, cell_size, ncell_size);
+ else
+ wd_generate_gap(trackbuf, obs, s->hend, s[1].hstart, s->hsynced, cell_size, ncell_size);
+ } else {
+ wd_generate_gap(trackbuf, obs, s->hend, s->dstart, s->hsynced, cell_size, cell_size);
+ wd_generate_sector_data(trackbuf, obs, i, s->dstart, cell_size);
+ if(i == obs.sector_count-1)
+ wd_generate_gap(trackbuf, obs, s->dend, obs.track_size, s->dsynced, cell_size, ncell_size);
+ else
+ wd_generate_gap(trackbuf, obs, s->dend, s[1].hstart, s->dsynced, cell_size, ncell_size);
+ }
+ cell_size = ncell_size;
+ }
+
+ } else
+ wd_generate_gap(trackbuf, obs, 0, obs.track_size, false, 1000, 1000);
+
+ generate_track_from_levels(track, head, trackbuf, 0, image);
+}
+
+void pasti_format::wd_generate_track_from_sectors_only(int track, int head, floppy_image *image, wd_obs &obs)
+{
+ if(0) {
+ printf("Track %d head %d sectors %d\n", track, head, obs.sector_count);
+ for(int i=0; i != obs.sector_count; i++) {
+ const wd_sect &s = obs.sectors[i];
+
+ printf("%2d: %02x.%02x.%02x.%02x.%02x.%02x %d %f\n",
+ i,
+ s.id[0], s.id[1], s.id[2], s.id[3], s.id[4], s.id[5],
+ s.position,
+ s.time_ratio);
+ if(track==10 && i==0)
+ hexdump(s.data, 512);
+ }
+ }
+
+ std::vector<UINT32> tdata;
+ for(int i=0; i != obs.sector_count; i++) {
+ const wd_sect &s = obs.sectors[i];
+ if(i+1 != obs.sector_count && obs.sectors[i+1].position < s.position+10+44+4+(128 << (s.id[3] & 3))) {
+ osd_printf_error("pasti: Unsupported sector data sharing, track %d head %d\n", track, head);
+ return;
+ }
+ if(tdata.size() >> 4 < s.position - 12) {
+ int count = s.position - 12 - (tdata.size() >> 4);
+ if(count & 1) {
+ mfm_w(tdata, 8, 0x4e);
+ count--;
+ }
+ for(int j=0; j<count; j+=2)
+ mfm_w(tdata, 8, 0x4e);
+ }
+ if(tdata.size() < s.position*16) {
+ int count = s.position - (tdata.size() >> 4);
+ if(count & 1) {
+ mfm_w(tdata, 8, 0x00);
+ count--;
+ }
+ for(int j=0; j<count; j+=2)
+ mfm_w(tdata, 8, 0x00);
+ }
+ raw_w(tdata, 16, 0x4489);
+ raw_w(tdata, 16, 0x4489);
+ raw_w(tdata, 16, 0x4489);
+ mfm_w(tdata, 8, 0xfe);
+ for(int j=0; j<6; j++)
+ mfm_w(tdata, 8, s.id[j]);
+
+ if(!s.data)
+ continue;
+
+ for(int j=0; j<22; j++)
+ mfm_w(tdata, 8, 0x4e);
+ for(int j=0; j<12; j++)
+ mfm_w(tdata, 8, 0x00);
+
+ raw_w(tdata, 16, 0x4489);
+ raw_w(tdata, 16, 0x4489);
+ raw_w(tdata, 16, 0x4489);
+ mfm_w(tdata, 8, 0xfb);
+ for(int j=0; j<128 << (s.id[3] & 3); j++)
+ mfm_w(tdata, 8, s.data[j]);
+ UINT16 crc = calc_crc_ccitt(tdata, tdata.size() - (2048 << (s.id[3] & 3)) - 16*4, tdata.size());
+ mfm_w(tdata, 8, crc >> 8);
+ mfm_w(tdata, 8, crc);
+ }
+
+ int count = (100015 - tdata.size()) >> 16;
+ for(int i=0; i<count; i++)
+ mfm_w(tdata, 8, 0x4e);
+
+ generate_track_from_levels(track, head, tdata, 0, image);
+}
+
+UINT16 pasti_format::byte_to_mfm(UINT8 data, bool context)
+{
+ static const UINT8 expand[32] = {
+ 0xaa, 0xa9, 0xa4, 0xa5, 0x92, 0x91, 0x94, 0x95, 0x4a, 0x49, 0x44, 0x45, 0x52, 0x51, 0x54, 0x55,
+ 0x2a, 0x29, 0x24, 0x25, 0x12, 0x11, 0x14, 0x15, 0x4a, 0x49, 0x44, 0x45, 0x52, 0x51, 0x54, 0x55,
+ };
+
+ return (expand[(data >> 4) | (context ? 16 : 0)] << 8) | expand[data & 0x1f];
+}
+
+void pasti_format::match_mfm_data(wd_obs &obs, int tpos, const UINT8 *data, int size, UINT8 context, int &bcount, int &tend, bool &synced)
+{
+ UINT16 shift = byte_to_mfm(context, true);
+ int bc = 0;
+ int bc_phase = 0;
+ int bi = 0;
+ UINT8 dbyte = 0;
+ bool ds_phase = false;
+ UINT16 inshift = byte_to_mfm(data[bi++], shift & 1);
+ synced = false;
+ for(;;) {
+ int bit = (inshift >> (15-bc)) & 1;
+ shift = (shift << 1) | bit;
+ if(ds_phase)
+ dbyte = (dbyte << 1) | bit;
+ // printf(" %04x %02x (%04x %02x)\n", shift, dbyte, inshift, data[bi-1]);
+ ds_phase = !ds_phase;
+ bc++;
+ if(shift == 0x4489 || shift == 0x5224) {
+ bc_phase = 16-bc;
+ ds_phase = false;
+ }
+ if(!((bc_phase + bc) & 15)) {
+ // printf("dbyte=%02x data=%02x in=%02x bc=%d bc_shift=%d ds_phase=%s\n", dbyte, obs.track_data[tpos], data[bi-1], bc, bc_phase, ds_phase ? "on" : "off");
+ if(dbyte != obs.track_data[tpos++]) {
+ bcount = bi-1;
+ tend = tpos-1;
+ return;
+ }
+ if(tpos == obs.track_size)
+ tpos = 0;
+ if(bi == size) {
+ bcount = bi;
+ tend = tpos;
+ synced = bc_phase == 0;
+ return;
+ }
+ }
+ if(bc == 16) {
+ inshift = byte_to_mfm(data[bi++], shift & 1);
+ bc = 0;
+ }
+ }
+}
+
+void pasti_format::match_raw_data(wd_obs &obs, int tpos, const UINT8 *data, int size, UINT8 context, int &bcount, int &tend)
+{
+ tend = tpos;
+ for(bcount=0; bcount != size; bcount++) {
+ if(data[bcount] != obs.track_data[tend])
+ return;
+ tend++;
+ if(tend == obs.track_size)
+ tend = 0;
+ }
+}
+
+UINT16 pasti_format::calc_crc(const UINT8 *data, int size, UINT16 crc1)
+{
+ UINT32 crc = crc1;
+ for(int i=0; i<size; i++) {
+ crc = (crc << 8) ^ (*data++ << 16);
+ if(crc & 0x800000) crc ^= 0x881080;
+ if(crc & 0x400000) crc ^= 0x440840;
+ if(crc & 0x200000) crc ^= 0x220420;
+ if(crc & 0x100000) crc ^= 0x110210;
+ if(crc & 0x080000) crc ^= 0x088108;
+ if(crc & 0x040000) crc ^= 0x044084;
+ if(crc & 0x020000) crc ^= 0x022042;
+ if(crc & 0x010000) crc ^= 0x011021;
+ }
+ return crc;
+}
+
+void pasti_format::map_sectors_in_track(wd_obs &obs, wd_sect_info *sect_infos)
+{
+ for(int i=0; i != obs.sector_count; i++) {
+ sect_infos[i].hstart = -1;
+ sect_infos[i].hend = -1;
+ sect_infos[i].dstart = -1;
+ sect_infos[i].dend = -1;
+ sect_infos[i].hsynced = false;
+ sect_infos[i].dsynced = false;
+ }
+
+ const UINT8 *tdata = obs.track_data;
+ int tsize = obs.track_size;
+
+ for(int i=0; i != tsize; i++)
+ if(tdata[i] == 0xa1 &&
+ tdata[(i+1) % tsize] == 0xa1 &&
+ (tdata[(i+2) % tsize] == 0xfe ||
+ tdata[(i+2) % tsize] == 0xff)) {
+ UINT8 hbyte = tdata[(i+2) % tsize];
+ int hpos = (i+3) % tsize;
+ int j;
+ bool synced = false;
+ int bcount=0, tend=0;
+ int best_bcount=0, best_j=0;
+ for(j=0; j != obs.sector_count; j++) {
+ match_mfm_data(obs, hpos, obs.sectors[j].id, 6, hbyte, bcount, tend, synced);
+ if(bcount > best_bcount) {
+ best_bcount = bcount;
+ best_j = j;
+ }
+ if(bcount == 6)
+ break;
+ match_raw_data(obs, hpos, obs.sectors[j].id, 6, hbyte, bcount, tend);
+ if(bcount > best_bcount) {
+ best_bcount = bcount;
+ best_j = j;
+ }
+ if(bcount == 6) {
+ synced = true;
+ break;
+ }
+ }
+
+ j = best_j;
+ if(best_bcount < 4) {
+ if(0)
+ printf("sector header at %x no match [%02x %02x %02x %02x %02x %02x]\n", i,
+ tdata[hpos], tdata[hpos+1], tdata[hpos+2], tdata[hpos+3], tdata[hpos+4], tdata[hpos+5]);
+ } else {
+ if(0)
+ printf("sector header at %x matches %d [%02x %02x %02x %02x %02x %02x] [%02x] - %d %s\n", i, j,
+ tdata[hpos], tdata[hpos+1], tdata[hpos+2], tdata[hpos+3], tdata[hpos+4], tdata[hpos+5], tdata[tend],
+ obs.sectors[j].position, synced ? "synced" : "unsynced");
+
+ sect_infos[j].hstart = hpos - 4;
+ sect_infos[j].hend = tend + (6-bcount);
+ sect_infos[j].hsynced = synced;
+
+ int dpos = -1;
+ if(obs.sectors[j].data)
+ for(int j=35; j<45; j++) {
+ if(tdata[(hpos+j) % tsize] == 0xa1 &&
+ tdata[(hpos+j+1) % tsize] == 0xa1 &&
+ tdata[(hpos+j+2) % tsize] >= 0xfa &&
+ tdata[(hpos+j+2) % tsize] <= 0xfd) {
+ dpos = (hpos+j+3) % tsize;
+ break;
+ }
+ }
+ if(dpos != -1) {
+ int bcount2, tend2;
+ UINT8 dhbyte = tdata[(dpos+tsize-1) % tsize];
+ int ssize = 128 << (obs.sectors[j].id[3] & 3);
+ match_mfm_data(obs, dpos, obs.sectors[j].data, ssize, dhbyte, bcount, tend, synced);
+ if(bcount < ssize) {
+ match_raw_data(obs, dpos, obs.sectors[j].data, ssize, dhbyte, bcount2, tend2);
+ if(bcount2 > bcount) {
+ bcount = bcount2;
+ tend = tend2;
+ if(bcount == ssize)
+ synced = true;
+ }
+ }
+ UINT16 crc = calc_crc(obs.sectors[j].data, ssize, calc_crc(tdata+((dpos+tsize-1) % tsize), 1, 0xcdb4));
+ if(synced && tdata[tend] == (crc >> 8) && tdata[(tend+1) % tsize] == (crc & 0xff)) {
+ tend = (tend+2) % tsize;
+ bcount += 2;
+ }
+
+ if(0)
+ printf(" associated data at %d, match %d [%02x %02x %02x] %04x, %s\n", dpos, bcount, tdata[tend], tdata[tend+1], tdata[tend+2], crc, synced ? "synced" : "unsynced");
+
+ sect_infos[j].dstart = dpos - 4;
+ sect_infos[j].dend = tend + (ssize+2-bcount);
+ sect_infos[j].dsynced = synced;
+
+ }
+ }
+ }
+
+}