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:
@@ -10,7 +10,7 @@
|
||||
* data in the form of FM/MFM-encoded transitions) which also
|
||||
* forms the core of the emulator's floppy disk emulation.
|
||||
*
|
||||
* Version: @(#)fdd_86f.c 1.0.16 2018/10/17
|
||||
* Version: @(#)fdd_86f.c 1.0.17 2018/11/12
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -190,6 +190,10 @@ typedef struct {
|
||||
* 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
|
||||
* Bit 12 If bits 6, 5 are not 0, they specify % of speedup instead
|
||||
* of slowdown;
|
||||
* If bits 6, 5 are 0, and bit 7 is 1, the extra bitcell count
|
||||
* specifies the entire bitcell count
|
||||
*/
|
||||
typedef struct {
|
||||
FILE *f;
|
||||
@@ -360,6 +364,14 @@ d86f_get_rpm_mode(int drive)
|
||||
return (d86f_handler[drive].disk_flags(drive) & 0x60) >> 5;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
d86f_get_speed_shift_dir(int drive)
|
||||
{
|
||||
return (d86f_handler[drive].disk_flags(drive) & 0x1000) >> 12;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
d86f_reverse_bytes(int drive)
|
||||
{
|
||||
@@ -521,12 +533,15 @@ common_get_raw_size(int drive, int side)
|
||||
double rpm, rpm_diff;
|
||||
double size = 100000.0;
|
||||
int mfm;
|
||||
int rm, ssd;
|
||||
|
||||
mfm = d86f_is_mfm(drive);
|
||||
rpm = ((d86f_track_flags(drive) & 0xE0) == 0x20) ? 360.0 : 300.0;
|
||||
rpm_diff = 1.0;
|
||||
rm = d86f_get_rpm_mode(drive);
|
||||
ssd = d86f_get_speed_shift_dir(drive);
|
||||
|
||||
switch (d86f_get_rpm_mode(drive)) {
|
||||
switch (rm) {
|
||||
case 1:
|
||||
rpm_diff = 1.01;
|
||||
break;
|
||||
@@ -544,6 +559,9 @@ common_get_raw_size(int drive, int side)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ssd)
|
||||
rpm_diff = 1.0 / rpm_diff;
|
||||
|
||||
switch (d86f_track_flags(drive) & 7) {
|
||||
case 0:
|
||||
rate = 500.0;
|
||||
@@ -572,9 +590,13 @@ common_get_raw_size(int drive, int side)
|
||||
|
||||
if (! mfm) rate /= 2.0;
|
||||
|
||||
size = (size / 250.0) * rate;
|
||||
size = (size * 300.0) / rpm;
|
||||
size *= rpm_diff;
|
||||
if (!rm && ssd)
|
||||
size = 0.0;
|
||||
else {
|
||||
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,
|
||||
@@ -640,25 +662,30 @@ d86f_get_array_size(int drive, int side)
|
||||
{
|
||||
int array_size;
|
||||
int hole, rm;
|
||||
int ssd;
|
||||
|
||||
rm = d86f_get_rpm_mode(drive);
|
||||
ssd = d86f_get_speed_shift_dir(drive);
|
||||
hole = (d86f_handler[drive].disk_flags(drive) & 6) >> 1;
|
||||
switch (hole) {
|
||||
|
||||
if (!rm && ssd) /* Special case - extra bit cells size specifies entire array size. */
|
||||
array_size = 0;
|
||||
else switch (hole) {
|
||||
case 0:
|
||||
case 1:
|
||||
default:
|
||||
array_size = 12500;
|
||||
switch (rm) {
|
||||
case 1:
|
||||
array_size = 12625;
|
||||
array_size = ssd ? 12376 : 12625;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
array_size = 12687;
|
||||
array_size = ssd ? 12315 : 12687;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
array_size = 12750;
|
||||
array_size = ssd ? 12254 : 12750;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -670,15 +697,15 @@ d86f_get_array_size(int drive, int side)
|
||||
array_size = 25000;
|
||||
switch (rm) {
|
||||
case 1:
|
||||
array_size = 25250;
|
||||
array_size = ssd ? 24752 : 25250;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
array_size = 25375;
|
||||
array_size = ssd ? 24630 : 25375;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
array_size = 25500;
|
||||
array_size = ssd ? 24509 : 25500;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -690,15 +717,15 @@ d86f_get_array_size(int drive, int side)
|
||||
array_size = 50000;
|
||||
switch (rm) {
|
||||
case 1:
|
||||
array_size = 50500;
|
||||
array_size = ssd ? 49504 : 50500;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
array_size = 50750;
|
||||
array_size = ssd ? 49261 : 50750;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
array_size = 51000;
|
||||
array_size = ssd ? 49019 : 51000;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1099,23 +1126,16 @@ d86f_get_bit(int drive, int side)
|
||||
|
||||
if (d86f_has_surface_desc(drive) && dev->track_surface_data && dev->track_surface_data[side]) {
|
||||
surface_bit = (surface_data >> track_bit) & 1;
|
||||
if (! surface_bit) {
|
||||
if (! current_bit) {
|
||||
/* Bit is 0 and is not set to fuzzy, we add it as read. */
|
||||
dev->last_word[side] |= 1;
|
||||
} else {
|
||||
/* Bit is 1 and is not set to fuzzy, we add it as read. */
|
||||
dev->last_word[side] |= 1;
|
||||
}
|
||||
} else {
|
||||
if (! surface_bit)
|
||||
dev->last_word[side] |= current_bit;
|
||||
else {
|
||||
if (current_bit) {
|
||||
/* Bit is 1 and is set to fuzzy, we randomly generate it. */
|
||||
dev->last_word[side] |= (random_generate() & 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else
|
||||
dev->last_word[side] |= current_bit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1267,7 +1287,7 @@ d86f_word_is_aligned(int drive, int side, uint32_t base_pos)
|
||||
|
||||
/* State 1: Find sector ID */
|
||||
void
|
||||
d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am, uint16_t other_am, uint16_t ignore_other_am)
|
||||
d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am, uint16_t other_am, uint16_t wrong_am, uint16_t ignore_other_am)
|
||||
{
|
||||
d86f_t *dev = d86f[drive];
|
||||
|
||||
@@ -1283,6 +1303,15 @@ d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am, ui
|
||||
return;
|
||||
}
|
||||
|
||||
if ((wrong_am) && (dev->last_word[side] == wrong_am)) {
|
||||
dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0;
|
||||
dev->error_condition = 0;
|
||||
dev->state = STATE_IDLE;
|
||||
fdc_finishread(d86f_fdc);
|
||||
fdc_nodataam(d86f_fdc);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ignore_other_am & 2) && (dev->last_word[side] == other_am)) {
|
||||
dev->calc_crc.word = 0xFFFF;
|
||||
fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc));
|
||||
@@ -1329,7 +1358,7 @@ d86f_write_find_address_mark_fm(int drive, int side, find_t *find)
|
||||
|
||||
|
||||
void
|
||||
d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_am, uint16_t other_am, uint16_t ignore_other_am)
|
||||
d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_am, uint16_t other_am, uint16_t wrong_am, uint16_t ignore_other_am)
|
||||
{
|
||||
d86f_t *dev = d86f[drive];
|
||||
|
||||
@@ -1341,6 +1370,15 @@ d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_am, u
|
||||
return;
|
||||
}
|
||||
|
||||
if ((wrong_am) && (dev->last_word[side] == wrong_am) && (find->sync_marks >= 3)) {
|
||||
dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0;
|
||||
dev->error_condition = 0;
|
||||
dev->state = STATE_IDLE;
|
||||
fdc_finishread(d86f_fdc);
|
||||
fdc_nodataam(d86f_fdc);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((dev->last_word[side] == req_am) && (find->sync_marks >= 3)) {
|
||||
if (d86f_word_is_aligned(drive, side, find->sync_pos)) {
|
||||
dev->calc_crc.word = 0xCDB4;
|
||||
@@ -1430,7 +1468,7 @@ d86f_read_sector_id(int drive, int side, int match)
|
||||
|
||||
if (dev->id_find.bytes_obtained == 6) {
|
||||
/* We've got the ID. */
|
||||
if (dev->calc_crc.word != dev->track_crc.word) {
|
||||
if ((dev->calc_crc.word != dev->track_crc.word) && (dev->last_sector.dword == dev->req_sector.dword)) {
|
||||
dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = 0;
|
||||
d86f_log("86F: ID CRC error: %04X != %04X (%08X)\n", dev->track_crc.word, dev->calc_crc.word, dev->last_sector.dword);
|
||||
if ((dev->state != STATE_02_READ_ID) && (dev->state != STATE_0A_READ_ID)) {
|
||||
@@ -2401,9 +2439,9 @@ d86f_poll(int drive)
|
||||
case STATE_11_FIND_ID:
|
||||
case STATE_16_FIND_ID:
|
||||
if (mfm)
|
||||
d86f_find_address_mark_mfm(drive, side, &(dev->id_find), 0x5554, 0, 0);
|
||||
d86f_find_address_mark_mfm(drive, side, &(dev->id_find), 0x5554, 0, 0, 0);
|
||||
else
|
||||
d86f_find_address_mark_fm(drive, side, &(dev->id_find), 0xF57E, 0, 0);
|
||||
d86f_find_address_mark_fm(drive, side, &(dev->id_find), 0xF57E, 0, 0, 0);
|
||||
break;
|
||||
|
||||
case STATE_0A_READ_ID:
|
||||
@@ -2422,18 +2460,18 @@ d86f_poll(int drive)
|
||||
|
||||
case STATE_02_FIND_DATA:
|
||||
if (mfm)
|
||||
d86f_find_address_mark_mfm(drive, side, &(dev->data_find), 0x5545, 0x554A, 2);
|
||||
d86f_find_address_mark_mfm(drive, side, &(dev->data_find), 0x5545, 0x554A, 0x5554, 2);
|
||||
else
|
||||
d86f_find_address_mark_fm(drive, side, &(dev->data_find), 0xF56F, 0xF56A, 2);
|
||||
d86f_find_address_mark_fm(drive, side, &(dev->data_find), 0xF56F, 0xF56A, 0xF57E, 2);
|
||||
break;
|
||||
|
||||
case STATE_06_FIND_DATA:
|
||||
case STATE_11_FIND_DATA:
|
||||
case STATE_16_FIND_DATA:
|
||||
if (mfm)
|
||||
d86f_find_address_mark_mfm(drive, side, &(dev->data_find), 0x5545, 0x554A, fdc_is_sk(d86f_fdc) | 2);
|
||||
d86f_find_address_mark_mfm(drive, side, &(dev->data_find), 0x5545, 0x554A, 0x5554, fdc_is_sk(d86f_fdc) | 2);
|
||||
else
|
||||
d86f_find_address_mark_fm(drive, side, &(dev->data_find), 0xF56F, 0xF56A, fdc_is_sk(d86f_fdc) | 2);
|
||||
d86f_find_address_mark_fm(drive, side, &(dev->data_find), 0xF56F, 0xF56A, 0xF57E, fdc_is_sk(d86f_fdc) | 2);
|
||||
break;
|
||||
|
||||
case STATE_05_FIND_DATA:
|
||||
@@ -2446,9 +2484,9 @@ d86f_poll(int drive)
|
||||
|
||||
case STATE_0C_FIND_DATA:
|
||||
if (mfm)
|
||||
d86f_find_address_mark_mfm(drive, side, &(dev->data_find), 0x554A, 0x5545, fdc_is_sk(d86f_fdc) | 2);
|
||||
d86f_find_address_mark_mfm(drive, side, &(dev->data_find), 0x554A, 0x5545, 0x5554, fdc_is_sk(d86f_fdc) | 2);
|
||||
else
|
||||
d86f_find_address_mark_fm(drive, side, &(dev->data_find), 0xF56A, 0xF56F, fdc_is_sk(d86f_fdc) | 2);
|
||||
d86f_find_address_mark_fm(drive, side, &(dev->data_find), 0xF56A, 0xF56F, 0xF57E, fdc_is_sk(d86f_fdc) | 2);
|
||||
break;
|
||||
|
||||
case STATE_02_READ_DATA:
|
||||
@@ -2808,6 +2846,7 @@ d86f_decompose_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];
|
||||
dst = d86f_handler[drive].encoded_data(drive, side);
|
||||
len = d86f_get_array_size(drive, side);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
@@ -2857,17 +2896,19 @@ d86f_read_track(int drive, int track, int thin_track, int side, uint16_t *da, ui
|
||||
fread(&(dev->side_flags[side]), 2, 1, dev->f);
|
||||
if (d86f_has_extra_bit_cells(drive)) {
|
||||
fread(&(dev->extra_bit_cells[side]), 4, 1, dev->f);
|
||||
if (dev->extra_bit_cells[side] < -32768)
|
||||
dev->extra_bit_cells[side] = -32768;
|
||||
if (dev->extra_bit_cells[side] > 32768)
|
||||
dev->extra_bit_cells[side] = 32768;
|
||||
} else {
|
||||
/* If RPM shift is 0% and direction is 1, do not adjust extra bit cells,
|
||||
as that is the whole track length. */
|
||||
if (d86f_get_rpm_mode(drive) || !d86f_get_speed_shift_dir(drive)) {
|
||||
if (dev->extra_bit_cells[side] < -32768)
|
||||
dev->extra_bit_cells[side] = -32768;
|
||||
if (dev->extra_bit_cells[side] > 32768)
|
||||
dev->extra_bit_cells[side] = 32768;
|
||||
}
|
||||
} else
|
||||
dev->extra_bit_cells[side] = 0;
|
||||
}
|
||||
fread(&(dev->index_hole_pos[side]), 4, 1, dev->f);
|
||||
} else {
|
||||
} 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;
|
||||
if (d86f_has_surface_desc(drive))
|
||||
fread(sa, 1, array_size, dev->f);
|
||||
@@ -3009,11 +3050,14 @@ d86f_write_tracks(int drive, FILE **f, uint32_t *track_table)
|
||||
tbl = track_table;
|
||||
|
||||
if (! fdd_doublestep_40(drive)) {
|
||||
for (side = 0; side < sides; side++) {
|
||||
fdd_set_head(drive, side);
|
||||
d86f_decompose_encoded_buffer(drive, side);
|
||||
d86f_decompose_encoded_buffer(drive, 0);
|
||||
if (sides == 2)
|
||||
d86f_decompose_encoded_buffer(drive, 1);
|
||||
|
||||
for (thin_track = 0; thin_track < 2; thin_track++) {
|
||||
for (side = 0; side < sides; side++) {
|
||||
fdd_set_head(drive, side);
|
||||
|
||||
for (thin_track = 0; thin_track < 2; thin_track++) {
|
||||
if (sides == 2)
|
||||
logical_track = ((dev->cur_track + thin_track) << 1) + side;
|
||||
else
|
||||
@@ -3021,8 +3065,9 @@ d86f_write_tracks(int drive, FILE **f, uint32_t *track_table)
|
||||
|
||||
if (track_table && !tbl[logical_track]) {
|
||||
fseek(*f, 0, SEEK_END);
|
||||
track_table[logical_track] = ftell(*f);
|
||||
tbl[logical_track] = ftell(*f);
|
||||
}
|
||||
|
||||
if (tbl[logical_track]) {
|
||||
fseek(*f, tbl[logical_track], SEEK_SET);
|
||||
d86f_write_track(drive, f, side, dev->thin_track_encoded_data[thin_track][side], dev->thin_track_surface_data[thin_track][side]);
|
||||
@@ -3039,12 +3084,12 @@ d86f_write_tracks(int drive, FILE **f, uint32_t *track_table)
|
||||
|
||||
if (track_table && !tbl[logical_track]) {
|
||||
fseek(*f, 0, SEEK_END);
|
||||
track_table[logical_track] = ftell(*f);
|
||||
tbl[logical_track] = ftell(*f);
|
||||
}
|
||||
|
||||
if (tbl[logical_track]) {
|
||||
fseek(*f, tbl[logical_track], SEEK_SET);
|
||||
d86f_write_track(drive, f, side, dev->track_encoded_data[side], dev->track_surface_data[side]);
|
||||
d86f_write_track(drive, f, side, d86f_handler[drive].encoded_data(drive, side), dev->track_surface_data[side]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3376,7 +3421,7 @@ d86f_export(int drive, wchar_t *fn)
|
||||
int i;
|
||||
int inc = 1;
|
||||
uint32_t magic = 0x46423638;
|
||||
uint16_t version = 0x020B;
|
||||
uint16_t version = 0x020C;
|
||||
uint16_t disk_flags = d86f_handler[drive].disk_flags(drive);
|
||||
|
||||
memset(tt, 0, 512 * sizeof(uint32_t));
|
||||
|
||||
Reference in New Issue
Block a user