Another major cleanup - folders for cdrom and floppy, renamed disc to floppy, renamed SuperIO stuff, others as needed.
This commit is contained in:
2262
src/floppy/fdc.c
Normal file
2262
src/floppy/fdc.c
Normal file
File diff suppressed because it is too large
Load Diff
92
src/floppy/fdc.h
Normal file
92
src/floppy/fdc.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the NEC uPD-765 and compatible floppy disk
|
||||
* controller.
|
||||
*
|
||||
* Version: @(#)fdc.h 1.0.2 2017/09/03
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
*/
|
||||
#ifndef EMU_FDC_H
|
||||
# define EMU_FDC_H
|
||||
|
||||
|
||||
extern void fdc_init(void);
|
||||
extern void fdc_add(void);
|
||||
extern void fdc_add_for_superio(void);
|
||||
extern void fdc_add_pcjr(void);
|
||||
extern void fdc_add_tandy(void);
|
||||
extern void fdc_remove(void);
|
||||
extern void fdc_reset(void);
|
||||
extern void fdc_poll(void);
|
||||
extern void fdc_abort(void);
|
||||
extern void fdc_floppychange_clear(int drive);
|
||||
extern void fdc_set_dskchg_activelow(void);
|
||||
extern void fdc_3f1_enable(int enable);
|
||||
extern void fdc_set_ps1(void);
|
||||
extern int fdc_get_bit_rate(void);
|
||||
extern int fdc_get_bitcell_period(void);
|
||||
|
||||
/* A few functions to communicate between Super I/O chips and the FDC. */
|
||||
extern void fdc_update_is_nsc(int is_nsc);
|
||||
extern void fdc_update_max_track(int max_track);
|
||||
extern void fdc_update_enh_mode(int enh_mode);
|
||||
extern int fdc_get_rwc(int drive);
|
||||
extern void fdc_update_rwc(int drive, int rwc);
|
||||
extern int fdc_get_boot_drive(void);
|
||||
extern void fdc_update_boot_drive(int boot_drive);
|
||||
extern void fdc_update_densel_polarity(int densel_polarity);
|
||||
extern uint8_t fdc_get_densel_polarity(void);
|
||||
extern void fdc_update_densel_force(int densel_force);
|
||||
extern void fdc_update_drvrate(int drive, int drvrate);
|
||||
extern void fdc_update_drv2en(int drv2en);
|
||||
|
||||
extern void fdc_noidam(void);
|
||||
extern void fdc_nosector(void);
|
||||
extern void fdc_nodataam(void);
|
||||
extern void fdc_cannotformat(void);
|
||||
extern void fdc_wrongcylinder(void);
|
||||
extern void fdc_badcylinder(void);
|
||||
|
||||
extern sector_id_t fdc_get_read_track_sector(void);
|
||||
extern int fdc_get_compare_condition(void);
|
||||
extern int fdc_is_deleted(void);
|
||||
extern int fdc_is_sk(void);
|
||||
extern void fdc_set_wrong_am(void);
|
||||
extern int fdc_get_drive(void);
|
||||
extern int fdc_get_perp(void);
|
||||
extern int fdc_get_format_n(void);
|
||||
extern int fdc_is_mfm(void);
|
||||
extern double fdc_get_hut(void);
|
||||
extern double fdc_get_hlt(void);
|
||||
extern void fdc_request_next_sector_id(void);
|
||||
extern void fdc_stop_id_request(void);
|
||||
extern int fdc_get_gap(void);
|
||||
extern int fdc_get_gap2(int drive);
|
||||
extern int fdc_get_dtl(void);
|
||||
extern int fdc_get_format_sectors(void);
|
||||
|
||||
extern void fdc_finishcompare(int satisfying);
|
||||
extern void fdc_finishread(void);
|
||||
extern void fdc_sector_finishcompare(int satisfying);
|
||||
extern void fdc_sector_finishread(void);
|
||||
extern void fdc_track_finishread(int condition);
|
||||
extern int fdc_is_verify(void);
|
||||
|
||||
extern int real_drive(int drive);
|
||||
extern void fdc_overrun(void);
|
||||
extern void fdc_set_base(int base, int super_io);
|
||||
extern int fdc_ps1_525(void);
|
||||
extern void fdc_hard_reset(void);
|
||||
|
||||
|
||||
#endif /*EMU_FDC_H*/
|
||||
358
src/floppy/fdd.c
Normal file
358
src/floppy/fdd.c
Normal file
@@ -0,0 +1,358 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the floppy drive emulation.
|
||||
*
|
||||
* Version: @(#)fdd.c 1.0.2 2017/09/03
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
*/
|
||||
#include "../ibm.h"
|
||||
#include "floppy.h"
|
||||
#include "fdc.h"
|
||||
#include "fdd.h"
|
||||
|
||||
|
||||
static struct
|
||||
{
|
||||
int type;
|
||||
|
||||
int track;
|
||||
|
||||
int densel;
|
||||
|
||||
int head;
|
||||
|
||||
int turbo;
|
||||
|
||||
int check_bpb;
|
||||
} fdd[FDD_NUM];
|
||||
|
||||
/* Flags:
|
||||
Bit 0: 300 rpm supported;
|
||||
Bit 1: 360 rpm supported;
|
||||
Bit 2: size (0 = 3.5", 1 = 5.25");
|
||||
Bit 3: sides (0 = 1, 1 = 2);
|
||||
Bit 4: double density supported;
|
||||
Bit 5: high density supported;
|
||||
Bit 6: extended density supported;
|
||||
Bit 7: double step for 40-track media;
|
||||
Bit 8: invert DENSEL polarity;
|
||||
Bit 9: ignore DENSEL;
|
||||
Bit 10: drive is a PS/2 drive;
|
||||
*/
|
||||
#define FLAG_RPM_300 1
|
||||
#define FLAG_RPM_360 2
|
||||
#define FLAG_525 4
|
||||
#define FLAG_DS 8
|
||||
#define FLAG_HOLE0 16
|
||||
#define FLAG_HOLE1 32
|
||||
#define FLAG_HOLE2 64
|
||||
#define FLAG_DOUBLE_STEP 128
|
||||
#define FLAG_INVERT_DENSEL 256
|
||||
#define FLAG_IGNORE_DENSEL 512
|
||||
#define FLAG_PS2 1024
|
||||
|
||||
static struct
|
||||
{
|
||||
int max_track;
|
||||
int flags;
|
||||
char name[64];
|
||||
char internal_name[24];
|
||||
} drive_types[] =
|
||||
{
|
||||
{ /*None*/
|
||||
0, 0, "None", "none"
|
||||
},
|
||||
{ /*5.25" 1DD*/
|
||||
43, FLAG_RPM_300 | FLAG_525 | FLAG_HOLE0, "5.25\" 180k", "525_1dd"
|
||||
},
|
||||
{ /*5.25" DD*/
|
||||
43, FLAG_RPM_300 | FLAG_525 | FLAG_DS | FLAG_HOLE0, "5.25\" 360k", "525_2dd"
|
||||
},
|
||||
{ /*5.25" QD*/
|
||||
86, FLAG_RPM_300 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_DOUBLE_STEP, "5.25\" 720k", "525_2qd"
|
||||
},
|
||||
{ /*5.25" HD PS/2*/
|
||||
86, FLAG_RPM_360 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP | FLAG_INVERT_DENSEL | FLAG_PS2, "5.25\" 1.2M PS/2", "525_2hd_ps2"
|
||||
},
|
||||
{ /*5.25" HD*/
|
||||
86, FLAG_RPM_360 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "5.25\" 1.2M", "525_2hd"
|
||||
},
|
||||
{ /*5.25" HD Dual RPM*/
|
||||
86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "5.25\" 1.2M 300/360 RPM", "525_2hd_dualrpm"
|
||||
},
|
||||
{ /*3.5" 1DD*/
|
||||
86, FLAG_RPM_300 | FLAG_HOLE0 | FLAG_DOUBLE_STEP, "3.5\" 360k", "35_1dd"
|
||||
},
|
||||
{ /*3.5" DD*/
|
||||
86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_DOUBLE_STEP, "3.5\" 720k", "35_2dd"
|
||||
},
|
||||
{ /*3.5" HD PS/2*/
|
||||
86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP | FLAG_INVERT_DENSEL | FLAG_PS2, "3.5\" 1.44M PS/2", "35_2hd_ps2"
|
||||
},
|
||||
{ /*3.5" HD*/
|
||||
86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "3.5\" 1.44M", "35_2hd"
|
||||
},
|
||||
{ /*3.5" HD PC-98*/
|
||||
86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP | FLAG_INVERT_DENSEL, "3.5\" 1.25M PC-98", "35_2hd_nec"
|
||||
},
|
||||
{ /*3.5" HD 3-Mode*/
|
||||
86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "3.5\" 1.44M 300/360 RPM", "35_2hd_3mode"
|
||||
},
|
||||
{ /*3.5" ED*/
|
||||
86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_HOLE2 | FLAG_DOUBLE_STEP, "3.5\" 2.88M", "35_2ed"
|
||||
},
|
||||
{ /*End of list*/
|
||||
-1, -1, "", ""
|
||||
}
|
||||
};
|
||||
|
||||
int fdd_swap = 0;
|
||||
|
||||
char *fdd_getname(int type)
|
||||
{
|
||||
return drive_types[type].name;
|
||||
}
|
||||
|
||||
char *fdd_get_internal_name(int type)
|
||||
{
|
||||
return drive_types[type].internal_name;
|
||||
}
|
||||
|
||||
int fdd_get_from_internal_name(char *s)
|
||||
{
|
||||
int c = 0;
|
||||
|
||||
while (strlen(drive_types[c].internal_name))
|
||||
{
|
||||
if (!strcmp(drive_types[c].internal_name, s))
|
||||
return c;
|
||||
c++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fdd_forced_seek(int drive, int track_diff)
|
||||
{
|
||||
drive = real_drive(drive);
|
||||
|
||||
fdd[drive].track += track_diff;
|
||||
|
||||
if (fdd[drive].track < 0)
|
||||
fdd[drive].track = 0;
|
||||
|
||||
if (fdd[drive].track > drive_types[fdd[drive].type].max_track)
|
||||
fdd[drive].track = drive_types[fdd[drive].type].max_track;
|
||||
|
||||
floppy_seek(drive, fdd[drive].track);
|
||||
floppytime = 5000;
|
||||
}
|
||||
|
||||
void fdd_seek(int drive, int track_diff)
|
||||
{
|
||||
drive = real_drive(drive);
|
||||
|
||||
if (!track_diff)
|
||||
{
|
||||
floppytime = 5000;
|
||||
return;
|
||||
}
|
||||
|
||||
fdd[drive].track += track_diff;
|
||||
|
||||
if (fdd[drive].track < 0)
|
||||
fdd[drive].track = 0;
|
||||
|
||||
if (fdd[drive].track > drive_types[fdd[drive].type].max_track)
|
||||
fdd[drive].track = drive_types[fdd[drive].type].max_track;
|
||||
|
||||
fdc_floppychange_clear(drive);
|
||||
floppy_seek(drive, fdd[drive].track);
|
||||
floppytime = 5000;
|
||||
}
|
||||
|
||||
int fdd_track0(int drive)
|
||||
{
|
||||
drive = real_drive(drive);
|
||||
|
||||
/* If drive is disabled, TRK0 never gets set. */
|
||||
if (!drive_types[fdd[drive].type].max_track) return 0;
|
||||
|
||||
return !fdd[drive].track;
|
||||
}
|
||||
|
||||
int fdd_track(int drive)
|
||||
{
|
||||
return fdd[drive].track;
|
||||
}
|
||||
|
||||
void fdd_set_densel(int densel)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (drive_types[fdd[i].type].flags & FLAG_INVERT_DENSEL)
|
||||
{
|
||||
fdd[i].densel = densel ^ 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
fdd[i].densel = densel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int fdd_getrpm(int drive)
|
||||
{
|
||||
int hole = floppy_hole(drive);
|
||||
|
||||
int densel = 0;
|
||||
|
||||
drive = real_drive(drive);
|
||||
|
||||
densel = fdd[drive].densel;
|
||||
|
||||
if (drive_types[fdd[drive].type].flags & FLAG_INVERT_DENSEL)
|
||||
{
|
||||
densel ^= 1;
|
||||
}
|
||||
|
||||
if (!(drive_types[fdd[drive].type].flags & FLAG_RPM_360)) return 300;
|
||||
if (!(drive_types[fdd[drive].type].flags & FLAG_RPM_300)) return 360;
|
||||
|
||||
if (drive_types[fdd[drive].type].flags & FLAG_525)
|
||||
{
|
||||
return densel ? 360 : 300;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* floppy_hole(drive) returns 0 for double density media, 1 for high density, and 2 for extended density. */
|
||||
if (hole == 1)
|
||||
{
|
||||
return densel ? 300 : 360;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 300;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fdd_setswap(int swap)
|
||||
{
|
||||
fdd_swap = swap ? 1 : 0;
|
||||
}
|
||||
|
||||
int fdd_can_read_medium(int drive)
|
||||
{
|
||||
int hole = floppy_hole(drive);
|
||||
|
||||
drive = real_drive(drive);
|
||||
|
||||
hole = 1 << (hole + 3);
|
||||
|
||||
return (drive_types[fdd[drive].type].flags & hole) ? 1 : 0;
|
||||
}
|
||||
|
||||
int fdd_doublestep_40(int drive)
|
||||
{
|
||||
return (drive_types[fdd[drive].type].flags & FLAG_DOUBLE_STEP) ? 1 : 0;
|
||||
}
|
||||
|
||||
void fdd_set_type(int drive, int type)
|
||||
{
|
||||
int old_type = fdd[drive].type;
|
||||
fdd[drive].type = type;
|
||||
if ((drive_types[old_type].flags ^ drive_types[type].flags) & FLAG_INVERT_DENSEL)
|
||||
{
|
||||
fdd[drive].densel ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
int fdd_get_type(int drive)
|
||||
{
|
||||
return fdd[drive].type;
|
||||
}
|
||||
|
||||
int fdd_get_flags(int drive)
|
||||
{
|
||||
return drive_types[fdd[drive].type].flags;
|
||||
}
|
||||
|
||||
int fdd_is_525(int drive)
|
||||
{
|
||||
return drive_types[fdd[drive].type].flags & FLAG_525;
|
||||
}
|
||||
|
||||
int fdd_is_dd(int drive)
|
||||
{
|
||||
return (drive_types[fdd[drive].type].flags & 0x70) == 0x10;
|
||||
}
|
||||
|
||||
int fdd_is_ed(int drive)
|
||||
{
|
||||
return drive_types[fdd[drive].type].flags & FLAG_HOLE2;
|
||||
}
|
||||
|
||||
int fdd_is_double_sided(int drive)
|
||||
{
|
||||
return drive_types[fdd[drive].type].flags & FLAG_DS;
|
||||
}
|
||||
|
||||
void fdd_set_head(int drive, int head)
|
||||
{
|
||||
drive = real_drive(drive);
|
||||
fdd[drive].head = head;
|
||||
}
|
||||
|
||||
int fdd_get_head(int drive)
|
||||
{
|
||||
return fdd[drive].head;
|
||||
}
|
||||
|
||||
void fdd_set_turbo(int drive, int turbo)
|
||||
{
|
||||
fdd[drive].turbo = turbo;
|
||||
}
|
||||
|
||||
int fdd_get_turbo(int drive)
|
||||
{
|
||||
return fdd[drive].turbo;
|
||||
}
|
||||
|
||||
void fdd_set_check_bpb(int drive, int check_bpb)
|
||||
{
|
||||
fdd[drive].check_bpb = check_bpb;
|
||||
}
|
||||
|
||||
int fdd_get_check_bpb(int drive)
|
||||
{
|
||||
return fdd[drive].check_bpb;
|
||||
}
|
||||
|
||||
int fdd_get_densel(int drive)
|
||||
{
|
||||
if (drive_types[fdd[drive].type].flags & FLAG_INVERT_DENSEL)
|
||||
{
|
||||
return fdd[drive].densel ^ 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return fdd[drive].densel;
|
||||
}
|
||||
}
|
||||
|
||||
void fdd_init()
|
||||
{
|
||||
}
|
||||
64
src/floppy/fdd.h
Normal file
64
src/floppy/fdd.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the floppy drive emulation.
|
||||
*
|
||||
* Version: @(#)fdd.h 1.0.2 2017/09/03
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
*/
|
||||
#ifndef EMU_FDD_H
|
||||
# define EMU_FDD_H
|
||||
|
||||
|
||||
#define SEEK_RECALIBRATE -999
|
||||
|
||||
|
||||
extern int fdd_swap;
|
||||
|
||||
|
||||
extern void fdd_forced_seek(int drive, int track_diff);
|
||||
extern void fdd_seek(int drive, int track_diff);
|
||||
extern int fdd_track0(int drive);
|
||||
extern int fdd_getrpm(int drive);
|
||||
extern void fdd_set_densel(int densel);
|
||||
extern int fdd_can_read_medium(int drive);
|
||||
extern int fdd_doublestep_40(int drive);
|
||||
extern int fdd_is_525(int drive);
|
||||
extern int fdd_is_dd(int drive);
|
||||
extern int fdd_is_ed(int drive);
|
||||
extern int fdd_is_double_sided(int drive);
|
||||
extern void fdd_set_head(int drive, int head);
|
||||
extern int fdd_get_head(int drive);
|
||||
extern void fdd_set_turbo(int drive, int turbo);
|
||||
extern int fdd_get_turbo(int drive);
|
||||
extern void fdd_set_check_bpb(int drive, int check_bpb);
|
||||
extern int fdd_get_check_bpb(int drive);
|
||||
|
||||
extern void fdd_set_type(int drive, int type);
|
||||
extern int fdd_get_type(int drive);
|
||||
|
||||
extern int fdd_get_flags(int drive);
|
||||
|
||||
extern void fdd_init(void);
|
||||
extern int fdd_get_densel(int drive);
|
||||
|
||||
extern void fdd_setswap(int swap);
|
||||
|
||||
extern char *fdd_getname(int type);
|
||||
|
||||
extern char *fdd_get_internal_name(int type);
|
||||
extern int fdd_get_from_internal_name(char *s);
|
||||
|
||||
extern int fdd_track(int drive);
|
||||
|
||||
|
||||
#endif /*EMU_FDD_H*/
|
||||
2171
src/floppy/fdi2raw.c
Normal file
2171
src/floppy/fdi2raw.c
Normal file
File diff suppressed because it is too large
Load Diff
37
src/floppy/fdi2raw.h
Normal file
37
src/floppy/fdi2raw.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/* Copyright holders: Toni Wilen
|
||||
see COPYING for more details
|
||||
*/
|
||||
#ifndef __FDI2RAW_H
|
||||
#define __FDI2RAW_H
|
||||
|
||||
#define uae_u8 uint8_t
|
||||
#define uae_u16 uint16_t
|
||||
#define uae_u32 uint32_t
|
||||
|
||||
#include <stdio.h>
|
||||
typedef struct fdi FDI;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern int fdi2raw_loadtrack (FDI*, uae_u16 *mfmbuf, uae_u16 *tracktiming, int track, int *tracklength, int *indexoffset, int *multirev, int mfm);
|
||||
|
||||
extern int fdi2raw_loadrevolution (FDI*, uae_u16 *mfmbuf, uae_u16 *tracktiming, int track, int *tracklength, int mfm);
|
||||
|
||||
extern FDI *fdi2raw_header(FILE *f);
|
||||
extern void fdi2raw_header_free (FDI *);
|
||||
extern int fdi2raw_get_last_track(FDI *);
|
||||
extern int fdi2raw_get_num_sector (FDI *);
|
||||
extern int fdi2raw_get_last_head(FDI *);
|
||||
extern int fdi2raw_get_type (FDI *);
|
||||
extern int fdi2raw_get_bit_rate (FDI *);
|
||||
extern int fdi2raw_get_rotation (FDI *);
|
||||
extern int fdi2raw_get_write_protect (FDI *);
|
||||
extern int fdi2raw_get_tpi (FDI *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
404
src/floppy/floppy.c
Normal file
404
src/floppy/floppy.c
Normal file
@@ -0,0 +1,404 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Generic floppy disk interface that communicates with the
|
||||
* other handlers.
|
||||
*
|
||||
* Version: @(#)floppy.c 1.0.2 2017/09/03
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
*/
|
||||
#define UNICODE
|
||||
#include <windows.h>
|
||||
#include "../ibm.h"
|
||||
#include "../config.h"
|
||||
#include "../timer.h"
|
||||
#include "floppy.h"
|
||||
#include "floppy_fdi.h"
|
||||
#include "floppy_img.h"
|
||||
#include "floppy_86f.h"
|
||||
#include "floppy_td0.h"
|
||||
#include "floppy_imd.h"
|
||||
#include "fdc.h"
|
||||
#include "fdd.h"
|
||||
|
||||
|
||||
extern int driveempty[4];
|
||||
|
||||
wchar_t floppyfns[4][512];
|
||||
|
||||
int floppy_poll_time[FDD_NUM] = { 16, 16, 16, 16 };
|
||||
|
||||
int floppy_track[FDD_NUM];
|
||||
int writeprot[FDD_NUM], fwriteprot[FDD_NUM];
|
||||
|
||||
DRIVE drives[FDD_NUM];
|
||||
int drive_type[FDD_NUM];
|
||||
|
||||
int curdrive = 0;
|
||||
|
||||
int swwp = 0;
|
||||
int disable_write = 0;
|
||||
|
||||
int defaultwriteprot = 0;
|
||||
|
||||
int fdc_time;
|
||||
int floppy_time;
|
||||
|
||||
int fdc_ready;
|
||||
|
||||
int drive_empty[FDD_NUM] = {1, 1, 1, 1};
|
||||
int floppy_changed[FDD_NUM];
|
||||
|
||||
int motorspin;
|
||||
int motoron[FDD_NUM];
|
||||
|
||||
int fdc_indexcount = 52;
|
||||
|
||||
#if 0 //FIXME:
|
||||
void (*fdc_callback)();
|
||||
void (*fdc_data)(uint8_t dat);
|
||||
void (*fdc_spindown)();
|
||||
void (*fdc_finishread)();
|
||||
void (*fdc_notfound)();
|
||||
void (*fdc_datacrcerror)();
|
||||
void (*fdc_headercrcerror)();
|
||||
void (*fdc_writeprotect)();
|
||||
int (*fdc_getdata)(int last);
|
||||
void (*fdc_sectorid)(uint8_t track, uint8_t side, uint8_t sector, uint8_t size, uint8_t crc1, uint8_t crc2);
|
||||
void (*fdc_indexpulse)();
|
||||
#endif
|
||||
|
||||
|
||||
static struct
|
||||
{
|
||||
wchar_t *ext;
|
||||
void (*load)(int drive, wchar_t *fn);
|
||||
void (*close)(int drive);
|
||||
int size;
|
||||
} loaders[]=
|
||||
{
|
||||
{L"001", img_load, img_close, -1},
|
||||
{L"002", img_load, img_close, -1},
|
||||
{L"003", img_load, img_close, -1},
|
||||
{L"004", img_load, img_close, -1},
|
||||
{L"005", img_load, img_close, -1},
|
||||
{L"006", img_load, img_close, -1},
|
||||
{L"007", img_load, img_close, -1},
|
||||
{L"008", img_load, img_close, -1},
|
||||
{L"009", img_load, img_close, -1},
|
||||
{L"010", img_load, img_close, -1},
|
||||
{L"12", img_load, img_close, -1},
|
||||
{L"144", img_load, img_close, -1},
|
||||
{L"360", img_load, img_close, -1},
|
||||
{L"720", img_load, img_close, -1},
|
||||
{L"86F", d86f_load, d86f_close, -1},
|
||||
{L"BIN", img_load, img_close, -1},
|
||||
{L"CQ", img_load, img_close, -1},
|
||||
{L"CQM", img_load, img_close, -1},
|
||||
{L"DSK", img_load, img_close, -1},
|
||||
{L"FDI", fdi_load, fdi_close, -1},
|
||||
{L"FDF", img_load, img_close, -1},
|
||||
{L"FLP", img_load, img_close, -1},
|
||||
{L"HDM", img_load, img_close, -1},
|
||||
{L"IMA", img_load, img_close, -1},
|
||||
{L"IMD", imd_load, imd_close, -1},
|
||||
{L"IMG", img_load, img_close, -1},
|
||||
{L"TD0", td0_load, td0_close, -1},
|
||||
{L"VFD", img_load, img_close, -1},
|
||||
{L"XDF", img_load, img_close, -1},
|
||||
{0,0,0}
|
||||
};
|
||||
|
||||
static int driveloaders[4];
|
||||
|
||||
void floppy_load(int drive, wchar_t *fn)
|
||||
{
|
||||
int c = 0, size;
|
||||
wchar_t *p;
|
||||
FILE *f;
|
||||
if (!fn) return;
|
||||
p = get_extension_w(fn);
|
||||
if (!p) return;
|
||||
f = _wfopen(fn, L"rb");
|
||||
if (!f) return;
|
||||
fseek(f, -1, SEEK_END);
|
||||
size = ftell(f) + 1;
|
||||
fclose(f);
|
||||
while (loaders[c].ext)
|
||||
{
|
||||
if (!_wcsicmp(p, loaders[c].ext) && (size == loaders[c].size || loaders[c].size == -1))
|
||||
{
|
||||
driveloaders[drive] = c;
|
||||
loaders[c].load(drive, fn);
|
||||
drive_empty[drive] = 0;
|
||||
memcpy(floppyfns[drive], fn, (wcslen(fn) << 1) + 2);
|
||||
fdd_forced_seek(real_drive(drive), 0);
|
||||
floppy_changed[drive] = 1;
|
||||
return;
|
||||
}
|
||||
c++;
|
||||
}
|
||||
pclog_w(L"Couldn't load %s %s\n",fn,p);
|
||||
drive_empty[drive] = 1;
|
||||
fdd_set_head(real_drive(drive), 0);
|
||||
memset(floppyfns[drive], 0, sizeof(floppyfns[drive]));
|
||||
update_status_bar_icon_state(drive, 1);
|
||||
}
|
||||
|
||||
void floppy_close(int drive)
|
||||
{
|
||||
if (loaders[driveloaders[drive]].close) loaders[driveloaders[drive]].close(drive);
|
||||
drive_empty[drive] = 1;
|
||||
fdd_set_head(real_drive(drive), 0);
|
||||
floppyfns[drive][0] = 0;
|
||||
drives[drive].hole = NULL;
|
||||
drives[drive].poll = NULL;
|
||||
drives[drive].seek = NULL;
|
||||
drives[drive].readsector = NULL;
|
||||
drives[drive].writesector = NULL;
|
||||
drives[drive].comparesector = NULL;
|
||||
drives[drive].readaddress = NULL;
|
||||
drives[drive].format = NULL;
|
||||
drives[drive].byteperiod = NULL;
|
||||
drives[drive].stop = NULL;
|
||||
update_status_bar_icon_state(drive, 1);
|
||||
}
|
||||
|
||||
int floppy_notfound=0;
|
||||
static int floppy_period = 32;
|
||||
|
||||
int floppy_hole(int drive)
|
||||
{
|
||||
drive = real_drive(drive);
|
||||
|
||||
if (drives[drive].hole)
|
||||
{
|
||||
return drives[drive].hole(drive);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
double floppy_byteperiod(int drive)
|
||||
{
|
||||
drive = real_drive(drive);
|
||||
|
||||
if (drives[drive].byteperiod)
|
||||
{
|
||||
return drives[drive].byteperiod(drive);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 32.0;
|
||||
}
|
||||
}
|
||||
|
||||
double floppy_real_period(int drive)
|
||||
{
|
||||
double ddbp;
|
||||
double dusec;
|
||||
|
||||
ddbp = floppy_byteperiod(real_drive(drive));
|
||||
|
||||
dusec = (double) TIMER_USEC;
|
||||
|
||||
/* This is a giant hack but until the timings become even more correct, this is needed to make floppies work right on that BIOS. */
|
||||
if (fdd_get_turbo(drive))
|
||||
{
|
||||
return (32.0 * dusec);
|
||||
}
|
||||
|
||||
if (romset == ROM_MRTHOR)
|
||||
{
|
||||
return (ddbp * dusec) / 4.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (ddbp * dusec);
|
||||
}
|
||||
}
|
||||
|
||||
void floppy_poll(int drive)
|
||||
{
|
||||
if (drive >= FDD_NUM)
|
||||
{
|
||||
fatal("Attempting to poll floppy drive %i that is not supposed to be there\n", drive);
|
||||
}
|
||||
|
||||
floppy_poll_time[drive] += (int) floppy_real_period(drive);
|
||||
|
||||
if (drives[drive].poll)
|
||||
drives[drive].poll(drive);
|
||||
|
||||
if (floppy_notfound)
|
||||
{
|
||||
floppy_notfound--;
|
||||
if (!floppy_notfound)
|
||||
fdc_noidam();
|
||||
}
|
||||
}
|
||||
|
||||
void floppy_poll_0(void *priv)
|
||||
{
|
||||
floppy_poll(0);
|
||||
}
|
||||
|
||||
void floppy_poll_1(void *priv)
|
||||
{
|
||||
floppy_poll(1);
|
||||
}
|
||||
|
||||
void floppy_poll_2(void *priv)
|
||||
{
|
||||
floppy_poll(2);
|
||||
}
|
||||
|
||||
void floppy_poll_3(void *priv)
|
||||
{
|
||||
floppy_poll(3);
|
||||
}
|
||||
|
||||
int floppy_get_bitcell_period(int rate)
|
||||
{
|
||||
int bit_rate = 250;
|
||||
|
||||
switch (rate)
|
||||
{
|
||||
case 0: /*High density*/
|
||||
bit_rate = 500;
|
||||
break;
|
||||
case 1: /*Double density (360 rpm)*/
|
||||
bit_rate = 300;
|
||||
break;
|
||||
case 2: /*Double density*/
|
||||
bit_rate = 250;
|
||||
break;
|
||||
case 3: /*Extended density*/
|
||||
bit_rate = 1000;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1000000 / bit_rate*2; /*Bitcell period in ns*/
|
||||
}
|
||||
|
||||
|
||||
void floppy_set_rate(int drive, int drvden, int rate)
|
||||
{
|
||||
switch (rate)
|
||||
{
|
||||
case 0: /*High density*/
|
||||
floppy_period = 16;
|
||||
break;
|
||||
case 1:
|
||||
switch(drvden)
|
||||
{
|
||||
case 0: /*Double density (360 rpm)*/
|
||||
floppy_period = 26;
|
||||
break;
|
||||
case 1: /*High density (360 rpm)*/
|
||||
floppy_period = 16;
|
||||
break;
|
||||
case 2:
|
||||
floppy_period = 4;
|
||||
break;
|
||||
}
|
||||
case 2: /*Double density*/
|
||||
floppy_period = 32;
|
||||
break;
|
||||
case 3: /*Extended density*/
|
||||
floppy_period = 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void floppy_reset()
|
||||
{
|
||||
curdrive = 0;
|
||||
floppy_period = 32;
|
||||
timer_add(floppy_poll_0, &(floppy_poll_time[0]), &(motoron[0]), NULL);
|
||||
timer_add(floppy_poll_1, &(floppy_poll_time[1]), &(motoron[1]), NULL);
|
||||
timer_add(floppy_poll_2, &(floppy_poll_time[2]), &(motoron[2]), NULL);
|
||||
timer_add(floppy_poll_3, &(floppy_poll_time[3]), &(motoron[3]), NULL);
|
||||
}
|
||||
|
||||
void floppy_init()
|
||||
{
|
||||
drives[0].poll = drives[1].poll = drives[2].poll = drives[3].poll = 0;
|
||||
drives[0].seek = drives[1].seek = drives[2].seek = drives[3].seek = 0;
|
||||
drives[0].readsector = drives[1].readsector = drives[2].readsector = drives[3].readsector = 0;
|
||||
floppy_reset();
|
||||
}
|
||||
|
||||
int oldtrack[FDD_NUM] = {0, 0, 0, 0};
|
||||
void floppy_seek(int drive, int track)
|
||||
{
|
||||
if (drives[drive].seek)
|
||||
drives[drive].seek(drive, track);
|
||||
}
|
||||
|
||||
void floppy_readsector(int drive, int sector, int track, int side, int density, int sector_size)
|
||||
{
|
||||
drive = real_drive(drive);
|
||||
|
||||
if (drives[drive].readsector)
|
||||
drives[drive].readsector(drive, sector, track, side, density, sector_size);
|
||||
else
|
||||
floppy_notfound = 1000;
|
||||
}
|
||||
|
||||
void floppy_writesector(int drive, int sector, int track, int side, int density, int sector_size)
|
||||
{
|
||||
drive = real_drive(drive);
|
||||
|
||||
if (drives[drive].writesector)
|
||||
drives[drive].writesector(drive, sector, track, side, density, sector_size);
|
||||
else
|
||||
floppy_notfound = 1000;
|
||||
}
|
||||
|
||||
void floppy_comparesector(int drive, int sector, int track, int side, int density, int sector_size)
|
||||
{
|
||||
drive = real_drive(drive);
|
||||
|
||||
if (drives[drive].comparesector)
|
||||
drives[drive].comparesector(drive, sector, track, side, density, sector_size);
|
||||
else
|
||||
floppy_notfound = 1000;
|
||||
}
|
||||
|
||||
void floppy_readaddress(int drive, int side, int density)
|
||||
{
|
||||
drive = real_drive(drive);
|
||||
|
||||
if (drives[drive].readaddress)
|
||||
drives[drive].readaddress(drive, side, density);
|
||||
}
|
||||
|
||||
void floppy_format(int drive, int side, int density, uint8_t fill)
|
||||
{
|
||||
drive = real_drive(drive);
|
||||
|
||||
if (drives[drive].format)
|
||||
drives[drive].format(drive, side, density, fill);
|
||||
else
|
||||
floppy_notfound = 1000;
|
||||
}
|
||||
|
||||
void floppy_stop(int drive)
|
||||
{
|
||||
drive = real_drive(drive);
|
||||
|
||||
if (drives[drive].stop)
|
||||
drives[drive].stop(drive);
|
||||
}
|
||||
240
src/floppy/floppy.h
Normal file
240
src/floppy/floppy.h
Normal file
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Generic floppy disk interface that communicates with the
|
||||
* other handlers.
|
||||
*
|
||||
* Version: @(#)floppy.h 1.0.3 2017/09/03
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
*/
|
||||
#ifndef EMU_FLOPPY_H
|
||||
# define EMU_FLOPPY_H
|
||||
|
||||
|
||||
#define FDD_NUM 4
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void (*seek)(int drive, int track);
|
||||
void (*readsector)(int drive, int sector, int track, int side, int density, int sector_size);
|
||||
void (*writesector)(int drive, int sector, int track, int side, int density, int sector_size);
|
||||
void (*comparesector)(int drive, int sector, int track, int side, int density, int sector_size);
|
||||
void (*readaddress)(int drive, int side, int density);
|
||||
void (*format)(int drive, int side, int density, uint8_t fill);
|
||||
int (*hole)(int drive);
|
||||
double (*byteperiod)(int drive);
|
||||
void (*stop)(int drive);
|
||||
void (*poll)(int drive);
|
||||
} DRIVE;
|
||||
|
||||
|
||||
extern DRIVE drives[FDD_NUM];
|
||||
extern int curdrive;
|
||||
|
||||
extern int floppy_time;
|
||||
extern int floppy_poll_time[FDD_NUM];
|
||||
|
||||
|
||||
extern void floppy_load(int drive, wchar_t *fn);
|
||||
extern void floppy_new(int drive, char *fn);
|
||||
extern void floppy_close(int drive);
|
||||
extern void floppy_init(void);
|
||||
extern void floppy_reset(void);
|
||||
extern void floppy_poll(int drive);
|
||||
extern void floppy_poll_0(void* priv);
|
||||
extern void floppy_poll_1(void* priv);
|
||||
extern void floppy_poll_2(void* priv);
|
||||
extern void floppy_poll_3(void* priv);
|
||||
extern void floppy_seek(int drive, int track);
|
||||
extern void floppy_readsector(int drive, int sector, int track,
|
||||
int side, int density, int sector_size);
|
||||
extern void floppy_writesector(int drive, int sector, int track,
|
||||
int side, int density, int sector_size);
|
||||
extern void floppy_comparesector(int drive, int sector, int track,
|
||||
int side, int density, int sector_size);
|
||||
extern void floppy_readaddress(int drive, int side, int density);
|
||||
extern void floppy_format(int drive, int side, int density, uint8_t fill);
|
||||
extern int floppy_hole(int drive);
|
||||
extern double floppy_byteperiod(int drive);
|
||||
extern void floppy_stop(int drive);
|
||||
extern int floppy_empty(int drive);
|
||||
extern void floppy_set_rate(int drive, int drvden, int rate);
|
||||
|
||||
extern void fdc_callback(void *priv);
|
||||
extern int fdc_data(uint8_t dat);
|
||||
extern void fdc_spindown(void);
|
||||
extern void fdc_finishread(void);
|
||||
extern void fdc_datacrcerror(void);
|
||||
extern void fdc_headercrcerror(void);
|
||||
extern void fdc_writeprotect(void);
|
||||
extern int fdc_getdata(int last);
|
||||
extern void fdc_sectorid(uint8_t track, uint8_t side, uint8_t sector,
|
||||
uint8_t size, uint8_t crc1, uint8_t crc2);
|
||||
extern void fdc_indexpulse(void);
|
||||
|
||||
/*extern int fdc_time;
|
||||
extern int fdc_ready;
|
||||
extern int fdc_indexcount;*/
|
||||
|
||||
extern int motorspin;
|
||||
extern int motoron[FDD_NUM];
|
||||
|
||||
extern int swwp;
|
||||
extern int disable_write;
|
||||
|
||||
extern int defaultwriteprot;
|
||||
|
||||
extern int writeprot[FDD_NUM], fwriteprot[FDD_NUM];
|
||||
extern int floppy_track[FDD_NUM];
|
||||
extern int floppy_changed[FDD_NUM];
|
||||
extern int drive_empty[FDD_NUM];
|
||||
extern int drive_type[FDD_NUM];
|
||||
|
||||
/*Used in the Read A Track command. Only valid for floppy_readsector(). */
|
||||
#define SECTOR_FIRST -2
|
||||
#define SECTOR_NEXT -1
|
||||
|
||||
#if 0
|
||||
/* Bits 0-3 define byte type, bit 5 defines whether it is a per-track (0) or per-sector (1) byte, if bit 7 is set, the byte is the index hole. */
|
||||
#define BYTE_GAP0 0x00
|
||||
#define BYTE_GAP1 0x10
|
||||
#define BYTE_GAP4 0x20
|
||||
#define BYTE_GAP2 0x40
|
||||
#define BYTE_GAP3 0x50
|
||||
#define BYTE_I_SYNC 0x01
|
||||
#define BYTE_ID_SYNC 0x41
|
||||
#define BYTE_DATA_SYNC 0x51
|
||||
#define BYTE_IAM_SYNC 0x02
|
||||
#define BYTE_IDAM_SYNC 0x42
|
||||
#define BYTE_DATAAM_SYNC 0x52
|
||||
#define BYTE_IAM 0x03
|
||||
#define BYTE_IDAM 0x43
|
||||
#define BYTE_DATAAM 0x53
|
||||
#define BYTE_ID 0x44
|
||||
#define BYTE_DATA 0x54
|
||||
#define BYTE_ID_CRC 0x45
|
||||
#define BYTE_DATA_CRC 0x55
|
||||
|
||||
#define BYTE_IS_FUZZY 0x80
|
||||
#define BYTE_INDEX_HOLE 0x80 /* 1 = index hole, 0 = regular byte */
|
||||
#define BYTE_IS_SECTOR 0x40 /* 1 = per-sector, 0 = per-track */
|
||||
#define BYTE_IS_POST_TRACK 0x20 /* 1 = after all sectors, 0 = before or during all sectors */
|
||||
#define BYTE_IS_DATA 0x10 /* 1 = data, 0 = id */
|
||||
#define BYTE_TYPE 0x0F /* 5 = crc, 4 = data, 3 = address mark, 2 = address mark sync, 1 = sync, 0 = gap */
|
||||
|
||||
#define BYTE_TYPE_GAP 0x00
|
||||
#define BYTE_TYPE_SYNC 0x01
|
||||
#define BYTE_TYPE_AM_SYNC 0x02
|
||||
#define BYTE_TYPE_AM 0x03
|
||||
#define BYTE_TYPE_DATA 0x04
|
||||
#define BYTE_TYPE_CRC 0x05
|
||||
#endif
|
||||
|
||||
typedef union {
|
||||
uint16_t word;
|
||||
uint8_t bytes[2];
|
||||
} crc_t;
|
||||
|
||||
void floppy_calccrc(uint8_t byte, crc_t *crc_var);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t (*disk_flags)(int drive);
|
||||
uint16_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);
|
||||
int32_t (*extra_bit_cells)(int drive, int side);
|
||||
uint16_t* (*encoded_data)(int drive, int side);
|
||||
void (*read_revolution)(int drive);
|
||||
uint32_t (*index_hole_pos)(int drive, int side);
|
||||
uint32_t (*get_raw_size)(int drive, int side);
|
||||
uint8_t check_crc;
|
||||
} d86f_handler_t;
|
||||
|
||||
d86f_handler_t d86f_handler[FDD_NUM];
|
||||
|
||||
void d86f_common_handlers(int drive);
|
||||
|
||||
int d86f_is_40_track(int drive);
|
||||
|
||||
void d86f_reset_index_hole_pos(int drive, int side);
|
||||
|
||||
uint16_t d86f_prepare_pretrack(int drive, int side, int iso);
|
||||
uint16_t d86f_prepare_sector(int drive, int side, int prev_pos, uint8_t *id_buf, uint8_t *data_buf, int data_len, int gap2, int gap3, int deleted, int bad_crc);
|
||||
|
||||
int gap3_sizes[5][8][48];
|
||||
|
||||
void null_writeback(int drive);
|
||||
void null_write_data(int drive, int side, uint16_t pos, uint8_t data);
|
||||
int null_format_conditions(int drive);
|
||||
void d86f_unregister(int drive);
|
||||
|
||||
uint8_t dmf_r[21];
|
||||
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);
|
||||
|
||||
void d86f_set_track_pos(int drive, uint32_t track_pos);
|
||||
|
||||
int32_t null_extra_bit_cells(int drive, int side);
|
||||
uint16_t* common_encoded_data(int drive, int side);
|
||||
|
||||
void common_read_revolution(int drive);
|
||||
void null_set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n);
|
||||
|
||||
uint32_t null_index_hole_pos(int drive, int side);
|
||||
|
||||
uint32_t common_get_raw_size(int drive, int side);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t c;
|
||||
uint8_t h;
|
||||
uint8_t r;
|
||||
uint8_t n;
|
||||
} sector_id_fields_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint32_t dword;
|
||||
uint8_t byte_array[4];
|
||||
sector_id_fields_t id;
|
||||
} sector_id_t;
|
||||
|
||||
void d86f_set_version(int drive, uint16_t version);
|
||||
|
||||
void d86f_initialize_last_sector_id(int drive, int c, int h, int r, int n);
|
||||
void d86f_zero_bit_field(int drive, int side);
|
||||
|
||||
|
||||
#endif /*EMU_FLOPPY_H*/
|
||||
3677
src/floppy/floppy_86f.c
Normal file
3677
src/floppy/floppy_86f.c
Normal file
File diff suppressed because it is too large
Load Diff
73
src/floppy/floppy_86f.h
Normal file
73
src/floppy/floppy_86f.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the 86F floppy image format (stores the
|
||||
* data in the form of FM/MFM-encoded transitions) which also
|
||||
* forms the core of the emulator's floppy disk emulation.
|
||||
*
|
||||
* Version: @(#)floppy_86f.h 1.0.2 2017/09/03
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2016-2017 Miran Grca.
|
||||
*/
|
||||
#ifndef EMU_FLOPPY_86F_H
|
||||
# define EMU_FLOPPY_86F_H
|
||||
|
||||
|
||||
extern void d86f_init(void);
|
||||
extern void d86f_load(int drive, wchar_t *fn);
|
||||
extern void d86f_close(int drive);
|
||||
extern void d86f_seek(int drive, int track);
|
||||
extern int d86f_hole(int drive);
|
||||
extern double d86f_byteperiod(int drive);
|
||||
extern void d86f_stop(int drive);
|
||||
extern void d86f_poll(int drive);
|
||||
extern int d86f_realtrack(int track, int drive);
|
||||
extern void d86f_reset(int drive, int side);
|
||||
extern void d86f_readsector(int drive, int sector, int track, int side, int density, int sector_size);
|
||||
extern void d86f_writesector(int drive, int sector, int track, int side, int density, int sector_size);
|
||||
extern void d86f_comparesector(int drive, int sector, int track, int side, int rate, int sector_size);
|
||||
extern void d86f_readaddress(int drive, int side, int density);
|
||||
extern void d86f_format(int drive, int side, int density, uint8_t fill);
|
||||
|
||||
extern void d86f_prepare_track_layout(int drive, int side);
|
||||
extern void d86f_set_version(int drive, uint16_t version);
|
||||
|
||||
#define length_gap0 80
|
||||
#define length_gap1 50
|
||||
#define length_sync 12
|
||||
#define length_am 4
|
||||
#define length_crc 2
|
||||
|
||||
#define IBM
|
||||
#define MFM
|
||||
#ifdef IBM
|
||||
#define pre_gap1 length_gap0 + length_sync + length_am
|
||||
#else
|
||||
#define pre_gap1 0
|
||||
#endif
|
||||
|
||||
#define pre_track pre_gap1 + length_gap1
|
||||
#define pre_gap length_sync + length_am + 4 + length_crc
|
||||
#define pre_data length_sync + length_am
|
||||
#define post_gap length_crc
|
||||
|
||||
#if 0
|
||||
extern int raw_tsize[2];
|
||||
extern int gap2_size[2];
|
||||
extern int gap3_size[2];
|
||||
extern int gap4_size[2];
|
||||
#endif
|
||||
|
||||
#define D86FVER 0x020B
|
||||
|
||||
extern void d86f_initialize_last_sector_id(int drive, int c, int h, int r, int n);
|
||||
extern void d86f_zero_bit_field(int drive, int side);
|
||||
|
||||
|
||||
#endif /*EMU_FLOPPY_86F_H*/
|
||||
338
src/floppy/floppy_fdi.c
Normal file
338
src/floppy/floppy_fdi.c
Normal file
@@ -0,0 +1,338 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the FDI floppy stream image format
|
||||
* interface to the FDI2RAW module.
|
||||
*
|
||||
* Version: @(#)floppy_fdi.c 1.0.1 2017/09/03
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <wchar.h>
|
||||
#include "../ibm.h"
|
||||
#include "floppy.h"
|
||||
#include "floppy_86f.h"
|
||||
#include "floppy_img.h"
|
||||
#include "floppy_fdi.h"
|
||||
#include "fdc.h"
|
||||
#include "fdd.h"
|
||||
#include "fdi2raw.h"
|
||||
|
||||
|
||||
static struct
|
||||
{
|
||||
FILE *f;
|
||||
FDI *h;
|
||||
uint8_t track_data[2][4][256*1024];
|
||||
uint8_t track_timing[2][4][256*1024];
|
||||
|
||||
int sides;
|
||||
int track;
|
||||
int tracklen[2][4];
|
||||
int trackindex[2][4];
|
||||
|
||||
int lasttrack;
|
||||
} fdi[FDD_NUM];
|
||||
|
||||
uint16_t fdi_disk_flags(int drive)
|
||||
{
|
||||
uint16_t temp_disk_flags = 0x80; /* We ALWAYS claim to have extra bit cells, even if the actual amount is 0. */
|
||||
|
||||
switch (fdi2raw_get_bit_rate(fdi[drive].h))
|
||||
{
|
||||
case 500:
|
||||
temp_disk_flags |= 2;
|
||||
break;
|
||||
case 300:
|
||||
case 250:
|
||||
temp_disk_flags |= 0;
|
||||
break;
|
||||
case 1000:
|
||||
temp_disk_flags |= 4;
|
||||
break;
|
||||
default:
|
||||
temp_disk_flags |= 0;
|
||||
}
|
||||
|
||||
if (fdi[drive].sides == 2)
|
||||
{
|
||||
temp_disk_flags |= 8;
|
||||
}
|
||||
|
||||
/* Tell the 86F handler that will handle our data to handle it in reverse byte endianness. */
|
||||
temp_disk_flags |= 0x800;
|
||||
|
||||
return temp_disk_flags;
|
||||
}
|
||||
|
||||
uint16_t fdi_side_flags(int drive)
|
||||
{
|
||||
uint16_t temp_side_flags = 0;
|
||||
switch (fdi2raw_get_bit_rate(fdi[drive].h))
|
||||
{
|
||||
case 500:
|
||||
temp_side_flags = 0;
|
||||
break;
|
||||
case 300:
|
||||
temp_side_flags = 1;
|
||||
break;
|
||||
case 250:
|
||||
temp_side_flags = 2;
|
||||
break;
|
||||
case 1000:
|
||||
temp_side_flags = 3;
|
||||
break;
|
||||
default:
|
||||
temp_side_flags = 2;
|
||||
}
|
||||
if (fdi2raw_get_rotation(fdi[drive].h) == 360)
|
||||
{
|
||||
temp_side_flags |= 0x20;
|
||||
}
|
||||
|
||||
/* Set the encoding value to match that provided by the FDC. Then if it's wrong, it will sector not found anyway. */
|
||||
temp_side_flags |= 0x08;
|
||||
|
||||
return temp_side_flags;
|
||||
}
|
||||
|
||||
int fdi_density()
|
||||
{
|
||||
if (!fdc_is_mfm())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (fdc_get_bit_rate())
|
||||
{
|
||||
case 0:
|
||||
return 2;
|
||||
case 1:
|
||||
return 1;
|
||||
case 2:
|
||||
return 1;
|
||||
case 3:
|
||||
case 5:
|
||||
return 3;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t fdi_extra_bit_cells(int drive, int side)
|
||||
{
|
||||
int density = 0;
|
||||
|
||||
int raw_size = 0;
|
||||
|
||||
int is_300_rpm = 0;
|
||||
|
||||
density = fdi_density();
|
||||
|
||||
is_300_rpm = (fdd_getrpm(real_drive(drive)) == 300);
|
||||
|
||||
switch (fdc_get_bit_rate())
|
||||
{
|
||||
case 0:
|
||||
raw_size = is_300_rpm ? 200000 : 166666;
|
||||
break;
|
||||
case 1:
|
||||
raw_size = is_300_rpm ? 120000 : 100000;
|
||||
break;
|
||||
case 2:
|
||||
raw_size = is_300_rpm ? 100000 : 83333;
|
||||
case 3:
|
||||
case 5:
|
||||
raw_size = is_300_rpm ? 400000 : 333333;
|
||||
break;
|
||||
default:
|
||||
raw_size = is_300_rpm ? 100000 : 83333;
|
||||
}
|
||||
|
||||
return (fdi[drive].tracklen[side][density] - raw_size);
|
||||
}
|
||||
|
||||
int fdi_hole(int drive)
|
||||
{
|
||||
switch (fdi2raw_get_bit_rate(fdi[drive].h))
|
||||
{
|
||||
case 1000:
|
||||
return 2;
|
||||
case 500:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void fdi_read_revolution(int drive)
|
||||
{
|
||||
int density;
|
||||
int track = fdi[drive].track;
|
||||
|
||||
int side = 0;
|
||||
|
||||
if (track > fdi[drive].lasttrack)
|
||||
{
|
||||
for (density = 0; density < 4; density++)
|
||||
{
|
||||
memset(fdi[drive].track_data[0][density], 0, 106096);
|
||||
memset(fdi[drive].track_data[1][density], 0, 106096);
|
||||
fdi[drive].tracklen[0][density] = fdi[drive].tracklen[1][density] = 100000;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (density = 0; density < 4; density++)
|
||||
{
|
||||
for (side = 0; side < fdi[drive].sides; side++)
|
||||
{
|
||||
int c = fdi2raw_loadtrack(fdi[drive].h, (uint16_t *)fdi[drive].track_data[side][density],
|
||||
(uint16_t *)fdi[drive].track_timing[side][density],
|
||||
(track * fdi[drive].sides) + side,
|
||||
&fdi[drive].tracklen[side][density],
|
||||
&fdi[drive].trackindex[side][density], NULL, density);
|
||||
if (!c)
|
||||
memset(fdi[drive].track_data[side][density], 0, fdi[drive].tracklen[side][density]);
|
||||
}
|
||||
|
||||
if (fdi[drive].sides == 1)
|
||||
{
|
||||
memset(fdi[drive].track_data[1][density], 0, 106096);
|
||||
fdi[drive].tracklen[1][density] = 100000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t fdi_index_hole_pos(int drive, int side)
|
||||
{
|
||||
int density;
|
||||
|
||||
density = fdi_density();
|
||||
|
||||
return fdi[drive].trackindex[side][density];
|
||||
}
|
||||
|
||||
uint32_t fdi_get_raw_size(int drive, int side)
|
||||
{
|
||||
int density;
|
||||
|
||||
density = fdi_density();
|
||||
|
||||
return fdi[drive].tracklen[side][density];
|
||||
}
|
||||
|
||||
uint16_t* fdi_encoded_data(int drive, int side)
|
||||
{
|
||||
int density = 0;
|
||||
|
||||
density = fdi_density();
|
||||
|
||||
return (uint16_t *)fdi[drive].track_data[side][density];
|
||||
}
|
||||
|
||||
void d86f_register_fdi(int drive)
|
||||
{
|
||||
d86f_handler[drive].disk_flags = fdi_disk_flags;
|
||||
d86f_handler[drive].side_flags = fdi_side_flags;
|
||||
d86f_handler[drive].writeback = null_writeback;
|
||||
d86f_handler[drive].set_sector = null_set_sector;
|
||||
d86f_handler[drive].write_data = null_write_data;
|
||||
d86f_handler[drive].format_conditions = null_format_conditions;
|
||||
d86f_handler[drive].extra_bit_cells = fdi_extra_bit_cells;
|
||||
d86f_handler[drive].encoded_data = fdi_encoded_data;
|
||||
d86f_handler[drive].read_revolution = fdi_read_revolution;
|
||||
d86f_handler[drive].index_hole_pos = fdi_index_hole_pos;
|
||||
d86f_handler[drive].get_raw_size = fdi_get_raw_size;
|
||||
d86f_handler[drive].check_crc = 1;
|
||||
d86f_set_version(drive, D86FVER);
|
||||
}
|
||||
|
||||
void fdi_load(int drive, wchar_t *fn)
|
||||
{
|
||||
char header[26];
|
||||
|
||||
writeprot[drive] = fwriteprot[drive] = 1;
|
||||
fdi[drive].f = _wfopen(fn, L"rb");
|
||||
if (!fdi[drive].f)
|
||||
{
|
||||
memset(floppyfns[drive], 0, sizeof(floppyfns[drive]));
|
||||
return;
|
||||
}
|
||||
|
||||
d86f_unregister(drive);
|
||||
|
||||
fread(header, 1, 25, fdi[drive].f);
|
||||
fseek(fdi[drive].f, 0, SEEK_SET);
|
||||
header[25] = 0;
|
||||
if (strcmp(header, "Formatted Disk Image file") != 0)
|
||||
{
|
||||
/* This is a Japanese FDI file. */
|
||||
pclog("fdi_load(): Japanese FDI file detected, redirecting to IMG loader\n");
|
||||
fclose(fdi[drive].f);
|
||||
fdi[drive].f = NULL;
|
||||
img_load(drive, fn);
|
||||
return;
|
||||
}
|
||||
|
||||
fdi[drive].h = fdi2raw_header(fdi[drive].f);
|
||||
fdi[drive].lasttrack = fdi2raw_get_last_track(fdi[drive].h);
|
||||
fdi[drive].sides = fdi2raw_get_last_head(fdi[drive].h) + 1;
|
||||
|
||||
d86f_register_fdi(drive);
|
||||
|
||||
drives[drive].seek = fdi_seek;
|
||||
d86f_common_handlers(drive);
|
||||
|
||||
pclog("Loaded as FDI\n");
|
||||
}
|
||||
|
||||
void fdi_close(int drive)
|
||||
{
|
||||
d86f_unregister(drive);
|
||||
drives[drive].seek = NULL;
|
||||
if (fdi[drive].h)
|
||||
fdi2raw_header_free(fdi[drive].h);
|
||||
if (fdi[drive].f)
|
||||
{
|
||||
fclose(fdi[drive].f);
|
||||
fdi[drive].f = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void fdi_seek(int drive, int track)
|
||||
{
|
||||
if (fdd_doublestep_40(drive))
|
||||
{
|
||||
if (fdi2raw_get_tpi(fdi[drive].h) < 2)
|
||||
{
|
||||
track /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fdi[drive].f)
|
||||
return;
|
||||
if (track < 0)
|
||||
track = 0;
|
||||
if (track > fdi[drive].lasttrack)
|
||||
track = fdi[drive].lasttrack - 1;
|
||||
|
||||
fdi[drive].track = track;
|
||||
|
||||
fdi_read_revolution(drive);
|
||||
}
|
||||
|
||||
void fdi_init()
|
||||
{
|
||||
return;
|
||||
}
|
||||
38
src/floppy/floppy_fdi.h
Normal file
38
src/floppy/floppy_fdi.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the FDI floppy stream image format
|
||||
* interface to the FDI2RAW module.
|
||||
*
|
||||
* Version: @(#)floppy_fdi.h 1.0.2 2017/09/03
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
*/
|
||||
#ifndef EMU_FLOPPY_FDI_H
|
||||
# define EMU_FLOPPY_FDI_H
|
||||
|
||||
|
||||
extern void fdi_init(void);
|
||||
extern void fdi_load(int drive, wchar_t *fn);
|
||||
extern void fdi_close(int drive);
|
||||
extern void fdi_seek(int drive, int track);
|
||||
extern void fdi_readsector(int drive, int sector, int track, int side, int density, int sector_size);
|
||||
extern void fdi_writesector(int drive, int sector, int track, int side, int density, int sector_size);
|
||||
extern void fdi_comparesector(int drive, int sector, int track, int side, int density, int sector_size);
|
||||
extern void fdi_readaddress(int drive, int sector, int side, int density);
|
||||
extern void fdi_format(int drive, int sector, int side, int density, uint8_t fill);
|
||||
extern int fdi_hole(int drive);
|
||||
extern double fdi_byteperiod(int drive);
|
||||
extern void fdi_stop(void);
|
||||
extern void fdi_poll(void);
|
||||
|
||||
|
||||
#endif /*EMU_FLOPPY_FDI_H*/
|
||||
817
src/floppy/floppy_imd.c
Normal file
817
src/floppy/floppy_imd.c
Normal file
@@ -0,0 +1,817 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the IMD floppy image format.
|
||||
*
|
||||
* Version: @(#)floppy_imd.c 1.0.1 2017/09/03
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2016-2017 Miran Grca.
|
||||
*/
|
||||
#include <malloc.h>
|
||||
#include <wchar.h>
|
||||
#include "../ibm.h"
|
||||
#include "floppy.h"
|
||||
#include "floppy_imd.h"
|
||||
#include "fdc.h"
|
||||
#include "fdd.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;
|
||||
char *buffer;
|
||||
uint32_t start_offs;
|
||||
int track_count, sides;
|
||||
int track;
|
||||
uint16_t disk_flags;
|
||||
int track_width;
|
||||
imd_track_t tracks[256][2];
|
||||
uint16_t current_side_flags[2];
|
||||
uint8_t xdf_ordered_pos[256][2];
|
||||
uint8_t interleave_ordered_pos[256][2];
|
||||
char *current_data[2];
|
||||
uint8_t track_buffer[2][25000];
|
||||
} imd[FDD_NUM];
|
||||
|
||||
void imd_init()
|
||||
{
|
||||
memset(imd, 0, sizeof(imd));
|
||||
}
|
||||
|
||||
void d86f_register_imd(int drive);
|
||||
|
||||
void imd_load(int drive, wchar_t *fn)
|
||||
{
|
||||
uint32_t magic = 0;
|
||||
uint32_t fsize = 0;
|
||||
char *buffer;
|
||||
char *buffer2;
|
||||
int i = 0;
|
||||
int track_spt = 0;
|
||||
int sector_size = 0;
|
||||
int track = 0;
|
||||
int side = 0;
|
||||
int extra = 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 = 0;
|
||||
|
||||
d86f_unregister(drive);
|
||||
|
||||
writeprot[drive] = 0;
|
||||
imd[drive].f = _wfopen(fn, L"rb+");
|
||||
if (!imd[drive].f)
|
||||
{
|
||||
imd[drive].f = _wfopen(fn, L"rb");
|
||||
if (!imd[drive].f)
|
||||
{
|
||||
memset(floppyfns[drive], 0, sizeof(floppyfns[drive]));
|
||||
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);
|
||||
imd[drive].f = NULL;
|
||||
memset(floppyfns[drive], 0, sizeof(floppyfns[drive]));
|
||||
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);
|
||||
imd[drive].f = NULL;
|
||||
memset(floppyfns[drive], 0, sizeof(floppyfns[drive]));
|
||||
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);
|
||||
imd[drive].f = NULL;
|
||||
memset(floppyfns[drive], 0, sizeof(floppyfns[drive]));
|
||||
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;
|
||||
|
||||
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;
|
||||
if ((imd[drive].tracks[track][side].side_flags & 7) == 1) 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;
|
||||
|
||||
/* Leaving even GAP4: 80 : 40 */
|
||||
/* Leaving only GAP1: 96 : 47 */
|
||||
/* Not leaving even GAP1: 146 : 73 */
|
||||
raw_tsize = td0_get_raw_tsize(imd[drive].tracks[track][side].side_flags, 0);
|
||||
minimum_gap3 = 12 * track_spt;
|
||||
if ((raw_tsize - track_total + (mfm ? 146 : 73)) < (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 + (mfm ? 146 : 73)) < (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);
|
||||
imd[drive].f = NULL;
|
||||
memset(floppyfns[drive], 0, sizeof(floppyfns[drive]));
|
||||
return;
|
||||
}
|
||||
}
|
||||
imd[drive].tracks[track][side].gap3_len = (raw_tsize - track_total - minimum_gap4 + (mfm ? 146 : 73)) / track_spt;
|
||||
|
||||
imd[drive].track_count++;
|
||||
|
||||
if (last_offset >= fsize)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
imd[drive].track_width = 0;
|
||||
if (imd[drive].track_count > 43) imd[drive].track_width = 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;
|
||||
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;
|
||||
char *data_base;
|
||||
char *cur_data;
|
||||
|
||||
effective_sectors = xdf_sectors = high_sectors = low_sectors = 0;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
imd[drive].xdf_ordered_pos[i][side] = 0;
|
||||
}
|
||||
|
||||
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 = (uint8_t *) (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[(int) r_map[i]][side] = i;
|
||||
}
|
||||
if ((r_map[i] >= 0x01) && (r_map[i] <= 0x08))
|
||||
{
|
||||
low_sectors++;
|
||||
imd[drive].xdf_ordered_pos[(int) 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 = (uint8_t *) (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[(int) r_map[i]][side] = i;
|
||||
}
|
||||
cur_data += (128 << ((uint32_t) n_map[i]));
|
||||
}
|
||||
if ((effective_sectors == 3) && (xdf_sectors == 3))
|
||||
{
|
||||
imd[drive].current_side_flags[side] = 0x28;
|
||||
return 1; /* 5.25" 2HD XDF */
|
||||
}
|
||||
if ((effective_sectors == 4) && (xdf_sectors == 4))
|
||||
{
|
||||
imd[drive].current_side_flags[side] = 0x08;
|
||||
return 2; /* 3.5" 2HD XDF */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int imd_track_is_interleave(int drive, int side, int track)
|
||||
{
|
||||
int i, effective_sectors;
|
||||
char *r_map;
|
||||
int track_spt;
|
||||
|
||||
effective_sectors = 0;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
imd[drive].interleave_ordered_pos[i][side] = 0;
|
||||
}
|
||||
|
||||
track_spt = imd[drive].tracks[track][side].params[3];
|
||||
|
||||
r_map = imd[drive].buffer + imd[drive].tracks[track][side].r_map_offs;
|
||||
|
||||
if (imd[drive].tracks[track][side].params[2] & 0xC0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (track_spt != 21)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (imd[drive].tracks[track][side].params[4] != 2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < track_spt; i++)
|
||||
{
|
||||
if ((r_map[i] >= 1) && (r_map[i] <= track_spt))
|
||||
{
|
||||
effective_sectors++;
|
||||
imd[drive].interleave_ordered_pos[(int) r_map[i]][side] = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (effective_sectors == track_spt)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void imd_sector_to_buffer(int drive, int track, int side, uint8_t *buffer, int sector, int len)
|
||||
{
|
||||
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 n = 0;
|
||||
int ssize = 512;
|
||||
|
||||
int track_rate = 0;
|
||||
|
||||
int track_gap2 = 22;
|
||||
int track_gap3 = 12;
|
||||
|
||||
int xdf_type = 0;
|
||||
int interleave_type = 0;
|
||||
|
||||
int is_trackx = 0;
|
||||
|
||||
int xdf_spt = 0;
|
||||
int xdf_sector = 0;
|
||||
|
||||
int ordered_pos = 0;
|
||||
|
||||
int real_sector = 0;
|
||||
int actual_sector = 0;
|
||||
|
||||
char *c_map = NULL;
|
||||
char *h_map = NULL;
|
||||
char *r_map;
|
||||
char *n_map = NULL;
|
||||
uint8_t *data;
|
||||
uint32_t track_buf_pos[2] = { 0, 0 };
|
||||
|
||||
if (!imd[drive].f)
|
||||
return;
|
||||
|
||||
if (!imd[drive].track_width && 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);
|
||||
|
||||
d86f_zero_bit_field(drive, 0);
|
||||
d86f_zero_bit_field(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;
|
||||
if ((imd[drive].current_side_flags[side] & 0x27) == 0x21) track_rate = 2;
|
||||
|
||||
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][(int) 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);
|
||||
|
||||
interleave_type = imd_track_is_interleave(drive, side, track);
|
||||
|
||||
current_pos = d86f_prepare_pretrack(drive, side, 0);
|
||||
|
||||
if (!xdf_type)
|
||||
{
|
||||
for (sector = 0; sector < imd[drive].tracks[track][side].params[3]; sector++)
|
||||
{
|
||||
if (interleave_type == 0)
|
||||
{
|
||||
real_sector = r_map[sector];
|
||||
actual_sector = sector;
|
||||
}
|
||||
else
|
||||
{
|
||||
real_sector = dmf_r[sector];
|
||||
actual_sector = imd[drive].interleave_ordered_pos[real_sector][side];
|
||||
}
|
||||
id[0] = (h & 0x80) ? c_map[actual_sector] : c;
|
||||
id[1] = (h & 0x40) ? h_map[actual_sector] : (h & 1);
|
||||
id[2] = real_sector;
|
||||
id[3] = (n == 0xFF) ? n_map[actual_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[actual_sector]];
|
||||
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, actual_sector, ssize);
|
||||
current_pos = d86f_prepare_sector(drive, side, current_pos, id, data, ssize, 22, track_gap3, deleted, bad_crc);
|
||||
track_buf_pos[side] += ssize;
|
||||
|
||||
if (sector == 0)
|
||||
{
|
||||
d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
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, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], deleted, bad_crc);
|
||||
}
|
||||
else
|
||||
{
|
||||
current_pos = d86f_prepare_sector(drive, side, current_pos, id, data, ssize, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], deleted, bad_crc);
|
||||
}
|
||||
|
||||
track_buf_pos[side] += ssize;
|
||||
|
||||
if (sector == 0)
|
||||
{
|
||||
d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
char *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] = (sh & 0x80) ? c_map[i] : sc;
|
||||
id[1] = (sh & 0x40) ? h_map[i] : (sh & 1);
|
||||
id[2] = r_map[i];
|
||||
id[3] = (sn == 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;
|
||||
|
||||
int i = 0;
|
||||
|
||||
char *n_map;
|
||||
|
||||
uint8_t h, n, spt;
|
||||
uint32_t ssize;
|
||||
|
||||
if (writeprot[drive])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (side = 0; side < imd[drive].sides; side++)
|
||||
{
|
||||
if (imd[drive].tracks[track][side].is_present)
|
||||
{
|
||||
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 & 1))
|
||||
{
|
||||
return 0xf6; /* Should never happen. */
|
||||
}
|
||||
return imd[drive].current_data[side][pos + 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].extra_bit_cells = null_extra_bit_cells;
|
||||
d86f_handler[drive].encoded_data = common_encoded_data;
|
||||
d86f_handler[drive].read_revolution = common_read_revolution;
|
||||
d86f_handler[drive].index_hole_pos = null_index_hole_pos;
|
||||
d86f_handler[drive].get_raw_size = common_get_raw_size;
|
||||
d86f_handler[drive].check_crc = 1;
|
||||
d86f_set_version(drive, 0x0063);
|
||||
}
|
||||
26
src/floppy/floppy_imd.h
Normal file
26
src/floppy/floppy_imd.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the IMD floppy image format.
|
||||
*
|
||||
* Version: @(#)floppy_imd.h 1.0.2 2017/09/03
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
*/
|
||||
#ifndef EMU_FLOPPY_IMD_H
|
||||
# define EMU_FLOPPY_IMD_H
|
||||
|
||||
|
||||
extern void imd_init(void);
|
||||
extern void imd_load(int drive, wchar_t *fn);
|
||||
extern void imd_close(int drive);
|
||||
extern void imd_seek(int drive, int track);
|
||||
|
||||
|
||||
#endif /*EMU_FLOPPY_IMD_H*/
|
||||
1149
src/floppy/floppy_img.c
Normal file
1149
src/floppy/floppy_img.c
Normal file
File diff suppressed because it is too large
Load Diff
29
src/floppy/floppy_img.h
Normal file
29
src/floppy/floppy_img.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the raw sector-based floppy image format,
|
||||
* as well as the Japanese FDI, CopyQM, and FDF formats.
|
||||
*
|
||||
* Version: @(#)floppy_img.h 1.0.2 2017/09/03
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
*/
|
||||
#ifndef EMU_FLOPPY_IMG_H
|
||||
# define EMU_FLOPPY_IMG_H
|
||||
|
||||
|
||||
extern void img_init(void);
|
||||
extern void img_load(int drive, wchar_t *fn);
|
||||
extern void img_close(int drive);
|
||||
extern void img_seek(int drive, int track);
|
||||
|
||||
|
||||
#endif /*EMU_FLOPPY_IMG_H*/
|
||||
1241
src/floppy/floppy_td0.c
Normal file
1241
src/floppy/floppy_td0.c
Normal file
File diff suppressed because it is too large
Load Diff
34
src/floppy/floppy_td0.h
Normal file
34
src/floppy/floppy_td0.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the Teledisk floppy image format.
|
||||
*
|
||||
* Version: @(#)floppy_td0.h 1.0.2 2017/09/03
|
||||
*
|
||||
* Authors: Milodrag Milanovic,
|
||||
* Haruhiko OKUMURA,
|
||||
* Haruyasu YOSHIZAKI,
|
||||
* Kenji RIKITAKE,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 1988-2017 Haruhiko OKUMURA.
|
||||
* Copyright 1988-2017 Haruyasu YOSHIZAKI.
|
||||
* Copyright 1988-2017 Kenji RIKITAKE.
|
||||
* Copyright 2013-2017 Milodrag Milanovic.
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
*/
|
||||
#ifndef EMU_FLOPPY_TD0_H
|
||||
# define EMU_FLOPPY_TD0_H
|
||||
|
||||
|
||||
extern void td0_init(void);
|
||||
extern void td0_load(int drive, wchar_t *fn);
|
||||
extern void td0_close(int drive);
|
||||
extern void td0_seek(int drive, int track);
|
||||
|
||||
|
||||
#endif /*EMU_FLOPPY_TD0_H*/
|
||||
Reference in New Issue
Block a user