The 86F handler now reads and writes .86F images correctly again;

Improved TeleDisk support;
Added support for ImageDisk (IMD) images;
Added MSR registers 186 and 570 for the Intel i686 CPU's;
Applied both mainline PCem commits.
This commit is contained in:
OBattler
2016-10-04 17:25:16 +02:00
parent 1371be8b45
commit 6ac2526dbb
17 changed files with 5218 additions and 4570 deletions

View File

@@ -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_86box.o disc_random.o disc_td0.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_imd.o disc_img_86box.o disc_random.o disc_td0.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 \

View File

@@ -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_86box.o disc_random.o disc_td0.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_imd.o disc_img_86box.o disc_random.o disc_td0.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 \

View File

@@ -105,7 +105,9 @@ uint64_t ecx8x_msr[4] = {0, 0, 0, 0};
uint64_t ecx116_msr = 0;
uint64_t ecx11x_msr[4] = {0, 0, 0, 0};
uint64_t ecx11e_msr = 0;
uint64_t ecx186_msr = 0;
uint64_t ecx1e0_msr = 0;
uint64_t ecx570_msr = 0;
/* AMD K5 and K6 MSR's. */
uint64_t ecx83_msr = 0;
@@ -2000,6 +2002,10 @@ void cpu_RDMSR()
if (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type == CPU_PENTIUMPRO) goto i686_invalid_rdmsr;
EAX = eip_msr;
break;
case 0x186:
EAX = ecx186_msr & 0xffffffff;
EDX = ecx186_msr >> 32;
break;
case 0x1E0:
EAX = ecx1e0_msr & 0xffffffff;
EDX = ecx1e0_msr >> 32;
@@ -2041,6 +2047,10 @@ void cpu_RDMSR()
EAX = mtrr_deftype_msr & 0xffffffff;
EDX = mtrr_deftype_msr >> 32;
break;
case 0x570:
EAX = ecx570_msr & 0xffffffff;
EDX = ecx570_msr >> 32;
break;
default:
i686_invalid_rdmsr:
#ifndef RELEASE_BUILD
@@ -2181,6 +2191,9 @@ void cpu_WRMSR()
// pclog("WRMSR SYSENTER_EIP: old=%08X, new=%08X\n", eip_msr, EAX);
eip_msr = EAX;
break;
case 0x186:
ecx186_msr = EAX | ((uint64_t)EDX << 32);
break;
case 0x1E0:
ecx1e0_msr = EAX | ((uint64_t)EDX << 32);
break;
@@ -2209,6 +2222,9 @@ void cpu_WRMSR()
case 0x2FF:
mtrr_deftype_msr = EAX | ((uint64_t)EDX << 32);
break;
case 0x570:
ecx570_msr = EAX | ((uint64_t)EDX << 32);
break;
default:
i686_invalid_wrmsr:
#ifndef RELEASE_BUILD

View File

@@ -9,6 +9,7 @@
#include "disc_img.h"
#include "disc_86f.h"
#include "disc_td0.h"
#include "disc_imd.h"
#include "fdc.h"
#include "fdd.h"
#include "timer.h"
@@ -70,13 +71,14 @@ loaders[]=
{"720", img_load, img_close, -1},
{"86F", d86f_load, d86f_close, -1},
{"DSK", img_load, img_close, -1},
{"FDI", fdi_load, fdi_close, -1},
{"FLP", img_load, img_close, -1},
{"IMG", img_load, img_close, -1},
{"IMA", img_load, img_close, -1},
{"IMD", imd_load, imd_close, -1},
{"IMG", img_load, img_close, -1},
{"TD0", td0_load, td0_close, -1},
{"VFD", img_load, img_close, -1},
{"XDF", img_load, img_close, -1},
{"FDI", fdi_load, fdi_close, -1},
{0,0,0}
};

View File

@@ -146,5 +146,25 @@ void null_writeback(int drive);
void null_poll_write_data(int drive, int side, uint16_t pos, uint8_t data);
int null_format_conditions(int drive);
void d86f_unregister(int drive);
void d86f_reset_index_hole_pos(int drive, int side);
uint8_t xdf_physical_sectors[2][2];
uint8_t xdf_gap3_sizes[2][2];
uint16_t xdf_trackx_spos[2][8];
typedef struct
{
uint8_t h;
uint8_t r;
} xdf_id_t;
typedef union
{
uint16_t word;
xdf_id_t id;
} xdf_sector_t;
xdf_sector_t xdf_img_layout[2][2][46];
xdf_sector_t xdf_disk_layout[2][2][38];
uint32_t td0_get_raw_tsize(int side_flags, int slower_rpm);

View File

@@ -832,10 +832,13 @@ void d86f_seek(int drive, int track)
uint8_t track_id = track;
int sides;
int side;
#if 0
int full_size, store_size;
int flag_bytes = 5;
#endif
sides = d86f_get_sides(drive);
#if 0
full_size = d86f_get_array_size(drive);
store_size = full_size << 1;
if (d86f_is_encoded(drive)) store_size += full_size;
@@ -848,6 +851,7 @@ void d86f_seek(int drive, int track)
}
}
if (d86f_get_sides(drive) == 2) flag_bytes += 4;
#endif
if (d86f_is_40_track(drive) && fdd_doublestep_40(drive))
track /= 2;
@@ -905,7 +909,7 @@ void d86f_seek(int drive, int track)
{
if (d86f_is_old_style(drive))
{
fread(d86f[drive].track_layout[side], 1, d86f_get_raw_size(drive), d86f[drive].f);
fread(d86f[drive].track_layout[side], 1, d86f_get_array_size(drive), d86f[drive].f);
}
else
{
@@ -916,11 +920,11 @@ void d86f_seek(int drive, int track)
}
if (d86f_is_encoded(drive))
{
fread(d86f[drive].track_encoded_data[side], 1, d86f_get_raw_size(drive) << 1, d86f[drive].f);
fread(d86f[drive].track_encoded_data[side], 1, d86f_get_array_size(drive) << 1, d86f[drive].f);
}
else
{
fread(d86f[drive].track_data[side], 1, d86f_get_raw_size(drive), d86f[drive].f);
fread(d86f[drive].track_data[side], 1, d86f_get_array_size(drive), d86f[drive].f);
}
}
}
@@ -930,6 +934,7 @@ void d86f_writeback(int drive)
int track = d86f[drive].cur_track;
uint8_t track_id = track;
int side;
#if 0
int full_size, store_size;
int flag_bytes = 5;
@@ -945,6 +950,7 @@ void d86f_writeback(int drive)
}
}
if (d86f_get_sides(drive) == 2) flag_bytes += 4;
#endif
if (!d86f[drive].f)
{
@@ -977,7 +983,7 @@ void d86f_writeback(int drive)
{
if (d86f_is_old_style(drive))
{
fwrite(d86f[drive].track_layout[side], 1, d86f_get_raw_size(drive), d86f[drive].f);
fwrite(d86f[drive].track_layout[side], 1, d86f_get_array_size(drive), d86f[drive].f);
}
else
{
@@ -988,11 +994,11 @@ void d86f_writeback(int drive)
}
if (d86f_is_encoded(drive))
{
fwrite(d86f[drive].track_encoded_data[side], 1, d86f_get_raw_size(drive) << 1, d86f[drive].f);
fwrite(d86f[drive].track_encoded_data[side], 1, d86f_get_array_size(drive) << 1, d86f[drive].f);
}
else
{
fwrite(d86f[drive].track_data[side], 1, d86f_get_raw_size(drive), d86f[drive].f);
fwrite(d86f[drive].track_data[side], 1, d86f_get_array_size(drive), d86f[drive].f);
}
}
@@ -1897,7 +1903,7 @@ int d86f_poll_check_notfound(int drive)
/* The index hole has been hit twice and we're still in a find state.
This means sector finding has failed for whatever reason.
Abort with sector not found and set state to idle. */
pclog("d86f_poll(): Sector not found (%i %i %i %i) (%i, %i)\n", d86f[drive].req_sector.id.c, d86f[drive].req_sector.id.h, d86f[drive].req_sector.id.r, d86f[drive].req_sector.id.n, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive));
// pclog("d86f_poll(): Sector not found (%i %i %i %i) (%i, %i)\n", d86f[drive].req_sector.id.c, d86f[drive].req_sector.id.h, d86f[drive].req_sector.id.r, d86f[drive].req_sector.id.n, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive));
fdc_notfound();
d86f[drive].state = STATE_IDLE;
d86f[drive].index_count = 0;

