Added the IBM 5161 ISA expansion for PC and XT;
Cleaned up the parallel port emulation, added IRQ support, and made enabling/disabling per port; Added the Award 430NX and the Intel Classic/PCI (Alfredo, 420TX); Finished the 586MC1; Added 8087 emulation; Moved Cyrix 6x86'es to the Dev branch; Sanitized/cleaned up memregs.c/h and intel.c/h; Split the chipsets from machines and sanitized Port 92 emulation; Added support for the 15bpp mode to the Compaq ATI 28800; Moved the MR 386DX and 486 machines to the Dev branch; Ported the new dynamic recompiler from PCem, but it remains in Dev branch until after v2.00; Ported the new timer code from PCem; Cleaned up the CPU table of unused stuff and better optimized its structure; Ported the Open-XT and Open-AT from VARCem, the Open-AT is in the Dev branch; Ported the XT MFM controller rewrite and adding of more controllers (incl. two RLL ones), from VARCem; Added the AHA-1540A and the BusTek BT-542B; Moved the Sumo SCSI-AT to the Dev branch; Minor IDE, FDC, and floppy drive code clean-ups; Made NCR 5380/53C400-based cards' BIOS address configurable; Got rid of the legacy romset variable; Unified (video) buffer and buffer32 into one and make the unified buffer 32-bit; Added the Amstead PPC512 per PCem patch by John Elliott; Switched memory mapping granularity from 16k to 4k (less than 1k not possible due to internal pages); Rewrote the CL-GD 54xx blitter, fixes Win-OS/2 on the 54x6 among other thing; Added the Image Manager 1024 and Professional Graphics Controller per PCem patch by John Elliott and work done on VARCem; Added Headland HT-216, GC-205 and Video 7 VGA 1024i emulation based on PCem commit; Implemented the fuction keys for the Toshiba T1000/T1200/T3100 enhancement; Amstrad MegaPC does now works correctly with non-internal graphics card; The SLiRP code no longer casts a packed struct type to a non-packed struct type; The Xi8088 and PB410a no longer hang on 86Box when PS/2 mouse is not present; The S3 Virge on BeOS is no longer broken (was broken by build #1591); OS/2 2.0 build 6.167 now sees key presses again; Xi8088 now work on CGA again; 86F images converted from either the old or new variants of the HxC MFM format now work correctly; Hardware interrupts with a vector of 0xFF are now handled correctly; OPTi 495SX boards no longer incorrectly have 64 MB maximum RAM when 32 MB is correct; Fixed VNC keyboard input bugs; Fixed AT RTC periodic interrupt - Chicago 58s / 73f / 73g / 81 MIDI play no longer hangs with the build's own VTD driver; Fixed mouse polling with internal mice - Amstrad and Olivetti mice now work correctly; Triones ATAPI DMA driver now correctly reads a file at the end of a CD image with a sectors number not divisible by 4; Compaq Portable now works with all graphics cards; Fixed various MDSI Genius bugs; Added segment limit checks and improved page fault checks for several CPU instructions - Memphis 15xx WINSETUP and Chicago 58s WINDISK.CPL no longer issue a GPF, and some S3 drivers that used to have glitches, now work correctly; Further improved the 808x emulation, also fixes the noticably choppy sound when using 808x CPU's, also fixes #355; OS/2 installer no logner locks up on splash screen on PS/2 Model 70 and 80, fixes #400. Fixed several Amstead bugs, GEM no longer crashes on the Amstrad 1640, fixes #391. Ported John Elliott's Amstrad fixes and improvement from PCem, and fixed the default language so it's correctly Engliish, fixes #278, fixes #389. Fixed a minor IDE timing bug, fixes #388. Fixed Toshiba T1000 RAM issues, fixes #379. Fixed EGA/(S)VGA overscan border handling, fixes #378; Got rid of the now long useless IDE channel 2 auto-removal, fixes #370; Fixed the BIOS files used by the AMSTRAD PC1512, fixes #366; Ported the Unicode CD image file name fix from VARCem, fixes #365; Fixed high density floppy disks on the Xi8088, fixes #359; Fixed some bugs in the Hercules emulation, fixes #346, fixes #358; Fixed the SCSI hard disk mode sense pages, fixes #356; Removed the AMI Unknown 386SX because of impossibility to identify the chipset, closes #349; Fixed bugs in the serial mouse emulation, fixes #344; Compiled 86Box binaries now include all the required .DLL's, fixes #341; Made some combo boxes in the Settings dialog slightly wider, fixes #276.
This commit is contained in:
334
src/floppy/fdc.c
334
src/floppy/fdc.c
@@ -9,7 +9,7 @@
|
||||
* Implementation of the NEC uPD-765 and compatible floppy disk
|
||||
* controller.
|
||||
*
|
||||
* Version: @(#)fdc.c 1.0.15 2019/01/26
|
||||
* Version: @(#)fdc.c 1.0.18 2019/03/23
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Sarah Walker, <tommowalker@tommowalker.co.uk>
|
||||
@@ -47,8 +47,6 @@
|
||||
#include "../cpu/cpu.h"
|
||||
#include "../machine/machine.h"
|
||||
#include "../io.h"
|
||||
#include "../mem.h"
|
||||
#include "../rom.h"
|
||||
#include "../dma.h"
|
||||
#include "../pic.h"
|
||||
#include "../timer.h"
|
||||
@@ -57,7 +55,7 @@
|
||||
#include "fdc.h"
|
||||
|
||||
|
||||
extern int64_t motoron[FDD_NUM];
|
||||
extern uint64_t motoron[FDD_NUM];
|
||||
|
||||
|
||||
const int command_has_drivesel[256] = {
|
||||
@@ -100,10 +98,10 @@ const int command_has_drivesel[256] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
uint8_t current_drive = 0;
|
||||
|
||||
static uint8_t current_drive = 0;
|
||||
|
||||
static void fdc_callback(void *priv);
|
||||
int timetolive;
|
||||
int lastbyte=0;
|
||||
|
||||
int floppymodified[4];
|
||||
@@ -131,16 +129,9 @@ fdc_log(const char *fmt, ...)
|
||||
|
||||
|
||||
uint8_t
|
||||
fdc_ps1_525(void)
|
||||
fdc_get_current_drive(void)
|
||||
{
|
||||
switch (romset) {
|
||||
case ROM_IBMPS1_2011:
|
||||
case ROM_IBMPS1_2121:
|
||||
case ROM_IBMPS1_2121_ISA:
|
||||
return fdd_is_525(current_drive) ? 0x40 : 0x00;
|
||||
default:
|
||||
return 0x00;
|
||||
}
|
||||
return current_drive;
|
||||
}
|
||||
|
||||
|
||||
@@ -156,7 +147,7 @@ fdc_ctrl_reset(void *p)
|
||||
fdc->head = 0;
|
||||
fdc->abort = 0;
|
||||
fdc->step = 0;
|
||||
if (!(fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_PS1))
|
||||
if (!(fdc->flags & FDC_FLAG_AT))
|
||||
fdc->rate = 2;
|
||||
}
|
||||
|
||||
@@ -354,9 +345,8 @@ fdc_watchdog_poll(void *priv)
|
||||
|
||||
fdc->watchdog_count--;
|
||||
if (fdc->watchdog_count)
|
||||
fdc->watchdog_timer += 1000LL * TIMER_USEC;
|
||||
timer_advance_u64(&fdc->watchdog_timer, 1000 * TIMER_USEC);
|
||||
else {
|
||||
fdc->watchdog_timer = 0LL;
|
||||
if (fdc->dor & 0x20)
|
||||
picint(1 << fdc->irq);
|
||||
}
|
||||
@@ -579,7 +569,6 @@ 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));
|
||||
}
|
||||
@@ -599,8 +588,6 @@ void
|
||||
fdc_seek(fdc_t *fdc, int drive, int params)
|
||||
{
|
||||
fdd_seek(real_drive(fdc, drive), params);
|
||||
fdc->time = 2048LL * (1 << TIMER_SHIFT);
|
||||
|
||||
fdc->stat |= (1 << fdc->drive);
|
||||
}
|
||||
|
||||
@@ -622,9 +609,7 @@ fdc_bad_command(fdc_t *fdc)
|
||||
{
|
||||
fdc->stat = 0x10;
|
||||
fdc->interrupt = 0xfc;
|
||||
timer_process();
|
||||
fdc->time = 200LL * (1LL << TIMER_SHIFT);
|
||||
timer_update_outstanding();
|
||||
timer_set_delay_u64(&fdc->timer, 100 * TIMER_USEC);
|
||||
}
|
||||
|
||||
|
||||
@@ -641,8 +626,7 @@ fdc_io_command_phase1(fdc_t *fdc, int out)
|
||||
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);
|
||||
ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 1);
|
||||
fdc->stat = out ? 0x90 : 0x50;
|
||||
if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma)
|
||||
fdc->stat |= 0x20;
|
||||
@@ -663,7 +647,7 @@ fdc_sis(fdc_t *fdc)
|
||||
|
||||
if (fdc->reset_stat) {
|
||||
drive_num = real_drive(fdc, 4 - fdc->reset_stat);
|
||||
if ((!fdd_get_flags(drive_num)) || (drive_num >= FDD_NUM)) {
|
||||
if ((drive_num < FDD_NUM) && fdd_get_flags(drive_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);
|
||||
@@ -698,8 +682,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
|
||||
fdc_log("Write FDC %04X %02X\n", addr, val);
|
||||
|
||||
cycles -= ISA_CYCLES(8);
|
||||
// pclog("fdc_write(): cycles -= ISA_CYCLES(8);\n");
|
||||
sub_cycles(ISA_CYCLES(8));
|
||||
|
||||
switch (addr&7) {
|
||||
case 0:
|
||||
@@ -709,25 +692,20 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
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;
|
||||
timer_set_delay_u64(&fdc->watchdog_timer, 1000 * TIMER_USEC);
|
||||
fdc->watchdog_count = 1000;
|
||||
picintc(1 << fdc->irq);
|
||||
}
|
||||
if ((val & 0x80) && !(fdc->dor & 0x80)) {
|
||||
timer_process();
|
||||
fdc->time = 128LL * (1LL << TIMER_SHIFT);
|
||||
timer_update_outstanding();
|
||||
timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC);
|
||||
fdc->interrupt = -1;
|
||||
ui_sb_update_icon(SB_FLOPPY | 0, 0);
|
||||
fdc_ctrl_reset(fdc);
|
||||
fdd_changed[0] = 1;
|
||||
fdd_changed[1] = 1;
|
||||
fdd_changed[2] = 1;
|
||||
fdd_changed[3] = 1;
|
||||
}
|
||||
if (!fdd_get_flags(0))
|
||||
val &= 0xfe;
|
||||
motoron[0] = val & 0x01;
|
||||
fdd_set_motor_enable(0, val & 0x01);
|
||||
fdc->st0 &= ~0x07;
|
||||
fdc->st0 |= (fdd_get_head(0) ? 4 : 0);
|
||||
} else {
|
||||
@@ -745,9 +723,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc->pnum = fdc->ptot = 0;
|
||||
}
|
||||
if ((val&4) && !(fdc->dor&4)) {
|
||||
timer_process();
|
||||
fdc->time = 128LL * (1LL << TIMER_SHIFT);
|
||||
timer_update_outstanding();
|
||||
timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC);
|
||||
fdc->interrupt = -1;
|
||||
fdc->perp &= 0xfc;
|
||||
|
||||
@@ -756,18 +732,16 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
|
||||
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(fdc, i);
|
||||
if ((!fdd_get_flags(drive_num)) || (drive_num >= FDD_NUM))
|
||||
val &= ~(0x10 << drive_num);
|
||||
else
|
||||
motoron[i] = (val & (0x10 << drive_num));
|
||||
fdd_set_motor_enable(i, (val & (0x10 << drive_num)));
|
||||
}
|
||||
drive_num = real_drive(fdc, val & 0x03);
|
||||
current_drive = real_drive(fdc, val & 0x03);
|
||||
current_drive = drive_num;
|
||||
fdc->st0 &= ~0x07;
|
||||
fdc->st0 |= real_drive(fdc, drive_num);
|
||||
fdc->st0 |= (fdd_get_head(drive_num) ? 4 : 0);
|
||||
@@ -782,9 +756,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
return;
|
||||
case 4:
|
||||
if (val & 0x80) {
|
||||
timer_process();
|
||||
fdc->time = 128LL * (1LL << TIMER_SHIFT);
|
||||
timer_update_outstanding();
|
||||
timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC);
|
||||
fdc->interrupt = -1;
|
||||
fdc->perp &= 0xfc;
|
||||
fdc_ctrl_reset(fdc);
|
||||
@@ -802,7 +774,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (fdc->pnum==fdc->ptot) {
|
||||
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
|
||||
@@ -963,15 +935,39 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc->stat |= (1 << real_drive(fdc, fdc->drive));
|
||||
}
|
||||
}
|
||||
if (fdc->pnum==fdc->ptot) {
|
||||
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;
|
||||
/* Disable timer if enabled. */
|
||||
timer_disable(&fdc->timer);
|
||||
/* Start timer if needed at this point. */
|
||||
switch (fdc->interrupt & 0x1F) {
|
||||
case 2: /*Read a track*/
|
||||
case 0x02: /* Read a track */
|
||||
case 0x03: /* Specify */
|
||||
case 0x0a: /* Read sector ID */
|
||||
case 0x05: /* Write data */
|
||||
case 0x06: /* Read data */
|
||||
case 0x09: /* Write deleted data */
|
||||
case 0x0c: /* Read deleted data */
|
||||
case 0x11: /* Scan equal */
|
||||
case 0x12: /* Perpendicular mode */
|
||||
case 0x16: /* Verify */
|
||||
case 0x19: /* Scan low or equal */
|
||||
case 0x1d: /* Scan high or equal */
|
||||
/* Do nothing. */
|
||||
break;
|
||||
case 0x07: /* Recalibrate */
|
||||
case 0x0f: /* Seek */
|
||||
timer_set_delay_u64(&fdc->timer, 2048 * TIMER_USEC);
|
||||
break;
|
||||
default:
|
||||
timer_set_delay_u64(&fdc->timer, 256 * TIMER_USEC);
|
||||
break;
|
||||
}
|
||||
/* Process the firt phase of the command. */
|
||||
switch (fdc->interrupt & 0x1F) {
|
||||
case 0x02: /* 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];
|
||||
@@ -983,28 +979,17 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
}
|
||||
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;
|
||||
case 0x03: /* 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:
|
||||
case 0x04: /*Sense drive status*/
|
||||
fdd_set_head(real_drive(fdc, fdc->drive), (fdc->params[0] & 4) ? 1 : 0);
|
||||
break;
|
||||
case 5: /*Write data*/
|
||||
case 9: /*Write deleted data*/
|
||||
case 0x05: /* Write data */
|
||||
case 0x09: /* Write deleted data */
|
||||
fdc_io_command_phase1(fdc, 1);
|
||||
if ((fdc->head & 0x01) && !fdd_is_double_sided(real_drive(fdc, fdc->drive))) {
|
||||
fdc_noidam(fdc);
|
||||
@@ -1012,9 +997,9 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
}
|
||||
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*/
|
||||
case 0x11: /* Scan equal */
|
||||
case 0x19: /* Scan low or equal */
|
||||
case 0x1d: /* Scan high or equal */
|
||||
fdc_io_command_phase1(fdc, 1);
|
||||
if ((fdc->head & 0x01) && !fdd_is_double_sided(real_drive(fdc, fdc->drive))) {
|
||||
fdc_noidam(fdc);
|
||||
@@ -1022,11 +1007,11 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
}
|
||||
fdd_comparesector(real_drive(fdc, fdc->drive), fdc->sector, fdc->params[1], fdc->head, fdc->rate, fdc->params[4]);
|
||||
break;
|
||||
case 0x16: /*Verify*/
|
||||
case 0x16: /* Verify */
|
||||
if (fdc->params[0] & 0x80)
|
||||
fdc->sc = fdc->params[7];
|
||||
case 6: /*Read data*/
|
||||
case 0xC: /*Read deleted data*/
|
||||
case 0x06: /* Read data */
|
||||
case 0x0c: /* 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 ((fdc->head & 0x01) && !fdd_is_double_sided(real_drive(fdc, fdc->drive))) {
|
||||
@@ -1042,12 +1027,12 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdd_readsector(real_drive(fdc, fdc->drive), fdc->sector, fdc->params[1], fdc->head, fdc->rate, fdc->params[4]);
|
||||
break;
|
||||
|
||||
case 7: /*Recalibrate*/
|
||||
case 0x07: /* Recalibrate */
|
||||
fdc->rw_drive = fdc->params[0] & 3;
|
||||
fdc->stat = (1 << real_drive(fdc, fdc->drive)) | 0x80;
|
||||
fdc->st0 = fdc->drive & 0x03;
|
||||
fdc->st0 = fdc->params[0] & 3;
|
||||
fdc->st0 |= fdd_get_head(real_drive(fdc, fdc->drive)) ? 0x04 : 0x00;
|
||||
fdc->st0 |= 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)) {
|
||||
@@ -1058,18 +1043,28 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc->st0 = 0x20 | (fdc->params[0] & 3);
|
||||
fdc->pcn[fdc->params[0] & 3] = 0;
|
||||
fdc->interrupt = -3;
|
||||
timer_process();
|
||||
fdc->time = 2048LL * (1LL << TIMER_SHIFT);
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
}
|
||||
if ((real_drive(fdc, fdc->drive) != 1) || fdc->drv2en)
|
||||
fdc_seek(fdc, fdc->drive, -fdc->max_track);
|
||||
fdc_log("Recalibrating...\n");
|
||||
fdc->time = 2048LL * (1 << TIMER_SHIFT);
|
||||
fdc->seek_dir = fdc->step = 1;
|
||||
break;
|
||||
case 0x0d: /*Format*/
|
||||
case 0x0a: /* Read sector ID */
|
||||
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);
|
||||
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_noidam(fdc);
|
||||
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);
|
||||
@@ -1081,14 +1076,14 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc->pos = 0;
|
||||
fdc->stat = 0x10;
|
||||
break;
|
||||
case 0xf: /*Seek*/
|
||||
case 0x0f: /* Seek */
|
||||
fdc->rw_drive = fdc->params[0] & 3;
|
||||
fdc->stat = (1 << fdc->drive) | 0x80;
|
||||
fdc->head = (fdc->params[0] & 4) ? 1 : 0;
|
||||
fdc->st0 = fdc->drive & 0x03;
|
||||
fdc->st0 = fdc->params[0] & 0x03;
|
||||
fdc->st0 |= (fdc->params[0] & 4);
|
||||
fdc->st0 |= 0x80;
|
||||
fdd_set_head(real_drive(fdc, fdc->drive), (fdc->params[0] & 4) ? 1 : 0);
|
||||
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]) {
|
||||
@@ -1102,9 +1097,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
} else
|
||||
fdc->pcn[fdc->params[0] & 3] = fdc->params[1];
|
||||
fdc->interrupt = -3;
|
||||
timer_process();
|
||||
fdc->time = 2048LL * (1LL << TIMER_SHIFT);
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
}
|
||||
if (fdc->command & 0x80) {
|
||||
@@ -1120,14 +1112,10 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc_seek(fdc, fdc->drive, -fdc->params[1]);
|
||||
fdc->pcn[fdc->params[0] & 3] -= fdc->params[1];
|
||||
}
|
||||
fdc->time = 2048LL * (1 << TIMER_SHIFT);
|
||||
fdc->step = 1;
|
||||
} else {
|
||||
fdc->st0 = 0x20 | (fdc->params[0] & 7);
|
||||
fdc->interrupt = -3;
|
||||
timer_process();
|
||||
fdc->time = 2048LL * (1LL << TIMER_SHIFT);
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -1136,9 +1124,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc_log("Failed seek\n");
|
||||
fdc->st0 = 0x20 | (fdc->params[0] & 7);
|
||||
fdc->interrupt = -3;
|
||||
timer_process();
|
||||
fdc->time = 2048LL * (1LL << TIMER_SHIFT);
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
}
|
||||
if (fdc->params[1] > fdc->pcn[fdc->params[0] & 3])
|
||||
@@ -1147,26 +1132,19 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
fdc->seek_dir = 1;
|
||||
fdc_seek(fdc, fdc->drive, fdc->params[1] - fdc->pcn[fdc->params[0] & 3]);
|
||||
fdc->pcn[fdc->params[0] & 3] = fdc->params[1];
|
||||
fdc->time = 2048LL * (1 << TIMER_SHIFT);
|
||||
fdc->step = 1;
|
||||
fdc_log("fdc->time = %i\n", fdc->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;
|
||||
case 0x12: /* Perpendicular mode */
|
||||
fdc->stat = 0x80;
|
||||
if (fdc->params[0] & 0x80)
|
||||
fdc->perp = fdc->params[0] & 0x3f;
|
||||
else {
|
||||
fdc->perp &= 0xfc;
|
||||
fdc->perp |= (fdc->params[0] & 0x03);
|
||||
}
|
||||
else
|
||||
fdc_noidam(fdc);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
} else
|
||||
fdc->stat = 0x90 | (fdc->stat & 0xf);
|
||||
@@ -1190,8 +1168,7 @@ fdc_read(uint16_t addr, void *priv)
|
||||
uint8_t ret;
|
||||
int drive;
|
||||
|
||||
cycles -= ISA_CYCLES(8);
|
||||
// pclog("fdc_read(): cycles -= ISA_CYCLES(8);\n");
|
||||
sub_cycles(ISA_CYCLES(8));
|
||||
|
||||
switch (addr & 7) {
|
||||
case 0: /* STA */
|
||||
@@ -1240,13 +1217,13 @@ fdc_read(uint16_t addr, void *priv)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (is486)
|
||||
if (is486 || !fdc->enable_3f1)
|
||||
return 0xff;
|
||||
drive = real_drive(fdc, fdc->dor & 3);
|
||||
if (!fdc->enable_3f1)
|
||||
ret = 0xff;
|
||||
|
||||
ret = 0x70;
|
||||
|
||||
drive = real_drive(fdc, fdc->dor & 3);
|
||||
|
||||
if (drive)
|
||||
ret &= ~0x40;
|
||||
else
|
||||
@@ -1322,7 +1299,6 @@ fdc_read(uint16_t addr, void *priv)
|
||||
drive = real_drive(fdc, fdc->dor & 3);
|
||||
|
||||
if (fdc->flags & FDC_FLAG_PS1) {
|
||||
fdc->step = 0;
|
||||
if (fdc->dor & (0x10 << drive)) {
|
||||
ret = (fdd_changed[drive] || drive_empty[drive]) ? 0x00 : 0x80;
|
||||
ret |= (fdc->dor & 0x08);
|
||||
@@ -1342,10 +1318,11 @@ fdc_read(uint16_t addr, void *priv)
|
||||
ret ^= 0x80;
|
||||
|
||||
/* 0 = ????, 1 = Ext. FDD off, 2 = Ext. FDD = FDD A, 3 = Ext. FDD = FDD B */
|
||||
if (fdc->flags & FDC_FLAG_TOSHIBA)
|
||||
if (fdc->flags & FDC_FLAG_TOSHIBA) {
|
||||
ret |= (3 << 5);
|
||||
|
||||
ret |= 0x01;
|
||||
ret |= 0x01;
|
||||
} else
|
||||
ret |= 0x7F;
|
||||
}
|
||||
|
||||
fdc->step = 0;
|
||||
@@ -1399,7 +1376,7 @@ fdc_poll_common_finish(fdc_t *fdc, int compare, int st5)
|
||||
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);
|
||||
ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 0);
|
||||
fdc->paramstogo = 7;
|
||||
}
|
||||
|
||||
@@ -1417,7 +1394,7 @@ fdc_poll_readwrite_finish(fdc_t *fdc, int compare)
|
||||
static void
|
||||
fdc_no_dma_end(fdc_t *fdc, int compare)
|
||||
{
|
||||
fdc->time = 0LL;
|
||||
timer_disable(&fdc->timer);
|
||||
|
||||
fdc_poll_common_finish(fdc, compare, 0x80);
|
||||
}
|
||||
@@ -1430,7 +1407,6 @@ fdc_callback(void *priv)
|
||||
int compare = 0;
|
||||
int drive_num = 0;
|
||||
int old_sector = 0;
|
||||
fdc->time = 0LL;
|
||||
fdc_log("fdc_callback(): %i\n", fdc->interrupt);
|
||||
switch (fdc->interrupt) {
|
||||
case -3: /*End of command with interrupt*/
|
||||
@@ -1446,12 +1422,12 @@ fdc_callback(void *priv)
|
||||
memset(fdc->pcn, 0, 4 * sizeof(int));
|
||||
fdc->reset_stat = 4;
|
||||
return;
|
||||
case 1: /*Mode*/
|
||||
case 0x01: /* 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);
|
||||
case 0x02: /* Read track */
|
||||
ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 1);
|
||||
fdc->eot[fdc->drive]--;
|
||||
fdc->read_track_sector.id.r++;
|
||||
if (!fdc->eot[fdc->drive] || fdc->tc) {
|
||||
@@ -1466,7 +1442,7 @@ fdc_callback(void *priv)
|
||||
}
|
||||
fdc->inread = 1;
|
||||
return;
|
||||
case 4: /*Sense drive status*/
|
||||
case 0x04: /* Sense drive status */
|
||||
fdc->res[10] = (fdc->params[0] & 7) | 0x20;
|
||||
if (fdd_is_double_sided(real_drive(fdc, fdc->drive)))
|
||||
fdc->res[10] |= 0x08;
|
||||
@@ -1480,16 +1456,15 @@ fdc_callback(void *priv)
|
||||
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*/
|
||||
case 0x05: /* Write data */
|
||||
case 0x09: /* Write deleted data */
|
||||
case 0x06: /* Read data */
|
||||
case 0x0c: /* 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
|
||||
@@ -1572,7 +1547,7 @@ fdc_callback(void *priv)
|
||||
}
|
||||
} else if (fdc->sector < fdc->params[5])
|
||||
fdc->sector++;
|
||||
ui_sb_update_icon(SB_FLOPPY | fdc->drive, 1);
|
||||
ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 1);
|
||||
switch (fdc->interrupt) {
|
||||
case 5:
|
||||
case 9:
|
||||
@@ -1603,24 +1578,20 @@ fdc_callback(void *priv)
|
||||
}
|
||||
fdc->inread = 1;
|
||||
return;
|
||||
case 7: /*Recalibrate*/
|
||||
case 0x07: /* 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();
|
||||
fdc->time = 2048LL * (1LL << TIMER_SHIFT);
|
||||
timer_update_outstanding();
|
||||
fdc->stat = 0x80 | (1 << fdc->drive);
|
||||
timer_set_delay_u64(&fdc->timer, 2048 * TIMER_USEC);
|
||||
fdc->stat = 0x80 | (1 << fdc->rw_drive);
|
||||
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();
|
||||
timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC);
|
||||
} else if (fdc->format_state == 2) {
|
||||
fdd_format(real_drive(fdc, fdc->drive), fdc->head, fdc->rate, fdc->params[4]);
|
||||
fdc->format_state = 3;
|
||||
@@ -1655,16 +1626,11 @@ fdc_callback(void *priv)
|
||||
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);
|
||||
fdc->stat = 0x80 | (1 << fdc->rw_drive);
|
||||
fdc_callback(fdc);
|
||||
return;
|
||||
case 0x10: /*Version*/
|
||||
@@ -1673,7 +1639,6 @@ fdc_callback(void *priv)
|
||||
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];
|
||||
@@ -1681,7 +1646,6 @@ fdc_callback(void *priv)
|
||||
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*/
|
||||
@@ -1690,7 +1654,6 @@ fdc_callback(void *priv)
|
||||
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;
|
||||
@@ -1698,7 +1661,6 @@ fdc_callback(void *priv)
|
||||
fdc->res[10] = fdc->st0;
|
||||
fdc->paramstogo = 1;
|
||||
fdc->interrupt = 0;
|
||||
fdc->time = 0LL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1707,7 +1669,7 @@ fdc_callback(void *priv)
|
||||
void
|
||||
fdc_error(fdc_t *fdc, int st5, int st6)
|
||||
{
|
||||
fdc->time = 0LL;
|
||||
timer_disable(&fdc->timer);
|
||||
|
||||
fdc_int(fdc);
|
||||
if (!(fdc->flags & FDC_FLAG_PS1))
|
||||
@@ -1741,7 +1703,7 @@ fdc_error(fdc_t *fdc, int st5, int st6)
|
||||
fdc->res[10]=0;
|
||||
break;
|
||||
}
|
||||
ui_sb_update_icon(SB_FLOPPY | fdc->drive, 0);
|
||||
ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 0);
|
||||
fdc->paramstogo = 7;
|
||||
}
|
||||
|
||||
@@ -1979,7 +1941,7 @@ fdc_sectorid(fdc_t *fdc, uint8_t track, uint8_t side, uint8_t sector, uint8_t si
|
||||
fdc->res[8] = side;
|
||||
fdc->res[9] = sector;
|
||||
fdc->res[10] = size;
|
||||
ui_sb_update_icon(SB_FLOPPY | fdc->drive, 0);
|
||||
ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 0);
|
||||
fdc->paramstogo = 7;
|
||||
}
|
||||
|
||||
@@ -2034,15 +1996,19 @@ fdc_set_base(fdc_t *fdc, int base)
|
||||
{
|
||||
int super_io = (fdc->flags & FDC_FLAG_SUPERIO);
|
||||
|
||||
if (fdc->flags & FDC_FLAG_AT) {
|
||||
if ((fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_AMSTRAD)) {
|
||||
io_sethandler(base + (super_io ? 2 : 0), super_io ? 0x0004 : 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_sethandler(base + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
} else {
|
||||
io_sethandler(base + 0x0002, 0x0001, NULL, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_sethandler(base + 0x0004, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc);
|
||||
io_sethandler(base + 0x0005, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
if (fdc->flags & FDC_FLAG_TOSHIBA)
|
||||
io_sethandler(base + 0x0007, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
if (fdc->flags & FDC_FLAG_PCJR)
|
||||
io_sethandler(base, 0x0010, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
else {
|
||||
io_sethandler(base + 0x0002, 0x0001, NULL, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_sethandler(base + 0x0004, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc);
|
||||
io_sethandler(base + 0x0005, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
if (fdc->flags & FDC_FLAG_TOSHIBA)
|
||||
io_sethandler(base + 0x0007, 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);
|
||||
@@ -2055,15 +2021,19 @@ fdc_remove(fdc_t *fdc)
|
||||
int super_io = (fdc->flags & FDC_FLAG_SUPERIO);
|
||||
|
||||
fdc_log("fdc_t Removed (%04X)\n", fdc->base_address);
|
||||
if (fdc->flags & FDC_FLAG_AT) {
|
||||
if ((fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_AMSTRAD)) {
|
||||
io_removehandler(fdc->base_address + (super_io ? 2 : 0), super_io ? 0x0004 : 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_removehandler(fdc->base_address + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
} else {
|
||||
io_removehandler(fdc->base_address + 0x0002, 0x0001, NULL, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_removehandler(fdc->base_address + 0x0004, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc);
|
||||
io_removehandler(fdc->base_address + 0x0005, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
if (fdc->flags & FDC_FLAG_TOSHIBA)
|
||||
io_removehandler(fdc->base_address + 0x0007, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
if (fdc->flags & FDC_FLAG_PCJR)
|
||||
io_removehandler(fdc->base_address, 0x0010, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
else {
|
||||
io_removehandler(fdc->base_address + 0x0002, 0x0001, NULL, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_removehandler(fdc->base_address + 0x0004, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc);
|
||||
io_removehandler(fdc->base_address + 0x0005, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
if (fdc->flags & FDC_FLAG_TOSHIBA)
|
||||
io_removehandler(fdc->base_address + 0x0007, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2138,11 +2108,8 @@ fdc_close(void *priv)
|
||||
fdc_reset(fdc);
|
||||
|
||||
/* Stop timers. */
|
||||
fdc->watchdog_timer = 0;
|
||||
fdc->watchdog_count = 0;
|
||||
|
||||
fdc->time = 0;
|
||||
|
||||
free(fdc);
|
||||
}
|
||||
|
||||
@@ -2159,13 +2126,13 @@ fdc_init(const device_t *info)
|
||||
fdc->irq = 6;
|
||||
|
||||
if (fdc->flags & FDC_FLAG_PCJR)
|
||||
timer_add(fdc_watchdog_poll, &fdc->watchdog_timer, &fdc->watchdog_timer, fdc);
|
||||
timer_add(&fdc->watchdog_timer, fdc_watchdog_poll, fdc, 0);
|
||||
else
|
||||
fdc->dma_ch = 2;
|
||||
|
||||
fdc_log("FDC added: %04X (flags: %08X)\n", fdc->base_address, fdc->flags);
|
||||
|
||||
timer_add(fdc_callback, &fdc->time, &fdc->time, fdc);
|
||||
timer_add(&fdc->timer, fdc_callback, fdc, 0);
|
||||
|
||||
d86f_set_fdc(fdc);
|
||||
fdi_set_fdc(fdc);
|
||||
@@ -2198,7 +2165,7 @@ const device_t fdc_xt_device = {
|
||||
};
|
||||
|
||||
const device_t fdc_xt_t1x00_device = {
|
||||
"PC/XT Floppy Drive Controller",
|
||||
"PC/XT Floppy Drive Controller (Toshiba)",
|
||||
0,
|
||||
FDC_FLAG_TOSHIBA,
|
||||
fdc_init,
|
||||
@@ -2207,6 +2174,17 @@ const device_t fdc_xt_t1x00_device = {
|
||||
NULL, NULL, NULL
|
||||
};
|
||||
|
||||
const device_t fdc_xt_amstrad_device = {
|
||||
"PC/XT Floppy Drive Controller (Amstrad)",
|
||||
0,
|
||||
FDC_FLAG_DISKCHG_ACTLOW | FDC_FLAG_AMSTRAD,
|
||||
fdc_init,
|
||||
fdc_close,
|
||||
fdc_reset,
|
||||
NULL, NULL, NULL
|
||||
};
|
||||
|
||||
|
||||
const device_t fdc_pcjr_device = {
|
||||
"PCjr Floppy Drive Controller",
|
||||
0,
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* Implementation of the NEC uPD-765 and compatible floppy disk
|
||||
* controller.
|
||||
*
|
||||
* Version: @(#)fdc.h 1.0.5 2018/09/22
|
||||
* Version: @(#)fdc.h 1.0.6 2019/03/23
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -50,6 +50,7 @@
|
||||
#define FDC_FLAG_MORE_TRACKS 0x40 /* W83877F, W83977F, PC87306, PC87309 */
|
||||
#define FDC_FLAG_NSC 0x80 /* PC87306, PC87309 */
|
||||
#define FDC_FLAG_TOSHIBA 0x100 /* T1000, T1200 */
|
||||
#define FDC_FLAG_AMSTRAD 0x200 /* Non-AT Amstrad machines */
|
||||
|
||||
|
||||
typedef struct {
|
||||
@@ -99,8 +100,9 @@ typedef struct {
|
||||
|
||||
sector_id_t read_track_sector;
|
||||
|
||||
int64_t time;
|
||||
int64_t watchdog_timer, watchdog_count;
|
||||
uint64_t watchdog_count;
|
||||
|
||||
pc_timer_t timer, watchdog_timer;
|
||||
} fdc_t;
|
||||
|
||||
|
||||
@@ -180,11 +182,12 @@ extern void fdc_sectorid(fdc_t *fdc, uint8_t track, uint8_t side,
|
||||
extern uint8_t fdc_read(uint16_t addr, void *priv);
|
||||
extern void fdc_reset(void *priv);
|
||||
|
||||
extern uint8_t fdc_ps1_525(void);
|
||||
extern uint8_t fdc_get_current_drive(void);
|
||||
|
||||
#ifdef EMU_DEVICE_H
|
||||
extern const device_t fdc_xt_device;
|
||||
extern const device_t fdc_xt_t1x00_device;
|
||||
extern const device_t fdc_xt_amstrad_device;
|
||||
extern const device_t fdc_pcjr_device;
|
||||
extern const device_t fdc_at_device;
|
||||
extern const device_t fdc_at_actlow_device;
|
||||
|
||||
1047
src/floppy/fdd.c
1047
src/floppy/fdd.c
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Definitions for the floppy drive emulation.
|
||||
*
|
||||
* Version: @(#)fdd.h 1.0.5 2018/11/12
|
||||
* Version: @(#)fdd.h 1.0.6 2019/02/11
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -50,7 +50,7 @@ extern "C" {
|
||||
|
||||
extern int fdd_swap;
|
||||
|
||||
|
||||
extern void fdd_set_motor_enable(int drive, int motor_enable);
|
||||
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);
|
||||
@@ -85,6 +85,8 @@ extern int fdd_current_track(int drive);
|
||||
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
|
||||
void (*seek)(int drive, int track);
|
||||
void (*readsector)(int drive, int sector, int track, int side,
|
||||
int density, int sector_size);
|
||||
@@ -95,17 +97,16 @@ typedef struct {
|
||||
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);
|
||||
uint64_t (*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 DRIVE drives[FDD_NUM];
|
||||
extern wchar_t floppyfns[FDD_NUM][512];
|
||||
extern pc_timer_t fdd_poll_time[FDD_NUM];
|
||||
extern int ui_writeprot[FDD_NUM];
|
||||
|
||||
extern int curdrive;
|
||||
|
||||
@@ -118,11 +119,6 @@ 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);
|
||||
@@ -133,12 +129,10 @@ extern void fdd_comparesector(int drive, int sector, int track,
|
||||
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 void fdd_set_rate(int drive, int drvden, int rate);
|
||||
|
||||
extern int motorspin;
|
||||
extern int64_t motoron[FDD_NUM];
|
||||
extern uint64_t motoron[FDD_NUM];
|
||||
|
||||
extern int swwp;
|
||||
extern int disable_write;
|
||||
@@ -146,10 +140,8 @@ 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
|
||||
|
||||
3924
src/floppy/fdd_86f - Cópia.c
Normal file
3924
src/floppy/fdd_86f - Cópia.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -45,6 +45,7 @@
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "../86box.h"
|
||||
#include "../timer.h"
|
||||
#include "../dma.h"
|
||||
#include "../nvr.h"
|
||||
#include "../random.h"
|
||||
@@ -534,6 +535,7 @@ common_get_raw_size(int drive, int side)
|
||||
double size = 100000.0;
|
||||
int mfm;
|
||||
int rm, ssd;
|
||||
uint32_t extra_bc = 0;
|
||||
|
||||
mfm = d86f_is_mfm(drive);
|
||||
rpm = ((d86f_track_flags(drive) & 0xE0) == 0x20) ? 360.0 : 300.0;
|
||||
@@ -541,6 +543,13 @@ common_get_raw_size(int drive, int side)
|
||||
rm = d86f_get_rpm_mode(drive);
|
||||
ssd = d86f_get_speed_shift_dir(drive);
|
||||
|
||||
/* 0% speed shift and shift direction 1: special case where extra bit cells are the entire track size. */
|
||||
if (!rm && ssd)
|
||||
extra_bc = d86f_handler[drive].extra_bit_cells(drive, side);
|
||||
|
||||
if (extra_bc)
|
||||
return extra_bc;
|
||||
|
||||
switch (rm) {
|
||||
case 1:
|
||||
rpm_diff = 1.01;
|
||||
@@ -590,13 +599,9 @@ common_get_raw_size(int drive, int side)
|
||||
|
||||
if (! mfm) rate /= 2.0;
|
||||
|
||||
if (!rm && ssd)
|
||||
size = 0.0;
|
||||
else {
|
||||
size = (size / 250.0) * rate;
|
||||
size = (size * 300.0) / rpm;
|
||||
size *= rpm_diff;
|
||||
}
|
||||
size = (size / 250.0) * rate;
|
||||
size = (size * 300.0) / rpm;
|
||||
size *= rpm_diff;
|
||||
|
||||
/*
|
||||
* Round down to a multiple of 16 and add the extra bit cells,
|
||||
@@ -658,7 +663,7 @@ d86f_register_86f(int drive)
|
||||
|
||||
|
||||
int
|
||||
d86f_get_array_size(int drive, int side)
|
||||
d86f_get_array_size(int drive, int side, int words)
|
||||
{
|
||||
int array_size;
|
||||
int hole, rm;
|
||||
@@ -736,10 +741,14 @@ d86f_get_array_size(int drive, int side)
|
||||
|
||||
array_size <<= 4;
|
||||
array_size += d86f_handler[drive].extra_bit_cells(drive, side);
|
||||
array_size >>= 4;
|
||||
|
||||
if (d86f_handler[drive].extra_bit_cells(drive, side) & 15)
|
||||
array_size++;
|
||||
if (array_size & 15)
|
||||
array_size = (array_size >> 4) + 1;
|
||||
else
|
||||
array_size = (array_size >> 4);
|
||||
|
||||
if (!words)
|
||||
array_size <<= 1;
|
||||
|
||||
return array_size;
|
||||
}
|
||||
@@ -795,37 +804,39 @@ d86f_get_encoding(int drive)
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
uint64_t
|
||||
d86f_byteperiod(int drive)
|
||||
{
|
||||
double dusec = (double) TIMER_USEC;
|
||||
double p = 2.0;
|
||||
|
||||
switch (d86f_track_flags(drive) & 0x0f) {
|
||||
case 0x02: /* 125 kbps, FM */
|
||||
return 4.0;
|
||||
|
||||
p = 4.0;
|
||||
break;
|
||||
case 0x01: /* 150 kbps, FM */
|
||||
return 20.0 / 6.0;
|
||||
|
||||
p = 20.0 / 6.0;
|
||||
break;
|
||||
case 0x0a: /* 250 kbps, MFM */
|
||||
case 0x00: /* 250 kbps, FM */
|
||||
return 2.0;
|
||||
|
||||
case 0x09: /* 300 kbps, MFM */
|
||||
return 10.0 / 6.0;
|
||||
|
||||
case 0x08: /* 500 kbps, MFM */
|
||||
return 1.0;
|
||||
|
||||
case 0x0b: /* 1000 kbps, MFM */
|
||||
return 0.5;
|
||||
|
||||
case 0x0d: /* 2000 kbps, MFM */
|
||||
return 0.25;
|
||||
|
||||
default:
|
||||
p = 2.0;
|
||||
break;
|
||||
case 0x09: /* 300 kbps, MFM */
|
||||
p = 10.0 / 6.0;
|
||||
break;
|
||||
case 0x08: /* 500 kbps, MFM */
|
||||
p = 1.0;
|
||||
break;
|
||||
case 0x0b: /* 1000 kbps, MFM */
|
||||
p = 0.5;
|
||||
break;
|
||||
case 0x0d: /* 2000 kbps, MFM */
|
||||
p = 0.25;
|
||||
break;
|
||||
}
|
||||
|
||||
return 2.0;
|
||||
return (uint64_t) (p * dusec);
|
||||
}
|
||||
|
||||
|
||||
@@ -1592,7 +1603,14 @@ d86f_read_sector_data(int drive, int side)
|
||||
/* We've got a byte. */
|
||||
d86f_log("86F: We've got a byte.\n");
|
||||
if (dev->data_find.bytes_obtained < sector_len) {
|
||||
data = decodefm(drive, dev->last_word[side]);
|
||||
#ifdef HACK_FOR_DBASE_III
|
||||
if ((dev->last_sector.id.c == 39) && (dev->last_sector.id.h == 0) &&
|
||||
(dev->last_sector.id.r == 5) && (dev->data_find.bytes_obtained >= 272)) {
|
||||
pclog("Randomly generating sector 39,0,5 byte %i...\n", dev->data_find.bytes_obtained);
|
||||
data = (random_generate() & 0xff);
|
||||
} else
|
||||
#endif
|
||||
data = decodefm(drive, dev->last_word[side]);
|
||||
if (dev->state == STATE_11_SCAN_DATA) {
|
||||
/* Scan/compare command. */
|
||||
recv_data = d86f_get_data(drive, 0);
|
||||
@@ -2618,7 +2636,11 @@ d86f_prepare_pretrack(int drive, int side, int iso)
|
||||
sync_len = mfm ? 12 : 6;
|
||||
real_gap1_len = mfm ? 50 : 26;
|
||||
gap_fill = mfm ? 0x4E : 0xFF;
|
||||
raw_size = d86f_handler[drive].get_raw_size(drive, side) >> 4;
|
||||
raw_size = d86f_handler[drive].get_raw_size(drive, side);
|
||||
if (raw_size & 15)
|
||||
raw_size = (raw_size >> 4) + 1;
|
||||
else
|
||||
raw_size = (raw_size >> 4);
|
||||
|
||||
dev->index_hole_pos[side] = 0;
|
||||
|
||||
@@ -2694,7 +2716,11 @@ d86f_prepare_sector(int drive, int side, int prev_pos, uint8_t *id_buf, uint8_t
|
||||
mfm = d86f_is_mfm(drive);
|
||||
|
||||
gap_fill = mfm ? 0x4E : 0xFF;
|
||||
raw_size = d86f_handler[drive].get_raw_size(drive, side) >> 4;
|
||||
raw_size = d86f_handler[drive].get_raw_size(drive, side);
|
||||
if (raw_size & 15)
|
||||
raw_size = (raw_size >> 4) + 1;
|
||||
else
|
||||
raw_size = (raw_size >> 4);
|
||||
|
||||
pos = prev_pos;
|
||||
|
||||
@@ -2800,7 +2826,7 @@ d86f_construct_encoded_buffer(int drive, int side)
|
||||
uint16_t *src1_s = dev->thin_track_surface_data[0][side];
|
||||
uint16_t *src2 = dev->thin_track_encoded_data[1][side];
|
||||
uint16_t *src2_s = dev->thin_track_surface_data[1][side];
|
||||
len = d86f_get_array_size(drive, side);
|
||||
len = d86f_get_array_size(drive, side, 1);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
/* The two bits differ. */
|
||||
@@ -2847,7 +2873,7 @@ d86f_decompose_encoded_buffer(int drive, int side)
|
||||
uint16_t *src2 = dev->thin_track_encoded_data[1][side];
|
||||
uint16_t *src2_s = dev->thin_track_surface_data[1][side];
|
||||
dst = d86f_handler[drive].encoded_data(drive, side);
|
||||
len = d86f_get_array_size(drive, side);
|
||||
len = d86f_get_array_size(drive, side, 1);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (d86f_has_surface_desc(drive)) {
|
||||
@@ -2909,7 +2935,7 @@ d86f_read_track(int drive, int track, int thin_track, int side, uint16_t *da, ui
|
||||
fread(&(dev->index_hole_pos[side]), 4, 1, dev->f);
|
||||
} else
|
||||
fseek(dev->f, dev->track_offset[logical_track] + d86f_track_header_size(drive), SEEK_SET);
|
||||
array_size = d86f_get_array_size(drive, side) << 1;
|
||||
array_size = d86f_get_array_size(drive, side, 0);
|
||||
if (d86f_has_surface_desc(drive))
|
||||
fread(sa, 1, array_size, dev->f);
|
||||
fread(da, 1, array_size, dev->f);
|
||||
@@ -2995,6 +3021,7 @@ d86f_seek(int drive, int track)
|
||||
void
|
||||
d86f_write_track(int drive, FILE **f, int side, uint16_t *da0, uint16_t *sa0)
|
||||
{
|
||||
uint32_t array_size = d86f_get_array_size(drive, side, 0);
|
||||
uint16_t side_flags = d86f_handler[drive].side_flags(drive);
|
||||
uint32_t extra_bit_cells = d86f_handler[drive].extra_bit_cells(drive, side);
|
||||
uint32_t index_hole_pos = d86f_handler[drive].index_hole_pos(drive, side);
|
||||
@@ -3007,9 +3034,9 @@ d86f_write_track(int drive, FILE **f, int side, uint16_t *da0, uint16_t *sa0)
|
||||
fwrite(&index_hole_pos, 1, 4, *f);
|
||||
|
||||
if (d86f_has_surface_desc(drive))
|
||||
fwrite(sa0, 1, d86f_get_array_size(drive, side) << 1, *f);
|
||||
fwrite(sa0, 1, array_size, *f);
|
||||
|
||||
fwrite(da0, 1, d86f_get_array_size(drive, side) << 1, *f);
|
||||
fwrite(da0, 1, array_size, *f);
|
||||
}
|
||||
|
||||
|
||||
@@ -3049,7 +3076,7 @@ d86f_write_tracks(int drive, FILE **f, uint32_t *track_table)
|
||||
if (track_table)
|
||||
tbl = track_table;
|
||||
|
||||
if (! fdd_doublestep_40(drive)) {
|
||||
if (!fdd_doublestep_40(drive)) {
|
||||
d86f_decompose_encoded_buffer(drive, 0);
|
||||
if (sides == 2)
|
||||
d86f_decompose_encoded_buffer(drive, 1);
|
||||
@@ -3281,8 +3308,7 @@ d86f_add_track(int drive, int track, int side)
|
||||
uint32_t array_size;
|
||||
int logical_track;
|
||||
|
||||
array_size = d86f_get_array_size(drive, side);
|
||||
array_size <<= 1;
|
||||
array_size = d86f_get_array_size(drive, side, 0);
|
||||
|
||||
if (d86f_get_sides(drive) == 2) {
|
||||
logical_track = (track << 1) + side;
|
||||
@@ -3338,7 +3364,7 @@ d86f_common_format(int drive, int side, int rate, uint8_t fill, int proxy)
|
||||
return;
|
||||
}
|
||||
|
||||
array_size = d86f_get_array_size(drive, side);
|
||||
array_size = d86f_get_array_size(drive, side, 0);
|
||||
|
||||
if (d86f_has_surface_desc(drive)) {
|
||||
/* Preserve the physical holes but get rid of the fuzzy bytes. */
|
||||
@@ -3351,7 +3377,7 @@ d86f_common_format(int drive, int side, int rate, uint8_t fill, int proxy)
|
||||
}
|
||||
|
||||
/* Zero the data buffer. */
|
||||
memset(dev->track_encoded_data[side], 0, array_size << 1);
|
||||
memset(dev->track_encoded_data[side], 0, array_size);
|
||||
|
||||
d86f_add_track(drive, dev->cur_track, side);
|
||||
if (! fdd_doublestep_40(drive))
|
||||
@@ -3727,8 +3753,10 @@ d86f_load(int drive, wchar_t *fn)
|
||||
fread(&(dev->side_flags[0]), 2, 1, dev->f);
|
||||
if (dev->disk_flags & 0x80) {
|
||||
fread(&(dev->extra_bit_cells[0]), 4, 1, dev->f);
|
||||
if (dev->extra_bit_cells[0] < -32768) dev->extra_bit_cells[0] = -32768;
|
||||
if (dev->extra_bit_cells[0] > 32768) dev->extra_bit_cells[0] = 32768;
|
||||
if ((dev->disk_flags & 0x1060) != 0x1000) {
|
||||
if (dev->extra_bit_cells[0] < -32768) dev->extra_bit_cells[0] = -32768;
|
||||
if (dev->extra_bit_cells[0] > 32768) dev->extra_bit_cells[0] = 32768;
|
||||
}
|
||||
} else {
|
||||
dev->extra_bit_cells[0] = 0;
|
||||
}
|
||||
@@ -3738,8 +3766,10 @@ d86f_load(int drive, wchar_t *fn)
|
||||
fread(&(dev->side_flags[1]), 2, 1, dev->f);
|
||||
if (dev->disk_flags & 0x80) {
|
||||
fread(&(dev->extra_bit_cells[1]), 4, 1, dev->f);
|
||||
if (dev->extra_bit_cells[1] < -32768) dev->extra_bit_cells[1] = -32768;
|
||||
if (dev->extra_bit_cells[1] > 32768) dev->extra_bit_cells[1] = 32768;
|
||||
if ((dev->disk_flags & 0x1060) != 0x1000) {
|
||||
if (dev->extra_bit_cells[1] < -32768) dev->extra_bit_cells[1] = -32768;
|
||||
if (dev->extra_bit_cells[1] > 32768) dev->extra_bit_cells[1] = 32768;
|
||||
}
|
||||
} else {
|
||||
dev->extra_bit_cells[0] = 0;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ 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 uint64_t d86f_byteperiod(int drive);
|
||||
extern void d86f_stop(int drive);
|
||||
extern void d86f_poll(int drive);
|
||||
extern int d86f_realtrack(int track, int drive);
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../timer.h"
|
||||
#include "fdd.h"
|
||||
#include "fdd_common.h"
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "../86box.h"
|
||||
#include "../timer.h"
|
||||
#include "../plat.h"
|
||||
#include "fdd.h"
|
||||
#include "fdd_86f.h"
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "../86box.h"
|
||||
#include "../timer.h"
|
||||
#include "../plat.h"
|
||||
#include "fdd.h"
|
||||
#include "fdd_imd.h"
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "../86box.h"
|
||||
#include "../timer.h"
|
||||
#include "../config.h"
|
||||
#include "../plat.h"
|
||||
#include "fdd.h"
|
||||
@@ -620,6 +621,16 @@ img_init(void)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
is_divisible(uint16_t total, uint8_t what)
|
||||
{
|
||||
if ((total != 0) && (what != 0))
|
||||
return ((total % what) == 0);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
img_load(int drive, wchar_t *fn)
|
||||
{
|
||||
@@ -968,10 +979,13 @@ jump_if_fdf:
|
||||
img_log("BPB reports %i sides and %i bytes per sector (%i sectors total)\n",
|
||||
bpb_sides, bpb_bps, bpb_total);
|
||||
|
||||
guess = (bpb_sides < 1);
|
||||
guess = guess || (bpb_sides > 2);
|
||||
guess = guess || !bps_is_valid(bpb_bps);
|
||||
guess = guess || !first_byte_is_valid(first_byte);
|
||||
/* Invalid conditions: */
|
||||
guess = (bpb_sides < 1); /* Sides < 1; */
|
||||
guess = guess || (bpb_sides > 2); /* Sides > 2; */
|
||||
guess = guess || !bps_is_valid(bpb_bps); /* Invalid number of bytes per sector; */
|
||||
guess = guess || !first_byte_is_valid(first_byte); /* Invalid first bytes; */
|
||||
guess = guess || !is_divisible(bpb_total, bpb_sectors); /* Total sectors not divisible by sectors per track; */
|
||||
guess = guess || !is_divisible(bpb_total, bpb_sides); /* Total sectors not divisible by sides. */
|
||||
guess = guess || !fdd_get_check_bpb(drive);
|
||||
guess = guess && !fdi;
|
||||
guess = guess && !cqm;
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "../86box.h"
|
||||
#include "../timer.h"
|
||||
#include "../plat.h"
|
||||
#include "fdd.h"
|
||||
#include "fdc.h"
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
*
|
||||
* Implementation of the HxC MFM image format.
|
||||
*
|
||||
* Version: @(#)fdd_mfm.c 1.0.0 2018/11/12
|
||||
* Version: @(#)fdd_mfm.c 1.0.1 2019/03/02
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2018 Miran Grca.
|
||||
* Copyright 2018,2019 Miran Grca.
|
||||
*/
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "../86box.h"
|
||||
#include "../timer.h"
|
||||
#include "../plat.h"
|
||||
#include "fdd.h"
|
||||
#include "fdd_86f.h"
|
||||
@@ -69,6 +70,9 @@ typedef struct {
|
||||
mfm_track_t *tracks;
|
||||
mfm_adv_track_t *adv_tracks;
|
||||
|
||||
uint16_t disk_flags, pad;
|
||||
uint16_t side_flags[2];
|
||||
|
||||
int br_rounded, rpm_rounded,
|
||||
total_tracks, cur_track;
|
||||
|
||||
@@ -101,15 +105,81 @@ mfm_log(const char *fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
static uint16_t
|
||||
disk_flags(int drive)
|
||||
static int
|
||||
get_track_index(int drive, int side, int track)
|
||||
{
|
||||
mfm_t *dev = mfm[drive];
|
||||
int i, ret = -1;
|
||||
|
||||
for (i = 0; i < dev->total_tracks; i++) {
|
||||
if ((dev->tracks[i].track_no == track) &&
|
||||
(dev->tracks[i].side_no == side)) {
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
get_adv_track_index(int drive, int side, int track)
|
||||
{
|
||||
mfm_t *dev = mfm[drive];
|
||||
int i, ret = -1;
|
||||
|
||||
for (i = 0; i < dev->total_tracks; i++) {
|
||||
if ((dev->adv_tracks[i].track_no == track) &&
|
||||
(dev->adv_tracks[i].side_no == side)) {
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
get_adv_track_bitrate(int drive, int side, int track, int *br, int *rpm)
|
||||
{
|
||||
mfm_t *dev = mfm[drive];
|
||||
int track_index;
|
||||
double dbr;
|
||||
|
||||
track_index = get_adv_track_index(drive, side, track);
|
||||
|
||||
if (track_index == -1) {
|
||||
*br = 250;
|
||||
*rpm = 300;
|
||||
} else {
|
||||
dbr = round(((double) dev->adv_tracks[track_index].bit_rate) / 50.0) * 50.0;
|
||||
*br = ((int) dbr);
|
||||
dbr = round(((double) dev->adv_tracks[track_index].rpm) / 60.0) * 60.0;
|
||||
*rpm = ((int) dbr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_disk_flags(int drive)
|
||||
{
|
||||
int br = 250, rpm = 300;
|
||||
mfm_t *dev = mfm[drive];
|
||||
uint16_t temp_disk_flags = 0x1080; /* We ALWAYS claim to have extra bit cells, even if the actual amount is 0;
|
||||
Bit 12 = 1, bits 6, 5 = 0 - extra bit cells field specifies the entire
|
||||
amount of bit cells per track. */
|
||||
|
||||
switch (dev->br_rounded) {
|
||||
/* If this is the modified MFM format, get bit rate (and RPM) from track 0 instead. */
|
||||
if (dev->hdr.if_type & 0x80)
|
||||
get_adv_track_bitrate(drive, 0, 0, &br, &rpm);
|
||||
else {
|
||||
br = dev->br_rounded;
|
||||
rpm = dev->rpm_rounded;
|
||||
}
|
||||
|
||||
switch (br) {
|
||||
case 500:
|
||||
temp_disk_flags |= 2;
|
||||
break;
|
||||
@@ -128,84 +198,35 @@ disk_flags(int drive)
|
||||
if (dev->hdr.sides_no == 2)
|
||||
temp_disk_flags |= 8;
|
||||
|
||||
return(temp_disk_flags);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
get_track_index(int drive, int side)
|
||||
{
|
||||
mfm_t *dev = mfm[drive];
|
||||
int i, ret = -1;
|
||||
|
||||
for (i = 0; i < dev->total_tracks; i++) {
|
||||
if ((dev->tracks[i].track_no == dev->cur_track) &&
|
||||
(dev->tracks[i].side_no == side)) {
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
get_adv_track_index(int drive, int side)
|
||||
{
|
||||
mfm_t *dev = mfm[drive];
|
||||
int i, ret = -1;
|
||||
|
||||
for (i = 0; i < dev->total_tracks; i++) {
|
||||
if ((dev->adv_tracks[i].track_no == dev->cur_track) &&
|
||||
(dev->adv_tracks[i].side_no == side)) {
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
get_adv_track_bitrate(int drive, int side, int *br, int *rpm)
|
||||
{
|
||||
mfm_t *dev = mfm[drive];
|
||||
int track_index;
|
||||
double dbr;
|
||||
|
||||
track_index = get_adv_track_index(drive, side);
|
||||
|
||||
if (track_index == -1) {
|
||||
*br = 250;
|
||||
*rpm = 300;
|
||||
} else {
|
||||
dbr = round(((double) dev->adv_tracks[track_index].bit_rate) / 50.0) * 50.0;
|
||||
*br = ((int) dbr);
|
||||
dbr = round(((double) dev->adv_tracks[track_index].rpm) / 60.0) * 60.0;
|
||||
*rpm = ((int) dbr);
|
||||
}
|
||||
dev->disk_flags = temp_disk_flags;
|
||||
}
|
||||
|
||||
|
||||
static uint16_t
|
||||
side_flags(int drive)
|
||||
disk_flags(int drive)
|
||||
{
|
||||
mfm_t *dev = mfm[drive];
|
||||
|
||||
return dev->disk_flags;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_side_flags(int drive, int side)
|
||||
{
|
||||
mfm_t *dev = mfm[drive];
|
||||
uint16_t temp_side_flags = 0;
|
||||
int side, br = 250, rpm = 300;
|
||||
int br = 250, rpm = 300;
|
||||
|
||||
if (dev->hdr.if_type & 0x80) {
|
||||
side = fdd_get_head(drive);
|
||||
get_adv_track_bitrate(drive, side, &br, &rpm);
|
||||
} else {
|
||||
if (dev->hdr.if_type & 0x80)
|
||||
get_adv_track_bitrate(drive, side, dev->cur_track, &br, &rpm);
|
||||
else {
|
||||
br = dev->br_rounded;
|
||||
rpm = dev->rpm_rounded;
|
||||
}
|
||||
|
||||
/* 300 kbps @ 360 rpm = 250 kbps @ 200 rpm */
|
||||
if ((rpm >= 352) && (rpm <= 367) && (br == 300)) {
|
||||
if ((br == 300) && (rpm == 360)) {
|
||||
br = 250;
|
||||
rpm = 300;
|
||||
}
|
||||
@@ -229,7 +250,7 @@ side_flags(int drive)
|
||||
break;
|
||||
}
|
||||
|
||||
if ((rpm >= 352) && (rpm <= 367))
|
||||
if (rpm == 360)
|
||||
temp_side_flags |= 0x20;
|
||||
|
||||
/*
|
||||
@@ -238,7 +259,19 @@ side_flags(int drive)
|
||||
*/
|
||||
temp_side_flags |= 0x08;
|
||||
|
||||
return(temp_side_flags);
|
||||
dev->side_flags[side] = temp_side_flags;
|
||||
}
|
||||
|
||||
|
||||
static uint16_t
|
||||
side_flags(int drive)
|
||||
{
|
||||
mfm_t *dev = mfm[drive];
|
||||
int side;
|
||||
|
||||
side = fdd_get_head(drive);
|
||||
|
||||
return dev->side_flags[side];
|
||||
}
|
||||
|
||||
|
||||
@@ -247,17 +280,32 @@ get_raw_size(int drive, int side)
|
||||
{
|
||||
mfm_t *dev = mfm[drive];
|
||||
int track_index, is_300_rpm;
|
||||
int br = 250, rpm = 300;
|
||||
|
||||
if (dev->hdr.if_type & 0x80)
|
||||
track_index = get_adv_track_index(drive, side);
|
||||
else
|
||||
track_index = get_track_index(drive, side);
|
||||
if (dev->hdr.if_type & 0x80) {
|
||||
track_index = get_adv_track_index(drive, side, dev->cur_track);
|
||||
get_adv_track_bitrate(drive, 0, 0, &br, &rpm);
|
||||
} else {
|
||||
track_index = get_track_index(drive, side, dev->cur_track);
|
||||
br = dev->br_rounded;
|
||||
rpm = dev->rpm_rounded;
|
||||
}
|
||||
|
||||
is_300_rpm = (dev->hdr.rpm < 352);
|
||||
is_300_rpm = (rpm == 300);
|
||||
|
||||
if (track_index == -1) {
|
||||
mfm_log("MFM: Unable to find track (%i, %i)\n", dev->cur_track, side);
|
||||
return is_300_rpm ? 100000 : 83333;
|
||||
switch (br) {
|
||||
case 250:
|
||||
default:
|
||||
return is_300_rpm ? 100000 : 83333;
|
||||
case 300:
|
||||
return is_300_rpm ? 120000 : 100000;
|
||||
case 500:
|
||||
return is_300_rpm ? 200000 : 166666;
|
||||
case 1000:
|
||||
return is_300_rpm ? 400000 : 333333;
|
||||
}
|
||||
}
|
||||
|
||||
/* Bit 7 on - my extension of the HxC MFM format to output exact bitcell counts
|
||||
@@ -293,9 +341,9 @@ mfm_read_side(int drive, int side)
|
||||
int track_bytes;
|
||||
|
||||
if (dev->hdr.if_type & 0x80)
|
||||
track_index = get_adv_track_index(drive, side);
|
||||
track_index = get_adv_track_index(drive, side, dev->cur_track);
|
||||
else
|
||||
track_index = get_track_index(drive, side);
|
||||
track_index = get_track_index(drive, side, dev->cur_track);
|
||||
|
||||
track_size = get_raw_size(drive, side);
|
||||
track_bytes = track_size >> 3;
|
||||
@@ -309,7 +357,7 @@ mfm_read_side(int drive, int side)
|
||||
fseek(dev->f, dev->adv_tracks[track_index].track_offset, SEEK_SET);
|
||||
else
|
||||
fseek(dev->f, dev->tracks[track_index].track_offset, SEEK_SET);
|
||||
fread(dev->track_data[side], 1, track_size, dev->f);
|
||||
fread(dev->track_data[side], 1, track_bytes, dev->f);
|
||||
}
|
||||
|
||||
mfm_log("drive = %i, side = %i, dev->cur_track = %i, track_index = %i, track_size = %i\n",
|
||||
@@ -340,6 +388,9 @@ mfm_seek(int drive, int track)
|
||||
|
||||
mfm_read_side(drive, 0);
|
||||
mfm_read_side(drive, 1);
|
||||
|
||||
set_side_flags(drive, 0);
|
||||
set_side_flags(drive, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -403,16 +454,18 @@ mfm_load(int drive, wchar_t *fn)
|
||||
if (!(dev->hdr.if_type & 0x80)) {
|
||||
dbr = round(((double) dev->hdr.bit_rate) / 50.0) * 50.0;
|
||||
dev->br_rounded = (int) dbr;
|
||||
mfm_log("Round bit rate: %i kbps\n", dev->br_rounded);
|
||||
mfm_log("Rounded bit rate: %i kbps\n", dev->br_rounded);
|
||||
|
||||
dbr = round(((double) dev->hdr.rpm) / 60.0) * 60.0;
|
||||
dev->rpm_rounded = (int) dbr;
|
||||
mfm_log("Round RPM: %i kbps\n", dev->rpm_rounded);
|
||||
mfm_log("Rounded RPM: %i kbps\n", dev->rpm_rounded);
|
||||
}
|
||||
|
||||
/* Set up the drive unit. */
|
||||
mfm[drive] = dev;
|
||||
|
||||
set_disk_flags(drive);
|
||||
|
||||
/* Attach this format to the D86F engine. */
|
||||
d86f_handler[drive].disk_flags = disk_flags;
|
||||
d86f_handler[drive].side_flags = side_flags;
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "../86box.h"
|
||||
#include "../timer.h"
|
||||
#include "../plat.h"
|
||||
#include "fdd.h"
|
||||
#include "fdd_td0.h"
|
||||
|
||||
Reference in New Issue
Block a user