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:
OBattler
2016-11-02 22:39:07 +01:00
parent 9a4e044d91
commit e280faa2d6
87 changed files with 16087 additions and 5675 deletions

View File

@@ -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)

View File

@@ -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();

View File

@@ -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

View File

@@ -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

View File

@@ -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++)
{

View File

@@ -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;

View File

@@ -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);

View File

@@ -3637,7 +3637,6 @@ static void FP_FXCH(int reg)
addbyte(0x4c);
addbyte(0xdd);
addbyte(cpu_state_offset(MM));
reg = reg;
}

View File

@@ -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
{

View File

@@ -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];

View File

@@ -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];

View File

@@ -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);

View File

@@ -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
View 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
View 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
View 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
View 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

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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);

File diff suppressed because it is too large Load Diff

View File

@@ -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");
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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];

View File

@@ -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;
}
}
}

View File

@@ -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
View File

@@ -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++;

View File

@@ -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();

View File

@@ -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);

View File

@@ -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)

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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)

View File

@@ -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");

View File

@@ -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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

25
src/lzf/configure.ac Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;
}

View File

@@ -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()
{

View File

@@ -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);

View File

@@ -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());

View File

@@ -26,7 +26,6 @@ static struct
uint8_t flags;
uint8_t resolution;
uint8_t sample_rate;
uint8_t type;
uint8_t command;

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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();

View File

@@ -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();

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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
View 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
View 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;

View File

@@ -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);

View File

@@ -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)
{

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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);

View File

@@ -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:

View File

@@ -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;

View File

@@ -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;

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
extern device_t voodoo_device;

View File

@@ -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;

View File

@@ -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;

View File

@@ -1,6 +1,3 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
uint8_t dither_rb[256][4][4] =
{
{

View File

@@ -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},

View File

@@ -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);

View File

@@ -1,6 +1,5 @@
static int opBT_w_r_a16(uint32_t fetchdat)
{
int tempc;
uint16_t temp;
fetch_ea_16(fetchdat);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);