Added support for version 1.20 of the 86F format;

Hopefully made the 86F handler for the FDC READ TRACK command work correctly.
This commit is contained in:
OBattler 2016-09-07 20:59:08 +02:00
parent a43004aebe
commit c6c6fe8e2d
6 changed files with 190 additions and 33 deletions

@ -5,7 +5,7 @@ WINDRES = windres.exe
CFLAGS = -O3 -march=native -mtune=native -fbranch-probabilities -fvpt -funroll-loops -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse -mstackrealign
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-iso.o \
cdrom-null.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.o compaq.o config.o cpu.o dac.o \
device.o disc.o disc_86f.o disc_fdi.o disc_img.o disc_sector_86box.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \
device.o disc.o disc_86f.o disc_fdi.o disc_img.o disc_random.o disc_sector_86box.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \
i430nx.o i430vx.o i440fx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o memregs.o model.o mouse.o mouse_ps2.o \
mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o rtc.o \

@ -5,7 +5,7 @@ WINDRES = windres.exe
CFLAGS = -O3 -march=native -mtune=native -fbranch-probabilities -fvpt -funroll-loops -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse -mstackrealign
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-iso.o \
cdrom-null.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86-64.o compaq.o config.o cpu.o dac.o \
device.o disc.o disc_86f.o disc_fdi.o disc_img.o disc_sector_86box.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \
device.o disc.o disc_86f.o disc_fdi.o disc_img.o disc_random.o disc_sector_86box.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \
i430nx.o i430vx.o i440fx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o memregs.o model.o mouse.o mouse_ps2.o \
mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o rtc.o \

@ -95,6 +95,7 @@ extern int drive_type[2];
#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 */

