Various changes to FDC emulation.

Support for multiple disc image formats.
Added preliminary FDI support.
This commit is contained in:
TomW 2015-03-19 21:33:19 +00:00
commit a8159f8c09
20 changed files with 3797 additions and 393 deletions

View file

@ -17,8 +17,8 @@ pcem_LDADD = $(allegro_LIBS) -lopenal -lalut
pcem_SOURCES = 386.c 808x.c acer386sx.c ali1429.c allegro-gui.c allegro-gui-configure.c \
allegro-gui-hdconf.c allegro-joystick.c allegro-keyboard.c allegro-main.c \
allegro-midi.c allegro-mouse.c allegro-video.c amstrad.c cdrom-ioctl-linux.c cdrom-null.c \
config.c cpu.c dac.c device.c dma.c fdc.c gameport.c headland.c i430lx.c i430fx.c i430vx.c \
ide.c intel.c intel_flash.c io.c jim.c \
config.c cpu.c dac.c device.c disc.c disc_fdi.c disc_img.c dma.c fdc.c fdi2raw.c gameport.c \
headland.c i430lx.c i430fx.c i430vx.c ide.c intel.c intel_flash.c io.c jim.c \
keyboard.c keyboard_amstrad.c keyboard_at.c keyboard_olim24.c keyboard_pcjr.c keyboard_xt.c \
linux-time.c lpt.c mcr.c mem.c model.c mouse.c mouse_ps2.c mouse_serial.c neat.c nmi.c nvr.c \
olivetti_m24.c opti.c pc.c pci.c pic.c piix.c pit.c ppi.c rom.c serial.c sis496.c sound.c \

View file

@ -58,7 +58,9 @@ am_pcem_OBJECTS = pcem-386.$(OBJEXT) pcem-808x.$(OBJEXT) \
pcem-allegro-video.$(OBJEXT) pcem-amstrad.$(OBJEXT) \
pcem-cdrom-ioctl-linux.$(OBJEXT) pcem-cdrom-null.$(OBJEXT) \
pcem-config.$(OBJEXT) pcem-cpu.$(OBJEXT) pcem-dac.$(OBJEXT) \
pcem-device.$(OBJEXT) pcem-dma.$(OBJEXT) pcem-fdc.$(OBJEXT) \
pcem-device.$(OBJEXT) pcem-disc.$(OBJEXT) \
pcem-disc_fdi.$(OBJEXT) pcem-disc_img.$(OBJEXT) \
pcem-dma.$(OBJEXT) pcem-fdc.$(OBJEXT) pcem-fdi2raw.$(OBJEXT) \
pcem-gameport.$(OBJEXT) pcem-headland.$(OBJEXT) \
pcem-i430lx.$(OBJEXT) pcem-i430fx.$(OBJEXT) \
pcem-i430vx.$(OBJEXT) pcem-ide.$(OBJEXT) pcem-intel.$(OBJEXT) \
@ -231,8 +233,8 @@ pcem_LDADD = $(allegro_LIBS) -lopenal -lalut
pcem_SOURCES = 386.c 808x.c acer386sx.c ali1429.c allegro-gui.c allegro-gui-configure.c \
allegro-gui-hdconf.c allegro-joystick.c allegro-keyboard.c allegro-main.c \
allegro-midi.c allegro-mouse.c allegro-video.c amstrad.c cdrom-ioctl-linux.c cdrom-null.c \
config.c cpu.c dac.c device.c dma.c fdc.c gameport.c headland.c i430lx.c i430fx.c i430vx.c \
ide.c intel.c intel_flash.c io.c jim.c \
config.c cpu.c dac.c device.c disc.c disc_fdi.c disc_img.c dma.c fdc.c fdi2raw.c gameport.c \
headland.c i430lx.c i430fx.c i430vx.c ide.c intel.c intel_flash.c io.c jim.c \
keyboard.c keyboard_amstrad.c keyboard_at.c keyboard_olim24.c keyboard_pcjr.c keyboard_xt.c \
linux-time.c lpt.c mcr.c mem.c model.c mouse.c mouse_ps2.c mouse_serial.c neat.c nmi.c nvr.c \
olivetti_m24.c opti.c pc.c pci.c pic.c piix.c pit.c ppi.c rom.c serial.c sis496.c sound.c \
@ -360,8 +362,12 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cpu.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-dac.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-disc.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-disc_fdi.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-disc_img.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-dma.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-fdc.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-fdi2raw.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-gameport.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-headland.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-i430fx.Po@am__quote@
@ -769,6 +775,48 @@ pcem-device.obj: device.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-device.obj `if test -f 'device.c'; then $(CYGPATH_W) 'device.c'; else $(CYGPATH_W) '$(srcdir)/device.c'; fi`
pcem-disc.o: disc.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-disc.o -MD -MP -MF $(DEPDIR)/pcem-disc.Tpo -c -o pcem-disc.o `test -f 'disc.c' || echo '$(srcdir)/'`disc.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pcem-disc.Tpo $(DEPDIR)/pcem-disc.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='disc.c' object='pcem-disc.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-disc.o `test -f 'disc.c' || echo '$(srcdir)/'`disc.c
pcem-disc.obj: disc.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-disc.obj -MD -MP -MF $(DEPDIR)/pcem-disc.Tpo -c -o pcem-disc.obj `if test -f 'disc.c'; then $(CYGPATH_W) 'disc.c'; else $(CYGPATH_W) '$(srcdir)/disc.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pcem-disc.Tpo $(DEPDIR)/pcem-disc.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='disc.c' object='pcem-disc.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-disc.obj `if test -f 'disc.c'; then $(CYGPATH_W) 'disc.c'; else $(CYGPATH_W) '$(srcdir)/disc.c'; fi`
pcem-disc_fdi.o: disc_fdi.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-disc_fdi.o -MD -MP -MF $(DEPDIR)/pcem-disc_fdi.Tpo -c -o pcem-disc_fdi.o `test -f 'disc_fdi.c' || echo '$(srcdir)/'`disc_fdi.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pcem-disc_fdi.Tpo $(DEPDIR)/pcem-disc_fdi.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='disc_fdi.c' object='pcem-disc_fdi.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-disc_fdi.o `test -f 'disc_fdi.c' || echo '$(srcdir)/'`disc_fdi.c
pcem-disc_fdi.obj: disc_fdi.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-disc_fdi.obj -MD -MP -MF $(DEPDIR)/pcem-disc_fdi.Tpo -c -o pcem-disc_fdi.obj `if test -f 'disc_fdi.c'; then $(CYGPATH_W) 'disc_fdi.c'; else $(CYGPATH_W) '$(srcdir)/disc_fdi.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pcem-disc_fdi.Tpo $(DEPDIR)/pcem-disc_fdi.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='disc_fdi.c' object='pcem-disc_fdi.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-disc_fdi.obj `if test -f 'disc_fdi.c'; then $(CYGPATH_W) 'disc_fdi.c'; else $(CYGPATH_W) '$(srcdir)/disc_fdi.c'; fi`
pcem-disc_img.o: disc_img.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-disc_img.o -MD -MP -MF $(DEPDIR)/pcem-disc_img.Tpo -c -o pcem-disc_img.o `test -f 'disc_img.c' || echo '$(srcdir)/'`disc_img.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pcem-disc_img.Tpo $(DEPDIR)/pcem-disc_img.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='disc_img.c' object='pcem-disc_img.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-disc_img.o `test -f 'disc_img.c' || echo '$(srcdir)/'`disc_img.c
pcem-disc_img.obj: disc_img.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-disc_img.obj -MD -MP -MF $(DEPDIR)/pcem-disc_img.Tpo -c -o pcem-disc_img.obj `if test -f 'disc_img.c'; then $(CYGPATH_W) 'disc_img.c'; else $(CYGPATH_W) '$(srcdir)/disc_img.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pcem-disc_img.Tpo $(DEPDIR)/pcem-disc_img.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='disc_img.c' object='pcem-disc_img.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-disc_img.obj `if test -f 'disc_img.c'; then $(CYGPATH_W) 'disc_img.c'; else $(CYGPATH_W) '$(srcdir)/disc_img.c'; fi`
pcem-dma.o: dma.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-dma.o -MD -MP -MF $(DEPDIR)/pcem-dma.Tpo -c -o pcem-dma.o `test -f 'dma.c' || echo '$(srcdir)/'`dma.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pcem-dma.Tpo $(DEPDIR)/pcem-dma.Po
@ -797,6 +845,20 @@ pcem-fdc.obj: fdc.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-fdc.obj `if test -f 'fdc.c'; then $(CYGPATH_W) 'fdc.c'; else $(CYGPATH_W) '$(srcdir)/fdc.c'; fi`
pcem-fdi2raw.o: fdi2raw.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-fdi2raw.o -MD -MP -MF $(DEPDIR)/pcem-fdi2raw.Tpo -c -o pcem-fdi2raw.o `test -f 'fdi2raw.c' || echo '$(srcdir)/'`fdi2raw.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pcem-fdi2raw.Tpo $(DEPDIR)/pcem-fdi2raw.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fdi2raw.c' object='pcem-fdi2raw.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-fdi2raw.o `test -f 'fdi2raw.c' || echo '$(srcdir)/'`fdi2raw.c
pcem-fdi2raw.obj: fdi2raw.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-fdi2raw.obj -MD -MP -MF $(DEPDIR)/pcem-fdi2raw.Tpo -c -o pcem-fdi2raw.obj `if test -f 'fdi2raw.c'; then $(CYGPATH_W) 'fdi2raw.c'; else $(CYGPATH_W) '$(srcdir)/fdi2raw.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pcem-fdi2raw.Tpo $(DEPDIR)/pcem-fdi2raw.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fdi2raw.c' object='pcem-fdi2raw.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-fdi2raw.obj `if test -f 'fdi2raw.c'; then $(CYGPATH_W) 'fdi2raw.c'; else $(CYGPATH_W) '$(srcdir)/fdi2raw.c'; fi`
pcem-gameport.o: gameport.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-gameport.o -MD -MP -MF $(DEPDIR)/pcem-gameport.Tpo -c -o pcem-gameport.o `test -f 'gameport.c' || echo '$(srcdir)/'`gameport.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pcem-gameport.Tpo $(DEPDIR)/pcem-gameport.Po

