Rewritten parts of the 86F handler to minimize false CRC errors and misidentification of sectors;

Replaced IMG handler with one that now proxies to the 86F handler;
Applies the remaining Mainline PCem speedup commit;
Fixed the National Semiconductors PC87306 Super I/O Chip's serial port IRQ assignment;
DMF images are now loaded with the correct sector interleave, improving read/write speed;
XDF images are now loaded in a way that emulates the real order of the sectors on the track, improving read/write speed;
Added 16-bit physical memory read/write routines (mem_phys_readw, mem_phys_writew) and modified the 16-bit DMA code to use them instead of two 8-bit reads/writes.
This commit is contained in:
OBattler 2016-09-22 21:22:56 +02:00
parent 0ae428b5f5
commit 6318e2bb17
24 changed files with 1688 additions and 513 deletions

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

@ -5,7 +5,7 @@ WINDRES = windres.exe
CFLAGS = -O3 -march=native -mtune=native -fbranch-probabilities -fvpt -funroll-loops -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse -mstackrealign
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-iso.o \
cdrom-null.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86-64.o compaq.o config.o cpu.o dac.o \
device.o disc.o disc_86f.o disc_fdi.o disc_img.o disc_random.o disc_sector_86box.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \
device.o disc.o disc_86f.o disc_fdi.o disc_img_86box.o disc_random.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 \

@ -580,6 +580,7 @@ static uint32_t ropFLDCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint
MEM_LOAD_ADDR_EA_W(target_seg);
STORE_HOST_REG_ADDR_W((uintptr_t)&cpu_state.npxc, 0);
UPDATE_NPXC(0);
return op_pc + 1;
}

@ -4556,6 +4556,10 @@ static void FP_COMPARE_IL()
FP_COMPARE_MEM();
}
static void UPDATE_NPXC(int reg)
{
}
static void SET_BITS(uintptr_t addr, uint32_t val)
{
if (IS_32_ADDR(addr))

@ -2173,82 +2173,6 @@ static void FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2)
*host_reg2 = REG_ECX;
}
static double _fp_half = 0.5;
static void FP_LOAD_ROUNDING()
{
pclog("cpu_state.npxc %04x\n", cpu_state.npxc);
addbyte(0x8b); /*MOV EDX, npxc*/
addbyte(0x15);
addlong((uintptr_t)&cpu_state.npxc);
addbyte(0xd9); /*FSTCW [ESP+8]*/
addbyte(0x7c);
addbyte(0x24);
addbyte(0x08);
addbyte(0x89); /*MOV [ESP+12],EDX*/
addbyte(0x54);
addbyte(0x24);
addbyte(0x0c);
addbyte(0xd9); /*FLDCW [ESP+12]*/
addbyte(0x6c);
addbyte(0x24);
addbyte(0x0c);
}
static void FP_RESTORE_ROUNDING()
{
addbyte(0xd9); /*FLDCW [ESP+8]*/
addbyte(0x6c);
addbyte(0x24);
addbyte(0x08);
}
static int32_t x87_fround32(double b)
{
int64_t a, c;
switch ((cpu_state.npxc >> 10) & 3)
{
case 0: /*Nearest*/
a = (int64_t)floor(b);
c = (int64_t)floor(b + 1.0);
if ((b - a) < (c - b))
return a;
else if ((b - a) > (c - b))
return c;
else
return (a & 1) ? c : a;
case 1: /*Down*/
return (int32_t)floor(b);
case 2: /*Up*/
return (int32_t)ceil(b);
case 3: /*Chop*/
return (int32_t)b;
}
}
static int64_t x87_fround64(double b)
{
int64_t a, c;
switch ((cpu_state.npxc >> 10) & 3)
{
case 0: /*Nearest*/
a = (int64_t)floor(b);
c = (int64_t)floor(b + 1.0);
if ((b - a) < (c - b))
return a;
else if ((b - a) > (c - b))
return c;
else
return (a & 1) ? c : a;
case 1: /*Down*/
return (int64_t)floor(b);
case 2: /*Up*/
return (int64_t)ceil(b);
case 3: /*Chop*/
return (int64_t)b;
}
}
static int FP_LOAD_REG_INT_W(int reg)
{
addbyte(0x8b); /*MOV EBX, TOP*/
@ -2268,25 +2192,19 @@ static int FP_LOAD_REG_INT_W(int reg)
addbyte(0xdd);
addbyte(cpu_state_offset(ST));
addbyte(0x89); /*MOV [ESP+8], EAX*/
addbyte(0x44);
addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/
addbyte(0x6d);
addbyte(cpu_state_offset(new_npxc));
addbyte(0xdb); /*FISTP [ESP]*/
addbyte(0x1c);
addbyte(0x24);
addbyte(0x08);
addbyte(0xdd); /*FSTP [ESP]*/
addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/
addbyte(0x6d);
addbyte(cpu_state_offset(old_npxc));
addbyte(0x8b); /*MOV EBX, [ESP]*/
addbyte(0x1c);
addbyte(0x24);
CALL_FUNC(x87_fround32);
addbyte(0x89); /*MOV EBX, EAX*/
addbyte(0xc3);
addbyte(0x8b); /*MOV EAX, [ESP+8]*/
addbyte(0x44);
addbyte(0x24);
addbyte(0x08);
return REG_EBX;
}
static int FP_LOAD_REG_INT(int reg)
@ -2308,25 +2226,19 @@ static int FP_LOAD_REG_INT(int reg)
addbyte(0xdd);
addbyte(cpu_state_offset(ST));
addbyte(0x89); /*MOV [ESP+8], EAX*/
addbyte(0x44);
addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/
addbyte(0x6d);
addbyte(cpu_state_offset(new_npxc));
addbyte(0xdb); /*FISTP [ESP]*/
addbyte(0x1c);
addbyte(0x24);
addbyte(0x08);
addbyte(0xdd); /*FSTP [ESP]*/
addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/
addbyte(0x6d);
addbyte(cpu_state_offset(old_npxc));
addbyte(0x8b); /*MOV EBX, [ESP]*/
addbyte(0x1c);
addbyte(0x24);
CALL_FUNC(x87_fround32);
addbyte(0x89); /*MOV EBX, EAX*/
addbyte(0xc3);
addbyte(0x8b); /*MOV EAX, [ESP+8]*/
addbyte(0x44);
addbyte(0x24);
addbyte(0x08);
return REG_EBX;
}
static void FP_LOAD_REG_INT_Q(int reg, int *host_reg1, int *host_reg2)
@ -2378,34 +2290,29 @@ static void FP_LOAD_REG_INT_Q(int reg, int *host_reg1, int *host_reg2)
addbyte(cpu_state_offset(MM));
addbyte(0xeb); /*JMP done*/
addbyte(4+4+3+5+2+2+4);
addbyte(4+3+3+3+3+4);
addbyte(0xdd); /*FLD ST[EBX*8]*/
addbyte(0x44);
addbyte(0xdd);
addbyte(cpu_state_offset(ST));
addbyte(0x89); /*MOV [ESP+8], EAX*/
addbyte(0x44);
addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/
addbyte(0x6d);
addbyte(cpu_state_offset(new_npxc));
addbyte(0xdf); /*FISTPQ [ESP]*/
addbyte(0x3c);
addbyte(0x24);
addbyte(0x08);
addbyte(0xdd); /*FSTP [ESP]*/
addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/
addbyte(0x6d);
addbyte(cpu_state_offset(old_npxc));
addbyte(0x8b); /*MOV EBX, [ESP]*/
addbyte(0x1c);
addbyte(0x24);
CALL_FUNC(x87_fround64);
addbyte(0x89); /*MOV EBX, EAX*/
addbyte(0xc3);
addbyte(0x89); /*MOV ECX, EDX*/
addbyte(0xd1);
addbyte(0x8b); /*MOV EAX, [ESP+8]*/
addbyte(0x44);
addbyte(0x8b); /*MOV ECX, 4[ESP]*/
addbyte(0x4c);
addbyte(0x24);
addbyte(0x08);
addbyte(4);
*host_reg1 = REG_EBX;
*host_reg2 = REG_ECX;
@ -2511,31 +2418,9 @@ static void FP_OP_D(int op)
addbyte(0x04);
if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD)
{
addbyte(0x9b); /*FSTCW [ESP+8]*/
addbyte(0xd9);
addbyte(0x7c);
addbyte(0x24);
addbyte(0x08);
addbyte(0x66); /*MOV AX, [ESP+8]*/
addbyte(0x8b);
addbyte(0x44);
addbyte(0x24);
addbyte(0x08);
addbyte(0x66); /*AND AX, ~(3 << 10)*/
addbyte(0x25);
addword(~(3 << 10));
addbyte(0x66); /*OR AX, npxc & (3 << 10)*/
addbyte(0x0d);
addword(cpu_state.npxc & (3 << 10));
addbyte(0x66); /*MOV [ESP+12], AX*/
addbyte(0x89);
addbyte(0x44);
addbyte(0x24);
addbyte(0x0c);
addbyte(0xd9); /*FLDCW [ESP+12]*/
addbyte(0x6c);
addbyte(0x24);
addbyte(0x0c);
addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/
addbyte(0x6d);
addbyte(cpu_state_offset(new_npxc));
}
addbyte(0xdd); /*FLD ST[dst][EBP]*/
addbyte(0x45);
@ -2552,10 +2437,9 @@ static void FP_OP_D(int op)
addbyte(cpu_state_offset(ST[cpu_state.TOP]));
if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD)
{
addbyte(0xd9); /*FLDCW [ESP+8]*/
addbyte(0x6c);
addbyte(0x24);
addbyte(0x08);
addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/
addbyte(0x6d);
addbyte(cpu_state_offset(old_npxc));
}
}
else
@ -2568,31 +2452,9 @@ static void FP_OP_D(int op)
addbyte(0x24);
if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD)
{
addbyte(0x9b); /*FSTCW [ESP+8]*/
addbyte(0xd9);
addbyte(0x7c);
addbyte(0x24);
addbyte(0x08);
addbyte(0x66); /*MOV AX, [ESP+8]*/
addbyte(0x8b);
addbyte(0x44);
addbyte(0x24);
addbyte(0x08);
addbyte(0x66); /*AND AX, ~(3 << 10)*/
addbyte(0x25);
addword(~(3 << 10));
addbyte(0x66); /*OR AX, npxc & (3 << 10)*/
addbyte(0x0d);
addword(cpu_state.npxc & (3 << 10));
addbyte(0x66); /*MOV [ESP+12], AX*/
addbyte(0x89);
addbyte(0x44);
addbyte(0x24);
addbyte(0x0c);
addbyte(0xd9); /*FLDCW [ESP+12]*/
addbyte(0x6c);
addbyte(0x24);
addbyte(0x0c);
addbyte(0xd9); /*FLDCW cpu_state.new_npxc*/
addbyte(0x6d);
addbyte(cpu_state_offset(new_npxc));
}
addbyte(0x89); /*MOV [ESP+4], EDX*/
addbyte(0x54);
@ -2616,10 +2478,9 @@ static void FP_OP_D(int op)
addbyte(cpu_state_offset(ST));
if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD)
{
addbyte(0xd9); /*FLDCW [ESP+8]*/
addbyte(0x6c);
addbyte(0x24);
addbyte(0x08);
addbyte(0xd9); /*FLDCW cpu_state.old_npxc*/
addbyte(0x6d);
addbyte(cpu_state_offset(old_npxc));
}
}
}
@ -3226,6 +3087,32 @@ static void FP_COMPARE_REG(int dst, int src)
}
}
static void UPDATE_NPXC(int reg)
{
addbyte(0x66); /*AND cpu_state.new_npxc, ~0xc00*/
addbyte(0x81);
addbyte(0x65);
addbyte(cpu_state_offset(new_npxc));
addword(~0xc00);
if (reg)
{
addbyte(0x66); /*AND reg, 0xc00*/
addbyte(0x81);
addbyte(0xe0 | reg);
addword(0xc00);
}
else
{
addbyte(0x66); /*AND AX, 0xc00*/
addbyte(0x25);
addword(0xc00);
}
addbyte(0x66); /*OR cpu_state.new_npxc, reg*/
addbyte(0x09);
addbyte(0x45 | (reg << 3));
addbyte(cpu_state_offset(new_npxc));
}
static int ZERO_EXTEND_W_B(int reg)
{
addbyte(0x0f); /*MOVZX regl, regb*/

@ -563,6 +563,11 @@ void codegen_init()
mem_store_addr_ea_b = gen_MEM_STORE_ADDR_EA_B();
block_pos = 1024;
mem_store_addr_ea_q = gen_MEM_STORE_ADDR_EA_Q();
asm(
"fstcw %0\n"
: "=m" (cpu_state.old_npxc)
);
}
void codegen_reset()

