mirror of
https://github.com/86Box/86Box.git
synced 2026-02-21 17:15:32 -07:00
86F format handler updated to 86F version 2.0 and bit by bit handling;
FDI stream images are now also handled by the 86F handler; Both floppy drives' motors now spin separately; Added Plantronics ColorPlus emulation per patch from PCem forum; Applied all mainline PCem commits; Fixed several bugs.
This commit is contained in:
@@ -232,7 +232,6 @@ void exec386(int cycs)
|
||||
/* testr[8]=flags;*/
|
||||
// oldcs2=oldcs;
|
||||
// oldpc2=oldpc;
|
||||
opcode_realstart:
|
||||
oldcs=CS;
|
||||
cpu_state.oldpc = cpu_state.pc;
|
||||
oldcpl=CPL;
|
||||
@@ -243,7 +242,6 @@ dontprint=0;
|
||||
cpu_state.ea_seg = &_ds;
|
||||
cpu_state.ssegs = 0;
|
||||
|
||||
opcodestart:
|
||||
fetchdat = fastreadl(cs + cpu_state.pc);
|
||||
|
||||
if (!cpu_state.abrt)
|
||||
|
||||
11
src/808x.c
11
src/808x.c
@@ -505,7 +505,7 @@ int indump = 0;
|
||||
|
||||
void dumpregs()
|
||||
{
|
||||
int c,d=0,e=0,ff;
|
||||
int c,d=0,e=0;
|
||||
#ifndef RELEASE_BUILD
|
||||
FILE *f;
|
||||
if (indump) return;
|
||||
@@ -644,7 +644,14 @@ void resetx86()
|
||||
eflags=0;
|
||||
cgate32=0;
|
||||
loadcs(0xFFFF);
|
||||
rammask = AT ? 0xFFFFFFFF : 0xfffff;
|
||||
if (AT)
|
||||
{
|
||||
rammask = mem_a20_state ? 0xffffffff : 0xffefffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
rammask = 0xfffff;
|
||||
}
|
||||
idt.base = 0;
|
||||
flags=2;
|
||||
makeznptable();
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
VPATH = . dosbox resid-fp slirp
|
||||
VPATH = . crcspeed dosbox lzf resid-fp slirp
|
||||
CPP = g++.exe
|
||||
CC = gcc.exe
|
||||
WINDRES = windres.exe
|
||||
CFLAGS = -O3 -march=native -mtune=native -fbranch-probabilities -fvpt -funroll-loops -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse -mstackrealign
|
||||
CFLAGS = -O3 -march=native -mtune=native -fbranch-probabilities -fvpt -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse -mstackrealign -g
|
||||
DFLAGS = -O3 -march=i686 -fomit-frame-pointer -msse2 -mstackrealign
|
||||
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-iso.o \
|
||||
cdrom-null.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.o compaq.o config.o cpu.o dac.o \
|
||||
device.o disc.o disc_86f.o disc_fdi.o disc_imd.o disc_img_86box.o disc_random.o disc_td0.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \
|
||||
device.o disc.o disc_86f.o disc_fdi.o disc_imd.o disc_img.o disc_random.o disc_td0.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \
|
||||
i430nx.o i430vx.o i440fx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \
|
||||
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o memregs.o model.o mouse.o mouse_amstrad.o mouse_ps2.o \
|
||||
mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o rtc.o \
|
||||
@@ -14,24 +14,25 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429
|
||||
sound_dbopl.o sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_resid.o \
|
||||
sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o sound_ym7128.o \
|
||||
soundopenal.o tandy_eeprom.o tandy_rom.o timer.o um8669f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o \
|
||||
vid_ati28800.o vid_ati68860_ramdac.o vid_bt485_ramdac.o vid_cga.o vid_cl_gd.o vid_cl_gd_blit.o vid_cl_ramdac.o vid_ega.o vid_et4000.o \
|
||||
vid_ati28800.o vid_ati68860_ramdac.o vid_bt485_ramdac.o vid_cga.o vid_cl_gd.o vid_cl_gd_blit.o vid_cl_ramdac.o vid_colorplus.o vid_ega.o vid_et4000.o \
|
||||
vid_et4000w32.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o vid_nv_riva128.o vid_nv_rivatnt.o \
|
||||
vid_olivetti_m24.o vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \
|
||||
vid_pcjr.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o \
|
||||
vid_svga_render.o vid_tandy.o vid_tandysl.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o \
|
||||
vid_vga.o vid_voodoo.o video.o w83877f.o wd76c10.o win.o win-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \
|
||||
vid_vga.o vid_voodoo.o video.o wd76c10.o win.o win-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \
|
||||
win-ddraw-fs.o win-ddraw-screenshot.o win-deviceconfig.o win-hdconf.o win-joystick.o win-joystickconfig.o win-keyboard.o win-midi.o win-mouse.o \
|
||||
win-status.o win-video.o x86seg.o x87.o xtide.o pc.res
|
||||
CRCOBJ = crcspeed.o crc64speed.o
|
||||
DBOBJ = dbopl.o nukedopl.o vid_cga_comp.o
|
||||
LZFOBJ = lzf_c.o lzf_d.o
|
||||
SIDOBJ = convolve.o convolve-sse.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o
|
||||
SLIRPOBJ = bootp.o ip_icmp.o misc.o socket.o tcp_timer.o cksum.o ip_input.o queue.o tcp_input.o tftp.o debug.o ip_output.o sbuf.o tcp_output.o udp.o if.o mbuf.o slirp.o tcp_subr.o
|
||||
|
||||
|
||||
LIBS = -mwindows -lwinmm -lopenal.dll -lopenal -lddraw -ldinput8 -ldxguid -ld3d9 -ld3dx9 -lwsock32 -liphlpapi -lstdc++ -static-libstdc++ -static-libgcc -static
|
||||
|
||||
86Box.exe: $(OBJ) $(DBOBJ) $(SIDOBJ) $(SLIRPOBJ)
|
||||
$(CC) $(OBJ) $(DBOBJ) $(SIDOBJ) $(SLIRPOBJ) -o "86Box.exe" $(LIBS)
|
||||
|
||||
86Box.exe: $(OBJ) $(CRCOBJ) $(DBOBJ) $(LZFOBJ) $(SIDOBJ) $(SLIRPOBJ)
|
||||
$(CC) $(OBJ) $(CRCOBJ) $(DBOBJ) $(LZFOBJ) $(SIDOBJ) $(SLIRPOBJ) -o "86Box.exe" $(LIBS)
|
||||
strip "86Box.exe"
|
||||
|
||||
all : 86Box.exe
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
VPATH = . dosbox resid-fp slirp
|
||||
VPATH = . crcspeed dosbox lzf resid-fp slirp
|
||||
CPP = g++.exe
|
||||
CC = gcc.exe
|
||||
WINDRES = windres.exe
|
||||
CFLAGS = -O3 -march=native -mtune=native -fbranch-probabilities -fvpt -funroll-loops -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse -mstackrealign
|
||||
CFLAGS = -O3 -march=native -mtune=native -fbranch-probabilities -fvpt -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse -mstackrealign
|
||||
DFLAGS = -O3 -fomit-frame-pointer -msse2
|
||||
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-iso.o \
|
||||
cdrom-null.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86-64.o compaq.o config.o cpu.o dac.o \
|
||||
device.o disc.o disc_86f.o disc_fdi.o disc_imd.o disc_img_86box.o disc_random.o disc_td0.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \
|
||||
device.o disc.o disc_86f.o disc_fdi.o disc_imd.o disc_img.o disc_random.o disc_td0.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \
|
||||
i430nx.o i430vx.o i440fx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \
|
||||
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o memregs.o model.o mouse.o mouse_amstrad.o mouse_ps2.o \
|
||||
mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o rtc.o \
|
||||
@@ -14,23 +14,25 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429
|
||||
sound_dbopl.o sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_resid.o \
|
||||
sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o sound_ym7128.o \
|
||||
soundopenal.o tandy_eeprom.o tandy_rom.o timer.o um8669f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o \
|
||||
vid_ati28800.o vid_ati68860_ramdac.o vid_bt485_ramdac.o vid_cga.o vid_cl_gd.o vid_cl_gd_blit.o vid_cl_ramdac.o vid_ega.o vid_et4000.o \
|
||||
vid_ati28800.o vid_ati68860_ramdac.o vid_bt485_ramdac.o vid_cga.o vid_cl_gd.o vid_cl_gd_blit.o vid_cl_ramdac.o vid_colorplus.o vid_ega.o vid_et4000.o \
|
||||
vid_et4000w32.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o vid_nv_riva128.o vid_nv_rivatnt.o \
|
||||
vid_olivetti_m24.o vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \
|
||||
vid_pcjr.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o \
|
||||
vid_svga_render.o vid_tandy.o vid_tandysl.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o \
|
||||
vid_vga.o vid_voodoo.o video.o w83877f.o wd76c10.o win.o win-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \
|
||||
vid_vga.o vid_voodoo.o video.o wd76c10.o win.o win-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \
|
||||
win-ddraw-fs.o win-ddraw-screenshot.o win-deviceconfig.o win-hdconf.o win-joystick.o win-joystickconfig.o win-keyboard.o win-midi.o win-mouse.o \
|
||||
win-status.o win-video.o x86seg.o x87.o xtide.o pc.res
|
||||
CRCOBJ = crcspeed.o crc64speed.o
|
||||
DBOBJ = dbopl.o nukedopl.o vid_cga_comp.o
|
||||
LZFOBJ = lzf_c.o lzf_d.o
|
||||
SIDOBJ = convolve.o convolve-sse.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o
|
||||
SLIRPOBJ = bootp.o ip_icmp.o misc.o socket.o tcp_timer.o cksum.o ip_input.o queue.o tcp_input.o tftp.o debug.o ip_output.o sbuf.o tcp_output.o udp.o if.o mbuf.o slirp.o tcp_subr.o
|
||||
|
||||
|
||||
LIBS = -mwindows -lwinmm -lopenal -lddraw -ldinput8 -ldxguid -ld3d9 -ld3dx9 -lwsock32 -liphlpapi -lstdc++ -static-libstdc++ -static-libgcc -static -lopenal.dll -lgcov -lPacket -lwpcap
|
||||
|
||||
86Box64.exe: $(OBJ) $(DBOBJ) $(SIDOBJ) $(SLIRPOBJ)
|
||||
$(CC) $(OBJ) $(DBOBJ) $(SIDOBJ) $(SLIRPOBJ) -o "86Box64.exe" $(LIBS)
|
||||
86Box64.exe: $(OBJ) $(CRCOBJ) $(DBOBJ) $(LZFOBJ) $(SIDOBJ) $(SLIRPOBJ)
|
||||
$(CC) $(OBJ) $(CRCOBJ) $(DBOBJ) $(LZFOBJ) $(SIDOBJ) $(SLIRPOBJ) -o "86Box64.exe" $(LIBS)
|
||||
strip "86Box64.exe"
|
||||
peflags --bigaddr=false 86Box64.exe
|
||||
|
||||
|
||||
@@ -210,7 +210,7 @@ static int read_toc(int fd, struct cdrom_tocentry *btoc)
|
||||
first_track = toc_hdr.cdth_trk0;
|
||||
last_track = toc_hdr.cdth_trk1;
|
||||
//pclog("read_toc: first_track=%i last_track=%i\n", first_track, last_track);
|
||||
memset(btoc, 0, sizeof(btoc));
|
||||
memset(btoc, 0, sizeof(cdrom_tocentry));
|
||||
|
||||
for (track = toc_hdr.cdth_trk0; track <= toc_hdr.cdth_trk1; track++)
|
||||
{
|
||||
|
||||
@@ -273,6 +273,7 @@ static int ioctl_get_last_block(unsigned char starttrack, int msf, int maxlen, i
|
||||
DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&lbtoc,sizeof(lbtoc),&size,NULL);
|
||||
ioctl_close();
|
||||
tocvalid=1;
|
||||
d=0;
|
||||
for (c=d;c<=lbtoc.LastTrack;c++)
|
||||
{
|
||||
uint32_t address;
|
||||
|
||||
@@ -157,7 +157,6 @@ static void lba_to_msf(uint8_t *buf, int lba)
|
||||
|
||||
static void iso_readsector_raw(uint8_t *b, int sector)
|
||||
{
|
||||
uint32_t temp;
|
||||
if (!cdrom_drive) return;
|
||||
iso_image = fopen(iso_path, "rb");
|
||||
fseek(iso_image, sector*2048, SEEK_SET);
|
||||
|
||||
@@ -3637,7 +3637,6 @@ static void FP_FXCH(int reg)
|
||||
addbyte(0x4c);
|
||||
addbyte(0xdd);
|
||||
addbyte(cpu_state_offset(MM));
|
||||
reg = reg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1802,7 +1802,6 @@ static void FP_LOAD_S()
|
||||
addbyte(0xdd); /*FSTP ST[reg][EBP]*/
|
||||
addbyte(0x5d);
|
||||
addbyte(cpu_state_offset(ST[(cpu_state.TOP - 1) & 7]));
|
||||
block_current = block_current;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -18,7 +18,7 @@ enum
|
||||
OP_RET = 0xc3
|
||||
};
|
||||
|
||||
#define NR_HOST_REGS 3
|
||||
#define NR_HOST_REGS 4
|
||||
extern int host_reg_mapping[NR_HOST_REGS];
|
||||
#define NR_HOST_XMM_REGS 7
|
||||
extern int host_reg_xmm_mapping[NR_HOST_XMM_REGS];
|
||||
|
||||
@@ -15,7 +15,7 @@ enum
|
||||
OP_RET = 0xc3
|
||||
};
|
||||
|
||||
#define NR_HOST_REGS 3
|
||||
#define NR_HOST_REGS 4
|
||||
extern int host_reg_mapping[NR_HOST_REGS];
|
||||
#define NR_HOST_XMM_REGS 7
|
||||
extern int host_reg_xmm_mapping[NR_HOST_XMM_REGS];
|
||||
|
||||
@@ -121,7 +121,7 @@ void config_load(char *fn)
|
||||
|
||||
c = 0;
|
||||
|
||||
while (buffer[c] == ' ' && buffer[c])
|
||||
while (buffer[c] == ' ')
|
||||
c++;
|
||||
|
||||
if (!buffer[c]) continue;
|
||||
@@ -281,7 +281,6 @@ char *config_get_string(char *head, char *name, char *def)
|
||||
{
|
||||
section_t *section;
|
||||
entry_t *entry;
|
||||
int value;
|
||||
|
||||
section = find_section(head);
|
||||
|
||||
|
||||
@@ -604,12 +604,12 @@ void cpu_set()
|
||||
|
||||
if (cpu_s->pci_speed)
|
||||
{
|
||||
pci_nonburst_time = 3*cpu_s->rspeed / cpu_s->pci_speed;
|
||||
pci_nonburst_time = 4*cpu_s->rspeed / cpu_s->pci_speed;
|
||||
pci_burst_time = cpu_s->rspeed / cpu_s->pci_speed;
|
||||
}
|
||||
else
|
||||
{
|
||||
pci_nonburst_time = 3;
|
||||
pci_nonburst_time = 4;
|
||||
pci_burst_time = 1;
|
||||
}
|
||||
pclog("PCI burst=%i nonburst=%i\n", pci_burst_time, pci_nonburst_time);
|
||||
|
||||
275
src/crcspeed/crc64speed.c
Normal file
275
src/crcspeed/crc64speed.c
Normal file
@@ -0,0 +1,275 @@
|
||||
/* Copyright (c) 2014, Matt Stancliff <matt@genges.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Redis nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE. */
|
||||
|
||||
#include "crc64speed.h"
|
||||
|
||||
/* If CRC64SPEED_DUAL is defined, we allow calls to
|
||||
* both _little and _big CRC.
|
||||
* By default, we only allow one endianness to be used
|
||||
* and the first call to either _init function will set the
|
||||
* lookup table endianness for the life of this module.
|
||||
* We don't enable dual lookups by default because
|
||||
* each 8x256 lookup table is 16k. */
|
||||
#ifndef CRC64SPEED_DUAL
|
||||
static uint64_t crc64_table[8][256] = {{0}};
|
||||
static void *crc64_table_little = NULL, *crc64_table_big = NULL;
|
||||
static const bool dual = false;
|
||||
#else
|
||||
static uint64_t crc64_table_little[8][256] = {{0}};
|
||||
static uint64_t crc64_table_big[8][256] = {{0}};
|
||||
static void *crc64_table = NULL;
|
||||
static const bool dual = true;
|
||||
#endif
|
||||
|
||||
/* value of crc64_table[0][1], architecture dependent. */
|
||||
#define LITTLE1 UINT64_C(0x7ad870c830358979)
|
||||
#define BIG1 UINT64_C(0x79893530c870d87a)
|
||||
|
||||
/* Define CRC64SPEED_SAFE if you want runtime checks to stop
|
||||
* CRCs from being calculated by uninitialized tables (and also stop tables
|
||||
* from being initialized more than once). */
|
||||
#ifdef CRC64SPEED_SAFE
|
||||
#define should_init(table, val) \
|
||||
do { \
|
||||
if ((table)[0][1] == (val)) \
|
||||
return false; \
|
||||
} while (0)
|
||||
#define check_init(table, val) \
|
||||
do { \
|
||||
if ((table)[0][1] != (val)) \
|
||||
return false; \
|
||||
} while (0)
|
||||
#else
|
||||
#define should_init(a, b)
|
||||
#define check_init(a, b)
|
||||
#endif
|
||||
|
||||
#define POLY UINT64_C(0xad93d23594c935a9)
|
||||
/******************** BEGIN GENERATED PYCRC FUNCTIONS ********************/
|
||||
/**
|
||||
* Generated on Sun Dec 21 14:14:07 2014,
|
||||
* by pycrc v0.8.2, https://www.tty1.net/pycrc/
|
||||
*
|
||||
* LICENSE ON GENERATED CODE:
|
||||
* ==========================
|
||||
* As of version 0.6, pycrc is released under the terms of the MIT licence.
|
||||
* The code generated by pycrc is not considered a substantial portion of the
|
||||
* software, therefore the author of pycrc will not claim any copyright on
|
||||
* the generated code.
|
||||
* ==========================
|
||||
*
|
||||
* CRC configuration:
|
||||
* Width = 64
|
||||
* Poly = 0xad93d23594c935a9
|
||||
* XorIn = 0xffffffffffffffff
|
||||
* ReflectIn = True
|
||||
* XorOut = 0x0000000000000000
|
||||
* ReflectOut = True
|
||||
* Algorithm = bit-by-bit-fast
|
||||
*
|
||||
* Modifications after generation (by matt):
|
||||
* - included finalize step in-line with update for single-call generation
|
||||
* - re-worked some inner variable architectures
|
||||
* - adjusted function parameters to match expected prototypes.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Reflect all bits of a \a data word of \a data_len bytes.
|
||||
*
|
||||
* \param data The data word to be reflected.
|
||||
* \param data_len The width of \a data expressed in number of bits.
|
||||
* \return The reflected data.
|
||||
*****************************************************************************/
|
||||
static inline uint_fast64_t crc_reflect(uint_fast64_t data, size_t data_len) {
|
||||
uint_fast64_t ret = data & 0x01;
|
||||
|
||||
for (size_t i = 1; i < data_len; i++) {
|
||||
data >>= 1;
|
||||
ret = (ret << 1) | (data & 0x01);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the crc value with new data.
|
||||
*
|
||||
* \param crc The current crc value.
|
||||
* \param data Pointer to a buffer of \a data_len bytes.
|
||||
* \param data_len Number of bytes in the \a data buffer.
|
||||
* \return The updated crc value.
|
||||
******************************************************************************/
|
||||
uint64_t crc64(uint_fast64_t crc, const void *in_data, const uint64_t len) {
|
||||
const uint8_t *data = in_data;
|
||||
bool bit;
|
||||
|
||||
for (uint64_t offset = 0; offset < len; offset++) {
|
||||
uint8_t c = data[offset];
|
||||
for (uint_fast8_t i = 0x01; i & 0xff; i <<= 1) {
|
||||
bit = crc & 0x8000000000000000;
|
||||
if (c & i) {
|
||||
bit = !bit;
|
||||
}
|
||||
|
||||
crc <<= 1;
|
||||
if (bit) {
|
||||
crc ^= POLY;
|
||||
}
|
||||
}
|
||||
|
||||
crc &= 0xffffffffffffffff;
|
||||
}
|
||||
|
||||
crc = crc & 0xffffffffffffffff;
|
||||
return crc_reflect(crc, 64) ^ 0x0000000000000000;
|
||||
}
|
||||
|
||||
/******************** END GENERATED PYCRC FUNCTIONS ********************/
|
||||
|
||||
/* Only for testing; doesn't support DUAL */
|
||||
uint64_t crc64_lookup(uint64_t crc, const void *in_data, const uint64_t len) {
|
||||
const uint8_t *data = in_data;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
crc = crc64_table[0][(uint8_t)crc ^ data[i]] ^ (crc >> 8);
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
/* Returns false if CRC64SPEED_SAFE and table already initialized. */
|
||||
bool crc64speed_init(void) {
|
||||
#ifndef CRC64SPEED_DUAL
|
||||
should_init(crc64_table, LITTLE1);
|
||||
#else
|
||||
should_init(crc64_table_little, LITTLE1);
|
||||
#endif
|
||||
crcspeed64little_init(crc64, dual ? crc64_table_little : crc64_table);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Returns false if CRC64SPEED_SAFE and table already initialized. */
|
||||
bool crc64speed_init_big(void) {
|
||||
#ifndef CRC64SPEED_DUAL
|
||||
should_init(crc64_table, BIG1);
|
||||
#else
|
||||
should_init(crc64_table_big, BIG1);
|
||||
#endif
|
||||
crcspeed64big_init(crc64, dual ? crc64_table_big : crc64_table);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t crc64speed(uint64_t crc, const void *s, const uint64_t l) {
|
||||
/* Quickly check if CRC table is initialized to little endian correctly. */
|
||||
#ifndef CRC64SPEED_DUAL
|
||||
check_init(crc64_table, LITTLE1);
|
||||
#else
|
||||
check_init(crc64_table_little, LITTLE1);
|
||||
#endif
|
||||
return crcspeed64little(dual ? crc64_table_little : crc64_table, crc,
|
||||
(void *)s, l);
|
||||
}
|
||||
|
||||
uint64_t crc64speed_big(uint64_t crc, const void *s, const uint64_t l) {
|
||||
/* Quickly check if CRC table is initialized to big endian correctly. */
|
||||
#ifndef CRC64SPEED_DUAL
|
||||
check_init(crc64_table, BIG1);
|
||||
#else
|
||||
check_init(crc64_table_big, BIG1);
|
||||
#endif
|
||||
return crcspeed64big(dual ? crc64_table_big : crc64_table, crc, (void *)s,
|
||||
l);
|
||||
}
|
||||
|
||||
bool crc64speed_init_native(void) {
|
||||
const uint64_t n = 1;
|
||||
return *(char *)&n ? crc64speed_init() : crc64speed_init_big();
|
||||
}
|
||||
|
||||
/* Iterate over table to fully load it into a cache near the CPU. */
|
||||
void crc64speed_cache_table(void) {
|
||||
uint64_t m;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
for (int j = 0; j < 256; ++j) {
|
||||
#ifndef CRC64SPEED_DUAL
|
||||
m = crc64_table[i][j];
|
||||
#else
|
||||
m = crc64_table_little[i][j];
|
||||
m += crc64_table_big[i][j];
|
||||
#endif
|
||||
++m;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If you are on a platform where endianness can change at runtime, this
|
||||
* will break unless you compile with CRC64SPEED_DUAL and manually run
|
||||
* _init() and _init_big() instead of using _init_native() */
|
||||
uint64_t crc64speed_native(uint64_t crc, const void *s, const uint64_t l) {
|
||||
const uint64_t n = 1;
|
||||
return *(char *)&n ? crc64speed(crc, s, l) : crc64speed_big(crc, s, l);
|
||||
}
|
||||
|
||||
/* Test main */
|
||||
#if defined(REDIS_TEST) || defined(REDIS_TEST_MAIN)
|
||||
#include <stdio.h>
|
||||
|
||||
#define UNUSED(x) (void)(x)
|
||||
int crc64Test(int argc, char *argv[]) {
|
||||
UNUSED(argc);
|
||||
UNUSED(argv);
|
||||
crc64speed_init();
|
||||
printf("[calcula]: e9c6d914c4b8d9ca == %016" PRIx64 "\n",
|
||||
(uint64_t)crc64(0, "123456789", 9));
|
||||
printf("[lookupt]: e9c6d914c4b8d9ca == %016" PRIx64 "\n",
|
||||
(uint64_t)crc64_lookup(0, "123456789", 9));
|
||||
printf("[64speed]: e9c6d914c4b8d9ca == %016" PRIx64 "\n",
|
||||
(uint64_t)crc64speed(0, "123456789", 9));
|
||||
char li[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed "
|
||||
"do eiusmod tempor incididunt ut labore et dolore magna "
|
||||
"aliqua. Ut enim ad minim veniam, quis nostrud exercitation "
|
||||
"ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis "
|
||||
"aute irure dolor in reprehenderit in voluptate velit esse "
|
||||
"cillum dolore eu fugiat nulla pariatur. Excepteur sint "
|
||||
"occaecat cupidatat non proident, sunt in culpa qui officia "
|
||||
"deserunt mollit anim id est laborum.";
|
||||
printf("[calcula]: c7794709e69683b3 == %016" PRIx64 "\n",
|
||||
(uint64_t)crc64(0, li, sizeof(li)));
|
||||
printf("[lookupt]: c7794709e69683b3 == %016" PRIx64 "\n",
|
||||
(uint64_t)crc64_lookup(0, li, sizeof(li)));
|
||||
printf("[64speed]: c7794709e69683b3 == %016" PRIx64 "\n",
|
||||
(uint64_t)crc64speed(0, li, sizeof(li)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef REDIS_TEST_MAIN
|
||||
int main(int argc, char *argv[]) {
|
||||
return crc64Test(argc, argv);
|
||||
}
|
||||
|
||||
#endif
|
||||
20
src/crcspeed/crc64speed.h
Normal file
20
src/crcspeed/crc64speed.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef CRC64SPEED_H
|
||||
#define CRC64SPEED_H
|
||||
#include "crcspeed.h"
|
||||
#include "stdbool.h"
|
||||
|
||||
/* Does not require init */
|
||||
uint64_t crc64(uint64_t crc, const void *data, const uint64_t len);
|
||||
void crc64speed_cache_table(void);
|
||||
|
||||
/* All other crc functions here require _init() before usage. */
|
||||
bool crc64speed_init(void);
|
||||
uint64_t crc64_lookup(uint64_t crc, const void *in_data, const uint64_t len);
|
||||
uint64_t crc64speed(uint64_t crc, const void *s, const uint64_t l);
|
||||
|
||||
bool crc64speed_init_big(void);
|
||||
uint64_t crc64speed_big(uint64_t crc, const void *s, const uint64_t l);
|
||||
|
||||
bool crc64speed_init_native(void);
|
||||
uint64_t crc64speed_native(uint64_t crc, const void *s, const uint64_t l);
|
||||
#endif
|
||||
281
src/crcspeed/crcspeed.c
Normal file
281
src/crcspeed/crcspeed.c
Normal file
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Mark Adler
|
||||
* Originally by: crc64.c Version 1.4 16 Dec 2013 Mark Adler
|
||||
* Modifications by Matt Stancliff <matt@genges.com>:
|
||||
* - removed CRC64-specific behavior
|
||||
* - added generation of lookup tables by parameters
|
||||
* - removed inversion of CRC input/result
|
||||
* - removed automatic initialization in favor of explicit initialization
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the author be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Mark Adler
|
||||
madler@alumni.caltech.edu
|
||||
*/
|
||||
|
||||
#include "crcspeed.h"
|
||||
|
||||
/* Fill in a CRC constants table. */
|
||||
void crcspeed64little_init(crcfn64 crcfn, uint64_t table[8][256]) {
|
||||
uint64_t crc;
|
||||
|
||||
/* generate CRCs for all single byte sequences */
|
||||
for (int n = 0; n < 256; n++) {
|
||||
table[0][n] = crcfn(0, &n, 1);
|
||||
}
|
||||
|
||||
/* generate nested CRC table for future slice-by-8 lookup */
|
||||
for (int n = 0; n < 256; n++) {
|
||||
crc = table[0][n];
|
||||
for (int k = 1; k < 8; k++) {
|
||||
crc = table[0][crc & 0xff] ^ (crc >> 8);
|
||||
table[k][n] = crc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void crcspeed16little_init(crcfn16 crcfn, uint16_t table[8][256]) {
|
||||
uint16_t crc;
|
||||
|
||||
/* generate CRCs for all single byte sequences */
|
||||
for (int n = 0; n < 256; n++) {
|
||||
table[0][n] = crcfn(0, &n, 1);
|
||||
}
|
||||
|
||||
/* generate nested CRC table for future slice-by-8 lookup */
|
||||
for (int n = 0; n < 256; n++) {
|
||||
crc = table[0][n];
|
||||
for (int k = 1; k < 8; k++) {
|
||||
crc = table[0][(crc >> 8) & 0xff] ^ (crc << 8);
|
||||
table[k][n] = crc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reverse the bytes in a 64-bit word. */
|
||||
static inline uint64_t rev8(uint64_t a) {
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
return __builtin_bswap64(a);
|
||||
#else
|
||||
uint64_t m;
|
||||
|
||||
m = UINT64_C(0xff00ff00ff00ff);
|
||||
a = ((a >> 8) & m) | (a & m) << 8;
|
||||
m = UINT64_C(0xffff0000ffff);
|
||||
a = ((a >> 16) & m) | (a & m) << 16;
|
||||
return a >> 32 | a << 32;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This function is called once to initialize the CRC table for use on a
|
||||
big-endian architecture. */
|
||||
void crcspeed64big_init(crcfn64 fn, uint64_t big_table[8][256]) {
|
||||
/* Create the little endian table then reverse all the entires. */
|
||||
crcspeed64little_init(fn, big_table);
|
||||
for (int k = 0; k < 8; k++) {
|
||||
for (int n = 0; n < 256; n++) {
|
||||
big_table[k][n] = rev8(big_table[k][n]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void crcspeed16big_init(crcfn16 fn, uint16_t big_table[8][256]) {
|
||||
/* Create the little endian table then reverse all the entires. */
|
||||
crcspeed16little_init(fn, big_table);
|
||||
for (int k = 0; k < 8; k++) {
|
||||
for (int n = 0; n < 256; n++) {
|
||||
big_table[k][n] = rev8(big_table[k][n]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate a non-inverted CRC multiple bytes at a time on a little-endian
|
||||
* architecture. If you need inverted CRC, invert *before* calling and invert
|
||||
* *after* calling.
|
||||
* 64 bit crc = process 8 bytes at once;
|
||||
*/
|
||||
uint64_t crcspeed64little(uint64_t little_table[8][256], uint64_t crc,
|
||||
void *buf, size_t len) {
|
||||
unsigned char *next = buf;
|
||||
|
||||
/* process individual bytes until we reach an 8-byte aligned pointer */
|
||||
while (len && ((uintptr_t)next & 7) != 0) {
|
||||
crc = little_table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
/* fast middle processing, 8 bytes (aligned!) per loop */
|
||||
while (len >= 8) {
|
||||
crc ^= *(uint64_t *)next;
|
||||
crc = little_table[7][crc & 0xff] ^
|
||||
little_table[6][(crc >> 8) & 0xff] ^
|
||||
little_table[5][(crc >> 16) & 0xff] ^
|
||||
little_table[4][(crc >> 24) & 0xff] ^
|
||||
little_table[3][(crc >> 32) & 0xff] ^
|
||||
little_table[2][(crc >> 40) & 0xff] ^
|
||||
little_table[1][(crc >> 48) & 0xff] ^
|
||||
little_table[0][crc >> 56];
|
||||
next += 8;
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
/* process remaining bytes (can't be larger than 8) */
|
||||
while (len) {
|
||||
crc = little_table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
uint16_t crcspeed16little(uint16_t little_table[8][256], uint16_t crc,
|
||||
void *buf, size_t len) {
|
||||
unsigned char *next = buf;
|
||||
|
||||
/* process individual bytes until we reach an 8-byte aligned pointer */
|
||||
while (len && ((uintptr_t)next & 7) != 0) {
|
||||
crc = little_table[0][((crc >> 8) ^ *next++) & 0xff] ^ (crc << 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
/* fast middle processing, 8 bytes (aligned!) per loop */
|
||||
while (len >= 8) {
|
||||
uint64_t n = *(uint64_t *)next;
|
||||
crc = little_table[7][(n & 0xff) ^ ((crc >> 8) & 0xff)] ^
|
||||
little_table[6][((n >> 8) & 0xff) ^ (crc & 0xff)] ^
|
||||
little_table[5][(n >> 16) & 0xff] ^
|
||||
little_table[4][(n >> 24) & 0xff] ^
|
||||
little_table[3][(n >> 32) & 0xff] ^
|
||||
little_table[2][(n >> 40) & 0xff] ^
|
||||
little_table[1][(n >> 48) & 0xff] ^
|
||||
little_table[0][n >> 56];
|
||||
next += 8;
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
/* process remaining bytes (can't be larger than 8) */
|
||||
while (len) {
|
||||
crc = little_table[0][((crc >> 8) ^ *next++) & 0xff] ^ (crc << 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
/* Calculate a non-inverted CRC eight bytes at a time on a big-endian
|
||||
* architecture.
|
||||
*/
|
||||
uint64_t crcspeed64big(uint64_t big_table[8][256], uint64_t crc, void *buf,
|
||||
size_t len) {
|
||||
unsigned char *next = buf;
|
||||
|
||||
crc = rev8(crc);
|
||||
while (len && ((uintptr_t)next & 7) != 0) {
|
||||
crc = big_table[0][(crc >> 56) ^ *next++] ^ (crc << 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
while (len >= 8) {
|
||||
crc ^= *(uint64_t *)next;
|
||||
crc = big_table[0][crc & 0xff] ^
|
||||
big_table[1][(crc >> 8) & 0xff] ^
|
||||
big_table[2][(crc >> 16) & 0xff] ^
|
||||
big_table[3][(crc >> 24) & 0xff] ^
|
||||
big_table[4][(crc >> 32) & 0xff] ^
|
||||
big_table[5][(crc >> 40) & 0xff] ^
|
||||
big_table[6][(crc >> 48) & 0xff] ^
|
||||
big_table[7][crc >> 56];
|
||||
next += 8;
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
while (len) {
|
||||
crc = big_table[0][(crc >> 56) ^ *next++] ^ (crc << 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
return rev8(crc);
|
||||
}
|
||||
|
||||
/* WARNING: Completely untested on big endian architecture. Possibly broken. */
|
||||
uint16_t crcspeed16big(uint16_t big_table[8][256], uint16_t crc_in, void *buf,
|
||||
size_t len) {
|
||||
unsigned char *next = buf;
|
||||
uint64_t crc = crc_in;
|
||||
|
||||
crc = rev8(crc);
|
||||
while (len && ((uintptr_t)next & 7) != 0) {
|
||||
crc = big_table[0][((crc >> (56 - 8)) ^ *next++) & 0xff] ^ (crc >> 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
while (len >= 8) {
|
||||
uint64_t n = *(uint64_t *)next;
|
||||
crc = big_table[0][(n & 0xff) ^ ((crc >> (56 - 8)) & 0xff)] ^
|
||||
big_table[1][((n >> 8) & 0xff) ^ (crc & 0xff)] ^
|
||||
big_table[2][(n >> 16) & 0xff] ^
|
||||
big_table[3][(n >> 24) & 0xff] ^
|
||||
big_table[4][(n >> 32) & 0xff] ^
|
||||
big_table[5][(n >> 40) & 0xff] ^
|
||||
big_table[6][(n >> 48) & 0xff] ^
|
||||
big_table[7][n >> 56];
|
||||
next += 8;
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
while (len) {
|
||||
crc = big_table[0][((crc >> (56 - 8)) ^ *next++) & 0xff] ^ (crc >> 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
return rev8(crc);
|
||||
}
|
||||
|
||||
/* Return the CRC of buf[0..len-1] with initial crc, processing eight bytes
|
||||
at a time using passed-in lookup table.
|
||||
This selects one of two routines depending on the endianess of
|
||||
the architecture. */
|
||||
uint64_t crcspeed64native(uint64_t table[8][256], uint64_t crc, void *buf,
|
||||
size_t len) {
|
||||
uint64_t n = 1;
|
||||
|
||||
return *(char *)&n ? crcspeed64little(table, crc, buf, len)
|
||||
: crcspeed64big(table, crc, buf, len);
|
||||
}
|
||||
|
||||
uint16_t crcspeed16native(uint16_t table[8][256], uint16_t crc, void *buf,
|
||||
size_t len) {
|
||||
uint64_t n = 1;
|
||||
|
||||
return *(char *)&n ? crcspeed16little(table, crc, buf, len)
|
||||
: crcspeed16big(table, crc, buf, len);
|
||||
}
|
||||
|
||||
/* Initialize CRC lookup table in architecture-dependent manner. */
|
||||
void crcspeed64native_init(crcfn64 fn, uint64_t table[8][256]) {
|
||||
uint64_t n = 1;
|
||||
|
||||
*(char *)&n ? crcspeed64little_init(fn, table)
|
||||
: crcspeed64big_init(fn, table);
|
||||
}
|
||||
|
||||
void crcspeed16native_init(crcfn16 fn, uint16_t table[8][256]) {
|
||||
uint64_t n = 1;
|
||||
|
||||
*(char *)&n ? crcspeed16little_init(fn, table)
|
||||
: crcspeed16big_init(fn, table);
|
||||
}
|
||||
60
src/crcspeed/crcspeed.h
Normal file
60
src/crcspeed/crcspeed.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* Copyright (c) 2014, Matt Stancliff <matt@genges.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Redis nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE. */
|
||||
|
||||
#ifndef CRCSPEED_H
|
||||
#define CRCSPEED_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef uint64_t (*crcfn64)(uint64_t, const void *, const uint64_t);
|
||||
typedef uint16_t (*crcfn16)(uint16_t, const void *, const uint64_t);
|
||||
|
||||
/* CRC-64 */
|
||||
void crcspeed64little_init(crcfn64 fn, uint64_t table[8][256]);
|
||||
void crcspeed64big_init(crcfn64 fn, uint64_t table[8][256]);
|
||||
void crcspeed64native_init(crcfn64 fn, uint64_t table[8][256]);
|
||||
|
||||
uint64_t crcspeed64little(uint64_t table[8][256], uint64_t crc, void *buf,
|
||||
size_t len);
|
||||
uint64_t crcspeed64big(uint64_t table[8][256], uint64_t crc, void *buf,
|
||||
size_t len);
|
||||
uint64_t crcspeed64native(uint64_t table[8][256], uint64_t crc, void *buf,
|
||||
size_t len);
|
||||
|
||||
/* CRC-16 */
|
||||
void crcspeed16little_init(crcfn16 fn, uint16_t table[8][256]);
|
||||
void crcspeed16big_init(crcfn16 fn, uint16_t table[8][256]);
|
||||
void crcspeed16native_init(crcfn16 fn, uint16_t table[8][256]);
|
||||
|
||||
uint16_t crcspeed16little(uint16_t table[8][256], uint16_t crc, void *buf,
|
||||
size_t len);
|
||||
uint16_t crcspeed16big(uint16_t table[8][256], uint16_t crc, void *buf,
|
||||
size_t len);
|
||||
uint16_t crcspeed16native(uint16_t table[8][256], uint16_t crc, void *buf,
|
||||
size_t len);
|
||||
#endif
|
||||
@@ -21,7 +21,7 @@ void device_add(device_t *d)
|
||||
int c = 0;
|
||||
void *priv;
|
||||
|
||||
while (devices[c] != NULL && c < 256)
|
||||
while ((c < 256) && (devices[c] != NULL))
|
||||
c++;
|
||||
|
||||
if (c >= 256)
|
||||
|
||||
52
src/disc.c
52
src/disc.c
@@ -14,8 +14,7 @@
|
||||
#include "fdd.h"
|
||||
#include "timer.h"
|
||||
|
||||
int disc_drivesel = 0;
|
||||
int64_t disc_poll_time = 16;
|
||||
int64_t disc_poll_time[2] = { 16, 16 };
|
||||
|
||||
int disc_track[2];
|
||||
int writeprot[2], fwriteprot[2];
|
||||
@@ -40,7 +39,7 @@ int drive_empty[2] = {1, 1};
|
||||
int disc_changed[2];
|
||||
|
||||
int motorspin;
|
||||
int64_t motoron;
|
||||
int64_t motoron[2];
|
||||
|
||||
int fdc_indexcount = 52;
|
||||
|
||||
@@ -140,7 +139,6 @@ void disc_close(int drive)
|
||||
drives[drive].comparesector = NULL;
|
||||
drives[drive].readaddress = NULL;
|
||||
drives[drive].format = NULL;
|
||||
drives[drive].realtrack = NULL;
|
||||
drives[drive].byteperiod = NULL;
|
||||
drives[drive].stop = NULL;
|
||||
}
|
||||
@@ -176,30 +174,30 @@ double disc_byteperiod(int drive)
|
||||
}
|
||||
}
|
||||
|
||||
double disc_real_period()
|
||||
double disc_real_period(int drive)
|
||||
{
|
||||
double ddbp;
|
||||
double dusec;
|
||||
|
||||
ddbp = disc_byteperiod(disc_drivesel ^ fdd_swap);
|
||||
ddbp = disc_byteperiod(drive ^ fdd_swap);
|
||||
|
||||
dusec = (double) TIMER_USEC;
|
||||
|
||||
return (ddbp * dusec);
|
||||
}
|
||||
|
||||
void disc_poll()
|
||||
void disc_poll(int drive)
|
||||
{
|
||||
if (disc_drivesel > 1)
|
||||
if (drive > 1)
|
||||
{
|
||||
disc_poll_time += (int64_t) (32.0 * TIMER_USEC);
|
||||
disc_poll_time[drive] += (int64_t) (32.0 * TIMER_USEC);
|
||||
return;
|
||||
}
|
||||
|
||||
disc_poll_time += (int64_t) disc_real_period();
|
||||
disc_poll_time[drive] += (int64_t) disc_real_period(drive);
|
||||
|
||||
if (drives[disc_drivesel].poll)
|
||||
drives[disc_drivesel].poll();
|
||||
if (drives[drive].poll)
|
||||
drives[drive].poll(drive);
|
||||
|
||||
if (disc_notfound)
|
||||
{
|
||||
@@ -209,6 +207,16 @@ void disc_poll()
|
||||
}
|
||||
}
|
||||
|
||||
void disc_poll_0()
|
||||
{
|
||||
disc_poll(0);
|
||||
}
|
||||
|
||||
void disc_poll_1()
|
||||
{
|
||||
disc_poll(1);
|
||||
}
|
||||
|
||||
int disc_get_bitcell_period(int rate)
|
||||
{
|
||||
int bit_rate;
|
||||
@@ -266,7 +274,8 @@ void disc_reset()
|
||||
{
|
||||
curdrive = 0;
|
||||
disc_period = 32;
|
||||
timer_add(disc_poll, &disc_poll_time, &motoron, NULL);
|
||||
timer_add(disc_poll_0, &(disc_poll_time[0]), &(motoron[0]), NULL);
|
||||
timer_add(disc_poll_1, &(disc_poll_time[1]), &(motoron[1]), NULL);
|
||||
}
|
||||
|
||||
void disc_init()
|
||||
@@ -338,16 +347,6 @@ void disc_format(int drive, int track, int side, int density, uint8_t fill)
|
||||
disc_notfound = 1000;
|
||||
}
|
||||
|
||||
int disc_realtrack(int drive, int track)
|
||||
{
|
||||
drive ^= fdd_swap;
|
||||
|
||||
if (drives[drive].realtrack)
|
||||
return drives[drive].realtrack(drive, track);
|
||||
else
|
||||
return track;
|
||||
}
|
||||
|
||||
void disc_stop(int drive)
|
||||
{
|
||||
drive ^= fdd_swap;
|
||||
@@ -355,10 +354,3 @@ void disc_stop(int drive)
|
||||
if (drives[drive].stop)
|
||||
drives[drive].stop(drive);
|
||||
}
|
||||
|
||||
void disc_set_drivesel(int drive)
|
||||
{
|
||||
drive ^= fdd_swap;
|
||||
|
||||
disc_drivesel = drive;
|
||||
}
|
||||
|
||||
41
src/disc.h
41
src/disc.h
@@ -12,8 +12,7 @@ typedef struct
|
||||
int (*hole)(int drive);
|
||||
double (*byteperiod)(int drive);
|
||||
void (*stop)(int drive);
|
||||
void (*poll)();
|
||||
int (*realtrack)(int drive, int track);
|
||||
void (*poll)(int drive);
|
||||
} DRIVE;
|
||||
|
||||
extern DRIVE drives[2];
|
||||
@@ -25,23 +24,22 @@ void disc_new(int drive, char *fn);
|
||||
void disc_close(int drive);
|
||||
void disc_init();
|
||||
void disc_reset();
|
||||
void disc_poll();
|
||||
void disc_poll(int drive);
|
||||
void disc_poll_0();
|
||||
void disc_poll_1();
|
||||
void disc_seek(int drive, int track);
|
||||
void disc_readsector(int drive, int sector, int track, int side, int density, int sector_size);
|
||||
void disc_writesector(int drive, int sector, int track, int side, int density, int sector_size);
|
||||
void disc_comparesector(int drive, int sector, int track, int side, int density, int sector_size);
|
||||
void disc_readaddress(int drive, int track, int side, int density);
|
||||
void disc_format(int drive, int track, int side, int density, uint8_t fill);
|
||||
int disc_realtrack(int drive, int track);
|
||||
int disc_hole(int drive);
|
||||
double disc_byteperiod(int drive);
|
||||
void disc_stop(int drive);
|
||||
int disc_empty(int drive);
|
||||
void disc_set_rate(int drive, int drvden, int rate);
|
||||
void disc_set_drivesel(int drive);
|
||||
extern int disc_time;
|
||||
extern int64_t disc_poll_time;
|
||||
extern int disc_drivesel;
|
||||
extern int64_t disc_poll_time[2];
|
||||
|
||||
void fdc_callback();
|
||||
int fdc_data(uint8_t dat);
|
||||
@@ -59,7 +57,7 @@ extern int fdc_ready;
|
||||
extern int fdc_indexcount;*/
|
||||
|
||||
extern int motorspin;
|
||||
extern int64_t motoron;
|
||||
extern int64_t motoron[2];
|
||||
|
||||
extern int swwp;
|
||||
extern int disable_write;
|
||||
@@ -116,7 +114,7 @@ typedef union {
|
||||
uint8_t bytes[2];
|
||||
} crc_t;
|
||||
|
||||
void disc_calccrc(int drive, uint8_t byte, crc_t *crc_var);
|
||||
void disc_calccrc(uint8_t byte, crc_t *crc_var);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -127,6 +125,11 @@ typedef struct
|
||||
uint8_t (*read_data)(int drive, int side, uint16_t pos);
|
||||
void (*write_data)(int drive, int side, uint16_t pos, uint8_t data);
|
||||
int (*format_conditions)(int drive);
|
||||
int32_t (*extra_bit_cells)(int drive);
|
||||
uint16_t* (*encoded_data)(int drive, int side);
|
||||
void (*read_revolution)(int drive);
|
||||
uint32_t (*index_hole_pos)(int drive, int side);
|
||||
uint32_t (*get_raw_size)(int drive);
|
||||
uint8_t check_crc;
|
||||
} d86f_handler_t;
|
||||
|
||||
@@ -136,19 +139,17 @@ void d86f_common_handlers(int drive);
|
||||
|
||||
int d86f_is_40_track(int drive);
|
||||
|
||||
uint8_t* d86f_track_data(int drive, int side);
|
||||
uint8_t* d86f_track_layout(int drive, int side);
|
||||
void d86f_reset_index_hole_pos(int drive, int side);
|
||||
|
||||
uint16_t d86f_prepare_pretrack(int drive, int side, int iso, int write_data);
|
||||
uint16_t d86f_prepare_sector(int drive, int side, int pos, uint8_t *id_buf, uint8_t *data_buf, int data_len, int write_data, int gap2, int gap3, int limit, int deleted, int bad_crc);
|
||||
uint16_t d86f_prepare_pretrack(int drive, int side, int iso);
|
||||
uint16_t d86f_prepare_sector(int drive, int side, int prev_pos, uint8_t *id_buf, uint8_t *data_buf, int data_len, int gap2, int gap3, int deleted, int bad_crc);
|
||||
|
||||
int gap3_sizes[5][8][256];
|
||||
|
||||
void null_writeback(int drive);
|
||||
void null_poll_write_data(int drive, int side, uint16_t pos, uint8_t data);
|
||||
void null_write_data(int drive, int side, uint16_t pos, uint8_t data);
|
||||
int null_format_conditions(int drive);
|
||||
void d86f_unregister(int drive);
|
||||
void d86f_reset_index_hole_pos(int drive, int side);
|
||||
|
||||
uint8_t dmf_r[21];
|
||||
uint8_t xdf_physical_sectors[2][2];
|
||||
@@ -173,3 +174,13 @@ xdf_sector_t xdf_disk_layout[2][2][38];
|
||||
uint32_t td0_get_raw_tsize(int side_flags, int slower_rpm);
|
||||
|
||||
void d86f_set_track_pos(int drive, uint32_t track_pos);
|
||||
|
||||
int32_t null_extra_bit_cells(int drive);
|
||||
uint16_t* common_encoded_data(int drive, int side);
|
||||
|
||||
void common_read_revolution(int drive);
|
||||
void null_set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n);
|
||||
|
||||
uint32_t null_index_hole_pos(int drive, int side);
|
||||
|
||||
uint32_t common_get_raw_size(int drive);
|
||||
|
||||
5126
src/disc_86f.c
5126
src/disc_86f.c
File diff suppressed because it is too large
Load Diff
793
src/disc_fdi.c
793
src/disc_fdi.c
@@ -8,6 +8,7 @@
|
||||
#include "disc_img.h"
|
||||
#include "disc_fdi.h"
|
||||
#include "fdc.h"
|
||||
#include "fdd.h"
|
||||
#include "fdi2raw.h"
|
||||
|
||||
static struct
|
||||
@@ -15,79 +16,101 @@ static struct
|
||||
FILE *f;
|
||||
FDI *h;
|
||||
uint8_t track_data[2][4][256*1024];
|
||||
uint8_t track_timing[2][4][256*1024];
|
||||
|
||||
int sides;
|
||||
int track;
|
||||
int tracklen[2][4];
|
||||
int trackindex[2][4];
|
||||
|
||||
int lasttrack;
|
||||
} fdi[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, fdi_n;
|
||||
static int fdi_inread, fdi_inwrite, fdi_incompare,fdi_readpos, fdi_inreadaddr;
|
||||
static int fdi_satisfying_bytes;
|
||||
|
||||
static uint16_t CRCTable[256];
|
||||
|
||||
static int pollbytesleft=0,pollbitsleft=0,polltotalbytes=0;
|
||||
|
||||
int fdi_realtrack(int drive, int track)
|
||||
uint16_t fdi_disk_flags(int drive)
|
||||
{
|
||||
return track;
|
||||
}
|
||||
uint16_t temp_disk_flags = 0x80; /* We ALWAYS claim to have extra bit cells, even if the actual amount is 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);
|
||||
}
|
||||
|
||||
double fdi_byteperiod(int drive)
|
||||
{
|
||||
switch (fdi2raw_get_bit_rate(fdi[drive].h))
|
||||
{
|
||||
case 1000:
|
||||
return 8.0;
|
||||
case 500:
|
||||
return 16.0;
|
||||
temp_disk_flags |= 2;
|
||||
case 300:
|
||||
return 160.0 / 6.0;
|
||||
case 250:
|
||||
return 32.0;
|
||||
temp_disk_flags |= 0;
|
||||
case 1000:
|
||||
temp_disk_flags |= 4;
|
||||
default:
|
||||
return 32.0;
|
||||
temp_disk_flags |= 0;
|
||||
}
|
||||
|
||||
if (fdi[drive].sides == 2)
|
||||
{
|
||||
temp_disk_flags |= 8;
|
||||
}
|
||||
|
||||
/* Tell the 86F handler that will handle our data to handle it in reverse byte endianness. */
|
||||
temp_disk_flags |= 0x800;
|
||||
|
||||
return temp_disk_flags;
|
||||
}
|
||||
|
||||
uint16_t fdi_side_flags(int drive)
|
||||
{
|
||||
uint16_t temp_side_flags = 0;
|
||||
switch (fdi2raw_get_bit_rate(fdi[drive].h))
|
||||
{
|
||||
case 500:
|
||||
temp_side_flags = 0;
|
||||
case 300:
|
||||
temp_side_flags = 1;
|
||||
case 250:
|
||||
temp_side_flags = 2;
|
||||
case 1000:
|
||||
temp_side_flags = 3;
|
||||
default:
|
||||
temp_side_flags = 2;
|
||||
}
|
||||
if (fdi2raw_get_rotation(fdi[drive].h) == 360)
|
||||
{
|
||||
temp_side_flags |= 0x20;
|
||||
}
|
||||
|
||||
/* Set the encoding value to match that provided by the FDC. Then if it's wrong, it will sector not found anyway. */
|
||||
temp_side_flags |= 0x08;
|
||||
|
||||
return temp_side_flags;
|
||||
}
|
||||
|
||||
int32_t fdi_extra_bit_cells(int drive)
|
||||
{
|
||||
int side = 0;
|
||||
int density = 0;
|
||||
|
||||
int raw_size = 0;
|
||||
|
||||
side = fdd_get_head(drive);
|
||||
|
||||
switch (fdc_get_bit_rate())
|
||||
{
|
||||
case 0:
|
||||
raw_size = (fdd_getrpm(drive ^ fdd_swap) == 300) ? 200000 : 166666;
|
||||
density = 2;
|
||||
case 1:
|
||||
raw_size = (fdd_getrpm(drive ^ fdd_swap) == 300) ? 120000 : 100000;
|
||||
density = 1;
|
||||
case 2:
|
||||
raw_size = (fdd_getrpm(drive ^ fdd_swap) == 300) ? 100000 : 83333;
|
||||
density = 1;
|
||||
case 3:
|
||||
case 5:
|
||||
raw_size = (fdd_getrpm(drive ^ fdd_swap) == 300) ? 400000 : 333333;
|
||||
density = 3;
|
||||
default:
|
||||
raw_size = (fdd_getrpm(drive ^ fdd_swap) == 300) ? 100000 : 83333;
|
||||
density = 1;
|
||||
}
|
||||
|
||||
return (fdi[drive].tracklen[side][density] - raw_size);
|
||||
}
|
||||
|
||||
int fdi_hole(int drive)
|
||||
@@ -103,6 +126,129 @@ int fdi_hole(int drive)
|
||||
}
|
||||
}
|
||||
|
||||
void fdi_read_revolution(int drive)
|
||||
{
|
||||
int density;
|
||||
int track = fdi[drive].track;
|
||||
|
||||
int side = 0;
|
||||
|
||||
if (track > fdi[drive].lasttrack)
|
||||
{
|
||||
for (density = 0; density < 4; density++)
|
||||
{
|
||||
memset(fdi[drive].track_data[0][density], 0, 106096);
|
||||
memset(fdi[drive].track_data[1][density], 0, 106096);
|
||||
fdi[drive].tracklen[0][density] = fdi[drive].tracklen[1][density] = 100000;
|
||||
}
|
||||
// pclog("Track is bigger than last track\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (density = 0; density < 4; density++)
|
||||
{
|
||||
for (side = 0; side < fdi[drive].sides; side++)
|
||||
{
|
||||
int c = fdi2raw_loadtrack(fdi[drive].h, (uint16_t *)fdi[drive].track_data[side][density],
|
||||
(uint16_t *)fdi[drive].track_timing[side][density],
|
||||
track * fdi[drive].sides,
|
||||
&fdi[drive].tracklen[side][density],
|
||||
&fdi[drive].trackindex[side][density], NULL, density);
|
||||
// pclog("Side 0 [%i]: len %i, index %i\n", density, fdi[drive].tracklen[side][density], fdi[drive].trackindex[side][density]);
|
||||
if (!c)
|
||||
memset(fdi[drive].track_data[side][density], 0, fdi[drive].tracklen[side][density]);
|
||||
}
|
||||
}
|
||||
|
||||
if (fdi[drive].sides == 1)
|
||||
{
|
||||
memset(fdi[drive].track_data[1][density], 0, 106096);
|
||||
fdi[drive].tracklen[1][density] = 100000;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t fdi_index_hole_pos(int drive, int side)
|
||||
{
|
||||
int density;
|
||||
|
||||
switch (fdc_get_bit_rate())
|
||||
{
|
||||
case 0:
|
||||
density = 2;
|
||||
case 1:
|
||||
density = 1;
|
||||
case 2:
|
||||
density = 1;
|
||||
case 3:
|
||||
case 5:
|
||||
density = 3;
|
||||
default:
|
||||
density = 1;
|
||||
}
|
||||
|
||||
return fdi[drive].trackindex[side][density];
|
||||
}
|
||||
|
||||
uint32_t fdi_get_raw_size(int drive)
|
||||
{
|
||||
int side = 0;
|
||||
int density;
|
||||
|
||||
side = fdd_get_head(drive);
|
||||
|
||||
switch (fdc_get_bit_rate())
|
||||
{
|
||||
case 0:
|
||||
density = 2;
|
||||
case 1:
|
||||
density = 1;
|
||||
case 2:
|
||||
density = 1;
|
||||
case 3:
|
||||
case 5:
|
||||
density = 3;
|
||||
default:
|
||||
density = 1;
|
||||
}
|
||||
|
||||
return fdi[drive].tracklen[side][density];
|
||||
}
|
||||
|
||||
uint16_t* fdi_encoded_data(int drive, int side)
|
||||
{
|
||||
int density = 0;
|
||||
|
||||
if (fdc_get_bit_rate() == 2)
|
||||
density = 1;
|
||||
if (fdc_get_bit_rate() == 0)
|
||||
density = 2;
|
||||
if (fdc_get_bit_rate() == 3)
|
||||
density = 3;
|
||||
|
||||
if (!fdc_is_mfm())
|
||||
{
|
||||
density = 0;
|
||||
}
|
||||
|
||||
return (uint16_t *)fdi[drive].track_data[side][density];
|
||||
}
|
||||
|
||||
void d86f_register_fdi(int drive)
|
||||
{
|
||||
d86f_handler[drive].disk_flags = fdi_disk_flags;
|
||||
d86f_handler[drive].side_flags = fdi_side_flags;
|
||||
d86f_handler[drive].writeback = null_writeback;
|
||||
d86f_handler[drive].set_sector = null_set_sector;
|
||||
d86f_handler[drive].write_data = null_write_data;
|
||||
d86f_handler[drive].format_conditions = null_format_conditions;
|
||||
d86f_handler[drive].extra_bit_cells = fdi_extra_bit_cells;
|
||||
d86f_handler[drive].encoded_data = fdi_encoded_data;
|
||||
d86f_handler[drive].read_revolution = fdi_read_revolution;
|
||||
d86f_handler[drive].index_hole_pos = fdi_index_hole_pos;
|
||||
d86f_handler[drive].get_raw_size = fdi_get_raw_size;
|
||||
d86f_handler[drive].check_crc = 1;
|
||||
}
|
||||
|
||||
void fdi_load(int drive, char *fn)
|
||||
{
|
||||
char header[26];
|
||||
@@ -111,6 +257,8 @@ void fdi_load(int drive, char *fn)
|
||||
fdi[drive].f = fopen(fn, "rb");
|
||||
if (!fdi[drive].f) return;
|
||||
|
||||
d86f_unregister(drive);
|
||||
|
||||
fread(header, 1, 25, fdi[drive].f);
|
||||
fseek(fdi[drive].f, 0, SEEK_SET);
|
||||
header[25] = 0;
|
||||
@@ -128,22 +276,19 @@ void fdi_load(int drive, char *fn)
|
||||
fdi[drive].lasttrack = fdi2raw_get_last_track(fdi[drive].h);
|
||||
fdi[drive].sides = fdi2raw_get_last_head(fdi[drive].h) + 1;
|
||||
// printf("Last track %i\n",fdilasttrack[drive]);
|
||||
|
||||
d86f_register_fdi(drive);
|
||||
|
||||
drives[drive].seek = fdi_seek;
|
||||
drives[drive].readsector = fdi_readsector;
|
||||
drives[drive].writesector = fdi_writesector;
|
||||
drives[drive].comparesector=fdi_comparesector;
|
||||
drives[drive].readaddress = fdi_readaddress;
|
||||
drives[drive].hole = fdi_hole;
|
||||
drives[drive].byteperiod = fdi_byteperiod;
|
||||
drives[drive].poll = fdi_poll;
|
||||
drives[drive].format = fdi_format;
|
||||
drives[drive].stop = fdi_stop;
|
||||
drives[drive].realtrack = fdi_realtrack;
|
||||
// pclog("Loaded as FDI\n");
|
||||
d86f_common_handlers(drive);
|
||||
|
||||
pclog("Loaded as FDI\n");
|
||||
}
|
||||
|
||||
void fdi_close(int drive)
|
||||
{
|
||||
d86f_unregister(drive);
|
||||
drives[drive].seek = NULL;
|
||||
if (fdi[drive].h)
|
||||
fdi2raw_header_free(fdi[drive].h);
|
||||
if (fdi[drive].f)
|
||||
@@ -153,8 +298,14 @@ void fdi_close(int drive)
|
||||
|
||||
void fdi_seek(int drive, int track)
|
||||
{
|
||||
int c;
|
||||
int density;
|
||||
if (fdd_doublestep_40(drive))
|
||||
{
|
||||
if (fdi[drive].lasttrack < 43)
|
||||
{
|
||||
track /= 2;
|
||||
}
|
||||
// pclog("fdi_seek(): %i %i\n", fdi[drive].lasttrack, track);
|
||||
}
|
||||
|
||||
if (!fdi[drive].f)
|
||||
return;
|
||||
@@ -163,507 +314,13 @@ void fdi_seek(int drive, int track)
|
||||
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;
|
||||
}
|
||||
}
|
||||
fdi[drive].track = track;
|
||||
|
||||
fdi_read_revolution(drive);
|
||||
}
|
||||
|
||||
void fdi_writeback(int drive, int track)
|
||||
void fdi_init()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void fdi_readsector(int drive, int sector, int track, int side, int rate, int sector_size)
|
||||
{
|
||||
fdi_revs = 0;
|
||||
fdi_sector = sector;
|
||||
fdi_track = track;
|
||||
fdi_side = side;
|
||||
fdi_n = sector_size;
|
||||
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_incompare = 0;
|
||||
fdi_inreadaddr = 0;
|
||||
fdi_readpos = 0;
|
||||
fdi_satisfying_bytes = 0;
|
||||
}
|
||||
|
||||
void fdi_writesector(int drive, int sector, int track, int side, int rate, int sector_size)
|
||||
{
|
||||
fdi_revs = 0;
|
||||
fdi_sector = sector;
|
||||
fdi_track = track;
|
||||
fdi_side = side;
|
||||
fdi_n = sector_size;
|
||||
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_incompare = 0;
|
||||
fdi_inreadaddr = 0;
|
||||
fdi_readpos = 0;
|
||||
fdi_satisfying_bytes = 0;
|
||||
}
|
||||
|
||||
void fdi_comparesector(int drive, int sector, int track, int side, int rate, int sector_size)
|
||||
{
|
||||
fdi_revs = 0;
|
||||
fdi_sector = sector;
|
||||
fdi_track = track;
|
||||
fdi_side = side;
|
||||
fdi_n = sector_size;
|
||||
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 = 0;
|
||||
fdi_inwrite = 0;
|
||||
fdi_incompare = 1;
|
||||
fdi_inreadaddr = 0;
|
||||
fdi_readpos = 0;
|
||||
fdi_satisfying_bytes = 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_incompare = 0;
|
||||
fdi_inreadaddr = 1;
|
||||
fdi_readpos = 0;
|
||||
fdi_satisfying_bytes = 0;
|
||||
}
|
||||
|
||||
void fdi_format(int drive, int track, int side, int rate, uint8_t fill)
|
||||
{
|
||||
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_incompare = 0;
|
||||
fdi_inreadaddr = 0;
|
||||
fdi_readpos = 0;
|
||||
fdi_satisfying_bytes = 0;
|
||||
}
|
||||
|
||||
static uint16_t fdi_buffer;
|
||||
static int readidpoll=0,readdatapoll=0,comparedatapoll=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(int drive)
|
||||
{
|
||||
// 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;
|
||||
int indata, readdata;
|
||||
int side = fdd_get_head(fdi_drive);
|
||||
|
||||
for (bitcount = 0; bitcount < 16; bitcount++)
|
||||
{
|
||||
if (fdi_pos >= fdi[fdi_drive].tracklen[side][fdi_density])
|
||||
{
|
||||
fdi_pos = 0;
|
||||
if (fdi[fdi_drive].tracklen[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[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 && !fdi_incompare)
|
||||
return;
|
||||
if (fdi_pos == fdi[fdi_drive].trackindex[side][fdi_density])
|
||||
{
|
||||
fdi_revs++;
|
||||
if (fdi_revs == 3)
|
||||
{
|
||||
// pclog("Not found!\n");
|
||||
fdc_notfound();
|
||||
fdi_inread = fdi_inreadaddr = 0;
|
||||
return;
|
||||
}
|
||||
if (fdi_sector == SECTOR_FIRST)
|
||||
fdi_sector = SECTOR_NEXT;
|
||||
}
|
||||
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[3] == fdi_n) && (fdi_sectordat[2] == fdi_sector || fdi_sector == SECTOR_NEXT)) || 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_sector == SECTOR_NEXT) && 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 (comparedatapoll)
|
||||
{
|
||||
// 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_finishcompare(fdi_satisfying_bytes == polltotalbytes);
|
||||
fdc_datacrcerror();
|
||||
comparedatapoll = 0;
|
||||
return;
|
||||
}
|
||||
//#endif
|
||||
// pclog("End of FDI read %02X %02X %02X %02X\n",crc>>8,crc&0xFF,sectorcrc[0],sectorcrc[1]);
|
||||
indata = fdc_getdata(!pollbytesleft);
|
||||
readdata = decodefm(lastfdidat[1]);
|
||||
if (indata == -1)
|
||||
{
|
||||
indata = 0;
|
||||
}
|
||||
switch(fdc_get_compare_condition())
|
||||
{
|
||||
case 0: /* SCAN EQUAL */
|
||||
if ((indata == readdata) || (indata == 0xFF))
|
||||
{
|
||||
fdi_satisfying_bytes++;
|
||||
}
|
||||
break;
|
||||
case 1: /* SCAN LOW OR EQUAL */
|
||||
if ((indata <= readdata) || (indata == 0xFF))
|
||||
{
|
||||
fdi_satisfying_bytes++;
|
||||
}
|
||||
break;
|
||||
case 2: /* SCAN HIGH OR EQUAL */
|
||||
if ((indata >= readdata) || (indata == 0xFF))
|
||||
{
|
||||
fdi_satisfying_bytes++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
fdc_finishcompare(fdi_satisfying_bytes == polltotalbytes);
|
||||
}
|
||||
else if (lastfdidat[1] != 0)
|
||||
{
|
||||
indata = fdc_getdata(!pollbytesleft);
|
||||
readdata = decodefm(lastfdidat[1]);
|
||||
if (indata == -1)
|
||||
{
|
||||
indata = 0;
|
||||
}
|
||||
switch(fdc_get_compare_condition())
|
||||
{
|
||||
case 0: /* SCAN EQUAL */
|
||||
if ((indata == readdata) || (indata == 0xFF))
|
||||
{
|
||||
fdi_satisfying_bytes++;
|
||||
}
|
||||
break;
|
||||
case 1: /* SCAN LOW OR EQUAL */
|
||||
if ((indata <= readdata) || (indata == 0xFF))
|
||||
{
|
||||
fdi_satisfying_bytes++;
|
||||
}
|
||||
break;
|
||||
case 2: /* SCAN HIGH OR EQUAL */
|
||||
if ((indata >= readdata) || (indata == 0xFF))
|
||||
{
|
||||
fdi_satisfying_bytes++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
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;
|
||||
if (fdi_inread)
|
||||
{
|
||||
readdatapoll = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
polltotalbytes = sectorsize;
|
||||
comparedatapoll = 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;
|
||||
if (fdi_inread)
|
||||
{
|
||||
readdatapoll = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
polltotalbytes = sectorsize;
|
||||
comparedatapoll = 1;
|
||||
}
|
||||
fdi_nextsector = 0;
|
||||
crc = 0xcdb4;
|
||||
if (fdi_buffer == 0xF56A) calccrc(0xF8);
|
||||
else calccrc(0xFB);
|
||||
lastfdidat[0] = lastfdidat[1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// printf("FDI reset\n");
|
||||
}
|
||||
|
||||
@@ -14,4 +14,3 @@ int fdi_hole(int drive);
|
||||
double fdi_byteperiod(int drive);
|
||||
void fdi_stop();
|
||||
void fdi_poll();
|
||||
int fdi_realtrack(int track, int drive);
|
||||
|
||||
@@ -33,6 +33,7 @@ static struct
|
||||
int track_count, sides;
|
||||
int track;
|
||||
uint16_t disk_flags;
|
||||
int track_width;
|
||||
imd_track_t tracks[256][2];
|
||||
uint16_t current_side_flags[2];
|
||||
uint8_t xdf_ordered_pos[256][2];
|
||||
@@ -261,7 +262,8 @@ void imd_load(int drive, char *fn)
|
||||
}
|
||||
}
|
||||
|
||||
if (imd[drive].track_count > 43) imd[drive].disk_flags |= 1; /* If the image has more than 43 tracks, then the tracks are thin (96 tpi). */
|
||||
imd[drive].track_width = 0;
|
||||
if (imd[drive].track_count > 43) imd[drive].track_width = 1; /* If the image has more than 43 tracks, then the tracks are thin (96 tpi). */
|
||||
if (imd[drive].sides == 2) imd[drive].disk_flags |= 8; /* If the has 2 sides, mark it as such. */
|
||||
|
||||
d86f_register_imd(drive);
|
||||
@@ -274,7 +276,6 @@ void imd_load(int drive, char *fn)
|
||||
void imd_close(int drive)
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
d86f_unregister(drive);
|
||||
if (imd[drive].f)
|
||||
{
|
||||
@@ -441,7 +442,6 @@ int imd_track_is_interleave(int drive, int side, int track)
|
||||
|
||||
void imd_sector_to_buffer(int drive, int track, int side, uint8_t *buffer, int sector, int len)
|
||||
{
|
||||
int i = 0;
|
||||
int type = imd[drive].buffer[imd[drive].tracks[track][side].sector_data_offs[sector]];
|
||||
if (type == 0)
|
||||
{
|
||||
@@ -471,7 +471,6 @@ void imd_seek(int drive, int track)
|
||||
|
||||
int c = 0;
|
||||
int h = 0;
|
||||
int r = 0;
|
||||
int n = 0;
|
||||
int ssize = 512;
|
||||
|
||||
@@ -505,7 +504,7 @@ void imd_seek(int drive, int track)
|
||||
|
||||
// pclog("IMD: Seeking...\n");
|
||||
|
||||
if (d86f_is_40_track(drive) && fdd_doublestep_40(drive))
|
||||
if (!imd[drive].track_width && fdd_doublestep_40(drive))
|
||||
track /= 2;
|
||||
|
||||
is_trackx = (track == 0) ? 0 : 1;
|
||||
@@ -524,7 +523,7 @@ void imd_seek(int drive, int track)
|
||||
{
|
||||
track_rate = imd[drive].current_side_flags[side] & 7;
|
||||
if (!track_rate && (imd[drive].current_side_flags[side] & 0x20)) track_rate = 4;
|
||||
if ((imd[drive].current_side_flags[side] & 27) == 0x21) track_rate = 2;
|
||||
if ((imd[drive].current_side_flags[side] & 0x27) == 0x21) track_rate = 2;
|
||||
|
||||
r_map = imd[drive].buffer + imd[drive].tracks[track][side].r_map_offs;
|
||||
h = imd[drive].tracks[track][side].params[2];
|
||||
@@ -559,7 +558,7 @@ void imd_seek(int drive, int track)
|
||||
|
||||
interleave_type = imd_track_is_interleave(drive, side, track);
|
||||
|
||||
current_pos = d86f_prepare_pretrack(drive, side, 0, 1);
|
||||
current_pos = d86f_prepare_pretrack(drive, side, 0);
|
||||
|
||||
if (!xdf_type)
|
||||
{
|
||||
@@ -589,7 +588,7 @@ void imd_seek(int drive, int track)
|
||||
|
||||
// pclog("IMD: (%i %i) %i %i %i %i (%i %i) (GPL=%i)\n", track, side, id[0], id[1], id[2], id[3], deleted, bad_crc, track_gap3);
|
||||
imd_sector_to_buffer(drive, track, side, data, actual_sector, ssize);
|
||||
current_pos = d86f_prepare_sector(drive, side, current_pos, id, data, ssize, 1, 22, track_gap3, 0, deleted, bad_crc);
|
||||
current_pos = d86f_prepare_sector(drive, side, current_pos, id, data, ssize, 22, track_gap3, deleted, bad_crc);
|
||||
track_buf_pos[side] += ssize;
|
||||
}
|
||||
}
|
||||
@@ -617,11 +616,11 @@ void imd_seek(int drive, int track)
|
||||
|
||||
if (is_trackx)
|
||||
{
|
||||
current_pos = d86f_prepare_sector(drive, side, xdf_trackx_spos[xdf_type][xdf_sector], id, data, ssize, 1, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], 0, deleted, bad_crc);
|
||||
current_pos = d86f_prepare_sector(drive, side, xdf_trackx_spos[xdf_type][xdf_sector], id, data, ssize, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], deleted, bad_crc);
|
||||
}
|
||||
else
|
||||
{
|
||||
current_pos = d86f_prepare_sector(drive, side, current_pos, id, data, ssize, 1, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], 0, deleted, bad_crc);
|
||||
current_pos = d86f_prepare_sector(drive, side, current_pos, id, data, ssize, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], deleted, bad_crc);
|
||||
}
|
||||
|
||||
track_buf_pos[side] += ssize;
|
||||
@@ -701,7 +700,6 @@ void imd_writeback(int drive)
|
||||
|
||||
int i = 0;
|
||||
|
||||
uint8_t *track_buf;
|
||||
uint8_t *n_map;
|
||||
|
||||
uint8_t h, n, spt;
|
||||
@@ -711,7 +709,6 @@ void imd_writeback(int drive)
|
||||
{
|
||||
if (imd[drive].tracks[track][side].is_present)
|
||||
{
|
||||
track_buf = imd[drive].buffer + imd[drive].tracks[track][side].file_offs;
|
||||
fseek(imd[drive].f, imd[drive].tracks[track][side].file_offs, SEEK_SET);
|
||||
h = imd[drive].tracks[track][side].params[2];
|
||||
spt = imd[drive].tracks[track][side].params[3];
|
||||
@@ -740,19 +737,6 @@ void imd_writeback(int drive)
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t imd_poll_read_data(int drive, int side, uint16_t pos)
|
||||
{
|
||||
int type = imd[drive].current_data[side][0];
|
||||
if (!type)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (type & 1) ? imd[drive].current_data[side][pos + 1] : imd[drive].current_data[side][1];
|
||||
}
|
||||
}
|
||||
|
||||
void imd_poll_write_data(int drive, int side, uint16_t pos, uint8_t data)
|
||||
{
|
||||
int type = imd[drive].current_data[side][0];
|
||||
@@ -784,8 +768,12 @@ void d86f_register_imd(int drive)
|
||||
d86f_handler[drive].side_flags = imd_side_flags;
|
||||
d86f_handler[drive].writeback = imd_writeback;
|
||||
d86f_handler[drive].set_sector = imd_set_sector;
|
||||
d86f_handler[drive].read_data = imd_poll_read_data;
|
||||
d86f_handler[drive].write_data = imd_poll_write_data;
|
||||
d86f_handler[drive].format_conditions = imd_format_conditions;
|
||||
d86f_handler[drive].extra_bit_cells = null_extra_bit_cells;
|
||||
d86f_handler[drive].encoded_data = common_encoded_data;
|
||||
d86f_handler[drive].read_revolution = common_read_revolution;
|
||||
d86f_handler[drive].index_hole_pos = null_index_hole_pos;
|
||||
d86f_handler[drive].get_raw_size = common_get_raw_size;
|
||||
d86f_handler[drive].check_crc = 1;
|
||||
}
|
||||
|
||||
713
src/disc_img.c
713
src/disc_img.c
@@ -2,74 +2,125 @@
|
||||
see COPYING for more details
|
||||
*/
|
||||
#include "ibm.h"
|
||||
#include "fdc.h"
|
||||
#include "fdd.h"
|
||||
#include "disc.h"
|
||||
#include "disc_img.h"
|
||||
#include "disc_sector.h"
|
||||
|
||||
static struct
|
||||
{
|
||||
FILE *f;
|
||||
// uint8_t track_data[2][20*1024];
|
||||
uint8_t track_data[2][50000];
|
||||
int sectors, tracks, sides;
|
||||
int sector_size;
|
||||
int rate;
|
||||
uint8_t sector_size;
|
||||
int xdf_type; /* 0 = not XDF, 1-5 = one of the five XDF types */
|
||||
int dmf;
|
||||
int hole;
|
||||
int byte_period;
|
||||
double bitcell_period_300rpm;
|
||||
int track;
|
||||
int track_width;
|
||||
uint32_t base;
|
||||
uint8_t gap2_size;
|
||||
uint8_t gap3_size;
|
||||
uint16_t disk_flags;
|
||||
uint16_t track_flags;
|
||||
uint8_t sector_pos_side[2][256];
|
||||
uint16_t sector_pos[2][256];
|
||||
uint8_t current_sector_pos_side;
|
||||
uint16_t current_sector_pos;
|
||||
} img[2];
|
||||
|
||||
static uint8_t xdf_track0[3][3];
|
||||
static uint8_t xdf_spt[3] = { 6, 8, 8 };
|
||||
static uint8_t xdf_map[3][24][3];
|
||||
static uint16_t xdf_track0_layout[3][92] = { { 0x8100, 0x8200, 0x8300, 0x8400, 0x8500, 0x8600, 0x8700, 0x8800,
|
||||
0x8101, 0x8201, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600,
|
||||
0x0700, 0x0800, 0, 0x8301, 0x8401, 0x8501, 0x8601, 0x8701,
|
||||
0x8801, 0x8901, 0x8A01, 0x8B01, 0x8C01, 0x8D01, 0x8E01, 0x8F01,
|
||||
0x9001 }, /* 5.25" 2HD */
|
||||
{ 0x8100, 0x8200, 0x8300, 0x8400, 0x8500, 0x8600, 0x8700, 0x8800,
|
||||
0x8900, 0x8A00, 0x8B00, 0x8101, 0x0100, 0x0200, 0x0300, 0x0400,
|
||||
0x0500, 0x0600, 0x0700, 0x0800, 0, 0, 0, 0x8201,
|
||||
0x8301, 0x8401, 0x8501, 0x8601, 0x8701, 0x8801, 0x8901, 0x8A01,
|
||||
0x8B01, 0x8C01, 0x8D01, 0x8E01, 0x8F01, 0, 0, 0,
|
||||
0, 0, 0x9001, 0x9101, 0x9201, 0x9301 }, /* 3.5" 2HD */
|
||||
{ 0x8100, 0x8200, 0x8300, 0x8400, 0x8500, 0x8600, 0x8700, 0x8800,
|
||||
0x8900, 0x8A00, 0x8B00, 0x8C00, 0x8D00, 0x8E00, 0x8F00, 0x9000,
|
||||
0x9100, 0x9200, 0x9300, 0x9400, 0x9500, 0x9600, 0x9700, 0x0100,
|
||||
0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700, 0x0800, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0x9800, 0x9900, 0x9A00,
|
||||
0x9B00, 0x9C00, 0x9D00, 0x9E00, 0x8101, 0x8201, 0x8301, 0x8401,
|
||||
0x8501, 0x8601, 0x8701, 0x8801, 0, 0, 0, 0,
|
||||
0x8901, 0x8A01, 0x8B01, 0x8C01, 0x8D01, 0x8E01, 0x8F01, 0x9001,
|
||||
0x9101, 0x9201, 0x9301, 0x9401, 0x9501, 0x9601, 0x9701, 0x9801,
|
||||
0x9901, 0x9A01, 0x9B01, 0x9C01, 0x9D01, 0x9E01, 0x9F01, 0xA001,
|
||||
0xA101, 0xA201, 0xA301, 0xA401 },
|
||||
};
|
||||
static uint16_t xdf_sector_pos[256];
|
||||
uint8_t dmf_r[21] = { 12, 2, 13, 3, 14, 4, 15, 5, 16, 6, 17, 7, 18, 8, 19, 9, 20, 10, 21, 11, 1 };
|
||||
static uint8_t xdf_spt[2] = { 6, 8 };
|
||||
static uint8_t xdf_logical_sectors[2][2] = { { 38, 6 }, { 46, 8 } };
|
||||
uint8_t xdf_physical_sectors[2][2] = { { 16, 3 }, { 19, 4 } };
|
||||
uint8_t xdf_gap3_sizes[2][2] = { { 60, 69 }, { 60, 50 } };
|
||||
uint16_t xdf_trackx_spos[2][8] = { { 0xA7F, 0xF02, 0x11B7, 0xB66, 0xE1B, 0x129E }, { 0x302, 0x7E2, 0xA52, 0x12DA, 0x572, 0xDFA, 0x106A, 0x154A } };
|
||||
|
||||
/* XDF: Layout of the sectors in the image. */
|
||||
xdf_sector_t xdf_img_layout[2][2][46] = { { { 0x8100, 0x8200, 0x8300, 0x8400, 0x8500, 0x8600, 0x8700, 0x8800,
|
||||
0x8101, 0x8201, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600,
|
||||
0x0700, 0x0800, 0,
|
||||
0x8301, 0x8401, 0x8501, 0x8601, 0x8701, 0x8801, 0x8901, 0x8A01,
|
||||
0x8B01, 0x8C01, 0x8D01, 0x8E01, 0x8F01, 0x9001, 0, 0,
|
||||
0, 0, 0 },
|
||||
{ 0x8300, 0x8600, 0x8201, 0x8200, 0x8601, 0x8301 }
|
||||
}, /* 5.25" 2HD */
|
||||
{ { 0x8100, 0x8200, 0x8300, 0x8400, 0x8500, 0x8600, 0x8700, 0x8800,
|
||||
0x8900, 0x8A00, 0x8B00, 0x8101, 0x0100, 0x0200, 0x0300, 0x0400,
|
||||
0x0500, 0x0600, 0x0700, 0x0800, 0, 0, 0,
|
||||
0x8201, 0x8301, 0x8401, 0x8501, 0x8601, 0x8701, 0x8801, 0x8901,
|
||||
0x8A01, 0x8B01, 0x8C01, 0x8D01, 0x8E01, 0x8F01, 0, 0,
|
||||
0, 0, 0, 0x9001, 0x9101, 0x9201, 0x9301 },
|
||||
{ 0x8300, 0x8400, 0x8601, 0x8200, 0x8201, 0x8600, 0x8401, 0x8301 }
|
||||
} /* 3.5" 2HD */
|
||||
};
|
||||
|
||||
/* XDF: Layout of the sectors on the disk's track. */
|
||||
xdf_sector_t xdf_disk_layout[2][2][38] = { { { 0x0100, 0x0200, 0x8100, 0x8800, 0x8200, 0x0300, 0x8300, 0x0400,
|
||||
0x8400, 0x0500, 0x8500, 0x0600, 0x8600, 0x0700, 0x8700, 0x0800,
|
||||
0x8D01, 0x8501, 0x8E01, 0x8601, 0x8F01, 0x8701, 0x9001, 0x8801,
|
||||
0x8101, 0x8901, 0x8201, 0x8A01, 0x8301, 0x8B01, 0x8401, 0x8C01 },
|
||||
{ 0x8300, 0x8200, 0x8600, 0x8201, 0x8301, 0x8601 }
|
||||
}, /* 5.25" 2HD */
|
||||
{ { 0x0100, 0x8A00, 0x8100, 0x8B00, 0x8200, 0x0200, 0x8300, 0x0300,
|
||||
0x8400, 0x0400, 0x8500, 0x0500, 0x8600, 0x0600, 0x8700, 0x0700,
|
||||
0x8800, 0x0800, 0x8900,
|
||||
0x9001, 0x8701, 0x9101, 0x8801, 0x9201, 0x8901, 0x9301, 0x8A01,
|
||||
0x8101, 0x8B01, 0x8201, 0x8C01, 0x8301, 0x8D01, 0x8401, 0x8E01,
|
||||
0x8501, 0x8F01, 0x8601 },
|
||||
{ 0x8300, 0x8200, 0x8400, 0x8600, 0x8401, 0x8201, 0x8301, 0x8601 },
|
||||
}, /* 3.5" 2HD */
|
||||
};
|
||||
|
||||
/* First dimension is possible sector sizes (0 = 128, 7 = 16384), second is possible bit rates (250/360, 250, 300, 500/360, 500, 1000). */
|
||||
/* Disks formatted at 250 kbps @ 360 RPM can be read with a 360 RPM single-RPM 5.25" drive by setting the rate to 250 kbps.
|
||||
Disks formatted at 300 kbps @ 300 RPM can be read with any 300 RPM single-RPM drive by setting the rate rate to 300 kbps. */
|
||||
static uint8_t maximum_sectors[8][6] = { { 26, 31, 38, 53, 64, 118 }, /* 128 */
|
||||
{ 15, 19, 23, 32, 38, 73 }, /* 256 */
|
||||
{ 7, 10, 12, 19, 23, 46 }, /* 512 */
|
||||
{ 7, 10, 12, 17, 21, 41 }, /* 512 */
|
||||
{ 3, 5, 6, 9, 11, 22 }, /* 1024 */
|
||||
{ 2, 2, 3, 4, 5, 11 }, /* 2048 */
|
||||
{ 1, 1, 1, 2, 2, 5 }, /* 4096 */
|
||||
{ 0, 0, 0, 1, 1, 3 }, /* 8192 */
|
||||
{ 0, 0, 0, 0, 0, 1 } }; /* 16384 */
|
||||
|
||||
static int gap3_sizes[5][8][256] = { [0][1][16] = 0x54,
|
||||
static uint8_t xdf_sectors[8][6] = { { 0, 0, 0, 0, 0, 0 }, /* 128 */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* 256 */
|
||||
{ 0, 0, 0, 19, 23, 0 }, /* 512 */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* 1024 */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* 2048 */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* 4096 */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* 8192 */
|
||||
{ 0, 0, 0, 0, 0, 0 } }; /* 16384 */
|
||||
|
||||
static uint8_t xdf_types[8][6] = { { 0, 0, 0, 0, 0, 0 }, /* 128 */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* 256 */
|
||||
{ 0, 0, 0, 1, 2, 0 }, /* 512 */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* 1024 */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* 2048 */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* 4096 */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* 8192 */
|
||||
{ 0, 0, 0, 0, 0, 0 } }; /* 16384 */
|
||||
|
||||
static double bit_rates_300[6] = { (250.0 * 300.0) / 360.0, 250.0, 300.0, (500.0 * 300.0) / 360.0, 500.0, 1000.0 };
|
||||
|
||||
static uint8_t rates[6] = { 2, 2, 1, 4, 0, 3 };
|
||||
|
||||
static uint8_t holes[6] = { 0, 0, 0, 1, 1, 2 };
|
||||
|
||||
int gap3_sizes[5][8][256] = { [0][1][16] = 0x54,
|
||||
[0][2][18] = 0x6C,
|
||||
[0][2][19] = 0x48,
|
||||
[0][2][20] = 0x2A,
|
||||
[0][2][21] = 0x0C,
|
||||
[0][2][21] = 0x08, /* Microsoft DMFWRITE.EXE uses this, 0x0C is used by FDFORMAT. */
|
||||
[0][2][23] = 0x01,
|
||||
[0][3][10] = 0x83,
|
||||
[0][3][11] = 0x26,
|
||||
[1][2][11] = 0x54,
|
||||
[1][2][12] = 0x1C,
|
||||
[1][2][13] = 0x0E,
|
||||
[1][3][6] = 0x79,
|
||||
[1][3][7] = 0x06,
|
||||
[2][1][10] = 0x32,
|
||||
[2][1][11] = 0x0C,
|
||||
[2][1][15] = 0x36,
|
||||
@@ -77,30 +128,32 @@ static int gap3_sizes[5][8][256] = { [0][1][16] = 0x54,
|
||||
[2][2][8] = 0x58,
|
||||
[2][2][9] = 0x50,
|
||||
[2][2][10] = 0x2E,
|
||||
[2][2][11] = 0x02,
|
||||
[2][2][21] = 0x1C,
|
||||
[2][3][4] = 0xF0,
|
||||
[2][3][5] = 0x74,
|
||||
[3][2][36] = 0x53,
|
||||
[3][2][39] = 0x20,
|
||||
[3][2][37] = 0x4E,
|
||||
[3][2][38] = 0x3D,
|
||||
[3][2][39] = 0x2C,
|
||||
[3][2][40] = 0x1C,
|
||||
[3][2][41] = 0x0D,
|
||||
[3][2][42] = 0x02,
|
||||
[3][2][46] = 0x01,
|
||||
[3][3][18] = 0xF7,
|
||||
[3][3][19] = 0xAF,
|
||||
[3][3][20] = 0x6F,
|
||||
[3][3][21] = 0x55,
|
||||
[3][3][22] = 0x1F,
|
||||
[4][1][32] = 0x36,
|
||||
[4][2][14] = 0x92,
|
||||
[4][2][15] = 0x54,
|
||||
[4][2][16] = 0x38,
|
||||
[4][2][17] = 0x23,
|
||||
[4][2][18] = 0x02,
|
||||
[4][2][19] = 0x01,
|
||||
[4][3][8] = 0x74
|
||||
[4][3][8] = 0x74,
|
||||
[4][3][9] = 0x24
|
||||
};
|
||||
|
||||
/* Needed for formatting! */
|
||||
int img_realtrack(int drive, int track)
|
||||
{
|
||||
if ((img[drive].tracks <= 43) && fdd_doublestep_40(drive))
|
||||
track /= 2;
|
||||
|
||||
return track;
|
||||
}
|
||||
|
||||
void img_writeback(int drive);
|
||||
|
||||
static int sector_size_code(int sector_size)
|
||||
@@ -138,18 +191,7 @@ void img_init()
|
||||
// adl[0] = adl[1] = 0;
|
||||
}
|
||||
|
||||
static void add_to_map(uint8_t *arr, uint8_t p1, uint8_t p2, uint8_t p3)
|
||||
{
|
||||
arr[0] = p1;
|
||||
arr[1] = p2;
|
||||
arr[2] = p3;
|
||||
}
|
||||
|
||||
static int xdf_maps_initialized = 0;
|
||||
|
||||
static uint16_t xdf_trackx_layout[3][8] = { { 0x8300, 0x8600, 0x8201, 0x8200, 0x8601, 0x8301},
|
||||
{ 0x8300, 0x8400, 0x8601, 0x8200, 0x8201, 0x8600, 0x8401, 0x8301},
|
||||
{ 0x8300, 0x8400, 0x8500, 0x8700, 0x8301, 0x8401, 0x8501, 0x8701} };
|
||||
void d86f_register_img(int drive);
|
||||
|
||||
void img_load(int drive, char *fn)
|
||||
{
|
||||
@@ -165,12 +207,15 @@ void img_load(int drive, char *fn)
|
||||
int temp_rate;
|
||||
char ext[4];
|
||||
int fdi;
|
||||
int i;
|
||||
|
||||
ext[0] = fn[strlen(fn) - 3] | 0x60;
|
||||
ext[1] = fn[strlen(fn) - 2] | 0x60;
|
||||
ext[2] = fn[strlen(fn) - 1] | 0x60;
|
||||
ext[3] = 0;
|
||||
|
||||
d86f_unregister(drive);
|
||||
|
||||
writeprot[drive] = 0;
|
||||
img[drive].f = fopen(fn, "rb+");
|
||||
if (!img[drive].f)
|
||||
@@ -230,7 +275,7 @@ void img_load(int drive, char *fn)
|
||||
}
|
||||
|
||||
img[drive].sides = 2;
|
||||
img[drive].sector_size = 512;
|
||||
img[drive].sector_size = 2;
|
||||
|
||||
img[drive].hole = 0;
|
||||
|
||||
@@ -241,74 +286,47 @@ void img_load(int drive, char *fn)
|
||||
/* The BPB is giving us a wacky number of sides and/or bytes per sector, therefore it is most probably
|
||||
not a BPB at all, so we have to guess the parameters from file size. */
|
||||
|
||||
if (size <= (160*1024)) { img[drive].sectors = 8; img[drive].tracks = 40; img[drive].sides = 1; bit_rate_300 = 250; raw_tsize[drive] = 6250; }
|
||||
else if (size <= (180*1024)) { img[drive].sectors = 9; img[drive].tracks = 40; img[drive].sides = 1; bit_rate_300 = 250; raw_tsize[drive] = 6250; }
|
||||
else if (size <= (320*1024)) { img[drive].sectors = 8; img[drive].tracks = 40; bit_rate_300 = 250; raw_tsize[drive] = 6250; }
|
||||
else if (size <= (360*1024)) { img[drive].sectors = 9; img[drive].tracks = 40; bit_rate_300 = 250; raw_tsize[drive] = 6250; } /*Double density*/
|
||||
else if (size <= (640*1024)) { img[drive].sectors = 8; img[drive].tracks = 80; bit_rate_300 = 250; raw_tsize[drive] = 6250; } /*Double density 640k*/
|
||||
else if (size < (1024*1024)) { img[drive].sectors = 9; img[drive].tracks = 80; bit_rate_300 = 250; raw_tsize[drive] = 6250; } /*Double density*/
|
||||
else if (size <= 1228800) { img[drive].sectors = 15; img[drive].tracks = 80; bit_rate_300 = (500.0 * 300.0) / 360.0; raw_tsize[drive] = 10416; } /*High density 1.2MB*/
|
||||
else if (size <= 1261568) { img[drive].sectors = 8; img[drive].tracks = 77; img[drive].sector_size = 1024; bit_rate_300 = (500.0 * 300.0) / 360.0; raw_tsize[drive] = 10416; } /*High density 1.25MB Japanese format*/
|
||||
else if (size <= (0x1A4000-1)) { img[drive].sectors = 18; img[drive].tracks = 80; bit_rate_300 = 500; raw_tsize[drive] = 12500; } /*High density (not supported by Tandy 1000)*/
|
||||
else if (size <= 1556480) { img[drive].sectors = 19; img[drive].tracks = 80; bit_rate_300 = 500; raw_tsize[drive] = 12500; } /*High density (not supported by Tandy 1000)*/
|
||||
else if (size <= 1638400) { img[drive].sectors = 10; img[drive].tracks = 80; img[drive].sector_size = 1024; bit_rate_300 = 500; raw_tsize[drive] = 12500; } /*High density (not supported by Tandy 1000)*/
|
||||
// else if (size == 1884160) { img[drive].sectors = 23; img[drive].tracks = 80; bit_rate_300 = 500; } /*XDF format - used by OS/2 Warp*/
|
||||
// else if (size == 1763328) { img[drive].sectors = 21; img[drive].tracks = 82; bit_rate_300 = 500; } /*XDF format - used by OS/2 Warp*/
|
||||
else if (size <= 2000000) { img[drive].sectors = 21; img[drive].tracks = 80; bit_rate_300 = 500; raw_tsize[drive] = 12500; } /*DMF format - used by Windows 95 - changed by OBattler to 2000000, ie. the real unformatted capacity @ 500 kbps and 300 rpm */
|
||||
else if (size <= 2949120) { img[drive].sectors = 36; img[drive].tracks = 80; bit_rate_300 = 1000; raw_tsize[drive] = 25000; } /*E density*/
|
||||
|
||||
temp_rate = 2;
|
||||
bpb_bps = img[drive].sector_size;
|
||||
bpt = bpb_bps * img[drive].sectors;
|
||||
if (bpt <= (maximum_sectors[sector_size_code(bpb_bps)][0] * bpb_bps))
|
||||
{
|
||||
temp_rate = 2;
|
||||
raw_tsize[drive] = 5208;
|
||||
}
|
||||
else if (bpt <= (maximum_sectors[sector_size_code(bpb_bps)][1] * bpb_bps))
|
||||
{
|
||||
temp_rate = 2;
|
||||
raw_tsize[drive] = 6250;
|
||||
}
|
||||
else if (bpt <= (maximum_sectors[sector_size_code(bpb_bps)][2] * bpb_bps))
|
||||
{
|
||||
temp_rate = 1;
|
||||
raw_tsize[drive] = 7500;
|
||||
}
|
||||
else if (bpt <= (maximum_sectors[sector_size_code(bpb_bps)][3] * bpb_bps))
|
||||
{
|
||||
if (bpb_bps == 512) max_spt = (bit_rate_300 == 500) ? 21 : 17;
|
||||
temp_rate = (bit_rate_300 == 500) ? 0 : 4;
|
||||
raw_tsize[drive] = (bit_rate_300 == 500) ? 12500 : 10416;
|
||||
}
|
||||
else if (bpt <= (maximum_sectors[sector_size_code(bpb_bps)][4] * bpb_bps))
|
||||
{
|
||||
if (bpb_bps == 512) max_spt = 21;
|
||||
pclog("max_spt is %i\n", max_spt);
|
||||
temp_rate = 0;
|
||||
raw_tsize[drive] = 12500;
|
||||
}
|
||||
else if (bpt <= (maximum_sectors[sector_size_code(bpb_bps)][5] * bpb_bps))
|
||||
{
|
||||
if (bpb_bps == 512) max_spt = 41;
|
||||
temp_rate = 3;
|
||||
raw_tsize[drive] = 25000;
|
||||
}
|
||||
else /* Image too big, eject */
|
||||
if (size <= (160*1024)) { img[drive].sectors = 8; img[drive].tracks = 40; img[drive].sides = 1; }
|
||||
else if (size <= (180*1024)) { img[drive].sectors = 9; img[drive].tracks = 40; img[drive].sides = 1; }
|
||||
else if (size <= (320*1024)) { img[drive].sectors = 8; img[drive].tracks = 40; }
|
||||
else if (size <= (360*1024)) { img[drive].sectors = 9; img[drive].tracks = 40; } /*Double density*/
|
||||
else if (size <= (400*1024)) { img[drive].sectors = 10; img[drive].tracks = 80; img[drive].sides = 1; } /*DEC RX50*/
|
||||
else if (size <= (640*1024)) { img[drive].sectors = 8; img[drive].tracks = 80; } /*Double density 640k*/
|
||||
else if (size <= (720*1024)) { img[drive].sectors = 9; img[drive].tracks = 80; } /*Double density*/
|
||||
else if (size <= (800*1024)) { img[drive].sectors = 10; img[drive].tracks = 80; } /*Double density*/
|
||||
else if (size <= (880*1024)) { img[drive].sectors = 11; img[drive].tracks = 80; } /*Double density*/
|
||||
else if (size <= (960*1024)) { img[drive].sectors = 12; img[drive].tracks = 80; } /*Double density*/
|
||||
else if (size <= (1040*1024)) { img[drive].sectors = 13; img[drive].tracks = 80; } /*Double density*/
|
||||
else if (size <= (1120*1024)) { img[drive].sectors = 14; img[drive].tracks = 80; } /*Double density*/
|
||||
else if (size <= 1228800) { img[drive].sectors = 15; img[drive].tracks = 80; } /*High density 1.2MB*/
|
||||
else if (size <= 1261568) { img[drive].sectors = 8; img[drive].tracks = 77; img[drive].sector_size = 3; } /*High density 1.25MB Japanese format*/
|
||||
else if (size <= (0x1A4000-1)) { img[drive].sectors = 18; img[drive].tracks = 80; } /*High density (not supported by Tandy 1000)*/
|
||||
else if (size <= 1556480) { img[drive].sectors = 19; img[drive].tracks = 80; } /*High density (not supported by Tandy 1000)*/
|
||||
else if (size <= 1638400) { img[drive].sectors = 10; img[drive].tracks = 80; img[drive].sector_size = 3; } /*High density (not supported by Tandy 1000)*/
|
||||
else if (size <= 1720320) { img[drive].sectors = 21; img[drive].tracks = 80; } /*DMF format - used by Windows 95 */
|
||||
else if (size <= 1741824) { img[drive].sectors = 21; img[drive].tracks = 81; }
|
||||
else if (size <= 1763328) { img[drive].sectors = 21; img[drive].tracks = 82; }
|
||||
else if (size <= 1802240) { img[drive].sectors = 11; img[drive].tracks = 80; img[drive].sector_size = 3; } /*High density (not supported by Tandy 1000)*/
|
||||
else if (size == 1884160) { img[drive].sectors = 23; img[drive].tracks = 80; } /*XDF format - used by OS/2 Warp*/
|
||||
else if (size <= 2949120) { img[drive].sectors = 36; img[drive].tracks = 80; } /*E density*/
|
||||
else if (size <= 3194880) { img[drive].sectors = 39; img[drive].tracks = 80; } /*E density*/
|
||||
else if (size <= 3276800) { img[drive].sectors = 40; img[drive].tracks = 80; } /*E density*/
|
||||
else if (size <= 3358720) { img[drive].sectors = 41; img[drive].tracks = 80; } /*E density, maximum possible size*/
|
||||
else if (size <= 3440640) { img[drive].sectors = 42; img[drive].tracks = 80; } /*E density, maximum possible size*/
|
||||
/* else if (size <= 3440640) { img[drive].sectors = 21; img[drive].tracks = 80; img[drive].sector_size = 3; } */ /*High density (not supported by Tandy 1000)*/
|
||||
else if (size <= 3604480) { img[drive].sectors = 22; img[drive].tracks = 80; img[drive].sector_size = 3; } /*High density (not supported by Tandy 1000)*/
|
||||
else if (size <= 3610624) { img[drive].sectors = 41; img[drive].tracks = 86; } /*E density, maximum possible size*/
|
||||
else if (size <= 3698688) { img[drive].sectors = 42; img[drive].tracks = 86; } /*E density, maximum possible size*/
|
||||
else
|
||||
{
|
||||
pclog("Image is bigger than can fit on an ED floppy, ejecting...\n");
|
||||
fclose(img[drive].f);
|
||||
return;
|
||||
}
|
||||
|
||||
pclog("Temporary rate: %i (%i bytes per track)\n", temp_rate, bpt);
|
||||
|
||||
img[drive].xdf_type = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The BPB readings appear to be valid, so let's set the values. */
|
||||
/* Number of tracks = number of total sectors divided by sides times sectors per track. */
|
||||
if (fdi)
|
||||
{
|
||||
/* The image is a Japanese FDI, therefore we read the number of tracks from the header. */
|
||||
@@ -317,297 +335,304 @@ void img_load(int drive, char *fn)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Number of tracks = number of total sectors divided by sides times sectors per track. */
|
||||
img[drive].tracks = ((uint32_t) bpb_total) / (((uint32_t) bpb_sides) * ((uint32_t) bpb_sectors));
|
||||
}
|
||||
/* The rest we just set directly from the BPB. */
|
||||
img[drive].sectors = bpb_sectors;
|
||||
img[drive].sides = bpb_sides;
|
||||
/* The sector size. */
|
||||
img[drive].sector_size = bpb_bps;
|
||||
/* Now we calculate bytes per track, which is bpb_sectors * bpb_bps. */
|
||||
bpt = (uint32_t) bpb_sectors * (uint32_t) bpb_bps;
|
||||
/* Now we should be able to calculate the bit rate. */
|
||||
pclog("The image has %i bytes per track\n", bpt);
|
||||
img[drive].sector_size = sector_size_code(bpb_bps);
|
||||
|
||||
temp_rate = 2;
|
||||
if (bpt <= (maximum_sectors[sector_size_code(bpb_bps)][0] * bpb_bps))
|
||||
{
|
||||
bit_rate_300 = ((250.0 * 300.0) / 360.0);
|
||||
temp_rate = 2;
|
||||
raw_tsize[drive] = 5208;
|
||||
}
|
||||
else if (bpt <= (maximum_sectors[sector_size_code(bpb_bps)][1] * bpb_bps))
|
||||
{
|
||||
bit_rate_300 = 250;
|
||||
temp_rate = 2;
|
||||
raw_tsize[drive] = 6250;
|
||||
}
|
||||
else if (bpt <= (maximum_sectors[sector_size_code(bpb_bps)][2] * bpb_bps))
|
||||
{
|
||||
bit_rate_300 = 300;
|
||||
temp_rate = 1;
|
||||
raw_tsize[drive] = 7500;
|
||||
}
|
||||
else if (bpt <= (maximum_sectors[sector_size_code(bpb_bps)][3] * bpb_bps))
|
||||
{
|
||||
bit_rate_300 = (bpb_mid == 0xF0) ? 500 : ((500.0 * 300.0) / 360.0);
|
||||
if (bpb_bps == 512) max_spt = (bit_rate_300 == 500) ? 21 : 17;
|
||||
temp_rate = (bit_rate_300 == 500) ? 0 : 4;
|
||||
raw_tsize[drive] = (bit_rate_300 == 500) ? 12500 : 10416;
|
||||
}
|
||||
else if (bpt <= (maximum_sectors[sector_size_code(bpb_bps)][4] * bpb_bps))
|
||||
{
|
||||
bit_rate_300 = 500;
|
||||
if (bpb_bps == 512) max_spt = 21;
|
||||
pclog("max_spt is %i\n", max_spt);
|
||||
temp_rate = 0;
|
||||
raw_tsize[drive] = 12500;
|
||||
}
|
||||
else if (bpt <= (maximum_sectors[sector_size_code(bpb_bps)][5] * bpb_bps))
|
||||
{
|
||||
bit_rate_300 = 1000;
|
||||
if (bpb_bps == 512) max_spt = 41;
|
||||
temp_rate = 3;
|
||||
raw_tsize[drive] = 25000;
|
||||
}
|
||||
else /* Image too big, eject */
|
||||
{
|
||||
pclog("Image is bigger than can fit on an ED floppy, ejecting...\n");
|
||||
fclose(img[drive].f);
|
||||
return;
|
||||
}
|
||||
temp_rate = 0xFF;
|
||||
}
|
||||
|
||||
if (bpb_bps == 512) /* BPB reports 512 bytes per sector, let's see if it's XDF or not */
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
if ((img[drive].sectors <= maximum_sectors[img[drive].sector_size][i]) || (img[drive].sectors == xdf_sectors[img[drive].sector_size][i]))
|
||||
{
|
||||
if (bit_rate_300 <= 300) /* Double-density disk, not XDF */
|
||||
bit_rate_300 = bit_rates_300[i];
|
||||
temp_rate = rates[i];
|
||||
img[drive].disk_flags = holes[i] << 1;
|
||||
img[drive].xdf_type = (img[drive].sectors == xdf_sectors[img[drive].sector_size][i]) ? xdf_types[img[drive].sector_size][i] : 0;
|
||||
if ((bit_rate_300 == 500.0) && (img[drive].sectors == 21) && (img[drive].sector_size == 2) && (img[drive].tracks >= 80) && (img[drive].tracks <= 82) && (img[drive].sides == 2))
|
||||
{
|
||||
img[drive].xdf_type = 0;
|
||||
/* This is a DMF floppy, set the flag so we know to interleave the sectors. */
|
||||
img[drive].dmf = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pclog("bpb_sectors is %i\n", bpb_sectors);
|
||||
if (bpb_sectors > max_spt)
|
||||
{
|
||||
switch(bpb_sectors)
|
||||
{
|
||||
case 19: /* High density XDF @ 360 rpm */
|
||||
img[drive].xdf_type = 1;
|
||||
break;
|
||||
case 23: /* High density XDF @ 300 rpm */
|
||||
img[drive].xdf_type = 2;
|
||||
pclog("XDF type is 2 @ %i kbps\n", bit_rate_300);
|
||||
break;
|
||||
case 46: /* Extended density XDF */
|
||||
img[drive].xdf_type = 3;
|
||||
break;
|
||||
default: /* Unknown, as we're beyond maximum sectors, get out */
|
||||
fclose(img[drive].f);
|
||||
return;
|
||||
}
|
||||
pclog("XDF type: %i\n", img[drive].xdf_type);
|
||||
}
|
||||
else /* Amount of sectors per track that fits into a track, therefore not XDF */
|
||||
{
|
||||
img[drive].xdf_type = 0;
|
||||
}
|
||||
img[drive].dmf = 0;
|
||||
}
|
||||
}
|
||||
else /* BPB reports sector size other than 512, can't possibly be XDF */
|
||||
{
|
||||
img[drive].xdf_type = 0;
|
||||
|
||||
pclog("Image parameters: bit rate 300: %f, temporary rate: %i, hole: %i, DMF: %i, XDF type: %i\n", bit_rate_300, temp_rate, img[drive].disk_flags >> 1, img[drive].dmf, img[drive].xdf_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gap2_size[drive] = (temp_rate == 3) ? 41 : 22;
|
||||
// pclog("GAP2 size: %i bytes\n", gap2_size[drive]);
|
||||
gap3_size[drive] = gap3_sizes[temp_rate][sector_size_code(img[drive].sector_size)][img[drive].sectors];
|
||||
if (!gap3_size[drive])
|
||||
if (temp_rate == 0xFF)
|
||||
{
|
||||
gap3_size[drive] = 40;
|
||||
pclog("WARNING: Floppy image of unknown format was inserted into drive %c:!\n", drive + 0x41);
|
||||
pclog("Image is bigger than can fit on an ED floppy, ejecting...\n");
|
||||
fclose(img[drive].f);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bit_rate_300 == 250)
|
||||
img[drive].gap2_size = (temp_rate == 3) ? 41 : 22;
|
||||
if (img[drive].dmf)
|
||||
{
|
||||
img[drive].hole = 0;
|
||||
/* If drive does not support 300 RPM, the medium is to be read at a period of 26 (300 kbps). */
|
||||
img[drive].byte_period = 29;
|
||||
}
|
||||
else if (bit_rate_300 == 300)
|
||||
{
|
||||
img[drive].hole = 0;
|
||||
img[drive].byte_period = 26;
|
||||
}
|
||||
else if (bit_rate_300 == 1000)
|
||||
{
|
||||
img[drive].hole = 2;
|
||||
img[drive].byte_period = 8;
|
||||
}
|
||||
else if (bit_rate_300 < 250)
|
||||
{
|
||||
img[drive].hole = 0;
|
||||
img[drive].byte_period = 32;
|
||||
img[drive].gap3_size = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
img[drive].hole = 1;
|
||||
img[drive].byte_period = 16;
|
||||
img[drive].gap3_size = gap3_sizes[temp_rate][img[drive].sector_size][img[drive].sectors];
|
||||
}
|
||||
if (!img[drive].gap3_size)
|
||||
{
|
||||
pclog("ERROR: Floppy image of unknown format was inserted into drive %c:!\n", drive + 0x41);
|
||||
fclose(img[drive].f);
|
||||
return;
|
||||
}
|
||||
|
||||
img[drive].track_width = 0;
|
||||
if (img[drive].tracks > 43) img[drive].track_width = 1; /* If the image has more than 43 tracks, then the tracks are thin (96 tpi). */
|
||||
if (img[drive].sides == 2) img[drive].disk_flags |= 8; /* If the has 2 sides, mark it as such. */
|
||||
|
||||
img[drive].track_flags = 0x08; /* IMG files are always assumed to be MFM-encoded. */
|
||||
img[drive].track_flags |= temp_rate & 3; /* Data rate. */
|
||||
if (temp_rate & 4) img[drive].track_flags |= 0x20; /* RPM. */
|
||||
|
||||
pclog("Disk flags: %i, track flags: %i\n", img[drive].disk_flags, img[drive].track_flags);
|
||||
|
||||
d86f_register_img(drive);
|
||||
|
||||
drives[drive].seek = img_seek;
|
||||
drives[drive].readsector = disc_sector_readsector;
|
||||
drives[drive].writesector = disc_sector_writesector;
|
||||
drives[drive].readaddress = disc_sector_readaddress;
|
||||
drives[drive].hole = img_hole;
|
||||
drives[drive].byteperiod = img_byteperiod;
|
||||
drives[drive].poll = disc_sector_poll;
|
||||
drives[drive].format = disc_sector_format;
|
||||
drives[drive].realtrack = img_realtrack;
|
||||
drives[drive].stop = disc_sector_stop;
|
||||
disc_sector_writeback[drive] = img_writeback;
|
||||
|
||||
img[drive].bitcell_period_300rpm = 1000000.0 / bit_rate_300*2.0;
|
||||
pclog("bit_rate_300=%g\n", bit_rate_300);
|
||||
pclog("bitcell_period_300=%g\n", img[drive].bitcell_period_300rpm);
|
||||
// img[drive].bitcell_period_300rpm = disc_get_bitcell_period(img[drive].rate);
|
||||
pclog("img_load %d %p sectors=%i tracks=%i sides=%i sector_size=%i hole=%i\n", drive, drives, img[drive].sectors, img[drive].tracks, img[drive].sides, img[drive].sector_size, img[drive].hole);
|
||||
}
|
||||
|
||||
int img_hole(int drive)
|
||||
{
|
||||
return img[drive].hole;
|
||||
}
|
||||
|
||||
double img_byteperiod(int drive)
|
||||
{
|
||||
if (img[drive].byte_period == 29)
|
||||
{
|
||||
return (fdd_get_type(drive) & 1) ? 32.0 : (160.0 / 6.0);
|
||||
}
|
||||
return (double) img[drive].byte_period;
|
||||
d86f_common_handlers(drive);
|
||||
}
|
||||
|
||||
void img_close(int drive)
|
||||
{
|
||||
d86f_unregister(drive);
|
||||
if (img[drive].f)
|
||||
fclose(img[drive].f);
|
||||
img[drive].f = NULL;
|
||||
}
|
||||
|
||||
#define xdf_img_sector xdf_img_layout[current_xdft][!is_t0][sector]
|
||||
#define xdf_disk_sector xdf_disk_layout[current_xdft][!is_t0][array_sector]
|
||||
|
||||
int interleave(int sector, int skew, int track_spt)
|
||||
{
|
||||
uint32_t skewed_i = 0;
|
||||
uint32_t adjusted_r = 0;
|
||||
|
||||
uint32_t add = (track_spt & 1);
|
||||
uint32_t adjust = (track_spt >> 1);
|
||||
|
||||
skewed_i = (sector + skew) % track_spt;
|
||||
adjusted_r = (skewed_i >> 1) + 1;
|
||||
if (skewed_i & 1)
|
||||
{
|
||||
adjusted_r += (adjust + add);
|
||||
}
|
||||
|
||||
return adjusted_r;
|
||||
}
|
||||
|
||||
void img_seek(int drive, int track)
|
||||
{
|
||||
int side;
|
||||
int current_xdft = img[drive].xdf_type - 1;
|
||||
|
||||
int sector, current_pos, sh, sr, sn, sside, total, max_pos;
|
||||
uint8_t id[4] = { 0, 0, 0, 0 };
|
||||
|
||||
int is_t0, sector, current_pos, img_pos, sr, sside, total, array_sector, buf_side, buf_pos;
|
||||
|
||||
int ssize = 128 << ((int) img[drive].sector_size);
|
||||
|
||||
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);
|
||||
// pclog(" %i %i\n", drive_type[drive], img[drive].tracks);
|
||||
if ((img[drive].tracks <= 43) && fdd_doublestep_40(drive))
|
||||
|
||||
if (!img[drive].track_width && fdd_doublestep_40(drive))
|
||||
track /= 2;
|
||||
|
||||
// pclog("Disk seeked to track %i\n", track);
|
||||
disc_track[drive] = track;
|
||||
img[drive].track = track;
|
||||
|
||||
if (img[drive].sides == 2)
|
||||
{
|
||||
fseek(img[drive].f, img[drive].base + (track * img[drive].sectors * img[drive].sector_size * 2), SEEK_SET);
|
||||
// pclog("Seek: Current file position (H0) is: %08X\n", ftell(img[drive].f));
|
||||
fread(img[drive].track_data[0], img[drive].sectors * img[drive].sector_size, 1, img[drive].f);
|
||||
// pclog("Seek: Current file position (H1) is: %08X\n", ftell(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, img[drive].base + (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);
|
||||
}
|
||||
|
||||
disc_sector_reset(drive, 0);
|
||||
disc_sector_reset(drive, 1);
|
||||
|
||||
if (img[drive].xdf_type)
|
||||
is_t0 = (track == 0) ? 1 : 0;
|
||||
|
||||
fseek(img[drive].f, img[drive].base + (track * img[drive].sectors * ssize * img[drive].sides), SEEK_SET);
|
||||
for (side = 0; side < img[drive].sides; side++)
|
||||
{
|
||||
max_pos = (img[drive].sectors * 512);
|
||||
if (!track)
|
||||
fread(img[drive].track_data[side], img[drive].sectors * ssize, 1, img[drive].f);
|
||||
}
|
||||
|
||||
d86f_reset_index_hole_pos(drive, 0);
|
||||
d86f_reset_index_hole_pos(drive, 1);
|
||||
|
||||
if (!img[drive].xdf_type)
|
||||
{
|
||||
for (side = 0; side < img[drive].sides; side++)
|
||||
{
|
||||
/* Track 0, register sectors according to track 0 layout. */
|
||||
total = img[drive].sectors;
|
||||
current_pos = 0;
|
||||
for (sector = 0; sector < (total << 1); sector++)
|
||||
current_pos = d86f_prepare_pretrack(drive, side, 0);
|
||||
|
||||
for (sector = 0; sector < img[drive].sectors; sector++)
|
||||
{
|
||||
current_pos = (sector % total) << 9;
|
||||
sside = (sector >= total) ? 1 : 0;
|
||||
if (xdf_track0_layout[current_xdft][sector])
|
||||
// sr = img[drive].dmf ? (dmf_r[sector]) : (sector + 1);
|
||||
if (img[drive].gap3_size < 68)
|
||||
{
|
||||
sh = xdf_track0_layout[current_xdft][sector] & 0xFF;
|
||||
sr = xdf_track0_layout[current_xdft][sector] >> 8;
|
||||
xdf_sector_pos[(sh << 8) | sr] = current_pos;
|
||||
disc_sector_add(drive, sh, track, sh, sr, 2,
|
||||
img[drive].bitcell_period_300rpm,
|
||||
&img[drive].track_data[sside][current_pos]);
|
||||
sr = interleave(sector, 1, img[drive].sectors);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Non-zero track, this will have sectors of various sizes. */
|
||||
total = xdf_spt[current_xdft] >> 1;
|
||||
current_pos = 0;
|
||||
for (sector = 0; sector < xdf_spt[current_xdft]; sector++)
|
||||
{
|
||||
sside = (sector >= total) ? 1 : 0;
|
||||
sh = xdf_trackx_layout[current_xdft][sector] & 0xFF;
|
||||
sr = xdf_trackx_layout[current_xdft][sector] >> 8;
|
||||
sn = sr & 7;
|
||||
disc_sector_add(drive, sh, track, sh, sr, sn,
|
||||
img[drive].bitcell_period_300rpm,
|
||||
&img[drive].track_data[sside][current_pos]);
|
||||
current_pos += (128 << sn);
|
||||
current_pos %= max_pos;
|
||||
else
|
||||
{
|
||||
sr = img[drive].dmf ? (dmf_r[sector]) : (sector + 1);
|
||||
}
|
||||
id[0] = track;
|
||||
id[1] = side;
|
||||
id[2] = sr;
|
||||
id[3] = img[drive].sector_size;
|
||||
img[drive].sector_pos_side[side][sr] = side;
|
||||
img[drive].sector_pos[side][sr] = (sr - 1) * ssize;
|
||||
// pclog("Seek: %i %i %i %i | %i %04X\n", id[0], id[1], id[2], id[3], side, (sr - 1) * ssize);
|
||||
current_pos = d86f_prepare_sector(drive, side, current_pos, id, &img[drive].track_data[side][(sr - 1) * ssize], ssize, img[drive].gap2_size, img[drive].gap3_size, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (side = 0; side < img[drive].sides; side++)
|
||||
{
|
||||
for (sector = 0; sector < img[drive].sectors; sector++)
|
||||
disc_sector_add(drive, side, track, side, sector+1, img_sector_size_code(drive),
|
||||
img[drive].bitcell_period_300rpm,
|
||||
&img[drive].track_data[side][sector * img[drive].sector_size]);
|
||||
{
|
||||
total = img[drive].sectors;
|
||||
img_pos = 0;
|
||||
sside = 0;
|
||||
|
||||
/* Pass 1, get sector positions in the image. */
|
||||
for (sector = 0; sector < xdf_logical_sectors[current_xdft][!is_t0]; sector++)
|
||||
{
|
||||
if (is_t0)
|
||||
{
|
||||
img_pos = (sector % total) << 9;
|
||||
sside = (sector >= total) ? 1 : 0;
|
||||
}
|
||||
|
||||
if (xdf_img_sector.word)
|
||||
{
|
||||
img[drive].sector_pos_side[xdf_img_sector.id.h][xdf_img_sector.id.r] = sside;
|
||||
img[drive].sector_pos[xdf_img_sector.id.h][xdf_img_sector.id.r] = img_pos;
|
||||
// pclog("Side: %i, Position: %04X\n", sside, img_pos);
|
||||
}
|
||||
|
||||
if (!is_t0)
|
||||
{
|
||||
img_pos += (128 << (xdf_img_sector.id.r & 7));
|
||||
if (img_pos >= (total << 9)) sside = 1;
|
||||
img_pos %= (total << 9);
|
||||
}
|
||||
}
|
||||
|
||||
/* Pass 2, prepare the actual track. */
|
||||
for (side = 0; side < img[drive].sides; side++)
|
||||
{
|
||||
current_pos = d86f_prepare_pretrack(drive, side, 0);
|
||||
|
||||
for (sector = 0; sector < xdf_physical_sectors[current_xdft][!is_t0]; sector++)
|
||||
{
|
||||
array_sector = (side * xdf_physical_sectors[current_xdft][!is_t0]) + sector;
|
||||
// pclog("Sector %i, array sector %i\n", sector, array_sector);
|
||||
|
||||
buf_side = img[drive].sector_pos_side[xdf_disk_sector.id.h][xdf_disk_sector.id.r];
|
||||
buf_pos = img[drive].sector_pos[xdf_disk_sector.id.h][xdf_disk_sector.id.r];
|
||||
|
||||
// pclog("Side: %i, Position: %04X\n", buf_side, buf_pos);
|
||||
|
||||
id[0] = track;
|
||||
id[1] = xdf_disk_sector.id.h;
|
||||
id[2] = xdf_disk_sector.id.r;
|
||||
|
||||
if (is_t0)
|
||||
{
|
||||
id[3] = 2;
|
||||
// pclog("XDF Track 0: Registering sector: %i %i %i %i\n", id[0], id[1], id[2], id[3]);
|
||||
current_pos = d86f_prepare_sector(drive, side, current_pos, id, &img[drive].track_data[buf_side][buf_pos], ssize, img[drive].gap2_size, xdf_gap3_sizes[current_xdft][!is_t0], 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
id[3] = id[2] & 7;
|
||||
// pclog("XDF Track X: Registering sector: %i %i %i %i\n", id[0], id[1], id[2], id[3]);
|
||||
ssize = (128 << id[3]);
|
||||
current_pos = d86f_prepare_sector(drive, side, xdf_trackx_spos[current_xdft][array_sector], id, &img[drive].track_data[buf_side][buf_pos], ssize, img[drive].gap2_size, xdf_gap3_sizes[current_xdft][!is_t0], 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (side = img[drive].sides - 1; side >= 0; side--)
|
||||
{
|
||||
disc_sector_prepare_track_layout(drive, side, track);
|
||||
}
|
||||
|
||||
// pclog("Seeked to track: %i\n", img[drive].track);
|
||||
}
|
||||
|
||||
void img_writeback(int drive)
|
||||
{
|
||||
int side;
|
||||
int ssize = 128 << ((int) img[drive].sector_size);
|
||||
|
||||
if (!img[drive].f)
|
||||
return;
|
||||
|
||||
// if (img[drive].xdf_type)
|
||||
// return; /*Should never happen*/
|
||||
|
||||
if (img[drive].sides == 2)
|
||||
{
|
||||
fseek(img[drive].f, img[drive].base + (disc_track[drive] * img[drive].sectors * img[drive].sector_size * 2), SEEK_SET);
|
||||
fwrite(img[drive].track_data[0], img[drive].sectors * img[drive].sector_size, 1, img[drive].f);
|
||||
fwrite(img[drive].track_data[1], img[drive].sectors * img[drive].sector_size, 1, img[drive].f);
|
||||
}
|
||||
else
|
||||
{
|
||||
fseek(img[drive].f, img[drive].base + (disc_track[drive] * img[drive].sectors * img[drive].sector_size), SEEK_SET);
|
||||
fwrite(img[drive].track_data[0], img[drive].sectors * img[drive].sector_size, 1, img[drive].f);
|
||||
}
|
||||
fseek(img[drive].f, img[drive].base + (img[drive].track * img[drive].sectors * ssize * img[drive].sides), SEEK_SET);
|
||||
for (side = 0; side < img[drive].sides; side++)
|
||||
{
|
||||
fwrite(img[drive].track_data[side], img[drive].sectors * ssize, 1, img[drive].f);
|
||||
}
|
||||
}
|
||||
|
||||
int img_xdf_type(int drive)
|
||||
{
|
||||
return img[drive].xdf_type;
|
||||
}
|
||||
|
||||
uint16_t img_disk_flags(int drive)
|
||||
{
|
||||
return img[drive].disk_flags;
|
||||
}
|
||||
|
||||
uint16_t img_side_flags(int drive)
|
||||
{
|
||||
return img[drive].track_flags;
|
||||
}
|
||||
|
||||
void img_set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n)
|
||||
{
|
||||
img[drive].current_sector_pos_side = img[drive].sector_pos_side[h][r];
|
||||
img[drive].current_sector_pos = img[drive].sector_pos[h][r];
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t img_poll_read_data(int drive, int side, uint16_t pos)
|
||||
{
|
||||
return img[drive].track_data[img[drive].current_sector_pos_side][img[drive].current_sector_pos + pos];
|
||||
}
|
||||
|
||||
void img_poll_write_data(int drive, int side, uint16_t pos, uint8_t data)
|
||||
{
|
||||
img[drive].track_data[img[drive].current_sector_pos_side][img[drive].current_sector_pos + pos] = data;
|
||||
}
|
||||
|
||||
int img_format_conditions(int drive)
|
||||
{
|
||||
int temp = (fdc_get_format_sectors() == img[drive].sectors);
|
||||
temp = temp && (fdc_get_format_n() == img[drive].sector_size);
|
||||
temp = temp && (img[drive].xdf_type == 0);
|
||||
return temp;
|
||||
}
|
||||
|
||||
void d86f_register_img(int drive)
|
||||
{
|
||||
d86f_handler[drive].disk_flags = img_disk_flags;
|
||||
d86f_handler[drive].side_flags = img_side_flags;
|
||||
d86f_handler[drive].writeback = img_writeback;
|
||||
d86f_handler[drive].set_sector = img_set_sector;
|
||||
d86f_handler[drive].write_data = img_poll_write_data;
|
||||
d86f_handler[drive].format_conditions = img_format_conditions;
|
||||
d86f_handler[drive].extra_bit_cells = null_extra_bit_cells;
|
||||
d86f_handler[drive].encoded_data = common_encoded_data;
|
||||
d86f_handler[drive].read_revolution = common_read_revolution;
|
||||
d86f_handler[drive].index_hole_pos = null_index_hole_pos;
|
||||
d86f_handler[drive].get_raw_size = common_get_raw_size;
|
||||
d86f_handler[drive].check_crc = 1;
|
||||
}
|
||||
|
||||
@@ -1,603 +0,0 @@
|
||||
/* Copyright holders: Sarah Walker, Tenshi
|
||||
see COPYING for more details
|
||||
*/
|
||||
#include "ibm.h"
|
||||
#include "fdc.h"
|
||||
#include "fdd.h"
|
||||
#include "disc.h"
|
||||
#include "disc_img.h"
|
||||
|
||||
static struct
|
||||
{
|
||||
FILE *f;
|
||||
uint8_t track_data[2][50000];
|
||||
int sectors, tracks, sides;
|
||||
uint8_t sector_size;
|
||||
int rate;
|
||||
int xdf_type; /* 0 = not XDF, 1-5 = one of the five XDF types */
|
||||
int dmf;
|
||||
int hole;
|
||||
int track;
|
||||
uint32_t base;
|
||||
uint8_t gap2_size;
|
||||
uint8_t gap3_size;
|
||||
uint16_t disk_flags;
|
||||
uint16_t track_flags;
|
||||
uint8_t sector_pos_side[2][256];
|
||||
uint16_t sector_pos[2][256];
|
||||
uint8_t current_sector_pos_side;
|
||||
uint16_t current_sector_pos;
|
||||
} img[2];
|
||||
|
||||
uint8_t dmf_r[21] = { 12, 2, 13, 3, 14, 4, 15, 5, 16, 6, 17, 7, 18, 8, 19, 9, 20, 10, 21, 11, 1 };
|
||||
static uint8_t xdf_spt[2] = { 6, 8 };
|
||||
static uint8_t xdf_logical_sectors[2][2] = { { 38, 6 }, { 46, 8 } };
|
||||
uint8_t xdf_physical_sectors[2][2] = { { 16, 3 }, { 19, 4 } };
|
||||
uint8_t xdf_gap3_sizes[2][2] = { { 60, 69 }, { 60, 50 } };
|
||||
uint16_t xdf_trackx_spos[2][8] = { { 0xA7F, 0xF02, 0x11B7, 0xB66, 0xE1B, 0x129E }, { 0x302, 0x7E2, 0xA52, 0x12DA, 0x572, 0xDFA, 0x106A, 0x154A } };
|
||||
|
||||
/* XDF: Layout of the sectors in the image. */
|
||||
xdf_sector_t xdf_img_layout[2][2][46] = { { { 0x8100, 0x8200, 0x8300, 0x8400, 0x8500, 0x8600, 0x8700, 0x8800,
|
||||
0x8101, 0x8201, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600,
|
||||
0x0700, 0x0800, 0,
|
||||
0x8301, 0x8401, 0x8501, 0x8601, 0x8701, 0x8801, 0x8901, 0x8A01,
|
||||
0x8B01, 0x8C01, 0x8D01, 0x8E01, 0x8F01, 0x9001, 0, 0,
|
||||
0, 0, 0 },
|
||||
{ 0x8300, 0x8600, 0x8201, 0x8200, 0x8601, 0x8301 }
|
||||
}, /* 5.25" 2HD */
|
||||
{ { 0x8100, 0x8200, 0x8300, 0x8400, 0x8500, 0x8600, 0x8700, 0x8800,
|
||||
0x8900, 0x8A00, 0x8B00, 0x8101, 0x0100, 0x0200, 0x0300, 0x0400,
|
||||
0x0500, 0x0600, 0x0700, 0x0800, 0, 0, 0,
|
||||
0x8201, 0x8301, 0x8401, 0x8501, 0x8601, 0x8701, 0x8801, 0x8901,
|
||||
0x8A01, 0x8B01, 0x8C01, 0x8D01, 0x8E01, 0x8F01, 0, 0,
|
||||
0, 0, 0, 0x9001, 0x9101, 0x9201, 0x9301 },
|
||||
{ 0x8300, 0x8400, 0x8601, 0x8200, 0x8201, 0x8600, 0x8401, 0x8301 }
|
||||
} /* 3.5" 2HD */
|
||||
};
|
||||
|
||||
/* XDF: Layout of the sectors on the disk's track. */
|
||||
xdf_sector_t xdf_disk_layout[2][2][38] = { { { 0x0100, 0x0200, 0x8100, 0x8800, 0x8200, 0x0300, 0x8300, 0x0400,
|
||||
0x8400, 0x0500, 0x8500, 0x0600, 0x8600, 0x0700, 0x8700, 0x0800,
|
||||
0x8D01, 0x8501, 0x8E01, 0x8601, 0x8F01, 0x8701, 0x9001, 0x8801,
|
||||
0x8101, 0x8901, 0x8201, 0x8A01, 0x8301, 0x8B01, 0x8401, 0x8C01 },
|
||||
{ 0x8300, 0x8200, 0x8600, 0x8201, 0x8301, 0x8601 }
|
||||
}, /* 5.25" 2HD */
|
||||
{ { 0x0100, 0x8A00, 0x8100, 0x8B00, 0x8200, 0x0200, 0x8300, 0x0300,
|
||||
0x8400, 0x0400, 0x8500, 0x0500, 0x8600, 0x0600, 0x8700, 0x0700,
|
||||
0x8800, 0x0800, 0x8900,
|
||||
0x9001, 0x8701, 0x9101, 0x8801, 0x9201, 0x8901, 0x9301, 0x8A01,
|
||||
0x8101, 0x8B01, 0x8201, 0x8C01, 0x8301, 0x8D01, 0x8401, 0x8E01,
|
||||
0x8501, 0x8F01, 0x8601 },
|
||||
{ 0x8300, 0x8200, 0x8400, 0x8600, 0x8401, 0x8201, 0x8301, 0x8601 },
|
||||
}, /* 3.5" 2HD */
|
||||
};
|
||||
|
||||
/* First dimension is possible sector sizes (0 = 128, 7 = 16384), second is possible bit rates (250/360, 250, 300, 500/360, 500, 1000). */
|
||||
/* Disks formatted at 250 kbps @ 360 RPM can be read with a 360 RPM single-RPM 5.25" drive by setting the rate to 250 kbps.
|
||||
Disks formatted at 300 kbps @ 300 RPM can be read with any 300 RPM single-RPM drive by setting the rate rate to 300 kbps. */
|
||||
static uint8_t maximum_sectors[8][6] = { { 26, 31, 38, 53, 64, 118 }, /* 128 */
|
||||
{ 15, 19, 23, 32, 38, 73 }, /* 256 */
|
||||
{ 7, 10, 12, 17, 21, 41 }, /* 512 */
|
||||
{ 3, 5, 6, 9, 11, 22 }, /* 1024 */
|
||||
{ 2, 2, 3, 4, 5, 11 }, /* 2048 */
|
||||
{ 1, 1, 1, 2, 2, 5 }, /* 4096 */
|
||||
{ 0, 0, 0, 1, 1, 3 }, /* 8192 */
|
||||
{ 0, 0, 0, 0, 0, 1 } }; /* 16384 */
|
||||
|
||||
static uint8_t xdf_sectors[8][6] = { { 0, 0, 0, 0, 0, 0 }, /* 128 */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* 256 */
|
||||
{ 0, 0, 0, 19, 23, 0 }, /* 512 */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* 1024 */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* 2048 */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* 4096 */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* 8192 */
|
||||
{ 0, 0, 0, 0, 0, 0 } }; /* 16384 */
|
||||
|
||||
static uint8_t xdf_types[8][6] = { { 0, 0, 0, 0, 0, 0 }, /* 128 */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* 256 */
|
||||
{ 0, 0, 0, 1, 2, 0 }, /* 512 */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* 1024 */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* 2048 */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* 4096 */
|
||||
{ 0, 0, 0, 0, 0, 0 }, /* 8192 */
|
||||
{ 0, 0, 0, 0, 0, 0 } }; /* 16384 */
|
||||
|
||||
static double bit_rates_300[6] = { (250.0 * 300.0) / 360.0, 250.0, 300.0, (500.0 * 300.0) / 360.0, 500.0, 1000.0 };
|
||||
|
||||
static uint8_t rates[6] = { 2, 2, 1, 4, 0, 3 };
|
||||
|
||||
static uint8_t holes[6] = { 0, 0, 0, 1, 1, 2 };
|
||||
|
||||
int gap3_sizes[5][8][256] = { [0][1][16] = 0x54,
|
||||
[0][2][18] = 0x6C,
|
||||
[0][2][19] = 0x48,
|
||||
[0][2][20] = 0x2A,
|
||||
[0][2][21] = 0x08, /* Microsoft DMFWRITE.EXE uses this, 0x0C is used by FDFORMAT. */
|
||||
[0][2][23] = 0x01,
|
||||
[0][3][10] = 0x83,
|
||||
[0][3][11] = 0x26,
|
||||
[1][2][11] = 0x54,
|
||||
[1][2][12] = 0x1C,
|
||||
[1][2][13] = 0x0E,
|
||||
[1][3][6] = 0x79,
|
||||
[1][3][7] = 0x06,
|
||||
[2][1][10] = 0x32,
|
||||
[2][1][11] = 0x0C,
|
||||
[2][1][15] = 0x36,
|
||||
[2][1][16] = 0x32,
|
||||
[2][2][8] = 0x58,
|
||||
[2][2][9] = 0x50,
|
||||
[2][2][10] = 0x2E,
|
||||
[2][2][21] = 0x1C,
|
||||
[2][3][4] = 0xF0,
|
||||
[2][3][5] = 0x74,
|
||||
[3][2][36] = 0x53,
|
||||
[3][2][37] = 0x4E,
|
||||
[3][2][38] = 0x40,
|
||||
[3][2][39] = 0x30,
|
||||
[3][2][40] = 0x20,
|
||||
[3][2][41] = 0x10,
|
||||
[3][2][46] = 0x01,
|
||||
[3][3][18] = 0xF7,
|
||||
[3][3][19] = 0xAF,
|
||||
[3][3][20] = 0x6F,
|
||||
[3][3][21] = 0x55,
|
||||
[3][3][22] = 0x1F,
|
||||
[4][1][32] = 0x36,
|
||||
[4][2][14] = 0x92,
|
||||
[4][2][15] = 0x54,
|
||||
[4][2][16] = 0x38,
|
||||
[4][2][17] = 0x23,
|
||||
[4][2][19] = 0x01,
|
||||
[4][3][8] = 0x74,
|
||||
[4][3][9] = 0x24
|
||||
};
|
||||
|
||||
void img_writeback(int drive);
|
||||
|
||||
static int sector_size_code(int sector_size)
|
||||
{
|
||||
switch(sector_size)
|
||||
{
|
||||
case 128:
|
||||
return 0;
|
||||
case 256:
|
||||
return 1;
|
||||
default:
|
||||
case 512:
|
||||
return 2;
|
||||
case 1024:
|
||||
return 3;
|
||||
case 2048:
|
||||
return 4;
|
||||
case 4096:
|
||||
return 5;
|
||||
case 8192:
|
||||
return 6;
|
||||
case 16384:
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
|
||||
static int img_sector_size_code(int drive)
|
||||
{
|
||||
return sector_size_code(img[drive].sector_size);
|
||||
}
|
||||
|
||||
void img_init()
|
||||
{
|
||||
memset(img, 0, sizeof(img));
|
||||
// adl[0] = adl[1] = 0;
|
||||
}
|
||||
|
||||
void d86f_register_img(int drive);
|
||||
|
||||
void img_load(int drive, char *fn)
|
||||
{
|
||||
int size;
|
||||
double bit_rate_300;
|
||||
uint16_t bpb_bps;
|
||||
uint16_t bpb_total;
|
||||
uint8_t bpb_mid; /* Media type ID. */
|
||||
uint8_t bpb_sectors;
|
||||
uint8_t bpb_sides;
|
||||
uint32_t bpt;
|
||||
uint8_t max_spt; /* Used for XDF detection. */
|
||||
int temp_rate;
|
||||
char ext[4];
|
||||
int fdi;
|
||||
int i;
|
||||
|
||||
ext[0] = fn[strlen(fn) - 3] | 0x60;
|
||||
ext[1] = fn[strlen(fn) - 2] | 0x60;
|
||||
ext[2] = fn[strlen(fn) - 1] | 0x60;
|
||||
ext[3] = 0;
|
||||
|
||||
d86f_unregister(drive);
|
||||
|
||||
writeprot[drive] = 0;
|
||||
img[drive].f = fopen(fn, "rb+");
|
||||
if (!img[drive].f)
|
||||
{
|
||||
img[drive].f = fopen(fn, "rb");
|
||||
if (!img[drive].f)
|
||||
return;
|
||||
writeprot[drive] = 1;
|
||||
}
|
||||
if (ui_writeprot[drive])
|
||||
{
|
||||
writeprot[drive] = 1;
|
||||
}
|
||||
fwriteprot[drive] = writeprot[drive];
|
||||
|
||||
if (strcmp(ext, "fdi") == 0)
|
||||
{
|
||||
/* This is a Japanese FDI image, so let's read the header */
|
||||
pclog("img_load(): File is a Japanese FDI image...\n");
|
||||
fseek(img[drive].f, 0x10, SEEK_SET);
|
||||
fread(&bpb_bps, 1, 2, img[drive].f);
|
||||
fseek(img[drive].f, 0x0C, SEEK_SET);
|
||||
fread(&size, 1, 4, img[drive].f);
|
||||
bpb_total = size / bpb_bps;
|
||||
fseek(img[drive].f, 0x08, SEEK_SET);
|
||||
fread(&(img[drive].base), 1, 4, img[drive].f);
|
||||
fseek(img[drive].f, img[drive].base + 0x15, SEEK_SET);
|
||||
bpb_mid = fgetc(img[drive].f);
|
||||
if (bpb_mid < 0xF0) bpb_mid = 0xF0;
|
||||
fseek(img[drive].f, 0x14, SEEK_SET);
|
||||
bpb_sectors = fgetc(img[drive].f);
|
||||
fseek(img[drive].f, 0x18, SEEK_SET);
|
||||
bpb_sides = fgetc(img[drive].f);
|
||||
|
||||
fdi = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read the BPB */
|
||||
pclog("img_load(): File is a raw image...\n");
|
||||
fseek(img[drive].f, 0x0B, SEEK_SET);
|
||||
fread(&bpb_bps, 1, 2, img[drive].f);
|
||||
fseek(img[drive].f, 0x13, SEEK_SET);
|
||||
fread(&bpb_total, 1, 2, img[drive].f);
|
||||
fseek(img[drive].f, 0x15, SEEK_SET);
|
||||
bpb_mid = fgetc(img[drive].f);
|
||||
fseek(img[drive].f, 0x18, SEEK_SET);
|
||||
bpb_sectors = fgetc(img[drive].f);
|
||||
fseek(img[drive].f, 0x1A, SEEK_SET);
|
||||
bpb_sides = fgetc(img[drive].f);
|
||||
|
||||
img[drive].base = 0;
|
||||
fdi = 0;
|
||||
|
||||
fseek(img[drive].f, -1, SEEK_END);
|
||||
size = ftell(img[drive].f) + 1;
|
||||
}
|
||||
|
||||
img[drive].sides = 2;
|
||||
img[drive].sector_size = 2;
|
||||
|
||||
img[drive].hole = 0;
|
||||
|
||||
pclog("BPB reports %i sides and %i bytes per sector\n", bpb_sides, bpb_bps);
|
||||
|
||||
if (((bpb_sides < 1) || (bpb_sides > 2) || (bpb_bps < 128) || (bpb_bps > 2048)) && !fdi)
|
||||
{
|
||||
/* The BPB is giving us a wacky number of sides and/or bytes per sector, therefore it is most probably
|
||||
not a BPB at all, so we have to guess the parameters from file size. */
|
||||
|
||||
if (size <= (160*1024)) { img[drive].sectors = 8; img[drive].tracks = 40; img[drive].sides = 1; }
|
||||
else if (size <= (180*1024)) { img[drive].sectors = 9; img[drive].tracks = 40; img[drive].sides = 1; }
|
||||
else if (size <= (320*1024)) { img[drive].sectors = 8; img[drive].tracks = 40; }
|
||||
else if (size <= (360*1024)) { img[drive].sectors = 9; img[drive].tracks = 40; } /*Double density*/
|
||||
else if (size <= (400*1024)) { img[drive].sectors = 10; img[drive].tracks = 80; img[drive].sides = 1; } /*DEC RX50*/
|
||||
else if (size <= (640*1024)) { img[drive].sectors = 8; img[drive].tracks = 80; } /*Double density 640k*/
|
||||
else if (size <= (720*1024)) { img[drive].sectors = 9; img[drive].tracks = 80; } /*Double density*/
|
||||
else if (size <= (800*1024)) { img[drive].sectors = 10; img[drive].tracks = 80; } /*Double density*/
|
||||
else if (size <= (880*1024)) { img[drive].sectors = 11; img[drive].tracks = 80; } /*Double density*/
|
||||
else if (size <= (960*1024)) { img[drive].sectors = 12; img[drive].tracks = 80; } /*Double density*/
|
||||
else if (size <= (1040*1024)) { img[drive].sectors = 13; img[drive].tracks = 80; } /*Double density*/
|
||||
else if (size <= (1120*1024)) { img[drive].sectors = 14; img[drive].tracks = 80; } /*Double density*/
|
||||
else if (size <= 1228800) { img[drive].sectors = 15; img[drive].tracks = 80; } /*High density 1.2MB*/
|
||||
else if (size <= 1261568) { img[drive].sectors = 8; img[drive].tracks = 77; img[drive].sector_size = 3; } /*High density 1.25MB Japanese format*/
|
||||
else if (size <= (0x1A4000-1)) { img[drive].sectors = 18; img[drive].tracks = 80; } /*High density (not supported by Tandy 1000)*/
|
||||
else if (size <= 1556480) { img[drive].sectors = 19; img[drive].tracks = 80; } /*High density (not supported by Tandy 1000)*/
|
||||
else if (size <= 1638400) { img[drive].sectors = 10; img[drive].tracks = 80; img[drive].sector_size = 3; } /*High density (not supported by Tandy 1000)*/
|
||||
else if (size <= 1720320) { img[drive].sectors = 21; img[drive].tracks = 80; } /*DMF format - used by Windows 95 */
|
||||
else if (size <= 1741824) { img[drive].sectors = 21; img[drive].tracks = 81; }
|
||||
else if (size <= 1763328) { img[drive].sectors = 21; img[drive].tracks = 82; }
|
||||
else if (size <= 1802240) { img[drive].sectors = 11; img[drive].tracks = 80; img[drive].sector_size = 3; } /*High density (not supported by Tandy 1000)*/
|
||||
else if (size == 1884160) { img[drive].sectors = 23; img[drive].tracks = 80; } /*XDF format - used by OS/2 Warp*/
|
||||
else if (size <= 2949120) { img[drive].sectors = 36; img[drive].tracks = 80; } /*E density*/
|
||||
else if (size <= 3194880) { img[drive].sectors = 39; img[drive].tracks = 80; } /*E density*/
|
||||
else if (size <= 3276800) { img[drive].sectors = 40; img[drive].tracks = 80; } /*E density*/
|
||||
else if (size <= 3358720) { img[drive].sectors = 41; img[drive].tracks = 80; } /*E density, maximum possible size*/
|
||||
else if (size <= 3440640) { img[drive].sectors = 21; img[drive].tracks = 80; img[drive].sector_size = 3; } /*High density (not supported by Tandy 1000)*/
|
||||
else if (size <= 3604480) { img[drive].sectors = 22; img[drive].tracks = 80; img[drive].sector_size = 3; } /*High density (not supported by Tandy 1000)*/
|
||||
else
|
||||
{
|
||||
pclog("Image is bigger than can fit on an ED floppy, ejecting...\n");
|
||||
fclose(img[drive].f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The BPB readings appear to be valid, so let's set the values. */
|
||||
if (fdi)
|
||||
{
|
||||
/* The image is a Japanese FDI, therefore we read the number of tracks from the header. */
|
||||
fseek(img[drive].f, 0x1C, SEEK_SET);
|
||||
fread(&(img[drive].tracks), 1, 4, img[drive].f);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Number of tracks = number of total sectors divided by sides times sectors per track. */
|
||||
img[drive].tracks = ((uint32_t) bpb_total) / (((uint32_t) bpb_sides) * ((uint32_t) bpb_sectors));
|
||||
}
|
||||
/* The rest we just set directly from the BPB. */
|
||||
img[drive].sectors = bpb_sectors;
|
||||
img[drive].sides = bpb_sides;
|
||||
/* The sector size. */
|
||||
img[drive].sector_size = sector_size_code(bpb_bps);
|
||||
|
||||
temp_rate = 0xFF;
|
||||
}
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
if ((img[drive].sectors <= maximum_sectors[img[drive].sector_size][i]) || (img[drive].sectors == xdf_sectors[img[drive].sector_size][i]))
|
||||
{
|
||||
bit_rate_300 = bit_rates_300[i];
|
||||
temp_rate = rates[i];
|
||||
img[drive].disk_flags = holes[i] << 1;
|
||||
img[drive].xdf_type = (img[drive].sectors == xdf_sectors[img[drive].sector_size][i]) ? xdf_types[img[drive].sector_size][i] : 0;
|
||||
if ((bit_rate_300 == 500.0) && (img[drive].sectors == 21) && (img[drive].sector_size == 2) && (img[drive].tracks >= 80) && (img[drive].tracks <= 82) && (img[drive].sides == 2))
|
||||
{
|
||||
/* This is a DMF floppy, set the flag so we know to interleave the sectors. */
|
||||
img[drive].dmf = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
img[drive].dmf = 0;
|
||||
}
|
||||
|
||||
pclog("Image parameters: bit rate 300: %f, temporary rate: %i, hole: %i, DMF: %i, XDF type: %i\n", bit_rate_300, temp_rate, img[drive].disk_flags >> 1, img[drive].dmf, img[drive].xdf_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (temp_rate == 0xFF)
|
||||
{
|
||||
pclog("Image is bigger than can fit on an ED floppy, ejecting...\n");
|
||||
fclose(img[drive].f);
|
||||
return;
|
||||
}
|
||||
|
||||
img[drive].gap2_size = (temp_rate == 3) ? 41 : 22;
|
||||
if (img[drive].dmf)
|
||||
{
|
||||
img[drive].gap3_size = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
img[drive].gap3_size = gap3_sizes[temp_rate][img[drive].sector_size][img[drive].sectors];
|
||||
}
|
||||
if (!img[drive].gap3_size)
|
||||
{
|
||||
pclog("ERROR: Floppy image of unknown format was inserted into drive %c:!\n", drive + 0x41);
|
||||
fclose(img[drive].f);
|
||||
return;
|
||||
}
|
||||
|
||||
if (img[drive].tracks > 43) img[drive].disk_flags |= 1; /* If the image has more than 43 tracks, then the tracks are thin (96 tpi). */
|
||||
if (img[drive].sides == 2) img[drive].disk_flags |= 8; /* If the has 2 sides, mark it as such. */
|
||||
|
||||
img[drive].track_flags = 0x08; /* IMG files are always assumed to be MFM-encoded. */
|
||||
img[drive].track_flags |= temp_rate & 3; /* Data rate. */
|
||||
if (temp_rate & 4) img[drive].track_flags |= 0x20; /* RPM. */
|
||||
|
||||
pclog("Disk flags: %i, track flags: %i\n", img[drive].disk_flags, img[drive].track_flags);
|
||||
|
||||
d86f_register_img(drive);
|
||||
|
||||
drives[drive].seek = img_seek;
|
||||
|
||||
d86f_common_handlers(drive);
|
||||
}
|
||||
|
||||
void img_close(int drive)
|
||||
{
|
||||
d86f_unregister(drive);
|
||||
if (img[drive].f)
|
||||
fclose(img[drive].f);
|
||||
img[drive].f = NULL;
|
||||
}
|
||||
|
||||
#define xdf_img_sector xdf_img_layout[current_xdft][!is_t0][sector]
|
||||
#define xdf_disk_sector xdf_disk_layout[current_xdft][!is_t0][array_sector]
|
||||
|
||||
void img_seek(int drive, int track)
|
||||
{
|
||||
int side;
|
||||
int current_xdft = img[drive].xdf_type - 1;
|
||||
|
||||
uint8_t id[4] = { 0, 0, 0, 0 };
|
||||
|
||||
int is_t0, sector, current_pos, img_pos, sh, sr, sn, sside, total, max_pos, bytes, array_sector, buf_side, buf_pos;
|
||||
|
||||
int ssize = 128 << ((int) img[drive].sector_size);
|
||||
|
||||
if (!img[drive].f)
|
||||
return;
|
||||
|
||||
if (d86f_is_40_track(drive) && fdd_doublestep_40(drive))
|
||||
track /= 2;
|
||||
|
||||
img[drive].track = track;
|
||||
|
||||
is_t0 = (track == 0) ? 1 : 0;
|
||||
|
||||
fseek(img[drive].f, img[drive].base + (track * img[drive].sectors * ssize * img[drive].sides), SEEK_SET);
|
||||
for (side = 0; side < img[drive].sides; side++)
|
||||
{
|
||||
fread(img[drive].track_data[side], img[drive].sectors * ssize, 1, img[drive].f);
|
||||
}
|
||||
|
||||
d86f_reset_index_hole_pos(drive, 0);
|
||||
d86f_reset_index_hole_pos(drive, 1);
|
||||
|
||||
if (!img[drive].xdf_type)
|
||||
{
|
||||
for (side = 0; side < img[drive].sides; side++)
|
||||
{
|
||||
current_pos = d86f_prepare_pretrack(drive, side, 0, 1);
|
||||
|
||||
for (sector = 0; sector < img[drive].sectors; sector++)
|
||||
{
|
||||
sr = img[drive].dmf ? (dmf_r[sector]) : (sector + 1);
|
||||
id[0] = track;
|
||||
id[1] = side;
|
||||
id[2] = sr;
|
||||
id[3] = img[drive].sector_size;
|
||||
img[drive].sector_pos_side[side][sr] = side;
|
||||
img[drive].sector_pos[side][sr] = (sr - 1) * ssize;
|
||||
// if (img[drive].dmf) pclog("DMF: %i %i %i %i | %i %04X\n", id[0], id[1], id[2], id[3], side, (sr - 1) * ssize);
|
||||
current_pos = d86f_prepare_sector(drive, side, current_pos, id, &img[drive].track_data[side][(sr - 1) * ssize], ssize, 1, img[drive].gap2_size, img[drive].gap3_size, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
total = img[drive].sectors;
|
||||
img_pos = 0;
|
||||
sside = 0;
|
||||
|
||||
/* Pass 1, get sector positions in the image. */
|
||||
for (sector = 0; sector < xdf_logical_sectors[current_xdft][!is_t0]; sector++)
|
||||
{
|
||||
if (is_t0)
|
||||
{
|
||||
img_pos = (sector % total) << 9;
|
||||
sside = (sector >= total) ? 1 : 0;
|
||||
}
|
||||
|
||||
if (xdf_img_sector.word)
|
||||
{
|
||||
img[drive].sector_pos_side[xdf_img_sector.id.h][xdf_img_sector.id.r] = sside;
|
||||
img[drive].sector_pos[xdf_img_sector.id.h][xdf_img_sector.id.r] = img_pos;
|
||||
// pclog("Side: %i, Position: %04X\n", sside, img_pos);
|
||||
}
|
||||
|
||||
if (!is_t0)
|
||||
{
|
||||
img_pos += (128 << (xdf_img_sector.id.r & 7));
|
||||
if (img_pos >= (total << 9)) sside = 1;
|
||||
img_pos %= (total << 9);
|
||||
}
|
||||
}
|
||||
|
||||
/* Pass 2, prepare the actual track. */
|
||||
for (side = 0; side < img[drive].sides; side++)
|
||||
{
|
||||
current_pos = d86f_prepare_pretrack(drive, side, 0, 1);
|
||||
|
||||
for (sector = 0; sector < xdf_physical_sectors[current_xdft][!is_t0]; sector++)
|
||||
{
|
||||
array_sector = (side * xdf_physical_sectors[current_xdft][!is_t0]) + sector;
|
||||
// pclog("Sector %i, array sector %i\n", sector, array_sector);
|
||||
|
||||
buf_side = img[drive].sector_pos_side[xdf_disk_sector.id.h][xdf_disk_sector.id.r];
|
||||
buf_pos = img[drive].sector_pos[xdf_disk_sector.id.h][xdf_disk_sector.id.r];
|
||||
|
||||
// pclog("Side: %i, Position: %04X\n", buf_side, buf_pos);
|
||||
|
||||
id[0] = track;
|
||||
id[1] = xdf_disk_sector.id.h;
|
||||
id[2] = xdf_disk_sector.id.r;
|
||||
|
||||
if (is_t0)
|
||||
{
|
||||
id[3] = 2;
|
||||
// pclog("XDF Track 0: Registering sector: %i %i %i %i\n", id[0], id[1], id[2], id[3]);
|
||||
current_pos = d86f_prepare_sector(drive, side, current_pos, id, &img[drive].track_data[buf_side][buf_pos], ssize, 1, img[drive].gap2_size, xdf_gap3_sizes[current_xdft][!is_t0], 0, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
id[3] = id[2] & 7;
|
||||
// pclog("XDF Track X: Registering sector: %i %i %i %i\n", id[0], id[1], id[2], id[3]);
|
||||
ssize = (128 << id[3]);
|
||||
current_pos = d86f_prepare_sector(drive, side, xdf_trackx_spos[current_xdft][array_sector], id, &img[drive].track_data[buf_side][buf_pos], ssize, 1, img[drive].gap2_size, xdf_gap3_sizes[current_xdft][!is_t0], 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pclog("Seeked to track: %i\n", img[drive].track);
|
||||
}
|
||||
|
||||
void img_writeback(int drive)
|
||||
{
|
||||
int side;
|
||||
int ssize = 128 << ((int) img[drive].sector_size);
|
||||
|
||||
if (!img[drive].f)
|
||||
return;
|
||||
|
||||
fseek(img[drive].f, img[drive].base + (img[drive].track * img[drive].sectors * ssize * img[drive].sides), SEEK_SET);
|
||||
for (side = 0; side < img[drive].sides; side++)
|
||||
{
|
||||
fwrite(img[drive].track_data[side], img[drive].sectors * ssize, 1, img[drive].f);
|
||||
}
|
||||
}
|
||||
|
||||
int img_xdf_type(int drive)
|
||||
{
|
||||
return img[drive].xdf_type;
|
||||
}
|
||||
|
||||
uint16_t img_disk_flags(int drive)
|
||||
{
|
||||
return img[drive].disk_flags;
|
||||
}
|
||||
|
||||
uint16_t img_side_flags(int drive)
|
||||
{
|
||||
return img[drive].track_flags;
|
||||
}
|
||||
|
||||
void img_set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n)
|
||||
{
|
||||
img[drive].current_sector_pos_side = img[drive].sector_pos_side[h][r];
|
||||
img[drive].current_sector_pos = img[drive].sector_pos[h][r];
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t img_poll_read_data(int drive, int side, uint16_t pos)
|
||||
{
|
||||
return img[drive].track_data[img[drive].current_sector_pos_side][img[drive].current_sector_pos + pos];
|
||||
}
|
||||
|
||||
void img_poll_write_data(int drive, int side, uint16_t pos, uint8_t data)
|
||||
{
|
||||
img[drive].track_data[img[drive].current_sector_pos_side][img[drive].current_sector_pos + pos] = data;
|
||||
}
|
||||
|
||||
int img_format_conditions(int drive)
|
||||
{
|
||||
int temp = (fdc_get_format_sectors() == img[drive].sectors);
|
||||
temp = temp && (fdc_get_format_n() == img[drive].sector_size);
|
||||
temp = temp && (img[drive].xdf_type == 0);
|
||||
return temp;
|
||||
}
|
||||
|
||||
void d86f_register_img(int drive)
|
||||
{
|
||||
d86f_handler[drive].disk_flags = img_disk_flags;
|
||||
d86f_handler[drive].side_flags = img_side_flags;
|
||||
d86f_handler[drive].writeback = img_writeback;
|
||||
d86f_handler[drive].set_sector = img_set_sector;
|
||||
d86f_handler[drive].read_data = img_poll_read_data;
|
||||
d86f_handler[drive].write_data = img_poll_write_data;
|
||||
d86f_handler[drive].format_conditions = img_format_conditions;
|
||||
d86f_handler[drive].check_crc = 1;
|
||||
}
|
||||
@@ -1,463 +0,0 @@
|
||||
/* Copyright holders: Sarah Walker, Tenshi
|
||||
see COPYING for more details
|
||||
*/
|
||||
#include "ibm.h"
|
||||
#include "disc.h"
|
||||
#include "disc_sector.h"
|
||||
#include "fdd.h"
|
||||
|
||||
/*Handling for 'sector based' image formats (like .IMG) as opposed to 'stream based' formats (eg .FDI)*/
|
||||
|
||||
#define MAX_SECTORS 256
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t c, h, r, n;
|
||||
int rate;
|
||||
uint8_t *data;
|
||||
} sector_t;
|
||||
|
||||
static sector_t disc_sector_data[2][2][MAX_SECTORS];
|
||||
static int disc_sector_count[2][2];
|
||||
void (*disc_sector_writeback[2])(int drive);
|
||||
|
||||
enum
|
||||
{
|
||||
STATE_IDLE,
|
||||
STATE_READ_FIND_SECTOR,
|
||||
STATE_READ_SECTOR,
|
||||
STATE_READ_FIND_FIRST_SECTOR,
|
||||
STATE_READ_FIRST_SECTOR,
|
||||
STATE_READ_FIND_NEXT_SECTOR,
|
||||
STATE_READ_NEXT_SECTOR,
|
||||
STATE_WRITE_FIND_SECTOR,
|
||||
STATE_WRITE_SECTOR,
|
||||
STATE_READ_FIND_ADDRESS,
|
||||
STATE_READ_ADDRESS,
|
||||
STATE_FORMAT_FIND,
|
||||
STATE_FORMAT
|
||||
};
|
||||
|
||||
static int disc_sector_state[2] = {0, 0};
|
||||
static int disc_sector_track[2] = {0, 0};
|
||||
static int disc_sector_side[2] = {0, 0};
|
||||
static int disc_sector_drive;
|
||||
static int disc_sector_sector[2] = {0, 0};
|
||||
static int disc_sector_n[2] = {0, 0};
|
||||
static int disc_intersector_delay[2] = {0, 0};
|
||||
static int disc_postdata_delay[2] = {0, 0};
|
||||
static int disc_track_delay[2] = {0, 0};
|
||||
static int disc_gap4_delay[2] = {0, 0};
|
||||
static uint8_t disc_sector_fill[2] = {0, 0};
|
||||
static int cur_sector[2], cur_byte[2];
|
||||
static int index_count[2];
|
||||
|
||||
int raw_tsize[2] = {6250, 6250};
|
||||
int gap2_size[2] = {22, 22};
|
||||
int gap3_size[2] = {0, 0};
|
||||
int gap4_size[2] = {0, 0};
|
||||
|
||||
void disc_sector_reset(int drive, int side)
|
||||
{
|
||||
disc_sector_count[drive][side] = 0;
|
||||
|
||||
disc_intersector_delay[drive] = 0;
|
||||
disc_postdata_delay[drive] = 0;
|
||||
disc_track_delay[drive] = 0;
|
||||
disc_gap4_delay[drive] = 0;
|
||||
cur_sector[drive] = 0;
|
||||
cur_byte[drive] = 0;
|
||||
index_count[drive] = 0;
|
||||
}
|
||||
|
||||
void disc_sector_add(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n, int rate, uint8_t *data)
|
||||
{
|
||||
sector_t *s = &disc_sector_data[drive][side][disc_sector_count[drive][side]];
|
||||
//pclog("disc_sector_add: drive=%i side=%i %i r=%i\n", drive, side, disc_sector_count[drive][side],r );
|
||||
if (disc_sector_count[drive][side] >= MAX_SECTORS)
|
||||
return;
|
||||
|
||||
s->c = c;
|
||||
s->h = h;
|
||||
s->r = r;
|
||||
s->n = n;
|
||||
s->rate = rate;
|
||||
s->data = data;
|
||||
|
||||
disc_sector_count[drive][side]++;
|
||||
}
|
||||
|
||||
static int get_bitcell_period(int drive)
|
||||
{
|
||||
return (disc_sector_data[drive][disc_sector_side[drive]][cur_sector[drive]].rate * 300) / fdd_getrpm(drive);
|
||||
}
|
||||
|
||||
void disc_sector_readsector(int drive, int sector, int track, int side, int rate, int sector_size)
|
||||
{
|
||||
pclog("disc_sector_readsector: fdc_period=%i img_period=%i rate=%i sector=%i track=%i side=%i\n", fdc_get_bitcell_period(), get_bitcell_period(drive), rate, sector, track, side);
|
||||
|
||||
disc_sector_track[drive] = track;
|
||||
disc_sector_side[drive] = side;
|
||||
disc_sector_drive = drive;
|
||||
disc_sector_sector[drive] = sector;
|
||||
disc_sector_n[drive] = sector_size;
|
||||
if ((cur_sector[drive] == 0) && (cur_byte[drive] == 0) && !disc_track_delay[drive]) disc_track_delay[drive] = pre_track;
|
||||
index_count[drive] = 0;
|
||||
if (sector == SECTOR_FIRST)
|
||||
disc_sector_state[drive] = STATE_READ_FIND_FIRST_SECTOR;
|
||||
else if (sector == SECTOR_NEXT)
|
||||
disc_sector_state[drive] = STATE_READ_FIND_NEXT_SECTOR;
|
||||
else
|
||||
disc_sector_state[drive] = STATE_READ_FIND_SECTOR;
|
||||
}
|
||||
|
||||
void disc_sector_writesector(int drive, int sector, int track, int side, int rate, int sector_size)
|
||||
{
|
||||
// pclog("disc_sector_writesector: fdc_period=%i img_period=%i rate=%i\n", fdc_get_bitcell_period(), get_bitcell_period(), rate);
|
||||
|
||||
disc_sector_track[drive] = track;
|
||||
disc_sector_side[drive] = side;
|
||||
disc_sector_drive = drive;
|
||||
disc_sector_sector[drive] = sector;
|
||||
disc_sector_n[drive] = sector_size;
|
||||
if ((cur_sector[drive] == 0) && (cur_byte[drive] == 0) && !disc_track_delay[drive]) disc_track_delay[drive] = pre_track;
|
||||
index_count[drive] = 0;
|
||||
disc_sector_state[drive] = STATE_WRITE_FIND_SECTOR;
|
||||
}
|
||||
|
||||
void disc_sector_readaddress(int drive, int track, int side, int rate)
|
||||
{
|
||||
// pclog("disc_sector_readaddress: fdc_period=%i img_period=%i rate=%i track=%i side=%i\n", fdc_get_bitcell_period(), get_bitcell_period(), rate, track, side);
|
||||
|
||||
disc_sector_track[drive] = track;
|
||||
disc_sector_side[drive] = side;
|
||||
disc_sector_drive = drive;
|
||||
if ((cur_sector[drive] == 0) && (cur_byte[drive] == 0) && !disc_track_delay[drive])
|
||||
{
|
||||
disc_track_delay[drive] = pre_track;
|
||||
index_count[drive] = -1;
|
||||
}
|
||||
else
|
||||
index_count[drive] = 0;
|
||||
disc_sector_state[drive] = STATE_READ_FIND_ADDRESS;
|
||||
}
|
||||
|
||||
void disc_sector_format(int drive, int track, int side, int rate, uint8_t fill)
|
||||
{
|
||||
disc_sector_track[drive] = track;
|
||||
disc_sector_side[drive] = side;
|
||||
disc_sector_drive = drive;
|
||||
disc_sector_fill[drive] = fill;
|
||||
index_count[drive] = 0;
|
||||
disc_sector_state[drive] = STATE_FORMAT_FIND;
|
||||
}
|
||||
|
||||
void disc_sector_stop(int drive)
|
||||
{
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
}
|
||||
|
||||
static void index_pulse(int drive)
|
||||
{
|
||||
if (disc_sector_state[drive] != STATE_IDLE) fdc_indexpulse();
|
||||
}
|
||||
|
||||
void disc_sector_prepare_track_layout(int drive, int side)
|
||||
{
|
||||
}
|
||||
|
||||
static void advance_byte()
|
||||
{
|
||||
int drive = disc_sector_drive;
|
||||
|
||||
if (disc_postdata_delay[drive])
|
||||
{
|
||||
disc_postdata_delay[drive]--;
|
||||
return;
|
||||
}
|
||||
if (disc_gap4_delay[drive])
|
||||
{
|
||||
disc_gap4_delay[drive]--;
|
||||
return;
|
||||
}
|
||||
if (disc_track_delay[drive])
|
||||
{
|
||||
if (disc_track_delay[drive] == pre_track)
|
||||
{
|
||||
index_pulse(drive);
|
||||
if (disc_sector_state[drive] != STATE_IDLE) index_count[drive]++;
|
||||
}
|
||||
disc_track_delay[drive]--;
|
||||
return;
|
||||
}
|
||||
if (disc_intersector_delay[drive])
|
||||
{
|
||||
disc_intersector_delay[drive]--;
|
||||
return;
|
||||
}
|
||||
cur_byte[drive]++;
|
||||
if (cur_byte[drive] >= (128 << disc_sector_data[drive][disc_sector_side[drive]][cur_sector[drive]].n))
|
||||
{
|
||||
cur_byte[drive] = 0;
|
||||
cur_sector[drive]++;
|
||||
disc_postdata_delay[drive] = post_gap + (gap3_size[drive]);
|
||||
if (cur_sector[drive] >= disc_sector_count[drive][disc_sector_side[drive]])
|
||||
{
|
||||
cur_sector[drive] = 0;
|
||||
disc_gap4_delay[drive] = (gap4_size[drive]);
|
||||
disc_track_delay[drive] = pre_track;
|
||||
disc_intersector_delay[drive] = pre_gap + gap2_size[drive] + pre_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
disc_gap4_delay[drive] = 0;
|
||||
disc_track_delay[drive] = 0;
|
||||
disc_intersector_delay[drive] = pre_gap + gap2_size[drive] + pre_data;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int disc_gap_has_ended(int drive)
|
||||
{
|
||||
return (disc_postdata_delay[drive] == (post_gap + (gap3_size[drive]) - fdc_get_gap() - length_crc));
|
||||
}
|
||||
|
||||
void disc_sector_poll()
|
||||
{
|
||||
sector_t *s;
|
||||
int data;
|
||||
int drive = disc_sector_drive;
|
||||
|
||||
if (cur_sector[drive] >= disc_sector_count[drive][disc_sector_side[drive]])
|
||||
cur_sector[drive] = 0;
|
||||
if (disc_sector_n[drive])
|
||||
{
|
||||
if (cur_byte[drive] >= (128 << disc_sector_data[drive][disc_sector_side[drive]][cur_sector[drive]].n))
|
||||
cur_byte[drive] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cur_byte[drive] >= fdc_get_dtl())
|
||||
cur_byte[drive] = 0;
|
||||
}
|
||||
|
||||
/* Note: Side to read from should be chosen from FDC head select rather than from the sector ID. */
|
||||
s = &disc_sector_data[drive][disc_sector_side[drive]][cur_sector[drive]];
|
||||
|
||||
switch (disc_sector_state[drive])
|
||||
{
|
||||
case STATE_IDLE:
|
||||
advance_byte();
|
||||
break;
|
||||
|
||||
case STATE_READ_FIND_SECTOR:
|
||||
if (index_count[drive] > 1)
|
||||
{
|
||||
pclog("READ: Sector (%i %i %i %i) not found (last: %i %i %i %i) (period=%i,%i) (ic=%i)\n", s->c, s->h, s->r, s->n, disc_sector_track[drive], disc_sector_side[drive], disc_sector_sector[drive], disc_sector_n[drive], fdc_get_bitcell_period(), get_bitcell_period(drive), index_count[drive]);
|
||||
fdc_notfound();
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
if (/*cur_byte[drive] || */ disc_sector_track[drive] != s->c ||
|
||||
disc_sector_side[drive] != s->h ||
|
||||
disc_sector_sector[drive] != s->r ||
|
||||
((disc_sector_n[drive] != s->n) && (disc_sector_n[drive])) ||
|
||||
(fdc_get_bitcell_period() != get_bitcell_period(drive)) ||
|
||||
!fdd_can_read_medium(drive ^ fdd_swap) ||
|
||||
disc_intersector_delay[drive] || disc_postdata_delay[drive] || disc_track_delay[drive] || disc_gap4_delay[drive])
|
||||
{
|
||||
advance_byte();
|
||||
break;
|
||||
}
|
||||
disc_sector_state[drive] = STATE_READ_SECTOR;
|
||||
|
||||
case STATE_READ_SECTOR:
|
||||
if (!disc_postdata_delay[drive])
|
||||
{
|
||||
if (fdc_data(s->data[cur_byte[drive]]))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
advance_byte();
|
||||
if (!cur_byte[drive] && disc_gap_has_ended(drive))
|
||||
{
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
fdc_finishread(drive);
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_READ_FIND_FIRST_SECTOR:
|
||||
if (!fdd_can_read_medium(drive ^ fdd_swap))
|
||||
{
|
||||
fdc_notfound();
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
if (cur_byte[drive] || !index_count[drive] || fdc_get_bitcell_period() != get_bitcell_period(drive) ||
|
||||
disc_intersector_delay[drive] || disc_postdata_delay[drive] || disc_track_delay[drive] || disc_gap4_delay[drive])
|
||||
{
|
||||
advance_byte();
|
||||
break;
|
||||
}
|
||||
disc_sector_state[drive] = STATE_READ_FIRST_SECTOR;
|
||||
|
||||
case STATE_READ_FIRST_SECTOR:
|
||||
if (!disc_postdata_delay[drive])
|
||||
{
|
||||
if (fdc_data(s->data[cur_byte[drive]]))
|
||||
return;
|
||||
}
|
||||
advance_byte();
|
||||
if (!cur_byte[drive] && disc_gap_has_ended(drive))
|
||||
{
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
fdc_finishread(drive);
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_READ_FIND_NEXT_SECTOR:
|
||||
if (!fdd_can_read_medium(drive ^ fdd_swap))
|
||||
{
|
||||
fdc_notfound();
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
if (index_count[drive] > 0)
|
||||
{
|
||||
fdc_notfound();
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
if (cur_byte[drive] || (fdc_get_bitcell_period() != get_bitcell_period(drive)) ||
|
||||
disc_intersector_delay[drive] || disc_postdata_delay[drive] || disc_track_delay[drive] || disc_gap4_delay[drive])
|
||||
{
|
||||
advance_byte();
|
||||
break;
|
||||
}
|
||||
disc_sector_state[drive] = STATE_READ_NEXT_SECTOR;
|
||||
|
||||
case STATE_READ_NEXT_SECTOR:
|
||||
if (!disc_postdata_delay[drive])
|
||||
{
|
||||
if (fdc_data(s->data[cur_byte[drive]]))
|
||||
break;
|
||||
}
|
||||
advance_byte();
|
||||
if (!cur_byte[drive] && disc_gap_has_ended(drive))
|
||||
{
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
fdc_finishread(drive);
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_WRITE_FIND_SECTOR:
|
||||
if (!fdd_can_read_medium(drive ^ fdd_swap))
|
||||
{
|
||||
fdc_notfound();
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
if (writeprot[drive] || swwp)
|
||||
{
|
||||
fdc_writeprotect();
|
||||
}
|
||||
if (index_count[drive] > 1)
|
||||
{
|
||||
fdc_notfound();
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
if (cur_byte[drive] || disc_sector_track[drive] != s->c ||
|
||||
disc_sector_side[drive] != s->h ||
|
||||
disc_sector_sector[drive] != s->r ||
|
||||
((disc_sector_n[drive] != s->n) && (disc_sector_n[drive])) ||
|
||||
(fdc_get_bitcell_period() != get_bitcell_period(drive)) ||
|
||||
disc_intersector_delay[drive] || disc_postdata_delay[drive] || disc_track_delay[drive] || disc_gap4_delay[drive])
|
||||
{
|
||||
advance_byte();
|
||||
break;
|
||||
}
|
||||
disc_sector_state[drive] = STATE_WRITE_SECTOR;
|
||||
|
||||
case STATE_WRITE_SECTOR:
|
||||
if (!disc_postdata_delay[drive])
|
||||
{
|
||||
data = fdc_getdata(cur_byte[drive] == ((128 << s->n) - 1));
|
||||
if (data == -1)
|
||||
break;
|
||||
if (!disable_write) s->data[cur_byte[drive]] = data;
|
||||
}
|
||||
advance_byte();
|
||||
if (!cur_byte[drive] && disc_gap_has_ended(drive))
|
||||
{
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
if (!disable_write) disc_sector_writeback[drive](drive);
|
||||
fdc_finishread(drive);
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_READ_FIND_ADDRESS:
|
||||
if (!fdd_can_read_medium(drive ^ fdd_swap))
|
||||
{
|
||||
fdc_notfound();
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
if (index_count[drive] > 0)
|
||||
{
|
||||
fdc_notfound();
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
if (cur_byte[drive] || (fdc_get_bitcell_period() != get_bitcell_period(drive)) ||
|
||||
disc_intersector_delay[drive] || disc_postdata_delay[drive] || disc_track_delay[drive] || disc_gap4_delay[drive])
|
||||
{
|
||||
advance_byte();
|
||||
break;
|
||||
}
|
||||
disc_sector_state[drive] = STATE_READ_ADDRESS;
|
||||
case STATE_READ_ADDRESS:
|
||||
fdc_sectorid(s->c, s->h, s->r, s->n, 0, 0);
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
break;
|
||||
|
||||
case STATE_FORMAT_FIND:
|
||||
if (writeprot[drive] || swwp)
|
||||
{
|
||||
fdc_writeprotect();
|
||||
}
|
||||
if (!index_count[drive] || (fdc_get_bitcell_period() != get_bitcell_period(drive)) ||
|
||||
disc_intersector_delay[drive] || disc_postdata_delay[drive] || disc_track_delay[drive] || disc_gap4_delay[drive])
|
||||
{
|
||||
advance_byte();
|
||||
break;
|
||||
}
|
||||
if (!(fdd_can_read_medium(drive ^ fdd_swap)))
|
||||
{
|
||||
fdc_notfound();
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
if (fdc_get_bitcell_period() != get_bitcell_period(drive))
|
||||
{
|
||||
fdc_notfound();
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
disc_sector_state[drive] = STATE_FORMAT;
|
||||
|
||||
case STATE_FORMAT:
|
||||
if (!disc_intersector_delay[drive] && fdc_get_bitcell_period() == get_bitcell_period(drive) && !disable_write)
|
||||
s->data[cur_byte[drive]] = disc_sector_fill[drive];
|
||||
advance_byte();
|
||||
if (index_count[drive] == 2)
|
||||
{
|
||||
if (!disable_write) disc_sector_writeback[drive](drive);
|
||||
fdc_finishread(drive);
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/* Copyright holders: Sarah Walker, Tenshi
|
||||
see COPYING for more details
|
||||
*/
|
||||
void disc_sector_reset(int drive, int side);
|
||||
void disc_sector_add(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n, int rate, uint8_t *data);
|
||||
void disc_sector_readsector(int drive, int sector, int track, int side, int density, int sector_size);
|
||||
void disc_sector_writesector(int drive, int sector, int track, int side, int density, int sector_size);
|
||||
void disc_sector_readaddress(int drive, int sector, int side, int density);
|
||||
void disc_sector_format(int drive, int sector, int side, int density, uint8_t fill);
|
||||
void disc_sector_stop();
|
||||
void disc_sector_poll();
|
||||
void disc_sector_stop();
|
||||
|
||||
extern void (*disc_sector_writeback[2])(int drive);
|
||||
void disc_sector_prepare_track_layout(int drive, int side, int track);
|
||||
|
||||
#define length_gap0 80
|
||||
#define length_gap1 50
|
||||
#define length_sync 12
|
||||
#define length_am 4
|
||||
#define length_crc 2
|
||||
|
||||
#define IBM
|
||||
#define MFM
|
||||
#ifdef IBM
|
||||
#define pre_gap1 length_gap0 + length_sync + length_am
|
||||
#else
|
||||
#define pre_gap1 0
|
||||
#endif
|
||||
|
||||
#define pre_track pre_gap1 + length_gap1
|
||||
#define pre_gap length_sync + length_am + 4 + length_crc
|
||||
#define pre_data length_sync + length_am
|
||||
#define post_gap length_crc
|
||||
|
||||
extern int raw_tsize[2];
|
||||
extern int gap2_size[2];
|
||||
extern int gap3_size[2];
|
||||
// extern int gap4_size[2];
|
||||
@@ -1,638 +0,0 @@
|
||||
/* Copyright holders: Tenshi
|
||||
see COPYING for more details
|
||||
*/
|
||||
#include "ibm.h"
|
||||
#include "disc.h"
|
||||
#include "disc_sector.h"
|
||||
#include "fdc.h"
|
||||
#include "fdd.h"
|
||||
|
||||
/*Handling for 'sector based' image formats (like .IMG) as opposed to 'stream based' formats (eg .FDI)*/
|
||||
|
||||
#define MAX_SECTORS 256
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t c, h, r, n;
|
||||
int rate;
|
||||
uint8_t *data;
|
||||
} sector_t;
|
||||
|
||||
static sector_t disc_sector_data[2][2][MAX_SECTORS];
|
||||
static int disc_sector_count[2][2];
|
||||
void (*disc_sector_writeback[2])(int drive);
|
||||
|
||||
int cur_track_pos[2] = {0, 0};
|
||||
int id_counter[2] = {0, 0};
|
||||
int data_counter[2] = {0, 0};
|
||||
int gap3_counter[2] = {0, 0};
|
||||
int cur_rate[2] = {0, 0};
|
||||
|
||||
sector_t *last_sector[2];
|
||||
|
||||
enum
|
||||
{
|
||||
STATE_IDLE,
|
||||
STATE_READ_FIND_SECTOR,
|
||||
STATE_READ_SECTOR,
|
||||
STATE_READ_FIND_FIRST_SECTOR,
|
||||
STATE_READ_FIRST_SECTOR,
|
||||
STATE_READ_FIND_NEXT_SECTOR,
|
||||
STATE_READ_NEXT_SECTOR,
|
||||
STATE_WRITE_FIND_SECTOR,
|
||||
STATE_WRITE_SECTOR,
|
||||
STATE_READ_FIND_ADDRESS,
|
||||
STATE_READ_ADDRESS,
|
||||
STATE_FORMAT_FIND,
|
||||
STATE_FORMAT,
|
||||
STATE_SEEK
|
||||
};
|
||||
|
||||
static int disc_sector_state[2] = {0, 0};
|
||||
static int disc_sector_track[2] = {0, 0};
|
||||
static int disc_sector_side[2] = {0, 0};
|
||||
static int disc_sector_drive;
|
||||
static int disc_sector_sector[2] = {0, 0};
|
||||
static int disc_sector_n[2] = {0, 0};
|
||||
static uint8_t disc_sector_fill[2] = {0, 0};
|
||||
static int cur_sector[2], cur_byte[2];
|
||||
static int index_count[2];
|
||||
|
||||
int raw_tsize[2] = {6250, 6250};
|
||||
int gap2_size[2] = {22, 22};
|
||||
int gap3_size[2] = {0, 0};
|
||||
|
||||
int disc_sector_reset_state(int drive);
|
||||
|
||||
void disc_sector_reset(int drive, int side)
|
||||
{
|
||||
disc_sector_count[drive][side] = 0;
|
||||
|
||||
if (side == 0)
|
||||
{
|
||||
disc_sector_reset_state(drive);
|
||||
disc_sector_state[drive] = STATE_SEEK;
|
||||
}
|
||||
}
|
||||
|
||||
void disc_sector_add(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n, int rate, uint8_t *data)
|
||||
{
|
||||
sector_t *s = &disc_sector_data[drive][side][disc_sector_count[drive][side]];
|
||||
//pclog("disc_sector_add: drive=%i side=%i %i r=%i\n", drive, side, disc_sector_count[drive][side],r );
|
||||
if (disc_sector_count[drive][side] >= MAX_SECTORS)
|
||||
return;
|
||||
|
||||
s->c = c;
|
||||
s->h = h;
|
||||
s->r = r;
|
||||
s->n = n;
|
||||
// pclog("Adding sector: %i %i %i %i\n", c, h, r, n);
|
||||
s->rate = rate;
|
||||
s->data = data;
|
||||
|
||||
disc_sector_count[drive][side]++;
|
||||
}
|
||||
|
||||
static int get_bitcell_period(int drive)
|
||||
{
|
||||
return ((&disc_sector_data[drive][0][0])->rate * 300) / fdd_getrpm(drive ^ fdd_swap);
|
||||
}
|
||||
|
||||
void disc_sector_readsector(int drive, int sector, int track, int side, int rate, int sector_size)
|
||||
{
|
||||
// pclog("disc_sector_readsector: fdc_period=%i img_period=%i rate=%i sector=%i track=%i side=%i\n", fdc_get_bitcell_period(), get_bitcell_period(drive), rate, sector, track, side);
|
||||
// pclog("disc_sector_readsector: fdc_period=%i img_period=%i rate=%i c=%i h=%i r=%i n=%i\n", fdc_get_bitcell_period(), get_bitcell_period(drive), rate, track, side, sector, sector_size);
|
||||
|
||||
disc_sector_track[drive] = track;
|
||||
disc_sector_side[drive] = side;
|
||||
disc_sector_drive = drive;
|
||||
disc_sector_sector[drive] = sector;
|
||||
disc_sector_n[drive] = sector_size;
|
||||
disc_sector_reset_state(drive);
|
||||
if (sector == SECTOR_FIRST)
|
||||
disc_sector_state[drive] = STATE_READ_FIND_FIRST_SECTOR;
|
||||
else if (sector == SECTOR_NEXT)
|
||||
disc_sector_state[drive] = STATE_READ_FIND_NEXT_SECTOR;
|
||||
else
|
||||
disc_sector_state[drive] = STATE_READ_FIND_SECTOR;
|
||||
}
|
||||
|
||||
void disc_sector_writesector(int drive, int sector, int track, int side, int rate, int sector_size)
|
||||
{
|
||||
// pclog("disc_sector_writesector: fdc_period=%i img_period=%i rate=%i\n", fdc_get_bitcell_period(), get_bitcell_period(drive), rate);
|
||||
|
||||
if (writeprot[drive] || swwp)
|
||||
{
|
||||
fdc_writeprotect();
|
||||
return;
|
||||
}
|
||||
|
||||
disc_sector_track[drive] = track;
|
||||
disc_sector_side[drive] = side;
|
||||
disc_sector_drive = drive;
|
||||
disc_sector_sector[drive] = sector;
|
||||
disc_sector_n[drive] = sector_size;
|
||||
disc_sector_reset_state(drive);
|
||||
disc_sector_state[drive] = STATE_WRITE_FIND_SECTOR;
|
||||
}
|
||||
|
||||
void disc_sector_readaddress(int drive, int track, int side, int rate)
|
||||
{
|
||||
// pclog("disc_sector_readaddress: fdc_period=%i img_period=%i rate=%i track=%i side=%i\n", fdc_get_bitcell_period(), get_bitcell_period(drive), rate, track, side);
|
||||
|
||||
disc_sector_track[drive] = track;
|
||||
disc_sector_side[drive] = side;
|
||||
disc_sector_drive = drive;
|
||||
disc_sector_reset_state(drive);
|
||||
disc_sector_state[drive] = STATE_READ_FIND_ADDRESS;
|
||||
}
|
||||
|
||||
void disc_sector_format(int drive, int track, int side, int rate, uint8_t fill)
|
||||
{
|
||||
disc_sector_track[drive] = track;
|
||||
disc_sector_side[drive] = side;
|
||||
disc_sector_drive = drive;
|
||||
disc_sector_fill[drive] = fill;
|
||||
disc_sector_reset_state(drive);
|
||||
disc_sector_state[drive] = STATE_FORMAT_FIND;
|
||||
}
|
||||
|
||||
void disc_sector_stop(int drive)
|
||||
{
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
}
|
||||
|
||||
static void index_pulse(int drive)
|
||||
{
|
||||
if (disc_sector_state[drive] != STATE_IDLE) fdc_indexpulse();
|
||||
}
|
||||
|
||||
// char *track_buffer[2][2][25512];
|
||||
char track_layout[2][2][25512];
|
||||
|
||||
int id_positions[2][2][MAX_SECTORS];
|
||||
|
||||
/* 0 = MFM, 1 = FM, 2 = MFM perpendicular, 3 = reserved */
|
||||
/* 4 = ISO, 0 = IBM */
|
||||
int media_type = 0;
|
||||
|
||||
#define GAP3_LEN_VARIABLE 0x1B
|
||||
|
||||
int disc_sector_get_gap3_size(int drive, int side, int track)
|
||||
{
|
||||
if (!img_xdf_type(drive))
|
||||
{
|
||||
return gap3_size[drive];
|
||||
}
|
||||
|
||||
switch (track)
|
||||
{
|
||||
case 0:
|
||||
return 60;
|
||||
default:
|
||||
return GAP3_LEN_VARIABLE;
|
||||
}
|
||||
|
||||
return 0x7A;
|
||||
}
|
||||
|
||||
void disc_sector_prepare_track_layout(int drive, int side, int track)
|
||||
{
|
||||
sector_t *s;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int real_gap0_len = ((media_type & 3) == 1) ? 40 : 80;
|
||||
int sync_len = ((media_type & 3) == 1) ? 6 : 12;
|
||||
int am_len = ((media_type & 3) == 1) ? 1 : 4;
|
||||
int real_gap1_len = ((media_type & 3) == 1) ? 26 : 50;
|
||||
// track_layout[drive][side] = (char *) malloc(raw_tsize[drive]);
|
||||
// id_positions[drive][side] = (int *) malloc(disc_sector_count[drive][side] * 4);
|
||||
memset(track_layout[drive][side], BYTE_GAP4, raw_tsize[drive]);
|
||||
memset(id_positions[drive][side], 0, 1024);
|
||||
i = 0;
|
||||
if (!(media_type & 4))
|
||||
{
|
||||
memset(track_layout[drive][side] + i, BYTE_GAP0, real_gap0_len);
|
||||
i += real_gap0_len - 1;
|
||||
memset(track_layout[drive][side] + i, BYTE_I_SYNC, sync_len);
|
||||
i += sync_len;
|
||||
if ((media_type & 3) != 1)
|
||||
{
|
||||
memset(track_layout[drive][side] + i, BYTE_IAM_SYNC, 3);
|
||||
i += 3;
|
||||
}
|
||||
memset(track_layout[drive][side] + i, BYTE_IAM, 1);
|
||||
i++;
|
||||
memset(track_layout[drive][side] + i, BYTE_GAP1, real_gap1_len);
|
||||
i += real_gap1_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(track_layout[drive][side] + i, BYTE_GAP1, real_gap1_len);
|
||||
i += real_gap1_len - 1;
|
||||
}
|
||||
track_layout[drive][side][0] |= BYTE_INDEX_HOLE;
|
||||
for (j = 0; j < disc_sector_count[drive][side]; j++)
|
||||
{
|
||||
s = &disc_sector_data[drive][side][j];
|
||||
// pclog("Sector %i (%i)\n", j, s->n);
|
||||
memset(track_layout[drive][side] + i, BYTE_ID_SYNC, sync_len);
|
||||
i += sync_len;
|
||||
if ((media_type & 3) != 1)
|
||||
{
|
||||
memset(track_layout[drive][side] + i, BYTE_IDAM_SYNC, 3);
|
||||
i += 3;
|
||||
}
|
||||
memset(track_layout[drive][side] + i, BYTE_IDAM, 1);
|
||||
i++;
|
||||
memset(track_layout[drive][side] + i, BYTE_ID, 4);
|
||||
i += 4;
|
||||
memset(track_layout[drive][side] + i, BYTE_ID_CRC, 2);
|
||||
i += 2;
|
||||
id_positions[drive][side][j] = i;
|
||||
memset(track_layout[drive][side] + i, BYTE_GAP2, gap2_size[drive]);
|
||||
i += gap2_size[drive];
|
||||
memset(track_layout[drive][side] + i, BYTE_DATA_SYNC, sync_len);
|
||||
i += sync_len;
|
||||
if ((media_type & 3) != 1)
|
||||
{
|
||||
memset(track_layout[drive][side] + i, BYTE_DATAAM_SYNC, 3);
|
||||
i += 3;
|
||||
}
|
||||
memset(track_layout[drive][side] + i, BYTE_DATAAM, 1);
|
||||
i++;
|
||||
memset(track_layout[drive][side] + i, BYTE_DATA, (128 << ((int) s->n)));
|
||||
i += (128 << ((int) s->n));
|
||||
memset(track_layout[drive][side] + i, BYTE_DATA_CRC, 2);
|
||||
i += 2;
|
||||
memset(track_layout[drive][side] + i, BYTE_GAP3, disc_sector_get_gap3_size(drive, side, track));
|
||||
i += disc_sector_get_gap3_size(drive, side, track);
|
||||
}
|
||||
// pclog("Track length: %i bytes\n", i);
|
||||
|
||||
if (side == 0) disc_sector_state[drive] = STATE_IDLE;
|
||||
}
|
||||
|
||||
int disc_sector_reset_state(int drive)
|
||||
{
|
||||
id_counter[drive] = data_counter[drive] = index_count[drive] = gap3_counter[drive] = cur_rate[drive] = 0;
|
||||
last_sector[drive] = NULL;
|
||||
}
|
||||
|
||||
int disc_sector_find_sector(int drive)
|
||||
{
|
||||
int side = fdd_get_head(drive);
|
||||
int i = 0;
|
||||
for (i = 0; i < disc_sector_count[drive][side]; i++)
|
||||
{
|
||||
if (id_positions[drive][side][i] == cur_track_pos[drive])
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int disc_sector_match(int drive)
|
||||
{
|
||||
int temp;
|
||||
if (last_sector[drive] == NULL) return 0;
|
||||
temp = (disc_sector_track[drive] == last_sector[drive]->c);
|
||||
temp = temp && (disc_sector_side[drive] == last_sector[drive]->h);
|
||||
temp = temp && (disc_sector_sector[drive] == last_sector[drive]->r);
|
||||
temp = temp && (disc_sector_n[drive] == last_sector[drive]->n);
|
||||
return temp;
|
||||
}
|
||||
|
||||
uint32_t disc_sector_get_data_len(int drive)
|
||||
{
|
||||
if (disc_sector_n[drive])
|
||||
{
|
||||
return (128 << ((uint32_t) disc_sector_n[drive]));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fdc_get_dtl() < 128)
|
||||
{
|
||||
return fdc_get_dtl();
|
||||
}
|
||||
else
|
||||
{
|
||||
return (128 << ((uint32_t) disc_sector_n[drive]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int disc_sector_can_read_address(int drive)
|
||||
{
|
||||
int temp;
|
||||
temp = (fdc_get_bitcell_period() == get_bitcell_period(drive));
|
||||
temp = temp && fdd_can_read_medium(drive ^ fdd_swap);
|
||||
return temp;
|
||||
}
|
||||
|
||||
int disc_sector_can_format(int drive)
|
||||
{
|
||||
int temp;
|
||||
temp = !writeprot[drive];
|
||||
temp = temp && !swwp;
|
||||
temp = temp && disc_sector_can_read_address(drive);
|
||||
temp = temp && (fdc_get_format_sectors() == disc_sector_count[drive][disc_sector_side[drive]]);
|
||||
temp = temp && (!img_xdf_type(drive));
|
||||
return temp;
|
||||
}
|
||||
|
||||
int disc_sector_find_state(int drive)
|
||||
{
|
||||
int temp;
|
||||
temp = (disc_sector_state[drive] == STATE_READ_FIND_SECTOR);
|
||||
temp = temp || (disc_sector_state[drive] == STATE_READ_FIND_FIRST_SECTOR);
|
||||
temp = temp || (disc_sector_state[drive] == STATE_READ_FIND_NEXT_SECTOR);
|
||||
temp = temp || (disc_sector_state[drive] == STATE_WRITE_FIND_SECTOR);
|
||||
temp = temp || (disc_sector_state[drive] == STATE_READ_FIND_ADDRESS);
|
||||
temp = temp || (disc_sector_state[drive] == STATE_FORMAT_FIND);
|
||||
return temp;
|
||||
}
|
||||
|
||||
int disc_sector_read_state(int drive)
|
||||
{
|
||||
int temp;
|
||||
temp = (disc_sector_state[drive] == STATE_READ_SECTOR);
|
||||
temp = temp || (disc_sector_state[drive] == STATE_READ_FIRST_SECTOR);
|
||||
temp = temp || (disc_sector_state[drive] == STATE_READ_NEXT_SECTOR);
|
||||
return temp;
|
||||
}
|
||||
|
||||
int section_pos[2] = {0, 0};
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint32_t dword;
|
||||
uint8_t byte_array[4];
|
||||
} sector_id;
|
||||
|
||||
sector_id format_sector_id;
|
||||
|
||||
void disc_sector_poll()
|
||||
{
|
||||
sector_t *s;
|
||||
int data;
|
||||
int drive = disc_sector_drive;
|
||||
int side = fdd_get_head(drive);
|
||||
int found_sector = 0;
|
||||
int b = 0;
|
||||
|
||||
int cur_id_pos = 0;
|
||||
int cur_data_pos = 0;
|
||||
int cur_gap3_pos = 0;
|
||||
int max_gap = 0;
|
||||
|
||||
uint8_t track_byte = 0;
|
||||
uint8_t track_index = 0;
|
||||
uint8_t track_sector = 0;
|
||||
uint8_t track_byte_type = 0;
|
||||
|
||||
uint8_t old_track_byte = 0;
|
||||
uint8_t old_track_index = 0;
|
||||
uint8_t old_track_sector = 0;
|
||||
uint8_t old_track_byte_type = 0;
|
||||
|
||||
if (disc_sector_state[drive] == STATE_SEEK)
|
||||
{
|
||||
cur_track_pos[drive]++;
|
||||
cur_track_pos[drive] %= raw_tsize[drive];
|
||||
return;
|
||||
}
|
||||
|
||||
if (disc_sector_state[drive] == STATE_FORMAT_FIND)
|
||||
{
|
||||
if (!(disc_sector_can_format(drive)))
|
||||
{
|
||||
if (disc_sector_can_read_address(drive))
|
||||
{
|
||||
// pclog("disc_sector_poll(): Disk is write protected or attempting to format wrong number of sectors per track\n");
|
||||
fdc_writeprotect();
|
||||
}
|
||||
else
|
||||
{
|
||||
// pclog("disc_sector_poll(): Unable to format at the requested density or bitcell period\n");
|
||||
fdc_notfound();
|
||||
}
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
disc_sector_reset_state(drive);
|
||||
cur_track_pos[drive]++;
|
||||
cur_track_pos[drive] %= raw_tsize[drive];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
track_byte = track_layout[drive][side][cur_track_pos[drive]];
|
||||
track_index = track_byte & BYTE_INDEX_HOLE;
|
||||
track_sector = track_byte & BYTE_IS_SECTOR;
|
||||
track_byte_type = track_byte & BYTE_TYPE;
|
||||
|
||||
if (track_index)
|
||||
{
|
||||
if (disc_sector_state[drive] != STATE_IDLE)
|
||||
{
|
||||
index_pulse(drive);
|
||||
index_count[drive]++;
|
||||
}
|
||||
if (disc_sector_state[drive] == STATE_FORMAT)
|
||||
{
|
||||
// pclog("Index hole hit again, format finished\n");
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
if (!disable_write) disc_sector_writeback[drive](drive);
|
||||
fdc_sector_finishread(drive);
|
||||
}
|
||||
if ((disc_sector_state[drive] == STATE_FORMAT_FIND) && disc_sector_can_read_address(drive))
|
||||
{
|
||||
// pclog("Index hole hit, formatting track...\n");
|
||||
disc_sector_state[drive] = STATE_FORMAT;
|
||||
}
|
||||
}
|
||||
|
||||
switch(track_byte)
|
||||
{
|
||||
case BYTE_ID_SYNC:
|
||||
if (disc_sector_state[drive] != STATE_FORMAT) break;
|
||||
cur_id_pos = cur_track_pos[drive] - section_pos[drive];
|
||||
if (cur_id_pos > 3) break;
|
||||
data = fdc_getdata(0);
|
||||
if ((data == -1) && (cur_id_pos < 3))
|
||||
{
|
||||
/* Data failed to be sent from the FDC, abort. */
|
||||
// pclog("disc_sector_poll(): Unable to receive further data from the FDC\n");
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
disc_sector_reset_state(drive);
|
||||
cur_track_pos[drive]++;
|
||||
cur_track_pos[drive] %= raw_tsize[drive];
|
||||
return;
|
||||
}
|
||||
format_sector_id.byte_array[cur_id_pos] = data & 0xff;
|
||||
// pclog("format_sector_id[%i] = %i\n", cur_id_pos, format_sector_id.byte_array[cur_id_pos]);
|
||||
if (cur_id_pos == 3)
|
||||
{
|
||||
fdc_stop_id_request();
|
||||
// pclog("Formatting sector: %08X...\n", format_sector_id.dword);
|
||||
}
|
||||
break;
|
||||
case BYTE_DATA:
|
||||
cur_data_pos = cur_track_pos[drive] - section_pos[drive];
|
||||
if (disc_sector_read_state(drive) && (last_sector[drive] != NULL))
|
||||
{
|
||||
if (fdc_data(last_sector[drive]->data[data_counter[drive]]))
|
||||
{
|
||||
/* Data failed to be sent to the FDC, abort. */
|
||||
// pclog("disc_sector_poll(): Unable to send further data to the FDC\n");
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
disc_sector_reset_state(drive);
|
||||
cur_track_pos[drive]++;
|
||||
cur_track_pos[drive] %= raw_tsize[drive];
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ((disc_sector_state[drive] == STATE_WRITE_SECTOR) && (last_sector[drive] != NULL))
|
||||
{
|
||||
data = fdc_getdata(data_counter[drive] == ((128 << ((uint32_t) last_sector[drive]->n)) - 1));
|
||||
if (data == -1)
|
||||
{
|
||||
/* Data failed to be sent from the FDC, abort. */
|
||||
// pclog("disc_sector_poll(): Unable to receive further data from the FDC\n");
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
disc_sector_reset_state(drive);
|
||||
cur_track_pos[drive]++;
|
||||
cur_track_pos[drive] %= raw_tsize[drive];
|
||||
return;
|
||||
}
|
||||
if (!disable_write) last_sector[drive]->data[data_counter[drive]] = data;
|
||||
}
|
||||
if ((disc_sector_state[drive] == STATE_FORMAT) && (last_sector[drive] != NULL))
|
||||
{
|
||||
if (!disable_write) last_sector[drive]->data[data_counter[drive]] = disc_sector_fill[drive];
|
||||
}
|
||||
data_counter[drive]++;
|
||||
if (last_sector[drive] == NULL)
|
||||
{
|
||||
data_counter[drive] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
data_counter[drive] %= (128 << ((uint32_t) last_sector[drive]->n));
|
||||
}
|
||||
break;
|
||||
case BYTE_GAP3:
|
||||
cur_gap3_pos = cur_track_pos[drive] - section_pos[drive];
|
||||
max_gap = fdc_get_gap();
|
||||
if (max_gap > disc_sector_get_gap3_size(drive, side, disc_sector_track[drive]))
|
||||
{
|
||||
max_gap = disc_sector_get_gap3_size(drive, side, disc_sector_track[drive]);
|
||||
}
|
||||
if (cur_gap3_pos == (max_gap - 1))
|
||||
{
|
||||
if (disc_sector_read_state(drive) && (last_sector[drive] != NULL))
|
||||
{
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
fdc_sector_finishread(drive);
|
||||
}
|
||||
if ((disc_sector_state[drive] == STATE_WRITE_SECTOR) && (last_sector[drive] != NULL))
|
||||
{
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
if (!disable_write) disc_sector_writeback[drive](drive);
|
||||
fdc_sector_finishread(drive);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
old_track_byte = track_byte;
|
||||
old_track_index = track_index;
|
||||
old_track_sector = track_sector;
|
||||
old_track_byte_type = track_byte_type;
|
||||
|
||||
cur_track_pos[drive]++;
|
||||
cur_track_pos[drive] %= raw_tsize[drive];
|
||||
|
||||
track_byte = track_layout[drive][side][cur_track_pos[drive]];
|
||||
track_index = track_byte & BYTE_INDEX_HOLE;
|
||||
track_sector = track_byte & BYTE_IS_SECTOR;
|
||||
track_byte_type = track_byte & BYTE_TYPE;
|
||||
|
||||
if ((disc_sector_state[drive] != STATE_IDLE) && (disc_sector_state[drive] != STATE_SEEK))
|
||||
{
|
||||
if (index_count[drive] > 1)
|
||||
{
|
||||
if (disc_sector_find_state(drive))
|
||||
{
|
||||
/* The index hole has been hit twice and we're still in a find state.
|
||||
This means sector finding has failed for whatever reason.
|
||||
Abort with sector not found and set state to idle. */
|
||||
// pclog("disc_sector_poll(): Sector not found (%i %i %i %i)\n", disc_sector_track[drive], disc_sector_side[drive], disc_sector_sector[drive], disc_sector_n[drive]);
|
||||
fdc_notfound();
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
disc_sector_reset_state(drive);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (track_byte != old_track_byte)
|
||||
{
|
||||
// if (disc_sector_state[drive] == STATE_FORMAT) pclog("Track byte: %02X, old: %02X\n", track_byte, old_track_byte);
|
||||
section_pos[drive] = cur_track_pos[drive];
|
||||
switch(track_byte)
|
||||
{
|
||||
case BYTE_ID_SYNC:
|
||||
if (disc_sector_state[drive] == STATE_FORMAT)
|
||||
{
|
||||
// pclog("Requesting next sector ID...\n");
|
||||
fdc_request_next_sector_id();
|
||||
}
|
||||
break;
|
||||
case BYTE_GAP2:
|
||||
found_sector = disc_sector_find_sector(drive);
|
||||
// pclog("Found sector: %i\n", found_sector);
|
||||
cur_sector[drive] = found_sector;
|
||||
last_sector[drive] = &disc_sector_data[drive][side][found_sector];
|
||||
cur_rate[drive] = last_sector[drive]->rate;
|
||||
if (!(disc_sector_can_read_address(drive))) last_sector[drive] = NULL;
|
||||
|
||||
/* ID CRC read, if state is read address, return address */
|
||||
// if ((disc_sector_state[drive] == STATE_READ_FIND_ADDRESS) && !(disc_sector_can_read_address(drive)))
|
||||
if ((disc_sector_state[drive] == STATE_READ_FIND_ADDRESS) && disc_sector_can_read_address(drive))
|
||||
{
|
||||
// pclog("Reading sector ID...\n");
|
||||
fdc_sectorid(last_sector[drive]->c, last_sector[drive]->h, last_sector[drive]->r, last_sector[drive]->n, 0, 0);
|
||||
disc_sector_state[drive] = STATE_IDLE;
|
||||
}
|
||||
break;
|
||||
case BYTE_DATA:
|
||||
// data_counter[drive] = 0;
|
||||
switch (disc_sector_state[drive])
|
||||
{
|
||||
case STATE_READ_FIND_SECTOR:
|
||||
if (disc_sector_match(drive) && disc_sector_can_read_address(drive))
|
||||
{
|
||||
disc_sector_state[drive] = STATE_READ_SECTOR;
|
||||
}
|
||||
break;
|
||||
case STATE_READ_FIND_FIRST_SECTOR:
|
||||
if ((cur_sector[drive] == 0) && disc_sector_can_read_address(drive)) disc_sector_state[drive] = STATE_READ_FIRST_SECTOR;
|
||||
break;
|
||||
case STATE_READ_FIND_NEXT_SECTOR:
|
||||
if (disc_sector_can_read_address(drive)) disc_sector_state[drive] = STATE_READ_NEXT_SECTOR;
|
||||
break;
|
||||
case STATE_WRITE_FIND_SECTOR:
|
||||
if (disc_sector_match(drive) && disc_sector_can_read_address(drive)) disc_sector_state[drive] = STATE_WRITE_SECTOR;
|
||||
break;
|
||||
/* case STATE_FORMAT:
|
||||
// pclog("Format: Starting sector fill...\n");
|
||||
break; */
|
||||
}
|
||||
break;
|
||||
case BYTE_GAP4:
|
||||
if (last_sector[drive] != NULL) last_sector[drive] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,6 +90,7 @@ typedef struct
|
||||
FILE *f;
|
||||
|
||||
int tracks;
|
||||
int track_width;
|
||||
int sides;
|
||||
uint16_t disk_flags;
|
||||
uint16_t default_track_flags;
|
||||
@@ -226,7 +227,7 @@ int td0_state_next_word(td0dsk_t *state)
|
||||
{
|
||||
state->tdctl.ibufndx = 0;
|
||||
state->tdctl.ibufcnt = td0_state_data_read(state, state->tdctl.inbuf,BUFSZ);
|
||||
if(state->tdctl.ibufcnt <= 0)
|
||||
if(state->tdctl.ibufcnt == 0)
|
||||
return(-1);
|
||||
}
|
||||
while (state->getlen <= 8) { // typically reads a word at a time
|
||||
@@ -503,12 +504,7 @@ uint8_t header[12];
|
||||
|
||||
void td0_load(int drive, char *fn)
|
||||
{
|
||||
int track;
|
||||
int head;
|
||||
int fm;
|
||||
int offset = 0;
|
||||
int ret = 0;
|
||||
const int max_size = 4*1024*1024; // 4MB ought to be large enough for any floppy
|
||||
|
||||
d86f_unregister(drive);
|
||||
|
||||
@@ -740,6 +736,8 @@ int td0_initialize(int drive)
|
||||
|
||||
td0[drive].disk_flags = header[5] & 0x06;
|
||||
|
||||
td0[drive].track_width = (header[7] & 1) ^ 1;
|
||||
|
||||
// rate = (header[5] & 0x7f) >= 3 ? 0 : rates[header[5] & 0x7f];
|
||||
// td0[drive].default_track_flags |= rate;
|
||||
|
||||
@@ -898,13 +896,16 @@ int td0_initialize(int drive)
|
||||
td0[drive].gap3_len = td0[drive].calculated_gap3_lengths[0][0]; /* If we can't determine the GAP3 length, assume the smallest one we possibly know of. */
|
||||
}
|
||||
|
||||
if (td0[drive].tracks > 43) td0[drive].disk_flags |= 1; /* If the image has more than 43 tracks, then the tracks are thin (96 tpi). */
|
||||
|
||||
if(head_count == 2)
|
||||
{
|
||||
td0[drive].disk_flags |= 8; /* 2 sides */
|
||||
}
|
||||
|
||||
if (td0[drive].tracks <= 43)
|
||||
{
|
||||
td0[drive].track_width &= ~1;
|
||||
}
|
||||
|
||||
td0[drive].sides = head_count;
|
||||
|
||||
td0[drive].current_side_flags[0] = td0[drive].side_flags[0][0];
|
||||
@@ -1076,7 +1077,7 @@ void td0_seek(int drive, int track)
|
||||
if (!td0[drive].f)
|
||||
return;
|
||||
|
||||
if (d86f_is_40_track(drive) && fdd_doublestep_40(drive))
|
||||
if (!td0[drive].track_width && fdd_doublestep_40(drive))
|
||||
track /= 2;
|
||||
|
||||
is_trackx = (track == 0) ? 0 : 1;
|
||||
@@ -1107,7 +1108,7 @@ void td0_seek(int drive, int track)
|
||||
|
||||
interleave_type = td0_track_is_interleave(drive, side, track);
|
||||
|
||||
current_pos = d86f_prepare_pretrack(drive, side, 0, 1);
|
||||
current_pos = d86f_prepare_pretrack(drive, side, 0);
|
||||
|
||||
if (!xdf_type)
|
||||
{
|
||||
@@ -1129,7 +1130,7 @@ void td0_seek(int drive, int track)
|
||||
id[3] = td0[drive].sects[track][side][actual_sector].size;
|
||||
// pclog("TD0: %i %i %i %i (%i %i) (GPL=%i)\n", id[0], id[1], id[2], id[3], td0[drive].sects[track][side][actual_sector].deleted, td0[drive].sects[track][side][actual_sector].bad_crc, track_gap3);
|
||||
ssize = 128 << ((uint32_t) td0[drive].sects[track][side][actual_sector].size);
|
||||
current_pos = d86f_prepare_sector(drive, side, current_pos, id, td0[drive].sects[track][side][actual_sector].data, ssize, 1, track_gap2, track_gap3, 0, td0[drive].sects[track][side][actual_sector].deleted, td0[drive].sects[track][side][actual_sector].bad_crc);
|
||||
current_pos = d86f_prepare_sector(drive, side, current_pos, id, td0[drive].sects[track][side][actual_sector].data, ssize, track_gap2, track_gap3, td0[drive].sects[track][side][actual_sector].deleted, td0[drive].sects[track][side][actual_sector].bad_crc);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1148,11 +1149,11 @@ void td0_seek(int drive, int track)
|
||||
// pclog("TD0: XDF: (%i %i) %i %i %i %i (%i %i) (GPL=%i)\n", track, side, id[0], id[1], id[2], id[3], td0[drive].sects[track][side][ordered_pos].deleted, td0[drive].sects[track][side][ordered_pos].bad_crc, track_gap3);
|
||||
if (is_trackx)
|
||||
{
|
||||
current_pos = d86f_prepare_sector(drive, side, xdf_trackx_spos[xdf_type][xdf_sector], id, td0[drive].sects[track][side][ordered_pos].data, ssize, 1, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], 0, td0[drive].sects[track][side][ordered_pos].deleted, td0[drive].sects[track][side][ordered_pos].bad_crc);
|
||||
current_pos = d86f_prepare_sector(drive, side, xdf_trackx_spos[xdf_type][xdf_sector], id, td0[drive].sects[track][side][ordered_pos].data, ssize, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], td0[drive].sects[track][side][ordered_pos].deleted, td0[drive].sects[track][side][ordered_pos].bad_crc);
|
||||
}
|
||||
else
|
||||
{
|
||||
current_pos = d86f_prepare_sector(drive, side, current_pos, id, td0[drive].sects[track][side][ordered_pos].data, ssize, 1, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], 0, td0[drive].sects[track][side][ordered_pos].deleted, td0[drive].sects[track][side][ordered_pos].bad_crc);
|
||||
current_pos = d86f_prepare_sector(drive, side, current_pos, id, td0[drive].sects[track][side][ordered_pos].data, ssize, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], td0[drive].sects[track][side][ordered_pos].deleted, td0[drive].sects[track][side][ordered_pos].bad_crc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1193,19 +1194,18 @@ void td0_set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t td0_poll_read_data(int drive, int side, uint16_t pos)
|
||||
{
|
||||
return td0[drive].sects[td0[drive].track][side][td0[drive].current_sector_index[side]].data[pos];
|
||||
}
|
||||
|
||||
void d86f_register_td0(int drive)
|
||||
{
|
||||
d86f_handler[drive].disk_flags = td0_disk_flags;
|
||||
d86f_handler[drive].side_flags = td0_side_flags;
|
||||
d86f_handler[drive].writeback = null_writeback;
|
||||
d86f_handler[drive].set_sector = td0_set_sector;
|
||||
d86f_handler[drive].read_data = td0_poll_read_data;
|
||||
d86f_handler[drive].write_data = null_poll_write_data;
|
||||
d86f_handler[drive].write_data = null_write_data;
|
||||
d86f_handler[drive].format_conditions = null_format_conditions;
|
||||
d86f_handler[drive].extra_bit_cells = null_extra_bit_cells;
|
||||
d86f_handler[drive].encoded_data = common_encoded_data;
|
||||
d86f_handler[drive].read_revolution = common_read_revolution;
|
||||
d86f_handler[drive].index_hole_pos = null_index_hole_pos;
|
||||
d86f_handler[drive].get_raw_size = common_get_raw_size;
|
||||
d86f_handler[drive].check_crc = 1;
|
||||
}
|
||||
136
src/fdc.c
136
src/fdc.c
@@ -12,10 +12,25 @@
|
||||
#include "pic.h"
|
||||
#include "timer.h"
|
||||
|
||||
extern int64_t motoron;
|
||||
extern int64_t motoron[2];
|
||||
|
||||
int ui_writeprot[2] = {0, 0};
|
||||
|
||||
int command_has_drivesel[256] = { [0x02] = 1, /* READ TRACK */
|
||||
[0x04] = 1, /* SENSE DRIVE STATUS */
|
||||
[0x05] = 1, /* WRITE DATA */
|
||||
[0x06] = 1, /* READ DATA */
|
||||
[0x07] = 1, /* RECALIBRATE */
|
||||
[0x09] = 1, /* WRITE DELETED DATA */
|
||||
[0x0A] = 1, /* READ ID */
|
||||
[0x0C] = 1, /* READ DELETED DATA */
|
||||
[0x0D] = 1, /* FORMAT TRACK */
|
||||
[0x0F] = 1, /* SEEK, RELATIVE SEEK */
|
||||
[0x11] = 1, /* SCAN EQUAL */
|
||||
[0x16] = 1, /* VERIFY */
|
||||
[0x19] = 1, /* SCAN LOW OR EQUAL */
|
||||
[0x1D] = 1 }; /* SCAN HIGH OR EQUAL */
|
||||
|
||||
static int fdc_reset_stat = 0;
|
||||
/*FDC*/
|
||||
typedef struct FDC
|
||||
@@ -239,7 +254,6 @@ int fdc_get_format_sectors()
|
||||
|
||||
void fdc_reset_fifo_buf()
|
||||
{
|
||||
int i = 0;
|
||||
memset(fdc.fifobuf, 0, 16);
|
||||
fdc.fifobufpos = 0;
|
||||
}
|
||||
@@ -346,7 +360,6 @@ void fdc_update_enh_mode(int enh_mode)
|
||||
int fdc_get_rwc(int drive)
|
||||
{
|
||||
return fdc.rwc[drive];
|
||||
fdc_rate(drive);
|
||||
}
|
||||
|
||||
void fdc_update_rwc(int drive, int rwc)
|
||||
@@ -525,8 +538,6 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
// 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);
|
||||
int drive;
|
||||
int seek_time;
|
||||
int temp_drive;
|
||||
int temp_motoron;
|
||||
|
||||
switch (addr&7)
|
||||
{
|
||||
@@ -551,8 +562,12 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
discint=-1;
|
||||
fdc_reset();
|
||||
}
|
||||
motoron = val & 0x01;
|
||||
fdc.drive = 0;
|
||||
if (!fdd_get_flags(0))
|
||||
{
|
||||
val &= 0xfe;
|
||||
}
|
||||
motoron[0] = val & 0x01;
|
||||
// fdc.drive = 0;
|
||||
/* if (motoron)
|
||||
output = 3;
|
||||
else
|
||||
@@ -577,25 +592,17 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
timer_process();
|
||||
timer_update_outstanding();
|
||||
val &= 0x3f; /* Drives 2 and 3 are not emulated, so their motors are always forced off. */
|
||||
temp_drive = val & 3;
|
||||
temp_motoron = 0x10 << temp_drive;
|
||||
temp_motoron = val & temp_motoron;
|
||||
motoron = 0;
|
||||
if (temp_motoron && (temp_drive <= 1))
|
||||
/* We can now simplify this since each motor now spins separately. */
|
||||
if (!fdd_get_flags(0 ^ fdd_swap))
|
||||
{
|
||||
/* Selected drive is drive 0 or 1 and has motor on bit set too, change drive selection. */
|
||||
fdc.drive = temp_drive;
|
||||
disc_drivesel = fdc.drive;
|
||||
disc_set_drivesel(fdc.drive);
|
||||
motoron = (val & 0xf0) ? 1 : 0;
|
||||
val &= 0x3f;
|
||||
val &= 0x2f;
|
||||
}
|
||||
else
|
||||
if (!fdd_get_flags(1 ^ fdd_swap))
|
||||
{
|
||||
/* Selected drive is either drive 2 or 3 or has motor on bit clear, turn off the motor. */
|
||||
motoron = 0;
|
||||
val &= 0x0f;
|
||||
val &= 0x1f;
|
||||
}
|
||||
motoron[0] = (val & 0x10);
|
||||
motoron[1] = (val & 0x20);
|
||||
}
|
||||
fdc.dor=val;
|
||||
// printf("DOR now %02X\n",val);
|
||||
@@ -809,22 +816,15 @@ bad_command:
|
||||
timer_process();
|
||||
disctime = 1024 * (1 << TIMER_SHIFT);
|
||||
timer_update_outstanding();
|
||||
// fdc.drive = fdc.params[0] & 3;
|
||||
if (command_has_drivesel[discint & 0x1F])
|
||||
{
|
||||
fdc.drive = fdc.params[0] & 3;
|
||||
}
|
||||
fdc_reset_stat = 0;
|
||||
if (fdc.dor & (0x10 << fdc.drive))
|
||||
{
|
||||
motoron = 0;
|
||||
disc_drivesel = fdc.drive;
|
||||
disc_set_drivesel(fdc.drive);
|
||||
motoron = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
motoron = 0;
|
||||
}
|
||||
switch (discint & 0x1F)
|
||||
{
|
||||
case 2: /*Read a track*/
|
||||
fdc_reset_fifo_buf();
|
||||
fdc_rate(fdc.drive);
|
||||
fdc.head=fdc.params[2];
|
||||
fdd_set_head(fdc.drive, (fdc.params[0] & 4) ? 1 : 0);
|
||||
@@ -877,6 +877,7 @@ bad_command:
|
||||
|
||||
case 5: /*Write data*/
|
||||
case 9: /*Write deleted data*/
|
||||
fdc_reset_fifo_buf();
|
||||
fdc_rate(fdc.drive);
|
||||
fdc.head=fdc.params[2];
|
||||
fdd_set_head(fdc.drive, (fdc.params[0] & 4) ? 1 : 0);
|
||||
@@ -900,12 +901,24 @@ bad_command:
|
||||
fdc.pos = 0;
|
||||
if (fdc.pcjr)
|
||||
fdc.stat = 0xb0;
|
||||
else
|
||||
{
|
||||
if (fdc.dma)
|
||||
{
|
||||
fdc.stat = 0x90;
|
||||
}
|
||||
else
|
||||
{
|
||||
fdc.stat = 0xb0;
|
||||
}
|
||||
}
|
||||
// ioc_fiq(IOC_FIQ_DISC_DATA);
|
||||
break;
|
||||
|
||||
case 0x11: /*Scan equal*/
|
||||
case 0x19: /*Scan low or equal*/
|
||||
case 0x1D: /*Scan high or equal*/
|
||||
fdc_reset_fifo_buf();
|
||||
fdc_rate(fdc.drive);
|
||||
fdc.head=fdc.params[2];
|
||||
fdd_set_head(fdc.drive, (fdc.params[0] & 4) ? 1 : 0);
|
||||
@@ -929,6 +942,17 @@ bad_command:
|
||||
fdc.pos = 0;
|
||||
if (fdc.pcjr)
|
||||
fdc.stat = 0xb0;
|
||||
else
|
||||
{
|
||||
if (fdc.dma)
|
||||
{
|
||||
fdc.stat = 0x90;
|
||||
}
|
||||
else
|
||||
{
|
||||
fdc.stat = 0xb0;
|
||||
}
|
||||
}
|
||||
// ioc_fiq(IOC_FIQ_DISC_DATA);
|
||||
break;
|
||||
|
||||
@@ -936,6 +960,7 @@ bad_command:
|
||||
if (fdc.params[0] & 0x80) fdc.sc = fdc.params[7];
|
||||
case 6: /*Read data*/
|
||||
case 0xC: /*Read deleted data*/
|
||||
fdc_reset_fifo_buf();
|
||||
fdc_rate(fdc.drive);
|
||||
fdc.head=fdc.params[2];
|
||||
fdd_set_head(fdc.drive, (fdc.params[0] & 4) ? 1 : 0);
|
||||
@@ -1176,7 +1201,7 @@ void fdc_poll_readwrite_finish(int compare)
|
||||
fdc.res[6] |= 0x40;
|
||||
fdc.wrong_am = 0;
|
||||
}
|
||||
if (compare)
|
||||
if (compare == 1)
|
||||
{
|
||||
if (!fdc.satisfying_sectors)
|
||||
{
|
||||
@@ -1187,6 +1212,18 @@ void fdc_poll_readwrite_finish(int compare)
|
||||
fdc.res[6] |= 8;
|
||||
}
|
||||
}
|
||||
else if (compare == 2)
|
||||
{
|
||||
if (fdc.satisfying_sectors & 1)
|
||||
{
|
||||
fdc.res[5] |= 0x20;
|
||||
}
|
||||
if (fdc.satisfying_sectors & 2)
|
||||
{
|
||||
fdc.res[5] |= 0x20;
|
||||
fdc.res[6] |= 0x20;
|
||||
}
|
||||
}
|
||||
fdc.res[7]=fdc.rw_track;
|
||||
fdc.res[8]=fdc.head;
|
||||
fdc.res[9]=fdc.sector;
|
||||
@@ -1208,7 +1245,7 @@ void fdc_no_dma_end(int compare)
|
||||
fdc.res[6] |= 0x40;
|
||||
fdc.wrong_am = 0;
|
||||
}
|
||||
if (compare)
|
||||
if (compare == 1)
|
||||
{
|
||||
if (!fdc.satisfying_sectors)
|
||||
{
|
||||
@@ -1219,6 +1256,18 @@ void fdc_no_dma_end(int compare)
|
||||
fdc.res[6] |= 8;
|
||||
}
|
||||
}
|
||||
else if (compare == 2)
|
||||
{
|
||||
if (fdc.satisfying_sectors & 1)
|
||||
{
|
||||
fdc.res[5] |= 0x20;
|
||||
}
|
||||
if (fdc.satisfying_sectors & 2)
|
||||
{
|
||||
fdc.res[5] |= 0x20;
|
||||
fdc.res[6] |= 0x20;
|
||||
}
|
||||
}
|
||||
fdc.res[7]=fdc.rw_track;
|
||||
fdc.res[8]=fdc.head;
|
||||
fdc.res[9]=fdc.sector;
|
||||
@@ -1259,7 +1308,7 @@ void fdc_callback()
|
||||
// pclog("Read a track callback, eot=%i\n", fdc.eot[fdc.drive]);
|
||||
if (!fdc.eot[fdc.drive] || fdc.tc)
|
||||
{
|
||||
fdc_poll_readwrite_finish(0);
|
||||
fdc_poll_readwrite_finish(2);
|
||||
return;
|
||||
}
|
||||
else
|
||||
@@ -1587,6 +1636,11 @@ void fdc_overrun()
|
||||
paramstogo=7;
|
||||
}
|
||||
|
||||
int fdc_is_verify()
|
||||
{
|
||||
return (fdc.deleted & 2) ? 1 : 0;
|
||||
}
|
||||
|
||||
int fdc_data(uint8_t data)
|
||||
{
|
||||
if (fdc.deleted & 2)
|
||||
@@ -1665,6 +1719,14 @@ void fdc_finishread()
|
||||
// rpclog("fdc_finishread\n");
|
||||
}
|
||||
|
||||
void fdc_track_finishread(int condition)
|
||||
{
|
||||
fdc.satisfying_sectors |= condition;
|
||||
fdc.inread = 0;
|
||||
fdc_callback();
|
||||
// rpclog("fdc_finishread\n");
|
||||
}
|
||||
|
||||
void fdc_sector_finishcompare(int satisfying)
|
||||
{
|
||||
fdc.satisfying_sectors++;
|
||||
|
||||
@@ -52,3 +52,5 @@ void fdc_finishcompare(int satisfying);
|
||||
void fdc_finishread();
|
||||
void fdc_sector_finishcompare(int satisfying);
|
||||
void fdc_sector_finishread();
|
||||
void fdc_track_finishread(int condition);
|
||||
int fdc_is_verify();
|
||||
|
||||
@@ -194,7 +194,7 @@ void fdc37c932fr_write(uint16_t port, uint8_t val, void *priv)
|
||||
else
|
||||
{
|
||||
valxor = val ^ fdc37c932fr_ld_regs[fdc37c932fr_regs[7]][fdc37c932fr_curreg];
|
||||
if ((fdc37c932fr_curreg & 0xF0 == 0x70) && (fdc37c932fr_regs[7] < 4)) return;
|
||||
if (((fdc37c932fr_curreg & 0xF0) == 0x70) && (fdc37c932fr_regs[7] < 4)) return;
|
||||
/* Block writes to IDE configuration. */
|
||||
if (fdc37c932fr_regs[7] == 1) return;
|
||||
if (fdc37c932fr_regs[7] == 2) return;
|
||||
@@ -474,6 +474,7 @@ void fdc37c932fr_init()
|
||||
fdc_update_rwc(1, 0);
|
||||
fdc_update_drvrate(0, 0);
|
||||
fdc_update_drvrate(1, 0);
|
||||
fdc_update_max_track(79);
|
||||
io_sethandler(0xe0, 0x0006, fdc37c932fr_gpio_read, NULL, NULL, fdc37c932fr_gpio_write, NULL, NULL, NULL);
|
||||
io_sethandler(0xea, 0x0002, fdc37c932fr_gpio_read, NULL, NULL, fdc37c932fr_gpio_write, NULL, NULL, NULL);
|
||||
io_sethandler(0x3f0, 0x0002, fdc37c932fr_read, NULL, NULL, fdc37c932fr_write, NULL, NULL, NULL);
|
||||
|
||||
15
src/fdd.c
15
src/fdd.c
@@ -14,11 +14,6 @@ static struct
|
||||
|
||||
int densel;
|
||||
|
||||
int drate;
|
||||
|
||||
int kbps;
|
||||
int fdc_kbps;
|
||||
|
||||
int head;
|
||||
} fdd[2];
|
||||
|
||||
@@ -63,19 +58,19 @@ static struct
|
||||
},
|
||||
{ /*3.5" DD*/
|
||||
.max_track = 86,
|
||||
.flags = FLAG_RPM_300 | FLAG_HOLE0
|
||||
.flags = FLAG_RPM_300 | FLAG_HOLE0 | FLAG_DOUBLE_STEP
|
||||
},
|
||||
{ /*3.5" HD*/
|
||||
.max_track = 86,
|
||||
.flags = FLAG_RPM_300 | FLAG_HOLE0 | FLAG_HOLE1
|
||||
.flags = FLAG_RPM_300 | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP
|
||||
},
|
||||
{ /*3.5" HD 3-Mode*/
|
||||
.max_track = 86,
|
||||
.flags = FLAG_RPM_300 | FLAG_RPM_360 | FLAG_HOLE0 | FLAG_HOLE1
|
||||
.flags = FLAG_RPM_300 | FLAG_RPM_360 | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP
|
||||
},
|
||||
{ /*3.5" ED*/
|
||||
.max_track = 86,
|
||||
.flags = FLAG_RPM_300 | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_HOLE2
|
||||
.flags = FLAG_RPM_300 | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_HOLE2 | FLAG_DOUBLE_STEP
|
||||
}
|
||||
};
|
||||
|
||||
@@ -186,7 +181,7 @@ int fdd_can_read_medium(int drive)
|
||||
|
||||
int fdd_doublestep_40(int drive)
|
||||
{
|
||||
return drive_types[fdd[drive].type].flags & FLAG_DOUBLE_STEP;
|
||||
return (drive_types[fdd[drive].type].flags & FLAG_DOUBLE_STEP) ? 1 : 0;
|
||||
}
|
||||
|
||||
void fdd_set_type(int drive, int type)
|
||||
|
||||
@@ -1913,8 +1913,8 @@ static int decode_lowlevel_track (FDI *fdi, int track, struct fdi_cache *cache)
|
||||
idxp[i] = sum;
|
||||
}
|
||||
len = totalavg / 100000;
|
||||
outlog("totalavg=%u index=%d (%d) maxidx=%d weakbits=%d len=%d\n",
|
||||
totalavg, indexoffset, maxidx, weakbits, len);
|
||||
/* 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;
|
||||
@@ -2073,8 +2073,8 @@ int fdi2raw_loadrevolution_2 (FDI *fdi, uae_u16 *mfmbuf, uae_u16 *tracktiming, i
|
||||
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);
|
||||
/* 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;
|
||||
@@ -2126,8 +2126,8 @@ int fdi2raw_loadtrack (FDI *fdi, uae_u16 *mfmbuf, uae_u16 *tracktiming, int trac
|
||||
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);
|
||||
/* 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) {
|
||||
|
||||
|
||||
@@ -347,7 +347,7 @@ char discfns[2][256];
|
||||
int driveempty[2];
|
||||
|
||||
#define MDA ((gfxcard==GFX_MDA || gfxcard==GFX_HERCULES || gfxcard==GFX_INCOLOR) && (romset<ROM_TANDY || romset>=ROM_IBMAT))
|
||||
#define VGA ((gfxcard>=GFX_TVGA || romset==ROM_ACER386) && gfxcard!=GFX_INCOLOR && gfxcard!=GFX_COMPAQ_EGA && gfxcard!=GFX_SUPER_EGA && romset!=ROM_PC1640 && romset!=ROM_PC1512 && romset!=ROM_TANDY && romset!=ROM_PC200)
|
||||
#define VGA ((gfxcard>=GFX_TVGA || romset==ROM_ACER386) && gfxcard!=GFX_COLORPLUS && gfxcard!=GFX_INCOLOR && gfxcard!=GFX_COMPAQ_EGA && gfxcard!=GFX_SUPER_EGA && romset!=ROM_PC1640 && romset!=ROM_PC1512 && romset!=ROM_TANDY && romset!=ROM_PC200)
|
||||
#define PCJR (romset == ROM_IBMPCJR)
|
||||
#define AMIBIOS (romset==ROM_AMI386 || romset==ROM_AMI486 || romset == ROM_WIN486)
|
||||
|
||||
@@ -413,7 +413,6 @@ enum
|
||||
ROM_P55VA, /*Epox P55-VA / 430VX / Award BIOS / SMC FDC37C932FR*/
|
||||
|
||||
ROM_440FX, /*Unknown / 440FX / Award BIOS / SMC FDC37C665*/
|
||||
ROM_KN97, /*ASUS KN-97 / 440FX / Award BIOS / Winbond W8387F*/
|
||||
|
||||
ROM_MARL, /*Intel Advanced/ML / 430HX / AMI BIOS / National Semiconductors PC87306*/
|
||||
ROM_THOR, /*Intel Advanced/ATX / 430FX / AMI BIOS / National Semiconductors PC87306*/
|
||||
@@ -448,7 +447,8 @@ enum
|
||||
GFX_VIRGEDX, /*S3 Virge/DX*/
|
||||
GFX_PHOENIX_TRIO32, /*S3 732/Trio32 (Phoenix)*/
|
||||
GFX_PHOENIX_TRIO64, /*S3 764/Trio64 (Phoenix)*/
|
||||
GFX_INCOLOR, /* Hercules InColor */
|
||||
GFX_INCOLOR, /* Hercules InColor */
|
||||
GFX_COLORPLUS, /* Plantronics ColorPlus */
|
||||
GFX_ET4000W32C, /*Tseng ET4000/W32p (Cardex) (STG RAMDAC) */
|
||||
GFX_COMPAQ_EGA, /*Compaq EGA*/
|
||||
GFX_SUPER_EGA, /*Using Chips & Technologies SuperEGA BIOS*/
|
||||
@@ -633,3 +633,5 @@ extern char nvr_path[1024];
|
||||
extern int path_len;
|
||||
|
||||
char *nvr_concat(char *to_concat);
|
||||
|
||||
int mem_a20_state;
|
||||
|
||||
28
src/ide.c
28
src/ide.c
@@ -751,8 +751,6 @@ static void loadhd(IDE *ide, int d, const char *fn)
|
||||
uint32_t sector_size = 512;
|
||||
uint32_t zero = 0;
|
||||
uint32_t full_size = 0;
|
||||
uint32_t transl_spt = 0;
|
||||
uint32_t transl_hpc = 0;
|
||||
int c;
|
||||
ide->base = 0;
|
||||
ide->hdi = 0;
|
||||
@@ -1327,7 +1325,8 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
|
||||
case WIN_CHECKPOWERMODE1:
|
||||
ide->atastat = BUSY_STAT;
|
||||
timer_process();
|
||||
callbackide(ide_board);
|
||||
idecallback[ide_board]=30*IDE_TIME;
|
||||
// callbackide(ide_board);
|
||||
// idecallback[ide_board]=200*IDE_TIME;
|
||||
timer_update_outstanding();
|
||||
return;
|
||||
@@ -1358,7 +1357,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val)
|
||||
ide->error = ABRT_ERR;
|
||||
ide_irq_raise(ide);
|
||||
/* fatal("Bad IDE command %02X\n", val);*/
|
||||
pclog("Bad IDE command %02X\n", val);
|
||||
// pclog("Bad IDE command %02X\n", val);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1640,6 +1639,9 @@ void callbackide(int ide_board)
|
||||
return;
|
||||
|
||||
case WIN_CHECKPOWERMODE1:
|
||||
if (IDE_DRIVE_IS_CDROM(ide)) {
|
||||
goto abort_cmd;
|
||||
}
|
||||
ide->secount = 0xFF;
|
||||
ide->atastat = READY_STAT | DSC_STAT;
|
||||
ide_irq_raise(ide);
|
||||
@@ -1671,16 +1673,12 @@ void callbackide(int ide_board)
|
||||
|
||||
case WIN_READ_DMA:
|
||||
if (IDE_DRIVE_IS_CDROM(ide)) {
|
||||
atapi->readsector(ide->buffer, ide_get_sector(ide));
|
||||
ide->pos=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = ide_get_sector(ide) * 512;
|
||||
fseeko64(ide->hdfile, ide->base + addr, SEEK_SET);
|
||||
fread(ide->buffer, 512, 1, ide->hdfile);
|
||||
ide->pos=0;
|
||||
goto abort_cmd;
|
||||
}
|
||||
addr = ide_get_sector(ide) * 512;
|
||||
fseeko64(ide->hdfile, addr, SEEK_SET);
|
||||
fread(ide->buffer, 512, 1, ide->hdfile);
|
||||
ide->pos=0;
|
||||
|
||||
if (ide_bus_master_read_sector)
|
||||
{
|
||||
@@ -1710,7 +1708,7 @@ void callbackide(int ide_board)
|
||||
return;
|
||||
|
||||
case WIN_READ_MULTIPLE:
|
||||
/* According to the official ATAPI reference:
|
||||
/* According to the official ATA reference:
|
||||
|
||||
If the Read Multiple command is attempted before the Set Multiple Mode
|
||||
command has been executed or when Read Multiple commands are
|
||||
@@ -2119,6 +2117,7 @@ static int atapi_read_structure(IDE *ide, int format,
|
||||
{
|
||||
int layer = packet[6];
|
||||
uint64_t total_sectors;
|
||||
total_sectors = (uint64_t) atapi->size();
|
||||
|
||||
if (layer != 0)
|
||||
return -ASC_INV_FIELD_IN_CMD_PACKET;
|
||||
@@ -3209,7 +3208,6 @@ atapi_out:
|
||||
|
||||
case GPCMD_SEND_DVD_STRUCTURE:
|
||||
default:
|
||||
bad_atapi_command:
|
||||
ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/
|
||||
ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR;
|
||||
if (atapi_sense.sensekey == SENSE_UNIT_ATTENTION)
|
||||
|
||||
@@ -280,25 +280,12 @@ void *intel_flash_init(uint8_t type)
|
||||
case ROM_MB500N:
|
||||
strcpy(flash_path, "roms/mb500n/");
|
||||
break;
|
||||
#if 0
|
||||
case ROM_P54TP4XE:
|
||||
strcpy(flash_path, "roms/p54tp4xe/");
|
||||
break;
|
||||
#endif
|
||||
case ROM_ACERM3A:
|
||||
strcpy(flash_path, "roms/acerm3a/");
|
||||
break;
|
||||
case ROM_ACERV35N:
|
||||
strcpy(flash_path, "roms/acerv35n/");
|
||||
break;
|
||||
case ROM_P55TVP4:
|
||||
strcpy(flash_path, "roms/p55tvp4/");
|
||||
break;
|
||||
#if 0
|
||||
case ROM_P55T2P4:
|
||||
strcpy(flash_path, "roms/p55t2p4/");
|
||||
break;
|
||||
#endif
|
||||
case ROM_430VX:
|
||||
strcpy(flash_path, "roms/430vx/");
|
||||
break;
|
||||
@@ -308,9 +295,6 @@ void *intel_flash_init(uint8_t type)
|
||||
case ROM_440FX:
|
||||
strcpy(flash_path, "roms/440fx/");
|
||||
break;
|
||||
case ROM_KN97:
|
||||
strcpy(flash_path, "roms/kn97/");
|
||||
break;
|
||||
case ROM_MARL:
|
||||
strcpy(flash_path, "roms/marl/");
|
||||
break;
|
||||
@@ -394,7 +378,6 @@ void *intel_flash_init(uint8_t type)
|
||||
}
|
||||
|
||||
/* Load the DMI block. */
|
||||
memset(fpath, 0, 1024);
|
||||
strcpy(fpath, flash_path);
|
||||
strcat(fpath, "dmi.bin");
|
||||
f = romfopen(fpath, "rb");
|
||||
@@ -405,7 +388,6 @@ void *intel_flash_init(uint8_t type)
|
||||
}
|
||||
|
||||
/* Load the ESCD block. */
|
||||
memset(fpath, 0, 1024);
|
||||
strcpy(fpath, flash_path);
|
||||
strcat(fpath, "escd.bin");
|
||||
f = romfopen(fpath, "rb");
|
||||
@@ -460,7 +442,6 @@ void intel_flash_close(void *p)
|
||||
fclose(f);
|
||||
|
||||
/* Save the DMI block. */
|
||||
memset(fpath, 0, 1024);
|
||||
strcpy(fpath, flash_path);
|
||||
strcat(fpath, "dmi.bin");
|
||||
f = romfopen(fpath, "wb");
|
||||
@@ -468,7 +449,6 @@ void intel_flash_close(void *p)
|
||||
fclose(f);
|
||||
|
||||
/* Save the ESCD block. */
|
||||
memset(fpath, 0, 1024);
|
||||
strcpy(fpath, flash_path);
|
||||
strcat(fpath, "escd.bin");
|
||||
f = romfopen(fpath, "wb");
|
||||
|
||||
@@ -73,7 +73,7 @@ void jim_init()
|
||||
europc_rtc.dat[3]=1;
|
||||
europc_rtc.dat[4]=1;
|
||||
europc_rtc.dat[5]=0x88;
|
||||
if (gfxcard==GFX_CGA) viddat=0x12;
|
||||
if (gfxcard==GFX_CGA || gfxcard == GFX_COLORPLUS) viddat=0x12;
|
||||
else if (gfxcard==GFX_MDA || gfxcard==GFX_HERCULES || gfxcard==GFX_INCOLOR) viddat=3;
|
||||
else viddat=0x10;
|
||||
europc_rtc.dat[0xB]=viddat;
|
||||
|
||||
136
src/lzf/Changes
Normal file
136
src/lzf/Changes
Normal file
@@ -0,0 +1,136 @@
|
||||
3.6 Mon Feb 7 17:37:31 CET 2011
|
||||
- fixed hash calculation in C♯ version (Tiago Freitas Leal).
|
||||
- unroll copy for small sizes, use memcpy for larger sizes,
|
||||
greatly speeding up decompression in most cases.
|
||||
- finally disable rep movsb - it's a big loss on modern intel cpus,
|
||||
and only a small win on amd cpus.
|
||||
- improve C++ compatibility of the code.
|
||||
- slightly improve compressor speed.
|
||||
- halved memory requirements for compressor on 64 bit architectures,
|
||||
which can improve the speed quite a bit on older cpus.
|
||||
|
||||
3.5 Fri May 1 02:28:42 CEST 2009
|
||||
- lzf_compress did sometimes write one octet past the given output
|
||||
buffer (analyzed and nice testcase by Salvatore Sanfilippo).
|
||||
|
||||
3.4 Tue Sep 2 06:45:00 CEST 2008
|
||||
- the fix from 3.3 introduced a compression bug, which is fixed in
|
||||
this release (which explains the mysterious prerelease...). Thanks
|
||||
once more to Clément Calmels.
|
||||
|
||||
3.3 Mon Aug 25 03:17:42 CEST 2008
|
||||
- lzf_compress could access memory after the given input buffer
|
||||
when outputting back references. reported with nice testcase
|
||||
by Clément Calmels.
|
||||
|
||||
3.2 Fri May 9 18:52:23 CEST 2008
|
||||
- include a workaround for failing POSIX and real-world compliance
|
||||
on 64 bit windows (microsoft claims to support POSIX, but is far
|
||||
from it). (bug found and analysed nicely by John Lilley).
|
||||
|
||||
3.1 Fri Nov 30 11:33:04 CET 2007
|
||||
- IMPORTANT BUGFIX: a too long final literal run would corrupt data
|
||||
in the encoder (this was introduced in 3.0 only, earlier versions
|
||||
are safe).
|
||||
|
||||
3.0 Tue Nov 13 22:13:09 CET 2007
|
||||
- switched to 2-clause bsd with "GPL v2 or any later version" option.
|
||||
- speed up compression by ~10-15% in common cases
|
||||
by some manual unrolling.
|
||||
- import some compiler tricks from JSON::XS, for further speed-ups.
|
||||
- tune hash functions depending on ULTRA_FAST or VERY_FAST settings.
|
||||
- for typical binary data (e.g. /bin/bash, memory dumps,
|
||||
canterbury corpus etc.), speed is now comparable to fastlz, but
|
||||
with better compression ratio. with ULTRA_FAST, it's typically
|
||||
3-15% faster than fastlz while still maintaining a similar ratio.
|
||||
(amd64 and core 2 duo, ymmv). thanks a lot for the competition :)
|
||||
- undo inline assembly in compressor, it is no longer helpful.
|
||||
- no changes to the decompressor.
|
||||
- use a HLOG of 16 by default now (formerly 15).
|
||||
|
||||
2.1 Fri Nov 2 13:34:42 CET 2007
|
||||
- switched to a 2-clause bsd license with GPL exception.
|
||||
- get rid of memcpy.
|
||||
- tentatively use rep movsb on x86 and x86_64 (gcc only) for a
|
||||
moderate speed improvement.
|
||||
- applied patch by Kein-Hong Man to maske lzf.c compile under
|
||||
the crippled mingw32 environment.
|
||||
|
||||
2.0 Fri Feb 16 23:11:18 CET 2007
|
||||
- replaced lzf demo by industrial-strength lzf utility with behaviour
|
||||
similar other compression utilities. Thanks for Stefan Traby for
|
||||
rewriting it!
|
||||
- fix state arg prototype.
|
||||
|
||||
1.7 Wed Sep 27 17:29:15 CEST 2006
|
||||
- remove bogus "unlzf" patch.
|
||||
note to self: never accept well-meant patches.
|
||||
- make lzf more robust in presence of padding bytes or sudden eof.
|
||||
|
||||
1.6 Fri Jul 7 17:31:26 CEST 2006
|
||||
- the lzf example utility will now uncompress if invoked
|
||||
as "unlzf" (patch by Scott Feeney).
|
||||
- add CHECK_INPUT option that adds more checks for input
|
||||
data validity.
|
||||
- help applications that do not pass in the correct length
|
||||
(such as php) by returning either EINVAL or E2BIG.
|
||||
- default HLOG size is now 15 (cpu caches have increased).
|
||||
- documentation fixes.
|
||||
|
||||
1.51 Thu Apr 14 22:15:46 CEST 2005
|
||||
- incorporated C♯ implementation of both the en- and decoder,
|
||||
written by "Oren J. Maurice".
|
||||
You can find it in the cs/ subdirectory.
|
||||
- make FRST, NEXT IDX overridable if lzf_c.c is directly included
|
||||
in the code.
|
||||
|
||||
1.5 Tue Mar 8 20:23:23 CET 2005
|
||||
- incorporated improvements by Adam D. Moss,
|
||||
which includes a new VERY_FAST mode which is
|
||||
a bit slower than ULTRA_FAST but much better,
|
||||
and enabled it as default.
|
||||
|
||||
1.401 Thu Mar 3 18:00:52 CET 2005
|
||||
- use cstring in c++, not string.h.
|
||||
- change of contact address.
|
||||
|
||||
1.4 Wed Dec 15 08:08:49 CET 2004
|
||||
- very very slight tuning of the hashing function.
|
||||
|
||||
1.3 Thu Mar 25 15:41:17 CET 2004
|
||||
- changed license of lzf core code to explicitly allow
|
||||
relicensing under the GPLv2.
|
||||
- added VPATH support as suggested by Björn Eriksson.
|
||||
|
||||
1.2 Mon Dec 29 13:47:28 CET 2003
|
||||
- avoid spurious memory accesses after the to-be-compressed
|
||||
memory region. originally reported by Michal Zalewski.
|
||||
- flip LZF_STACK_ARG meaning (to be correct).
|
||||
|
||||
1.1 Tue Dec 23 05:48:32 CET 2003
|
||||
- removed #warn directive, it's not worth the hassle.
|
||||
- add LZF_STACK_ARG and AVOID_ERRNO configurations
|
||||
for embedded systems.
|
||||
- make it compile cleanly as c++.
|
||||
- some small documentation and code fixes.
|
||||
|
||||
1.0 Sun Nov 17 12:37:37 CET 2002
|
||||
- slightly better compression ratio, almost unmeasurably
|
||||
slower.
|
||||
- some documentation fixes.
|
||||
|
||||
0.4 Thu Jun 13 14:11:10 CEST 2002
|
||||
- typoe fix.
|
||||
- lzf demo program now properly decompresses small files.
|
||||
- fix another 64 bit issue, found by Laurent Deniel.
|
||||
|
||||
0.3 Tue Jan 16 13:21:14 CET 2001
|
||||
- fix silly beginners 32/64 bit mistake.
|
||||
|
||||
0.2 Thu Jan 4 05:56:42 CET 2001
|
||||
- now totally independent of autoconfig, for
|
||||
easy inclusion into other programs.
|
||||
- much better fine-tuning, faster and better than 0.1.
|
||||
|
||||
0.1 2000
|
||||
- initial release.
|
||||
27
src/lzf/LICENSE
Normal file
27
src/lzf/LICENSE
Normal file
@@ -0,0 +1,27 @@
|
||||
Copyright (c) 2000-2009 Marc Alexander Lehmann <schmorp@schmorp.de>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modifica-
|
||||
tion, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
|
||||
CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
|
||||
CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
|
||||
ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Alternatively, the following files carry an additional notice that
|
||||
explicitly allows relicensing under the GPLv2: lzf.c lzf.h lzfP.h lzf_c.c
|
||||
lzf_d.c
|
||||
|
||||
66
src/lzf/Makefile.in
Normal file
66
src/lzf/Makefile.in
Normal file
@@ -0,0 +1,66 @@
|
||||
VERSION = 3.6
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
libdir = @libdir@
|
||||
bindir = @bindir@
|
||||
includedir = @includedir@
|
||||
|
||||
VPATH = @srcdir@
|
||||
|
||||
CC = @CC@
|
||||
CPPFLAGS = -I. @CPPFLAGS@
|
||||
CFLAGS = @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
RANLIB = @RANLIB@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
all: Makefile lzf
|
||||
|
||||
clean:
|
||||
-rm -f *.o *.a lzf bench
|
||||
|
||||
lzf_c.o: lzf_c.c lzfP.h
|
||||
|
||||
lzf_d.o: lzf_d.c lzfP.h
|
||||
|
||||
lzf.o: lzf.c
|
||||
|
||||
lzf: lzf.o liblzf.a
|
||||
|
||||
lzfP.h: lzf.h config.h
|
||||
|
||||
liblzf.a: lzf_c.o lzf_d.o
|
||||
rm -f $@
|
||||
$(AR) rc $@ $^
|
||||
$(RANLIB) $@
|
||||
|
||||
install: all
|
||||
$(INSTALL) -d $(bindir)
|
||||
$(INSTALL) -m 755 lzf $(bindir)
|
||||
$(INSTALL) -d $(includedir)
|
||||
$(INSTALL_DATA) lzf.h $(includedir)
|
||||
$(INSTALL) -d $(libdir)
|
||||
$(INSTALL_DATA) liblzf.a $(libdir)
|
||||
|
||||
dist:
|
||||
mkdir liblzf-$(VERSION)
|
||||
tar c LICENSE README Makefile.in config.h.in \
|
||||
configure configure.ac install-sh \
|
||||
cs/README cs/CLZF.cs \
|
||||
lzf.h lzfP.h lzf_c.c lzf_d.c \
|
||||
crc32.h lzf.c Changes \
|
||||
| tar xpC liblzf-$(VERSION)
|
||||
-chown -R root.root liblzf-$(VERSION)
|
||||
chmod -R u=rwX,go=rX liblzf-$(VERSION)
|
||||
tar cvf - liblzf-$(VERSION) | gzip -9 >liblzf-$(VERSION).tar.gz
|
||||
rm -rf liblzf-$(VERSION)
|
||||
ls -l liblzf-$(VERSION).tar.gz
|
||||
|
||||
Makefile: Makefile.in
|
||||
./config.status
|
||||
|
||||
bench: Makefile liblzf.a bench.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -g -o bench bench.c -L. -llzf
|
||||
|
||||
29
src/lzf/README
Normal file
29
src/lzf/README
Normal file
@@ -0,0 +1,29 @@
|
||||
DESCRIPTION
|
||||
LZF is an extremely fast (not that much slower than a pure memcpy)
|
||||
compression algorithm. It is ideal for applications where you want to
|
||||
save *some* space but not at the cost of speed. It is ideal for
|
||||
repetitive data as well. The module is self-contained and very small.
|
||||
|
||||
It's written in ISO-C with no external dependencies other than what
|
||||
C provides and can easily be #include'd into your code, no makefile
|
||||
changes or library builds requires.
|
||||
|
||||
A C♯ implementation without external dependencies is available, too.
|
||||
|
||||
I do not know for certain whether any patents in any countries apply
|
||||
to this algorithm, but at the moment it is believed that it is free
|
||||
from any patents. More importantly, it is also free to use in every
|
||||
software package (see LICENSE).
|
||||
|
||||
See the lzf.h file for details on how the functions in this
|
||||
mini-library are to be used.
|
||||
|
||||
NOTE: This package contains a very bare-bones command-line utility
|
||||
which is neither optimized for speed nor for compression. This library
|
||||
is really intended to be used inside larger programs.
|
||||
|
||||
AUTHOR
|
||||
This library was written by Marc Lehmann <schmorp@schmorp.de> (See also
|
||||
http://software.schmorp.de/pkg/liblzf).
|
||||
|
||||
|
||||
16
src/lzf/config.h
Normal file
16
src/lzf/config.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/* config.h.in. Generated automatically from configure.in by autoheader 2.13. */
|
||||
|
||||
/* Define to empty if the keyword does not work. */
|
||||
#undef const
|
||||
|
||||
/* Define if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* The number of bytes in a int. */
|
||||
#undef SIZEOF_INT
|
||||
|
||||
/* The number of bytes in a long. */
|
||||
#undef SIZEOF_LONG
|
||||
|
||||
/* The number of bytes in a short. */
|
||||
#undef SIZEOF_SHORT
|
||||
7871
src/lzf/configure
vendored
Normal file
7871
src/lzf/configure
vendored
Normal file
File diff suppressed because it is too large
Load Diff
25
src/lzf/configure.ac
Normal file
25
src/lzf/configure.ac
Normal file
@@ -0,0 +1,25 @@
|
||||
AC_INIT
|
||||
AC_CONFIG_SRCDIR([lzfP.h])
|
||||
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
|
||||
AC_GNU_SOURCE
|
||||
AC_SYS_LARGEFILE
|
||||
AC_PROG_CC
|
||||
AC_PROG_RANLIB
|
||||
AC_PROG_INSTALL
|
||||
AC_HEADER_STDC
|
||||
|
||||
AC_C_CONST
|
||||
AC_C_INLINE
|
||||
AC_CHECK_HEADERS(getopt.h)
|
||||
AC_CHECK_FUNCS(getopt_long)
|
||||
|
||||
if test "$GCC" = yes; then
|
||||
CFLAGS="$CFLAGS -O3 -funroll-all-loops"
|
||||
else
|
||||
AC_MSG_RESULT(no gcc)
|
||||
fi
|
||||
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_OUTPUT
|
||||
65
src/lzf/crc32.h
Normal file
65
src/lzf/crc32.h
Normal file
@@ -0,0 +1,65 @@
|
||||
#ifndef CRC32_H
|
||||
#define CRC32_H
|
||||
|
||||
/* crc32 0xdebb20e3 table and supplementary functions. */
|
||||
|
||||
static const u32 crc_32_tab[] =
|
||||
{
|
||||
0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
|
||||
0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
|
||||
0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
|
||||
0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
|
||||
0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
|
||||
0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
|
||||
0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
|
||||
0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
|
||||
0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
|
||||
0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
|
||||
0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
|
||||
0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
|
||||
0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
|
||||
0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
|
||||
0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
|
||||
0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
|
||||
0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
|
||||
0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
|
||||
0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
|
||||
0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
|
||||
0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
|
||||
0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
|
||||
0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
|
||||
0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
|
||||
0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
|
||||
0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
|
||||
0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
|
||||
0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
|
||||
0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
|
||||
0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
|
||||
0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
|
||||
0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
|
||||
0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
|
||||
0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
|
||||
0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
|
||||
0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
|
||||
0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
|
||||
0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
|
||||
0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
|
||||
0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
|
||||
0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
|
||||
0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
|
||||
0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
|
||||
0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
|
||||
0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
|
||||
0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
|
||||
0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
|
||||
0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
|
||||
0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
|
||||
0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
|
||||
0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
|
||||
0x2d02ef8dL
|
||||
};
|
||||
|
||||
#define crc32(crc,byte) (crc_32_tab[(u8)(crc) ^ (u8)(byte)] ^ ((crc) >> 8))
|
||||
|
||||
#endif
|
||||
|
||||
251
src/lzf/install-sh
Normal file
251
src/lzf/install-sh
Normal file
@@ -0,0 +1,251 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# install - install a program, script, or datafile
|
||||
# This comes from X11R5 (mit/util/scripts/install.sh).
|
||||
#
|
||||
# Copyright 1991 by the Massachusetts Institute of Technology
|
||||
#
|
||||
# Permission to use, copy, modify, distribute, and sell this software and its
|
||||
# documentation for any purpose is hereby granted without fee, provided that
|
||||
# the above copyright notice appear in all copies and that both that
|
||||
# copyright notice and this permission notice appear in supporting
|
||||
# documentation, and that the name of M.I.T. not be used in advertising or
|
||||
# publicity pertaining to distribution of the software without specific,
|
||||
# written prior permission. M.I.T. makes no representations about the
|
||||
# suitability of this software for any purpose. It is provided "as is"
|
||||
# without express or implied warranty.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch. It can only install one file at a time, a restriction
|
||||
# shared with many OS's install programs.
|
||||
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit="${DOITPROG-}"
|
||||
|
||||
|
||||
# put in absolute paths if you don't have them in your path; or use env. vars.
|
||||
|
||||
mvprog="${MVPROG-mv}"
|
||||
cpprog="${CPPROG-cp}"
|
||||
chmodprog="${CHMODPROG-chmod}"
|
||||
chownprog="${CHOWNPROG-chown}"
|
||||
chgrpprog="${CHGRPPROG-chgrp}"
|
||||
stripprog="${STRIPPROG-strip}"
|
||||
rmprog="${RMPROG-rm}"
|
||||
mkdirprog="${MKDIRPROG-mkdir}"
|
||||
|
||||
transformbasename=""
|
||||
transform_arg=""
|
||||
instcmd="$mvprog"
|
||||
chmodcmd="$chmodprog 0755"
|
||||
chowncmd=""
|
||||
chgrpcmd=""
|
||||
stripcmd=""
|
||||
rmcmd="$rmprog -f"
|
||||
mvcmd="$mvprog"
|
||||
src=""
|
||||
dst=""
|
||||
dir_arg=""
|
||||
|
||||
while [ x"$1" != x ]; do
|
||||
case $1 in
|
||||
-c) instcmd="$cpprog"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-d) dir_arg=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-s) stripcmd="$stripprog"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
*) if [ x"$src" = x ]
|
||||
then
|
||||
src=$1
|
||||
else
|
||||
# this colon is to work around a 386BSD /bin/sh bug
|
||||
:
|
||||
dst=$1
|
||||
fi
|
||||
shift
|
||||
continue;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ x"$src" = x ]
|
||||
then
|
||||
echo "install: no input file specified"
|
||||
exit 1
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]; then
|
||||
dst=$src
|
||||
src=""
|
||||
|
||||
if [ -d $dst ]; then
|
||||
instcmd=:
|
||||
chmodcmd=""
|
||||
else
|
||||
instcmd=mkdir
|
||||
fi
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
|
||||
if [ -f $src -o -d $src ]
|
||||
then
|
||||
true
|
||||
else
|
||||
echo "install: $src does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ x"$dst" = x ]
|
||||
then
|
||||
echo "install: no destination specified"
|
||||
exit 1
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
# If destination is a directory, append the input filename; if your system
|
||||
# does not like double slashes in filenames, you may need to add some logic
|
||||
|
||||
if [ -d $dst ]
|
||||
then
|
||||
dst="$dst"/`basename $src`
|
||||
else
|
||||
true
|
||||
fi
|
||||
fi
|
||||
|
||||
## this sed command emulates the dirname command
|
||||
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||
|
||||
# Make sure that the destination directory exists.
|
||||
# this part is taken from Noah Friedman's mkinstalldirs script
|
||||
|
||||
# Skip lots of stat calls in the usual case.
|
||||
if [ ! -d "$dstdir" ]; then
|
||||
defaultIFS='
|
||||
'
|
||||
IFS="${IFS-${defaultIFS}}"
|
||||
|
||||
oIFS="${IFS}"
|
||||
# Some sh's can't handle IFS=/ for some reason.
|
||||
IFS='%'
|
||||
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||
IFS="${oIFS}"
|
||||
|
||||
pathcomp=''
|
||||
|
||||
while [ $# -ne 0 ] ; do
|
||||
pathcomp="${pathcomp}${1}"
|
||||
shift
|
||||
|
||||
if [ ! -d "${pathcomp}" ] ;
|
||||
then
|
||||
$mkdirprog "${pathcomp}"
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
pathcomp="${pathcomp}/"
|
||||
done
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]
|
||||
then
|
||||
$doit $instcmd $dst &&
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
|
||||
else
|
||||
|
||||
# If we're going to rename the final executable, determine the name now.
|
||||
|
||||
if [ x"$transformarg" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
else
|
||||
dstfile=`basename $dst $transformbasename |
|
||||
sed $transformarg`$transformbasename
|
||||
fi
|
||||
|
||||
# don't allow the sed command to completely eliminate the filename
|
||||
|
||||
if [ x"$dstfile" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
# Make a temp file name in the proper directory.
|
||||
|
||||
dsttmp=$dstdir/#inst.$$#
|
||||
|
||||
# Move or copy the file name to the temp name
|
||||
|
||||
$doit $instcmd $src $dsttmp &&
|
||||
|
||||
trap "rm -f ${dsttmp}" 0 &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits
|
||||
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $instcmd $src $dsttmp" command.
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
|
||||
$doit $rmcmd -f $dstdir/$dstfile &&
|
||||
$doit $mvcmd $dsttmp $dstdir/$dstfile
|
||||
|
||||
fi &&
|
||||
|
||||
|
||||
exit 0
|
||||
537
src/lzf/lzf.c
Normal file
537
src/lzf/lzf.c
Normal file
@@ -0,0 +1,537 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Stefan Traby <stefan@hello-penguin.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modifica-
|
||||
* tion, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
|
||||
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
|
||||
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
|
||||
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* the GNU General Public License ("GPL") version 2 or any later version,
|
||||
* in which case the provisions of the GPL are applicable instead of
|
||||
* the above. If you wish to allow the use of your version of this file
|
||||
* only under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the BSD license, indicate your decision
|
||||
* by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete the
|
||||
* provisions above, a recipient may use your version of this file under
|
||||
* either the BSD or the GPL.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include "lzf.h"
|
||||
|
||||
#ifdef HAVE_GETOPT_H
|
||||
# include <getopt.h>
|
||||
#endif
|
||||
|
||||
#define BLOCKSIZE (1024 * 64 - 1)
|
||||
#define MAX_BLOCKSIZE BLOCKSIZE
|
||||
|
||||
typedef unsigned char u8;
|
||||
|
||||
static off_t nr_read, nr_written;
|
||||
|
||||
static const char *imagename;
|
||||
static enum { compress, uncompress, lzcat } mode = compress;
|
||||
static int verbose = 0;
|
||||
static int force = 0;
|
||||
static long blocksize = BLOCKSIZE;
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
|
||||
struct option longopts[] = {
|
||||
{"compress", 0, 0, 'c'},
|
||||
{"decompress", 0, 0, 'd'},
|
||||
{"uncompress", 0, 0, 'd'},
|
||||
{"force", 0, 0, 'f'},
|
||||
{"help", 0, 0, 'h'},
|
||||
{"verbose", 0, 0, 'v'},
|
||||
{"blocksize", 1, 0, 'b'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static const char *opt =
|
||||
"-c --compress compress\n"
|
||||
"-d --decompress decompress\n"
|
||||
"-f --force force overwrite of output file\n"
|
||||
"-h --help give this help\n" "-v --verbose verbose mode\n" "-b # --blocksize # set blocksize\n" "\n";
|
||||
|
||||
#else
|
||||
|
||||
static const char *opt =
|
||||
"-c compress\n"
|
||||
"-d decompress\n"
|
||||
"-f force overwrite of output file\n"
|
||||
"-h give this help\n"
|
||||
"-v verbose mode\n"
|
||||
"-b # set blocksize\n"
|
||||
"\n";
|
||||
|
||||
#endif
|
||||
|
||||
static void
|
||||
usage (int rc)
|
||||
{
|
||||
fprintf (stderr, "\n"
|
||||
"lzf, a very lightweight compression/decompression utility written by Stefan Traby.\n"
|
||||
"uses liblzf written by Marc Lehmann <schmorp@schmorp.de> You can find more info at\n"
|
||||
"http://liblzf.plan9.de/\n"
|
||||
"\n"
|
||||
"usage: lzf [-dufhvb] [file ...]\n"
|
||||
" unlzf [file ...]\n"
|
||||
" lzcat [file ...]\n"
|
||||
"\n%s",
|
||||
opt);
|
||||
|
||||
exit (rc);
|
||||
}
|
||||
|
||||
static inline ssize_t
|
||||
rread (int fd, void *buf, size_t len)
|
||||
{
|
||||
ssize_t rc = 0, offset = 0;
|
||||
char *p = buf;
|
||||
|
||||
while (len && (rc = read (fd, &p[offset], len)) > 0)
|
||||
{
|
||||
offset += rc;
|
||||
len -= rc;
|
||||
}
|
||||
|
||||
nr_read += offset;
|
||||
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/* returns 0 if all written else -1 */
|
||||
static inline ssize_t
|
||||
wwrite (int fd, void *buf, size_t len)
|
||||
{
|
||||
ssize_t rc;
|
||||
char *b = buf;
|
||||
size_t l = len;
|
||||
|
||||
while (l)
|
||||
{
|
||||
rc = write (fd, b, l);
|
||||
if (rc < 0)
|
||||
{
|
||||
fprintf (stderr, "%s: write error: ", imagename);
|
||||
perror ("");
|
||||
return -1;
|
||||
}
|
||||
|
||||
l -= rc;
|
||||
b += rc;
|
||||
}
|
||||
|
||||
nr_written += len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Anatomy: an lzf file consists of any number of blocks in the following format:
|
||||
*
|
||||
* \x00 EOF (optional)
|
||||
* "ZV\0" 2-byte-usize <uncompressed data>
|
||||
* "ZV\1" 2-byte-csize 2-byte-usize <compressed data>
|
||||
* "ZV\2" 4-byte-crc32-0xdebb20e3 (NYI)
|
||||
*/
|
||||
|
||||
|
||||
#define TYPE0_HDR_SIZE 5
|
||||
#define TYPE1_HDR_SIZE 7
|
||||
#define MAX_HDR_SIZE 7
|
||||
#define MIN_HDR_SIZE 5
|
||||
|
||||
static int
|
||||
compress_fd (int from, int to)
|
||||
{
|
||||
ssize_t us, cs, len;
|
||||
u8 buf1[MAX_BLOCKSIZE + MAX_HDR_SIZE + 16];
|
||||
u8 buf2[MAX_BLOCKSIZE + MAX_HDR_SIZE + 16];
|
||||
u8 *header;
|
||||
|
||||
nr_read = nr_written = 0;
|
||||
while ((us = rread (from, &buf1[MAX_HDR_SIZE], blocksize)) > 0)
|
||||
{
|
||||
cs = lzf_compress (&buf1[MAX_HDR_SIZE], us, &buf2[MAX_HDR_SIZE], us > 4 ? us - 4 : us);
|
||||
if (cs)
|
||||
{
|
||||
header = &buf2[MAX_HDR_SIZE - TYPE1_HDR_SIZE];
|
||||
header[0] = 'Z';
|
||||
header[1] = 'V';
|
||||
header[2] = 1;
|
||||
header[3] = cs >> 8;
|
||||
header[4] = cs & 0xff;
|
||||
header[5] = us >> 8;
|
||||
header[6] = us & 0xff;
|
||||
len = cs + TYPE1_HDR_SIZE;
|
||||
}
|
||||
else
|
||||
{ // write uncompressed
|
||||
header = &buf1[MAX_HDR_SIZE - TYPE0_HDR_SIZE];
|
||||
header[0] = 'Z';
|
||||
header[1] = 'V';
|
||||
header[2] = 0;
|
||||
header[3] = us >> 8;
|
||||
header[4] = us & 0xff;
|
||||
len = us + TYPE0_HDR_SIZE;
|
||||
}
|
||||
|
||||
if (wwrite (to, header, len) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
uncompress_fd (int from, int to)
|
||||
{
|
||||
u8 header[MAX_HDR_SIZE];
|
||||
u8 buf1[MAX_BLOCKSIZE + MAX_HDR_SIZE + 16];
|
||||
u8 buf2[MAX_BLOCKSIZE + MAX_HDR_SIZE + 16];
|
||||
u8 *p;
|
||||
int l, rd;
|
||||
ssize_t rc, cs, us, bytes, over = 0;
|
||||
|
||||
nr_read = nr_written = 0;
|
||||
while (1)
|
||||
{
|
||||
rc = rread (from, header + over, MAX_HDR_SIZE - over);
|
||||
if (rc < 0)
|
||||
{
|
||||
fprintf (stderr, "%s: read error: ", imagename);
|
||||
perror ("");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc += over;
|
||||
over = 0;
|
||||
if (!rc || header[0] == 0)
|
||||
return 0;
|
||||
|
||||
if (rc < MIN_HDR_SIZE || header[0] != 'Z' || header[1] != 'V')
|
||||
{
|
||||
fprintf (stderr, "%s: invalid data stream - magic not found or short header\n", imagename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (header[2])
|
||||
{
|
||||
case 0:
|
||||
cs = -1;
|
||||
us = (header[3] << 8) | header[4];
|
||||
p = &header[TYPE0_HDR_SIZE];
|
||||
break;
|
||||
case 1:
|
||||
if (rc < TYPE1_HDR_SIZE)
|
||||
{
|
||||
goto short_read;
|
||||
}
|
||||
cs = (header[3] << 8) | header[4];
|
||||
us = (header[5] << 8) | header[6];
|
||||
p = &header[TYPE1_HDR_SIZE];
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "%s: unknown blocktype\n", imagename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bytes = cs == -1 ? us : cs;
|
||||
l = &header[rc] - p;
|
||||
|
||||
if (l > 0)
|
||||
memcpy (buf1, p, l);
|
||||
|
||||
if (l > bytes)
|
||||
{
|
||||
over = l - bytes;
|
||||
memmove (header, &p[bytes], over);
|
||||
}
|
||||
|
||||
p = &buf1[l];
|
||||
rd = bytes - l;
|
||||
if (rd > 0)
|
||||
if ((rc = rread (from, p, rd)) != rd)
|
||||
goto short_read;
|
||||
|
||||
if (cs == -1)
|
||||
{
|
||||
if (wwrite (to, buf1, us))
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lzf_decompress (buf1, cs, buf2, us) != us)
|
||||
{
|
||||
fprintf (stderr, "%s: decompress: invalid stream - data corrupted\n", imagename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (wwrite (to, buf2, us))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
short_read:
|
||||
fprintf (stderr, "%s: short data\n", imagename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
open_out (const char *name)
|
||||
{
|
||||
int fd;
|
||||
int m = O_EXCL;
|
||||
|
||||
if (force)
|
||||
m = 0;
|
||||
|
||||
fd = open (name, O_CREAT | O_WRONLY | O_TRUNC | m, 600);
|
||||
#if defined(__MINGW32__)
|
||||
_setmode(fd, _O_BINARY);
|
||||
#endif
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int
|
||||
compose_name (const char *fname, char *oname)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (mode == compress)
|
||||
{
|
||||
if (strlen (fname) > PATH_MAX - 4)
|
||||
{
|
||||
fprintf (stderr, "%s: %s.lzf: name too long", imagename, fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy (oname, fname);
|
||||
strcat (oname, ".lzf");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strlen (fname) > PATH_MAX)
|
||||
{
|
||||
fprintf (stderr, "%s: %s: name too long\n", imagename, fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy (oname, fname);
|
||||
p = &oname[strlen (oname)] - 4;
|
||||
if (p < oname || strcmp (p, ".lzf"))
|
||||
{
|
||||
fprintf (stderr, "%s: %s: unknown suffix\n", imagename, fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*p = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
run_file (const char *fname)
|
||||
{
|
||||
int fd, fd2;
|
||||
int rc;
|
||||
struct stat mystat;
|
||||
char oname[PATH_MAX + 1];
|
||||
|
||||
if (mode != lzcat)
|
||||
if (compose_name (fname, oname))
|
||||
return -1;
|
||||
|
||||
#if !defined(__MINGW32__)
|
||||
rc = lstat (fname, &mystat);
|
||||
#else
|
||||
rc = stat (fname, &mystat);
|
||||
#endif
|
||||
fd = open (fname, O_RDONLY);
|
||||
#if defined(__MINGW32__)
|
||||
_setmode(fd, _O_BINARY);
|
||||
#endif
|
||||
if (rc || fd == -1)
|
||||
{
|
||||
fprintf (stderr, "%s: %s: ", imagename, fname);
|
||||
perror ("");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!S_ISREG (mystat.st_mode))
|
||||
{
|
||||
fprintf (stderr, "%s: %s: not a regular file.\n", imagename, fname);
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mode == lzcat)
|
||||
{
|
||||
rc = uncompress_fd (fd, 1);
|
||||
close (fd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
fd2 = open_out (oname);
|
||||
if (fd2 == -1)
|
||||
{
|
||||
fprintf (stderr, "%s: %s: ", imagename, oname);
|
||||
perror ("");
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mode == compress)
|
||||
{
|
||||
rc = compress_fd (fd, fd2);
|
||||
if (!rc && verbose)
|
||||
fprintf (stderr, "%s: %5.1f%% -- replaced with %s\n",
|
||||
fname, nr_read == 0 ? 0 : 100.0 - nr_written / ((double) nr_read / 100.0), oname);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = uncompress_fd (fd, fd2);
|
||||
if (!rc && verbose)
|
||||
fprintf (stderr, "%s: %5.1f%% -- replaced with %s\n",
|
||||
fname, nr_written == 0 ? 0 : 100.0 - nr_read / ((double) nr_written / 100.0), oname);
|
||||
}
|
||||
|
||||
#if !defined(__MINGW32__)
|
||||
fchmod (fd2, mystat.st_mode);
|
||||
#else
|
||||
chmod (oname, mystat.st_mode);
|
||||
#endif
|
||||
close (fd);
|
||||
close (fd2);
|
||||
|
||||
if (!rc)
|
||||
unlink (fname);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
char *p = argv[0];
|
||||
int optc;
|
||||
int rc = 0;
|
||||
|
||||
errno = 0;
|
||||
p = getenv ("LZF_BLOCKSIZE");
|
||||
if (p)
|
||||
{
|
||||
blocksize = strtoul (p, 0, 0);
|
||||
if (errno || !blocksize || blocksize > MAX_BLOCKSIZE)
|
||||
blocksize = BLOCKSIZE;
|
||||
}
|
||||
|
||||
p = strrchr (argv[0], '/');
|
||||
imagename = p ? ++p : argv[0];
|
||||
|
||||
if (!strncmp (imagename, "un", 2) || !strncmp (imagename, "de", 2))
|
||||
mode = uncompress;
|
||||
|
||||
if (strstr (imagename, "cat"))
|
||||
mode = lzcat;
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
while ((optc = getopt_long (argc, argv, "cdfhvb:", longopts, 0)) != -1)
|
||||
#else
|
||||
while ((optc = getopt (argc, argv, "cdfhvb:")) != -1)
|
||||
#endif
|
||||
{
|
||||
switch (optc)
|
||||
{
|
||||
case 'c':
|
||||
mode = compress;
|
||||
break;
|
||||
case 'd':
|
||||
mode = uncompress;
|
||||
break;
|
||||
case 'f':
|
||||
force = 1;
|
||||
break;
|
||||
case 'h':
|
||||
usage (0);
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'b':
|
||||
errno = 0;
|
||||
blocksize = strtoul (optarg, 0, 0);
|
||||
if (errno || !blocksize || blocksize > MAX_BLOCKSIZE)
|
||||
blocksize = BLOCKSIZE;
|
||||
break;
|
||||
default:
|
||||
usage (1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind == argc)
|
||||
{ // stdin stdout
|
||||
if (!force)
|
||||
{
|
||||
if ((mode == uncompress || mode == lzcat) && isatty (0))
|
||||
{
|
||||
fprintf (stderr, "%s: compressed data not read from a terminal. Use -f to force decompression.\n", imagename);
|
||||
exit (1);
|
||||
}
|
||||
if (mode == compress && isatty (1))
|
||||
{
|
||||
fprintf (stderr, "%s: compressed data not written to a terminal. Use -f to force compression.\n", imagename);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == compress)
|
||||
rc = compress_fd (0, 1);
|
||||
else
|
||||
rc = uncompress_fd (0, 1);
|
||||
|
||||
exit (rc ? 1 : 0);
|
||||
}
|
||||
|
||||
while (optind < argc)
|
||||
rc |= run_file (argv[optind++]);
|
||||
|
||||
exit (rc ? 1 : 0);
|
||||
}
|
||||
|
||||
100
src/lzf/lzf.h
Normal file
100
src/lzf/lzf.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2008 Marc Alexander Lehmann <schmorp@schmorp.de>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modifica-
|
||||
* tion, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
|
||||
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
|
||||
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
|
||||
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* the GNU General Public License ("GPL") version 2 or any later version,
|
||||
* in which case the provisions of the GPL are applicable instead of
|
||||
* the above. If you wish to allow the use of your version of this file
|
||||
* only under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the BSD license, indicate your decision
|
||||
* by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete the
|
||||
* provisions above, a recipient may use your version of this file under
|
||||
* either the BSD or the GPL.
|
||||
*/
|
||||
|
||||
#ifndef LZF_H
|
||||
#define LZF_H
|
||||
|
||||
/***********************************************************************
|
||||
**
|
||||
** lzf -- an extremely fast/free compression/decompression-method
|
||||
** http://liblzf.plan9.de/
|
||||
**
|
||||
** This algorithm is believed to be patent-free.
|
||||
**
|
||||
***********************************************************************/
|
||||
|
||||
#define LZF_VERSION 0x0105 /* 1.5, API version */
|
||||
|
||||
/*
|
||||
* Compress in_len bytes stored at the memory block starting at
|
||||
* in_data and write the result to out_data, up to a maximum length
|
||||
* of out_len bytes.
|
||||
*
|
||||
* If the output buffer is not large enough or any error occurs return 0,
|
||||
* otherwise return the number of bytes used, which might be considerably
|
||||
* more than in_len (but less than 104% of the original size), so it
|
||||
* makes sense to always use out_len == in_len - 1), to ensure _some_
|
||||
* compression, and store the data uncompressed otherwise (with a flag, of
|
||||
* course.
|
||||
*
|
||||
* lzf_compress might use different algorithms on different systems and
|
||||
* even different runs, thus might result in different compressed strings
|
||||
* depending on the phase of the moon or similar factors. However, all
|
||||
* these strings are architecture-independent and will result in the
|
||||
* original data when decompressed using lzf_decompress.
|
||||
*
|
||||
* The buffers must not be overlapping.
|
||||
*
|
||||
* If the option LZF_STATE_ARG is enabled, an extra argument must be
|
||||
* supplied which is not reflected in this header file. Refer to lzfP.h
|
||||
* and lzf_c.c.
|
||||
*
|
||||
*/
|
||||
unsigned int
|
||||
lzf_compress (const void *const in_data, unsigned int in_len,
|
||||
void *out_data, unsigned int out_len);
|
||||
|
||||
/*
|
||||
* Decompress data compressed with some version of the lzf_compress
|
||||
* function and stored at location in_data and length in_len. The result
|
||||
* will be stored at out_data up to a maximum of out_len characters.
|
||||
*
|
||||
* If the output buffer is not large enough to hold the decompressed
|
||||
* data, a 0 is returned and errno is set to E2BIG. Otherwise the number
|
||||
* of decompressed bytes (i.e. the original length of the data) is
|
||||
* returned.
|
||||
*
|
||||
* If an error in the compressed data is detected, a zero is returned and
|
||||
* errno is set to EINVAL.
|
||||
*
|
||||
* This function is very fast, about as fast as a copying loop.
|
||||
*/
|
||||
unsigned int
|
||||
lzf_decompress (const void *const in_data, unsigned int in_len,
|
||||
void *out_data, unsigned int out_len);
|
||||
|
||||
#endif
|
||||
|
||||
185
src/lzf/lzfP.h
Normal file
185
src/lzf/lzfP.h
Normal file
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Marc Alexander Lehmann <schmorp@schmorp.de>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modifica-
|
||||
* tion, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
|
||||
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
|
||||
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
|
||||
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* the GNU General Public License ("GPL") version 2 or any later version,
|
||||
* in which case the provisions of the GPL are applicable instead of
|
||||
* the above. If you wish to allow the use of your version of this file
|
||||
* only under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the BSD license, indicate your decision
|
||||
* by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete the
|
||||
* provisions above, a recipient may use your version of this file under
|
||||
* either the BSD or the GPL.
|
||||
*/
|
||||
|
||||
#ifndef LZFP_h
|
||||
#define LZFP_h
|
||||
|
||||
#define STANDALONE 1 /* at the moment, this is ok. */
|
||||
|
||||
#ifndef STANDALONE
|
||||
# include "lzf.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Size of hashtable is (1 << HLOG) * sizeof (char *)
|
||||
* decompression is independent of the hash table size
|
||||
* the difference between 15 and 14 is very small
|
||||
* for small blocks (and 14 is usually a bit faster).
|
||||
* For a low-memory/faster configuration, use HLOG == 13;
|
||||
* For best compression, use 15 or 16 (or more, up to 22).
|
||||
*/
|
||||
#ifndef HLOG
|
||||
# define HLOG 16
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Sacrifice very little compression quality in favour of compression speed.
|
||||
* This gives almost the same compression as the default code, and is
|
||||
* (very roughly) 15% faster. This is the preferred mode of operation.
|
||||
*/
|
||||
#ifndef VERY_FAST
|
||||
# define VERY_FAST 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Sacrifice some more compression quality in favour of compression speed.
|
||||
* (roughly 1-2% worse compression for large blocks and
|
||||
* 9-10% for small, redundant, blocks and >>20% better speed in both cases)
|
||||
* In short: when in need for speed, enable this for binary data,
|
||||
* possibly disable this for text data.
|
||||
*/
|
||||
#ifndef ULTRA_FAST
|
||||
# define ULTRA_FAST 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Unconditionally aligning does not cost very much, so do it if unsure
|
||||
*/
|
||||
#ifndef STRICT_ALIGN
|
||||
# define STRICT_ALIGN !(defined(__i386) || defined (__amd64))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* You may choose to pre-set the hash table (might be faster on some
|
||||
* modern cpus and large (>>64k) blocks, and also makes compression
|
||||
* deterministic/repeatable when the configuration otherwise is the same).
|
||||
*/
|
||||
#ifndef INIT_HTAB
|
||||
# define INIT_HTAB 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Avoid assigning values to errno variable? for some embedding purposes
|
||||
* (linux kernel for example), this is necessary. NOTE: this breaks
|
||||
* the documentation in lzf.h. Avoiding errno has no speed impact.
|
||||
*/
|
||||
#ifndef AVOID_ERRNO
|
||||
# define AVOID_ERRNO 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Whether to pass the LZF_STATE variable as argument, or allocate it
|
||||
* on the stack. For small-stack environments, define this to 1.
|
||||
* NOTE: this breaks the prototype in lzf.h.
|
||||
*/
|
||||
#ifndef LZF_STATE_ARG
|
||||
# define LZF_STATE_ARG 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Whether to add extra checks for input validity in lzf_decompress
|
||||
* and return EINVAL if the input stream has been corrupted. This
|
||||
* only shields against overflowing the input buffer and will not
|
||||
* detect most corrupted streams.
|
||||
* This check is not normally noticeable on modern hardware
|
||||
* (<1% slowdown), but might slow down older cpus considerably.
|
||||
*/
|
||||
#ifndef CHECK_INPUT
|
||||
# define CHECK_INPUT 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Whether to store pointers or offsets inside the hash table. On
|
||||
* 64 bit architetcures, pointers take up twice as much space,
|
||||
* and might also be slower. Default is to autodetect.
|
||||
*/
|
||||
/*#define LZF_USER_OFFSETS autodetect */
|
||||
|
||||
/*****************************************************************************/
|
||||
/* nothing should be changed below */
|
||||
|
||||
#ifdef __cplusplus
|
||||
# include <cstring>
|
||||
# include <climits>
|
||||
using namespace std;
|
||||
#else
|
||||
# include <string.h>
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
#ifndef LZF_USE_OFFSETS
|
||||
# if defined (WIN32)
|
||||
# define LZF_USE_OFFSETS defined(_M_X64)
|
||||
# else
|
||||
# if __cplusplus > 199711L
|
||||
# include <cstdint>
|
||||
# else
|
||||
# include <stdint.h>
|
||||
# endif
|
||||
# define LZF_USE_OFFSETS (UINTPTR_MAX > 0xffffffffU)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef unsigned char u8;
|
||||
|
||||
#if LZF_USE_OFFSETS
|
||||
# define LZF_HSLOT_BIAS ((const u8 *)in_data)
|
||||
typedef unsigned int LZF_HSLOT;
|
||||
#else
|
||||
# define LZF_HSLOT_BIAS 0
|
||||
typedef const u8 *LZF_HSLOT;
|
||||
#endif
|
||||
|
||||
typedef LZF_HSLOT LZF_STATE[1 << (HLOG)];
|
||||
|
||||
#if !STRICT_ALIGN
|
||||
/* for unaligned accesses we need a 16 bit datatype. */
|
||||
# if USHRT_MAX == 65535
|
||||
typedef unsigned short u16;
|
||||
# elif UINT_MAX == 65535
|
||||
typedef unsigned int u16;
|
||||
# else
|
||||
# undef STRICT_ALIGN
|
||||
# define STRICT_ALIGN 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if ULTRA_FAST
|
||||
# undef VERY_FAST
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
291
src/lzf/lzf_c.c
Normal file
291
src/lzf/lzf_c.c
Normal file
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2010 Marc Alexander Lehmann <schmorp@schmorp.de>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modifica-
|
||||
* tion, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
|
||||
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
|
||||
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
|
||||
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* the GNU General Public License ("GPL") version 2 or any later version,
|
||||
* in which case the provisions of the GPL are applicable instead of
|
||||
* the above. If you wish to allow the use of your version of this file
|
||||
* only under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the BSD license, indicate your decision
|
||||
* by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete the
|
||||
* provisions above, a recipient may use your version of this file under
|
||||
* either the BSD or the GPL.
|
||||
*/
|
||||
|
||||
#include "lzfP.h"
|
||||
|
||||
#define HSIZE (1 << (HLOG))
|
||||
|
||||
/*
|
||||
* don't play with this unless you benchmark!
|
||||
* the data format is not dependent on the hash function.
|
||||
* the hash function might seem strange, just believe me,
|
||||
* it works ;)
|
||||
*/
|
||||
#ifndef FRST
|
||||
# define FRST(p) (((p[0]) << 8) | p[1])
|
||||
# define NEXT(v,p) (((v) << 8) | p[2])
|
||||
# if ULTRA_FAST
|
||||
# define IDX(h) ((( h >> (3*8 - HLOG)) - h ) & (HSIZE - 1))
|
||||
# elif VERY_FAST
|
||||
# define IDX(h) ((( h >> (3*8 - HLOG)) - h*5) & (HSIZE - 1))
|
||||
# else
|
||||
# define IDX(h) ((((h ^ (h << 5)) >> (3*8 - HLOG)) - h*5) & (HSIZE - 1))
|
||||
# endif
|
||||
#endif
|
||||
/*
|
||||
* IDX works because it is very similar to a multiplicative hash, e.g.
|
||||
* ((h * 57321 >> (3*8 - HLOG)) & (HSIZE - 1))
|
||||
* the latter is also quite fast on newer CPUs, and compresses similarly.
|
||||
*
|
||||
* the next one is also quite good, albeit slow ;)
|
||||
* (int)(cos(h & 0xffffff) * 1e6)
|
||||
*/
|
||||
|
||||
#if 0
|
||||
/* original lzv-like hash function, much worse and thus slower */
|
||||
# define FRST(p) (p[0] << 5) ^ p[1]
|
||||
# define NEXT(v,p) ((v) << 5) ^ p[2]
|
||||
# define IDX(h) ((h) & (HSIZE - 1))
|
||||
#endif
|
||||
|
||||
#define MAX_LIT (1 << 5)
|
||||
#define MAX_OFF (1 << 13)
|
||||
#define MAX_REF ((1 << 8) + (1 << 3))
|
||||
|
||||
#if __GNUC__ >= 3
|
||||
# define expect(expr,value) __builtin_expect ((expr),(value))
|
||||
# define inline inline
|
||||
#else
|
||||
# define expect(expr,value) (expr)
|
||||
# define inline static
|
||||
#endif
|
||||
|
||||
#define expect_false(expr) expect ((expr) != 0, 0)
|
||||
#define expect_true(expr) expect ((expr) != 0, 1)
|
||||
|
||||
/*
|
||||
* compressed format
|
||||
*
|
||||
* 000LLLLL <L+1> ; literal, L+1=1..33 octets
|
||||
* LLLooooo oooooooo ; backref L+1=1..7 octets, o+1=1..4096 offset
|
||||
* 111ooooo LLLLLLLL oooooooo ; backref L+8 octets, o+1=1..4096 offset
|
||||
*
|
||||
*/
|
||||
|
||||
unsigned int
|
||||
lzf_compress (const void *const in_data, unsigned int in_len,
|
||||
void *out_data, unsigned int out_len
|
||||
#if LZF_STATE_ARG
|
||||
, LZF_STATE htab
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#if !LZF_STATE_ARG
|
||||
LZF_STATE htab;
|
||||
#endif
|
||||
const u8 *ip = (const u8 *)in_data;
|
||||
u8 *op = (u8 *)out_data;
|
||||
const u8 *in_end = ip + in_len;
|
||||
u8 *out_end = op + out_len;
|
||||
const u8 *ref;
|
||||
|
||||
/* off requires a type wide enough to hold a general pointer difference.
|
||||
* ISO C doesn't have that (size_t might not be enough and ptrdiff_t only
|
||||
* works for differences within a single object). We also assume that no
|
||||
* no bit pattern traps. Since the only platform that is both non-POSIX
|
||||
* and fails to support both assumptions is windows 64 bit, we make a
|
||||
* special workaround for it.
|
||||
*/
|
||||
#if defined (WIN32) && defined (_M_X64)
|
||||
unsigned _int64 off; /* workaround for missing POSIX compliance */
|
||||
#else
|
||||
unsigned long off;
|
||||
#endif
|
||||
unsigned int hval;
|
||||
int lit;
|
||||
|
||||
if (!in_len || !out_len)
|
||||
return 0;
|
||||
|
||||
#if INIT_HTAB
|
||||
memset (htab, 0, sizeof (htab));
|
||||
#endif
|
||||
|
||||
lit = 0; op++; /* start run */
|
||||
|
||||
hval = FRST (ip);
|
||||
while (ip < in_end - 2)
|
||||
{
|
||||
LZF_HSLOT *hslot;
|
||||
|
||||
hval = NEXT (hval, ip);
|
||||
hslot = htab + IDX (hval);
|
||||
ref = *hslot + LZF_HSLOT_BIAS; *hslot = ip - LZF_HSLOT_BIAS;
|
||||
|
||||
if (1
|
||||
#if INIT_HTAB
|
||||
&& ref < ip /* the next test will actually take care of this, but this is faster */
|
||||
#endif
|
||||
&& (off = ip - ref - 1) < MAX_OFF
|
||||
&& ref > (u8 *)in_data
|
||||
&& ref[2] == ip[2]
|
||||
#if STRICT_ALIGN
|
||||
&& ((ref[1] << 8) | ref[0]) == ((ip[1] << 8) | ip[0])
|
||||
#else
|
||||
&& *(u16 *)ref == *(u16 *)ip
|
||||
#endif
|
||||
)
|
||||
{
|
||||
/* match found at *ref++ */
|
||||
unsigned int len = 2;
|
||||
unsigned int maxlen = in_end - ip - len;
|
||||
maxlen = maxlen > MAX_REF ? MAX_REF : maxlen;
|
||||
|
||||
if (expect_false (op + 3 + 1 >= out_end)) /* first a faster conservative test */
|
||||
if (op - !lit + 3 + 1 >= out_end) /* second the exact but rare test */
|
||||
return 0;
|
||||
|
||||
op [- lit - 1] = lit - 1; /* stop run */
|
||||
op -= !lit; /* undo run if length is zero */
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (expect_true (maxlen > 16))
|
||||
{
|
||||
len++; if (ref [len] != ip [len]) break;
|
||||
len++; if (ref [len] != ip [len]) break;
|
||||
len++; if (ref [len] != ip [len]) break;
|
||||
len++; if (ref [len] != ip [len]) break;
|
||||
|
||||
len++; if (ref [len] != ip [len]) break;
|
||||
len++; if (ref [len] != ip [len]) break;
|
||||
len++; if (ref [len] != ip [len]) break;
|
||||
len++; if (ref [len] != ip [len]) break;
|
||||
|
||||
len++; if (ref [len] != ip [len]) break;
|
||||
len++; if (ref [len] != ip [len]) break;
|
||||
len++; if (ref [len] != ip [len]) break;
|
||||
len++; if (ref [len] != ip [len]) break;
|
||||
|
||||
len++; if (ref [len] != ip [len]) break;
|
||||
len++; if (ref [len] != ip [len]) break;
|
||||
len++; if (ref [len] != ip [len]) break;
|
||||
len++; if (ref [len] != ip [len]) break;
|
||||
}
|
||||
|
||||
do
|
||||
len++;
|
||||
while (len < maxlen && ref[len] == ip[len]);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
len -= 2; /* len is now #octets - 1 */
|
||||
ip++;
|
||||
|
||||
if (len < 7)
|
||||
{
|
||||
*op++ = (off >> 8) + (len << 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
*op++ = (off >> 8) + ( 7 << 5);
|
||||
*op++ = len - 7;
|
||||
}
|
||||
|
||||
*op++ = off;
|
||||
|
||||
lit = 0; op++; /* start run */
|
||||
|
||||
ip += len + 1;
|
||||
|
||||
if (expect_false (ip >= in_end - 2))
|
||||
break;
|
||||
|
||||
#if ULTRA_FAST || VERY_FAST
|
||||
--ip;
|
||||
# if VERY_FAST && !ULTRA_FAST
|
||||
--ip;
|
||||
# endif
|
||||
hval = FRST (ip);
|
||||
|
||||
hval = NEXT (hval, ip);
|
||||
htab[IDX (hval)] = ip - LZF_HSLOT_BIAS;
|
||||
ip++;
|
||||
|
||||
# if VERY_FAST && !ULTRA_FAST
|
||||
hval = NEXT (hval, ip);
|
||||
htab[IDX (hval)] = ip - LZF_HSLOT_BIAS;
|
||||
ip++;
|
||||
# endif
|
||||
#else
|
||||
ip -= len + 1;
|
||||
|
||||
do
|
||||
{
|
||||
hval = NEXT (hval, ip);
|
||||
htab[IDX (hval)] = ip - LZF_HSLOT_BIAS;
|
||||
ip++;
|
||||
}
|
||||
while (len--);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* one more literal byte we must copy */
|
||||
if (expect_false (op >= out_end))
|
||||
return 0;
|
||||
|
||||
lit++; *op++ = *ip++;
|
||||
|
||||
if (expect_false (lit == MAX_LIT))
|
||||
{
|
||||
op [- lit - 1] = lit - 1; /* stop run */
|
||||
lit = 0; op++; /* start run */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (op + 3 > out_end) /* at most 3 bytes can be missing here */
|
||||
return 0;
|
||||
|
||||
while (ip < in_end)
|
||||
{
|
||||
lit++; *op++ = *ip++;
|
||||
|
||||
if (expect_false (lit == MAX_LIT))
|
||||
{
|
||||
op [- lit - 1] = lit - 1; /* stop run */
|
||||
lit = 0; op++; /* start run */
|
||||
}
|
||||
}
|
||||
|
||||
op [- lit - 1] = lit - 1; /* end run */
|
||||
op -= !lit; /* undo run if length is zero */
|
||||
|
||||
return op - (u8 *)out_data;
|
||||
}
|
||||
|
||||
185
src/lzf/lzf_d.c
Normal file
185
src/lzf/lzf_d.c
Normal file
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2010 Marc Alexander Lehmann <schmorp@schmorp.de>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modifica-
|
||||
* tion, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
|
||||
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
|
||||
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
|
||||
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* the GNU General Public License ("GPL") version 2 or any later version,
|
||||
* in which case the provisions of the GPL are applicable instead of
|
||||
* the above. If you wish to allow the use of your version of this file
|
||||
* only under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the BSD license, indicate your decision
|
||||
* by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete the
|
||||
* provisions above, a recipient may use your version of this file under
|
||||
* either the BSD or the GPL.
|
||||
*/
|
||||
|
||||
#include "lzfP.h"
|
||||
|
||||
#if AVOID_ERRNO
|
||||
# define SET_ERRNO(n)
|
||||
#else
|
||||
# include <errno.h>
|
||||
# define SET_ERRNO(n) errno = (n)
|
||||
#endif
|
||||
|
||||
#if USE_REP_MOVSB /* small win on amd, big loss on intel */
|
||||
#if (__i386 || __amd64) && __GNUC__ >= 3
|
||||
# define lzf_movsb(dst, src, len) \
|
||||
asm ("rep movsb" \
|
||||
: "=D" (dst), "=S" (src), "=c" (len) \
|
||||
: "0" (dst), "1" (src), "2" (len));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
unsigned int
|
||||
lzf_decompress (const void *const in_data, unsigned int in_len,
|
||||
void *out_data, unsigned int out_len)
|
||||
{
|
||||
u8 const *ip = (const u8 *)in_data;
|
||||
u8 *op = (u8 *)out_data;
|
||||
u8 const *const in_end = ip + in_len;
|
||||
u8 *const out_end = op + out_len;
|
||||
|
||||
do
|
||||
{
|
||||
unsigned int ctrl = *ip++;
|
||||
|
||||
if (ctrl < (1 << 5)) /* literal run */
|
||||
{
|
||||
ctrl++;
|
||||
|
||||
if (op + ctrl > out_end)
|
||||
{
|
||||
SET_ERRNO (E2BIG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if CHECK_INPUT
|
||||
if (ip + ctrl > in_end)
|
||||
{
|
||||
SET_ERRNO (EINVAL);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef lzf_movsb
|
||||
lzf_movsb (op, ip, ctrl);
|
||||
#else
|
||||
switch (ctrl)
|
||||
{
|
||||
case 32: *op++ = *ip++; case 31: *op++ = *ip++; case 30: *op++ = *ip++; case 29: *op++ = *ip++;
|
||||
case 28: *op++ = *ip++; case 27: *op++ = *ip++; case 26: *op++ = *ip++; case 25: *op++ = *ip++;
|
||||
case 24: *op++ = *ip++; case 23: *op++ = *ip++; case 22: *op++ = *ip++; case 21: *op++ = *ip++;
|
||||
case 20: *op++ = *ip++; case 19: *op++ = *ip++; case 18: *op++ = *ip++; case 17: *op++ = *ip++;
|
||||
case 16: *op++ = *ip++; case 15: *op++ = *ip++; case 14: *op++ = *ip++; case 13: *op++ = *ip++;
|
||||
case 12: *op++ = *ip++; case 11: *op++ = *ip++; case 10: *op++ = *ip++; case 9: *op++ = *ip++;
|
||||
case 8: *op++ = *ip++; case 7: *op++ = *ip++; case 6: *op++ = *ip++; case 5: *op++ = *ip++;
|
||||
case 4: *op++ = *ip++; case 3: *op++ = *ip++; case 2: *op++ = *ip++; case 1: *op++ = *ip++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else /* back reference */
|
||||
{
|
||||
unsigned int len = ctrl >> 5;
|
||||
|
||||
u8 *ref = op - ((ctrl & 0x1f) << 8) - 1;
|
||||
|
||||
#if CHECK_INPUT
|
||||
if (ip >= in_end)
|
||||
{
|
||||
SET_ERRNO (EINVAL);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (len == 7)
|
||||
{
|
||||
len += *ip++;
|
||||
#if CHECK_INPUT
|
||||
if (ip >= in_end)
|
||||
{
|
||||
SET_ERRNO (EINVAL);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
ref -= *ip++;
|
||||
|
||||
if (op + len + 2 > out_end)
|
||||
{
|
||||
SET_ERRNO (E2BIG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ref < (u8 *)out_data)
|
||||
{
|
||||
SET_ERRNO (EINVAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef lzf_movsb
|
||||
len += 2;
|
||||
lzf_movsb (op, ref, len);
|
||||
#else
|
||||
switch (len)
|
||||
{
|
||||
default:
|
||||
len += 2;
|
||||
|
||||
if (op >= ref + len)
|
||||
{
|
||||
/* disjunct areas */
|
||||
memcpy (op, ref, len);
|
||||
op += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* overlapping, use octte by octte copying */
|
||||
do
|
||||
*op++ = *ref++;
|
||||
while (--len);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 9: *op++ = *ref++;
|
||||
case 8: *op++ = *ref++;
|
||||
case 7: *op++ = *ref++;
|
||||
case 6: *op++ = *ref++;
|
||||
case 5: *op++ = *ref++;
|
||||
case 4: *op++ = *ref++;
|
||||
case 3: *op++ = *ref++;
|
||||
case 2: *op++ = *ref++;
|
||||
case 1: *op++ = *ref++;
|
||||
case 0: *op++ = *ref++; /* two octets more */
|
||||
*op++ = *ref++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
while (ip < in_end);
|
||||
|
||||
return op - (u8 *)out_data;
|
||||
}
|
||||
|
||||
34
src/mem.c
34
src/mem.c
@@ -665,14 +665,6 @@ int loadbios()
|
||||
biosmask = 0x1ffff;
|
||||
return 1;
|
||||
|
||||
case ROM_P54TP4XE:
|
||||
f = romfopen("roms/p54tp4xe/T15I0302.AWD", "rb");
|
||||
if (!f) break;
|
||||
fread(rom, 0x20000, 1, f);
|
||||
fclose(f);
|
||||
biosmask = 0x1ffff;
|
||||
return 1;
|
||||
|
||||
case ROM_ACERM3A:
|
||||
f = romfopen("roms/acerm3a/r01-b3.bin", "rb");
|
||||
if (!f) break;
|
||||
@@ -689,22 +681,6 @@ int loadbios()
|
||||
biosmask = 0x1ffff;
|
||||
return 1;
|
||||
|
||||
case ROM_P55T2P4:
|
||||
f = romfopen("roms/p55t2p4/0207_J2.BIN", "rb");
|
||||
if (!f) break;
|
||||
fread(rom, 0x20000, 1, f);
|
||||
fclose(f);
|
||||
biosmask = 0x1ffff;
|
||||
return 1;
|
||||
|
||||
case ROM_P55TVP4:
|
||||
f = romfopen("roms/p55tvp4/tv5i0201.awd", "rb");
|
||||
if (!f) break;
|
||||
fread(rom, 0x20000, 1, f);
|
||||
fclose(f);
|
||||
biosmask = 0x1ffff;
|
||||
return 1;
|
||||
|
||||
case ROM_P55VA:
|
||||
f = romfopen("roms/p55va/VA021297.BIN", "rb");
|
||||
if (!f) break;
|
||||
@@ -721,14 +697,6 @@ int loadbios()
|
||||
biosmask = 0x1ffff;
|
||||
return 1;
|
||||
|
||||
case ROM_KN97:
|
||||
f = romfopen("roms/kn97/NAKI0116.AWD", "rb");
|
||||
if (!f) break;
|
||||
fread(rom, 0x20000, 1, f);
|
||||
fclose(f);
|
||||
biosmask = 0x1ffff;
|
||||
return 1;
|
||||
|
||||
case ROM_MARL:
|
||||
f = romfopen("roms/marl/1008DB0_.BIO", "rb");
|
||||
if (!f) break;
|
||||
@@ -1961,7 +1929,7 @@ void mem_add_bios()
|
||||
}
|
||||
|
||||
int mem_a20_key = 0, mem_a20_alt = 0;
|
||||
static int mem_a20_state = 1;
|
||||
int mem_a20_state = 1;
|
||||
|
||||
void mem_init()
|
||||
{
|
||||
|
||||
@@ -25,8 +25,6 @@ uint8_t memregs_read(uint16_t port, void *priv)
|
||||
|
||||
void memregs_init()
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
pclog("Memory Registers Init\n");
|
||||
|
||||
io_sethandler(0x00e1, 0x0002, memregs_read, NULL, NULL, memregs_write, NULL, NULL, NULL);
|
||||
|
||||
23
src/model.c
23
src/model.c
@@ -98,12 +98,10 @@ void at_mb500n_init();
|
||||
void at_acerm3a_init();
|
||||
void at_acerv35n_init();
|
||||
// void at_p55t2p4_init();
|
||||
void at_p55tvp4_init();
|
||||
// void at_p55tvp4_init();
|
||||
void at_marl_init();
|
||||
void at_p55va_init();
|
||||
void at_i440fx_init();
|
||||
void at_kn97_init();
|
||||
void at_deskpro2k_init();
|
||||
|
||||
int model;
|
||||
|
||||
@@ -165,11 +163,9 @@ MODEL models[] =
|
||||
// {"ASUS P/I-P55T2P4", ROM_P55T2P4, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, 1, 1, 512, 1, at_p55t2p4_init},
|
||||
{"Award 430VX PCI", ROM_430VX, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, 1, 1, 256, 1, at_i430vx_init},
|
||||
{"Epox P55-VA", ROM_P55VA, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, 1, 1, 256, 1, at_p55va_init},
|
||||
{"ASUS P/I-P55TVP4", ROM_P55TVP4, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, 1, 1, 256, 1, at_p55tvp4_init},
|
||||
/* {"ASUS P/I-P55TVP4", ROM_P55TVP4, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, 1, 1, 256, 1, at_p55tvp4_init}, */
|
||||
{"Award 440FX PCI", ROM_440FX, { "Intel", cpus_PentiumPro, "", NULL, "", NULL}, 0, 1, 1, 1024, 1, at_i440fx_init},
|
||||
{"Award KN97 (440FX PCI)",ROM_KN97, { "Intel", cpus_PentiumPro, "", NULL, "", NULL}, 0, 1, 1, 1024, 1, at_kn97_init},
|
||||
// {"Award 440FX PCI", ROM_440FX, { "Intel", cpus_PentiumPro,"Klamath", cpus_Pentium2, "Deschutes", cpus_Pentium2D}, 0, 1, 1, 1024, 1, at_i440fx_init},
|
||||
// {"Award KN97 (440FX PCI)",ROM_KN97, { "Intel", cpus_PentiumPro,"Klamath", cpus_Pentium2, "Deschutes", cpus_Pentium2D}, 0, 1, 1, 1024, 1, at_kn97_init},
|
||||
{"", -1, {"", 0, "", 0, "", 0}, 0,0,0, 0}
|
||||
};
|
||||
|
||||
@@ -596,6 +592,7 @@ void at_i430vx_init()
|
||||
|
||||
// rom_t ami_ec_rom;
|
||||
|
||||
#if 0
|
||||
void at_p55tvp4_init()
|
||||
{
|
||||
at_init();
|
||||
@@ -614,6 +611,7 @@ void at_p55tvp4_init()
|
||||
|
||||
if (cdrom_channel >= 4) ide_ter_init();
|
||||
}
|
||||
#endif
|
||||
|
||||
void at_p55va_init()
|
||||
{
|
||||
@@ -641,19 +639,6 @@ void at_i440fx_init()
|
||||
if (cdrom_channel >= 4) ide_ter_init();
|
||||
}
|
||||
|
||||
void at_kn97_init()
|
||||
{
|
||||
at_init();
|
||||
memregs_init();
|
||||
mouse_always_serial ? mouse_serial_init() : mouse_ps2_init();
|
||||
pci_init(PCI_CONFIG_TYPE_1, 0, 31);
|
||||
i440fx_init();
|
||||
piix3_init(7);
|
||||
w83877f_init();
|
||||
device_add(&intel_flash_bxt_device);
|
||||
if (cdrom_channel >= 4) ide_ter_init();
|
||||
}
|
||||
|
||||
void model_init()
|
||||
{
|
||||
pclog("Initting as %s\n", model_getname());
|
||||
|
||||
@@ -26,7 +26,6 @@ static struct
|
||||
uint8_t flags;
|
||||
uint8_t resolution;
|
||||
uint8_t sample_rate;
|
||||
uint8_t type;
|
||||
|
||||
uint8_t command;
|
||||
|
||||
|
||||
@@ -25,8 +25,8 @@ void mouse_serial_poll(int x, int y, int b)
|
||||
|
||||
/*Use Microsoft format*/
|
||||
mousedat[0]=0x40;
|
||||
mousedat[0]|=(((y>>6)&3)<<2);
|
||||
mousedat[0]|=((x>>6)&3);
|
||||
mousedat[0]|=(((y / 64)&3)<<2);
|
||||
mousedat[0]|=((x / 64)&3);
|
||||
if (b&1) mousedat[0]|=0x20;
|
||||
if (b&2) mousedat[0]|=0x10;
|
||||
mousedat[1]=x&0x3F;
|
||||
|
||||
@@ -461,13 +461,13 @@ uint32_t ne2000_chipmem_read(ne2000_t *ne2000, uint32_t address, unsigned int io
|
||||
|
||||
// ROM'd MAC address
|
||||
if ((address >=0) && (address <= 31)) {
|
||||
retval = ne2000->macaddr[address];
|
||||
retval = ne2000->macaddr[address % 32];
|
||||
if ((io_len == 2) || (io_len == 4)) {
|
||||
retval |= (ne2000->macaddr[address + 1] << 8);
|
||||
retval |= (ne2000->macaddr[(address + 1) % 32] << 8);
|
||||
}
|
||||
if (io_len == 4) {
|
||||
retval |= (ne2000->macaddr[address + 2] << 16);
|
||||
retval |= (ne2000->macaddr[address + 3] << 24);
|
||||
retval |= (ne2000->macaddr[(address + 2) % 32] << 16);
|
||||
retval |= (ne2000->macaddr[(address + 3) % 32] << 24);
|
||||
}
|
||||
return (retval);
|
||||
}
|
||||
|
||||
@@ -231,10 +231,8 @@ void loadnvr()
|
||||
case ROM_MB500N: f = romfopen(nvr_concat("mb500n.nvr"), "rb"); nvrmask = 127; break;
|
||||
case ROM_ACERM3A: f = romfopen(nvr_concat("acerm3a.nvr"), "rb"); nvrmask = 127; break;
|
||||
case ROM_ACERV35N: f = romfopen(nvr_concat("acerv35n.nvr"), "rb"); nvrmask = 127; break;
|
||||
case ROM_P55TVP4: f = romfopen(nvr_concat("p55tvp4.nvr"), "rb"); nvrmask = 127; break;
|
||||
case ROM_P55VA: f = romfopen(nvr_concat("p55va.nvr"), "rb"); nvrmask = 127; break;
|
||||
case ROM_440FX: f = romfopen(nvr_concat("440fx.nvr"), "rb"); nvrmask = 127; break;
|
||||
case ROM_KN97: f = romfopen(nvr_concat("kn97.nvr"), "rb"); nvrmask = 127; break;
|
||||
case ROM_MARL: f = romfopen(nvr_concat("marl.nvr"), "rb"); nvrmask = 127; break;
|
||||
case ROM_THOR: f = romfopen(nvr_concat("thor.nvr"), "rb"); nvrmask = 127; break;
|
||||
default: return;
|
||||
@@ -301,10 +299,8 @@ void savenvr()
|
||||
case ROM_MB500N: f = romfopen(nvr_concat("mb500n.nvr"), "wb"); break;
|
||||
case ROM_ACERM3A: f = romfopen(nvr_concat("acerm3a.nvr"), "wb"); break;
|
||||
case ROM_ACERV35N: f = romfopen(nvr_concat("acerv35n.nvr"), "wb"); break;
|
||||
case ROM_P55TVP4: f = romfopen(nvr_concat("p55tvp4.nvr"), "wb"); break;
|
||||
case ROM_P55VA: f = romfopen(nvr_concat("p55va.nvr"), "wb"); break;
|
||||
case ROM_440FX: f = romfopen(nvr_concat("440fx.nvr"), "wb"); break;
|
||||
case ROM_KN97: f = romfopen(nvr_concat("kn97.nvr"), "wb"); break;
|
||||
case ROM_MARL: f = romfopen(nvr_concat("marl.nvr"), "wb"); break;
|
||||
case ROM_THOR: f = romfopen(nvr_concat("thor.nvr"), "wb"); break;
|
||||
default: return;
|
||||
|
||||
2
src/pc.c
2
src/pc.c
@@ -273,7 +273,7 @@ void initpc(int argc, char *argv[])
|
||||
sound_reset();
|
||||
fdc_init();
|
||||
disc_init();
|
||||
fdi_init();
|
||||
fdi_init();
|
||||
img_init();
|
||||
d86f_init();
|
||||
td0_init();
|
||||
|
||||
@@ -251,7 +251,7 @@ process_value:
|
||||
break;
|
||||
case 9:
|
||||
// pclog("Setting DENSEL polarity to: %i (before: %i)\n", (val & 0x40 ? 1 : 0), fdc_get_densel_polarity());
|
||||
fdc_update_densel_polarity(val & 0x40 ? 1 : 0);
|
||||
fdc_update_densel_polarity((val & 0x40) ? 1 : 0);
|
||||
break;
|
||||
case 0xF:
|
||||
pc87306_gpio_init();
|
||||
|
||||
13
src/piix.c
13
src/piix.c
@@ -35,7 +35,6 @@ void piix_write(int func, int addr, uint8_t val, void *priv)
|
||||
switch (addr)
|
||||
{
|
||||
case 0x04:
|
||||
if (val & 0x10) resetide(); /* Only the ASUS boards attempt to modify this register - reset IDE when that happens. Fixes soft reset on the ASUS boards. */
|
||||
card_piix_ide[0x04] = (card_piix_ide[0x04] & ~5) | (val & 5);
|
||||
break;
|
||||
case 0x07:
|
||||
@@ -52,18 +51,6 @@ void piix_write(int func, int addr, uint8_t val, void *priv)
|
||||
card_piix_ide[0x21] = val;
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case 0x33:
|
||||
/* Note by OBattler: This is a hack, but it's needed to reset the cylinders of the IDE devices. */
|
||||
if (romset != ROM_P55T2P4) break;
|
||||
if (val != piix_33)
|
||||
{
|
||||
resetide();
|
||||
}
|
||||
piix_33 = val;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 0x40:
|
||||
card_piix_ide[0x40] = val;
|
||||
break;
|
||||
|
||||
@@ -164,8 +164,6 @@ static void time_internal_set(struct tm *time_var)
|
||||
|
||||
static void time_set_nvrram(char *nvrram, struct tm *cur_time_tm)
|
||||
{
|
||||
int dow, mon, year;
|
||||
|
||||
if (nvrram[RTC_REGB] & RTC_DM)
|
||||
{
|
||||
nvrram[RTC_SECONDS] = cur_time_tm->tm_sec;
|
||||
|
||||
@@ -875,6 +875,7 @@ void mach64_start_fill(mach64_t *mach64)
|
||||
mach64->accel.dst_width = (mach64->dst_height_width >> 16) & 0x1fff;
|
||||
mach64->accel.dst_height = mach64->dst_height_width & 0x1fff;
|
||||
mach64->accel.x_count = mach64->accel.dst_width;
|
||||
mach64->accel.y_count = mach64->accel.dst_height;
|
||||
|
||||
mach64->accel.src_x = 0;
|
||||
mach64->accel.src_y = 0;
|
||||
@@ -2574,7 +2575,6 @@ void mach64_pci_write(int func, int addr, uint8_t val, void *p)
|
||||
switch (addr)
|
||||
{
|
||||
case PCI_REG_COMMAND:
|
||||
if (romset == ROM_KN97) return;
|
||||
mach64->pci_regs[PCI_REG_COMMAND] = val & 0x27;
|
||||
if (val & PCI_COMMAND_IO)
|
||||
mach64_io_set(mach64);
|
||||
|
||||
@@ -208,7 +208,7 @@ uint8_t clgd_in(uint16_t addr, void *p)
|
||||
clgd_t *clgd = (clgd_t *)p;
|
||||
svga_t *svga = &clgd->svga;
|
||||
|
||||
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3d0) && !(svga->miscout & 1))
|
||||
if ((((addr & 0xfff0) == 0x3d0) || (addr & 0xfff0) == 0x3d0) && !(svga->miscout & 1))
|
||||
addr ^= 0x60;
|
||||
|
||||
// if (addr != 0x3da) pclog("IN clgd %04X\n", addr);
|
||||
|
||||
470
src/vid_colorplus.c
Normal file
470
src/vid_colorplus.c
Normal file
@@ -0,0 +1,470 @@
|
||||
/*Plantronics ColorPlus emulation*/
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "ibm.h"
|
||||
#include "device.h"
|
||||
#include "io.h"
|
||||
#include "mem.h"
|
||||
#include "timer.h"
|
||||
#include "video.h"
|
||||
#include "vid_cga.h"
|
||||
#include "vid_colorplus.h"
|
||||
#include "dosbox/vid_cga_comp.h"
|
||||
|
||||
/* Bits in the colorplus control register: */
|
||||
#define COLORPLUS_PLANE_SWAP 0x40 /* Swap planes at 0000h and 4000h */
|
||||
#define COLORPLUS_640x200_MODE 0x20 /* 640x200x4 mode active */
|
||||
#define COLORPLUS_320x200_MODE 0x10 /* 320x200x16 mode active */
|
||||
#define COLORPLUS_EITHER_MODE 0x30 /* Either mode active */
|
||||
|
||||
/* Bits in the CGA graphics mode register */
|
||||
#define CGA_GRAPHICS_MODE 0x02 /* CGA graphics mode selected? */
|
||||
|
||||
#define CGA_RGB 0
|
||||
#define CGA_COMPOSITE 1
|
||||
|
||||
#define COMPOSITE_OLD 0
|
||||
#define COMPOSITE_NEW 1
|
||||
|
||||
|
||||
void cga_recalctimings(cga_t *cga);
|
||||
|
||||
void colorplus_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
colorplus_t *colorplus = (colorplus_t *)p;
|
||||
|
||||
// pclog("COLORPLUS_OUT %04X %02X\n", addr, val);
|
||||
if (addr == 0x3DD)
|
||||
{
|
||||
colorplus->control = val & 0x70;
|
||||
}
|
||||
else
|
||||
{
|
||||
cga_out(addr, val, &colorplus->cga);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t colorplus_in(uint16_t addr, void *p)
|
||||
{
|
||||
colorplus_t *colorplus = (colorplus_t *)p;
|
||||
|
||||
return cga_in(addr, &colorplus->cga);
|
||||
}
|
||||
|
||||
void colorplus_write(uint32_t addr, uint8_t val, void *p)
|
||||
{
|
||||
colorplus_t *colorplus = (colorplus_t *)p;
|
||||
|
||||
// pclog("COLORPLUS_WRITE %04X %02X\n", addr, val);
|
||||
if ((colorplus->control & COLORPLUS_PLANE_SWAP) &&
|
||||
(colorplus->control & COLORPLUS_EITHER_MODE) &&
|
||||
(colorplus->cga.cgamode & CGA_GRAPHICS_MODE))
|
||||
{
|
||||
addr ^= 0x4000;
|
||||
}
|
||||
else if (!(colorplus->control & COLORPLUS_EITHER_MODE))
|
||||
{
|
||||
addr &= 0x3FFF;
|
||||
}
|
||||
colorplus->cga.vram[addr & 0x7fff] = val;
|
||||
if (colorplus->cga.snow_enabled)
|
||||
{
|
||||
colorplus->cga.charbuffer[ ((int)(((colorplus->cga.dispontime - colorplus->cga.vidtime) * 2) / CGACONST)) & 0xfc] = val;
|
||||
colorplus->cga.charbuffer[(((int)(((colorplus->cga.dispontime - colorplus->cga.vidtime) * 2) / CGACONST)) & 0xfc) | 1] = val;
|
||||
}
|
||||
egawrites++;
|
||||
cycles -= 4;
|
||||
}
|
||||
|
||||
uint8_t colorplus_read(uint32_t addr, void *p)
|
||||
{
|
||||
colorplus_t *colorplus = (colorplus_t *)p;
|
||||
|
||||
if ((colorplus->control & COLORPLUS_PLANE_SWAP) &&
|
||||
(colorplus->control & COLORPLUS_EITHER_MODE) &&
|
||||
(colorplus->cga.cgamode & CGA_GRAPHICS_MODE))
|
||||
{
|
||||
addr ^= 0x4000;
|
||||
}
|
||||
else if (!(colorplus->control & COLORPLUS_EITHER_MODE))
|
||||
{
|
||||
addr &= 0x3FFF;
|
||||
}
|
||||
cycles -= 4;
|
||||
if (colorplus->cga.snow_enabled)
|
||||
{
|
||||
colorplus->cga.charbuffer[ ((int)(((colorplus->cga.dispontime - colorplus->cga.vidtime) * 2) / CGACONST)) & 0xfc] = colorplus->cga.vram[addr & 0x7fff];
|
||||
colorplus->cga.charbuffer[(((int)(((colorplus->cga.dispontime - colorplus->cga.vidtime) * 2) / CGACONST)) & 0xfc) | 1] = colorplus->cga.vram[addr & 0x7fff];
|
||||
}
|
||||
egareads++;
|
||||
// pclog("COLORPLUS_READ %04X\n", addr);
|
||||
return colorplus->cga.vram[addr & 0x7fff];
|
||||
}
|
||||
|
||||
void colorplus_recalctimings(colorplus_t *colorplus)
|
||||
{
|
||||
cga_recalctimings(&colorplus->cga);
|
||||
}
|
||||
|
||||
void colorplus_poll(void *p)
|
||||
{
|
||||
colorplus_t *colorplus = (colorplus_t *)p;
|
||||
int x, c;
|
||||
int oldvc;
|
||||
uint16_t dat0, dat1;
|
||||
int cols[4];
|
||||
int col;
|
||||
int oldsc;
|
||||
static const int cols16[16] = { 0x10,0x12,0x14,0x16,
|
||||
0x18,0x1A,0x1C,0x1E,
|
||||
0x11,0x13,0x15,0x17,
|
||||
0x19,0x1B,0x1D,0x1F };
|
||||
uint8_t *plane0 = colorplus->cga.vram;
|
||||
uint8_t *plane1 = colorplus->cga.vram + 0x4000;
|
||||
|
||||
/* If one of the extra modes is not selected, drop down to the CGA
|
||||
* drawing code. */
|
||||
if (!((colorplus->control & COLORPLUS_EITHER_MODE) &&
|
||||
(colorplus->cga.cgamode & CGA_GRAPHICS_MODE)))
|
||||
{
|
||||
cga_poll(&colorplus->cga);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!colorplus->cga.linepos)
|
||||
{
|
||||
colorplus->cga.vidtime += colorplus->cga.dispofftime;
|
||||
colorplus->cga.cgastat |= 1;
|
||||
colorplus->cga.linepos = 1;
|
||||
oldsc = colorplus->cga.sc;
|
||||
if ((colorplus->cga.crtc[8] & 3) == 3)
|
||||
colorplus->cga.sc = ((colorplus->cga.sc << 1) + colorplus->cga.oddeven) & 7;
|
||||
if (colorplus->cga.cgadispon)
|
||||
{
|
||||
if (colorplus->cga.displine < colorplus->cga.firstline)
|
||||
{
|
||||
colorplus->cga.firstline = colorplus->cga.displine;
|
||||
video_wait_for_buffer();
|
||||
// printf("Firstline %i\n",firstline);
|
||||
}
|
||||
colorplus->cga.lastline = colorplus->cga.displine;
|
||||
/* Left / right border */
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
buffer->line[colorplus->cga.displine][c] =
|
||||
buffer->line[colorplus->cga.displine][c + (colorplus->cga.crtc[1] << 4) + 8] = (colorplus->cga.cgacol & 15) + 16;
|
||||
}
|
||||
if (colorplus->control & COLORPLUS_320x200_MODE)
|
||||
{
|
||||
for (x = 0; x < colorplus->cga.crtc[1]; x++)
|
||||
{
|
||||
dat0 = (plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) |
|
||||
plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1];
|
||||
dat1 = (plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) |
|
||||
plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1];
|
||||
colorplus->cga.ma++;
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
buffer->line[colorplus->cga.displine][(x << 4) + (c << 1) + 8] =
|
||||
buffer->line[colorplus->cga.displine][(x << 4) + (c << 1) + 1 + 8] =
|
||||
cols16[(dat0 >> 14) | ((dat1 >> 14) << 2)];
|
||||
dat0 <<= 2;
|
||||
dat1 <<= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (colorplus->control & COLORPLUS_640x200_MODE)
|
||||
{
|
||||
cols[0] = (colorplus->cga.cgacol & 15) | 16;
|
||||
col = (colorplus->cga.cgacol & 16) ? 24 : 16;
|
||||
if (colorplus->cga.cgamode & 4)
|
||||
{
|
||||
cols[1] = col | 3;
|
||||
cols[2] = col | 4;
|
||||
cols[3] = col | 7;
|
||||
}
|
||||
else if (colorplus->cga.cgacol & 32)
|
||||
{
|
||||
cols[1] = col | 3;
|
||||
cols[2] = col | 5;
|
||||
cols[3] = col | 7;
|
||||
}
|
||||
else
|
||||
{
|
||||
cols[1] = col | 2;
|
||||
cols[2] = col | 4;
|
||||
cols[3] = col | 6;
|
||||
}
|
||||
for (x = 0; x < colorplus->cga.crtc[1]; x++)
|
||||
{
|
||||
dat0 = (plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) |
|
||||
plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1];
|
||||
dat1 = (plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) |
|
||||
plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1];
|
||||
colorplus->cga.ma++;
|
||||
for (c = 0; c < 16; c++)
|
||||
{
|
||||
buffer->line[colorplus->cga.displine][(x << 4) + c + 8] =
|
||||
cols[(dat0 >> 15) | ((dat1 >> 15) << 1)];
|
||||
dat0 <<= 1;
|
||||
dat1 <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* Top / bottom border */
|
||||
{
|
||||
cols[0] = (colorplus->cga.cgacol & 15) + 16;
|
||||
hline(buffer, 0, colorplus->cga.displine, (colorplus->cga.crtc[1] << 4) + 16, cols[0]);
|
||||
}
|
||||
|
||||
x = (colorplus->cga.crtc[1] << 4) + 16;
|
||||
|
||||
if (colorplus->cga.composite)
|
||||
{
|
||||
for (c = 0; c < x; c++)
|
||||
buffer32->line[colorplus->cga.displine][c] = buffer->line[colorplus->cga.displine][c] & 0xf;
|
||||
|
||||
Composite_Process(&colorplus->cga, 0, x >> 2, buffer32->line[colorplus->cga.displine]);
|
||||
}
|
||||
|
||||
colorplus->cga.sc = oldsc;
|
||||
if (colorplus->cga.vc == colorplus->cga.crtc[7] && !colorplus->cga.sc)
|
||||
colorplus->cga.cgastat |= 8;
|
||||
colorplus->cga.displine++;
|
||||
if (colorplus->cga.displine >= 360)
|
||||
colorplus->cga.displine = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
colorplus->cga.vidtime += colorplus->cga.dispontime;
|
||||
colorplus->cga.linepos = 0;
|
||||
if (colorplus->cga.vsynctime)
|
||||
{
|
||||
colorplus->cga.vsynctime--;
|
||||
if (!colorplus->cga.vsynctime)
|
||||
colorplus->cga.cgastat &= ~8;
|
||||
}
|
||||
if (colorplus->cga.sc == (colorplus->cga.crtc[11] & 31) || ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[11] & 31) >> 1)))
|
||||
{
|
||||
colorplus->cga.con = 0;
|
||||
colorplus->cga.coff = 1;
|
||||
}
|
||||
if ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == (colorplus->cga.crtc[9] >> 1))
|
||||
colorplus->cga.maback = colorplus->cga.ma;
|
||||
if (colorplus->cga.vadj)
|
||||
{
|
||||
colorplus->cga.sc++;
|
||||
colorplus->cga.sc &= 31;
|
||||
colorplus->cga.ma = colorplus->cga.maback;
|
||||
colorplus->cga.vadj--;
|
||||
if (!colorplus->cga.vadj)
|
||||
{
|
||||
colorplus->cga.cgadispon = 1;
|
||||
colorplus->cga.ma = colorplus->cga.maback = (colorplus->cga.crtc[13] | (colorplus->cga.crtc[12] << 8)) & 0x3fff;
|
||||
colorplus->cga.sc = 0;
|
||||
}
|
||||
}
|
||||
else if (colorplus->cga.sc == colorplus->cga.crtc[9])
|
||||
{
|
||||
colorplus->cga.maback = colorplus->cga.ma;
|
||||
colorplus->cga.sc = 0;
|
||||
oldvc = colorplus->cga.vc;
|
||||
colorplus->cga.vc++;
|
||||
colorplus->cga.vc &= 127;
|
||||
|
||||
if (colorplus->cga.vc == colorplus->cga.crtc[6])
|
||||
colorplus->cga.cgadispon = 0;
|
||||
|
||||
if (oldvc == colorplus->cga.crtc[4])
|
||||
{
|
||||
colorplus->cga.vc = 0;
|
||||
colorplus->cga.vadj = colorplus->cga.crtc[5];
|
||||
if (!colorplus->cga.vadj) colorplus->cga.cgadispon = 1;
|
||||
if (!colorplus->cga.vadj) colorplus->cga.ma = colorplus->cga.maback = (colorplus->cga.crtc[13] | (colorplus->cga.crtc[12] << 8)) & 0x3fff;
|
||||
if ((colorplus->cga.crtc[10] & 0x60) == 0x20) colorplus->cga.cursoron = 0;
|
||||
else colorplus->cga.cursoron = colorplus->cga.cgablink & 8;
|
||||
}
|
||||
|
||||
if (colorplus->cga.vc == colorplus->cga.crtc[7])
|
||||
{
|
||||
colorplus->cga.cgadispon = 0;
|
||||
colorplus->cga.displine = 0;
|
||||
colorplus->cga.vsynctime = 16;
|
||||
if (colorplus->cga.crtc[7])
|
||||
{
|
||||
if (colorplus->cga.cgamode & 1) x = (colorplus->cga.crtc[1] << 3) + 16;
|
||||
else x = (colorplus->cga.crtc[1] << 4) + 16;
|
||||
colorplus->cga.lastline++;
|
||||
if (x != xsize || (colorplus->cga.lastline - colorplus->cga.firstline) != ysize)
|
||||
{
|
||||
xsize = x;
|
||||
ysize = colorplus->cga.lastline - colorplus->cga.firstline;
|
||||
if (xsize < 64) xsize = 656;
|
||||
if (ysize < 32) ysize = 200;
|
||||
updatewindowsize(xsize, (ysize << 1) + 16);
|
||||
}
|
||||
|
||||
if (colorplus->cga.composite)
|
||||
video_blit_memtoscreen(0, colorplus->cga.firstline - 4, 0, (colorplus->cga.lastline - colorplus->cga.firstline) + 8, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8);
|
||||
else
|
||||
video_blit_memtoscreen_8(0, colorplus->cga.firstline - 4, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8);
|
||||
frames++;
|
||||
|
||||
video_res_x = xsize - 16;
|
||||
video_res_y = ysize;
|
||||
if (colorplus->cga.cgamode & 1)
|
||||
{
|
||||
video_res_x /= 8;
|
||||
video_res_y /= colorplus->cga.crtc[9] + 1;
|
||||
video_bpp = 0;
|
||||
}
|
||||
else if (!(colorplus->cga.cgamode & 2))
|
||||
{
|
||||
video_res_x /= 16;
|
||||
video_res_y /= colorplus->cga.crtc[9] + 1;
|
||||
video_bpp = 0;
|
||||
}
|
||||
else if (!(colorplus->cga.cgamode & 16))
|
||||
{
|
||||
video_res_x /= 2;
|
||||
video_bpp = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
video_bpp = 1;
|
||||
}
|
||||
}
|
||||
colorplus->cga.firstline = 1000;
|
||||
colorplus->cga.lastline = 0;
|
||||
colorplus->cga.cgablink++;
|
||||
colorplus->cga.oddeven ^= 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
colorplus->cga.sc++;
|
||||
colorplus->cga.sc &= 31;
|
||||
colorplus->cga.ma = colorplus->cga.maback;
|
||||
}
|
||||
if (colorplus->cga.cgadispon)
|
||||
colorplus->cga.cgastat &= ~1;
|
||||
if ((colorplus->cga.sc == (colorplus->cga.crtc[10] & 31) || ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[10] & 31) >> 1))))
|
||||
colorplus->cga.con = 1;
|
||||
if (colorplus->cga.cgadispon && (colorplus->cga.cgamode & 1))
|
||||
{
|
||||
for (x = 0; x < (colorplus->cga.crtc[1] << 1); x++)
|
||||
colorplus->cga.charbuffer[x] = colorplus->cga.vram[(((colorplus->cga.ma << 1) + x) & 0x3fff)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void colorplus_init(colorplus_t *colorplus)
|
||||
{
|
||||
cga_init(&colorplus->cga);
|
||||
}
|
||||
|
||||
void *colorplus_standalone_init()
|
||||
{
|
||||
int display_type;
|
||||
|
||||
colorplus_t *colorplus = malloc(sizeof(colorplus_t));
|
||||
memset(colorplus, 0, sizeof(colorplus_t));
|
||||
|
||||
/* Copied from the CGA init. Ideally this would be done by
|
||||
* calling a helper function rather than duplicating code */
|
||||
display_type = device_get_config_int("display_type");
|
||||
colorplus->cga.composite = (display_type != CGA_RGB);
|
||||
colorplus->cga.revision = device_get_config_int("composite_type");
|
||||
colorplus->cga.snow_enabled = device_get_config_int("snow_enabled");
|
||||
|
||||
colorplus->cga.vram = malloc(0x8000);
|
||||
|
||||
cga_comp_init(&colorplus->cga);
|
||||
timer_add(colorplus_poll, &colorplus->cga.vidtime, TIMER_ALWAYS_ENABLED, colorplus);
|
||||
mem_mapping_add(&colorplus->cga.mapping, 0xb8000, 0x08000, colorplus_read, NULL, NULL, colorplus_write, NULL, NULL, NULL, 0, colorplus);
|
||||
io_sethandler(0x03d0, 0x0010, colorplus_in, NULL, NULL, colorplus_out, NULL, NULL, colorplus);
|
||||
|
||||
return colorplus;
|
||||
}
|
||||
|
||||
void colorplus_close(void *p)
|
||||
{
|
||||
colorplus_t *colorplus = (colorplus_t *)p;
|
||||
|
||||
free(colorplus->cga.vram);
|
||||
free(colorplus);
|
||||
}
|
||||
|
||||
void colorplus_speed_changed(void *p)
|
||||
{
|
||||
colorplus_t *colorplus = (colorplus_t *)p;
|
||||
|
||||
cga_recalctimings(&colorplus->cga);
|
||||
}
|
||||
|
||||
static device_config_t colorplus_config[] =
|
||||
{
|
||||
{
|
||||
.name = "display_type",
|
||||
.description = "Display type",
|
||||
.type = CONFIG_SELECTION,
|
||||
.selection =
|
||||
{
|
||||
{
|
||||
.description = "RGB",
|
||||
.value = CGA_RGB
|
||||
},
|
||||
{
|
||||
.description = "Composite",
|
||||
.value = CGA_COMPOSITE
|
||||
},
|
||||
{
|
||||
.description = ""
|
||||
}
|
||||
},
|
||||
.default_int = CGA_RGB
|
||||
},
|
||||
{
|
||||
.name = "composite_type",
|
||||
.description = "Composite type",
|
||||
.type = CONFIG_SELECTION,
|
||||
.selection =
|
||||
{
|
||||
{
|
||||
.description = "Old",
|
||||
.value = COMPOSITE_OLD
|
||||
},
|
||||
{
|
||||
.description = "New",
|
||||
.value = COMPOSITE_NEW
|
||||
},
|
||||
{
|
||||
.description = ""
|
||||
}
|
||||
},
|
||||
.default_int = COMPOSITE_OLD
|
||||
},
|
||||
{
|
||||
.name = "snow_enabled",
|
||||
.description = "Snow emulation",
|
||||
.type = CONFIG_BINARY,
|
||||
.default_int = 1
|
||||
},
|
||||
{
|
||||
.type = -1
|
||||
}
|
||||
};
|
||||
|
||||
device_t colorplus_device =
|
||||
{
|
||||
"Colorplus",
|
||||
0,
|
||||
colorplus_standalone_init,
|
||||
colorplus_close,
|
||||
NULL,
|
||||
colorplus_speed_changed,
|
||||
NULL,
|
||||
NULL,
|
||||
colorplus_config
|
||||
};
|
||||
15
src/vid_colorplus.h
Normal file
15
src/vid_colorplus.h
Normal file
@@ -0,0 +1,15 @@
|
||||
typedef struct colorplus_t
|
||||
{
|
||||
cga_t cga;
|
||||
uint8_t control;
|
||||
} colorplus_t;
|
||||
|
||||
void colorplus_init(colorplus_t *colorplus);
|
||||
void colorplus_out(uint16_t addr, uint8_t val, void *p);
|
||||
uint8_t colorplus_in(uint16_t addr, void *p);
|
||||
void colorplus_write(uint32_t addr, uint8_t val, void *p);
|
||||
uint8_t colorplus_read(uint32_t addr, void *p);
|
||||
void colorplus_recalctimings(colorplus_t *colorplus);
|
||||
void colorplus_poll(void *p);
|
||||
|
||||
extern device_t colorplus_device;
|
||||
@@ -1191,7 +1191,6 @@ void et4000w32p_pci_write(int func, int addr, uint8_t val, void *p)
|
||||
switch (addr)
|
||||
{
|
||||
case PCI_REG_COMMAND:
|
||||
if (romset == ROM_KN97) return;
|
||||
et4000->pci_regs[PCI_REG_COMMAND] = val & 0x27;
|
||||
if (val & PCI_COMMAND_IO)
|
||||
et4000w32p_io_set(et4000);
|
||||
|
||||
@@ -1267,7 +1267,6 @@ static void riva128_pci_write(int func, int addr, uint8_t val, void *p)
|
||||
return;
|
||||
|
||||
case PCI_REG_COMMAND:
|
||||
if (romset == ROM_KN97) return;
|
||||
riva128->pci_regs[PCI_REG_COMMAND] = val & 0x27;
|
||||
if (val & PCI_COMMAND_IO)
|
||||
{
|
||||
|
||||
@@ -1153,7 +1153,6 @@ static void rivatnt_pci_write(int func, int addr, uint8_t val, void *p)
|
||||
return;
|
||||
|
||||
case PCI_REG_COMMAND:
|
||||
if (romset == ROM_KN97) return;
|
||||
rivatnt->pci_regs[PCI_REG_COMMAND] = val & 0x27;
|
||||
if (val & PCI_COMMAND_IO)
|
||||
{
|
||||
|
||||
@@ -704,7 +704,6 @@ static void fifo_thread(void *param)
|
||||
static void s3_queue(s3_t *s3, uint32_t addr, uint32_t val, uint32_t type)
|
||||
{
|
||||
fifo_entry_t *fifo = &s3->fifo[s3->fifo_write_idx & FIFO_MASK];
|
||||
int c;
|
||||
|
||||
if (FIFO_FULL)
|
||||
{
|
||||
@@ -2115,7 +2114,6 @@ void s3_pci_write(int func, int addr, uint8_t val, void *p)
|
||||
switch (addr)
|
||||
{
|
||||
case PCI_REG_COMMAND:
|
||||
if (romset == ROM_KN97) return;
|
||||
s3->pci_regs[PCI_REG_COMMAND] = val & 0x27;
|
||||
if (val & PCI_COMMAND_IO)
|
||||
s3_io_set(s3);
|
||||
|
||||
@@ -3711,7 +3711,6 @@ static void s3_virge_pci_write(int func, int addr, uint8_t val, void *p)
|
||||
return;
|
||||
|
||||
case PCI_REG_COMMAND:
|
||||
if (romset == ROM_KN97) return;
|
||||
if (val & PCI_COMMAND_IO)
|
||||
{
|
||||
io_removehandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge);
|
||||
|
||||
@@ -334,7 +334,6 @@ uint8_t svga_in(uint16_t addr, void *p)
|
||||
case 0x32CB:
|
||||
pclog("Read port %04X\n", addr);
|
||||
return 0xEE;
|
||||
return charsettings;
|
||||
// return 0xEE | (charedit_on ? 0x10 : 0);
|
||||
|
||||
case 0x3C0:
|
||||
|
||||
@@ -7,7 +7,7 @@ typedef struct svga_t
|
||||
|
||||
uint8_t crtcreg;
|
||||
uint8_t crtc[128];
|
||||
uint8_t gdcreg[16];
|
||||
uint8_t gdcreg[64];
|
||||
int gdcaddr;
|
||||
uint8_t attrregs[32];
|
||||
int attraddr, attrff;
|
||||
|
||||
@@ -161,7 +161,6 @@ void svga_render_text_40_12(svga_t *svga)
|
||||
|
||||
void svga_render_text_80(svga_t *svga)
|
||||
{
|
||||
FILE *f;
|
||||
int y_add = (enable_overscan) ? 16 : 0;
|
||||
int x_add = y_add >> 1;
|
||||
|
||||
@@ -228,7 +227,6 @@ void svga_render_text_80(svga_t *svga)
|
||||
|
||||
void svga_render_text_80_12(svga_t *svga)
|
||||
{
|
||||
FILE *f;
|
||||
int y_add = (enable_overscan) ? 16 : 0;
|
||||
int x_add = (enable_overscan) ? 12 : 0;
|
||||
|
||||
|
||||
1475
src/vid_voodoo.c
1475
src/vid_voodoo.c
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1 @@
|
||||
/* Copyright holders: Sarah Walker
|
||||
see COPYING for more details
|
||||
*/
|
||||
extern device_t voodoo_device;
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#define BLOCK_MASK (BLOCK_NUM-1)
|
||||
#define BLOCK_SIZE 8192
|
||||
|
||||
#define LOD_MASK (LOD_TMIRROR_S | LOD_TMIRROR_T)
|
||||
|
||||
typedef struct voodoo_x86_data_t
|
||||
{
|
||||
uint8_t code_block[BLOCK_SIZE];
|
||||
@@ -29,7 +31,8 @@ typedef struct voodoo_x86_data_t
|
||||
uint32_t fbzMode;
|
||||
uint32_t fogMode;
|
||||
uint32_t fbzColorPath;
|
||||
uint32_t textureMode;
|
||||
uint32_t textureMode[2];
|
||||
uint32_t tLOD[2];
|
||||
uint32_t trexInit1;
|
||||
} voodoo_x86_data_t;
|
||||
|
||||
@@ -250,6 +253,25 @@ static inline int codegen_texture_fetch(uint8_t *code_block, voodoo_t *voodoo, v
|
||||
addbyte(0x8b); /*MOV EBX, state->tex_t[RDI]*/
|
||||
addbyte(0x9f);
|
||||
addlong(offsetof(voodoo_state_t, tex_t));
|
||||
if (params->tLOD[tmu] & LOD_TMIRROR_S)
|
||||
{
|
||||
addbyte(0xa9); /*TEST EAX, 0x1000*/
|
||||
addlong(0x1000);
|
||||
addbyte(0x74); /*JZ +*/
|
||||
addbyte(2);
|
||||
addbyte(0xf7); /*NOT EAX*/
|
||||
addbyte(0xd0);
|
||||
}
|
||||
if (params->tLOD[tmu] & LOD_TMIRROR_T)
|
||||
{
|
||||
addbyte(0xf7); /*TEST EBX, 0x1000*/
|
||||
addbyte(0xc3);
|
||||
addlong(0x1000);
|
||||
addbyte(0x74); /*JZ +*/
|
||||
addbyte(2);
|
||||
addbyte(0xf7); /*NOT EBX*/
|
||||
addbyte(0xd3);
|
||||
}
|
||||
addbyte(0x29); /*SUB EAX, EBP*/
|
||||
addbyte(0xe8);
|
||||
addbyte(0x29); /*SUB EBX, EBP*/
|
||||
@@ -567,6 +589,25 @@ static inline int codegen_texture_fetch(uint8_t *code_block, voodoo_t *voodoo, v
|
||||
addbyte(0x8b); /*MOV EBX, state->tex_t[EDI]*/
|
||||
addbyte(0x9f);
|
||||
addlong(offsetof(voodoo_state_t, tex_t));
|
||||
if (params->tLOD[tmu] & LOD_TMIRROR_S)
|
||||
{
|
||||
addbyte(0xa9); /*TEST EAX, 0x1000*/
|
||||
addlong(0x1000);
|
||||
addbyte(0x74); /*JZ +*/
|
||||
addbyte(2);
|
||||
addbyte(0xf7); /*NOT EAX*/
|
||||
addbyte(0xd0);
|
||||
}
|
||||
if (params->tLOD[tmu] & LOD_TMIRROR_T)
|
||||
{
|
||||
addbyte(0xf7); /*TEST EBX, 0x1000*/
|
||||
addbyte(0xc3);
|
||||
addlong(0x1000);
|
||||
addbyte(0x74); /*JZ +*/
|
||||
addbyte(2);
|
||||
addbyte(0xf7); /*NOT EBX*/
|
||||
addbyte(0xd3);
|
||||
}
|
||||
addbyte(0xd3); /*SHR EAX, CL*/
|
||||
addbyte(0xe8);
|
||||
addbyte(0xd3); /*SHR EBX, CL*/
|
||||
@@ -898,7 +939,7 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
|
||||
addbyte(0x0f);
|
||||
addbyte(0x6e);
|
||||
addbyte(0xc0);
|
||||
addbyte(0xc1); /*SHR EAX, 8*/
|
||||
addbyte(0xc1); /*SHR EAX, 24*/
|
||||
addbyte(0xe8);
|
||||
addbyte(24);
|
||||
addbyte(0x89); /*MOV state->tex_a[RDI], EAX*/
|
||||
@@ -914,7 +955,7 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
|
||||
addbyte(0x0f);
|
||||
addbyte(0x6e);
|
||||
addbyte(0xc0);
|
||||
addbyte(0xc1); /*SHR EAX, 8*/
|
||||
addbyte(0xc1); /*SHR EAX, 24*/
|
||||
addbyte(0xe8);
|
||||
addbyte(24);
|
||||
addbyte(0x89); /*MOV state->tex_a[RDI], EAX*/
|
||||
@@ -1224,6 +1265,10 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
|
||||
addbyte(0x0f);
|
||||
addbyte(0x6e);
|
||||
addbyte(0xc0);
|
||||
addbyte(0x66); /*MOVD XMM7, EAX*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x6e);
|
||||
addbyte(0xf8);
|
||||
|
||||
if (params->textureMode[0] & TEXTUREMODE_TRILINEAR)
|
||||
{
|
||||
@@ -1390,6 +1435,13 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
|
||||
addbyte(0xd5);
|
||||
addbyte(0xcc);
|
||||
|
||||
if (tca_sub_clocal)
|
||||
{
|
||||
addbyte(0x66); /*MOV EBX, XMM7*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x7e);
|
||||
addbyte(0xfb);
|
||||
}
|
||||
|
||||
addbyte(0x66); /*PMULHW XMM5, XMM4*/
|
||||
addbyte(0x0f);
|
||||
@@ -1409,6 +1461,13 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
|
||||
addbyte(0x6b);
|
||||
addbyte(0xc9);
|
||||
|
||||
if (tca_sub_clocal)
|
||||
{
|
||||
addbyte(0xc1); /*SHR EBX, 24*/
|
||||
addbyte(0xeb);
|
||||
addbyte(24);
|
||||
}
|
||||
|
||||
if (tc_add_clocal)
|
||||
{
|
||||
addbyte(0x66); /*PADDW XMM1, XMM0*/
|
||||
@@ -1467,13 +1526,6 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
|
||||
}
|
||||
if (tca_sub_clocal)
|
||||
{
|
||||
addbyte(0x66); /*MOV EBX, XMM0*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x7e);
|
||||
addbyte(0xc3);
|
||||
addbyte(0xc1); /*SHR EBX, 24*/
|
||||
addbyte(0xeb);
|
||||
addbyte(24);
|
||||
addbyte(0x29); /*SUB EAX, EBX*/
|
||||
addbyte(0xd8);
|
||||
}
|
||||
@@ -1484,10 +1536,10 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
|
||||
addbyte(0xdb);
|
||||
break;
|
||||
case TCA_MSELECT_CLOCAL:
|
||||
addbyte(0x66); /*MOV EBX, XMM0*/
|
||||
addbyte(0x66); /*MOV EBX, XMM7*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x7e);
|
||||
addbyte(0xc3);
|
||||
addbyte(0xfb);
|
||||
addbyte(0xc1); /*SHR EBX, 24*/
|
||||
addbyte(0xeb);
|
||||
addbyte(0x24);
|
||||
@@ -1502,10 +1554,10 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
|
||||
addbyte(0x24);
|
||||
break;
|
||||
case TCA_MSELECT_ALOCAL:
|
||||
addbyte(0x66); /*MOV EBX, XMM0*/
|
||||
addbyte(0x66); /*MOV EBX, XMM7*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x7e);
|
||||
addbyte(0xc3);
|
||||
addbyte(0xfb);
|
||||
addbyte(0xc1); /*SHR EBX, 24*/
|
||||
addbyte(0xeb);
|
||||
addbyte(0x24);
|
||||
@@ -1555,15 +1607,15 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
|
||||
addbyte(0xc3);
|
||||
addbyte(0x31); /*XOR EDX, EDX*/
|
||||
addbyte(0xd2);
|
||||
addbyte(0xc1); /*SHR EAX, 8*/
|
||||
addbyte(0xe8);
|
||||
addbyte(0xc1); /*SAR EAX, 8*/
|
||||
addbyte(0xf8);
|
||||
addbyte(8);
|
||||
if (tca_add_clocal || tca_add_alocal)
|
||||
{
|
||||
addbyte(0x66); /*MOV EBX, XMM0*/
|
||||
addbyte(0x66); /*MOV EBX, XMM7*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x7e);
|
||||
addbyte(0xc3);
|
||||
addbyte(0xfb);
|
||||
addbyte(0xc1); /*SHR EBX, 24*/
|
||||
addbyte(0xeb);
|
||||
addbyte(24);
|
||||
@@ -2185,40 +2237,9 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
|
||||
addbyte(0xe3);
|
||||
addbyte(1);
|
||||
|
||||
if (params->fogMode & FOG_Z)
|
||||
{
|
||||
addbyte(0x8b); /*MOV EAX, state->z[EDI]*/
|
||||
addbyte(0x87);
|
||||
addlong(offsetof(voodoo_state_t, z));
|
||||
addbyte(0xc1); /*SHR EAX, 12*/
|
||||
addbyte(0xe8);
|
||||
addbyte(12);
|
||||
addbyte(0x25); /*AND EAX, 0xff*/
|
||||
addlong(0xff);
|
||||
}
|
||||
else if (params->fogMode & FOG_ALPHA)
|
||||
{
|
||||
addbyte(0x8b); /*MOV EAX, state->ia[EDI]*/
|
||||
addbyte(0x87);
|
||||
addlong(offsetof(voodoo_state_t, ia));
|
||||
addbyte(0x31); /*XOR EBX, EBX*/
|
||||
addbyte(0xdb);
|
||||
addbyte(0xc1); /*SAR EAX, 12*/
|
||||
addbyte(0xf8);
|
||||
addbyte(12);
|
||||
addbyte(0x0f); /*CMOVS EAX, EBX*/
|
||||
addbyte(0x48);
|
||||
addbyte(0xc3);
|
||||
addbyte(0xbb); /*MOV EBX, 0xff*/
|
||||
addlong(0xff);
|
||||
addbyte(0x3d); /*CMP EAX, 0xff*/
|
||||
addlong(0xff);
|
||||
addbyte(0x0f); /*CMOVAE EAX, EBX*/
|
||||
addbyte(0x43);
|
||||
addbyte(0xc3);
|
||||
}
|
||||
else
|
||||
switch (params->fogMode & (FOG_Z|FOG_ALPHA))
|
||||
{
|
||||
case 0:
|
||||
addbyte(0x8b); /*MOV EBX, state->w_depth[EDI]*/
|
||||
addbyte(0x9f);
|
||||
addlong(offsetof(voodoo_state_t, w_depth));
|
||||
@@ -2249,6 +2270,66 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
|
||||
addbyte(10);
|
||||
addbyte(0x01); /*ADD EAX, EBX*/
|
||||
addbyte(0xd8);
|
||||
/* int fog_idx = (w_depth >> 10) & 0x3f;
|
||||
|
||||
fog_a = params->fogTable[fog_idx].fog;
|
||||
fog_a += (params->fogTable[fog_idx].dfog * ((w_depth >> 2) & 0xff)) >> 10;*/
|
||||
break;
|
||||
|
||||
case FOG_Z:
|
||||
addbyte(0x8b); /*MOV EAX, state->z[EDI]*/
|
||||
addbyte(0x87);
|
||||
addlong(offsetof(voodoo_state_t, z));
|
||||
addbyte(0xc1); /*SHR EAX, 12*/
|
||||
addbyte(0xe8);
|
||||
addbyte(12);
|
||||
addbyte(0x25); /*AND EAX, 0xff*/
|
||||
addlong(0xff);
|
||||
// fog_a = (z >> 20) & 0xff;
|
||||
break;
|
||||
|
||||
case FOG_ALPHA:
|
||||
addbyte(0x8b); /*MOV EAX, state->ia[EDI]*/
|
||||
addbyte(0x87);
|
||||
addlong(offsetof(voodoo_state_t, ia));
|
||||
addbyte(0x31); /*XOR EBX, EBX*/
|
||||
addbyte(0xdb);
|
||||
addbyte(0xc1); /*SAR EAX, 12*/
|
||||
addbyte(0xf8);
|
||||
addbyte(12);
|
||||
addbyte(0x0f); /*CMOVS EAX, EBX*/
|
||||
addbyte(0x48);
|
||||
addbyte(0xc3);
|
||||
addbyte(0xbb); /*MOV EBX, 0xff*/
|
||||
addlong(0xff);
|
||||
addbyte(0x3d); /*CMP EAX, 0xff*/
|
||||
addlong(0xff);
|
||||
addbyte(0x0f); /*CMOVAE EAX, EBX*/
|
||||
addbyte(0x43);
|
||||
addbyte(0xc3);
|
||||
// fog_a = CLAMP(ia >> 12);
|
||||
break;
|
||||
|
||||
case FOG_W:
|
||||
addbyte(0x8b); /*MOV EAX, state->w[EDI]+4*/
|
||||
addbyte(0x87);
|
||||
addlong(offsetof(voodoo_state_t, w)+4);
|
||||
addbyte(0x31); /*XOR EBX, EBX*/
|
||||
addbyte(0xdb);
|
||||
addbyte(0x09); /*OR EAX, EAX*/
|
||||
addbyte(0xc0);
|
||||
addbyte(0x0f); /*CMOVS EAX, EBX*/
|
||||
addbyte(0x48);
|
||||
addbyte(0xc3);
|
||||
addbyte(0xbb); /*MOV EBX, 0xff*/
|
||||
addlong(0xff);
|
||||
addbyte(0x3d); /*CMP EAX, 0xff*/
|
||||
addlong(0xff);
|
||||
addbyte(0x0f); /*CMOVAE EAX, EBX*/
|
||||
addbyte(0x43);
|
||||
addbyte(0xc3);
|
||||
// fog_a = CLAMP(w >> 32);
|
||||
break;
|
||||
}
|
||||
addbyte(0x01); /*ADD EAX, EAX*/
|
||||
addbyte(0xc0);
|
||||
@@ -3169,7 +3250,10 @@ static inline void *voodoo_get_block(voodoo_t *voodoo, voodoo_params_t *params,
|
||||
params->fogMode == data->fogMode &&
|
||||
params->fbzColorPath == data->fbzColorPath &&
|
||||
(voodoo->trexInit1[0] & (1 << 18)) == data->trexInit1 &&
|
||||
params->textureMode == data->textureMode)
|
||||
params->textureMode[0] == data->textureMode[0] &&
|
||||
params->textureMode[1] == data->textureMode[1] &&
|
||||
(params->tLOD[0] & LOD_MASK) == data->tLOD[0] &&
|
||||
(params->tLOD[1] & LOD_MASK) == data->tLOD[1])
|
||||
{
|
||||
last_block[odd_even] = b;
|
||||
return data->code_block;
|
||||
@@ -3189,7 +3273,10 @@ voodoo_recomp++;
|
||||
data->fogMode = params->fogMode;
|
||||
data->fbzColorPath = params->fbzColorPath;
|
||||
data->trexInit1 = voodoo->trexInit1[0] & (1 << 18);
|
||||
data->textureMode = params->textureMode;
|
||||
data->textureMode[0] = params->textureMode[0];
|
||||
data->textureMode[1] = params->textureMode[1];
|
||||
data->tLOD[0] = params->tLOD[0] & LOD_MASK;
|
||||
data->tLOD[1] = params->tLOD[1] & LOD_MASK;
|
||||
|
||||
next_block_to_write[odd_even] = (next_block_to_write[odd_even] + 1) & 7;
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#define BLOCK_MASK (BLOCK_NUM-1)
|
||||
#define BLOCK_SIZE 8192
|
||||
|
||||
#define LOD_MASK (LOD_TMIRROR_S | LOD_TMIRROR_T)
|
||||
|
||||
typedef struct voodoo_x86_data_t
|
||||
{
|
||||
uint8_t code_block[BLOCK_SIZE];
|
||||
@@ -29,7 +31,8 @@ typedef struct voodoo_x86_data_t
|
||||
uint32_t fbzMode;
|
||||
uint32_t fogMode;
|
||||
uint32_t fbzColorPath;
|
||||
uint32_t textureMode;
|
||||
uint32_t textureMode[2];
|
||||
uint32_t tLOD[2];
|
||||
uint32_t trexInit1;
|
||||
} voodoo_x86_data_t;
|
||||
|
||||
@@ -239,6 +242,25 @@ static inline int codegen_texture_fetch(uint8_t *code_block, voodoo_t *voodoo, v
|
||||
addbyte(0x8b); /*MOV EBX, state->tex_t[EDI]*/
|
||||
addbyte(0x9f);
|
||||
addlong(offsetof(voodoo_state_t, tex_t));
|
||||
if (params->tLOD[tmu] & LOD_TMIRROR_S)
|
||||
{
|
||||
addbyte(0xa9); /*TEST EAX, 0x1000*/
|
||||
addlong(0x1000);
|
||||
addbyte(0x74); /*JZ +*/
|
||||
addbyte(2);
|
||||
addbyte(0xf7); /*NOT EAX*/
|
||||
addbyte(0xd0);
|
||||
}
|
||||
if (params->tLOD[tmu] & LOD_TMIRROR_T)
|
||||
{
|
||||
addbyte(0xf7); /*TEST EBX, 0x1000*/
|
||||
addbyte(0xc3);
|
||||
addlong(0x1000);
|
||||
addbyte(0x74); /*JZ +*/
|
||||
addbyte(2);
|
||||
addbyte(0xf7); /*NOT EBX*/
|
||||
addbyte(0xd3);
|
||||
}
|
||||
addbyte(0x29); /*SUB EAX, EBP*/
|
||||
addbyte(0xe8);
|
||||
addbyte(0x29); /*SUB EBX, EBP*/
|
||||
@@ -548,6 +570,25 @@ static inline int codegen_texture_fetch(uint8_t *code_block, voodoo_t *voodoo, v
|
||||
addbyte(0x8b); /*MOV EBX, state->tex_t[EDI]*/
|
||||
addbyte(0x9f);
|
||||
addlong(offsetof(voodoo_state_t, tex_t));
|
||||
if (params->tLOD[tmu] & LOD_TMIRROR_S)
|
||||
{
|
||||
addbyte(0xa9); /*TEST EAX, 0x1000*/
|
||||
addlong(0x1000);
|
||||
addbyte(0x74); /*JZ +*/
|
||||
addbyte(2);
|
||||
addbyte(0xf7); /*NOT EAX*/
|
||||
addbyte(0xd0);
|
||||
}
|
||||
if (params->tLOD[tmu] & LOD_TMIRROR_T)
|
||||
{
|
||||
addbyte(0xf7); /*TEST EBX, 0x1000*/
|
||||
addbyte(0xc3);
|
||||
addlong(0x1000);
|
||||
addbyte(0x74); /*JZ +*/
|
||||
addbyte(2);
|
||||
addbyte(0xf7); /*NOT EBX*/
|
||||
addbyte(0xd3);
|
||||
}
|
||||
addbyte(0xd3); /*SHR EAX, CL*/
|
||||
addbyte(0xe8);
|
||||
addbyte(0xd3); /*SHR EBX, CL*/
|
||||
@@ -883,7 +924,7 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
|
||||
addbyte(0x0f);
|
||||
addbyte(0x6e);
|
||||
addbyte(0xc0);
|
||||
addbyte(0xc1); /*SHR EAX, 8*/
|
||||
addbyte(0xc1); /*SHR EAX, 24*/
|
||||
addbyte(0xe8);
|
||||
addbyte(24);
|
||||
addbyte(0x89); /*MOV state->tex_a[EDI], EAX*/
|
||||
@@ -899,7 +940,7 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
|
||||
addbyte(0x0f);
|
||||
addbyte(0x6e);
|
||||
addbyte(0xc0);
|
||||
addbyte(0xc1); /*SHR EAX, 8*/
|
||||
addbyte(0xc1); /*SHR EAX, 24*/
|
||||
addbyte(0xe8);
|
||||
addbyte(24);
|
||||
addbyte(0x89); /*MOV state->tex_a[EDI], EAX*/
|
||||
@@ -1207,6 +1248,10 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
|
||||
addbyte(0x0f);
|
||||
addbyte(0x6e);
|
||||
addbyte(0xc0);
|
||||
addbyte(0x66); /*MOVD XMM7, EAX*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x6e);
|
||||
addbyte(0xf8);
|
||||
|
||||
if (params->textureMode[0] & TEXTUREMODE_TRILINEAR)
|
||||
{
|
||||
@@ -1371,6 +1416,13 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
|
||||
addbyte(0xd5);
|
||||
addbyte(0xcc);
|
||||
|
||||
if (tca_sub_clocal)
|
||||
{
|
||||
addbyte(0x66); /*MOV EBX, XMM7*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x7e);
|
||||
addbyte(0xfb);
|
||||
}
|
||||
|
||||
addbyte(0x66); /*PMULHW XMM5, XMM4*/
|
||||
addbyte(0x0f);
|
||||
@@ -1390,6 +1442,13 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
|
||||
addbyte(0x6b);
|
||||
addbyte(0xc9);
|
||||
|
||||
if (tca_sub_clocal)
|
||||
{
|
||||
addbyte(0xc1); /*SHR EBX, 24*/
|
||||
addbyte(0xeb);
|
||||
addbyte(24);
|
||||
}
|
||||
|
||||
if (tc_add_clocal)
|
||||
{
|
||||
addbyte(0x66); /*PADDW XMM1, XMM0*/
|
||||
@@ -1448,13 +1507,6 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
|
||||
}
|
||||
if (tca_sub_clocal)
|
||||
{
|
||||
addbyte(0x66); /*MOV EBX, XMM0*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x7e);
|
||||
addbyte(0xc3);
|
||||
addbyte(0xc1); /*SHR EBX, 24*/
|
||||
addbyte(0xeb);
|
||||
addbyte(24);
|
||||
addbyte(0x29); /*SUB EAX, EBX*/
|
||||
addbyte(0xd8);
|
||||
}
|
||||
@@ -1465,10 +1517,10 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
|
||||
addbyte(0xdb);
|
||||
break;
|
||||
case TCA_MSELECT_CLOCAL:
|
||||
addbyte(0x66); /*MOV EBX, XMM0*/
|
||||
addbyte(0x66); /*MOV EBX, XMM7*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x7e);
|
||||
addbyte(0xc3);
|
||||
addbyte(0xfb);
|
||||
addbyte(0xc1); /*SHR EBX, 24*/
|
||||
addbyte(0xeb);
|
||||
addbyte(0x24);
|
||||
@@ -1483,10 +1535,10 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
|
||||
addbyte(0x24);
|
||||
break;
|
||||
case TCA_MSELECT_ALOCAL:
|
||||
addbyte(0x66); /*MOV EBX, XMM0*/
|
||||
addbyte(0x66); /*MOV EBX, XMM7*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x7e);
|
||||
addbyte(0xc3);
|
||||
addbyte(0xfb);
|
||||
addbyte(0xc1); /*SHR EBX, 24*/
|
||||
addbyte(0xeb);
|
||||
addbyte(0x24);
|
||||
@@ -1536,15 +1588,15 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
|
||||
addbyte(0xc3);
|
||||
addbyte(0x31); /*XOR EDX, EDX*/
|
||||
addbyte(0xd2);
|
||||
addbyte(0xc1); /*SHR EAX, 8*/
|
||||
addbyte(0xe8);
|
||||
addbyte(0xc1); /*SAR EAX, 8*/
|
||||
addbyte(0xf8);
|
||||
addbyte(8);
|
||||
if (tca_add_clocal || tca_add_alocal)
|
||||
{
|
||||
addbyte(0x66); /*MOV EBX, XMM0*/
|
||||
addbyte(0x66); /*MOV EBX, XMM7*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x7e);
|
||||
addbyte(0xc3);
|
||||
addbyte(0xfb);
|
||||
addbyte(0xc1); /*SHR EBX, 24*/
|
||||
addbyte(0xeb);
|
||||
addbyte(24);
|
||||
@@ -2178,42 +2230,9 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
|
||||
addbyte(0xe3);
|
||||
addbyte(1);
|
||||
|
||||
if (params->fogMode & FOG_Z)
|
||||
{
|
||||
addbyte(0x8b); /*MOV EAX, state->z[EDI]*/
|
||||
addbyte(0x87);
|
||||
addlong(offsetof(voodoo_state_t, z));
|
||||
addbyte(0xc1); /*SHR EAX, 12*/
|
||||
addbyte(0xe8);
|
||||
addbyte(12);
|
||||
addbyte(0x25); /*AND EAX, 0xff*/
|
||||
addlong(0xff);
|
||||
// fog_a = (z >> 20) & 0xff;
|
||||
}
|
||||
else if (params->fogMode & FOG_ALPHA)
|
||||
{
|
||||
addbyte(0x8b); /*MOV EAX, state->ia[EDI]*/
|
||||
addbyte(0x87);
|
||||
addlong(offsetof(voodoo_state_t, ia));
|
||||
addbyte(0x31); /*XOR EBX, EBX*/
|
||||
addbyte(0xdb);
|
||||
addbyte(0xc1); /*SAR EAX, 12*/
|
||||
addbyte(0xf8);
|
||||
addbyte(12);
|
||||
addbyte(0x0f); /*CMOVS EAX, EBX*/
|
||||
addbyte(0x48);
|
||||
addbyte(0xc3);
|
||||
addbyte(0xbb); /*MOV EBX, 0xff*/
|
||||
addlong(0xff);
|
||||
addbyte(0x3d); /*CMP EAX, 0xff*/
|
||||
addlong(0xff);
|
||||
addbyte(0x0f); /*CMOVAE EAX, EBX*/
|
||||
addbyte(0x43);
|
||||
addbyte(0xc3);
|
||||
// fog_a = CLAMP(ia >> 12);
|
||||
}
|
||||
else
|
||||
switch (params->fogMode & (FOG_Z|FOG_ALPHA))
|
||||
{
|
||||
case 0:
|
||||
addbyte(0x8b); /*MOV EBX, state->w_depth[EDI]*/
|
||||
addbyte(0x9f);
|
||||
addlong(offsetof(voodoo_state_t, w_depth));
|
||||
@@ -2249,6 +2268,62 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
|
||||
|
||||
fog_a = params->fogTable[fog_idx].fog;
|
||||
fog_a += (params->fogTable[fog_idx].dfog * ((w_depth >> 2) & 0xff)) >> 10;*/
|
||||
break;
|
||||
|
||||
case FOG_Z:
|
||||
addbyte(0x8b); /*MOV EAX, state->z[EDI]*/
|
||||
addbyte(0x87);
|
||||
addlong(offsetof(voodoo_state_t, z));
|
||||
addbyte(0xc1); /*SHR EAX, 12*/
|
||||
addbyte(0xe8);
|
||||
addbyte(12);
|
||||
addbyte(0x25); /*AND EAX, 0xff*/
|
||||
addlong(0xff);
|
||||
// fog_a = (z >> 20) & 0xff;
|
||||
break;
|
||||
|
||||
case FOG_ALPHA:
|
||||
addbyte(0x8b); /*MOV EAX, state->ia[EDI]*/
|
||||
addbyte(0x87);
|
||||
addlong(offsetof(voodoo_state_t, ia));
|
||||
addbyte(0x31); /*XOR EBX, EBX*/
|
||||
addbyte(0xdb);
|
||||
addbyte(0xc1); /*SAR EAX, 12*/
|
||||
addbyte(0xf8);
|
||||
addbyte(12);
|
||||
addbyte(0x0f); /*CMOVS EAX, EBX*/
|
||||
addbyte(0x48);
|
||||
addbyte(0xc3);
|
||||
addbyte(0xbb); /*MOV EBX, 0xff*/
|
||||
addlong(0xff);
|
||||
addbyte(0x3d); /*CMP EAX, 0xff*/
|
||||
addlong(0xff);
|
||||
addbyte(0x0f); /*CMOVAE EAX, EBX*/
|
||||
addbyte(0x43);
|
||||
addbyte(0xc3);
|
||||
// fog_a = CLAMP(ia >> 12);
|
||||
break;
|
||||
|
||||
case FOG_W:
|
||||
addbyte(0x8b); /*MOV EAX, state->w[EDI]+4*/
|
||||
addbyte(0x87);
|
||||
addlong(offsetof(voodoo_state_t, w)+4);
|
||||
addbyte(0x31); /*XOR EBX, EBX*/
|
||||
addbyte(0xdb);
|
||||
addbyte(0x09); /*OR EAX, EAX*/
|
||||
addbyte(0xc0);
|
||||
addbyte(0x0f); /*CMOVS EAX, EBX*/
|
||||
addbyte(0x48);
|
||||
addbyte(0xc3);
|
||||
addbyte(0xbb); /*MOV EBX, 0xff*/
|
||||
addlong(0xff);
|
||||
addbyte(0x3d); /*CMP EAX, 0xff*/
|
||||
addlong(0xff);
|
||||
addbyte(0x0f); /*CMOVAE EAX, EBX*/
|
||||
addbyte(0x43);
|
||||
addbyte(0xc3);
|
||||
// fog_a = CLAMP(w >> 32);
|
||||
break;
|
||||
}
|
||||
addbyte(0x01); /*ADD EAX, EAX*/
|
||||
addbyte(0xc0);
|
||||
@@ -3147,6 +3222,7 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
|
||||
cs = cs;
|
||||
}
|
||||
static int voodoo_recomp = 0;
|
||||
|
||||
static inline void *voodoo_get_block(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int odd_even)
|
||||
{
|
||||
int c;
|
||||
@@ -3164,7 +3240,10 @@ static inline void *voodoo_get_block(voodoo_t *voodoo, voodoo_params_t *params,
|
||||
params->fogMode == data->fogMode &&
|
||||
params->fbzColorPath == data->fbzColorPath &&
|
||||
(voodoo->trexInit1[0] & (1 << 18)) == data->trexInit1 &&
|
||||
params->textureMode[0] == data->textureMode)
|
||||
params->textureMode[0] == data->textureMode[0] &&
|
||||
params->textureMode[1] == data->textureMode[1] &&
|
||||
(params->tLOD[0] & LOD_MASK) == data->tLOD[0] &&
|
||||
(params->tLOD[1] & LOD_MASK) == data->tLOD[1])
|
||||
{
|
||||
last_block[odd_even] = b;
|
||||
return data->code_block;
|
||||
@@ -3184,7 +3263,10 @@ voodoo_recomp++;
|
||||
data->fogMode = params->fogMode;
|
||||
data->fbzColorPath = params->fbzColorPath;
|
||||
data->trexInit1 = voodoo->trexInit1[0] & (1 << 18);
|
||||
data->textureMode = params->textureMode[0];
|
||||
data->textureMode[0] = params->textureMode[0];
|
||||
data->textureMode[1] = params->textureMode[1];
|
||||
data->tLOD[0] = params->tLOD[0] & LOD_MASK;
|
||||
data->tLOD[1] = params->tLOD[1] & LOD_MASK;
|
||||
|
||||
next_block_to_write[odd_even] = (next_block_to_write[odd_even] + 1) & 7;
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
/* Copyright holders: Sarah Walker
|
||||
see COPYING for more details
|
||||
*/
|
||||
uint8_t dither_rb[256][4][4] =
|
||||
{
|
||||
{
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "vid_et4000w32.h"
|
||||
#include "vid_hercules.h"
|
||||
#include "vid_incolor.h"
|
||||
#include "vid_colorplus.h"
|
||||
#include "vid_mda.h"
|
||||
#include "vid_nv_riva128.h"
|
||||
#include "vid_nv_rivatnt.h"
|
||||
@@ -86,6 +87,7 @@ static VIDEO_CARD video_cards[] =
|
||||
{"Phoenix S3 Vision864", &s3_phoenix_vision864_device,GFX_PHOENIX_VISION864},
|
||||
{"Phoenix S3 Trio32", &s3_phoenix_trio32_device, GFX_PHOENIX_TRIO32},
|
||||
{"Phoenix S3 Trio64", &s3_phoenix_trio64_device, GFX_PHOENIX_TRIO64},
|
||||
{"Plantronics ColorPlus", &colorplus_device, GFX_COLORPLUS},
|
||||
{"S3 ViRGE/DX", &s3_virge_375_device, GFX_VIRGEDX},
|
||||
{"Trident TVGA8900D", &tvga8900d_device, GFX_TVGA},
|
||||
{"Tseng ET4000AX", &et4000_device, GFX_ET4000},
|
||||
|
||||
@@ -57,7 +57,6 @@ void CopySurface(IDirectDrawSurface4 *pDDSurface)
|
||||
void DoubleLines(uint8_t *dst, uint8_t *src)
|
||||
{
|
||||
int i = 0;
|
||||
uint8_t temp_buf[8320];
|
||||
for (i = 0; i < ys; i++)
|
||||
{
|
||||
memcpy(dst + (i * xs * 8), src + (i * xs * 4), xs * 4);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
static int opBT_w_r_a16(uint32_t fetchdat)
|
||||
{
|
||||
int tempc;
|
||||
uint16_t temp;
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
|
||||
@@ -255,14 +255,14 @@ static int opFXSAVESTOR_a16(uint32_t fetchdat)
|
||||
/* FXSAVE */
|
||||
// pclog("FXSAVE issued\n");
|
||||
|
||||
if (twd & 0x0003 == 0x0003) ftwb |= 0x01;
|
||||
if (twd & 0x000C == 0x000C) ftwb |= 0x02;
|
||||
if (twd & 0x0030 == 0x0030) ftwb |= 0x04;
|
||||
if (twd & 0x00C0 == 0x00C0) ftwb |= 0x08;
|
||||
if (twd & 0x0300 == 0x0300) ftwb |= 0x10;
|
||||
if (twd & 0x0C00 == 0x0C00) ftwb |= 0x20;
|
||||
if (twd & 0x3000 == 0x3000) ftwb |= 0x40;
|
||||
if (twd & 0xC000 == 0xC000) ftwb |= 0x80;
|
||||
if ((twd & 0x0003) == 0x0003) ftwb |= 0x01;
|
||||
if ((twd & 0x000C) == 0x000C) ftwb |= 0x02;
|
||||
if ((twd & 0x0030) == 0x0030) ftwb |= 0x04;
|
||||
if ((twd & 0x00C0) == 0x00C0) ftwb |= 0x08;
|
||||
if ((twd & 0x0300) == 0x0300) ftwb |= 0x10;
|
||||
if ((twd & 0x0C00) == 0x0C00) ftwb |= 0x20;
|
||||
if ((twd & 0x3000) == 0x3000) ftwb |= 0x40;
|
||||
if ((twd & 0xC000) == 0xC000) ftwb |= 0x80;
|
||||
|
||||
writememw(easeg,cpu_state.eaaddr,cpu_state.npxc);
|
||||
writememw(easeg,cpu_state.eaaddr+2,cpu_state.npxs);
|
||||
@@ -431,14 +431,14 @@ static int opFXSAVESTOR_a32(uint32_t fetchdat)
|
||||
/* FXSAVE */
|
||||
// pclog("FXSAVE issued\n");
|
||||
|
||||
if (twd & 0x0003 == 0x0003) ftwb |= 0x01;
|
||||
if (twd & 0x000C == 0x000C) ftwb |= 0x02;
|
||||
if (twd & 0x0030 == 0x0030) ftwb |= 0x04;
|
||||
if (twd & 0x00C0 == 0x00C0) ftwb |= 0x08;
|
||||
if (twd & 0x0300 == 0x0300) ftwb |= 0x10;
|
||||
if (twd & 0x0C00 == 0x0C00) ftwb |= 0x20;
|
||||
if (twd & 0x3000 == 0x3000) ftwb |= 0x40;
|
||||
if (twd & 0xC000 == 0xC000) ftwb |= 0x80;
|
||||
if ((twd & 0x0003) == 0x0003) ftwb |= 0x01;
|
||||
if ((twd & 0x000C) == 0x000C) ftwb |= 0x02;
|
||||
if ((twd & 0x0030) == 0x0030) ftwb |= 0x04;
|
||||
if ((twd & 0x00C0) == 0x00C0) ftwb |= 0x08;
|
||||
if ((twd & 0x0300) == 0x0300) ftwb |= 0x10;
|
||||
if ((twd & 0x0C00) == 0x0C00) ftwb |= 0x20;
|
||||
if ((twd & 0x3000) == 0x3000) ftwb |= 0x40;
|
||||
if ((twd & 0xC000) == 0xC000) ftwb |= 0x80;
|
||||
|
||||
writememw(easeg,cpu_state.eaaddr,cpu_state.npxc);
|
||||
writememw(easeg,cpu_state.eaaddr+2,cpu_state.npxs);
|
||||
|
||||
@@ -1636,7 +1636,7 @@ void pmodeint(int num, int soft)
|
||||
else
|
||||
{
|
||||
// pclog("INT out of range\n");
|
||||
x86gpf(NULL,(num*8)+2+(soft)?0:1);
|
||||
x86gpf(NULL,(num*8)+2+((soft)?0:1));
|
||||
}
|
||||
if (output) pclog("addr >= IDT.limit\n");
|
||||
return;
|
||||
|
||||
@@ -75,7 +75,6 @@ static int opFST(uint32_t fetchdat)
|
||||
|
||||
static int opFSTP(uint32_t fetchdat)
|
||||
{
|
||||
int temp;
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
if (fplog) pclog("FSTP\n");
|
||||
@@ -507,7 +506,7 @@ static int opFYL2XP1(uint32_t fetchdat)
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
if (fplog) pclog("FYL2XP1\n");
|
||||
ST(1) = ST(1) * (log(ST(0)+1.0) / log(2.0));
|
||||
ST(1) = ST(1) * (log1p(ST(0)) / log(2.0));
|
||||
cpu_state.tag[(cpu_state.TOP + 1) & 7] &= ~TAG_UINT64;
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(250);
|
||||
|
||||
Reference in New Issue
Block a user