717
src/disc_imd.c Normal file
View File

@@ -0,0 +1,717 @@
/* Copyright holders: Kiririn
see COPYING for more details
*/
#include "ibm.h"
#include "fdc.h"
#include "fdd.h"
#include "disc.h"
#include "disc_imd.h"
#include <malloc.h>
typedef struct
{
uint8_t is_present;
uint32_t file_offs;
uint8_t params[5];
uint32_t r_map_offs;
uint32_t c_map_offs;
uint32_t h_map_offs;
uint32_t n_map_offs;
uint32_t data_offs;
uint32_t sector_data_offs[255];
uint32_t sector_data_size[255];
uint32_t gap3_len;
uint16_t side_flags;
} imd_track_t;
static struct
{
FILE *f;
uint8_t *buffer;
uint32_t start_offs;
int track_count, sides;
int track;
uint16_t disk_flags;
imd_track_t tracks[256][2];
uint16_t current_side_flags[2];
uint8_t xdf_ordered_pos[256][2];
uint8_t *current_data[2];
uint8_t track_buffer[2][25000];
} imd[2];
void imd_init()
{
memset(imd, 0, sizeof(imd));
}
void d86f_register_imd(int drive);
void imd_load(int drive, char *fn)
{
uint32_t magic = 0;
uint32_t fsize = 0;
uint8_t *buffer;
uint8_t *buffer2;
int i = 0;
int has_cyl_map = 0;
int has_head_map = 0;
int has_size_map = 0;
int track_spt = 0;
int sector_size = 0;
int track = 0;
int side = 0;
int extra = 0;
int fm = 0;
uint32_t last_offset = 0;
uint32_t data_size = 512;
uint32_t mfm = 0;
uint32_t pre_sector = 0;
uint32_t track_total = 0;
uint32_t raw_tsize = 0;
uint32_t minimum_gap3 = 0;
uint32_t minimum_gap4 = 12;
d86f_unregister(drive);
writeprot[drive] = 0;
imd[drive].f = fopen(fn, "rb+");
if (!imd[drive].f)
{
imd[drive].f = fopen(fn, "rb");
if (!imd[drive].f)
return;
writeprot[drive] = 1;
}
if (ui_writeprot[drive])
{
writeprot[drive] = 1;
}
fwriteprot[drive] = writeprot[drive];
fseek(imd[drive].f, 0, SEEK_SET);
fread(&magic, 1, 4, imd[drive].f);
if (magic != 0x20444D49)
{
pclog("IMD: Not a valid ImageDisk image\n");
fclose(imd[drive].f);
return;
}
else
{
pclog("IMD: Valid ImageDisk image\n");
}
fseek(imd[drive].f, 0, SEEK_END);
fsize = ftell(imd[drive].f);
fseek(imd[drive].f, 0, SEEK_SET);
imd[drive].buffer = malloc(fsize);
fread(imd[drive].buffer, 1, fsize, imd[drive].f);
buffer = imd[drive].buffer;
buffer2 = strchr(buffer, 0x1A);
if (buffer2 == NULL)
{
pclog("IMD: No ASCII EOF character\n");
fclose(imd[drive].f);
return;
}
else
{
pclog("IMD: ASCII EOF character found at offset %08X\n", buffer2 - buffer);
}
buffer2++;
if ((buffer2 - buffer) == fsize)
{
pclog("IMD: File ends after ASCII EOF character\n");
fclose(imd[drive].f);
return;
}
else
{
pclog("IMD: File continues after ASCII EOF character\n");
}
imd[drive].start_offs = (buffer2 - buffer);
imd[drive].disk_flags = 0x00;
imd[drive].track_count = 0;
imd[drive].sides = 1;
while(1)
{
track = buffer2[1];
side = buffer2[2];
if (side & 1) imd[drive].sides = 2;
extra = side & 0xC0;
side &= 0x3F;
// pclog("IMD: Loading track %i, side %i\n", track, side);
imd[drive].tracks[track][side].side_flags = (buffer2[0] % 3);
if (!imd[drive].tracks[track][side].side_flags) imd[drive].disk_flags |= (0x02);
imd[drive].tracks[track][side].side_flags |= (!(buffer2[0] - imd[drive].tracks[track][side].side_flags) ? 0 : 8);
mfm = imd[drive].tracks[track][side].side_flags & 8;
track_total = mfm ? 146 : 73;
pre_sector = mfm ? 60 : 42;
track_spt = buffer2[3];
sector_size = buffer2[4];
if ((track_spt == 15) && (sector_size == 2)) imd[drive].tracks[track][side].side_flags |= 0x20;
if ((track_spt == 16) && (sector_size == 2)) imd[drive].tracks[track][side].side_flags |= 0x20;
if ((track_spt == 17) && (sector_size == 2)) imd[drive].tracks[track][side].side_flags |= 0x20;
if ((track_spt == 8) && (sector_size == 3)) imd[drive].tracks[track][side].side_flags |= 0x20;
imd[drive].tracks[track][side].is_present = 1;
imd[drive].tracks[track][side].file_offs = (buffer2 - buffer);
memcpy(imd[drive].tracks[track][side].params, buffer2, 5);
imd[drive].tracks[track][side].r_map_offs = imd[drive].tracks[track][side].file_offs + 5;
last_offset = imd[drive].tracks[track][side].r_map_offs + track_spt;
if (extra & 0x80)
{
imd[drive].tracks[track][side].c_map_offs = last_offset;
last_offset += track_spt;
}
if (extra & 0x40)
{
imd[drive].tracks[track][side].h_map_offs = last_offset;
last_offset += track_spt;
}
if (sector_size == 0xFF)
{
imd[drive].tracks[track][side].n_map_offs = last_offset;
buffer2 = buffer + last_offset;
last_offset += track_spt;
imd[drive].tracks[track][side].data_offs = last_offset;
for (i = 0; i < track_spt; i++)
{
data_size = buffer2[i];
data_size = 128 << data_size;
imd[drive].tracks[track][side].sector_data_offs[i] = last_offset;
imd[drive].tracks[track][side].sector_data_size[i] = 1;
if (buffer[imd[drive].tracks[track][side].sector_data_offs[i]] != 0)
{
imd[drive].tracks[track][side].sector_data_size[i] += (buffer[imd[drive].tracks[track][side].sector_data_offs[i]] & 1) ? data_size : 1;
}
last_offset += imd[drive].tracks[track][side].sector_data_size[i];
if (!(buffer[imd[drive].tracks[track][side].sector_data_offs[i]] & 1))
{
fwriteprot[drive] = writeprot[drive] = 1;
}
track_total += (pre_sector + data_size + 2);
}
}
else
{
imd[drive].tracks[track][side].data_offs = last_offset;
for (i = 0; i < track_spt; i++)
{
data_size = sector_size;
data_size = 128 << data_size;
imd[drive].tracks[track][side].sector_data_offs[i] = last_offset;
imd[drive].tracks[track][side].sector_data_size[i] = 1;
if (buffer[imd[drive].tracks[track][side].sector_data_offs[i]] != 0)
{
imd[drive].tracks[track][side].sector_data_size[i] += (buffer[imd[drive].tracks[track][side].sector_data_offs[i]] & 1) ? data_size : 1;
}
last_offset += imd[drive].tracks[track][side].sector_data_size[i];
if (!(buffer[imd[drive].tracks[track][side].sector_data_offs[i]] & 1))
{
fwriteprot[drive] = writeprot[drive] = 1;
}
track_total += (pre_sector + data_size + 2);
}
}
buffer2 = buffer + last_offset;
raw_tsize = td0_get_raw_tsize(imd[drive].tracks[track][side].side_flags, 0);
minimum_gap3 = 12 * track_spt;
if ((raw_tsize - track_total) < (minimum_gap3 + minimum_gap4))
{
/* If we can't fit the sectors with a reasonable minimum gap at perfect RPM, let's try 2% slower. */
raw_tsize = td0_get_raw_tsize(imd[drive].tracks[track][side].side_flags, 1);
/* Set disk flags so that rotation speed is 2% slower. */
imd[drive].disk_flags |= (3 << 5);
if ((raw_tsize - track_total) < (minimum_gap3 + minimum_gap4))
{
/* If we can't fit the sectors with a reasonable minimum gap even at 2% slower RPM, abort. */
pclog("IMD: Unable to fit the %i sectors in a track\n", track_spt);
fclose(imd[drive].f);
return;
}
}
imd[drive].tracks[track][side].gap3_len = (raw_tsize - track_total - minimum_gap4) / track_spt;
imd[drive].track_count++;
if (last_offset >= fsize)
{
break;
}
}
if (imd[drive].track_count > 43) imd[drive].disk_flags |= 1; /* If the image has more than 43 tracks, then the tracks are thin (96 tpi). */
if (imd[drive].sides == 2) imd[drive].disk_flags |= 8; /* If the has 2 sides, mark it as such. */
d86f_register_imd(drive);
drives[drive].seek = imd_seek;
d86f_common_handlers(drive);
}
void imd_close(int drive)
{
int i = 0;
int j = 0;
d86f_unregister(drive);
if (imd[drive].f)
{
free(imd[drive].buffer);
for (i = 0; i < 256; i++)
{
memset(&(imd[drive].tracks[i][0]), 0, sizeof(imd_track_t));
memset(&(imd[drive].tracks[i][1]), 0, sizeof(imd_track_t));
}
fclose(imd[drive].f);
}
imd[drive].f = NULL;
}
int imd_track_is_xdf(int drive, int side, int track)
{
int i, effective_sectors, xdf_sectors;
int high_sectors, low_sectors;
int max_high_id, expected_high_count, expected_low_count;
uint8_t *r_map;
uint8_t *n_map;
uint8_t *data_base;
uint8_t *cur_data;
effective_sectors = xdf_sectors = high_sectors = low_sectors = 0;
memset(imd[drive].xdf_ordered_pos[side], 0, 256);
if (imd[drive].tracks[track][side].params[2] & 0xC0)
{
return 0;
}
if ((imd[drive].tracks[track][side].params[3] != 16) && (imd[drive].tracks[track][side].params[3] != 19))
{
return 0;
}
r_map = imd[drive].buffer + imd[drive].tracks[track][side].r_map_offs;
data_base = imd[drive].buffer + imd[drive].tracks[track][side].data_offs;
if (!track)
{
if (imd[drive].tracks[track][side].params[4] != 2)
{
return 0;
}
if (!side)
{
max_high_id = (imd[drive].tracks[track][side].params[3] == 19) ? 0x8B : 0x88;
expected_high_count = (imd[drive].tracks[track][side].params[3] == 19) ? 0x0B : 0x08;
expected_low_count = 8;
}
else
{
max_high_id = (imd[drive].tracks[track][side].params[3] == 19) ? 0x93 : 0x90;
expected_high_count = (imd[drive].tracks[track][side].params[3] == 19) ? 0x13 : 0x10;
expected_low_count = 0;
}
for (i = 0; i < imd[drive].tracks[track][side].params[3]; i++)
{
if ((r_map[i] >= 0x81) && (r_map[i] <= max_high_id))
{
high_sectors++;
imd[drive].xdf_ordered_pos[r_map[i]][side] = i;
}
if ((r_map[i] >= 0x01) && (r_map[i] <= 0x08))
{
low_sectors++;
imd[drive].xdf_ordered_pos[r_map[i]][side] = i;
}
if ((high_sectors == expected_high_count) && (low_sectors == expected_low_count))
{
imd[drive].current_side_flags[side] = (imd[drive].tracks[track][side].params[3] == 19) ? 0x08 : 0x28;
return (imd[drive].tracks[track][side].params[3] == 19) ? 2 : 1;
}
return 0;
}
}
else
{
if (imd[drive].tracks[track][side].params[4] != 0xFF)
{
return 0;
}
n_map = imd[drive].buffer + imd[drive].tracks[track][side].n_map_offs;
cur_data = data_base;
for (i = 0; i < imd[drive].tracks[track][side].params[3]; i++)
{
effective_sectors++;
if (!(r_map[i]) && !(n_map[i]))
{
effective_sectors--;
}
if ((r_map[i] == (n_map[i] | 0x80)))
{
xdf_sectors++;
imd[drive].xdf_ordered_pos[r_map[i]][side] = i;
}
cur_data += (128 << ((uint32_t) n_map[i]));
}
if ((effective_sectors == 3) && (xdf_sectors == 3))
{
td0[drive].current_side_flags[side] = 0x28;
return 1; /* 5.25" 2HD XDF */
}
if ((effective_sectors == 4) && (xdf_sectors == 4))
{
td0[drive].current_side_flags[side] = 0x08;
return 2; /* 3.5" 2HD XDF */
}
return 0;
}
}
void imd_sector_to_buffer(int drive, int track, int side, uint8_t *buffer, int sector, int len)
{
int i = 0;
int type = imd[drive].buffer[imd[drive].tracks[track][side].sector_data_offs[sector]];
if (type == 0)
{
memset(buffer, 0, len);
}
else
{
if (type & 1)
{
memcpy(buffer, &(imd[drive].buffer[imd[drive].tracks[track][side].sector_data_offs[sector] + 1]), len);
}
else
{
memset(buffer, imd[drive].buffer[imd[drive].tracks[track][side].sector_data_offs[sector] + 1], len);
}
}
}
void imd_seek(int drive, int track)
{
int side;
uint8_t id[4] = { 0, 0, 0, 0 };
uint8_t type, deleted, bad_crc;
int sector, current_pos;
int c = 0;
int h = 0;
int r = 0;
int n = 0;
int ssize = 512;
int track_rate = 0;
int track_gap2 = 22;
int track_gap3 = 12;
int xdf_type = 0;
int is_trackx = 0;
int xdf_spt = 0;
int xdf_sector = 0;
int ordered_pos = 0;
uint8_t *c_map;
uint8_t *h_map;
uint8_t *r_map;
uint8_t *n_map;
uint8_t *data;
uint32_t track_buf_pos[2] = { 0, 0 };
if (!imd[drive].f)
return;
// pclog("IMD: Seeking...\n");
if (d86f_is_40_track(drive) && fdd_doublestep_40(drive))
track /= 2;
is_trackx = (track == 0) ? 0 : 1;
imd[drive].track = track;
imd[drive].current_side_flags[0] = imd[drive].tracks[track][0].side_flags;
imd[drive].current_side_flags[1] = imd[drive].tracks[track][1].side_flags;
d86f_reset_index_hole_pos(drive, 0);
d86f_reset_index_hole_pos(drive, 1);
for (side = 0; side < imd[drive].sides; side++)
{
track_rate = imd[drive].current_side_flags[side] & 7;
if (!track_rate && (imd[drive].current_side_flags[side] & 0x20)) track_rate = 4;
r_map = imd[drive].buffer + imd[drive].tracks[track][side].r_map_offs;
h = imd[drive].tracks[track][side].params[2];
if (h & 0x80)
{
c_map = imd[drive].buffer + imd[drive].tracks[track][side].c_map_offs;
}
else
{
c = imd[drive].tracks[track][side].params[1];
}
if (h & 0x40)
{
h_map = imd[drive].buffer + imd[drive].tracks[track][side].h_map_offs;
}
n = imd[drive].tracks[track][side].params[4];
if (n == 0xFF)
{
n_map = imd[drive].buffer + imd[drive].tracks[track][side].n_map_offs;
track_gap3 = gap3_sizes[track_rate][n_map[0]][imd[drive].tracks[track][side].params[3]];
}
else
{
track_gap3 = gap3_sizes[track_rate][n][imd[drive].tracks[track][side].params[3]];
}
if (!track_gap3)
{
track_gap3 = imd[drive].tracks[track][side].gap3_len;
}
xdf_type = imd_track_is_xdf(drive, side, track);
current_pos = d86f_prepare_pretrack(drive, side, 0, 1);
if (!xdf_type)
{
for (sector = 0; sector < imd[drive].tracks[track][side].params[3]; sector++)
{
id[0] = (h & 0x80) ? c_map[sector] : c;
id[1] = (h & 0x40) ? h_map[sector] : (h & 1);
id[2] = r_map[sector];
id[3] = (n == 0xFF) ? n_map[sector] : n;
ssize = 128 << ((uint32_t) id[3]);
data = imd[drive].track_buffer[side] + track_buf_pos[side];
type = imd[drive].buffer[imd[drive].tracks[track][side].sector_data_offs[sector]];
type = (type >> 1) & 7;
deleted = bad_crc = 0;
if ((type == 2) || (type == 4)) deleted = 1;
if ((type == 3) || (type == 4)) bad_crc = 1;
// pclog("IMD: (%i %i) %i %i %i %i (%i %i) (GPL=%i)\n", track, side, id[0], id[1], id[2], id[3], deleted, bad_crc, track_gap3);
imd_sector_to_buffer(drive, track, side, data, sector, ssize);
current_pos = d86f_prepare_sector(drive, side, current_pos, id, data, ssize, 1, 22, track_gap3, 0, deleted, bad_crc);
track_buf_pos[side] += ssize;
}
}
else
{
xdf_type--;
xdf_spt = xdf_physical_sectors[xdf_type][is_trackx];
for (sector = 0; sector < xdf_spt; sector++)
{
xdf_sector = (side * xdf_spt) + sector;
id[0] = track;
id[1] = side;
id[2] = xdf_disk_layout[xdf_type][is_trackx][xdf_sector].id.r;
id[3] = is_trackx ? (id[2] & 7) : 2;
ssize = 128 << ((uint32_t) id[3]);
ordered_pos = imd[drive].xdf_ordered_pos[id[2]][side];
data = imd[drive].track_buffer[side] + track_buf_pos[side];
type = imd[drive].buffer[imd[drive].tracks[track][side].sector_data_offs[ordered_pos]];
type = (type >> 1) & 7;
deleted = bad_crc = 0;
if ((type == 2) || (type == 4)) deleted = 1;
if ((type == 3) || (type == 4)) bad_crc = 1;
imd_sector_to_buffer(drive, track, side, data, ordered_pos, ssize);
if (is_trackx)
{
current_pos = d86f_prepare_sector(drive, side, xdf_trackx_spos[xdf_type][xdf_sector], id, data, ssize, 1, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], 0, deleted, bad_crc);
}
else
{
current_pos = d86f_prepare_sector(drive, side, current_pos, id, data, ssize, 1, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], 0, deleted, bad_crc);
}
track_buf_pos[side] += ssize;
}
}
}
// pclog("Seeked to track: %i (%02X, %02X)\n", imd[drive].track, imd[drive].current_side_flags[0], imd[drive].current_side_flags[1]);
}
uint16_t imd_disk_flags(int drive)
{
return imd[drive].disk_flags;
}
uint16_t imd_side_flags(int drive)
{
int side = 0;
uint8_t sflags = 0;
side = fdd_get_head(drive);
sflags = imd[drive].current_side_flags[side];
return sflags;
}
void imd_set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n)
{
int i = 0;
int track = imd[drive].track;
int sc = 0;
int sh = 0;
int sn = 0;
uint8_t *c_map, *h_map, *r_map, *n_map;
uint8_t id[4] = { 0, 0, 0, 0 };
sc = imd[drive].tracks[track][side].params[1];
sh = imd[drive].tracks[track][side].params[2];
sn = imd[drive].tracks[track][side].params[4];
if (sh & 0x80)
{
c_map = imd[drive].buffer + imd[drive].tracks[track][side].c_map_offs;
}
if (sh & 0x40)
{
h_map = imd[drive].buffer + imd[drive].tracks[track][side].h_map_offs;
}
r_map = imd[drive].buffer + imd[drive].tracks[track][side].r_map_offs;
if (sn == 0xFF)
{
n_map = imd[drive].buffer + imd[drive].tracks[track][side].n_map_offs;
}
if (c != imd[drive].track) return;
for (i = 0; i < imd[drive].tracks[track][side].params[3]; i++)
{
id[0] = (h & 0x80) ? c_map[i] : sc;
id[1] = (h & 0x40) ? h_map[i] : (sh & 1);
id[2] = r_map[i];
id[3] = (n == 0xFF) ? n_map[i] : sn;
if ((id[0] == c) &&
(id[1] == h) &&
(id[2] == r) &&
(id[3] == n))
{
imd[drive].current_data[side] = imd[drive].buffer + imd[drive].tracks[track][side].sector_data_offs[i];
}
}
return;
}
void imd_writeback(int drive)
{
int side;
int track = imd[drive].track;
if (writeprot[drive])
{
return;
}
int i = 0;
uint8_t *track_buf;
uint8_t *n_map;
uint8_t h, n, spt;
uint32_t ssize;
for (side = 0; side < imd[drive].sides; side++)
{
if (imd[drive].tracks[track][side].is_present)
{
track_buf = imd[drive].buffer + imd[drive].tracks[track][side].file_offs;
fseek(imd[drive].f, imd[drive].tracks[track][side].file_offs, SEEK_SET);
h = imd[drive].tracks[track][side].params[2];
spt = imd[drive].tracks[track][side].params[3];
n = imd[drive].tracks[track][side].params[4];
fwrite(imd[drive].tracks[track][side].params, 1, 5, imd[drive].f);
if (h & 0x80)
{
fwrite(imd[drive].buffer + imd[drive].tracks[track][side].c_map_offs, 1, spt, imd[drive].f);
}
if (h & 0x40)
{
fwrite(imd[drive].buffer + imd[drive].tracks[track][side].h_map_offs, 1, spt, imd[drive].f);
}
if (n == 0xFF)
{
n_map = imd[drive].buffer + imd[drive].tracks[track][side].n_map_offs;
fwrite(n_map, 1, spt, imd[drive].f);
}
for (i = 0; i < spt; i++)
{
ssize = (n == 0xFF) ? n_map[i] : n;
ssize = 128 << ssize;
fwrite(imd[drive].buffer + imd[drive].tracks[track][side].sector_data_offs[i], 1, ssize, imd[drive].f);
}
}
}
}
uint8_t imd_poll_read_data(int drive, int side, uint16_t pos)
{
int type = imd[drive].current_data[side][0];
if (!type)
{
return 0;
}
else
{
return (type & 1) ? imd[drive].current_data[side][pos + 1] : imd[drive].current_data[side][1];
}
}
void imd_poll_write_data(int drive, int side, uint16_t pos, uint8_t data)
{
int type = imd[drive].current_data[side][0];
if (writeprot[drive])
{
return;
}
if (!(type & 1))
{
return; /* Should never happen. */
}
imd[drive].current_data[side][pos + 1] = data;
}
int imd_format_conditions(int drive)
{
int track = imd[drive].track;
int side = 0;
int temp = 0;
side = fdd_get_head(drive);
temp = (fdc_get_format_sectors() == imd[drive].tracks[track][side].params[3]);
temp = temp && (fdc_get_format_n() == imd[drive].tracks[track][side].params[4]);
return temp;
}
void d86f_register_imd(int drive)
{
d86f_handler[drive].disk_flags = imd_disk_flags;
d86f_handler[drive].side_flags = imd_side_flags;
d86f_handler[drive].writeback = imd_writeback;
d86f_handler[drive].set_sector = imd_set_sector;
d86f_handler[drive].read_data = imd_poll_read_data;
d86f_handler[drive].write_data = imd_poll_write_data;
d86f_handler[drive].format_conditions = imd_format_conditions;
d86f_handler[drive].check_crc = 1;
}

7
src/disc_imd.h Normal file
View File

@@ -0,0 +1,7 @@
/* Copyright holders: Kiririn
see COPYING for more details
*/
void imd_init();
void imd_load(int drive, char *fn);
void imd_close(int drive);
void imd_seek(int drive, int track);

View File

@@ -68,9 +68,8 @@ static int gap3_sizes[5][8][256] = { [0][1][16] = 0x54,
[0][2][19] = 0x48,
[0][2][20] = 0x2A,
[0][2][21] = 0x0C,
// [0][2][23] = 0x7A,
[0][2][23] = 0x01,
// [0][2][24] = 0x38,
[0][3][11] = 0x26,
[2][1][10] = 0x32,
[2][1][11] = 0x0C,
[2][1][15] = 0x36,
@@ -84,18 +83,13 @@ static int gap3_sizes[5][8][256] = { [0][1][16] = 0x54,
[2][3][5] = 0x74,
[3][2][36] = 0x53,
[3][2][39] = 0x20,
// [3][2][46] = 0x0E,
[3][2][46] = 0x01,
// [3][2][48] = 0x51,
[4][1][32] = 0x36,
[4][2][15] = 0x54,
[4][2][17] = 0x23,
[4][2][18] = 0x02,
// [4][2][19] = 0x29,
[4][2][19] = 0x01,
[4][3][8] = 0x74,
[4][3][9] = 0x74,
[4][3][10] = 0x74
[4][3][8] = 0x74
};
/* Needed for formatting! */

View File

@@ -32,21 +32,9 @@ static struct
static uint8_t dmf_r[21] = { 12, 2, 13, 3, 14, 4, 15, 5, 16, 6, 17, 7, 18, 8, 19, 9, 20, 10, 21, 11, 1 };
static uint8_t xdf_spt[2] = { 6, 8 };
static uint8_t xdf_logical_sectors[2][2] = { { 38, 6 }, { 46, 8 } };
static uint8_t xdf_physical_sectors[2][2] = { { 16, 3 }, { 19, 4 } };
static uint8_t xdf_gap3_sizes[2][2] = { { 60, 69 }, { 60, 50 } };
static uint16_t xdf_trackx_spos[2][8] = { { 0xA7F, 0xF02, 0x11B7, 0xB66, 0xE1B, 0x129E }, { 0x302, 0x7E2, 0xA52, 0x12DA, 0x572, 0xDFA, 0x106A, 0x154A } };
typedef struct
{
uint8_t h;
uint8_t r;
} xdf_id_t;
typedef union
{
uint16_t word;
xdf_id_t id;
} xdf_sector_t;
uint8_t xdf_physical_sectors[2][2] = { { 16, 3 }, { 19, 4 } };
uint8_t xdf_gap3_sizes[2][2] = { { 60, 69 }, { 60, 50 } };
uint16_t xdf_trackx_spos[2][8] = { { 0xA7F, 0xF02, 0x11B7, 0xB66, 0xE1B, 0x129E }, { 0x302, 0x7E2, 0xA52, 0x12DA, 0x572, 0xDFA, 0x106A, 0x154A } };
/* XDF: Layout of the sectors in the image. */
xdf_sector_t xdf_img_layout[2][2][46] = { { { 0x8100, 0x8200, 0x8300, 0x8400, 0x8500, 0x8600, 0x8700, 0x8800,
@@ -124,11 +112,9 @@ int gap3_sizes[5][8][256] = { [0][1][16] = 0x54,
[0][2][18] = 0x6C,
[0][2][19] = 0x48,
[0][2][20] = 0x2A,
// [0][2][21] = 0x0C,
[0][2][21] = 0x08, /* Microsoft DMFWRITE.EXE uses this, 0x0C is used by FDFORMAT. */
// [0][2][23] = 0x7A,
[0][2][23] = 0x01,
// [0][2][24] = 0x38,
[0][3][11] = 0x26,
[2][1][10] = 0x32,
[2][1][11] = 0x0C,
[2][1][15] = 0x36,
@@ -142,17 +128,12 @@ int gap3_sizes[5][8][256] = { [0][1][16] = 0x54,
[2][3][5] = 0x74,
[3][2][36] = 0x53,
[3][2][39] = 0x20,
// [3][2][46] = 0x0E,
[3][2][46] = 0x01,
// [3][2][48] = 0x51,
[4][1][32] = 0x36,
[4][2][15] = 0x54,
[4][2][17] = 0x23,
// [4][2][19] = 0x29,
[4][2][19] = 0x01,
[4][3][8] = 0x74,
[4][3][9] = 0x74,
[4][3][10] = 0x74
[4][3][8] = 0x74
};
void img_writeback(int drive);
@@ -291,6 +272,7 @@ void img_load(int drive, char *fn)
else if (size <= (180*1024)) { img[drive].sectors = 9; img[drive].tracks = 40; img[drive].sides = 1; }
else if (size <= (320*1024)) { img[drive].sectors = 8; img[drive].tracks = 40; }
else if (size <= (360*1024)) { img[drive].sectors = 9; img[drive].tracks = 40; } /*Double density*/
else if (size <= (400*1024)) { img[drive].sectors = 10; img[drive].tracks = 80; img[drive].sides = 1; } /*DEC RX50*/
else if (size <= (640*1024)) { img[drive].sectors = 8; img[drive].tracks = 80; } /*Double density 640k*/
else if (size < (1024*1024)) { img[drive].sectors = 9; img[drive].tracks = 80; } /*Double density*/
else if (size <= 1228800) { img[drive].sectors = 15; img[drive].tracks = 80; } /*High density 1.2MB*/

View File

@@ -102,6 +102,7 @@ typedef struct
int track;
int current_sector_index[2];
uint8_t calculated_gap3_lengths[256][2];
uint8_t xdf_ordered_pos[256][2];
} td0_t;
td0_t td0[2];
@@ -492,7 +493,7 @@ void td0_init()
void d86f_register_td0(int drive);
static const int rates[3] = { 2, 1, 0 };
// static const int rates[3] = { 2, 1, 0, 2, 3 }; /* 0 = 250 kbps, 1 = 300 kbps, 2 = 500 kbps, 3 = unknown, 4 = 1000 kbps */
const int max_size = 4*1024*1024; // 4MB ought to be large enough for any floppy
const int max_processed_size = 5*1024*1024;
uint8_t imagebuf[4*1024*1024];
@@ -587,10 +588,10 @@ void td0_close(int drive)
td0[drive].f = NULL;
}
uint32_t td0_get_raw_tsize(int drive, int track, int side, int slower_rpm)
uint32_t td0_get_raw_tsize(int side_flags, int slower_rpm)
{
uint32_t size;
switch(td0[drive].side_flags[track][side] & 0x27)
switch(side_flags & 0x27)
{
case 0x22:
size = slower_rpm ? 5314 : 5208;
@@ -636,7 +637,8 @@ int td0_initialize(int drive)
int offset = 0;
int ret = 0;
int gap3_len = 0;
int rate = 0;
// int rate = 0;
int density = 0;
int i = 0;
int j = 0;
int temp_rate = 0;
@@ -648,6 +650,7 @@ int td0_initialize(int drive)
uint16_t size;
uint8_t *dbuf = processed_buf;
uint32_t total_size = 0;
uint32_t pre_sector = 0;
uint32_t track_size = 0;
uint32_t raw_tsize = 0;
uint32_t minimum_gap3 = 0;
@@ -703,26 +706,40 @@ int td0_initialize(int drive)
return 0;
}
density = (header[5] >> 1) & 3;
if (density == 3)
{
pclog("TD0: Unknown density\n");
return 0;
}
/* We determine RPM from the drive type as well as we possibly can. */
/* This byte is actually the BIOS floppy drive type read by Teledisk from the CMOS. */
switch(header[6])
{
case 0: /* 5.25" 2DD in 2HD drive: 360 rpm */
case 2: /* 5.25" 2HD: 360 rpm */
td0[drive].default_track_flags = ((header[5] & 0x7f) == 2) ? 0x20 : 0x00;
case 0: /* 5.25" 360k in 1.2M drive: 360 rpm
CMOS Drive type: None, value probably reused by Teledisk */
case 2: /* 5.25" 1.2M 360 rpm */
case 5: /* 8"/5.25"/3.5" 1.25M 360 rpm */
td0[drive].default_track_flags = (density == 1) ? 0x20 : 0x21;
break;
case 5: /* 8 " 2?D: 360 rpm */
td0[drive].default_track_flags = 0x20;
case 1: /* 5.25" 360k: 300 rpm */
case 3: /* 3.5" 720k: 300 rpm */
td0[drive].default_track_flags = 0x02;
break;
case 1: /* 5.25" 2DD: 300 rpm */
case 3: /* 3.5 " 2DD: 300 rpm */
case 4: /* 3.5 " 2HD: 300 rpm */
case 6: /* 3.5 " 2ED?: 300 rpm */
td0[drive].default_track_flags = 0x00;
case 4: /* 3.5" 1.44M: 300 rpm */
td0[drive].default_track_flags = (density == 1) ? 0x00 : 0x02;
break;
case 6: /* 3.5" 2.88M: 300 rpm */
td0[drive].default_track_flags = (density == 1) ? 0x00 : ((density == 2) ? 0x03 : 0x02);
break;
}
rate = (header[5] & 0x7f) >= 3 ? 0 : rates[header[5] & 0x7f];
td0[drive].default_track_flags |= rate;
td0[drive].disk_flags = header[5] & 0x06;
// rate = (header[5] & 0x7f) >= 3 ? 0 : rates[header[5] & 0x7f];
// td0[drive].default_track_flags |= rate;
for (i = 0; i < 256; i++)
{
@@ -743,7 +760,9 @@ int td0_initialize(int drive)
td0[drive].side_flags[track][head] = td0[drive].default_track_flags | (fm ? 0 : 8);
td0[drive].track_in_file[track][head] = 1;
offset += 4;
track_size = 146;
track_size = fm ? 73 : 146;
pre_sector = fm ? 42 : 60;
for(i = 0; i < track_spt; i++)
{
hs = &imagebuf[offset];
@@ -826,23 +845,26 @@ int td0_initialize(int drive)
dbuf += size;
total_size += size;
track_size += size;
track_size += (pre_sector + size + 2);
}
track_count = track;
track_spt = imagebuf[offset];
if (track_spt != 255)
{
td0[drive].track_spt[track][head] = track_spt;
raw_tsize = td0_get_raw_tsize(drive, track, head, 0);
if ((td0[drive].track_spt[track][head] == 8) && (td0[drive].sects[track][head][0].size == 3))
{
td0[drive].side_flags[track][head] |= 0x20;
}
raw_tsize = td0_get_raw_tsize(td0[drive].side_flags[track][head], 0);
minimum_gap3 = 12 * track_spt;
if ((raw_tsize - track_size) < (minimum_gap3 + minimum_gap4))
{
/* If we can't fit the sectors with a reasonable minimum gap at perfect RPM, let's try 2% slower. */
raw_tsize = td0_get_raw_tsize(drive, track, head, 1);
raw_tsize = td0_get_raw_tsize(td0[drive].side_flags[track][head], 1);
/* Set disk flags so that rotation speed is 2% slower. */
td0[drive].disk_flags |= (3 << 5);
if ((raw_tsize - track_size) < (minimum_gap3 + minimum_gap4))
@@ -853,6 +875,8 @@ int td0_initialize(int drive)
}
}
td0[drive].calculated_gap3_lengths[track][head] = (raw_tsize - track_size - minimum_gap4) / track_spt;
track_spt = imagebuf[offset];
}
}
@@ -863,7 +887,7 @@ int td0_initialize(int drive)
td0[drive].tracks = track_count + 1;
temp_rate = rate;
temp_rate = td0[drive].default_track_flags & 7;
if ((td0[drive].default_track_flags & 0x27) == 0x20) temp_rate = 4;
td0[drive].gap3_len = gap3_sizes[temp_rate][td0[drive].sects[0][0][0].size][td0[drive].track_spt[0][0]];
// pclog("GAP3 length for %i %i %i is %i\n", temp_rate, td0[drive].sects[0][0][0].size, td0[drive].track_spt[0][0], td0[drive].gap3_len);
@@ -876,14 +900,8 @@ int td0_initialize(int drive)
if(head_count == 2)
{
td0[drive].disk_flags = 8; /* 2 sides */
td0[drive].disk_flags |= 8; /* 2 sides */
}
else
{
td0[drive].disk_flags = 0; /* 1 side */
}
if (td0[drive].tracks > 43) td0[drive].disk_flags |= 1; /* If the image has more than 43 tracks, then the tracks are thin (96 tpi). */
td0[drive].sides = head_count;
@@ -895,6 +913,101 @@ int td0_initialize(int drive)
return 1;
}
int td0_track_is_xdf(int drive, int side, int track)
{
uint8_t id[4] = { 0, 0, 0, 0 };
int i, effective_sectors, xdf_sectors;
int high_sectors, low_sectors;
int max_high_id, expected_high_count, expected_low_count;
effective_sectors = xdf_sectors = high_sectors = low_sectors = 0;
memset(td0[drive].xdf_ordered_pos[side], 0, 256);
if (!track)
{
if ((td0[drive].track_spt[track][side] == 16) || (td0[drive].track_spt[track][side] == 19))
{
if (!side)
{
max_high_id = (td0[drive].track_spt[track][side] == 19) ? 0x8B : 0x88;
expected_high_count = (td0[drive].track_spt[track][side] == 19) ? 0x0B : 0x08;
expected_low_count = 8;
}
else
{
max_high_id = (td0[drive].track_spt[track][side] == 19) ? 0x93 : 0x90;
expected_high_count = (td0[drive].track_spt[track][side] == 19) ? 0x13 : 0x10;
expected_low_count = 0;
}
for (i = 0; i < td0[drive].track_spt[track][side]; i++)
{
id[0] = td0[drive].sects[track][side][i].track;
id[1] = td0[drive].sects[track][side][i].head;
id[2] = td0[drive].sects[track][side][i].sector;
id[3] = td0[drive].sects[track][side][i].size;
if (!(id[0]) && (id[1] == side) && (id[3] == 2))
{
if ((id[2] >= 0x81) && (id[2] <= max_high_id))
{
high_sectors++;
td0[drive].xdf_ordered_pos[id[2]][side] = i;
}
if ((id[2] >= 0x01) && (id[2] <= 0x08))
{
low_sectors++;
td0[drive].xdf_ordered_pos[id[2]][side] = i;
}
}
}
if ((high_sectors == expected_high_count) && (low_sectors == expected_low_count))
{
td0[drive].current_side_flags[side] = (td0[drive].track_spt[track][side] == 19) ? 0x08 : 0x28;
return (td0[drive].track_spt[track][side] == 19) ? 2 : 1;
}
// pclog("XDF: %i %i %i %i\n", high_sectors, expected_high_count, low_sectors, expected_low_count);
return 0;
}
else
{
// pclog("XDF: %i sectors per track (%i %i)\n", td0[drive].track_spt[track][side], track, side);
return 0;
}
}
else
{
for (i = 0; i < td0[drive].track_spt[track][side]; i++)
{
id[0] = td0[drive].sects[track][side][i].track;
id[1] = td0[drive].sects[track][side][i].head;
id[2] = td0[drive].sects[track][side][i].sector;
id[3] = td0[drive].sects[track][side][i].size;
effective_sectors++;
if ((id[0] == track) && (id[1] == side) && !(id[2]) && !(id[3]))
{
effective_sectors--;
}
if ((id[0] == track) && (id[1] == side) && (id[2] == (id[3] | 0x80)))
{
xdf_sectors++;
td0[drive].xdf_ordered_pos[id[2]][side] = i;
}
}
// pclog("XDF: %i %i\n", effective_sectors, xdf_sectors);
if ((effective_sectors == 3) && (xdf_sectors == 3))
{
td0[drive].current_side_flags[side] = 0x28;
return 1; /* 5.25" 2HD XDF */
}
if ((effective_sectors == 4) && (xdf_sectors == 4))
{
td0[drive].current_side_flags[side] = 0x08;
return 2; /* 3.5" 2HD XDF */
}
return 0;
}
}
void td0_seek(int drive, int track)
{
int side;
@@ -906,7 +1019,18 @@ void td0_seek(int drive, int track)
int ssize = 512;
int track_rate = 0;
int track_gap2 = 22;
int track_gap3 = 12;
int xdf_type = 0;
int is_trackx = 0;
int xdf_spt = 0;
int xdf_sector = 0;
int ordered_pos = 0;
if (!td0[drive].f)
return;
@@ -914,11 +1038,15 @@ void td0_seek(int drive, int track)
if (d86f_is_40_track(drive) && fdd_doublestep_40(drive))
track /= 2;
is_trackx = (track == 0) ? 0 : 1;
td0[drive].track = track;
td0[drive].current_side_flags[0] = td0[drive].side_flags[track][0];
td0[drive].current_side_flags[1] = td0[drive].side_flags[track][1];
// pclog("TD0 Seek: %02X %02X (%02X)\n", td0[drive].current_side_flags[0], td0[drive].current_side_flags[1], td0[drive].disk_flags);
d86f_reset_index_hole_pos(drive, 0);
d86f_reset_index_hole_pos(drive, 1);
@@ -929,20 +1057,51 @@ void td0_seek(int drive, int track)
track_gap3 = gap3_sizes[track_rate][td0[drive].sects[track][side][0].size][td0[drive].track_spt[track][side]];
if (!track_gap3)
{
td0[drive].calculated_gap3_lengths[track][side];
track_gap3 = td0[drive].calculated_gap3_lengths[track][side];
}
track_gap2 = ((td0[drive].current_side_flags[side] & 7) >= 3) ? 41 : 22;
xdf_type = td0_track_is_xdf(drive, side, track);
current_pos = d86f_prepare_pretrack(drive, side, 0, 1);
for (sector = 0; sector < td0[drive].track_spt[track][side]; sector++)
if (!xdf_type)
{
id[0] = td0[drive].sects[track][side][sector].track;
id[1] = td0[drive].sects[track][side][sector].head;
id[2] = td0[drive].sects[track][side][sector].sector;
id[3] = td0[drive].sects[track][side][sector].size;
// pclog("TD0: %i %i %i %i (%i %i) (GPL=%i)\n", id[0], id[1], id[2], id[3], td0[drive].sects[track][side][sector].deleted, td0[drive].sects[track][side][sector].bad_crc, track_gap3);
ssize = 128 << ((uint32_t) td0[drive].sects[track][side][sector].size);
current_pos = d86f_prepare_sector(drive, side, current_pos, id, td0[drive].sects[track][side][sector].data, ssize, 1, 0x22, track_gap3, 0, td0[drive].sects[track][side][sector].deleted, td0[drive].sects[track][side][sector].bad_crc);
for (sector = 0; sector < td0[drive].track_spt[track][side]; sector++)
{
id[0] = td0[drive].sects[track][side][sector].track;
id[1] = td0[drive].sects[track][side][sector].head;
id[2] = td0[drive].sects[track][side][sector].sector;
id[3] = td0[drive].sects[track][side][sector].size;
// pclog("TD0: %i %i %i %i (%i %i) (GPL=%i)\n", id[0], id[1], id[2], id[3], td0[drive].sects[track][side][sector].deleted, td0[drive].sects[track][side][sector].bad_crc, track_gap3);
ssize = 128 << ((uint32_t) td0[drive].sects[track][side][sector].size);
current_pos = d86f_prepare_sector(drive, side, current_pos, id, td0[drive].sects[track][side][sector].data, ssize, 1, track_gap2, track_gap3, 0, td0[drive].sects[track][side][sector].deleted, td0[drive].sects[track][side][sector].bad_crc);
}
}
else
{
xdf_type--;
xdf_spt = xdf_physical_sectors[xdf_type][is_trackx];
for (sector = 0; sector < xdf_spt; sector++)
{
xdf_sector = (side * xdf_spt) + sector;
id[0] = track;
id[1] = side;
id[2] = xdf_disk_layout[xdf_type][is_trackx][xdf_sector].id.r;
id[3] = is_trackx ? (id[2] & 7) : 2;
ssize = 128 << ((uint32_t) id[3]);
ordered_pos = td0[drive].xdf_ordered_pos[id[2]][side];
// pclog("TD0: XDF: (%i %i) %i %i %i %i (%i %i) (GPL=%i)\n", track, side, id[0], id[1], id[2], id[3], td0[drive].sects[track][side][ordered_pos].deleted, td0[drive].sects[track][side][ordered_pos].bad_crc, track_gap3);
if (is_trackx)
{
current_pos = d86f_prepare_sector(drive, side, xdf_trackx_spos[xdf_type][xdf_sector], id, td0[drive].sects[track][side][ordered_pos].data, ssize, 1, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], 0, td0[drive].sects[track][side][ordered_pos].deleted, td0[drive].sects[track][side][ordered_pos].bad_crc);
}
else
{
current_pos = d86f_prepare_sector(drive, side, current_pos, id, td0[drive].sects[track][side][ordered_pos].data, ssize, 1, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], 0, td0[drive].sects[track][side][ordered_pos].deleted, td0[drive].sects[track][side][ordered_pos].bad_crc);
}
}
}
}
@@ -957,8 +1116,10 @@ uint16_t td0_disk_flags(int drive)
uint16_t td0_side_flags(int drive)
{
int side = 0;
uint8_t sflags = 0;
side = fdd_get_head(drive);
return td0[drive].current_side_flags[side];
sflags = td0[drive].current_side_flags[side];
return sflags;
}
void td0_set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n)

