Rewritten 808x CPU emulation core based on reenigne's XTCE, VisiOn, SnatchIt, and 8088 MPH now work correctly;

Fixed PC speaker sound volume in PIT mode 0;
A few CPU emulation clean-ups;
Hard disk controller changing redone in a less messy way;
Re-added the long-missing key send delay handling to the XT keyboard handler;
Fixed a bug that was causing SLiRP not to work when compiled with MingW/GCC 7.3.0-2 or newer;
Some serial mouse and port fixes;
A lot of changes to printer emulation, mostly based on DOSBox-X;
Printer PNG writer now uses statically linked libpng;
Added support for the HxC MFM floppy image format and upped 86F format version to 2.12;
Ported various things from PCem and some from VARCem;
Added the S3 86c801/805 emulation (patch from TheCollector1995);
Fixed and renamed the EGA monitor options;
Better synchronized the 808x to the PIT and the CGA;
Fixed the CGA wait state calculation;
Cleaned up some things in mem.c;
Fixed some things in the floppy emulation to make VisiOn get the correct errors from the copy protection disk;
Fixed several renderer-related bugs, including the SDL2 renderer's failure to take screenshots;
The Jenkins builds are now compiled with MingW/GCC 7.4.0-1 and include all the required DLL's.
This commit is contained in:
OBattler
2019-02-06 03:34:39 +01:00
parent c91b1f2b8e
commit 46d0ed2baa
104 changed files with 7749 additions and 6608 deletions

View File