@ -91,7 +91,7 @@ void disc_load(int drive, char *fn)
p = get_extension(fn);
if (!p) return;
// setejecttext(drive, fn);
pclog("Loading :%i %s %s\n", drive, fn,p);
// pclog("Loading :%i %s %s\n", drive, fn,p);
f = fopen(fn, "rb");
if (!f) return;
fseek(f, -1, SEEK_END);
@ -101,7 +101,7 @@ void disc_load(int drive, char *fn)
{
if (!strcasecmp(p, loaders[c].ext) && (size == loaders[c].size || loaders[c].size == -1))
{
pclog("Loading as %s\n", p);
// pclog("Loading as %s (UI write protected = %s)\n", p, ui_writeprot[drive] ? "yes" : "no");
driveloaders[drive] = c;
loaders[c].load(drive, fn);
drive_empty[drive] = 0;

@ -108,3 +108,34 @@ extern int drive_type[2];
#define BYTE_TYPE_AM 0x03
#define BYTE_TYPE_DATA 0x04
#define BYTE_TYPE_CRC 0x05
typedef union {
uint16_t word;
uint8_t bytes[2];
} crc_t;
void disc_calccrc(int drive, uint8_t byte, crc_t *crc_var);
typedef struct
{
uint8_t (*disk_flags)(int drive);
uint8_t (*side_flags)(int drive);
void (*writeback)(int drive);
void (*set_sector)(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n);
uint8_t (*read_data)(int drive, int side, uint16_t pos);
void (*write_data)(int drive, int side, uint16_t pos, uint8_t data);
int (*format_conditions)(int drive);
uint8_t check_crc;
} d86f_handler_t;
d86f_handler_t d86f_handler[2];
void d86f_common_handlers(int drive);
int d86f_is_40_track(int drive);
uint8_t* d86f_track_data(int drive, int side);
uint8_t* d86f_track_layout(int drive, int side);
uint16_t d86f_prepare_pretrack(int drive, int side, int iso, int write_data);
uint16_t d86f_prepare_sector(int drive, int side, int pos, uint8_t *id_buf, uint8_t *data_buf, int data_len, int write_data, int gap2, int gap3);

File diff suppressed because it is too large Load Diff

@ -23,7 +23,7 @@ static struct
} img[2];
static uint8_t xdf_track0[3][3];
static uint8_t xdf_spt[3];
static uint8_t xdf_spt[3] = { 6, 8, 8 };
static uint8_t xdf_map[3][24][3];
static uint16_t xdf_track0_layout[3][92] = { { 0x8100, 0x8200, 0x8300, 0x8400, 0x8500, 0x8600, 0x8700, 0x8800,
0x8101, 0x8201, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600,
@ -49,6 +49,7 @@ static uint16_t xdf_track0_layout[3][92] = { { 0x8100, 0x8200, 0x8300, 0x8400, 0
0x9901, 0x9A01, 0x9B01, 0x9C01, 0x9D01, 0x9E01, 0x9F01, 0xA001,
0xA101, 0xA201, 0xA301, 0xA401 },
};
static uint16_t xdf_sector_pos[256];
/* First dimension is possible sector sizes (0 = 128, 7 = 16384), second is possible bit rates (250/360, 250, 300, 500/360, 500, 1000). */
/* Disks formatted at 250 kbps @ 360 RPM can be read with a 360 RPM single-RPM 5.25" drive by setting the rate to 250 kbps.
@ -152,46 +153,9 @@ static void add_to_map(uint8_t *arr, uint8_t p1, uint8_t p2, uint8_t p3)
static int xdf_maps_initialized = 0;
static void initialize_xdf_maps()
{
// XDF 5.25" 2HD
/* Adds, in this order: sectors per FAT, sectors per each side of track 0, difference between that and virtual sector number specified in BPB. */
add_to_map(xdf_track0[0], 9, 17, 2);
xdf_spt[0] = 3;
/* Adds, in this order: side, sequential order (not used in PCem), sector size. */
add_to_map(xdf_map[0][0], 0, 0, 3);
add_to_map(xdf_map[0][1], 0, 2, 6);
add_to_map(xdf_map[0][2], 1, 0, 2);
add_to_map(xdf_map[0][3], 0, 1, 2);
add_to_map(xdf_map[0][4], 1, 2, 6);
add_to_map(xdf_map[0][5], 1, 1, 3);
// XDF 3.5" 2HD
add_to_map(xdf_track0[1], 11, 19, 4);
xdf_spt[1] = 4;
add_to_map(xdf_map[1][0], 0, 0, 3);
add_to_map(xdf_map[1][1], 0, 2, 4);
add_to_map(xdf_map[1][2], 1, 3, 6);
add_to_map(xdf_map[1][3], 0, 1, 2);
add_to_map(xdf_map[1][4], 1, 1, 2);
add_to_map(xdf_map[1][5], 0, 3, 6);
add_to_map(xdf_map[1][6], 1, 0, 4);
add_to_map(xdf_map[1][7], 1, 2, 3);
// XDF 3.5" 2ED
add_to_map(xdf_track0[2], 22, 37, 9);
xdf_spt[2] = 4;
add_to_map(xdf_map[2][0], 0, 0, 3);
add_to_map(xdf_map[2][1], 0, 1, 4);
add_to_map(xdf_map[2][2], 0, 2, 5);
add_to_map(xdf_map[2][3], 0, 3, 7);
add_to_map(xdf_map[2][4], 1, 0, 3);
add_to_map(xdf_map[2][5], 1, 1, 4);
add_to_map(xdf_map[2][6], 1, 2, 5);
add_to_map(xdf_map[2][7], 1, 3, 7);
xdf_maps_initialized = 1;
}
static uint16_t xdf_trackx_layout[3][8] = { { 0x8300, 0x8600, 0x8201, 0x8200, 0x8601, 0x8301},
{ 0x8300, 0x8400, 0x8601, 0x8200, 0x8201, 0x8600, 0x8401, 0x8301},
{ 0x8300, 0x8400, 0x8500, 0x8700, 0x8301, 0x8401, 0x8501, 0x8701} };
void img_load(int drive, char *fn)
{
@ -208,8 +172,6 @@ void img_load(int drive, char *fn)
char ext[4];
int fdi;
if (!xdf_maps_initialized) initialize_xdf_maps(); /* Initialize XDF maps, will need them to properly register sectors in tracks. */
ext[0] = fn[strlen(fn) - 3] | 0x60;
ext[1] = fn[strlen(fn) - 2] | 0x60;
ext[2] = fn[strlen(fn) - 1] | 0x60;
@ -224,6 +186,10 @@ void img_load(int drive, char *fn)
return;
writeprot[drive] = 1;
}
if (ui_writeprot[drive])
{
writeprot[drive] = 1;
}
fwriteprot[drive] = writeprot[drive];
if (strcmp(ext, "fdi") == 0)
@ -432,7 +398,6 @@ void img_load(int drive, char *fn)
{
case 19: /* High density XDF @ 360 rpm */
img[drive].xdf_type = 1;
raw_tsize[drive] = 10521; /* Rotate at 356.4 RPM in order to fit the data. */
break;
case 23: /* High density XDF @ 300 rpm */
img[drive].xdf_type = 2;
@ -495,12 +460,6 @@ void img_load(int drive, char *fn)
img[drive].byte_period = 16;
}
if (img[drive].xdf_type) /* In case of XDF-formatted image, write-protect */
{
writeprot[drive] = 1;
fwriteprot[drive] = writeprot[drive];
}
drives[drive].seek = img_seek;
drives[drive].readsector = disc_sector_readsector;
drives[drive].writesector = disc_sector_writesector;
@ -546,9 +505,7 @@ void img_seek(int drive, int track)
int side;
int current_xdft = img[drive].xdf_type - 1;
uint8_t sectors_fat, effective_sectors, sector_gap; /* Needed for XDF */
int sector, current_pos, sh, sr, sside, total;
int sector, current_pos, sh, sr, sn, sside, total, max_pos;
if (!img[drive].f)
return;
@ -579,14 +536,11 @@ void img_seek(int drive, int track)
if (img[drive].xdf_type)
{
sectors_fat = xdf_track0[current_xdft][0];
effective_sectors = xdf_track0[current_xdft][1];
sector_gap = xdf_track0[current_xdft][2];
total = img[drive].sectors;
max_pos = (img[drive].sectors * 512);
if (!track)
{
/* Track 0, register sectors according to track 0 layout. */
total = img[drive].sectors;
current_pos = 0;
for (sector = 0; sector < (total << 1); sector++)
{
@ -596,6 +550,7 @@ void img_seek(int drive, int track)
{
sh = xdf_track0_layout[current_xdft][sector] & 0xFF;
sr = xdf_track0_layout[current_xdft][sector] >> 8;
xdf_sector_pos[(sh << 8) | sr] = current_pos;
disc_sector_add(drive, sh, track, sh, sr, 2,
img[drive].bitcell_period_300rpm,
&img[drive].track_data[sside][current_pos]);
@ -605,25 +560,19 @@ void img_seek(int drive, int track)
else
{
/* Non-zero track, this will have sectors of various sizes. */
/* First, the "Side 0" buffer. */
total = xdf_spt[current_xdft] >> 1;
current_pos = 0;
for (sector = 0; sector < xdf_spt[current_xdft]; sector++)
for (sector = 0; sector < xdf_spt[current_xdft]; sector++)
{
disc_sector_add(drive, xdf_map[current_xdft][sector][0], track, xdf_map[current_xdft][sector][0],
xdf_map[current_xdft][sector][2] + 0x80, xdf_map[current_xdft][sector][2],
img[drive].bitcell_period_300rpm,
&img[drive].track_data[0][current_pos]);
current_pos += (128 << xdf_map[current_xdft][sector][2]);
}
/* Then, the "Side 1" buffer. */
current_pos = 0;
for (sector = xdf_spt[current_xdft]; sector < (xdf_spt[current_xdft] << 1); sector++)
{
disc_sector_add(drive, xdf_map[current_xdft][sector][0], track, xdf_map[current_xdft][sector][0],
xdf_map[current_xdft][sector][2] + 0x80, xdf_map[current_xdft][sector][2],
img[drive].bitcell_period_300rpm,
&img[drive].track_data[1][current_pos]);
current_pos += (128 << xdf_map[current_xdft][sector][2]);
sside = (sector >= total) ? 1 : 0;
sh = xdf_trackx_layout[current_xdft][sector] & 0xFF;
sr = xdf_trackx_layout[current_xdft][sector] >> 8;
sn = sr & 7;
disc_sector_add(drive, sh, track, sh, sr, sn,
img[drive].bitcell_period_300rpm,
&img[drive].track_data[sside][current_pos]);
current_pos += (128 << sn);
current_pos %= max_pos;
}
}
}
@ -648,19 +597,19 @@ void img_writeback(int drive)
if (!img[drive].f)
return;
if (img[drive].xdf_type)
return; /*Should never happen*/
// if (img[drive].xdf_type)
// return; /*Should never happen*/
if (img[drive].sides == 2)
{
fseek(img[drive].f, img[drive].base + (disc_track[drive] * img[drive].sectors * img[drive].sector_size * 2), SEEK_SET);
fseek(img[drive].f, img[drive].base + (disc_track[drive] * img[drive].sectors * img[drive].sector_size * 2), SEEK_SET);
fwrite(img[drive].track_data[0], img[drive].sectors * img[drive].sector_size, 1, img[drive].f);
fwrite(img[drive].track_data[1], img[drive].sectors * img[drive].sector_size, 1, img[drive].f);
}
else
{
{
fseek(img[drive].f, img[drive].base + (disc_track[drive] * img[drive].sectors * img[drive].sector_size), SEEK_SET);
fwrite(img[drive].track_data[0], img[drive].sectors * img[drive].sector_size, 1, img[drive].f);
fwrite(img[drive].track_data[0], img[drive].sectors * img[drive].sector_size, 1, img[drive].f);
}
}

598
src/disc_img_86box.c Normal file

@ -0,0 +1,598 @@
/* Copyright holders: Sarah Walker, Tenshi
see COPYING for more details
*/
#include "ibm.h"
#include "fdc.h"
#include "fdd.h"
#include "disc.h"
#include "disc_img.h"
#include "disc_sector.h"
static struct
{
FILE *f;
uint8_t track_data[2][50000];
int sectors, tracks, sides;
uint8_t sector_size;
int rate;
int xdf_type; /* 0 = not XDF, 1-5 = one of the five XDF types */
int dmf;
int hole;
int track;
uint32_t base;
uint8_t gap2_size;
uint8_t gap3_size;
uint8_t disk_flags;
uint8_t track_flags;
uint8_t sector_pos_side[2][256];
uint16_t sector_pos[2][256];
uint8_t current_sector_pos_side;
uint16_t current_sector_pos;
} img[2];
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;
/* 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,
0x8101, 0x8201, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600,
0x0700, 0x0800, 0,
0x8301, 0x8401, 0x8501, 0x8601, 0x8701, 0x8801, 0x8901, 0x8A01,
0x8B01, 0x8C01, 0x8D01, 0x8E01, 0x8F01, 0x9001, 0, 0,
0, 0, 0 },
{ 0x8300, 0x8600, 0x8201, 0x8200, 0x8601, 0x8301 }
}, /* 5.25" 2HD */
{ { 0x8100, 0x8200, 0x8300, 0x8400, 0x8500, 0x8600, 0x8700, 0x8800,
0x8900, 0x8A00, 0x8B00, 0x8101, 0x0100, 0x0200, 0x0300, 0x0400,
0x0500, 0x0600, 0x0700, 0x0800, 0, 0, 0,
0x8201, 0x8301, 0x8401, 0x8501, 0x8601, 0x8701, 0x8801, 0x8901,
0x8A01, 0x8B01, 0x8C01, 0x8D01, 0x8E01, 0x8F01, 0, 0,
0, 0, 0, 0x9001, 0x9101, 0x9201, 0x9301 },
{ 0x8300, 0x8400, 0x8601, 0x8200, 0x8201, 0x8600, 0x8401, 0x8301 }
} /* 3.5" 2HD */
};
/* XDF: Layout of the sectors on the disk's track. */
xdf_sector_t xdf_disk_layout[2][2][38] = { { { 0x0100, 0x0200, 0x8100, 0x8800, 0x8200, 0x0300, 0x8300, 0x0400,
0x8400, 0x0500, 0x8500, 0x0600, 0x8600, 0x0700, 0x8700, 0x0800,
0x8D01, 0x8501, 0x8E01, 0x8601, 0x8F01, 0x8701, 0x9001, 0x8801,
0x8101, 0x8901, 0x8201, 0x8A01, 0x8301, 0x8B01, 0x8401, 0x8C01 },
{ 0x8300, 0x8200, 0x8600, 0x8201, 0x8301, 0x8601 }
}, /* 5.25" 2HD */
{ { 0x0100, 0x8A00, 0x8100, 0x8B00, 0x8200, 0x0200, 0x8300, 0x0300,
0x8400, 0x0400, 0x8500, 0x0500, 0x8600, 0x0600, 0x8700, 0x0700,
0x8800, 0x0800, 0x8900,
0x9001, 0x8701, 0x9101, 0x8801, 0x9201, 0x8901, 0x9301, 0x8A01,
0x8101, 0x8B01, 0x8201, 0x8C01, 0x8301, 0x8D01, 0x8401, 0x8E01,
0x8501, 0x8F01, 0x8601 },
{ 0x8300, 0x8200, 0x8400, 0x8600, 0x8401, 0x8201, 0x8301, 0x8601 },
}, /* 3.5" 2HD */
};
/* First dimension is possible sector sizes (0 = 128, 7 = 16384), second is possible bit rates (250/360, 250, 300, 500/360, 500, 1000). */
/* Disks formatted at 250 kbps @ 360 RPM can be read with a 360 RPM single-RPM 5.25" drive by setting the rate to 250 kbps.
Disks formatted at 300 kbps @ 300 RPM can be read with any 300 RPM single-RPM drive by setting the rate rate to 300 kbps. */
static uint8_t maximum_sectors[8][6] = { { 26, 31, 38, 53, 64, 118 }, /* 128 */
{ 15, 19, 23, 32, 38, 73 }, /* 256 */
{ 7, 10, 12, 17, 21, 41 }, /* 512 */
{ 3, 5, 6, 9, 11, 22 }, /* 1024 */
{ 2, 2, 3, 4, 5, 11 }, /* 2048 */
{ 1, 1, 1, 2, 2, 5 }, /* 4096 */
{ 0, 0, 0, 1, 1, 3 }, /* 8192 */
{ 0, 0, 0, 0, 0, 1 } }; /* 16384 */
static uint8_t xdf_sectors[8][6] = { { 0, 0, 0, 0, 0, 0 }, /* 128 */
{ 0, 0, 0, 0, 0, 0 }, /* 256 */
{ 0, 0, 0, 19, 23, 0 }, /* 512 */
{ 0, 0, 0, 0, 0, 0 }, /* 1024 */
{ 0, 0, 0, 0, 0, 0 }, /* 2048 */
{ 0, 0, 0, 0, 0, 0 }, /* 4096 */
{ 0, 0, 0, 0, 0, 0 }, /* 8192 */
{ 0, 0, 0, 0, 0, 0 } }; /* 16384 */
static uint8_t xdf_types[8][6] = { { 0, 0, 0, 0, 0, 0 }, /* 128 */
{ 0, 0, 0, 0, 0, 0 }, /* 256 */
{ 0, 0, 0, 1, 2, 0 }, /* 512 */
{ 0, 0, 0, 0, 0, 0 }, /* 1024 */
{ 0, 0, 0, 0, 0, 0 }, /* 2048 */
{ 0, 0, 0, 0, 0, 0 }, /* 4096 */
{ 0, 0, 0, 0, 0, 0 }, /* 8192 */
{ 0, 0, 0, 0, 0, 0 } }; /* 16384 */
static double bit_rates_300[6] = { (250.0 * 300.0) / 360.0, 250.0, 300.0, (500.0 * 300.0) / 360.0, 500.0, 1000.0 };
static uint8_t rates[6] = { 2, 2, 1, 4, 0, 3 };
static uint8_t holes[6] = { 0, 0, 0, 1, 1, 2 };
static 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,
[2][1][10] = 0x32,
[2][1][11] = 0x0C,
[2][1][15] = 0x36,
[2][1][16] = 0x32,
[2][2][8] = 0x58,
[2][2][9] = 0x50,
[2][2][10] = 0x2E,
[2][2][11] = 0x02,
[2][2][21] = 0x1C,
[2][3][4] = 0xF0,
[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
};
/* Needed for formatting! */
int img_realtrack(int drive, int track)
{
if ((img[drive].tracks <= 43) && fdd_doublestep_40(drive))
track /= 2;
return track;
}
void img_writeback(int drive);
static int sector_size_code(int sector_size)
{
switch(sector_size)
{
case 128:
return 0;
case 256:
return 1;
default:
case 512:
return 2;
case 1024:
return 3;
case 2048:
return 4;
case 4096:
return 5;
case 8192:
return 6;
case 16384:
return 7;
}
}
static int img_sector_size_code(int drive)
{
return sector_size_code(img[drive].sector_size);
}
void img_init()
{
memset(img, 0, sizeof(img));
// adl[0] = adl[1] = 0;
}
void d86f_register_img(int drive);
void img_load(int drive, char *fn)
{
int size;
double bit_rate_300;
uint16_t bpb_bps;
uint16_t bpb_total;
uint8_t bpb_mid; /* Media type ID. */
uint8_t bpb_sectors;
uint8_t bpb_sides;
uint32_t bpt;
uint8_t max_spt; /* Used for XDF detection. */
int temp_rate;
char ext[4];
int fdi;
int i;
ext[0] = fn[strlen(fn) - 3] | 0x60;
ext[1] = fn[strlen(fn) - 2] | 0x60;
ext[2] = fn[strlen(fn) - 1] | 0x60;
ext[3] = 0;
writeprot[drive] = 0;
img[drive].f = fopen(fn, "rb+");
if (!img[drive].f)
{
img[drive].f = fopen(fn, "rb");
if (!img[drive].f)
return;
writeprot[drive] = 1;
}
if (ui_writeprot[drive])
{
writeprot[drive] = 1;
}
fwriteprot[drive] = writeprot[drive];
d86f_unregister(drive);
if (strcmp(ext, "fdi") == 0)
{
/* This is a Japanese FDI image, so let's read the header */
pclog("img_load(): File is a Japanese FDI image...\n");
fseek(img[drive].f, 0x10, SEEK_SET);
fread(&bpb_bps, 1, 2, img[drive].f);
fseek(img[drive].f, 0x0C, SEEK_SET);
fread(&size, 1, 4, img[drive].f);
bpb_total = size / bpb_bps;
fseek(img[drive].f, 0x08, SEEK_SET);
fread(&(img[drive].base), 1, 4, img[drive].f);
fseek(img[drive].f, img[drive].base + 0x15, SEEK_SET);
bpb_mid = fgetc(img[drive].f);
if (bpb_mid < 0xF0) bpb_mid = 0xF0;
fseek(img[drive].f, 0x14, SEEK_SET);
bpb_sectors = fgetc(img[drive].f);
fseek(img[drive].f, 0x18, SEEK_SET);
bpb_sides = fgetc(img[drive].f);
fdi = 1;
}
else
{
/* Read the BPB */
pclog("img_load(): File is a raw image...\n");
fseek(img[drive].f, 0x0B, SEEK_SET);
fread(&bpb_bps, 1, 2, img[drive].f);
fseek(img[drive].f, 0x13, SEEK_SET);
fread(&bpb_total, 1, 2, img[drive].f);
fseek(img[drive].f, 0x15, SEEK_SET);
bpb_mid = fgetc(img[drive].f);
fseek(img[drive].f, 0x18, SEEK_SET);
bpb_sectors = fgetc(img[drive].f);
fseek(img[drive].f, 0x1A, SEEK_SET);
bpb_sides = fgetc(img[drive].f);
img[drive].base = 0;
fdi = 0;
fseek(img[drive].f, -1, SEEK_END);
size = ftell(img[drive].f) + 1;
}
img[drive].sides = 2;
img[drive].sector_size = 2;
img[drive].hole = 0;
pclog("BPB reports %i sides and %i bytes per sector\n", bpb_sides, bpb_bps);
if (((bpb_sides < 1) || (bpb_sides > 2) || (bpb_bps < 128) || (bpb_bps > 2048)) && !fdi)
{
/* The BPB is giving us a wacky number of sides and/or bytes per sector, therefore it is most probably
not a BPB at all, so we have to guess the parameters from file size. */
if (size <= (160*1024)) { img[drive].sectors = 8; img[drive].tracks = 40; img[drive].sides = 1; }
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 <= (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*/
else if (size <= 1261568) { img[drive].sectors = 8; img[drive].tracks = 77; img[drive].sector_size = 3; } /*High density 1.25MB Japanese format*/
else if (size <= (0x1A4000-1)) { img[drive].sectors = 18; img[drive].tracks = 80; } /*High density (not supported by Tandy 1000)*/
else if (size <= 1556480) { img[drive].sectors = 19; img[drive].tracks = 80; } /*High density (not supported by Tandy 1000)*/
else if (size <= 1638400) { img[drive].sectors = 10; img[drive].tracks = 80; img[drive].sector_size = 3; } /*High density (not supported by Tandy 1000)*/
else if (size == 1884160) { img[drive].sectors = 23; img[drive].tracks = 80; } /*XDF format - used by OS/2 Warp*/
else if (size <= 2000000) { img[drive].sectors = 21; img[drive].tracks = 80; } /*DMF format - used by Windows 95 - changed by OBattler to 2000000, ie. the real unformatted capacity @ 500 kbps and 300 rpm */
else if (size <= 2949120) { img[drive].sectors = 36; img[drive].tracks = 80; } /*E density*/
else if (size <= 3358720) { img[drive].sectors = 41; img[drive].tracks = 80; } /*E density, maximum possible size*/
else
{
pclog("Image is bigger than can fit on an ED floppy, ejecting...\n");
fclose(img[drive].f);
return;
}
}
else
{
/* The BPB readings appear to be valid, so let's set the values. */
if (fdi)
{
/* The image is a Japanese FDI, therefore we read the number of tracks from the header. */
fseek(img[drive].f, 0x1C, SEEK_SET);
fread(&(img[drive].tracks), 1, 4, img[drive].f);
}
else
{
/* Number of tracks = number of total sectors divided by sides times sectors per track. */
img[drive].tracks = ((uint32_t) bpb_total) / (((uint32_t) bpb_sides) * ((uint32_t) bpb_sectors));
}
/* The rest we just set directly from the BPB. */
img[drive].sectors = bpb_sectors;
img[drive].sides = bpb_sides;
/* The sector size. */
img[drive].sector_size = sector_size_code(bpb_bps);
temp_rate = 0xFF;
}
for (i = 0; i < 6; i++)
{
if ((img[drive].sectors <= maximum_sectors[img[drive].sector_size][i]) || (img[drive].sectors == xdf_sectors[img[drive].sector_size][i]))
{
bit_rate_300 = bit_rates_300[i];
temp_rate = rates[i];
img[drive].disk_flags = holes[i] << 1;
img[drive].xdf_type = (img[drive].sectors == xdf_sectors[img[drive].sector_size][i]) ? xdf_types[img[drive].sector_size][i] : 0;
if ((bit_rate_300 == 500.0) && (img[drive].sectors == 21) && (img[drive].sector_size == 2) && (img[drive].tracks == 80) && (img[drive].sides == 2))
{
/* This is a DMF floppy, set the flag so we know to interleave the sectors. */
img[drive].dmf = 1;
}
else
{
img[drive].dmf = 0;
}
pclog("Image parameters: bit rate 300: %f, temporary rate: %i, hole: %i, XDF type: %i\n", bit_rate_300, temp_rate, img[drive].disk_flags >> 1, img[drive].xdf_type);
break;
}
}
if (temp_rate == 0xFF)
{
pclog("Image is bigger than can fit on an ED floppy, ejecting...\n");
fclose(img[drive].f);
return;
}
img[drive].gap2_size = (temp_rate == 3) ? 41 : 22;
if (img[drive].dmf)
{
img[drive].gap3_size = 8;
}
else
{
img[drive].gap3_size = gap3_sizes[temp_rate][img[drive].sector_size][img[drive].sectors];
}
if (!img[drive].gap3_size)
{
pclog("ERROR: Floppy image of unknown format was inserted into drive %c:!\n", drive + 0x41);
fclose(img[drive].f);
return;
}
if (img[drive].tracks > 43) img[drive].disk_flags |= 1; /* If the image has more than 43 tracks, then the tracks are thin (96 tpi). */
if (img[drive].sides == 2) img[drive].disk_flags |= 8; /* If the has 2 sides, mark it as such. */
img[drive].track_flags = 0x08; /* IMG files are always assumed to be MFM-encoded. */
img[drive].track_flags |= temp_rate & 3; /* Data rate. */
if (temp_rate & 4) img[drive].track_flags |= 0x20; /* RPM. */
pclog("Disk flags: %i, track flags: %i\n", img[drive].disk_flags, img[drive].track_flags);
d86f_register_img(drive);
drives[drive].seek = img_seek;
d86f_common_handlers(drive);
}
void img_close(int drive)
{
if (img[drive].f)
fclose(img[drive].f);
img[drive].f = NULL;
}
#define xdf_img_sector xdf_img_layout[current_xdft][!is_t0][sector]
#define xdf_disk_sector xdf_disk_layout[current_xdft][!is_t0][array_sector]
void img_seek(int drive, int track)
{
int side;
int current_xdft = img[drive].xdf_type - 1;
uint8_t id[4] = { 0, 0, 0, 0 };
int is_t0, sector, current_pos, img_pos, sh, sr, sn, sside, total, max_pos, bytes, array_sector, buf_side, buf_pos;
int ssize = 128 << ((int) img[drive].sector_size);
if (!img[drive].f)
return;
if (d86f_is_40_track(drive) && fdd_doublestep_40(drive))
track /= 2;
img[drive].track = track;
is_t0 = (track == 0) ? 1 : 0;
fseek(img[drive].f, img[drive].base + (track * img[drive].sectors * ssize * img[drive].sides), SEEK_SET);
for (side = 0; side < img[drive].sides; side++)
{
fread(img[drive].track_data[side], img[drive].sectors * ssize, 1, img[drive].f);
}
if (!img[drive].xdf_type)
{
for (side = 0; side < img[drive].sides; side++)
{
current_pos = d86f_prepare_pretrack(drive, side, 0, 1);
for (sector = 0; sector < img[drive].sectors; sector++)
{
sr = img[drive].dmf ? (dmf_r[sector]) : (sector + 1);
id[0] = track;
id[1] = side;
id[2] = sr;
id[3] = img[drive].sector_size;
img[drive].sector_pos_side[side][sr] = side;
img[drive].sector_pos[side][sr] = (sr - 1) * ssize;
// if (img[drive].dmf) pclog("DMF: %i %i %i %i | %i %04X\n", id[0], id[1], id[2], id[3], side, (sr - 1) * ssize);
current_pos = d86f_prepare_sector(drive, side, current_pos, id, &img[drive].track_data[side][(sr - 1) * ssize], ssize, 1, img[drive].gap2_size, img[drive].gap3_size);
}
}
}
else
{
total = img[drive].sectors;
img_pos = 0;
sside = 0;
/* Pass 1, get sector positions in the image. */
for (sector = 0; sector < xdf_logical_sectors[current_xdft][!is_t0]; sector++)
{
if (is_t0)
{
img_pos = (sector % total) << 9;
sside = (sector >= total) ? 1 : 0;
}
if (xdf_img_sector.word)
{
img[drive].sector_pos_side[xdf_img_sector.id.h][xdf_img_sector.id.r] = sside;
img[drive].sector_pos[xdf_img_sector.id.h][xdf_img_sector.id.r] = img_pos;
// pclog("Side: %i, Position: %04X\n", sside, img_pos);
}
if (!is_t0)
{
img_pos += (128 << (xdf_img_sector.id.r & 7));
if (img_pos >= (total << 9)) sside = 1;
img_pos %= (total << 9);
}
}
/* Pass 2, prepare the actual track. */
for (side = 0; side < img[drive].sides; side++)
{
current_pos = d86f_prepare_pretrack(drive, side, 0, 1);
for (sector = 0; sector < xdf_physical_sectors[current_xdft][!is_t0]; sector++)
{
array_sector = (side * xdf_physical_sectors[current_xdft][!is_t0]) + sector;
// pclog("Sector %i, array sector %i\n", sector, array_sector);
buf_side = img[drive].sector_pos_side[xdf_disk_sector.id.h][xdf_disk_sector.id.r];
buf_pos = img[drive].sector_pos[xdf_disk_sector.id.h][xdf_disk_sector.id.r];
// pclog("Side: %i, Position: %04X\n", buf_side, buf_pos);
id[0] = track;
id[1] = xdf_disk_sector.id.h;
id[2] = xdf_disk_sector.id.r;
if (is_t0)
{
id[3] = 2;
// pclog("XDF Track 0: Registering sector: %i %i %i %i\n", id[0], id[1], id[2], id[3]);
current_pos = d86f_prepare_sector(drive, side, current_pos, id, &img[drive].track_data[buf_side][buf_pos], ssize, 1, img[drive].gap2_size, xdf_gap3_sizes[current_xdft][!is_t0]);
}
else
{
id[3] = id[2] & 7;
// pclog("XDF Track X: Registering sector: %i %i %i %i\n", id[0], id[1], id[2], id[3]);
ssize = (128 << id[3]);
current_pos = d86f_prepare_sector(drive, side, xdf_trackx_spos[current_xdft][array_sector], id, &img[drive].track_data[buf_side][buf_pos], ssize, 1, img[drive].gap2_size, xdf_gap3_sizes[current_xdft][!is_t0]);
}
}
}
}
// pclog("Seeked to track: %i\n", img[drive].track);
}
void img_writeback(int drive)
{
int side;
int ssize = 128 << ((int) img[drive].sector_size);
if (!img[drive].f)
return;
fseek(img[drive].f, img[drive].base + (img[drive].track * img[drive].sectors * ssize * img[drive].sides), SEEK_SET);
for (side = 0; side < img[drive].sides; side++)
{
fwrite(img[drive].track_data[side], img[drive].sectors * ssize, 1, img[drive].f);
}
}
int img_xdf_type(int drive)
{
return img[drive].xdf_type;
}
uint8_t img_disk_flags(int drive)
{
return img[drive].disk_flags;
}
uint8_t img_side_flags(int drive)
{
return img[drive].track_flags;
}
void img_set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n)
{
img[drive].current_sector_pos_side = img[drive].sector_pos_side[h][r];
img[drive].current_sector_pos = img[drive].sector_pos[h][r];
return;
}
uint8_t img_poll_read_data(int drive, int side, uint16_t pos)
{
return img[drive].track_data[img[drive].current_sector_pos_side][img[drive].current_sector_pos + pos];
}
void img_poll_write_data(int drive, int side, uint16_t pos, uint8_t data)
{
img[drive].track_data[img[drive].current_sector_pos_side][img[drive].current_sector_pos + pos] = data;
}
int img_format_conditions(int drive)
{
int temp = (fdc_get_format_sectors() == img[drive].sectors);
temp = temp && (fdc_get_format_n() == img[drive].sector_size);
temp = temp && (img[drive].xdf_type == 0);
return temp;
}
void d86f_register_img(int drive)
{
d86f_handler[drive].disk_flags = img_disk_flags;
d86f_handler[drive].side_flags = img_side_flags;
d86f_handler[drive].writeback = img_writeback;
d86f_handler[drive].set_sector = img_set_sector;
d86f_handler[drive].read_data = img_poll_read_data;
d86f_handler[drive].write_data = img_poll_write_data;
d86f_handler[drive].format_conditions = img_format_conditions;
d86f_handler[drive].check_crc = 1;
}

@ -101,6 +101,7 @@ static int get_bitcell_period(int drive)
void disc_sector_readsector(int drive, int sector, int track, int side, int rate, int sector_size)
{
// pclog("disc_sector_readsector: fdc_period=%i img_period=%i rate=%i sector=%i track=%i side=%i\n", fdc_get_bitcell_period(), get_bitcell_period(drive), rate, sector, track, side);
// pclog("disc_sector_readsector: fdc_period=%i img_period=%i rate=%i c=%i h=%i r=%i n=%i\n", fdc_get_bitcell_period(), get_bitcell_period(drive), rate, track, side, sector, sector_size);
disc_sector_track[drive] = track;
disc_sector_side[drive] = side;
@ -120,6 +121,12 @@ void disc_sector_writesector(int drive, int sector, int track, int side, int rat
{
// pclog("disc_sector_writesector: fdc_period=%i img_period=%i rate=%i\n", fdc_get_bitcell_period(), get_bitcell_period(drive), rate);
if (writeprot[drive] || swwp)
{
fdc_writeprotect();
return;
}
disc_sector_track[drive] = track;
disc_sector_side[drive] = side;
disc_sector_drive = drive;
@ -171,8 +178,6 @@ int media_type = 0;
#define GAP3_LEN_VARIABLE 0x1B
int gap3_sizes[3][2] = { {74, 36}, {77, 77}, {60, 60} };
int disc_sector_get_gap3_size(int drive, int side, int track)
{
if (!img_xdf_type(drive))
@ -183,7 +188,7 @@ int disc_sector_get_gap3_size(int drive, int side, int track)
switch (track)
{
case 0:
return gap3_sizes[img_xdf_type(drive) - 1][side];
return 60;
default:
return GAP3_LEN_VARIABLE;
}
@ -333,6 +338,7 @@ int disc_sector_can_format(int drive)
temp = temp && !swwp;
temp = temp && disc_sector_can_read_address(drive);
temp = temp && (fdc_get_format_sectors() == disc_sector_count[drive][disc_sector_side[drive]]);
temp = temp && (!img_xdf_type(drive));
return temp;
}

@ -246,12 +246,23 @@ uint8_t _dma_read(uint32_t addr)
return mem_readb_phys(addr);
}
uint16_t _dma_readw(uint32_t addr)
{
return mem_readw_phys(addr);
}
void _dma_write(uint32_t addr, uint8_t val)
{
mem_writeb_phys(addr, val);
mem_invalidate_range(addr, addr);
}
void _dma_writew(uint32_t addr, uint16_t val)
{
mem_writew_phys(addr, val);
mem_invalidate_range(addr, addr + 1);
}
int dma_channel_read(int channel)
{
uint16_t temp;
@ -300,8 +311,12 @@ int dma_channel_read(int channel)
if ((dma16.mode[channel] & 0xC) != 8)
return DMA_NODATA;
#if 0
temp = _dma_read((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16)) |
(_dma_read((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16) + 1) << 8);
#endif
temp = _dma_readw((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16));
if (dma16.mode[channel] & 0x20) dma16.ac[channel]--;
else dma16.ac[channel]++;
@ -325,6 +340,18 @@ int dma_channel_read(int channel)
}
}
void dma_channel_dump()
{
int i = 0;
FILE *f;
f = fopen("dma.dmp", "wb");
for (i = 0; i < (21 * 512); i++)
{
fputc(mem_readb_phys((dma.page[2] << 16) + dma16.ac[2] + i), f);
}
fclose(f);
}
int dma_channel_write(int channel, uint16_t val)
{
if (dma.command & 0x04)
@ -368,8 +395,12 @@ int dma_channel_write(int channel, uint16_t val)
if ((dma16.mode[channel] & 0xC) != 4)
return DMA_NODATA;
#if 0
_dma_write((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16), val);
_dma_write((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16) + 1, val >> 8);
#endif
_dma_writew((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16), val);
if (dma16.mode[channel]&0x20) dma16.ac[channel]--;
else dma16.ac[channel]++;

@ -14,6 +14,8 @@
extern int64_t motoron;
int ui_writeprot[2] = {0, 0};
static int fdc_reset_stat = 0;
/*FDC*/
typedef struct FDC
@ -66,12 +68,11 @@ typedef struct FDC
int drv2en;
uint8_t fifobuf[16];
int seek_params; /* Needed for relative seek. */
int gap, dtl;
int format_sectors;
int max_track;
int mfm;
} FDC;
static FDC fdc;
@ -102,13 +103,39 @@ void fdc_reset()
// pclog("Reset FDC\n");
}
int fdc_get_drive()
{
return fdc.drive;
}
int fdc_get_bitcell_period();
int fdc_get_perp()
{
if (!AT || fdc.pcjr || fdc.ps1) return 0;
return fdc.perp;
}
int fdc_get_bit_rate();
int fdc_get_gap2(int drive)
{
int auto_gap2 = 22;
if (!AT || fdc.pcjr || fdc.ps1) return 22;
if (fdc.perp & 3)
{
return ((fdc.perp & 3) == 3) ? 41 : 22;
}
else
{
auto_gap2 = (fdc_get_bit_rate() >= 3) ? 41 : 22;
return (fdc.perp & (4 << drive)) ? auto_gap2 : 22;
}
}
int fdc_get_format_n()
{
return fdc.format_n;
@ -116,7 +143,7 @@ int fdc_get_format_n()
int fdc_is_mfm()
{
return (fdc.command & 0x40) ? 1 : 0;
return fdc.mfm ? 1 : 0;
}
double fdc_get_hut()
@ -371,7 +398,7 @@ void fdc_update_rate(int drive)
}
fdc.bitcell_period = 1000000 / bit_rate*2; /*Bitcell period in ns*/
pclog("fdc_update_rate: rate=%i bit_rate=%i bitcell_period=%i\n", fdc.rate, bit_rate, fdc.bitcell_period);
// pclog("fdc_update_rate: rate=%i bit_rate=%i bitcell_period=%i\n", fdc.rate, bit_rate, fdc.bitcell_period);
}
int fdc_get_bit_rate()
@ -506,15 +533,18 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
disctime = 128 * (1 << TIMER_SHIFT);
timer_update_outstanding();
discint=-1;
fdc.perp &= 0xfc;
fdc_reset();
}
timer_process();
motoron = (val & 0xf0) ? 1 : 0;
timer_update_outstanding();
fdc.drive = val & 3;
disc_drivesel = fdc.drive & 1;
disc_set_drivesel(fdc.drive & 1);
}
fdc.dor=val;
// printf("DOR now %02X\n",val);
// printf("DOR now %02X\n",val);
return;
case 3:
/* TDR */
@ -531,6 +561,7 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
disctime = 128 * (1 << TIMER_SHIFT);
timer_update_outstanding();
discint=-1;
fdc.perp &= 0xfc;
fdc_reset();
}
return;
@ -575,6 +606,7 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc.ptot=8;
fdc.stat=0x90;
fdc.pos=0;
fdc.mfm=(fdc.command&0x40)?1:0;
break;
case 3: /*Specify*/
fdc.pnum=0;
@ -592,6 +624,7 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc.ptot=8;
fdc.stat=0x90;
fdc.pos=0;
fdc.mfm=(fdc.command&0x40)?1:0;
// readflash=1;
break;
case 6: /*Read data*/
@ -599,6 +632,7 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc.ptot=8;
fdc.stat=0x90;
fdc.pos=0;
fdc.mfm=(fdc.command&0x40)?1:0;
break;
case 7: /*Recalibrate*/
fdc.pnum=0;
@ -619,6 +653,7 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc.ptot=1;
fdc.stat=0x90;
fdc.pos=0;
fdc.mfm=(fdc.command&0x40)?1:0;
break;
case 0x0d: /*Format track*/
fdc.pnum=0;
@ -626,6 +661,7 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc.stat=0x90;
fdc.pos=0;
fdc.format_state = 0;
fdc.mfm=(fdc.command&0x40)?1:0;
break;
case 15: /*Seek*/
fdc.pnum=0;
@ -645,6 +681,7 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc_callback();
break;
case 0x12: /*Set perpendicular mode*/
if (!AT || fdc.pcjr || fdc.ps1) goto bad_command;
fdc.pnum=0;
fdc.ptot=1;
fdc.stat=0x90;
@ -739,8 +776,16 @@ bad_command:
case 0x12:
fdc.stat=0x80;
fdc.perp = fdc.params[0];
pclog("PERPENDICULAR: Set to: %02X\n", fdc.perp);
if (fdc.params[0] & 0x80)
{
fdc.perp = fdc.params[0] & 0x3f;
}
else
{
fdc.perp &= 0xfc;
fdc.perp |= (fdc.params[0] & 0x03);
}
// pclog("PERPENDICULAR: Set to: %02X\n", fdc.perp);
disctime = 0;
return;
@ -822,7 +867,7 @@ bad_command:
fdc.gap = fdc.params[3];
fdc.dtl = 4000000;
fdc.format_sectors = fdc.params[2];
pclog("Formatting with %i sectors per track\n", fdc.format_sectors);
// pclog("Formatting with %i sectors per track\n", fdc.format_sectors);
fdc.format_n = fdc.params[1];
fdc.format_state = 1;
fdc.pos = 0;
@ -834,9 +879,9 @@ bad_command:
fdc.head = (fdc.params[0] & 4) ? 1 : 0;
fdd_set_head(fdc.drive, (fdc.params[0] & 4) ? 1 : 0);
disctime = 0;
if (fdc.seek_params & 0x80)
if (fdc.command & 0x80)
{
if (fdc.seek_params & 0x40)
if (fdc.command & 0x40)
{
/* Relative seek inwards. */
fdc_seek(fdc.drive, fdc.params[1]);
@ -846,12 +891,13 @@ bad_command:
/* Relative seek outwards. */
fdc_seek(fdc.drive, -fdc.params[1]);
}
disctime = ((int) fdc.params[1]) * 10 * TIMER_USEC;
}
else
{
fdc_seek(fdc.drive, fdc.params[1] - fdc.track[fdc.drive]);
disctime = ((int) (fdc.params[1] - fdc.track[fdc.drive])) * 10 * TIMER_USEC;
}
disctime = 790 * TIMER_USEC;
fdc.st0 &= 0x30;
break;
@ -1130,7 +1176,7 @@ void fdc_callback()
case 7: /*Recalibrate*/
fdc.track[fdc.drive]=0;
// if (!driveempty[fdc.dor & 1]) discchanged[fdc.dor & 1] = 0;
if (fdc.drive <= 1)
if (fdc.params[0] <= 1)
fdc.st0 = 0x20 | (fdc.params[0] & 3) | (fdd_get_head(fdc.drive ^ fdd_swap)?4:0);
else
fdc.st0 = 0x68 | (fdc.params[0] & 3) | (fdd_get_head(fdc.drive ^ fdd_swap)?4:0);
@ -1147,9 +1193,15 @@ void fdc_callback()
fdc.stat = (fdc.stat & 0xf) | 0xd0;
if (fdc_reset_stat)
{
disc_stop(4 - fdc_reset_stat);
fdc.res[9] = 0xc0 | (4 - fdc_reset_stat) | (fdd_get_head(fdc.drive ^ fdd_swap) ? 4 : 0);
}
else
{
disc_stop(fdc.drive);
fdc.res[9] = fdc.st0;
}
fdc.res[10] = fdc.track[fdc.drive];
if (!fdc_reset_stat)
fdc.st0 = 0x80;
@ -1198,7 +1250,7 @@ void fdc_callback()
fdc.track[fdc.drive]=fdc.params[1];
// if (!driveempty[fdc.dor & 1]) discchanged[fdc.dor & 1] = 0;
// printf("Seeked to track %i %i\n",fdc.track[fdc.drive], fdc.drive);
if (fdc.drive <= 1)
if (fdc.params[0] <= 1)
fdc.st0 = 0x20 | (fdc.params[0] & 3) | (fdd_get_head(fdc.drive ^ fdd_swap)?4:0);
else
fdc.st0 = 0x68 | (fdc.params[0] & 3) | (fdd_get_head(fdc.drive ^ fdd_swap)?4:0);
@ -1232,16 +1284,6 @@ void fdc_callback()
disctime = 0;
return;
#if 0
case 0x12:
fdc.perp = fdc.params[0];
pclog("PERPENDICULAR: Set to: %02X\n", fdc.perp);
fdc.stat = 0x80;
disctime = 0;
// picint(0x40);
return;
#endif
case 0x13: /*Configure*/
fdc.config = fdc.params[1];
fdc.pretrk = fdc.params[2];
@ -1550,6 +1592,7 @@ void fdc_add()
fdc.pcjr = 0;
fdc.ps1 = 0;
fdc.max_track = 79;
fdc.perp = 0;
}
void fdc_add_for_superio()
@ -1567,6 +1610,7 @@ void fdc_add_pcjr()
fdc.pcjr = 1;
fdc.ps1 = 0;
fdc.max_track = 79;
fdc.perp = 0;
}
void fdc_remove()

