diff --git a/src/Makefile.mingw b/src/Makefile.mingw index d0216e955..92b1365f8 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -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 \ diff --git a/src/Makefile.mingw64 b/src/Makefile.mingw64 index 8caa256ef..e1f21c9db 100644 --- a/src/Makefile.mingw64 +++ b/src/Makefile.mingw64 @@ -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 \ diff --git a/src/disc.h b/src/disc.h index 358d7c2b3..19a5371b7 100644 --- a/src/disc.h +++ b/src/disc.h @@ -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 */ diff --git a/src/disc_86f.c b/src/disc_86f.c index 341f3b106..047fa41d1 100644 --- a/src/disc_86f.c +++ b/src/disc_86f.c @@ -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; } diff --git a/src/disc_random.c b/src/disc_random.c new file mode 100644 index 000000000..22ddbe892 --- /dev/null +++ b/src/disc_random.c @@ -0,0 +1,66 @@ +/* Better random number generator by Battler. */ + +#include +#include + +#include + +#include +#include +#include +#include + +#include "disc_random.h" + +dword preconst = 0x6ED9EBA1; + +static __inline__ uint32_t rotl32c (uint32_t x, uint32_t n) +{ + assert (n<32); + return (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; +} diff --git a/src/disc_random.h b/src/disc_random.h new file mode 100644 index 000000000..25dc87326 --- /dev/null +++ b/src/disc_random.h @@ -0,0 +1,2 @@ +uint8_t disc_random_generate(); +void disc_random_init();