@@ -9,7 +9,7 @@
* Implementation of the NEC uPD-765 and compatible floppy disk
* controller.
*
* Version: @(#)fdc.c 1.0.12 2018/10/18
* Version: @(#)fdc.c 1.0.15 2019/01/26
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <tommowalker@tommowalker.co.uk>
@@ -156,7 +156,7 @@ fdc_ctrl_reset(void *p)
fdc->head = 0;
fdc->abort = 0;
fdc->step = 0;
if (!(fdc->flags & FDC_FLAG_AT))
if (!(fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_PS1))
fdc->rate = 2;
}
@@ -383,20 +383,6 @@ fdc_update_rates(fdc_t *fdc)
}
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)
{
@@ -613,7 +599,7 @@ void
fdc_seek(fdc_t *fdc, int drive, int params)
{
fdd_seek(real_drive(fdc, drive), params);
fdc->time = 5000LL * (1 << TIMER_SHIFT);
fdc->time = 2048LL * (1 << TIMER_SHIFT);
fdc->stat |= (1 << fdc->drive);
}
@@ -636,7 +622,7 @@ fdc_bad_command(fdc_t *fdc)
{
fdc->stat = 0x10;
fdc->interrupt = 0xfc;
timer_clock();
timer_process();
fdc->time = 200LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
}
@@ -713,6 +699,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");
switch (addr&7) {
case 0:
@@ -727,7 +714,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
picintc(1 << fdc->irq);
}
if ((val & 0x80) && !(fdc->dor & 0x80)) {
timer_clock();
timer_process();
fdc->time = 128LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
fdc->interrupt = -1;
@@ -758,7 +745,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc->pnum = fdc->ptot = 0;
}
if ((val&4) && !(fdc->dor&4)) {
timer_clock();
timer_process();
fdc->time = 128LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
fdc->interrupt = -1;
@@ -769,7 +756,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc_ctrl_reset(fdc);
}
timer_clock();
timer_process();
timer_update_outstanding();
/* We can now simplify this since each motor now spins separately. */
for (i = 0; i < FDD_NUM; i++) {
@@ -795,15 +782,13 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
return;
case 4:
if (val & 0x80) {
timer_clock();
timer_process();
fdc->time = 128LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
fdc->interrupt = -1;
fdc->perp &= 0xfc;
fdc_ctrl_reset(fdc);
}
/* if (fdc->flags & FDC_FLAG_PS1)
fdc->rate = val & 0x03; */
return;
case 5: /*Command register*/
if ((fdc->stat & 0xf0) == 0xb0) {
@@ -981,7 +966,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
if (fdc->pnum==fdc->ptot) {
fdc_log("Got all params %02X\n", fdc->command);
fdc->interrupt = fdc->command & 0x1F;
timer_clock();
timer_process();
fdc->time = 1024LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
fdc->reset_stat = 0;
@@ -1073,7 +1058,7 @@ 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_clock();
timer_process();
fdc->time = 2048LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
break;
@@ -1081,8 +1066,8 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
if ((real_drive(fdc, fdc->drive) != 1) || fdc->drv2en)
fdc_seek(fdc, fdc->drive, -fdc->max_track);
fdc_log("Recalibrating...\n");
fdc->time = 5000LL * (1 << TIMER_SHIFT);
fdc->step = fdc->seek_dir = 1;
fdc->time = 2048LL * (1 << TIMER_SHIFT);
fdc->seek_dir = fdc->step = 1;
break;
case 0x0d: /*Format*/
fdc_rate(fdc, fdc->drive);
@@ -1117,7 +1102,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
} else
fdc->pcn[fdc->params[0] & 3] = fdc->params[1];
fdc->interrupt = -3;
timer_clock();
timer_process();
fdc->time = 2048LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
break;
@@ -1135,12 +1120,12 @@ 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 = 5000LL * (1 << TIMER_SHIFT);
fdc->time = 2048LL * (1 << TIMER_SHIFT);
fdc->step = 1;
} else {
fdc->st0 = 0x20 | (fdc->params[0] & 7);
fdc->interrupt = -3;
timer_clock();
timer_process();
fdc->time = 2048LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
break;
@@ -1151,7 +1136,7 @@ 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_clock();
timer_process();
fdc->time = 2048LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
break;
@@ -1162,7 +1147,7 @@ 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 = 5000LL * (1 << TIMER_SHIFT);
fdc->time = 2048LL * (1 << TIMER_SHIFT);
fdc->step = 1;
fdc_log("fdc->time = %i\n", fdc->time);
}
@@ -1206,8 +1191,9 @@ fdc_read(uint16_t addr, void *priv)
int drive;
cycles -= ISA_CYCLES(8);
// pclog("fdc_read(): cycles -= ISA_CYCLES(8);\n");
switch (addr&7) {
switch (addr & 7) {
case 0: /* STA */
if (fdc->flags & FDC_FLAG_PS1) {
drive = real_drive(fdc, fdc->dor & 3);
@@ -1216,9 +1202,9 @@ fdc_read(uint16_t addr, void *priv)
Bit 2: INDEX (best return always 0 as it goes by very fast)
Bit 6: DRQ
*/
if (writeprot[drive]) /* WRITEPROT */
ret |= 0x01;
if (fdc->seek_dir) /* nDIRECTION */
ret |= 0x01;
if (writeprot[drive]) /* WRITEPROT */
ret |= 0x02;
if (!fdd_get_head(drive)) /* nHDSEL */
ret |= 0x08;
@@ -1239,10 +1225,20 @@ fdc_read(uint16_t addr, void *priv)
if (!fdd_get_type(1))
ret |= 80;
/* -Drive Select 1,0 */
if (drive)
ret |= 0x20;
else
ret |= 0x40;
switch (drive) {
case 0:
ret |= 0x43;
break;
case 1:
ret |= 0x23;
break;
case 2:
ret |= 0x62;
break;
case 3:
ret |= 0x61;
break;
}
} else {
if (is486)
return 0xff;
@@ -1326,6 +1322,7 @@ 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);
@@ -1613,7 +1610,7 @@ fdc_callback(void *priv)
if (!fdd_track0(drive_num))
fdc->st0 |= 0x50;
fdc->interrupt = -3;
timer_clock();
timer_process();
fdc->time = 2048LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
fdc->stat = 0x80 | (1 << fdc->drive);
@@ -1621,7 +1618,7 @@ fdc_callback(void *priv)
case 0x0d: /*Format track*/
if (fdc->format_state == 1) {
fdc->format_state = 2;
timer_clock();
timer_process();
fdc->time = 128LL * (1LL << TIMER_SHIFT);
timer_update_outstanding();
} else if (fdc->format_state == 2) {
@@ -1664,7 +1661,7 @@ fdc_callback(void *priv)
drive_num = real_drive(fdc, fdc->rw_drive);
fdc->st0 = 0x20 | (fdc->params[0] & 7);
fdc->interrupt = -3;
/* timer_clock();
/* timer_process();
fdc->time = 2048LL * (1LL << TIMER_SHIFT);
timer_update_outstanding(); */
fdc->stat = 0x80 | (1 << fdc->drive);
@@ -2083,13 +2080,15 @@ fdc_reset(void *priv)
fdc->enable_3f1 = 1;
fdc_update_is_nsc(fdc, 0);
fdc_update_enh_mode(fdc, 0);
if (fdc->flags & FDC_FLAG_PS1)
fdc_update_densel_polarity(fdc, 0);
else
fdc_update_densel_polarity(fdc, 1);
fdc_update_densel_force(fdc, 0);
if (fdc->flags & FDC_FLAG_NSC)
fdc_update_densel_force(fdc, 3);
else
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);
@@ -2099,6 +2098,7 @@ fdc_reset(void *priv)
fdc_update_drvrate(fdc, 2, 0);
fdc_update_drvrate(fdc, 3, 0);
fdc_update_drv2en(fdc, 1);
fdc_update_rates(fdc);
fdc->fifo = 0;
fdc->tfifo = 1;
@@ -2172,6 +2172,7 @@ fdc_init(const device_t *info)
fdd_set_fdc(fdc);
imd_set_fdc(fdc);
img_set_fdc(fdc);
mfm_set_fdc(fdc);
fdc_reset(fdc);