View File

@@ -276,6 +276,8 @@ void initpc(int argc, char *argv[])
fdi_init();
img_init();
d86f_init();
td0_init();
imd_init();
vlan_reset(); //NETWORK
network_card_init(network_card_current);

View File

@@ -212,6 +212,7 @@ void svga_out(uint16_t addr, uint8_t val, void *p)
break;
case 0x3C8:
svga->dac_write = val;
svga->dac_read = val - 1;
svga->dac_pos = 0;
break;
case 0x3C9:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -950,6 +950,8 @@ void atapi_close(void)
}
}
char *floppy_image_extensions = "All floppy images (*.12;*.144;*.360;*.720;*.86F;*.BIN;*.DSK;*.FDI;*.FLP;*.IMA;*.IMD;*.IMG;*.TD0;*.VFD;*.XDF)\0*.12;*.144;*.360;*.720;*.86F;*.BIN;*.DSK;*.FDI;*.FLP;*.IMA;*.IMD;*.IMG;*.TD0;*.VFD;*.XDF\0Advanced sector-based images (*.IMD;*.TD0)\0*.IMD;*.TD0\0Basic sector-based images (*.12;*.144;*.360;*.720;*.BIN;*.DSK;*.FDI;*.FLP;*.IMA;*.IMG;*.VFD;*.XDF)\0*.12;*.144;*.360;*.720;*.BIN;*.DSK;*.FDI;*.FLP;*.IMA;*.IMG;*.VFD;*.XDF\0Flux images (*.FDI)\0*.FDI\0Surface-based images (*.86F)\0*.86F\0All files (*.*)\0*.*\0";
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HMENU hmenu;
@@ -1001,7 +1003,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
break;
case IDM_DISC_A:
case IDM_DISC_A_WP:
if (!getfile(hwnd,"Disc image (*.12;*.144;*.360;*.720;*.86F;*.DSK;*.IMG;*.IMA;*.FDI;*.FLP;*.TD0;*.VFD;*.XDF)\0*.12;*.144;*.360;*.720;*.86F;*.DSK;*.IMG;*.IMA;*.FDI;*.FLP;*.TD0;*.VFD;*.XDF\0All files (*.*)\0*.*\0",discfns[0]))
if (!getfile(hwnd, floppy_image_extensions, discfns[0]))
{
disc_close(0);
ui_writeprot[0] = (LOWORD(wParam) == IDM_DISC_A_WP) ? 1 : 0;
@@ -1011,7 +1013,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
break;
case IDM_DISC_B:
case IDM_DISC_B_WP:
if (!getfile(hwnd,"Disc image (*.12;*.144;*.360;*.720;*.86F;*.DSK;*.IMG;*.IMA;*.FDI;*.FLP;*.TD0;*.VFD;*.XDF)\0*.12;*.144;*.360;*.720;*.86F;*.DSK;*.IMG;*.IMA;*.FDI;*.FLP;*.TD0;*.VFD;*.XDF\0All files (*.*)\0*.*\0",discfns[1]))
if (!getfile(hwnd, floppy_image_extensions, discfns[1]))
{
disc_close(1);
ui_writeprot[1] = (LOWORD(wParam) == IDM_DISC_B_WP) ? 1 : 0;