@ -4,6 +4,7 @@
#include "ibm.h"
#include "disc.h"
#include "disc_86f.h"
#include "disc_random.h"
#include "fdc.h"
#include "fdd.h"
@ -89,6 +90,7 @@ static struct
uint8_t old_track_byte;
uint8_t old_track_index;
uint8_t cur_track;
uint8_t side_flag_bytes;
} d86f[2];
/* Needed for formatting! */
@ -138,6 +140,8 @@ static void d86f_calccrc(int drive, uint8_t byte)
void d86f_init()
{
disc_random_init();
memset(d86f, 0, sizeof(d86f));
d86f_setupcrc(0x1021, 0xcdb4);
}
@ -191,6 +195,8 @@ void d86f_load(int drive, char *fn)
int i = 0;
int j = 0;
uint8_t temp = 0;
writeprot[drive] = 0;
d86f[drive].f = fopen(fn, "rb+");
if (!d86f[drive].f)
@ -225,7 +231,7 @@ void d86f_load(int drive, char *fn)
fread(&(d86f[drive].version), 2, 1, d86f[drive].f);
if ((d86f[drive].version != 0x0100) && (d86f[drive].version != 0x010A))
if ((d86f[drive].version != 0x0100) && (d86f[drive].version != 0x010A) && (d86f[drive].version != 0x0114))
{
/* File is not of a recognized format version abort. */
pclog("86F: Unrecognized file version: %i.%02i\n", d86f[drive].version >> 8, d86f[drive].version & 0xFF);
@ -264,8 +270,16 @@ void d86f_load(int drive, char *fn)
}
/* Load track 0 flags as default. */
if (d86f[drive].version == 0x010A)
d86f[drive].side_flag_bytes = d86f_get_sides(drive);
if ((d86f[drive].version == 0x010A) || (d86f[drive].version == 0x0114))
{
if ((d86f[drive].version == 0x010A) && (d86f_get_sides(drive) == 1))
{
/* This is needed to detect the early variant of 86F version 1.10 images and handle it correctly. */
fseek(d86f[drive].f, d86f[drive].track_offset[0] + 3, SEEK_SET);
fread(&temp, 1, 1, d86f[drive].f);
if (temp & 0x80) d86f[drive].side_flag_bytes = 2;
}
fseek(d86f[drive].f, d86f[drive].track_offset[0], SEEK_SET);
fread(&(d86f[drive].side_flags[0]), 1, 1, d86f[drive].f);
if (d86f_get_sides(drive) == 2)
@ -304,7 +318,7 @@ int d86f_hole(int drive)
uint8_t d86f_flags(int drive)
{
int side = fdd_get_head(drive);
if (d86f[drive].version == 0x010A)
if ((d86f[drive].version == 0x010A) || (d86f[drive].version == 0x0114))
{
return d86f[drive].side_flags[side];
}
@ -419,11 +433,12 @@ void d86f_seek(int drive, int track)
int full_size = 25000;
int store_size = 50000;
int flag_bytes = 2;
if (d86f[drive].version == 0x010A)
if ((d86f[drive].version == 0x010A) || (d86f[drive].version == 0x0114))
{
full_size = d86f_get_array_size(drive);
store_size = full_size << 1;
if (d86f_get_sides(drive) == 2) flag_bytes++;
if (d86f[drive].side_flag_bytes == 2) flag_bytes++;
if (d86f[drive].version == 0x0114) flag_bytes += 4;
}
if (d86f_is_40_track(drive) && fdd_doublestep_40(drive))
@ -441,7 +456,7 @@ void d86f_seek(int drive, int track)
{
/* Track does not exist in the image, initialize it as unformatted. */
d86f[drive].track_in_file = 0;
if (d86f[drive].version == 0x010A)
if ((d86f[drive].version == 0x010A) || (d86f[drive].version == 0x0114))
{
for (side = 0; side < d86f_get_sides(drive); side++)
{
@ -459,12 +474,20 @@ void d86f_seek(int drive, int track)
fseek(d86f[drive].f, d86f[drive].track_offset[track], SEEK_SET);
if (d86f[drive].version == 0x010A)
if ((d86f[drive].version == 0x010A) || (d86f[drive].version == 0x0114))
{
for (side = 0; side < d86f_get_sides(drive); side++)
for (side = 0; side < d86f[drive].side_flag_bytes; side++)
{
fread(&(d86f[drive].side_flags[side]), 1, 1, d86f[drive].f);
}
if (d86f[drive].version == 0x0114)
{
for (side = 0; side < d86f[drive].side_flag_bytes; side++)
{
fread(&(d86f[drive].index_hole_pos[side]), 2, 1, d86f[drive].f);
}
}
}
else
{
@ -483,15 +506,17 @@ void d86f_seek(int drive, int track)
void d86f_writeback(int drive)
{
int track = d86f[drive].cur_track;
uint8_t track_id = track;
int side;
int full_size = 25000;
int store_size = 50000;
int flag_bytes = 2;
if (d86f[drive].version == 0x010A)
if ((d86f[drive].version == 0x010A) || (d86f[drive].version == 0x0114))
{
full_size = d86f_get_array_size(drive);
store_size = full_size * 2;
if (d86f_get_sides(drive) == 2) flag_bytes++;
store_size = full_size << 1;
if (d86f[drive].side_flag_bytes == 2) flag_bytes++;
if (d86f[drive].version == 0x0114) flag_bytes += 4;
}
if (!d86f[drive].f)
@ -504,17 +529,27 @@ void d86f_writeback(int drive)
fwrite(d86f[drive].track_offset, 1, 1024, d86f[drive].f);
fseek(d86f[drive].f, d86f[drive].track_offset[track], SEEK_SET);
if (d86f[drive].version == 0x010A)
if ((d86f[drive].version == 0x010A) || (d86f[drive].version == 0x0114))
{
for (side = 0; side < d86f_get_sides(drive); side++)
for (side = 0; side < d86f[drive].side_flag_bytes; side++)
{
fwrite(&(d86f[drive].side_flags[side]), 1, 1, d86f[drive].f);
}
if (d86f[drive].version == 0x0114)
{
for (side = 0; side < d86f[drive].side_flag_bytes; side++)
{
fwrite(&(d86f[drive].index_hole_pos[side]), 2, 1, d86f[drive].f);
}
}
}
else
{
fwrite(&(d86f[drive].track_flags), 1, 1, d86f[drive].f);
}
fwrite(&track_id, 1, 1, d86f[drive].f);
for (side = 0; side < d86f_get_sides(drive); side++)
{
@ -574,7 +609,7 @@ void d86f_readsector(int drive, int sector, int track, int side, int rate, int s
d86f[drive].req_sector.id.c = track;
d86f[drive].req_sector.id.h = side;
if (side && (d86f_get_sides(drive) == 1))
if (fdd_get_head(drive) && (d86f_get_sides(drive) == 1))
{
fdc_notfound();
d86f[drive].state = STATE_IDLE;
@ -583,15 +618,27 @@ void d86f_readsector(int drive, int sector, int track, int side, int rate, int s
}
d86f_drive = drive;
d86f[drive].req_sector.id.r = sector;
if (sector == SECTOR_FIRST)
d86f[drive].req_sector.id.r = 1;
else if (sector == SECTOR_NEXT)
d86f[drive].req_sector.id.r++;
else
d86f[drive].req_sector.id.r = sector;
d86f[drive].req_sector.id.n = sector_size;
d86f[drive].index_count = 0;
#if 0
if (sector == SECTOR_FIRST)
d86f[drive].state = STATE_READ_FIND_FIRST_SECTOR;
else if (sector == SECTOR_NEXT)
d86f[drive].state = STATE_READ_FIND_NEXT_SECTOR;
else
d86f[drive].state = STATE_READ_FIND_SECTOR;
#endif
d86f[drive].state = STATE_READ_FIND_SECTOR;
}
void d86f_writesector(int drive, int sector, int track, int side, int rate, int sector_size)
@ -603,7 +650,7 @@ void d86f_writesector(int drive, int sector, int track, int side, int rate, int
// pclog("d86f_writesector: drive=%c: fdc_period=%i img_period=%i rate=%i chrn=%08X\n", drive + 0x41, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), rate, d86f[drive].req_sector.dword);
if (side && (d86f_get_sides(drive) == 1))
if (fdd_get_head(drive) && (d86f_get_sides(drive) == 1))
{
fdc_notfound();
d86f[drive].state = STATE_IDLE;
@ -623,7 +670,7 @@ void d86f_readaddress(int drive, int track, int side, int rate)
d86f[drive].req_sector.id.c = track;
d86f[drive].req_sector.id.h = side;
if (side && (d86f_get_sides(drive) == 1))
if (fdd_get_head(drive) && (d86f_get_sides(drive) == 1))
{
fdc_notfound();
d86f[drive].state = STATE_IDLE;
@ -664,7 +711,10 @@ void d86f_prepare_track_layout(int drive, int side)
memset(d86f[drive].track_layout[side] + i, BYTE_GAP1, real_gap1_len);
i += real_gap1_len;
d86f[drive].track_layout[side][0] |= BYTE_INDEX_HOLE;
if ((d86f[drive].version == 0x0100) || (d86f[drive].version == 0x010A))
{
d86f[drive].track_layout[side][0] |= BYTE_INDEX_HOLE;
}
for (j = 0; j < fdc_get_format_sectors(); j++)
{
// pclog("Sector %i (%i)\n", j, s->n);
@ -706,11 +756,12 @@ void d86f_format(int drive, int track, int side, int rate, uint8_t fill)
int full_size = 25000;
int store_size = 50000;
int flag_bytes = 2;
if (d86f[drive].version == 0x010A)
if ((d86f[drive].version == 0x010A) || (d86f[drive].version == 0x0114))
{
full_size = d86f_get_array_size(drive);
store_size = full_size << 1;
if (d86f_get_sides(drive) == 2) flag_bytes++;
if (d86f[drive].side_flag_bytes == 2) flag_bytes++;
if (d86f[drive].version == 0x0114) flag_bytes += 4;
}
d86f[drive].req_sector.id.c = d86f[drive].cur_track;
@ -744,6 +795,10 @@ void d86f_format(int drive, int track, int side, int rate, uint8_t fill)
{
d86f[drive].side_flags[side] = d86f[drive].track_flags;
}
if (d86f[drive].version == 0x0114)
{
d86f[drive].index_hole_pos[side] = 0;
}
memset(d86f[drive].track_data[side], 0xFF, full_size);
d86f_prepare_track_layout(drive, side);
@ -904,8 +959,16 @@ void d86f_poll_advancebyte(int drive, int side)
d86f[drive].track_pos++;
d86f[drive].track_pos %= d86f_get_raw_size(drive);
d86f[drive].track_byte = d86f[drive].track_layout[side][d86f[drive].track_pos] & ~BYTE_INDEX_HOLE;
d86f[drive].track_index = d86f[drive].track_layout[side][d86f[drive].track_pos] & BYTE_INDEX_HOLE;
if ((d86f[drive].version == 0x0100) || (d86f[drive].version == 0x010A))
{
d86f[drive].track_byte = d86f[drive].track_layout[side][d86f[drive].track_pos] & ~BYTE_INDEX_HOLE;
d86f[drive].track_index = d86f[drive].track_layout[side][d86f[drive].track_pos] & BYTE_INDEX_HOLE;
}
else if (d86f[drive].version == 0x0114)
{
d86f[drive].track_byte = d86f[drive].track_layout[side][d86f[drive].track_pos] & ~BYTE_IS_FUZZY;
d86f[drive].track_index = (d86f[drive].track_pos == d86f[drive].index_hole_pos[side]);
}
}
void d86f_poll_reset(int drive, int side)
@ -941,6 +1004,23 @@ void d86f_poll_finish(int drive, int side)
d86f[drive].last_sector.dword = 0xFFFFFFFF;
}
void d86f_poll_data(int drive, int side)
{
uint8_t ret = d86f[drive].track_data[side][d86f[drive].track_pos];
if ((d86f[drive].version == 0x0114) && (d86f[drive].track_layout[side][d86f[drive].track_pos] & BYTE_IS_FUZZY))
{
ret = disc_random_generate();
}
return ret;
}
int d86f_mark_index_hole(int drive)
{
int temp = (d86f[drive].version == 0x0100);
temp = temp || (d86f[drive].version == 0x010A);
return temp;
}
void d86f_poll_readwrite(int drive, int side)
{
int data;
@ -949,11 +1029,12 @@ void d86f_poll_readwrite(int drive, int side)
if (d86f_read_state_data(drive))
{
max_len = d86f_data_size(drive);
data = d86f_poll_data(drive);
if (d86f[drive].datac < d86f_get_data_len(drive))
{
fdc_data(d86f[drive].track_data[side][d86f[drive].track_pos]);
fdc_data(data);
}
d86f_calccrc(drive, d86f[drive].track_data[side][d86f[drive].track_pos]);
d86f_calccrc(drive, data);
}
else if (d86f[drive].state == STATE_WRITE_SECTOR)
{
@ -974,14 +1055,14 @@ void d86f_poll_readwrite(int drive, int side)
{
d86f[drive].track_data[side][d86f[drive].track_pos] = data;
d86f[drive].track_layout[side][d86f[drive].track_pos] = BYTE_DATA;
if (!d86f[drive].track_pos) d86f[drive].track_layout[side][d86f[drive].track_pos] |= BYTE_INDEX_HOLE;
if (!d86f[drive].track_pos && d86f_mark_index_hole(drive)) d86f[drive].track_layout[side][d86f[drive].track_pos] |= BYTE_INDEX_HOLE;
}
d86f_calccrc(drive, d86f[drive].track_data[side][d86f[drive].track_pos]);
}
else if (d86f_read_state_crc(drive))
{
max_len = 2;
d86f[drive].track_crc.bytes[d86f[drive].datac] = d86f[drive].track_data[side][d86f[drive].track_pos];
d86f[drive].track_crc.bytes[d86f[drive].datac] = d86f_poll_data(drive);
}
else if (d86f[drive].state == STATE_WRITE_SECTOR_CRC)
{
@ -1044,6 +1125,8 @@ void d86f_poll_readwrite(int drive, int side)
void d86f_poll_find_nf(int drive, int side)
{
uint8_t data = 0;
if (d86f[drive].track_index)
{
// pclog("d86f_poll_find_nf(): Index pulse\n");
@ -1056,7 +1139,7 @@ void d86f_poll_find_nf(int drive, int side)
case BYTE_IDAM:
d86f[drive].calc_crc.word = fdc_is_mfm() ? 0xcdb4 : 0xffff;
// pclog("CRC reset: %02X\n", d86f[drive].track_byte);
d86f_calccrc(drive, d86f[drive].track_data[side][d86f[drive].track_pos]);
d86f_calccrc(drive, d86f_poll_data(drive));
break;
case BYTE_DATAAM:
@ -1066,17 +1149,22 @@ void d86f_poll_find_nf(int drive, int side)
if ((d86f[drive].state == STATE_WRITE_FIND_SECTOR) && (d86f[drive].req_sector.dword == d86f[drive].last_sector.dword) && d86f_can_read_address(drive))
{
d86f[drive].track_data[side][d86f[drive].track_pos] = 0xFB;
if (d86f[drive].version == 0x0114)
{
d86f[drive].track_layout[side][d86f[drive].track_pos] &= ~BYTE_IS_FUZZY;
}
}
d86f_calccrc(drive, d86f[drive].track_data[side][d86f[drive].track_pos]);
d86f_calccrc(drive, d86f_poll_data(drive));
break;
case BYTE_ID:
d86f[drive].id_pos = d86f[drive].track_pos - d86f[drive].section_pos;
d86f[drive].rw_sector_id.byte_array[d86f[drive].id_pos] = d86f[drive].track_data[side][d86f[drive].track_pos];
d86f_calccrc(drive, d86f[drive].track_data[side][d86f[drive].track_pos]);
data = d86f_poll_data(drive);
d86f[drive].rw_sector_id.byte_array[d86f[drive].id_pos] = data;
d86f_calccrc(drive, data);
break;
case BYTE_ID_CRC:
d86f[drive].id_pos = d86f[drive].track_pos - d86f[drive].section_pos;
d86f[drive].track_crc.bytes[d86f[drive].id_pos] = d86f[drive].track_data[side][d86f[drive].track_pos];
d86f[drive].track_crc.bytes[d86f[drive].id_pos] = d86f_poll_data(drive);
break;
}

66
src/disc_random.c Normal file

@ -0,0 +1,66 @@
/* Better random number generator by Battler. */
#include <assert.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "disc_random.h"
dword preconst = 0x6ED9EBA1;
static __inline__ uint32_t rotl32c (uint32_t x, uint32_t n)
{
assert (n<32);
return (x<<n) | (x>>(-n&31));
}
static __inline__ uint32_t rotr32c (uint32_t x, uint32_t n)
{
assert (n<32);
return (x>>n) | (x<<(-n&31));
}
#define ROTATE_LEFT rotl32c
#define ROTATE_RIGHT rotr32c
static __inline__ unsigned long long rdtsc(void)
{
unsigned hi, lo;
__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
}
static UINT4 RDTSC(void)
{
return (UINT4) (rdtsc());
}
static void disc_random_twist(uint32_t *val)
{
*val = ROTATE_LEFT(*val, rand() % 32);
*val ^= 0x5A827999;
*val = ROTATE_RIGHT(*val, rand() % 32);
*val ^= 0x4ED32706;
}
uint8_t disc_random_generate()
{
uint16_t r = 0;
r = (rand() ^ ROTATE_LEFT(preconst, rand() % 32)) % 256;
disc_random_twist(&preconst);
return (r & 0xff);
}
void disc_random_init()
{
dword seed = RDTSC();
srand(seed);
return;
}

2
src/disc_random.h Normal file

@ -0,0 +1,2 @@
uint8_t disc_random_generate();
void disc_random_init();