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:
@@ -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 \
|
||||
|
||||
@@ -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 \
|
||||
|
||||
16
src/cpu.c
16
src/cpu.c
@@ -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
|
||||
|
||||
@@ -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}
|
||||
};
|
||||
|
||||
|
||||
22
src/disc.h
22
src/disc.h
@@ -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);
|
||||
|
||||
@@ -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
717
src/disc_imd.c
Normal 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
7
src/disc_imd.h
Normal 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);
|
||||
@@ -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! */
|
||||
|
||||
@@ -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*/
|
||||
|
||||
241
src/disc_td0.c
241
src/disc_td0.c
@@ -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)
|
||||
|
||||
2
src/pc.c
2
src/pc.c
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
1887
src/vid_voodoo.c
1887
src/vid_voodoo.c
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
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user