@ -31,6 +31,7 @@ void fdc_update_densel_force(int densel_force);
void fdc_update_drvrate(int drive, int drvrate);
void fdc_update_drv2en(int drv2en);
int fdc_get_drive();
int fdc_get_perp();
int fdc_get_format_n();
int fdc_is_mfm();
@ -39,6 +40,7 @@ double fdc_get_hlt();
void fdc_request_next_sector_id();
void fdc_stop_id_request();
int fdc_get_gap();
int fdc_get_gap2(int drive);
int fdc_get_dtl();
int fdc_get_format_sectors();

@ -167,6 +167,8 @@ struct
uint16_t MM_w4[8];
MMX_REG MM[8];
uint16_t old_npxc, new_npxc;
} cpu_state;
#define cycles cpu_state._cycles
@ -575,6 +577,8 @@ extern uint32_t atapi_get_cd_volume(int channel);
extern int ide_ter_enabled;
extern int ui_writeprot[2];
void pclog(const char *format, ...);
extern int nmi;

@ -1552,6 +1552,16 @@ uint8_t mem_readb_phys(uint32_t addr)
return 0xff;
}
uint16_t mem_readw_phys(uint32_t addr)
{
mem_logical_addr = 0xffffffff;
if (_mem_read_w[addr >> 14])
return _mem_read_w[addr >> 14](addr, _mem_priv_r[addr >> 14]);
return 0xff;
}
void mem_writeb_phys(uint32_t addr, uint8_t val)
{
mem_logical_addr = 0xffffffff;
@ -1560,6 +1570,14 @@ void mem_writeb_phys(uint32_t addr, uint8_t val)
_mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]);
}
void mem_writew_phys(uint32_t addr, uint16_t val)
{
mem_logical_addr = 0xffffffff;
if (_mem_write_w[addr >> 14])
_mem_write_w[addr >> 14](addr, val, _mem_priv_w[addr >> 14]);
}
uint8_t mem_read_ram(uint32_t addr, void *priv)
{
// if (addr >= 0xc0000 && addr < 0x0c8000) pclog("Read RAMb %08X\n", addr);

@ -96,6 +96,7 @@ void fatal(const char *format, ...)
va_end(ap);
fflush(stdout);
savenvr();
saveconfig();
dumppic();
dumpregs();
fflush(stdout);
@ -360,6 +361,7 @@ void resetpc_cad()
void resetpchard()
{
savenvr();
saveconfig();
device_close_all();
device_init();
@ -618,13 +620,18 @@ void loadconfig(char *fn)
video_speed = config_get_int(NULL, "video_speed", 3);
sound_card_current = config_get_int(NULL, "sndcard", SB2);
// d86f_unregister(0);
// d86f_unregister(1);
p = (char *)config_get_string(NULL, "disc_a", "");
if (p) strcpy(discfns[0], p);
else strcpy(discfns[0], "");
ui_writeprot[0] = config_get_int(NULL, "disc_a_writeprot", 0);
p = (char *)config_get_string(NULL, "disc_b", "");
if (p) strcpy(discfns[1], p);
else strcpy(discfns[1], "");
ui_writeprot[1] = config_get_int(NULL, "disc_b_writeprot", 0);
mem_size = config_get_int(NULL, "mem_size", 4096);
if (mem_size < (models[model].is_at ? models[model].min_ram*1024 : models[model].min_ram))
@ -746,7 +753,9 @@ void saveconfig()
config_set_int(NULL, "cache", cache);
config_set_int(NULL, "cga_composite", cga_comp);
config_set_string(NULL, "disc_a", discfns[0]);
config_set_int(NULL, "disc_a_writeprot", ui_writeprot[0]);
config_set_string(NULL, "disc_b", discfns[1]);
config_set_int(NULL, "disc_b_writeprot", ui_writeprot[1]);
config_set_int(NULL, "mem_size", mem_size);
config_set_int(NULL, "cdrom_drive", cdrom_drive);
config_set_int(NULL, "cdrom_enabled", cdrom_enabled);

@ -19,9 +19,11 @@ BEGIN
POPUP "&Disc"
BEGIN
MENUITEM "Change drive &A:...", IDM_DISC_A
MENUITEM "Change drive A (&Write-protected):...", IDM_DISC_A_WP
MENUITEM "Change drive &B:...", IDM_DISC_B
MENUITEM "Change drive B (W&rite-protected):...", IDM_DISC_B_WP
MENUITEM "&Eject drive A:", IDM_EJECT_A
MENUITEM "Eject drive B:", IDM_EJECT_B
MENUITEM "E&ject drive B:", IDM_EJECT_B
MENUITEM "&Configure hard discs...",IDM_HDCONF
END
POPUP "&Settings"

@ -33,22 +33,24 @@ void pc87306_gpio_write(uint16_t port, uint8_t val, void *priv)
uint8_t uart_int1()
{
return ((pc87306_regs[0x1C] >> 2) & 1) ? 3 : 4;
return ((pc87306_regs[0x1C] >> 2) & 1) ? 4 : 3;
}
uint8_t uart_int2()
{
return ((pc87306_regs[0x1C] >> 6) & 1) ? 3 : 4;
return ((pc87306_regs[0x1C] >> 6) & 1) ? 4 : 3;
}
uint8_t uart1_int()
{
return (pc87306_regs[0x1C] & 1) ? uart_int1() : 4;
temp = ((pc87306_regs[1] >> 2) & 1) ? 3 : 4; /* 0 = IRQ 4, 1 = IRQ 3 */
return (pc87306_regs[0x1C] & 1) ? uart_int1() : temp;
}
uint8_t uart2_int()
{
return (pc87306_regs[0x1C] & 1) ? uart_int2() : 3;
temp = ((pc87306_regs[1] >> 4) & 1) ? 3 : 4; /* 0 = IRQ 4, 1 = IRQ 3 */
return (pc87306_regs[0x1C] & 1) ? uart_int2() : temp;
}
void serial1_handler()
@ -178,7 +180,7 @@ process_value:
if (val & 2)
{
serial1_handler();
if (mouse_always_serial) mouse_serial_init();
// if (mouse_always_serial) mouse_serial_init();
}
if (val & 4) serial2_handler();
@ -218,7 +220,7 @@ process_value:
if (pc87306_regs[0] & 2)
{
serial1_handler();
if (mouse_always_serial) mouse_serial_init();
// if (mouse_always_serial) mouse_serial_init();
}
if (pc87306_regs[0] & 4) serial2_handler();
break;
@ -237,7 +239,7 @@ process_value:
if (pc87306_regs[0] & 2)
{
serial1_handler();
if (mouse_always_serial) mouse_serial_init();
// if (mouse_always_serial) mouse_serial_init();
}
if (pc87306_regs[0] & 4) serial2_handler();
}

@ -519,6 +519,7 @@ void piix_init(int card)
card_piix_ide[0x0d] = 0x00;
card_piix_ide[0x0e] = 0x00;
card_piix_ide[0x20] = 0x01; card_piix_ide[0x21] = card_piix_ide[0x22] = card_piix_ide[0x23] = 0x00; /*Bus master interface base address*/
card_piix_ide[0x3C] = 14; /* Default IRQ */
card_piix_ide[0x40] = card_piix_ide[0x41] = 0x00;
card_piix_ide[0x42] = card_piix_ide[0x43] = 0x00;

@ -10,6 +10,8 @@
#define IDM_EJECT_A 40012
#define IDM_EJECT_B 40013
#define IDM_HDCONF 40014
#define IDM_DISC_A_WP 40015
#define IDM_DISC_B_WP 40016
#define IDM_CONFIG 40020
#define IDM_CONFIG_LOAD 40021
#define IDM_CONFIG_SAVE 40022

@ -805,6 +805,7 @@ int WINAPI WinMain (HINSTANCE hThisInstance,
// pclog("Quited? %i\n",quited);
// pclog("Closepc\n");
savenvr();
saveconfig();
if (save_window_pos && window_remember)
saveconfig();
closepc();
@ -974,6 +975,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
pause=1;
Sleep(100);
savenvr();
saveconfig();
resetpc();
pause=0;
break;
@ -982,6 +984,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
pause=1;
Sleep(100);
savenvr();
saveconfig();
resetpchard();
pause=0;
break;
@ -989,6 +992,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
pause=1;
Sleep(100);
savenvr();
saveconfig();
resetpc_cad();
pause=0;
break;
@ -996,17 +1000,21 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
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;*.XDF;*.VFD)\0*.12;*.144;*.360;*.720;*.86F;*.DSK;*.IMG;*.IMA;*.FDI;*.FLP;*.XDF;*.VFD\0All files (*.*)\0*.*\0",discfns[0]))
{
disc_close(0);
ui_writeprot[0] = (LOWORD(wParam) == IDM_DISC_A_WP) ? 1 : 0;
disc_load(0, openfilestring);
saveconfig();
}
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;*.XDF;*.VFD)\0*.12;*.144;*.360;*.720;*.86F;*.DSK;*.IMG;*.IMA;*.FDI;*.FLP;*.XDF;*.VFD\0All files (*.*)\0*.*\0",discfns[1]))
{
disc_close(1);
ui_writeprot[1] = (LOWORD(wParam) == IDM_DISC_B_WP) ? 1 : 0;
disc_load(1, openfilestring);
saveconfig();
}