View file

@ -5,11 +5,11 @@ WINDRES = windres.exe
CFLAGS = -O3 -march=i686 -fomit-frame-pointer
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o \
codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_pentium.o codegen_x86.o config.o cpu.o dac.o \
device.o dma.o fdc.o gameport.o headland.o i430lx.o i430fx.o i430vx.o ide.o intel.o \
intel_flash.o io.o jim.o keyboard.o keyboard_amstrad.o keyboard_at.o keyboard_olim24.o \
keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o model.o mouse.o mouse_ps2.o mouse_serial.o \
neat.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pci.o pic.o piix.o pit.o ppi.o rom.o serial.o \
sis496.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o sound_dbopl.o \
device.o disc.o disc_fdi.o disc_img.o dma.o fdc.o fdi2raw.o gameport.o headland.o i430lx.o i430fx.o \
i430vx.o ide.o intel.o intel_flash.o io.o jim.o keyboard.o keyboard_amstrad.o keyboard_at.o \
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o model.o mouse.o mouse_ps2.o \
mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pci.o pic.o piix.o pit.o ppi.o rom.o \
serial.o sis496.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o sound_dbopl.o \
sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_resid.o \
sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \
soundopenal.o timer.o um8881f.o um8669f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o \

View file

@ -2,6 +2,7 @@
#include "allegro-main.h"
#include "allegro-gui.h"
#include "device.h"
#include "disc.h"
#include "ide.h"
static int file_return(void)
@ -35,11 +36,11 @@ static int disc_load_a()
int ret;
int xsize = SCREEN_W - 32, ysize = SCREEN_H - 64;
strcpy(fn, discfns[0]);
ret = file_select_ex("Please choose a disc image", fn, "IMG;IMA", 260, xsize, ysize);
ret = file_select_ex("Please choose a disc image", fn, "IMG;IMA;FDI", 260, xsize, ysize);
if (ret)
{
savedisc(0);
loaddisc(0, fn);
disc_close(0);
disc_load(0, fn);
saveconfig();
}
return D_O_K;
@ -51,11 +52,11 @@ static int disc_load_b()
int ret;
int xsize = SCREEN_W - 32, ysize = SCREEN_H - 64;
strcpy(fn, discfns[1]);
ret = file_select_ex("Please choose a disc image", fn, "IMG;IMA", 260, xsize, ysize);
ret = file_select_ex("Please choose a disc image", fn, "IMG;IMA;FDI", 260, xsize, ysize);
if (ret)
{
savedisc(1);
loaddisc(1, fn);
disc_close(1);
disc_load(1, fn);
saveconfig();
}
return D_O_K;
@ -63,8 +64,7 @@ static int disc_load_b()
static int disc_eject_a()
{
savedisc(0);
ejectdisc(0);
disc_close(0);
saveconfig();
return D_O_K;
@ -72,8 +72,7 @@ static int disc_eject_a()
static int disc_eject_b()
{
savedisc(1);
ejectdisc(1);
disc_close(1);
saveconfig();
return D_O_K;

View file

@ -3,6 +3,7 @@
#define get_filename allegro_get_filename
#define append_filename allegro_append_filename
#define put_backslash allegro_put_backslash
#define get_extension allegro_get_extension
#define GFX_VGA allegro_GFX_VGA
#include <allegro.h>
@ -13,3 +14,4 @@
#undef get_filename
#undef append_filename
#undef put_backslash
#undef get_extension

View file

@ -354,6 +354,22 @@ void put_backslash(char *s)
s[c] = '/';
}
char *get_extension(char *s)
{
int c = strlen(s) - 1;
if (c <= 0)
return s;
while (c && s[c] != '.')
c--;
if (!c)
return &s[strlen(s)];
return &s[c+1];
}
void config_save(char *fn)
{
FILE *f = fopen(fn, "wt");

View file

@ -6,6 +6,7 @@ void config_set_string(char *head, char *name, char *val);
char *get_filename(char *s);
void append_filename(char *dest, char *s1, char *s2, int size);
void put_backslash(char *s);
char *get_extension(char *s);
void config_load(char *fn);
void config_save(char *fn);

203
src/disc.c Normal file
View file

@ -0,0 +1,203 @@
#include "ibm.h"
#include "config.h"
#include "disc.h"
#include "disc_fdi.h"
#include "disc_img.h"
#include "fdc.h"
#include "timer.h"
int disc_drivesel = 0;
int disc_poll_time = 16;
int disc_track[2];
int writeprot[2], fwriteprot[2];
DRIVE drives[2];
int curdrive = 0;
//char discfns[2][260] = {"", ""};
int defaultwriteprot = 0;
int fdc_time;
int disc_time;
int fdc_ready;
int drive_empty[2] = {1, 1};
int disc_changed[2];
int motorspin;
int motoron;
int fdc_indexcount = 52;
/*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)();*/
static struct
{
char *ext;
void (*load)(int drive, char *fn);
void (*close)(int drive);
int size;
}
loaders[]=
{
{"IMG", img_load, img_close, -1},
{"IMA", img_load, img_close, -1},
{"FDI", fdi_load, fdi_close, -1},
{0,0,0}
};
static int driveloaders[4];
void disc_load(int drive, char *fn)
{
int c = 0, size;
char *p;
FILE *f;
// pclog("disc_load %i %s\n", drive, fn);
// setejecttext(drive, "");
if (!fn) return;
p = get_extension(fn);
if (!p) return;
// setejecttext(drive, fn);
pclog("Loading :%i %s %s\n", drive, fn,p);
f = fopen(fn, "rb");
if (!f) return;
fseek(f, -1, SEEK_END);
size = ftell(f) + 1;
fclose(f);
while (loaders[c].ext)
{
if (!strcasecmp(p, loaders[c].ext) && (size == loaders[c].size || loaders[c].size == -1))
{
pclog("Loading as %s\n", p);
driveloaders[drive] = c;
loaders[c].load(drive, fn);
drive_empty[drive] = 0;
disc_changed[drive] = 1;
strcpy(discfns[drive], fn);
return;
}
c++;
}
pclog("Couldn't load %s %s\n",fn,p);
drive_empty[drive] = 1;
discfns[drive][0] = 0;
}
void disc_close(int drive)
{
// pclog("disc_close %i\n", drive);
if (loaders[driveloaders[drive]].close) loaders[driveloaders[drive]].close(drive);
drive_empty[drive] = 1;
discfns[drive][0] = 0;
}
int disc_notfound=0;
static int disc_period = 32;
void disc_poll()
{
disc_poll_time += disc_period * TIMER_USEC;
if (drives[disc_drivesel].poll)
drives[disc_drivesel].poll();
if (disc_notfound)
{
disc_notfound--;
if (!disc_notfound)
fdc_notfound();
}
}
void disc_set_rate(int rate)
{
switch (rate)
{
case 0: /*High density*/
case 1: /*High density (360 rpm)*/
disc_period = 16;
break;
case 2: /*Double density*/
disc_period = 32;
break;
case 3: /*Extended density*/
disc_period = 8;
break;
}
}
void disc_init()
{
// pclog("disc_init %p\n", drives);
drives[0].poll = drives[1].poll = 0;
drives[0].seek = drives[1].seek = 0;
drives[0].readsector = drives[1].readsector = 0;
curdrive = 0;
disc_period = 32;
timer_add(disc_poll, &disc_poll_time, &motoron, NULL);
}
int oldtrack[2] = {0, 0};
void disc_seek(int drive, int track)
{
if (drives[drive].seek)
drives[drive].seek(drive, track);
// if (track != oldtrack[drive])
fdc_discchange_clear(drive);
// ddnoise_seek(track - oldtrack[drive]);
oldtrack[drive] = track;
disctime = 5000;
}
void disc_readsector(int drive, int sector, int track, int side, int density)
{
if (drives[drive].readsector)
drives[drive].readsector(drive, sector, track, side, density);
else
disc_notfound = 1000;
}
void disc_writesector(int drive, int sector, int track, int side, int density)
{
if (drives[drive].writesector)
drives[drive].writesector(drive, sector, track, side, density);
else
disc_notfound = 1000;
}
void disc_readaddress(int drive, int track, int side, int density)
{
if (drives[drive].readaddress)
drives[drive].readaddress(drive, track, side, density);
else
disc_notfound = 1000;
}
void disc_format(int drive, int track, int side, int density)
{
if (drives[drive].format)
drives[drive].format(drive, track, side, density);
else
disc_notfound = 1000;
}
void disc_stop(int drive)
{
if (drives[drive].stop)
drives[drive].stop(drive);
}

57
src/disc.h Normal file
View file

@ -0,0 +1,57 @@
typedef struct
{
void (*seek)(int drive, int track);
void (*readsector)(int drive, int sector, int track, int side, int density);
void (*writesector)(int drive, int sector, int track, int side, int density);
void (*readaddress)(int drive, int track, int side, int density);
void (*format)(int drive, int track, int side, int density);
void (*stop)();
void (*poll)();
} DRIVE;
extern DRIVE drives[2];
extern int curdrive;
void disc_load(int drive, char *fn);
void disc_new(int drive, char *fn);
void disc_close(int drive);
void disc_init();
void disc_poll();
void disc_seek(int drive, int track);
void disc_readsector(int drive, int sector, int track, int side, int density);
void disc_writesector(int drive, int sector, int track, int side, int density);
void disc_readaddress(int drive, int track, int side, int density);
void disc_format(int drive, int track, int side, int density);
void disc_stop(int drive);
int disc_empty(int drive);
void disc_set_rate(int rate);
extern int disc_time;
extern int disc_poll_time;
extern int disc_drivesel;
void fdc_callback();
int 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();
/*extern int fdc_time;
extern int fdc_ready;
extern int fdc_indexcount;*/
extern int motorspin;
extern int motoron;
extern int defaultwriteprot;
//extern char discfns[4][260];
extern int writeprot[2], fwriteprot[2];
extern int disc_track[2];
extern int disc_changed[2];
extern int drive_empty[2];

463
src/disc_fdi.c Normal file
View file

@ -0,0 +1,463 @@
#include <stdio.h>
#include <stdint.h>
#include "ibm.h"
#include "disc.h"
#include "disc_fdi.h"
#include "fdi2raw.h"
static struct
{
FILE *f;
FDI *h;
uint8_t track_data[2][4][256*1024];
int sides;
int tracklen[2][4];
int trackindex[2][4];
int lasttrack;
} fdi[2];
static uint8_t fdi_timing[256*1024];
static int fdi_pos;
static int fdi_revs;
static int fdi_sector, fdi_track, fdi_side, fdi_drive, fdi_density;
static int fdi_inread, fdi_inwrite, fdi_readpos, fdi_inreadaddr;
static uint16_t CRCTable[256];
static int pollbytesleft=0,pollbitsleft=0;
static void fdi_setupcrc(uint16_t poly, uint16_t rvalue)
{
int c = 256, bc;
uint16_t crctemp;
while(c--)
{
crctemp = c << 8;
bc = 8;
while(bc--)
{
if(crctemp & 0x8000)
{
crctemp = (crctemp << 1) ^ poly;
}
else
{
crctemp <<= 1;
}
}
CRCTable[c] = crctemp;
}
}
void fdi_init()
{
// printf("FDI reset\n");
memset(&fdi, 0, sizeof(fdi));
fdi_setupcrc(0x1021, 0xcdb4);
}
void fdi_load(int drive, char *fn)
{
writeprot[drive] = fwriteprot[drive] = 1;
fdi[drive].f = fopen(fn, "rb");
if (!fdi[drive].f) return;
fdi[drive].h = fdi2raw_header(fdi[drive].f);
// if (!fdih[drive]) printf("Failed to load!\n");
fdi[drive].lasttrack = fdi2raw_get_last_track(fdi[drive].h);
fdi[drive].sides = (fdi[drive].lasttrack > 83) ? 2 : 1;
// printf("Last track %i\n",fdilasttrack[drive]);
drives[drive].seek = fdi_seek;
drives[drive].readsector = fdi_readsector;
drives[drive].writesector = fdi_writesector;
drives[drive].readaddress = fdi_readaddress;
drives[drive].poll = fdi_poll;
drives[drive].format = fdi_format;
drives[drive].stop = fdi_stop;
// pclog("Loaded as FDI\n");
}
void fdi_close(int drive)
{
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)
{
int c;
int density;
if (!fdi[drive].f)
return;
// printf("Track start %i\n",track);
if (track < 0)
track = 0;
if (track > fdi[drive].lasttrack)
track = fdi[drive].lasttrack - 1;
for (density = 0; density < 4; density++)
{
int c = fdi2raw_loadtrack(fdi[drive].h, (uint16_t *)fdi[drive].track_data[0][density],
(uint16_t *)fdi_timing,
track * fdi[drive].sides,
&fdi[drive].tracklen[0][density],
&fdi[drive].trackindex[0][density], NULL, density);
if (!c)
memset(fdi[drive].track_data[0][density], 0, fdi[drive].tracklen[0][density]);
if (fdi[drive].sides == 2)
{
c = fdi2raw_loadtrack(fdi[drive].h, (uint16_t *)fdi[drive].track_data[1][density],
(uint16_t *)fdi_timing,
(track * fdi[drive].sides) + 1,
&fdi[drive].tracklen[1][density],
&fdi[drive].trackindex[1][density], NULL, density);
if (!c)
memset(fdi[drive].track_data[1][density], 0, fdi[drive].tracklen[1][density]);
}
else
{
memset(fdi[drive].track_data[1][density], 0, 65536);
fdi[drive].tracklen[1][density] = fdi[drive].tracklen[1][density] = 10000;
}
}
}
void fdi_writeback(int drive, int track)
{
return;
}
void fdi_readsector(int drive, int sector, int track, int side, int rate)
{
fdi_revs = 0;
fdi_sector = sector;
fdi_track = track;
fdi_side = side;
fdi_drive = drive;
if (rate == 2)
fdi_density = 1;
if (rate == 0)
fdi_density = 2;
if (rate == 3)
fdi_density = 3;
// pclog("FDI Read sector %i %i %i %i %i\n",drive,side,track,sector, fdi_density);
// if (pollbytesleft)
// pclog("In the middle of a sector!\n");
fdi_inread = 1;
fdi_inwrite = 0;
fdi_inreadaddr = 0;
fdi_readpos = 0;
}
void fdi_writesector(int drive, int sector, int track, int side, int rate)
{
fdi_revs = 0;
fdi_sector = sector;
fdi_track = track;
fdi_side = side;
fdi_drive = drive;
if (rate == 2)
fdi_density = 1;
if (rate == 0)
fdi_density = 2;
if (rate == 3)
fdi_density = 3;
// pclog("Write sector %i %i %i %i\n",drive,side,track,sector);
fdi_inread = 0;
fdi_inwrite = 1;
fdi_inreadaddr = 0;
fdi_readpos = 0;
}
void fdi_readaddress(int drive, int track, int side, int rate)
{
fdi_revs = 0;
fdi_track = track;
fdi_side = side;
fdi_drive = drive;
if (rate == 2)
fdi_density = 1;
if (rate == 0)
fdi_density = 2;
if (rate == 3)
fdi_density = 3;
// pclog("Read address %i %i %i %i %i %p\n",drive,side,track, rate, fdi_density, &fdi_inreadaddr);
fdi_inread = 0;
fdi_inwrite = 0;
fdi_inreadaddr = 1;
fdi_readpos = 0;
}
void fdi_format(int drive, int track, int side, int rate)
{
fdi_revs = 0;
fdi_track = track;
fdi_side = side;
fdi_drive = drive;
if (rate == 2)
fdi_density = 1;
if (rate == 0)
fdi_density = 2;
if (rate == 3)
fdi_density = 3;
// pclog("Format %i %i %i\n",drive,side,track);
fdi_inread = 0;
fdi_inwrite = 1;
fdi_inreadaddr = 0;
fdi_readpos = 0;
}
static uint16_t fdi_buffer;
static int readidpoll=0,readdatapoll=0,fdi_nextsector=0,inreadop=0;
static uint8_t fdi_sectordat[1026];
static int lastfdidat[2],sectorcrc[2];
static int sectorsize,fdc_sectorsize;
static int ddidbitsleft=0;
static uint8_t decodefm(uint16_t dat)
{
uint8_t temp;
temp = 0;
if (dat & 0x0001) temp |= 1;
if (dat & 0x0004) temp |= 2;
if (dat & 0x0010) temp |= 4;
if (dat & 0x0040) temp |= 8;
if (dat & 0x0100) temp |= 16;
if (dat & 0x0400) temp |= 32;
if (dat & 0x1000) temp |= 64;
if (dat & 0x4000) temp |= 128;
return temp;
}
void fdi_stop()
{
// pclog("fdi_stop\n");
fdi_inread = fdi_inwrite = fdi_inreadaddr = 0;
fdi_nextsector = ddidbitsleft = pollbitsleft = 0;
}
static uint16_t crc;
static void calccrc(uint8_t byte)
{
crc = (crc << 8) ^ CRCTable[(crc >> 8)^byte];
}
static int fdi_indextime_blank = 6250 * 8;
void fdi_poll()
{
int tempi, c;
int bitcount;
for (bitcount = 0; bitcount < 16; bitcount++)
{
if (fdi_pos >= fdi[fdi_drive].tracklen[fdi_side][fdi_density])
{
fdi_pos = 0;
if (fdi[fdi_drive].tracklen[fdi_side][fdi_density])
fdc_indexpulse();
else
{
fdi_indextime_blank--;
if (!fdi_indextime_blank)
{
fdi_indextime_blank = 6250 * 8;
fdc_indexpulse();
}
}
}
tempi = fdi[fdi_drive].track_data[fdi_side][fdi_density][((fdi_pos >> 3) & 0xFFFF) ^ 1] & (1 << (7 - (fdi_pos & 7)));
fdi_pos++;
fdi_buffer <<= 1;
fdi_buffer |= (tempi ? 1 : 0);
if (fdi_inwrite)
{
fdi_inwrite = 0;
fdc_writeprotect();
return;
}
if (!fdi_inread && !fdi_inreadaddr)
return;
if (fdi_pos == fdi[fdi_drive].trackindex[fdi_side][fdi_density])
{
fdi_revs++;
if (fdi_revs == 3)
{
// pclog("Not found!\n");
fdc_notfound();
fdi_inread = fdi_inreadaddr = 0;
return;
}
}
if (pollbitsleft)
{
pollbitsleft--;
if (!pollbitsleft)
{
pollbytesleft--;
if (pollbytesleft) pollbitsleft = 16; /*Set up another word if we need it*/
if (readidpoll)
{
fdi_sectordat[5 - pollbytesleft] = decodefm(fdi_buffer);
if (fdi_inreadaddr && !fdc_sectorid)// && pollbytesleft > 1)
{
// rpclog("inreadaddr - %02X\n", fdi_sectordat[5 - pollbytesleft]);
fdc_data(fdi_sectordat[5 - pollbytesleft]);
}
if (!pollbytesleft)
{
// pclog("Header over %i,%i %i,%i\n", fdi_sectordat[0], fdi_sectordat[2], fdi_track, fdi_sector);
if ((fdi_sectordat[0] == fdi_track && fdi_sectordat[2] == fdi_sector) || fdi_inreadaddr)
{
crc = (fdi_density) ? 0xcdb4 : 0xffff;
calccrc(0xFE);
for (c = 0; c < 4; c++)
calccrc(fdi_sectordat[c]);
if ((crc >> 8) != fdi_sectordat[4] || (crc & 0xFF) != fdi_sectordat[5])
{
// pclog("Header CRC error : %02X %02X %02X %02X\n",crc>>8,crc&0xFF,fdi_sectordat[4],fdi_sectordat[5]);
// dumpregs();
// exit(-1);
inreadop = 0;
if (fdi_inreadaddr)
{
// rpclog("inreadaddr - %02X\n", fdi_sector);
// fdc_data(fdi_sector);
if (fdc_sectorid)
fdc_sectorid(fdi_sectordat[0], fdi_sectordat[1], fdi_sectordat[2], fdi_sectordat[3], fdi_sectordat[4], fdi_sectordat[5]);
else
fdc_finishread();
}
else fdc_headercrcerror();
return;
}
// pclog("Sector %i,%i %i,%i\n", fdi_sectordat[0], fdi_sectordat[2], fdi_track, fdi_sector);
if (fdi_sectordat[0] == fdi_track && fdi_sectordat[2] == fdi_sector && fdi_inread && !fdi_inreadaddr)
{
fdi_nextsector = 1;
readidpoll = 0;
sectorsize = (1 << (fdi_sectordat[3] + 7)) + 2;
fdc_sectorsize = fdi_sectordat[3];
}
if (fdi_inreadaddr)
{
if (fdc_sectorid)
fdc_sectorid(fdi_sectordat[0], fdi_sectordat[1], fdi_sectordat[2], fdi_sectordat[3], fdi_sectordat[4], fdi_sectordat[5]);
else
fdc_finishread();
fdi_inreadaddr = 0;
}
}
}
}
if (readdatapoll)
{
// pclog("readdatapoll %i %02x\n", pollbytesleft, decodefm(fdi_buffer));
if (pollbytesleft > 1)
{
calccrc(decodefm(fdi_buffer));
}
else
sectorcrc[1 - pollbytesleft] = decodefm(fdi_buffer);
if (!pollbytesleft)
{
fdi_inread = 0;
//#if 0
if ((crc >> 8) != sectorcrc[0] || (crc & 0xFF) != sectorcrc[1])// || (fditrack==79 && fdisect==4 && fdc_side&1))
{
// pclog("Data CRC error : %02X %02X %02X %02X %i %04X %02X%02X\n",crc>>8,crc&0xFF,sectorcrc[0],sectorcrc[1],fdi_pos,crc,sectorcrc[0],sectorcrc[1]);
inreadop = 0;
fdc_data(decodefm(lastfdidat[1]));
fdc_finishread();
fdc_datacrcerror();
readdatapoll = 0;
return;
}
//#endif
// pclog("End of FDI read %02X %02X %02X %02X\n",crc>>8,crc&0xFF,sectorcrc[0],sectorcrc[1]);
fdc_data(decodefm(lastfdidat[1]));
fdc_finishread();
}
else if (lastfdidat[1] != 0)
fdc_data(decodefm(lastfdidat[1]));
lastfdidat[1] = lastfdidat[0];
lastfdidat[0] = fdi_buffer;
if (!pollbytesleft)
readdatapoll = 0;
}
}
}
if (fdi_buffer == 0x4489 && fdi_density)
{
// rpclog("Found sync\n");
ddidbitsleft = 17;
}
if (fdi_buffer == 0xF57E && !fdi_density)
{
pollbytesleft = 6;
pollbitsleft = 16;
readidpoll = 1;
}
if ((fdi_buffer == 0xF56F || fdi_buffer == 0xF56A) && !fdi_density)
{
if (fdi_nextsector)
{
pollbytesleft = sectorsize;
pollbitsleft = 16;
readdatapoll = 1;
fdi_nextsector = 0;
crc = 0xffff;
if (fdi_buffer == 0xF56A) calccrc(0xF8);
else calccrc(0xFB);
lastfdidat[0] = lastfdidat[1] = 0;
}
}
if (ddidbitsleft)
{
ddidbitsleft--;
if (!ddidbitsleft && !readdatapoll)
{
// printf("ID bits over %04X %02X %i\n",fdibuffer,decodefm(fdibuffer),fdipos);
if (decodefm(fdi_buffer) == 0xFE)
{
// printf("Sector header %i %i\n", fdi_inread, fdi_inreadaddr);
pollbytesleft = 6;
pollbitsleft = 16;
readidpoll = 1;
}
else if (decodefm(fdi_buffer) == 0xFB)
{
// printf("Data header %i %i\n", fdi_inread, fdi_inreadaddr);
if (fdi_nextsector)
{
pollbytesleft = sectorsize;
pollbitsleft = 16;
readdatapoll = 1;
fdi_nextsector = 0;
crc = 0xcdb4;
if (fdi_buffer == 0xF56A) calccrc(0xF8);
else calccrc(0xFB);
lastfdidat[0] = lastfdidat[1] = 0;
}
}
}
}
}
}

10
src/disc_fdi.h Normal file
View file

@ -0,0 +1,10 @@
void fdi_init();
void fdi_load(int drive, char *fn);
void fdi_close(int drive);
void fdi_seek(int drive, int track);
void fdi_readsector(int drive, int sector, int track, int side, int density);
void fdi_writesector(int drive, int sector, int track, int side, int density);
void fdi_readaddress(int drive, int sector, int side, int density);
void fdi_format(int drive, int sector, int side, int density);
void fdi_stop();
void fdi_poll();

307
src/disc_img.c Normal file
View file

@ -0,0 +1,307 @@
#include "ibm.h"
#include "disc.h"
#include "disc_img.h"
static struct
{
FILE *f;
uint8_t track_data[2][20*1024];
int sectors, tracks, sides;
int sector_size;
int rate;
} img[2];
//static FILE *img_f[2];
//static uint8_t trackinfoa[2][2][20*1024];
//static int img_dblside[2];
//static int img_sectors[2], img_size[2], img_trackc[2];
//static int img_dblstep[2];
//static int img_density[2];
static int img_sector, img_track, img_side, img_drive;
static int img_inread, img_readpos, img_inwrite, img_inreadaddr;
static int img_notfound;
static int img_rsector=0;
static int img_informat=0;
static int img_pause = 0;
static int img_index = 6250;
void img_init()
{
memset(img, 0, sizeof(img));
// adl[0] = adl[1] = 0;
img_notfound = 0;
}
void img_load(int drive, char *fn)
{
int size;
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;
}
fwriteprot[drive] = writeprot[drive];
fseek(img[drive].f, -1, SEEK_END);
size = ftell(img[drive].f) + 1;
img[drive].sides = 2;
img[drive].sector_size = 512;
if (size <= (160*1024)) { img[drive].sectors = 8; img[drive].tracks = 40; img[drive].sides = 1; img[drive].rate = 2; }
else if (size <= (180*1024)) { img[drive].sectors = 9; img[drive].tracks = 40; img[drive].sides = 1; img[drive].rate = 2; }
else if (size <= (320*1024)) { img[drive].sectors = 8; img[drive].tracks = 40; img[drive].rate = 2; }
else if (size <= (360*1024)) { img[drive].sectors = 9; img[drive].tracks = 40; img[drive].rate = 2; } /*Double density*/
else if (size < (1024*1024)) { img[drive].sectors = 9; img[drive].tracks = 80; img[drive].rate = 2; } /*Double density*/
else if (size <= 1228800) { img[drive].sectors = 15; img[drive].tracks = 80; img[drive].rate = 0; } /*High density 1.2MB*/
else if (size <= (0x1A4000-1)) { img[drive].sectors = 18; img[drive].tracks = 80; img[drive].rate = 0; } /*High density (not supported by Tandy 1000)*/
else if (size == 1884160) { img[drive].sectors = 23; img[drive].tracks = 80; img[drive].rate = 0; } /*XDF format - used by OS/2 Warp*/
else if (size == 1763328) { img[drive].sectors = 21; img[drive].tracks = 82; img[drive].rate = 0; } /*XDF format - used by OS/2 Warp*/
else if (size < (2048*1024)) { img[drive].sectors = 21; img[drive].tracks = 80; img[drive].rate = 0; } /*DMF format - used by Windows 95*/
else { img[drive].sectors = 36; img[drive].tracks = 80; img[drive].rate = 3; } /*E density*/
drives[drive].seek = img_seek;
drives[drive].readsector = img_readsector;
drives[drive].writesector = img_writesector;
drives[drive].readaddress = img_readaddress;
drives[drive].poll = img_poll;
drives[drive].format = img_format;
// pclog("img_load %d %p sectors=%i tracks=%i sides=%i sector_size=%i\n", drive, drives, img[drive].sectors, img[drive].tracks, img[drive].sides, img[drive].sector_size);
}
void img_close(int drive)
{
if (img[drive].f)
fclose(img[drive].f);
img[drive].f = NULL;
}
void img_seek(int drive, int track)
{
if (!img[drive].f)
return;
// pclog("Seek drive=%i track=%i sectors=%i sector_size=%i sides=%i\n", drive, track, img[drive].sectors,img[drive].sector_size, img[drive].sides);
disc_track[drive] = track;
if (img[drive].sides == 2)
{
fseek(img[drive].f, track * img[drive].sectors * img[drive].sector_size * 2, SEEK_SET);
fread(img[drive].track_data[0], img[drive].sectors * img[drive].sector_size, 1, img[drive].f);
fread(img[drive].track_data[1], img[drive].sectors * img[drive].sector_size, 1, img[drive].f);
}
else
{
fseek(img[drive].f, track * img[drive].sectors * img[drive].sector_size, SEEK_SET);
fread(img[drive].track_data[0], img[drive].sectors * img[drive].sector_size, 1, img[drive].f);
}
}
void img_writeback(int drive, int track)
{
if (!img[drive].f)
return;
if (img[drive].sides == 2)
{
fseek(img[drive].f, track * 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, track * 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);
}
}
void img_readsector(int drive, int sector, int track, int side, int rate)
{
img_sector = sector - 1;
img_track = track;
img_side = side;
img_drive = drive;
// pclog("imgS Read sector drive=%i side=%i track=%i sector=%i rate=%i\n",drive,side,track,sector, rate);
if (!img[drive].f || (side && img[drive].sides == 1) ||
(rate != img[drive].rate) || (track != disc_track[drive]))
{
// pclog("Sector not found rate %i,%i track %i,%i\n", rate, img[drive].rate, track, disc_track[drive]);
img_notfound=500;
return;
}
// printf("Found\n");
img_inread = 1;
img_readpos = 0;
img_pause = 32;
}
void img_writesector(int drive, int sector, int track, int side, int rate)
{
// if (imgdblstep[drive]) track/=2;
img_sector = sector - 1;
img_track = track;
img_side = side;
img_drive = drive;
// printf("imgS Write sector %i %i %i %i\n",drive,side,track,sector);
if (!img[drive].f || (side && img[drive].sides == 1) ||
(rate != img[drive].rate) || (track != disc_track[drive]))
{
img_notfound = 500;
return;
}
img_inwrite = 1;
img_readpos = 0;
img_pause = 32;
}
void img_readaddress(int drive, int track, int side, int rate)
{
img_drive = drive;
img_track = track;
img_side = side;
// pclog("Read address %i %i %i %i\n",drive,side,track, rate);
if (!img[drive].f || (side && img[drive].sides == 1) ||
(rate != img[drive].rate) || (track != disc_track[drive]))
{
// pclog("Address not found rate %i,%i track %i,%i\n", rate, img[drive].rate, track, disc_track[drive]);
img_notfound=500;
return;
}
img_inreadaddr = 1;
img_readpos = 0;
img_pause = 100;//500;
img_pause = 32;
}
void img_format(int drive, int track, int side, int rate)
{
img_drive = drive;
img_track = track;
img_side = side;
if (!img[drive].f || (side && img[drive].sides == 1) ||
(rate != img[drive].rate) || (track != disc_track[drive]))
{
img_notfound = 500;
return;
}
img_sector = 0;
img_readpos = 0;
img_informat = 1;
img_pause = 32;
}
void img_stop()
{
img_pause = img_notfound = img_inread = img_inwrite = img_inreadaddr = img_informat = 0;
}
void img_poll()
{
// pclog("img_poll %i %i %p\n", img_inread, img_readpos, img[img_drive].f);
img_index--;
if (!img_index)
{
img_index = 6250;
fdc_indexpulse();
}
if (img_pause)
{
img_pause--;
if (img_pause)
return;
}
if (img_notfound)
{
img_notfound--;
if (!img_notfound)
{
// pclog("Not found!\n");
fdc_notfound();
}
}
if (img_inread && img[img_drive].f)
{
// pclog("Read pos %i\n", img_readpos);
// if (!imgreadpos) pclog("%i\n",imgsector*imgsize[imgdrive]);
if (fdc_data(img[img_drive].track_data[img_side][(img_sector * img[img_drive].sector_size) + img_readpos]))
return;
img_readpos++;
if (img_readpos == img[img_drive].sector_size)
{
// pclog("Read %i bytes\n",img_readpos);
img_inread = 0;
fdc_finishread();
}
}
if (img_inwrite && img[img_drive].f)
{
int data;
if (writeprot[img_drive])
{
// pclog("writeprotect\n");
fdc_writeprotect();
img_inwrite = 0;
return;
}
// pclog("Write data %i\n",img_readpos);
data = fdc_getdata(img_readpos == (img[img_drive].sector_size - 1));
if (data == -1)
return;
img[img_drive].track_data[img_side][(img_sector * img[img_drive].sector_size) + img_readpos] = data;
img_readpos++;
if (img_readpos == img[img_drive].sector_size)
{
// pclog("write over\n");
img_inwrite = 0;
fdc_finishread();
img_writeback(img_drive, img_track);
}
}
if (img_inreadaddr && img[img_drive].f)
{
// pclog("img_inreadaddr %08X\n", fdc_sectorid);
fdc_sectorid(img_track, img_side,
img_rsector + ((img[img_drive].sector_size == 512) ? 1 : 0), (img[img_drive].sector_size == 256) ? 1 : ((img[img_drive].sector_size == 512) ? 2 : 3), 0, 0);
img_inreadaddr = 0;
img_rsector++;
if (img_rsector == img[img_drive].sectors)
{
img_rsector=0;
// pclog("img_rsector reset\n");
}
}
if (img_informat && img[img_drive].f)
{
if (writeprot[img_drive])
{
fdc_writeprotect();
img_informat = 0;
return;
}
img[img_drive].track_data[img_side][(img_sector * img[img_drive].sector_size) + img_readpos] = 0;
img_readpos++;
if (img_readpos == img[img_drive].sector_size)
{
img_readpos = 0;
img_sector++;
if (img_sector == img[img_drive].sectors)
{
img_informat = 0;
fdc_finishread();
img_writeback(img_drive, img_track);
}
}
}
}

10
src/disc_img.h Normal file
View file

@ -0,0 +1,10 @@
void img_init();
void img_load(int drive, char *fn);
void img_close(int drive);
void img_seek(int drive, int track);
void img_readsector(int drive, int sector, int track, int side, int density);
void img_writesector(int drive, int sector, int track, int side, int density);
void img_readaddress(int drive, int sector, int side, int density);
void img_format(int drive, int sector, int side, int density);
void img_stop();
void img_poll();

674
src/fdc.c
View file

@ -2,11 +2,14 @@
#include <string.h>
#include "ibm.h"
#include "disc.h"
#include "dma.h"
#include "io.h"
#include "pic.h"
#include "timer.h"
extern int motoron;
/*FDC*/
typedef struct FDC
{
@ -23,106 +26,31 @@ typedef struct FDC
int perp;
uint8_t config, pretrk;
int abort;
uint8_t format_dat[256];
int format_state;
int tc;
int written;
int pcjr;
int watchdog_timer;
int watchdog_count;
int data_ready;
int inread;
} FDC;
static FDC fdc;
void fdc_poll();
void fdc_callback();
int timetolive;
int TRACKS[2] = {80, 80};
int SECTORS[2]={9,9};
int SIDES[2]={2,2};
//#define SECTORS 9
int output;
int lastbyte=0;
uint8_t disc[2][2][80][36][512];
uint8_t disc_3f7;
int discchanged[2];
int discmodified[2];
int discrate[2];
void loaddisc(int d, char *fn)
{
FILE *f=fopen(fn,"rb");
int h,t,s,b;
if (!f)
{
SECTORS[d]=9; SIDES[d]=1;
driveempty[d]=1; discrate[d]=4;
return;
}
driveempty[d]=0;
SIDES[d]=2;
fseek(f,-1,SEEK_END);
if (ftell(f)<=(160*1024)) { SECTORS[d]=8; TRACKS[d] = 40; SIDES[d]=1; discrate[d]=2; }
else if (ftell(f)<=(180*1024)) { SECTORS[d]=9; TRACKS[d] = 40; SIDES[d]=1; discrate[d]=2; }
else if (ftell(f)<=(320*1024)) { SECTORS[d]=8; TRACKS[d] = 40; discrate[d]=2; }
else if (ftell(f)<=(360*1024)) { SECTORS[d]=9; TRACKS[d] = 40; discrate[d]=2; } /*Double density*/
else if (ftell(f)<(1024*1024)) { SECTORS[d]=9; TRACKS[d] = 80; discrate[d]=2; } /*Double density*/
else if (ftell(f) <= 1228800) { SECTORS[d]=15; TRACKS[d] = 80; discrate[d]=0; } /*High density 1.2MB*/
else if (ftell(f)<(0x1A4000-1)) { SECTORS[d]=18; TRACKS[d] = 80; discrate[d]=0; } /*High density (not supported by Tandy 1000)*/
else if (ftell(f) == 1884159) { SECTORS[d]=23; TRACKS[d] = 80; discrate[d]=0; } /*XDF format - used by OS/2 Warp*/
else if (ftell(f) == 1763327) { SECTORS[d]=21; TRACKS[d] = 82; discrate[d]=0; } /*XDF format - used by OS/2 Warp*/
else if (ftell(f)<(2048*1024)) { SECTORS[d]=21; TRACKS[d] = 80; discrate[d]=0; } /*DMF format - used by Windows 95*/
else { SECTORS[d]=36; TRACKS[d] = 80; discrate[d]=3; } /*E density (not supported by anything)*/
printf("Drive %c: has %i sectors and %i sides and is %i bytes long\n",'A'+d,SECTORS[0],SIDES[0],ftell(f));
fseek(f,0,SEEK_SET);
for (t=0;t<80;t++)
{
for (h=0;h<SIDES[d];h++)
{
for (s=0;s<SECTORS[d];s++)
{
for (b=0;b<512;b++)
{
disc[d][h][t][s][b]=getc(f);
}
}
}
}
fclose(f);
discmodified[d]=0;
strcpy(discfns[d],fn);
discchanged[d]=1;
}
void ejectdisc(int d)
{
discfns[d][0]=0;
SECTORS[d]=9; SIDES[d]=1;
driveempty[d]=1; discrate[d]=4;
}
void savedisc(int d)
{
FILE *f;
int h,t,s,b;
if (!discmodified[d]) return;
f=fopen(discfns[d],"wb");
if (!f) return;
printf("Save disc %c: %s %i %i\n",'A'+d,discfns[0],SIDES[0],SECTORS[0]);
for (t=0;t<80;t++)
{
for (h=0;h<SIDES[d];h++)
{
for (s=0;s<SECTORS[d];s++)
{
for (b=0;b<512;b++)
{
putc(disc[d][h][t][s][b],f);
}
}
}
}
fclose(f);
}
int discint;
void fdc_reset()
{
@ -163,7 +91,7 @@ static void fdc_watchdog_poll(void *p)
void fdc_write(uint16_t addr, uint8_t val, void *priv)
{
// printf("Write FDC %04X %02X %04X:%04X %i %02X %i rate=%i\n",addr,val,cs>>4,pc,ins,fdc.st0,ins,fdc.rate);
// pclog("Write FDC %04X %02X %04X:%04X %i %02X %i rate=%i %i\n",addr,val,cs>>4,pc,ins,fdc.st0,ins,fdc.rate, fdc.data_ready);
switch (addr&7)
{
case 1: return;
@ -187,6 +115,11 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
discint=-1;
fdc_reset();
}
motoron = val & 0x01;
/* if (motoron)
output = 3;
else
output = 0;*/
}
else
{
@ -203,6 +136,9 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
discint=-1;
fdc_reset();
}
timer_process();
motoron = (val & 0xf0) ? 1 : 0;
timer_update_outstanding();
}
fdc.dor=val;
// printf("DOR now %02X\n",val);
@ -224,20 +160,18 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc.stat &= ~0x80;
break;
}
// pclog("Write command reg %i %i\n",fdc.pnum, fdc.ptot);
// if (fdc.inread)
// rpclog("c82c711_fdc_write : writing while inread! %02X\n", val);
// rpclog("Write command reg %i %i\n",fdc.pnum, fdc.ptot);
if (fdc.pnum==fdc.ptot)
{
fdc.tc = 0;
fdc.data_ready = 0;
fdc.command=val;
// printf("Starting FDC command %02X\n",fdc.command);
// pclog("Starting FDC command %02X\n",fdc.command);
switch (fdc.command&0x1F)
{
case 2: /*Read track*/
// printf("Read track!\n");
fdc.pnum=0;
fdc.ptot=8;
fdc.stat=0x90;
fdc.pos=0;
break;
case 3: /*Specify*/
fdc.pnum=0;
fdc.ptot=2;
@ -254,15 +188,13 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc.ptot=8;
fdc.stat=0x90;
fdc.pos=0;
readflash=1;
// readflash=1;
break;
case 6: /*Read data*/
fullspeed();
fdc.pnum=0;
fdc.ptot=8;
fdc.stat=0x90;
fdc.pos=0;
readflash=1;
break;
case 7: /*Recalibrate*/
fdc.pnum=0;
@ -270,13 +202,13 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc.stat=0x90;
break;
case 8: /*Sense interrupt status*/
// printf("Sense interrupt status %i\n",fdc.drive);
// printf("Sense interrupt status %i\n",curdrive);
fdc.lastdrive = fdc.drive;
// fdc.stat = 0x10 | (fdc.stat & 0xf);
// disctime=1024;
// fdc_time=1024;
discint = 8;
fdc.pos = 0;
fdc_poll();
fdc_callback();
break;
case 10: /*Read sector ID*/
fdc.pnum=0;
@ -284,6 +216,13 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc.stat=0x90;
fdc.pos=0;
break;
case 0x0d: /*Format track*/
fdc.pnum=0;
fdc.ptot=5;
fdc.stat=0x90;
fdc.pos=0;
fdc.format_state = 0;
break;
case 15: /*Seek*/
fdc.pnum=0;
fdc.ptot=2;
@ -293,13 +232,13 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc.lastdrive = fdc.drive;
discint = 0x0e;
fdc.pos = 0;
fdc_poll();
fdc_callback();
break;
case 0x10: /*Get version*/
fdc.lastdrive = fdc.drive;
discint = 0x10;
fdc.pos = 0;
fdc_poll();
fdc_callback();
break;
case 0x12: /*Set perpendicular mode*/
fdc.pnum=0;
@ -318,17 +257,17 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc.lastdrive = fdc.drive;
discint = fdc.command;
fdc.pos = 0;
fdc_poll();
fdc_callback();
break;
case 0x18:
fdc.stat = 0x10;
discint = 0xfc;
fdc_poll();
fdc_callback();
break;
default:
pclog("Bad FDC command %02X\n",val);
fatal("Bad FDC command %02X\n",val);
// dumpregs();
// exit(-1);
fdc.stat=0x10;
@ -344,64 +283,80 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc.params[fdc.pnum++]=val;
if (fdc.pnum==fdc.ptot)
{
// pclog("Got all params\n");
// pclog("Got all params %02X\n", fdc.command);
fdc.stat=0x30;
discint=fdc.command&0x1F;
timer_process();
disctime = 1024 * (1 << TIMER_SHIFT);
fdc.drive=fdc.params[0]&1;
if (discint==2 || discint==5 || discint==6)
timer_update_outstanding();
fdc.drive = fdc.params[0] & 3;
switch (discint)
{
case 5: /*Write data*/
fdc.track[fdc.drive]=fdc.params[1];
fdc.head=fdc.params[2];
fdc.sector=fdc.params[3];
fdc.eot[fdc.drive] = fdc.params[4];
if (!fdc.params[5])
{
fdc.params[5]=fdc.sector;
}
if (fdc.params[5]>SECTORS[fdc.drive]) fdc.params[5]=SECTORS[fdc.drive];
if (driveempty[fdc.drive])
{
// pclog("Drive empty\n");
discint=0xFE;
}
}
if (discint==2 || discint==5 || discint==6 || discint==10)
{
// pclog("Rate %i %i %i\n",fdc.rate,discrate[fdc.drive],driveempty[fdc.drive]);
if (fdc.rate!=discrate[fdc.drive])
{
// pclog("Wrong rate %i %i\n",fdc.rate,discrate[fdc.drive]);
discint=0xFF;
disctime = 1024 * (1 << TIMER_SHIFT);
}
if (driveempty[fdc.drive])
{
// pclog("Drive empty\n");
discint=0xFE;
disctime = 1024 * (1 << TIMER_SHIFT);
}
}
if (discint == 7 || discint == 0xf)
{
fdc.stat = 1 << fdc.drive;
// disctime = 8000000;
}
if (discint == 0xf || discint == 10)
{
fdc.head = (fdc.params[0] & 4) ? 1 : 0;
}
if (discint == 5 && fdc.pcjr)
if (fdc.config & 0x40)
disc_seek(fdc.drive, fdc.track[fdc.drive]);
disc_writesector(fdc.drive, fdc.sector, fdc.track[fdc.drive], fdc.head, fdc.rate);
disctime = 0;
fdc.written = 0;
readflash = 1;
fdc.pos = 0;
if (fdc.pcjr)
fdc.stat = 0xb0;
timer_update_outstanding();
// if (discint==5) fdc.pos=512;
// ioc_fiq(IOC_FIQ_DISC_DATA);
break;
case 6: /*Read data*/
fdc.track[fdc.drive]=fdc.params[1];
fdc.head=fdc.params[2];
fdc.sector=fdc.params[3];
fdc.eot[fdc.drive] = fdc.params[4];
if (fdc.config & 0x40)
disc_seek(fdc.drive, fdc.track[fdc.drive]);
disc_readsector(fdc.drive, fdc.sector, fdc.track[fdc.drive], fdc.head, fdc.rate);
disctime = 0;
readflash = 1;
fdc.inread = 1;
break;
case 7: /*Recalibrate*/
fdc.stat = 1 << fdc.drive;
disctime = 0;
disc_seek(fdc.drive, 0);
break;
case 0x0d: /*Format*/
fdc.format_state = 1;
fdc.pos = 0;
fdc.stat = 0x30;
break;
case 0xf: /*Seek*/
fdc.stat = 1 << fdc.drive;
fdc.head = (fdc.params[0] & 4) ? 1 : 0;
disctime = 0;
disc_seek(fdc.drive, fdc.params[1]);
break;
case 10: /*Read sector ID*/
disctime = 0;
fdc.head = (fdc.params[0] & 4) ? 1 : 0;
// rpclog("Read sector ID %i %i\n", fdc.rate, fdc.drive);
disc_readaddress(fdc.drive, fdc.track[fdc.drive], fdc.head, fdc.rate);
break;
}
}
}
return;
case 7:
if (!AT) return;
fdc.rate=val&3;
disc_set_rate(fdc.rate);
disc_3f7=val;
return;
@ -415,7 +370,7 @@ int paramstogo=0;
uint8_t fdc_read(uint16_t addr, void *priv)
{
uint8_t temp;
// /*if (addr!=0x3f4) */printf("Read FDC %04X %04X:%04X %04X %i %02X %i ",addr,cs>>4,pc,BX,fdc.pos,fdc.st0,ins);
// /*if (addr!=0x3f4) */printf("Read FDC %04X %04X:%04X %04X %i %02X %02x %i ",addr,cs>>4,pc,BX,fdc.pos,fdc.st0,fdc.stat,ins);
switch (addr&7)
{
case 1: /*???*/
@ -438,7 +393,7 @@ uint8_t fdc_read(uint16_t addr, void *priv)
{
paramstogo--;
temp=fdc.res[10 - paramstogo];
// printf("Read param %i %02X\n",6-paramstogo,temp);
// pclog("Read param %i %02X\n",10-paramstogo,temp);
if (!paramstogo)
{
fdc.stat=0x80;
@ -456,6 +411,7 @@ uint8_t fdc_read(uint16_t addr, void *priv)
fdc.stat = 0x80;
lastbyte=0;
temp=fdc.dat;
fdc.data_ready = 0;
}
if (discint==0xA)
{
@ -467,7 +423,7 @@ uint8_t fdc_read(uint16_t addr, void *priv)
break;
case 7: /*Disk change*/
if (fdc.dor & (0x10 << (fdc.dor & 1)))
temp = (discchanged[fdc.dor & 1] || driveempty[fdc.dor & 1])?0x80:0;
temp = (disc_changed[fdc.dor & 1] || drive_empty[fdc.dor & 1])?0x80:0;
else
temp = 0;
if (AMSTRADIO) /*PC2086/3086 seem to reverse this bit*/
@ -481,32 +437,34 @@ uint8_t fdc_read(uint16_t addr, void *priv)
// dumpregs();
// exit(-1);
}
// /*if (addr!=0x3f4) */printf("%02X rate=%i\n",temp,fdc.rate);
// /*if (addr!=0x3f4) */printf("%02X rate=%i %i\n",temp,fdc.rate, fdc.data_ready);
return temp;
}
static int fdc_reset_stat = 0;
void fdc_poll()
void fdc_callback()
{
int temp;
disctime = 0;
// pclog("fdc_poll %08X %i %02X\n", discint, fdc.drive, fdc.st0);
// pclog("fdc_callback %i %i\n", discint, disctime);
// if (fdc.inread)
// rpclog("c82c711_fdc_callback : while inread! %08X %i %02X %i\n", discint, fdc.drive, fdc.st0, ins);
switch (discint)
{
case -3: /*End of command with interrupt*/
// if (output) printf("EOC - interrupt!\n");
//pclog("EOC\n");
//rpclog("EOC\n");
fdc_int();
case -2: /*End of command*/
fdc.stat = (fdc.stat & 0xf) | 0x80;
return;
case -1: /*Reset*/
//pclog("Reset\n");
//rpclog("Reset\n");
fdc_int();
fdc_reset_stat = 4;
return;
case 2: /*Read track*/
if (!fdc.pos)
/* if (!fdc.pos)
{
// printf("Read Track Side %i Track %i Sector %02X sector size %i end sector %02X %05X\n",fdc.head,fdc.track,fdc.sector,fdc.params[4],fdc.params[5],(dma.page[2]<<16)+dma.ac[2]);
}
@ -548,7 +506,7 @@ void fdc_poll()
fdc.sector=1;
}
fdc.params[5]--;
}
}*/
return;
case 3: /*Specify*/
fdc.stat=0x80;
@ -557,7 +515,8 @@ void fdc_poll()
return;
case 4: /*Sense drive status*/
fdc.res[10] = (fdc.params[0] & 7) | 0x28;
if (!fdc.track[fdc.drive]) fdc.res[10] |= 0x10;
if (!fdc.track[fdc.drive])
fdc.res[10] |= 0x10;
fdc.stat = (fdc.stat & 0xf) | 0xd0;
paramstogo = 1;
@ -565,95 +524,31 @@ void fdc_poll()
disctime = 0;
return;
case 5: /*Write data*/
discmodified[fdc.drive]=1;
// printf("Write data %i\n",fdc.pos);
if (!fdc.pos)
{
// printf("Write data Side %i Track %i Sector %02X sector size %i end sector %02X\n",fdc.params[2],fdc.params[1],fdc.params[3],fdc.params[4],fdc.params[5]);
// dumpregs();
// exit(-1);
}
if (fdc.pos<512)
{
if (fdc.pcjr)
temp = fdc.dat;
else
temp = dma_channel_read(2);
if (temp == DMA_NODATA)
{
discint=0xFD;
timer_process();
disctime = 50 * (1 << TIMER_SHIFT);
timer_update_outstanding();
return;
}
else
{
fdc.dat=disc[fdc.drive][fdc.head][fdc.track[fdc.drive]][fdc.sector-1][fdc.pos]=temp;
// printf("Write data %i %i %02X %i:%i:%i:%i\n",fdc.sector-1,fdc.pos,fdc.dat,fdc.head,fdc.track[fdc.drive],fdc.sector-1,fdc.pos);
timer_process();
disctime = 600 * (1 << TIMER_SHIFT);
timer_update_outstanding();
if (fdc.pcjr && fdc.pos != 512)
fdc.stat = 0xb0;
}
}
else
{
disctime=0;
discint=-2;
// pclog("WD\n");
fdc_int();
fdc.stat=0xD0;
fdc.res[4]=(fdc.head?4:0)|fdc.drive;
fdc.res[5]=0;
fdc.res[6]=0;
fdc.res[7]=fdc.track[fdc.drive];
fdc.res[8]=fdc.head;
fdc.res[9]=fdc.sector;
fdc.res[10]=fdc.params[4];
paramstogo=7;
return;
}
fdc.pos++;
if (fdc.pos==512 && fdc.sector!=fdc.params[5])
{
fdc.pos=0;
readflash = 1;
fdc.sector++;
if (fdc.pcjr)
fdc.stat = 0xb0;
if (fdc.sector > fdc.params[5])
{
if (fdc.command & 0x80)
{
fdc.sector=1;
fdc.head ^= 1;
if (!fdc.head)
{
fdc.track[fdc.drive]++;
/* if (fdc.track[fdc.drive] >= 79)
{
fdc.track[fdc.drive] = 79;
fdc.tc = 1;
}*/
}
return;
case 6: /*Read data*/
if (!fdc.pos)
{
// printf("Reading sector %i track %i side %i drive %i %02X to %05X %04X\n",fdc.sector,fdc.track[fdc.drive],fdc.head,fdc.drive,fdc.params[5],(dma.ac[2]+(dma.page[2]<<16))&rammask, dma.cc[2]);
}
if (fdc.pos<512)
{
fdc.dat = disc[fdc.drive][fdc.head][fdc.track[fdc.drive]][fdc.sector - 1][fdc.pos];
// printf("Read disc %i %i %i %i %02X\n",fdc.head,fdc.track,fdc.sector,fdc.pos,fdc.dat);
if (fdc.pcjr)
{
fdc.stat = 0xf0;
}
else
{
if (dma_channel_write(2, fdc.dat) & DMA_OVER)
fdc.abort = 1;
fdc.tc = 1;
}
timer_process();
disctime = 256 * (1 << TIMER_SHIFT);
timer_update_outstanding();
}
else
if (fdc.tc)
{
// printf("End of command - params to go! %i %i %i\n", fdc.track[fdc.drive], fdc.head, fdc.sector);
fdc.abort = 0;
disctime=0;
discint=-2;
fdc_int();
// pclog("RD\n");
fdc.stat=0xD0;
fdc.res[4]=(fdc.head?4:0)|fdc.drive;
fdc.res[5]=fdc.res[6]=0;
@ -663,54 +558,55 @@ void fdc_poll()
fdc.res[10]=fdc.params[4];
paramstogo=7;
return;
switch (fdc.pos-512)
{
case 0: case 1: case 2: fdc.dat=0; break;
case 3: fdc.dat=fdc.track[fdc.drive]; break;
case 4: fdc.dat=fdc.head; break;
case 5: fdc.dat=fdc.sector; break;
case 6: fdc.dat=fdc.params[4]; discint=-2; lastbyte=1; break;
}
}
fdc.pos++;
if (fdc.pos==512)// && fdc.sector!=fdc.params[5])
{
// pclog("Sector complete! %02X\n",fdc.params[5]);
fdc.pos=0;
disc_writesector(fdc.drive, fdc.sector, fdc.track[fdc.drive], fdc.head, fdc.rate);
// ioc_fiq(IOC_FIQ_DISC_DATA);
return;
case 6: /*Read data*/
// rpclog("Read data %i\n", fdc.tc);
readflash = 1;
fdc.sector++;
if (fdc.sector > fdc.params[5])
{
// pclog("Overrunnit! %02X\n", fdc.command & 0x80);
// dumpregs();
// exit(-1);
fdc.sector=1;
if (fdc.command & 0x80)
{
fdc.sector=1;
fdc.head ^= 1;
if (!fdc.head)
{
fdc.track[fdc.drive]++;
if (fdc.track[fdc.drive] >= TRACKS[fdc.drive])
/* if (fdc.track[fdc.drive] >= 79)
{
fdc.track[fdc.drive] = TRACKS[fdc.drive];
fdc.pos = 512;
}
fdc.track[fdc.drive] = 79;
fdc.tc = 1;
}*/
}
}
else
fdc.pos = 512;
}
if (fdc.abort)
fdc.pos = 512;
fdc.tc = 1;
}
if (fdc.tc)
{
fdc.inread = 0;
discint=-2;
fdc_int();
fdc.stat=0xD0;
fdc.res[4]=(fdc.head?4:0)|fdc.drive;
fdc.res[5]=fdc.res[6]=0;
fdc.res[7]=fdc.track[fdc.drive];
fdc.res[8]=fdc.head;
fdc.res[9]=fdc.sector;
fdc.res[10]=fdc.params[4];
paramstogo=7;
return;
/* printf("Read data\n");
printf("Side %i Track %i Sector %i sector size %i\n",fdc.params[1],fdc.params[2],fdc.params[3],fdc.params[4]);
dumpregs();
exit(-1);*/
}
disc_readsector(fdc.drive, fdc.sector, fdc.track[fdc.drive], fdc.head, fdc.rate);
fdc.inread = 1;
return;
case 7: /*Recalibrate*/
fdc.track[fdc.drive]=0;
if (!driveempty[fdc.dor & 1]) discchanged[fdc.dor & 1] = 0;
// if (!driveempty[fdc.dor & 1]) discchanged[fdc.dor & 1] = 0;
fdc.st0=0x20|fdc.drive|(fdc.head?4:0);
discint=-3;
timer_process();
@ -719,6 +615,7 @@ void fdc_poll()
// printf("Recalibrate complete!\n");
fdc.stat = 0x80 | (1 << fdc.drive);
return;
case 8: /*Sense interrupt status*/
// pclog("Sense interrupt status %i\n", fdc_reset_stat);
@ -738,26 +635,60 @@ void fdc_poll()
discint = 0;
disctime = 0;
return;
case 10: /*Read sector ID*/
disctime=0;
case 0x0d: /*Format track*/
// rpclog("Format\n");
if (fdc.format_state == 1)
{
// ioc_fiq(IOC_FIQ_DISC_DATA);
fdc.format_state = 2;
timer_process();
disctime = 128 * (1 << TIMER_SHIFT);
timer_update_outstanding();
}
else if (fdc.format_state == 2)
{
temp = fdc_getdata(fdc.pos == ((fdc.params[2] * 4) - 1));
if (temp == -1)
{
timer_process();
disctime = 128 * (1 << TIMER_SHIFT);
timer_update_outstanding();
return;
}
fdc.format_dat[fdc.pos++] = temp;
if (fdc.pos == (fdc.params[2] * 4))
fdc.format_state = 3;
timer_process();
disctime = 128 * (1 << TIMER_SHIFT);
timer_update_outstanding();
}
else if (fdc.format_state == 4)
{
// rpclog("Format next stage\n");
disc_format(fdc.drive, fdc.track[fdc.drive], fdc.head, fdc.rate);
fdc.format_state = 4;
}
else
{
discint=-2;
fdc_int();
fdc.stat=0xD0;
fdc.res[4] = (fdc.head?4:0)|fdc.drive;
fdc.res[5]=0;
fdc.res[6]=0;
fdc.res[5] = fdc.res[6] = 0;
fdc.res[7] = fdc.track[fdc.drive];
fdc.res[8] = fdc.head;
fdc.res[9]=fdc.sector;
fdc.res[9] = fdc.format_dat[fdc.pos - 2] + 1;
fdc.res[10] = fdc.params[4];
paramstogo=7;
fdc.sector++;
if (fdc.sector==SECTORS[fdc.drive]+1)
fdc.sector=1;
fdc.format_state = 0;
return;
}
return;
case 15: /*Seek*/
fdc.track[fdc.drive]=fdc.params[1];
if (!driveempty[fdc.dor & 1]) discchanged[fdc.dor & 1] = 0;
// if (!driveempty[fdc.dor & 1]) discchanged[fdc.dor & 1] = 0;
// printf("Seeked to track %i %i\n",fdc.track[fdc.drive], fdc.drive);
fdc.st0=0x20|fdc.drive|(fdc.head?4:0);
discint=-3;
@ -794,14 +725,14 @@ void fdc_poll()
fdc.perp = fdc.params[0];
fdc.stat = 0x80;
disctime = 0;
// fdc_int();
// picint(0x40);
return;
case 0x13: /*Configure*/
fdc.config = fdc.params[1];
fdc.pretrk = fdc.params[2];
fdc.stat = 0x80;
disctime = 0;
// fdc_int();
// picint(0x40);
return;
case 0x14: /*Unlock*/
fdc.lock = 0;
@ -824,7 +755,7 @@ void fdc_poll()
case 0xfc: /*Invalid*/
fdc.dat = fdc.st0 = 0x80;
// pclog("Inv!\n");
//fdc_int();
//picint(0x40);
fdc.stat = (fdc.stat & 0xf) | 0xd0;
// fdc.stat|=0xC0;
fdc.res[10] = fdc.st0;
@ -832,49 +763,68 @@ void fdc_poll()
discint=0;
disctime = 0;
return;
}
// printf("Bad FDC disc int %i\n",discint);
// dumpregs();
// exit(-1);
}
case 0xFD: /*DMA aborted (PC1512)*/
/*In the absence of other information, lie and claim the command completed successfully.
The PC1512 BIOS likes to program the FDC to write to all sectors on the track, but
program the DMA length to the number of sectors actually transferred. Not aborting
correctly causes disc corruption.
This only matters on writes, on reads the DMA controller will ignore excess data.
*/
pclog("DMA Aborted\n");
void fdc_overrun()
{
img_stop();
disctime = 0;
discint=-2;
fdc_int();
fdc.stat=0xD0;
fdc.res[4]=(fdc.head?4:0)|fdc.drive;
fdc.res[5]=0;
fdc.res[6]=0;
fdc.res[7]=fdc.track[fdc.drive];
fdc.res[8]=fdc.head;
fdc.res[9]=fdc.sector;
fdc.res[10]=fdc.params[4];
paramstogo=7;
return;
case 0xFE: /*Drive empty*/
pclog("Drive empty\n");
fdc.stat = 0x10;
disctime = 0;
/* disctime=0;
discint=-2;
fdc_int();
fdc.stat=0xD0;
fdc.res[4]=0xC8|(fdc.head?4:0)|fdc.drive;
fdc.res[5]=0;
fdc.res[4]=0x40|(fdc.head?4:0)|fdc.drive;
fdc.res[5]=0x10; /*Overrun*/
fdc.res[6]=0;
fdc.res[7]=0;
fdc.res[8]=0;
fdc.res[9]=0;
fdc.res[10]=0;
paramstogo=7;*/
return;
case 0xFF: /*Wrong rate*/
pclog("Wrong rate\n");
paramstogo=7;
}
int fdc_data(uint8_t data)
{
if (fdc.tc)
return 0;
if (fdc.pcjr)
{
if (fdc.data_ready)
{
fdc_overrun();
// pclog("Overrun\n");
return -1;
}
fdc.dat = data;
fdc.data_ready = 1;
fdc.stat = 0xf0;
// pclog("fdc_data\n");
}
else
{
if (dma_channel_write(2, data) & DMA_OVER)
fdc.tc = 1;
}
return 0;
}
void fdc_finishread()
{
fdc.inread = 0;
disctime = 200 * TIMER_USEC;
// rpclog("fdc_finishread\n");
}
void fdc_notfound()
{
disctime = 0;
discint=-2;
fdc_int();
fdc.stat=0xD0;
fdc.res[4]=0x40|(fdc.head?4:0)|fdc.drive;
@ -885,16 +835,99 @@ void fdc_poll()
fdc.res[9]=0;
fdc.res[10]=0;
paramstogo=7;
return;
// rpclog("c82c711_fdc_notfound\n");
}
// printf("Bad FDC disc int %i\n",discint);
// dumpregs();
// exit(-1);
void fdc_datacrcerror()
{
disctime = 0;
fdc_int();
fdc.stat=0xD0;
fdc.res[4]=0x40|(fdc.head?4:0)|fdc.drive;
fdc.res[5]=0x20; /*Data error*/
fdc.res[6]=0x20; /*Data error in data field*/
fdc.res[7]=0;
fdc.res[8]=0;
fdc.res[9]=0;
fdc.res[10]=0;
paramstogo=7;
// rpclog("c82c711_fdc_datacrcerror\n");
}
void fdc_headercrcerror()
{
disctime = 0;
fdc_int();
fdc.stat=0xD0;
fdc.res[4]=0x40|(fdc.head?4:0)|fdc.drive;
fdc.res[5]=0x20; /*Data error*/
fdc.res[6]=0;
fdc.res[7]=0;
fdc.res[8]=0;
fdc.res[9]=0;
fdc.res[10]=0;
paramstogo=7;
// rpclog("c82c711_fdc_headercrcerror\n");
}
void fdc_writeprotect()
{
}
int fdc_getdata(int last)
{
int data;
if (fdc.pcjr)
{
if (fdc.written)
{
fdc_overrun();
// pclog("Overrun\n");
return -1;
}
data = fdc.dat;
if (!last)
fdc.stat = 0xb0;
}
else
{
data = dma_channel_read(2);
if (data & DMA_OVER)
fdc.tc = 1;
}
fdc.written = 0;
return data & 0xff;
}
void fdc_sectorid(uint8_t track, uint8_t side, uint8_t sector, uint8_t size, uint8_t crc1, uint8_t crc2)
{
// pclog("SectorID %i %i %i %i\n", track, side, sector, size);
fdc_int();
fdc.stat=0xD0;
fdc.res[4]=(fdc.head?4:0)|fdc.drive;
fdc.res[5]=0;
fdc.res[6]=0;
fdc.res[7]=track;
fdc.res[8]=side;
fdc.res[9]=sector;
fdc.res[10]=size;
paramstogo=7;
}
void fdc_indexpulse()
{
// ioc_irqa(IOC_IRQA_DISC_INDEX);
// rpclog("c82c711_fdc_indexpulse\n");
}
void fdc_init()
{
timer_add(fdc_poll, &disctime, &disctime, NULL);
timer_add(fdc_callback, &disctime, &disctime, NULL);
}
void fdc_add()
@ -916,3 +949,8 @@ void fdc_remove()
io_removehandler(0x03f0, 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL);
io_removehandler(0x03f7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL);
}
void fdc_discchange_clear(int drive)
{
disc_changed[drive] = 0;
}

View file

@ -5,3 +5,4 @@ void fdc_remove();
void fdc_reset();
void fdc_poll();
void fdc_abort();
void fdc_discchange_clear(int drive);

2190
src/fdi2raw.c Normal file

File diff suppressed because it is too large Load diff

34
src/fdi2raw.h Normal file
View file

@ -0,0 +1,34 @@
#ifndef __FDI2RAW_H
#define __FDI2RAW_H
#define uae_u8 uint8_t
#define uae_u16 uint16_t
#define uae_u32 uint32_t
//#include "types.h"
#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 *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -2,6 +2,7 @@
#include "device.h"
#include "io.h"
#include "mem.h"
#include "nmi.h"
#include "pic.h"
#include "sound.h"
#include "sound_sn76489.h"
@ -24,7 +25,6 @@ struct
{
int latched;
int data;
int nmi_enabled;
int serial_data[44];
int serial_pos;
@ -142,7 +142,7 @@ void keyboard_pcjr_write(uint16_t port, uint8_t val, void *priv)
break;
case 0xa0:
keyboard_pcjr.nmi_enabled = val & 0x80;
nmi_mask = val & 0x80;
pit_set_using_timer(1, !(val & 0x20));
break;
}

View file

@ -221,12 +221,15 @@ void initpc()
loadbios();
mem_add_bios();
loaddisc(0,discfns[0]);
loaddisc(1,discfns[1]);
disc_load(0, discfns[0]);
disc_load(1, discfns[1]);
timer_reset();
sound_reset();
fdc_init();
disc_init();
fdi_init();
img_init();
//loadfont();
loadnvr();
@ -283,6 +286,15 @@ void resetpchard()
sound_reset();
mem_resize();
fdc_init();
disc_init();
fdi_init();
img_init();
disc_close(0);
disc_close(1);
disc_load(0, discfns[0]);
disc_load(1, discfns[1]);
model_init();
video_init();
speaker_init();
@ -447,8 +459,8 @@ void closepc()
// output=7;
// setpitclock(clocks[0][0][0]);
// while (1) runpc();
savedisc(0);
savedisc(1);
disc_close(0);
disc_close(1);
dumpregs();
closevideo();
device_close_all();

View file

@ -23,6 +23,7 @@
#include "nvr.h"
#include "sound.h"
#include "thread.h"
#include "disc.h"
#include "plat-midi.h"
#include "plat-keyboard.h"
@ -774,29 +775,27 @@ 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:
if (!getfile(hwnd,"Disc image (*.IMG;*.IMA)\0*.IMG;*.IMA\0All files (*.*)\0*.*\0",discfns[0]))
if (!getfile(hwnd,"Disc image (*.IMG;*.IMA;*.FDI)\0*.IMG;*.IMA;*.FDI\0All files (*.*)\0*.*\0",discfns[0]))
{
savedisc(0);
loaddisc(0,openfilestring);
disc_close(0);
disc_load(0, openfilestring);
saveconfig();
}
break;
case IDM_DISC_B:
if (!getfile(hwnd,"Disc image (*.IMG;*.IMA)\0*.IMG;*.IMA\0All files (*.*)\0*.*\0",discfns[1]))
if (!getfile(hwnd,"Disc image (*.IMG;*.IMA;*.FDI)\0*.IMG;*.IMA;*.FDI\0All files (*.*)\0*.*\0",discfns[1]))
{
savedisc(1);
loaddisc(1,openfilestring);
disc_close(1);
disc_load(1, openfilestring);
saveconfig();
}
break;
case IDM_EJECT_A:
savedisc(0);
ejectdisc(0);
disc_close(0);
saveconfig();
break;
case IDM_EJECT_B:
savedisc(1);
ejectdisc(1);
disc_close(1);
saveconfig();
break;
case IDM_HDCONF: