From e1da051f44e6cd9c53c7509baad60743363e7569 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 5 Oct 2016 05:37:07 +0200 Subject: [PATCH] Added the FDC SCAN EQUAL, SCAN LOW OR EQUAL, and SCAN HIGH OR EQUAL commands. --- src/disc.c | 11 ++++ src/disc.h | 2 + src/disc_86f.c | 101 ++++++++++++++++++++++++++++++-- src/disc_86f.h | 1 + src/disc_fdi.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++-- src/disc_fdi.h | 1 + src/fdc.c | 121 +++++++++++++++++++++++++++++++++++--- src/fdc.h | 3 + 8 files changed, 378 insertions(+), 18 deletions(-) diff --git a/src/disc.c b/src/disc.c index 1c80b6491..7d064a7e0 100644 --- a/src/disc.c +++ b/src/disc.c @@ -137,6 +137,7 @@ void disc_close(int drive) drives[drive].seek = NULL; drives[drive].readsector = NULL; drives[drive].writesector = NULL; + drives[drive].comparesector = NULL; drives[drive].readaddress = NULL; drives[drive].format = NULL; drives[drive].realtrack = NULL; @@ -309,6 +310,16 @@ void disc_writesector(int drive, int sector, int track, int side, int density, i disc_notfound = 1000; } +void disc_comparesector(int drive, int sector, int track, int side, int density, int sector_size) +{ + drive ^= fdd_swap; + + if (drives[drive].comparesector) + drives[drive].comparesector(drive, sector, track, side, density, sector_size); + else + disc_notfound = 1000; +} + void disc_readaddress(int drive, int track, int side, int density) { drive ^= fdd_swap; diff --git a/src/disc.h b/src/disc.h index 1bfaa9ea6..ef644ce93 100644 --- a/src/disc.h +++ b/src/disc.h @@ -6,6 +6,7 @@ typedef struct void (*seek)(int drive, int track); void (*readsector)(int drive, int sector, int track, int side, int density, int sector_size); void (*writesector)(int drive, int sector, int track, int side, int density, int sector_size); + void (*comparesector)(int drive, int sector, int track, int side, int density, int sector_size); void (*readaddress)(int drive, int track, int side, int density); void (*format)(int drive, int track, int side, int density, uint8_t fill); int (*hole)(int drive); @@ -28,6 +29,7 @@ void disc_poll(); void disc_seek(int drive, int track); void disc_readsector(int drive, int sector, int track, int side, int density, int sector_size); void disc_writesector(int drive, int sector, int track, int side, int density, int sector_size); +void disc_comparesector(int drive, int sector, int track, int side, int density, int sector_size); void disc_readaddress(int drive, int track, int side, int density); void disc_format(int drive, int track, int side, int density, uint8_t fill); int disc_realtrack(int drive, int track); diff --git a/src/disc_86f.c b/src/disc_86f.c index bc3210454..ee7fa4e3c 100644 --- a/src/disc_86f.c +++ b/src/disc_86f.c @@ -29,6 +29,10 @@ enum STATE_WRITE_SECTOR, STATE_WRITE_SECTOR_CRC, STATE_WRITE_SECTOR_GAP3, + STATE_COMPARE_FIND_SECTOR, + STATE_COMPARE_SECTOR, + STATE_COMPARE_SECTOR_CRC, + STATE_COMPARE_SECTOR_GAP3, STATE_READ_FIND_ADDRESS, STATE_READ_ADDRESS, STATE_FORMAT_FIND, @@ -129,6 +133,7 @@ static struct uint8_t id_read_state; uint8_t sector_count; uint8_t format_state; + uint16_t satisfying_bytes; } d86f[2]; uint8_t encoded_fm[64] = { 0xAA, 0xAB, 0xAE, 0xAF, 0xBA, 0xBB, 0xBE, 0xBF, 0xEA, 0xEB, 0xEE, 0xEF, 0xFA, 0xFB, 0xFE, 0xFF, @@ -535,6 +540,7 @@ void d86f_common_handlers(int drive) { drives[drive].readsector = d86f_readsector; drives[drive].writesector = d86f_writesector; + drives[drive].comparesector=d86f_comparesector; drives[drive].readaddress = d86f_readaddress; drives[drive].hole = d86f_hole; drives[drive].byteperiod = d86f_byteperiod; @@ -1084,7 +1090,7 @@ void d86f_readsector(int drive, int sector, int track, int side, int rate, int s d86f[drive].rw_sector_id.dword = 0xFFFFFFFF; d86f[drive].last_sector.dword = 0xFFFFFFFF; d86f[drive].req_sector.id.n = sector_size; - d86f[drive].index_count = 0; + d86f[drive].index_count = d86f[drive].satisfying_bytes = 0; d86f[drive].wait_state = 1; d86f_new_style_reset(drive); d86f[drive].state = STATE_READ_FIND_SECTOR; @@ -1118,12 +1124,46 @@ void d86f_writesector(int drive, int sector, int track, int side, int rate, int d86f[drive].rw_sector_id.dword = 0xFFFFFFFF; d86f[drive].last_sector.dword = 0xFFFFFFFF; d86f_drive = drive; - d86f[drive].index_count = 0; + d86f[drive].index_count = d86f[drive].satisfying_bytes = 0; d86f[drive].wait_state = 1; d86f_new_style_reset(drive); d86f[drive].state = STATE_WRITE_FIND_SECTOR; } +void d86f_comparesector(int drive, int sector, int track, int side, int rate, int sector_size) +{ + d86f[drive].req_sector.id.c = track; + d86f[drive].req_sector.id.h = side; + d86f[drive].req_sector.id.r = sector; + d86f[drive].req_sector.id.n = sector_size; + + // pclog("d86f_comparesector: drive=%c: fdc_period=%i img_period=%i rate=%i chrn=%08X\n", drive + 0x41, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), rate, d86f[drive].req_sector.dword); + + if (writeprot[drive] || swwp) + { + // pclog("Write protected\n"); + fdc_writeprotect(); + return; + } + + if (fdd_get_head(drive) && (d86f_get_sides(drive) == 1)) + { + // pclog("Wrong side\n"); + fdc_notfound(); + d86f[drive].state = STATE_IDLE; + d86f[drive].index_count = 0; + return; + } + + d86f[drive].rw_sector_id.dword = 0xFFFFFFFF; + d86f[drive].last_sector.dword = 0xFFFFFFFF; + d86f_drive = drive; + d86f[drive].index_count = d86f[drive].satisfying_bytes = 0; + d86f[drive].wait_state = 1; + d86f_new_style_reset(drive); + d86f[drive].state = STATE_COMPARE_FIND_SECTOR; +} + void d86f_readaddress(int drive, int track, int side, int rate) { // pclog("d86f_readaddress: fdc_period=%i img_period=%i rate=%i track=%i side=%i\n", fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), rate, track, side); @@ -1142,7 +1182,7 @@ void d86f_readaddress(int drive, int track, int side, int rate) d86f[drive].rw_sector_id.dword = 0xFFFFFFFF; d86f[drive].last_sector.dword = 0xFFFFFFFF; d86f_drive = drive; - d86f[drive].index_count = 0; + d86f[drive].index_count = d86f[drive].satisfying_bytes = 0; d86f[drive].wait_state = 1; d86f_new_style_reset(drive); d86f[drive].state = STATE_READ_FIND_ADDRESS; @@ -1583,6 +1623,7 @@ int d86f_find_state_nf(int drive) int temp; temp = (d86f[drive].state == STATE_READ_FIND_SECTOR); temp = temp || d86f_find_state_nf_ignore_id(drive); + temp = (d86f[drive].state == STATE_COMPARE_FIND_SECTOR); temp = temp || (d86f[drive].state == STATE_WRITE_FIND_SECTOR); temp = temp || (d86f[drive].state == STATE_READ_FIND_ADDRESS); return temp; @@ -1611,6 +1652,7 @@ int d86f_read_state_crc(int drive) temp = (d86f[drive].state == STATE_READ_SECTOR_CRC); temp = temp || (d86f[drive].state == STATE_READ_FIRST_SECTOR_CRC); temp = temp || (d86f[drive].state == STATE_READ_NEXT_SECTOR_CRC); + temp = temp || (d86f[drive].state == STATE_COMPARE_SECTOR_CRC); return temp; } @@ -1620,6 +1662,7 @@ int d86f_read_state_gap3(int drive) temp = (d86f[drive].state == STATE_READ_SECTOR_GAP3); temp = temp || (d86f[drive].state == STATE_READ_FIRST_SECTOR_GAP3); temp = temp || (d86f[drive].state == STATE_READ_NEXT_SECTOR_GAP3); + temp = temp || (d86f[drive].state == STATE_COMPARE_SECTOR_GAP3); return temp; } @@ -1987,6 +2030,46 @@ void d86f_poll_readwrite(int drive, int side) } d86f_calccrc(drive, data & 0xff); } + else if (d86f[drive].state == STATE_COMPARE_SECTOR) + { + max_len = d86f_data_size(drive); + + if (d86f[drive].datac < d86f_get_data_len(drive)) + { + data = fdc_getdata(d86f[drive].datac == ((128 << ((uint32_t) d86f[drive].last_sector.id.n)) - 1)); + + if (data == -1) + { + data = 0; + } + } + else + { + data = 0; + } + switch(fdc_get_compare_condition()) + { + case 0: /* SCAN EQUAL */ + if ((data == d86f[drive].track_data_byte) || (data == 0xFF)) + { + d86f[drive].satisfying_bytes++; + } + break; + case 1: /* SCAN LOW OR EQUAL */ + if ((data <= d86f[drive].track_data_byte) || (data == 0xFF)) + { + d86f[drive].satisfying_bytes++; + } + break; + case 2: /* SCAN HIGH OR EQUAL */ + if ((data >= d86f[drive].track_data_byte) || (data == 0xFF)) + { + d86f[drive].satisfying_bytes++; + } + break; + } + d86f_calccrc(drive, data & 0xff); + } else if (d86f_read_state_crc(drive)) { max_len = 2; @@ -2022,7 +2105,14 @@ void d86f_poll_readwrite(int drive, int side) else { // pclog("Read finished (%i %i %i %i)\n", d86f[drive].req_sector.id.c, d86f[drive].req_sector.id.h, d86f[drive].req_sector.id.r, d86f[drive].req_sector.id.n); - fdc_sector_finishread(); + if (d86f[drive].state == STATE_COMPARE_SECTOR_GAP3) + { + fdc_sector_finishcompare((d86f[drive].satisfying_bytes == ((128 << ((uint32_t) d86f[drive].last_sector.id.n)) - 1)) ? 1 : 0); + } + else + { + fdc_sector_finishread(); + } } return; } @@ -2266,6 +2356,7 @@ void d86f_poll_find_nf(int drive, int side) case STATE_WRITE_FIND_SECTOR: case STATE_READ_FIND_FIRST_SECTOR: case STATE_READ_FIND_NEXT_SECTOR: + case STATE_COMPARE_FIND_SECTOR: /* If the data address mark counter is anything other than 0, then either the ID matches or the FDC is in the ignore sector ID mode (ie. the READ TRACK command). Also, the bitcell period, etc. are already checked during the wait state which is designed to never end in case of a mismatch. Therefore, ensuring the data address mark acounter is at a correct length is all we need to do. */ @@ -2574,6 +2665,7 @@ void d86f_poll_find_am_fm(int drive, int side) case STATE_WRITE_FIND_SECTOR: case STATE_READ_FIND_FIRST_SECTOR: case STATE_READ_FIND_NEXT_SECTOR: + case STATE_COMPARE_FIND_SECTOR: d86f[drive].state++; d86f_poll_advancebyte(drive, side); d86f[drive].id_was_read = 0; /* Invalidate ID was read flag to avoid false positives after read. */ @@ -2644,6 +2736,7 @@ void d86f_poll_find_am_mfm(int drive, int side) case STATE_WRITE_FIND_SECTOR: case STATE_READ_FIND_FIRST_SECTOR: case STATE_READ_FIND_NEXT_SECTOR: + case STATE_COMPARE_FIND_SECTOR: // pclog("Advancing state (%04X)...\n", d86f[drive].calc_crc); d86f[drive].state++; d86f_poll_advancebyte(drive, side); diff --git a/src/disc_86f.h b/src/disc_86f.h index 96a83131f..873110d6b 100644 --- a/src/disc_86f.h +++ b/src/disc_86f.h @@ -13,6 +13,7 @@ int d86f_realtrack(int track, int drive); void d86f_reset(int drive, int side); void d86f_readsector(int drive, int sector, int track, int side, int density, int sector_size); void d86f_writesector(int drive, int sector, int track, int side, int density, int sector_size); +void d86f_comparesector(int drive, int sector, int track, int side, int rate, int sector_size); void d86f_readaddress(int drive, int sector, int side, int density); void d86f_format(int drive, int sector, int side, int density, uint8_t fill); diff --git a/src/disc_fdi.c b/src/disc_fdi.c index fd451c16c..8e8c98ba7 100644 --- a/src/disc_fdi.c +++ b/src/disc_fdi.c @@ -7,6 +7,7 @@ #include "disc.h" #include "disc_img.h" #include "disc_fdi.h" +#include "fdc.h" #include "fdi2raw.h" static struct @@ -27,11 +28,12 @@ static int fdi_pos; static int fdi_revs; static int fdi_sector, fdi_track, fdi_side, fdi_drive, fdi_density, fdi_n; -static int fdi_inread, fdi_inwrite, fdi_readpos, fdi_inreadaddr; +static int fdi_inread, fdi_inwrite, fdi_incompare,fdi_readpos, fdi_inreadaddr; +static int fdi_satisfying_bytes; static uint16_t CRCTable[256]; -static int pollbytesleft=0,pollbitsleft=0; +static int pollbytesleft=0,pollbitsleft=0,polltotalbytes=0; int fdi_realtrack(int drive, int track) { @@ -129,6 +131,7 @@ void fdi_load(int drive, char *fn) drives[drive].seek = fdi_seek; drives[drive].readsector = fdi_readsector; drives[drive].writesector = fdi_writesector; + drives[drive].comparesector=fdi_comparesector; drives[drive].readaddress = fdi_readaddress; drives[drive].hole = fdi_hole; drives[drive].byteperiod = fdi_byteperiod; @@ -215,8 +218,10 @@ void fdi_readsector(int drive, int sector, int track, int side, int rate, int se fdi_inread = 1; fdi_inwrite = 0; + fdi_incompare = 0; fdi_inreadaddr = 0; fdi_readpos = 0; + fdi_satisfying_bytes = 0; } void fdi_writesector(int drive, int sector, int track, int side, int rate, int sector_size) @@ -237,8 +242,37 @@ void fdi_writesector(int drive, int sector, int track, int side, int rate, int s fdi_inread = 0; fdi_inwrite = 1; + fdi_incompare = 0; fdi_inreadaddr = 0; fdi_readpos = 0; + fdi_satisfying_bytes = 0; +} + +void fdi_comparesector(int drive, int sector, int track, int side, int rate, int sector_size) +{ + fdi_revs = 0; + fdi_sector = sector; + fdi_track = track; + fdi_side = side; + fdi_n = sector_size; + fdi_drive = drive; + if (rate == 2) + fdi_density = 1; + if (rate == 0) + fdi_density = 2; + if (rate == 3) + fdi_density = 3; + +// pclog("FDI Read sector %i %i %i %i %i\n",drive,side,track,sector, fdi_density); +// if (pollbytesleft) +// pclog("In the middle of a sector!\n"); + + fdi_inread = 0; + fdi_inwrite = 0; + fdi_incompare = 1; + fdi_inreadaddr = 0; + fdi_readpos = 0; + fdi_satisfying_bytes = 0; } void fdi_readaddress(int drive, int track, int side, int rate) @@ -257,8 +291,10 @@ void fdi_readaddress(int drive, int track, int side, int rate) fdi_inread = 0; fdi_inwrite = 0; + fdi_incompare = 0; fdi_inreadaddr = 1; fdi_readpos = 0; + fdi_satisfying_bytes = 0; } void fdi_format(int drive, int track, int side, int rate, uint8_t fill) @@ -277,12 +313,14 @@ void fdi_format(int drive, int track, int side, int rate, uint8_t fill) fdi_inread = 0; fdi_inwrite = 1; + fdi_incompare = 0; fdi_inreadaddr = 0; fdi_readpos = 0; + fdi_satisfying_bytes = 0; } static uint16_t fdi_buffer; -static int readidpoll=0,readdatapoll=0,fdi_nextsector=0,inreadop=0; +static int readidpoll=0,readdatapoll=0,comparedatapoll=0,fdi_nextsector=0,inreadop=0; static uint8_t fdi_sectordat[1026]; static int lastfdidat[2],sectorcrc[2]; static int sectorsize,fdc_sectorsize; @@ -322,6 +360,7 @@ void fdi_poll() { int tempi, c; int bitcount; + int indata, readdata; int side = fdd_get_head(fdi_drive); for (bitcount = 0; bitcount < 16; bitcount++) @@ -351,7 +390,7 @@ void fdi_poll() fdc_writeprotect(); return; } - if (!fdi_inread && !fdi_inreadaddr) + if (!fdi_inread && !fdi_inreadaddr && !fdi_incompare) return; if (fdi_pos == fdi[fdi_drive].trackindex[side][fdi_density]) { @@ -463,6 +502,95 @@ void fdi_poll() if (!pollbytesleft) readdatapoll = 0; } + if (comparedatapoll) + { +// pclog("readdatapoll %i %02x\n", pollbytesleft, decodefm(fdi_buffer)); + if (pollbytesleft > 1) + { + calccrc(decodefm(fdi_buffer)); + } + else + sectorcrc[1 - pollbytesleft] = decodefm(fdi_buffer); + if (!pollbytesleft) + { + fdi_inread = 0; +//#if 0 + if ((crc >> 8) != sectorcrc[0] || (crc & 0xFF) != sectorcrc[1])// || (fditrack==79 && fdisect==4 && fdc_side&1)) + { +// pclog("Data CRC error : %02X %02X %02X %02X %i %04X %02X%02X\n",crc>>8,crc&0xFF,sectorcrc[0],sectorcrc[1],fdi_pos,crc,sectorcrc[0],sectorcrc[1]); + inreadop = 0; + fdc_data(decodefm(lastfdidat[1])); + fdc_finishcompare(fdi_satisfying_bytes == polltotalbytes); + fdc_datacrcerror(); + comparedatapoll = 0; + return; + } +//#endif +// pclog("End of FDI read %02X %02X %02X %02X\n",crc>>8,crc&0xFF,sectorcrc[0],sectorcrc[1]); + indata = fdc_getdata(!pollbytesleft); + readdata = decodefm(lastfdidat[1]); + if (indata == -1) + { + indata = 0; + } + switch(fdc_get_compare_condition()) + { + case 0: /* SCAN EQUAL */ + if ((indata == readdata) || (indata == 0xFF)) + { + fdi_satisfying_bytes++; + } + break; + case 1: /* SCAN LOW OR EQUAL */ + if ((indata <= readdata) || (indata == 0xFF)) + { + fdi_satisfying_bytes++; + } + break; + case 2: /* SCAN HIGH OR EQUAL */ + if ((indata >= readdata) || (indata == 0xFF)) + { + fdi_satisfying_bytes++; + } + break; + } + fdc_finishcompare(fdi_satisfying_bytes == polltotalbytes); + } + else if (lastfdidat[1] != 0) + { + indata = fdc_getdata(!pollbytesleft); + readdata = decodefm(lastfdidat[1]); + if (indata == -1) + { + indata = 0; + } + switch(fdc_get_compare_condition()) + { + case 0: /* SCAN EQUAL */ + if ((indata == readdata) || (indata == 0xFF)) + { + fdi_satisfying_bytes++; + } + break; + case 1: /* SCAN LOW OR EQUAL */ + if ((indata <= readdata) || (indata == 0xFF)) + { + fdi_satisfying_bytes++; + } + break; + case 2: /* SCAN HIGH OR EQUAL */ + if ((indata >= readdata) || (indata == 0xFF)) + { + fdi_satisfying_bytes++; + } + break; + } + } + lastfdidat[1] = lastfdidat[0]; + lastfdidat[0] = fdi_buffer; + if (!pollbytesleft) + readdatapoll = 0; + } } } if (fdi_buffer == 0x4489 && fdi_density) @@ -483,7 +611,15 @@ void fdi_poll() { pollbytesleft = sectorsize; pollbitsleft = 16; - readdatapoll = 1; + if (fdi_inread) + { + readdatapoll = 1; + } + else + { + polltotalbytes = sectorsize; + comparedatapoll = 1; + } fdi_nextsector = 0; crc = 0xffff; if (fdi_buffer == 0xF56A) calccrc(0xF8); @@ -511,7 +647,15 @@ void fdi_poll() { pollbytesleft = sectorsize; pollbitsleft = 16; - readdatapoll = 1; + if (fdi_inread) + { + readdatapoll = 1; + } + else + { + polltotalbytes = sectorsize; + comparedatapoll = 1; + } fdi_nextsector = 0; crc = 0xcdb4; if (fdi_buffer == 0xF56A) calccrc(0xF8); diff --git a/src/disc_fdi.h b/src/disc_fdi.h index f1399b48e..c977e0b31 100644 --- a/src/disc_fdi.h +++ b/src/disc_fdi.h @@ -7,6 +7,7 @@ void fdi_close(int drive); void fdi_seek(int drive, int track); void fdi_readsector(int drive, int sector, int track, int side, int density, int sector_size); void fdi_writesector(int drive, int sector, int track, int side, int density, int sector_size); +void fdi_comparesector(int drive, int sector, int track, int side, int density, int sector_size); void fdi_readaddress(int drive, int sector, int side, int density); void fdi_format(int drive, int sector, int side, int density, uint8_t fill); int fdi_hole(int drive); diff --git a/src/fdc.c b/src/fdc.c index 15daf2f20..1adf7d500 100644 --- a/src/fdc.c +++ b/src/fdc.c @@ -78,6 +78,7 @@ typedef struct FDC int wrong_am; int sc; + int satisfying_sectors; } FDC; static FDC fdc; @@ -108,6 +109,20 @@ void fdc_reset() // pclog("Reset FDC\n"); } +int fdc_get_compare_condition() +{ + switch (discint) + { + case 0x11: + default: + return 0; + case 0x19: + return 1; + case 0x1D: + return 2; + } +} + int fdc_is_deleted() { return fdc.deleted & 1; @@ -641,6 +656,7 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) break; case 2: /*Read track*/ + fdc.satisfying_sectors=0; fdc.sc=0; fdc.wrong_am=0; fdc.pnum=0; @@ -661,6 +677,7 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) break; case 5: /*Write data*/ case 9: /*Write deleted data*/ + fdc.satisfying_sectors=0; fdc.sc=0; fdc.wrong_am=0; fdc.deleted = ((fdc.command&0x1F) == 9) ? 1 : 0; @@ -674,7 +691,11 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) break; case 6: /*Read data*/ case 0xC: /*Read deleted data*/ + case 0x11: /*Scan equal*/ + case 0x19: /*Scan low or equal*/ case 0x16: /*Verify*/ + case 0x1D: /*Scan high or equal*/ + fdc.satisfying_sectors=0; fdc.sc=0; fdc.wrong_am=0; fdc.deleted = ((fdc.command&0x1F) == 0xC) ? 1 : 0; @@ -882,6 +903,35 @@ bad_command: // ioc_fiq(IOC_FIQ_DISC_DATA); break; + case 0x11: /*Scan equal*/ + case 0x19: /*Scan low or equal*/ + case 0x1D: /*Scan high or equal*/ + fdc_rate(fdc.drive); + fdc.head=fdc.params[2]; + fdd_set_head(fdc.drive, (fdc.params[0] & 4) ? 1 : 0); + fdc.sector=fdc.params[3]; + fdc.eot[fdc.drive] = fdc.params[5]; + fdc.gap = fdc.params[6]; + fdc.dtl = fdc.params[7]; + if (fdc.config & 0x40) + { + if (fdc.params[1] != fdc.track[fdc.drive]) + { + fdc_seek(fdc.drive, ((int) fdc.params[1]) - ((int) fdc.track[fdc.drive])); + fdc.track[fdc.drive] = fdc.params[1]; + } + } + fdc.rw_track = fdc.params[1]; + disc_comparesector(fdc.drive, fdc.sector, fdc.params[1], fdc.head, fdc.rate, fdc.params[4]); + disctime = 0; + fdc.written = 0; + readflash = 1; + fdc.pos = 0; + if (fdc.pcjr) + fdc.stat = 0xb0; + // ioc_fiq(IOC_FIQ_DISC_DATA); + break; + case 0x16: /*Verify*/ if (fdc.params[0] & 0x80) fdc.sc = fdc.params[7]; case 6: /*Read data*/ @@ -1113,7 +1163,7 @@ uint8_t fdc_read(uint16_t addr, void *priv) return temp; } -void fdc_poll_readwrite_finish() +void fdc_poll_readwrite_finish(int compare) { fdc.inread = 0; discint=-2; @@ -1126,6 +1176,17 @@ void fdc_poll_readwrite_finish() fdc.res[6] |= 0x40; fdc.wrong_am = 0; } + if (compare) + { + if (!fdc.satisfying_sectors) + { + fdc.res[6] |= 4; + } + else if (fdc.satisfying_sectors == (fdc.params[5] << ((fdc.command & 80) ? 1 : 0))) + { + fdc.res[6] |= 8; + } + } fdc.res[7]=fdc.rw_track; fdc.res[8]=fdc.head; fdc.res[9]=fdc.sector; @@ -1133,7 +1194,7 @@ void fdc_poll_readwrite_finish() paramstogo=7; } -void fdc_no_dma_end() +void fdc_no_dma_end(int compare) { disctime = 0; @@ -1147,6 +1208,17 @@ void fdc_no_dma_end() fdc.res[6] |= 0x40; fdc.wrong_am = 0; } + if (compare) + { + if (!fdc.satisfying_sectors) + { + fdc.res[6] |= 4; + } + else if (fdc.satisfying_sectors == (fdc.params[5] << ((fdc.command & 80) ? 1 : 0))) + { + fdc.res[6] |= 8; + } + } fdc.res[7]=fdc.rw_track; fdc.res[8]=fdc.head; fdc.res[9]=fdc.sector; @@ -1157,6 +1229,7 @@ void fdc_no_dma_end() void fdc_callback() { int temp; + int compare = 0; disctime = 0; // pclog("fdc_callback %i %i\n", discint, disctime); // if (fdc.inread) @@ -1186,7 +1259,7 @@ void fdc_callback() // pclog("Read a track callback, eot=%i\n", fdc.eot[fdc.drive]); if (!fdc.eot[fdc.drive] || fdc.tc) { - fdc_poll_readwrite_finish(); + fdc_poll_readwrite_finish(0); return; } else @@ -1212,8 +1285,19 @@ void fdc_callback() case 9: /*Write deleted data*/ case 6: /*Read data*/ case 0xC: /*Read deleted data*/ + case 0x11: /*Scan equal*/ + case 0x19: /*Scan low or equal*/ case 0x1C: /*Verify*/ + case 0x1D: /*Scan high or equal*/ // rpclog("Read data %i\n", fdc.tc); + if ((discint == 0x11) || (discint == 0x19) || (discint == 0x1D)) + { + compare = 1; + } + else + { + compare = 0; + } if ((discint == 6) || (discint == 0xC)) { if (fdc.wrong_am && !(fdc.deleted & 0x20)) @@ -1224,7 +1308,7 @@ void fdc_callback() } if (fdc.tc) { - fdc_poll_readwrite_finish(); + fdc_poll_readwrite_finish(compare); return; } readflash = 1; @@ -1234,7 +1318,7 @@ void fdc_callback() fdc.sc--; if (!fdc.sc) { - fdc_poll_readwrite_finish(); + fdc_poll_readwrite_finish(0); return; } /* The rest is processed normally per MT flag and EOT. */ @@ -1244,7 +1328,7 @@ void fdc_callback() /* VERIFY command, EC clear */ if ((fdc.sector == fdc.params[5]) && (fdc.head == (fdc.command & 0x80) ? 1 : 0)) { - fdc_poll_readwrite_finish(); + fdc_poll_readwrite_finish(0); return; } } @@ -1255,7 +1339,7 @@ void fdc_callback() { fdc.rw_track++; fdc.sector = 1; - fdc_no_dma_end(); + fdc_no_dma_end(compare); return; } /* Reached end of track, MT bit is set, head is 1 */ @@ -1265,7 +1349,7 @@ void fdc_callback() fdc.sector = 1; fdc.head &= 0xFE; fdd_set_head(fdc.drive, 0); - fdc_no_dma_end(); + fdc_no_dma_end(compare); return; } if ((fdc.command & 0x80) && (fdd_get_head(fdc.drive ^ fdd_swap) == 0)) @@ -1290,6 +1374,11 @@ void fdc_callback() case 0x16: disc_readsector(fdc.drive, fdc.sector, fdc.rw_track, fdc.head, fdc.rate, fdc.params[4]); break; + case 0x11: + case 0x19: + case 0x1D: + disc_comparesector(fdc.drive, fdc.sector, fdc.rw_track, fdc.head, fdc.rate, fdc.params[4]); + break; } fdc.inread = 1; return; @@ -1552,6 +1641,14 @@ int fdc_data(uint8_t data) return 0; } +void fdc_finishcompare(int satisfying) +{ + fdc.satisfying_sectors++; + fdc.inread = 0; + disctime = 200 * TIMER_USEC; +// rpclog("fdc_finishread\n"); +} + void fdc_finishread() { fdc.inread = 0; @@ -1559,6 +1656,14 @@ void fdc_finishread() // rpclog("fdc_finishread\n"); } +void fdc_sector_finishcompare(int satisfying) +{ + fdc.satisfying_sectors++; + fdc.inread = 0; + fdc_callback(); +// rpclog("fdc_finishread\n"); +} + void fdc_sector_finishread() { fdc.inread = 0; diff --git a/src/fdc.h b/src/fdc.h index dd61dc0c9..232411bf6 100644 --- a/src/fdc.h +++ b/src/fdc.h @@ -31,6 +31,7 @@ void fdc_update_densel_force(int densel_force); void fdc_update_drvrate(int drive, int drvrate); void fdc_update_drv2en(int drv2en); +int fdc_get_compare_condition(); int fdc_is_deleted(); int fdc_is_sk(); void fdc_set_wrong_am(); @@ -47,5 +48,7 @@ int fdc_get_gap2(int drive); int fdc_get_dtl(); int fdc_get_format_sectors(); +void fdc_finishcompare(int satisfying); void fdc_finishread(); +void fdc_sector_finishcompare(int satisfying); void fdc_sector_finishread();