diff --git a/README.md b/README.md index d9885ccd7..d7c1f4e08 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Building -------- In order to compile 86Box from this repository, please follow this step-by-step guide: -1. Download the development environment from http://tinyurl.com/pcemude. +1. Download the development environment from http://tinyurl.com/de86box. Afterwards, extract it to your desired location. Of course, also clone the repository in your desired location. Downloading ZIPs is not recommended, as it makes it more inconvenient to keep the code up-to-date. To avoid diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 9e727c525..dd61fdbde 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -9,7 +9,7 @@ * Implementation of the CD-ROM drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)cdrom.c 1.0.27 2018/01/10 + * Version: @(#)cdrom.c 1.0.28 2018/01/17 * * Author: Miran Grca, * @@ -235,6 +235,53 @@ static const mode_sense_pages_t cdrom_mode_sense_pages_default = { GPMODE_CAPABILITIES_PAGE, 0x14, 0x3B, 0, 0x71, 0x60, 0x29, 0, 0x02, 0xC2, 0, 2, 0, 0, 0x02, 0xC2, 0, 0, 0, 0, 0, 0 } } }; +static const mode_sense_pages_t cdrom_mode_sense_pages_default_scsi = +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, + { 0x8E, 0xE, 5, 4, 0,0x80,0, 75, 1, 0xFF, 2, 0xFF, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CAPABILITIES_PAGE, 0x14, 0x3B, 0, 0x71, 0x60, 0x29, 0, 0x02, 0xC2, 0, 2, 0, 0, 0x02, 0xC2, 0, 0, 0, 0, 0, 0 } +} }; + static const mode_sense_pages_t cdrom_mode_sense_pages_changeable = { { { 0, 0 }, @@ -251,7 +298,7 @@ static const mode_sense_pages_t cdrom_mode_sense_pages_changeable = { 0, 0 }, { 0, 0 }, { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, - { 0x8E, 0xE, 4, 0, 0, 0, 0, 75, 1, 0xFF, 2, 0xFF, 0, 0, 0, 0 }, + { 0x8E, 0xE, 5, 4, 0,0x80,0, 75, 1, 0xFF, 2, 0xFF, 0, 0, 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, @@ -509,11 +556,18 @@ void cdrom_mode_sense_load(uint8_t id) int i; memset(&cdrom_mode_sense_pages_saved[id], 0, sizeof(mode_sense_pages_t)); for (i = 0; i < 0x3f; i++) { - if (cdrom_mode_sense_pages_default.pages[i][1] != 0) - memcpy(cdrom_mode_sense_pages_saved[id].pages[i], cdrom_mode_sense_pages_default.pages[i], cdrom_mode_sense_pages_default.pages[i][1] + 2); + if (cdrom_mode_sense_pages_default.pages[i][1] != 0) { + if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) + memcpy(cdrom_mode_sense_pages_saved[id].pages[i], cdrom_mode_sense_pages_default_scsi.pages[i], cdrom_mode_sense_pages_default_scsi.pages[i][1] + 2); + else + memcpy(cdrom_mode_sense_pages_saved[id].pages[i], cdrom_mode_sense_pages_default.pages[i], cdrom_mode_sense_pages_default.pages[i][1] + 2); + } } memset(file_name, 0, 512 * sizeof(wchar_t)); - swprintf(file_name, 512, L"cdrom_%02i_mode_sense_bin", id); + if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) + swprintf(file_name, 512, L"scsi_cdrom_%02i_mode_sense_bin", id); + else + swprintf(file_name, 512, L"cdrom_%02i_mode_sense_bin", id); f = plat_fopen(nvr_path(file_name), L"rb"); if (f) { fread(cdrom_mode_sense_pages_saved[id].pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, f); @@ -526,7 +580,10 @@ void cdrom_mode_sense_save(uint8_t id) FILE *f; wchar_t file_name[512]; memset(file_name, 0, 512 * sizeof(wchar_t)); - swprintf(file_name, 512, L"cdrom_%02i_mode_sense_bin", id); + if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) + swprintf(file_name, 512, L"scsi_cdrom_%02i_mode_sense_bin", id); + else + swprintf(file_name, 512, L"cdrom_%02i_mode_sense_bin", id); f = plat_fopen(nvr_path(file_name), L"wb"); if (f) { fwrite(cdrom_mode_sense_pages_saved[id].pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, f); @@ -576,7 +633,10 @@ uint8_t cdrom_mode_sense_read(uint8_t id, uint8_t page_control, uint8_t page, ui return cdrom_mode_sense_pages_changeable.pages[page][pos]; break; case 2: - return cdrom_mode_sense_pages_default.pages[page][pos]; + if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) + return cdrom_mode_sense_pages_default_scsi.pages[page][pos]; + else + return cdrom_mode_sense_pages_default.pages[page][pos]; break; } @@ -2515,7 +2575,10 @@ uint8_t cdrom_phase_data_out(uint8_t id) pos += page_len; - val = cdrom_mode_sense_pages_default.pages[page][0] & 0x80; + if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) + val = cdrom_mode_sense_pages_default_scsi.pages[page][0] & 0x80; + else + val = cdrom_mode_sense_pages_default.pages[page][0] & 0x80; if (cdrom[id].do_page_save && val) cdrom_mode_sense_save(id); diff --git a/src/config.c b/src/config.c index fa85591dc..2c4bea7b1 100644 --- a/src/config.c +++ b/src/config.c @@ -8,16 +8,16 @@ * * Configuration file handler. * - * Version: @(#)config.c 1.0.36 2017/12/28 + * Version: @(#)config.c 1.0.37 2018/01/16 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * Overdoze, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. - * Copyright 2017 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. * * NOTE: Forcing config files to be in Unicode encoding breaks * it on Windows XP, and possibly also Vista. Use the @@ -39,9 +39,8 @@ #include "disk/hdd.h" #include "disk/hdc.h" #include "disk/hdc_ide.h" -#include "floppy/floppy.h" -#include "floppy/fdc.h" #include "floppy/fdd.h" +#include "floppy/fdc.h" #include "game/gameport.h" #include "machine/machine.h" #include "mouse.h" diff --git a/src/cpu/386.c b/src/cpu/386.c index 85f8948f4..72ba7c008 100644 --- a/src/cpu/386.c +++ b/src/cpu/386.c @@ -16,7 +16,7 @@ #include "../pic.h" #include "../pit.h" #include "../timer.h" -#include "../floppy/floppy.h" +#include "../floppy/fdd.h" #include "../floppy/fdc.h" #include "386_common.h" diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index 495853aa1..4aca453e5 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -17,7 +17,7 @@ #include "../nmi.h" #include "../pic.h" #include "../timer.h" -#include "../floppy/floppy.h" +#include "../floppy/fdd.h" #include "../floppy/fdc.h" #ifdef USE_DYNAREC #include "codegen.h" diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 60746c309..e41e44f81 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -9,20 +9,23 @@ * Implementation of the NEC uPD-765 and compatible floppy disk * controller. * - * Version: @(#)fdc.c 1.0.10 2017/12/08 + * Version: @(#)fdc->c 1.0.11 2018/01/16 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include +#include #include #include #include +#define HAVE_STDARG_H #include "../86box.h" +#include "../device.h" #include "../cpu/cpu.h" #include "../machine/machine.h" #include "../io.h" @@ -32,9 +35,8 @@ #include "../pic.h" #include "../timer.h" #include "../ui.h" -#include "floppy.h" -#include "fdc.h" #include "fdd.h" +#include "fdc.h" extern int64_t motoron[FDD_NUM]; @@ -80,93 +82,15 @@ int command_has_drivesel[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static int fdc_reset_stat = 0; -/*FDC*/ -typedef struct FDC -{ - uint8_t dor,stat,command,dat,st0; - int head,sector,drive,lastdrive; - int pcn[4]; - int rw_track; - int pos; - uint8_t params[256]; - uint8_t res[256]; - int pnum,ptot; - int rate; - uint8_t specify[256]; - int eot[256]; - int lock; - int perp; - uint8_t config, pretrk; - int abort; - uint8_t format_dat[256]; - int format_state; - int format_n; - int tc; - int written; - - int pcjr, ps1; - - int64_t watchdog_timer; - int64_t watchdog_count; +uint8_t current_drive = 0; - int data_ready; - int inread; - - int dskchg_activelow; - int enable_3f1; - - int bitcell_period; - - int is_nsc; /* 1 = FDC is on a National Semiconductor Super I/O chip, 0 = other FDC. This is needed, - because the National Semiconductor Super I/O chips add some FDC commands. */ - int enh_mode; - int rwc[4]; - int boot_drive; - int densel_polarity; - int densel_force; - int drvrate[4]; - - int dma; - int fifo, tfifo; - int fifobufpos; - int drv2en; - uint8_t fifobuf[16]; - - int gap, dtl; - int format_sectors; - - int max_track; - int mfm; - - int deleted; - int wrong_am; - - int sc; - int satisfying_sectors; - - sector_id_t read_track_sector; - int fintr; - - int rw_drive; - - uint16_t base_address; -} FDC; - -int64_t floppytime; - -static FDC fdc; - -void fdc_callback(void *priv); +static void fdc_callback(void *priv); int timetolive; int lastbyte=0; -uint8_t floppy_3f7; int floppymodified[4]; int floppyrate[4]; -int floppyint; - #ifdef ENABLE_FDC_LOG int fdc_do_log = ENABLE_FDC_LOG; #endif @@ -181,1162 +105,1033 @@ fdc_log(const char *fmt, ...) if (fdc_do_log) { va_start(ap, fmt); - pclog(fmt, ap); + pclog_ex(fmt, ap); va_end(ap); } #endif } -void fdc_reset(void) +uint8_t +fdc_ps1_525(void) { - fdc.stat=0x80; - fdc.pnum=fdc.ptot=0; - fdc.st0=0; - fdc.lock = 0; - fdc.head = 0; - fdc.abort = 0; - if (!AT) - { - fdc.rate = 2; - } -} - -sector_id_t fdc_get_read_track_sector(void) -{ - return fdc.read_track_sector; -} - -int fdc_ps1_525(void) -{ - if ((romset == ROM_IBMPS1_2011) && fdd_is_525(real_drive(fdc.dor & 3))) - { - return 0x40; - } - else - { - return 0; - } -} - -int fdc_get_compare_condition(void) -{ - switch (floppyint) - { - case 0x11: - default: - return 0; - case 0x19: - return 1; - case 0x1D: - return 2; - } -} - -int fdc_is_deleted(void) -{ - return fdc.deleted & 1; -} - -int fdc_is_sk(void) -{ - return (fdc.deleted & 0x20) ? 1 : 0; -} - -void fdc_set_wrong_am(void) -{ - fdc.wrong_am = 1; -} - -int fdc_get_drive(void) -{ - return fdc.drive; -} - -int fdc_get_bitcell_period(void); - -int fdc_get_perp(void) -{ - if (!AT || fdc.pcjr || fdc.ps1) return 0; - - return fdc.perp; -} - -int fdc_get_bit_rate(void); - -int fdc_get_gap2(int drive) -{ - int auto_gap2 = 22; - - if (!AT || fdc.pcjr || fdc.ps1) return 22; - - if (fdc.perp & 3) - { - return ((fdc.perp & 3) == 3) ? 41 : 22; - } - else - { - auto_gap2 = (fdc_get_bit_rate() >= 3) ? 41 : 22; - return (fdc.perp & (4 << drive)) ? auto_gap2 : 22; - } -} - -int fdc_get_format_n(void) -{ - return fdc.format_n; -} - -int fdc_is_mfm() -{ - return fdc.mfm ? 1 : 0; -} - -#if 0 -double fdc_get_hut(void) -{ - int hut = (fdc.specify[0] & 0xF); - double dusec; - double bcp = ((double) fdc_get_bitcell_period()) / 250.0; - double dhut = (double) hut; - if (fdc_get_bitcell_period() == 3333) bcp = 160.0 / 6.0; - if (hut == 0) dhut = 16.0; - dusec = (double) TIMER_USEC; - return (bcp * dhut * dusec * 1000.0); -} - -double fdc_get_hlt(void) -{ - int hlt = (fdc.specify[1] >> 1); - double dusec; - double bcp = ((double) fdc_get_bitcell_period()) / 2000.0; - double dhlt = (double) hlt; - if (fdc_get_bitcell_period() == 3333) bcp = 20.0 / 6.0; - if (hlt == 0) dhlt = 256.0; - dusec = (double) TIMER_USEC; - return (bcp * dhlt * dusec * 1000.0); -} -#endif - -void fdc_request_next_sector_id(void) -{ - if (fdc.pcjr || !fdc.dma) - { - fdc.stat = 0xf0; - } - else - { - fdc.stat = 0xd0; - } -} - -void fdc_stop_id_request(void) -{ - fdc.stat &= 0x7f; -} - -int fdc_get_gap(void) -{ - return fdc.gap; -} - -int fdc_get_dtl(void) -{ - return fdc.dtl; -} - -int fdc_get_format_sectors(void) -{ - return fdc.format_sectors; -} - -void fdc_reset_fifo_buf(void) -{ - memset(fdc.fifobuf, 0, 16); - fdc.fifobufpos = 0; -} - -void fdc_fifo_buf_advance(void) -{ - if (fdc.fifobufpos == fdc.tfifo) - { - fdc.fifobufpos = 0; - } - else - { - fdc.fifobufpos++; - } -} - -void fdc_fifo_buf_write(int val) -{ - fdc.fifobuf[fdc.fifobufpos] = val; - fdc_fifo_buf_advance(); -} - -int fdc_fifo_buf_read(void) -{ - int temp = 0; - temp = fdc.fifobuf[fdc.fifobufpos]; - fdc_fifo_buf_advance(); - return temp; -} - -static void fdc_int(void) -{ - if (!fdc.pcjr) - { - if (fdc.dor & 8) - { - picint(1 << 6); - fdc.fintr = 1; - } - } -} - -static void fdc_watchdog_poll(void *p) -{ - FDC *fdc = (FDC *)p; - - fdc->watchdog_count--; - if (fdc->watchdog_count) - fdc->watchdog_timer += 1000LL * TIMER_USEC; - else - { - fdc->watchdog_timer = 0LL; - if (fdc->dor & 0x20) - picint(1 << 6); - } -} - -/* fdc.rwc per Winbond W83877F datasheet: - 0 = normal; - 1 = 500 kbps, 360 rpm; - 2 = 500 kbps, 300 rpm; - 3 = 250 kbps - - Drive is only aware of selected rate and densel, so on real hardware, the rate expected by FDC and the rate actually being - processed by drive can mismatch, in which case the FDC won't receive the correct data. -*/ - -int bit_rate = 250; - -static void fdc_rate(int drive); - -void fdc_update_rates(void) -{ - fdc_rate(0); - fdc_rate(1); - fdc_rate(2); - fdc_rate(3); -} - -void fdc_update_is_nsc(int is_nsc) -{ - int old_is_nsc = fdc.is_nsc; - fdc.is_nsc = is_nsc; - if (old_is_nsc != is_nsc) - { - fdc.densel_force = fdc.densel_force ^ 3; - } - fdc_update_rates(); -} - -void fdc_update_max_track(int max_track) -{ - fdc.max_track = max_track; -} - -void fdc_update_enh_mode(int enh_mode) -{ - fdc.enh_mode = enh_mode; - fdc_update_rates(); -} - -int fdc_get_rwc(int drive) -{ - return fdc.rwc[drive]; -} - -void fdc_update_rwc(int drive, int rwc) -{ - fdc_log("FDD %c: New RWC is %i\n", 0x41 + drive, rwc); - fdc.rwc[drive] = rwc; - fdc_rate(drive); -} - -int fdc_get_boot_drive(void) -{ - return fdc.boot_drive; -} - -void fdc_update_boot_drive(int boot_drive) -{ - fdc.boot_drive = boot_drive; -} - -void fdc_update_densel_polarity(int densel_polarity) -{ - fdc_log("FDC: New DENSEL polarity is %i\n", densel_polarity); - fdc.densel_polarity = densel_polarity; - fdc_update_rates(); -} - -uint8_t fdc_get_densel_polarity(void) -{ - return fdc.densel_polarity; -} - -void fdc_update_densel_force(int densel_force) -{ - fdc_log("FDC: New DENSEL force is %i\n", densel_force); - fdc.densel_force = densel_force; - fdc_update_rates(); -} - -void fdc_update_drvrate(int drive, int drvrate) -{ - fdc_log("FDD %c: New drive rate is %i\n", 0x41 + drive, drvrate); - fdc.drvrate[drive] = drvrate; - fdc_rate(drive); -} - -void fdc_update_drv2en(int drv2en) -{ - fdc.drv2en = drv2en; -} - -void fdc_update_rate(int drive) -{ - if (((fdc.rwc[drive] == 1) || (fdc.rwc[drive] == 2)) && fdc.enh_mode) - { - bit_rate = 500; - } - else if ((fdc.rwc[drive] == 3) && fdc.enh_mode) - { - bit_rate = 250; - } - else switch (fdc.rate) - { - case 0: /*High density*/ - bit_rate = 500; - break; - case 1: /*Double density (360 rpm)*/ - switch(fdc.drvrate[drive]) - { - case 0: - bit_rate = 300; - break; - case 1: - bit_rate = 500; - break; - case 2: - bit_rate = 2000; - break; - } - break; - case 2: /*Double density*/ - bit_rate = 250; - break; - case 3: /*Extended density*/ - bit_rate = 1000; - break; - } - - fdc.bitcell_period = 1000000 / bit_rate*2; /*Bitcell period in ns*/ -} - -int fdc_get_bit_rate(void) -{ - switch(bit_rate) - { - case 500: - return 0; - case 300: - return 1; - case 2000: - return 1 | 4; - case 250: - return 2; - case 1000: - return 3; - default: - return 2; - } - return 2; -} - -int fdc_get_bitcell_period(void) -{ - return fdc.bitcell_period; -} - -static int fdc_get_densel(int drive) -{ - if (fdc.enh_mode) - { - switch (fdc.rwc[drive]) - { - case 1: - case 3: - return 0; - case 2: - return 1; - } - } - - if (!fdc.is_nsc) - { - switch (fdc.densel_force) - { - case 2: - return 1; - case 3: - return 0; - } - } - else - { - switch (fdc.densel_force) - { - case 0: - return 0; - case 1: - return 1; - } - } - - switch (fdc.rate) - { - case 0: - case 3: - return fdc.densel_polarity ? 1 : 0; - case 1: - case 2: - return fdc.densel_polarity ? 0 : 1; - } - + if ((romset == ROM_IBMPS1_2011) && fdd_is_525(current_drive)) + return 0x40; + else return 0; } -static void fdc_rate(int drive) + +void +fdc_ctrl_reset(void *p) { - fdc_update_rate(drive); - floppy_set_rate(drive, fdc.drvrate[drive], fdc.rate); - fdc_log("FDD %c: Setting rate: %i, %i, %i (%i, %i)\n", 0x41 + drive, fdc.drvrate[drive], fdc.rate, fdc_get_densel(drive), fdc.rwc[drive], fdc.densel_force); - fdd_set_densel(fdc_get_densel(drive)); + fdc_t *fdc = (fdc_t *) p; + + fdc->stat = 0x80; + fdc->pnum = fdc->ptot=0; + fdc->st0 = 0; + fdc->lock = 0; + fdc->head = 0; + fdc->abort = 0; + if (!(fdc->flags & FDC_FLAG_AT)) + fdc->rate = 2; } -void fdc_seek(int drive, int params) + +sector_id_t +fdc_get_read_track_sector(fdc_t *fdc) { - fdd_seek(drive, params); - fdc.stat |= (1 << fdc.drive); + return fdc->read_track_sector; } -int real_drive(int drive) + +int +fdc_get_compare_condition(fdc_t *fdc) { - if (drive < 2) - { - return drive ^ fdd_swap; - } - else - { - return drive; + switch (fdc->interrupt) { + case 0x11: + default: + return 0; + case 0x19: + return 1; + case 0x1D: + return 2; + } +} + + +int +fdc_is_deleted(fdc_t *fdc) +{ + return fdc->deleted & 1; +} + + +int +fdc_is_sk(fdc_t *fdc) +{ + return (fdc->deleted & 0x20) ? 1 : 0; +} + + +void +fdc_set_wrong_am(fdc_t *fdc) +{ + fdc->wrong_am = 1; +} + + +int +fdc_get_drive(fdc_t *fdc) +{ + return fdc->drive; +} + + +int fdc_get_bitcell_period(fdc_t *fdc); +int fdc_get_bit_rate(fdc_t *fdc); +static void fdc_rate(fdc_t *fdc, int drive); + + +int +fdc_get_perp(fdc_t *fdc) +{ + if (!(fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_PCJR) || (fdc->flags & FDC_FLAG_PS1)) + return 0; + + return fdc->perp; +} + + +int +fdc_get_gap2(fdc_t *fdc, int drive) +{ + int auto_gap2 = 22; + + if (!(fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_PCJR) || (fdc->flags & FDC_FLAG_PS1)) + return 22; + + if (fdc->perp & 3) + return ((fdc->perp & 3) == 3) ? 41 : 22; + else { + auto_gap2 = (fdc_get_bit_rate(fdc) >= 3) ? 41 : 22; + return (fdc->perp & (4 << drive)) ? auto_gap2 : 22; + } +} + + +int +fdc_get_format_n(fdc_t *fdc) +{ + return fdc->format_n; +} + + +int +fdc_is_mfm(fdc_t *fdc) +{ + return fdc->mfm ? 1 : 0; +} + + +void +fdc_request_next_sector_id(fdc_t *fdc) +{ + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) + fdc->stat = 0xf0; + else + fdc->stat = 0xd0; +} + + +void +fdc_stop_id_request(fdc_t *fdc) +{ + fdc->stat &= 0x7f; +} + + +int +fdc_get_gap(fdc_t *fdc) +{ + return fdc->gap; +} + + +int +fdc_get_dtl(fdc_t *fdc) +{ + return fdc->dtl; +} + + +int +fdc_get_format_sectors(fdc_t *fdc) +{ + return fdc->format_sectors; +} + + +static void +fdc_reset_fifo_buf(fdc_t *fdc) +{ + memset(fdc->fifobuf, 0, 16); + fdc->fifobufpos = 0; +} + + +static void +fdc_fifo_buf_advance(fdc_t *fdc) +{ + if (fdc->fifobufpos == fdc->tfifo) + fdc->fifobufpos = 0; + else + fdc->fifobufpos++; +} + + +static void +fdc_fifo_buf_write(fdc_t *fdc, uint8_t val) +{ + fdc->fifobuf[fdc->fifobufpos] = val; + fdc_fifo_buf_advance(fdc); +} + + +static int +fdc_fifo_buf_read(fdc_t *fdc) +{ + int temp = fdc->fifobuf[fdc->fifobufpos]; + fdc_fifo_buf_advance(fdc); + return temp; +} + + +static +void fdc_int(fdc_t *fdc) +{ + if (!(fdc->flags & FDC_FLAG_PCJR)) { + if (fdc->dor & 8) { + picint(1 << fdc->irq); + fdc->fintr = 1; } + } } -void fdc_implied_seek(void) + +static void +fdc_watchdog_poll(void *priv) { - if (fdc.config & 0x40) - { - if (fdc.params[1] != fdc.pcn[fdc.params[0] & 3]) - { - fdc_seek(fdc.drive, ((int) fdc.params[1]) - ((int) fdc.pcn[fdc.params[0] & 3])); - fdc.pcn[fdc.params[0] & 3] = fdc.params[1]; + fdc_t *fdc = (fdc_t *) priv; + + fdc->watchdog_count--; + if (fdc->watchdog_count) + fdc->watchdog_timer += 1000LL * TIMER_USEC; + else { + fdc->watchdog_timer = 0LL; + if (fdc->dor & 0x20) + picint(1 << fdc->irq); + } +} + + +/* fdc->rwc per Winbond W83877F datasheet: + 0 = normal; + 1 = 500 kbps, 360 rpm; + 2 = 500 kbps, 300 rpm; + 3 = 250 kbps + + Drive is only aware of selected rate and densel, so on real hardware, the rate expected by fdc_t and the rate actually being + processed by drive can mismatch, in which case the fdc_t won't receive the correct data. +*/ + +void +fdc_update_rates(fdc_t *fdc) +{ + fdc_rate(fdc, 0); + fdc_rate(fdc, 1); + fdc_rate(fdc, 2); + fdc_rate(fdc, 3); +} + + +void +fdc_update_is_nsc(fdc_t *fdc, int is_nsc) +{ + int old_is_nsc = fdc->flags & FDC_FLAG_NSC; + if (is_nsc) + fdc->flags |= FDC_FLAG_NSC; + else + fdc->flags &= ~FDC_FLAG_NSC; + if ((old_is_nsc ^ fdc->flags) & FDC_FLAG_NSC) + fdc->densel_force = fdc->densel_force ^ 3; + fdc_update_rates(fdc); +} + + +void +fdc_update_max_track(fdc_t *fdc, int max_track) +{ + fdc->max_track = max_track; +} + + +void +fdc_update_enh_mode(fdc_t *fdc, int enh_mode) +{ + fdc->enh_mode = enh_mode; + fdc_update_rates(fdc); +} + + +int +fdc_get_rwc(fdc_t *fdc, int drive) +{ + return fdc->rwc[drive]; +} + + +void +fdc_update_rwc(fdc_t *fdc, int drive, int rwc) +{ + fdc_log("FDD %c: New RWC is %i\n", 0x41 + drive, rwc); + fdc->rwc[drive] = rwc; + fdc_rate(fdc, drive); +} + + +int +fdc_get_boot_drive(fdc_t *fdc) +{ + return fdc->boot_drive; +} + + +void +fdc_update_boot_drive(fdc_t *fdc, int boot_drive) +{ + fdc->boot_drive = boot_drive; +} + + +void +fdc_update_densel_polarity(fdc_t *fdc, int densel_polarity) +{ + fdc_log("FDC: New DENSEL polarity is %i\n", densel_polarity); + fdc->densel_polarity = densel_polarity; + fdc_update_rates(fdc); +} + + +uint8_t +fdc_get_densel_polarity(fdc_t *fdc) +{ + return fdc->densel_polarity; +} + + +void +fdc_update_densel_force(fdc_t *fdc, int densel_force) +{ + fdc_log("FDC: New DENSEL force is %i\n", densel_force); + fdc->densel_force = densel_force; + fdc_update_rates(fdc); +} + + +void +fdc_update_drvrate(fdc_t *fdc, int drive, int drvrate) +{ + fdc_log("FDD %c: New drive rate is %i\n", 0x41 + drive, drvrate); + fdc->drvrate[drive] = drvrate; + fdc_rate(fdc, drive); +} + + +void +fdc_update_drv2en(fdc_t *fdc, int drv2en) +{ + fdc->drv2en = drv2en; +} + + +void +fdc_update_rate(fdc_t *fdc, int drive) +{ + if (((fdc->rwc[drive] == 1) || (fdc->rwc[drive] == 2)) && fdc->enh_mode) + fdc->bit_rate = 500; + else if ((fdc->rwc[drive] == 3) && fdc->enh_mode) + fdc->bit_rate = 250; + else switch (fdc->rate) { + case 0: /*High density*/ + fdc->bit_rate = 500; + break; + case 1: /*Double density (360 rpm)*/ + switch(fdc->drvrate[drive]) { + case 0: + fdc->bit_rate = 300; + break; + case 1: + fdc->bit_rate = 500; + break; + case 2: + fdc->bit_rate = 2000; + break; } - } + break; + case 2: /*Double density*/ + fdc->bit_rate = 250; + break; + case 3: /*Extended density*/ + fdc->bit_rate = 1000; + break; + } + + fdc->bitcell_period = 1000000 / fdc->bit_rate * 2; /*Bitcell period in ns*/ } -int fifo_count = 0; -void fdc_write(uint16_t addr, uint8_t val, void *priv) +int +fdc_get_bit_rate(fdc_t *fdc) { - int drive, i, drive_num; - int seek_time, seek_time_base; + switch(fdc->bit_rate) { + case 500: + return 0; + case 300: + return 1; + case 2000: + return 1 | 4; + case 250: + return 2; + case 1000: + return 3; + default: + return 2; + } + return 2; +} - fdc_log("Write FDC %04X %02X\n",addr,val); - switch (addr&7) - { - case 0: return; - case 1: return; - case 2: /*DOR*/ - if (fdc.pcjr) - { - if ((fdc.dor & 0x40) && !(val & 0x40)) - { - fdc.watchdog_timer = 1000LL * TIMER_USEC; - fdc.watchdog_count = 1000LL; - picintc(1 << 6); - } - if ((val & 0x80) && !(fdc.dor & 0x80)) - { - timer_process(); - floppytime = 128LL * (1LL << TIMER_SHIFT); - timer_update_outstanding(); - floppyint=-1; +int +fdc_get_bitcell_period(fdc_t *fdc) +{ + return fdc->bitcell_period; +} + + +static int +fdc_get_densel(fdc_t *fdc, int drive) +{ + if (fdc->enh_mode) { + switch (fdc->rwc[drive]) { + case 1: + case 3: + return 0; + case 2: + return 1; + } + } + + if (!(fdc->flags & FDC_FLAG_NSC)) { + switch (fdc->densel_force) { + case 2: + return 1; + case 3: + return 0; + } + } else { + switch (fdc->densel_force) { + case 0: + return 0; + case 1: + return 1; + } + } + + switch (fdc->rate) { + case 0: + case 3: + return fdc->densel_polarity ? 1 : 0; + case 1: + case 2: + return fdc->densel_polarity ? 0 : 1; + } + + return 0; +} + + +static void +fdc_rate(fdc_t *fdc, int drive) +{ + fdc_update_rate(fdc, drive); + fdd_set_rate(drive, fdc->drvrate[drive], fdc->rate); + fdc_log("FDD %c: Setting rate: %i, %i, %i (%i, %i)\n", 0x41 + drive, fdc->drvrate[drive], fdc->rate, fdc_get_densel(fdc, drive), fdc->rwc[drive], fdc->densel_force); + fdd_set_densel(fdc_get_densel(fdc, drive)); +} + + +int +real_drive(fdc_t *fdc, int drive) +{ + if (drive < 2) + return drive ^ fdc->swap; + else + return drive; +} + + +void +fdc_seek(fdc_t *fdc, int drive, int params) +{ + fdd_seek(real_drive(fdc, drive), params); + fdc->time = 5000 * TIMER_SHIFT; + + fdc->stat |= (1 << fdc->drive); +} + + +void +fdc_implied_seek(fdc_t *fdc) +{ + if (fdc->config & 0x40) { + if (fdc->params[1] != fdc->pcn[fdc->params[0] & 3]) { + fdc_seek(fdc, fdc->drive, ((int) fdc->params[1]) - ((int) fdc->pcn[fdc->params[0] & 3])); + fdc->pcn[fdc->params[0] & 3] = fdc->params[1]; + } + } +} + + +static void +fdc_bad_command(fdc_t *fdc) +{ + fdc->stat |= 0x10; + fdc->interrupt = 0xfc; + timer_process(); + fdc->time = 200LL * (1LL << TIMER_SHIFT); + timer_update_outstanding(); +} + + +static void +fdc_io_command_phase1(fdc_t *fdc, int out) +{ + fdc_reset_fifo_buf(fdc); + fdc_rate(fdc, fdc->drive); + fdc->head = fdc->params[2]; + fdd_set_head(real_drive(fdc, 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]; + fdc_implied_seek(fdc); + fdc->rw_track = fdc->params[1]; + fdc->time = 0LL; + ui_sb_update_icon(SB_FLOPPY | fdc->drive, 1); + fdc->stat = out ? 0x90 : 0x50; + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) + fdc->stat |= 0x20; + if (out) { + fdc->written = 0; + fdc->pos = 0; + } else + fdc->inread = 1; +} + + +static void +fdc_write(uint16_t addr, uint8_t val, void *priv) +{ + fdc_t *fdc = (fdc_t *) priv; + + int drive, i, drive_num; + int seek_time, seek_time_base; + + fdc_log("Write FDC %04X %02X\n", addr, val); + + switch (addr&7) { + case 0: + return; + case 1: + return; + case 2: /*DOR*/ + if ((fdc->flags & FDC_FLAG_PCJR)) { + if ((fdc->dor & 0x40) && !(val & 0x40)) { + fdc->watchdog_timer = 1000LL * TIMER_USEC; + fdc->watchdog_count = 1000LL; + picintc(1 << fdc->irq); + } + if ((val & 0x80) && !(fdc->dor & 0x80)) { + timer_process(); + fdc->time = 128LL * (1LL << TIMER_SHIFT); + timer_update_outstanding(); + fdc->interrupt = -1; ui_sb_update_icon(SB_FLOPPY | 0, 0); - fdc_reset(); - } + fdc_ctrl_reset(fdc); + } if (!fdd_get_flags(0)) - { val &= 0xfe; + motoron[0 ^ fdc->swap] = val & 0x01; + } else { + if (!(val & 8) && (fdc->dor & 8)) { + fdc->tc = 1; + fdc_int(fdc); } - motoron[0 ^ fdd_swap] = val & 0x01; - } - else - { - if (!(val & 8) && (fdc.dor & 8)) - { - fdc.tc = 1; - fdc_int(); + if (!(val&4)) { + fdd_stop(real_drive(fdc, val & 3)); + fdc->stat = 0x00; + fdc->pnum = fdc->ptot = 0; } - if (!(val&4)) - { - floppy_stop(real_drive(val & 3)); - fdc.stat=0x00; - fdc.pnum=fdc.ptot=0; - } - if (val&4) - { - fdc.stat=0x80; - fdc.pnum=fdc.ptot=0; + if (val&4) { + fdc->stat = 0x80; + fdc->pnum = fdc->ptot = 0; } - if ((val&4) && !(fdc.dor&4)) - { - timer_process(); - floppytime = 128LL * (1LL << TIMER_SHIFT); - timer_update_outstanding(); - floppyint=-1; - fdc.perp &= 0xfc; + if ((val&4) && !(fdc->dor&4)) { + timer_process(); + fdc->time = 128LL * (1LL << TIMER_SHIFT); + timer_update_outstanding(); + fdc->interrupt = -1; + fdc->perp &= 0xfc; for (i = 0; i < FDD_NUM; i++) - { ui_sb_update_icon(SB_FLOPPY | i, 0); - } - fdc_reset(); - } + fdc_ctrl_reset(fdc); + } timer_process(); timer_update_outstanding(); /* We can now simplify this since each motor now spins separately. */ - for (i = 0; i < FDD_NUM; i++) - { - drive_num = real_drive(i); + for (i = 0; i < FDD_NUM; i++) { + drive_num = real_drive(fdc, i); if ((!fdd_get_flags(drive_num)) || (drive_num >= FDD_NUM)) - { val &= ~(0x10 << drive_num); - } else - { motoron[i] = (val & (0x10 << drive_num)); - } } - drive_num = real_drive(val & 3); - } - fdc.dor=val; - return; - case 3: - /* TDR */ - if (fdc.enh_mode) - { - drive = real_drive(fdc.dor & 3); - fdc_update_rwc(drive, (val & 0x30) >> 4); + drive_num = real_drive(fdc, val & 3); + current_drive = real_drive(fdc, val & 3); + } + fdc->dor=val; + return; + case 3: /* TDR */ + if (fdc->enh_mode) { + drive = real_drive(fdc, fdc->dor & 3); + fdc_update_rwc(fdc, drive, (val & 0x30) >> 4); } return; - case 4: - if (val & 0x80) - { + case 4: + if (val & 0x80) { timer_process(); - floppytime = 128LL * (1LL << TIMER_SHIFT); - timer_update_outstanding(); - floppyint=-1; - fdc.perp &= 0xfc; - fdc_reset(); - } - return; - case 5: /*Command register*/ - if ((fdc.stat & 0xf0) == 0xb0) - { - if (fdc.pcjr || !fdc.fifo) - { - fdc.dat = val; - fdc.stat &= ~0x80; + fdc->time = 128LL * (1LL << TIMER_SHIFT); + timer_update_outstanding(); + fdc->interrupt = -1; + fdc->perp &= 0xfc; + fdc_ctrl_reset(fdc); + } + return; + case 5: /*Command register*/ + if ((fdc->stat & 0xf0) == 0xb0) { + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo) { + fdc->dat = val; + fdc->stat &= ~0x80; + } else { + fdc_fifo_buf_write(fdc, val); + if (fdc->fifobufpos == 0) + fdc->stat &= ~0x80; } - else - { - fdc_fifo_buf_write(val); - if (fdc.fifobufpos == 0) fdc.stat &= ~0x80; - } - break; - } - if (fdc.pnum==fdc.ptot) - { - if ((fdc.stat & 0xf0) != 0x80) - { - /* If bit 4 of the MSR is set, or the MSR is 0x00, the FDC is NOT in the command phase, therefore do NOT accept commands. */ + break; + } + if (fdc->pnum==fdc->ptot) { + if ((fdc->stat & 0xf0) != 0x80) { + /* If bit 4 of the MSR is set, or the MSR is 0x00, + the fdc_t is NOT in the command phase, therefore + do NOT accept commands. */ return; } - fdc.stat &= 0xf; + fdc->stat &= 0xf; - fdc.tc = 0; - fdc.data_ready = 0; - - fdc.command=val; - fdc.stat |= 0x10; - fdc_log("Starting FDC command %02X\n",fdc.command); - switch (fdc.command&0x1F) - { - case 1: /*Mode*/ - if (!fdc.is_nsc) goto bad_command; - fdc.pnum=0; - fdc.ptot=4; - fdc.stat |= 0x90; - fdc.pos=0; - fdc.format_state = 0; - break; + fdc->tc = 0; + fdc->data_ready = 0; - case 2: /*Read track*/ - fdc.satisfying_sectors=0; - fdc.sc=0; - fdc.wrong_am=0; - fdc.pnum=0; - fdc.ptot=8; - fdc.stat |= 0x90; - fdc.pos=0; - fdc.mfm=(fdc.command&0x40)?1:0; - break; - case 3: /*Specify*/ - fdc.pnum=0; - fdc.ptot=2; - fdc.stat |= 0x90; - break; - case 4: /*Sense drive status*/ - fdc.pnum=0; - fdc.ptot=1; - fdc.stat |= 0x90; - 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; - fdc.pnum=0; - fdc.ptot=8; - fdc.stat |= 0x90; - fdc.pos=0; - fdc.mfm=(fdc.command&0x40)?1:0; - 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*/ - fifo_count = 0; - fdc.satisfying_sectors=0; - fdc.sc=0; - fdc.wrong_am=0; - fdc.deleted = ((fdc.command&0x1F) == 0xC) ? 1 : 0; - if ((fdc.command&0x1F) == 0x16) fdc.deleted = 2; - fdc.deleted |= (fdc.command & 0x20); - fdc.pnum=0; - fdc.ptot=8; - fdc.stat |= 0x90; - fdc.pos=0; - fdc.mfm=(fdc.command&0x40)?1:0; - break; - case 7: /*Recalibrate*/ - fdc.pnum=0; - fdc.ptot=1; - fdc.stat |= 0x90; - break; - case 8: /*Sense interrupt status*/ - if (!fdc.fintr && !fdc_reset_stat) goto bad_command; - fdc.lastdrive = fdc.drive; - floppyint = 8; - fdc.pos = 0; - fdc_callback(NULL); - break; - case 10: /*Read sector ID*/ - fdc.pnum=0; - fdc.ptot=1; - fdc.stat |= 0x90; - fdc.pos=0; - fdc.mfm=(fdc.command&0x40)?1:0; - break; - case 0x0d: /*Format track*/ - fdc.pnum=0; - fdc.ptot=5; - fdc.stat |= 0x90; - fdc.pos=0; - fdc.format_state = 0; - fdc.mfm=(fdc.command&0x40)?1:0; - break; - case 15: /*Seek*/ - fdc.pnum=0; - fdc.ptot=2; - fdc.stat |= 0x90; - break; - case 0x0e: /*Dump registers*/ - fdc.lastdrive = fdc.drive; - floppyint = 0x0e; - fdc.pos = 0; - fdc_callback(NULL); - break; - case 0x10: /*Get version*/ - fdc.lastdrive = fdc.drive; - floppyint = 0x10; - fdc.pos = 0; - fdc_callback(NULL); - break; - case 0x12: /*Set perpendicular mode*/ - if (!AT || fdc.pcjr || fdc.ps1) goto bad_command; - fdc.pnum=0; - fdc.ptot=1; - fdc.stat |= 0x90; - fdc.pos=0; - break; - case 0x13: /*Configure*/ - fdc.pnum=0; - fdc.ptot=3; - fdc.stat |= 0x90; - fdc.pos=0; - break; - case 0x14: /*Unlock*/ - case 0x94: /*Lock*/ - fdc.lastdrive = fdc.drive; - floppyint = fdc.command; - fdc.pos = 0; - fdc_callback(NULL); - break; + fdc->command=val; + fdc->stat |= 0x10; + fdc_log("Starting fdc_t command %02X\n",fdc->command); - case 0x18: - if (!fdc.is_nsc) goto bad_command; - fdc.lastdrive = fdc.drive; - floppyint = 0x10; - fdc.pos = 0; - fdc_callback(NULL); - /* fdc.stat = 0x10; - floppyint = 0xfc; - fdc_callback(NULL); */ - break; - - default: -bad_command: - fdc.stat |= 0x10; - floppyint=0xfc; - timer_process(); - floppytime = 200LL * (1LL << TIMER_SHIFT); - timer_update_outstanding(); - break; - } - } - else - { - fdc.stat = 0x10 | (fdc.stat & 0xf); - fdc.params[fdc.pnum++]=val; - if (fdc.pnum == 1) - { - if (command_has_drivesel[fdc.command & 0x1F]) - { - fdc.drive = fdc.dor & 3; - fdc.rw_drive = fdc.params[0] & 3; - if (((fdc.command & 0x1F) == 7) || ((fdc.command & 0x1F) == 15)) - { - fdc.stat |= (1 << real_drive(fdc.drive)); - } + switch (fdc->command & 0x1f) { + case 0x01: /*Mode*/ + if (fdc->flags & FDC_FLAG_NSC) { + fdc->pnum = 0; + fdc->ptot = 4; + fdc->stat |= 0x90; + fdc->pos = 0; + fdc->format_state = 0; + } else + fdc_bad_command(fdc); + break; + case 0x02: /*Read track*/ + fdc->satisfying_sectors = 0; + fdc->sc = 0; + fdc->wrong_am = 0; + fdc->pnum = 0; + fdc->ptot = 8; + fdc->stat |= 0x90; + fdc->pos = 0; + fdc->mfm = (fdc->command & 0x40) ? 1:0; + break; + case 0x03: /*Specify*/ + fdc->pnum = 0; + fdc->ptot = 2; + fdc->stat |= 0x90; + break; + case 0x04: /*Sense drive status*/ + fdc->pnum = 0; + fdc->ptot = 1; + fdc->stat |= 0x90; + break; + case 0x05: /*Write data*/ + case 0x09: /*Write deleted data*/ + fdc->satisfying_sectors = 0; + fdc->sc = 0; + fdc->wrong_am = 0; + fdc->deleted = ((fdc->command&0x1F) == 9) ? 1 : 0; + fdc->pnum = 0; + fdc->ptot = 8; + fdc->stat |= 0x90; + fdc->pos = 0; + fdc->mfm = (fdc->command & 0x40) ? 1 : 0; + break; + case 0x06: /*Read data*/ + case 0x0c: /*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; + if ((fdc->command&0x1F) == 0x16) fdc->deleted = 2; + fdc->deleted |= (fdc->command & 0x20); + fdc->pnum = 0; + fdc->ptot = 8; + fdc->stat |= 0x90; + fdc->pos = 0; + fdc->mfm = (fdc->command&0x40)?1:0; + break; + case 0x07: /*Recalibrate*/ + fdc->pnum=0; + fdc->ptot=1; + fdc->stat |= 0x90; + break; + case 0x08: /*Sense interrupt status*/ + if (fdc->fintr || fdc->reset_stat) { + fdc->lastdrive = fdc->drive; + fdc->interrupt = 8; + fdc->pos = 0; + fdc_callback(fdc); + } else + fdc_bad_command(fdc); + break; + case 0x0a: /*Read sector ID*/ + fdc->pnum = 0; + fdc->ptot = 1; + fdc->stat |= 0x90; + fdc->pos = 0; + fdc->mfm = (fdc->command & 0x40) ? 1 : 0; + break; + case 0x0d: /*Format track*/ + fdc->pnum = 0; + fdc->ptot = 5; + fdc->stat |= 0x90; + fdc->pos = 0; + fdc->mfm = (fdc->command & 0x40) ? 1:0; + fdc->format_state = 0; + break; + case 0x0e: /*Dump registers*/ + fdc->lastdrive = fdc->drive; + fdc->interrupt = 0x0e; + fdc->pos = 0; + fdc_callback(fdc); + break; + case 0x0f: /*Seek*/ + fdc->pnum = 0; + fdc->ptot = 2; + fdc->stat |= 0x90; + break; + case 0x18: /*NSC*/ + if (!(fdc->flags & FDC_FLAG_NSC)) { + fdc_bad_command(fdc); + break; + } + case 0x10: /*Get version*/ + case 0x14: /*Unlock*/ + case 0x94: /*Lock*/ + fdc->lastdrive = fdc->drive; + fdc->interrupt = fdc->command; + fdc->pos = 0; + fdc_callback(fdc); + break; + case 0x12: /*Set perpendicular mode*/ + if ((fdc->flags & FDC_FLAG_AT) && !(fdc->flags & FDC_FLAG_PCJR) && !(fdc->flags & FDC_FLAG_PS1)) { + fdc->pnum=0; + fdc->ptot=1; + fdc->stat |= 0x90; + fdc->pos=0; + } else + fdc_bad_command(fdc); + break; + case 0x13: /*Configure*/ + fdc->pnum=0; + fdc->ptot=3; + fdc->stat |= 0x90; + fdc->pos=0; + break; + default: + fdc_bad_command(fdc); + break; + } + } else { + fdc->stat = 0x10 | (fdc->stat & 0xf); + fdc->params[fdc->pnum++]=val; + if (fdc->pnum == 1) { + if (command_has_drivesel[fdc->command & 0x1F]) { + fdc->drive = fdc->dor & 3; + fdc->rw_drive = fdc->params[0] & 3; + if (((fdc->command & 0x1F) == 7) || ((fdc->command & 0x1F) == 15)) + fdc->stat |= (1 << real_drive(fdc, fdc->drive)); } } - if (fdc.pnum==fdc.ptot) - { - fdc_log("Got all params %02X\n", fdc.command); - floppyint=fdc.command&0x1F; - timer_process(); - floppytime = 1024LL * (1LL << TIMER_SHIFT); - timer_update_outstanding(); - fdc_reset_stat = 0; - switch (floppyint & 0x1F) - { - case 2: /*Read a track*/ - fdc_reset_fifo_buf(); - 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]; - fdc.read_track_sector.id.c = fdc.params[1]; - fdc.read_track_sector.id.h = fdc.params[2]; - fdc.read_track_sector.id.r = 1; - fdc.read_track_sector.id.n = fdc.params[4]; - fdc_implied_seek(); - fdc.rw_track = fdc.params[1]; - floppy_readsector(fdc.drive, SECTOR_FIRST, fdc.params[1], fdc.head, fdc.rate, fdc.params[4]); - if (fdc.pcjr || !fdc.dma) - { - fdc.stat = 0x70; - } - else - { - fdc.stat = 0x50; - } - floppytime = 0LL; - ui_sb_update_icon(SB_FLOPPY | fdc.drive, 1); - fdc.inread = 1; - break; - - case 3: /*Specify*/ - fdc.stat=0x80; - fdc.specify[0] = fdc.params[0]; - fdc.specify[1] = fdc.params[1]; - fdc.dma = (fdc.specify[1] & 1) ^ 1; - floppytime = 0LL; - break; - - case 0x12: - fdc.stat=0x80; - if (fdc.params[0] & 0x80) - { - fdc.perp = fdc.params[0] & 0x3f; - } - else - { - fdc.perp &= 0xfc; - fdc.perp |= (fdc.params[0] & 0x03); - } - floppytime = 0LL; - return; - + if (fdc->pnum==fdc->ptot) { + fdc_log("Got all params %02X\n", fdc->command); + fdc->interrupt = fdc->command & 0x1F; + timer_process(); + fdc->time = 1024LL * (1LL << TIMER_SHIFT); + timer_update_outstanding(); + fdc->reset_stat = 0; + switch (fdc->interrupt & 0x1F) { + case 2: /*Read a track*/ + fdc_io_command_phase1(fdc, 0); + fdc->read_track_sector.id.c = fdc->params[1]; + fdc->read_track_sector.id.h = fdc->params[2]; + fdc->read_track_sector.id.r = 1; + fdc->read_track_sector.id.n = fdc->params[4]; + fdd_readsector(real_drive(fdc, fdc->drive), SECTOR_FIRST, fdc->params[1], fdc->head, fdc->rate, fdc->params[4]); + break; + case 3: /*Specify*/ + fdc->stat=0x80; + fdc->specify[0] = fdc->params[0]; + fdc->specify[1] = fdc->params[1]; + fdc->dma = (fdc->specify[1] & 1) ^ 1; + fdc->time = 0LL; + break; + case 0x12: + fdc->stat=0x80; + if (fdc->params[0] & 0x80) + fdc->perp = fdc->params[0] & 0x3f; + else { + fdc->perp &= 0xfc; + fdc->perp |= (fdc->params[0] & 0x03); + } + fdc->time = 0LL; + return; case 4: - fdd_set_head(fdc.drive, (fdc.params[0] & 4) ? 1 : 0); - break; - - case 5: /*Write data*/ - case 9: /*Write deleted data*/ - fdc_reset_fifo_buf(); - 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]; - fdc_implied_seek(); - fdc.rw_track = fdc.params[1]; - floppy_writesector(fdc.drive, fdc.sector, fdc.params[1], fdc.head, fdc.rate, fdc.params[4]); - floppytime = 0LL; - fdc.written = 0; - ui_sb_update_icon(SB_FLOPPY | fdc.drive, 1); - fdc.pos = 0; - if (fdc.pcjr) - fdc.stat = 0xb0; - else - { - if (fdc.dma) - { - fdc.stat = 0x90; + fdd_set_head(real_drive(fdc, fdc->drive), (fdc->params[0] & 4) ? 1 : 0); + break; + case 5: /*Write data*/ + case 9: /*Write deleted data*/ + fdc_io_command_phase1(fdc, 1); + fdd_writesector(real_drive(fdc, fdc->drive), fdc->sector, fdc->params[1], fdc->head, fdc->rate, fdc->params[4]); + break; + case 0x11: /*Scan equal*/ + case 0x19: /*Scan low or equal*/ + case 0x1D: /*Scan high or equal*/ + fdc_io_command_phase1(fdc, 1); + fdd_comparesector(real_drive(fdc, fdc->drive), fdc->sector, fdc->params[1], fdc->head, fdc->rate, fdc->params[4]); + break; + case 0x16: /*Verify*/ + if (fdc->params[0] & 0x80) + fdc->sc = fdc->params[7]; + case 6: /*Read data*/ + case 0xC: /*Read deleted data*/ + fdc_io_command_phase1(fdc, 0); + fdc_log("Reading sector (drive %i) (%i) (%i %i %i %i) (%i %i %i)\n", fdc->drive, fdc->params[0], fdc->params[1], fdc->params[2], fdc->params[3], fdc->params[4], fdc->params[5], fdc->params[6], fdc->params[7]); + if (((dma_mode(2) & 0x0C) == 0x00) && !(fdc->flags & FDC_FLAG_PCJR) && fdc->dma) { + /* DMA is in verify mode, treat this like a VERIFY command. */ + fdc_log("Verify-mode read!\n"); + fdc->tc = 1; + fdc->deleted |= 2; } - else - { - fdc.stat = 0xb0; - } - } - break; - - case 0x11: /*Scan equal*/ - case 0x19: /*Scan low or equal*/ - case 0x1D: /*Scan high or equal*/ - fdc_reset_fifo_buf(); - 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]; - fdc_implied_seek(); - fdc.rw_track = fdc.params[1]; - floppy_comparesector(fdc.drive, fdc.sector, fdc.params[1], fdc.head, fdc.rate, fdc.params[4]); - floppytime = 0LL; - fdc.written = 0; - ui_sb_update_icon(SB_FLOPPY | fdc.drive, 1); - fdc.pos = 0; - if (fdc.pcjr || !fdc.dma) - { - fdc.stat = 0xb0; - } - else - { - fdc.stat = 0x90; - } - break; - - case 0x16: /*Verify*/ - if (fdc.params[0] & 0x80) fdc.sc = fdc.params[7]; - case 6: /*Read data*/ - case 0xC: /*Read deleted data*/ - fdc_reset_fifo_buf(); - 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]; - fdc_implied_seek(); - fdc.rw_track = fdc.params[1]; - fdc_log("Reading sector (drive %i) (%i) (%i %i %i %i) (%i %i %i)\n", fdc.drive, fdc.params[0], fdc.params[1], fdc.params[2], fdc.params[3], fdc.params[4], fdc.params[5], fdc.params[6], fdc.params[7]); - if (((dma_mode(2) & 0x0C) == 0x00) && !fdc.pcjr && fdc.dma) - { - /* DMA is in verify mode, treat this like a VERIFY command. */ - fdc_log("Verify-mode read!\n"); - fdc.tc = 1; - fdc.deleted |= 2; - } - floppy_readsector(fdc.drive, fdc.sector, fdc.params[1], fdc.head, fdc.rate, fdc.params[4]); - if (fdc.pcjr || !fdc.dma) - { - fdc.stat = 0x70; - } - else - { - fdc.stat = 0x50; - } - floppytime = 0LL; - ui_sb_update_icon(SB_FLOPPY | fdc.drive, 1); - fdc.inread = 1; - break; + fdd_readsector(real_drive(fdc, fdc->drive), fdc->sector, fdc->params[1], fdc->head, fdc->rate, fdc->params[4]); + break; case 7: /*Recalibrate*/ - seek_time_base = fdd_doublestep_40(real_drive(fdc.drive)) ? 10 : 5; - fdc.stat = (1 << real_drive(fdc.drive)) | 0x80; - floppytime = 0LL; - - drive_num = real_drive(fdc.drive); - - /* Three conditions under which the command should fail. */ - if (!fdd_get_flags(drive_num) || (drive_num >= FDD_NUM) || !motoron[drive_num] || fdd_track0(real_drive(drive_num))) - { - if (!fdd_get_flags(drive_num) || (drive_num >= FDD_NUM) || !motoron[drive_num]) - { - fdc.st0 = 0x70 | (fdc.params[0] & 3); - } - else - { - fdc.st0 = 0x20 | (fdc.params[0] & 3); - } - fdc.pcn[fdc.params[0] & 3] = 0; - floppytime = 0LL; - floppyint=-3; - timer_process(); - floppytime = 2048LL * (1LL << TIMER_SHIFT); - timer_update_outstanding(); - break; - } - - if ((real_drive(fdc.drive) != 1) || fdc.drv2en) - { - fdc_seek(fdc.drive, -fdc.max_track); - } - floppytime = ((int64_t) fdc.max_track) * ((int64_t) seek_time_base) * TIMER_USEC; - break; - - case 0x0d: /*Format*/ - fdc_rate(fdc.drive); - fdc.head = (fdc.params[0] & 4) ? 1 : 0; - fdd_set_head(fdc.drive, (fdc.params[0] & 4) ? 1 : 0); - fdc.gap = fdc.params[3]; - fdc.dtl = 4000000; - fdc.format_sectors = fdc.params[2]; - fdc.format_n = fdc.params[1]; - fdc.format_state = 1; - fdc.pos = 0; - fdc.stat = 0x10; - break; - - case 0xf: /*Seek*/ - fdc.stat = (1 << fdc.drive) | 0x80; - fdc.head = (fdc.params[0] & 4) ? 1 : 0; - fdd_set_head(fdc.drive, (fdc.params[0] & 4) ? 1 : 0); - floppytime = 0LL; - - drive_num = real_drive(fdc.drive); - seek_time_base = fdd_doublestep_40(drive_num) ? 10 : 5; - - /* Three conditions under which the command should fail. */ - if (!fdd_get_flags(drive_num) || (drive_num >= FDD_NUM) || !motoron[drive_num]) - { - /* Yes, failed SEEK's still report success, unlike failed RECALIBRATE's. */ - fdc.st0 = 0x20 | (fdc.params[0] & 7); - if (fdc.command & 0x80) - { - if (fdc.command & 0x40) - { - fdc.pcn[fdc.params[0] & 3] += fdc.params[1]; - } + seek_time_base = fdd_doublestep_40(real_drive(fdc, fdc->drive)) ? 10 : 5; + fdc->stat = (1 << real_drive(fdc, fdc->drive)) | 0x80; + fdc->time = 0LL; + drive_num = real_drive(fdc, fdc->drive); + /* Three conditions under which the command should fail. */ + if (!fdd_get_flags(drive_num) || (drive_num >= FDD_NUM) || !motoron[drive_num] || fdd_track0(drive_num)) { + if (!fdd_get_flags(drive_num) || (drive_num >= FDD_NUM) || !motoron[drive_num]) + fdc->st0 = 0x70 | (fdc->params[0] & 3); else - { - fdc.pcn[fdc.params[0] & 3] -= fdc.params[1]; - } - } - else - { - fdc.pcn[fdc.params[0] & 3] = fdc.params[1]; - } - floppytime = 0LL; - floppyint=-3; - timer_process(); - floppytime = 2048LL * (1LL << TIMER_SHIFT); - timer_update_outstanding(); - break; - } - - if (fdc.command & 0x80) - { - if (fdc.params[1]) - { - if (fdc.command & 0x40) - { - /* Relative seek inwards. */ - fdc_seek(fdc.drive, fdc.params[1]); - fdc.pcn[fdc.params[0] & 3] += fdc.params[1]; - } - else - { - /* Relative seek outwards. */ - fdc_seek(fdc.drive, -fdc.params[1]); - fdc.pcn[fdc.params[0] & 3] -= fdc.params[1]; - } - floppytime = ((int64_t) fdc.params[1]) * ((int64_t) seek_time_base) * TIMER_USEC; - } - else - { - floppytime = ((int64_t) seek_time_base) * TIMER_USEC; - - fdc.st0 = 0x20 | (fdc.params[0] & 7); - floppytime = 0LL; - floppyint=-3; + fdc->st0 = 0x20 | (fdc->params[0] & 3); + fdc->pcn[fdc->params[0] & 3] = 0; + fdc->time = 0LL; + fdc->interrupt = -3; timer_process(); - floppytime = 2048LL * (1LL << TIMER_SHIFT); + fdc->time = 2048LL * (1LL << TIMER_SHIFT); timer_update_outstanding(); break; } - } - else - { - fdc_log("Seeking to track %i...\n", fdc.params[1]); - seek_time = ((int) (fdc.params[1] - fdc.pcn[fdc.params[0] & 3])) * seek_time_base * TIMER_USEC; - - if ((fdc.params[1] - fdc.pcn[fdc.params[0] & 3]) == 0) - { - fdc.st0 = 0x20 | (fdc.params[0] & 7); - floppytime = 0LL; - floppyint=-3; + if ((real_drive(fdc, fdc->drive) != 1) || fdc->drv2en) + fdc_seek(fdc, fdc->drive, -fdc->max_track); + fdc->time = ((int64_t) fdc->max_track) * ((int64_t) seek_time_base) * TIMER_USEC; + break; + case 0x0d: /*Format*/ + fdc_rate(fdc, fdc->drive); + fdc->head = (fdc->params[0] & 4) ? 1 : 0; + fdd_set_head(real_drive(fdc, fdc->drive), (fdc->params[0] & 4) ? 1 : 0); + fdc->gap = fdc->params[3]; + fdc->dtl = 4000000; + fdc->format_sectors = fdc->params[2]; + fdc->format_n = fdc->params[1]; + fdc->format_state = 1; + fdc->pos = 0; + fdc->stat = 0x10; + break; + case 0xf: /*Seek*/ + fdc->stat = (1 << fdc->drive) | 0x80; + fdc->head = (fdc->params[0] & 4) ? 1 : 0; + fdd_set_head(real_drive(fdc, fdc->drive), (fdc->params[0] & 4) ? 1 : 0); + fdc->time = 0LL; + drive_num = real_drive(fdc, fdc->drive); + seek_time_base = fdd_doublestep_40(drive_num) ? 10 : 5; + /* Three conditions under which the command should fail. */ + if (!fdd_get_flags(drive_num) || (drive_num >= FDD_NUM) || !motoron[drive_num]) { + /* Yes, failed SEEK's still report success, unlike failed RECALIBRATE's. */ + fdc->st0 = 0x20 | (fdc->params[0] & 7); + if (fdc->command & 0x80) { + if (fdc->command & 0x40) + fdc->pcn[fdc->params[0] & 3] += fdc->params[1]; + else + fdc->pcn[fdc->params[0] & 3] -= fdc->params[1]; + } else + fdc->pcn[fdc->params[0] & 3] = fdc->params[1]; + fdc->time = 0LL; + fdc->interrupt = -3; timer_process(); - floppytime = 2048LL * (1LL << TIMER_SHIFT); + fdc->time = 2048LL * (1LL << TIMER_SHIFT); timer_update_outstanding(); break; } - - fdc_seek(fdc.drive, fdc.params[1] - fdc.pcn[fdc.params[0] & 3]); - fdc.pcn[fdc.params[0] & 3] = fdc.params[1]; - if (seek_time < 0) seek_time = -seek_time; - floppytime = ((int64_t) seek_time); - } - break; - - case 10: /*Read sector ID*/ - fdc_rate(fdc.drive); - floppytime = 0LL; - fdc.head = (fdc.params[0] & 4) ? 1 : 0; - fdd_set_head(fdc.drive, (fdc.params[0] & 4) ? 1 : 0); - if ((real_drive(fdc.drive) != 1) || fdc.drv2en) - { - floppy_readaddress(fdc.drive, fdc.head, fdc.rate); - if (fdc.pcjr || !fdc.dma) - { - fdc.stat = 0x70; + if (fdc->command & 0x80) { + if (fdc->params[1]) { + if (fdc->command & 0x40) { + /* Relative seek inwards. */ + fdc_seek(fdc, fdc->drive, fdc->params[1]); + fdc->pcn[fdc->params[0] & 3] += fdc->params[1]; + } else { + /* Relative seek outwards. */ + fdc_seek(fdc, fdc->drive, -fdc->params[1]); + fdc->pcn[fdc->params[0] & 3] -= fdc->params[1]; + } + fdc->time = ((int64_t) fdc->params[1]) * ((int64_t) seek_time_base) * TIMER_USEC; + } else { + fdc->time = ((int64_t) seek_time_base) * TIMER_USEC; + fdc->st0 = 0x20 | (fdc->params[0] & 7); + fdc->time = 0LL; + fdc->interrupt = -3; + timer_process(); + fdc->time = 2048LL * (1LL << TIMER_SHIFT); + timer_update_outstanding(); + break; + } + } else { + fdc_log("Seeking to track %i...\n", fdc->params[1]); + seek_time = ((int) (fdc->params[1] - fdc->pcn[fdc->params[0] & 3])) * seek_time_base * TIMER_USEC; + if ((fdc->params[1] - fdc->pcn[fdc->params[0] & 3]) == 0) { + fdc->st0 = 0x20 | (fdc->params[0] & 7); + fdc->time = 0LL; + fdc->interrupt = -3; + timer_process(); + fdc->time = 2048LL * (1LL << TIMER_SHIFT); + timer_update_outstanding(); + break; + } + fdc_seek(fdc, fdc->drive, fdc->params[1] - fdc->pcn[fdc->params[0] & 3]); + fdc->pcn[fdc->params[0] & 3] = fdc->params[1]; + if (seek_time < 0) seek_time = -seek_time; + fdc->time = ((int64_t) seek_time); + } + break; + case 10: /*Read sector ID*/ + fdc_rate(fdc, fdc->drive); + fdc->time = 0LL; + fdc->head = (fdc->params[0] & 4) ? 1 : 0; + fdd_set_head(real_drive(fdc, fdc->drive), (fdc->params[0] & 4) ? 1 : 0); + if ((real_drive(fdc, fdc->drive) != 1) || fdc->drv2en) { + fdd_readaddress(real_drive(fdc, fdc->drive), fdc->head, fdc->rate); + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) + fdc->stat = 0x70; + else + fdc->stat = 0x50; } else - { - fdc.stat = 0x50; - } - } - else - fdc_noidam(); - break; - } - } - else - { - fdc.stat = 0x90 | (fdc.stat & 0xf); - } - } - return; - case 7: - if (!AT) return; - fdc.rate=val&3; - - floppy_3f7=val; - return; - } + fdc_noidam(fdc); + break; + } + } else + fdc->stat = 0x90 | (fdc->stat & 0xf); + } + return; + case 7: + if (!(fdc->flags & FDC_FLAG_AT)) + return; + fdc->rate=val&3; + return; + } } -int paramstogo=0; -uint8_t fdc_read(uint16_t addr, void *priv) + +static uint8_t +fdc_read(uint16_t addr, void *priv) { - uint8_t temp; - int drive; - switch (addr&7) - { - case 0: /* STA */ - temp = 0xff; + fdc_t *fdc = (fdc_t *) priv; + uint8_t ret; + int drive; + switch (addr&7) { + case 0: /* STA */ + ret = 0xff; break; - case 1: /* STB */ + case 1: /* STB */ if (is486) - { return 0xff; - } - drive = real_drive(fdc.dor & 3); - if (!fdc.enable_3f1) - { - temp = 0xff; - } - temp = 0x70; - if (drive) - temp &= ~0x40; - else - temp &= ~0x20; - - if (fdc.dor & 0x10) - temp |= 1; - if (fdc.dor & 0x20) - temp |= 2; - break; - case 2: - temp = fdc.dor; + drive = real_drive(fdc, fdc->dor & 3); + if (!fdc->enable_3f1) + ret = 0xff; + ret = 0x70; + if (drive) + ret &= ~0x40; + else + ret &= ~0x20; + + if (fdc->dor & 0x10) + ret |= 1; + if (fdc->dor & 0x20) + ret |= 2; break; - case 3: - drive = real_drive(fdc.dor & 3); - if (fdc.ps1) - { - /* PS/1 Model 2121 seems return drive type in port - * 0x3f3, despite the 82077AA FDC not implementing + case 2: + ret = fdc->dor; + break; + case 3: + drive = real_drive(fdc, fdc->dor & 3); + if (fdc->flags & FDC_FLAG_PS1) { + /* PS/1 Model 2121 seems return drive type in port + * 0x3f3, despite the 82077AA fdc_t not implementing * this. This is presumably implemented outside the - * FDC on one of the motherboard's support chips. + * fdc_t on one of the motherboard's support chips. * * Confirmed: 00=1.44M 3.5 * 10=2.88M 3.5 @@ -1345,951 +1140,975 @@ uint8_t fdc_read(uint16_t addr, void *priv) * * as reported by Configur.exe. */ - if (fdd_is_525(drive)) - temp = 0x20; - else if (fdd_is_ed(drive)) - temp = 0x10; - else - temp = 0x00; - } - else if (!fdc.enh_mode) - temp = 0x20; + if (fdd_is_525(drive)) + ret = 0x20; + else if (fdd_is_ed(drive)) + ret = 0x10; + else + ret = 0x00; + } else if (!fdc->enh_mode) + ret = 0x20; else - { - temp = fdc.rwc[drive] << 4; - } - break; - case 4: /*Status*/ - if (!(fdc.dor & 4) & !fdc.pcjr) - { - temp = 0; + ret = fdc->rwc[drive] << 4; + break; + case 4: /*Status*/ + if (!(fdc->dor & 4) & !(fdc->flags & FDC_FLAG_PCJR)) { + ret = 0; break; } - temp=fdc.stat; - break; - case 5: /*Data*/ - fdc.stat&=~0x80; - if ((fdc.stat & 0xf0) == 0xf0) - { - if (fdc.pcjr || !fdc.fifo) - temp = fdc.dat; + ret = fdc->stat; + break; + case 5: /*Data*/ + fdc->stat&=~0x80; + if ((fdc->stat & 0xf0) == 0xf0) { + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo) + ret = fdc->dat; else - { - temp = fdc_fifo_buf_read(); - } - break; - } - if (paramstogo) - { - paramstogo--; - temp=fdc.res[10 - paramstogo]; - if (!paramstogo) - { - fdc.stat=0x80; - } - else - { - fdc.stat|=0xC0; - } - } - else - { - if (lastbyte) - fdc.stat = 0x80; - lastbyte=0; - temp=fdc.dat; - fdc.data_ready = 0; - } - /* What the heck is this even doing?! */ - /* if (floppyint==0xA) - { - timer_process(); - floppytime = 1024LL * (1LL << TIMER_SHIFT); - timer_update_outstanding(); - } */ - fdc.stat &= 0xf0; - break; - case 7: /*Disk change*/ - drive = real_drive(fdc.dor & 3); - if (fdc.dor & (0x10 << drive)) - temp = (floppy_changed[drive] || drive_empty[drive])?0x80:0; - else - temp = 0; - if (fdc.dskchg_activelow) /*PC2086/3086 seem to reverse this bit*/ - temp ^= 0x80; - temp |= 0x01; - break; - default: - temp=0xFF; - } - fdc_log("Read FDC %04X %02X\n",addr, temp); - return temp; -} - -void fdc_poll_common_finish(int compare, int st5) -{ - fdc_int(); - fdc.fintr = 0; - fdc.stat=0xD0; - fdc.res[4]=(fdd_get_head(real_drive(fdc.drive))?4:0)|fdc.rw_drive; - fdc.res[5]=st5; - fdc.res[6]=0; - if (fdc.wrong_am) - { - fdc.res[6] |= 0x40; - fdc.wrong_am = 0; - } - if (compare == 1) - { - if (!fdc.satisfying_sectors) - { - fdc.res[6] |= 4; + ret = fdc_fifo_buf_read(fdc); + break; } - else if (fdc.satisfying_sectors == (fdc.params[5] << ((fdc.command & 80) ? 1 : 0))) - { - fdc.res[6] |= 8; - } - } - else if (compare == 2) - { - if (fdc.satisfying_sectors & 1) - { - fdc.res[5] |= 0x20; - } - if (fdc.satisfying_sectors & 2) - { - fdc.res[5] |= 0x20; - fdc.res[6] |= 0x20; - } - if (fdc.satisfying_sectors & 4) - { - fdc.res[5] |= 0x04; - } - if (fdc.satisfying_sectors & 8) - { - fdc.res[5] |= 0x04; - fdc.res[6] |= 0x02; - } - if (fdc.satisfying_sectors & 0x10) - { - fdc.res[5] |= 0x04; - fdc.res[6] |= 0x10; - } - } - fdc.res[7]=fdc.rw_track; - fdc.res[8]=fdc.head; - fdc.res[9]=fdc.sector; - fdc.res[10]=fdc.params[4]; - fdc_log("Read/write finish (%02X %02X %02X %02X %02X %02X %02X)\n" , fdc.res[4], fdc.res[5], fdc.res[6], fdc.res[7], fdc.res[8], fdc.res[9], fdc.res[10]); - ui_sb_update_icon(SB_FLOPPY | fdc.drive, 0); - paramstogo=7; -} - -void fdc_poll_readwrite_finish(int compare) -{ - fdc.inread = 0; - floppyint=-2; - - fdc_poll_common_finish(compare, 0); -} - -void fdc_no_dma_end(int compare) -{ - floppytime = 0LL; - - fdc_poll_common_finish(compare, 0x80); -} - -void fdc_callback(void *priv) -{ - int compare = 0; - int drive_num = 0; - int old_sector = 0; - floppytime = 0LL; - switch (floppyint) - { - case -3: /*End of command with interrupt*/ - fdc_int(); - fdc.stat = (fdc.stat & 0xf) | 0x80; - return; - case -2: /*End of command*/ - fdc.stat = (fdc.stat & 0xf) | 0x80; - return; - case -1: /*Reset*/ - fdc_int(); - fdc.fintr = 0; - memset(fdc.pcn, 0, 4 * sizeof(int)); - fdc_reset_stat = 4; - return; - case 1: /*Mode*/ - fdc.stat=0x80; - fdc.densel_force = (fdc.params[2] & 0xC0) >> 6; - return; - - case 2: /*Read track*/ - ui_sb_update_icon(SB_FLOPPY | fdc.drive, 1); - fdc.eot[fdc.drive]--; - fdc.read_track_sector.id.r++; - if (!fdc.eot[fdc.drive] || fdc.tc) - { - fdc_poll_readwrite_finish(2); - return; - } - else - { - floppy_readsector(fdc.drive, SECTOR_NEXT, fdc.rw_track, fdc.head, fdc.rate, fdc.params[4]); - if (fdc.pcjr || !fdc.dma) - { - fdc.stat = 0x70; - } + if (fdc->paramstogo) { + fdc->paramstogo--; + ret = fdc->res[10 - fdc->paramstogo]; + if (!fdc->paramstogo) + fdc->stat=0x80; else - { - fdc.stat = 0x50; - } - } - fdc.inread = 1; - return; - - case 4: /*Sense drive status*/ - fdc.res[10] = (fdc.params[0] & 7) | 0x28; - if ((real_drive(fdc.drive) != 1) || fdc.drv2en) - { - if (fdd_track0(real_drive(fdc.drive))) - fdc.res[10] |= 0x10; - } - if (writeprot[fdc.drive]) - fdc.res[10] |= 0x40; - - fdc.stat = (fdc.stat & 0xf) | 0xd0; - paramstogo = 1; - floppyint = 0; - floppytime = 0LL; - return; - case 5: /*Write data*/ - 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*/ - if ((floppyint == 0x11) || (floppyint == 0x19) || (floppyint == 0x1D)) - { - compare = 1; + fdc->stat|=0xC0; + } else { + if (lastbyte) + fdc->stat = 0x80; + lastbyte=0; + ret = fdc->dat; + fdc->data_ready = 0; } + fdc->stat &= 0xf0; + break; + case 7: /*Disk change*/ + drive = real_drive(fdc, fdc->dor & 3); + if (fdc->dor & (0x10 << drive)) + ret = (fdd_changed[drive] || drive_empty[drive])?0x80:0; else - { - compare = 0; + ret = 0; + if (fdc->flags & FDC_FLAG_DISKCHG_ACTLOW) /*PC2086/3086 seem to reverse this bit*/ + ret ^= 0x80; + ret |= 0x01; + break; + default: + ret = 0xFF; + } + fdc_log("Read FDC %04X %02X\n", addr, ret); + return ret; +} + +static void +fdc_poll_common_finish(fdc_t *fdc, int compare, int st5) +{ + fdc_int(fdc); + fdc->fintr = 0; + fdc->stat = 0xD0; + fdc->res[4] = (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->rw_drive; + fdc->res[5] = st5; + fdc->res[6] = 0; + if (fdc->wrong_am) { + fdc->res[6] |= 0x40; + fdc->wrong_am = 0; + } + if (compare == 1) { + 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; + } else if (compare == 2) { + if (fdc->satisfying_sectors & 1) + fdc->res[5] |= 0x20; + if (fdc->satisfying_sectors & 2) { + fdc->res[5] |= 0x20; + fdc->res[6] |= 0x20; + } + if (fdc->satisfying_sectors & 4) + fdc->res[5] |= 0x04; + if (fdc->satisfying_sectors & 8) { + fdc->res[5] |= 0x04; + fdc->res[6] |= 0x02; + } + if (fdc->satisfying_sectors & 0x10) { + fdc->res[5] |= 0x04; + fdc->res[6] |= 0x10; + } + } + fdc->res[7]=fdc->rw_track; + fdc->res[8]=fdc->head; + fdc->res[9]=fdc->sector; + fdc->res[10]=fdc->params[4]; + fdc_log("Read/write finish (%02X %02X %02X %02X %02X %02X %02X)\n" , fdc->res[4], fdc->res[5], fdc->res[6], fdc->res[7], fdc->res[8], fdc->res[9], fdc->res[10]); + ui_sb_update_icon(SB_FLOPPY | fdc->drive, 0); + fdc->paramstogo = 7; +} + + +static void +fdc_poll_readwrite_finish(fdc_t *fdc, int compare) +{ + fdc->inread = 0; + fdc->interrupt = -2; + + fdc_poll_common_finish(fdc, compare, 0); +} + + +static void +fdc_no_dma_end(fdc_t *fdc, int compare) +{ + fdc->time = 0LL; + + fdc_poll_common_finish(fdc, compare, 0x80); +} + + +static void +fdc_callback(void *priv) +{ + fdc_t *fdc = (fdc_t *) priv; + int compare = 0; + int drive_num = 0; + int old_sector = 0; + fdc->time = 0LL; + switch (fdc->interrupt) { + case -3: /*End of command with interrupt*/ + fdc_int(fdc); + fdc->stat = (fdc->stat & 0xf) | 0x80; + return; + case -2: /*End of command*/ + fdc->stat = (fdc->stat & 0xf) | 0x80; + return; + case -1: /*Reset*/ + fdc_int(fdc); + fdc->fintr = 0; + memset(fdc->pcn, 0, 4 * sizeof(int)); + fdc->reset_stat = 4; + return; + case 1: /*Mode*/ + fdc->stat=0x80; + fdc->densel_force = (fdc->params[2] & 0xC0) >> 6; + return; + case 2: /*Read track*/ + ui_sb_update_icon(SB_FLOPPY | fdc->drive, 1); + fdc->eot[fdc->drive]--; + fdc->read_track_sector.id.r++; + if (!fdc->eot[fdc->drive] || fdc->tc) { + fdc_poll_readwrite_finish(fdc, 2); + return; + } else { + fdd_readsector(real_drive(fdc, fdc->drive), SECTOR_NEXT, fdc->rw_track, fdc->head, fdc->rate, fdc->params[4]); + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) + fdc->stat = 0x70; + else + fdc->stat = 0x50; } - if ((floppyint == 6) || (floppyint == 0xC)) - { - if (fdc.wrong_am && !(fdc.deleted & 0x20)) - { + fdc->inread = 1; + return; + case 4: /*Sense drive status*/ + fdc->res[10] = (fdc->params[0] & 7) | 0x28; + if ((real_drive(fdc, fdc->drive) != 1) || fdc->drv2en) { + if (fdd_track0(real_drive(fdc, fdc->drive))) + fdc->res[10] |= 0x10; + } + if (writeprot[fdc->drive]) + fdc->res[10] |= 0x40; + + fdc->stat = (fdc->stat & 0xf) | 0xd0; + fdc->paramstogo = 1; + fdc->interrupt = 0; + fdc->time = 0LL; + return; + case 5: /*Write data*/ + 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*/ + if ((fdc->interrupt == 0x11) || (fdc->interrupt == 0x19) || (fdc->interrupt == 0x1D)) + compare = 1; + else + compare = 0; + if ((fdc->interrupt == 6) || (fdc->interrupt == 0xC)) { + if (fdc->wrong_am && !(fdc->deleted & 0x20)) { /* Mismatching data address mark and no skip, set TC. */ - fdc.tc = 1; + fdc->tc = 1; } } - old_sector = fdc.sector; - if (fdc.tc) - { + old_sector = fdc->sector; + if (fdc->tc) { /* This is needed so that the correct results are returned in case of TC. */ - if (fdc.sector == fdc.params[5]) - { - if (!(fdc.command & 0x80)) - { - fdc.rw_track++; - fdc.sector = 1; - } - else - { - if (fdc.head) - { - fdc.rw_track++; - } + if (fdc->sector == fdc->params[5]) { + if (!(fdc->command & 0x80)) { + fdc->rw_track++; + fdc->sector = 1; + } else { + if (fdc->head) + fdc->rw_track++; - fdc.head ^= 1; - fdd_set_head(fdc.drive, fdc.head); - fdc.sector = 1; + fdc->head ^= 1; + fdd_set_head(real_drive(fdc, fdc->drive), fdc->head); + fdc->sector = 1; } - } - else - { - fdc.sector++; - } - fdc_poll_readwrite_finish(compare); + } else + fdc->sector++; + fdc_poll_readwrite_finish(fdc, compare); return; } - if ((floppyint == 0x16) && (fdc.params[0] & 0x80)) - { + if ((fdc->interrupt == 0x16) && (fdc->params[0] & 0x80)) { /* VERIFY command, EC set */ - fdc.sc--; - if (!fdc.sc) - { - fdc.sector++; - fdc_poll_readwrite_finish(0); + fdc->sc--; + if (!fdc->sc) { + fdc->sector++; + fdc_poll_readwrite_finish(fdc, 0); return; } /* The rest is processed normally per MT flag and EOT. */ - } - else if ((floppyint == 0x16) && !(fdc.params[0] & 0x80)) - { + } else if ((fdc->interrupt == 0x16) && !(fdc->params[0] & 0x80)) { /* VERIFY command, EC clear */ - if ((fdc.sector == old_sector) && (fdc.head == (fdc.command & 0x80) ? 1 : 0)) - { - fdc.sector++; - fdc_poll_readwrite_finish(0); + if ((fdc->sector == old_sector) && (fdc->head == (fdc->command & 0x80) ? 1 : 0)) { + fdc->sector++; + fdc_poll_readwrite_finish(fdc, 0); return; } } - if (fdc.sector == fdc.params[5]) - { + if (fdc->sector == fdc->params[5]) { /* Reached end of track, MT bit is clear */ - if (!(fdc.command & 0x80)) - { - fdc.rw_track++; - fdc.sector = 1; - if (!fdc.pcjr && fdc.dma && (old_sector == 255)) - { - fdc_no_dma_end(compare); - } + if (!(fdc->command & 0x80)) { + fdc->rw_track++; + fdc->sector = 1; + if (!(fdc->flags & FDC_FLAG_PCJR) && fdc->dma && (old_sector == 255)) + fdc_no_dma_end(fdc, compare); else - { - fdc_poll_readwrite_finish(compare); - } + fdc_poll_readwrite_finish(fdc, compare); return; } /* Reached end of track, MT bit is set, head is 1 */ - if (fdd_get_head(real_drive(fdc.drive)) == 1) - { - fdc.rw_track++; - fdc.sector = 1; - fdc.head &= 0xFE; - fdd_set_head(fdc.drive, 0); - if (!fdc.pcjr && fdc.dma && (old_sector == 255)) - { - fdc_no_dma_end(compare); - } + if (fdd_get_head(real_drive(fdc, fdc->drive)) == 1) { + fdc->rw_track++; + fdc->sector = 1; + fdc->head &= 0xFE; + fdd_set_head(real_drive(fdc, fdc->drive), 0); + if (!(fdc->flags & FDC_FLAG_PCJR) && fdc->dma && (old_sector == 255)) + fdc_no_dma_end(fdc, compare); else - { - fdc_poll_readwrite_finish(compare); - } + fdc_poll_readwrite_finish(fdc, compare); return; } - if ((fdc.command & 0x80) && (fdd_get_head(real_drive(fdc.drive)) == 0)) - { - fdc.sector = 1; - fdc.head |= 1; - fdd_set_head(fdc.drive, 1); + if ((fdc->command & 0x80) && (fdd_get_head(real_drive(fdc, fdc->drive)) == 0)) { + fdc->sector = 1; + fdc->head |= 1; + fdd_set_head(real_drive(fdc, fdc->drive), 1); } - } - else if (fdc.sector < fdc.params[5]) - { - fdc.sector++; - } - ui_sb_update_icon(SB_FLOPPY | fdc.drive, 1); - switch (floppyint) - { + } else if (fdc->sector < fdc->params[5]) + fdc->sector++; + ui_sb_update_icon(SB_FLOPPY | fdc->drive, 1); + switch (fdc->interrupt) { case 5: case 9: - floppy_writesector(fdc.drive, fdc.sector, fdc.rw_track, fdc.head, fdc.rate, fdc.params[4]); - if (fdc.pcjr || !fdc.dma) - { - fdc.stat = 0xb0; - } + fdd_writesector(real_drive(fdc, fdc->drive), fdc->sector, fdc->rw_track, fdc->head, fdc->rate, fdc->params[4]); + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) + fdc->stat = 0xb0; else - { - fdc.stat = 0x90; - } + fdc->stat = 0x90; break; case 6: case 0xC: case 0x16: - floppy_readsector(fdc.drive, fdc.sector, fdc.rw_track, fdc.head, fdc.rate, fdc.params[4]); - if (fdc.pcjr || !fdc.dma) - { - fdc.stat = 0x70; - } + fdd_readsector(real_drive(fdc, fdc->drive), fdc->sector, fdc->rw_track, fdc->head, fdc->rate, fdc->params[4]); + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) + fdc->stat = 0x70; else - { - fdc.stat = 0x50; - } + fdc->stat = 0x50; break; case 0x11: case 0x19: case 0x1D: - floppy_comparesector(fdc.drive, fdc.sector, fdc.rw_track, fdc.head, fdc.rate, fdc.params[4]); - if (fdc.pcjr || !fdc.dma) - { - fdc.stat = 0xb0; - } + fdd_comparesector(real_drive(fdc, fdc->drive), fdc->sector, fdc->rw_track, fdc->head, fdc->rate, fdc->params[4]); + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) + fdc->stat = 0xb0; else - { - fdc.stat = 0x90; - } + fdc->stat = 0x90; break; } - fdc.inread = 1; - return; - - case 7: /*Recalibrate*/ - fdc.pcn[fdc.params[0] & 3] = 0; - drive_num = real_drive(fdc.rw_drive); - fdc.st0 = 0x20 | (fdc.params[0] & 3); - if (!fdd_track0(drive_num)) - { - fdc.st0 |= 0x50; - } - floppyint=-3; - timer_process(); - floppytime = 2048LL * (1LL << TIMER_SHIFT); - timer_update_outstanding(); - fdc.stat = 0x80 | (1 << fdc.drive); - return; - - case 8: /*Sense interrupt status*/ - - fdc.stat = (fdc.stat & 0xf) | 0xd0; - - if (fdc.fintr) - { - fdc.res[9] = fdc.st0; - fdc.fintr = 0; - } - else - { - if (fdc_reset_stat) - { - drive_num = real_drive(4 - fdc_reset_stat); - if ((!fdd_get_flags(drive_num)) || (drive_num >= FDD_NUM)) - { - floppy_stop(drive_num); - fdd_set_head(drive_num, 0); - fdc.res[9] = 0xc0 | (4 - fdc_reset_stat) | (fdd_get_head(drive_num) ? 4 : 0); - } - else - { - fdc.res[9] = 0xc0 | (4 - fdc_reset_stat); - } - - fdc_reset_stat--; - } - } - - fdc.res[10] = fdc.pcn[fdc.res[9] & 3]; - - paramstogo = 2; - floppyint = 0; - floppytime = 0LL; + fdc->inread = 1; return; - - case 0x0d: /*Format track*/ - if (fdc.format_state == 1) - { - fdc.format_state = 2; - timer_process(); - floppytime = 128LL * (1LL << TIMER_SHIFT); - timer_update_outstanding(); - } - else if (fdc.format_state == 2) - { - floppy_format(fdc.drive, fdc.head, fdc.rate, fdc.params[4]); - fdc.format_state = 3; - } - else - { - floppyint=-2; - fdc_int(); - fdc.fintr = 0; - fdc.stat=0xD0; - fdc.res[4] = (fdd_get_head(real_drive(fdc.drive))?4:0)|fdc.drive; - fdc.res[5] = fdc.res[6] = 0; - fdc.res[7] = fdc.pcn[fdc.params[0] & 3]; - fdc.res[8] = fdd_get_head(real_drive(fdc.drive)); - fdc.res[9] = fdc.format_dat[fdc.pos - 2] + 1; - fdc.res[10] = fdc.params[4]; - paramstogo=7; - fdc.format_state = 0; - return; - } - return; - - case 15: /*Seek*/ - drive_num = real_drive(fdc.rw_drive); - fdc.st0 = 0x20 | (fdc.params[0] & 7); - floppyint=-3; + case 7: /*Recalibrate*/ + fdc->pcn[fdc->params[0] & 3] = 0; + drive_num = real_drive(fdc, fdc->rw_drive); + fdc->st0 = 0x20 | (fdc->params[0] & 3); + if (!fdd_track0(drive_num)) + fdc->st0 |= 0x50; + fdc->interrupt = -3; timer_process(); - floppytime = 2048LL * (1LL << TIMER_SHIFT); + fdc->time = 2048LL * (1LL << TIMER_SHIFT); timer_update_outstanding(); - fdc.stat = 0x80 | (1 << fdc.drive); - return; - case 0x0e: /*Dump registers*/ - fdc.stat = (fdc.stat & 0xf) | 0xd0; - fdc.res[1] = fdc.pcn[0]; - fdc.res[2] = fdc.pcn[1]; - fdc.res[3] = fdc.pcn[2]; - fdc.res[4] = fdc.pcn[3]; - fdc.res[5] = fdc.specify[0]; - fdc.res[6] = fdc.specify[1]; - fdc.res[7] = fdc.eot[fdc.drive]; - fdc.res[8] = (fdc.perp & 0x7f) | ((fdc.lock) ? 0x80 : 0); - fdc.res[9] = fdc.config; - fdc.res[10] = fdc.pretrk; - paramstogo = 10; - floppyint=0; - floppytime = 0LL; - return; + fdc->stat = 0x80 | (1 << fdc->drive); + return; + case 8: /*Sense interrupt status*/ + fdc->stat = (fdc->stat & 0xf) | 0xd0; - case 0x10: /*Version*/ - fdc.stat = (fdc.stat & 0xf) | 0xd0; - fdc.res[10] = 0x90; - paramstogo=1; - floppyint=0; - floppytime = 0LL; - return; - - case 0x13: /*Configure*/ - fdc.config = fdc.params[1]; - fdc.pretrk = fdc.params[2]; - fdc.fifo = (fdc.params[1] & 0x20) ? 0 : 1; - fdc.tfifo = (fdc.params[1] & 0xF); - fdc.stat = 0x80; - floppytime = 0LL; - return; - case 0x14: /*Unlock*/ - fdc.lock = 0; - fdc.stat = (fdc.stat & 0xf) | 0xd0; - fdc.res[10] = 0; - paramstogo=1; - floppyint=0; - floppytime = 0LL; - return; - case 0x94: /*Lock*/ - fdc.lock = 1; - fdc.stat = (fdc.stat & 0xf) | 0xd0; - fdc.res[10] = 0x10; - paramstogo=1; - floppyint=0; - floppytime = 0LL; - return; + if (fdc->fintr) { + fdc->res[9] = fdc->st0; + fdc->fintr = 0; + } else { + if (fdc->reset_stat) { + drive_num = real_drive(fdc, 4 - fdc->reset_stat); + if ((!fdd_get_flags(drive_num)) || (drive_num >= FDD_NUM)) { + fdd_stop(drive_num); + fdd_set_head(drive_num, 0); + fdc->res[9] = 0xc0 | (4 - fdc->reset_stat) | (fdd_get_head(drive_num) ? 4 : 0); + } else + fdc->res[9] = 0xc0 | (4 - fdc->reset_stat); - case 0x18: /*NSC*/ - fdc.stat = (fdc.stat & 0xf) | 0xd0; - fdc.res[10] = 0x73; - paramstogo=1; - floppyint=0; - floppytime = 0LL; - return; + fdc->reset_stat--; + } + } - case 0xfc: /*Invalid*/ - fdc.dat = fdc.st0 = 0x80; - fdc.stat = (fdc.stat & 0xf) | 0xd0; - fdc.res[10] = fdc.st0; - paramstogo=1; - floppyint=0; - floppytime = 0LL; - return; - } -} + fdc->res[10] = fdc->pcn[fdc->res[9] & 3]; -void fdc_error(int st5, int st6) -{ - floppytime = 0LL; - - fdc_int(); - fdc.fintr = 0; - fdc.stat=0xD0; - fdc.res[4]=0x40|(fdd_get_head(real_drive(fdc.drive))?4:0)|fdc.rw_drive; - fdc.res[5]=st5; - fdc.res[6]=st6; - fdc_log("FDC Error: %02X %02X %02X\n", fdc.res[4], fdc.res[5], fdc.res[6]); - switch(floppyint) - { - case 0x02: - case 0x05: - case 0x06: - case 0x09: - case 0x0C: - case 0x11: - case 0x16: - case 0x19: - case 0x1D: - fdc.res[7]=fdc.rw_track; - fdc.res[8]=fdc.head; - fdc.res[9]=fdc.sector; - fdc.res[10]=fdc.params[4]; - break; - default: - fdc.res[7]=0; - fdc.res[8]=0; - fdc.res[9]=0; - fdc.res[10]=0; - break; - } - ui_sb_update_icon(SB_FLOPPY | fdc.drive, 0); - paramstogo=7; + fdc->paramstogo = 2; + fdc->interrupt = 0; + fdc->time = 0LL; + return; + case 0x0d: /*Format track*/ + if (fdc->format_state == 1) { + fdc->format_state = 2; + timer_process(); + fdc->time = 128LL * (1LL << TIMER_SHIFT); + timer_update_outstanding(); + } else if (fdc->format_state == 2) { + fdd_format(real_drive(fdc, fdc->drive), fdc->head, fdc->rate, fdc->params[4]); + fdc->format_state = 3; + } else { + fdc->interrupt = -2; + fdc_int(fdc); + fdc->fintr = 0; + fdc->stat = 0xD0; + fdc->res[4] = (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->drive; + fdc->res[5] = fdc->res[6] = 0; + fdc->res[7] = fdc->pcn[fdc->params[0] & 3]; + fdc->res[8] = fdd_get_head(real_drive(fdc, fdc->drive)); + fdc->res[9] = fdc->format_dat[fdc->pos - 2] + 1; + fdc->res[10] = fdc->params[4]; + fdc->paramstogo = 7; + fdc->format_state = 0; + return; + } + return; + case 0x0e: /*Dump registers*/ + fdc->stat = (fdc->stat & 0xf) | 0xd0; + fdc->res[1] = fdc->pcn[0]; + fdc->res[2] = fdc->pcn[1]; + fdc->res[3] = fdc->pcn[2]; + fdc->res[4] = fdc->pcn[3]; + fdc->res[5] = fdc->specify[0]; + fdc->res[6] = fdc->specify[1]; + fdc->res[7] = fdc->eot[fdc->drive]; + fdc->res[8] = (fdc->perp & 0x7f) | ((fdc->lock) ? 0x80 : 0); + fdc->res[9] = fdc->config; + fdc->res[10] = fdc->pretrk; + fdc->paramstogo = 10; + fdc->interrupt = 0; + fdc->time = 0LL; + return; + case 0x0f: /*Seek*/ + drive_num = real_drive(fdc, fdc->rw_drive); + fdc->st0 = 0x20 | (fdc->params[0] & 7); + fdc->interrupt = -3; + timer_process(); + fdc->time = 2048LL * (1LL << TIMER_SHIFT); + timer_update_outstanding(); + fdc->stat = 0x80 | (1 << fdc->drive); + return; + case 0x10: /*Version*/ + case 0x18: /*NSC*/ + fdc->stat = (fdc->stat & 0xf) | 0xd0; + fdc->res[10] = (fdc->interrupt & 0x08) ? 0x73 : 0x90; + fdc->paramstogo = 1; + fdc->interrupt = 0; + fdc->time = 0LL; + return; + case 0x13: /*Configure*/ + fdc->config = fdc->params[1]; + fdc->pretrk = fdc->params[2]; + fdc->fifo = (fdc->params[1] & 0x20) ? 0 : 1; + fdc->tfifo = (fdc->params[1] & 0xF); + fdc->stat = 0x80; + fdc->time = 0LL; + return; + case 0x14: /*Unlock*/ + case 0x94: /*Lock*/ + fdc->lock = (fdc->interrupt & 0x80) ? 1 : 0; + fdc->stat = (fdc->stat & 0xf) | 0xd0; + fdc->res[10] = (fdc->interrupt & 0x80) ? 0x10 : 0x00; + fdc->paramstogo = 1; + fdc->interrupt = 0; + fdc->time = 0LL; + return; + case 0xfc: /*Invalid*/ + fdc->dat = fdc->st0 = 0x80; + fdc->stat = (fdc->stat & 0xf) | 0xd0; + fdc->res[10] = fdc->st0; + fdc->paramstogo = 1; + fdc->interrupt = 0; + fdc->time = 0LL; + return; + } } -void fdc_overrun() +void +fdc_error(fdc_t *fdc, int st5, int st6) { - floppy_stop(fdc.drive); + fdc->time = 0LL; - fdc_error(0x10, 0); + fdc_int(fdc); + fdc->fintr = 0; + fdc->stat = 0xD0; + fdc->res[4] = 0x40 | (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->rw_drive; + fdc->res[5] = st5; + fdc->res[6] = st6; + fdc_log("fdc_t Error: %02X %02X %02X\n", fdc->res[4], fdc->res[5], fdc->res[6]); + switch(fdc->interrupt) { + case 0x02: + case 0x05: + case 0x06: + case 0x09: + case 0x0C: + case 0x11: + case 0x16: + case 0x19: + case 0x1D: + fdc->res[7]=fdc->rw_track; + fdc->res[8]=fdc->head; + fdc->res[9]=fdc->sector; + fdc->res[10]=fdc->params[4]; + break; + default: + fdc->res[7]=0; + fdc->res[8]=0; + fdc->res[9]=0; + fdc->res[10]=0; + break; + } + ui_sb_update_icon(SB_FLOPPY | fdc->drive, 0); + fdc->paramstogo = 7; } -int fdc_is_verify(void) + +void +fdc_overrun(fdc_t *fdc) { - return (fdc.deleted & 2) ? 1 : 0; + fdd_stop(fdc->drive); + + fdc_error(fdc, 0x10, 0); } -int fdc_data(uint8_t data) -{ - int result = 0; - if (fdc.deleted & 2) - { - /* We're in a VERIFY command, so return with 0. */ +int +fdc_is_verify(fdc_t *fdc) +{ + return (fdc->deleted & 2) ? 1 : 0; +} + + +int +fdc_data(fdc_t *fdc, uint8_t data) +{ + int result = 0; + + if (fdc->deleted & 2) { + /* We're in a VERIFY command, so return with 0. */ + return 0; + } + + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) { + if (fdc->tc) return 0; + + if (fdc->data_ready) { + fdc_overrun(fdc); + return -1; } - if (fdc.pcjr || !fdc.dma) - { - if (fdc.tc) - return 0; - - if (fdc.data_ready) - { - fdc_overrun(); - return -1; - } - - if (fdc.pcjr || !fdc.fifo || (fdc.tfifo < 1)) - { - fdc.dat = data; - fdc.data_ready = 1; - fdc.stat = 0xf0; + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo || (fdc->tfifo < 1)) { + fdc->dat = data; + fdc->data_ready = 1; + fdc->stat = 0xf0; + } else { + /* FIFO enabled */ + fdc_fifo_buf_write(fdc, data); + if (fdc->fifobufpos == 0) { + /* We have wrapped around, means FIFO is over */ + fdc->data_ready = 1; + fdc->stat = 0xf0; } - else - { - /* FIFO enabled */ - fdc_fifo_buf_write(data); - if (fdc.fifobufpos == 0) - { - /* We have wrapped around, means FIFO is over */ - fdc.data_ready = 1; - fdc.stat = 0xf0; - } - } - } - else - { - result = dma_channel_write(2, data); + } + } else { + result = dma_channel_write(fdc->dma_ch, data); - if (fdc.tc) - return -1; + if (fdc->tc) + return -1; - if (result & DMA_OVER) - { - fdc.data_ready = 1; - fdc.stat = 0xd0; - fdc.tc = 1; - return -1; - } + if (result & DMA_OVER) { + fdc->data_ready = 1; + fdc->stat = 0xd0; + fdc->tc = 1; + return -1; + } - if (!fdc.fifo || (fdc.tfifo < 1)) - { - fdc.data_ready = 1; - fdc.stat = 0xd0; + if (!fdc->fifo || (fdc->tfifo < 1)) { + fdc->data_ready = 1; + fdc->stat = 0xd0; + } else { + fdc_fifo_buf_advance(fdc); + if (fdc->fifobufpos == 0) { + /* We have wrapped around, means FIFO is over */ + fdc->data_ready = 1; + fdc->stat = 0xd0; } - else - { - fdc_fifo_buf_advance(); - if (fdc.fifobufpos == 0) - { - /* We have wrapped around, means FIFO is over */ - fdc.data_ready = 1; - fdc.stat = 0xd0; - } - } - } - - return 0; + } + } + + return 0; } -void fdc_finishread(void) + +void +fdc_finishread(fdc_t *fdc) { - fdc.inread = 0; + fdc->inread = 0; } -void fdc_track_finishread(int condition) + +void +fdc_track_finishread(fdc_t *fdc, int condition) { - fdc.stat = 0x10; - fdc.satisfying_sectors |= condition; - fdc.inread = 0; - fdc_callback(NULL); + fdc->stat = 0x10; + fdc->satisfying_sectors |= condition; + fdc->inread = 0; + fdc_callback(fdc); } -void fdc_sector_finishcompare(int satisfying) + +void +fdc_sector_finishcompare(fdc_t *fdc, int satisfying) { - fdc.stat = 0x10; - fdc.satisfying_sectors++; - fdc.inread = 0; - fdc_callback(NULL); + fdc->stat = 0x10; + fdc->satisfying_sectors++; + fdc->inread = 0; + fdc_callback(fdc); } -void fdc_sector_finishread(void) + +void +fdc_sector_finishread(fdc_t *fdc) { - fdc.stat = 0x10; - fdc.inread = 0; - fdc_callback(NULL); + fdc->stat = 0x10; + fdc->inread = 0; + fdc_callback(fdc); } + /* There is no sector ID. */ -void fdc_noidam(void) +void +fdc_noidam(fdc_t *fdc) { - fdc_error(1, 0); + fdc_error(fdc, 1, 0); } + /* Sector ID's are there, but there is no sector. */ -void fdc_nosector(void) +void fdc_nosector(fdc_t *fdc) { - fdc_error(4, 0); + fdc_error(fdc, 4, 0); } + /* There is no sector data. */ -void fdc_nodataam(void) +void fdc_nodataam(fdc_t *fdc) { - fdc_error(1, 1); + fdc_error(fdc, 1, 1); } + /* Abnormal termination with both status 1 and 2 set to 0, used when abnormally - terminating the FDC FORMAT TRACK command. */ -void fdc_cannotformat(void) + terminating the fdc_t FORMAT TRACK command. */ +void fdc_cannotformat(fdc_t *fdc) { - fdc_error(0, 0); + fdc_error(fdc, 0, 0); } -void fdc_datacrcerror(void) + +void +fdc_datacrcerror(fdc_t *fdc) { - fdc_error(0x20, 0x20); + fdc_error(fdc, 0x20, 0x20); } -void fdc_headercrcerror(void) + +void +fdc_headercrcerror(fdc_t *fdc) { - fdc_error(0x20, 0); + fdc_error(fdc, 0x20, 0); } -void fdc_wrongcylinder(void) + +void +fdc_wrongcylinder(fdc_t *fdc) { - fdc_error(4, 0x10); + fdc_error(fdc, 4, 0x10); } -void fdc_badcylinder(void) + +void +fdc_badcylinder(fdc_t *fdc) { - fdc_error(4, 0x02); + fdc_error(fdc, 4, 0x02); } -void fdc_writeprotect(void) + +void +fdc_writeprotect(fdc_t *fdc) { - fdc_error(0x02, 0); + fdc_error(fdc, 0x02, 0); } -int fdc_getdata(int last) + +int fdc_getdata(fdc_t *fdc, int last) { - int data; - - if (fdc.pcjr || !fdc.dma) - { - if (fdc.written) - { - fdc_overrun(); - return -1; - } - if (fdc.pcjr || !fdc.fifo) - { - data = fdc.dat; + int data; - if (!last) - fdc.stat = 0xb0; - } - else - { - data = fdc_fifo_buf_read(); - - if (!last && (fdc.fifobufpos == 0)) - fdc.stat = 0xb0; - } - } - else - { - data = dma_channel_read(2); - - if (!fdc.fifo) - { - if (!last) - fdc.stat = 0x90; - } - else - { - fdc_fifo_buf_advance(); - - if (!last && (fdc.fifobufpos == 0)) - fdc.stat = 0x90; - } - - if (data & DMA_OVER) - fdc.tc = 1; - } - - fdc.written = 0; - return data & 0xff; -} - -void fdc_sectorid(uint8_t track, uint8_t side, uint8_t sector, uint8_t size, uint8_t crc1, uint8_t crc2) -{ - fdc_int(); - fdc.stat=0xD0; - fdc.res[4]=(fdd_get_head(real_drive(fdc.drive))?4:0)|fdc.drive; - fdc.res[5]=0; - fdc.res[6]=0; - fdc.res[7]=track; - fdc.res[8]=side; - fdc.res[9]=sector; - fdc.res[10]=size; - ui_sb_update_icon(SB_FLOPPY | fdc.drive, 0); - paramstogo=7; -} - -void fdc_indexpulse(void) -{ - return; -} - -void fdc_hard_reset(void) -{ - int i = 0; - int base_address = fdc.base_address; - - memset(&fdc, 0, sizeof(FDC)); - fdc.dskchg_activelow = 0; - fdc.enable_3f1 = 1; - - fdc_update_is_nsc(0); - fdc_update_enh_mode(0); - fdc_update_densel_polarity(1); - fdc_update_rwc(0, 0); - fdc_update_rwc(1, 0); - fdc_update_rwc(2, 0); - fdc_update_rwc(3, 0); - fdc_update_densel_force(0); - fdc_update_drv2en(1); - - fdc.fifo = 0; - fdc.tfifo = 1; - - fdd_init(); - - if (fdc.pcjr) - { - fdc.dma = 0; - fdc.specify[1] = 1; + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) { + if (fdc->written) { + fdc_overrun(fdc); + return -1; } - else - { - fdc.dma = 1; - fdc.specify[1] = 0; + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo) { + data = fdc->dat; + + if (!last) + fdc->stat = 0xb0; + } else { + data = fdc_fifo_buf_read(fdc); + + if (!last && (fdc->fifobufpos == 0)) + fdc->stat = 0xb0; } - fdc.config = 0x20; - fdc.pretrk = 0; + } else { + data = dma_channel_read(fdc->dma_ch); - swwp = 0; - disable_write = 0; + if (!fdc->fifo) { + if (!last) + fdc->stat = 0x90; + } else { + fdc_fifo_buf_advance(fdc); - fdc_reset(); - - fdc.max_track = 79; - fdc.base_address = base_address; - - for (i = 0; i < FDD_NUM; i++) - { - ui_sb_update_icon(SB_FLOPPY | i, 0); + if (!last && (fdc->fifobufpos == 0)) + fdc->stat = 0x90; } + + if (data & DMA_OVER) + fdc->tc = 1; + } + + fdc->written = 0; + return data & 0xff; } -void fdc_init(void) + +void +fdc_sectorid(fdc_t *fdc, uint8_t track, uint8_t side, uint8_t sector, uint8_t size, uint8_t crc1, uint8_t crc2) { - fdc_hard_reset(); - - timer_add(fdc_callback, &floppytime, &floppytime, NULL); + fdc_int(fdc); + fdc->stat = 0xD0; + fdc->res[4] = (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->drive; + fdc->res[5] = 0; + fdc->res[6] = 0; + fdc->res[7] = track; + fdc->res[8] = side; + fdc->res[9] = sector; + fdc->res[10] = size; + ui_sb_update_icon(SB_FLOPPY | fdc->drive, 0); + fdc->paramstogo = 7; } -void fdc_add(void) + +uint8_t +fdc_get_swwp(fdc_t *fdc) { - io_sethandler(0x03f0, 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL); - io_sethandler(0x03f7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL); - fdc.pcjr = 0; - fdc.ps1 = 0; - fdc.max_track = 79; - fdc.perp = 0; - fdc.base_address = 0x03f0; - fdc_log("FDC Added (%04X)\n", fdc.base_address); + return fdc->swwp; } -void fdc_set_base(int base, int super_io) + +void +fdc_set_swwp(fdc_t *fdc, uint8_t swwp) { - io_sethandler(base + (super_io ? 2 : 0), super_io ? 0x0004 : 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL); - io_sethandler(base + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL); - fdc.base_address = base; - fdc_log("FDC Base address set%s (%04X)\n", super_io ? " for Super I/O" : "", fdc.base_address); + fdc->swwp = swwp; } -void fdc_add_for_superio(void) + +uint8_t +fdc_get_diswr(fdc_t *fdc) { - io_sethandler(0x03f2, 0x0004, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL); - io_sethandler(0x03f7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL); - fdc.pcjr = 0; - fdc.ps1 = 0; - fdc.base_address = 0x03f0; - fdc_log("FDC Added for Super I/O (%04X)\n", fdc.base_address); + if (!fdc) + return 0; + + return fdc->disable_write; } -void fdc_add_pcjr(void) + +void +fdc_set_diswr(fdc_t *fdc, uint8_t diswr) { - io_sethandler(0x00f0, 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL); - timer_add(fdc_watchdog_poll, &fdc.watchdog_timer, &fdc.watchdog_timer, &fdc); - fdc.pcjr = 1; - fdc.ps1 = 0; - fdc.max_track = 79; - fdc.perp = 0; - fdc.base_address = 0x03f0; - fdc_log("FDC Added for PCjr (%04X)\n", fdc.base_address); + fdc->disable_write = diswr; } -void fdc_remove(void) + +uint8_t +fdc_get_swap(fdc_t *fdc) { - fdc_log("FDC Removed (%04X)\n", fdc.base_address); - io_removehandler(fdc.base_address, 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL); - io_removehandler(fdc.base_address + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL); + return fdc->swap; } -void fdc_floppychange_clear(int drive) + +void +fdc_set_swap(fdc_t *fdc, uint8_t swap) { - if (drive < FDD_NUM) - floppy_changed[drive] = 0; + fdc->swap = swap; } -void fdc_set_dskchg_activelow(void) + +void +fdc_set_base(fdc_t *fdc, int base) { - fdc.dskchg_activelow = 1; + int super_io = (fdc->flags & FDC_FLAG_SUPERIO); + + io_sethandler(base + (super_io ? 2 : 0), super_io ? 0x0004 : 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + if (!(fdc->flags & FDC_FLAG_PCJR)) + io_sethandler(base + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + fdc->base_address = base; + fdc_log("fdc_t Base address set%s (%04X)\n", super_io ? " for Super I/O" : "", fdc->base_address); } -void fdc_3f1_enable(int enable) + +void +fdc_remove(fdc_t *fdc) { - fdc.enable_3f1 = enable; + int super_io = (fdc->flags & FDC_FLAG_SUPERIO); + + fdc_log("fdc_t Removed (%04X)\n", fdc->base_address); + io_removehandler(fdc->base_address + (super_io ? 2 : 0), super_io ? 0x0004 : 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + if (!(fdc->flags & FDC_FLAG_PCJR)) + io_removehandler(fdc->base_address + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); } -void fdc_set_ps1(void) + +void +fdc_reset(void *priv) { - fdc.ps1 = 1; + int i = 0; + uint8_t default_rwc; + + fdc_t *fdc = (fdc_t *) priv; + + default_rwc = (fdc->flags & FDC_FLAG_START_RWC_1) ? 1 : 0; + + fdc->flags &= ~FDC_FLAG_DISKCHG_ACTLOW; + fdc->enable_3f1 = 1; + + fdc_update_is_nsc(fdc, 0); + fdc_update_enh_mode(fdc, 0); + fdc_update_densel_polarity(fdc, 1); + fdc_update_densel_force(fdc, 0); + fdc_update_rwc(fdc, 0, default_rwc); + fdc_update_rwc(fdc, 1, default_rwc); + fdc_update_rwc(fdc, 2, default_rwc); + fdc_update_rwc(fdc, 3, default_rwc); + fdc_update_drvrate(fdc, 0, 0); + fdc_update_drvrate(fdc, 1, 0); + fdc_update_drvrate(fdc, 2, 0); + fdc_update_drvrate(fdc, 3, 0); + fdc_update_drv2en(fdc, 1); + + fdc->fifo = 0; + fdc->tfifo = 1; + + if ((fdc->flags & FDC_FLAG_PCJR)) { + fdc->dma = 0; + fdc->specify[1] = 1; + } else { + fdc->dma = 1; + fdc->specify[1] = 0; + } + fdc->config = 0x20; + fdc->pretrk = 0; + + fdc->swwp = 0; + fdc->disable_write = 0; + + fdc_ctrl_reset(fdc); + + fdc->max_track = (fdc->flags & FDC_FLAG_MORE_TRACKS) ? 85 : 79; + + fdc_remove(fdc); + fdc_set_base(fdc, (fdc->flags & FDC_FLAG_PCJR) ? 0x00f0 : 0x03f0); + + current_drive = 0; + + for (i = 0; i < FDD_NUM; i++) + ui_sb_update_icon(SB_FLOPPY | i, 0); } + + +static void +fdc_close(void *priv) +{ + fdc_t *fdc = (fdc_t *) priv; + + fdc_reset(fdc); + + /* Stop timers. */ + fdc->watchdog_timer = 0; + fdc->watchdog_count = 0; + + fdc->time = 0; + + free(fdc); +} + + +static void * +fdc_init(device_t *info) +{ + fdc_t *fdc = (fdc_t *) malloc(sizeof(fdc_t)); + memset(fdc, 0, sizeof(fdc_t)); + + fdc->flags = info->local; + fdc_reset(fdc); + + fdc->irq = 6; + + if (fdc->flags & FDC_FLAG_PCJR) + timer_add(fdc_watchdog_poll, &fdc->watchdog_timer, &fdc->watchdog_timer, fdc); + else + fdc->dma_ch = 2; + + pclog("FDC added: %04X (flags: %08X)\n", fdc->base_address, fdc->flags); + + timer_add(fdc_callback, &fdc->time, &fdc->time, fdc); + + d86f_set_fdc(fdc); + fdi_set_fdc(fdc); + fdd_set_fdc(fdc); + imd_set_fdc(fdc); + img_set_fdc(fdc); + + fdc_reset(fdc); + + return fdc; +} + + +void +fdc_3f1_enable(fdc_t *fdc, int enable) +{ + fdc->enable_3f1 = enable; +} + + +device_t fdc_xt_device = { + "PC/XT Floppy Drive Controller", + 0, + 0, + fdc_init, + fdc_close, + fdc_reset, + NULL, NULL, NULL, NULL +}; + +device_t fdc_xt_amstrad_device = { + "PC/XT Floppy Drive Controller (Amstrad)", + 0, + FDC_FLAG_DISKCHG_ACTLOW, + fdc_init, + fdc_close, + fdc_reset, + NULL, NULL, NULL, NULL +}; + +device_t fdc_pcjr_device = { + "PCjr Floppy Drive Controller", + 0, + FDC_FLAG_PCJR, + fdc_init, + fdc_close, + fdc_reset, + NULL, NULL, NULL, NULL +}; + +device_t fdc_at_device = { + "PC/AT Floppy Drive Controller", + 0, + FDC_FLAG_AT, + fdc_init, + fdc_close, + fdc_reset, + NULL, NULL, NULL, NULL +}; + +device_t fdc_at_actlow_device = { + "PC/AT Floppy Drive Controller (Active low)", + 0, + FDC_FLAG_DISKCHG_ACTLOW | FDC_FLAG_AT, + fdc_init, + fdc_close, + fdc_reset, + NULL, NULL, NULL, NULL +}; + +device_t fdc_at_ps1_device = { + "PC/AT Floppy Drive Controller (PS/1, PS/2 ISA)", + 0, + FDC_FLAG_DISKCHG_ACTLOW | FDC_FLAG_AT | FDC_FLAG_PS1, + fdc_init, + fdc_close, + fdc_reset, + NULL, NULL, NULL, NULL +}; + +device_t fdc_at_smc_device = { + "PC/AT Floppy Drive Controller (SM(s)C FDC37Cxxx)", + 0, + FDC_FLAG_AT | FDC_FLAG_SUPERIO, + fdc_init, + fdc_close, + fdc_reset, + NULL, NULL, NULL, NULL +}; + +device_t fdc_at_winbond_device = { + "PC/AT Floppy Drive Controller (Winbond W83x77F)", + 0, + FDC_FLAG_AT | FDC_FLAG_SUPERIO | FDC_FLAG_START_RWC_1 | FDC_FLAG_MORE_TRACKS, + fdc_init, + fdc_close, + fdc_reset, + NULL, NULL, NULL, NULL +}; + +device_t fdc_at_nsc_device = { + "PC/AT Floppy Drive Controller (NSC PC8730x)", + 0, + FDC_FLAG_AT | FDC_FLAG_MORE_TRACKS | FDC_FLAG_NSC, + fdc_init, + fdc_close, + fdc_reset, + NULL, NULL, NULL, NULL +}; diff --git a/src/floppy/fdc.h b/src/floppy/fdc.h index c9768c94a..ba6fe4ebe 100644 --- a/src/floppy/fdc.h +++ b/src/floppy/fdc.h @@ -9,84 +9,162 @@ * Implementation of the NEC uPD-765 and compatible floppy disk * controller. * - * Version: @(#)fdc.h 1.0.2 2017/09/03 + * Version: @(#)fdc.h 1.0.3 2018/01/16 * * Authors: Sarah Walker, * Miran Grca, - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #ifndef EMU_FDC_H # define EMU_FDC_H -extern void fdc_init(void); -extern void fdc_add(void); -extern void fdc_add_for_superio(void); -extern void fdc_add_pcjr(void); -extern void fdc_add_tandy(void); -extern void fdc_remove(void); -extern void fdc_reset(void); -extern void fdc_poll(void); -extern void fdc_abort(void); -extern void fdc_floppychange_clear(int drive); -extern void fdc_set_dskchg_activelow(void); -extern void fdc_3f1_enable(int enable); -extern void fdc_set_ps1(void); -extern int fdc_get_bit_rate(void); -extern int fdc_get_bitcell_period(void); +#define FDC_FLAG_PCJR 0x01 /* PCjr */ +#define FDC_FLAG_DISKCHG_ACTLOW 0x02 /* Amstrad, PS/1, PS/2 ISA */ +#define FDC_FLAG_AT 0x04 /* AT+, PS/x */ +#define FDC_FLAG_PS1 0x08 /* PS/1, PS/2 ISA */ +#define FDC_FLAG_SUPERIO 0x10 /* Super I/O chips */ +#define FDC_FLAG_START_RWC_1 0x20 /* W83877F, W83977F */ +#define FDC_FLAG_MORE_TRACKS 0x40 /* W83877F, W83977F, PC87306, PC87309 */ +#define FDC_FLAG_NSC 0x80 /* PC87306, PC87309 */ + +typedef struct +{ + uint8_t dor, stat, command, dat, st0, swap; + uint8_t swwp, disable_write; + uint8_t params[256], res[256]; + uint8_t specify[256], format_dat[256]; + uint8_t config, pretrk; + uint8_t fifobuf[16]; + + uint16_t base_address; + + int head, sector, drive, lastdrive; + int pcn[4], eot[256]; + int rw_track, pos; + int pnum, ptot; + int rate, reset_stat; + int lock, perp; + int abort; + int format_state, format_n; + int tc, written; + + int data_ready, inread; + int bitcell_period, enh_mode; + int rwc[4], drvrate[4]; + int boot_drive, dma; + int densel_polarity, densel_force; + int fifo, tfifo; + int fifobufpos, drv2en; + + int gap, dtl; + int enable_3f1, format_sectors; + int max_track, mfm; + int deleted, wrong_am; + int sc, satisfying_sectors; + int fintr, rw_drive; + + int flags, interrupt; + + int irq; /* Should be 6 by default. */ + int dma_ch; /* Should be 2 by default. */ + + int bit_rate; /* Should be 250 at start. */ + int paramstogo; + + sector_id_t read_track_sector; + + int64_t time; + int64_t watchdog_timer, watchdog_count; +} fdc_t; + +extern void fdc_remove(fdc_t *fdc); +extern void fdc_poll(fdc_t *fdc); +extern void fdc_abort(fdc_t *fdc); +extern void fdc_set_dskchg_activelow(fdc_t *fdc); +extern void fdc_3f1_enable(fdc_t *fdc, int enable); +extern int fdc_get_bit_rate(fdc_t *fdc); +extern int fdc_get_bitcell_period(fdc_t *fdc); /* A few functions to communicate between Super I/O chips and the FDC. */ -extern void fdc_update_is_nsc(int is_nsc); -extern void fdc_update_max_track(int max_track); -extern void fdc_update_enh_mode(int enh_mode); -extern int fdc_get_rwc(int drive); -extern void fdc_update_rwc(int drive, int rwc); -extern int fdc_get_boot_drive(void); -extern void fdc_update_boot_drive(int boot_drive); -extern void fdc_update_densel_polarity(int densel_polarity); -extern uint8_t fdc_get_densel_polarity(void); -extern void fdc_update_densel_force(int densel_force); -extern void fdc_update_drvrate(int drive, int drvrate); -extern void fdc_update_drv2en(int drv2en); +extern void fdc_update_enh_mode(fdc_t *fdc, int enh_mode); +extern int fdc_get_rwc(fdc_t *fdc, int drive); +extern void fdc_update_rwc(fdc_t *fdc, int drive, int rwc); +extern int fdc_get_boot_drive(fdc_t *fdc); +extern void fdc_update_boot_drive(fdc_t *fdc, int boot_drive); +extern void fdc_update_densel_polarity(fdc_t *fdc, int densel_polarity); +extern uint8_t fdc_get_densel_polarity(fdc_t *fdc); +extern void fdc_update_densel_force(fdc_t *fdc, int densel_force); +extern void fdc_update_drvrate(fdc_t *fdc, int drive, int drvrate); +extern void fdc_update_drv2en(fdc_t *fdc, int drv2en); -extern void fdc_noidam(void); -extern void fdc_nosector(void); -extern void fdc_nodataam(void); -extern void fdc_cannotformat(void); -extern void fdc_wrongcylinder(void); -extern void fdc_badcylinder(void); +extern void fdc_noidam(fdc_t *fdc); +extern void fdc_nosector(fdc_t *fdc); +extern void fdc_nodataam(fdc_t *fdc); +extern void fdc_cannotformat(fdc_t *fdc); +extern void fdc_wrongcylinder(fdc_t *fdc); +extern void fdc_badcylinder(fdc_t *fdc); +extern void fdc_writeprotect(fdc_t *fdc); +extern void fdc_datacrcerror(fdc_t *fdc); +extern void fdc_headercrcerror(fdc_t *fdc); +extern void fdc_nosector(fdc_t *fdc); -extern sector_id_t fdc_get_read_track_sector(void); -extern int fdc_get_compare_condition(void); -extern int fdc_is_deleted(void); -extern int fdc_is_sk(void); -extern void fdc_set_wrong_am(void); -extern int fdc_get_drive(void); -extern int fdc_get_perp(void); -extern int fdc_get_format_n(void); -extern int fdc_is_mfm(void); -extern double fdc_get_hut(void); -extern double fdc_get_hlt(void); -extern void fdc_request_next_sector_id(void); -extern void fdc_stop_id_request(void); -extern int fdc_get_gap(void); -extern int fdc_get_gap2(int drive); -extern int fdc_get_dtl(void); -extern int fdc_get_format_sectors(void); +extern int real_drive(fdc_t *fdc, int drive); -extern void fdc_finishcompare(int satisfying); -extern void fdc_finishread(void); -extern void fdc_sector_finishcompare(int satisfying); -extern void fdc_sector_finishread(void); -extern void fdc_track_finishread(int condition); -extern int fdc_is_verify(void); +extern sector_id_t fdc_get_read_track_sector(fdc_t *fdc); +extern int fdc_get_compare_condition(fdc_t *fdc); +extern int fdc_is_deleted(fdc_t *fdc); +extern int fdc_is_sk(fdc_t *fdc); +extern void fdc_set_wrong_am(fdc_t *fdc); +extern int fdc_get_drive(fdc_t *fdc); +extern int fdc_get_perp(fdc_t *fdc); +extern int fdc_get_format_n(fdc_t *fdc); +extern int fdc_is_mfm(fdc_t *fdc); +extern double fdc_get_hut(fdc_t *fdc); +extern double fdc_get_hlt(fdc_t *fdc); +extern void fdc_request_next_sector_id(fdc_t *fdc); +extern void fdc_stop_id_request(fdc_t *fdc); +extern int fdc_get_gap(fdc_t *fdc); +extern int fdc_get_gap2(fdc_t *fdc, int drive); +extern int fdc_get_dtl(fdc_t *fdc); +extern int fdc_get_format_sectors(fdc_t *fdc); +extern uint8_t fdc_get_swwp(fdc_t *fdc); +extern void fdc_set_swwp(fdc_t *fdc, uint8_t swwp); +extern uint8_t fdc_get_diswr(fdc_t *fdc); +extern void fdc_set_diswr(fdc_t *fdc, uint8_t diswr); +extern uint8_t fdc_get_swap(fdc_t *fdc); +extern void fdc_set_swap(fdc_t *fdc, uint8_t swap); -extern int real_drive(int drive); -extern void fdc_overrun(void); -extern void fdc_set_base(int base, int super_io); -extern int fdc_ps1_525(void); -extern void fdc_hard_reset(void); +extern void fdc_finishcompare(fdc_t *fdc, int satisfying); +extern void fdc_finishread(fdc_t *fdc); +extern void fdc_sector_finishcompare(fdc_t *fdc, int satisfying); +extern void fdc_sector_finishread(fdc_t *fdc); +extern void fdc_track_finishread(fdc_t *fdc, int condition); +extern int fdc_is_verify(fdc_t *fdc); + +extern void fdc_overrun(fdc_t *fdc); +extern void fdc_set_base(fdc_t *fdc, int base); +extern int fdc_getdata(fdc_t *fdc, int last); +extern int fdc_data(fdc_t *fdc, uint8_t data); + +extern void fdc_sectorid(fdc_t *fdc, uint8_t track, uint8_t side, uint8_t sector, uint8_t size, uint8_t crc1, uint8_t crc2); + +extern void fdc_reset(void *priv); + +extern uint8_t fdc_ps1_525(void); + +#ifdef EMU_DEVICE_H +extern device_t fdc_xt_device; +extern device_t fdc_xt_amstrad_device; +extern device_t fdc_pcjr_device; +extern device_t fdc_at_device; +extern device_t fdc_at_actlow_device; +extern device_t fdc_at_ps1_device; +extern device_t fdc_at_smc_device; +extern device_t fdc_at_winbond_device; +extern device_t fdc_at_nsc_device; +#endif #endif /*EMU_FDC_H*/ diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index a4fb557f9..85975efdc 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -8,22 +8,107 @@ * * Implementation of the floppy drive emulation. * - * Version: @(#)fdd.c 1.0.5 2017/11/04 + * Version: @(#)fdd.c 1.0.6 2018/01/16 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include #include #include #include "../86box.h" -#include "floppy.h" -#include "fdc.h" +#include "../machine/machine.h" +#include "../mem.h" +#include "../rom.h" +#include "../config.h" +#include "../timer.h" +#include "../plat.h" +#include "../ui.h" #include "fdd.h" +#include "fdd_86f.h" +#include "fdd_fdi.h" +#include "fdd_imd.h" +#include "fdd_img.h" +#include "fdd_json.h" +#include "fdd_td0.h" +#include "fdc.h" + + +extern int driveempty[4]; + +wchar_t floppyfns[4][512]; + +int64_t fdd_poll_time[FDD_NUM] = { 16LL, 16LL, 16LL, 16LL }; + +int fdd_cur_track[FDD_NUM]; +int writeprot[FDD_NUM], fwriteprot[FDD_NUM]; + +DRIVE drives[FDD_NUM]; +int drive_type[FDD_NUM]; + +int curdrive = 0; + +int defaultwriteprot = 0; + +int fdc_ready; + +int drive_empty[FDD_NUM] = {1, 1, 1, 1}; +int fdd_changed[FDD_NUM]; + +int motorspin; +int64_t motoron[FDD_NUM]; + +int fdc_indexcount = 52; + +fdc_t *fdd_fdc; + + +static struct +{ + wchar_t *ext; + void (*load)(int drive, wchar_t *fn); + void (*close)(int drive); + int size; +} loaders[]= +{ + {L"001", img_load, img_close, -1}, + {L"002", img_load, img_close, -1}, + {L"003", img_load, img_close, -1}, + {L"004", img_load, img_close, -1}, + {L"005", img_load, img_close, -1}, + {L"006", img_load, img_close, -1}, + {L"007", img_load, img_close, -1}, + {L"008", img_load, img_close, -1}, + {L"009", img_load, img_close, -1}, + {L"010", img_load, img_close, -1}, + {L"12", img_load, img_close, -1}, + {L"144", img_load, img_close, -1}, + {L"360", img_load, img_close, -1}, + {L"720", img_load, img_close, -1}, + {L"86F", d86f_load, d86f_close, -1}, + {L"BIN", img_load, img_close, -1}, + {L"CQ", img_load, img_close, -1}, + {L"CQM", img_load, img_close, -1}, + {L"DSK", img_load, img_close, -1}, + {L"FDI", fdi_load, fdi_close, -1}, + {L"FDF", img_load, img_close, -1}, + {L"FLP", img_load, img_close, -1}, + {L"HDM", img_load, img_close, -1}, + {L"IMA", img_load, img_close, -1}, + {L"IMD", imd_load, imd_close, -1}, + {L"IMG", img_load, img_close, -1}, + {L"JSON", json_load, json_close, -1}, + {L"TD0", td0_load, td0_close, -1}, + {L"VFD", img_load, img_close, -1}, + {L"XDF", img_load, img_close, -1}, + {0,0,0} +}; + +static int driveloaders[4]; typedef struct { @@ -120,8 +205,6 @@ static struct } }; -int fdd_swap = 0; - char *fdd_getname(int type) { return drive_types[type].name; @@ -146,10 +229,15 @@ int fdd_get_from_internal_name(char *s) return 0; } +/* This is needed for the dump as 86F feature. */ +void fdd_do_seek(int drive, int track) +{ + if (drives[drive].seek) + drives[drive].seek(drive, fdd[drive].track); +} + void fdd_forced_seek(int drive, int track_diff) { - drive = real_drive(drive); - fdd[drive].track += track_diff; if (fdd[drive].track < 0) @@ -158,19 +246,13 @@ void fdd_forced_seek(int drive, int track_diff) if (fdd[drive].track > drive_types[fdd[drive].type].max_track) fdd[drive].track = drive_types[fdd[drive].type].max_track; - floppy_seek(drive, fdd[drive].track); - floppytime = 5000; + fdd_do_seek(drive, fdd[drive].track); } void fdd_seek(int drive, int track_diff) { - drive = real_drive(drive); - if (!track_diff) - { - floppytime = 5000; return; - } fdd[drive].track += track_diff; @@ -180,22 +262,20 @@ void fdd_seek(int drive, int track_diff) if (fdd[drive].track > drive_types[fdd[drive].type].max_track) fdd[drive].track = drive_types[fdd[drive].type].max_track; - fdc_floppychange_clear(drive); - floppy_seek(drive, fdd[drive].track); - floppytime = 5000; + fdd_changed[drive] = 0; + + fdd_do_seek(drive, fdd[drive].track); } int fdd_track0(int drive) { - drive = real_drive(drive); - /* If drive is disabled, TRK0 never gets set. */ if (!drive_types[fdd[drive].type].max_track) return 0; return !fdd[drive].track; } -int fdd_track(int drive) +int fdd_current_track(int drive) { return fdd[drive].track; } @@ -219,12 +299,10 @@ void fdd_set_densel(int densel) int fdd_getrpm(int drive) { - int hole = floppy_hole(drive); + int hole = fdd_hole(drive); int densel = 0; - drive = real_drive(drive); - densel = fdd[drive].densel; if (drive_types[fdd[drive].type].flags & FLAG_INVERT_DENSEL) @@ -241,7 +319,7 @@ int fdd_getrpm(int drive) } else { - /* floppy_hole(drive) returns 0 for double density media, 1 for high density, and 2 for extended density. */ + /* fdd_hole(drive) returns 0 for double density media, 1 for high density, and 2 for extended density. */ if (hole == 1) { return densel ? 300 : 360; @@ -253,16 +331,9 @@ int fdd_getrpm(int drive) } } -void fdd_setswap(int swap) -{ - fdd_swap = swap ? 1 : 0; -} - int fdd_can_read_medium(int drive) { - int hole = floppy_hole(drive); - - drive = real_drive(drive); + int hole = fdd_hole(drive); hole = 1 << (hole + 3); @@ -316,7 +387,6 @@ int fdd_is_double_sided(int drive) void fdd_set_head(int drive, int head) { - drive = real_drive(drive); fdd[drive].head = head; } @@ -357,6 +427,279 @@ int fdd_get_densel(int drive) } } -void fdd_init() +void fdd_load(int drive, wchar_t *fn) { + int c = 0, size; + wchar_t *p; + FILE *f; + if (!fn) return; + p = plat_get_extension(fn); + if (!p) return; + f = plat_fopen(fn, L"rb"); + if (!f) return; + fseek(f, -1, SEEK_END); + size = ftell(f) + 1; + fclose(f); + while (loaders[c].ext) + { + if (!wcscasecmp(p, loaders[c].ext) && (size == loaders[c].size || loaders[c].size == -1)) + { + driveloaders[drive] = c; + memcpy(floppyfns[drive], fn, (wcslen(fn) << 1) + 2); + loaders[c].load(drive, floppyfns[drive]); + drive_empty[drive] = 0; + fdd_forced_seek(drive, 0); + fdd_changed[drive] = 1; + return; + } + c++; + } + pclog("Couldn't load %ls %s\n",fn,p); + drive_empty[drive] = 1; + fdd_set_head(drive, 0); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + ui_sb_update_icon_state(drive, 1); +} + +void fdd_close(int drive) +{ + if (loaders[driveloaders[drive]].close) loaders[driveloaders[drive]].close(drive); + drive_empty[drive] = 1; + fdd_set_head(drive, 0); + floppyfns[drive][0] = 0; + drives[drive].hole = NULL; + drives[drive].poll = NULL; + 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].byteperiod = NULL; + drives[drive].stop = NULL; + ui_sb_update_icon_state(drive, 1); +} + +int fdd_notfound = 0; +static int fdd_period = 32; + +int fdd_hole(int drive) +{ + if (drives[drive].hole) + { + return drives[drive].hole(drive); + } + else + { + return 0; + } +} + +double fdd_byteperiod(int drive) +{ + if (drives[drive].byteperiod) + { + return drives[drive].byteperiod(drive); + } + else + { + return 32.0; + } +} + +double fdd_real_period(int drive) +{ + double ddbp; + double dusec; + + ddbp = fdd_byteperiod(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 (fdd_get_turbo(drive)) + { + return (32.0 * dusec); + } + + if (romset == ROM_MRTHOR) + { + return (ddbp * dusec) / 4.0; + } + else + { + return (ddbp * dusec); + } +} + +void fdd_poll(int drive) +{ + if (drive >= FDD_NUM) + { + fatal("Attempting to poll floppy drive %i that is not supposed to be there\n", drive); + } + + fdd_poll_time[drive] += (int64_t) fdd_real_period(drive); + + if (drives[drive].poll) + drives[drive].poll(drive); + + if (fdd_notfound) + { + fdd_notfound--; + if (!fdd_notfound) + fdc_noidam(fdd_fdc); + } +} + +void fdd_poll_0(void *priv) +{ + fdd_poll(0); +} + +void fdd_poll_1(void *priv) +{ + fdd_poll(1); +} + +void fdd_poll_2(void *priv) +{ + fdd_poll(2); +} + +void fdd_poll_3(void *priv) +{ + fdd_poll(3); +} + +int fdd_get_bitcell_period(int rate) +{ + int bit_rate = 250; + + switch (rate) + { + case 0: /*High density*/ + bit_rate = 500; + break; + case 1: /*Double density (360 rpm)*/ + bit_rate = 300; + break; + case 2: /*Double density*/ + bit_rate = 250; + break; + case 3: /*Extended density*/ + bit_rate = 1000; + break; + } + + return 1000000 / bit_rate*2; /*Bitcell period in ns*/ +} + + +void fdd_set_rate(int drive, int drvden, int rate) +{ + switch (rate) + { + case 0: /*High density*/ + fdd_period = 16; + break; + case 1: + switch(drvden) + { + case 0: /*Double density (360 rpm)*/ + fdd_period = 26; + break; + case 1: /*High density (360 rpm)*/ + fdd_period = 16; + break; + case 2: + fdd_period = 4; + break; + } + case 2: /*Double density*/ + fdd_period = 32; + break; + case 3: /*Extended density*/ + fdd_period = 8; + break; + } +} + +void fdd_reset() +{ + curdrive = 0; + fdd_period = 32; + timer_add(fdd_poll_0, &(fdd_poll_time[0]), &(motoron[0]), NULL); + timer_add(fdd_poll_1, &(fdd_poll_time[1]), &(motoron[1]), NULL); + timer_add(fdd_poll_2, &(fdd_poll_time[2]), &(motoron[2]), NULL); + timer_add(fdd_poll_3, &(fdd_poll_time[3]), &(motoron[3]), NULL); +} + +int oldtrack[FDD_NUM] = {0, 0, 0, 0}; + +void fdd_readsector(int drive, int sector, int track, int side, int density, int sector_size) +{ + if (drives[drive].readsector) + drives[drive].readsector(drive, sector, track, side, density, sector_size); + else + fdd_notfound = 1000; +} + +void fdd_writesector(int drive, int sector, int track, int side, int density, int sector_size) +{ + if (drives[drive].writesector) + drives[drive].writesector(drive, sector, track, side, density, sector_size); + else + fdd_notfound = 1000; +} + +void fdd_comparesector(int drive, int sector, int track, int side, int density, int sector_size) +{ + if (drives[drive].comparesector) + drives[drive].comparesector(drive, sector, track, side, density, sector_size); + else + fdd_notfound = 1000; +} + +void fdd_readaddress(int drive, int side, int density) +{ + if (drives[drive].readaddress) + drives[drive].readaddress(drive, side, density); +} + +void fdd_format(int drive, int side, int density, uint8_t fill) +{ + if (drives[drive].format) + drives[drive].format(drive, side, density, fill); + else + fdd_notfound = 1000; +} + +void fdd_stop(int drive) +{ + if (drives[drive].stop) + drives[drive].stop(drive); +} + +void fdd_set_fdc(void *fdc) +{ + fdd_fdc = (fdc_t *) fdc; +} + +void fdd_init(void) +{ + drives[0].poll = drives[1].poll = drives[2].poll = drives[3].poll = 0; + drives[0].seek = drives[1].seek = drives[2].seek = drives[3].seek = 0; + drives[0].readsector = drives[1].readsector = drives[2].readsector = drives[3].readsector = 0; + fdd_reset(); + + img_init(); + d86f_init(); + td0_init(); + imd_init(); + + fdd_load(0, floppyfns[0]); + fdd_load(1, floppyfns[1]); + fdd_load(2, floppyfns[2]); + fdd_load(3, floppyfns[3]); } diff --git a/src/floppy/fdd.h b/src/floppy/fdd.h index 627317ffc..6ca86ed16 100644 --- a/src/floppy/fdd.h +++ b/src/floppy/fdd.h @@ -8,18 +8,19 @@ * * Implementation of the floppy drive emulation. * - * Version: @(#)fdd.h 1.0.3 2017/10/01 + * Version: @(#)fdd.h 1.0.4 2018/01/16 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #ifndef EMU_FDD_H # define EMU_FDD_H +#define FDD_NUM 4 #define SEEK_RECALIBRATE -999 @@ -30,6 +31,7 @@ extern "C" { extern int fdd_swap; +extern void fdd_do_seek(int drive, int track); extern void fdd_forced_seek(int drive, int track_diff); extern void fdd_seek(int drive, int track_diff); extern int fdd_track0(int drive); @@ -52,18 +54,225 @@ extern void fdd_set_type(int drive, int type); extern int fdd_get_type(int drive); extern int fdd_get_flags(int drive); - -extern void fdd_init(void); extern int fdd_get_densel(int drive); -extern void fdd_setswap(int swap); - extern char *fdd_getname(int type); extern char *fdd_get_internal_name(int type); extern int fdd_get_from_internal_name(char *s); -extern int fdd_track(int drive); +extern int fdd_current_track(int drive); + + +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 side, int density); + void (*format)(int drive, int side, int density, uint8_t fill); + int (*hole)(int drive); + double (*byteperiod)(int drive); + void (*stop)(int drive); + void (*poll)(int drive); +} DRIVE; + + +extern DRIVE drives[FDD_NUM]; +extern wchar_t floppyfns[FDD_NUM][512]; +extern int driveempty[FDD_NUM]; +extern int64_t fdd_poll_time[FDD_NUM]; +extern int ui_writeprot[FDD_NUM]; + +extern int curdrive; + +extern int fdd_time; +extern int64_t floppytime; + + +extern void fdd_load(int drive, wchar_t *fn); +extern void fdd_new(int drive, char *fn); +extern void fdd_close(int drive); +extern void fdd_init(void); +extern void fdd_reset(void); +extern void fdd_poll(int drive); +extern void fdd_poll_0(void* priv); +extern void fdd_poll_1(void* priv); +extern void fdd_poll_2(void* priv); +extern void fdd_poll_3(void* priv); +extern void fdd_seek(int drive, int track); +extern void fdd_readsector(int drive, int sector, int track, + int side, int density, int sector_size); +extern void fdd_writesector(int drive, int sector, int track, + int side, int density, int sector_size); +extern void fdd_comparesector(int drive, int sector, int track, + int side, int density, int sector_size); +extern void fdd_readaddress(int drive, int side, int density); +extern void fdd_format(int drive, int side, int density, uint8_t fill); +extern int fdd_hole(int drive); +extern double fdd_byteperiod(int drive); +extern void fdd_stop(int drive); +extern int fdd_empty(int drive); +extern void fdd_set_rate(int drive, int drvden, int rate); + +extern int motorspin; +extern int64_t motoron[FDD_NUM]; + +extern int swwp; +extern int disable_write; + +extern int defaultwriteprot; + +extern int writeprot[FDD_NUM], fwriteprot[FDD_NUM]; +extern int fdd_cur_track[FDD_NUM]; +extern int fdd_changed[FDD_NUM]; +extern int drive_empty[FDD_NUM]; +extern int drive_type[FDD_NUM]; + +/*Used in the Read A Track command. Only valid for fdd_readsector(). */ +#define SECTOR_FIRST -2 +#define SECTOR_NEXT -1 + +#if 0 +/* Bits 0-3 define byte type, bit 5 defines whether it is a per-track (0) or per-sector (1) byte, if bit 7 is set, the byte is the index hole. */ +#define BYTE_GAP0 0x00 +#define BYTE_GAP1 0x10 +#define BYTE_GAP4 0x20 +#define BYTE_GAP2 0x40 +#define BYTE_GAP3 0x50 +#define BYTE_I_SYNC 0x01 +#define BYTE_ID_SYNC 0x41 +#define BYTE_DATA_SYNC 0x51 +#define BYTE_IAM_SYNC 0x02 +#define BYTE_IDAM_SYNC 0x42 +#define BYTE_DATAAM_SYNC 0x52 +#define BYTE_IAM 0x03 +#define BYTE_IDAM 0x43 +#define BYTE_DATAAM 0x53 +#define BYTE_ID 0x44 +#define BYTE_DATA 0x54 +#define BYTE_ID_CRC 0x45 +#define BYTE_DATA_CRC 0x55 + +#define BYTE_IS_FUZZY 0x80 +#define BYTE_INDEX_HOLE 0x80 /* 1 = index hole, 0 = regular byte */ +#define BYTE_IS_SECTOR 0x40 /* 1 = per-sector, 0 = per-track */ +#define BYTE_IS_POST_TRACK 0x20 /* 1 = after all sectors, 0 = before or during all sectors */ +#define BYTE_IS_DATA 0x10 /* 1 = data, 0 = id */ +#define BYTE_TYPE 0x0F /* 5 = crc, 4 = data, 3 = address mark, 2 = address mark sync, 1 = sync, 0 = gap */ + +#define BYTE_TYPE_GAP 0x00 +#define BYTE_TYPE_SYNC 0x01 +#define BYTE_TYPE_AM_SYNC 0x02 +#define BYTE_TYPE_AM 0x03 +#define BYTE_TYPE_DATA 0x04 +#define BYTE_TYPE_CRC 0x05 +#endif + +typedef union { + uint16_t word; + uint8_t bytes[2]; +} crc_t; + +void fdd_calccrc(uint8_t byte, crc_t *crc_var); + +typedef struct +{ + uint16_t (*disk_flags)(int drive); + uint16_t (*side_flags)(int drive); + void (*writeback)(int drive); + void (*set_sector)(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n); + uint8_t (*read_data)(int drive, int side, uint16_t pos); + void (*write_data)(int drive, int side, uint16_t pos, uint8_t data); + int (*format_conditions)(int drive); + int32_t (*extra_bit_cells)(int drive, int side); + uint16_t* (*encoded_data)(int drive, int side); + void (*read_revolution)(int drive); + uint32_t (*index_hole_pos)(int drive, int side); + uint32_t (*get_raw_size)(int drive, int side); + uint8_t check_crc; +} d86f_handler_t; + +d86f_handler_t d86f_handler[FDD_NUM]; + +void d86f_common_handlers(int drive); + +int d86f_is_40_track(int drive); + +void d86f_reset_index_hole_pos(int drive, int side); + +uint16_t d86f_prepare_pretrack(int drive, int side, int iso); +uint16_t d86f_prepare_sector(int drive, int side, int prev_pos, uint8_t *id_buf, uint8_t *data_buf, int data_len, int gap2, int gap3, int deleted, int bad_crc); + +extern int gap3_sizes[5][8][48]; + +void null_writeback(int drive); +void null_write_data(int drive, int side, uint16_t pos, uint8_t data); +int null_format_conditions(int drive); +void d86f_unregister(int drive); + +extern uint8_t dmf_r[21]; +extern uint8_t xdf_physical_sectors[2][2]; +extern uint8_t xdf_gap3_sizes[2][2]; +extern uint16_t xdf_trackx_spos[2][8]; + +typedef struct +{ + uint8_t h; + uint8_t r; +} xdf_id_t; + +typedef union +{ + uint16_t word; + xdf_id_t id; +} xdf_sector_t; + +extern xdf_sector_t xdf_img_layout[2][2][46]; +extern xdf_sector_t xdf_disk_layout[2][2][38]; + +uint32_t td0_get_raw_tsize(int side_flags, int slower_rpm); + +void d86f_set_track_pos(int drive, uint32_t track_pos); + +int32_t null_extra_bit_cells(int drive, int side); +uint16_t* common_encoded_data(int drive, int side); + +void common_read_revolution(int drive); +void null_set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n); + +uint32_t null_index_hole_pos(int drive, int side); + +uint32_t common_get_raw_size(int drive, int side); + +typedef struct +{ + uint8_t c; + uint8_t h; + uint8_t r; + uint8_t n; +} sector_id_fields_t; + +typedef union +{ + uint32_t dword; + uint8_t byte_array[4]; + 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); + +void d86f_set_fdc(void *fdc); +void fdi_set_fdc(void *fdc); +void fdd_set_fdc(void *fdc); +void imd_set_fdc(void *fdc); +void img_set_fdc(void *fdc); + +extern void d86f_set_cur_track(int drive, int track); +extern void d86f_zero_track(int drive); #ifdef __cplusplus } diff --git a/src/floppy/floppy_86f.c b/src/floppy/fdd_86f.c similarity index 92% rename from src/floppy/floppy_86f.c rename to src/floppy/fdd_86f.c index 9cecc3066..4804f9bcf 100644 --- a/src/floppy/floppy_86f.c +++ b/src/floppy/fdd_86f.c @@ -10,10 +10,10 @@ * data in the form of FM/MFM-encoded transitions) which also * forms the core of the emulator's floppy disk emulation. * - * Version: @(#)floppy_86f.c 1.0.12 2017/11/24 + * Version: @(#)fdd_86f.c 1.0.13 2018/01/16 * * Author: Miran Grca, - * Copyright 2016,2017 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -30,10 +30,9 @@ #include "../random.h" #include "../plat.h" #include "../ui.h" -#include "floppy.h" -#include "fdc.h" #include "fdd.h" -#include "floppy_86f.h" +#include "fdc.h" +#include "fdd_86f.h" #define CHUNK 16384 @@ -191,6 +190,10 @@ typedef union { Bits 10, 9 Zone type (3 = Commodore 64 zoned, 2 = Apple zoned, 1 = Pre-Apple zoned #2, 0 = Pre-Apple zoned #1) Bit 11 Data and surface bits are stored in reverse byte endianness */ + +static fdc_t *d86f_fdc; + + #pragma pack(push,1) struct { @@ -618,7 +621,7 @@ int d86f_valid_bit_rate(int drive) { int rate = 0; int hole = 0; - rate = fdc_get_bit_rate(); + rate = fdc_get_bit_rate(d86f_fdc); hole = (d86f_handler[drive].disk_flags(drive) & 6) >> 1; switch (hole) { @@ -689,9 +692,9 @@ uint32_t d86f_get_data_len(int drive) } else { - if (fdc_get_dtl() < 128) + if (fdc_get_dtl(d86f_fdc) < 128) { - return fdc_get_dtl(); + return fdc_get_dtl(d86f_fdc); } else { @@ -813,8 +816,8 @@ int d86f_can_format(int drive) { int temp; temp = !writeprot[drive]; - temp = temp && !swwp; - temp = temp && fdd_can_read_medium(real_drive(drive)); + temp = temp && !fdc_get_swwp(d86f_fdc); + temp = temp && fdd_can_read_medium(real_drive(d86f_fdc, drive)); temp = temp && d86f_handler[drive].format_conditions(drive); /* Allows proxied formats to add their own extra conditions to formatting. */ temp = temp && !d86f_wrong_densel(drive); return temp; @@ -893,16 +896,16 @@ static int d86f_get_bitcell_period(int drive) if (!mfm) rate /= 2.0; size = (size * 250.0) / rate; size = (size * 300.0) / rpm; - size = (size * fdd_getrpm(real_drive(drive))) / 300.0; + size = (size * fdd_getrpm(real_drive(d86f_fdc, drive))) / 300.0; return (int) size; } int d86f_can_read_address(int drive) { int temp = 0; - temp = (fdc_get_bitcell_period() == d86f_get_bitcell_period(drive)); - temp = temp && fdd_can_read_medium(real_drive(drive)); - temp = temp && (fdc_is_mfm() == d86f_is_mfm(drive)); + temp = (fdc_get_bitcell_period(d86f_fdc) == d86f_get_bitcell_period(drive)); + temp = temp && fdd_can_read_medium(real_drive(d86f_fdc, drive)); + temp = temp && (fdc_is_mfm(d86f_fdc) == d86f_is_mfm(drive)); temp = temp && (d86f_get_encoding(drive) <= 1); return temp; } @@ -988,6 +991,9 @@ void d86f_put_bit(int drive, int side, int bit) uint16_t current_bit; uint16_t surface_bit; + if (fdc_get_diswr(d86f_fdc)) + return; + track_word = d86f[drive].track_pos >> 4; /* We need to make sure we read the bits from MSB to LSB. */ track_bit = 15 - (d86f[drive].track_pos & 15); @@ -1096,14 +1102,14 @@ static uint8_t decodefm(int drive, uint16_t dat) return temp; } -void floppy_calccrc(uint8_t byte, crc_t *crc_var) +void fdd_calccrc(uint8_t byte, crc_t *crc_var) { crc_var->word = (crc_var->word << 8) ^ CRCTable[(crc_var->word >> 8)^byte]; } static void d86f_calccrc(int drive, uint8_t byte) { - floppy_calccrc(byte, &(d86f[drive].calc_crc)); + fdd_calccrc(byte, &(d86f[drive].calc_crc)); } int d86f_word_is_aligned(int drive, int side, uint32_t base_pos) @@ -1139,7 +1145,7 @@ void d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_a if (d86f[drive].last_word[side] == req_am) { d86f[drive].calc_crc.word = 0xFFFF; - floppy_calccrc(decodefm(drive, d86f[drive].last_word[side]), &(d86f[drive].calc_crc)); + fdd_calccrc(decodefm(drive, d86f[drive].last_word[side]), &(d86f[drive].calc_crc)); find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; find->sync_pos = 0xFFFFFFFF; d86f[drive].preceding_bit[side] = d86f[drive].last_word[side] & 1; @@ -1150,7 +1156,7 @@ void d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_a if ((ignore_other_am & 2) && (d86f[drive].last_word[side] == other_am)) { d86f[drive].calc_crc.word = 0xFFFF; - floppy_calccrc(decodefm(drive, d86f[drive].last_word[side]), &(d86f[drive].calc_crc)); + fdd_calccrc(decodefm(drive, d86f[drive].last_word[side]), &(d86f[drive].calc_crc)); find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; find->sync_pos = 0xFFFFFFFF; if (ignore_other_am & 1) @@ -1161,7 +1167,7 @@ void d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_a else { /* Not skip mode, process the sector anyway. */ - fdc_set_wrong_am(); + fdc_set_wrong_am(d86f_fdc); d86f[drive].preceding_bit[side] = d86f[drive].last_word[side] & 1; d86f[drive].state++; } @@ -1212,7 +1218,7 @@ void d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_ if (d86f_word_is_aligned(drive, side, find->sync_pos)) { d86f[drive].calc_crc.word = 0xCDB4; - floppy_calccrc(decodefm(drive, d86f[drive].last_word[side]), &(d86f[drive].calc_crc)); + fdd_calccrc(decodefm(drive, d86f[drive].last_word[side]), &(d86f[drive].calc_crc)); find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; find->sync_pos = 0xFFFFFFFF; d86f[drive].preceding_bit[side] = d86f[drive].last_word[side] & 1; @@ -1226,7 +1232,7 @@ void d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_ if (d86f_word_is_aligned(drive, side, find->sync_pos)) { d86f[drive].calc_crc.word = 0xCDB4; - floppy_calccrc(decodefm(drive, d86f[drive].last_word[side]), &(d86f[drive].calc_crc)); + fdd_calccrc(decodefm(drive, d86f[drive].last_word[side]), &(d86f[drive].calc_crc)); find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; find->sync_pos = 0xFFFFFFFF; if (ignore_other_am & 1) @@ -1237,7 +1243,7 @@ void d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_ else { /* Not skip mode, process the sector anyway. */ - fdc_set_wrong_am(); + fdc_set_wrong_am(d86f_fdc); d86f[drive].preceding_bit[side] = d86f[drive].last_word[side] & 1; d86f[drive].state++; } @@ -1296,7 +1302,7 @@ void d86f_read_sector_id(int drive, int side, int match) if (d86f[drive].id_find.bytes_obtained < 4) { d86f[drive].last_sector.byte_array[d86f[drive].id_find.bytes_obtained] = decodefm(drive, d86f[drive].last_word[side]); - floppy_calccrc(d86f[drive].last_sector.byte_array[d86f[drive].id_find.bytes_obtained], &(d86f[drive].calc_crc)); + fdd_calccrc(d86f[drive].last_sector.byte_array[d86f[drive].id_find.bytes_obtained], &(d86f[drive].calc_crc)); } else if ((d86f[drive].id_find.bytes_obtained >= 4) && (d86f[drive].id_find.bytes_obtained < 6)) { @@ -1315,8 +1321,8 @@ void d86f_read_sector_id(int drive, int side, int match) { d86f[drive].error_condition = 0; d86f[drive].state = STATE_IDLE; - fdc_finishread(); - fdc_headercrcerror(); + fdc_finishread(d86f_fdc); + fdc_headercrcerror(d86f_fdc); } else if (d86f[drive].state == STATE_0A_READ_ID) { @@ -1332,7 +1338,7 @@ void d86f_read_sector_id(int drive, int side, int match) { /* CRC is valid and this is a read sector ID command. */ 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); + fdc_sectorid(d86f_fdc, 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; } else @@ -1347,11 +1353,11 @@ void d86f_read_sector_id(int drive, int side, int match) { /* READ TRACK command, we need some special handling here. */ /* Code corrected: Only the C, H, and N portions of the sector ID are compared, the R portion (the sector number) is ignored. */ - if ((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.n != fdc_get_read_track_sector().id.n)) + if ((d86f[drive].last_sector.id.c != fdc_get_read_track_sector(d86f_fdc).id.c) || (d86f[drive].last_sector.id.h != fdc_get_read_track_sector(d86f_fdc).id.h) || (d86f[drive].last_sector.id.n != fdc_get_read_track_sector(d86f_fdc).id.n)) { d86f[drive].error_condition |= 4; /* Mark that the sector ID is not the one expected by the FDC. */ /* Make sure we use the sector size from the FDC. */ - d86f[drive].last_sector.id.n = fdc_get_read_track_sector().id.n; + d86f[drive].last_sector.id.n = fdc_get_read_track_sector(d86f_fdc).id.n; } /* If the two ID's are identical, then we do not need to do anything regarding the sector size. */ } @@ -1389,7 +1395,7 @@ uint8_t d86f_get_data(int drive, int base) if (d86f[drive].data_find.bytes_obtained < (d86f_get_data_len(drive) + base)) { - data = fdc_getdata(d86f[drive].data_find.bytes_obtained == (d86f_get_data_len(drive) + base - 1)); + data = fdc_getdata(d86f_fdc, d86f[drive].data_find.bytes_obtained == (d86f_get_data_len(drive) + base - 1)); if ((data & DMA_OVER) || (data == -1)) { d86f[drive].dma_over++; @@ -1413,7 +1419,7 @@ uint8_t d86f_get_data(int drive, int base) void d86f_compare_byte(int drive, uint8_t received_byte, uint8_t disk_byte) { - switch(fdc_get_compare_condition()) + switch(fdc_get_compare_condition(d86f_fdc)) { case 0: /* SCAN EQUAL */ if ((received_byte == disk_byte) || (received_byte == 0xFF)) @@ -1467,7 +1473,7 @@ void d86f_read_sector_data(int drive, int side) { if (d86f[drive].state != STATE_16_VERIFY_DATA) { - read_status = fdc_data(data); + read_status = fdc_data(d86f_fdc, data); if (read_status == -1) { d86f[drive].dma_over++; @@ -1475,7 +1481,7 @@ void d86f_read_sector_data(int drive, int side) } } } - floppy_calccrc(data, &(d86f[drive].calc_crc)); + fdd_calccrc(data, &(d86f[drive].calc_crc)); } else if (d86f[drive].data_find.bytes_obtained < crc_pos) { @@ -1483,7 +1489,7 @@ void d86f_read_sector_data(int drive, int side) } d86f[drive].data_find.bytes_obtained++; - if (d86f[drive].data_find.bytes_obtained == (crc_pos + fdc_get_gap())) + if (d86f[drive].data_find.bytes_obtained == (crc_pos + fdc_get_gap(d86f_fdc))) { /* We've got the data. */ if (d86f[drive].dma_over > 1) @@ -1491,8 +1497,8 @@ void d86f_read_sector_data(int drive, int side) 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(); + fdc_finishread(d86f_fdc); + fdc_overrun(d86f_fdc); d86f_get_bit(drive, side); @@ -1506,15 +1512,15 @@ void d86f_read_sector_data(int drive, int side) 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_datacrcerror(); + fdc_finishread(d86f_fdc); + fdc_datacrcerror(d86f_fdc); } else if ((d86f[drive].calc_crc.word != d86f[drive].track_crc.word) && (d86f[drive].state == STATE_02_READ_DATA)) { d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; d86f[drive].error_condition |= 2; /* Mark that there was a data error. */ d86f[drive].state = STATE_IDLE; - fdc_track_finishread(d86f[drive].error_condition); + fdc_track_finishread(d86f_fdc, d86f[drive].error_condition); } else { @@ -1524,12 +1530,12 @@ void d86f_read_sector_data(int drive, int side) 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); + fdc_sector_finishcompare(d86f_fdc, (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(); + fdc_sector_finishread(d86f_fdc); } } } @@ -1563,7 +1569,8 @@ void d86f_write_sector_data(int drive, int side, int mfm, uint16_t am) { /* We're in the data field of the sector, read byte from FDC and request new byte. */ d86f[drive].current_byte[side] = d86f_get_data(drive, 1); - d86f_handler[drive].write_data(drive, side, d86f[drive].data_find.bytes_obtained - 1, d86f[drive].current_byte[side]); + if (!fdc_get_diswr(d86f_fdc)) + d86f_handler[drive].write_data(drive, side, d86f[drive].data_find.bytes_obtained - 1, d86f[drive].current_byte[side]); } else { @@ -1596,11 +1603,11 @@ void d86f_write_sector_data(int drive, int side, int mfm, uint16_t am) /* This is a data byte, so CRC it. */ if (!d86f[drive].data_find.bytes_obtained) { - floppy_calccrc(decodefm(drive, am), &(d86f[drive].calc_crc)); + fdd_calccrc(decodefm(drive, am), &(d86f[drive].calc_crc)); } else { - floppy_calccrc(d86f[drive].current_byte[side], &(d86f[drive].calc_crc)); + fdd_calccrc(d86f[drive].current_byte[side], &(d86f[drive].calc_crc)); } } } @@ -1648,15 +1655,15 @@ void d86f_write_sector_data(int drive, int side, int mfm, uint16_t am) { d86f[drive].data_find.bytes_obtained++; - if (d86f[drive].data_find.bytes_obtained == (crc_pos + fdc_get_gap())) + if (d86f[drive].data_find.bytes_obtained == (crc_pos + fdc_get_gap(d86f_fdc))) { 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(); + fdc_finishread(d86f_fdc); + fdc_overrun(d86f_fdc); d86f[drive].data_find.bits_obtained++; return; @@ -1667,7 +1674,7 @@ void d86f_write_sector_data(int drive, int side, int mfm, uint16_t am) d86f[drive].error_condition = 0; d86f[drive].state = STATE_IDLE; d86f_handler[drive].writeback(drive); - fdc_sector_finishread(); + fdc_sector_finishread(d86f_fdc); return; } } @@ -1726,6 +1733,9 @@ void d86f_write_direct_common(int drive, int side, uint16_t byte, uint8_t type, uint16_t encoded_byte = 0, mask_data, mask_surface, mask_hole, mask_fuzzy; decoded_t dbyte, dpbyte; + if (fdc_get_diswr(d86f_fdc)) + return; + dbyte.byte = byte; dpbyte.byte = d86f[drive].preceding_bit[side]; @@ -1805,7 +1815,7 @@ void d86f_format_finish(int drive, int side, int mfm, uint16_t sc, uint16_t gap_ d86f[drive].error_condition = 0; d86f[drive].datac = 0; - fdc_sector_finishread(); + fdc_sector_finishread(d86f_fdc); } void d86f_format_turbo_finish(int drive, int side, int do_write) @@ -1819,7 +1829,7 @@ void d86f_format_turbo_finish(int drive, int side, int do_write) d86f[drive].error_condition = 0; d86f[drive].datac = 0; - fdc_sector_finishread(); + fdc_sector_finishread(d86f_fdc); } void d86f_format_track(int drive, int side, int do_write) @@ -1845,11 +1855,11 @@ void d86f_format_track(int drive, int side, int do_write) am_len = mfm ? 4 : 1; gap_sizes[0] = mfm ? 80 : 40; gap_sizes[1] = mfm ? 50 : 26; - gap_sizes[2] = fdc_get_gap2(real_drive(drive)); - gap_sizes[3] = fdc_get_gap(); + gap_sizes[2] = fdc_get_gap2(d86f_fdc, real_drive(d86f_fdc, drive)); + gap_sizes[3] = fdc_get_gap(d86f_fdc); sync_len = mfm ? 12 : 6; - sc = fdc_get_format_sectors(); - dtl = 128 << fdc_get_format_n(); + sc = fdc_get_format_sectors(d86f_fdc); + dtl = 128 << fdc_get_format_n(d86f_fdc); gap_fill = mfm ? 0x4E : 0xFF; switch(d86f[drive].format_state) @@ -1866,7 +1876,7 @@ void d86f_format_track(int drive, int side, int do_write) max_len = sync_len; if (d86f[drive].datac <= 3) { - data = fdc_getdata(0); + data = fdc_getdata(d86f_fdc, 0); if (data != -1) { data &= 0xff; @@ -1878,7 +1888,7 @@ void d86f_format_track(int drive, int side, int do_write) d86f[drive].format_sector_id.byte_array[d86f[drive].datac] = data & 0xff; if (d86f[drive].datac == 3) { - fdc_stop_id_request(); + fdc_stop_id_request(d86f_fdc); } } case FMT_PRETRK_SYNC: @@ -1990,7 +2000,7 @@ void d86f_format_track(int drive, int side, int do_write) switch (d86f[drive].format_state) { case FMT_SECTOR_ID_SYNC: - fdc_request_next_sector_id(); + fdc_request_next_sector_id(d86f_fdc); break; case FMT_SECTOR_IDAM: case FMT_SECTOR_DATAAM: @@ -2007,7 +2017,7 @@ void d86f_format_track(int drive, int side, int do_write) { /* Sector within allotted amount, change state to SECTOR_ID_SYNC. */ d86f[drive].format_state = FMT_SECTOR_ID_SYNC; - fdc_request_next_sector_id(); + fdc_request_next_sector_id(d86f_fdc); break; } else @@ -2060,7 +2070,7 @@ void d86f_turbo_read(int drive, int side) { if (d86f[drive].state != STATE_16_VERIFY_DATA) { - read_status = fdc_data(dat); + read_status = fdc_data(d86f_fdc, dat); if (read_status == -1) { d86f[drive].dma_over++; @@ -2074,8 +2084,8 @@ void d86f_turbo_read(int drive, int side) 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(); + fdc_finishread(d86f_fdc); + fdc_overrun(d86f_fdc); return; } @@ -2087,12 +2097,12 @@ void d86f_turbo_read(int drive, int side) 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); + fdc_sector_finishcompare(d86f_fdc, (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(); + fdc_sector_finishread(d86f_fdc); } } } @@ -2113,7 +2123,7 @@ void d86f_turbo_write(int drive, int side) d86f[drive].error_condition = 0; d86f[drive].state = STATE_IDLE; d86f_handler[drive].writeback(drive); - fdc_sector_finishread(); + fdc_sector_finishread(d86f_fdc); return; } } @@ -2126,12 +2136,12 @@ void d86f_turbo_format(int drive, int side, int nop) uint16_t sc = 0; uint16_t dtl = 0; - sc = fdc_get_format_sectors(); - dtl = 128 << fdc_get_format_n(); + sc = fdc_get_format_sectors(d86f_fdc); + dtl = 128 << fdc_get_format_n(d86f_fdc); if (d86f[drive].datac <= 3) { - dat = fdc_getdata(0); + dat = fdc_getdata(d86f_fdc, 0); if (dat != -1) { dat &= 0xff; @@ -2143,7 +2153,7 @@ void d86f_turbo_format(int drive, int side, int nop) d86f[drive].format_sector_id.byte_array[d86f[drive].datac] = dat & 0xff; if (d86f[drive].datac == 3) { - fdc_stop_id_request(); + fdc_stop_id_request(d86f_fdc); 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); } } @@ -2169,7 +2179,7 @@ void d86f_turbo_format(int drive, int side, int nop) if (d86f[drive].sector_count < sc) { /* Sector within allotted amount. */ - fdc_request_next_sector_id(); + fdc_request_next_sector_id(d86f_fdc); } else { @@ -2185,13 +2195,8 @@ void d86f_turbo_poll(int drive, int side) { if (!d86f_can_read_address(drive)) { - /* if (fdc_get_bitcell_period() != d86f_get_bitcell_period(drive)) d86f_log("[%i, %i] Bitcell period mismatch (%i != %i)\n", drive, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive)); - if (!fdd_can_read_medium(real_drive(drive))) d86f_log("[%i, %i] Drive can not read medium (hole = %01X)\n", drive, side, d86f_hole(drive)); - if (fdc_is_mfm() != d86f_is_mfm(drive)) d86f_log("[%i, %i] Encoding mismatch\n", drive, side); - if (d86f_get_encoding(drive) > 1) d86f_log("[%i, %i] Image encoding (%s) not FM or MFM\n", drive, side, (d86f_get_encoding(drive) == 2) ? "M2FM" : "GCR"); */ - d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = d86f[drive].error_condition = 0; - fdc_noidam(); + fdc_noidam(d86f_fdc); d86f[drive].state = STATE_IDLE; return; } @@ -2207,17 +2212,17 @@ void d86f_turbo_poll(int drive, int side) 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))) + if (!(d86f[drive].sector_id_bit_field[side][fdc_get_read_track_sector(d86f_fdc).id.c][fdc_get_read_track_sector(d86f_fdc).id.h][fdc_get_read_track_sector(d86f_fdc).id.r] & (1 << fdc_get_read_track_sector(d86f_fdc).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(); + fdc_nosector(d86f_fdc); 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[drive].last_sector.id.c = fdc_get_read_track_sector(d86f_fdc).id.c; + d86f[drive].last_sector.id.h = fdc_get_read_track_sector(d86f_fdc).id.h; + d86f[drive].last_sector.id.r = fdc_get_read_track_sector(d86f_fdc).id.r; + d86f[drive].last_sector.id.n = fdc_get_read_track_sector(d86f_fdc).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++; @@ -2231,7 +2236,7 @@ void d86f_turbo_poll(int drive, int side) 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(); + fdc_nosector(d86f_fdc); d86f[drive].state = STATE_IDLE; return; } @@ -2246,7 +2251,7 @@ void d86f_turbo_poll(int drive, int side) 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); + fdc_sectorid(d86f_fdc, 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: @@ -2302,7 +2307,7 @@ void d86f_poll(int drive) side = 0; } - mfm = fdc_is_mfm(); + mfm = fdc_is_mfm(d86f_fdc); if ((d86f[drive].state & 0xF8) == 0xE8) { @@ -2322,10 +2327,6 @@ void d86f_poll(int drive) { if (!d86f_can_read_address(drive)) { - /* if (fdc_get_bitcell_period() != d86f_get_bitcell_period(drive)) d86f_log("[%i, %i] Bitcell period mismatch (%i != %i)\n", drive, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive)); - if (!fdd_can_read_medium(real_drive(drive))) d86f_log("[%i, %i] Drive can not read medium (hole = %01X)\n", drive, side, d86f_hole(drive)); - if (fdc_is_mfm() != d86f_is_mfm(drive)) d86f_log("[%i, %i] Encoding mismatch\n", drive, side); - if (d86f_get_encoding(drive) > 1) d86f_log("[%i, %i] Image encoding (%s) not FM or MFM\n", drive, side, (d86f_get_encoding(drive) == 2) ? "M2FM" : "GCR"); */ d86f[drive].state = STATE_SECTOR_NOT_FOUND; } @@ -2387,11 +2388,11 @@ void d86f_poll(int drive) case STATE_16_FIND_DATA: if (mfm) { - d86f_find_address_mark_mfm(drive, side, &(d86f[drive].data_find), 0x5545, 0x554A, fdc_is_sk() | 2); + d86f_find_address_mark_mfm(drive, side, &(d86f[drive].data_find), 0x5545, 0x554A, fdc_is_sk(d86f_fdc) | 2); } else { - d86f_find_address_mark_fm(drive, side, &(d86f[drive].data_find), 0xF56F, 0xF56A, fdc_is_sk() | 2); + d86f_find_address_mark_fm(drive, side, &(d86f[drive].data_find), 0xF56F, 0xF56A, fdc_is_sk(d86f_fdc) | 2); } break; case STATE_05_FIND_DATA: @@ -2408,11 +2409,11 @@ void d86f_poll(int drive) case STATE_0C_FIND_DATA: if (mfm) { - d86f_find_address_mark_mfm(drive, side, &(d86f[drive].data_find), 0x554A, 0x5545, fdc_is_sk() | 2); + d86f_find_address_mark_mfm(drive, side, &(d86f[drive].data_find), 0x554A, 0x5545, fdc_is_sk(d86f_fdc) | 2); } else { - d86f_find_address_mark_fm(drive, side, &(d86f[drive].data_find), 0xF56A, 0xF56F, fdc_is_sk() | 2); + d86f_find_address_mark_fm(drive, side, &(d86f[drive].data_find), 0xF56A, 0xF56F, fdc_is_sk(d86f_fdc) | 2); } break; case STATE_02_READ_DATA: @@ -2466,7 +2467,7 @@ void d86f_poll(int drive) if (d86f_wrong_densel(drive) && (d86f[drive].state != STATE_IDLE)) { d86f[drive].state = STATE_IDLE; - fdc_noidam(); + fdc_noidam(d86f_fdc); return; } @@ -2477,7 +2478,7 @@ void d86f_poll(int drive) case STATE_0A_FIND_ID: case STATE_SECTOR_NOT_FOUND: d86f[drive].state = STATE_IDLE; - fdc_noidam(); + fdc_noidam(d86f_fdc); break; case STATE_02_FIND_DATA: case STATE_06_FIND_DATA: @@ -2487,7 +2488,7 @@ void d86f_poll(int drive) case STATE_09_FIND_DATA: case STATE_0C_FIND_DATA: d86f[drive].state = STATE_IDLE; - fdc_nodataam(); + fdc_nodataam(d86f_fdc); break; case STATE_02_SPIN_TO_INDEX: case STATE_02_READ_DATA: @@ -2509,21 +2510,21 @@ void d86f_poll(int drive) { if ((d86f[drive].error_condition & 0x18) == 0x08) { - fdc_badcylinder(); + fdc_badcylinder(d86f_fdc); } if ((d86f[drive].error_condition & 0x10) == 0x10) { - fdc_wrongcylinder(); + fdc_wrongcylinder(d86f_fdc); } } else { - fdc_nosector(); + fdc_nosector(d86f_fdc); } } else { - fdc_noidam(); + fdc_noidam(d86f_fdc); } break; } @@ -2543,7 +2544,7 @@ void d86f_poll(int drive) void d86f_poll() { int drive = 0; - drive = fdc_get_drive(); + drive = fdc_get_drive(d86f_fdc); d86f_poll_per_drive(drive); } #endif @@ -2897,6 +2898,21 @@ void d86f_read_track(int drive, int track, int thin_track, int side, uint16_t *d } } +void d86f_zero_track(int drive) +{ + int sides, side; + sides = d86f_get_sides(drive); + + for (side = 0; side < sides; side++) + { + if (d86f_has_surface_desc(drive)) + { + memset(d86f[drive].track_surface_data[side], 0, 106096); + } + memset(d86f[drive].track_encoded_data[side], 0, 106096); + } +} + void d86f_seek(int drive, int track) { int sides; @@ -2921,14 +2937,7 @@ void d86f_seek(int drive, int track) } } - for (side = 0; side < sides; side++) - { - if (d86f_has_surface_desc(drive)) - { - memset(d86f[drive].track_surface_data[side], 0, 106096); - } - memset(d86f[drive].track_encoded_data[side], 0, 106096); - } + d86f_zero_track(drive); d86f[drive].cur_track = track; @@ -2955,23 +2964,23 @@ void d86f_seek(int drive, int track) d86f[drive].state = STATE_IDLE; } -void d86f_write_track(int drive, int side, uint16_t *da0, uint16_t *sa0) +void d86f_write_track(int drive, FILE **f, int side, uint16_t *da0, uint16_t *sa0) { - fwrite(&(d86f[drive].side_flags[side]), 1, 2, d86f[drive].f); + fwrite(&(d86f[drive].side_flags[side]), 1, 2, *f); if (d86f_has_extra_bit_cells(drive)) { - fwrite(&(d86f[drive].extra_bit_cells[side]), 1, 4, d86f[drive].f); + fwrite(&(d86f[drive].extra_bit_cells[side]), 1, 4, *f); } - fwrite(&(d86f[drive].index_hole_pos[side]), 1, 4, d86f[drive].f); + fwrite(&(d86f[drive].index_hole_pos[side]), 1, 4, *f); if (d86f_has_surface_desc(drive)) { - fwrite(sa0, 1, d86f_get_array_size(drive, side) << 1, d86f[drive].f); + fwrite(sa0, 1, d86f_get_array_size(drive, side) << 1, *f); } - fwrite(da0, 1, d86f_get_array_size(drive, side) << 1, d86f[drive].f); + fwrite(da0, 1, d86f_get_array_size(drive, side) << 1, *f); } int d86f_get_track_table_size(int drive) @@ -2986,29 +2995,17 @@ int d86f_get_track_table_size(int drive) return temp; } -void d86f_writeback(int drive) +void d86f_set_cur_track(int drive, int track) { - uint8_t header[32]; - int sides, header_size; + d86f[drive].cur_track = track; +} + +void d86f_write_tracks(int drive, FILE **f) +{ + int sides; int side, thin_track; - uint32_t len; - int ret = 0; int logical_track = 0; - FILE *cf; sides = d86f_get_sides(drive); - header_size = d86f_header_size(drive); - - if (!d86f[drive].f) - { - return; - } - - /* First write the track offsets table. */ - fseek(d86f[drive].f, 0, SEEK_SET); - fread(header, 1, header_size, d86f[drive].f); - - fseek(d86f[drive].f, 8, SEEK_SET); - fwrite(d86f[drive].track_offset, 1, d86f_get_track_table_size(drive), d86f[drive].f); if (!fdd_doublestep_40(drive)) { @@ -3028,8 +3025,8 @@ void d86f_writeback(int drive) } if (d86f[drive].track_offset[logical_track]) { - fseek(d86f[drive].f, d86f[drive].track_offset[logical_track], SEEK_SET); - d86f_write_track(drive, side, d86f[drive].thin_track_encoded_data[thin_track][side], d86f[drive].thin_track_surface_data[thin_track][side]); + fseek(*f, d86f[drive].track_offset[logical_track], SEEK_SET); + d86f_write_track(drive, f, side, d86f[drive].thin_track_encoded_data[thin_track][side], d86f[drive].thin_track_surface_data[thin_track][side]); } } } @@ -3048,11 +3045,35 @@ void d86f_writeback(int drive) } if (d86f[drive].track_offset[logical_track]) { - fseek(d86f[drive].f, d86f[drive].track_offset[logical_track], SEEK_SET); - d86f_write_track(drive, side, d86f[drive].track_encoded_data[side], d86f[drive].track_surface_data[side]); + fseek(*f, d86f[drive].track_offset[logical_track], SEEK_SET); + d86f_write_track(drive, f, side, d86f[drive].track_encoded_data[side], d86f[drive].track_surface_data[side]); } } } +} + +void d86f_writeback(int drive) +{ + uint8_t header[32]; + int header_size; + uint32_t len; + int ret = 0; + FILE *cf; + header_size = d86f_header_size(drive); + + if (!d86f[drive].f) + { + return; + } + + /* First write the track offsets table. */ + fseek(d86f[drive].f, 0, SEEK_SET); + fread(header, 1, header_size, d86f[drive].f); + + fseek(d86f[drive].f, 8, SEEK_SET); + fwrite(d86f[drive].track_offset, 1, d86f_get_track_table_size(drive), d86f[drive].f); + + d86f_write_tracks(drive, &d86f[drive].f); if (d86f[drive].is_compressed) { @@ -3094,7 +3115,7 @@ void d86f_stop(int drive) int d86f_common_command(int drive, int sector, int track, int side, int rate, int sector_size) { - d86f_log("d86f_common_command (drive %i): fdc_period=%i img_period=%i rate=%i sector=%i track=%i side=%i\n", drive, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), rate, sector, track, side); + d86f_log("d86f_common_command (drive %i): fdc_period=%i img_period=%i rate=%i sector=%i track=%i side=%i\n", drive, fdc_get_bitcell_period(d86f_fdc), d86f_get_bitcell_period(drive), rate, sector, track, side); d86f[drive].req_sector.id.c = track; d86f[drive].req_sector.id.h = side; @@ -3114,7 +3135,7 @@ int d86f_common_command(int drive, int sector, int track, int side, int rate, in if (fdd_get_head(drive) && (d86f_get_sides(drive) == 1)) { - fdc_noidam(); + fdc_noidam(d86f_fdc); d86f[drive].state = STATE_IDLE; d86f[drive].index_count = 0; return 0; @@ -3141,7 +3162,7 @@ void d86f_readsector(int drive, int sector, int track, int side, int rate, int s else if (sector == SECTOR_NEXT) d86f[drive].state = STATE_02_FIND_ID; else - d86f[drive].state = fdc_is_deleted() ? STATE_0C_FIND_ID : (fdc_is_verify() ? STATE_16_FIND_ID : STATE_06_FIND_ID); + d86f[drive].state = fdc_is_deleted(d86f_fdc) ? STATE_0C_FIND_ID : (fdc_is_verify(d86f_fdc) ? STATE_16_FIND_ID : STATE_06_FIND_ID); } void d86f_writesector(int drive, int sector, int track, int side, int rate, int sector_size) @@ -3150,7 +3171,7 @@ void d86f_writesector(int drive, int sector, int track, int side, int rate, int if (writeprot[drive]) { - fdc_writeprotect(); + fdc_writeprotect(d86f_fdc); d86f[drive].state = STATE_IDLE; d86f[drive].index_count = 0; return; @@ -3159,7 +3180,7 @@ void d86f_writesector(int drive, int sector, int track, int side, int rate, int ret = d86f_common_command(drive, sector, track, side, rate, sector_size); if (!ret) return; - d86f[drive].state = fdc_is_deleted() ? STATE_09_FIND_ID : STATE_05_FIND_ID; + d86f[drive].state = fdc_is_deleted(d86f_fdc) ? STATE_09_FIND_ID : STATE_05_FIND_ID; } void d86f_comparesector(int drive, int sector, int track, int side, int rate, int sector_size) @@ -3176,7 +3197,7 @@ void d86f_readaddress(int drive, int side, int rate) { if (fdd_get_head(drive) && (d86f_get_sides(drive) == 1)) { - fdc_noidam(); + fdc_noidam(d86f_fdc); d86f[drive].state = STATE_IDLE; d86f[drive].index_count = 0; return; @@ -3237,7 +3258,7 @@ void d86f_common_format(int drive, int side, int rate, uint8_t fill, int proxy) if (writeprot[drive]) { - fdc_writeprotect(); + fdc_writeprotect(d86f_fdc); d86f[drive].state = STATE_IDLE; d86f[drive].index_count = 0; return; @@ -3245,7 +3266,7 @@ void d86f_common_format(int drive, int side, int rate, uint8_t fill, int proxy) if (!(d86f_can_format(drive))) { - fdc_cannotformat(); + fdc_cannotformat(d86f_fdc); d86f[drive].state = STATE_IDLE; d86f[drive].index_count = 0; return; @@ -3259,7 +3280,7 @@ void d86f_common_format(int drive, int side, int rate, uint8_t fill, int proxy) if (d86f[drive].cur_track > 256) { - fdc_writeprotect(); + fdc_writeprotect(d86f_fdc); d86f[drive].state = STATE_IDLE; d86f[drive].index_count = 0; return; @@ -3294,9 +3315,9 @@ void d86f_common_format(int drive, int side, int rate, uint8_t fill, int proxy) if (!proxy) { d86f[drive].side_flags[side] = 0; - d86f[drive].side_flags[side] |= (fdd_getrpm(real_drive(drive)) == 360) ? 0x20 : 0; - d86f[drive].side_flags[side] |= fdc_get_bit_rate(); - d86f[drive].side_flags[side] |= fdc_is_mfm() ? 8 : 0; + d86f[drive].side_flags[side] |= (fdd_getrpm(real_drive(d86f_fdc, drive)) == 360) ? 0x20 : 0; + d86f[drive].side_flags[side] |= fdc_get_bit_rate(d86f_fdc); + d86f[drive].side_flags[side] |= fdc_is_mfm(d86f_fdc) ? 8 : 0; d86f[drive].index_hole_pos[side] = 0; } @@ -3332,7 +3353,6 @@ void d86f_common_handlers(int drive) 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; drives[drive].poll = d86f_poll; drives[drive].format = d86f_proxy_format; @@ -3650,6 +3670,11 @@ void d86f_init() d86f[0].state = d86f[1].state = STATE_IDLE; } +void d86f_set_fdc(void *fdc) +{ + d86f_fdc = (fdc_t *) fdc; +} + void d86f_close(int drive) { wchar_t temp_file_name[2048]; diff --git a/src/floppy/floppy_86f.h b/src/floppy/fdd_86f.h similarity index 57% rename from src/floppy/floppy_86f.h rename to src/floppy/fdd_86f.h index bed51dfbf..a04ddb2fa 100644 --- a/src/floppy/floppy_86f.h +++ b/src/floppy/fdd_86f.h @@ -10,33 +10,36 @@ * data in the form of FM/MFM-encoded transitions) which also * forms the core of the emulator's floppy disk emulation. * - * Version: @(#)floppy_86f.h 1.0.2 2017/09/03 + * Version: @(#)floppy_86f.h 1.0.3 2018/01/17 * * Author: Miran Grca, - * Copyright 2016-2017 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ #ifndef EMU_FLOPPY_86F_H # define EMU_FLOPPY_86F_H -extern void d86f_init(void); -extern void d86f_load(int drive, wchar_t *fn); -extern void d86f_close(int drive); -extern void d86f_seek(int drive, int track); -extern int d86f_hole(int drive); -extern double d86f_byteperiod(int drive); -extern void d86f_stop(int drive); -extern void d86f_poll(int drive); -extern int d86f_realtrack(int track, int drive); -extern void d86f_reset(int drive, int side); -extern void d86f_readsector(int drive, int sector, int track, int side, int density, int sector_size); -extern void d86f_writesector(int drive, int sector, int track, int side, int density, int sector_size); -extern void d86f_comparesector(int drive, int sector, int track, int side, int rate, int sector_size); -extern void d86f_readaddress(int drive, int side, int density); -extern void d86f_format(int drive, int side, int density, uint8_t fill); +extern void d86f_init(void); +extern void d86f_load(int drive, wchar_t *fn); +extern void d86f_close(int drive); +extern void d86f_seek(int drive, int track); +extern int d86f_hole(int drive); +extern double d86f_byteperiod(int drive); +extern void d86f_stop(int drive); +extern void d86f_poll(int drive); +extern int d86f_realtrack(int track, int drive); +extern void d86f_reset(int drive, int side); +extern void d86f_readsector(int drive, int sector, int track, int side, int density, int sector_size); +extern void d86f_writesector(int drive, int sector, int track, int side, int density, int sector_size); +extern void d86f_comparesector(int drive, int sector, int track, int side, int rate, int sector_size); +extern void d86f_readaddress(int drive, int side, int density); +extern void d86f_format(int drive, int side, int density, uint8_t fill); -extern void d86f_prepare_track_layout(int drive, int side); -extern void d86f_set_version(int drive, uint16_t version); +extern void d86f_prepare_track_layout(int drive, int side); +extern void d86f_set_version(int drive, uint16_t version); +extern uint16_t d86f_side_flags(int drive); +extern uint16_t d86f_track_flags(int drive); +extern void d86f_write_tracks(int drive, FILE **f); #define length_gap0 80 #define length_gap1 50 diff --git a/src/floppy/floppy_common.c b/src/floppy/fdd_common.c similarity index 95% rename from src/floppy/floppy_common.c rename to src/floppy/fdd_common.c index bbc1ec011..fcd04ab16 100644 --- a/src/floppy/floppy_common.c +++ b/src/floppy/fdd_common.c @@ -8,10 +8,10 @@ * * Shared code for all the floppy modules. * - * Version: @(#)floppy_common.c 1.0.4 2017/11/04 + * Version: @(#)fdd_common.c 1.0.5 2018/01/16 * * Author: Fred N. van Kempen, - * Copyright 2017 Fred N. van Kempen. + * Copyright 2017,2018 Fred N. van Kempen. */ #include #include @@ -19,15 +19,15 @@ #include #include #include "../86box.h" -#include "../floppy/floppy.h" -#include "floppy_common.h" +#include "fdd.h" +#include "fdd_common.h" -uint8_t floppy_holes[6] = { 0, 0, 0, 1, 1, 2 }; +uint8_t fdd_holes[6] = { 0, 0, 0, 1, 1, 2 }; -uint8_t floppy_rates[6] = { 2, 2, 1, 4, 0, 3 }; +uint8_t fdd_rates[6] = { 2, 2, 1, 4, 0, 3 }; -double floppy_bit_rates_300[6] = { +double fdd_bit_rates_300[6] = { (250.0 * 300.0) / 360.0, 250.0, 300.0, @@ -46,7 +46,7 @@ double floppy_bit_rates_300[6] = { * Disks formatted at 300 kbps @ 300 RPM can be read with any 300 RPM * single-RPM drive by setting the rate to 300 kbps. */ -uint8_t floppy_max_sectors[8][6] = { +uint8_t fdd_max_sectors[8][6] = { { 26, 31, 38, 53, 64, 118 }, /* 128 */ { 15, 19, 23, 32, 38, 73 }, /* 256 */ { 7, 10, 12, 17, 22, 41 }, /* 512 */ @@ -57,12 +57,12 @@ uint8_t floppy_max_sectors[8][6] = { { 0, 0, 0, 0, 0, 1 } /* 16384 */ }; -uint8_t floppy_dmf_r[21] = { +uint8_t fdd_dmf_r[21] = { 12,2,13,3,14,4,15,5,16,6,17,7,18,8,19,9,20,10,21,11,1 }; -static uint8_t floppy_gap3_sizes[5][8][48] = { +static uint8_t fdd_gap3_sizes[5][8][48] = { { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [0][0] */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, @@ -348,14 +348,14 @@ static uint8_t floppy_gap3_sizes[5][8][48] = { int -floppy_get_gap3_size(int rate, int size, int sector) +fdd_get_gap3_size(int rate, int size, int sector) { - return(floppy_gap3_sizes[rate][size][sector]); + return(fdd_gap3_sizes[rate][size][sector]); } uint8_t -floppy_sector_size_code(int size) +fdd_sector_size_code(int size) { int ret = 2; @@ -401,14 +401,14 @@ floppy_sector_size_code(int size) int -floppy_sector_code_size(uint8_t code) +fdd_sector_code_size(uint8_t code) { return(128 << code); } int -floppy_bps_valid(uint16_t bps) +fdd_bps_valid(uint16_t bps) { int i; @@ -423,7 +423,7 @@ floppy_bps_valid(uint16_t bps) int -floppy_interleave(int sector, int skew, int spt) +fdd_interleave(int sector, int skew, int spt) { uint32_t add = (spt & 1); uint32_t adjust = (spt >> 1); diff --git a/src/floppy/fdd_common.h b/src/floppy/fdd_common.h new file mode 100644 index 000000000..77d9a4798 --- /dev/null +++ b/src/floppy/fdd_common.h @@ -0,0 +1,34 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Shared code for all the floppy modules. + * + * Version: @(#)fdd_common.h 1.0.2 2018/01/16 + * + * Author: Fred N. van Kempen, + * Copyright 2017,2018 Fred N. van Kempen. + */ +#ifndef fdd_COMMON_H +# define fdd_COMMON_H + + +extern uint8_t fdd_holes[6]; +extern uint8_t fdd_rates[6]; +extern double fdd_bit_rates_300[6]; +extern uint8_t fdd_max_sectors[8][6]; +extern uint8_t fdd_dmf_r[21]; + + +extern int fdd_get_gap3_size(int rate, int size, int sector); +extern uint8_t fdd_sector_size_code(int size); +extern int fdd_sector_code_size(uint8_t code); +extern int fdd_bps_valid(uint16_t bps); +extern int fdd_interleave(int sector, int skew, int spt); + + +#endif /*fdd_COMMON_H*/ diff --git a/src/floppy/floppy_fdi.c b/src/floppy/fdd_fdi.c similarity index 93% rename from src/floppy/floppy_fdi.c rename to src/floppy/fdd_fdi.c index 22181a210..d8004fc51 100644 --- a/src/floppy/floppy_fdi.c +++ b/src/floppy/fdd_fdi.c @@ -9,13 +9,13 @@ * Implementation of the FDI floppy stream image format * interface to the FDI2RAW module. * - * Version: @(#)floppy_fdi.c 1.0.6 2017/12/14 + * Version: @(#)fdd_fdi.c 1.0.7 2018/01/16 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -23,12 +23,11 @@ #include #include "../86box.h" #include "../plat.h" -#include "floppy.h" -#include "floppy_86f.h" -#include "floppy_img.h" -#include "floppy_fdi.h" -#include "fdc.h" #include "fdd.h" +#include "fdd_86f.h" +#include "fdd_img.h" +#include "fdd_fdi.h" +#include "fdc.h" #include "fdi2raw.h" @@ -47,6 +46,8 @@ static struct int lasttrack; } fdi[FDD_NUM]; +static fdc_t *fdi_fdc; + uint16_t fdi_disk_flags(int drive) { uint16_t temp_disk_flags = 0x80; /* We ALWAYS claim to have extra bit cells, even if the actual amount is 0. */ @@ -111,12 +112,12 @@ uint16_t fdi_side_flags(int drive) int fdi_density() { - if (!fdc_is_mfm()) + if (!fdc_is_mfm(fdi_fdc)) { return 0; } - switch (fdc_get_bit_rate()) + switch (fdc_get_bit_rate(fdi_fdc)) { case 0: return 2; @@ -142,9 +143,9 @@ int32_t fdi_extra_bit_cells(int drive, int side) density = fdi_density(); - is_300_rpm = (fdd_getrpm(real_drive(drive)) == 300); + is_300_rpm = (fdd_getrpm(drive) == 300); - switch (fdc_get_bit_rate()) + switch (fdc_get_bit_rate(fdi_fdc)) { case 0: raw_size = is_300_rpm ? 200000 : 166666; @@ -322,15 +323,25 @@ void fdi_seek(int drive, int track) track /= 2; } } + + d86f_set_cur_track(drive, track); if (!fdi[drive].f) return; if (track < 0) track = 0; + +#if 0 if (track > fdi[drive].lasttrack) track = fdi[drive].lasttrack - 1; +#endif fdi[drive].track = track; fdi_read_revolution(drive); } + +void fdi_set_fdc(void *fdc) +{ + fdi_fdc = (fdc_t *) fdc; +} diff --git a/src/floppy/floppy_fdi.h b/src/floppy/fdd_fdi.h similarity index 100% rename from src/floppy/floppy_fdi.h rename to src/floppy/fdd_fdi.h diff --git a/src/floppy/floppy_imd.c b/src/floppy/fdd_imd.c similarity index 97% rename from src/floppy/floppy_imd.c rename to src/floppy/fdd_imd.c index eb1844557..0eef14d34 100644 --- a/src/floppy/floppy_imd.c +++ b/src/floppy/fdd_imd.c @@ -8,10 +8,10 @@ * * Implementation of the IMD floppy image format. * - * Version: @(#)floppy_imd.c 1.0.5 2017/11/04 + * Version: @(#)fdd_imd.c 1.0.6 2018/01/16 * * Author: Miran Grca, - * Copyright 2016,2017 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -20,10 +20,9 @@ #include #include "../86box.h" #include "../plat.h" -#include "floppy.h" -#include "floppy_imd.h" -#include "fdc.h" #include "fdd.h" +#include "fdd_imd.h" +#include "fdc.h" typedef struct @@ -59,6 +58,8 @@ static struct uint8_t track_buffer[2][25000]; } imd[FDD_NUM]; +static fdc_t *imd_fdc; + void imd_init() { memset(imd, 0, sizeof(imd)); @@ -529,6 +530,8 @@ void imd_seek(int drive, int track) if (!imd[drive].track_width && fdd_doublestep_40(drive)) track /= 2; + d86f_set_cur_track(drive, track); + is_trackx = (track == 0) ? 0 : 1; imd[drive].track = track; @@ -542,6 +545,12 @@ void imd_seek(int drive, int track) d86f_zero_bit_field(drive, 0); d86f_zero_bit_field(drive, 1); + if (track > imd[drive].track_count) + { + d86f_zero_track(drive); + return; + } + for (side = 0; side < imd[drive].sides; side++) { track_rate = imd[drive].current_side_flags[side] & 7; @@ -797,11 +806,16 @@ int imd_format_conditions(int drive) int side = 0; int temp = 0; side = fdd_get_head(drive); - temp = (fdc_get_format_sectors() == imd[drive].tracks[track][side].params[3]); - temp = temp && (fdc_get_format_n() == imd[drive].tracks[track][side].params[4]); + temp = (fdc_get_format_sectors(imd_fdc) == imd[drive].tracks[track][side].params[3]); + temp = temp && (fdc_get_format_n(imd_fdc) == imd[drive].tracks[track][side].params[4]); return temp; } +void imd_set_fdc(void *fdc) +{ + imd_fdc = (fdc_t *) fdc; +} + void d86f_register_imd(int drive) { d86f_handler[drive].disk_flags = imd_disk_flags; diff --git a/src/floppy/floppy_imd.h b/src/floppy/fdd_imd.h similarity index 100% rename from src/floppy/floppy_imd.h rename to src/floppy/fdd_imd.h diff --git a/src/floppy/floppy_img.c b/src/floppy/fdd_img.c similarity index 98% rename from src/floppy/floppy_img.c rename to src/floppy/fdd_img.c index 88b16192f..23ac2d919 100644 --- a/src/floppy/floppy_img.c +++ b/src/floppy/fdd_img.c @@ -9,13 +9,13 @@ * Implementation of the raw sector-based floppy image format, * as well as the Japanese FDI, CopyQM, and FDF formats. * - * Version: @(#)floppy_img.c 1.0.7 2017/11/04 + * Version: @(#)fdd_img.c 1.0.8 2018/01/16 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -25,10 +25,9 @@ #include "../86box.h" #include "../config.h" #include "../plat.h" -#include "floppy.h" -#include "floppy_img.h" -#include "fdc.h" #include "fdd.h" +#include "fdd_img.h" +#include "fdc.h" static struct @@ -57,6 +56,8 @@ static struct uint8_t skew; } img[FDD_NUM]; +static fdc_t *img_fdc; + uint8_t dmf_r[21] = { 12, 2, 13, 3, 14, 4, 15, 5, 16, 6, 17, 7, 18, 8, 19, 9, 20, 10, 21, 11, 1 }; static uint8_t xdf_logical_sectors[2][2] = { { 38, 6 }, { 46, 8 } }; uint8_t xdf_physical_sectors[2][2] = { { 16, 3 }, { 19, 4 } }; @@ -930,6 +931,7 @@ void img_seek(int drive, int track) track /= 2; img[drive].track = track; + d86f_set_cur_track(drive, track); is_t0 = (track == 0) ? 1 : 0; @@ -961,6 +963,12 @@ void img_seek(int drive, int track) d86f_zero_bit_field(drive, 0); d86f_zero_bit_field(drive, 1); + if (track > img[drive].tracks) + { + d86f_zero_track(drive); + return; + } + if (!img[drive].xdf_type || img[drive].is_cqm) { for (side = 0; side < img[drive].sides; side++) @@ -1129,12 +1137,17 @@ void img_poll_write_data(int drive, int side, uint16_t pos, uint8_t data) int img_format_conditions(int drive) { - int temp = (fdc_get_format_sectors() == img[drive].sectors); - temp = temp && (fdc_get_format_n() == img[drive].sector_size); + int temp = (fdc_get_format_sectors(img_fdc) == img[drive].sectors); + temp = temp && (fdc_get_format_n(img_fdc) == img[drive].sector_size); temp = temp && (img[drive].xdf_type == 0); return temp; } +void img_set_fdc(void *fdc) +{ + img_fdc = (fdc_t *) fdc; +} + void d86f_register_img(int drive) { d86f_handler[drive].disk_flags = img_disk_flags; diff --git a/src/floppy/floppy_img.h b/src/floppy/fdd_img.h similarity index 100% rename from src/floppy/floppy_img.h rename to src/floppy/fdd_img.h diff --git a/src/floppy/floppy_json.c b/src/floppy/fdd_json.c similarity index 95% rename from src/floppy/floppy_json.c rename to src/floppy/fdd_json.c index 10dafafae..8bf8cc6c4 100644 --- a/src/floppy/floppy_json.c +++ b/src/floppy/fdd_json.c @@ -8,11 +8,11 @@ * * Implementation of the PCjs JSON floppy image format. * - * Version: @(#)floppy_json.c 1.0.9 2017/11/04 + * Version: @(#)fdd_json.c 1.0.10 2018/01/16 * * Author: Fred N. van Kempen, * - * Copyright 2017 Fred N. van Kempen. + * Copyright 2017,2018 Fred N. van Kempen. */ #include #include @@ -21,11 +21,10 @@ #include #include "../86box.h" #include "../plat.h" -#include "floppy.h" -#include "fdc.h" #include "fdd.h" -#include "floppy_common.h" -#include "floppy_json.h" +#include "fdc.h" +#include "fdd_common.h" +#include "fdd_json.h" #define NTRACKS 256 @@ -96,7 +95,7 @@ handle(json_t *img, char *name, char *str) } /* Encode the sector size. */ - sec->size = floppy_sector_size_code(sec->size); + sec->size = fdd_sector_size_code(sec->size); /* Set up the rest of the Sector ID. */ sec->track = img->track; @@ -353,6 +352,7 @@ json_seek(int drive, int track) /* Set the new track. */ img->track = track; + d86f_set_cur_track(drive, track); /* Reset the 86F state machine. */ d86f_reset_index_hole_pos(drive, 0); @@ -361,13 +361,19 @@ json_seek(int drive, int track) d86f_zero_bit_field(drive, 1); interleave_type = 0; + + if (track > img->tracks) { + d86f_zero_track(drive); + return; + } + for (side=0; sidesides; side++) { /* Get transfer rate for this side. */ rate = img->track_flags & 0x07; if (!rate && (img->track_flags & 0x20)) rate = 4; /* Get correct GAP3 value for this side. */ - gap3 = floppy_get_gap3_size(rate, + gap3 = fdd_get_gap3_size(rate, img->sects[track][side][0].size, img->spt[track][side]); @@ -381,14 +387,14 @@ json_seek(int drive, int track) rsec = img->sects[track][side][sector].sector; asec = sector; } else { - rsec = floppy_dmf_r[sector]; + rsec = fdd_dmf_r[sector]; asec = img->interleave_ordered[rsec][side]; } id[0] = track; id[1] = side; id[2] = rsec; id[3] = img->sects[track][side][asec].size; - ssize = floppy_sector_code_size(img->sects[track][side][asec].size); + ssize = fdd_sector_code_size(img->sects[track][side][asec].size); pos = d86f_prepare_sector( drive, side, pos, id, @@ -521,11 +527,11 @@ json_load(int drive, wchar_t *fn) temp_rate = 0xff; sec = &img->sects[0][0][0]; for (i=0; i<6; i++) { - if (img->spt[0][0] > floppy_max_sectors[sec->size][i]) continue; + if (img->spt[0][0] > fdd_max_sectors[sec->size][i]) continue; - bit_rate = floppy_bit_rates_300[i]; - temp_rate = floppy_rates[i]; - img->disk_flags |= (floppy_holes[i] << 1); + bit_rate = fdd_bit_rates_300[i]; + temp_rate = fdd_rates[i]; + img->disk_flags |= (fdd_holes[i] << 1); if ((bit_rate == 500.0) && (img->spt[0][0] == 21) && (sec->size == 2) && (img->tracks >= 80) && @@ -569,7 +575,7 @@ json_load(int drive, wchar_t *fn) if (img->dmf) { img->gap3_len = 8; } else { - img->gap3_len = floppy_get_gap3_size(temp_rate,sec->size,img->spt[0][0]); + img->gap3_len = fdd_get_gap3_size(temp_rate,sec->size,img->spt[0][0]); } if (! img->gap3_len) { diff --git a/src/floppy/floppy_json.h b/src/floppy/fdd_json.h similarity index 100% rename from src/floppy/floppy_json.h rename to src/floppy/fdd_json.h diff --git a/src/floppy/floppy_td0.c b/src/floppy/fdd_td0.c similarity index 97% rename from src/floppy/floppy_td0.c rename to src/floppy/fdd_td0.c index 5024acbad..20e1a019c 100644 --- a/src/floppy/floppy_td0.c +++ b/src/floppy/fdd_td0.c @@ -8,18 +8,18 @@ * * Implementation of the Teledisk floppy image format. * - * Version: @(#)floppy_td0.c 1.0.6 2017/11/04 + * Version: @(#)fdd_td0.c 1.0.7 2018/01/16 * * Authors: Milodrag Milanovic, * Haruhiko OKUMURA, * Haruyasu YOSHIZAKI, * Kenji RIKITAKE, * Miran Grca, - * Copyright 1988-2017 Haruhiko OKUMURA. - * Copyright 1988-2017 Haruyasu YOSHIZAKI. - * Copyright 1988-2017 Kenji RIKITAKE. - * Copyright 2013-2017 Milodrag Milanovic. - * Copyright 2016-2017 Miran Grca. + * Copyright 1988-2018 Haruhiko OKUMURA. + * Copyright 1988-2018 Haruyasu YOSHIZAKI. + * Copyright 1988-2018 Kenji RIKITAKE. + * Copyright 2013-2018 Milodrag Milanovic. + * Copyright 2016-2018 Miran Grca. */ /* license:BSD-3-Clause @@ -44,10 +44,9 @@ #include #include "../86box.h" #include "../plat.h" -#include "floppy.h" -#include "floppy_td0.h" -#include "fdc.h" #include "fdd.h" +#include "fdd_td0.h" +#include "fdc.h" #define BUFSZ 512 /* new input buffer */ @@ -80,8 +79,8 @@ typedef struct { typedef struct { - FILE *floppy_file; - uint64_t floppy_file_offset; + FILE *fdd_file; + uint64_t fdd_file_offset; tdlzhuf tdctl; uint8_t text_buf[N + F - 1]; @@ -136,7 +135,7 @@ typedef struct td0_t td0[FDD_NUM]; -void floppy_image_read(int drive, char *buffer, uint32_t offset, uint32_t len) +void fdd_image_read(int drive, char *buffer, uint32_t offset, uint32_t len) { fseek(td0[drive].f, offset, SEEK_SET); fread(buffer, 1, len, td0[drive].f); @@ -146,7 +145,7 @@ int td0_dsk_identify(int drive) { char header[2]; - floppy_image_read(drive, header, 0, 2); + fdd_image_read(drive, header, 0, 2); if (header[0]=='T' && header[1]=='D') { return 1; } else if (header[0]=='t' && header[1]=='d') { @@ -159,14 +158,14 @@ int td0_dsk_identify(int drive) int td0_state_data_read(td0dsk_t *state, uint8_t *buf, uint16_t size) { uint32_t image_size = 0; - fseek(state->floppy_file, 0, SEEK_END); - image_size = ftell(state->floppy_file); - if (size > image_size - state->floppy_file_offset) { - size = image_size - state->floppy_file_offset; + fseek(state->fdd_file, 0, SEEK_END); + image_size = ftell(state->fdd_file); + if (size > image_size - state->fdd_file_offset) { + size = image_size - state->fdd_file_offset; } - fseek(state->floppy_file, state->floppy_file_offset, SEEK_SET); - fread(buf, 1, size, state->floppy_file); - state->floppy_file_offset += size; + fseek(state->fdd_file, state->fdd_file_offset, SEEK_SET); + fread(buf, 1, size, state->fdd_file); + state->fdd_file_offset += size; return size; } @@ -711,9 +710,9 @@ int td0_initialize(int drive) if(header[0] == 't') { pclog("TD0: File is compressed\n"); - disk_decode.floppy_file = td0[drive].f; + disk_decode.fdd_file = td0[drive].f; td0_state_init_Decode(&disk_decode); - disk_decode.floppy_file_offset = 12; + disk_decode.fdd_file_offset = 12; td0_state_Decode(&disk_decode, imagebuf, max_size); } else @@ -1100,6 +1099,8 @@ void td0_seek(int drive, int track) if (!td0[drive].track_width && fdd_doublestep_40(drive)) track /= 2; + d86f_set_cur_track(drive, track); + is_trackx = (track == 0) ? 0 : 1; td0[drive].track = track; @@ -1113,6 +1114,12 @@ void td0_seek(int drive, int track) d86f_zero_bit_field(drive, 0); d86f_zero_bit_field(drive, 1); + if (track > td0[drive].tracks) + { + d86f_zero_track(drive); + return; + } + for (side = 0; side < td0[drive].sides; side++) { track_rate = td0[drive].current_side_flags[side] & 7; diff --git a/src/floppy/floppy_td0.h b/src/floppy/fdd_td0.h similarity index 100% rename from src/floppy/floppy_td0.h rename to src/floppy/fdd_td0.h diff --git a/src/floppy/floppy.c b/src/floppy/floppy.c deleted file mode 100644 index e5c4760bc..000000000 --- a/src/floppy/floppy.c +++ /dev/null @@ -1,428 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Generic floppy disk interface that communicates with the - * other handlers. - * - * Version: @(#)floppy.c 1.0.13 2017/12/14 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. - */ -#include -#include -#include -#include -#include "../86box.h" -#include "../machine/machine.h" -#include "../mem.h" -#include "../rom.h" -#include "../config.h" -#include "../timer.h" -#include "../plat.h" -#include "../ui.h" -#include "floppy.h" -#include "floppy_86f.h" -#include "floppy_fdi.h" -#include "floppy_imd.h" -#include "floppy_img.h" -#include "floppy_json.h" -#include "floppy_td0.h" -#include "fdc.h" -#include "fdd.h" - - -extern int driveempty[4]; - -wchar_t floppyfns[4][512]; - -int64_t floppy_poll_time[FDD_NUM] = { 16LL, 16LL, 16LL, 16LL }; - -int floppy_track[FDD_NUM]; -int writeprot[FDD_NUM], fwriteprot[FDD_NUM]; - -DRIVE drives[FDD_NUM]; -int drive_type[FDD_NUM]; - -int curdrive = 0; - -int swwp = 0; -int disable_write = 0; - -int defaultwriteprot = 0; - -int fdc_time; -int floppy_time; - -int fdc_ready; - -int drive_empty[FDD_NUM] = {1, 1, 1, 1}; -int floppy_changed[FDD_NUM]; - -int motorspin; -int64_t motoron[FDD_NUM]; - -int fdc_indexcount = 52; - -#if 0 //FIXME: -void (*fdc_callback)(); -void (*fdc_data)(uint8_t dat); -void (*fdc_spindown)(); -void (*fdc_finishread)(); -void (*fdc_notfound)(); -void (*fdc_datacrcerror)(); -void (*fdc_headercrcerror)(); -void (*fdc_writeprotect)(); -int (*fdc_getdata)(int last); -void (*fdc_sectorid)(uint8_t track, uint8_t side, uint8_t sector, uint8_t size, uint8_t crc1, uint8_t crc2); -void (*fdc_indexpulse)(); -#endif - - -static struct -{ - wchar_t *ext; - void (*load)(int drive, wchar_t *fn); - void (*close)(int drive); - int size; -} loaders[]= -{ - {L"001", img_load, img_close, -1}, - {L"002", img_load, img_close, -1}, - {L"003", img_load, img_close, -1}, - {L"004", img_load, img_close, -1}, - {L"005", img_load, img_close, -1}, - {L"006", img_load, img_close, -1}, - {L"007", img_load, img_close, -1}, - {L"008", img_load, img_close, -1}, - {L"009", img_load, img_close, -1}, - {L"010", img_load, img_close, -1}, - {L"12", img_load, img_close, -1}, - {L"144", img_load, img_close, -1}, - {L"360", img_load, img_close, -1}, - {L"720", img_load, img_close, -1}, - {L"86F", d86f_load, d86f_close, -1}, - {L"BIN", img_load, img_close, -1}, - {L"CQ", img_load, img_close, -1}, - {L"CQM", img_load, img_close, -1}, - {L"DSK", img_load, img_close, -1}, - {L"FDI", fdi_load, fdi_close, -1}, - {L"FDF", img_load, img_close, -1}, - {L"FLP", img_load, img_close, -1}, - {L"HDM", img_load, img_close, -1}, - {L"IMA", img_load, img_close, -1}, - {L"IMD", imd_load, imd_close, -1}, - {L"IMG", img_load, img_close, -1}, - {L"JSON", json_load, json_close, -1}, - {L"TD0", td0_load, td0_close, -1}, - {L"VFD", img_load, img_close, -1}, - {L"XDF", img_load, img_close, -1}, - {0,0,0} -}; - -static int driveloaders[4]; - -void floppy_load(int drive, wchar_t *fn) -{ - int c = 0, size; - wchar_t *p; - FILE *f; - if (!fn) return; - p = plat_get_extension(fn); - if (!p) return; - f = plat_fopen(fn, L"rb"); - if (!f) return; - fseek(f, -1, SEEK_END); - size = ftell(f) + 1; - fclose(f); - while (loaders[c].ext) - { - if (!wcscasecmp(p, loaders[c].ext) && (size == loaders[c].size || loaders[c].size == -1)) - { - driveloaders[drive] = c; - memcpy(floppyfns[drive], fn, (wcslen(fn) << 1) + 2); - loaders[c].load(drive, floppyfns[drive]); - drive_empty[drive] = 0; - fdd_forced_seek(real_drive(drive), 0); - floppy_changed[drive] = 1; - return; - } - c++; - } - pclog("Couldn't load %ls %s\n",fn,p); - drive_empty[drive] = 1; - fdd_set_head(real_drive(drive), 0); - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - ui_sb_update_icon_state(drive, 1); -} - -void floppy_close(int drive) -{ - if (loaders[driveloaders[drive]].close) loaders[driveloaders[drive]].close(drive); - drive_empty[drive] = 1; - fdd_set_head(real_drive(drive), 0); - floppyfns[drive][0] = 0; - drives[drive].hole = NULL; - drives[drive].poll = NULL; - 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].byteperiod = NULL; - drives[drive].stop = NULL; - ui_sb_update_icon_state(drive, 1); -} - -int floppy_notfound=0; -static int floppy_period = 32; - -int floppy_hole(int drive) -{ - drive = real_drive(drive); - - if (drives[drive].hole) - { - return drives[drive].hole(drive); - } - else - { - return 0; - } -} - -double floppy_byteperiod(int drive) -{ - drive = real_drive(drive); - - if (drives[drive].byteperiod) - { - return drives[drive].byteperiod(drive); - } - else - { - return 32.0; - } -} - -double floppy_real_period(int drive) -{ - double ddbp; - double dusec; - - ddbp = floppy_byteperiod(real_drive(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 (fdd_get_turbo(drive)) - { - return (32.0 * dusec); - } - - if (romset == ROM_MRTHOR) - { - return (ddbp * dusec) / 4.0; - } - else - { - return (ddbp * dusec); - } -} - -void floppy_poll(int drive) -{ - if (drive >= FDD_NUM) - { - fatal("Attempting to poll floppy drive %i that is not supposed to be there\n", drive); - } - - floppy_poll_time[drive] += (int64_t) floppy_real_period(drive); - - if (drives[drive].poll) - drives[drive].poll(drive); - - if (floppy_notfound) - { - floppy_notfound--; - if (!floppy_notfound) - fdc_noidam(); - } -} - -void floppy_poll_0(void *priv) -{ - floppy_poll(0); -} - -void floppy_poll_1(void *priv) -{ - floppy_poll(1); -} - -void floppy_poll_2(void *priv) -{ - floppy_poll(2); -} - -void floppy_poll_3(void *priv) -{ - floppy_poll(3); -} - -int floppy_get_bitcell_period(int rate) -{ - int bit_rate = 250; - - switch (rate) - { - case 0: /*High density*/ - bit_rate = 500; - break; - case 1: /*Double density (360 rpm)*/ - bit_rate = 300; - break; - case 2: /*Double density*/ - bit_rate = 250; - break; - case 3: /*Extended density*/ - bit_rate = 1000; - break; - } - - return 1000000 / bit_rate*2; /*Bitcell period in ns*/ -} - - -void floppy_set_rate(int drive, int drvden, int rate) -{ - switch (rate) - { - case 0: /*High density*/ - floppy_period = 16; - break; - case 1: - switch(drvden) - { - case 0: /*Double density (360 rpm)*/ - floppy_period = 26; - break; - case 1: /*High density (360 rpm)*/ - floppy_period = 16; - break; - case 2: - floppy_period = 4; - break; - } - case 2: /*Double density*/ - floppy_period = 32; - break; - case 3: /*Extended density*/ - floppy_period = 8; - break; - } -} - -void floppy_reset() -{ - curdrive = 0; - floppy_period = 32; - timer_add(floppy_poll_0, &(floppy_poll_time[0]), &(motoron[0]), NULL); - timer_add(floppy_poll_1, &(floppy_poll_time[1]), &(motoron[1]), NULL); - timer_add(floppy_poll_2, &(floppy_poll_time[2]), &(motoron[2]), NULL); - timer_add(floppy_poll_3, &(floppy_poll_time[3]), &(motoron[3]), NULL); -} - -void floppy_init() -{ - drives[0].poll = drives[1].poll = drives[2].poll = drives[3].poll = 0; - drives[0].seek = drives[1].seek = drives[2].seek = drives[3].seek = 0; - drives[0].readsector = drives[1].readsector = drives[2].readsector = drives[3].readsector = 0; - floppy_reset(); -} - -int oldtrack[FDD_NUM] = {0, 0, 0, 0}; -void floppy_seek(int drive, int track) -{ - if (drives[drive].seek) - drives[drive].seek(drive, track); -} - -void floppy_readsector(int drive, int sector, int track, int side, int density, int sector_size) -{ - drive = real_drive(drive); - - if (drives[drive].readsector) - drives[drive].readsector(drive, sector, track, side, density, sector_size); - else - floppy_notfound = 1000; -} - -void floppy_writesector(int drive, int sector, int track, int side, int density, int sector_size) -{ - drive = real_drive(drive); - - if (drives[drive].writesector) - drives[drive].writesector(drive, sector, track, side, density, sector_size); - else - floppy_notfound = 1000; -} - -void floppy_comparesector(int drive, int sector, int track, int side, int density, int sector_size) -{ - drive = real_drive(drive); - - if (drives[drive].comparesector) - drives[drive].comparesector(drive, sector, track, side, density, sector_size); - else - floppy_notfound = 1000; -} - -void floppy_readaddress(int drive, int side, int density) -{ - drive = real_drive(drive); - - if (drives[drive].readaddress) - drives[drive].readaddress(drive, side, density); -} - -void floppy_format(int drive, int side, int density, uint8_t fill) -{ - drive = real_drive(drive); - - if (drives[drive].format) - drives[drive].format(drive, side, density, fill); - else - floppy_notfound = 1000; -} - -void floppy_stop(int drive) -{ - drive = real_drive(drive); - - if (drives[drive].stop) - drives[drive].stop(drive); -} - -void floppy_general_init(void) -{ - floppy_init(); - img_init(); - d86f_init(); - td0_init(); - imd_init(); - - floppy_load(0, floppyfns[0]); - floppy_load(1, floppyfns[1]); - floppy_load(2, floppyfns[2]); - floppy_load(3, floppyfns[3]); -} diff --git a/src/floppy/floppy.h b/src/floppy/floppy.h deleted file mode 100644 index aeb09b604..000000000 --- a/src/floppy/floppy.h +++ /dev/null @@ -1,248 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Generic floppy disk interface that communicates with the - * other handlers. - * - * Version: @(#)floppy.h 1.0.6 2017/11/04 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. - */ -#ifndef EMU_FLOPPY_H -# define EMU_FLOPPY_H - - -#define FDD_NUM 4 - - -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 side, int density); - void (*format)(int drive, int side, int density, uint8_t fill); - int (*hole)(int drive); - double (*byteperiod)(int drive); - void (*stop)(int drive); - void (*poll)(int drive); -} DRIVE; - - -extern DRIVE drives[FDD_NUM]; -extern wchar_t floppyfns[FDD_NUM][512]; -extern int driveempty[FDD_NUM]; -extern int64_t floppy_poll_time[FDD_NUM]; -extern int ui_writeprot[FDD_NUM]; - -extern int curdrive; - -extern int floppy_time; -extern int64_t floppytime; - - -extern void floppy_load(int drive, wchar_t *fn); -extern void floppy_new(int drive, char *fn); -extern void floppy_close(int drive); -extern void floppy_init(void); -extern void floppy_general_init(void); -extern void floppy_reset(void); -extern void floppy_poll(int drive); -extern void floppy_poll_0(void* priv); -extern void floppy_poll_1(void* priv); -extern void floppy_poll_2(void* priv); -extern void floppy_poll_3(void* priv); -extern void floppy_seek(int drive, int track); -extern void floppy_readsector(int drive, int sector, int track, - int side, int density, int sector_size); -extern void floppy_writesector(int drive, int sector, int track, - int side, int density, int sector_size); -extern void floppy_comparesector(int drive, int sector, int track, - int side, int density, int sector_size); -extern void floppy_readaddress(int drive, int side, int density); -extern void floppy_format(int drive, int side, int density, uint8_t fill); -extern int floppy_hole(int drive); -extern double floppy_byteperiod(int drive); -extern void floppy_stop(int drive); -extern int floppy_empty(int drive); -extern void floppy_set_rate(int drive, int drvden, int rate); - -extern void fdc_callback(void *priv); -extern int fdc_data(uint8_t dat); -extern void fdc_spindown(void); -extern void fdc_finishread(void); -extern void fdc_datacrcerror(void); -extern void fdc_headercrcerror(void); -extern void fdc_writeprotect(void); -extern int fdc_getdata(int last); -extern void fdc_sectorid(uint8_t track, uint8_t side, uint8_t sector, - uint8_t size, uint8_t crc1, uint8_t crc2); -extern void fdc_indexpulse(void); - -#if 0 -extern int fdc_time; -extern int fdc_ready; -extern int fdc_indexcount; -#endif - -extern int motorspin; -extern int64_t motoron[FDD_NUM]; - -extern int swwp; -extern int disable_write; - -extern int defaultwriteprot; - -extern int writeprot[FDD_NUM], fwriteprot[FDD_NUM]; -extern int floppy_track[FDD_NUM]; -extern int floppy_changed[FDD_NUM]; -extern int drive_empty[FDD_NUM]; -extern int drive_type[FDD_NUM]; - -/*Used in the Read A Track command. Only valid for floppy_readsector(). */ -#define SECTOR_FIRST -2 -#define SECTOR_NEXT -1 - -#if 0 -/* Bits 0-3 define byte type, bit 5 defines whether it is a per-track (0) or per-sector (1) byte, if bit 7 is set, the byte is the index hole. */ -#define BYTE_GAP0 0x00 -#define BYTE_GAP1 0x10 -#define BYTE_GAP4 0x20 -#define BYTE_GAP2 0x40 -#define BYTE_GAP3 0x50 -#define BYTE_I_SYNC 0x01 -#define BYTE_ID_SYNC 0x41 -#define BYTE_DATA_SYNC 0x51 -#define BYTE_IAM_SYNC 0x02 -#define BYTE_IDAM_SYNC 0x42 -#define BYTE_DATAAM_SYNC 0x52 -#define BYTE_IAM 0x03 -#define BYTE_IDAM 0x43 -#define BYTE_DATAAM 0x53 -#define BYTE_ID 0x44 -#define BYTE_DATA 0x54 -#define BYTE_ID_CRC 0x45 -#define BYTE_DATA_CRC 0x55 - -#define BYTE_IS_FUZZY 0x80 -#define BYTE_INDEX_HOLE 0x80 /* 1 = index hole, 0 = regular byte */ -#define BYTE_IS_SECTOR 0x40 /* 1 = per-sector, 0 = per-track */ -#define BYTE_IS_POST_TRACK 0x20 /* 1 = after all sectors, 0 = before or during all sectors */ -#define BYTE_IS_DATA 0x10 /* 1 = data, 0 = id */ -#define BYTE_TYPE 0x0F /* 5 = crc, 4 = data, 3 = address mark, 2 = address mark sync, 1 = sync, 0 = gap */ - -#define BYTE_TYPE_GAP 0x00 -#define BYTE_TYPE_SYNC 0x01 -#define BYTE_TYPE_AM_SYNC 0x02 -#define BYTE_TYPE_AM 0x03 -#define BYTE_TYPE_DATA 0x04 -#define BYTE_TYPE_CRC 0x05 -#endif - -typedef union { - uint16_t word; - uint8_t bytes[2]; -} crc_t; - -void floppy_calccrc(uint8_t byte, crc_t *crc_var); - -typedef struct -{ - uint16_t (*disk_flags)(int drive); - uint16_t (*side_flags)(int drive); - void (*writeback)(int drive); - void (*set_sector)(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n); - uint8_t (*read_data)(int drive, int side, uint16_t pos); - void (*write_data)(int drive, int side, uint16_t pos, uint8_t data); - int (*format_conditions)(int drive); - int32_t (*extra_bit_cells)(int drive, int side); - uint16_t* (*encoded_data)(int drive, int side); - void (*read_revolution)(int drive); - uint32_t (*index_hole_pos)(int drive, int side); - uint32_t (*get_raw_size)(int drive, int side); - uint8_t check_crc; -} d86f_handler_t; - -d86f_handler_t d86f_handler[FDD_NUM]; - -void d86f_common_handlers(int drive); - -int d86f_is_40_track(int drive); - -void d86f_reset_index_hole_pos(int drive, int side); - -uint16_t d86f_prepare_pretrack(int drive, int side, int iso); -uint16_t d86f_prepare_sector(int drive, int side, int prev_pos, uint8_t *id_buf, uint8_t *data_buf, int data_len, int gap2, int gap3, int deleted, int bad_crc); - -extern int gap3_sizes[5][8][48]; - -void null_writeback(int drive); -void null_write_data(int drive, int side, uint16_t pos, uint8_t data); -int null_format_conditions(int drive); -void d86f_unregister(int drive); - -extern uint8_t dmf_r[21]; -extern uint8_t xdf_physical_sectors[2][2]; -extern uint8_t xdf_gap3_sizes[2][2]; -extern uint16_t xdf_trackx_spos[2][8]; - -typedef struct -{ - uint8_t h; - uint8_t r; -} xdf_id_t; - -typedef union -{ - uint16_t word; - xdf_id_t id; -} xdf_sector_t; - -extern xdf_sector_t xdf_img_layout[2][2][46]; -extern xdf_sector_t xdf_disk_layout[2][2][38]; - -uint32_t td0_get_raw_tsize(int side_flags, int slower_rpm); - -void d86f_set_track_pos(int drive, uint32_t track_pos); - -int32_t null_extra_bit_cells(int drive, int side); -uint16_t* common_encoded_data(int drive, int side); - -void common_read_revolution(int drive); -void null_set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n); - -uint32_t null_index_hole_pos(int drive, int side); - -uint32_t common_get_raw_size(int drive, int side); - -typedef struct -{ - uint8_t c; - uint8_t h; - uint8_t r; - uint8_t n; -} sector_id_fields_t; - -typedef union -{ - uint32_t dword; - uint8_t byte_array[4]; - 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_FLOPPY_H*/ diff --git a/src/floppy/floppy_common.h b/src/floppy/floppy_common.h deleted file mode 100644 index f8972d6e3..000000000 --- a/src/floppy/floppy_common.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Shared code for all the floppy modules. - * - * Version: @(#)floppy_common.h 1.0.1 2017/09/10 - * - * Author: Fred N. van Kempen, - * Copyright 2017 Fred N. van Kempen. - */ -#ifndef FLOPPY_COMMON_H -# define FLOPPY_COMMON_H - - -extern uint8_t floppy_holes[6]; -extern uint8_t floppy_rates[6]; -extern double floppy_bit_rates_300[6]; -extern uint8_t floppy_max_sectors[8][6]; -extern uint8_t floppy_dmf_r[21]; - - -extern int floppy_get_gap3_size(int rate, int size, int sector); -extern uint8_t floppy_sector_size_code(int size); -extern int floppy_sector_code_size(uint8_t code); -extern int floppy_bps_valid(uint16_t bps); -extern int floppy_interleave(int sector, int skew, int spt); - - -#endif /*FLOPPY_COMMON_H*/ diff --git a/src/keyboard_at.c b/src/keyboard_at.c index da1d3ebfa..cf9861ea8 100644 --- a/src/keyboard_at.c +++ b/src/keyboard_at.c @@ -8,15 +8,15 @@ * * Intel 8042 (AT keyboard controller) emulation. * - * Version: @(#)keyboard_at.c 1.0.22 2018/01/09 + * Version: @(#)keyboard_at.c 1.0.24 2018/01/17 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * * Copyright 2008-2018 Sarah Walker. - * Copyright 2016,2018 Miran Grca. - * Copyright 2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. */ #include #include @@ -37,7 +37,7 @@ #include "timer.h" #include "machine/machine.h" #include "machine/m_at_t3100e.h" -#include "floppy/floppy.h" +#include "floppy/fdd.h" #include "floppy/fdc.h" #include "sound/sound.h" #include "sound/snd_speaker.h" @@ -936,8 +936,6 @@ kbd_output_write(atkbd_t *kbd, uint8_t val) static void kbd_cmd_write(atkbd_t *kbd, uint8_t val) { - uint8_t temp_op = kbd->output_port; - kbdlog("Write command byte: %02X (old: %02X)\n", val, kbd->mem[0]); if ((val & 1) && (kbd->status & STAT_OFULL)) @@ -959,9 +957,6 @@ kbd_cmd_write(atkbd_t *kbd, uint8_t val) kbdlog("ATkbd: keyboard is now %s\n", mouse_scan ? "enabled" : "disabled"); kbdlog("ATkbd: keyboard interrupt is now %s\n", (val & 0x01) ? "enabled" : "disabled"); - temp_op &= 0xbf; - temp_op |= (keyboard_scan ? 0x40 : 0x00); - /* ISA AT keyboard controllers use bit 5 for keyboard mode (1 = PC/XT, 2 = AT); PS/2 (and EISA/PCI) keyboard controllers use it as the PS/2 mouse enable switch. */ if ((kbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) { @@ -970,9 +965,6 @@ kbd_cmd_write(atkbd_t *kbd, uint8_t val) mouse_scan = !(val & 0x20); kbdlog("ATkbd: mouse is now %s\n", mouse_scan ? "enabled" : "disabled"); - temp_op &= 0xf7; - temp_op |= (mouse_scan ? 0x08 : 0x00); - kbdlog("ATkbd: mouse interrupt is now %s\n", (val & 0x02) ? "enabled" : "disabled"); } @@ -1033,21 +1025,24 @@ kbd_write64_generic(void *p, uint8_t val) kbdlog("ATkbd: check if password installed\n"); kbd_adddata(0xf1); return 0; - } + } else + kbdlog("ATkbd: bad command A4\n"); break; case 0xa7: /*Disable mouse port*/ if ((kbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) { kbdlog("ATkbd: disable mouse port\n"); kbd_mouse_set(kbd, 0); return 0; - } + } else + kbdlog("ATkbd: bad command A7\n"); break; case 0xa8: /*Enable mouse port*/ if ((kbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) { kbdlog("ATkbd: enable mouse port\n"); kbd_mouse_set(kbd, 1); return 0; - } + } else + kbdlog("ATkbd: bad command A8\n"); break; case 0xa9: /*Test mouse port*/ kbdlog("ATkbd: test mouse port\n"); @@ -1057,7 +1052,9 @@ kbd_write64_generic(void *p, uint8_t val) else kbd_adddata(0xff); /*no mouse*/ return 0; - } + } else + kbdlog("ATkbd: bad command A9\n"); + break; case 0xaf: /*Read keyboard version*/ kbdlog("ATkbd: read keyboard version\n"); kbd_adddata(0x00); @@ -1475,10 +1472,13 @@ kbd_write(uint16_t port, uint8_t val, void *priv) case 0xd4: /*Write to mouse*/ kbdlog("ATkbd: write to mouse (%02X)\n", val); kbd_mouse_set(kbd, 1); - if (mouse_write && ((kbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1)) + if (mouse_write && ((kbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1)) { + pclog("Mouse write\n"); mouse_write(val, mouse_p); - else if (!mouse_write && ((kbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1)) + } else if (!mouse_write && ((kbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1)) { + pclog("Adding 0xFF to queue\n"); keyboard_at_adddata_mouse(0xff); + } break; default: @@ -1786,6 +1786,7 @@ kbd_read(uint16_t port, void *priv) switch (port) { case 0x60: ret = kbd->out; + pclog("Reading: %02X\n", ret); kbd->status &= ~(STAT_OFULL); picintc(kbd->last_irq); kbd->last_irq = 0; @@ -1806,7 +1807,9 @@ kbd_read(uint16_t port, void *priv) case 0x64: ret = (kbd->status & 0xFB) | (keyboard_mode & CCB_SYSTEM); ret |= STAT_LOCK; - kbd->status &= ~(STAT_RTIMEOUT | STAT_TTIMEOUT); + /* The transmit timeout (TTIMEOUT) flag should *NOT* be cleared, otherwise + the IBM PS/2 Model 80's BIOS gives error 8601 (mouse error). */ + kbd->status &= ~(STAT_RTIMEOUT/* | STAT_TTIMEOUT*/); break; } @@ -2035,6 +2038,7 @@ keyboard_at_adddata_keyboard_raw(uint8_t val) void keyboard_at_adddata_mouse(uint8_t val) { + pclog("Adding mouse data: %02X\n", val); mouse_queue[mouse_queue_end] = val; mouse_queue_end = (mouse_queue_end + 1) & 0xf; } diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index df38e44da..0b85bb549 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -32,15 +32,15 @@ * in alpha mode, but in highres ("ECD350") mode, it displays * some semi-random junk. Video-memory pointer maybe? * - * Version: @(#)m_amstrad.c 1.0.5 2018/01/09 + * Version: @(#)m_amstrad.c 1.0.5 2018/01/16 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * * Copyright 2008-2018 Sarah Walker. - * Copyright 2016,2018 Miran Grca. - * Copyright 2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. */ #include #include @@ -63,7 +63,6 @@ #include "../mouse.h" #include "../game/gameport.h" #include "../lpt.h" -#include "../floppy/floppy.h" #include "../floppy/fdd.h" #include "../floppy/fdc.h" #include "../sound/sound.h" @@ -1274,5 +1273,5 @@ machine_amstrad_init(machine_t *model) if (joystick_type != 7) device_add(&gameport_device); - fdc_set_dskchg_activelow(); + device_add(&fdc_xt_amstrad_device); } diff --git a/src/machine/m_at_4gpv31.c b/src/machine/m_at_4gpv31.c index 8acd9307f..c8d3d8215 100644 --- a/src/machine/m_at_4gpv31.c +++ b/src/machine/m_at_4gpv31.c @@ -11,10 +11,10 @@ * NOTE: The NEAT 82c206 code should be moved into a 82c206 module, * so it can be re-used by other boards. * - * Version: @(#)m_4gpv31.c 1.0.3 2018/01/04 + * Version: @(#)m_4gpv31.c 1.0.4 2018/01/16 * * Author: Fred N. van Kempen, - * Copyright 2018 Fred N. van Kempen. + * Copyright 2017,2018 Fred N. van Kempen. */ #include #include @@ -25,6 +25,8 @@ #include "../io.h" #include "../device.h" #include "../keyboard.h" +#include "../floppy/fdd.h" +#include "../floppy/fdc.h" #include "machine.h" @@ -145,6 +147,7 @@ machine_at_4gpv31_init(machine_t *model) { machine_at_common_ide_init(model); device_add(&keyboard_at_ami_device); + device_add(&fdc_at_device); neat_init(); } diff --git a/src/machine/m_at_ali1429.c b/src/machine/m_at_ali1429.c index 9a8bcb926..aadec2a14 100644 --- a/src/machine/m_at_ali1429.c +++ b/src/machine/m_at_ali1429.c @@ -11,6 +11,8 @@ #include "../mem.h" #include "../device.h" #include "../keyboard.h" +#include "../floppy/fdd.h" +#include "../floppy/fdc.h" #include "../disk/hdc.h" #include "../disk/hdc_ide.h" #include "machine.h" @@ -101,7 +103,9 @@ machine_at_ali1429_init(machine_t *model) ali1429_reset(); machine_at_common_ide_init(model); + device_add(&keyboard_at_ami_device); + device_add(&fdc_at_device); ali1429_init(); diff --git a/src/machine/m_at_commodore.c b/src/machine/m_at_commodore.c index 9b7689ba8..ea5eb8fcc 100644 --- a/src/machine/m_at_commodore.c +++ b/src/machine/m_at_commodore.c @@ -3,9 +3,12 @@ #include #include #include "../86box.h" +#include "../device.h" #include "../io.h" #include "../lpt.h" #include "../serial.h" +#include "../floppy/fdd.h" +#include "../floppy/fdc.h" #include "machine.h" @@ -46,6 +49,7 @@ void machine_at_cmdpc_init(machine_t *model) { machine_at_ide_top_remap_init(model); + device_add(&fdc_at_device); cbm_io_init(); } diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index 6c1090c05..0bb79f561 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -8,14 +8,14 @@ * * Emulation of various Compaq PC's. * - * Version: @(#)m_at_compaq.c 1.0.2 2017/12/29 + * Version: @(#)m_at_compaq.c 1.0.3 2018/01/16 * * Authors: Sarah Walker, * Miran Grca, * TheCollector1995, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -26,6 +26,8 @@ #include "../mem.h" #include "../rom.h" #include "../device.h" +#include "../floppy/fdd.h" +#include "../floppy/fdc.h" #include "../disk/hdc.h" #include "../disk/hdc_ide.h" #include "machine.h" @@ -99,6 +101,7 @@ void machine_at_compaq_init(machine_t *model) { machine_at_top_remap_init(model); + device_add(&fdc_at_device); mem_mapping_add(&ram_mapping, 0xfa0000, 0x60000, read_ram, read_ramw, read_raml, diff --git a/src/machine/m_at_headland.c b/src/machine/m_at_headland.c index bfbb473e6..a8997e1a6 100644 --- a/src/machine/m_at_headland.c +++ b/src/machine/m_at_headland.c @@ -12,6 +12,8 @@ #include "../device.h" #include "../keyboard.h" #include "../mem.h" +#include "../floppy/fdd.h" +#include "../floppy/fdc.h" #include "machine.h" @@ -71,7 +73,9 @@ void machine_at_headland_init(machine_t *model) { machine_at_common_ide_init(model); + device_add(&keyboard_at_ami_device); + device_add(&fdc_at_device); headland_init(); } diff --git a/src/machine/m_at_neat.c b/src/machine/m_at_neat.c index 5c5ccd4bf..89baf7e17 100644 --- a/src/machine/m_at_neat.c +++ b/src/machine/m_at_neat.c @@ -10,6 +10,8 @@ #include "../device.h" #include "../io.h" #include "../keyboard.h" +#include "../floppy/fdd.h" +#include "../floppy/fdc.h" #include "machine.h" @@ -89,6 +91,7 @@ void machine_at_neat_init(machine_t *model) { machine_at_init(model); + device_add(&fdc_at_device); neat_init(); } @@ -98,7 +101,9 @@ void machine_at_neat_ami_init(machine_t *model) { machine_at_common_init(model); + device_add(&keyboard_at_ami_device); + device_add(&fdc_at_device); neat_init(); } diff --git a/src/machine/m_at_opti495.c b/src/machine/m_at_opti495.c index 23f599554..5db7ca55f 100644 --- a/src/machine/m_at_opti495.c +++ b/src/machine/m_at_opti495.c @@ -261,6 +261,8 @@ SeeAlso: #P0178,#P0187 #include "../device.h" #include "../keyboard.h" #include "../mem.h" +#include "../floppy/fdd.h" +#include "../floppy/fdc.h" #include "machine.h" @@ -324,7 +326,9 @@ void machine_at_opti495_init(machine_t *model) { machine_at_common_ide_init(model); + device_add(&keyboard_at_device); + device_add(&fdc_at_device); opti495_init(); } @@ -334,7 +338,9 @@ void machine_at_opti495_ami_init(machine_t *model) { machine_at_common_ide_init(model); + device_add(&keyboard_at_ami_device); + device_add(&fdc_at_device); opti495_init(); } diff --git a/src/machine/m_at_scat.c b/src/machine/m_at_scat.c index b74571c43..5ee1aaefc 100644 --- a/src/machine/m_at_scat.c +++ b/src/machine/m_at_scat.c @@ -10,20 +10,23 @@ * * Re-worked version based on the 82C235 datasheet and errata. * - * Version: @(#)m_at_scat.c 1.0.7 2018/01/05 + * Version: @(#)m_at_scat.c 1.0.8 2018/01/16 * * Authors: Original by GreatPsycho for PCem. * Fred N. van Kempen, * - * Copyright 2018 Fred N. van Kempen. + * Copyright 2017,2018 Fred N. van Kempen. */ #include #include #include #include #include "../86box.h" +#include "../device.h" #include "../cpu/cpu.h" #include "../cpu/x86.h" +#include "../floppy/fdd.h" +#include "../floppy/fdc.h" #include "../io.h" #include "../mem.h" #include "machine.h" @@ -736,6 +739,7 @@ void machine_at_scat_init(machine_t *model) { machine_at_init(model); + device_add(&fdc_at_device); scat_init(); } diff --git a/src/machine/m_at_sis_85c471.c b/src/machine/m_at_sis_85c471.c index c2004e085..c3f6b47fc 100644 --- a/src/machine/m_at_sis_85c471.c +++ b/src/machine/m_at_sis_85c471.c @@ -9,11 +9,11 @@ * SiS sis85c471 Super I/O Chip * Used by DTK PKM-0038S E-2 * - * Version: @(#)m_at_sis85c471.c 1.0.8 2017/11/04 + * Version: @(#)m_at_sis85c471.c 1.0.9 2018/01/16 * * Author: Miran Grca, * - * Copyright 2017 Miran Grca. + * Copyright 2015-2018 Miran Grca. */ #include #include @@ -27,9 +27,8 @@ #include "../serial.h" #include "../disk/hdc.h" #include "../disk/hdc_ide.h" -#include "../floppy/floppy.h" -#include "../floppy/fdc.h" #include "../floppy/fdd.h" +#include "../floppy/fdc.h" #include "machine.h" @@ -236,9 +235,6 @@ static void sis_85c471_init(void) sis_85c471_regs[0x23] = 0xF0; sis_85c471_regs[0x26] = 1; - fdc_update_densel_polarity(1); - fdc_update_densel_force(0); - fdd_swap = 0; io_sethandler(0x0022, 0x0002, sis_85c471_read, NULL, NULL, sis_85c471_write, NULL, NULL, NULL); } @@ -247,6 +243,7 @@ void machine_at_dtk486_init(machine_t *model) { machine_at_ide_init(model); + device_add(&fdc_at_device); memregs_init(); sis_85c471_init(); diff --git a/src/machine/m_at_t3100e.c b/src/machine/m_at_t3100e.c index 5e49e8278..7327cd23d 100644 --- a/src/machine/m_at_t3100e.c +++ b/src/machine/m_at_t3100e.c @@ -12,6 +12,7 @@ #include "../keyboard.h" #include "../cpu/cpu.h" #include "../floppy/fdd.h" +#include "../floppy/fdc.h" #include "../video/vid_t3100e.h" #include "machine.h" @@ -685,7 +686,9 @@ void machine_at_t3100e_init(machine_t *model) memset(&t3100e_ems, 0, sizeof(t3100e_ems)); machine_at_common_ide_init(model); + device_add(&keyboard_at_toshiba_device); + device_add(&fdc_at_device); /* Hook up system control port */ io_sethandler(0x8084, 0x0001, diff --git a/src/machine/m_at_wd76c10.c b/src/machine/m_at_wd76c10.c index 18096a408..1e1f3ac1f 100644 --- a/src/machine/m_at_wd76c10.c +++ b/src/machine/m_at_wd76c10.c @@ -11,7 +11,7 @@ #include "../keyboard.h" #include "../mem.h" #include "../serial.h" -#include "../floppy/floppy.h" +#include "../floppy/fdd.h" #include "../floppy/fdc.h" #include "../video/vid_paradise.h" #include "machine.h" @@ -23,6 +23,9 @@ static uint16_t wd76c10_2872; static uint16_t wd76c10_5872; +static fdc_t *wd76c10_fdc; + + static uint16_t wd76c10_read(uint16_t port, void *priv) { @@ -89,9 +92,9 @@ wd76c10_write(uint16_t port, uint16_t val, void *priv) case 0x2872: wd76c10_2872 = val; - fdc_remove(); + fdc_remove(wd76c10_fdc); if (!(val & 1)) - fdc_add(); + fdc_set_base(wd76c10_fdc, 0x03f0); break; case 0x5872: @@ -142,7 +145,9 @@ void machine_at_wd76c10_init(machine_t *model) { machine_at_common_ide_init(model); + device_add(&keyboard_ps2_quadtel_device); + wd76c10_fdc = device_add(&fdc_at_device); wd76c10_init(); diff --git a/src/machine/m_europc.c b/src/machine/m_europc.c index a417a3eda..614ef122a 100644 --- a/src/machine/m_europc.c +++ b/src/machine/m_europc.c @@ -67,7 +67,7 @@ * * WARNING THIS IS A WORK-IN-PROGRESS MODULE. USE AT OWN RISK. * - * Version: @(#)europc.c 1.0.5 2017/11/18 + * Version: @(#)europc.c 1.0.6 2018/01/16 * * Author: Fred N. van Kempen, * @@ -76,7 +76,7 @@ * Schneider's schematics and technical manuals, and the * input from people with real EuroPC hardware. * - * Copyright 2017 Fred N. van Kempen. + * Copyright 2017,2018 Fred N. van Kempen. */ #include #include @@ -90,6 +90,8 @@ #include "../rom.h" #include "../nvr.h" #include "../device.h" +#include "../floppy/fdd.h" +#include "../floppy/fdc.h" #include "../disk/hdc.h" #include "../keyboard.h" #include "../mouse.h" @@ -700,6 +702,9 @@ machine_europc_init(machine_t *model) /* Initialize the actual NVR. */ nvr_init(&vm->nvr); + /* Enable and set up the FDC. */ + device_add(&fdc_xt_device); + /* Enable and set up the mainboard device. */ device_add(&europc_device); } diff --git a/src/machine/m_olivetti_m24.c b/src/machine/m_olivetti_m24.c index fd0ace98e..2bc8257a8 100644 --- a/src/machine/m_olivetti_m24.c +++ b/src/machine/m_olivetti_m24.c @@ -8,15 +8,15 @@ * * Emulation of the Olivetti M24. * - * Version: @(#)m_olivetti_m24.c 1.0.8 2018/01/09 + * Version: @(#)m_olivetti_m24.c 1.0.9 2018/01/16 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * * Copyright 2008-2018 Sarah Walker. - * Copyright 2016,2018 Miran Grca. - * Copyright 2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. */ #include #include @@ -36,6 +36,8 @@ #include "../nvr.h" #include "../keyboard.h" #include "../mouse.h" +#include "../floppy/fdd.h" +#include "../floppy/fdc.h" #include "../game/gameport.h" #include "../sound/sound.h" #include "../sound/snd_speaker.h" @@ -807,6 +809,7 @@ machine_olim24_init(machine_t *model) memset(m24, 0x00, sizeof(olim24_t)); machine_common_init(model); + device_add(&fdc_xt_device); io_sethandler(0x0066, 2, m24_read, NULL, NULL, NULL, NULL, NULL, m24); diff --git a/src/machine/m_pcjr.c b/src/machine/m_pcjr.c index 1dc18c8ba..1a59c2cb6 100644 --- a/src/machine/m_pcjr.c +++ b/src/machine/m_pcjr.c @@ -8,15 +8,15 @@ * * Emulation of the IBM PCjr. * - * Version: @(#)m_pcjr.c 1.0.3 2018/01/09 + * Version: @(#)m_pcjr.c 1.0.4 2018/01/16 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * * Copyright 2008-2018 Sarah Walker. - * Copyright 2016,2018 Miran Grca. - * Copyright 2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. */ #include #include @@ -34,9 +34,8 @@ #include "../device.h" #include "../serial.h" #include "../keyboard.h" -#include "../floppy/floppy.h" -#include "../floppy/fdc.h" #include "../floppy/fdd.h" +#include "../floppy/fdc.h" #include "../sound/sound.h" #include "../sound/snd_speaker.h" #include "../sound/snd_sn76489.h" @@ -765,9 +764,9 @@ machine_pcjr_init(machine_t *model) keyboard_set_table(scancode_xt); keyboard_send = kbd_adddata_ex; - fdc_add_pcjr(); - device_add(&sn76489_device); nmi_mask = 0x80; + + device_add(&fdc_pcjr_device); } diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index 216108ab0..afa9a9588 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -28,15 +28,15 @@ * boot. Sometimes, they do, and then it shows an "Incorrect * DOS" error message?? --FvK * - * Version: @(#)m_ps1.c 1.0.4 2018/01/04 + * Version: @(#)m_ps1.c 1.0.5 2018/01/16 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * * Copyright 2008-2018 Sarah Walker. - * Copyright 2016,2018 Miran Grca. - * Copyright 2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. */ #include #include @@ -61,7 +61,6 @@ #include "../keyboard.h" #include "../disk/hdc.h" #include "../disk/hdc_ide.h" -#include "../floppy/floppy.h" #include "../floppy/fdd.h" #include "../floppy/fdc.h" #include "../sound/sound.h" @@ -554,8 +553,13 @@ ps1_common_init(machine_t *model) device_add(&keyboard_ps2_device); - if (romset != ROM_IBMPS1_2133) { - fdc_set_dskchg_activelow(); + if (romset == ROM_IBMPS1_2133) + device_add(&fdc_at_device); + else { + if ((romset == ROM_IBMPS1_2121) || (romset == ROM_IBMPS1_2121_ISA)) + device_add(&fdc_at_ps1_device); + else + device_add(&fdc_at_actlow_device); device_add(&snd_device); } @@ -580,8 +584,6 @@ machine_ps1_m2121_init(machine_t *model) ps1_common_init(model); ps1_setup(2121); - - fdc_set_ps1(); } diff --git a/src/machine/m_ps2_isa.c b/src/machine/m_ps2_isa.c index 9b9e6c6fc..8f9c1906d 100644 --- a/src/machine/m_ps2_isa.c +++ b/src/machine/m_ps2_isa.c @@ -15,7 +15,6 @@ #include "../keyboard.h" #include "../lpt.h" #include "../serial.h" -#include "../floppy/floppy.h" #include "../floppy/fdd.h" #include "../floppy/fdc.h" #include "../video/vid_vga.h" @@ -152,6 +151,7 @@ void machine_ps2_m30_286_init(machine_t *model) { machine_common_init(model); + device_add(&fdc_at_ps1_device); pit_set_out_func(&pit, 1, pit_refresh_timer_at); dma16_init(); @@ -159,7 +159,5 @@ machine_ps2_m30_286_init(machine_t *model) nvr_at_init(8); pic2_init(); ps2board_init(); - fdc_set_dskchg_activelow(); - fdc_set_ps1(); device_add(&ps1vga_device); } diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index c4641ff89..8d4d77d2b 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -14,6 +14,8 @@ #include "../nmi.h" #include "../rom.h" #include "../device.h" +#include "../floppy/fdd.h" +#include "../floppy/fdc.h" #include "../nvr.h" #include "../nvr_ps2.h" #include "../keyboard.h" @@ -790,6 +792,7 @@ static void machine_ps2_common_init(machine_t *model) { machine_common_init(model); + device_add(&fdc_at_device); dma16_init(); ps2_dma_init(); diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index c34c5cc5d..ea6e01934 100644 --- a/src/machine/m_tandy.c +++ b/src/machine/m_tandy.c @@ -8,13 +8,13 @@ * * Emulation of Tandy models 1000, 1000HX and 1000SL2. * - * Version: @(#)m_tandy.c 1.0.1 2018/01/10 + * Version: @(#)m_tandy.c 1.0.2 2018/01/16 * * Authors: Sarah Walker, * Miran Grca, * * Copyright 2008-2018 Sarah Walker. - * Copyright 2016,2018 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -31,6 +31,8 @@ #include "../timer.h" #include "../device.h" #include "../nvr.h" +#include "../floppy/fdd.h" +#include "../floppy/fdc.h" #include "../game/gameport.h" #include "../keyboard.h" #include "../sound/sound.h" @@ -1688,6 +1690,8 @@ machine_tandy1k_init(machine_t *model) device_add(&keyboard_tandy_device); keyboard_set_table(scancode_tandy); + device_add(&fdc_xt_device); + switch(romset) { case ROM_TANDY: io_sethandler(0x00a0, 1, diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index d8bb9bba5..bb4ef2fb1 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -7,6 +7,8 @@ #include "../pit.h" #include "../mem.h" #include "../device.h" +#include "../floppy/fdd.h" +#include "../floppy/fdc.h" #include "../game/gameport.h" #include "../keyboard.h" #include "machine.h" @@ -20,6 +22,7 @@ machine_xt_init(machine_t *model) pit_set_out_func(&pit, 1, pit_refresh_timer_xt); device_add(&keyboard_xt_device); + device_add(&fdc_xt_device); nmi_init(); if (joystick_type != 7) device_add(&gameport_device); diff --git a/src/machine/m_xt_compaq.c b/src/machine/m_xt_compaq.c index c72aca1a8..50941ef7b 100644 --- a/src/machine/m_xt_compaq.c +++ b/src/machine/m_xt_compaq.c @@ -8,14 +8,14 @@ * * Emulation of various Compaq XT-class PC's. * - * Version: @(#)m_xt_compaq.c 1.0.1 2017/11/11 + * Version: @(#)m_xt_compaq.c 1.0.2 2018/01/16 * * Authors: Sarah Walker, * Miran Grca, * TheCollector1995, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -28,6 +28,8 @@ #include "../mem.h" #include "../rom.h" #include "../device.h" +#include "../floppy/fdd.h" +#include "../floppy/fdc.h" #include "../game/gameport.h" #include "../keyboard.h" #include "machine.h" @@ -41,6 +43,7 @@ machine_xt_compaq_init(machine_t *model) pit_set_out_func(&pit, 1, pit_refresh_timer_xt); device_add(&keyboard_xt_device); + device_add(&fdc_xt_device); nmi_init(); if (joystick_type != 7) device_add(&gameport_device); diff --git a/src/machine/machine.c b/src/machine/machine.c index 912785fef..d43707b4f 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -8,7 +8,7 @@ * * Handling of the emulated machines. * - * Version: @(#)machine.c 1.0.28 2018/01/01 + * Version: @(#)machine.c 1.0.29 2018/01/16 * * Authors: Sarah Walker, * Miran Grca, @@ -16,7 +16,7 @@ * * Copyright 2008-2018 Sarah Walker. * Copyright 2016-2018 Miran Grca. - * Copyright 2018 Fred N. van Kempen. + * Copyright 2017,2018 Fred N. van Kempen. */ #include #include @@ -31,9 +31,6 @@ #include "../rom.h" #include "../lpt.h" #include "../serial.h" -#include "../floppy/floppy.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" #include "../disk/hdc.h" #include "../disk/hdc_ide.h" #include "machine.h" @@ -80,6 +77,4 @@ machine_common_init(machine_t *model) if (serial_enabled[1]) serial_setup(2, SERIAL2_ADDR, SERIAL2_IRQ); - - fdc_add(); } diff --git a/src/mem.c b/src/mem.c index 8ddddffdf..42ae7f775 100644 --- a/src/mem.c +++ b/src/mem.c @@ -256,6 +256,34 @@ int mmu_page_fault_check(uint32_t addr, int rw, uint32_t flags, int pde, int is_ #define PAGE_DIRTY 0x40 #define PAGE_ACCESSED 0x20 +/* This is needed so that mmutranslate reads things from the correct place + if it has to read something from a remapped mapping. */ +uint32_t mem_readl_phys(uint32_t addr) +{ + uint8_t i, temp[4]; + uint32_t ta; + + for (i = 0; i < 4; i++) { + ta = addr + i; + temp[i] = _mem_exec[ta >> 14][ta & 0x3fff]; + } + + return *(uint32_t *) temp; +} + +void mem_writel_phys(uint32_t addr, uint32_t val) +{ + uint8_t i, temp[4]; + uint32_t ta; + + *(uint32_t *) temp = val; + + for (i = 0; i < 4; i++) { + ta = addr + i; + _mem_exec[ta >> 14][ta & 0x3fff] = temp[i]; + } +} + /* rw means 0 = read, 1 = write */ uint32_t mmutranslate(uint32_t addr, int rw, int is_abrt) { @@ -277,7 +305,7 @@ uint32_t mmutranslate(uint32_t addr, int rw, int is_abrt) table_addr = dir_base + ((addr >> 20) & 0xffc); /* First check the flags of the page directory entry. */ - table_flags = ((uint32_t *)ram)[table_addr >> 2]; + table_flags = mem_readl_phys(table_addr); if ((table_flags & 0x80) && (cr4 & CR4_PSE)) { @@ -291,7 +319,7 @@ uint32_t mmutranslate(uint32_t addr, int rw, int is_abrt) if (is_abrt) { mmu_perm = table_flags & 4; - ((uint32_t *)ram)[table_addr >> 2] |= (rw ? PAGE_DIRTY_AND_ACCESSED : PAGE_ACCESSED); + mem_writel_phys(table_addr, table_flags | (rw ? PAGE_DIRTY_AND_ACCESSED : PAGE_ACCESSED)); } return (table_flags & ~0x3FFFFF) + (addr & 0x3FFFFF); @@ -309,7 +337,7 @@ uint32_t mmutranslate(uint32_t addr, int rw, int is_abrt) page_addr += ((addr >> 10) & 0xffc); /* Then check the flags of the page table entry. */ - page_flags = ((uint32_t *)ram)[page_addr >> 2]; + page_flags = mem_readl_phys(page_addr); if (mmu_page_fault_check(addr, rw, page_flags & 7, 1, is_abrt) == -1) { @@ -319,8 +347,8 @@ uint32_t mmutranslate(uint32_t addr, int rw, int is_abrt) if (is_abrt) { mmu_perm = page_flags & 4; - ((uint32_t *)ram)[table_addr >> 2] |= PAGE_ACCESSED; - ((uint32_t *)ram)[page_addr >> 2] |= (rw ? PAGE_DIRTY_AND_ACCESSED : PAGE_ACCESSED); + mem_writel_phys(table_addr, table_flags | PAGE_ACCESSED); + mem_writel_phys(page_addr, page_flags | (rw ? PAGE_DIRTY_AND_ACCESSED : PAGE_ACCESSED)); } return (page_flags & ~0xFFF) + (addr & 0xFFF); @@ -947,7 +975,7 @@ uint8_t mem_readb_phys_dma(uint32_t addr) if (_mem_read_b[addr >> 14]) { if (_mem_mapping_r[addr >> 14] && (_mem_mapping_r[addr >> 14]->flags & MEM_MAPPING_INTERNAL)) { - return ram[addr]; + return _mem_exec[addr >> 14][addr & 0x3fff]; } else return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]); } @@ -980,7 +1008,7 @@ void mem_writeb_phys_dma(uint32_t addr, uint8_t val) if (_mem_write_b[addr >> 14]) { if (_mem_mapping_w[addr >> 14] && (_mem_mapping_w[addr >> 14]->flags & MEM_MAPPING_INTERNAL)) { - ram[addr] = val; + _mem_exec[addr >> 14][addr & 0x3fff] = val; } else _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]); } diff --git a/src/pc.c b/src/pc.c index 16025b36f..4dd5769ce 100644 --- a/src/pc.c +++ b/src/pc.c @@ -8,15 +8,15 @@ * * Main emulator module where most things are controlled. * - * Version: @(#)pc.c 1.0.51 2017/12/16 + * Version: @(#)pc.c 1.0.52 2018/01/16 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. - * Copyright 2017 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. */ #include #include @@ -50,7 +50,7 @@ #include "keyboard.h" #include "mouse.h" #include "game/gameport.h" -#include "floppy/floppy.h" +#include "floppy/fdd.h" #include "floppy/fdc.h" #include "disk/hdd.h" #include "disk/hdc.h" @@ -503,7 +503,7 @@ pc_reload(wchar_t *fn) config_write(cfg_path); for (i=0; iexit(i); if (cdrom_drives[i].host_drive == 200) @@ -532,10 +532,10 @@ pc_reload(wchar_t *fn) cdrom_null_open(i, cdrom_drives[i].host_drive); } - floppy_load(0, floppyfns[0]); - floppy_load(1, floppyfns[1]); - floppy_load(2, floppyfns[2]); - floppy_load(3, floppyfns[3]); + fdd_load(0, floppyfns[0]); + fdd_load(1, floppyfns[1]); + fdd_load(2, floppyfns[2]); + fdd_load(3, floppyfns[3]); mem_resize(); rom_load_bios(romset); @@ -638,9 +638,7 @@ again2: sound_reset(); - fdc_init(); - - floppy_general_init(); + fdd_init(); sound_init(); @@ -755,10 +753,6 @@ pc_reset_hard_init(void) inital(); sound_reset(); - fdc_init(); - fdc_update_is_nsc(0); - floppy_reset(); - #ifndef WALTJE_SERIAL /* This is needed to initialize the serial timer. */ serial_init(); @@ -767,6 +761,8 @@ pc_reset_hard_init(void) /* Initialize the actual machine and its basic modules. */ machine_init(); + fdd_reset(); + /* * Once the machine has been initialized, all that remains * should be resetting all devices set up for it, to their @@ -791,14 +787,11 @@ pc_reset_hard_init(void) * serial_init() doesn't break the serial mouse by resetting * the RCR callback to NULL. */ - // mouse_reset(); + mouse_reset(); /* Reset the video card. */ video_reset(gfxcard); - /* Reset the Floppy Disk controller. */ - fdc_reset(); - /* Reset the Hard Disk Controller module. */ hdc_reset(); @@ -857,8 +850,6 @@ pc_reset_hard_init(void) setpitclock(machines[machine].cpu[cpu_manufacturer].cpus[cpu].rspeed); else setpitclock(14318184.0); - - mouse_reset(); } @@ -920,7 +911,7 @@ pc_close(thread_t *ptr) cdrom_drives[i].handler->exit(i); for (i=0; i + * + * Copyright 2016-2018 Miran Grca. + */ #include #include #include #include #include "86box.h" +#include "device.h" #include "io.h" -#include "floppy/floppy.h" +#include "floppy/fdd.h" #include "floppy/fdc.h" #include "sio.h" @@ -32,8 +49,7 @@ static uint8_t superio_detect_read(uint16_t port, void *priv) void superio_detect_init(void) { - fdc_remove(); - fdc_add_for_superio(); + device_add(&fdc_at_smc_device); io_sethandler(0x24, 0x0002, superio_detect_read, NULL, NULL, superio_detect_write, NULL, NULL, NULL); io_sethandler(0x26, 0x0002, superio_detect_read, NULL, NULL, superio_detect_write, NULL, NULL, NULL); diff --git a/src/sio_fdc37c669.c b/src/sio_fdc37c669.c index 9df4558f1..ea5398020 100644 --- a/src/sio_fdc37c669.c +++ b/src/sio_fdc37c669.c @@ -8,10 +8,10 @@ * * Implementation of the SMC FDC37C669 Super I/O Chip. * - * Version: @(#)sio_fdc37c669.c 1.0.6 2017/11/04 + * Version: @(#)sio_fdc37c669.c 1.0.7 2018/01/16 * * Author: Miran Grca, - * Copyright 2016,2017 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -25,9 +25,8 @@ #include "serial.h" #include "disk/hdc.h" #include "disk/hdc_ide.h" -#include "floppy/floppy.h" -#include "floppy/fdc.h" #include "floppy/fdd.h" +#include "floppy/fdc.h" #include "sio.h" @@ -36,6 +35,7 @@ static int fdc37c669_rw_locked = 0; static int fdc37c669_curreg = 0; static uint8_t fdc37c669_regs[42]; static uint8_t tries; +static fdc_t *fdc37c669_fdc; static uint16_t make_port(uint8_t reg) { @@ -131,8 +131,8 @@ process_value: #endif if (valxor & 8) { - fdc_remove(); - if ((fdc37c669_regs[0] & 8) && (fdc37c669_regs[0x20] & 0xc0)) fdc_set_base(make_port(0x20), 1); + fdc_remove(fdc37c669_fdc); + if ((fdc37c669_regs[0] & 8) && (fdc37c669_regs[0x20] & 0xc0)) fdc_set_base(fdc37c669_fdc, make_port(0x20)); } break; case 1: @@ -174,21 +174,21 @@ process_value: } break; case 3: - if (valxor & 2) fdc_update_enh_mode((val & 2) ? 1 : 0); + if (valxor & 2) fdc_update_enh_mode(fdc37c669_fdc, (val & 2) ? 1 : 0); break; case 5: - if (valxor & 0x18) fdc_update_densel_force((val & 0x18) >> 3); - if (valxor & 0x20) fdd_swap = ((val & 0x20) >> 5); + if (valxor & 0x18) fdc_update_densel_force(fdc37c669_fdc, (val & 0x18) >> 3); + if (valxor & 0x20) fdc_set_swap(fdc37c669_fdc, (val & 0x20) >> 5); break; case 0xB: - if (valxor & 3) fdc_update_rwc(0, val & 3); - if (valxor & 0xC) fdc_update_rwc(1, (val & 0xC) >> 2); + if (valxor & 3) fdc_update_rwc(fdc37c669_fdc, 0, val & 3); + if (valxor & 0xC) fdc_update_rwc(fdc37c669_fdc, 1, (val & 0xC) >> 2); break; case 0x20: if (valxor & 0xfc) { - fdc_remove(); - if ((fdc37c669_regs[0] & 8) && (fdc37c669_regs[0x20] & 0xc0)) fdc_set_base(make_port(0x20), 1); + fdc_remove(fdc37c669_fdc); + if ((fdc37c669_regs[0] & 8) && (fdc37c669_regs[0x20] & 0xc0)) fdc_set_base(fdc37c669_fdc, make_port(0x20)); } break; case 0x21: @@ -294,10 +294,7 @@ uint8_t fdc37c669_read(uint16_t port, void *priv) void fdc37c669_reset(void) { - fdc_remove(); - fdc_add_for_superio(); - - fdc_update_is_nsc(0); + fdc_reset(fdc37c669_fdc); serial_remove(1); serial_setup(1, SERIAL1_ADDR, SERIAL1_IRQ); @@ -309,7 +306,7 @@ void fdc37c669_reset(void) lpt1_remove(); lpt1_init(0x378); - + memset(fdc37c669_regs, 0, 42); fdc37c669_regs[0] = 0x28; fdc37c669_regs[1] = 0x9C; @@ -337,15 +334,14 @@ void fdc37c669_reset(void) fdc37c669_regs[0x27] = (6 << 4) | 7; fdc37c669_regs[0x28] = (4 << 4) | 3; - fdc_update_densel_polarity(1); - fdc_update_densel_force(0); - fdd_swap = 0; fdc37c669_locked = 0; fdc37c669_rw_locked = 0; } void fdc37c669_init() { + fdc37c669_fdc = device_add(&fdc_at_smc_device); + io_sethandler(0x3f0, 0x0002, fdc37c669_read, NULL, NULL, fdc37c669_write, NULL, NULL, NULL); fdc37c669_reset(); diff --git a/src/sio_fdc37c66x.c b/src/sio_fdc37c66x.c index 8a71c7e3a..222233db4 100644 --- a/src/sio_fdc37c66x.c +++ b/src/sio_fdc37c66x.c @@ -9,13 +9,13 @@ * Implementation of the SMC FDC37C663 and FDC37C665 Super * I/O Chips. * - * Version: @(#)sio_fdc37c66x.c 1.0.9 2017/11/04 + * Version: @(#)sio_fdc37c66x.c 1.0.10 2018/01/16 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -29,9 +29,8 @@ #include "serial.h" #include "disk/hdc.h" #include "disk/hdc_ide.h" -#include "floppy/floppy.h" -#include "floppy/fdc.h" #include "floppy/fdd.h" +#include "floppy/fdc.h" #include "sio.h" @@ -39,14 +38,15 @@ static uint8_t fdc37c66x_lock[2]; static int fdc37c66x_curreg; static uint8_t fdc37c66x_regs[16]; static int com3_addr, com4_addr; +static fdc_t *fdc37c66x_fdc; static void write_lock(uint8_t val) { if (val == 0x55 && fdc37c66x_lock[1] == 0x55) - fdc_3f1_enable(0); + fdc_3f1_enable(fdc37c66x_fdc, 0); if (fdc37c66x_lock[0] == 0x55 && fdc37c66x_lock[1] == 0x55 && val != 0x55) - fdc_3f1_enable(1); + fdc_3f1_enable(fdc37c66x_fdc, 1); fdc37c66x_lock[0] = fdc37c66x_lock[1]; fdc37c66x_lock[1] = val; @@ -235,7 +235,7 @@ static void fdc37c66x_write(uint16_t port, uint8_t val, void *priv) case 3: if (valxor & 2) { - fdc_update_enh_mode((fdc37c66x_regs[3] & 2) ? 1 : 0); + fdc_update_enh_mode(fdc37c66x_fdc, (fdc37c66x_regs[3] & 2) ? 1 : 0); } break; case 5: @@ -245,11 +245,11 @@ static void fdc37c66x_write(uint16_t port, uint8_t val, void *priv) } if (valxor & 0x18) { - fdc_update_densel_force((fdc37c66x_regs[5] & 0x18) >> 3); + fdc_update_densel_force(fdc37c66x_fdc, (fdc37c66x_regs[5] & 0x18) >> 3); } if (valxor & 0x20) { - fdd_swap = ((fdc37c66x_regs[5] & 0x20) >> 5); + fdc_set_swap(fdc37c66x_fdc, (fdc37c66x_regs[5] & 0x20) >> 5); } break; } @@ -277,11 +277,6 @@ static void fdc37c66x_reset(void) com3_addr = 0x338; com4_addr = 0x238; - fdc_remove(); - fdc_add_for_superio(); - - fdc_update_is_nsc(0); - serial_remove(1); serial_setup(1, SERIAL1_ADDR, SERIAL1_IRQ); @@ -292,6 +287,8 @@ static void fdc37c66x_reset(void) lpt1_remove(); lpt1_init(0x378); + + fdc_reset(fdc37c66x_fdc); memset(fdc37c66x_lock, 0, 2); memset(fdc37c66x_regs, 0, 16); @@ -301,10 +298,6 @@ static void fdc37c66x_reset(void) fdc37c66x_regs[0x3] = 0x78; fdc37c66x_regs[0x6] = 0xff; fdc37c66x_regs[0xe] = 0x01; - - fdc_update_densel_polarity(1); - fdc_update_densel_force(0); - fdd_swap = 0; } static void fdc37c663_reset(void) @@ -321,6 +314,8 @@ static void fdc37c665_reset(void) void fdc37c663_init() { + fdc37c66x_fdc = device_add(&fdc_at_smc_device); + io_sethandler(0x03f0, 0x0002, fdc37c66x_read, NULL, NULL, fdc37c66x_write, NULL, NULL, NULL); fdc37c663_reset(); @@ -330,6 +325,8 @@ void fdc37c663_init() void fdc37c665_init() { + fdc37c66x_fdc = device_add(&fdc_at_smc_device); + io_sethandler(0x03f0, 0x0002, fdc37c66x_read, NULL, NULL, fdc37c66x_write, NULL, NULL, NULL); fdc37c665_reset(); diff --git a/src/sio_fdc37c93x.c b/src/sio_fdc37c93x.c index b7a087882..ae8206b6a 100644 --- a/src/sio_fdc37c93x.c +++ b/src/sio_fdc37c93x.c @@ -9,10 +9,10 @@ * Implementation of the SMC FDC37C932FR and FDC37C935 Super * I/O Chips. * - * Version: @(#)sio_fdc37c93x.c 1.0.10 2018/01/04 + * Version: @(#)sio_fdc37c93x.c 1.0.10 2018/01/16 * * Author: Miran Grca, - * Copyright 2016,2017 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -26,9 +26,8 @@ #include "serial.h" #include "disk/hdc.h" #include "disk/hdc_ide.h" -#include "floppy/floppy.h" -#include "floppy/fdc.h" #include "floppy/fdd.h" +#include "floppy/fdc.h" #include "sio.h" @@ -38,6 +37,7 @@ static int fdc37c93x_gpio_reg = 0; static uint8_t fdc37c93x_regs[48]; static uint8_t fdc37c93x_ld_regs[10][256]; static uint8_t fdc37c93x_gpio_base = 0x00EA; +static fdc_t *fdc37c93x_fdc; static uint8_t tries; @@ -70,14 +70,14 @@ static void fdc37c93x_fdc_handler(void) uint8_t global_enable = !!(fdc37c93x_regs[0x22] & (1 << 0)); uint8_t local_enable = !!fdc37c93x_ld_regs[0][0x30]; - fdc_remove(); + fdc_remove(fdc37c93x_fdc); /* pclog("fdc37c93x: Removing FDC (%i, %i)\n", global_enable, local_enable); */ if (global_enable && local_enable) { ld_port = make_port(0); /* pclog("fdc37c93x: Setting FDC port to %04X\n", ld_port); */ if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) { - fdc_set_base(ld_port, 1); + fdc_set_base(fdc37c93x_fdc, ld_port); } } } @@ -216,7 +216,7 @@ static void fdc37c93x_write(uint16_t port, uint8_t val, void *priv) if (tries) { fdc37c93x_locked = 1; - fdc_3f1_enable(0); + fdc_3f1_enable(fdc37c93x_fdc, 0); tries = 0; } else @@ -231,7 +231,7 @@ static void fdc37c93x_write(uint16_t port, uint8_t val, void *priv) if (val == 0xaa) { fdc37c93x_locked = 0; - fdc_3f1_enable(1); + fdc_3f1_enable(fdc37c93x_fdc, 1); return; } fdc37c93x_curreg = val; @@ -306,29 +306,29 @@ process_value: } break; case 0xF0: - if (valxor & 0x01) fdc_update_enh_mode(val & 0x01); - if (valxor & 0x10) fdd_swap = ((val & 0x10) >> 4); + if (valxor & 0x01) fdc_update_enh_mode(fdc37c93x_fdc, val & 0x01); + if (valxor & 0x10) fdc_set_swap(fdc37c93x_fdc, (val & 0x10) >> 4); break; case 0xF1: - if (valxor & 0xC) fdc_update_densel_force((val & 0xC) >> 2); + if (valxor & 0xC) fdc_update_densel_force(fdc37c93x_fdc, (val & 0xC) >> 2); break; case 0xF2: - if (valxor & 0xC0) fdc_update_rwc(3, (valxor & 0xC0) >> 6); - if (valxor & 0x30) fdc_update_rwc(2, (valxor & 0x30) >> 4); - if (valxor & 0x0C) fdc_update_rwc(1, (valxor & 0x0C) >> 2); - if (valxor & 0x03) fdc_update_rwc(0, (valxor & 0x03)); + if (valxor & 0xC0) fdc_update_rwc(fdc37c93x_fdc, 3, (valxor & 0xC0) >> 6); + if (valxor & 0x30) fdc_update_rwc(fdc37c93x_fdc, 2, (valxor & 0x30) >> 4); + if (valxor & 0x0C) fdc_update_rwc(fdc37c93x_fdc, 1, (valxor & 0x0C) >> 2); + if (valxor & 0x03) fdc_update_rwc(fdc37c93x_fdc, 0, (valxor & 0x03)); break; case 0xF4: - if (valxor & 0x18) fdc_update_drvrate(0, (val & 0x18) >> 3); + if (valxor & 0x18) fdc_update_drvrate(fdc37c93x_fdc, 0, (val & 0x18) >> 3); break; case 0xF5: - if (valxor & 0x18) fdc_update_drvrate(1, (val & 0x18) >> 3); + if (valxor & 0x18) fdc_update_drvrate(fdc37c93x_fdc, 1, (val & 0x18) >> 3); break; case 0xF6: - if (valxor & 0x18) fdc_update_drvrate(2, (val & 0x18) >> 3); + if (valxor & 0x18) fdc_update_drvrate(fdc37c93x_fdc, 2, (val & 0x18) >> 3); break; case 0xF7: - if (valxor & 0x18) fdc_update_drvrate(3, (val & 0x18) >> 3); + if (valxor & 0x18) fdc_update_drvrate(fdc37c93x_fdc, 3, (val & 0x18) >> 3); break; } break; @@ -428,7 +428,7 @@ static uint8_t fdc37c93x_read(uint16_t port, void *priv) } else { - if ((fdc37c93x_regs[7] == 0) && (fdc37c93x_curreg == 0xF2)) return (fdc_get_rwc(0) | (fdc_get_rwc(1) << 2)); + if ((fdc37c93x_regs[7] == 0) && (fdc37c93x_curreg == 0xF2)) return (fdc_get_rwc(fdc37c93x_fdc, 0) | (fdc_get_rwc(fdc37c93x_fdc, 1) << 2)); return fdc37c93x_ld_regs[fdc37c93x_regs[7]][fdc37c93x_curreg]; } } @@ -521,22 +521,17 @@ static void fdc37c93x_reset(void) /* Logical device 9: ACCESS.bus */ - fdc_update_densel_force(0); - fdd_swap = 0; - fdc_update_rwc(0, 0); - fdc_update_rwc(1, 0); - fdc_update_rwc(2, 0); - fdc_update_rwc(3, 0); - fdc_update_drvrate(0, 0); - fdc_update_drvrate(1, 0); - fdc_update_drvrate(2, 0); - fdc_update_drvrate(3, 0); - fdc_update_max_track(79); - io_removehandler(fdc37c93x_gpio_base, 0x0001, fdc37c93x_gpio_read, NULL, NULL, fdc37c93x_gpio_write, NULL, NULL, NULL); fdc37c93x_gpio_base = 0x00EA; io_sethandler(fdc37c93x_gpio_base, 0x0001, fdc37c93x_gpio_read, NULL, NULL, fdc37c93x_gpio_write, NULL, NULL, NULL); + fdc37c93x_lpt_handler(); + fdc37c93x_serial_handler(1); + fdc37c93x_serial_handler(2); + fdc37c93x_auxio_handler(); + + fdc_reset(fdc37c93x_fdc); + fdc37c93x_locked = 0; } @@ -545,6 +540,8 @@ static void fdc37c932fr_reset(void) fdc37c93x_reset(); fdc37c93x_regs[0x20] = 3; + + fdc37c932fr_access_bus_handler(); } static void fdc37c935_reset(void) @@ -558,8 +555,7 @@ static void fdc37c93x_init(void) { lpt2_remove(); - fdc_remove(); - fdc_add_for_superio(); + fdc37c93x_fdc = device_add(&fdc_at_smc_device); fdc37c93x_gpio_reg = 0xFD; diff --git a/src/sio_pc87306.c b/src/sio_pc87306.c index 947c7c27c..b99be40fd 100644 --- a/src/sio_pc87306.c +++ b/src/sio_pc87306.c @@ -8,10 +8,10 @@ * * Emulation of the NatSemi PC87306 Super I/O chip. * - * Version: @(#)sio_pc87306.c 1.0.8 2018/01/12 + * Version: @(#)sio_pc87306.c 1.0.8 2018/01/16 * * Author: Miran Grca, - * Copyright 2016,2018 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -25,15 +25,15 @@ #include "serial.h" #include "disk/hdc.h" #include "disk/hdc_ide.h" -#include "floppy/floppy.h" -#include "floppy/fdc.h" #include "floppy/fdd.h" +#include "floppy/fdc.h" #include "sio.h" static int pc87306_curreg; static uint8_t pc87306_regs[29]; static uint8_t pc87306_gpio[2] = {0xFF, 0xFB}; +static fdc_t *pc87306_fdc; static uint8_t tries; static uint16_t lpt_port; @@ -234,10 +234,10 @@ process_value: } if (valxor & 0x28) { - fdc_remove(); + fdc_remove(pc87306_fdc); if (val & 8) { - fdc_set_base((val & 0x20) ? 0x370 : 0x3f0, 0); + fdc_set_base(pc87306_fdc, (val & 0x20) ? 0x370 : 0x3f0); } } if (valxor & 0xc0) @@ -304,7 +304,7 @@ process_value: lpt1_remove(); serial_remove(1); serial_remove(2); - fdc_remove(); + fdc_remove(pc87306_fdc); } else { @@ -322,7 +322,7 @@ process_value: } if (pc87306_regs[0] & 8) { - fdc_set_base((pc87306_regs[0] & 0x20) ? 0x370 : 0x3f0, 0); + fdc_set_base(pc87306_fdc, (pc87306_regs[0] & 0x20) ? 0x370 : 0x3f0); } } } @@ -330,8 +330,8 @@ process_value: case 9: if (valxor & 0x44) { - fdc_update_enh_mode((val & 4) ? 1 : 0); - fdc_update_densel_polarity((val & 0x40) ? 1 : 0); + fdc_update_enh_mode(pc87306_fdc, (val & 4) ? 1 : 0); + fdc_update_densel_polarity(pc87306_fdc, (val & 0x40) ? 1 : 0); } break; case 0xF: @@ -456,22 +456,21 @@ void pc87306_reset(void) 0 = 360 rpm @ 500 kbps for 3.5" 1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5" */ - fdc_update_is_nsc(1); - fdc_update_enh_mode(0); - fdc_update_densel_polarity(1); - fdc_update_max_track(85); - fdc_remove(); - fdc_set_base(0x3f0, 0); - fdd_swap = 0; + lpt1_remove(); + lpt2_remove(); + lpt1_handler(); serial_remove(1); serial_remove(2); serial1_handler(); serial2_handler(); + fdc_reset(pc87306_fdc); pc87306_gpio_init(); } void pc87306_init() { + device_add(&fdc_at_nsc_device); + lpt2_remove(); pc87306_reset(); diff --git a/src/sio_um8669f.c b/src/sio_um8669f.c index 88bf762e6..207904299 100644 --- a/src/sio_um8669f.c +++ b/src/sio_um8669f.c @@ -26,11 +26,11 @@ PnP registers : #include #include #include "86box.h" +#include "device.h" #include "io.h" #include "pci.h" #include "lpt.h" #include "serial.h" -#include "floppy/floppy.h" #include "floppy/fdd.h" #include "floppy/fdc.h" #include "sio.h" @@ -51,6 +51,8 @@ typedef struct um8669f_t int irq; int dma; } dev[8]; + + fdc_t *fdc; } um8669f_t; @@ -120,9 +122,9 @@ void um8669f_pnp_write(uint16_t port, uint8_t val, void *p) case DEV_FDC: if ((um8669f->cur_reg == REG_ENABLE) && valxor) { - fdc_remove(); + fdc_remove(um8669f_global.fdc); if (um8669f->dev[DEV_FDC].enable & 1) - fdc_add(); + fdc_set_base(um8669f_global.fdc, 0x03f0); } break; case DEV_COM1: @@ -235,8 +237,8 @@ uint8_t um8669f_read(uint16_t port, void *p) void um8669f_reset(void) { - fdc_update_is_nsc(0); - + fdc_reset(um8669f_global.fdc); + serial_remove(1); serial_setup(1, SERIAL1_ADDR, SERIAL1_IRQ); @@ -252,11 +254,6 @@ void um8669f_reset(void) um8669f_global.locked = 1; - fdc_update_densel_polarity(1); - fdc_update_densel_force(0); - - fdd_swap = 0; - io_removehandler(0x0279, 0x0001, NULL, NULL, NULL, um8669f_pnp_write, NULL, NULL, &um8669f_global); io_removehandler(0x0a79, 0x0001, NULL, NULL, NULL, um8669f_pnp_write, NULL, NULL, &um8669f_global); io_removehandler(0x03e3, 0x0001, um8669f_pnp_read, NULL, NULL, NULL, NULL, NULL, &um8669f_global); @@ -282,6 +279,8 @@ void um8669f_reset(void) void um8669f_init(void) { + um8669f_global.fdc = device_add(&fdc_at_device); + io_sethandler(0x0108, 0x0002, um8669f_read, NULL, NULL, um8669f_write, NULL, NULL, &um8669f_global); um8669f_reset(); diff --git a/src/sio_w83877f.c b/src/sio_w83877f.c index 9d818ef0a..149222602 100644 --- a/src/sio_w83877f.c +++ b/src/sio_w83877f.c @@ -11,10 +11,10 @@ * Winbond W83877F Super I/O Chip * Used by the Award 430HX * - * Version: @(#)sio_w83877f.c 1.0.7 2017/12/28 + * Version: @(#)sio_w83877f.c 1.0.8 2018/01/16 * * Author: Miran Grca, - * Copyright 2016,2017 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -22,15 +22,15 @@ #include #include "86box.h" #include "machine/machine.h" +#include "device.h" #include "io.h" #include "pci.h" #include "mem.h" #include "rom.h" #include "lpt.h" #include "serial.h" -#include "floppy/floppy.h" -#include "floppy/fdc.h" #include "floppy/fdd.h" +#include "floppy/fdc.h" #include "sio.h" @@ -39,6 +39,7 @@ static int w83877f_rw_locked = 0; static int w83877f_curreg = 0; static uint8_t w83877f_regs[0x2A]; static uint8_t tries; +static fdc_t *w83877f_fdc; static int winbond_port = 0x3f0; static int winbond_key = 0x89; @@ -378,8 +379,9 @@ process_value: case 1: if (valxor & 0x80) { - fdd_setswap((w83877f_regs[1] & 0x80) ? 1 : 0); + fdc_set_swap(w83877f_fdc, (w83877f_regs[1] & 0x80) ? 1 : 0); } + break; case 4: if (valxor & 0x10) { @@ -398,25 +400,25 @@ process_value: case 6: if (valxor & 0x08) { - fdc_remove(); - if (!(w83877f_regs[6] & 0x08)) fdc_add(); + fdc_remove(w83877f_fdc); + if (!(w83877f_regs[6] & 0x08)) fdc_set_base(w83877f_fdc, 0x03f0); } break; case 7: - if (valxor & 3) fdc_update_rwc(0, FDDA_TYPE); - if (valxor & 0xC) fdc_update_rwc(1, FDDB_TYPE); - if (valxor & 0x30) fdc_update_rwc(2, FDDC_TYPE); - if (valxor & 0xC0) fdc_update_rwc(3, FDDD_TYPE); + if (valxor & 3) fdc_update_rwc(w83877f_fdc, 0, FDDA_TYPE); + if (valxor & 0xC) fdc_update_rwc(w83877f_fdc, 1, FDDB_TYPE); + if (valxor & 0x30) fdc_update_rwc(w83877f_fdc, 2, FDDC_TYPE); + if (valxor & 0xC0) fdc_update_rwc(w83877f_fdc, 3, FDDD_TYPE); break; case 8: - if (valxor & 3) fdc_update_boot_drive(FD_BOOT); - if (valxor & 0x10) swwp = SWWP ? 1 : 0; - if (valxor & 0x20) disable_write = DISFDDWR ? 1 : 0; + if (valxor & 3) fdc_update_boot_drive(w83877f_fdc, FD_BOOT); + if (valxor & 0x10) fdc_set_swwp(w83877f_fdc, SWWP ? 1 : 0); + if (valxor & 0x20) fdc_set_diswr(w83877f_fdc, DISFDDWR ? 1 : 0); break; case 9: if (valxor & 0x20) { - fdc_update_enh_mode(EN3MODE ? 1 : 0); + fdc_update_enh_mode(w83877f_fdc, EN3MODE ? 1 : 0); } if (valxor & 0x40) { @@ -424,8 +426,8 @@ process_value: } break; case 0xB: - if (valxor & 1) fdc_update_drv2en(DRV2EN_NEG ? 0 : 1); - if (valxor & 2) fdc_update_densel_polarity(INVERTZ ? 1 : 0); + if (valxor & 1) fdc_update_drv2en(w83877f_fdc, DRV2EN_NEG ? 0 : 1); + if (valxor & 2) fdc_update_densel_polarity(w83877f_fdc, INVERTZ ? 1 : 0); break; case 0xC: if (valxor & 0x20) w83877f_remap(); @@ -488,9 +490,7 @@ uint8_t w83877f_read(uint16_t port, void *priv) { if ((w83877f_curreg < 0x18) && w83877f_rw_locked) return 0xff; if (w83877f_curreg == 7) - { - return (fdc_get_rwc(0) | (fdc_get_rwc(1) << 2)); - } + return (fdc_get_rwc(w83877f_fdc, 0) | (fdc_get_rwc(w83877f_fdc, 1) << 2)); return w83877f_regs[w83877f_curreg]; } } @@ -501,8 +501,7 @@ void w83877f_reset(void) lpt1_remove(); lpt1_init(0x378); - fdc_remove(); - fdc_add_for_superio(); + fdc_reset(w83877f_fdc); w83877f_regs[3] = 0x30; w83877f_regs[7] = 0xF5; @@ -523,18 +522,6 @@ void w83877f_reset(void) w83877f_regs[0x28] = (4 << 4) | 3; w83877f_regs[0x29] = 0x62; - fdc_update_densel_polarity(1); - fdc_update_densel_force(0); - fdc_update_rwc(0, 1); - fdc_update_rwc(1, 1); - fdc_update_drvrate(0, 0); - fdc_update_drvrate(1, 0); - fdc_update_enh_mode(0); - fdc_update_max_track(85); - swwp = 0; - disable_write = 0; - fdc_update_drv2en(1); - fdd_setswap(0); serial_setup(1, SERIAL1_ADDR, SERIAL1_IRQ); serial_setup(2, SERIAL2_ADDR, SERIAL2_IRQ); w83877f_remap(); @@ -545,6 +532,8 @@ void w83877f_reset(void) void w83877f_init(void) { + w83877f_fdc = device_add(&fdc_at_winbond_device); + lpt2_remove(); w83877f_reset(); diff --git a/src/sound/openal.c b/src/sound/openal.c index f579b5f4e..016125bfb 100644 --- a/src/sound/openal.c +++ b/src/sound/openal.c @@ -8,13 +8,13 @@ * * Interface to the OpenAL sound processing library. * - * Version: @(#)openal.c 1.0.2 2017/12/15 + * Version: @(#)openal.c 1.0.3 2018/01/16 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -221,9 +221,7 @@ givealbuffer_common(void *buf, uint8_t src, int size, int freq) int processed; int state; ALuint buffer; -#if 0 double gain; -#endif alGetSourcei(source[src], AL_SOURCE_STATE, &state); @@ -233,11 +231,9 @@ givealbuffer_common(void *buf, uint8_t src, int size, int freq) alGetSourcei(source[src], AL_BUFFERS_PROCESSED, &processed); if (processed >= 1) { -#if 0 gain = pow(10.0, (double)sound_gain[src] / 20.0); - alSourcef(source[src], AL_GAIN, gain); -#endif + alListenerf(AL_GAIN, gain); alSourceUnqueueBuffers(source[src], 1, &buffer); diff --git a/src/video/video.h b/src/video/video.h index 2cc8b00a5..338ff6009 100644 --- a/src/video/video.h +++ b/src/video/video.h @@ -116,7 +116,8 @@ enum { FULLSCR_SCALE_FULL = 0, FULLSCR_SCALE_43, FULLSCR_SCALE_SQ, - FULLSCR_SCALE_INT + FULLSCR_SCALE_INT, + FULLSCR_SCALE_KEEPRATIO }; diff --git a/src/win/86Box.rc b/src/win/86Box.rc index 50d5922fc..fc81764d5 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -8,12 +8,12 @@ * * Application resource script for Windows. * - * Version: @(#)86Box.rc 1.0.22 2017/12/09 + * Version: @(#)86Box.rc 1.0.22 2018/01/17 * * Authors: Miran Grca, * Fred N. van Kempen, * - * Copyright 2016,2017 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ #include #define IN_RESOURCE_H @@ -88,6 +88,7 @@ BEGIN MENUITEM "&4:3", IDM_VID_FS_43 MENUITEM "&Square pixels", IDM_VID_FS_SQ MENUITEM "&Integer scale", IDM_VID_FS_INT + MENUITEM "&Keep size", IDM_VID_FS_KEEPRATIO END POPUP "E&GA/(S)VGA settings" BEGIN @@ -116,11 +117,10 @@ BEGIN BEGIN MENUITEM "&Settings...", IDM_CONFIG MENUITEM SEPARATOR - MENUITEM "&Load configuration...", IDM_CONFIG_LOAD - MENUITEM "&Save configuration...", IDM_CONFIG_SAVE - MENUITEM SEPARATOR MENUITEM "S&tatus", IDM_STATUS MENUITEM "Take s&creenshot\tCtrl+F11", IDM_ACTION_SCREENSHOT + MENUITEM SEPARATOR + MENUITEM "S&ound gain...", IDM_SND_GAIN END #if defined(ENABLE_LOG_TOGGLES) || defined(ENABLE_LOG_COMMANDS) POPUP "&Logging" @@ -238,6 +238,39 @@ BEGIN LTEXT "1",IDT_STEXT,16,186,180,1000 END +DLG_SND_GAIN DIALOG DISCARDABLE 0, 0, 174, 136 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Sound Gain" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,117,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,117,24,50,14 + CONTROL "Main",IDC_SLIDER_MAIN,"msctls_trackbar32",TBS_VERT | + TBS_BOTH | TBS_AUTOTICKS | WS_TABSTOP,15,20,20,109 + CONTROL "CD",IDC_SLIDER_CD,"msctls_trackbar32",TBS_VERT | + TBS_BOTH | TBS_AUTOTICKS | WS_TABSTOP,45,20,20,109 + CONTROL "MIDI",IDC_SLIDER_MIDI,"msctls_trackbar32",TBS_VERT | + TBS_BOTH | TBS_AUTOTICKS | WS_TABSTOP,77,20,20,109 + CTEXT "Main",IDT_1746,7,7,32,9,SS_CENTERIMAGE + CTEXT "CD",IDT_1747,38,7,32,9,SS_CENTERIMAGE + CTEXT "MIDI",IDT_1748,70,7,32,9,SS_CENTERIMAGE +END + +DLG_NEW_FLOPPY DIALOG DISCARDABLE 0, 0, 186, 65 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "New Floppy Image" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,74,44,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,44,50,14 + LTEXT "File name:",IDT_1749,7,6,34,12,SS_CENTERIMAGE + LTEXT "Disk size:",IDT_1750,7,25,34,12,SS_CENTERIMAGE + EDITTEXT IDC_EDIT_FILE_NAME,43,7,124,12,ES_AUTOHSCROLL | ES_READONLY + COMBOBOX IDC_COMBO_DISK_SIZE,43,25,136,14,CBS_DROPDOWN | CBS_SORT | + WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "...",IDC_CFILE,166,7,13,12 +END + DLG_CONFIG DIALOG DISCARDABLE 0, 0, 366, 241 STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "86Box Settings" @@ -606,6 +639,22 @@ END #ifdef APSTUDIO_INVOKED GUIDELINES DESIGNINFO DISCARDABLE BEGIN + DLG_SND_GAIN, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 167 + TOPMARGIN, 7 + BOTTOMMARGIN, 129 + END + + DLG_NEW_FLOPPY, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 58 + END + DLG_CFG_MAIN, DIALOG BEGIN RIGHTMARGIN, 365 diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 336eb7802..00fcaa527 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -8,7 +8,7 @@ # # Makefile for Win32 (MinGW32) environment. # -# Version: @(#)Makefile.mingw 1.0.91 2018/01/01 +# Version: @(#)Makefile.mingw 1.0.92 2018/01/16 # # Authors: Miran Grca, # Fred N. van Kempen, @@ -255,7 +255,8 @@ ifneq ($(WX), n) else UIOBJ := win_ui.o win_ddraw.o win_d3d.o win_png.o \ win_dialog.o win_about.o win_status.o win_stbar.o \ - win_settings.o win_devconf.o win_jsconf.o + win_settings.o win_devconf.o \ + win_snd_gain.o win_jsconf.o endif ifeq ($(OPENAL), y) @@ -394,9 +395,9 @@ DEVOBJ := bugger.o lpt.o $(SERIAL) \ mouse_serial.o mouse_ps2.o mouse_bus.o FDDOBJ := fdd.o fdc.o fdi2raw.o \ - floppy.o floppy_common.o floppy_86f.o \ - floppy_fdi.o floppy_imd.o floppy_img.o floppy_json.o \ - floppy_td0.o + fdd_common.o fdd_86f.o \ + fdd_fdi.o fdd_imd.o fdd_img.o fdd_json.o \ + fdd_td0.o HDDOBJ := hdd.o \ hdd_image.o hdd_table.o \ diff --git a/src/win/resource.h b/src/win/resource.h index 00f99f1ba..c02acb69a 100644 --- a/src/win/resource.h +++ b/src/win/resource.h @@ -8,14 +8,14 @@ * * Windows resource defines. * - * Version: @(#)resource.h 1.0.15 2017/12/09 + * Version: @(#)resource.h 1.0.16 2018/01/17 * * Authors: Sarah Walker, * Miran Grca, - * Fred N. van Kempem, + * Fred N. van Kempen, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #ifndef WIN_RESOURCE_H # define WIN_RESOURCE_H @@ -24,6 +24,8 @@ /* Dialog IDs. */ #define DLG_ABOUT 101 /* top-level dialog */ #define DLG_STATUS 102 /* top-level dialog */ +#define DLG_SND_GAIN 103 /* top-level dialog */ +#define DLG_NEW_FLOPPY 104 /* top-level dialog */ #define DLG_CONFIG 110 /* top-level dialog */ #define DLG_CFG_MACHINE 111 /* sub-dialog of config */ #define DLG_CFG_VIDEO 112 /* sub-dialog of config */ @@ -77,6 +79,11 @@ #define IDT_1743 1743 /* Channel: */ #define IDT_STEXT 1744 /* text in status window */ #define IDT_SDEVICE 1745 /* text in status window */ +#define IDT_1746 1746 /* Main */ +#define IDT_1747 1747 /* CD */ +#define IDT_1748 1748 /* MIDI */ +#define IDT_1749 1749 /* File name: */ +#define IDT_1750 1750 /* Disk size: */ /* @@ -180,6 +187,13 @@ #define IDC_BUTTON_CDROM_EDIT 1164 // status bar menu #define IDC_BUTTON_CDROM_REMOVE 1165 // status bar menu +#define IDC_SLIDER_MAIN 1180 /* sound gain dialog */ +#define IDC_SLIDER_CD 1181 +#define IDC_SLIDER_MIDI 1182 + +#define IDC_EDIT_FILE_NAME 1190 /* new floppy image dialog */ +#define IDC_COMBO_DISK_SIZE 1191 + /* For the DeviceConfig code, re-do later. */ #define IDC_CONFIG_BASE 1200 @@ -213,6 +227,7 @@ #define IDM_CONFIG_LOAD 40021 #define IDM_CONFIG_SAVE 40022 #define IDM_STATUS 40030 +#define IDM_SND_GAIN 40040 #define IDM_VID_RESIZE 40050 #define IDM_VID_REMEMBER 40051 #define IDM_VID_DDRAW 40060 @@ -228,8 +243,9 @@ #define IDM_VID_FS_43 40072 #define IDM_VID_FS_SQ 40073 #define IDM_VID_FS_INT 40074 -#define IDM_VID_FORCE43 40075 -#define IDM_VID_OVERSCAN 40076 +#define IDM_VID_FS_KEEPRATIO 40075 +#define IDM_VID_FORCE43 40076 +#define IDM_VID_OVERSCAN 40077 #define IDM_VID_INVERT 40079 #define IDM_VID_CGACON 40080 #define IDM_VID_GRAYCT_601 40085 diff --git a/src/win/win.h b/src/win/win.h index 0453ae88a..3c2fedf0b 100644 --- a/src/win/win.h +++ b/src/win/win.h @@ -110,6 +110,10 @@ extern int ui_init(int nCmdShow); extern void AboutDialogCreate(HWND hwnd); +/* Functions in win_snd_gain.c: */ +extern void SoundGainDialogCreate(HWND hwnd); + + /* Functions in win_status.c: */ extern HWND hwndStatus; extern void StatusWindowCreate(HWND hwnd); diff --git a/src/win/win_about.c b/src/win/win_about.c index ffe1df1b0..9e83d7a5c 100644 --- a/src/win/win_about.c +++ b/src/win/win_about.c @@ -10,11 +10,9 @@ * * Version: @(#)win_about.c 1.0.5 2017/12/13 * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2017 Sarah Walker. * Copyright 2016,2017 Miran Grca. * Copyright 2017 Fred N. van Kempen. */ diff --git a/src/win/win_cdrom_ioctl.c b/src/win/win_cdrom_ioctl.c index ea1245556..5ca208261 100644 --- a/src/win/win_cdrom_ioctl.c +++ b/src/win/win_cdrom_ioctl.c @@ -9,13 +9,13 @@ * Implementation of the CD-ROM host drive IOCTL interface for * Windows using SCSI Passthrough Direct. * - * Version: @(#)cdrom_ioctl.c 1.0.8 2017/11/24 + * Version: @(#)cdrom_ioctl.c 1.0.9 2018/01/17 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2016 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #define WINVER 0x0600 #include @@ -573,13 +573,16 @@ static int is_track_audio(uint8_t id, uint32_t pos) return 0; } - for (c = 0; c <= cdrom_ioctl_windows[id].toc.LastTrack; c++) + for (c = 0; cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber != 0xaa; c++) { track_address = MSFtoLBA(cdrom_ioctl_windows[id].toc.TrackData[c].Address[1],cdrom_ioctl_windows[id].toc.TrackData[c].Address[2],cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]); - if (track_address <= pos) + if (cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber >= cdrom_ioctl_windows[id].toc.FirstTrack && + cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber <= cdrom_ioctl_windows[id].toc.LastTrack && + track_address <= pos) { control = cdrom_ioctl_windows[id].toc.TrackData[c].Control; + break; } } @@ -1048,7 +1051,6 @@ static int ioctl_readtoc(uint8_t id, unsigned char *b, unsigned char starttrack, break; } } - b[2]=cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber; last_block = 0; for (c=d;c<=cdrom_ioctl_windows[id].toc.LastTrack;c++) { diff --git a/src/win/win_d3d.cpp b/src/win/win_d3d.cpp index 818694045..209875414 100644 --- a/src/win/win_d3d.cpp +++ b/src/win/win_d3d.cpp @@ -8,15 +8,15 @@ * * Rendering module for Microsoft Direct3D 9. * - * Version: @(#)win_d3d.cpp 1.0.9 2017/12/15 + * Version: @(#)win_d3d.cpp 1.0.10 2018/01/15 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. - * Copyright 2017 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. */ #include #include @@ -64,17 +64,25 @@ static CUSTOMVERTEX d3d_verts[] = { }; +static void +d3d_size_default(RECT w_rect, double *l, double *t, double *r, double *b) +{ + *l = -0.5; + *t = -0.5; + *r = (w_rect.right - w_rect.left) - 0.5; + *b = (w_rect.bottom - w_rect.top) - 0.5; +} + + static void d3d_size(RECT w_rect, double *l, double *t, double *r, double *b, int w, int h) { int ratio_w, ratio_h; + double hsr, gsr, ra, d; switch (video_fullscreen_scale) { case FULLSCR_SCALE_FULL: - *l = -0.5; - *t = -0.5; - *r = (w_rect.right - w_rect.left) - 0.5; - *b = (w_rect.bottom - w_rect.top) - 0.5; + d3d_size_default(w_rect, l, t, r, b); break; case FULLSCR_SCALE_43: @@ -113,6 +121,38 @@ d3d_size(RECT w_rect, double *l, double *t, double *r, double *b, int w, int h) *t = ((w_rect.bottom - w_rect.top) / 2) - ((h * ratio_w) / 2) - 0.5; *b = ((w_rect.bottom - w_rect.top) / 2) + ((h * ratio_w) / 2) - 0.5; break; + + case FULLSCR_SCALE_KEEPRATIO: + hsr = ((double) (w_rect.right - w_rect.left)) / ((double) (w_rect.bottom - w_rect.top)); + gsr = ((double) w) / ((double) h); + + if (hsr > gsr) { + /* Host ratio is bigger than guest ratio. */ + ra = ((double) (w_rect.bottom - w_rect.top)) / ((double) h); + + d = ((double) w) * ra; + d = (((double) (w_rect.right - w_rect.left)) - d) / 2.0; + + *l = ((int) d) - 0.5; + *r = (w_rect.right - w_rect.left) - ((int) d) - 0.5; + *t = -0.5; + *b = (w_rect.bottom - w_rect.top) - 0.5; + } else if (hsr < gsr) { + /* Host ratio is smaller or rqual than guest ratio. */ + ra = ((double) (w_rect.right - w_rect.left)) / ((double) w); + + d = ((double) h) * ra; + d = (((double) (w_rect.bottom - w_rect.top)) - d) / 2.0; + + *l = -0.5; + *r = (w_rect.right - w_rect.left) - 0.5; + *t = ((int) d) - 0.5; + *b = (w_rect.bottom - w_rect.top) - ((int) d) - 0.5; + } else { + /* Host ratio is equal to guest ratio. */ + d3d_size_default(w_rect, l, t, r, b); + } + break; } } diff --git a/src/win/win_ddraw.cpp b/src/win/win_ddraw.cpp index 3ed6b9dd0..bd6228c00 100644 --- a/src/win/win_ddraw.cpp +++ b/src/win/win_ddraw.cpp @@ -11,15 +11,15 @@ * NOTES: This code should be re-merged into a single init() with a * 'fullscreen' argument, indicating FS mode is requested. * - * Version: @(#)win_ddraw.cpp 1.0.4 2017/12/15 + * Version: @(#)win_ddraw.cpp 1.0.5 2018/01/15 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. - * Copyright 2017 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. */ #include #include @@ -155,17 +155,27 @@ SaveBitmap(wchar_t *szFilename, HBITMAP hBitmap) } +static void +ddraw_fs_size_default(RECT w_rect, RECT *r_dest) +{ + r_dest->left = 0; + r_dest->top = 0; + r_dest->right = (w_rect.right - w_rect.left) - 1; + r_dest->bottom = (w_rect.bottom - w_rect.top) - 1; +} + + static void ddraw_fs_size(RECT w_rect, RECT *r_dest, int w, int h) { int ratio_w, ratio_h; + double hsr, gsr, ra, d; + + pclog("video_fullscreen_scale = %i\n", video_fullscreen_scale); switch (video_fullscreen_scale) { case FULLSCR_SCALE_FULL: - r_dest->left = 0; - r_dest->top = 0; - r_dest->right = (w_rect.right - w_rect.left) - 1; - r_dest->bottom = (w_rect.bottom - w_rect.top) - 1; + ddraw_fs_size_default(w_rect, r_dest); break; case FULLSCR_SCALE_43: @@ -204,6 +214,38 @@ ddraw_fs_size(RECT w_rect, RECT *r_dest, int w, int h) r_dest->top = ((w_rect.bottom - w_rect.top) / 2) - ((h * ratio_w) / 2); r_dest->bottom = ((w_rect.bottom - w_rect.top) / 2) + ((h * ratio_w) / 2) - 1; break; + + case FULLSCR_SCALE_KEEPRATIO: + hsr = ((double) (w_rect.right - w_rect.left)) / ((double) (w_rect.bottom - w_rect.top)); + gsr = ((double) w) / ((double) h); + + if (hsr > gsr) { + /* Host ratio is bigger than guest ratio. */ + ra = ((double) (w_rect.bottom - w_rect.top)) / ((double) h); + + d = ((double) w) * ra; + d = (((double) (w_rect.right - w_rect.left)) - d) / 2.0; + + r_dest->left = ((int) d); + r_dest->right = (w_rect.right - w_rect.left) - ((int) d) - 1; + r_dest->top = 0; + r_dest->bottom = (w_rect.bottom - w_rect.top) - 1; + } else if (hsr < gsr) { + /* Host ratio is smaller or rqual than guest ratio. */ + ra = ((double) (w_rect.right - w_rect.left)) / ((double) w); + + d = ((double) h) * ra; + d = (((double) (w_rect.bottom - w_rect.top)) - d) / 2.0; + + r_dest->left = 0; + r_dest->right = (w_rect.right - w_rect.left) - 1; + r_dest->top = ((int) d); + r_dest->bottom = (w_rect.bottom - w_rect.top) - ((int) d) - 1; + } else { + /* Host ratio is equal to guest ratio. */ + ddraw_fs_size_default(w_rect, r_dest); + } + break; } } diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 9af4fd3d1..c52c8c9bc 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -8,11 +8,11 @@ * * Windows 86Box Settings dialog handler. * - * Version: @(#)win_settings.c 1.0.27 2017/12/13 + * Version: @(#)win_settings.c 1.0.28 2018/01/16 * * Author: Miran Grca, * - * Copyright 2016,2017 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ #define UNICODE #define BITMAP WINDOWS_BITMAP @@ -40,7 +40,6 @@ #include "../disk/hdd.h" #include "../disk/hdc.h" #include "../disk/hdc_ide.h" -#include "../floppy/floppy.h" #include "../floppy/fdd.h" #include "../scsi/scsi.h" #include "../network/network.h" diff --git a/src/win/win_stbar.c b/src/win/win_stbar.c index 25cf8a0fb..96e58aa28 100644 --- a/src/win/win_stbar.c +++ b/src/win/win_stbar.c @@ -8,13 +8,13 @@ * * Implement the application's Status Bar. * - * Version: @(#)win_stbar.c 1.0.7 2017/12/13 + * Version: @(#)win_stbar.c 1.0.8 2018/01/16 * * Authors: Miran Grca, * Fred N. van Kempen, * - * Copyright 2016,2017 Miran Grca. - * Copyright 2017 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. */ #define UNICODE #define BITMAP WINDOWS_BITMAP @@ -38,7 +38,6 @@ #include "../cdrom/cdrom_null.h" #include "../disk/hdd.h" #include "../disk/hdc.h" -#include "../floppy/floppy.h" #include "../floppy/fdd.h" #include "../scsi/scsi.h" #include "../scsi/scsi_disk.h" @@ -826,9 +825,9 @@ StatusBarProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) ret = file_dlg_w_st(hwnd, IDS_2159, floppyfns[id], 0); if (! ret) { - floppy_close(id); + fdd_close(id); ui_writeprot[id] = (item_id == IDM_FLOPPY_IMAGE_EXISTING_WP) ? 1 : 0; - floppy_load(id, wopenfilestring); + fdd_load(id, wopenfilestring); ui_sb_update_icon_state(SB_FLOPPY | id, wcslen(floppyfns[id]) ? 0 : 1); EnableMenuItem(sb_menu_handles[part], IDM_FLOPPY_EJECT | id, MF_BYCOMMAND | (wcslen(floppyfns[id]) ? MF_ENABLED : MF_GRAYED)); ui_sb_update_tip(SB_FLOPPY | id); @@ -842,7 +841,7 @@ StatusBarProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) if ((part == -1) || (sb_menu_handles == NULL)) break; - floppy_close(id); + fdd_close(id); ui_sb_update_icon_state(SB_FLOPPY | id, 1); EnableMenuItem(sb_menu_handles[part], IDM_FLOPPY_EJECT | id, MF_BYCOMMAND | MF_GRAYED); ui_sb_update_tip(SB_FLOPPY | id); diff --git a/src/win/win_ui.c b/src/win/win_ui.c index af6aa4ad6..d43ff8664 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -8,15 +8,15 @@ * * user Interface module for WinAPI on Windows. * - * Version: @(#)win_ui.c 1.0.11 2017/12/28 + * Version: @(#)win_ui.c 1.0.12 2018/01/15 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. - * Copyright 2017 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. */ #define UNICODE #include @@ -173,6 +173,7 @@ ResetAllMenus(void) CheckMenuItem(menuMain, IDM_VID_FS_FULL+1, MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_FS_FULL+2, MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_FS_FULL+3, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_FS_FULL+4, MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_REMEMBER, MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_SCALE_1X+0, MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_SCALE_1X+1, MF_UNCHECKED); @@ -309,6 +310,10 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) win_settings_open(hwnd); break; + case IDM_SND_GAIN: + SoundGainDialogCreate(hwnd); + break; + case IDM_ABOUT: AboutDialogCreate(hwnd); break; @@ -378,6 +383,7 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case IDM_VID_FS_43: case IDM_VID_FS_SQ: case IDM_VID_FS_INT: + case IDM_VID_FS_KEEPRATIO: CheckMenuItem(hmenu, IDM_VID_FS_FULL+video_fullscreen_scale, MF_UNCHECKED); video_fullscreen_scale = LOWORD(wParam) - IDM_VID_FS_FULL; CheckMenuItem(hmenu, IDM_VID_FS_FULL+video_fullscreen_scale, MF_CHECKED);