From a8159f8c0940e931f75bf5e6ae5a5d6941596f53 Mon Sep 17 00:00:00 2001 From: TomW Date: Thu, 19 Mar 2015 21:33:19 +0000 Subject: [PATCH] Various changes to FDC emulation. Support for multiple disc image formats. Added preliminary FDI support. --- src/Makefile.am | 4 +- src/Makefile.in | 68 +- src/Makefile.mingw | 10 +- src/allegro-gui.c | 19 +- src/allegro-main.h | 2 + src/config.c | 16 + src/config.h | 1 + src/disc.c | 203 ++++ src/disc.h | 57 ++ src/disc_fdi.c | 463 +++++++++ src/disc_fdi.h | 10 + src/disc_img.c | 307 ++++++ src/disc_img.h | 10 + src/fdc.c | 786 ++++++++-------- src/fdc.h | 1 + src/fdi2raw.c | 2190 +++++++++++++++++++++++++++++++++++++++++++ src/fdi2raw.h | 34 + src/keyboard_pcjr.c | 4 +- src/pc.c | 22 +- src/win.c | 19 +- 20 files changed, 3815 insertions(+), 411 deletions(-) create mode 100644 src/disc.c create mode 100644 src/disc.h create mode 100644 src/disc_fdi.c create mode 100644 src/disc_fdi.h create mode 100644 src/disc_img.c create mode 100644 src/disc_img.h create mode 100644 src/fdi2raw.c create mode 100644 src/fdi2raw.h diff --git a/src/Makefile.am b/src/Makefile.am index 4c1f9a6..daaa09a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 \ diff --git a/src/Makefile.in b/src/Makefile.in index 563d5e4..38952b1 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -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 diff --git a/src/Makefile.mingw b/src/Makefile.mingw index 3411183..3232828 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -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 \ diff --git a/src/allegro-gui.c b/src/allegro-gui.c index aa7d346..3ea74b0 100644 --- a/src/allegro-gui.c +++ b/src/allegro-gui.c @@ -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; diff --git a/src/allegro-main.h b/src/allegro-main.h index de6ecc4..0988d5f 100644 --- a/src/allegro-main.h +++ b/src/allegro-main.h @@ -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 @@ -13,3 +14,4 @@ #undef get_filename #undef append_filename #undef put_backslash +#undef get_extension diff --git a/src/config.c b/src/config.c index 2af2052..f396cef 100644 --- a/src/config.c +++ b/src/config.c @@ -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"); diff --git a/src/config.h b/src/config.h index 82adce4..d8710b0 100644 --- a/src/config.h +++ b/src/config.h @@ -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); diff --git a/src/disc.c b/src/disc.c new file mode 100644 index 0000000..7ba7038 --- /dev/null +++ b/src/disc.c @@ -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); +} diff --git a/src/disc.h b/src/disc.h new file mode 100644 index 0000000..3a2efa0 --- /dev/null +++ b/src/disc.h @@ -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]; diff --git a/src/disc_fdi.c b/src/disc_fdi.c new file mode 100644 index 0000000..9d9ed0c --- /dev/null +++ b/src/disc_fdi.c @@ -0,0 +1,463 @@ +#include +#include +#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; + } + } + } + } + } +} diff --git a/src/disc_fdi.h b/src/disc_fdi.h new file mode 100644 index 0000000..9877a5b --- /dev/null +++ b/src/disc_fdi.h @@ -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(); diff --git a/src/disc_img.c b/src/disc_img.c new file mode 100644 index 0000000..5b10682 --- /dev/null +++ b/src/disc_img.c @@ -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); + } + } + } +} diff --git a/src/disc_img.h b/src/disc_img.h new file mode 100644 index 0000000..9d694bd --- /dev/null +++ b/src/disc_img.h @@ -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(); diff --git a/src/fdc.c b/src/fdc.c index c6a97f5..65df743 100644 --- a/src/fdc.c +++ b/src/fdc.c @@ -2,11 +2,14 @@ #include #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;hwatchdog_count--; if (fdc->watchdog_count) fdc->watchdog_timer += 1000 * TIMER_USEC; @@ -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,24 +257,24 @@ 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; discint=0xfc; - timer_process(); - disctime = 200 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_process(); + disctime = 200 * (1 << TIMER_SHIFT); + timer_update_outstanding(); break; } } @@ -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_process(); + disctime = 1024 * (1 << TIMER_SHIFT); + 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) - { + 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; +// 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; -// disctime = 8000000; - } - if (discint == 0xf || discint == 10) - { 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; } - if (discint == 5 && fdc.pcjr) - fdc.stat = 0xb0; - timer_update_outstanding(); -// if (discint==5) fdc.pos=512; } } 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; @@ -453,9 +408,10 @@ uint8_t fdc_read(uint16_t addr, void *priv) else { if (lastbyte) - fdc.stat=0x80; + 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) + readflash = 1; + fdc.sector++; + if (fdc.sector > fdc.params[5]) { -// 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) + if (fdc.command & 0x80) { - discint=0xFD; - timer_process(); - disctime = 50 * (1 << TIMER_SHIFT); - timer_update_outstanding(); - return; + 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; + }*/ + } } 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; - } + fdc.tc = 1; } - else + if (fdc.tc) { - 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; - fdc.sector++; - if (fdc.pcjr) - fdc.stat = 0xb0; - } - 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; - } - timer_process(); - disctime = 256 * (1 << TIMER_SHIFT); - timer_update_outstanding(); - } - else - { -// 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,62 +558,64 @@ 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; - 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.head ^= 1; - if (!fdc.head) - { - fdc.track[fdc.drive]++; - if (fdc.track[fdc.drive] >= TRACKS[fdc.drive]) - { - fdc.track[fdc.drive] = TRACKS[fdc.drive]; - fdc.pos = 512; - } - } - } - else - fdc.pos = 512; - } - if (fdc.abort) - fdc.pos = 512; - } + } + disc_writesector(fdc.drive, fdc.sector, fdc.track[fdc.drive], fdc.head, fdc.rate); +// ioc_fiq(IOC_FIQ_DISC_DATA); 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);*/ + case 6: /*Read data*/ +// rpclog("Read data %i\n", fdc.tc); + readflash = 1; + fdc.sector++; + 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; + }*/ + } + } + else + 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; + } + 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(); - disctime = 2048 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_process(); + disctime = 2048 * (1 << TIMER_SHIFT); + timer_update_outstanding(); // 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); @@ -736,34 +633,68 @@ void fdc_poll() paramstogo = 2; discint = 0; - disctime = 0; + disctime = 0; return; - case 10: /*Read sector ID*/ - 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; - fdc.sector++; - if (fdc.sector==SECTORS[fdc.drive]+1) - fdc.sector=1; + + 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] = fdc.res[6] = 0; + fdc.res[7] = fdc.track[fdc.drive]; + fdc.res[8] = fdc.head; + fdc.res[9] = fdc.format_dat[fdc.pos - 2] + 1; + fdc.res[10] = fdc.params[4]; + paramstogo=7; + 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; - timer_process(); - disctime = 2048 * (1 << TIMER_SHIFT); - timer_update_outstanding(); + timer_process(); + disctime = 2048 * (1 << TIMER_SHIFT); + timer_update_outstanding(); fdc.stat = 0x80 | (1 << fdc.drive); // pclog("Stat %02X ST0 %02X\n", fdc.stat, fdc.st0); return; @@ -779,7 +710,7 @@ void fdc_poll() fdc.res[10] = (fdc.perp & 0x7f) | ((fdc.lock) ? 0x80 : 0); paramstogo=10; discint=0; - disctime=0; + disctime = 0; return; case 0x10: /*Version*/ @@ -787,21 +718,21 @@ void fdc_poll() fdc.res[10] = 0x90; paramstogo=1; discint=0; - disctime=0; + disctime = 0; return; case 0x12: 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; @@ -809,7 +740,7 @@ void fdc_poll() fdc.res[10] = 0; paramstogo=1; discint=0; - disctime=0; + disctime = 0; return; case 0x94: /*Lock*/ fdc.lock = 1; @@ -817,74 +748,20 @@ void fdc_poll() fdc.res[10] = 0x10; paramstogo=1; discint=0; - disctime=0; + disctime = 0; return; 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; paramstogo=1; discint=0; - disctime=0; - return; - - 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"); - 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[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"); - disctime=0; - discint=-2; - fdc_int(); - fdc.stat=0xD0; - fdc.res[4]=0x40|(fdc.head?4:0)|fdc.drive; - fdc.res[5]=5; - fdc.res[6]=0; - fdc.res[7]=0; - fdc.res[8]=0; - fdc.res[9]=0; - fdc.res[10]=0; - paramstogo=7; return; } // printf("Bad FDC disc int %i\n",discint); @@ -892,9 +769,165 @@ void fdc_poll() // exit(-1); } +void fdc_overrun() +{ + img_stop(); + disctime = 0; + + fdc_int(); + fdc.stat=0xD0; + 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; +} + +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; + + fdc_int(); + fdc.stat=0xD0; + fdc.res[4]=0x40|(fdc.head?4:0)|fdc.drive; + fdc.res[5]=5; + 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_notfound\n"); +} + +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; +} diff --git a/src/fdc.h b/src/fdc.h index 1f6fb28..de1b1ae 100644 --- a/src/fdc.h +++ b/src/fdc.h @@ -5,3 +5,4 @@ void fdc_remove(); void fdc_reset(); void fdc_poll(); void fdc_abort(); +void fdc_discchange_clear(int drive); diff --git a/src/fdi2raw.c b/src/fdi2raw.c new file mode 100644 index 0000000..f2ac8e7 --- /dev/null +++ b/src/fdi2raw.c @@ -0,0 +1,2190 @@ +/* + + FDI to raw bit stream converter + Copyright (c) 2001 by Toni Wilen + FDI 2.0 support + Copyright (c) 2003-2004 by Toni Wilen + and Vincent Joguin + + FDI format created by Vincent "ApH" Joguin + + Tiny changes - function type fixes, multiple drives, addition of + get_last_head and C++ callability - by Thomas Harte, 2001, + T.Harte@excite.co.uk + + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +*/ + +#define STATIC_INLINE +#include +#include +#include +#include + +/* IF UAE */ +/*#include "sysconfig.h" +#include "sysdeps.h" +#include "zfile.h"*/ +/* ELSE */ +//#include "types.h" +#define xmalloc malloc +#include "fdi2raw.h" + +#include "ibm.h" + +#undef DEBUG +#define VERBOSE +#undef VERBOSE + +#include + +#ifdef DEBUG +static char *datalog(uae_u8 *src, int len) +{ + static char buf[1000]; + static int offset; + int i = 0, offset2; + + offset2 = offset; + buf[offset++]='\''; + while(len--) { + sprintf (buf + offset, "%02.2X", src[i]); + offset += 2; + i++; + if (i > 10) break; + } + buf[offset++]='\''; + buf[offset++] = 0; + if (offset >= 900) offset = 0; + return buf + offset2; +} +#else +static char *datalog(uae_u8 *src, int len) { return ""; } +#endif + +#define outlog pclog +#define debuglog pclog + +static int fdi_allocated; +#ifdef DEBUG +static void fdi_free (void *p) +{ + int size; + if (!p) + return; + size = ((int*)p)[-1]; + fdi_allocated -= size; + write_log ("%d freed (%d)\n", size, fdi_allocated); + free ((int*)p - 1); +} +static void *fdi_malloc (int size) +{ + void *p = xmalloc (size + sizeof (int)); + ((int*)p)[0] = size; + fdi_allocated += size; + write_log ("%d allocated (%d)\n", size, fdi_allocated); + return (int*)p + 1; +} +#else +#define fdi_free free +#define fdi_malloc xmalloc +#endif + +#define MAX_SRC_BUFFER 4194304 +#define MAX_DST_BUFFER 40000 +#define MAX_MFM_SYNC_BUFFER 60000 +#define MAX_TIMING_BUFFER 400000 +#define MAX_TRACKS 166 + +struct fdi_cache { + uae_u32 *avgp, *minp, *maxp; + uae_u8 *idxp; + int avg_free, idx_free, min_free, max_free; + uae_u32 totalavg, pulses, maxidx, indexoffset; + int weakbits; + int lowlevel; +}; + +struct fdi { + uae_u8 *track_src_buffer; + uae_u8 *track_src; + int track_src_len; + uae_u8 *track_dst_buffer; + uae_u8 *track_dst; + uae_u16 *track_dst_buffer_timing; + uae_u8 track_len; + uae_u8 track_type; + int current_track; + int last_track; + int last_head; + int rotation_speed; + int bit_rate; + int disk_type; + int write_protect; + int err; + uae_u8 header[2048]; + int track_offsets[MAX_TRACKS]; + FILE *file; + int out; + int mfmsync_offset; + int *mfmsync_buffer; + /* sector described only */ + int index_offset; + int encoding_type; + /* bit handling */ + int nextdrop; + struct fdi_cache cache[MAX_TRACKS]; +}; + +#define get_u32(x) ((((x)[0])<<24)|(((x)[1])<<16)|(((x)[2])<<8)|((x)[3])) +#define get_u24(x) ((((x)[0])<<16)|(((x)[1])<<8)|((x)[2])) +STATIC_INLINE void put_u32 (uae_u8 *d, uae_u32 v) +{ + d[0] = v >> 24; + d[1] = v >> 16; + d[2] = v >> 8; + d[3] = v; +} + +struct node { + uae_u16 v; + struct node *left; + struct node *right; +}; +typedef struct node NODE; + +static uae_u8 temp, temp2; + +static uae_u8 *expand_tree (uae_u8 *stream, NODE *node) +{ + if (temp & temp2) { + fdi_free (node->left); + node->left = 0; + fdi_free (node->right); + node->right = 0; + temp2 >>= 1; + if (!temp2) { + temp = *stream++; + temp2 = 0x80; + } + return stream; + } else { + uae_u8 *stream_temp; + temp2 >>= 1; + if (!temp2) { + temp = *stream++; + temp2 = 0x80; + } + node->left = fdi_malloc (sizeof (NODE)); + memset (node->left, 0, sizeof (NODE)); + stream_temp = expand_tree (stream, node->left); + node->right = fdi_malloc (sizeof (NODE)); + memset (node->right, 0, sizeof (NODE)); + return expand_tree (stream_temp, node->right); + } +} + +static uae_u8 *values_tree8 (uae_u8 *stream, NODE *node) +{ + if (node->left == 0) { + node->v = *stream++; + return stream; + } else { + uae_u8 *stream_temp = values_tree8 (stream, node->left); + return values_tree8 (stream_temp, node->right); + } +} + +static uae_u8 *values_tree16 (uae_u8 *stream, NODE *node) +{ + if (node->left == 0) { + uae_u16 high_8_bits = (*stream++) << 8; + node->v = high_8_bits | (*stream++); + return stream; + } else { + uae_u8 *stream_temp = values_tree16 (stream, node->left); + return values_tree16 (stream_temp, node->right); + } +} + +static void free_nodes (NODE *node) +{ + if (node) { + free_nodes (node->left); + free_nodes (node->right); + fdi_free (node); + } +} + +static uae_u32 sign_extend16 (uae_u32 v) +{ + if (v & 0x8000) + v |= 0xffff0000; + return v; +} + +static uae_u32 sign_extend8 (uae_u32 v) +{ + if (v & 0x80) + v |= 0xffffff00; + return v; +} + +static void fdi_decode (uae_u8 *stream, int size, uae_u8 *out) +{ + int i; + uae_u8 sign_extend, sixteen_bit, sub_stream_shift; + NODE root; + NODE *current_node; + + memset (out, 0, size * 4); + sub_stream_shift = 1; + while (sub_stream_shift) { + + //sub-stream header decode + sign_extend = *stream++; + sub_stream_shift = sign_extend & 0x7f; + sign_extend &= 0x80; + sixteen_bit = (*stream++) & 0x80; + + //huffman tree architecture decode + temp = *stream++; + temp2 = 0x80; + stream = expand_tree (stream, &root); + if (temp2 == 0x80) + stream--; + + //huffman output values decode + if (sixteen_bit) + stream = values_tree16 (stream, &root); + else + stream = values_tree8 (stream, &root); + + //sub-stream data decode + temp2 = 0; + for (i = 0; i < size; i++) { + uae_u32 v; + uae_u8 decode = 1; + current_node = &root; + while (decode) { + if (current_node->left == 0) { + decode = 0; + } else { + temp2 >>= 1; + if (!temp2) { + temp2 = 0x80; + temp = *stream++; + } + if (temp & temp2) + current_node = current_node->right; + else + current_node = current_node->left; + } + } + v = ((uae_u32*)out)[i]; + if (sign_extend) { + if (sixteen_bit) + v |= sign_extend16 (current_node->v) << sub_stream_shift; + else + v |= sign_extend8 (current_node->v) << sub_stream_shift; + } else { + v |= current_node->v << sub_stream_shift; + } + ((uae_u32*)out)[i] = v; + } + free_nodes (root.left); + free_nodes (root.right); + } +} + + +static int decode_raw_track (FDI *fdi) +{ + int size = get_u32(fdi->track_src); + memcpy (fdi->track_dst, fdi->track_src, (size + 7) >> 3); + fdi->track_src += (size + 7) >> 3; + return size; +} + +/* unknown track */ +static void zxx (FDI *fdi) +{ + outlog ("track %d: unknown track type 0x%02.2X\n", fdi->current_track, fdi->track_type); +// return -1; +} +/* unsupported track */ +#if 0 +static void zyy (FDI *fdi) +{ + outlog ("track %d: unsupported track type 0x%02.2X\n", fdi->current_track, fdi->track_type); +// return -1; +} +#endif +/* empty track */ +static void track_empty (FDI *fdi) +{ +// return 0; +} + +/* unknown sector described type */ +static void dxx (FDI *fdi) +{ + outlog ("\ntrack %d: unknown sector described type 0x%02.2X\n", fdi->current_track, fdi->track_type); + fdi->err = 1; +} +/* unsupported sector described type */ +#if 0 +static void dyy (FDI *fdi) +{ + outlog ("\ntrack %d: unsupported sector described 0x%02.2X\n", fdi->current_track, fdi->track_type); + fdi->err = 1; +} +#endif +/* add position of mfm sync bit */ +static void add_mfm_sync_bit (FDI *fdi) +{ + if (fdi->nextdrop) { + fdi->nextdrop = 0; + return; + } + fdi->mfmsync_buffer[fdi->mfmsync_offset++] = fdi->out; + if (fdi->out == 0) { + outlog ("illegal position for mfm sync bit, offset=%d\n",fdi->out); + fdi->err = 1; + } + if (fdi->mfmsync_offset >= MAX_MFM_SYNC_BUFFER) { + fdi->mfmsync_offset = 0; + outlog ("mfmsync buffer overflow\n"); + fdi->err = 1; + } + fdi->out++; +} + +#define BIT_BYTEOFFSET ((fdi->out) >> 3) +#define BIT_BITOFFSET (7-((fdi->out)&7)) + +/* add one bit */ +static void bit_add (FDI *fdi, int bit) +{ + if (fdi->nextdrop) { + fdi->nextdrop = 0; + return; + } + fdi->track_dst[BIT_BYTEOFFSET] &= ~(1 << BIT_BITOFFSET); + if (bit) + fdi->track_dst[BIT_BYTEOFFSET] |= (1 << BIT_BITOFFSET); + fdi->out++; + if (fdi->out >= MAX_DST_BUFFER * 8) { + outlog ("destination buffer overflow\n"); + fdi->err = 1; + fdi->out = 1; + } +} +/* add bit and mfm sync bit */ +static void bit_mfm_add (FDI *fdi, int bit) +{ + add_mfm_sync_bit (fdi); + bit_add (fdi, bit); +} +/* remove following bit */ +static void bit_drop_next (FDI *fdi) +{ + if (fdi->nextdrop > 0) { + outlog("multiple bit_drop_next() called"); + } else if (fdi->nextdrop < 0) { + fdi->nextdrop = 0; + debuglog(":DNN:"); + return; + } + debuglog(":DN:"); + fdi->nextdrop = 1; +} + +/* ignore next bit_drop_next() */ +static void bit_dedrop (FDI *fdi) +{ + if (fdi->nextdrop) { + outlog("bit_drop_next called before bit_dedrop"); + } + fdi->nextdrop = -1; + debuglog(":BDD:"); +} + +/* add one byte */ +static void byte_add (FDI *fdi, uae_u8 v) +{ + int i; + for (i = 7; i >= 0; i--) + bit_add (fdi, v & (1 << i)); +} +/* add one word */ +static void word_add (FDI *fdi, uae_u16 v) +{ + byte_add (fdi, (uae_u8)(v >> 8)); + byte_add (fdi, (uae_u8)v); +} +/* add one byte and mfm encode it */ +static void byte_mfm_add (FDI *fdi, uae_u8 v) +{ + int i; + for (i = 7; i >= 0; i--) + bit_mfm_add (fdi, v & (1 << i)); +} +/* add multiple bytes and mfm encode them */ +static void bytes_mfm_add (FDI *fdi, uae_u8 v, int len) +{ + int i; + for (i = 0; i < len; i++) byte_mfm_add (fdi, v); +} +/* add one mfm encoded word and re-mfm encode it */ +static void word_post_mfm_add (FDI *fdi, uae_u16 v) +{ + int i; + for (i = 14; i >= 0; i -= 2) + bit_mfm_add (fdi, v & (1 << i)); +} + +/* bit 0 */ +static void s00(FDI *fdi) { bit_add (fdi, 0); } +/* bit 1*/ +static void s01(FDI *fdi) { bit_add (fdi, 1); } +/* 4489 */ +static void s02(FDI *fdi) { word_add (fdi, 0x4489); } +/* 5224 */ +static void s03(FDI *fdi) { word_add (fdi, 0x5224); } +/* mfm sync bit */ +static void s04(FDI *fdi) { add_mfm_sync_bit (fdi); } +/* RLE MFM-encoded data */ +static void s08(FDI *fdi) +{ + int bytes = *fdi->track_src++; + uae_u8 byte = *fdi->track_src++; + if (bytes == 0) bytes = 256; + debuglog ("s08:len=%d,data=%02.2X",bytes,byte); + while(bytes--) byte_add (fdi, byte); +} +/* RLE MFM-decoded data */ +static void s09(FDI *fdi) +{ + int bytes = *fdi->track_src++; + uae_u8 byte = *fdi->track_src++; + if (bytes == 0) bytes = 256; + bit_drop_next (fdi); + debuglog ("s09:len=%d,data=%02.2X",bytes,byte); + while(bytes--) byte_mfm_add (fdi, byte); +} +/* MFM-encoded data */ +static void s0a(FDI *fdi) +{ + int i, bits = (fdi->track_src[0] << 8) | fdi->track_src[1]; + uae_u8 b; + fdi->track_src += 2; + debuglog ("s0a:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); + while (bits >= 8) { + byte_add (fdi, *fdi->track_src++); + bits -= 8; + } + if (bits > 0) { + i = 7; + b = *fdi->track_src++; + while (bits--) { + bit_add (fdi, b & (1 << i)); + i--; + } + } +} +/* MFM-encoded data */ +static void s0b(FDI *fdi) +{ + int i, bits = ((fdi->track_src[0] << 8) | fdi->track_src[1]) + 65536; + uae_u8 b; + fdi->track_src += 2; + debuglog ("s0b:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); + while (bits >= 8) { + byte_add (fdi, *fdi->track_src++); + bits -= 8; + } + if (bits > 0) { + i = 7; + b = *fdi->track_src++; + while (bits--) { + bit_add (fdi, b & (1 << i)); + i--; + } + } +} +/* MFM-decoded data */ +static void s0c(FDI *fdi) +{ + int i, bits = (fdi->track_src[0] << 8) | fdi->track_src[1]; + uae_u8 b; + fdi->track_src += 2; + bit_drop_next (fdi); + debuglog ("s0c:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); + while (bits >= 8) { + byte_mfm_add (fdi, *fdi->track_src++); + bits -= 8; + } + if (bits > 0) { + i = 7; + b = *fdi->track_src++; + while(bits--) { + bit_mfm_add (fdi, b & (1 << i)); + i--; + } + } +} +/* MFM-decoded data */ +static void s0d(FDI *fdi) +{ + int i, bits = ((fdi->track_src[0] << 8) | fdi->track_src[1]) + 65536; + uae_u8 b; + fdi->track_src += 2; + bit_drop_next (fdi); + debuglog ("s0d:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); + while (bits >= 8) { + byte_mfm_add (fdi, *fdi->track_src++); + bits -= 8; + } + if (bits > 0) { + i = 7; + b = *fdi->track_src++; + while(bits--) { + bit_mfm_add (fdi, b & (1 << i)); + i--; + } + } +} + +/* ***** */ +/* AMIGA */ +/* ***** */ + +/* just for testing integrity of Amiga sectors */ + +/*static void rotateonebit (uae_u8 *start, uae_u8 *end, int shift) +{ + if (shift == 0) + return; + while (start <= end) { + start[0] <<= shift; + start[0] |= start[1] >> (8 - shift); + start++; + } +}*/ + +//static int check_offset; +/*static uae_u16 getmfmword (uae_u8 *mbuf) +{ + uae_u32 v; + + v = (mbuf[0] << 8) | (mbuf[1] << 0); + if (check_offset == 0) + return v; + v <<= 8; + v |= mbuf[2]; + v >>= check_offset; + return v; +}*/ + +#define MFMMASK 0x55555555 +/*static uae_u32 getmfmlong (uae_u8 * mbuf) +{ + return ((getmfmword (mbuf) << 16) | getmfmword (mbuf + 2)) & MFMMASK; +}*/ + +#if 0 +static int amiga_check_track (FDI *fdi) +{ + int i, j, secwritten = 0; + int fwlen = fdi->out / 8; + int length = 2 * fwlen; + int drvsec = 11; + uae_u32 odd, even, chksum, id, dlong; + uae_u8 *secdata; + uae_u8 secbuf[544]; + uae_u8 bigmfmbuf[60000]; + uae_u8 *mbuf, *mbuf2, *mend; + char sectable[22]; + uae_u8 *raw = fdi->track_dst_buffer; + int slabel, off; + int ok = 1; + + memset (bigmfmbuf, 0, sizeof (bigmfmbuf)); + mbuf = bigmfmbuf; + check_offset = 0; + for (i = 0; i < (fdi->out + 7) / 8; i++) + *mbuf++ = raw[i]; + off = fdi->out & 7; +#if 1 + if (off > 0) { + mbuf--; + *mbuf &= ~((1 << (8 - off)) - 1); + } + j = 0; + while (i < (fdi->out + 7) / 8 + 600) { + *mbuf++ |= (raw[j] >> off) | ((raw[j + 1]) << (8 - off)); + j++; + i++; + } +#endif + mbuf = bigmfmbuf; + + memset (sectable, 0, sizeof (sectable)); + //memcpy (mbuf + fwlen, mbuf, fwlen * sizeof (uae_u16)); + mend = bigmfmbuf + length; + mend -= (4 + 16 + 8 + 512); + + while (secwritten < drvsec) { + int trackoffs; + + for (;;) { + rotateonebit (bigmfmbuf, mend, 1); + if (getmfmword (mbuf) == 0) + break; + if (secwritten == 10) { + mbuf[0] = 0x44; + mbuf[1] = 0x89; + } +// check_offset++; + if (check_offset > 7) { + check_offset = 0; + mbuf++; + if (mbuf >= mend || *mbuf == 0) + break; + } + if (getmfmword (mbuf) == 0x4489) + break; + } + if (mbuf >= mend || *mbuf == 0) + break; + + rotateonebit (bigmfmbuf, mend, check_offset); + check_offset = 0; + + while (getmfmword (mbuf) == 0x4489) + mbuf+= 1 * 2; + mbuf2 = mbuf + 8; + + odd = getmfmlong (mbuf); + even = getmfmlong (mbuf + 2 * 2); + mbuf += 4 * 2; + id = (odd << 1) | even; + + trackoffs = (id & 0xff00) >> 8; + if (trackoffs + 1 > drvsec) { + outlog("illegal sector offset %d\n",trackoffs); + ok = 0; + mbuf = mbuf2; + continue; + } + if ((id >> 24) != 0xff) { + outlog ("sector %d format type %02.2X?\n", trackoffs, id >> 24); + ok = 0; + } + chksum = odd ^ even; + slabel = 0; + for (i = 0; i < 4; i++) { + odd = getmfmlong (mbuf); + even = getmfmlong (mbuf + 8 * 2); + mbuf += 2* 2; + + dlong = (odd << 1) | even; + if (dlong) slabel = 1; + chksum ^= odd ^ even; + } + mbuf += 8 * 2; + odd = getmfmlong (mbuf); + even = getmfmlong (mbuf + 2 * 2); + mbuf += 4 * 2; + if (((odd << 1) | even) != chksum) { + outlog("sector %d header crc error\n", trackoffs); + ok = 0; + mbuf = mbuf2; + continue; + } + outlog("sector %d header crc ok\n", trackoffs); + if (((id & 0x00ff0000) >> 16) != (uae_u32)fdi->current_track) { + outlog("illegal track number %d <> %d\n",fdi->current_track,(id & 0x00ff0000) >> 16); + ok++; + mbuf = mbuf2; + continue; + } + odd = getmfmlong (mbuf); + even = getmfmlong (mbuf + 2 * 2); + mbuf += 4 * 2; + chksum = (odd << 1) | even; + secdata = secbuf + 32; + for (i = 0; i < 128; i++) { + odd = getmfmlong (mbuf); + even = getmfmlong (mbuf + 256 * 2); + mbuf += 2 * 2; + dlong = (odd << 1) | even; + *secdata++ = (uae_u8) (dlong >> 24); + *secdata++ = (uae_u8) (dlong >> 16); + *secdata++ = (uae_u8) (dlong >> 8); + *secdata++ = (uae_u8) dlong; + chksum ^= odd ^ even; + } + mbuf += 256 * 2; + if (chksum) { + outlog("sector %d data checksum error\n",trackoffs); + ok = 0; + } else if (sectable[trackoffs]) { + outlog("sector %d already found?\n", trackoffs); + mbuf = mbuf2; + } else { + outlog("sector %d ok\n",trackoffs); + if (slabel) outlog("(non-empty sector header)\n"); + sectable[trackoffs] = 1; + secwritten++; + if (trackoffs == 9) + mbuf += 0x228; + } + } + for (i = 0; i < drvsec; i++) { + if (!sectable[i]) { + outlog ("sector %d missing\n", i); + ok = 0; + } + } + return ok; +} +#endif + +static void amiga_data_raw (FDI *fdi, uae_u8 *secbuf, uae_u8 *crc, int len) +{ + int i; + uae_u8 crcbuf[4]; + + if (!crc) { + memset (crcbuf, 0, 4); + } else { + memcpy (crcbuf, crc ,4); + } + for (i = 0; i < 4; i++) + byte_mfm_add (fdi, crcbuf[i]); + for (i = 0; i < len; i++) + byte_mfm_add (fdi, secbuf[i]); +} + +static void amiga_data (FDI *fdi, uae_u8 *secbuf) +{ + uae_u16 mfmbuf[4 + 512]; + uae_u32 dodd, deven, dck; + int i; + + for (i = 0; i < 512; i += 4) { + deven = ((secbuf[i + 0] << 24) | (secbuf[i + 1] << 16) + | (secbuf[i + 2] << 8) | (secbuf[i + 3])); + dodd = deven >> 1; + deven &= 0x55555555; + dodd &= 0x55555555; + mfmbuf[(i >> 1) + 4] = (uae_u16) (dodd >> 16); + mfmbuf[(i >> 1) + 5] = (uae_u16) dodd; + mfmbuf[(i >> 1) + 256 + 4] = (uae_u16) (deven >> 16); + mfmbuf[(i >> 1) + 256 + 5] = (uae_u16) deven; + } + dck = 0; + for (i = 4; i < 4 + 512; i += 2) + dck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1]; + deven = dodd = dck; + dodd >>= 1; + deven &= 0x55555555; + dodd &= 0x55555555; + mfmbuf[0] = (uae_u16) (dodd >> 16); + mfmbuf[1] = (uae_u16) dodd; + mfmbuf[2] = (uae_u16) (deven >> 16); + mfmbuf[3] = (uae_u16) deven; + + for (i = 0; i < 4 + 512; i ++) + word_post_mfm_add (fdi, mfmbuf[i]); +} + +static void amiga_sector_header (FDI *fdi, uae_u8 *header, uae_u8 *data, int sector, int untilgap) +{ + uae_u8 headerbuf[4], databuf[16]; + uae_u32 deven, dodd, hck; + uae_u16 mfmbuf[24]; + int i; + + byte_mfm_add (fdi, 0); + byte_mfm_add (fdi, 0); + word_add (fdi, 0x4489); + word_add (fdi, 0x4489); + if (header) { + memcpy (headerbuf, header, 4); + } else { + headerbuf[0] = 0xff; + headerbuf[1] = (uae_u8)fdi->current_track; + headerbuf[2] = (uae_u8)sector; + headerbuf[3] = (uae_u8)untilgap; + } + if (data) + memcpy (databuf, data, 16); + else + memset (databuf, 0, 16); + + deven = ((headerbuf[0] << 24) | (headerbuf[1] << 16) + | (headerbuf[2] << 8) | (headerbuf[3])); + dodd = deven >> 1; + deven &= 0x55555555; + dodd &= 0x55555555; + mfmbuf[0] = (uae_u16) (dodd >> 16); + mfmbuf[1] = (uae_u16) dodd; + mfmbuf[2] = (uae_u16) (deven >> 16); + mfmbuf[3] = (uae_u16) deven; + for (i = 0; i < 16; i += 4) { + deven = ((databuf[i] << 24) | (databuf[i + 1] << 16) + | (databuf[i + 2] << 8) | (databuf[i + 3])); + dodd = deven >> 1; + deven &= 0x55555555; + dodd &= 0x55555555; + mfmbuf[(i >> 1) + 0 + 4] = (uae_u16) (dodd >> 16); + mfmbuf[(i >> 1) + 0 + 5] = (uae_u16) dodd; + mfmbuf[(i >> 1) + 8 + 4] = (uae_u16) (deven >> 16); + mfmbuf[(i >> 1) + 8 + 5] = (uae_u16) deven; + } + hck = 0; + for (i = 0; i < 4 + 16; i += 2) + hck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1]; + deven = dodd = hck; + dodd >>= 1; + deven &= 0x55555555; + dodd &= 0x55555555; + mfmbuf[20] = (uae_u16) (dodd >> 16); + mfmbuf[21] = (uae_u16) dodd; + mfmbuf[22] = (uae_u16) (deven >> 16); + mfmbuf[23] = (uae_u16) deven; + + for (i = 0; i < 4 + 16 + 4; i ++) + word_post_mfm_add (fdi, mfmbuf[i]); +} + +/* standard super-extended Amiga sector header */ +static void s20(FDI *fdi) +{ + bit_drop_next (fdi); + debuglog ("s20:header=%s,data=%s", datalog(fdi->track_src, 4), datalog(fdi->track_src + 4, 16)); + amiga_sector_header (fdi, fdi->track_src, fdi->track_src + 4, 0, 0); + fdi->track_src += 4 + 16; +} +/* standard extended Amiga sector header */ +static void s21(FDI *fdi) +{ + bit_drop_next (fdi); + debuglog ("s21:header=%s", datalog(fdi->track_src, 4)); + amiga_sector_header (fdi, fdi->track_src, 0, 0, 0); + fdi->track_src += 4; +} +/* standard Amiga sector header */ +static void s22(FDI *fdi) +{ + bit_drop_next (fdi); + debuglog("s22:sector=%d,untilgap=%d", fdi->track_src[0], fdi->track_src[1]); + amiga_sector_header (fdi, 0, 0, fdi->track_src[0], fdi->track_src[1]); + fdi->track_src += 2; +} +/* standard 512-byte, CRC-correct Amiga data */ +static void s23(FDI *fdi) +{ + debuglog("s23:data=%s", datalog (fdi->track_src, 512)); + amiga_data (fdi, fdi->track_src); + fdi->track_src += 512; +} +/* not-decoded, 128*2^x-byte, CRC-correct Amiga data */ +static void s24(FDI *fdi) +{ + int shift = *fdi->track_src++; + debuglog("s24:shift=%d,data=%s", shift, datalog (fdi->track_src, 128 << shift)); + amiga_data_raw (fdi, fdi->track_src, 0, 128 << shift); + fdi->track_src += 128 << shift; +} +/* not-decoded, 128*2^x-byte, CRC-incorrect Amiga data */ +static void s25(FDI *fdi) +{ + int shift = *fdi->track_src++; + debuglog("s25:shift=%d,crc=%s,data=%s", shift, datalog (fdi->track_src, 4), datalog (fdi->track_src + 4, 128 << shift)); + amiga_data_raw (fdi, fdi->track_src + 4, fdi->track_src, 128 << shift); + fdi->track_src += 4 + (128 << shift); +} +/* standard extended Amiga sector */ +static void s26(FDI *fdi) +{ + s21 (fdi); + debuglog("s26:data=%s", datalog (fdi->track_src, 512)); + amiga_data (fdi, fdi->track_src); + fdi->track_src += 512; +} +/* standard short Amiga sector */ +static void s27(FDI *fdi) +{ + s22 (fdi); + debuglog("s27:data=%s", datalog (fdi->track_src, 512)); + amiga_data (fdi, fdi->track_src); + fdi->track_src += 512; +} + +/* *** */ +/* IBM */ +/* *** */ + +static uae_u16 ibm_crc (uae_u8 byte, int reset) +{ + static uae_u16 crc; + int i; + + if (reset) crc = 0xcdb4; + for (i = 0; i < 8; i++) { + if (crc & 0x8000) { + crc <<= 1; + if (!(byte & 0x80)) crc ^= 0x1021; + } else { + crc <<= 1; + if (byte & 0x80) crc ^= 0x1021; + } + byte <<= 1; + } + return crc; +} + +static void ibm_data (FDI *fdi, uae_u8 *data, uae_u8 *crc, int len) +{ + int i; + uae_u8 crcbuf[2]; + uae_u16 crcv = 0; + + word_add (fdi, 0x4489); + word_add (fdi, 0x4489); + word_add (fdi, 0x4489); + byte_mfm_add (fdi, 0xfb); + ibm_crc (0xfb, 1); + for (i = 0; i < len; i++) { + byte_mfm_add (fdi, data[i]); + crcv = ibm_crc (data[i], 0); + } + if (!crc) { + crc = crcbuf; + crc[0] = (uae_u8)(crcv >> 8); + crc[1] = (uae_u8)crcv; + } + byte_mfm_add (fdi, crc[0]); + byte_mfm_add (fdi, crc[1]); +} + +static void ibm_sector_header (FDI *fdi, uae_u8 *data, uae_u8 *crc, int secnum, int pre) +{ + uae_u8 secbuf[5]; + uae_u8 crcbuf[2]; + uae_u16 crcv; + int i; + + if (pre) + bytes_mfm_add (fdi, 0, 12); + word_add (fdi, 0x4489); + word_add (fdi, 0x4489); + word_add (fdi, 0x4489); + secbuf[0] = 0xfe; + if (secnum >= 0) { + secbuf[1] = (uae_u8)(fdi->current_track/2); + secbuf[2] = (uae_u8)(fdi->current_track%2); + secbuf[3] = (uae_u8)secnum; + secbuf[4] = 2; + } else { + memcpy (secbuf + 1, data, 4); + } + ibm_crc (secbuf[0], 1); + ibm_crc (secbuf[1], 0); + ibm_crc (secbuf[2], 0); + ibm_crc (secbuf[3], 0); + crcv = ibm_crc (secbuf[4], 0); + if (crc) { + memcpy (crcbuf, crc, 2); + } else { + crcbuf[0] = (uae_u8)(crcv >> 8); + crcbuf[1] = (uae_u8)crcv; + } + /* data */ + for (i = 0;i < 5; i++) + byte_mfm_add (fdi, secbuf[i]); + /* crc */ + byte_mfm_add (fdi, crcbuf[0]); + byte_mfm_add (fdi, crcbuf[1]); +} + +/* standard IBM index address mark */ +static void s10(FDI *fdi) +{ + bit_drop_next (fdi); + bytes_mfm_add (fdi, 0, 12); + word_add (fdi, 0x5224); + word_add (fdi, 0x5224); + word_add (fdi, 0x5224); + byte_mfm_add (fdi, 0xfc); +} +/* standard IBM pre-gap */ +static void s11(FDI *fdi) +{ + bit_drop_next (fdi); + bytes_mfm_add (fdi, 0x4e, 78); + bit_dedrop (fdi); + s10 (fdi); + bytes_mfm_add (fdi, 0x4e, 50); +} +/* standard ST pre-gap */ +static void s12(FDI *fdi) +{ + bit_drop_next (fdi); + bytes_mfm_add (fdi, 0x4e, 78); +} +/* standard extended IBM sector header */ +static void s13(FDI *fdi) +{ + bit_drop_next (fdi); + debuglog ("s13:header=%s", datalog (fdi->track_src, 4)); + ibm_sector_header (fdi, fdi->track_src, 0, -1, 1); + fdi->track_src += 4; +} +/* standard mini-extended IBM sector header */ +static void s14(FDI *fdi) +{ + debuglog ("s14:header=%s", datalog (fdi->track_src, 4)); + ibm_sector_header (fdi, fdi->track_src, 0, -1, 0); + fdi->track_src += 4; +} +/* standard short IBM sector header */ +static void s15(FDI *fdi) +{ + bit_drop_next (fdi); + debuglog ("s15:sector=%d", *fdi->track_src); + ibm_sector_header (fdi, 0, 0, *fdi->track_src++, 1); +} +/* standard mini-short IBM sector header */ +static void s16(FDI *fdi) +{ + debuglog ("s16:track=%d", *fdi->track_src); + ibm_sector_header (fdi, 0, 0, *fdi->track_src++, 0); +} +/* standard CRC-incorrect mini-extended IBM sector header */ +static void s17(FDI *fdi) +{ + debuglog ("s17:header=%s,crc=%s", datalog (fdi->track_src, 4), datalog (fdi->track_src + 4, 2)); + ibm_sector_header (fdi, fdi->track_src, fdi->track_src + 4, -1, 0); + fdi->track_src += 4 + 2; +} +/* standard CRC-incorrect mini-short IBM sector header */ +static void s18(FDI *fdi) +{ + debuglog ("s18:sector=%d,header=%s", *fdi->track_src, datalog (fdi->track_src + 1, 4)); + ibm_sector_header (fdi, 0, fdi->track_src + 1, *fdi->track_src, 0); + fdi->track_src += 1 + 4; +} +/* standard 512-byte CRC-correct IBM data */ +static void s19(FDI *fdi) +{ + debuglog ("s19:data=%s", datalog (fdi->track_src , 512)); + ibm_data (fdi, fdi->track_src, 0, 512); + fdi->track_src += 512; +} +/* standard 128*2^x-byte-byte CRC-correct IBM data */ +static void s1a(FDI *fdi) +{ + int shift = *fdi->track_src++; + debuglog ("s1a:shift=%d,data=%s", shift, datalog (fdi->track_src , 128 << shift)); + ibm_data (fdi, fdi->track_src, 0, 128 << shift); + fdi->track_src += 128 << shift; +} +/* standard 128*2^x-byte-byte CRC-incorrect IBM data */ +static void s1b(FDI *fdi) +{ + int shift = *fdi->track_src++; + debuglog ("s1b:shift=%d,crc=%s,data=%s", shift, datalog (fdi->track_src + (128 << shift), 2), datalog (fdi->track_src , 128 << shift)); + ibm_data (fdi, fdi->track_src, fdi->track_src + (128 << shift), 128 << shift); + fdi->track_src += (128 << shift) + 2; +} +/* standard extended IBM sector */ +static void s1c(FDI *fdi) +{ + int shift = fdi->track_src[3]; + s13 (fdi); + bytes_mfm_add (fdi, 0x4e, 22); + bytes_mfm_add (fdi, 0x00, 12); + ibm_data (fdi, fdi->track_src, 0, 128 << shift); + fdi->track_src += 128 << shift; +} +/* standard short IBM sector */ +static void s1d(FDI *fdi) +{ + s15 (fdi); + bytes_mfm_add (fdi, 0x4e, 22); + bytes_mfm_add (fdi, 0x00, 12); + s19 (fdi); +} + +/* end marker */ +static void sff(FDI *fdi) +{ +} + +typedef void (*decode_described_track_func)(FDI*); + +static decode_described_track_func decode_sectors_described_track[] = +{ + s00,s01,s02,s03,s04,dxx,dxx,dxx,s08,s09,s0a,s0b,s0c,s0d,dxx,dxx, /* 00-0F */ + s10,s11,s12,s13,s14,s15,s16,s17,s18,s19,s1a,s1b,s1c,s1d,dxx,dxx, /* 10-1F */ + s20,s21,s22,s23,s24,s25,s26,s27,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 20-2F */ + dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 30-3F */ + dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 40-4F */ + dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 50-5F */ + dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 60-6F */ + dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 70-7F */ + dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 80-8F */ + dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* 90-9F */ + dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* A0-AF */ + dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* B0-BF */ + dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* C0-CF */ + dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* D0-DF */ + dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx, /* E0-EF */ + dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,dxx,sff /* F0-FF */ +}; + +static void track_amiga (struct fdi *fdi, int first_sector, int max_sector) +{ + int i; + + bit_add (fdi, 0); + bit_drop_next (fdi); + for (i = 0; i < max_sector; i++) { + amiga_sector_header (fdi, 0, 0, first_sector, max_sector - i); + amiga_data (fdi, fdi->track_src + first_sector * 512); + first_sector++; + if (first_sector >= max_sector) first_sector = 0; + } + bytes_mfm_add (fdi, 0, 260); /* gap */ +} +static void track_atari_st (struct fdi *fdi, int max_sector) +{ + int i, gap3 = 0; + uae_u8 *p = fdi->track_src; + + switch (max_sector) + { + case 9: + gap3 = 40; + break; + case 10: + gap3 = 24; + break; + } + s15 (fdi); + for (i = 0; i < max_sector; i++) { + byte_mfm_add (fdi, 0x4e); + byte_mfm_add (fdi, 0x4e); + ibm_sector_header (fdi, 0, 0, fdi->current_track, 1); + ibm_data (fdi, p + i * 512, 0, 512); + bytes_mfm_add (fdi, 0x4e, gap3); + } + bytes_mfm_add (fdi, 0x4e, 660 - gap3); + fdi->track_src += fdi->track_len * 256; +} +static void track_pc (struct fdi *fdi, int max_sector) +{ + int i, gap3; + uae_u8 *p = fdi->track_src; + + switch (max_sector) + { + case 8: + gap3 = 116; + break; + case 9: + gap3 = 54; + break; + default: + gap3 = 100; /* fixme */ + break; + } + s11 (fdi); + for (i = 0; i < max_sector; i++) { + byte_mfm_add (fdi, 0x4e); + byte_mfm_add (fdi, 0x4e); + ibm_sector_header (fdi, 0, 0, fdi->current_track, 1); + ibm_data (fdi, p + i * 512, 0, 512); + bytes_mfm_add (fdi, 0x4e, gap3); + } + bytes_mfm_add (fdi, 0x4e, 600 - gap3); + fdi->track_src += fdi->track_len * 256; +} + +/* amiga dd */ +static void track_amiga_dd (struct fdi *fdi) +{ + uae_u8 *p = fdi->track_src; + track_amiga (fdi, fdi->track_len >> 4, 11); + fdi->track_src = p + (fdi->track_len & 15) * 512; +} +/* amiga hd */ +static void track_amiga_hd (struct fdi *fdi) +{ + uae_u8 *p = fdi->track_src; + track_amiga (fdi, 0, 22); + fdi->track_src = p + fdi->track_len * 256; +} +/* atari st 9 sector */ +static void track_atari_st_9 (struct fdi *fdi) +{ + track_atari_st (fdi, 9); +} +/* atari st 10 sector */ +static void track_atari_st_10 (struct fdi *fdi) +{ + track_atari_st (fdi, 10); +} +/* pc 8 sector */ +static void track_pc_8 (struct fdi *fdi) +{ + track_pc (fdi, 8); +} +/* pc 9 sector */ +static void track_pc_9 (struct fdi *fdi) +{ + track_pc (fdi, 9); +} +/* pc 15 sector */ +static void track_pc_15 (struct fdi *fdi) +{ + track_pc (fdi, 15); +} +/* pc 18 sector */ +static void track_pc_18 (struct fdi *fdi) +{ + track_pc (fdi, 18); +} +/* pc 36 sector */ +static void track_pc_36 (struct fdi *fdi) +{ + track_pc (fdi, 36); +} + +typedef void (*decode_normal_track_func)(FDI*); + +static decode_normal_track_func decode_normal_track[] = +{ + track_empty, /* 0 */ + track_amiga_dd, track_amiga_hd, /* 1-2 */ + track_atari_st_9, track_atari_st_10, /* 3-4 */ + track_pc_8, track_pc_9, track_pc_15, track_pc_18, track_pc_36, /* 5-9 */ + zxx,zxx,zxx,zxx,zxx /* A-F */ +}; + +static void fix_mfm_sync (FDI *fdi) +{ + int i, pos, off1, off2, off3, mask1, mask2, mask3; + + for (i = 0; i < fdi->mfmsync_offset; i++) { + pos = fdi->mfmsync_buffer[i]; + off1 = (pos - 1) >> 3; + off2 = (pos + 1) >> 3; + off3 = pos >> 3; + mask1 = 1 << (7 - ((pos - 1) & 7)); + mask2 = 1 << (7 - ((pos + 1) & 7)); + mask3 = 1 << (7 - (pos & 7)); + if (!(fdi->track_dst[off1] & mask1) && !(fdi->track_dst[off2] & mask2)) + fdi->track_dst[off3] |= mask3; + else + fdi->track_dst[off3] &= ~mask3; + } +} + +static int handle_sectors_described_track (FDI *fdi) +{ + int oldout; + uae_u8 *start_src = fdi->track_src ; + fdi->encoding_type = *fdi->track_src++; + fdi->index_offset = get_u32(fdi->track_src); + fdi->index_offset >>= 8; + fdi->track_src += 3; + outlog ("sectors_described, index offset: %d\n",fdi->index_offset); + + do { + fdi->track_type = *fdi->track_src++; + outlog ("%06.6X %06.6X %02.2X:",fdi->track_src - start_src + 0x200, fdi->out/8, fdi->track_type); + oldout = fdi->out; + decode_sectors_described_track[fdi->track_type](fdi); + outlog(" %d\n", fdi->out - oldout); + oldout = fdi->out; + if (fdi->out < 0 || fdi->err) { + outlog ("\nin %d bytes, out %d bits\n", fdi->track_src - fdi->track_src_buffer, fdi->out); + return -1; + } + if (fdi->track_src - fdi->track_src_buffer >= fdi->track_src_len) { + outlog ("source buffer overrun, previous type: %02.2X\n", fdi->track_type); + return -1; + } + } while (fdi->track_type != 0xff); + outlog("\n"); + fix_mfm_sync (fdi); + return fdi->out; +} + +static uae_u8 *fdi_decompress (int pulses, uae_u8 *sizep, uae_u8 *src, int *dofree) +{ + uae_u32 size = get_u24 (sizep); + uae_u32 *dst2; + int len = size & 0x3fffff; + uae_u8 *dst; + int mode = size >> 22, i; + + *dofree = 0; + if (mode == 0 && pulses * 2 > len) + mode = 1; + if (mode == 0) { + dst2 = (uae_u32*)src; + dst = src; + for (i = 0; i < pulses; i++) { + *dst2++ = get_u32 (src); + src += 4; + } + } else if (mode == 1) { + dst = fdi_malloc (pulses *4); + *dofree = 1; + fdi_decode (src, pulses, dst); + } else { + dst = 0; + } + return dst; +} + +static void dumpstream(int track, uae_u8 *stream, int len) +{ +#if 0 + char name[100]; + FILE *f; + + sprintf (name, "track_%d.raw", track); + f = fopen(name, "wb"); + fwrite (stream, 1, len * 4, f); + fclose (f); +#endif +} + +static int bitoffset; + +STATIC_INLINE void addbit (uae_u8 *p, int bit) +{ + int off1 = bitoffset / 8; + int off2 = bitoffset % 8; + p[off1] |= bit << (7 - off2); + bitoffset++; +} + + +struct pulse_sample { + uint32_t size; + int number_of_bits; +}; + + +#define FDI_MAX_ARRAY 10 /* change this value as you want */ +static int pulse_limitval = 15; /* tolerance of 15% */ +static struct pulse_sample psarray[FDI_MAX_ARRAY]; +static int array_index; +static unsigned long total; +static int totaldiv; + +static void init_array(uint32_t standard_MFM_2_bit_cell_size, int nb_of_bits) +{ + int i; + + for (i = 0; i < FDI_MAX_ARRAY; i++) { + psarray[i].size = standard_MFM_2_bit_cell_size; // That is (total track length / 50000) for Amiga double density + total += psarray[i].size; + psarray[i].number_of_bits = nb_of_bits; + totaldiv += psarray[i].number_of_bits; + } + array_index = 0; +} + +#if 0 + +static void fdi2_decode (FDI *fdi, uint32_t totalavg, uae_u32 *avgp, uae_u32 *minp, uae_u32 *maxp, uae_u8 *idx, int maxidx, int *indexoffsetp, int pulses, int mfm) +{ + uint32_t adjust; + uint32_t adjusted_pulse; + uint32_t standard_MFM_2_bit_cell_size = totalavg / 50000; + uint32_t standard_MFM_8_bit_cell_size = totalavg / 12500; + int real_size, i, j, eodat, outstep; + int indexoffset = *indexoffsetp; + uae_u8 *d = fdi->track_dst_buffer; + uae_u16 *pt = fdi->track_dst_buffer_timing; + uae_u32 ref_pulse, pulse; + + /* detects a long-enough stable pulse coming just after another stable pulse */ + i = 1; + while ( (i < pulses) && ( (idx[i] < maxidx) + || (idx[i - 1] < maxidx) + || (avgp[i] < (standard_MFM_2_bit_cell_size - (standard_MFM_2_bit_cell_size / 4))) ) ) + i++; + if (i == pulses) { + outlog ("No stable and long-enough pulse in track.\n"); + return; + } + i--; + eodat = i; + adjust = 0; + total = 0; + totaldiv = 0; + init_array(standard_MFM_2_bit_cell_size, 2); + bitoffset = 0; + ref_pulse = 0; + outstep = 0; + while (outstep < 2) { + + /* calculates the current average bitrate from previous decoded data */ + uae_u32 avg_size = (total << 3) / totaldiv; /* this is the new average size for one MFM bit */ + /* uae_u32 avg_size = (uae_u32)((((float)total)*8.0) / ((float)totaldiv)); */ + /* you can try tighter ranges than 25%, or wider ranges. I would probably go for tighter... */ + if ((avg_size < (standard_MFM_8_bit_cell_size - (pulse_limitval * standard_MFM_8_bit_cell_size / 100))) || + (avg_size > (standard_MFM_8_bit_cell_size + (pulse_limitval * standard_MFM_8_bit_cell_size / 100)))) { + //init_array(standard_MFM_2_bit_cell_size, 2); + avg_size = standard_MFM_8_bit_cell_size; + } + /* this is to prevent the average value from going too far + * from the theoretical value, otherwise it could progressively go to (2 * + * real value), or (real value / 2), etc. */ + + /* gets the next long-enough pulse (this may require more than one pulse) */ + pulse = 0; + while (pulse < ((avg_size / 4) - (avg_size / 16))) { + int indx; + i++; + if (i >= pulses) + i = 0; + indx = idx[i]; + if (rand() <= (indx * RAND_MAX) / maxidx) { + pulse += avgp[i] - ref_pulse; + if (indx >= maxidx) + ref_pulse = 0; + else + ref_pulse = avgp[i]; + } + if (i == eodat) + outstep++; + if (outstep == 1 && indexoffset == i) + *indexoffsetp = bitoffset; + } + + /* gets the size in bits from the pulse width, considering the current average bitrate */ + adjusted_pulse = pulse; + real_size = 0; + while (adjusted_pulse >= avg_size) { + real_size += 4; + adjusted_pulse -= avg_size / 2; + } + adjusted_pulse <<= 3; + while (adjusted_pulse >= ((avg_size * 4) + (avg_size / 4))) { + real_size += 2; + adjusted_pulse -= avg_size * 2; + } + if (adjusted_pulse >= ((avg_size * 3) + (avg_size / 4))) { + if (adjusted_pulse <= ((avg_size * 4) - (avg_size / 4))) { + if ((2 * ((adjusted_pulse >> 2) - adjust)) <= ((2 * avg_size) - (avg_size / 4))) + real_size += 3; + else + real_size += 4; + } else + real_size += 4; + } else { + if (adjusted_pulse > ((avg_size * 3) - (avg_size / 4))) { + real_size += 3; + } else { + if (adjusted_pulse >= ((avg_size * 2) + (avg_size / 4))) { + if ((2 * ((adjusted_pulse >> 2) - adjust)) < (avg_size + (avg_size / 4))) + real_size += 2; + else + real_size += 3; + } else + real_size += 2; + } + } + + if (outstep == 1) { + for (j = real_size; j > 1; j--) + addbit (d, 0); + addbit (d, 1); + for (j = 0; j < real_size; j++) + *pt++ = (uae_u16)(pulse / real_size); + } + + /* prepares for the next pulse */ + adjust = ((real_size * avg_size)/8) - pulse; + total -= psarray[array_index].size; + totaldiv -= psarray[array_index].number_of_bits; + psarray[array_index].size = pulse; + psarray[array_index].number_of_bits = real_size; + total += pulse; + totaldiv += real_size; + array_index++; + if (array_index >= FDI_MAX_ARRAY) + array_index = 0; + } + + fdi->out = bitoffset; +} + +#else + +static void fdi2_decode (FDI *fdi, uint32_t totalavg, uae_u32 *avgp, uae_u32 *minp, uae_u32 *maxp, uae_u8 *idx, int maxidx, int *indexoffsetp, int pulses, int mfm) +{ + uint32_t adjust; + uint32_t adjusted_pulse; + uint32_t standard_MFM_2_bit_cell_size = totalavg / 50000; + uint32_t standard_MFM_8_bit_cell_size = totalavg / 12500; + int real_size, i, j, nexti, eodat, outstep, randval; + int indexoffset = *indexoffsetp; + uae_u8 *d = fdi->track_dst_buffer; + uae_u16 *pt = fdi->track_dst_buffer_timing; + uae_u32 ref_pulse, pulse; + long jitter; + + /* detects a long-enough stable pulse coming just after another stable pulse */ + i = 1; + while ( (i < pulses) && ( (idx[i] < maxidx) + || (idx[i - 1] < maxidx) + || (minp[i] < (standard_MFM_2_bit_cell_size - (standard_MFM_2_bit_cell_size / 4))) ) ) + i++; + if (i == pulses) { + outlog ("FDI: No stable and long-enough pulse in track.\n"); + return; + } + nexti = i; + eodat = i; + i--; + adjust = 0; + total = 0; + totaldiv = 0; + init_array(standard_MFM_2_bit_cell_size, 1 + mfm); + bitoffset = 0; + ref_pulse = 0; + jitter = 0; + outstep = -1; + while (outstep < 2) { + + /* calculates the current average bitrate from previous decoded data */ + uae_u32 avg_size = (total << (2 + mfm)) / totaldiv; /* this is the new average size for one MFM bit */ + /* uae_u32 avg_size = (uae_u32)((((float)total)*((float)(mfm+1))*4.0) / ((float)totaldiv)); */ + /* you can try tighter ranges than 25%, or wider ranges. I would probably go for tighter... */ + if ((avg_size < (standard_MFM_8_bit_cell_size - (pulse_limitval * standard_MFM_8_bit_cell_size / 100))) || + (avg_size > (standard_MFM_8_bit_cell_size + (pulse_limitval * standard_MFM_8_bit_cell_size / 100)))) { + //init_array(standard_MFM_2_bit_cell_size, mfm + 1); + avg_size = standard_MFM_8_bit_cell_size; + } + /* this is to prevent the average value from going too far + * from the theoretical value, otherwise it could progressively go to (2 * + * real value), or (real value / 2), etc. */ + + /* gets the next long-enough pulse (this may require more than one pulse) */ + pulse = 0; + while (pulse < ((avg_size / 4) - (avg_size / 16))) { + uae_u32 avg_pulse, min_pulse, max_pulse; + i++; + if (i >= pulses) + i = 0; + if (i == nexti) { + do { + nexti++; + if (nexti >= pulses) + nexti = 0; + } while (idx[nexti] < maxidx); + } + if (idx[i] >= maxidx) { /* stable pulse */ + avg_pulse = avgp[i] - jitter; + min_pulse = minp[i]; + max_pulse = maxp[i]; + if (jitter >= 0) + max_pulse -= jitter; + else + min_pulse -= jitter; + if ((maxp[nexti] - avgp[nexti]) < (avg_pulse - min_pulse)) + min_pulse = avg_pulse - (maxp[nexti] - avgp[nexti]); + if ((avgp[nexti] - minp[nexti]) < (max_pulse - avg_pulse)) + max_pulse = avg_pulse + (avgp[nexti] - minp[nexti]); + if (min_pulse < ref_pulse) + min_pulse = ref_pulse; + randval = rand(); + if (randval < (RAND_MAX / 2)) { + if (randval > (RAND_MAX / 4)) { + if (randval <= (3 * RAND_MAX / 8)) + randval = (2 * randval) - (RAND_MAX /4); + else + randval = (4 * randval) - RAND_MAX; + } + jitter = 0 - (randval * (avg_pulse - min_pulse)) / RAND_MAX; + } else { + randval -= RAND_MAX / 2; + if (randval > (RAND_MAX / 4)) { + if (randval <= (3 * RAND_MAX / 8)) + randval = (2 * randval) - (RAND_MAX /4); + else + randval = (4 * randval) - RAND_MAX; + } + jitter = (randval * (max_pulse - avg_pulse)) / RAND_MAX; + } + avg_pulse += jitter; + if ((avg_pulse < min_pulse) || (avg_pulse > max_pulse)) { + outlog ("FDI: avg_pulse outside bounds! avg=%u min=%u max=%u\n", avg_pulse, min_pulse, max_pulse); + outlog ("FDI: avgp=%u (%u) minp=%u (%u) maxp=%u (%u) jitter=%d i=%d ni=%d\n", + avgp[i], avgp[nexti], minp[i], minp[nexti], maxp[i], maxp[nexti], jitter, i, nexti); + } + if (avg_pulse < ref_pulse) + outlog ("FDI: avg_pulse < ref_pulse! (%u < %u)\n", avg_pulse, ref_pulse); + pulse += avg_pulse - ref_pulse; + ref_pulse = 0; + if (i == eodat) + outstep++; + } else if (rand() <= ((idx[i] * RAND_MAX) / maxidx)) { + avg_pulse = avgp[i]; + min_pulse = minp[i]; + max_pulse = maxp[i]; + randval = rand(); + if (randval < (RAND_MAX / 2)) { + if (randval > (RAND_MAX / 4)) { + if (randval <= (3 * RAND_MAX / 8)) + randval = (2 * randval) - (RAND_MAX /4); + else + randval = (4 * randval) - RAND_MAX; + } + avg_pulse -= (randval * (avg_pulse - min_pulse)) / RAND_MAX; + } else { + randval -= RAND_MAX / 2; + if (randval > (RAND_MAX / 4)) { + if (randval <= (3 * RAND_MAX / 8)) + randval = (2 * randval) - (RAND_MAX /4); + else + randval = (4 * randval) - RAND_MAX; + } + avg_pulse += (randval * (max_pulse - avg_pulse)) / RAND_MAX; + } + if ((avg_pulse > ref_pulse) && (avg_pulse < (avgp[nexti] - jitter))) { + pulse += avg_pulse - ref_pulse; + ref_pulse = avg_pulse; + } + } + if (outstep == 1 && indexoffset == i) + *indexoffsetp = bitoffset; + } + + /* gets the size in bits from the pulse width, considering the current average bitrate */ + adjusted_pulse = pulse; + real_size = 0; + if (mfm) { + while (adjusted_pulse >= avg_size) { + real_size += 4; + adjusted_pulse -= avg_size / 2; + } + adjusted_pulse <<= 3; + while (adjusted_pulse >= ((avg_size * 4) + (avg_size / 4))) { + real_size += 2; + adjusted_pulse -= avg_size * 2; + } + if (adjusted_pulse >= ((avg_size * 3) + (avg_size / 4))) { + if (adjusted_pulse <= ((avg_size * 4) - (avg_size / 4))) { + if ((2 * ((adjusted_pulse >> 2) - adjust)) <= ((2 * avg_size) - (avg_size / 4))) + real_size += 3; + else + real_size += 4; + } else + real_size += 4; + } else { + if (adjusted_pulse > ((avg_size * 3) - (avg_size / 4))) { + real_size += 3; + } else { + if (adjusted_pulse >= ((avg_size * 2) + (avg_size / 4))) { + if ((2 * ((adjusted_pulse >> 2) - adjust)) < (avg_size + (avg_size / 4))) + real_size += 2; + else + real_size += 3; + } else + real_size += 2; + } + } + } else { + while (adjusted_pulse >= (2*avg_size)) + { + real_size+=4; + adjusted_pulse-=avg_size; + } + adjusted_pulse<<=2; + while (adjusted_pulse >= ((avg_size*3)+(avg_size/4))) + { + real_size+=2; + adjusted_pulse-=avg_size*2; + } + if (adjusted_pulse >= ((avg_size*2)+(avg_size/4))) + { + if (adjusted_pulse <= ((avg_size*3)-(avg_size/4))) + { + if (((adjusted_pulse>>1)-adjust) < (avg_size+(avg_size/4))) + real_size+=2; + else + real_size+=3; + } + else + real_size+=3; + } + else + { + if (adjusted_pulse > ((avg_size*2)-(avg_size/4))) + real_size+=2; + else + { + if (adjusted_pulse >= (avg_size+(avg_size/4))) + { + if (((adjusted_pulse>>1)-adjust) <= (avg_size-(avg_size/4))) + real_size++; + else + real_size+=2; + } + else + real_size++; + } + } + } + + /* after one pass to correctly initialize the average bitrate, outputs the bits */ + if (outstep == 1) { + for (j = real_size; j > 1; j--) + addbit (d, 0); + addbit (d, 1); + for (j = 0; j < real_size; j++) + *pt++ = (uae_u16)(pulse / real_size); + } + + /* prepares for the next pulse */ + adjust = ((real_size * avg_size) / (4 << mfm)) - pulse; + total -= psarray[array_index].size; + totaldiv -= psarray[array_index].number_of_bits; + psarray[array_index].size = pulse; + psarray[array_index].number_of_bits = real_size; + total += pulse; + totaldiv += real_size; + array_index++; + if (array_index >= FDI_MAX_ARRAY) + array_index = 0; + } + + fdi->out = bitoffset; +} + +#endif + +static void fdi2_celltiming (FDI *fdi, uint32_t totalavg, int bitoffset, uae_u16 *out) +{ + uae_u16 *pt2, *pt; + double avg_bit_len; + int i; + + avg_bit_len = (double)totalavg / (double)bitoffset; + pt2 = fdi->track_dst_buffer_timing; + pt = out; + for (i = 0; i < bitoffset / 8; i++) { + double v = (pt2[0] + pt2[1] + pt2[2] + pt2[3] + pt2[4] + pt2[5] + pt2[6] + pt2[7]) / 8.0; + v = 1000.0 * v / avg_bit_len; + *pt++ = (uae_u16)v; + pt2 += 8; + } + *pt++ = out[0]; + *pt = out[0]; +} + +static int decode_lowlevel_track (FDI *fdi, int track, struct fdi_cache *cache) +{ + uae_u8 *p1, *d; + uae_u32 *p2; + uae_u32 *avgp, *minp = 0, *maxp = 0; + uae_u8 *idxp = 0; + uae_u32 maxidx, totalavg, weakbits; + int i, j, len, pulses, indexoffset; + int avg_free, min_free = 0, max_free = 0, idx_free; + int idx_off1, idx_off2, idx_off3; + + d = fdi->track_dst; + p1 = fdi->track_src; + pulses = get_u32 (p1); + if (!pulses) + return -1; + p1 += 4; + len = 12; + avgp = (uae_u32*)fdi_decompress (pulses, p1 + 0, p1 + len, &avg_free); + dumpstream(track, (uae_u8*)avgp, pulses); + len += get_u24 (p1 + 0) & 0x3fffff; + if (!avgp) + return -1; + if (get_u24 (p1 + 3) && get_u24 (p1 + 6)) { + minp = (uae_u32*)fdi_decompress (pulses, p1 + 3, p1 + len, &min_free); + len += get_u24 (p1 + 3) & 0x3fffff; + maxp = (uae_u32*)fdi_decompress (pulses, p1 + 6, p1 + len, &max_free); + len += get_u24 (p1 + 6) & 0x3fffff; + /* Computes the real min and max values */ + for (i = 0; i < pulses; i++) { + maxp[i] = avgp[i] + minp[i] - maxp[i]; + minp[i] = avgp[i] - minp[i]; + } + } else { + minp = avgp; + maxp = avgp; + } + if (get_u24 (p1 + 9)) { + idx_off1 = 0; + idx_off2 = 1; + idx_off3 = 2; + idxp = fdi_decompress (pulses, p1 + 9, p1 + len, &idx_free); + if (idx_free) { + if (idxp[0] == 0 && idxp[1] == 0) { + idx_off1 = 2; + idx_off2 = 3; + } else { + idx_off1 = 1; + idx_off2 = 0; + } + idx_off3 = 4; + } + } else { + idxp = fdi_malloc (pulses * 2); + idx_free = 1; + for (i = 0; i < pulses; i++) { + idxp[i * 2 + 0] = 2; + idxp[i * 2 + 1] = 0; + } + idxp[0] = 1; + idxp[1] = 1; + } + + maxidx = 0; + indexoffset = 0; + p1 = idxp; + for (i = 0; i < pulses; i++) { + if (p1[idx_off1] + p1[idx_off2] > maxidx) + maxidx = p1[idx_off1] + p1[idx_off2]; + p1 += idx_off3; + } + p1 = idxp; + for (i = 0; (i < pulses) && (p1[idx_off2] != 0); i++) /* falling edge, replace with idx_off1 for rising edge */ + p1 += idx_off3; + if (i < pulses) { + j = i; + do { + i++; + p1 += idx_off3; + if (i >= pulses) { + i = 0; + p1 = idxp; + } + } while ((i != j) && (p1[idx_off2] == 0)); /* falling edge, replace with idx_off1 for rising edge */ + if (i != j) /* index pulse detected */ + { + while ((i != j) && (p1[idx_off1] > p1[idx_off2])) { /* falling edge, replace with "<" for rising edge */ + i++; + p1 += idx_off3; + if (i >= pulses) { + i = 0; + p1 = idxp; + } + } + if (i != j) + indexoffset = i; /* index position detected */ + } + } + p1 = idxp; + p2 = avgp; + totalavg = 0; + weakbits = 0; + for (i = 0; i < pulses; i++) { + int sum = p1[idx_off1] + p1[idx_off2]; + if (sum >= maxidx) { + totalavg += *p2; + } else { + weakbits++; + } + p2++; + p1 += idx_off3; + idxp[i] = sum; + } + len = totalavg / 100000; + outlog("totalavg=%u index=%d (%d) maxidx=%d weakbits=%d len=%d\n", + totalavg, indexoffset, maxidx, weakbits, len); + cache->avgp = avgp; + cache->idxp = idxp; + cache->minp = minp; + cache->maxp = maxp; + cache->avg_free = avg_free; + cache->idx_free = idx_free; + cache->min_free = min_free; + cache->max_free = max_free; + cache->totalavg = totalavg; + cache->pulses = pulses; + cache->maxidx = maxidx; + cache->indexoffset = indexoffset; + cache->weakbits = weakbits; + cache->lowlevel = 1; + + return 1; +} + +static unsigned char fdiid[]={"Formatted Disk Image file"}; +static int bit_rate_table[16] = { 125,150,250,300,500,1000 }; + +void fdi2raw_header_free (FDI *fdi) +{ + int i; + + fdi_free (fdi->mfmsync_buffer); + fdi_free (fdi->track_src_buffer); + fdi_free (fdi->track_dst_buffer); + fdi_free (fdi->track_dst_buffer_timing); + for (i = 0; i < MAX_TRACKS; i++) { + struct fdi_cache *c = &fdi->cache[i]; + if (c->idx_free) + fdi_free (c->idxp); + if (c->avg_free) + fdi_free (c->avgp); + if (c->min_free) + fdi_free (c->minp); + if (c->max_free) + fdi_free (c->maxp); + } + fdi_free (fdi); + debuglog ("FREE: memory allocated %d\n", fdi_allocated); +} + +int fdi2raw_get_last_track (FDI *fdi) +{ + return fdi->last_track; +} + +int fdi2raw_get_num_sector (FDI *fdi) +{ + if (fdi->header[152] == 0x02) + return 22; + return 11; +} + +int fdi2raw_get_last_head (FDI *fdi) +{ + return fdi->last_head; +} + +int fdi2raw_get_rotation (FDI *fdi) +{ + return fdi->rotation_speed; +} + +int fdi2raw_get_bit_rate (FDI *fdi) +{ + return fdi->bit_rate; +} + +int fdi2raw_get_type (FDI *fdi) +{ + return fdi->disk_type; +} + +int fdi2raw_get_write_protect (FDI *fdi) +{ + return fdi->write_protect; +} + +FDI *fdi2raw_header(FILE *f) +{ + int i, offset, oldseek; + uae_u8 type, size; + FDI *fdi; + + debuglog ("ALLOC: memory allocated %d\n", fdi_allocated); + fdi = fdi_malloc(sizeof(FDI)); + memset (fdi, 0, sizeof (FDI)); + fdi->file = f; + oldseek = ftell (fdi->file); + fseek (fdi->file, 0, SEEK_SET); + fread (fdi->header, 2048, 1, fdi->file); + fseek (fdi->file, oldseek, SEEK_SET); + if (memcmp (fdiid, fdi->header, strlen ((char *)fdiid)) ) { + fdi_free(fdi); + return NULL; + } + if ((fdi->header[140] != 1 && fdi->header[140] != 2) || (fdi->header[141] != 0 && !(fdi->header[140]==2 && fdi->header[141]==1))) { + fdi_free(fdi); + return NULL; + } + + fdi->mfmsync_buffer = fdi_malloc (MAX_MFM_SYNC_BUFFER * sizeof(int)); + fdi->track_src_buffer = fdi_malloc (MAX_SRC_BUFFER); + fdi->track_dst_buffer = fdi_malloc (MAX_DST_BUFFER); + fdi->track_dst_buffer_timing = fdi_malloc (MAX_TIMING_BUFFER); + + fdi->last_track = ((fdi->header[142] << 8) + fdi->header[143]) + 1; + fdi->last_track *= fdi->header[144] + 1; + if (fdi->last_track > MAX_TRACKS) + fdi->last_track = MAX_TRACKS; + fdi->last_head = fdi->header[144]; + fdi->disk_type = fdi->header[145]; + fdi->rotation_speed = fdi->header[146] + 128; + fdi->write_protect = fdi->header[147] & 1; + outlog ("FDI version %d.%d\n", fdi->header[140], fdi->header[141]); + outlog ("last_track=%d rotation_speed=%d\n",fdi->last_track,fdi->rotation_speed); + + offset = 512; + i = fdi->last_track; + if (i > 180) { + offset += 512; + i -= 180; + while (i > 256) { + offset += 512; + i -= 256; + } + } + for (i = 0; i < fdi->last_track; i++) { + fdi->track_offsets[i] = offset; + type = fdi->header[152 + i * 2]; + size = fdi->header[152 + i * 2 + 1]; + if (type == 1) + offset += (size & 15) * 512; + else if ((type & 0xc0) == 0x80) + offset += (((type & 0x3f) << 8) | size) * 256; + else + offset += size * 256; + } + fdi->track_offsets[i] = offset; + + return fdi; +} + + +int fdi2raw_loadrevolution_2 (FDI *fdi, uae_u16 *mfmbuf, uae_u16 *tracktiming, int track, int *tracklength, int *indexoffsetp, int *multirev, int mfm) +{ + struct fdi_cache *cache = &fdi->cache[track]; + int len, i, idx; + + memset (fdi->track_dst_buffer, 0, MAX_DST_BUFFER); + idx = cache->indexoffset; + fdi2_decode (fdi, cache->totalavg, + cache->avgp, cache->minp, cache->maxp, cache->idxp, + cache->maxidx, &idx, cache->pulses, mfm); + //fdi2_gcr_decode (fdi, totalavg, avgp, minp, maxp, idxp, idx_off1, idx_off2, idx_off3, maxidx, pulses); + outlog("track %d: nbits=%d avg len=%.2f weakbits=%d idx=%d\n", + track, bitoffset, (double)cache->totalavg / bitoffset, cache->weakbits, cache->indexoffset); + len = fdi->out; + if (cache->weakbits >= 10 && multirev) + *multirev = 1; + *tracklength = len; + + for (i = 0; i < (len + 15) / (2 * 8); i++) { + uae_u8 *data = fdi->track_dst_buffer + i * 2; + *mfmbuf++ = 256 * *data + *(data + 1); + } + fdi2_celltiming (fdi, cache->totalavg, len, tracktiming); + if (indexoffsetp) + *indexoffsetp = idx; + return 1; +} + +int fdi2raw_loadrevolution (FDI *fdi, uae_u16 *mfmbuf, uae_u16 *tracktiming, int track, int *tracklength, int mfm) +{ + return fdi2raw_loadrevolution_2 (fdi, mfmbuf, tracktiming, track, tracklength, 0, 0, mfm); +} + +int fdi2raw_loadtrack (FDI *fdi, uae_u16 *mfmbuf, uae_u16 *tracktiming, int track, int *tracklength, int *indexoffsetp, int *multirev, int mfm) +{ + uae_u8 *p; + int outlen, i; + struct fdi_cache *cache = &fdi->cache[track]; + + if (cache->lowlevel) + return fdi2raw_loadrevolution_2 (fdi, mfmbuf, tracktiming, track, tracklength, indexoffsetp, multirev, mfm); + + fdi->err = 0; + fdi->track_src_len = fdi->track_offsets[track + 1] - fdi->track_offsets[track]; + fseek (fdi->file, fdi->track_offsets[track], SEEK_SET); + fread (fdi->track_src_buffer, fdi->track_src_len, 1, fdi->file); + memset (fdi->track_dst_buffer, 0, MAX_DST_BUFFER); + fdi->track_dst_buffer_timing[0] = 0; + + fdi->current_track = track; + fdi->track_src = fdi->track_src_buffer; + fdi->track_dst = fdi->track_dst_buffer; + p = fdi->header + 152 + fdi->current_track * 2; + fdi->track_type = *p++; + fdi->track_len = *p++; + fdi->bit_rate = 0; + fdi->out = 0; + fdi->mfmsync_offset = 0; + + if ((fdi->track_type & 0xf0) == 0xf0 || (fdi->track_type & 0xf0) == 0xe0) + fdi->bit_rate = bit_rate_table[fdi->track_type & 0x0f]; + else + fdi->bit_rate = 250; + + outlog ("track %d: srclen: %d track_type: %02.2X, bitrate: %d\n", + fdi->current_track, fdi->track_src_len, fdi->track_type, fdi->bit_rate); + + if ((fdi->track_type & 0xc0) == 0x80) { + + outlen = decode_lowlevel_track (fdi, track, cache); + + } else if ((fdi->track_type & 0xf0) == 0xf0) { + + outlen = decode_raw_track (fdi); + + } else if ((fdi->track_type & 0xf0) == 0xe0) { + + outlen = handle_sectors_described_track (fdi); + + } else if ((fdi->track_type & 0xf0)) { + + zxx (fdi); + outlen = -1; + + } else if (fdi->track_type < 0x10) { + + decode_normal_track[fdi->track_type](fdi); + fix_mfm_sync (fdi); + outlen = fdi->out; + + } else { + + zxx (fdi); + outlen = -1; + + } + +// amiga_check_track (fdi); + + if (fdi->err) + return 0; + + if (outlen > 0) { + if (cache->lowlevel) + return fdi2raw_loadrevolution_2 (fdi, mfmbuf, tracktiming, track, tracklength, indexoffsetp, multirev, mfm); + *tracklength = fdi->out; + for (i = 0; i < ((*tracklength) + 15) / (2 * 8); i++) { + uae_u8 *data = fdi->track_dst_buffer + i * 2; + *mfmbuf++ = 256 * *data + *(data + 1); + } + } + return outlen; +} + diff --git a/src/fdi2raw.h b/src/fdi2raw.h new file mode 100644 index 0000000..1ca272d --- /dev/null +++ b/src/fdi2raw.h @@ -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 +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 diff --git a/src/keyboard_pcjr.c b/src/keyboard_pcjr.c index 017a653..dd85d44 100644 --- a/src/keyboard_pcjr.c +++ b/src/keyboard_pcjr.c @@ -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; } diff --git a/src/pc.c b/src/pc.c index 590583e..a172712 100644 --- a/src/pc.c +++ b/src/pc.c @@ -221,13 +221,16 @@ 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(); sound_init(); @@ -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(); diff --git a/src/win.c b/src/win.c index f9b2ae6..4d2dd23 100644 --- a/src/win.c +++ b/src/win.c @@ -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: