diff --git a/src/disc.c b/src/disc.c index 1a0321f39..bc6a7977e 100644 --- a/src/disc.c +++ b/src/disc.c @@ -194,11 +194,6 @@ double disc_byteperiod(int drive) if (drives[drive].byteperiod) { - if (fdd_get_turbo(drive)) - { - return 1.0; - } - return drives[drive].byteperiod(drive); } else @@ -217,7 +212,12 @@ double disc_real_period(int drive) dusec = (double) TIMER_USEC; /* This is a giant hack but until the timings become even more correct, this is needed to make floppies work right on that BIOS. */ - if ((romset == ROM_MRTHOR) && !fdd_get_turbo(drive)) + if (fdd_get_turbo(drive)) + { + return (32.0 * dusec); + } + + if (romset == ROM_MRTHOR) { return (ddbp * dusec) / 4.0; } diff --git a/src/disc.h b/src/disc.h index eb5c7a1bd..b6f5f7c43 100644 --- a/src/disc.h +++ b/src/disc.h @@ -231,5 +231,10 @@ typedef union sector_id_fields_t id; } sector_id_t; +void d86f_set_version(int drive, uint16_t version); + +void d86f_initialize_last_sector_id(int drive, int c, int h, int r, int n); +void d86f_zero_bit_field(int drive, int side); + #endif /*EMU_DISC_H*/ diff --git a/src/disc_86f.c b/src/disc_86f.c index 9eb713365..eac0b9128 100644 --- a/src/disc_86f.c +++ b/src/disc_86f.c @@ -35,8 +35,6 @@ #include "fdd.h" #include "ibm.h" -#define D86FVER 0x020B - #define CHUNK 16384 uint64_t poly = 0x42F0E1EBA9EA3693ll; /* ECMA normal */ @@ -252,6 +250,8 @@ struct __attribute__((__packed__)) uint8_t *filebuf; uint8_t *outbuf; uint32_t dma_over; + int turbo_pos; + uint16_t sector_id_bit_field[2][256][256][256]; } d86f[FDD_NUM]; #ifdef __MSC__ # pragma pack(pop) @@ -273,6 +273,28 @@ void d86f_log(const char *format, ...) #endif } +void d86f_zero_bit_field(int drive, int side) +{ + int i = 0; + int j = 0; + int k = 0; + int l = 0; + + for (i = 0; i < side; i++) + { + for (j = 0; j < 256; j++) + { + for (k = 0; k < 256; k++) + { + for (l = 0; l < 256; l++) + { + d86f[drive].sector_id_bit_field[i][j][k][l] = 0; + } + } + } + } +} + static void d86f_setupcrc(uint16_t poly) { int c = 256, bc; @@ -490,6 +512,11 @@ uint32_t common_get_raw_size(int drive, int side) return ((((uint32_t) size) >> 4) << 4) + d86f_handler[drive].extra_bit_cells(drive, side); } +void d86f_set_version(int drive, uint16_t version) +{ + d86f[drive].version = version; +} + void d86f_unregister(int drive) { d86f_handler[drive].disk_flags = null_disk_flags; @@ -1793,6 +1820,20 @@ void d86f_format_finish(int drive, int side, int mfm, uint16_t sc, uint16_t gap_ fdc_sector_finishread(); } +void d86f_format_turbo_finish(int drive, int side, int do_write) +{ + d86f[drive].state = STATE_IDLE; + + if (do_write) + { + d86f_handler[drive].writeback(drive); + } + + d86f[drive].error_condition = 0; + d86f[drive].datac = 0; + fdc_sector_finishread(); +} + void d86f_format_track(int drive, int side, int do_write) { int data; @@ -2001,6 +2042,251 @@ void d86f_format_track_nop(int drive, int side) d86f_format_track(drive, side, 0); } +void d86f_initialize_last_sector_id(int drive, int c, int h, int r, int n) +{ + d86f[drive].last_sector.id.c = c; + d86f[drive].last_sector.id.h = h; + d86f[drive].last_sector.id.r = r; + d86f[drive].last_sector.id.n = n; +} + +void d86f_turbo_read(int drive, int side) +{ + uint8_t dat = 0; + + int recv_data = 0; + int read_status = 0; + + dat = d86f_handler[drive].read_data(drive, side, d86f[drive].turbo_pos); + d86f[drive].turbo_pos++; + + if (d86f[drive].state == STATE_11_SCAN_DATA) + { + /* Scan/compare command. */ + recv_data = d86f_get_data(drive, 0); + d86f_compare_byte(drive, recv_data, dat); + } + else + { + if (d86f[drive].data_find.bytes_obtained < (128 << d86f[drive].last_sector.id.n)) + { + if (d86f[drive].state != STATE_16_VERIFY_DATA) + { + read_status = fdc_data(dat); + if (read_status == -1) + { + d86f[drive].dma_over++; + } + } + } + } + + if (d86f[drive].dma_over > 1) + { + d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; + d86f[drive].error_condition = 0; + d86f[drive].state = STATE_IDLE; + fdc_finishread(); + fdc_overrun(); + return; + } + + if (d86f[drive].turbo_pos >= (128 << d86f[drive].last_sector.id.n)) + { + /* CRC is valid. */ + d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; + d86f[drive].error_condition = 0; + if (d86f[drive].state == STATE_11_SCAN_DATA) + { + d86f[drive].state = STATE_IDLE; + fdc_sector_finishcompare((d86f[drive].satisfying_bytes == ((128 << ((uint32_t) d86f[drive].last_sector.id.n)) - 1)) ? 1 : 0); + } + else + { + d86f[drive].state = STATE_IDLE; + fdc_sector_finishread(); + } + } +} + +void d86f_turbo_write(int drive, int side) +{ + uint8_t dat = 0; + + dat = d86f_get_data(drive, 1); + d86f_handler[drive].write_data(drive, side, d86f[drive].turbo_pos, dat); + + d86f[drive].turbo_pos++; + + if (d86f[drive].turbo_pos >= (128 << d86f[drive].last_sector.id.n)) + { + /* We've written the data. */ + d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; + d86f[drive].error_condition = 0; + d86f[drive].state = STATE_IDLE; + d86f_handler[drive].writeback(drive); + fdc_sector_finishread(); + return; + } +} + +void d86f_turbo_format(int drive, int side, int nop) +{ + int dat; + int i = 0; + + uint16_t sc = 0; + uint16_t dtl = 0; + + sc = fdc_get_format_sectors(); + dtl = 128 << fdc_get_format_n(); + + if (d86f[drive].datac <= 3) + { + dat = fdc_getdata(0); + if (dat != -1) + { + dat &= 0xff; + } + if ((dat == -1) && (d86f[drive].datac < 3)) + { + dat = 0; + } + d86f[drive].format_sector_id.byte_array[d86f[drive].datac] = dat & 0xff; + if (d86f[drive].datac == 3) + { + fdc_stop_id_request(); + d86f_handler[drive].set_sector(drive, side, d86f[drive].format_sector_id.id.c, d86f[drive].format_sector_id.id.h, d86f[drive].format_sector_id.id.r, d86f[drive].format_sector_id.id.n); + } + } + else if (d86f[drive].datac == 4) + { + if (!nop) + { + for (i = 0; i < dtl; i++) + { + d86f_handler[drive].write_data(drive, side, i, d86f[drive].fill); + } + } + + d86f[drive].sector_count++; + } + + d86f[drive].datac++; + + if (d86f[drive].datac == 6) + { + d86f[drive].datac = 0; + + if (d86f[drive].sector_count < sc) + { + /* Sector within allotted amount. */ + fdc_request_next_sector_id(); + } + else + { + d86f[drive].state = STATE_IDLE; + d86f_format_turbo_finish(drive, side, nop); + } + } +} + +void d86f_turbo_poll(int drive, int side) +{ + switch(d86f[drive].state) + { + case STATE_0D_SPIN_TO_INDEX: + case STATE_0D_NOP_SPIN_TO_INDEX: + d86f[drive].sector_count = 0; + d86f[drive].datac = 5; + case STATE_02_SPIN_TO_INDEX: + d86f[drive].state++; + return; + case STATE_02_FIND_ID: + if (!(d86f[drive].sector_id_bit_field[side][fdc_get_read_track_sector().id.c][fdc_get_read_track_sector().id.h][fdc_get_read_track_sector().id.r] & (1 << fdc_get_read_track_sector().id.n))) + { + d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = d86f[drive].error_condition = 0; + fdc_nosector(); + d86f[drive].state = STATE_IDLE; + return; + } + d86f[drive].last_sector.id.c = fdc_get_read_track_sector().id.c; + d86f[drive].last_sector.id.h = fdc_get_read_track_sector().id.h; + d86f[drive].last_sector.id.r = fdc_get_read_track_sector().id.r; + d86f[drive].last_sector.id.n = fdc_get_read_track_sector().id.n; + d86f_handler[drive].set_sector(drive, side, d86f[drive].last_sector.id.c, d86f[drive].last_sector.id.h, d86f[drive].last_sector.id.r, d86f[drive].last_sector.id.n); + d86f[drive].turbo_pos = 0; + d86f[drive].state++; + return; + case STATE_05_FIND_ID: + case STATE_09_FIND_ID: + case STATE_06_FIND_ID: + case STATE_0C_FIND_ID: + case STATE_11_FIND_ID: + case STATE_16_FIND_ID: + if (!(d86f[drive].sector_id_bit_field[side][d86f[drive].req_sector.id.c][d86f[drive].req_sector.id.h][d86f[drive].req_sector.id.r] & (1 << d86f[drive].req_sector.id.n))) + { + d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = d86f[drive].error_condition = 0; + fdc_nosector(); + d86f[drive].state = STATE_IDLE; + return; + } + d86f[drive].last_sector.id.c = d86f[drive].req_sector.id.c; + d86f[drive].last_sector.id.h = d86f[drive].req_sector.id.h; + d86f[drive].last_sector.id.r = d86f[drive].req_sector.id.r; + d86f[drive].last_sector.id.n = d86f[drive].req_sector.id.n; + d86f_handler[drive].set_sector(drive, side, d86f[drive].last_sector.id.c, d86f[drive].last_sector.id.h, d86f[drive].last_sector.id.r, d86f[drive].last_sector.id.n); + case STATE_0A_FIND_ID: + d86f[drive].turbo_pos = 0; + d86f[drive].state++; + return; + case STATE_0A_READ_ID: + d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = d86f[drive].error_condition = 0; + fdc_sectorid(d86f[drive].last_sector.id.c, d86f[drive].last_sector.id.h, d86f[drive].last_sector.id.r, d86f[drive].last_sector.id.n, 0, 0); + d86f[drive].state = STATE_IDLE; + break; + case STATE_02_READ_ID: + case STATE_05_READ_ID: + case STATE_09_READ_ID: + case STATE_06_READ_ID: + case STATE_0C_READ_ID: + case STATE_11_READ_ID: + case STATE_16_READ_ID: + d86f[drive].state++; + break; + case STATE_02_FIND_DATA: + case STATE_06_FIND_DATA: + case STATE_11_FIND_DATA: + case STATE_16_FIND_DATA: + case STATE_05_FIND_DATA: + case STATE_09_FIND_DATA: + case STATE_0C_FIND_DATA: + d86f[drive].state++; + break; + case STATE_02_READ_DATA: + case STATE_06_READ_DATA: + case STATE_0C_READ_DATA: + case STATE_11_SCAN_DATA: + case STATE_16_VERIFY_DATA: + d86f_turbo_read(drive, side); + break; + case STATE_05_WRITE_DATA: + case STATE_09_WRITE_DATA: + d86f_turbo_write(drive, side); + break; + case STATE_0D_FORMAT_TRACK: + d86f_turbo_format(drive, side, 0); + return; + case STATE_0D_NOP_FORMAT_TRACK: + d86f_turbo_format(drive, side, 1); + return; + case STATE_IDLE: + case STATE_SECTOR_NOT_FOUND: + default: + break; + } +} + void d86f_poll(int drive) { int side = 0; @@ -2035,6 +2321,12 @@ void d86f_poll(int drive) } } + if (fdd_get_turbo(drive) && (d86f[drive].version == 0x0063)) + { + d86f_turbo_poll(drive, side); + return; + } + if ((d86f[drive].state != STATE_02_SPIN_TO_INDEX) && (d86f[drive].state != STATE_0D_SPIN_TO_INDEX)) { d86f_get_bit(drive, side ^ 1); @@ -2337,6 +2629,8 @@ uint16_t d86f_prepare_sector(int drive, int side, int prev_pos, uint8_t *id_buf, uint16_t dataam_mfm = 0x4555; uint16_t datadam_mfm = 0x4A55; + d86f[drive].sector_id_bit_field[side][id_buf[0]][id_buf[1]][id_buf[2]] |= (1 << id_buf[3]); + mfm = d86f_is_mfm(drive); gap_fill = mfm ? 0x4E : 0xFF; diff --git a/src/disc_86f.h b/src/disc_86f.h index ec7e83c1e..bea967108 100644 --- a/src/disc_86f.h +++ b/src/disc_86f.h @@ -33,6 +33,7 @@ void d86f_readaddress(int drive, int side, int density); void d86f_format(int drive, int side, int density, uint8_t fill); void d86f_prepare_track_layout(int drive, int side); +void d86f_set_version(int drive, uint16_t version); #define length_gap0 80 #define length_gap1 50 @@ -59,3 +60,8 @@ extern int gap2_size[2]; extern int gap3_size[2]; extern int gap4_size[2]; #endif + +#define D86FVER 0x020B + +void d86f_initialize_last_sector_id(int drive, int c, int h, int r, int n); +void d86f_zero_bit_field(int drive, int side); diff --git a/src/disc_fdi.c b/src/disc_fdi.c index af192b76f..219b29f21 100644 --- a/src/disc_fdi.c +++ b/src/disc_fdi.c @@ -22,6 +22,7 @@ #include #include "ibm.h" #include "disc.h" +#include "disc_86f.h" #include "disc_img.h" #include "disc_fdi.h" #include "fdc.h" @@ -254,6 +255,7 @@ void d86f_register_fdi(int drive) d86f_handler[drive].index_hole_pos = fdi_index_hole_pos; d86f_handler[drive].get_raw_size = fdi_get_raw_size; d86f_handler[drive].check_crc = 1; + d86f_set_version(drive, D86FVER); } void fdi_load(int drive, wchar_t *fn) diff --git a/src/disc_imd.c b/src/disc_imd.c index d511dd46d..e8ca921e6 100644 --- a/src/disc_imd.c +++ b/src/disc_imd.c @@ -531,6 +531,9 @@ void imd_seek(int drive, int track) d86f_reset_index_hole_pos(drive, 0); d86f_reset_index_hole_pos(drive, 1); + d86f_zero_bit_field(drive, 0); + d86f_zero_bit_field(drive, 1); + for (side = 0; side < imd[drive].sides; side++) { track_rate = imd[drive].current_side_flags[side] & 7; @@ -601,6 +604,11 @@ void imd_seek(int drive, int track) imd_sector_to_buffer(drive, track, side, data, actual_sector, ssize); current_pos = d86f_prepare_sector(drive, side, current_pos, id, data, ssize, 22, track_gap3, deleted, bad_crc); track_buf_pos[side] += ssize; + + if (sector == 0) + { + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + } } } else @@ -635,6 +643,11 @@ void imd_seek(int drive, int track) } track_buf_pos[side] += ssize; + + if (sector == 0) + { + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + } } } } @@ -746,6 +759,16 @@ void imd_writeback(int drive) } } +uint8_t imd_poll_read_data(int drive, int side, uint16_t pos) +{ + int type = imd[drive].current_data[side][0]; + if (!(type & 1)) + { + return 0xf6; /* Should never happen. */ + } + return imd[drive].current_data[side][pos + 1]; +} + void imd_poll_write_data(int drive, int side, uint16_t pos, uint8_t data) { int type = imd[drive].current_data[side][0]; @@ -777,6 +800,7 @@ void d86f_register_imd(int drive) d86f_handler[drive].side_flags = imd_side_flags; d86f_handler[drive].writeback = imd_writeback; d86f_handler[drive].set_sector = imd_set_sector; + d86f_handler[drive].read_data = imd_poll_read_data; d86f_handler[drive].write_data = imd_poll_write_data; d86f_handler[drive].format_conditions = imd_format_conditions; d86f_handler[drive].extra_bit_cells = null_extra_bit_cells; @@ -785,4 +809,5 @@ void d86f_register_imd(int drive) d86f_handler[drive].index_hole_pos = null_index_hole_pos; d86f_handler[drive].get_raw_size = common_get_raw_size; d86f_handler[drive].check_crc = 1; + d86f_set_version(drive, 0x0063); } diff --git a/src/disc_img.c b/src/disc_img.c index 4220e5af0..2429352a0 100644 --- a/src/disc_img.c +++ b/src/disc_img.c @@ -938,6 +938,9 @@ void img_seek(int drive, int track) d86f_reset_index_hole_pos(drive, 0); d86f_reset_index_hole_pos(drive, 1); + d86f_zero_bit_field(drive, 0); + d86f_zero_bit_field(drive, 1); + if (!img[drive].xdf_type || img[drive].is_cqm) { for (side = 0; side < img[drive].sides; side++) @@ -980,6 +983,11 @@ void img_seek(int drive, int track) img[drive].sector_pos_side[side][sr] = side; img[drive].sector_pos[side][sr] = (sr - 1) * ssize; current_pos = d86f_prepare_sector(drive, side, current_pos, id, &img[drive].track_data[side][(sr - 1) * ssize], ssize, img[drive].gap2_size, img[drive].gap3_size, 0, 0); + + if (sector == 0) + { + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + } } } } @@ -1039,6 +1047,11 @@ void img_seek(int drive, int track) ssize = (128 << id[3]); current_pos = d86f_prepare_sector(drive, side, xdf_trackx_spos[current_xdft][array_sector], id, &img[drive].track_data[buf_side][buf_pos], ssize, img[drive].gap2_size, xdf_gap3_sizes[current_xdft][!is_t0], 0, 0); } + + if (sector == 0) + { + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + } } } } @@ -1108,6 +1121,7 @@ void d86f_register_img(int drive) d86f_handler[drive].side_flags = img_side_flags; d86f_handler[drive].writeback = img_writeback; d86f_handler[drive].set_sector = img_set_sector; + d86f_handler[drive].read_data = img_poll_read_data; d86f_handler[drive].write_data = img_poll_write_data; d86f_handler[drive].format_conditions = img_format_conditions; d86f_handler[drive].extra_bit_cells = null_extra_bit_cells; @@ -1116,4 +1130,5 @@ void d86f_register_img(int drive) d86f_handler[drive].index_hole_pos = null_index_hole_pos; d86f_handler[drive].get_raw_size = common_get_raw_size; d86f_handler[drive].check_crc = 1; + d86f_set_version(drive, 0x0063); } diff --git a/src/disc_td0.c b/src/disc_td0.c index ac2cd9a6b..574dde621 100644 --- a/src/disc_td0.c +++ b/src/disc_td0.c @@ -1103,6 +1103,9 @@ void td0_seek(int drive, int track) d86f_reset_index_hole_pos(drive, 0); d86f_reset_index_hole_pos(drive, 1); + d86f_zero_bit_field(drive, 0); + d86f_zero_bit_field(drive, 1); + for (side = 0; side < td0[drive].sides; side++) { track_rate = td0[drive].current_side_flags[side] & 7; @@ -1141,6 +1144,11 @@ void td0_seek(int drive, int track) id[3] = td0[drive].sects[track][side][actual_sector].size; ssize = 128 << ((uint32_t) td0[drive].sects[track][side][actual_sector].size); current_pos = d86f_prepare_sector(drive, side, current_pos, id, td0[drive].sects[track][side][actual_sector].data, ssize, track_gap2, track_gap3, td0[drive].sects[track][side][actual_sector].deleted, td0[drive].sects[track][side][actual_sector].bad_crc); + + if (sector == 0) + { + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + } } } else @@ -1164,6 +1172,11 @@ void td0_seek(int drive, int track) { current_pos = d86f_prepare_sector(drive, side, current_pos, id, td0[drive].sects[track][side][ordered_pos].data, ssize, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], td0[drive].sects[track][side][ordered_pos].deleted, td0[drive].sects[track][side][ordered_pos].bad_crc); } + + if (sector == 0) + { + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + } } } } @@ -1201,12 +1214,18 @@ void td0_set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_ return; } +uint8_t td0_poll_read_data(int drive, int side, uint16_t pos) +{ + return td0[drive].sects[td0[drive].track][side][td0[drive].current_sector_index[side]].data[pos]; +} + void d86f_register_td0(int drive) { d86f_handler[drive].disk_flags = td0_disk_flags; d86f_handler[drive].side_flags = td0_side_flags; d86f_handler[drive].writeback = null_writeback; d86f_handler[drive].set_sector = td0_set_sector; + d86f_handler[drive].read_data = td0_poll_read_data; d86f_handler[drive].write_data = null_write_data; d86f_handler[drive].format_conditions = null_format_conditions; d86f_handler[drive].extra_bit_cells = null_extra_bit_cells; @@ -1215,4 +1234,5 @@ void d86f_register_td0(int drive) d86f_handler[drive].index_hole_pos = null_index_hole_pos; d86f_handler[drive].get_raw_size = common_get_raw_size; d86f_handler[drive].check_crc = 1; + d86f_set_version(drive, 0x0063); } diff --git a/src/fdd.c b/src/fdd.c index dd6649ee2..1fb1e50ec 100644 --- a/src/fdd.c +++ b/src/fdd.c @@ -189,6 +189,11 @@ int fdd_track0(int drive) return !fdd[drive].track; } +int fdd_track(int drive) +{ + return fdd[drive].track; +} + void fdd_set_densel(int densel) { int i = 0; diff --git a/src/fdd.h b/src/fdd.h index e8de9db96..6a28743f4 100644 --- a/src/fdd.h +++ b/src/fdd.h @@ -49,3 +49,5 @@ char *fdd_getname(int type); char *fdd_get_internal_name(int type); int fdd_get_from_internal_name(char *s); + +int fdd_track(int drive);