@ -32,6 +32,7 @@ static int opFINIT(uint32_t fetchdat)
FP_ENTER();
cpu_state.pc++;
cpu_state.npxc = 0x37F;
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00);
cpu_state.npxs = 0;
*(uint64_t *)cpu_state.tag = 0x0303030303030303ll;
cpu_state.TOP = 0;
@ -96,6 +97,7 @@ static int FSTOR()
case 0x000: /*16-bit real mode*/
case 0x001: /*16-bit protected mode*/
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00);
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+2);
x87_settag(readmemw(easeg, cpu_state.eaaddr+4));
cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
@ -104,6 +106,7 @@ static int FSTOR()
case 0x100: /*32-bit real mode*/
case 0x101: /*32-bit protected mode*/
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00);
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+4);
x87_settag(readmemw(easeg, cpu_state.eaaddr+8));
cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
@ -676,6 +679,7 @@ static int FLDENV()
case 0x000: /*16-bit real mode*/
case 0x001: /*16-bit protected mode*/
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00);
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+2);
x87_settag(readmemw(easeg, cpu_state.eaaddr+4));
cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
@ -683,6 +687,7 @@ static int FLDENV()
case 0x100: /*32-bit real mode*/
case 0x101: /*32-bit protected mode*/
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00);
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+4);
x87_settag(readmemw(easeg, cpu_state.eaaddr+8));
cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
@ -716,6 +721,7 @@ static int opFLDCW_a16(uint32_t fetchdat)
tempw = geteaw();
if (cpu_state.abrt) return 1;
cpu_state.npxc = tempw;
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00);
CLOCK_CYCLES(4);
return 0;
}
@ -728,6 +734,7 @@ static int opFLDCW_a32(uint32_t fetchdat)
tempw = geteaw();
if (cpu_state.abrt) return 1;
cpu_state.npxc = tempw;
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00);
CLOCK_CYCLES(4);
return 0;
}