diff --git a/src/86box.h b/src/86box.h index 19ffc1e30..7998741cf 100644 --- a/src/86box.h +++ b/src/86box.h @@ -8,7 +8,7 @@ * * Main include file for the application. * - * Version: @(#)86box.h 1.0.19 2018/03/17 + * Version: @(#)86box.h 1.0.20 2018/03/18 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -90,11 +90,11 @@ extern int vid_cga_contrast, /* (C) video */ video_fullscreen_scale, /* (C) video */ enable_overscan, /* (C) video */ force_43, /* (C) video */ + gfxcard, /* (C) graphics/video card */ video_speed; /* (C) video */ extern int serial_enabled[], /* (C) enable serial ports */ lpt_enabled, /* (C) enable LPT ports */ bugger_enabled; /* (C) enable ISAbugger */ -extern int gfxcard; /* (C) graphics/video card */ extern int sound_is_float, /* (C) sound uses FP values */ GAMEBLASTER, /* (C) sound option */ GUS, /* (C) sound option */ @@ -106,6 +106,9 @@ extern int cpu_manufacturer, /* (C) cpu manufacturer */ cpu_use_dynarec, /* (C) cpu uses/needs Dyna */ enable_external_fpu; /* (C) enable external FPU */ extern int enable_sync; /* (C) enable time sync */ +extern int network_type; /* (C) net provider type */ +extern int network_card; /* (C) net interface num */ +extern char network_host[512]; /* (C) host network intf */ #ifdef ENABLE_LOG_TOGGLES diff --git a/src/bugger.c b/src/bugger.c index 7f2ced877..f70a25c6e 100644 --- a/src/bugger.c +++ b/src/bugger.c @@ -44,10 +44,10 @@ * configuration register (CTRL_SPCFG bit set) but have to * remember that stuff first... * - * Version: @(#)bugger.c 1.0.9 2017/10/28 + * Version: @(#)bugger.c 1.0.10 2018/03/18 * * Author: Fred N. van Kempen, - * Copyright 1989-2017 Fred N. van Kempen. + * Copyright 1989-2018 Fred N. van Kempen. */ #include #include @@ -309,7 +309,7 @@ bug_read(uint16_t port, void *priv) /* Initialize the ISA BusBugger emulator. */ static void * -bug_init(device_t *info) +bug_init(const device_t *info) { pclog("%s, I/O=%04x\n", info->name, BUGGER_ADDR); @@ -320,7 +320,7 @@ bug_init(device_t *info) bug_read, NULL, NULL, bug_write, NULL, NULL, NULL); /* Just so its not NULL. */ - return(info); + return(&bug_ctrl); } @@ -333,7 +333,7 @@ bug_close(UNUSED(void *priv)) } -device_t bugger_device = { +const device_t bugger_device = { "ISA/PCI Bus Bugger", DEVICE_ISA | DEVICE_AT, 0, diff --git a/src/bugger.h b/src/bugger.h index 0726d8b01..d3a1ac775 100644 --- a/src/bugger.h +++ b/src/bugger.h @@ -15,11 +15,11 @@ * * Definitions for the BUGGER card. * - * Version: @(#)bugger.h 1.0.5 2017/10/28 + * Version: @(#)bugger.h 1.0.6 2018/03/18 * * Author: Fred N. van Kempen, * - * Copyright 1989-2017 Fred N. van Kempen. + * Copyright 1989-2018 Fred N. van Kempen. */ #ifndef BUGGER_H # define BUGGER_H @@ -35,7 +35,7 @@ extern "C" { #endif /* Global variables. */ -extern device_t bugger_device; +extern const device_t bugger_device; /* Functions. */ diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index cc7391a0d..437b686cd 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -9,7 +9,7 @@ * Implementation of the CD-ROM drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)cdrom.c 1.0.40 2018/03/18 + * Version: @(#)cdrom.c 1.0.41 2018/03/18 * * Author: Miran Grca, * @@ -97,7 +97,7 @@ static struct /* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ -uint8_t cdrom_command_flags[0x100] = +const uint8_t cdrom_command_flags[0x100] = { IMPLEMENTED | CHECK_READY | NONDATA, IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, diff --git a/src/config.c b/src/config.c index c6d348bc5..494600002 100644 --- a/src/config.c +++ b/src/config.c @@ -8,7 +8,7 @@ * * Configuration file handler. * - * Version: @(#)config.c 1.0.45 2018/03/17 + * Version: @(#)config.c 1.0.46 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -55,7 +55,6 @@ #include "sound/sound.h" #include "video/video.h" #include "plat.h" -#include "plat_joystick.h" #include "plat_midi.h" #include "ui.h" @@ -649,22 +648,27 @@ load_network(void) } else network_type = NET_TYPE_NONE; - memset(network_pcap, '\0', sizeof(network_pcap)); - p = config_get_string(cat, "net_pcap_device", NULL); + memset(network_host, '\0', sizeof(network_host)); + p = config_get_string(cat, "net_host_device", NULL); + if (p == NULL) { + p = config_get_string(cat, "net_host_device", NULL); + if (p != NULL) + config_delete_var(cat, "net_host_device"); + } if (p != NULL) { if ((network_dev_to_id(p) == -1) || (network_ndev == 1)) { - if ((network_ndev == 1) && strcmp(network_pcap, "none")) { + if ((network_ndev == 1) && strcmp(network_host, "none")) { ui_msgbox(MBX_ERROR, (wchar_t *)IDS_2140); } else if (network_dev_to_id(p) == -1) { ui_msgbox(MBX_ERROR, (wchar_t *)IDS_2141); } - strcpy(network_pcap, "none"); + strcpy(network_host, "none"); } else { - strcpy(network_pcap, p); + strcpy(network_host, p); } } else - strcpy(network_pcap, "none"); + strcpy(network_host, "none"); p = config_get_string(cat, "net_card", NULL); if (p != NULL) @@ -1752,14 +1756,14 @@ save_network(void) config_set_string(cat, "net_type", (network_type == NET_TYPE_SLIRP) ? "slirp" : "pcap"); - if (network_pcap[0] != '\0') { - if (! strcmp(network_pcap, "none")) - config_delete_var(cat, "net_pcap_device"); + if (network_host[0] != '\0') { + if (! strcmp(network_host, "none")) + config_delete_var(cat, "net_host_device"); else - config_set_string(cat, "net_pcap_device", network_pcap); + config_set_string(cat, "net_host_device", network_host); } else { - /* config_set_string(cat, "net_pcap_device", "none"); */ - config_delete_var(cat, "net_pcap_device"); + /* config_set_string(cat, "net_host_device", "none"); */ + config_delete_var(cat, "net_host_device"); } if (network_card == 0) diff --git a/src/device.c b/src/device.c index 0e057cd53..98f665a5e 100644 --- a/src/device.c +++ b/src/device.c @@ -1,21 +1,41 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * Implementation of the generic device interface to handle * all devices attached to the emulator. * - * Version: @(#)device.c 1.0.9 2018/03/02 + * Version: @(#)device.c 1.0.5 2018/03/18 * - * Authors: Sarah Walker, + * Authors: Fred N. van Kempen, * Miran Grca, + * Sarah Walker, * - * Copyright 2008-2018 Sarah Walker. + * Copyright 2017,2018 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ #include #include @@ -32,8 +52,8 @@ #define DEVICE_MAX 256 /* max # of devices */ -static device_t *devices[DEVICE_MAX]; static void *device_priv[DEVICE_MAX]; +static device_t *devices[DEVICE_MAX]; static device_t *device_current; @@ -45,48 +65,49 @@ device_init(void) void * -device_add(device_t *d) +device_add(const device_t *d) { void *priv = NULL; int c; for (c=0; c<256; c++) { - if (devices[c] == d) { - fatal("device_add: device already exists!\n"); - break; + if (devices[c] == (device_t *)d) { + pclog("DEVICE: device already exists!\n"); + return(NULL); } if (devices[c] == NULL) break; } if (c >= DEVICE_MAX) - fatal("device_add: too many devices\n"); + fatal("DEVICE: too many devices\n"); - device_current = d; + device_current = (device_t *)d; if (d->init != NULL) { priv = d->init(d); if (priv == NULL) { if (d->name) - fatal("device_add: device init failed (%s)\n", d->name); - else - fatal("device_add: device init failed\n"); + pclog("DEVICE: device '%s' init failed\n", d->name); + else + pclog("DEVICE: device init failed\n"); + return(NULL); } } - devices[c] = d; + devices[c] = (device_t *)d; device_priv[c] = priv; - return priv; + return(priv); } /* For devices that do not have an init function (internal video etc.) */ void -device_add_ex(device_t *d, void *priv) +device_add_ex(const device_t *d, void *priv) { int c; for (c=0; c<256; c++) { - if (devices[c] == d) { + if (devices[c] == (device_t *)d) { fatal("device_add: device already exists!\n"); break; } @@ -95,9 +116,9 @@ device_add_ex(device_t *d, void *priv) if (c >= DEVICE_MAX) fatal("device_add: too many devices\n"); - device_current = d; + device_current = (device_t *)d; - devices[c] = d; + devices[c] = (device_t *)d; device_priv[c] = priv; } @@ -132,7 +153,7 @@ device_reset_all(void) void * -device_get_priv(device_t *d) +device_get_priv(const device_t *d) { int c; @@ -148,7 +169,7 @@ device_get_priv(device_t *d) int -device_available(device_t *d) +device_available(const device_t *d) { #ifdef RELEASE_BUILD if (d->flags & DEVICE_NOT_WORKING) return(0); @@ -207,11 +228,11 @@ device_add_status_info(char *s, int max_len) char * device_get_config_string(char *s) { - device_config_t *c = device_current->config; + const device_config_t *c = device_current->config; while (c && c->type != -1) { if (! strcmp(s, c->name)) - return(config_get_string((char *) device_current->name, s, (char *) c->default_string)); + return(config_get_string((char *)device_current->name, s, (char *)c->default_string)); c++; } @@ -223,11 +244,11 @@ device_get_config_string(char *s) int device_get_config_int(char *s) { - device_config_t *c = device_current->config; + const device_config_t *c = device_current->config; while (c && c->type != -1) { if (! strcmp(s, c->name)) - return(config_get_int((char *) device_current->name, s, c->default_int)); + return(config_get_int((char *)device_current->name, s, c->default_int)); c++; } @@ -239,11 +260,11 @@ device_get_config_int(char *s) int device_get_config_int_ex(char *s, int default_int) { - device_config_t *c = device_current->config; + const device_config_t *c = device_current->config; while (c && c->type != -1) { if (! strcmp(s, c->name)) - return(config_get_int((char *) device_current->name, s, default_int)); + return(config_get_int((char *)device_current->name, s, default_int)); c++; } @@ -255,11 +276,11 @@ device_get_config_int_ex(char *s, int default_int) int device_get_config_hex16(char *s) { - device_config_t *c = device_current->config; + const device_config_t *c = device_current->config; while (c && c->type != -1) { if (! strcmp(s, c->name)) - return(config_get_hex16((char *) device_current->name, s, c->default_int)); + return(config_get_hex16((char *)device_current->name, s, c->default_int)); c++; } @@ -271,11 +292,11 @@ device_get_config_hex16(char *s) int device_get_config_hex20(char *s) { - device_config_t *c = device_current->config; + const device_config_t *c = device_current->config; while (c && c->type != -1) { if (! strcmp(s, c->name)) - return(config_get_hex20((char *) device_current->name, s, c->default_int)); + return(config_get_hex20((char *)device_current->name, s, c->default_int)); c++; } @@ -287,11 +308,11 @@ device_get_config_hex20(char *s) int device_get_config_mac(char *s, int default_int) { - device_config_t *c = device_current->config; + const device_config_t *c = device_current->config; while (c && c->type != -1) { if (! strcmp(s, c->name)) - return(config_get_mac((char *) device_current->name, s, default_int)); + return(config_get_mac((char *)device_current->name, s, default_int)); c++; } @@ -303,11 +324,11 @@ device_get_config_mac(char *s, int default_int) void device_set_config_int(char *s, int val) { - device_config_t *c = device_current->config; + const device_config_t *c = device_current->config; while (c && c->type != -1) { if (! strcmp(s, c->name)) { - config_set_int((char *) device_current->name, s, val); + config_set_int((char *)device_current->name, s, val); break; } @@ -319,11 +340,11 @@ device_set_config_int(char *s, int val) void device_set_config_hex16(char *s, int val) { - device_config_t *c = device_current->config; + const device_config_t *c = device_current->config; while (c && c->type != -1) { if (! strcmp(s, c->name)) { - config_set_hex16((char *) device_current->name, s, val); + config_set_hex16((char *)device_current->name, s, val); break; } @@ -335,11 +356,11 @@ device_set_config_hex16(char *s, int val) void device_set_config_hex20(char *s, int val) { - device_config_t *c = device_current->config; + const device_config_t *c = device_current->config; while (c && c->type != -1) { if (! strcmp(s, c->name)) { - config_set_hex20((char *) device_current->name, s, val); + config_set_hex20((char *)device_current->name, s, val); break; } @@ -351,11 +372,11 @@ device_set_config_hex20(char *s, int val) void device_set_config_mac(char *s, int val) { - device_config_t *c = device_current->config; + const device_config_t *c = device_current->config; while (c && c->type != -1) { if (! strcmp(s, c->name)) { - config_set_mac((char *) device_current->name, s, val); + config_set_mac((char *)device_current->name, s, val); break; } @@ -365,65 +386,43 @@ device_set_config_mac(char *s, int val) int -device_is_valid(device_t *device, int machine_flags) +device_is_valid(const device_t *device, int mflags) { - if (!device) - { - return 1; - } + if (device == NULL) return(1); - if ((device->flags & DEVICE_AT) && !(machine_flags & MACHINE_AT)) { - return 0; - } + if ((device->flags & DEVICE_AT) && !(mflags & MACHINE_AT)) return(0); - if ((device->flags & DEVICE_CBUS) && !(machine_flags & MACHINE_CBUS)) { - return 0; - } + if ((device->flags & DEVICE_CBUS) && !(mflags & MACHINE_CBUS)) return(0); - if ((device->flags & DEVICE_ISA) && !(machine_flags & MACHINE_ISA)) { - return 0; - } + if ((device->flags & DEVICE_ISA) && !(mflags & MACHINE_ISA)) return(0); - if ((device->flags & DEVICE_MCA) && !(machine_flags & MACHINE_MCA)) { - return 0; - } + if ((device->flags & DEVICE_MCA) && !(mflags & MACHINE_MCA)) return(0); - if ((device->flags & DEVICE_EISA) && !(machine_flags & MACHINE_EISA)) { - return 0; - } + if ((device->flags & DEVICE_EISA) && !(mflags & MACHINE_EISA)) return(0); - if ((device->flags & DEVICE_VLB) && !(machine_flags & MACHINE_VLB)) { - return 0; - } + if ((device->flags & DEVICE_VLB) && !(mflags & MACHINE_VLB)) return(0); - if ((device->flags & DEVICE_PCI) && !(machine_flags & MACHINE_PCI)) { - return 0; - } + if ((device->flags & DEVICE_PCI) && !(mflags & MACHINE_PCI)) return(0); - if ((device->flags & DEVICE_PS2) && !(machine_flags & MACHINE_HDC_PS2)) { - return 0; - } + if ((device->flags & DEVICE_PS2) && !(mflags & MACHINE_HDC_PS2)) return(0); + if ((device->flags & DEVICE_AGP) && !(mflags & MACHINE_AGP)) return(0); - if ((device->flags & DEVICE_AGP) && !(machine_flags & MACHINE_AGP)) { - return 0; - } - - return 1; + return(1); } int machine_get_config_int(char *s) { - device_t *d = machine_getdevice(machine); - device_config_t *c; + const device_t *d = machine_getdevice(machine); + const device_config_t *c; if (d == NULL) return(0); c = d->config; while (c && c->type != -1) { if (! strcmp(s, c->name)) - return(config_get_int((char *) d->name, s, c->default_int)); + return(config_get_int((char *)d->name, s, c->default_int)); c++; } @@ -435,15 +434,15 @@ machine_get_config_int(char *s) char * machine_get_config_string(char *s) { - device_t *d = machine_getdevice(machine); - device_config_t *c; + const device_t *d = machine_getdevice(machine); + const device_config_t *c; if (d == NULL) return(0); c = d->config; while (c && c->type != -1) { if (! strcmp(s, c->name)) - return(config_get_string((char *) d->name, s, (char *) c->default_string)); + return(config_get_string((char *)d->name, s, (char *)c->default_string)); c++; } diff --git a/src/device.h b/src/device.h index 5c55c7992..32f803aff 100644 --- a/src/device.h +++ b/src/device.h @@ -1,23 +1,40 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * - * Implementation of the generic device interface to handle - * all devices attached to the emulator. + * Definitions for the device handler. * - * Version: @(#)device.h 1.0.8 2018/02/18 + * Version: @(#)device.h 1.0.3 2018/03/15 * - * Authors: Sarah Walker, + * Authors: Fred N. van Kempen, * Miran Grca, - * Fred N. van Kempen, + * Sarah Walker, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ #ifndef EMU_DEVICE_H # define EMU_DEVICE_H @@ -81,7 +98,7 @@ typedef struct _device_ { uint32_t flags; /* system flags */ uint32_t local; /* flags local to device */ - void *(*init)(struct _device_ *); + void *(*init)(const struct _device_ *); void (*close)(void *p); void (*reset)(void *p); int (*available)(/*void*/); @@ -89,7 +106,7 @@ typedef struct _device_ { void (*force_redraw)(void *p); void (*add_status_info)(char *s, int max_len, void *p); - device_config_t *config; + const device_config_t *config; } device_t; @@ -98,12 +115,12 @@ extern "C" { #endif extern void device_init(void); -extern void *device_add(device_t *d); -extern void device_add_ex(device_t *d, void *priv); +extern void *device_add(const device_t *d); +extern void device_add_ex(const device_t *d, void *priv); extern void device_close_all(void); extern void device_reset_all(void); -extern void *device_get_priv(device_t *d); -extern int device_available(device_t *d); +extern void *device_get_priv(const device_t *d); +extern int device_available(const device_t *d); extern void device_speed_changed(void); extern void device_force_redraw(void); extern void device_add_status_info(char *s, int max_len); @@ -118,7 +135,7 @@ extern void device_set_config_hex16(char *s, int val); extern void device_set_config_hex20(char *s, int val); extern void device_set_config_mac(char *s, int val); extern char *device_get_config_string(char *name); -extern int device_is_valid(device_t *device, int machine_flags); +extern int device_is_valid(const device_t *device, int machine_flags); extern int machine_get_config_int(char *s); extern char *machine_get_config_string(char *s); diff --git a/src/disk/hdc.c b/src/disk/hdc.c index e11c80367..809b82592 100644 --- a/src/disk/hdc.c +++ b/src/disk/hdc.c @@ -8,7 +8,7 @@ * * Common code to handle all sorts of disk controllers. * - * Version: @(#)hdc.c 1.0.10 2018/03/17 + * Version: @(#)hdc.c 1.0.11 2018/03/18 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -32,7 +32,7 @@ int hdc_current; static void * -null_init(device_t *info) +null_init(const device_t *info) { return(NULL); } @@ -44,7 +44,7 @@ null_close(void *priv) } -static device_t null_device = { +static const device_t null_device = { "Null HDC", 0, 0, null_init, null_close, NULL, NULL, NULL, NULL, NULL, NULL @@ -52,7 +52,7 @@ static device_t null_device = { static void * -inthdc_init(device_t *info) +inthdc_init(const device_t *info) { return(NULL); } @@ -64,17 +64,17 @@ inthdc_close(void *priv) } -static device_t inthdc_device = { +static const device_t inthdc_device = { "Internal Controller", 0, 0, inthdc_init, inthdc_close, NULL, NULL, NULL, NULL, NULL, NULL }; -static struct { +static const struct { char *name; char *internal_name; - device_t *device; + const device_t *device; int is_mfm; } controllers[] = { { "None", "none", @@ -185,7 +185,7 @@ hdc_get_internal_name(int hdc) } -device_t * +const device_t * hdc_get_device(int hdc) { return(controllers[hdc].device); diff --git a/src/disk/hdc.h b/src/disk/hdc.h index 3066a579b..5f4f9a934 100644 --- a/src/disk/hdc.h +++ b/src/disk/hdc.h @@ -8,7 +8,7 @@ * * Definitions for the common disk controller handler. * - * Version: @(#)hdc.h 1.0.5 2018/02/14 + * Version: @(#)hdc.h 1.0.6 2018/03/18 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -32,25 +32,25 @@ extern char *hdc_name; extern int hdc_current; -extern device_t mfm_xt_xebec_device; /* mfm_xt_xebec */ -extern device_t mfm_xt_dtc5150x_device; /* mfm_xt_dtc */ -extern device_t mfm_at_wd1003_device; /* mfm_at_wd1003 */ +extern const device_t mfm_xt_xebec_device; /* mfm_xt_xebec */ +extern const device_t mfm_xt_dtc5150x_device; /* mfm_xt_dtc */ +extern const device_t mfm_at_wd1003_device; /* mfm_at_wd1003 */ -extern device_t esdi_at_wd1007vse1_device; /* esdi_at */ -extern device_t esdi_ps2_device; /* esdi_mca */ +extern const device_t esdi_at_wd1007vse1_device; /* esdi_at */ +extern const device_t esdi_ps2_device; /* esdi_mca */ -extern device_t ide_isa_device; /* isa_ide */ -extern device_t ide_isa_2ch_device; /* isa_ide_2ch */ -extern device_t ide_isa_2ch_opt_device; /* isa_ide_2ch_opt */ -extern device_t ide_vlb_device; /* vlb_ide */ -extern device_t ide_vlb_2ch_device; /* vlb_ide_2ch */ -extern device_t ide_pci_device; /* pci_ide */ -extern device_t ide_pci_2ch_device; /* pci_ide_2ch */ +extern const device_t ide_isa_device; /* isa_ide */ +extern const device_t ide_isa_2ch_device; /* isa_ide_2ch */ +extern const device_t ide_isa_2ch_opt_device; /* isa_ide_2ch_opt */ +extern const device_t ide_vlb_device; /* vlb_ide */ +extern const device_t ide_vlb_2ch_device; /* vlb_ide_2ch */ +extern const device_t ide_pci_device; /* pci_ide */ +extern const device_t ide_pci_2ch_device; /* pci_ide_2ch */ -extern device_t xtide_device; /* xtide_xt */ -extern device_t xtide_at_device; /* xtide_at */ -extern device_t xtide_acculogic_device; /* xtide_ps2 */ -extern device_t xtide_at_ps2_device; /* xtide_at_ps2 */ +extern const device_t xtide_device; /* xtide_xt */ +extern const device_t xtide_at_device; /* xtide_at */ +extern const device_t xtide_acculogic_device; /* xtide_ps2 */ +extern const device_t xtide_at_ps2_device; /* xtide_at_ps2 */ extern void hdc_init(char *name); @@ -58,7 +58,7 @@ extern void hdc_reset(void); extern char *hdc_get_name(int hdc); extern char *hdc_get_internal_name(int hdc); -extern device_t *hdc_get_device(int hdc); +extern const device_t *hdc_get_device(int hdc); extern int hdc_get_flags(int hdc); extern int hdc_available(int hdc); extern int hdc_current_is_mfm(void); diff --git a/src/disk/hdc_esdi_at.c b/src/disk/hdc_esdi_at.c index 6dc05e237..fe8dd1870 100644 --- a/src/disk/hdc_esdi_at.c +++ b/src/disk/hdc_esdi_at.c @@ -8,15 +8,15 @@ * * Driver for the ESDI controller (WD1007-vse1) for PC/AT. * - * Version: @(#)hdc_esdi_at.c 1.0.8 2017/11/08 + * Version: @(#)hdc_esdi_at.c 1.0.9 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. - * Copyright 2017 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. */ #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE @@ -770,7 +770,7 @@ loadhd(esdi_t *esdi, int hdd_num, int d, const wchar_t *fn) static void * -wd1007vse1_init(device_t *info) +wd1007vse1_init(const device_t *info) { int c, d; @@ -835,7 +835,7 @@ wd1007vse1_available(void) } -device_t esdi_at_wd1007vse1_device = { +const device_t esdi_at_wd1007vse1_device = { "Western Digital WD1007V-SE1 (ESDI)", DEVICE_ISA | DEVICE_AT, 0, diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index c2d0bf5c2..b7dbeb515 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -52,13 +52,13 @@ * however, are auto-configured by the system software as * shown above. * - * Version: @(#)hdc_esdi_mca.c 1.0.8 2017/11/04 + * Version: @(#)hdc_esdi_mca.c 1.0.9 2018/03/18 * * Authors: Sarah Walker, * Fred N. van Kempen, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2017 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2017,2018 Fred N. van Kempen. */ #include #include @@ -1041,7 +1041,7 @@ esdi_mca_write(int port, uint8_t val, void *priv) static void * -esdi_init(device_t *info) +esdi_init(const device_t *info) { drive_t *drive; esdi_t *dev; @@ -1135,7 +1135,7 @@ esdi_available(void) } -device_t esdi_ps2_device = { +const device_t esdi_ps2_device = { "IBM ESDI Fixed Disk Adapter (MCA)", DEVICE_MCA, 0, esdi_init, esdi_close, NULL, diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 6d42a91ce..889058198 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -9,7 +9,7 @@ * Implementation of the IDE emulation for hard disks and ATAPI * CD-ROM devices. * - * Version: @(#)hdc_ide.c 1.0.39 2018/03/17 + * Version: @(#)hdc_ide.c 1.0.40 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -2856,12 +2856,12 @@ void secondary_ide_check(void) * Initialization of standalone IDE controller instance. * * Eventually, we should clean up the whole mess by only - * using device_t units, with configuration parameters to + * using const device_t units, with configuration parameters to * indicate primary/secondary and all that, rather than * keeping a zillion of duplicate functions around. */ static void * -ide_sainit(device_t *info) +ide_sainit(const device_t *info) { switch(info->local) { case 0: /* ISA, single-channel */ @@ -2891,7 +2891,7 @@ ide_sainit(device_t *info) break; } - return(info); + return(ide_drives); } @@ -2903,7 +2903,7 @@ ide_saclose(void *priv) } -device_t ide_isa_device = { +const device_t ide_isa_device = { "ISA PC/AT IDE Controller", DEVICE_ISA | DEVICE_AT, 0, @@ -2912,7 +2912,7 @@ device_t ide_isa_device = { NULL }; -device_t ide_isa_2ch_device = { +const device_t ide_isa_2ch_device = { "ISA PC/AT IDE Controller (Dual-Channel)", DEVICE_ISA | DEVICE_AT, 2, @@ -2921,7 +2921,7 @@ device_t ide_isa_2ch_device = { NULL }; -device_t ide_isa_2ch_opt_device = { +const device_t ide_isa_2ch_opt_device = { "ISA PC/AT IDE Controller (Single/Dual)", DEVICE_ISA | DEVICE_AT, 3, @@ -2930,7 +2930,7 @@ device_t ide_isa_2ch_opt_device = { NULL }; -device_t ide_vlb_device = { +const device_t ide_vlb_device = { "VLB IDE Controller", DEVICE_VLB | DEVICE_AT, 4, @@ -2939,7 +2939,7 @@ device_t ide_vlb_device = { NULL }; -device_t ide_vlb_2ch_device = { +const device_t ide_vlb_2ch_device = { "VLB IDE Controller (Dual-Channel)", DEVICE_VLB | DEVICE_AT, 6, @@ -2948,7 +2948,7 @@ device_t ide_vlb_2ch_device = { NULL }; -device_t ide_pci_device = { +const device_t ide_pci_device = { "PCI IDE Controller", DEVICE_PCI | DEVICE_AT, 8, @@ -2957,7 +2957,7 @@ device_t ide_pci_device = { NULL }; -device_t ide_pci_2ch_device = { +const device_t ide_pci_2ch_device = { "PCI IDE Controller (Dual-Channel)", DEVICE_PCI | DEVICE_AT, 10, diff --git a/src/disk/hdc_mfm_at.c b/src/disk/hdc_mfm_at.c index 907338b6a..0879c75b5 100644 --- a/src/disk/hdc_mfm_at.c +++ b/src/disk/hdc_mfm_at.c @@ -12,13 +12,13 @@ * based design. Most cards were WD1003-WA2 or -WAH, where the * -WA2 cards had a floppy controller as well (to save space.) * - * Version: @(#)hdc_mfm_at.c 1.0.12 2017/12/09 + * Version: @(#)hdc_mfm_at.c 1.0.13 2018/03/18 * * Authors: Sarah Walker, * Fred N. van Kempen, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2017 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2017,2018 Fred N. van Kempen. */ #define __USE_LARGEFILE64 #define _LARGEFILE_SOURCE @@ -707,7 +707,7 @@ loadhd(mfm_t *mfm, int c, int d, const wchar_t *fn) static void * -mfm_init(device_t *info) +mfm_init(const device_t *info) { mfm_t *mfm; int c, d; @@ -764,7 +764,7 @@ mfm_close(void *priv) } -device_t mfm_at_wd1003_device = { +const device_t mfm_at_wd1003_device = { "WD1003 AT MFM/RLL Controller", DEVICE_ISA | DEVICE_AT, 0, diff --git a/src/disk/hdc_mfm_xt.c b/src/disk/hdc_mfm_xt.c index 798fa526a..2eb2fd2c4 100644 --- a/src/disk/hdc_mfm_xt.c +++ b/src/disk/hdc_mfm_xt.c @@ -41,13 +41,13 @@ * Since all controllers (including the ones made by DTC) use * (mostly) the same API, we keep them all in this module. * - * Version: @(#)hdc_mfm_xt.c 1.0.13 2017/11/06 + * Version: @(#)hdc_mfm_xt.c 1.0.14 2018/03/18 * * Authors: Sarah Walker, * Fred N. van Kempen, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2017 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2017,2018 Fred N. van Kempen. */ #define __USE_LARGEFILE64 #define _LARGEFILE_SOURCE @@ -808,7 +808,7 @@ mfm_set_switches(mfm_t *mfm) static void * -xebec_init(device_t *info) +xebec_init(const device_t *info) { int i, c = 0; @@ -863,7 +863,7 @@ xebec_available(void) } -device_t mfm_xt_xebec_device = { +const device_t mfm_xt_xebec_device = { "IBM PC Fixed Disk Adapter", DEVICE_ISA, 0, @@ -874,7 +874,7 @@ device_t mfm_xt_xebec_device = { static void * -dtc5150x_init(device_t *info) +dtc5150x_init(const device_t *info) { int i, c = 0; @@ -918,7 +918,7 @@ dtc5150x_available(void) } -device_t mfm_xt_dtc5150x_device = { +const device_t mfm_xt_dtc5150x_device = { "DTC 5150X", DEVICE_ISA, 0, diff --git a/src/disk/hdc_xtide.c b/src/disk/hdc_xtide.c index 6948869f8..bc4cdcd92 100644 --- a/src/disk/hdc_xtide.c +++ b/src/disk/hdc_xtide.c @@ -21,7 +21,7 @@ * already on their way out, the newer IDE standard based on the * PC/AT controller and 16b design became the IDE we now know. * - * Version: @(#)hdc_xtide.c 1.0.11 2018/02/14 + * Version: @(#)hdc_xtide.c 1.0.11 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -127,7 +127,7 @@ xtide_read(uint16_t port, void *priv) static void * -xtide_init(device_t *info) +xtide_init(const device_t *info) { xtide_t *xtide = malloc(sizeof(xtide_t)); @@ -154,7 +154,7 @@ xtide_available(void) static void * -xtide_at_init(device_t *info) +xtide_at_init(const device_t *info) { xtide_t *xtide = malloc(sizeof(xtide_t)); @@ -177,7 +177,7 @@ xtide_at_available(void) static void * -xtide_acculogic_init(device_t *info) +xtide_acculogic_init(const device_t *info) { xtide_t *xtide = malloc(sizeof(xtide_t)); @@ -204,7 +204,7 @@ xtide_acculogic_available(void) static void * -xtide_at_ps2_init(device_t *info) +xtide_at_ps2_init(const device_t *info) { xtide_t *xtide = malloc(sizeof(xtide_t)); @@ -235,7 +235,7 @@ xtide_close(void *priv) } -device_t xtide_device = { +const device_t xtide_device = { "XTIDE", DEVICE_ISA, 0, @@ -244,7 +244,7 @@ device_t xtide_device = { NULL }; -device_t xtide_at_device = { +const device_t xtide_at_device = { "XTIDE (AT)", DEVICE_ISA | DEVICE_AT, 0, @@ -253,7 +253,7 @@ device_t xtide_at_device = { NULL }; -device_t xtide_acculogic_device = { +const device_t xtide_acculogic_device = { "XTIDE (Acculogic)", DEVICE_ISA, 0, @@ -262,7 +262,7 @@ device_t xtide_acculogic_device = { NULL }; -device_t xtide_at_ps2_device = { +const device_t xtide_at_ps2_device = { "XTIDE (AT) (1.1.5)", DEVICE_ISA | DEVICE_PS2, 0, diff --git a/src/disk/zip.c b/src/disk/zip.c index 86f1dd3c7..a02f64204 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -9,7 +9,7 @@ * Implementation of the Iomega ZIP drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)zip.c 1.0.12 2018/03/17 + * Version: @(#)zip.c 1.0.13 2018/03/18 * * Author: Miran Grca, * @@ -70,7 +70,7 @@ uint8_t scsi_zip_drives[16][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0 /* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ -uint8_t zip_command_flags[0x100] = +const uint8_t zip_command_flags[0x100] = { IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 04b9c118b..ab4e8c4ef 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -1,21 +1,39 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * Implementation of the NEC uPD-765 and compatible floppy disk * controller. * - * Version: @(#)fdc->c 1.0.18 2018/03/08 + * Version: @(#)fdc.c 1.0.5 2018/03/16 * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Miran Grca, + * Sarah Walker, * - * Copyright 2008-2018 Sarah Walker. * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ #include #include @@ -42,7 +60,7 @@ extern int64_t motoron[FDD_NUM]; -int command_has_drivesel[256] = { +const int command_has_drivesel[256] = { 0, 0, 1, /* READ TRACK */ 0, @@ -1147,7 +1165,6 @@ fdc_read(uint16_t addr, void *priv) { fdc_t *fdc = (fdc_t *) priv; uint8_t ret; - int drive; cycles -= ISA_CYCLES(8); @@ -2020,7 +2037,7 @@ fdc_close(void *priv) static void * -fdc_init(device_t *info) +fdc_init(const device_t *info) { fdc_t *fdc = (fdc_t *) malloc(sizeof(fdc_t)); memset(fdc, 0, sizeof(fdc_t)); @@ -2058,7 +2075,7 @@ fdc_3f1_enable(fdc_t *fdc, int enable) } -device_t fdc_xt_device = { +const device_t fdc_xt_device = { "PC/XT Floppy Drive Controller", 0, 0, @@ -2068,7 +2085,7 @@ device_t fdc_xt_device = { NULL, NULL, NULL, NULL }; -device_t fdc_pcjr_device = { +const device_t fdc_pcjr_device = { "PCjr Floppy Drive Controller", 0, FDC_FLAG_PCJR, @@ -2078,7 +2095,7 @@ device_t fdc_pcjr_device = { NULL, NULL, NULL, NULL }; -device_t fdc_at_device = { +const device_t fdc_at_device = { "PC/AT Floppy Drive Controller", 0, FDC_FLAG_AT, @@ -2088,7 +2105,7 @@ device_t fdc_at_device = { NULL, NULL, NULL, NULL }; -device_t fdc_at_actlow_device = { +const device_t fdc_at_actlow_device = { "PC/AT Floppy Drive Controller (Active low)", 0, FDC_FLAG_DISKCHG_ACTLOW | FDC_FLAG_AT, @@ -2098,7 +2115,7 @@ device_t fdc_at_actlow_device = { NULL, NULL, NULL, NULL }; -device_t fdc_at_ps1_device = { +const device_t fdc_at_ps1_device = { "PC/AT Floppy Drive Controller (PS/1, PS/2 ISA)", 0, FDC_FLAG_DISKCHG_ACTLOW | FDC_FLAG_AT | FDC_FLAG_PS1, @@ -2108,7 +2125,7 @@ device_t fdc_at_ps1_device = { NULL, NULL, NULL, NULL }; -device_t fdc_at_smc_device = { +const device_t fdc_at_smc_device = { "PC/AT Floppy Drive Controller (SM(s)C FDC37Cxxx)", 0, FDC_FLAG_AT | FDC_FLAG_SUPERIO, @@ -2118,7 +2135,7 @@ device_t fdc_at_smc_device = { NULL, NULL, NULL, NULL }; -device_t fdc_at_winbond_device = { +const device_t fdc_at_winbond_device = { "PC/AT Floppy Drive Controller (Winbond W83x77F)", 0, FDC_FLAG_AT | FDC_FLAG_SUPERIO | FDC_FLAG_START_RWC_1 | FDC_FLAG_MORE_TRACKS, @@ -2128,7 +2145,7 @@ device_t fdc_at_winbond_device = { NULL, NULL, NULL, NULL }; -device_t fdc_at_nsc_device = { +const device_t fdc_at_nsc_device = { "PC/AT Floppy Drive Controller (NSC PC8730x)", 0, FDC_FLAG_AT | FDC_FLAG_MORE_TRACKS | FDC_FLAG_NSC, diff --git a/src/floppy/fdc.h b/src/floppy/fdc.h index 4f59828b5..0d540e918 100644 --- a/src/floppy/fdc.h +++ b/src/floppy/fdc.h @@ -1,20 +1,41 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * Implementation of the NEC uPD-765 and compatible floppy disk * controller. * - * Version: @(#)fdc.h 1.0.5 2018/03/02 + * Version: @(#)fdc.h 1.0.3 2018/03/17 * - * Authors: Sarah Walker, + * Authors: Fred N. van Kempen, * Miran Grca, - * Copyright 2008-2018 Sarah Walker. + * Sarah Walker, + * + * Copyright 2018 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ #ifndef EMU_FDC_H # define EMU_FDC_H @@ -29,8 +50,8 @@ #define FDC_FLAG_MORE_TRACKS 0x40 /* W83877F, W83977F, PC87306, PC87309 */ #define FDC_FLAG_NSC 0x80 /* PC87306, PC87309 */ -typedef struct -{ + +typedef struct { uint8_t dor, stat, command, dat, st0, swap; uint8_t swwp, disable_write; uint8_t params[256], res[256]; @@ -79,6 +100,7 @@ typedef struct int64_t watchdog_timer, watchdog_count; } fdc_t; + extern void fdc_remove(fdc_t *fdc); extern void fdc_poll(fdc_t *fdc); extern void fdc_abort(fdc_t *fdc); @@ -148,7 +170,9 @@ extern void fdc_set_base(fdc_t *fdc, int base); extern int fdc_getdata(fdc_t *fdc, int last); extern int fdc_data(fdc_t *fdc, uint8_t data); -extern void fdc_sectorid(fdc_t *fdc, uint8_t track, uint8_t side, uint8_t sector, uint8_t size, uint8_t crc1, uint8_t crc2); +extern void fdc_sectorid(fdc_t *fdc, uint8_t track, uint8_t side, + uint8_t sector, uint8_t size, uint8_t crc1, + uint8_t crc2); extern uint8_t fdc_read(uint16_t addr, void *priv); extern void fdc_reset(void *priv); @@ -156,14 +180,14 @@ extern void fdc_reset(void *priv); extern uint8_t fdc_ps1_525(void); #ifdef EMU_DEVICE_H -extern device_t fdc_xt_device; -extern device_t fdc_pcjr_device; -extern device_t fdc_at_device; -extern device_t fdc_at_actlow_device; -extern device_t fdc_at_ps1_device; -extern device_t fdc_at_smc_device; -extern device_t fdc_at_winbond_device; -extern device_t fdc_at_nsc_device; +extern const device_t fdc_xt_device; +extern const device_t fdc_pcjr_device; +extern const device_t fdc_at_device; +extern const device_t fdc_at_actlow_device; +extern const device_t fdc_at_ps1_device; +extern const device_t fdc_at_smc_device; +extern const device_t fdc_at_winbond_device; +extern const device_t fdc_at_nsc_device; #endif diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index a309e7e3a..006a6ed87 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -1,20 +1,40 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * Implementation of the floppy drive emulation. * - * Version: @(#)fdd.c 1.0.9 2018/03/14 + * Version: @(#)fdd.c 1.0.5 2018/03/16 * - * Authors: Sarah Walker, + * Authors: Fred N. van Kempen, * Miran Grca, + * Sarah Walker, * - * Copyright 2008-2018 Sarah Walker. + * Copyright 2018 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ #include #include @@ -66,8 +86,9 @@ int fdc_indexcount = 52; fdc_t *fdd_fdc; +d86f_handler_t d86f_handler[FDD_NUM]; -static struct +static const struct { wchar_t *ext; void (*load)(int drive, wchar_t *fn); @@ -150,7 +171,7 @@ int ui_writeprot[FDD_NUM] = {0, 0, 0, 0}; #define FLAG_IGNORE_DENSEL 512 #define FLAG_PS2 1024 -static struct +static const struct { int max_track; int flags; @@ -207,12 +228,12 @@ static struct char *fdd_getname(int type) { - return drive_types[type].name; + return (char *)drive_types[type].name; } char *fdd_get_internal_name(int type) { - return drive_types[type].internal_name; + return (char *)drive_types[type].internal_name; } int fdd_get_from_internal_name(char *s) @@ -221,7 +242,7 @@ int fdd_get_from_internal_name(char *s) while (strlen(drive_types[c].internal_name)) { - if (!strcmp(drive_types[c].internal_name, s)) + if (!strcmp((char *)drive_types[c].internal_name, s)) return c; c++; } @@ -433,6 +454,9 @@ void fdd_load(int drive, wchar_t *fn) int c = 0, size; wchar_t *p; FILE *f; + + pclog("FDD: loading drive %d with '%ls'\n", drive, fn); + if (!fn) return; p = plat_get_extension(fn); if (!p) return; @@ -447,7 +471,7 @@ void fdd_load(int drive, wchar_t *fn) { driveloaders[drive] = c; memcpy(floppyfns[drive], fn, (wcslen(fn) << 1) + 2); - d86f_initialize_linked_lists(drive); + d86f_setup(drive); loaders[c].load(drive, floppyfns[drive]); drive_empty[drive] = 0; fdd_forced_seek(drive, 0); @@ -456,7 +480,7 @@ void fdd_load(int drive, wchar_t *fn) } c++; } - pclog("Couldn't load %ls %s\n",fn,p); + pclog("FDD: could not load '%ls' %s\n",fn,p); drive_empty[drive] = 1; fdd_set_head(drive, 0); memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); @@ -465,12 +489,13 @@ void fdd_load(int drive, wchar_t *fn) void fdd_close(int drive) { + pclog("FDD: closing drive %d\n", drive); + if (loaders[driveloaders[drive]].close) loaders[driveloaders[drive]].close(drive); drive_empty[drive] = 1; fdd_set_head(drive, 0); floppyfns[drive][0] = 0; - d86f_destroy_linked_lists(drive, 0); - d86f_destroy_linked_lists(drive, 1); + d86f_destroy(drive); drives[drive].hole = NULL; drives[drive].poll = NULL; drives[drive].seek = NULL; @@ -526,18 +551,7 @@ double fdd_real_period(int drive) return (32.0 * dusec); } -#if defined(DEV_BRANCH) && defined(USE_MRTHOR) - if (romset == ROM_MRTHOR) - { - return (ddbp * dusec) / 4.0; - } - else - { - return (ddbp * dusec); - } -#else return (ddbp * dusec); -#endif } void fdd_poll(int drive) @@ -705,6 +719,7 @@ void fdd_init(void) d86f_init(); td0_init(); imd_init(); + json_init(); fdd_load(0, floppyfns[0]); fdd_load(1, floppyfns[1]); diff --git a/src/floppy/fdd.h b/src/floppy/fdd.h index f4a26e988..7610cee46 100644 --- a/src/floppy/fdd.h +++ b/src/floppy/fdd.h @@ -1,34 +1,54 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * - * Implementation of the floppy drive emulation. + * Definitions for the floppy drive emulation. * - * Version: @(#)fdd.h 1.0.5 2018/01/18 + * Version: @(#)fdd.h 1.0.3 2018/03/17 * - * Authors: Sarah Walker, + * Authors: Fred N. van Kempen, * Miran Grca, + * Sarah Walker, * - * Copyright 2008-2018 Sarah Walker. + * Copyright 2018 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ #ifndef EMU_FDD_H # define EMU_FDD_H -#define FDD_NUM 4 -#define SEEK_RECALIBRATE -999 +#define FDD_NUM 4 +#define SEEK_RECALIBRATE -999 #ifdef __cplusplus extern "C" { #endif -extern int fdd_swap; +extern int fdd_swap; extern void fdd_do_seek(int drive, int track); @@ -65,16 +85,19 @@ extern int fdd_current_track(int drive); typedef struct { - void (*seek)(int drive, int track); - void (*readsector)(int drive, int sector, int track, int side, int density, int sector_size); - void (*writesector)(int drive, int sector, int track, int side, int density, int sector_size); - void (*comparesector)(int drive, int sector, int track, int side, int density, int sector_size); - void (*readaddress)(int drive, int side, int density); - void (*format)(int drive, int side, int density, uint8_t fill); - int (*hole)(int drive); - double (*byteperiod)(int drive); - void (*stop)(int drive); - void (*poll)(int drive); + void (*seek)(int drive, int track); + void (*readsector)(int drive, int sector, int track, int side, + int density, int sector_size); + void (*writesector)(int drive, int sector, int track, int side, + int density, int sector_size); + void (*comparesector)(int drive, int sector, int track, int side, + int density, int sector_size); + void (*readaddress)(int drive, int side, int density); + void (*format)(int drive, int side, int density, uint8_t fill); + int (*hole)(int drive); + double (*byteperiod)(int drive); + void (*stop)(int drive); + void (*poll)(int drive); } DRIVE; @@ -115,60 +138,24 @@ extern void fdd_stop(int drive); extern int fdd_empty(int drive); extern void fdd_set_rate(int drive, int drvden, int rate); -extern int motorspin; -extern int64_t motoron[FDD_NUM]; +extern int motorspin; +extern int64_t motoron[FDD_NUM]; -extern int swwp; -extern int disable_write; +extern int swwp; +extern int disable_write; -extern int defaultwriteprot; +extern int defaultwriteprot; -extern int writeprot[FDD_NUM], fwriteprot[FDD_NUM]; -extern int fdd_cur_track[FDD_NUM]; -extern int fdd_changed[FDD_NUM]; -extern int drive_empty[FDD_NUM]; -extern int drive_type[FDD_NUM]; +extern int writeprot[FDD_NUM], fwriteprot[FDD_NUM]; +extern int fdd_cur_track[FDD_NUM]; +extern int fdd_changed[FDD_NUM]; +extern int drive_empty[FDD_NUM]; +extern int drive_type[FDD_NUM]; /*Used in the Read A Track command. Only valid for fdd_readsector(). */ #define SECTOR_FIRST -2 #define SECTOR_NEXT -1 -#if 0 -/* Bits 0-3 define byte type, bit 5 defines whether it is a per-track (0) or per-sector (1) byte, if bit 7 is set, the byte is the index hole. */ -#define BYTE_GAP0 0x00 -#define BYTE_GAP1 0x10 -#define BYTE_GAP4 0x20 -#define BYTE_GAP2 0x40 -#define BYTE_GAP3 0x50 -#define BYTE_I_SYNC 0x01 -#define BYTE_ID_SYNC 0x41 -#define BYTE_DATA_SYNC 0x51 -#define BYTE_IAM_SYNC 0x02 -#define BYTE_IDAM_SYNC 0x42 -#define BYTE_DATAAM_SYNC 0x52 -#define BYTE_IAM 0x03 -#define BYTE_IDAM 0x43 -#define BYTE_DATAAM 0x53 -#define BYTE_ID 0x44 -#define BYTE_DATA 0x54 -#define BYTE_ID_CRC 0x45 -#define BYTE_DATA_CRC 0x55 - -#define BYTE_IS_FUZZY 0x80 -#define BYTE_INDEX_HOLE 0x80 /* 1 = index hole, 0 = regular byte */ -#define BYTE_IS_SECTOR 0x40 /* 1 = per-sector, 0 = per-track */ -#define BYTE_IS_POST_TRACK 0x20 /* 1 = after all sectors, 0 = before or during all sectors */ -#define BYTE_IS_DATA 0x10 /* 1 = data, 0 = id */ -#define BYTE_TYPE 0x0F /* 5 = crc, 4 = data, 3 = address mark, 2 = address mark sync, 1 = sync, 0 = gap */ - -#define BYTE_TYPE_GAP 0x00 -#define BYTE_TYPE_SYNC 0x01 -#define BYTE_TYPE_AM_SYNC 0x02 -#define BYTE_TYPE_AM 0x03 -#define BYTE_TYPE_DATA 0x04 -#define BYTE_TYPE_CRC 0x05 -#endif - typedef union { uint16_t word; uint8_t bytes[2]; @@ -176,94 +163,92 @@ typedef union { void fdd_calccrc(uint8_t byte, crc_t *crc_var); -typedef struct -{ - uint16_t (*disk_flags)(int drive); - uint16_t (*side_flags)(int drive); - void (*writeback)(int drive); - void (*set_sector)(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n); - uint8_t (*read_data)(int drive, int side, uint16_t pos); - void (*write_data)(int drive, int side, uint16_t pos, uint8_t data); - int (*format_conditions)(int drive); - int32_t (*extra_bit_cells)(int drive, int side); - uint16_t* (*encoded_data)(int drive, int side); - void (*read_revolution)(int drive); - uint32_t (*index_hole_pos)(int drive, int side); - uint32_t (*get_raw_size)(int drive, int side); - uint8_t check_crc; +typedef struct { + uint16_t (*disk_flags)(int drive); + uint16_t (*side_flags)(int drive); + void (*writeback)(int drive); + void (*set_sector)(int drive, int side, uint8_t c, uint8_t h, + uint8_t r, uint8_t n); + uint8_t (*read_data)(int drive, int side, uint16_t pos); + void (*write_data)(int drive, int side, uint16_t pos, + uint8_t data); + int (*format_conditions)(int drive); + int32_t (*extra_bit_cells)(int drive, int side); + uint16_t* (*encoded_data)(int drive, int side); + void (*read_revolution)(int drive); + uint32_t (*index_hole_pos)(int drive, int side); + uint32_t (*get_raw_size)(int drive, int side); + + uint8_t check_crc; } d86f_handler_t; -d86f_handler_t d86f_handler[FDD_NUM]; +extern const int gap3_sizes[5][8][48]; +extern d86f_handler_t d86f_handler[FDD_NUM]; -void d86f_common_handlers(int drive); +extern void d86f_setup(int drive); +extern void d86f_destroy(int drive); +extern int d86f_export(int drive, wchar_t *fn); +extern void d86f_unregister(int drive); +extern void d86f_common_handlers(int drive); +extern void d86f_set_version(int drive, uint16_t version); +extern int d86f_is_40_track(int drive); +extern void d86f_reset_index_hole_pos(int drive, int side); +extern uint16_t d86f_prepare_pretrack(int drive, int side, int iso); +extern 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); +extern void d86f_set_track_pos(int drive, uint32_t track_pos); +extern void d86f_set_cur_track(int drive, int track); +extern void d86f_zero_track(int drive); +extern void d86f_initialize_last_sector_id(int drive, int c, int h, + int r, int n); +extern void d86f_initialize_linked_lists(int drive); +extern void d86f_destroy_linked_lists(int drive, int side); +extern uint16_t *common_encoded_data(int drive, int side); +extern void common_read_revolution(int drive); +extern uint32_t common_get_raw_size(int drive, int side); +extern void null_writeback(int drive); +extern void null_write_data(int drive, int side, uint16_t pos, + uint8_t data); +extern int null_format_conditions(int drive); +extern int32_t null_extra_bit_cells(int drive, int side); +extern void null_set_sector(int drive, int side, uint8_t c, uint8_t h, + uint8_t r, uint8_t n); +extern uint32_t null_index_hole_pos(int drive, int side); -int d86f_is_40_track(int drive); +extern const uint8_t dmf_r[21]; +extern const uint8_t xdf_physical_sectors[2][2]; +extern const uint8_t xdf_gap3_sizes[2][2]; +extern const uint16_t xdf_trackx_spos[2][8]; -void d86f_reset_index_hole_pos(int drive, int side); - -uint16_t d86f_prepare_pretrack(int drive, int side, int iso); -uint16_t d86f_prepare_sector(int drive, int side, int prev_pos, uint8_t *id_buf, uint8_t *data_buf, int data_len, int gap2, int gap3, int deleted, int bad_crc); - -extern int gap3_sizes[5][8][48]; - -void null_writeback(int drive); -void null_write_data(int drive, int side, uint16_t pos, uint8_t data); -int null_format_conditions(int drive); -void d86f_unregister(int drive); - -extern uint8_t dmf_r[21]; -extern uint8_t xdf_physical_sectors[2][2]; -extern uint8_t xdf_gap3_sizes[2][2]; -extern uint16_t xdf_trackx_spos[2][8]; - -typedef struct -{ - uint8_t h; - uint8_t r; +typedef struct { + uint8_t h; + uint8_t r; } xdf_id_t; -typedef union -{ - uint16_t word; - xdf_id_t id; +typedef union { + uint16_t word; + xdf_id_t id; } xdf_sector_t; -extern xdf_sector_t xdf_img_layout[2][2][46]; -extern xdf_sector_t xdf_disk_layout[2][2][38]; +extern const xdf_sector_t xdf_img_layout[2][2][46]; +extern const xdf_sector_t xdf_disk_layout[2][2][38]; -uint32_t td0_get_raw_tsize(int side_flags, int slower_rpm); -void d86f_set_track_pos(int drive, uint32_t track_pos); - -int32_t null_extra_bit_cells(int drive, int side); -uint16_t* common_encoded_data(int drive, int side); - -void common_read_revolution(int drive); -void null_set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n); - -uint32_t null_index_hole_pos(int drive, int side); - -uint32_t common_get_raw_size(int drive, int side); - -typedef struct -{ - uint8_t c; - uint8_t h; - uint8_t r; - uint8_t n; +typedef struct { + uint8_t c; + uint8_t h; + uint8_t r; + uint8_t n; } sector_id_fields_t; -typedef union -{ - uint32_t dword; - uint8_t byte_array[4]; - sector_id_fields_t id; +typedef union { + uint32_t dword; + uint8_t byte_array[4]; + sector_id_fields_t id; } sector_id_t; -void d86f_set_version(int drive, uint16_t version); - -void d86f_initialize_last_sector_id(int drive, int c, int h, int r, int n); -void d86f_destroy_linked_lists(int drive, int side); void d86f_set_fdc(void *fdc); void fdi_set_fdc(void *fdc); @@ -271,10 +256,6 @@ void fdd_set_fdc(void *fdc); void imd_set_fdc(void *fdc); void img_set_fdc(void *fdc); -extern void d86f_set_cur_track(int drive, int track); -extern void d86f_zero_track(int drive); - -extern int d86f_export(int drive, wchar_t *fn); #ifdef __cplusplus } diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index a110798db..21500c44d 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -1,19 +1,40 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * Implementation of the 86F floppy image format (stores the * data in the form of FM/MFM-encoded transitions) which also * forms the core of the emulator's floppy disk emulation. * - * Version: @(#)fdd_86f.c 1.0.18 2018/03/17 + * Version: @(#)fdd_86f.c 1.0.6 2018/03/16 * - * Author: Miran Grca, + * Authors: Fred N. van Kempen, + * Miran Grca, + * + * Copyright 2018 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ #include #include @@ -22,7 +43,6 @@ #include #include #include -#include "../lzf/lzf.h" #define HAVE_STDARG_H #include "../86box.h" #include "../config.h" @@ -34,317 +54,221 @@ #include "fdd.h" #include "fdc.h" #include "fdd_86f.h" +#include "lzf/lzf.h" -#define CHUNK 16384 +/* + * Let's give this some more logic: + * + * Bits 4,3 = Read/write (0 = read, 1 = write, 2 = scan, 3 = verify) + * Bits 6,5 = Sector/track (0 = ID, 1 = sector, 2 = deleted sector, 3 = track) + * Bit 7 = State type (0 = idle states, 1 = active states) + */ +enum { + /* 0 ?? ?? ??? */ + STATE_IDLE = 0x00, + STATE_SECTOR_NOT_FOUND, + /* 1 00 00 ??? */ + STATE_0A_FIND_ID = 0x80, /* READ SECTOR ID */ + STATE_0A_READ_ID, -uint64_t poly = 0x42F0E1EBA9EA3693ll; /* ECMA normal */ + /* 1 01 00 ??? */ + STATE_06_FIND_ID = 0xA0, /* READ DATA */ + STATE_06_READ_ID, + STATE_06_FIND_DATA, + STATE_06_READ_DATA, -uint64_t table[256]; + /* 1 01 01 ??? */ + STATE_05_FIND_ID = 0xA8, /* WRITE DATA */ + STATE_05_READ_ID, + STATE_05_FIND_DATA, + STATE_05_WRITE_DATA, -/* Let's give this some more logic: - Bits 4,3 = Read/write (0 = read, 1 = write, 2 = scan, 3 = verify) - Bits 6,5 = Sector/track (0 = ID, 1 = sector, 2 = deleted sector, 3 = track) - Bit 7 = State type (0 = idle states, 1 = active states) -*/ -enum -{ - /* 0 ?? ?? ??? */ - STATE_IDLE = 0x00, - STATE_SECTOR_NOT_FOUND, + /* 1 01 10 ??? */ + STATE_11_FIND_ID = 0xB0, /* SCAN EQUAL,SCAN LOW/EQUAL,SCAN HIGH/EQUAL */ + STATE_11_READ_ID, + STATE_11_FIND_DATA, + STATE_11_SCAN_DATA, - /* 1 00 00 ??? */ - STATE_0A_FIND_ID = 0x80, /* READ SECTOR ID */ - STATE_0A_READ_ID, + /* 1 01 11 ??? */ + STATE_16_FIND_ID = 0xB8, /* VERIFY */ + STATE_16_READ_ID, + STATE_16_FIND_DATA, + STATE_16_VERIFY_DATA, - /* 1 01 00 ??? */ - STATE_06_FIND_ID = 0xA0, /* READ DATA */ - STATE_06_READ_ID, - STATE_06_FIND_DATA, - STATE_06_READ_DATA, + /* 1 10 00 ??? */ + STATE_0C_FIND_ID = 0xC0, /* READ DELETED DATA */ + STATE_0C_READ_ID, + STATE_0C_FIND_DATA, + STATE_0C_READ_DATA, - /* 1 01 01 ??? */ - STATE_05_FIND_ID = 0xA8, /* WRITE DATA */ - STATE_05_READ_ID, - STATE_05_FIND_DATA, - STATE_05_WRITE_DATA, + /* 1 10 01 ??? */ + STATE_09_FIND_ID = 0xC8, /* WRITE DELETED DATA */ + STATE_09_READ_ID, + STATE_09_FIND_DATA, + STATE_09_WRITE_DATA, - /* 1 01 10 ??? */ - STATE_11_FIND_ID = 0xB0, /* SCAN EQUAL, SCAN LOW OR EQUAL, SCAN HIGH OR EQUAL */ - STATE_11_READ_ID, - STATE_11_FIND_DATA, - STATE_11_SCAN_DATA, + /* 1 11 00 ??? */ + STATE_02_SPIN_TO_INDEX = 0xE0, /* READ TRACK */ + STATE_02_FIND_ID, + STATE_02_READ_ID, + STATE_02_FIND_DATA, + STATE_02_READ_DATA, - /* 1 01 11 ??? */ - STATE_16_FIND_ID = 0xB8, /* VERIFY */ - STATE_16_READ_ID, - STATE_16_FIND_DATA, - STATE_16_VERIFY_DATA, + /* 1 11 01 ??? */ + STATE_0D_SPIN_TO_INDEX = 0xE8, /* FORMAT TRACK */ + STATE_0D_FORMAT_TRACK, - /* 1 10 00 ??? */ - STATE_0C_FIND_ID = 0xC0, /* READ DELETED DATA */ - STATE_0C_READ_ID, - STATE_0C_FIND_DATA, - STATE_0C_READ_DATA, - - /* 1 10 01 ??? */ - STATE_09_FIND_ID = 0xC8, /* WRITE DELETED DATA */ - STATE_09_READ_ID, - STATE_09_FIND_DATA, - STATE_09_WRITE_DATA, - - /* 1 11 00 ??? */ - STATE_02_SPIN_TO_INDEX = 0xE0, /* READ TRACK */ - STATE_02_FIND_ID, - STATE_02_READ_ID, - STATE_02_FIND_DATA, - STATE_02_READ_DATA, - - /* 1 11 01 ??? */ - STATE_0D_SPIN_TO_INDEX = 0xE8, /* FORMAT TRACK */ - STATE_0D_FORMAT_TRACK, - - /* 1 11 11 ??? */ - STATE_0D_NOP_SPIN_TO_INDEX = 0xF8, /* FORMAT TRACK */ - STATE_0D_NOP_FORMAT_TRACK + /* 1 11 11 ??? */ + STATE_0D_NOP_SPIN_TO_INDEX = 0xF8, /* FORMAT TRACK */ + STATE_0D_NOP_FORMAT_TRACK }; -static uint16_t CRCTable[256]; +enum { + FMT_PRETRK_GAP0, + FMT_PRETRK_SYNC, + FMT_PRETRK_IAM, + FMT_PRETRK_GAP1, -#pragma pack(push,1) -typedef struct -{ - uint8_t buffer[10]; - uint32_t pos; - uint32_t len; + FMT_SECTOR_ID_SYNC, + FMT_SECTOR_IDAM, + FMT_SECTOR_ID, + FMT_SECTOR_ID_CRC, + FMT_SECTOR_GAP2, + FMT_SECTOR_DATA_SYNC, + FMT_SECTOR_DATAAM, + FMT_SECTOR_DATA, + FMT_SECTOR_DATA_CRC, + FMT_SECTOR_GAP3, + + FMT_POSTTRK_CHECK, + FMT_POSTTRK_GAP4 +}; + + +typedef struct { + uint8_t buffer[10]; + uint32_t pos; + uint32_t len; } sliding_buffer_t; -#pragma pack(pop) -#pragma pack(push,1) -typedef struct -{ - uint32_t sync_marks; - uint32_t bits_obtained; - uint32_t bytes_obtained; - uint32_t sync_pos; +typedef struct { + uint32_t sync_marks; + uint32_t bits_obtained; + uint32_t bytes_obtained; + uint32_t sync_pos; } find_t; -#pragma pack(pop) - -uint8_t encoded_fm[64] = { 0xAA, 0xAB, 0xAE, 0xAF, 0xBA, 0xBB, 0xBE, 0xBF, 0xEA, 0xEB, 0xEE, 0xEF, 0xFA, 0xFB, 0xFE, 0xFF, - 0xAA, 0xAB, 0xAE, 0xAF, 0xBA, 0xBB, 0xBE, 0xBF, 0xEA, 0xEB, 0xEE, 0xEF, 0xFA, 0xFB, 0xFE, 0xFF, - 0xAA, 0xAB, 0xAE, 0xAF, 0xBA, 0xBB, 0xBE, 0xBF, 0xEA, 0xEB, 0xEE, 0xEF, 0xFA, 0xFB, 0xFE, 0xFF, - 0xAA, 0xAB, 0xAE, 0xAF, 0xBA, 0xBB, 0xBE, 0xBF, 0xEA, 0xEB, 0xEE, 0xEF, 0xFA, 0xFB, 0xFE, 0xFF }; - -uint8_t encoded_mfm[64] = { 0xAA, 0xA9, 0xA4, 0xA5, 0x92, 0x91, 0x94, 0x95, 0x4A, 0x49, 0x44, 0x45, 0x52, 0x51, 0x54, 0x55, - 0x2A, 0x29, 0x24, 0x25, 0x12, 0x11, 0x14, 0x15, 0x4A, 0x49, 0x44, 0x45, 0x52, 0x51, 0x54, 0x55, - 0xAA, 0xA9, 0xA4, 0xA5, 0x92, 0x91, 0x94, 0x95, 0x4A, 0x49, 0x44, 0x45, 0x52, 0x51, 0x54, 0x55, - 0x2A, 0x29, 0x24, 0x25, 0x12, 0x11, 0x14, 0x15, 0x4A, 0x49, 0x44, 0x45, 0x52, 0x51, 0x54, 0x55 }; - - -enum -{ - FMT_PRETRK_GAP0, - FMT_PRETRK_SYNC, - FMT_PRETRK_IAM, - FMT_PRETRK_GAP1, - - FMT_SECTOR_ID_SYNC, - FMT_SECTOR_IDAM, - FMT_SECTOR_ID, - FMT_SECTOR_ID_CRC, - FMT_SECTOR_GAP2, - FMT_SECTOR_DATA_SYNC, - FMT_SECTOR_DATAAM, - FMT_SECTOR_DATA, - FMT_SECTOR_DATA_CRC, - FMT_SECTOR_GAP3, - - FMT_POSTTRK_CHECK, - FMT_POSTTRK_GAP4 -}; - - -#pragma pack(push,1) -typedef struct -{ - unsigned nibble0 :4; - unsigned nibble1 :4; +typedef struct { + unsigned nibble0 :4; + unsigned nibble1 :4; } split_byte_t; -#pragma pack(pop) typedef union { - uint8_t byte; - split_byte_t nibbles; + uint8_t byte; + split_byte_t nibbles; } decoded_t; - -/* Disk flags: Bit 0 Has surface data (1 = yes, 0 = no) - Bits 2, 1 Hole (3 = ED + 2000 kbps, 2 = ED, 1 = HD, 0 = DD) - Bit 3 Sides (1 = 2 sides, 0 = 1 side) - Bit 4 Write protect (1 = yes, 0 = no) - Bits 6, 5 RPM slowdown (3 = 2%, 2 = 1.5%, 1 = 1%, 0 = 0%) - Bit 7 Bitcell mode (1 = Extra bitcells count specified after disk flags, 0 = No extra bitcells) - The maximum number of extra bitcells is 1024 (which after decoding translates to 64 bytes) - Bit 8 Disk type (1 = Zoned, 0 = Fixed RPM) - Bits 10, 9 Zone type (3 = Commodore 64 zoned, 2 = Apple zoned, 1 = Pre-Apple zoned #2, 0 = Pre-Apple zoned #1) - Bit 11 Data and surface bits are stored in reverse byte endianness */ - - -static fdc_t *d86f_fdc; - - -#pragma pack(push,1) -typedef struct -{ - uint8_t c, h, r, n; - void *prev; +typedef struct { + uint8_t c, h, r, n; + void *prev; } sector_t; -#pragma pack(pop) -#pragma pack(push,1) -struct -{ - FILE *f; - uint16_t version; - uint16_t disk_flags; - int32_t extra_bit_cells[2]; - uint16_t track_encoded_data[2][53048]; - uint16_t track_surface_data[2][53048]; - uint16_t thin_track_encoded_data[2][2][53048]; - uint16_t thin_track_surface_data[2][2][53048]; - uint16_t side_flags[2]; - uint32_t index_hole_pos[2]; - uint32_t track_offset[512]; - uint32_t file_size; - sector_id_t format_sector_id; - sector_id_t last_sector; - sector_id_t req_sector; - uint32_t index_count; - uint8_t state; - uint8_t fill; - uint32_t track_pos; - uint32_t datac; - uint32_t id_pos; - uint16_t last_word[2]; - find_t id_find; - find_t data_find; - crc_t calc_crc; - crc_t track_crc; - uint8_t sector_count; - uint8_t format_state; - uint16_t satisfying_bytes; - uint16_t preceding_bit[2]; - uint16_t current_byte[2]; - uint16_t current_bit[2]; - int cur_track; - uint32_t error_condition; - int is_compressed; - int id_found; - wchar_t original_file_name[2048]; - uint8_t *filebuf; - uint8_t *outbuf; - uint32_t dma_over; - int turbo_pos; - sector_t *last_side_sector[2]; -} d86f[FDD_NUM + 1]; -#pragma pack(pop) +/* Disk flags: + * Bit 0 Has surface data (1 = yes, 0 = no) + * Bits 2, 1 Hole (3 = ED + 2000 kbps, 2 = ED, 1 = HD, 0 = DD) + * Bit 3 Sides (1 = 2 sides, 0 = 1 side) + * Bit 4 Write protect (1 = yes, 0 = no) + * Bits 6, 5 RPM slowdown (3 = 2%, 2 = 1.5%, 1 = 1%, 0 = 0%) + * Bit 7 Bitcell mode (1 = Extra bitcells count specified after + * disk flags, 0 = No extra bitcells) + * The maximum number of extra bitcells is 1024 (which + * after decoding translates to 64 bytes) + * Bit 8 Disk type (1 = Zoned, 0 = Fixed RPM) + * Bits 10, 9 Zone type (3 = Commodore 64 zoned, 2 = Apple zoned, + * 1 = Pre-Apple zoned #2, 0 = Pre-Apple zoned #1) + * Bit 11 Data and surface bits are stored in reverse byte endianness + */ +typedef struct { + FILE *f; + uint16_t version; + uint16_t disk_flags; + int32_t extra_bit_cells[2]; + uint16_t track_encoded_data[2][53048]; + uint16_t track_surface_data[2][53048]; + uint16_t thin_track_encoded_data[2][2][53048]; + uint16_t thin_track_surface_data[2][2][53048]; + uint16_t side_flags[2]; + uint32_t index_hole_pos[2]; + uint32_t track_offset[512]; + uint32_t file_size; + sector_id_t format_sector_id; + sector_id_t last_sector; + sector_id_t req_sector; + uint32_t index_count; + uint8_t state; + uint8_t fill; + uint32_t track_pos; + uint32_t datac; + uint32_t id_pos; + uint16_t last_word[2]; + find_t id_find; + find_t data_find; + crc_t calc_crc; + crc_t track_crc; + uint8_t sector_count; + uint8_t format_state; + uint16_t satisfying_bytes; + uint16_t preceding_bit[2]; + uint16_t current_byte[2]; + uint16_t current_bit[2]; + int cur_track; + uint32_t error_condition; + int is_compressed; + int id_found; + wchar_t original_file_name[2048]; + uint8_t *filebuf; + uint8_t *outbuf; + uint32_t dma_over; + int turbo_pos; + sector_t *last_side_sector[2]; +} d86f_t; #ifdef ENABLE_D86F_LOG -int d86f_do_log = ENABLE_D86F_LOG; +int d86f_do_log = ENABLE_D86F_LOG; #endif -static void -d86f_log(const char *format, ...) -{ -#ifdef ENABLE_D86F_LOG - va_list ap; +static const uint8_t encoded_fm[64] = { + 0xaa, 0xab, 0xae, 0xaf, 0xba, 0xbb, 0xbe, 0xbf, + 0xea, 0xeb, 0xee, 0xef, 0xfa, 0xfb, 0xfe, 0xff, + 0xaa, 0xab, 0xae, 0xaf, 0xba, 0xbb, 0xbe, 0xbf, + 0xea, 0xeb, 0xee, 0xef, 0xfa, 0xfb, 0xfe, 0xff, + 0xaa, 0xab, 0xae, 0xaf, 0xba, 0xbb, 0xbe, 0xbf, + 0xea, 0xeb, 0xee, 0xef, 0xfa, 0xfb, 0xfe, 0xff, + 0xaa, 0xab, 0xae, 0xaf, 0xba, 0xbb, 0xbe, 0xbf, + 0xea, 0xeb, 0xee, 0xef, 0xfa, 0xfb, 0xfe, 0xff +}; +static const uint8_t encoded_mfm[64] = { + 0xaa, 0xa9, 0xa4, 0xa5, 0x92, 0x91, 0x94, 0x95, + 0x4a, 0x49, 0x44, 0x45, 0x52, 0x51, 0x54, 0x55, + 0x2a, 0x29, 0x24, 0x25, 0x12, 0x11, 0x14, 0x15, + 0x4a, 0x49, 0x44, 0x45, 0x52, 0x51, 0x54, 0x55, + 0xaa, 0xa9, 0xa4, 0xa5, 0x92, 0x91, 0x94, 0x95, + 0x4a, 0x49, 0x44, 0x45, 0x52, 0x51, 0x54, 0x55, + 0x2a, 0x29, 0x24, 0x25, 0x12, 0x11, 0x14, 0x15, + 0x4a, 0x49, 0x44, 0x45, 0x52, 0x51, 0x54, 0x55 +}; - if (d86f_do_log) - { - va_start(ap, format); - pclog_ex(format, ap); - va_end(ap); - } -#endif -} +static d86f_t *d86f[FDD_NUM]; +static uint16_t CRCTable[256]; +static fdc_t *d86f_fdc; +uint64_t poly = 0x42F0E1EBA9EA3693ll; /* ECMA normal */ +uint64_t table[256]; -void d86f_initialize_linked_lists(int drive) -{ - d86f[drive].last_side_sector[0] = NULL; - d86f[drive].last_side_sector[1] = NULL; -} - -void d86f_destroy_linked_lists(int drive, int side) -{ - sector_t *s; - sector_t *t; - - if (d86f[drive].last_side_sector[side]) - { - s = d86f[drive].last_side_sector[side]; - while (s) { - t = s->prev; - free(s); - s = NULL; - if (!t) - break; - s = t; - } - d86f[drive].last_side_sector[side] = NULL; - } -} - -static void d86f_setupcrc(uint16_t poly) -{ - 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; - } -} - -static int d86f_has_surface_desc(int drive) -{ - return (d86f_handler[drive].disk_flags(drive) & 1); -} - -int d86f_get_sides(int drive) -{ - return ((d86f_handler[drive].disk_flags(drive) >> 3) & 1) + 1; -} - -int d86f_get_rpm_mode(int drive) -{ - return (d86f_handler[drive].disk_flags(drive) & 0x60) >> 5; -} - -int d86f_reverse_bytes(int drive) -{ - return (d86f_handler[drive].disk_flags(drive) & 0x800) >> 11; -} - uint16_t d86f_side_flags(int drive); int d86f_is_mfm(int drive); void d86f_writeback(int drive); @@ -352,3481 +276,3529 @@ uint8_t d86f_poll_read_data(int drive, int side, uint16_t pos); void d86f_poll_write_data(int drive, int side, uint16_t pos, uint8_t data); int d86f_format_conditions(int drive); -uint16_t d86f_disk_flags(int drive) + +static void +d86f_log(const char *format, ...) { - return d86f[drive].disk_flags; +#ifdef ENABLE_D86F_LOG + va_list ap; + + if (d86f_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif } -uint32_t d86f_index_hole_pos(int drive, int side) +static void +setup_crc(uint16_t poly) { - return d86f[drive].index_hole_pos[side]; -} + int c = 256, bc; + uint16_t temp; -uint32_t null_index_hole_pos(int drive, int side) -{ - return 0; -} + while(c--) { + temp = c << 8; + bc = 8; -uint16_t null_disk_flags(int drive) -{ - return 0x09; -} + while (bc--) { + if (temp & 0x8000) + temp = (temp << 1) ^ poly; + else + temp <<= 1; -uint16_t null_side_flags(int drive) -{ - return 0x0A; -} - -void null_writeback(int drive) -{ - return; -} - -void null_set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n) -{ - return; -} - -void null_write_data(int drive, int side, uint16_t pos, uint8_t data) -{ - return; -} - -int null_format_conditions(int drive) -{ - return 0; -} - -int32_t d86f_extra_bit_cells(int drive, int side) -{ - return d86f[drive].extra_bit_cells[side]; -} - -int32_t null_extra_bit_cells(int drive, int side) -{ - return 0; -} - -uint16_t* common_encoded_data(int drive, int side) -{ - return d86f[drive].track_encoded_data[side]; -} - -void common_read_revolution(int drive) -{ - return; -} - -uint16_t d86f_side_flags(int drive) -{ - int side = 0; - side = fdd_get_head(drive); - return d86f[drive].side_flags[side]; -} - -uint16_t d86f_track_flags(int drive) -{ - uint16_t tf = 0; - uint16_t rr = 0; - uint16_t dr = 0; - - tf = d86f_handler[drive].side_flags(drive); - rr = tf & 0x67; - dr = fdd_get_flags(drive) & 7; - tf &= ~0x67; - - switch (rr) - { - case 0x02: - case 0x21: - /* 1 MB unformatted medium, treat these two as equivalent. */ - switch (dr) - { - case 0x06: - /* 5.25" Single-RPM HD drive, treat as 300 kbps, 360 rpm. */ - tf |= 0x21; - break; - default: - /* Any other drive, treat as 250 kbps, 300 rpm. */ - tf |= 0x02; - break; - } - break; - default: - tf |= rr; - break; + CRCTable[c] = temp; } - return tf; + } } -uint32_t common_get_raw_size(int drive, int side) + +void +d86f_destroy_linked_lists(int drive, int side) { - double rate = 0.0; - int mfm = 0; - double rpm; - double rpm_diff = 0.0; - double size = 100000.0; + d86f_t *dev = d86f[drive]; + sector_t *s, *t; - mfm = d86f_is_mfm(drive); - rpm = ((d86f_track_flags(drive) & 0xE0) == 0x20) ? 360.0 : 300.0; - rpm_diff = 1.0; + if (dev == NULL) return; - switch (d86f_get_rpm_mode(drive)) - { - case 1: - rpm_diff = 1.01; + if (dev->last_side_sector[side]) { + s = dev->last_side_sector[side]; + while (s) { + t = s->prev; + free(s); + s = NULL; + if (! t) break; - case 2: - rpm_diff = 1.015; - break; - case 3: - rpm_diff = 1.02; - break; - default: - rpm_diff = 1.0; - break; - } - switch (d86f_track_flags(drive) & 7) - { - case 0: - rate = 500.0; - break; - case 1: - rate = 300.0; - break; - case 2: - rate = 250.0; - break; - case 3: - rate = 1000.0; - break; - case 5: - rate = 2000.0; - break; - default: - rate = 250.0; - break; - } - if (!mfm) rate /= 2.0; - size = (size / 250.0) * rate; - size = (size * 300.0) / rpm; - size *= rpm_diff; - /* Round down to a multiple of 16 and add the extra bit cells, then return. */ - return ((((uint32_t) size) >> 4) << 4) + d86f_handler[drive].extra_bit_cells(drive, side); + s = t; + } + dev->last_side_sector[side] = NULL; + } } -void d86f_set_version(int drive, uint16_t version) + +static int +d86f_has_surface_desc(int drive) { - d86f[drive].version = version; + return (d86f_handler[drive].disk_flags(drive) & 1); } -void d86f_unregister(int drive) + +int +d86f_get_sides(int drive) { - d86f_handler[drive].disk_flags = null_disk_flags; - d86f_handler[drive].side_flags = null_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 = 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 = 0; - d86f[drive].version = 0x0063; /* Proxied formats report as version 0.99. */ + return ((d86f_handler[drive].disk_flags(drive) >> 3) & 1) + 1; } -void d86f_register_86f(int drive) + +int +d86f_get_rpm_mode(int drive) { - d86f_handler[drive].disk_flags = d86f_disk_flags; - d86f_handler[drive].side_flags = d86f_side_flags; - d86f_handler[drive].writeback = d86f_writeback; - d86f_handler[drive].set_sector = null_set_sector; - d86f_handler[drive].write_data = null_write_data; - d86f_handler[drive].format_conditions = d86f_format_conditions; - d86f_handler[drive].extra_bit_cells = d86f_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 = d86f_index_hole_pos; - d86f_handler[drive].get_raw_size = common_get_raw_size; - d86f_handler[drive].check_crc = 1; + return (d86f_handler[drive].disk_flags(drive) & 0x60) >> 5; } -int d86f_get_array_size(int drive, int side) +int +d86f_reverse_bytes(int drive) { - int array_size = 0; - int rm = 0; - int hole = 0; - rm = d86f_get_rpm_mode(drive); - hole = (d86f_handler[drive].disk_flags(drive) & 6) >> 1; - switch (hole) - { - case 0: - case 1: - default: - array_size = 12500; - switch (rm) - { - case 1: - array_size = 12625; - break; - case 2: - array_size = 12687; - break; - case 3: - array_size = 12750; - break; - default: - array_size = 12500; - break; - } - break; - case 2: - array_size = 25000; - switch (rm) - { - case 1: - array_size = 25250; - break; - case 2: - array_size = 25375; - break; - case 3: - array_size = 25500; - break; - default: - array_size = 25000; - break; - } - break; - case 3: - array_size = 50000; - switch (rm) - { - case 1: - array_size = 50500; - break; - case 2: - array_size = 50750; - break; - case 3: - array_size = 51000; - break; - default: - array_size = 50000; - break; - } - break; - } - array_size <<= 4; - array_size += d86f_handler[drive].extra_bit_cells(drive, side); - array_size >>= 4; - if (d86f_handler[drive].extra_bit_cells(drive, side) & 15) - { - array_size++; - } - return array_size; + return (d86f_handler[drive].disk_flags(drive) & 0x800) >> 11; } -int d86f_valid_bit_rate(int drive) + +uint16_t +d86f_disk_flags(int drive) { - int rate = 0; - int hole = 0; - rate = fdc_get_bit_rate(d86f_fdc); - hole = (d86f_handler[drive].disk_flags(drive) & 6) >> 1; - switch (hole) - { - case 0: /* DD */ - if (!rate && (fdd_get_flags(drive) & 0x10)) return 1; - if ((rate < 1) || (rate > 2)) return 0; - return 1; - case 1: /* HD */ - if (rate != 0) return 0; - return 1; - case 2: /* ED */ - if (rate != 3) return 0; - return 1; - case 3: /* ED with 2000 kbps support */ - if (rate < 3) return 0; - return 1; - } - return 1; + d86f_t *dev = d86f[drive]; + + return dev->disk_flags; } -int d86f_hole(int drive) + +uint32_t +d86f_index_hole_pos(int drive, int side) { - if (((d86f_handler[drive].disk_flags(drive) >> 1) & 3) == 3) return 2; - return (d86f_handler[drive].disk_flags(drive) >> 1) & 3; + d86f_t *dev = d86f[drive]; + + return dev->index_hole_pos[side]; } -uint8_t d86f_get_encoding(int drive) + +uint32_t +null_index_hole_pos(int drive, int side) { - return (d86f_track_flags(drive) & 0x18) >> 3; + return 0; } -double d86f_byteperiod(int drive) + +uint16_t +null_disk_flags(int drive) { - switch (d86f_track_flags(drive) & 0x0f) - { - case 0x02: /* 125 kbps, FM */ - return 4.0; - case 0x01: /* 150 kbps, FM */ - return 20.0 / 6.0; - case 0x0A: /* 250 kbps, MFM */ - case 0x00: /* 250 kbps, FM */ - return 2.0; - case 0x09: /* 300 kbps, MFM */ - return 10.0 / 6.0; - case 0x08: /* 500 kbps, MFM */ - return 1.0; - case 0x0B: /* 1000 kbps, MFM */ - return 0.5; - case 0x0D: /* 2000 kbps, MFM */ - return 0.25; - default: - return 2.0; - } - return 2.0; + return 0x09; } -int d86f_is_mfm(int drive) + +uint16_t +null_side_flags(int drive) { - return (d86f_track_flags(drive) & 8) ? 1 : 0; + return 0x0A; } -uint32_t d86f_get_data_len(int drive) + +void +null_writeback(int drive) { - if (d86f[drive].req_sector.id.n) - { - if (d86f[drive].req_sector.id.n == 8) return 32768; - return (128 << ((uint32_t) d86f[drive].req_sector.id.n)); - } - else - { - if (fdc_get_dtl(d86f_fdc) < 128) - { - return fdc_get_dtl(d86f_fdc); + return; +} + + +void +null_set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n) +{ + return; +} + + +void +null_write_data(int drive, int side, uint16_t pos, uint8_t data) +{ + return; +} + + +int +null_format_conditions(int drive) +{ + return 0; +} + + +int32_t +d86f_extra_bit_cells(int drive, int side) +{ + d86f_t *dev = d86f[drive]; + + return dev->extra_bit_cells[side]; +} + + +int32_t +null_extra_bit_cells(int drive, int side) +{ + return 0; +} + + +uint16_t* +common_encoded_data(int drive, int side) +{ + d86f_t *dev = d86f[drive]; + + return dev->track_encoded_data[side]; +} + + +void +common_read_revolution(int drive) +{ + return; +} + + +uint16_t +d86f_side_flags(int drive) +{ + d86f_t *dev = d86f[drive]; + int side; + + side = fdd_get_head(drive); + + return dev->side_flags[side]; +} + + +uint16_t +d86f_track_flags(int drive) +{ + uint16_t dr, rr, tf; + + tf = d86f_handler[drive].side_flags(drive); + rr = tf & 0x67; + dr = fdd_get_flags(drive) & 7; + tf &= ~0x67; + + switch (rr) { + case 0x02: + case 0x21: + /* 1 MB unformatted medium, treat these two as equivalent. */ + switch (dr) { + case 0x06: + /* 5.25" Single-RPM HD drive, treat as 300 kbps, 360 rpm. */ + tf |= 0x21; + break; + + default: + /* Any other drive, treat as 250 kbps, 300 rpm. */ + tf |= 0x02; + break; } - else - { - return (128 << ((uint32_t) d86f[drive].req_sector.id.n)); + break; + + default: + tf |= rr; + break; + } + + return tf; +} + + +uint32_t +common_get_raw_size(int drive, int side) +{ + double rate = 0.0; + double rpm, rpm_diff; + double size = 100000.0; + int mfm; + + mfm = d86f_is_mfm(drive); + rpm = ((d86f_track_flags(drive) & 0xE0) == 0x20) ? 360.0 : 300.0; + rpm_diff = 1.0; + + switch (d86f_get_rpm_mode(drive)) { + case 1: + rpm_diff = 1.01; + break; + + case 2: + rpm_diff = 1.015; + break; + + case 3: + rpm_diff = 1.02; + break; + + default: + rpm_diff = 1.0; + break; + } + + switch (d86f_track_flags(drive) & 7) { + case 0: + rate = 500.0; + break; + + case 1: + rate = 300.0; + break; + + case 2: + rate = 250.0; + break; + + case 3: + rate = 1000.0; + break; + + case 5: + rate = 2000.0; + break; + + default: + rate = 250.0; + break; + } + + if (! mfm) rate /= 2.0; + + size = (size / 250.0) * rate; + size = (size * 300.0) / rpm; + size *= rpm_diff; + + /* + * Round down to a multiple of 16 and add the extra bit cells, + * then return. + */ + return ((((uint32_t) size) >> 4) << 4) + d86f_handler[drive].extra_bit_cells(drive, side); +} + + +void +d86f_set_version(int drive, uint16_t version) +{ + d86f_t *dev = d86f[drive]; + + dev->version = version; +} + + +void +d86f_unregister(int drive) +{ + d86f_t *dev = d86f[drive]; + + if (dev == NULL) return; + + d86f_handler[drive].disk_flags = null_disk_flags; + d86f_handler[drive].side_flags = null_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 = 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 = 0; + + dev->version = 0x0063; /* Proxied formats report as version 0.99. */ +} + + +void +d86f_register_86f(int drive) +{ + d86f_handler[drive].disk_flags = d86f_disk_flags; + d86f_handler[drive].side_flags = d86f_side_flags; + d86f_handler[drive].writeback = d86f_writeback; + d86f_handler[drive].set_sector = null_set_sector; + d86f_handler[drive].write_data = null_write_data; + d86f_handler[drive].format_conditions = d86f_format_conditions; + d86f_handler[drive].extra_bit_cells = d86f_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 = d86f_index_hole_pos; + d86f_handler[drive].get_raw_size = common_get_raw_size; + d86f_handler[drive].check_crc = 1; +} + + +int +d86f_get_array_size(int drive, int side) +{ + int array_size; + int hole, rm; + + rm = d86f_get_rpm_mode(drive); + hole = (d86f_handler[drive].disk_flags(drive) & 6) >> 1; + switch (hole) { + case 0: + case 1: + default: + array_size = 12500; + switch (rm) { + case 1: + array_size = 12625; + break; + + case 2: + array_size = 12687; + break; + + case 3: + array_size = 12750; + break; + + default: + break; } - } -} + break; -uint32_t d86f_has_extra_bit_cells(int drive) -{ - return (d86f_handler[drive].disk_flags(drive) >> 7) & 1; -} + case 2: + array_size = 25000; + switch (rm) { + case 1: + array_size = 25250; + break; -uint32_t d86f_header_size(int drive) -{ - return 8; -} + case 2: + array_size = 25375; + break; -static uint16_t d86f_encode_get_data(uint8_t dat) -{ - uint16_t temp; - temp = 0; - if (dat & 0x01) temp |= 1; - if (dat & 0x02) temp |= 4; - if (dat & 0x04) temp |= 16; - if (dat & 0x08) temp |= 64; - if (dat & 0x10) temp |= 256; - if (dat & 0x20) temp |= 1024; - if (dat & 0x40) temp |= 4096; - if (dat & 0x80) temp |= 16384; - return temp; -} + case 3: + array_size = 25500; + break; -static uint16_t d86f_encode_get_clock(uint8_t dat) -{ - uint16_t temp; - temp = 0; - if (dat & 0x01) temp |= 2; - if (dat & 0x02) temp |= 8; - if (dat & 0x40) temp |= 32; - if (dat & 0x08) temp |= 128; - if (dat & 0x10) temp |= 512; - if (dat & 0x20) temp |= 2048; - if (dat & 0x40) temp |= 8192; - if (dat & 0x80) temp |= 32768; - return temp; -} - -int d86f_format_conditions(int drive) -{ - return d86f_valid_bit_rate(drive); -} - -int d86f_wrong_densel(int drive) -{ - int is_3mode = 0; - - if ((fdd_get_flags(drive) & 7) == 3) - { - is_3mode = 1; - } - - switch (d86f_hole(drive)) - { - case 0: - default: - if (fdd_is_dd(drive)) - { - return 0; - } - if (fdd_get_densel(drive)) - { - return 1; - } - else - { - return 0; - } - break; - case 1: - if (fdd_is_dd(drive)) - { - return 1; - } - if (fdd_get_densel(drive)) - { - return 0; - } - else - { - if (is_3mode) - { - return 0; - } - else - { - return 1; - } - } - break; - case 2: - if (fdd_is_dd(drive) || !fdd_is_ed(drive)) - { - return 1; - } - if (fdd_get_densel(drive)) - { - return 0; - } - else - { - return 1; - } - break; - } -} - -int d86f_can_format(int drive) -{ - int temp; - temp = !writeprot[drive]; - temp = temp && !fdc_get_swwp(d86f_fdc); - temp = temp && fdd_can_read_medium(real_drive(d86f_fdc, drive)); - temp = temp && d86f_handler[drive].format_conditions(drive); /* Allows proxied formats to add their own extra conditions to formatting. */ - temp = temp && !d86f_wrong_densel(drive); - return temp; -} - -uint16_t d86f_encode_byte(int drive, int sync, decoded_t b, decoded_t prev_b) -{ - uint8_t encoding = d86f_get_encoding(drive); - uint8_t bits89AB = prev_b.nibbles.nibble0; - uint8_t bits7654 = b.nibbles.nibble1; - uint8_t bits3210 = b.nibbles.nibble0; - uint16_t encoded_7654, encoded_3210, result; - if (encoding > 1) return 0xFF; - if (sync) - { - result = d86f_encode_get_data(b.byte); - if (encoding) - { - switch(b.byte) - { - case 0xA1: return result | d86f_encode_get_clock(0x0A); - case 0xC2: return result | d86f_encode_get_clock(0x14); - case 0xF8: return result | d86f_encode_get_clock(0x03); - case 0xFB: case 0xFE: return result | d86f_encode_get_clock(0x00); - case 0xFC: return result | d86f_encode_get_clock(0x01); - } + default: + break; } - else - { - switch(b.byte) - { - case 0xF8: case 0xFB: case 0xFE: return result | d86f_encode_get_clock(0xC7); - case 0xFC: return result | d86f_encode_get_clock(0xD7); - } + break; + + case 3: + array_size = 50000; + switch (rm) { + case 1: + array_size = 50500; + break; + + case 2: + array_size = 50750; + break; + + case 3: + array_size = 51000; + break; + + default: + break; } - } - bits3210 += ((bits7654 & 3) << 4); - bits7654 += ((bits89AB & 3) << 4); - encoded_3210 = (encoding == 1) ? encoded_mfm[bits3210] : encoded_fm[bits3210]; - encoded_7654 = (encoding == 1) ? encoded_mfm[bits7654] : encoded_fm[bits7654]; - result = (encoded_7654 << 8) | encoded_3210; - return result; + break; + } + + array_size <<= 4; + array_size += d86f_handler[drive].extra_bit_cells(drive, side); + array_size >>= 4; + + if (d86f_handler[drive].extra_bit_cells(drive, side) & 15) + array_size++; + + return array_size; } -static int d86f_get_bitcell_period(int drive) + +int +d86f_valid_bit_rate(int drive) { - double rate = 0.0; - int mfm = 0; - int tflags = 0; - double rpm = 0; - double size = 8000.0; + int hole, rate; - tflags = d86f_track_flags(drive); - - mfm = (tflags & 8) ? 1 : 0; - rpm = ((tflags & 0xE0) == 0x20) ? 360.0 : 300.0; - - switch (tflags & 7) - { - case 0: - rate = 500.0; - break; - case 1: - rate = 300.0; - break; - case 2: - rate = 250.0; - break; - case 3: - rate = 1000.0; - break; - case 5: - rate = 2000.0; - break; - } - if (!mfm) rate /= 2.0; - size = (size * 250.0) / rate; - size = (size * 300.0) / rpm; - size = (size * fdd_getrpm(real_drive(d86f_fdc, drive))) / 300.0; - return (int) size; -} - -int d86f_can_read_address(int drive) -{ - int temp = 0; - temp = (fdc_get_bitcell_period(d86f_fdc) == d86f_get_bitcell_period(drive)); - temp = temp && fdd_can_read_medium(real_drive(d86f_fdc, drive)); - temp = temp && (fdc_is_mfm(d86f_fdc) == d86f_is_mfm(drive)); - temp = temp && (d86f_get_encoding(drive) <= 1); - return temp; -} - -void d86f_get_bit(int drive, int side) -{ - uint32_t track_word; - uint32_t track_bit; - uint16_t encoded_data; - uint16_t surface_data = 0; - uint16_t current_bit; - uint16_t surface_bit; - - track_word = d86f[drive].track_pos >> 4; - /* We need to make sure we read the bits from MSB to LSB. */ - track_bit = 15 - (d86f[drive].track_pos & 15); - - if (d86f_reverse_bytes(drive)) - { - /* Image is in reverse endianness, read the data as is. */ - encoded_data = d86f_handler[drive].encoded_data(drive, side)[track_word]; - } - else - { - /* We store the words as big endian, so we need to convert them to little endian when reading. */ - encoded_data = (d86f_handler[drive].encoded_data(drive, side)[track_word] & 0xFF) << 8; - encoded_data |= (d86f_handler[drive].encoded_data(drive, side)[track_word] >> 8); - } - - if (d86f_has_surface_desc(drive)) - { - if (d86f_reverse_bytes(drive)) - { - surface_data = d86f[drive].track_surface_data[side][track_word] & 0xFF; - } - else - { - surface_data = (d86f[drive].track_surface_data[side][track_word] & 0xFF) << 8; - surface_data |= (d86f[drive].track_surface_data[side][track_word] >> 8); - } - } - - current_bit = (encoded_data >> track_bit) & 1; - d86f[drive].last_word[side] <<= 1; - - if (d86f_has_surface_desc(drive)) - { - surface_bit = (surface_data >> track_bit) & 1; - if (!surface_bit) - { - if (!current_bit) - { - /* Bit is 0 and is not set to fuzzy, we add it as read. */ - d86f[drive].last_word[side] |= 1; - } - else - { - /* Bit is 1 and is not set to fuzzy, we add it as read. */ - d86f[drive].last_word[side] |= 1; - } - } - else - { - if (current_bit) - { - /* Bit is 1 and is set to fuzzy, we randomly generate it. */ - d86f[drive].last_word[side] |= (random_generate() & 1); - } - } - } - else - { - d86f[drive].last_word[side] |= current_bit; - } -} - -void d86f_put_bit(int drive, int side, int bit) -{ - uint32_t track_word; - uint32_t track_bit; - uint16_t encoded_data; - uint16_t surface_data = 0; - uint16_t current_bit; - uint16_t surface_bit; - - if (fdc_get_diswr(d86f_fdc)) - return; - - track_word = d86f[drive].track_pos >> 4; - /* We need to make sure we read the bits from MSB to LSB. */ - track_bit = 15 - (d86f[drive].track_pos & 15); - - if (d86f_reverse_bytes(drive)) - { - /* Image is in reverse endianness, read the data as is. */ - encoded_data = d86f_handler[drive].encoded_data(drive, side)[track_word]; - } - else - { - /* We store the words as big endian, so we need to convert them to little endian when reading. */ - encoded_data = (d86f_handler[drive].encoded_data(drive, side)[track_word] & 0xFF) << 8; - encoded_data |= (d86f_handler[drive].encoded_data(drive, side)[track_word] >> 8); - } - - if (d86f_has_surface_desc(drive)) - { - if (d86f_reverse_bytes(drive)) - { - surface_data = d86f[drive].track_surface_data[side][track_word] & 0xFF; - } - else - { - surface_data = (d86f[drive].track_surface_data[side][track_word] & 0xFF) << 8; - surface_data |= (d86f[drive].track_surface_data[side][track_word] >> 8); - } - } - - current_bit = (encoded_data >> track_bit) & 1; - d86f[drive].last_word[side] <<= 1; - - if (d86f_has_surface_desc(drive)) - { - surface_bit = (surface_data >> track_bit) & 1; - if (!surface_bit) - { - if (!current_bit) - { - /* Bit is 0 and is not set to fuzzy, we overwrite it as is. */ - d86f[drive].last_word[side] |= bit; - current_bit = bit; - } - else - { - /* Bit is 1 and is not set to fuzzy, we overwrite it as is. */ - d86f[drive].last_word[side] |= bit; - current_bit = bit; - } - } - else - { - if (current_bit) - { - /* Bit is 1 and is set to fuzzy, we overwrite it with a non-fuzzy bit. */ - d86f[drive].last_word[side] |= bit; - current_bit = bit; - surface_bit = 0; - } - } - - surface_data &= ~(1 << track_bit); - surface_data |= (surface_bit << track_bit); - if (d86f_reverse_bytes(drive)) - { - d86f[drive].track_surface_data[side][track_word] = surface_data; - } - else - { - d86f[drive].track_surface_data[side][track_word] = (surface_data & 0xFF) << 8; - d86f[drive].track_surface_data[side][track_word] |= (surface_data >> 8); - } - } - else - { - d86f[drive].last_word[side] |= bit; - current_bit = bit; - } - - encoded_data &= ~(1 << track_bit); - encoded_data |= (current_bit << track_bit); - - if (d86f_reverse_bytes(drive)) - { - d86f_handler[drive].encoded_data(drive, side)[track_word] = encoded_data; - } - else - { - d86f_handler[drive].encoded_data(drive, side)[track_word] = (encoded_data & 0xFF) << 8; - d86f_handler[drive].encoded_data(drive, side)[track_word] |= (encoded_data >> 8); - } -} - -static uint8_t decodefm(int drive, uint16_t dat) -{ - uint8_t temp = 0; - /* We write the encoded bytes in big endian, so we process the two 8-bit halves swapped here. */ - 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 fdd_calccrc(uint8_t byte, crc_t *crc_var) -{ - crc_var->word = (crc_var->word << 8) ^ CRCTable[(crc_var->word >> 8)^byte]; -} - -static void d86f_calccrc(int drive, uint8_t byte) -{ - fdd_calccrc(byte, &(d86f[drive].calc_crc)); -} - -int d86f_word_is_aligned(int drive, int side, uint32_t base_pos) -{ - int adjusted_track_pos = d86f[drive].track_pos; - - if (base_pos == 0xFFFFFFFF) - { - return 0; - } - - /* This is very important, it makes sure alignment is detected correctly even across the index hole of a track whose length is not divisible by 16. */ - if (adjusted_track_pos < base_pos) - { - adjusted_track_pos += d86f_handler[drive].get_raw_size(drive, side); - } - - if ((adjusted_track_pos & 15) == (base_pos & 15)) - { + rate = fdc_get_bit_rate(d86f_fdc); + hole = (d86f_handler[drive].disk_flags(drive) & 6) >> 1; + switch (hole) { + case 0: /* DD */ + if (!rate && (fdd_get_flags(drive) & 0x10)) return 1; + if ((rate < 1) || (rate > 2)) return 0; return 1; - } - else - { - return 0; - } + + case 1: /* HD */ + if (rate != 0) return 0; + return 1; + + case 2: /* ED */ + if (rate != 3) return 0; + return 1; + + case 3: /* ED with 2000 kbps support */ + if (rate < 3) return 0; + return 1; + } + + return 1; //FIXME: should be 0 for error? } + +int +d86f_hole(int drive) +{ + if (((d86f_handler[drive].disk_flags(drive) >> 1) & 3) == 3) + return 2; + + return (d86f_handler[drive].disk_flags(drive) >> 1) & 3; +} + + +uint8_t +d86f_get_encoding(int drive) +{ + return (d86f_track_flags(drive) & 0x18) >> 3; +} + + +double +d86f_byteperiod(int drive) +{ + switch (d86f_track_flags(drive) & 0x0f) { + case 0x02: /* 125 kbps, FM */ + return 4.0; + + case 0x01: /* 150 kbps, FM */ + return 20.0 / 6.0; + + case 0x0a: /* 250 kbps, MFM */ + case 0x00: /* 250 kbps, FM */ + return 2.0; + + case 0x09: /* 300 kbps, MFM */ + return 10.0 / 6.0; + + case 0x08: /* 500 kbps, MFM */ + return 1.0; + + case 0x0b: /* 1000 kbps, MFM */ + return 0.5; + + case 0x0d: /* 2000 kbps, MFM */ + return 0.25; + + default: + break; + } + + return 2.0; +} + + +int +d86f_is_mfm(int drive) +{ + return (d86f_track_flags(drive) & 8) ? 1 : 0; +} + + +uint32_t +d86f_get_data_len(int drive) +{ + d86f_t *dev = d86f[drive]; + + if (dev->req_sector.id.n) { + if (dev->req_sector.id.n == 8) return 32768; + return (128 << ((uint32_t) dev->req_sector.id.n)); + } else { + if (fdc_get_dtl(d86f_fdc) < 128) + return fdc_get_dtl(d86f_fdc); + else + return (128 << ((uint32_t) dev->req_sector.id.n)); + } +} + + +uint32_t +d86f_has_extra_bit_cells(int drive) +{ + return (d86f_handler[drive].disk_flags(drive) >> 7) & 1; +} + + +uint32_t +d86f_header_size(int drive) +{ + return 8; +} + + +static uint16_t +d86f_encode_get_data(uint8_t dat) +{ + uint16_t temp; + temp = 0; + + if (dat & 0x01) temp |= 1; + if (dat & 0x02) temp |= 4; + if (dat & 0x04) temp |= 16; + if (dat & 0x08) temp |= 64; + if (dat & 0x10) temp |= 256; + if (dat & 0x20) temp |= 1024; + if (dat & 0x40) temp |= 4096; + if (dat & 0x80) temp |= 16384; + + return temp; +} + + +static uint16_t +d86f_encode_get_clock(uint8_t dat) +{ + uint16_t temp; + temp = 0; + + if (dat & 0x01) temp |= 2; + if (dat & 0x02) temp |= 8; + if (dat & 0x40) temp |= 32; + if (dat & 0x08) temp |= 128; + if (dat & 0x10) temp |= 512; + if (dat & 0x20) temp |= 2048; + if (dat & 0x40) temp |= 8192; + if (dat & 0x80) temp |= 32768; + + return temp; +} + + +int +d86f_format_conditions(int drive) +{ + return d86f_valid_bit_rate(drive); +} + + +int +d86f_wrong_densel(int drive) +{ + int is_3mode = 0; + + if ((fdd_get_flags(drive) & 7) == 3) + is_3mode = 1; + + switch (d86f_hole(drive)) { + case 0: + default: + if (fdd_is_dd(drive)) + return 0; + if (fdd_get_densel(drive)) + return 1; + else + return 0; + break; + + case 1: + if (fdd_is_dd(drive)) + return 1; + if (fdd_get_densel(drive)) + return 0; + else { + if (is_3mode) + return 0; + else + return 1; + } + break; + + case 2: + if (fdd_is_dd(drive) || !fdd_is_ed(drive)) + return 1; + if (fdd_get_densel(drive)) + return 0; + else + return 1; + break; + } +} + + +int +d86f_can_format(int drive) +{ + int temp; + + temp = !writeprot[drive]; + temp = temp && !fdc_get_swwp(d86f_fdc); + temp = temp && fdd_can_read_medium(real_drive(d86f_fdc, drive)); + temp = temp && d86f_handler[drive].format_conditions(drive); /* Allows proxied formats to add their own extra conditions to formatting. */ + temp = temp && !d86f_wrong_densel(drive); + + return temp; +} + + +uint16_t +d86f_encode_byte(int drive, int sync, decoded_t b, decoded_t prev_b) +{ + uint8_t encoding = d86f_get_encoding(drive); + uint8_t bits89AB = prev_b.nibbles.nibble0; + uint8_t bits7654 = b.nibbles.nibble1; + uint8_t bits3210 = b.nibbles.nibble0; + uint16_t encoded_7654, encoded_3210, result; + + if (encoding > 1) return 0xff; + + if (sync) { + result = d86f_encode_get_data(b.byte); + if (encoding) { + switch(b.byte) { + case 0xa1: + return result | d86f_encode_get_clock(0x0a); + + case 0xc2: + return result | d86f_encode_get_clock(0x14); + + case 0xf8: + return result | d86f_encode_get_clock(0x03); + + case 0xfb: + case 0xfe: + return result | d86f_encode_get_clock(0x00); + + case 0xfc: + return result | d86f_encode_get_clock(0x01); + } + } else { + switch(b.byte) { + case 0xf8: + case 0xfb: + case 0xfe: + return result | d86f_encode_get_clock(0xc7); + + case 0xfc: + return result | d86f_encode_get_clock(0xd7); + } + } + } + + bits3210 += ((bits7654 & 3) << 4); + bits7654 += ((bits89AB & 3) << 4); + encoded_3210 = (encoding == 1) ? encoded_mfm[bits3210] : encoded_fm[bits3210]; + encoded_7654 = (encoding == 1) ? encoded_mfm[bits7654] : encoded_fm[bits7654]; + result = (encoded_7654 << 8) | encoded_3210; + + return result; +} + + +static int +d86f_get_bitcell_period(int drive) +{ + double rate = 0.0; + int mfm = 0; + int tflags = 0; + double rpm = 0; + double size = 8000.0; + + tflags = d86f_track_flags(drive); + + mfm = (tflags & 8) ? 1 : 0; + rpm = ((tflags & 0xE0) == 0x20) ? 360.0 : 300.0; + + switch (tflags & 7) { + case 0: + rate = 500.0; + break; + + case 1: + rate = 300.0; + break; + + case 2: + rate = 250.0; + break; + + case 3: + rate = 1000.0; + break; + + case 5: + rate = 2000.0; + break; + } + + if (! mfm) + rate /= 2.0; + size = (size * 250.0) / rate; + size = (size * 300.0) / rpm; + size = (size * fdd_getrpm(real_drive(d86f_fdc, drive))) / 300.0; + + return (int)size; +} + + +int +d86f_can_read_address(int drive) +{ + int temp; + + temp = (fdc_get_bitcell_period(d86f_fdc) == d86f_get_bitcell_period(drive)); + temp = temp && fdd_can_read_medium(real_drive(d86f_fdc, drive)); + temp = temp && (fdc_is_mfm(d86f_fdc) == d86f_is_mfm(drive)); + temp = temp && (d86f_get_encoding(drive) <= 1); + + return temp; +} + + +void +d86f_get_bit(int drive, int side) +{ + d86f_t *dev = d86f[drive]; + uint32_t track_word; + uint32_t track_bit; + uint16_t encoded_data; + uint16_t surface_data = 0; + uint16_t current_bit; + uint16_t surface_bit; + + track_word = dev->track_pos >> 4; + + /* We need to make sure we read the bits from MSB to LSB. */ + track_bit = 15 - (dev->track_pos & 15); + + if (d86f_reverse_bytes(drive)) { + /* Image is in reverse endianness, read the data as is. */ + encoded_data = d86f_handler[drive].encoded_data(drive, side)[track_word]; + } else { + /* We store the words as big endian, so we need to convert them to little endian when reading. */ + encoded_data = (d86f_handler[drive].encoded_data(drive, side)[track_word] & 0xFF) << 8; + encoded_data |= (d86f_handler[drive].encoded_data(drive, side)[track_word] >> 8); + } + + if (d86f_has_surface_desc(drive)) { + if (d86f_reverse_bytes(drive)) { + surface_data = dev->track_surface_data[side][track_word] & 0xFF; + } else { + surface_data = (dev->track_surface_data[side][track_word] & 0xFF) << 8; + surface_data |= (dev->track_surface_data[side][track_word] >> 8); + } + } + + current_bit = (encoded_data >> track_bit) & 1; + dev->last_word[side] <<= 1; + + if (d86f_has_surface_desc(drive)) { + surface_bit = (surface_data >> track_bit) & 1; + if (! surface_bit) { + if (! current_bit) { + /* Bit is 0 and is not set to fuzzy, we add it as read. */ + dev->last_word[side] |= 1; + } else { + /* Bit is 1 and is not set to fuzzy, we add it as read. */ + dev->last_word[side] |= 1; + } + } else { + if (current_bit) { + /* Bit is 1 and is set to fuzzy, we randomly generate it. */ + dev->last_word[side] |= (random_generate() & 1); + } + } + } else { + dev->last_word[side] |= current_bit; + } +} + + +void +d86f_put_bit(int drive, int side, int bit) +{ + d86f_t *dev = d86f[drive]; + uint32_t track_word; + uint32_t track_bit; + uint16_t encoded_data; + uint16_t surface_data = 0; + uint16_t current_bit; + uint16_t surface_bit; + + if (fdc_get_diswr(d86f_fdc)) + return; + + track_word = dev->track_pos >> 4; + + /* We need to make sure we read the bits from MSB to LSB. */ + track_bit = 15 - (dev->track_pos & 15); + + if (d86f_reverse_bytes(drive)) { + /* Image is in reverse endianness, read the data as is. */ + encoded_data = d86f_handler[drive].encoded_data(drive, side)[track_word]; + } else { + /* We store the words as big endian, so we need to convert them to little endian when reading. */ + encoded_data = (d86f_handler[drive].encoded_data(drive, side)[track_word] & 0xFF) << 8; + encoded_data |= (d86f_handler[drive].encoded_data(drive, side)[track_word] >> 8); + } + + if (d86f_has_surface_desc(drive)) { + if (d86f_reverse_bytes(drive)) { + surface_data = dev->track_surface_data[side][track_word] & 0xFF; + } else { + surface_data = (dev->track_surface_data[side][track_word] & 0xFF) << 8; + surface_data |= (dev->track_surface_data[side][track_word] >> 8); + } + } + + current_bit = (encoded_data >> track_bit) & 1; + dev->last_word[side] <<= 1; + + if (d86f_has_surface_desc(drive)) { + surface_bit = (surface_data >> track_bit) & 1; + if (! surface_bit) { + if (! current_bit) { + /* Bit is 0 and is not set to fuzzy, we overwrite it as is. */ + dev->last_word[side] |= bit; + current_bit = bit; + } else { + /* Bit is 1 and is not set to fuzzy, we overwrite it as is. */ + dev->last_word[side] |= bit; + current_bit = bit; + } + } else { + if (current_bit) { + /* Bit is 1 and is set to fuzzy, we overwrite it with a non-fuzzy bit. */ + dev->last_word[side] |= bit; + current_bit = bit; + surface_bit = 0; + } + } + + surface_data &= ~(1 << track_bit); + surface_data |= (surface_bit << track_bit); + if (d86f_reverse_bytes(drive)) { + dev->track_surface_data[side][track_word] = surface_data; + } else { + dev->track_surface_data[side][track_word] = (surface_data & 0xFF) << 8; + dev->track_surface_data[side][track_word] |= (surface_data >> 8); + } + } else { + dev->last_word[side] |= bit; + current_bit = bit; + } + + encoded_data &= ~(1 << track_bit); + encoded_data |= (current_bit << track_bit); + + if (d86f_reverse_bytes(drive)) { + d86f_handler[drive].encoded_data(drive, side)[track_word] = encoded_data; + } else { + d86f_handler[drive].encoded_data(drive, side)[track_word] = (encoded_data & 0xFF) << 8; + d86f_handler[drive].encoded_data(drive, side)[track_word] |= (encoded_data >> 8); + } +} + + +static uint8_t +decodefm(int drive, uint16_t dat) +{ + uint8_t temp = 0; + + /* + * We write the encoded bytes in big endian, so we + * process the two 8-bit halves swapped here. + */ + 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 +fdd_calccrc(uint8_t byte, crc_t *crc_var) +{ + crc_var->word = (crc_var->word << 8) ^ + CRCTable[(crc_var->word >> 8)^byte]; +} + + +static void +d86f_calccrc(d86f_t *dev, uint8_t byte) +{ + fdd_calccrc(byte, &(dev->calc_crc)); +} + + +int +d86f_word_is_aligned(int drive, int side, uint32_t base_pos) +{ + d86f_t *dev = d86f[drive]; + uint32_t adjusted_track_pos = dev->track_pos; + + if (base_pos == 0xFFFFFFFF) return 0; + + /* + * This is very important, it makes sure alignment is detected + * correctly even across the index hole of a track whose length + * is not divisible by 16. + */ + if (adjusted_track_pos < base_pos) { + adjusted_track_pos += d86f_handler[drive].get_raw_size(drive, side); + } + + if ((adjusted_track_pos & 15) == (base_pos & 15)) return 1; + + return 0; +} + + /* State 1: Find sector ID */ -void d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am, uint16_t other_am, uint16_t ignore_other_am) +void +d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am, uint16_t other_am, uint16_t ignore_other_am) { - d86f_get_bit(drive, side); + d86f_t *dev = d86f[drive]; - if (d86f[drive].last_word[side] == req_am) - { - d86f[drive].calc_crc.word = 0xFFFF; - fdd_calccrc(decodefm(drive, d86f[drive].last_word[side]), &(d86f[drive].calc_crc)); - find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; - find->sync_pos = 0xFFFFFFFF; - d86f[drive].preceding_bit[side] = d86f[drive].last_word[side] & 1; - d86f[drive].state++; - return; - } + d86f_get_bit(drive, side); - if ((ignore_other_am & 2) && (d86f[drive].last_word[side] == other_am)) - { - d86f[drive].calc_crc.word = 0xFFFF; - fdd_calccrc(decodefm(drive, d86f[drive].last_word[side]), &(d86f[drive].calc_crc)); - find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; - find->sync_pos = 0xFFFFFFFF; - if (ignore_other_am & 1) - { - /* Skip mode, let's go back to finding ID. */ - d86f[drive].state -= 2; - } - else - { - /* Not skip mode, process the sector anyway. */ - fdc_set_wrong_am(d86f_fdc); - d86f[drive].preceding_bit[side] = d86f[drive].last_word[side] & 1; - d86f[drive].state++; - } - return; + if (dev->last_word[side] == req_am) { + dev->calc_crc.word = 0xFFFF; + fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc)); + find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; + find->sync_pos = 0xFFFFFFFF; + dev->preceding_bit[side] = dev->last_word[side] & 1; + dev->state++; + return; + } + + if ((ignore_other_am & 2) && (dev->last_word[side] == other_am)) { + dev->calc_crc.word = 0xFFFF; + fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc)); + find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; + find->sync_pos = 0xFFFFFFFF; + if (ignore_other_am & 1) { + /* Skip mode, let's go back to finding ID. */ + dev->state -= 2; + } else { + /* Not skip mode, process the sector anyway. */ + fdc_set_wrong_am(d86f_fdc); + dev->preceding_bit[side] = dev->last_word[side] & 1; + dev->state++; } + } } + /* When writing in FM mode, we find the beginning of the address mark by looking for 352 (22 * 16) set bits (gap fill = 0xFF, 0xFFFF FM-encoded). */ -void d86f_write_find_address_mark_fm(int drive, int side, find_t *find) +void +d86f_write_find_address_mark_fm(int drive, int side, find_t *find) { - d86f_get_bit(drive, side); + d86f_t *dev = d86f[drive]; - if (d86f[drive].last_word[side] & 1) - { - find->sync_marks++; - if (find->sync_marks == 352) - { - d86f[drive].calc_crc.word = 0xFFFF; - d86f[drive].preceding_bit[side] = 1; - find->sync_marks = 0; - d86f[drive].state++; - return; - } + d86f_get_bit(drive, side); + + if (dev->last_word[side] & 1) { + find->sync_marks++; + if (find->sync_marks == 352) { + dev->calc_crc.word = 0xFFFF; + dev->preceding_bit[side] = 1; + find->sync_marks = 0; + dev->state++; + return; } + } - /* If we hadn't found enough set bits but have found a clear bit, null the counter of set bits. */ - if (!(d86f[drive].last_word[side] & 1)) - { + /* If we hadn't found enough set bits but have found a clear bit, null the counter of set bits. */ + if (!(dev->last_word[side] & 1)) { + find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; + find->sync_pos = 0xFFFFFFFF; + } +} + + +void +d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_am, uint16_t other_am, uint16_t ignore_other_am) +{ + d86f_t *dev = d86f[drive]; + + d86f_get_bit(drive, side); + + if (dev->last_word[side] == 0x4489) { + find->sync_marks++; + find->sync_pos = dev->track_pos; + return; + } + + if ((dev->last_word[side] == req_am) && (find->sync_marks >= 3)) { + if (d86f_word_is_aligned(drive, side, find->sync_pos)) { + dev->calc_crc.word = 0xCDB4; + fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc)); + find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; + find->sync_pos = 0xFFFFFFFF; + dev->preceding_bit[side] = dev->last_word[side] & 1; + dev->state++; + return; + } + } + + if ((ignore_other_am & 2) && (dev->last_word[side] == other_am) && (find->sync_marks >= 3)) { + if (d86f_word_is_aligned(drive, side, find->sync_pos)) { + dev->calc_crc.word = 0xCDB4; + fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc)); + find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; + find->sync_pos = 0xFFFFFFFF; + if (ignore_other_am & 1) { + /* Skip mode, let's go back to finding ID. */ + dev->state -= 2; + } else { + /* Not skip mode, process the sector anyway. */ + fdc_set_wrong_am(d86f_fdc); + dev->preceding_bit[side] = dev->last_word[side] & 1; + dev->state++; + } + return; + } + } + + if (dev->last_word[side] != 0x4489) { + if (d86f_word_is_aligned(drive, side, find->sync_pos)) { find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; find->sync_pos = 0xFFFFFFFF; } + } } -void d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_am, uint16_t other_am, uint16_t ignore_other_am) -{ - d86f_get_bit(drive, side); - - if (d86f[drive].last_word[side] == 0x4489) - { - find->sync_marks++; - find->sync_pos = d86f[drive].track_pos; - - return; - } - - if ((d86f[drive].last_word[side] == req_am) && (find->sync_marks >= 3)) - { - if (d86f_word_is_aligned(drive, side, find->sync_pos)) - { - d86f[drive].calc_crc.word = 0xCDB4; - fdd_calccrc(decodefm(drive, d86f[drive].last_word[side]), &(d86f[drive].calc_crc)); - find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; - find->sync_pos = 0xFFFFFFFF; - d86f[drive].preceding_bit[side] = d86f[drive].last_word[side] & 1; - d86f[drive].state++; - return; - } - } - - if ((ignore_other_am & 2) && (d86f[drive].last_word[side] == other_am) && (find->sync_marks >= 3)) - { - if (d86f_word_is_aligned(drive, side, find->sync_pos)) - { - d86f[drive].calc_crc.word = 0xCDB4; - fdd_calccrc(decodefm(drive, d86f[drive].last_word[side]), &(d86f[drive].calc_crc)); - find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; - find->sync_pos = 0xFFFFFFFF; - if (ignore_other_am & 1) - { - /* Skip mode, let's go back to finding ID. */ - d86f[drive].state -= 2; - } - else - { - /* Not skip mode, process the sector anyway. */ - fdc_set_wrong_am(d86f_fdc); - d86f[drive].preceding_bit[side] = d86f[drive].last_word[side] & 1; - d86f[drive].state++; - } - return; - } - } - - if (d86f[drive].last_word[side] != 0x4489) - { - if (d86f_word_is_aligned(drive, side, find->sync_pos)) - { - find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; - find->sync_pos = 0xFFFFFFFF; - } - } -} /* When writing in MFM mode, we find the beginning of the address mark by looking for 3 0xA1 sync bytes. */ -void d86f_write_find_address_mark_mfm(int drive, int side, find_t *find) +void +d86f_write_find_address_mark_mfm(int drive, int side, find_t *find) { - d86f_get_bit(drive, side); + d86f_t *dev = d86f[drive]; - if (d86f[drive].last_word[side] == 0x4489) - { - find->sync_marks++; - find->sync_pos = d86f[drive].track_pos; - if (find->sync_marks == 3) - { - d86f[drive].calc_crc.word = 0xCDB4; - d86f[drive].preceding_bit[side] = 1; - find->sync_marks = 0; - d86f[drive].state++; + d86f_get_bit(drive, side); + + if (dev->last_word[side] == 0x4489) { + find->sync_marks++; + find->sync_pos = dev->track_pos; + if (find->sync_marks == 3) { + dev->calc_crc.word = 0xCDB4; + dev->preceding_bit[side] = 1; + find->sync_marks = 0; + dev->state++; + return; + } + } + + /* If we hadn't found enough address mark sync marks, null the counter. */ + if (dev->last_word[side] != 0x4489) { + if (d86f_word_is_aligned(drive, side, find->sync_pos)) { + find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; + find->sync_pos = 0xFFFFFFFF; + } + } +} + + +/* State 2: Read sector ID and CRC*/ +void +d86f_read_sector_id(int drive, int side, int match) +{ + d86f_t *dev = d86f[drive]; + + if (dev->id_find.bits_obtained) { + if (! (dev->id_find.bits_obtained & 15)) { + /* We've got a byte. */ + if (dev->id_find.bytes_obtained < 4) { + dev->last_sector.byte_array[dev->id_find.bytes_obtained] = decodefm(drive, dev->last_word[side]); + fdd_calccrc(dev->last_sector.byte_array[dev->id_find.bytes_obtained], &(dev->calc_crc)); + } else if ((dev->id_find.bytes_obtained >= 4) && (dev->id_find.bytes_obtained < 6)) { + dev->track_crc.bytes[(dev->id_find.bytes_obtained & 1) ^ 1] = decodefm(drive, dev->last_word[side]); + } + dev->id_find.bytes_obtained++; + + if (dev->id_find.bytes_obtained == 6) { + /* We've got the ID. */ + if (dev->calc_crc.word != dev->track_crc.word) { + dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = 0; + d86f_log("86F: ID CRC error: %04X != %04X (%08X)\n", dev->track_crc.word, dev->calc_crc.word, dev->last_sector.dword); + if ((dev->state != STATE_02_READ_ID) && (dev->state != STATE_0A_READ_ID)) { + dev->error_condition = 0; + dev->state = STATE_IDLE; + fdc_finishread(d86f_fdc); + fdc_headercrcerror(d86f_fdc); + } else if (dev->state == STATE_0A_READ_ID) { + dev->state--; + } else { + dev->error_condition |= 1; /* Mark that there was an ID CRC error. */ + dev->state++; + } + } else if ((dev->calc_crc.word == dev->track_crc.word) && (dev->state == STATE_0A_READ_ID)) { + /* CRC is valid and this is a read sector ID command. */ + dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = dev->error_condition = 0; + fdc_sectorid(d86f_fdc, dev->last_sector.id.c, dev->last_sector.id.h, dev->last_sector.id.r, dev->last_sector.id.n, 0, 0); + dev->state = STATE_IDLE; + } else { + /* CRC is valid. */ + dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = 0; + dev->id_found++; + if ((dev->last_sector.dword == dev->req_sector.dword) || !match) { + d86f_handler[drive].set_sector(drive, side, dev->last_sector.id.c, dev->last_sector.id.h, dev->last_sector.id.r, dev->last_sector.id.n); + if (dev->state == STATE_02_READ_ID) { + /* READ TRACK command, we need some special handling here. */ + /* Code corrected: Only the C, H, and N portions of the sector ID are compared, the R portion (the sector number) is ignored. */ + if ((dev->last_sector.id.c != fdc_get_read_track_sector(d86f_fdc).id.c) || (dev->last_sector.id.h != fdc_get_read_track_sector(d86f_fdc).id.h) || (dev->last_sector.id.n != fdc_get_read_track_sector(d86f_fdc).id.n)) { + dev->error_condition |= 4; /* Mark that the sector ID is not the one expected by the FDC. */ + /* Make sure we use the sector size from the FDC. */ + dev->last_sector.id.n = fdc_get_read_track_sector(d86f_fdc).id.n; + } + + /* If the two ID's are identical, then we do not need to do anything regarding the sector size. */ + } + dev->state++; + } else { + if (dev->last_sector.id.c != dev->req_sector.id.c) { + if (dev->last_sector.id.c == 0xFF) { + dev->error_condition |= 8; + } else { + dev->error_condition |= 0x10; + } + } + + dev->state--; + } + } + } + } + } + + d86f_get_bit(drive, side); + + dev->id_find.bits_obtained++; +} + + +uint8_t +d86f_get_data(int drive, int base) +{ + d86f_t *dev = d86f[drive]; + int data; + + if (dev->data_find.bytes_obtained < (d86f_get_data_len(drive) + base)) { + data = fdc_getdata(d86f_fdc, dev->data_find.bytes_obtained == (d86f_get_data_len(drive) + base - 1)); + if ((data & DMA_OVER) || (data == -1)) { + dev->dma_over++; + if (data == -1) + data = 0; + else + data &= 0xff; + } + } else { + data = 0; + } + + return data; +} + + +void +d86f_compare_byte(int drive, uint8_t received_byte, uint8_t disk_byte) +{ + d86f_t *dev = d86f[drive]; + + switch(fdc_get_compare_condition(d86f_fdc)) { + case 0: /* SCAN EQUAL */ + if ((received_byte == disk_byte) || (received_byte == 0xFF)) + dev->satisfying_bytes++; + break; + + case 1: /* SCAN LOW OR EQUAL */ + if ((received_byte <= disk_byte) || (received_byte == 0xFF)) + dev->satisfying_bytes++; + break; + + case 2: /* SCAN HIGH OR EQUAL */ + if ((received_byte >= disk_byte) || (received_byte == 0xFF)) + dev->satisfying_bytes++; + break; + } +} + + +/* State 4: Read sector data and CRC*/ +void +d86f_read_sector_data(int drive, int side) +{ + d86f_t *dev = d86f[drive]; + int data = 0; + int recv_data = 0; + int read_status = 0; + uint32_t sector_len = dev->last_sector.id.n; + uint32_t crc_pos = 0; + sector_len = 1 << (7 + sector_len); + crc_pos = sector_len + 2; + + if (dev->data_find.bits_obtained) { + if (!(dev->data_find.bits_obtained & 15)) { + /* We've got a byte. */ + if (dev->data_find.bytes_obtained < sector_len) { + data = decodefm(drive, dev->last_word[side]); + if (dev->state == STATE_11_SCAN_DATA) { + /* Scan/compare command. */ + recv_data = d86f_get_data(drive, 0); + d86f_compare_byte(drive, recv_data, data); + } else { + if (dev->data_find.bytes_obtained < d86f_get_data_len(drive)) { + if (dev->state != STATE_16_VERIFY_DATA) { + read_status = fdc_data(d86f_fdc, data); + if (read_status == -1) { + dev->dma_over++; + } + } + } + } + fdd_calccrc(data, &(dev->calc_crc)); + } else if (dev->data_find.bytes_obtained < crc_pos) { + dev->track_crc.bytes[(dev->data_find.bytes_obtained - sector_len) ^ 1] = decodefm(drive, dev->last_word[side]); + } + dev->data_find.bytes_obtained++; + + if (dev->data_find.bytes_obtained == (crc_pos + fdc_get_gap(d86f_fdc))) { + /* We've got the data. */ + if (dev->dma_over > 1) { + dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; + dev->error_condition = 0; + dev->state = STATE_IDLE; + fdc_finishread(d86f_fdc); + fdc_overrun(d86f_fdc); + + d86f_get_bit(drive, side); + + dev->data_find.bits_obtained++; + return; + } + + if ((dev->calc_crc.word != dev->track_crc.word) && (dev->state != STATE_02_READ_DATA)) { + d86f_log("86F: Data CRC error: %04X != %04X (%08X)\n", dev->track_crc.word, dev->calc_crc.word, dev->last_sector.dword); + dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; + dev->error_condition = 0; + dev->state = STATE_IDLE; + fdc_finishread(d86f_fdc); + fdc_datacrcerror(d86f_fdc); + } else if ((dev->calc_crc.word != dev->track_crc.word) && (dev->state == STATE_02_READ_DATA)) { + dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; + dev->error_condition |= 2; /* Mark that there was a data error. */ + dev->state = STATE_IDLE; + fdc_track_finishread(d86f_fdc, dev->error_condition); + } else { + /* CRC is valid. */ + dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; + dev->error_condition = 0; + if (dev->state == STATE_11_SCAN_DATA) { + dev->state = STATE_IDLE; + fdc_sector_finishcompare(d86f_fdc, (dev->satisfying_bytes == ((128 << ((uint32_t) dev->last_sector.id.n)) - 1)) ? 1 : 0); + } else { + dev->state = STATE_IDLE; + fdc_sector_finishread(d86f_fdc); + } + } + } + } + } + + d86f_get_bit(drive, side); + + dev->data_find.bits_obtained++; +} + + +void +d86f_write_sector_data(int drive, int side, int mfm, uint16_t am) +{ + d86f_t *dev = d86f[drive]; + uint16_t bit_pos; + uint16_t temp; + uint32_t sector_len = dev->last_sector.id.n; + uint32_t crc_pos = 0; + sector_len = (1 << (7 + sector_len)) + 1; + crc_pos = sector_len + 2; + + if (! (dev->data_find.bits_obtained & 15)) { + if (dev->data_find.bytes_obtained < crc_pos) { + if (! dev->data_find.bytes_obtained) { + /* We're writing the address mark. */ + dev->current_byte[side] = am; + } else if (dev->data_find.bytes_obtained < sector_len) { + /* We're in the data field of the sector, read byte from FDC and request new byte. */ + dev->current_byte[side] = d86f_get_data(drive, 1); + if (! fdc_get_diswr(d86f_fdc)) + d86f_handler[drive].write_data(drive, side, dev->data_find.bytes_obtained - 1, dev->current_byte[side]); + } else { + /* We're in the data field of the sector, use a CRC byte. */ + dev->current_byte[side] = dev->calc_crc.bytes[(dev->data_find.bytes_obtained & 1)]; + } + + dev->current_bit[side] = (15 - (dev->data_find.bits_obtained & 15)) >> 1; + + /* Write the bit. */ + temp = (dev->current_byte[side] >> dev->current_bit[side]) & 1; + if ((!temp && !dev->preceding_bit[side]) || !mfm) { + temp |= 2; + } + + /* This is an even bit, so write the clock. */ + if (! dev->data_find.bytes_obtained) { + /* Address mark, write bit directly. */ + d86f_put_bit(drive, side, am >> 15); + } else { + d86f_put_bit(drive, side, temp >> 1); + } + + if (dev->data_find.bytes_obtained < sector_len) { + /* This is a data byte, so CRC it. */ + if (! dev->data_find.bytes_obtained) { + fdd_calccrc(decodefm(drive, am), &(dev->calc_crc)); + } else { + fdd_calccrc(dev->current_byte[side], &(dev->calc_crc)); + } + } + } + } else { + if (dev->data_find.bytes_obtained < crc_pos) { + /* Encode the bit. */ + bit_pos = 15 - (dev->data_find.bits_obtained & 15); + dev->current_bit[side] = bit_pos >> 1; + + temp = (dev->current_byte[side] >> dev->current_bit[side]) & 1; + if ((!temp && !dev->preceding_bit[side]) || !mfm) { + temp |= 2; + } + + if (! dev->data_find.bytes_obtained) { + /* Address mark, write directly. */ + d86f_put_bit(drive, side, am >> bit_pos); + if (! (bit_pos & 1)) { + dev->preceding_bit[side] = am >> bit_pos; + } + } else { + if (bit_pos & 1) { + /* Clock bit */ + d86f_put_bit(drive, side, temp >> 1); + } else { + /* Data bit */ + d86f_put_bit(drive, side, temp & 1); + dev->preceding_bit[side] = temp & 1; + } + } + } + + if ((dev->data_find.bits_obtained & 15) == 15) { + dev->data_find.bytes_obtained++; + + if (dev->data_find.bytes_obtained == (crc_pos + fdc_get_gap(d86f_fdc))) { + if (dev->dma_over > 1) { + dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; + dev->error_condition = 0; + dev->state = STATE_IDLE; + fdc_finishread(d86f_fdc); + fdc_overrun(d86f_fdc); + + dev->data_find.bits_obtained++; + return; + } + + /* We've written the data. */ + dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; + dev->error_condition = 0; + dev->state = STATE_IDLE; + d86f_handler[drive].writeback(drive); + fdc_sector_finishread(d86f_fdc); return; } } + } - /* If we hadn't found enough address mark sync marks, null the counter. */ - if (d86f[drive].last_word[side] != 0x4489) - { - if (d86f_word_is_aligned(drive, side, find->sync_pos)) - { - find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; - find->sync_pos = 0xFFFFFFFF; - } - } + dev->data_find.bits_obtained++; } -/* State 2: Read sector ID and CRC*/ -void d86f_read_sector_id(int drive, int side, int match) -{ - if (d86f[drive].id_find.bits_obtained) - { - if (!(d86f[drive].id_find.bits_obtained & 15)) - { - /* We've got a byte. */ - if (d86f[drive].id_find.bytes_obtained < 4) - { - d86f[drive].last_sector.byte_array[d86f[drive].id_find.bytes_obtained] = decodefm(drive, d86f[drive].last_word[side]); - fdd_calccrc(d86f[drive].last_sector.byte_array[d86f[drive].id_find.bytes_obtained], &(d86f[drive].calc_crc)); - } - else if ((d86f[drive].id_find.bytes_obtained >= 4) && (d86f[drive].id_find.bytes_obtained < 6)) - { - d86f[drive].track_crc.bytes[(d86f[drive].id_find.bytes_obtained & 1) ^ 1] = decodefm(drive, d86f[drive].last_word[side]); - } - d86f[drive].id_find.bytes_obtained++; - - if (d86f[drive].id_find.bytes_obtained == 6) - { - /* We've got the ID. */ - if (d86f[drive].calc_crc.word != d86f[drive].track_crc.word) - { - d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = 0; - d86f_log("86F: ID CRC error: %04X != %04X (%08X)\n", d86f[drive].track_crc.word, d86f[drive].calc_crc.word, d86f[drive].last_sector.dword); - if ((d86f[drive].state != STATE_02_READ_ID) && (d86f[drive].state != STATE_0A_READ_ID)) - { - d86f[drive].error_condition = 0; - d86f[drive].state = STATE_IDLE; - fdc_finishread(d86f_fdc); - fdc_headercrcerror(d86f_fdc); - } - else if (d86f[drive].state == STATE_0A_READ_ID) - { - d86f[drive].state--; - } - else - { - d86f[drive].error_condition |= 1; /* Mark that there was an ID CRC error. */ - d86f[drive].state++; - } - } - else if ((d86f[drive].calc_crc.word == d86f[drive].track_crc.word) && (d86f[drive].state == STATE_0A_READ_ID)) - { - /* CRC is valid and this is a read sector ID command. */ - d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = d86f[drive].error_condition = 0; - fdc_sectorid(d86f_fdc, d86f[drive].last_sector.id.c, d86f[drive].last_sector.id.h, d86f[drive].last_sector.id.r, d86f[drive].last_sector.id.n, 0, 0); - d86f[drive].state = STATE_IDLE; - } - else - { - /* CRC is valid. */ - d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = 0; - d86f[drive].id_found++; - if ((d86f[drive].last_sector.dword == d86f[drive].req_sector.dword) || !match) - { - d86f_handler[drive].set_sector(drive, side, d86f[drive].last_sector.id.c, d86f[drive].last_sector.id.h, d86f[drive].last_sector.id.r, d86f[drive].last_sector.id.n); - if (d86f[drive].state == STATE_02_READ_ID) - { - /* READ TRACK command, we need some special handling here. */ - /* Code corrected: Only the C, H, and N portions of the sector ID are compared, the R portion (the sector number) is ignored. */ - if ((d86f[drive].last_sector.id.c != fdc_get_read_track_sector(d86f_fdc).id.c) || (d86f[drive].last_sector.id.h != fdc_get_read_track_sector(d86f_fdc).id.h) || (d86f[drive].last_sector.id.n != fdc_get_read_track_sector(d86f_fdc).id.n)) - { - d86f[drive].error_condition |= 4; /* Mark that the sector ID is not the one expected by the FDC. */ - /* Make sure we use the sector size from the FDC. */ - d86f[drive].last_sector.id.n = fdc_get_read_track_sector(d86f_fdc).id.n; - } - /* If the two ID's are identical, then we do not need to do anything regarding the sector size. */ - } - d86f[drive].state++; - } - else - { - if (d86f[drive].last_sector.id.c != d86f[drive].req_sector.id.c) - { - if (d86f[drive].last_sector.id.c == 0xFF) - { - d86f[drive].error_condition |= 8; - } - else - { - d86f[drive].error_condition |= 0x10; - } - } - - d86f[drive].state--; - } - } - } - } - } - - d86f_get_bit(drive, side); - - d86f[drive].id_find.bits_obtained++; -} - -uint8_t d86f_get_data(int drive, int base) -{ - int data; - - if (d86f[drive].data_find.bytes_obtained < (d86f_get_data_len(drive) + base)) - { - data = fdc_getdata(d86f_fdc, d86f[drive].data_find.bytes_obtained == (d86f_get_data_len(drive) + base - 1)); - if ((data & DMA_OVER) || (data == -1)) - { - d86f[drive].dma_over++; - if (data == -1) - { - data = 0; - } - else - { - data &= 0xff; - } - } - } - else - { - data = 0; - } - - return data; -} - -void d86f_compare_byte(int drive, uint8_t received_byte, uint8_t disk_byte) -{ - switch(fdc_get_compare_condition(d86f_fdc)) - { - case 0: /* SCAN EQUAL */ - if ((received_byte == disk_byte) || (received_byte == 0xFF)) - { - d86f[drive].satisfying_bytes++; - } - break; - case 1: /* SCAN LOW OR EQUAL */ - if ((received_byte <= disk_byte) || (received_byte == 0xFF)) - { - d86f[drive].satisfying_bytes++; - } - break; - case 2: /* SCAN HIGH OR EQUAL */ - if ((received_byte >= disk_byte) || (received_byte == 0xFF)) - { - d86f[drive].satisfying_bytes++; - } - break; - } -} - -/* State 4: Read sector data and CRC*/ -void d86f_read_sector_data(int drive, int side) -{ - int data = 0; - int recv_data = 0; - int read_status = 0; - uint32_t sector_len = d86f[drive].last_sector.id.n; - uint32_t crc_pos = 0; - sector_len = 1 << (7 + sector_len); - crc_pos = sector_len + 2; - - if (d86f[drive].data_find.bits_obtained) - { - if (!(d86f[drive].data_find.bits_obtained & 15)) - { - /* We've got a byte. */ - if (d86f[drive].data_find.bytes_obtained < sector_len) - { - data = decodefm(drive, d86f[drive].last_word[side]); - if (d86f[drive].state == STATE_11_SCAN_DATA) - { - /* Scan/compare command. */ - recv_data = d86f_get_data(drive, 0); - d86f_compare_byte(drive, recv_data, data); - } - else - { - if (d86f[drive].data_find.bytes_obtained < d86f_get_data_len(drive)) - { - if (d86f[drive].state != STATE_16_VERIFY_DATA) - { - read_status = fdc_data(d86f_fdc, data); - if (read_status == -1) - { - d86f[drive].dma_over++; - } - } - } - } - fdd_calccrc(data, &(d86f[drive].calc_crc)); - } - else if (d86f[drive].data_find.bytes_obtained < crc_pos) - { - d86f[drive].track_crc.bytes[(d86f[drive].data_find.bytes_obtained - sector_len) ^ 1] = decodefm(drive, d86f[drive].last_word[side]); - } - d86f[drive].data_find.bytes_obtained++; - - if (d86f[drive].data_find.bytes_obtained == (crc_pos + fdc_get_gap(d86f_fdc))) - { - /* We've got the data. */ - if (d86f[drive].dma_over > 1) - { - d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; - d86f[drive].error_condition = 0; - d86f[drive].state = STATE_IDLE; - fdc_finishread(d86f_fdc); - fdc_overrun(d86f_fdc); - - d86f_get_bit(drive, side); - - d86f[drive].data_find.bits_obtained++; - return; - } - - if ((d86f[drive].calc_crc.word != d86f[drive].track_crc.word) && (d86f[drive].state != STATE_02_READ_DATA)) - { - d86f_log("86F: Data CRC error: %04X != %04X (%08X)\n", d86f[drive].track_crc.word, d86f[drive].calc_crc.word, d86f[drive].last_sector.dword); - d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; - d86f[drive].error_condition = 0; - d86f[drive].state = STATE_IDLE; - fdc_finishread(d86f_fdc); - fdc_datacrcerror(d86f_fdc); - } - else if ((d86f[drive].calc_crc.word != d86f[drive].track_crc.word) && (d86f[drive].state == STATE_02_READ_DATA)) - { - d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; - d86f[drive].error_condition |= 2; /* Mark that there was a data error. */ - d86f[drive].state = STATE_IDLE; - fdc_track_finishread(d86f_fdc, d86f[drive].error_condition); - } - else - { - /* CRC is valid. */ - d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; - d86f[drive].error_condition = 0; - if (d86f[drive].state == STATE_11_SCAN_DATA) - { - d86f[drive].state = STATE_IDLE; - fdc_sector_finishcompare(d86f_fdc, (d86f[drive].satisfying_bytes == ((128 << ((uint32_t) d86f[drive].last_sector.id.n)) - 1)) ? 1 : 0); - } - else - { - d86f[drive].state = STATE_IDLE; - fdc_sector_finishread(d86f_fdc); - } - } - } - } - } - - d86f_get_bit(drive, side); - - d86f[drive].data_find.bits_obtained++; -} - -void d86f_write_sector_data(int drive, int side, int mfm, uint16_t am) -{ - uint16_t bit_pos; - uint16_t temp; - uint32_t sector_len = d86f[drive].last_sector.id.n; - uint32_t crc_pos = 0; - sector_len = (1 << (7 + sector_len)) + 1; - crc_pos = sector_len + 2; - - if (!(d86f[drive].data_find.bits_obtained & 15)) - { - if (d86f[drive].data_find.bytes_obtained < crc_pos) - { - if (!d86f[drive].data_find.bytes_obtained) - { - /* We're writing the address mark. */ - d86f[drive].current_byte[side] = am; - } - else if (d86f[drive].data_find.bytes_obtained < sector_len) - { - /* We're in the data field of the sector, read byte from FDC and request new byte. */ - d86f[drive].current_byte[side] = d86f_get_data(drive, 1); - if (!fdc_get_diswr(d86f_fdc)) - d86f_handler[drive].write_data(drive, side, d86f[drive].data_find.bytes_obtained - 1, d86f[drive].current_byte[side]); - } - else - { - /* We're in the data field of the sector, use a CRC byte. */ - d86f[drive].current_byte[side] = d86f[drive].calc_crc.bytes[(d86f[drive].data_find.bytes_obtained & 1)]; - } - - d86f[drive].current_bit[side] = (15 - (d86f[drive].data_find.bits_obtained & 15)) >> 1; - - /* Write the bit. */ - temp = (d86f[drive].current_byte[side] >> d86f[drive].current_bit[side]) & 1; - if ((!temp && !d86f[drive].preceding_bit[side]) || !mfm) - { - temp |= 2; - } - - /* This is an even bit, so write the clock. */ - if (!d86f[drive].data_find.bytes_obtained) - { - /* Address mark, write bit directly. */ - d86f_put_bit(drive, side, am >> 15); - } - else - { - d86f_put_bit(drive, side, temp >> 1); - } - - if (d86f[drive].data_find.bytes_obtained < sector_len) - { - /* This is a data byte, so CRC it. */ - if (!d86f[drive].data_find.bytes_obtained) - { - fdd_calccrc(decodefm(drive, am), &(d86f[drive].calc_crc)); - } - else - { - fdd_calccrc(d86f[drive].current_byte[side], &(d86f[drive].calc_crc)); - } - } - } - } - else - { - if (d86f[drive].data_find.bytes_obtained < crc_pos) - { - /* Encode the bit. */ - bit_pos = 15 - (d86f[drive].data_find.bits_obtained & 15); - d86f[drive].current_bit[side] = bit_pos >> 1; - - temp = (d86f[drive].current_byte[side] >> d86f[drive].current_bit[side]) & 1; - if ((!temp && !d86f[drive].preceding_bit[side]) || !mfm) - { - temp |= 2; - } - - if (!d86f[drive].data_find.bytes_obtained) - { - /* Address mark, write directly. */ - d86f_put_bit(drive, side, am >> bit_pos); - if (!(bit_pos & 1)) - { - d86f[drive].preceding_bit[side] = am >> bit_pos; - } - } - else - { - if (bit_pos & 1) - { - /* Clock bit */ - d86f_put_bit(drive, side, temp >> 1); - } - else - { - /* Data bit */ - d86f_put_bit(drive, side, temp & 1); - d86f[drive].preceding_bit[side] = temp & 1; - } - } - } - - if ((d86f[drive].data_find.bits_obtained & 15) == 15) - { - d86f[drive].data_find.bytes_obtained++; - - if (d86f[drive].data_find.bytes_obtained == (crc_pos + fdc_get_gap(d86f_fdc))) - { - if (d86f[drive].dma_over > 1) - { - d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; - d86f[drive].error_condition = 0; - d86f[drive].state = STATE_IDLE; - fdc_finishread(d86f_fdc); - fdc_overrun(d86f_fdc); - - d86f[drive].data_find.bits_obtained++; - return; - } - - /* We've written the data. */ - d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; - d86f[drive].error_condition = 0; - d86f[drive].state = STATE_IDLE; - d86f_handler[drive].writeback(drive); - fdc_sector_finishread(d86f_fdc); - return; - } - } - } - - d86f[drive].data_find.bits_obtained++; -} void d86f_advance_bit(int drive, int side) { - d86f[drive].track_pos++; - d86f[drive].track_pos %= d86f_handler[drive].get_raw_size(drive, side); + d86f_t *dev = d86f[drive]; - if (d86f[drive].track_pos == d86f_handler[drive].index_hole_pos(drive, side)) - { - d86f_handler[drive].read_revolution(drive); + dev->track_pos++; + dev->track_pos %= d86f_handler[drive].get_raw_size(drive, side); - if (d86f[drive].state != STATE_IDLE) - { - d86f[drive].index_count++; + if (dev->track_pos == d86f_handler[drive].index_hole_pos(drive, side)) { + d86f_handler[drive].read_revolution(drive); + + if (dev->state != STATE_IDLE) + dev->index_count++; + } +} + + +void +d86f_advance_word(int drive, int side) +{ + d86f_t *dev = d86f[drive]; + + dev->track_pos += 16; + dev->track_pos %= d86f_handler[drive].get_raw_size(drive, side); + + if ((dev->track_pos == d86f_handler[drive].index_hole_pos(drive, side)) && (dev->state != STATE_IDLE)) + dev->index_count++; +} + + +void +d86f_spin_to_index(int drive, int side) +{ + d86f_t *dev = d86f[drive]; + + d86f_get_bit(drive, side); + d86f_get_bit(drive, side ^ 1); + + d86f_advance_bit(drive, side); + + if (dev->track_pos == d86f_handler[drive].index_hole_pos(drive, side)) { + if ((dev->state == STATE_0D_SPIN_TO_INDEX) || (dev->state == STATE_0D_NOP_SPIN_TO_INDEX)) { + /* When starting format, reset format state to the beginning. */ + dev->preceding_bit[side] = 1; + dev->format_state = FMT_PRETRK_GAP0; + } + + /* This is to make sure both READ TRACK and FORMAT TRACK command don't end prematurely. */ + dev->index_count = 0; + dev->state++; + } +} + + +void +d86f_write_direct_common(int drive, int side, uint16_t byte, uint8_t type, uint32_t pos) +{ + d86f_t *dev = d86f[drive]; + uint16_t encoded_byte = 0, mask_data, mask_surface, mask_hole, mask_fuzzy; + decoded_t dbyte, dpbyte; + + if (fdc_get_diswr(d86f_fdc)) return; + + dbyte.byte = byte & 0xff; + dpbyte.byte = dev->preceding_bit[side] & 0xff; + + if (type == 0) { + /* Byte write. */ + encoded_byte = d86f_encode_byte(drive, 0, dbyte, dpbyte); + if (! d86f_reverse_bytes(drive)) { + mask_data = encoded_byte >> 8; + encoded_byte &= 0xFF; + encoded_byte <<= 8; + encoded_byte |= mask_data; + } + } else { + /* Word write. */ + encoded_byte = byte; + if (d86f_reverse_bytes(drive)) { + mask_data = encoded_byte >> 8; + encoded_byte &= 0xFF; + encoded_byte <<= 8; + encoded_byte |= mask_data; + } + } + + dev->preceding_bit[side] = encoded_byte & 1; + + if (d86f_has_surface_desc(drive)) { + mask_data = dev->track_encoded_data[side][pos] ^= 0xFFFF; + mask_surface = dev->track_surface_data[side][pos]; + mask_hole = (mask_surface & mask_data) ^ 0xFFFF; /* This will retain bits that are both fuzzy and 0, therefore physical holes. */ + encoded_byte &= mask_hole; /* Filter out physical hole bits from the encoded data. */ + mask_data ^= 0xFFFF; /* Invert back so bits 1 are 1 again. */ + mask_fuzzy = (mask_surface & mask_data) ^ 0xFFFF; /* All fuzzy bits are 0. */ + dev->track_surface_data[side][pos] &= mask_fuzzy; /* Remove fuzzy bits (but not hole bits) from the surface mask, making them regular again. */ + } + + dev->track_encoded_data[side][pos] = encoded_byte; + dev->last_word[side] = encoded_byte; +} + + +void +d86f_write_direct(int drive, int side, uint16_t byte, uint8_t type) +{ + d86f_t *dev = d86f[drive]; + + d86f_write_direct_common(drive, side, byte, type, dev->track_pos >> 4); +} + + +uint16_t +endian_swap(uint16_t word) +{ + uint16_t temp; + + temp = word & 0xff; + temp <<= 8; + temp |= (word >> 8); + + return temp; +} + + +void +d86f_format_finish(int drive, int side, int mfm, uint16_t sc, uint16_t gap_fill, int do_write) +{ + d86f_t *dev = d86f[drive]; + + if (mfm && do_write) { + if (do_write && (dev->track_pos == d86f_handler[drive].index_hole_pos(drive, side))) { + d86f_write_direct_common(drive, side, gap_fill, 0, 0); + } + } + + dev->state = STATE_IDLE; + + if (do_write) + d86f_handler[drive].writeback(drive); + + dev->error_condition = 0; + dev->datac = 0; + fdc_sector_finishread(d86f_fdc); +} + + +void +d86f_format_turbo_finish(int drive, int side, int do_write) +{ + d86f_t *dev = d86f[drive]; + + dev->state = STATE_IDLE; + + if (do_write) + d86f_handler[drive].writeback(drive); + + dev->error_condition = 0; + dev->datac = 0; + fdc_sector_finishread(d86f_fdc); +} + + +void +d86f_format_track(int drive, int side, int do_write) +{ + d86f_t *dev = d86f[drive]; + int data; + uint16_t max_len; + + int mfm; + uint16_t sc = 0; + uint16_t dtl = 0; + int gap_sizes[4] = { 0, 0, 0, 0 }; + int am_len = 0; + int sync_len = 0; + uint16_t iam_mfm[4] = { 0x2452, 0x2452, 0x2452, 0x5255 }; + uint16_t idam_mfm[4] = { 0x8944, 0x8944, 0x8944, 0x5455 }; + uint16_t dataam_mfm[4] = { 0x8944, 0x8944, 0x8944, 0x4555 }; + uint16_t iam_fm = 0xFAF7; + uint16_t idam_fm = 0x7EF5; + uint16_t dataam_fm = 0x6FF5; + uint16_t gap_fill = 0x4E; + + mfm = d86f_is_mfm(drive); + am_len = mfm ? 4 : 1; + gap_sizes[0] = mfm ? 80 : 40; + gap_sizes[1] = mfm ? 50 : 26; + gap_sizes[2] = fdc_get_gap2(d86f_fdc, real_drive(d86f_fdc, drive)); + gap_sizes[3] = fdc_get_gap(d86f_fdc); + sync_len = mfm ? 12 : 6; + sc = fdc_get_format_sectors(d86f_fdc); + dtl = 128 << fdc_get_format_n(d86f_fdc); + gap_fill = mfm ? 0x4E : 0xFF; + + switch(dev->format_state) { + case FMT_POSTTRK_GAP4: + max_len = 60000; + if (do_write) + d86f_write_direct(drive, side, gap_fill, 0); + break; + + case FMT_PRETRK_GAP0: + max_len = gap_sizes[0]; + if (do_write) + d86f_write_direct(drive, side, gap_fill, 0); + break; + + case FMT_SECTOR_ID_SYNC: + max_len = sync_len; + if (dev->datac <= 3) { + data = fdc_getdata(d86f_fdc, 0); + if (data != -1) + data &= 0xff; + if ((data == -1) && (dev->datac < 3)) + data = 0; + dev->format_sector_id.byte_array[dev->datac] = data & 0xff; + if (dev->datac == 3) + fdc_stop_id_request(d86f_fdc); } - } -} + /*FALLTHROUGH*/ -void d86f_advance_word(int drive, int side) -{ - d86f[drive].track_pos += 16; - d86f[drive].track_pos %= d86f_handler[drive].get_raw_size(drive, side); + case FMT_PRETRK_SYNC: + case FMT_SECTOR_DATA_SYNC: + max_len = sync_len; + if (do_write) + d86f_write_direct(drive, side, 0x00, 0); + break; - if ((d86f[drive].track_pos == d86f_handler[drive].index_hole_pos(drive, side)) && (d86f[drive].state != STATE_IDLE)) d86f[drive].index_count++; -} - -void d86f_spin_to_index(int drive, int side) -{ - d86f_get_bit(drive, side); - d86f_get_bit(drive, side ^ 1); - - d86f_advance_bit(drive, side); - - if (d86f[drive].track_pos == d86f_handler[drive].index_hole_pos(drive, side)) - { - if ((d86f[drive].state == STATE_0D_SPIN_TO_INDEX) || (d86f[drive].state == STATE_0D_NOP_SPIN_TO_INDEX)) - { - /* When starting format, reset format state to the beginning. */ - d86f[drive].preceding_bit[side] = 1; - d86f[drive].format_state = FMT_PRETRK_GAP0; + case FMT_PRETRK_IAM: + max_len = am_len; + if (do_write) { + if (mfm) + d86f_write_direct(drive, side, iam_mfm[dev->datac], 1); + else + d86f_write_direct(drive, side, iam_fm, 1); } - /* This is to make sure both READ TRACK and FORMAT TRACK command don't end prematurely. */ - d86f[drive].index_count = 0; - d86f[drive].state++; - } -} + break; -void d86f_write_direct_common(int drive, int side, uint16_t byte, uint8_t type, uint32_t pos) -{ - uint16_t encoded_byte = 0, mask_data, mask_surface, mask_hole, mask_fuzzy; - decoded_t dbyte, dpbyte; + case FMT_PRETRK_GAP1: + max_len = gap_sizes[1]; + if (do_write) + d86f_write_direct(drive, side, gap_fill, 0); + break; - if (fdc_get_diswr(d86f_fdc)) - return; - - dbyte.byte = byte; - dpbyte.byte = d86f[drive].preceding_bit[side]; - - if (type == 0) - { - /* Byte write. */ - encoded_byte = d86f_encode_byte(drive, 0, dbyte, dpbyte); - if (!d86f_reverse_bytes(drive)) - { - mask_data = encoded_byte >> 8; - encoded_byte &= 0xFF; - encoded_byte <<= 8; - encoded_byte |= mask_data; + case FMT_SECTOR_IDAM: + max_len = am_len; + if (mfm) { + if (do_write) + d86f_write_direct(drive, side, idam_mfm[dev->datac], 1); + d86f_calccrc(dev, (dev->datac < 3) ? 0xA1 : 0xFE); + } else { + if (do_write) + d86f_write_direct(drive, side, idam_fm, 1); + d86f_calccrc(dev, 0xFE); } - } - else - { - /* Word write. */ - encoded_byte = byte; - if (d86f_reverse_bytes(drive)) - { - mask_data = encoded_byte >> 8; - encoded_byte &= 0xFF; - encoded_byte <<= 8; - encoded_byte |= mask_data; + break; + + case FMT_SECTOR_ID: + max_len = 4; + if (do_write) { + d86f_write_direct(drive, side, dev->format_sector_id.byte_array[dev->datac], 0); + d86f_calccrc(dev, dev->format_sector_id.byte_array[dev->datac]); + } else { + if (dev->datac == 3) { + d86f_handler[drive].set_sector(drive, side, dev->format_sector_id.id.c, dev->format_sector_id.id.h, dev->format_sector_id.id.r, dev->format_sector_id.id.n); + } } - } + break; - d86f[drive].preceding_bit[side] = encoded_byte & 1; + case FMT_SECTOR_ID_CRC: + case FMT_SECTOR_DATA_CRC: + max_len = 2; + if (do_write) + d86f_write_direct(drive, side, dev->calc_crc.bytes[dev->datac ^ 1], 0); + break; - if (d86f_has_surface_desc(drive)) - { - mask_data = d86f[drive].track_encoded_data[side][pos] ^= 0xFFFF; - mask_surface = d86f[drive].track_surface_data[side][pos]; - mask_hole = (mask_surface & mask_data) ^ 0xFFFF; /* This will retain bits that are both fuzzy and 0, therefore physical holes. */ - encoded_byte &= mask_hole; /* Filter out physical hole bits from the encoded data. */ - mask_data ^= 0xFFFF; /* Invert back so bits 1 are 1 again. */ - mask_fuzzy = (mask_surface & mask_data) ^ 0xFFFF; /* All fuzzy bits are 0. */ - d86f[drive].track_surface_data[side][pos] &= mask_fuzzy; /* Remove fuzzy bits (but not hole bits) from the surface mask, making them regular again. */ - } + case FMT_SECTOR_GAP2: + max_len = gap_sizes[2]; + if (do_write) + d86f_write_direct(drive, side, gap_fill, 0); + break; - d86f[drive].track_encoded_data[side][pos] = encoded_byte; - d86f[drive].last_word[side] = encoded_byte; -} - -void d86f_write_direct(int drive, int side, uint16_t byte, uint8_t type) -{ - d86f_write_direct_common(drive, side, byte, type, d86f[drive].track_pos >> 4); -} - -uint16_t endian_swap(uint16_t word) -{ - uint16_t temp; - - temp = word & 0xff; - temp <<= 8; - temp |= (word >> 8); - return temp; -} - -void d86f_format_finish(int drive, int side, int mfm, uint16_t sc, uint16_t gap_fill, int do_write) -{ - if (mfm && do_write) - { - if (do_write && (d86f[drive].track_pos == d86f_handler[drive].index_hole_pos(drive, side))) - { - d86f_write_direct_common(drive, side, gap_fill, 0, 0); + case FMT_SECTOR_DATAAM: + max_len = am_len; + if (mfm) { + if (do_write) + d86f_write_direct(drive, side, dataam_mfm[dev->datac], 1); + d86f_calccrc(dev, (dev->datac < 3) ? 0xA1 : 0xFB); + } else { + if (do_write) + d86f_write_direct(drive, side, dataam_fm, 1); + d86f_calccrc(dev, 0xFB); } - } + break; - d86f[drive].state = STATE_IDLE; + case FMT_SECTOR_DATA: + max_len = dtl; + if (do_write) { + d86f_write_direct(drive, side, dev->fill, 0); + d86f_handler[drive].write_data(drive, side, dev->datac, dev->fill); + } + d86f_calccrc(dev, dev->fill); + break; - if (do_write) - { - d86f_handler[drive].writeback(drive); - } + case FMT_SECTOR_GAP3: + max_len = gap_sizes[3]; + if (do_write) + d86f_write_direct(drive, side, gap_fill, 0); + break; - d86f[drive].error_condition = 0; - d86f[drive].datac = 0; - fdc_sector_finishread(d86f_fdc); -} + default: + max_len = 0; + break; + } -void d86f_format_turbo_finish(int drive, int side, int do_write) -{ - d86f[drive].state = STATE_IDLE; + dev->datac++; - if (do_write) - { - d86f_handler[drive].writeback(drive); - } + d86f_advance_word(drive, side); - d86f[drive].error_condition = 0; - d86f[drive].datac = 0; - fdc_sector_finishread(d86f_fdc); -} + if ((dev->index_count) && ((dev->format_state < FMT_SECTOR_ID_SYNC) || (dev->format_state > FMT_SECTOR_GAP3))) { + d86f_format_finish(drive, side, mfm, sc, gap_fill, do_write); + return; + } -void d86f_format_track(int drive, int side, int do_write) -{ - int data; - uint16_t max_len; + if (dev->datac >= max_len) { + dev->datac = 0; + dev->format_state++; - int mfm; - uint16_t sc = 0; - uint16_t dtl = 0; - int gap_sizes[4] = { 0, 0, 0, 0 }; - int am_len = 0; - int sync_len = 0; - uint16_t iam_mfm[4] = { 0x2452, 0x2452, 0x2452, 0x5255 }; - uint16_t idam_mfm[4] = { 0x8944, 0x8944, 0x8944, 0x5455 }; - uint16_t dataam_mfm[4] = { 0x8944, 0x8944, 0x8944, 0x4555 }; - uint16_t iam_fm = 0xFAF7; - uint16_t idam_fm = 0x7EF5; - uint16_t dataam_fm = 0x6FF5; - uint16_t gap_fill = 0x4E; - - mfm = d86f_is_mfm(drive); - am_len = mfm ? 4 : 1; - gap_sizes[0] = mfm ? 80 : 40; - gap_sizes[1] = mfm ? 50 : 26; - gap_sizes[2] = fdc_get_gap2(d86f_fdc, real_drive(d86f_fdc, drive)); - gap_sizes[3] = fdc_get_gap(d86f_fdc); - sync_len = mfm ? 12 : 6; - sc = fdc_get_format_sectors(d86f_fdc); - dtl = 128 << fdc_get_format_n(d86f_fdc); - gap_fill = mfm ? 0x4E : 0xFF; - - switch(d86f[drive].format_state) - { - case FMT_POSTTRK_GAP4: - max_len = 60000; - if (do_write) d86f_write_direct(drive, side, gap_fill, 0); - break; - case FMT_PRETRK_GAP0: - max_len = gap_sizes[0]; - if (do_write) d86f_write_direct(drive, side, gap_fill, 0); - break; + switch (dev->format_state) { case FMT_SECTOR_ID_SYNC: - max_len = sync_len; - if (d86f[drive].datac <= 3) - { - data = fdc_getdata(d86f_fdc, 0); - if (data != -1) - { - data &= 0xff; - } - if ((data == -1) && (d86f[drive].datac < 3)) - { - data = 0; - } - d86f[drive].format_sector_id.byte_array[d86f[drive].datac] = data & 0xff; - if (d86f[drive].datac == 3) - { - fdc_stop_id_request(d86f_fdc); - } - } - case FMT_PRETRK_SYNC: - case FMT_SECTOR_DATA_SYNC: - max_len = sync_len; - if (do_write) d86f_write_direct(drive, side, 0x00, 0); - break; - case FMT_PRETRK_IAM: - max_len = am_len; - if (do_write) - { - if (mfm) - { - d86f_write_direct(drive, side, iam_mfm[d86f[drive].datac], 1); - } - else - { - d86f_write_direct(drive, side, iam_fm, 1); - } - } - break; - case FMT_PRETRK_GAP1: - max_len = gap_sizes[1]; - if (do_write) d86f_write_direct(drive, side, gap_fill, 0); + fdc_request_next_sector_id(d86f_fdc); break; + case FMT_SECTOR_IDAM: - max_len = am_len; - if (mfm) - { - if (do_write) d86f_write_direct(drive, side, idam_mfm[d86f[drive].datac], 1); - d86f_calccrc(drive, (d86f[drive].datac < 3) ? 0xA1 : 0xFE); - } - else - { - if (do_write) d86f_write_direct(drive, side, idam_fm, 1); - d86f_calccrc(drive, 0xFE); - } - break; - case FMT_SECTOR_ID: - max_len = 4; - if (do_write) - { - d86f_write_direct(drive, side, d86f[drive].format_sector_id.byte_array[d86f[drive].datac], 0); - d86f_calccrc(drive, d86f[drive].format_sector_id.byte_array[d86f[drive].datac]); - } - else - { - if (d86f[drive].datac == 3) - { - d86f_handler[drive].set_sector(drive, side, d86f[drive].format_sector_id.id.c, d86f[drive].format_sector_id.id.h, d86f[drive].format_sector_id.id.r, d86f[drive].format_sector_id.id.n); - } - } - break; - case FMT_SECTOR_ID_CRC: - case FMT_SECTOR_DATA_CRC: - max_len = 2; - if (do_write) d86f_write_direct(drive, side, d86f[drive].calc_crc.bytes[d86f[drive].datac ^ 1], 0); - break; - case FMT_SECTOR_GAP2: - max_len = gap_sizes[2]; - if (do_write) d86f_write_direct(drive, side, gap_fill, 0); - break; case FMT_SECTOR_DATAAM: - max_len = am_len; - if (mfm) - { - if (do_write) d86f_write_direct(drive, side, dataam_mfm[d86f[drive].datac], 1); - d86f_calccrc(drive, (d86f[drive].datac < 3) ? 0xA1 : 0xFB); + dev->calc_crc.word = 0xffff; + break; + + case FMT_POSTTRK_CHECK: + if (dev->index_count) { + d86f_format_finish(drive, side, mfm, sc, gap_fill, do_write); + return; } - else - { - if (do_write) d86f_write_direct(drive, side, dataam_fm, 1); - d86f_calccrc(drive, 0xFB); - } - break; - case FMT_SECTOR_DATA: - max_len = dtl; - if (do_write) - { - d86f_write_direct(drive, side, d86f[drive].fill, 0); - d86f_handler[drive].write_data(drive, side, d86f[drive].datac, d86f[drive].fill); - } - d86f_calccrc(drive, d86f[drive].fill); - break; - case FMT_SECTOR_GAP3: - max_len = gap_sizes[3]; - if (do_write) d86f_write_direct(drive, side, gap_fill, 0); - break; - default: - max_len = 0; - break; - } - - d86f[drive].datac++; - - d86f_advance_word(drive, side); - - if ((d86f[drive].index_count) && ((d86f[drive].format_state < FMT_SECTOR_ID_SYNC) || (d86f[drive].format_state > FMT_SECTOR_GAP3))) - { - d86f_format_finish(drive, side, mfm, sc, gap_fill, do_write); - return; - } - - if (d86f[drive].datac >= max_len) - { - d86f[drive].datac = 0; - d86f[drive].format_state++; - - switch (d86f[drive].format_state) - { - case FMT_SECTOR_ID_SYNC: + dev->sector_count++; + if (dev->sector_count < sc) { + /* Sector within allotted amount, change state to SECTOR_ID_SYNC. */ + dev->format_state = FMT_SECTOR_ID_SYNC; fdc_request_next_sector_id(d86f_fdc); break; - case FMT_SECTOR_IDAM: - case FMT_SECTOR_DATAAM: - d86f[drive].calc_crc.word = 0xffff; + } else { + dev->format_state = FMT_POSTTRK_GAP4; + dev->sector_count = 0; break; - case FMT_POSTTRK_CHECK: - if (d86f[drive].index_count) - { - d86f_format_finish(drive, side, mfm, sc, gap_fill, do_write); - return; - } - d86f[drive].sector_count++; - if (d86f[drive].sector_count < sc) - { - /* Sector within allotted amount, change state to SECTOR_ID_SYNC. */ - d86f[drive].format_state = FMT_SECTOR_ID_SYNC; - fdc_request_next_sector_id(d86f_fdc); - break; - } - else - { - d86f[drive].format_state = FMT_POSTTRK_GAP4; - d86f[drive].sector_count = 0; - break; - } - } - } -} - -void d86f_format_track_normal(int drive, int side) -{ - d86f_format_track(drive, side, (d86f[drive].version == D86FVER)); -} - -void d86f_format_track_nop(int drive, int side) -{ - d86f_format_track(drive, side, 0); -} - -void d86f_initialize_last_sector_id(int drive, int c, int h, int r, int n) -{ - d86f[drive].last_sector.id.c = c; - d86f[drive].last_sector.id.h = h; - d86f[drive].last_sector.id.r = r; - d86f[drive].last_sector.id.n = n; -} - -void d86f_turbo_read(int drive, int side) -{ - uint8_t dat = 0; - - int recv_data = 0; - int read_status = 0; - - dat = d86f_handler[drive].read_data(drive, side, d86f[drive].turbo_pos); - d86f[drive].turbo_pos++; - - if (d86f[drive].state == STATE_11_SCAN_DATA) - { - /* Scan/compare command. */ - recv_data = d86f_get_data(drive, 0); - d86f_compare_byte(drive, recv_data, dat); - } - else - { - if (d86f[drive].data_find.bytes_obtained < (128 << d86f[drive].last_sector.id.n)) - { - if (d86f[drive].state != STATE_16_VERIFY_DATA) - { - read_status = fdc_data(d86f_fdc, dat); - if (read_status == -1) - { - d86f[drive].dma_over++; - } } - } - } - - if (d86f[drive].dma_over > 1) - { - d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; - d86f[drive].error_condition = 0; - d86f[drive].state = STATE_IDLE; - fdc_finishread(d86f_fdc); - fdc_overrun(d86f_fdc); - return; - } - - if (d86f[drive].turbo_pos >= (128 << d86f[drive].last_sector.id.n)) - { - /* CRC is valid. */ - d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; - d86f[drive].error_condition = 0; - if (d86f[drive].state == STATE_11_SCAN_DATA) - { - d86f[drive].state = STATE_IDLE; - fdc_sector_finishcompare(d86f_fdc, (d86f[drive].satisfying_bytes == ((128 << ((uint32_t) d86f[drive].last_sector.id.n)) - 1)) ? 1 : 0); - } - else - { - d86f[drive].state = STATE_IDLE; - fdc_sector_finishread(d86f_fdc); - } + break; } + } } -void d86f_turbo_write(int drive, int side) + +void +d86f_format_track_normal(int drive, int side) { - uint8_t dat = 0; + d86f_t *dev = d86f[drive]; - dat = d86f_get_data(drive, 1); - d86f_handler[drive].write_data(drive, side, d86f[drive].turbo_pos, dat); + d86f_format_track(drive, side, (dev->version == D86FVER)); +} - d86f[drive].turbo_pos++; - if (d86f[drive].turbo_pos >= (128 << d86f[drive].last_sector.id.n)) - { - /* We've written the data. */ - d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; - d86f[drive].error_condition = 0; - d86f[drive].state = STATE_IDLE; - d86f_handler[drive].writeback(drive); +void +d86f_format_track_nop(int drive, int side) +{ + d86f_format_track(drive, side, 0); +} + + +void +d86f_initialize_last_sector_id(int drive, int c, int h, int r, int n) +{ + d86f_t *dev = d86f[drive]; + + dev->last_sector.id.c = c; + dev->last_sector.id.h = h; + dev->last_sector.id.r = r; + dev->last_sector.id.n = n; +} + + +void +d86f_turbo_read(int drive, int side) +{ + d86f_t *dev = d86f[drive]; + uint8_t dat = 0; + int recv_data = 0; + int read_status = 0; + + dat = d86f_handler[drive].read_data(drive, side, dev->turbo_pos); + dev->turbo_pos++; + + if (dev->state == STATE_11_SCAN_DATA) { + /* Scan/compare command. */ + recv_data = d86f_get_data(drive, 0); + d86f_compare_byte(drive, recv_data, dat); + } else { + if (dev->data_find.bytes_obtained < (128UL << dev->last_sector.id.n)) { + if (dev->state != STATE_16_VERIFY_DATA) { + read_status = fdc_data(d86f_fdc, dat); + if (read_status == -1) + dev->dma_over++; + } + } + } + + if (dev->dma_over > 1) { + dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; + dev->error_condition = 0; + dev->state = STATE_IDLE; + fdc_finishread(d86f_fdc); + fdc_overrun(d86f_fdc); + return; + } + + if (dev->turbo_pos >= (128 << dev->last_sector.id.n)) { + /* CRC is valid. */ + dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; + dev->error_condition = 0; + if (dev->state == STATE_11_SCAN_DATA) { + dev->state = STATE_IDLE; + fdc_sector_finishcompare(d86f_fdc, (dev->satisfying_bytes == ((128 << ((uint32_t) dev->last_sector.id.n)) - 1)) ? 1 : 0); + } else { + dev->state = STATE_IDLE; fdc_sector_finishread(d86f_fdc); - return; } + } } -void d86f_turbo_format(int drive, int side, int nop) + +void +d86f_turbo_write(int drive, int side) { - int dat; - int i = 0; + d86f_t *dev = d86f[drive]; + uint8_t dat = 0; - uint16_t sc = 0; - uint16_t dtl = 0; + dat = d86f_get_data(drive, 1); + d86f_handler[drive].write_data(drive, side, dev->turbo_pos, dat); - sc = fdc_get_format_sectors(d86f_fdc); - dtl = 128 << fdc_get_format_n(d86f_fdc); + dev->turbo_pos++; - if (d86f[drive].datac <= 3) - { - dat = fdc_getdata(d86f_fdc, 0); - if (dat != -1) - { - dat &= 0xff; - } - if ((dat == -1) && (d86f[drive].datac < 3)) - { - dat = 0; - } - d86f[drive].format_sector_id.byte_array[d86f[drive].datac] = dat & 0xff; - if (d86f[drive].datac == 3) - { - fdc_stop_id_request(d86f_fdc); - d86f_handler[drive].set_sector(drive, side, d86f[drive].format_sector_id.id.c, d86f[drive].format_sector_id.id.h, d86f[drive].format_sector_id.id.r, d86f[drive].format_sector_id.id.n); - } - } - else if (d86f[drive].datac == 4) - { - if (!nop) - { - for (i = 0; i < dtl; i++) - { - d86f_handler[drive].write_data(drive, side, i, d86f[drive].fill); - } - } - - d86f[drive].sector_count++; - } - - d86f[drive].datac++; - - if (d86f[drive].datac == 6) - { - d86f[drive].datac = 0; - - if (d86f[drive].sector_count < sc) - { - /* Sector within allotted amount. */ - fdc_request_next_sector_id(d86f_fdc); - } - else - { - d86f[drive].state = STATE_IDLE; - d86f_format_turbo_finish(drive, side, nop); - } - } + if (dev->turbo_pos >= (128 << dev->last_sector.id.n)) { + /* We've written the data. */ + dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; + dev->error_condition = 0; + dev->state = STATE_IDLE; + d86f_handler[drive].writeback(drive); + fdc_sector_finishread(d86f_fdc); + } } -int d86f_sector_is_present(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n) -{ - sector_t *s, *t; - if (d86f[drive].last_side_sector[side]) { - s = d86f[drive].last_side_sector[side]; - while (s) { - if ((s->c == c) && (s->h == h) && (s->r == r) && (s->n == n)) - return 1; - if (!s->prev) - break; - t = s->prev; - s = t; - } +void +d86f_turbo_format(int drive, int side, int nop) +{ + d86f_t *dev = d86f[drive]; + int dat; + uint16_t sc; + uint16_t dtl; + int i; + + sc = fdc_get_format_sectors(d86f_fdc); + dtl = 128 << fdc_get_format_n(d86f_fdc); + + if (dev->datac <= 3) { + dat = fdc_getdata(d86f_fdc, 0); + if (dat != -1) + dat &= 0xff; + if ((dat == -1) && (dev->datac < 3)) + dat = 0; + dev->format_sector_id.byte_array[dev->datac] = dat & 0xff; + if (dev->datac == 3) { + fdc_stop_id_request(d86f_fdc); + d86f_handler[drive].set_sector(drive, side, dev->format_sector_id.id.c, dev->format_sector_id.id.h, dev->format_sector_id.id.r, dev->format_sector_id.id.n); } - return 0; + } else if (dev->datac == 4) { + if (! nop) { + for (i = 0; i < dtl; i++) + d86f_handler[drive].write_data(drive, side, i, dev->fill); + } + + dev->sector_count++; + } + + dev->datac++; + + if (dev->datac == 6) { + dev->datac = 0; + + if (dev->sector_count < sc) { + /* Sector within allotted amount. */ + fdc_request_next_sector_id(d86f_fdc); + } else { + dev->state = STATE_IDLE; + d86f_format_turbo_finish(drive, side, nop); + } + } } -void d86f_turbo_poll(int drive, int side) -{ - if ((d86f[drive].state != STATE_IDLE) && (d86f[drive].state != STATE_SECTOR_NOT_FOUND) && ((d86f[drive].state & 0xF8) != 0xE8)) - { - if (!d86f_can_read_address(drive)) - { - d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = d86f[drive].error_condition = 0; - fdc_noidam(d86f_fdc); - d86f[drive].state = STATE_IDLE; - return; - } - } - switch(d86f[drive].state) - { - case STATE_0D_SPIN_TO_INDEX: - case STATE_0D_NOP_SPIN_TO_INDEX: - d86f[drive].sector_count = 0; - d86f[drive].datac = 5; - case STATE_02_SPIN_TO_INDEX: - d86f[drive].state++; - return; - case STATE_02_FIND_ID: - if (!d86f_sector_is_present(drive, side, - fdc_get_read_track_sector(d86f_fdc).id.c, - fdc_get_read_track_sector(d86f_fdc).id.h, - fdc_get_read_track_sector(d86f_fdc).id.r, - fdc_get_read_track_sector(d86f_fdc).id.n)) - { - d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = d86f[drive].error_condition = 0; - fdc_nosector(d86f_fdc); - d86f[drive].state = STATE_IDLE; - return; - } - d86f[drive].last_sector.id.c = fdc_get_read_track_sector(d86f_fdc).id.c; - d86f[drive].last_sector.id.h = fdc_get_read_track_sector(d86f_fdc).id.h; - d86f[drive].last_sector.id.r = fdc_get_read_track_sector(d86f_fdc).id.r; - d86f[drive].last_sector.id.n = fdc_get_read_track_sector(d86f_fdc).id.n; - d86f_handler[drive].set_sector(drive, side, d86f[drive].last_sector.id.c, d86f[drive].last_sector.id.h, d86f[drive].last_sector.id.r, d86f[drive].last_sector.id.n); - d86f[drive].turbo_pos = 0; - d86f[drive].state++; - return; - case STATE_05_FIND_ID: - case STATE_09_FIND_ID: - case STATE_06_FIND_ID: - case STATE_0C_FIND_ID: - case STATE_11_FIND_ID: - case STATE_16_FIND_ID: - if (!d86f_sector_is_present(drive, side, - d86f[drive].req_sector.id.c, - d86f[drive].req_sector.id.h, - d86f[drive].req_sector.id.r, - d86f[drive].req_sector.id.n)) - { - d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = d86f[drive].error_condition = 0; - fdc_nosector(d86f_fdc); - d86f[drive].state = STATE_IDLE; - return; - } - d86f[drive].last_sector.id.c = d86f[drive].req_sector.id.c; - d86f[drive].last_sector.id.h = d86f[drive].req_sector.id.h; - d86f[drive].last_sector.id.r = d86f[drive].req_sector.id.r; - d86f[drive].last_sector.id.n = d86f[drive].req_sector.id.n; - d86f_handler[drive].set_sector(drive, side, d86f[drive].last_sector.id.c, d86f[drive].last_sector.id.h, d86f[drive].last_sector.id.r, d86f[drive].last_sector.id.n); - case STATE_0A_FIND_ID: - d86f[drive].turbo_pos = 0; - d86f[drive].state++; - return; - case STATE_0A_READ_ID: - d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = d86f[drive].error_condition = 0; - fdc_sectorid(d86f_fdc, d86f[drive].last_sector.id.c, d86f[drive].last_sector.id.h, d86f[drive].last_sector.id.r, d86f[drive].last_sector.id.n, 0, 0); - d86f[drive].state = STATE_IDLE; - break; - case STATE_02_READ_ID: - case STATE_05_READ_ID: - case STATE_09_READ_ID: - case STATE_06_READ_ID: - case STATE_0C_READ_ID: - case STATE_11_READ_ID: - case STATE_16_READ_ID: - d86f[drive].state++; - break; - case STATE_02_FIND_DATA: - case STATE_06_FIND_DATA: - case STATE_11_FIND_DATA: - case STATE_16_FIND_DATA: - case STATE_05_FIND_DATA: - case STATE_09_FIND_DATA: - case STATE_0C_FIND_DATA: - d86f[drive].state++; - break; - case STATE_02_READ_DATA: - case STATE_06_READ_DATA: - case STATE_0C_READ_DATA: - case STATE_11_SCAN_DATA: - case STATE_16_VERIFY_DATA: - d86f_turbo_read(drive, side); - break; - case STATE_05_WRITE_DATA: - case STATE_09_WRITE_DATA: - d86f_turbo_write(drive, side); - break; - case STATE_0D_FORMAT_TRACK: - d86f_turbo_format(drive, side, 0); - return; - case STATE_0D_NOP_FORMAT_TRACK: - d86f_turbo_format(drive, side, 1); - return; - case STATE_IDLE: - case STATE_SECTOR_NOT_FOUND: - default: +int +d86f_sector_is_present(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n) +{ + d86f_t *dev = d86f[drive]; + sector_t *s, *t; + + if (dev->last_side_sector[side]) { + s = dev->last_side_sector[side]; + while (s) { + if ((s->c == c) && (s->h == h) && (s->r == r) && (s->n == n)) + return 1; + if (! s->prev) break; + t = s->prev; + s = t; } + } + + return 0; } -void d86f_poll(int drive) + +void +d86f_turbo_poll(int drive, int side) { - int side = 0; - int mfm = 1; + d86f_t *dev = d86f[drive]; - side = fdd_get_head(drive); - if (!fdd_is_double_sided(drive)) - { - side = 0; - } - - mfm = fdc_is_mfm(d86f_fdc); - - if ((d86f[drive].state & 0xF8) == 0xE8) - { - if (!d86f_can_format(drive)) - { - d86f[drive].state = STATE_SECTOR_NOT_FOUND; - } - } - - if (fdd_get_turbo(drive) && (d86f[drive].version == 0x0063)) - { - d86f_turbo_poll(drive, side); - return; - } - - if ((d86f[drive].state != STATE_IDLE) && (d86f[drive].state != STATE_SECTOR_NOT_FOUND) && ((d86f[drive].state & 0xF8) != 0xE8)) - { - if (!d86f_can_read_address(drive)) - { - - d86f[drive].state = STATE_SECTOR_NOT_FOUND; - } - } - - if ((d86f[drive].state != STATE_02_SPIN_TO_INDEX) && (d86f[drive].state != STATE_0D_SPIN_TO_INDEX)) - { - d86f_get_bit(drive, side ^ 1); - } - - switch(d86f[drive].state) - { - case STATE_02_SPIN_TO_INDEX: - case STATE_0D_SPIN_TO_INDEX: - case STATE_0D_NOP_SPIN_TO_INDEX: - d86f_spin_to_index(drive, side); - return; - case STATE_02_FIND_ID: - case STATE_05_FIND_ID: - case STATE_09_FIND_ID: - case STATE_06_FIND_ID: - case STATE_0A_FIND_ID: - case STATE_0C_FIND_ID: - case STATE_11_FIND_ID: - case STATE_16_FIND_ID: - if (mfm) - { - d86f_find_address_mark_mfm(drive, side, &(d86f[drive].id_find), 0x5554, 0, 0); - } - else - { - d86f_find_address_mark_fm(drive, side, &(d86f[drive].id_find), 0xF57E, 0, 0); - } - break; - case STATE_0A_READ_ID: - case STATE_02_READ_ID: - d86f_read_sector_id(drive, side, 0); - break; - case STATE_05_READ_ID: - case STATE_09_READ_ID: - case STATE_06_READ_ID: - case STATE_0C_READ_ID: - case STATE_11_READ_ID: - case STATE_16_READ_ID: - d86f_read_sector_id(drive, side, 1); - break; - case STATE_02_FIND_DATA: - if (mfm) - { - d86f_find_address_mark_mfm(drive, side, &(d86f[drive].data_find), 0x5545, 0x554A, 2); - } - else - { - d86f_find_address_mark_fm(drive, side, &(d86f[drive].data_find), 0xF56F, 0xF56A, 2); - } - break; - case STATE_06_FIND_DATA: - case STATE_11_FIND_DATA: - case STATE_16_FIND_DATA: - if (mfm) - { - d86f_find_address_mark_mfm(drive, side, &(d86f[drive].data_find), 0x5545, 0x554A, fdc_is_sk(d86f_fdc) | 2); - } - else - { - d86f_find_address_mark_fm(drive, side, &(d86f[drive].data_find), 0xF56F, 0xF56A, fdc_is_sk(d86f_fdc) | 2); - } - break; - case STATE_05_FIND_DATA: - case STATE_09_FIND_DATA: - if (mfm) - { - d86f_write_find_address_mark_mfm(drive, side, &(d86f[drive].data_find)); - } - else - { - d86f_write_find_address_mark_fm(drive, side, &(d86f[drive].data_find)); - } - break; - case STATE_0C_FIND_DATA: - if (mfm) - { - d86f_find_address_mark_mfm(drive, side, &(d86f[drive].data_find), 0x554A, 0x5545, fdc_is_sk(d86f_fdc) | 2); - } - else - { - d86f_find_address_mark_fm(drive, side, &(d86f[drive].data_find), 0xF56A, 0xF56F, fdc_is_sk(d86f_fdc) | 2); - } - break; - case STATE_02_READ_DATA: - case STATE_06_READ_DATA: - case STATE_0C_READ_DATA: - case STATE_11_SCAN_DATA: - case STATE_16_VERIFY_DATA: - d86f_read_sector_data(drive, side); - break; - case STATE_05_WRITE_DATA: - if (mfm) - { - d86f_write_sector_data(drive, side, mfm, 0x5545); - } - else - { - d86f_write_sector_data(drive, side, mfm, 0xF56F); - } - break; - case STATE_09_WRITE_DATA: - if (mfm) - { - d86f_write_sector_data(drive, side, mfm, 0x554A); - } - else - { - d86f_write_sector_data(drive, side, mfm, 0xF56A); - } - break; - case STATE_0D_FORMAT_TRACK: - if (!(d86f[drive].track_pos & 15)) - { - d86f_format_track_normal(drive, side); - } - return; - case STATE_0D_NOP_FORMAT_TRACK: - if (!(d86f[drive].track_pos & 15)) - { - d86f_format_track_nop(drive, side); - } - return; - case STATE_IDLE: - case STATE_SECTOR_NOT_FOUND: - default: - d86f_get_bit(drive, side); - break; - } - - d86f_advance_bit(drive, side); - - if (d86f_wrong_densel(drive) && (d86f[drive].state != STATE_IDLE)) - { - d86f[drive].state = STATE_IDLE; + if ((dev->state != STATE_IDLE) && (dev->state != STATE_SECTOR_NOT_FOUND) && ((dev->state & 0xF8) != 0xE8)) { + if (! d86f_can_read_address(drive)) { + dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = dev->error_condition = 0; fdc_noidam(d86f_fdc); + dev->state = STATE_IDLE; return; } + } - if ((d86f[drive].index_count == 2) && (d86f[drive].state != STATE_IDLE)) - { - switch(d86f[drive].state) - { - case STATE_0A_FIND_ID: - case STATE_SECTOR_NOT_FOUND: - d86f[drive].state = STATE_IDLE; - fdc_noidam(d86f_fdc); - break; - case STATE_02_FIND_DATA: - case STATE_06_FIND_DATA: - case STATE_11_FIND_DATA: - case STATE_16_FIND_DATA: - case STATE_05_FIND_DATA: - case STATE_09_FIND_DATA: - case STATE_0C_FIND_DATA: - d86f[drive].state = STATE_IDLE; - fdc_nodataam(d86f_fdc); - break; - case STATE_02_SPIN_TO_INDEX: - case STATE_02_READ_DATA: - case STATE_05_WRITE_DATA: - case STATE_06_READ_DATA: - case STATE_09_WRITE_DATA: - case STATE_0C_READ_DATA: - case STATE_0D_SPIN_TO_INDEX: - case STATE_0D_FORMAT_TRACK: - case STATE_11_SCAN_DATA: - case STATE_16_VERIFY_DATA: - /* In these states, we should *NEVER* care about how many index pulses there have been. */ - break; - default: - d86f[drive].state = STATE_IDLE; - if (d86f[drive].id_found) - { - if (d86f[drive].error_condition & 0x18) - { - if ((d86f[drive].error_condition & 0x18) == 0x08) - { - fdc_badcylinder(d86f_fdc); - } - if ((d86f[drive].error_condition & 0x10) == 0x10) - { - fdc_wrongcylinder(d86f_fdc); - } - } - else - { - fdc_nosector(d86f_fdc); - } - } - else - { - fdc_noidam(d86f_fdc); - } - break; + switch(dev->state) { + case STATE_0D_SPIN_TO_INDEX: + case STATE_0D_NOP_SPIN_TO_INDEX: + dev->sector_count = 0; + dev->datac = 5; + /*FALLTHROUGH*/ + + case STATE_02_SPIN_TO_INDEX: + dev->state++; + return; + + case STATE_02_FIND_ID: + if (! d86f_sector_is_present(drive, side, + fdc_get_read_track_sector(d86f_fdc).id.c, + fdc_get_read_track_sector(d86f_fdc).id.h, + fdc_get_read_track_sector(d86f_fdc).id.r, + fdc_get_read_track_sector(d86f_fdc).id.n)) { + dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = dev->error_condition = 0; + fdc_nosector(d86f_fdc); + dev->state = STATE_IDLE; + return; } - } -} + dev->last_sector.id.c = fdc_get_read_track_sector(d86f_fdc).id.c; + dev->last_sector.id.h = fdc_get_read_track_sector(d86f_fdc).id.h; + dev->last_sector.id.r = fdc_get_read_track_sector(d86f_fdc).id.r; + dev->last_sector.id.n = fdc_get_read_track_sector(d86f_fdc).id.n; + d86f_handler[drive].set_sector(drive, side, dev->last_sector.id.c, dev->last_sector.id.h, dev->last_sector.id.r, dev->last_sector.id.n); + dev->turbo_pos = 0; + dev->state++; + return; -#if 0 -void d86f_poll(int drive) -{ - int i = 0; - for (i = 0; i < 16; i++) - { - d86f_bit_poll(drive); - } -} - -void d86f_poll() -{ - int drive = 0; - drive = fdc_get_drive(d86f_fdc); - d86f_poll_per_drive(drive); -} -#endif - -void d86f_reset_index_hole_pos(int drive, int side) -{ - d86f[drive].index_hole_pos[side] = 0; -} - -uint16_t d86f_prepare_pretrack(int drive, int side, int iso) -{ - uint16_t i, pos; - - int mfm = 0; - int real_gap0_len = 0; - int sync_len = 0; - int real_gap1_len = 0; - uint16_t gap_fill = 0; - uint32_t raw_size = 0; - uint16_t iam_fm = 0xFAF7; - uint16_t iam_mfm = 0x5255; - - mfm = d86f_is_mfm(drive); - real_gap0_len = mfm ? 80 : 40; - sync_len = mfm ? 12 : 6; - real_gap1_len = mfm ? 50 : 26; - gap_fill = mfm ? 0x4E : 0xFF; - raw_size = d86f_handler[drive].get_raw_size(drive, side) >> 4; - - d86f[drive].index_hole_pos[side] = 0; - - d86f_destroy_linked_lists(drive, side); - - for (i = 0; i < raw_size; i++) - { - d86f_write_direct_common(drive, side, gap_fill, 0, i); - } - - pos = 0; - - if (!iso) - { - for (i = 0; i < real_gap0_len; i++) - { - d86f_write_direct_common(drive, side, gap_fill, 0, pos); - pos = (pos + 1) % raw_size; - } - for (i = 0; i < sync_len; i++) - { - d86f_write_direct_common(drive, side, 0, 0, pos); - pos = (pos + 1) % raw_size; + case STATE_05_FIND_ID: + case STATE_09_FIND_ID: + case STATE_06_FIND_ID: + case STATE_0C_FIND_ID: + case STATE_11_FIND_ID: + case STATE_16_FIND_ID: + if (! d86f_sector_is_present(drive, side, + dev->req_sector.id.c, + dev->req_sector.id.h, + dev->req_sector.id.r, + dev->req_sector.id.n)) { + dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = dev->error_condition = 0; + fdc_nosector(d86f_fdc); + dev->state = STATE_IDLE; + return; } + dev->last_sector.id.c = dev->req_sector.id.c; + dev->last_sector.id.h = dev->req_sector.id.h; + dev->last_sector.id.r = dev->req_sector.id.r; + dev->last_sector.id.n = dev->req_sector.id.n; + d86f_handler[drive].set_sector(drive, side, dev->last_sector.id.c, dev->last_sector.id.h, dev->last_sector.id.r, dev->last_sector.id.n); + /*FALLTHROUGH*/ + + case STATE_0A_FIND_ID: + dev->turbo_pos = 0; + dev->state++; + return; + + case STATE_0A_READ_ID: + dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = dev->error_condition = 0; + fdc_sectorid(d86f_fdc, dev->last_sector.id.c, dev->last_sector.id.h, dev->last_sector.id.r, dev->last_sector.id.n, 0, 0); + dev->state = STATE_IDLE; + break; + + case STATE_02_READ_ID: + case STATE_05_READ_ID: + case STATE_09_READ_ID: + case STATE_06_READ_ID: + case STATE_0C_READ_ID: + case STATE_11_READ_ID: + case STATE_16_READ_ID: + dev->state++; + break; + + case STATE_02_FIND_DATA: + case STATE_06_FIND_DATA: + case STATE_11_FIND_DATA: + case STATE_16_FIND_DATA: + case STATE_05_FIND_DATA: + case STATE_09_FIND_DATA: + case STATE_0C_FIND_DATA: + dev->state++; + break; + + case STATE_02_READ_DATA: + case STATE_06_READ_DATA: + case STATE_0C_READ_DATA: + case STATE_11_SCAN_DATA: + case STATE_16_VERIFY_DATA: + d86f_turbo_read(drive, side); + break; + + case STATE_05_WRITE_DATA: + case STATE_09_WRITE_DATA: + d86f_turbo_write(drive, side); + break; + + case STATE_0D_FORMAT_TRACK: + d86f_turbo_format(drive, side, 0); + return; + + case STATE_0D_NOP_FORMAT_TRACK: + d86f_turbo_format(drive, side, 1); + return; + + case STATE_IDLE: + case STATE_SECTOR_NOT_FOUND: + default: + break; + } +} + + +void +d86f_poll(int drive) +{ + d86f_t *dev = d86f[drive]; + int mfm, side; + + side = fdd_get_head(drive); + if (! fdd_is_double_sided(drive)) + side = 0; + + mfm = fdc_is_mfm(d86f_fdc); + + if ((dev->state & 0xF8) == 0xE8) { + if (! d86f_can_format(drive)) + dev->state = STATE_SECTOR_NOT_FOUND; + } + + if (fdd_get_turbo(drive) && (dev->version == 0x0063)) { + d86f_turbo_poll(drive, side); + return; + } + + if ((dev->state != STATE_IDLE) && (dev->state != STATE_SECTOR_NOT_FOUND) && ((dev->state & 0xF8) != 0xE8)) { + if (! d86f_can_read_address(drive)) + dev->state = STATE_SECTOR_NOT_FOUND; + } + + if ((dev->state != STATE_02_SPIN_TO_INDEX) && (dev->state != STATE_0D_SPIN_TO_INDEX)) + d86f_get_bit(drive, side ^ 1); + + switch(dev->state) { + case STATE_02_SPIN_TO_INDEX: + case STATE_0D_SPIN_TO_INDEX: + case STATE_0D_NOP_SPIN_TO_INDEX: + d86f_spin_to_index(drive, side); + return; + + case STATE_02_FIND_ID: + case STATE_05_FIND_ID: + case STATE_09_FIND_ID: + case STATE_06_FIND_ID: + case STATE_0A_FIND_ID: + case STATE_0C_FIND_ID: + case STATE_11_FIND_ID: + case STATE_16_FIND_ID: if (mfm) - { - for (i = 0; i < 3; i++) - { - d86f_write_direct_common(drive, side, 0x2452, 1, pos); - pos = (pos + 1) % raw_size; - } - } - d86f_write_direct_common(drive, side, mfm ? iam_mfm : iam_fm, 1, pos); - pos = (pos + 1) % raw_size; - } - for (i = 0; i < real_gap1_len; i++) - { - d86f_write_direct_common(drive, side, gap_fill, 0, pos); - pos = (pos + 1) % raw_size; - } - - return pos; -} - -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) -{ - uint16_t pos; - - int i; - sector_t *s; - - int real_gap2_len = gap2; - int real_gap3_len = gap3; - int mfm = 0; - int sync_len = 0; - uint16_t gap_fill = 0; - uint32_t raw_size = 0; - uint16_t idam_fm = 0x7EF5; - uint16_t dataam_fm = 0x6FF5; - uint16_t datadam_fm = 0x6AF5; - uint16_t idam_mfm = 0x5455; - uint16_t dataam_mfm = 0x4555; - uint16_t datadam_mfm = 0x4A55; - - if (fdd_get_turbo(drive) && (d86f[drive].version == 0x0063)) { - s = (sector_t *) malloc(sizeof(sector_t)); - memset(s, 0, sizeof(sector_t)); - s->c = id_buf[0]; - s->h = id_buf[1]; - s->r = id_buf[2]; - s->n = id_buf[3]; - if (d86f[drive].last_side_sector[side]) - s->prev = d86f[drive].last_side_sector[side]; - d86f[drive].last_side_sector[side] = s; - } - - mfm = d86f_is_mfm(drive); - - gap_fill = mfm ? 0x4E : 0xFF; - raw_size = d86f_handler[drive].get_raw_size(drive, side) >> 4; - - pos = prev_pos; - - sync_len = mfm ? 12 : 6; - - for (i = 0; i < sync_len; i++) - { - d86f_write_direct_common(drive, side, 0, 0, pos); - pos = (pos + 1) % raw_size; - } - d86f[drive].calc_crc.word = 0xffff; - if (mfm) - { - for (i = 0; i < 3; i++) - { - d86f_write_direct_common(drive, side, 0x8944, 1, pos); - pos = (pos + 1) % raw_size; - d86f_calccrc(drive, 0xA1); - } - } - d86f_write_direct_common(drive, side, mfm ? idam_mfm : idam_fm, 1, pos); - pos = (pos + 1) % raw_size; - d86f_calccrc(drive, 0xFE); - for (i = 0; i < 4; i++) - { - d86f_write_direct_common(drive, side, id_buf[i], 0, pos); - pos = (pos + 1) % raw_size; - d86f_calccrc(drive, id_buf[i]); - } - for (i = 1; i >= 0; i--) - { - d86f_write_direct_common(drive, side, d86f[drive].calc_crc.bytes[i], 0, pos); - pos = (pos + 1) % raw_size; - } - for (i = 0; i < real_gap2_len; i++) - { - d86f_write_direct_common(drive, side, gap_fill, 0, pos); - pos = (pos + 1) % raw_size; - } - for (i = 0; i < sync_len; i++) - { - d86f_write_direct_common(drive, side, 0, 0, pos); - pos = (pos + 1) % raw_size; - } - d86f[drive].calc_crc.word = 0xffff; - if (mfm) - { - for (i = 0; i < 3; i++) - { - d86f_write_direct_common(drive, side, 0x8944, 1, pos); - pos = (pos + 1) % raw_size; - d86f_calccrc(drive, 0xA1); - } - } - d86f_write_direct_common(drive, side, mfm ? (deleted ? datadam_mfm : dataam_mfm) : (deleted ? datadam_fm : dataam_fm), 1, pos); - pos = (pos + 1) % raw_size; - d86f_calccrc(drive, deleted ? 0xF8 : 0xFB); - for (i = 0; i < data_len; i++) - { - d86f_write_direct_common(drive, side, data_buf[i], 0, pos); - pos = (pos + 1) % raw_size; - d86f_calccrc(drive, data_buf[i]); - } - if (bad_crc) - { - d86f[drive].calc_crc.word ^= 0xffff; - } - for (i = 1; i >= 0; i--) - { - d86f_write_direct_common(drive, side, d86f[drive].calc_crc.bytes[i], 0, pos); - pos = (pos + 1) % raw_size; - } - for (i = 0; i < real_gap3_len; i++) - { - d86f_write_direct_common(drive, side, gap_fill, 0, pos); - pos = (pos + 1) % raw_size; - } - - return pos; -} - -/* Note on handling of tracks on thick track drives: - - On seek, encoded data is constructed from both (track << 1) and ((track << 1) + 1); - - Any bits that differ are treated as thus: - - Both are regular but contents differ -> Output is fuzzy; - - One is regular and one is fuzzy -> Output is fuzzy; - - Both are fuzzy -> Output is fuzzy; - - Both are physical holes -> Output is a physical hole; - - One is regular and one is a physical hole -> Output is puzzy, the hole half is handled appropriately on writeback; - - One is fuzzy and one is a physical hole -> Output is puzzy, the hole half is handled appropriately on writeback; - - On write back, apart from the above notes, the final two tracks are written; - - Destination ALWAYS has surface data even if the image does not. - In case of a thin track drive, tracks are handled normally. */ - -void d86f_construct_encoded_buffer(int drive, int side) -{ - int i = 0; - /* *_fuzm are fuzzy bit masks, *_holm are hole masks, dst_neim are masks is mask for bits that are neither fuzzy nor holes in both, - and src1_d and src2_d are filtered source data. */ - uint16_t src1_fuzm, src2_fuzm, dst_fuzm, src1_holm, src2_holm, dst_holm, dst_neim, src1_d, src2_d; - uint32_t len; - uint16_t *dst = d86f[drive].track_encoded_data[side]; - uint16_t *dst_s = d86f[drive].track_surface_data[side]; - uint16_t *src1 = d86f[drive].thin_track_encoded_data[0][side]; - uint16_t *src1_s = d86f[drive].thin_track_surface_data[0][side]; - uint16_t *src2 = d86f[drive].thin_track_encoded_data[1][side]; - uint16_t *src2_s = d86f[drive].thin_track_surface_data[1][side]; - len = d86f_get_array_size(drive, side); - - for (i = 0; i < len; i++) - { - /* The two bits differ. */ - if (d86f_has_surface_desc(drive)) - { - /* Source image has surface description data, so we have some more handling to do. */ - src1_fuzm = src1[i] & src1_s[i]; - src2_fuzm = src2[i] & src2_s[i]; - dst_fuzm = src1_fuzm | src2_fuzm; /* The bits that remain set are fuzzy in either one or - the other or both. */ - src1_holm = src1[i] | (src1_s[i] ^ 0xffff); - src2_holm = src2[i] | (src2_s[i] ^ 0xffff); - dst_holm = (src1_holm & src2_holm) ^ 0xffff; /* The bits that remain set are holes in both. */ - dst_neim = (dst_fuzm | dst_holm) ^ 0xffff; /* The bits that remain set are those that are neither - fuzzy nor are holes in both. */ - src1_d = src1[i] & dst_neim; - src2_d = src2[i] & dst_neim; - - dst_s[i] = (dst_neim ^ 0xffff); /* The set bits are those that are either fuzzy or are - holes in both. */ - dst[i] = (src1_d | src2_d); /* Initial data is remaining data from Source 1 and - Source 2. */ - dst[i] |= dst_fuzm; /* Add to it the fuzzy bytes (holes have surface bit set - but data bit clear). */ - } + d86f_find_address_mark_mfm(drive, side, &(dev->id_find), 0x5554, 0, 0); else - { - /* No surface data, the handling is much simpler - a simple OR. */ - dst[i] = src1[i] | src2[i]; - dst_s[i] = 0; + d86f_find_address_mark_fm(drive, side, &(dev->id_find), 0xF57E, 0, 0); + break; + + case STATE_0A_READ_ID: + case STATE_02_READ_ID: + d86f_read_sector_id(drive, side, 0); + break; + + case STATE_05_READ_ID: + case STATE_09_READ_ID: + case STATE_06_READ_ID: + case STATE_0C_READ_ID: + case STATE_11_READ_ID: + case STATE_16_READ_ID: + d86f_read_sector_id(drive, side, 1); + break; + + case STATE_02_FIND_DATA: + if (mfm) + d86f_find_address_mark_mfm(drive, side, &(dev->data_find), 0x5545, 0x554A, 2); + else + d86f_find_address_mark_fm(drive, side, &(dev->data_find), 0xF56F, 0xF56A, 2); + break; + + case STATE_06_FIND_DATA: + case STATE_11_FIND_DATA: + case STATE_16_FIND_DATA: + if (mfm) + d86f_find_address_mark_mfm(drive, side, &(dev->data_find), 0x5545, 0x554A, fdc_is_sk(d86f_fdc) | 2); + else + d86f_find_address_mark_fm(drive, side, &(dev->data_find), 0xF56F, 0xF56A, fdc_is_sk(d86f_fdc) | 2); + break; + + case STATE_05_FIND_DATA: + case STATE_09_FIND_DATA: + if (mfm) + d86f_write_find_address_mark_mfm(drive, side, &(dev->data_find)); + else + d86f_write_find_address_mark_fm(drive, side, &(dev->data_find)); + break; + + case STATE_0C_FIND_DATA: + if (mfm) + d86f_find_address_mark_mfm(drive, side, &(dev->data_find), 0x554A, 0x5545, fdc_is_sk(d86f_fdc) | 2); + else + d86f_find_address_mark_fm(drive, side, &(dev->data_find), 0xF56A, 0xF56F, fdc_is_sk(d86f_fdc) | 2); + break; + + case STATE_02_READ_DATA: + case STATE_06_READ_DATA: + case STATE_0C_READ_DATA: + case STATE_11_SCAN_DATA: + case STATE_16_VERIFY_DATA: + d86f_read_sector_data(drive, side); + break; + + case STATE_05_WRITE_DATA: + if (mfm) + d86f_write_sector_data(drive, side, mfm, 0x5545); + else + d86f_write_sector_data(drive, side, mfm, 0xF56F); + break; + + case STATE_09_WRITE_DATA: + if (mfm) + d86f_write_sector_data(drive, side, mfm, 0x554A); + else + d86f_write_sector_data(drive, side, mfm, 0xF56A); + break; + + case STATE_0D_FORMAT_TRACK: + if (! (dev->track_pos & 15)) + d86f_format_track_normal(drive, side); + return; + + case STATE_0D_NOP_FORMAT_TRACK: + if (! (dev->track_pos & 15)) + d86f_format_track_nop(drive, side); + return; + + case STATE_IDLE: + case STATE_SECTOR_NOT_FOUND: + default: + d86f_get_bit(drive, side); + break; + } + + d86f_advance_bit(drive, side); + + if (d86f_wrong_densel(drive) && (dev->state != STATE_IDLE)) { + dev->state = STATE_IDLE; + fdc_noidam(d86f_fdc); + return; + } + + if ((dev->index_count == 2) && (dev->state != STATE_IDLE)) { + switch(dev->state) { + case STATE_0A_FIND_ID: + case STATE_SECTOR_NOT_FOUND: + dev->state = STATE_IDLE; + fdc_noidam(d86f_fdc); + break; + + case STATE_02_FIND_DATA: + case STATE_06_FIND_DATA: + case STATE_11_FIND_DATA: + case STATE_16_FIND_DATA: + case STATE_05_FIND_DATA: + case STATE_09_FIND_DATA: + case STATE_0C_FIND_DATA: + + dev->state = STATE_IDLE; + fdc_nodataam(d86f_fdc); + break; + + case STATE_02_SPIN_TO_INDEX: + case STATE_02_READ_DATA: + case STATE_05_WRITE_DATA: + case STATE_06_READ_DATA: + case STATE_09_WRITE_DATA: + case STATE_0C_READ_DATA: + case STATE_0D_SPIN_TO_INDEX: + case STATE_0D_FORMAT_TRACK: + case STATE_11_SCAN_DATA: + case STATE_16_VERIFY_DATA: + /* In these states, we should *NEVER* care about how many index pulses there have been. */ + break; + + default: + dev->state = STATE_IDLE; + if (dev->id_found) { + if (dev->error_condition & 0x18) { + if ((dev->error_condition & 0x18) == 0x08) + fdc_badcylinder(d86f_fdc); + if ((dev->error_condition & 0x10) == 0x10) + fdc_wrongcylinder(d86f_fdc); + else + fdc_nosector(d86f_fdc); + } + } else { + fdc_noidam(d86f_fdc); + } + break; + } + } +} + + +void +d86f_reset_index_hole_pos(int drive, int side) +{ + d86f_t *dev = d86f[drive]; + + dev->index_hole_pos[side] = 0; +} + + +uint16_t +d86f_prepare_pretrack(int drive, int side, int iso) +{ + d86f_t *dev = d86f[drive]; + uint16_t i, pos; + int mfm; + int real_gap0_len; + int sync_len; + int real_gap1_len; + uint16_t gap_fill; + uint32_t raw_size; + uint16_t iam_fm = 0xFAF7; + uint16_t iam_mfm = 0x5255; + + mfm = d86f_is_mfm(drive); + real_gap0_len = mfm ? 80 : 40; + sync_len = mfm ? 12 : 6; + real_gap1_len = mfm ? 50 : 26; + gap_fill = mfm ? 0x4E : 0xFF; + raw_size = d86f_handler[drive].get_raw_size(drive, side) >> 4; + + dev->index_hole_pos[side] = 0; + + d86f_destroy_linked_lists(drive, side); + + for (i = 0; i < raw_size; i++) + d86f_write_direct_common(drive, side, gap_fill, 0, i); + + pos = 0; + + if (! iso) { + for (i = 0; i < real_gap0_len; i++) { + d86f_write_direct_common(drive, side, gap_fill, 0, pos); + pos = (pos + 1) % raw_size; + } + for (i = 0; i < sync_len; i++) { + d86f_write_direct_common(drive, side, 0, 0, pos); + pos = (pos + 1) % raw_size; + } + if (mfm) { + for (i = 0; i < 3; i++) { + d86f_write_direct_common(drive, side, 0x2452, 1, pos); + pos = (pos + 1) % raw_size; } } + + d86f_write_direct_common(drive, side, mfm ? iam_mfm : iam_fm, 1, pos); + pos = (pos + 1) % raw_size; + } + + for (i = 0; i < real_gap1_len; i++) { + d86f_write_direct_common(drive, side, gap_fill, 0, pos); + pos = (pos + 1) % raw_size; + } + + return pos; } + +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) +{ + d86f_t *dev = d86f[drive]; + uint16_t pos; + int i; + sector_t *s; + + int real_gap2_len = gap2; + int real_gap3_len = gap3; + int mfm; + int sync_len; + uint16_t gap_fill; + uint32_t raw_size; + uint16_t idam_fm = 0x7EF5; + uint16_t dataam_fm = 0x6FF5; + uint16_t datadam_fm = 0x6AF5; + uint16_t idam_mfm = 0x5455; + uint16_t dataam_mfm = 0x4555; + uint16_t datadam_mfm = 0x4A55; + + if (fdd_get_turbo(drive) && (dev->version == 0x0063)) { + s = (sector_t *) malloc(sizeof(sector_t)); + memset(s, 0, sizeof(sector_t)); + s->c = id_buf[0]; + s->h = id_buf[1]; + s->r = id_buf[2]; + s->n = id_buf[3]; + if (dev->last_side_sector[side]) + s->prev = dev->last_side_sector[side]; + dev->last_side_sector[side] = s; + } + + mfm = d86f_is_mfm(drive); + + gap_fill = mfm ? 0x4E : 0xFF; + raw_size = d86f_handler[drive].get_raw_size(drive, side) >> 4; + + pos = prev_pos; + + sync_len = mfm ? 12 : 6; + + for (i = 0; i < sync_len; i++) { + d86f_write_direct_common(drive, side, 0, 0, pos); + pos = (pos + 1) % raw_size; + } + dev->calc_crc.word = 0xffff; + if (mfm) { + for (i = 0; i < 3; i++) { + d86f_write_direct_common(drive, side, 0x8944, 1, pos); + pos = (pos + 1) % raw_size; + d86f_calccrc(dev, 0xA1); + } + } + d86f_write_direct_common(drive, side, mfm ? idam_mfm : idam_fm, 1, pos); + pos = (pos + 1) % raw_size; + d86f_calccrc(dev, 0xFE); + for (i = 0; i < 4; i++) { + d86f_write_direct_common(drive, side, id_buf[i], 0, pos); + pos = (pos + 1) % raw_size; + d86f_calccrc(dev, id_buf[i]); + } + for (i = 1; i >= 0; i--) { + d86f_write_direct_common(drive, side, dev->calc_crc.bytes[i], 0, pos); + pos = (pos + 1) % raw_size; + } + for (i = 0; i < real_gap2_len; i++) { + d86f_write_direct_common(drive, side, gap_fill, 0, pos); + pos = (pos + 1) % raw_size; + } + for (i = 0; i < sync_len; i++) { + d86f_write_direct_common(drive, side, 0, 0, pos); + pos = (pos + 1) % raw_size; + } + dev->calc_crc.word = 0xffff; + if (mfm) { + for (i = 0; i < 3; i++) { + d86f_write_direct_common(drive, side, 0x8944, 1, pos); + pos = (pos + 1) % raw_size; + d86f_calccrc(dev, 0xA1); + } + } + d86f_write_direct_common(drive, side, mfm ? (deleted ? datadam_mfm : dataam_mfm) : (deleted ? datadam_fm : dataam_fm), 1, pos); + pos = (pos + 1) % raw_size; + d86f_calccrc(dev, deleted ? 0xF8 : 0xFB); + for (i = 0; i < data_len; i++) { + d86f_write_direct_common(drive, side, data_buf[i], 0, pos); + pos = (pos + 1) % raw_size; + d86f_calccrc(dev, data_buf[i]); + } + if (bad_crc) + dev->calc_crc.word ^= 0xffff; + for (i = 1; i >= 0; i--) { + d86f_write_direct_common(drive, side, dev->calc_crc.bytes[i], 0, pos); + pos = (pos + 1) % raw_size; + } + for (i = 0; i < real_gap3_len; i++) { + d86f_write_direct_common(drive, side, gap_fill, 0, pos); + pos = (pos + 1) % raw_size; + } + + return pos; +} + + +/* + * Note on handling of tracks on thick track drives: + * + * - On seek, encoded data is constructed from both (track << 1) and + * ((track << 1) + 1); + * + * - Any bits that differ are treated as thus: + * - Both are regular but contents differ -> Output is fuzzy; + * - One is regular and one is fuzzy -> Output is fuzzy; + * - Both are fuzzy -> Output is fuzzy; + * - Both are physical holes -> Output is a physical hole; + * - One is regular and one is a physical hole -> Output is puzzy, + * the hole half is handled appropriately on writeback; + * - One is fuzzy and one is a physical hole -> Output is puzzy, + * the hole half is handled appropriately on writeback; + * - On write back, apart from the above notes, the final two tracks + * are written; + * - Destination ALWAYS has surface data even if the image does not. + * + * In case of a thin track drive, tracks are handled normally. + */ +void +d86f_construct_encoded_buffer(int drive, int side) +{ + d86f_t *dev = d86f[drive]; + uint32_t i = 0; + + /* *_fuzm are fuzzy bit masks, *_holm are hole masks, dst_neim are masks is mask for bits that are neither fuzzy nor holes in both, + and src1_d and src2_d are filtered source data. */ + uint16_t src1_fuzm, src2_fuzm, dst_fuzm, src1_holm, src2_holm, dst_holm, dst_neim, src1_d, src2_d; + uint32_t len; + uint16_t *dst = dev->track_encoded_data[side]; + uint16_t *dst_s = dev->track_surface_data[side]; + uint16_t *src1 = dev->thin_track_encoded_data[0][side]; + uint16_t *src1_s = dev->thin_track_surface_data[0][side]; + uint16_t *src2 = dev->thin_track_encoded_data[1][side]; + uint16_t *src2_s = dev->thin_track_surface_data[1][side]; + len = d86f_get_array_size(drive, side); + + for (i = 0; i < len; i++) { + /* The two bits differ. */ + if (d86f_has_surface_desc(drive)) { + /* Source image has surface description data, so we have some more handling to do. */ + src1_fuzm = src1[i] & src1_s[i]; + src2_fuzm = src2[i] & src2_s[i]; + dst_fuzm = src1_fuzm | src2_fuzm; /* The bits that remain set are fuzzy in either one or + the other or both. */ + src1_holm = src1[i] | (src1_s[i] ^ 0xffff); + src2_holm = src2[i] | (src2_s[i] ^ 0xffff); + dst_holm = (src1_holm & src2_holm) ^ 0xffff; /* The bits that remain set are holes in both. */ + dst_neim = (dst_fuzm | dst_holm) ^ 0xffff; /* The bits that remain set are those that are neither + fuzzy nor are holes in both. */ + src1_d = src1[i] & dst_neim; + src2_d = src2[i] & dst_neim; + + dst_s[i] = (dst_neim ^ 0xffff); /* The set bits are those that are either fuzzy or are + holes in both. */ + dst[i] = (src1_d | src2_d); /* Initial data is remaining data from Source 1 and + Source 2. */ + dst[i] |= dst_fuzm; /* Add to it the fuzzy bytes (holes have surface bit set + but data bit clear). */ + } else { + /* No surface data, the handling is much simpler - a simple OR. */ + dst[i] = src1[i] | src2[i]; + dst_s[i] = 0; + } + } +} + + /* Decomposition is easier since we at most have to care about the holes. */ -void d86f_decompose_encoded_buffer(int drive, int side) +void +d86f_decompose_encoded_buffer(int drive, int side) { - int i = 0; - uint16_t temp, temp2; - uint32_t len; - uint16_t *dst = d86f[drive].track_encoded_data[side]; - uint16_t *src1 = d86f[drive].thin_track_encoded_data[0][side]; - uint16_t *src1_s = d86f[drive].thin_track_surface_data[0][side]; - uint16_t *src2 = d86f[drive].thin_track_encoded_data[1][side]; - uint16_t *src2_s = d86f[drive].thin_track_surface_data[1][side]; - len = d86f_get_array_size(drive, side); + d86f_t *dev = d86f[drive]; + uint32_t i = 0; + uint16_t temp, temp2; + uint32_t len; + uint16_t *dst = dev->track_encoded_data[side]; + uint16_t *src1 = dev->thin_track_encoded_data[0][side]; + uint16_t *src1_s = dev->thin_track_surface_data[0][side]; + uint16_t *src2 = dev->thin_track_encoded_data[1][side]; + uint16_t *src2_s = dev->thin_track_surface_data[1][side]; + len = d86f_get_array_size(drive, side); - for (i = 0; i < len; i++) - { - if (d86f_has_surface_desc(drive)) - { - /* Source image has surface description data, so we have some more handling to do. - We need hole masks for both buffers. Holes have data bit clear and surface bit set. */ - temp = src1[i] & (src1_s[i] ^ 0xffff); - temp2 = src2[i] & (src2_s[i] ^ 0xffff); - src1[i] = dst[i] & temp; - src1_s[i] = temp ^ 0xffff; - src2[i] = dst[i] & temp2; - src2_s[i] = temp2 ^ 0xffff; - } - else - { - src1[i] = src2[i] = dst[i]; - } + for (i = 0; i < len; i++) { + if (d86f_has_surface_desc(drive)) { + /* Source image has surface description data, so we have some more handling to do. + We need hole masks for both buffers. Holes have data bit clear and surface bit set. */ + temp = src1[i] & (src1_s[i] ^ 0xffff); + temp2 = src2[i] & (src2_s[i] ^ 0xffff); + src1[i] = dst[i] & temp; + src1_s[i] = temp ^ 0xffff; + src2[i] = dst[i] & temp2; + src2_s[i] = temp2 ^ 0xffff; + } else { + src1[i] = src2[i] = dst[i]; } + } } -int d86f_track_header_size(int drive) + +int +d86f_track_header_size(int drive) { - int temp = 6; - if (d86f_has_extra_bit_cells(drive)) - { - temp += 4; - } - return temp; + int temp = 6; + + if (d86f_has_extra_bit_cells(drive)) + temp += 4; + + return temp; } -void d86f_read_track(int drive, int track, int thin_track, int side, uint16_t *da, uint16_t *sa) -{ - int logical_track = 0; - int array_size = 0; - if (d86f_get_sides(drive) == 2) - { - logical_track = ((track + thin_track) << 1) + side; - } +void +d86f_read_track(int drive, int track, int thin_track, int side, uint16_t *da, uint16_t *sa) +{ + d86f_t *dev = d86f[drive]; + int logical_track = 0; + int array_size = 0; + + if (d86f_get_sides(drive) == 2) + logical_track = ((track + thin_track) << 1) + side; else - { - logical_track = track + thin_track; - } + logical_track = track + thin_track; - if (d86f[drive].track_offset[logical_track]) - { - if (!thin_track) - { - fseek(d86f[drive].f, d86f[drive].track_offset[logical_track], SEEK_SET); - fread(&(d86f[drive].side_flags[side]), 2, 1, d86f[drive].f); - if (d86f_has_extra_bit_cells(drive)) - { - fread(&(d86f[drive].extra_bit_cells[side]), 4, 1, d86f[drive].f); - if (d86f[drive].extra_bit_cells[side] < -32768) - { - d86f[drive].extra_bit_cells[side] = -32768; - } - if (d86f[drive].extra_bit_cells[side] > 32768) - { - d86f[drive].extra_bit_cells[side] = 32768; - } - } - else - { - d86f[drive].extra_bit_cells[side] = 0; - } - fread(&(d86f[drive].index_hole_pos[side]), 4, 1, d86f[drive].f); + if (dev->track_offset[logical_track]) { + if (! thin_track) { + fseek(dev->f, dev->track_offset[logical_track], SEEK_SET); + fread(&(dev->side_flags[side]), 2, 1, dev->f); + if (d86f_has_extra_bit_cells(drive)) { + fread(&(dev->extra_bit_cells[side]), 4, 1, dev->f); + if (dev->extra_bit_cells[side] < -32768) + dev->extra_bit_cells[side] = -32768; + if (dev->extra_bit_cells[side] > 32768) + dev->extra_bit_cells[side] = 32768; + } else { + dev->extra_bit_cells[side] = 0; } - else - { - fseek(d86f[drive].f, d86f[drive].track_offset[logical_track] + d86f_track_header_size(drive), SEEK_SET); - } - array_size = d86f_get_array_size(drive, side) << 1; - if (d86f_has_surface_desc(drive)) - { - fread(sa, 1, array_size, d86f[drive].f); - } - fread(da, 1, array_size, d86f[drive].f); + fread(&(dev->index_hole_pos[side]), 4, 1, dev->f); + } else { + fseek(dev->f, dev->track_offset[logical_track] + d86f_track_header_size(drive), SEEK_SET); } - else - { - if (!thin_track) - { - switch((d86f[drive].disk_flags >> 1) & 3) - { - case 0: - default: - d86f[drive].side_flags[side] = 0x0A; - break; - case 1: - d86f[drive].side_flags[side] = 0x00; - break; - case 2: - case 3: - d86f[drive].side_flags[side] = 0x03; - break; - } - d86f[drive].extra_bit_cells[side] = 0; - } - } -} - -void d86f_zero_track(int drive) -{ - int sides, side; - sides = d86f_get_sides(drive); - - for (side = 0; side < sides; side++) - { - if (d86f_has_surface_desc(drive)) - { - memset(d86f[drive].track_surface_data[side], 0, 106096); - } - memset(d86f[drive].track_encoded_data[side], 0, 106096); - } -} - -void d86f_seek(int drive, int track) -{ - int sides; - int side, thin_track; - sides = d86f_get_sides(drive); - - /* If the drive has thick tracks, shift the track number by 1. */ - if (!fdd_doublestep_40(drive)) - { - track <<= 1; - - for (thin_track = 0; thin_track < sides; thin_track++) - { - for (side = 0; side < sides; side++) - { - if (d86f_has_surface_desc(drive)) - { - memset(d86f[drive].thin_track_surface_data[thin_track][side], 0, 106096); - } - memset(d86f[drive].thin_track_encoded_data[thin_track][side], 0, 106096); - } - } - } - - d86f_zero_track(drive); - - d86f[drive].cur_track = track; - - if (!fdd_doublestep_40(drive)) - { - for (side = 0; side < sides; side++) - { - for (thin_track = 0; thin_track < 2; thin_track++) - { - d86f_read_track(drive, track, thin_track, side, d86f[drive].thin_track_encoded_data[thin_track][side], d86f[drive].thin_track_surface_data[thin_track][side]); - } - - d86f_construct_encoded_buffer(drive, side); - } - } - else - { - for (side = 0; side < sides; side++) - { - d86f_read_track(drive, track, 0, side, d86f[drive].track_encoded_data[side], d86f[drive].track_surface_data[side]); - } - } - - d86f[drive].state = STATE_IDLE; -} - -void d86f_write_track(int drive, FILE **f, int side, uint16_t *da0, uint16_t *sa0) -{ - uint16_t side_flags = d86f_handler[drive].side_flags(drive); - uint32_t extra_bit_cells = d86f_handler[drive].extra_bit_cells(drive, side); - uint32_t index_hole_pos = d86f_handler[drive].index_hole_pos(drive, side); - - fwrite(&side_flags, 1, 2, *f); - - if (d86f_has_extra_bit_cells(drive)) - { - fwrite(&extra_bit_cells, 1, 4, *f); - } - - fwrite(&index_hole_pos, 1, 4, *f); - + array_size = d86f_get_array_size(drive, side) << 1; if (d86f_has_surface_desc(drive)) - { - fwrite(sa0, 1, d86f_get_array_size(drive, side) << 1, *f); + fread(sa, 1, array_size, dev->f); + fread(da, 1, array_size, dev->f); + } else { + if (! thin_track) { + switch((dev->disk_flags >> 1) & 3) { + case 0: + default: + dev->side_flags[side] = 0x0A; + break; + + case 1: + dev->side_flags[side] = 0x00; + break; + + case 2: + case 3: + dev->side_flags[side] = 0x03; + break; + } + dev->extra_bit_cells[side] = 0; } - - fwrite(da0, 1, d86f_get_array_size(drive, side) << 1, *f); + } } -int d86f_get_track_table_size(int drive) + +void +d86f_zero_track(int drive) { - int temp = 2048; + d86f_t *dev = d86f[drive]; + int sides, side; + sides = d86f_get_sides(drive); - if (d86f_get_sides(drive) == 1) - { - temp >>= 1; - } - - return temp; + for (side = 0; side < sides; side++) { + if (d86f_has_surface_desc(drive)) + memset(dev->track_surface_data[side], 0, 106096); + memset(dev->track_encoded_data[side], 0, 106096); + } } -void d86f_set_cur_track(int drive, int track) + +void +d86f_seek(int drive, int track) { - d86f[drive].cur_track = track; -} + d86f_t *dev = d86f[drive]; + int sides; + int side, thin_track; + sides = d86f_get_sides(drive); -void d86f_write_tracks(int drive, FILE **f, uint32_t *track_table) -{ - int sides; - int side, thin_track; - int logical_track = 0; - sides = d86f_get_sides(drive); - uint32_t *tbl = d86f[drive].track_offset; - if (track_table) - tbl = track_table; - int fdd_side = fdd_get_head(drive); + /* If the drive has thick tracks, shift the track number by 1. */ + if (! fdd_doublestep_40(drive)) { + track <<= 1; - if (!fdd_doublestep_40(drive)) - { - for (side = 0; side < sides; side++) - { - fdd_set_head(drive, side); - d86f_decompose_encoded_buffer(drive, side); - - for (thin_track = 0; thin_track < 2; thin_track++) - { - if (sides == 2) - { - logical_track = ((d86f[drive].cur_track + thin_track) << 1) + side; - } - else - { - logical_track = d86f[drive].cur_track + thin_track; - } - if (track_table && !tbl[logical_track]) - { - fseek(*f, 0, SEEK_END); - track_table[logical_track] = ftell(*f); - } - if (tbl[logical_track]) - { - fseek(*f, tbl[logical_track], SEEK_SET); - d86f_write_track(drive, f, side, d86f[drive].thin_track_encoded_data[thin_track][side], d86f[drive].thin_track_surface_data[thin_track][side]); - } - } + for (thin_track = 0; thin_track < sides; thin_track++) { + for (side = 0; side < sides; side++) { + if (d86f_has_surface_desc(drive)) + memset(dev->thin_track_surface_data[thin_track][side], 0, 106096); + memset(dev->thin_track_encoded_data[thin_track][side], 0, 106096); } } - else - { - for (side = 0; side < sides; side++) - { - fdd_set_head(drive, side); + } + + d86f_zero_track(drive); + + dev->cur_track = track; + + if (! fdd_doublestep_40(drive)) { + for (side = 0; side < sides; side++) { + for (thin_track = 0; thin_track < 2; thin_track++) + d86f_read_track(drive, track, thin_track, side, dev->thin_track_encoded_data[thin_track][side], dev->thin_track_surface_data[thin_track][side]); + + d86f_construct_encoded_buffer(drive, side); + } + } else { + for (side = 0; side < sides; side++) + d86f_read_track(drive, track, 0, side, dev->track_encoded_data[side], dev->track_surface_data[side]); + } + + dev->state = STATE_IDLE; +} + + +void +d86f_write_track(int drive, FILE **f, int side, uint16_t *da0, uint16_t *sa0) +{ + uint16_t side_flags = d86f_handler[drive].side_flags(drive); + uint32_t extra_bit_cells = d86f_handler[drive].extra_bit_cells(drive, side); + uint32_t index_hole_pos = d86f_handler[drive].index_hole_pos(drive, side); + + fwrite(&side_flags, 1, 2, *f); + + if (d86f_has_extra_bit_cells(drive)) + fwrite(&extra_bit_cells, 1, 4, *f); + + fwrite(&index_hole_pos, 1, 4, *f); + + if (d86f_has_surface_desc(drive)) + fwrite(sa0, 1, d86f_get_array_size(drive, side) << 1, *f); + + fwrite(da0, 1, d86f_get_array_size(drive, side) << 1, *f); +} + + +int +d86f_get_track_table_size(int drive) +{ + int temp = 2048; + + if (d86f_get_sides(drive) == 1) + temp >>= 1; + + return temp; +} + + +void +d86f_set_cur_track(int drive, int track) +{ + d86f_t *dev = d86f[drive]; + + dev->cur_track = track; +} + + +void +d86f_write_tracks(int drive, FILE **f, uint32_t *track_table) +{ + d86f_t *dev = d86f[drive]; + int sides; + int side, thin_track; + int logical_track = 0; + sides = d86f_get_sides(drive); + uint32_t *tbl = dev->track_offset; + int fdd_side = fdd_get_head(drive); + + if (track_table) + tbl = track_table; + + if (! fdd_doublestep_40(drive)) { + for (side = 0; side < sides; side++) { + fdd_set_head(drive, side); + d86f_decompose_encoded_buffer(drive, side); + + for (thin_track = 0; thin_track < 2; thin_track++) { if (sides == 2) - { - logical_track = (d86f[drive].cur_track << 1) + side; - } + logical_track = ((dev->cur_track + thin_track) << 1) + side; else - { - logical_track = d86f[drive].cur_track; - } - if (track_table && !tbl[logical_track]) - { + logical_track = dev->cur_track + thin_track; + + if (track_table && !tbl[logical_track]) { fseek(*f, 0, SEEK_END); track_table[logical_track] = ftell(*f); } - if (tbl[logical_track]) - { + if (tbl[logical_track]) { fseek(*f, tbl[logical_track], SEEK_SET); - d86f_write_track(drive, f, side, d86f[drive].track_encoded_data[side], d86f[drive].track_surface_data[side]); + d86f_write_track(drive, f, side, dev->thin_track_encoded_data[thin_track][side], dev->thin_track_surface_data[thin_track][side]); } } } + } else { + for (side = 0; side < sides; side++) { + fdd_set_head(drive, side); + if (sides == 2) + logical_track = (dev->cur_track << 1) + side; + else + logical_track = dev->cur_track; - fdd_set_head(drive, fdd_side); -} - -void d86f_writeback(int drive) -{ - uint8_t header[32]; - int header_size; - uint32_t len; - int ret = 0; - FILE *cf; - header_size = d86f_header_size(drive); - - if (!d86f[drive].f) - { - return; - } - - /* First write the track offsets table. */ - fseek(d86f[drive].f, 0, SEEK_SET); - fread(header, 1, header_size, d86f[drive].f); - - fseek(d86f[drive].f, 8, SEEK_SET); - fwrite(d86f[drive].track_offset, 1, d86f_get_track_table_size(drive), d86f[drive].f); - - d86f_write_tracks(drive, &d86f[drive].f, NULL); - - if (d86f[drive].is_compressed) - { - /* The image is compressed. */ - - /* Open the original, compressed file. */ - cf = plat_fopen(d86f[drive].original_file_name, L"wb"); - - /* Write the header to the original file. */ - fwrite(header, 1, header_size, cf); - - fseek(d86f[drive].f, 0, SEEK_END); - len = ftell(d86f[drive].f); - len -= header_size; - - fseek(d86f[drive].f, header_size, SEEK_SET); - - /* Compress data from the temporary uncompressed file to the original, compressed file. */ - d86f[drive].filebuf = (uint8_t *) malloc(len); - d86f[drive].outbuf = (uint8_t *) malloc(len - 1); - fread(d86f[drive].filebuf, 1, len, d86f[drive].f); - ret = lzf_compress(d86f[drive].filebuf, len, d86f[drive].outbuf, len - 1); - - if (!ret) - { - d86f_log("86F: Error compressing file\n"); + if (track_table && !tbl[logical_track]) { + fseek(*f, 0, SEEK_END); + track_table[logical_track] = ftell(*f); } - fwrite(d86f[drive].outbuf, 1, ret, cf); - free(d86f[drive].outbuf); - free(d86f[drive].filebuf); + if (tbl[logical_track]) { + fseek(*f, tbl[logical_track], SEEK_SET); + d86f_write_track(drive, f, side, dev->track_encoded_data[side], dev->track_surface_data[side]); + } } + } + + fdd_set_head(drive, fdd_side); } -void d86f_stop(int drive) + +void +d86f_writeback(int drive) { - d86f[drive].state = STATE_IDLE; + d86f_t *dev = d86f[drive]; + uint8_t header[32]; + int header_size; + uint32_t len; + int ret = 0; + FILE *cf; + header_size = d86f_header_size(drive); + + if (! dev->f) return; + + /* First write the track offsets table. */ + fseek(dev->f, 0, SEEK_SET); + fread(header, 1, header_size, dev->f); + + fseek(dev->f, 8, SEEK_SET); + fwrite(dev->track_offset, 1, d86f_get_track_table_size(drive), dev->f); + + d86f_write_tracks(drive, &dev->f, NULL); + + if (dev->is_compressed) { + /* The image is compressed. */ + + /* Open the original, compressed file. */ + cf = plat_fopen(dev->original_file_name, L"wb"); + + /* Write the header to the original file. */ + fwrite(header, 1, header_size, cf); + + fseek(dev->f, 0, SEEK_END); + len = ftell(dev->f); + len -= header_size; + + fseek(dev->f, header_size, SEEK_SET); + + /* Compress data from the temporary uncompressed file to the original, compressed file. */ + dev->filebuf = (uint8_t *) malloc(len); + dev->outbuf = (uint8_t *) malloc(len - 1); + fread(dev->filebuf, 1, len, dev->f); + ret = lzf_compress(dev->filebuf, len, dev->outbuf, len - 1); + + if (! ret) + d86f_log("86F: Error compressing file\n"); + + fwrite(dev->outbuf, 1, ret, cf); + free(dev->outbuf); + free(dev->filebuf); + } } -int d86f_common_command(int drive, int sector, int track, int side, int rate, int sector_size) + +void +d86f_stop(int drive) { - d86f_log("d86f_common_command (drive %i): fdc_period=%i img_period=%i rate=%i sector=%i track=%i side=%i\n", drive, fdc_get_bitcell_period(d86f_fdc), d86f_get_bitcell_period(drive), rate, sector, track, side); + d86f_t *dev = d86f[drive]; - d86f[drive].req_sector.id.c = track; - d86f[drive].req_sector.id.h = side; - if (sector == SECTOR_FIRST) - { - d86f[drive].req_sector.id.r = 1; - } - else if (sector == SECTOR_NEXT) - { - d86f[drive].req_sector.id.r++; - } - else - { - d86f[drive].req_sector.id.r = sector; - } - d86f[drive].req_sector.id.n = sector_size; - - if (fdd_get_head(drive) && (d86f_get_sides(drive) == 1)) - { - fdc_noidam(d86f_fdc); - d86f[drive].state = STATE_IDLE; - d86f[drive].index_count = 0; - return 0; - } - - d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = 0; - d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; - d86f[drive].index_count = d86f[drive].error_condition = d86f[drive].satisfying_bytes = 0; - d86f[drive].id_found = 0; - d86f[drive].dma_over = 0; - - return 1; + dev->state = STATE_IDLE; } -void d86f_readsector(int drive, int sector, int track, int side, int rate, int sector_size) + +int +d86f_common_command(int drive, int sector, int track, int side, int rate, int sector_size) { - int ret = 0; + d86f_t *dev = d86f[drive]; - ret = d86f_common_command(drive, sector, track, side, rate, sector_size); - if (!ret) return; + d86f_log("d86f_common_command (drive %i): fdc_period=%i img_period=%i rate=%i sector=%i track=%i side=%i\n", drive, fdc_get_bitcell_period(d86f_fdc), d86f_get_bitcell_period(drive), rate, sector, track, side); - if (sector == SECTOR_FIRST) - d86f[drive].state = STATE_02_SPIN_TO_INDEX; - else if (sector == SECTOR_NEXT) - d86f[drive].state = STATE_02_FIND_ID; - else - d86f[drive].state = fdc_is_deleted(d86f_fdc) ? STATE_0C_FIND_ID : (fdc_is_verify(d86f_fdc) ? STATE_16_FIND_ID : STATE_06_FIND_ID); + dev->req_sector.id.c = track; + dev->req_sector.id.h = side; + if (sector == SECTOR_FIRST) { + dev->req_sector.id.r = 1; + } else if (sector == SECTOR_NEXT) { + dev->req_sector.id.r++; + } else { + dev->req_sector.id.r = sector; + } + dev->req_sector.id.n = sector_size; + + if (fdd_get_head(drive) && (d86f_get_sides(drive) == 1)) { + fdc_noidam(d86f_fdc); + dev->state = STATE_IDLE; + dev->index_count = 0; + return 0; + } + + dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = 0; + dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; + dev->index_count = dev->error_condition = dev->satisfying_bytes = 0; + dev->id_found = 0; + dev->dma_over = 0; + + return 1; } -void d86f_writesector(int drive, int sector, int track, int side, int rate, int sector_size) -{ - int ret = 0; - if (writeprot[drive]) - { - fdc_writeprotect(d86f_fdc); - d86f[drive].state = STATE_IDLE; - d86f[drive].index_count = 0; +void +d86f_readsector(int drive, int sector, int track, int side, int rate, int sector_size) +{ + d86f_t *dev = d86f[drive]; + int ret = 0; + + ret = d86f_common_command(drive, sector, track, side, rate, sector_size); + if (! ret) return; + + if (sector == SECTOR_FIRST) + dev->state = STATE_02_SPIN_TO_INDEX; + else if (sector == SECTOR_NEXT) + dev->state = STATE_02_FIND_ID; + else + dev->state = fdc_is_deleted(d86f_fdc) ? STATE_0C_FIND_ID : (fdc_is_verify(d86f_fdc) ? STATE_16_FIND_ID : STATE_06_FIND_ID); +} + + +void +d86f_writesector(int drive, int sector, int track, int side, int rate, int sector_size) +{ + d86f_t *dev = d86f[drive]; + int ret = 0; + + if (writeprot[drive]) { + fdc_writeprotect(d86f_fdc); + dev->state = STATE_IDLE; + dev->index_count = 0; + return; + } + + ret = d86f_common_command(drive, sector, track, side, rate, sector_size); + if (! ret) return; + + dev->state = fdc_is_deleted(d86f_fdc) ? STATE_09_FIND_ID : STATE_05_FIND_ID; +} + + +void +d86f_comparesector(int drive, int sector, int track, int side, int rate, int sector_size) +{ + d86f_t *dev = d86f[drive]; + int ret = 0; + + ret = d86f_common_command(drive, sector, track, side, rate, sector_size); + if (! ret) return; + + dev->state = STATE_11_FIND_ID; +} + + +void +d86f_readaddress(int drive, int side, int rate) +{ + d86f_t *dev = d86f[drive]; + + if (fdd_get_head(drive) && (d86f_get_sides(drive) == 1)) { + fdc_noidam(d86f_fdc); + dev->state = STATE_IDLE; + dev->index_count = 0; + return; + } + + dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = 0; + dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; + dev->index_count = dev->error_condition = dev->satisfying_bytes = 0; + dev->id_found = 0; + dev->dma_over = 0; + + dev->state = STATE_0A_FIND_ID; +} + + +void +d86f_add_track(int drive, int track, int side) +{ + d86f_t *dev = d86f[drive]; + uint32_t array_size; + int logical_track; + + array_size = d86f_get_array_size(drive, side); + array_size <<= 1; + + if (d86f_get_sides(drive) == 2) { + logical_track = (track << 1) + side; + } else { + if (side) return; - } + logical_track = track; + } - ret = d86f_common_command(drive, sector, track, side, rate, sector_size); - if (!ret) return; + if (! dev->track_offset[logical_track]) { + /* Track is absent from the file, let's add it. */ + dev->track_offset[logical_track] = dev->file_size; - d86f[drive].state = fdc_is_deleted(d86f_fdc) ? STATE_09_FIND_ID : STATE_05_FIND_ID; + dev->file_size += (array_size + 6); + if (d86f_has_extra_bit_cells(drive)) + dev->file_size += 4; + if (d86f_has_surface_desc(drive)) + dev->file_size += array_size; + } } -void d86f_comparesector(int drive, int sector, int track, int side, int rate, int sector_size) + +void +d86f_common_format(int drive, int side, int rate, uint8_t fill, int proxy) { - int ret = 0; + d86f_t *dev = d86f[drive]; + uint32_t i = 0; + uint16_t temp, temp2; + uint32_t array_size; - ret = d86f_common_command(drive, sector, track, side, rate, sector_size); - if (!ret) return; + if (writeprot[drive]) { + fdc_writeprotect(d86f_fdc); + dev->state = STATE_IDLE; + dev->index_count = 0; + return; + } - d86f[drive].state = STATE_11_FIND_ID; -} + if (! d86f_can_format(drive)) { + fdc_cannotformat(d86f_fdc); + dev->state = STATE_IDLE; + dev->index_count = 0; + return; + } -void d86f_readaddress(int drive, int side, int rate) -{ - if (fdd_get_head(drive) && (d86f_get_sides(drive) == 1)) - { - fdc_noidam(d86f_fdc); - d86f[drive].state = STATE_IDLE; - d86f[drive].index_count = 0; - return; - } + if (!side || (d86f_get_sides(drive) == 2)) { + if (! proxy) { + d86f_reset_index_hole_pos(drive, side); - d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = 0; - d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; - d86f[drive].index_count = d86f[drive].error_condition = d86f[drive].satisfying_bytes = 0; - d86f[drive].id_found = 0; - d86f[drive].dma_over = 0; - - d86f[drive].state = STATE_0A_FIND_ID; -} - -void d86f_add_track(int drive, int track, int side) -{ - uint32_t array_size; - int logical_track = 0; - - array_size = d86f_get_array_size(drive, side); - array_size <<= 1; - - if (d86f_get_sides(drive) == 2) - { - logical_track = (track << 1) + side; - } - else - { - if (side) - { + if (dev->cur_track > 256) { + fdc_writeprotect(d86f_fdc); + dev->state = STATE_IDLE; + dev->index_count = 0; return; } - logical_track = track; - } - if (!d86f[drive].track_offset[logical_track]) - { - /* Track is absent from the file, let's add it. */ - d86f[drive].track_offset[logical_track] = d86f[drive].file_size; + array_size = d86f_get_array_size(drive, side); - d86f[drive].file_size += (array_size + 6); - if (d86f_has_extra_bit_cells(drive)) - { - d86f[drive].file_size += 4; - } - if (d86f_has_surface_desc(drive)) - { - d86f[drive].file_size += array_size; + if (d86f_has_surface_desc(drive)) { + /* Preserve the physical holes but get rid of the fuzzy bytes. */ + for (i = 0; i < array_size; i++) { + temp = dev->track_encoded_data[side][i] ^ 0xffff; + temp2 = dev->track_surface_data[side][i]; + temp &= temp2; + dev->track_surface_data[side][i] = temp; + } } + + /* Zero the data buffer. */ + memset(dev->track_encoded_data[side], 0, array_size << 1); + + d86f_add_track(drive, dev->cur_track, side); + if (! fdd_doublestep_40(drive)) + d86f_add_track(drive, dev->cur_track + 1, side); } + } + + dev->fill = fill; + + if (! proxy) { + dev->side_flags[side] = 0; + dev->side_flags[side] |= (fdd_getrpm(real_drive(d86f_fdc, drive)) == 360) ? 0x20 : 0; + dev->side_flags[side] |= fdc_get_bit_rate(d86f_fdc); + dev->side_flags[side] |= fdc_is_mfm(d86f_fdc) ? 8 : 0; + + dev->index_hole_pos[side] = 0; + } + + dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = 0; + dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; + dev->index_count = dev->error_condition = dev->satisfying_bytes = dev->sector_count = 0; + dev->dma_over = 0; + + if (!side || (d86f_get_sides(drive) == 2)) + dev->state = STATE_0D_SPIN_TO_INDEX; + else + dev->state = STATE_0D_NOP_SPIN_TO_INDEX; } -void d86f_common_format(int drive, int side, int rate, uint8_t fill, int proxy) + +void +d86f_proxy_format(int drive, int side, int rate, uint8_t fill) { - int i = 0; - uint16_t temp, temp2; - uint32_t array_size; + d86f_common_format(drive, side, rate, fill, 1); +} - if (writeprot[drive]) - { - fdc_writeprotect(d86f_fdc); - d86f[drive].state = STATE_IDLE; - d86f[drive].index_count = 0; - return; - } - if (!(d86f_can_format(drive))) - { - fdc_cannotformat(d86f_fdc); - d86f[drive].state = STATE_IDLE; - d86f[drive].index_count = 0; - return; - } +void +d86f_format(int drive, int side, int rate, uint8_t fill) +{ + d86f_common_format(drive, side, rate, fill, 0); +} - if (!side || (d86f_get_sides(drive) == 2)) - { - if (!proxy) - { - d86f_reset_index_hole_pos(drive, side); - if (d86f[drive].cur_track > 256) - { - fdc_writeprotect(d86f_fdc); - d86f[drive].state = STATE_IDLE; - d86f[drive].index_count = 0; - return; - } +void +d86f_common_handlers(int drive) +{ + drives[drive].readsector = d86f_readsector; + drives[drive].writesector = d86f_writesector; + drives[drive].comparesector =d86f_comparesector; + drives[drive].readaddress = d86f_readaddress; + drives[drive].byteperiod = d86f_byteperiod; + drives[drive].poll = d86f_poll; + drives[drive].format = d86f_proxy_format; + drives[drive].stop = d86f_stop; +} - array_size = d86f_get_array_size(drive, side); - if (d86f_has_surface_desc(drive)) - { - /* Preserve the physical holes but get rid of the fuzzy bytes. */ - for (i = 0; i < array_size; i++) - { - temp = d86f[drive].track_encoded_data[side][i] ^ 0xffff; - temp2 = d86f[drive].track_surface_data[side][i]; - temp &= temp2; - d86f[drive].track_surface_data[side][i] = temp; - } - } - /* Zero the data buffer. */ - memset(d86f[drive].track_encoded_data[side], 0, array_size << 1); +int +d86f_export(int drive, wchar_t *fn) +{ + uint32_t tt[512]; + d86f_t *dev = d86f[drive]; + d86f_t *temp86; + FILE *f; + int tracks = 86; + int i; + int inc = 1; + uint32_t magic = 0x46423638; + uint16_t version = 0x020B; + uint16_t disk_flags = d86f_handler[drive].disk_flags(drive); - d86f_add_track(drive, d86f[drive].cur_track, side); - if (!fdd_doublestep_40(drive)) - { - d86f_add_track(drive, d86f[drive].cur_track + 1, side); - } - } - } + memset(tt, 0, 512 * sizeof(uint32_t)); - d86f[drive].fill = fill; + f = plat_fopen(fn, L"wb"); + if (!f) + return 0; - if (!proxy) - { - d86f[drive].side_flags[side] = 0; - d86f[drive].side_flags[side] |= (fdd_getrpm(real_drive(d86f_fdc, drive)) == 360) ? 0x20 : 0; - d86f[drive].side_flags[side] |= fdc_get_bit_rate(d86f_fdc); - d86f[drive].side_flags[side] |= fdc_is_mfm(d86f_fdc) ? 8 : 0; + /* Allocate a temporary drive for conversion. */ + temp86 = (d86f_t *)malloc(sizeof(d86f_t)); + memcpy(temp86, dev, sizeof(d86f_t)); - d86f[drive].index_hole_pos[side] = 0; - } + fwrite(&magic, 4, 1, f); + fwrite(&version, 2, 1, f); + fwrite(&disk_flags, 2, 1, f); - d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = 0; - d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; - d86f[drive].index_count = d86f[drive].error_condition = d86f[drive].satisfying_bytes = d86f[drive].sector_count = 0; - d86f[drive].dma_over = 0; + fwrite(tt, 1, ((d86f_get_sides(drive) == 2) ? 2048 : 1024), f); - if (!side || (d86f_get_sides(drive) == 2)) - { - d86f[drive].state = STATE_0D_SPIN_TO_INDEX; - } + /* In the case of a thick track drive, always increment track + by two, since two tracks are going to get output at once. */ + if (!fdd_doublestep_40(drive)) + inc = 2; + + for (i = 0; i < tracks; i += inc) { + if (inc == 2) + fdd_do_seek(drive, i >> 1); else - { - d86f[drive].state = STATE_0D_NOP_SPIN_TO_INDEX; - } + fdd_do_seek(drive, i); + dev->cur_track = i; + d86f_write_tracks(drive, &f, tt); + } + + fclose(f); + + f = plat_fopen(fn, L"rb+"); + + fseek(f, 8, SEEK_SET); + fwrite(tt, 1, ((d86f_get_sides(drive) == 2) ? 2048 : 1024), f); + + fclose(f); + + fdd_do_seek(drive, fdd_current_track(drive)); + + /* Restore the drive from temp. */ + memcpy(dev, temp86, sizeof(d86f_t)); + free(temp86); + + return 1; } -void d86f_proxy_format(int drive, int side, int rate, uint8_t fill) + +void +d86f_load(int drive, wchar_t *fn) { - d86f_common_format(drive, side, rate, fill, 1); -} + wchar_t temp_file_name[2048]; + d86f_t *dev = d86f[drive]; + uint32_t magic = 0; + uint32_t len = 0; + uint16_t temp = 0; + int i = 0; + FILE *tf; -void d86f_format(int drive, int side, int rate, uint8_t fill) -{ - d86f_common_format(drive, side, rate, fill, 0); -} + d86f_unregister(drive); -void d86f_common_handlers(int drive) -{ - drives[drive].readsector = d86f_readsector; - drives[drive].writesector = d86f_writesector; - drives[drive].comparesector=d86f_comparesector; - drives[drive].readaddress = d86f_readaddress; - drives[drive].byteperiod = d86f_byteperiod; - drives[drive].poll = d86f_poll; - drives[drive].format = d86f_proxy_format; - drives[drive].stop = d86f_stop; -} + writeprot[drive] = 0; -int d86f_export(int drive, wchar_t *fn) -{ - FILE *f; - uint32_t tt[512]; - - int tracks = 86; - int i; - - int inc = 1; - - uint32_t magic = 0x46423638; - uint16_t version = 0x020B; - - uint16_t disk_flags = d86f_handler[drive].disk_flags(drive); - - uint32_t struct_size = sizeof(d86f) / (FDD_NUM + 1); - - memset(tt, 0, 512 * sizeof(uint32_t)); - - memcpy(&(d86f[4]), &(d86f[drive]), struct_size); - - f = plat_fopen(fn, L"wb"); - if (!f) - return 0; - - fwrite(&magic, 4, 1, f); - fwrite(&version, 2, 1, f); - fwrite(&disk_flags, 2, 1, f); - - fwrite(tt, 1, ((d86f_get_sides(drive) == 2) ? 2048 : 1024), f); - - /* In the case of a thick track drive, always increment track - by two, since two tracks are going to get output at once. */ - if (!fdd_doublestep_40(drive)) - inc = 2; - - for (i = 0; i < tracks; i += inc) { - if (inc == 2) - fdd_do_seek(drive, i >> 1); - else - fdd_do_seek(drive, i); - d86f[drive].cur_track = i; - d86f_write_tracks(drive, &f, tt); - } - - fclose(f); - - f = plat_fopen(fn, L"rb+"); - - fseek(f, 8, SEEK_SET); - fwrite(tt, 1, ((d86f_get_sides(drive) == 2) ? 2048 : 1024), f); - - fclose(f); - - fdd_do_seek(drive, fdd_current_track(drive)); - - memcpy(&(d86f[drive]), &(d86f[4]), struct_size); - - return 1; -} - -void d86f_load(int drive, wchar_t *fn) -{ - uint32_t magic = 0; - uint32_t len = 0; - wchar_t temp_file_name[2048]; - uint16_t temp = 0; - int i = 0; - FILE *tf; - - d86f_unregister(drive); - - writeprot[drive] = 0; - d86f[drive].f = plat_fopen(fn, L"rb+"); - if (!d86f[drive].f) - { - d86f[drive].f = plat_fopen(fn, L"rb"); - if (!d86f[drive].f) - { - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; - } - writeprot[drive] = 1; - } - if (ui_writeprot[drive]) - { - writeprot[drive] = 1; - } - fwriteprot[drive] = writeprot[drive]; - - fseek(d86f[drive].f, 0, SEEK_END); - len = ftell(d86f[drive].f); - fseek(d86f[drive].f, 0, SEEK_SET); - - fread(&magic, 4, 1, d86f[drive].f); - - if (len < 16) - { - /* File is WAY too small, abort. */ - fclose(d86f[drive].f); - d86f[drive].f = NULL; + dev->f = plat_fopen(fn, L"rb+"); + if (! dev->f) { + dev->f = plat_fopen(fn, L"rb"); + if (! dev->f) { memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); return; } + writeprot[drive] = 1; + } - if ((magic != 0x46423638) && (magic != 0x66623638)) - { - /* File is not of the valid format, abort. */ - d86f_log("86F: Unrecognized magic bytes: %08X\n", magic); - fclose(d86f[drive].f); - d86f[drive].f = NULL; - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; + if (ui_writeprot[drive]) { + writeprot[drive] = 1; + } + fwriteprot[drive] = writeprot[drive]; + + fseek(dev->f, 0, SEEK_END); + len = ftell(dev->f); + fseek(dev->f, 0, SEEK_SET); + + fread(&magic, 4, 1, dev->f); + + if (len < 16) { + /* File is WAY too small, abort. */ + fclose(dev->f); + dev->f = NULL; + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); + return; + } + + if ((magic != 0x46423638) && (magic != 0x66623638)) { + /* File is not of the valid format, abort. */ + d86f_log("86F: Unrecognized magic bytes: %08X\n", magic); + fclose(dev->f); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); + return; + } + + fread(&(dev->version), 2, 1, dev->f); + if (dev->version != D86FVER) { + /* File is not of a recognized format version, abort. */ + if (dev->version == 0x0063) { + d86f_log("86F: File has emulator-internal version 0.99, this version is not valid in a file\n"); + } else if ((dev->version >= 0x0100) && (dev->version < D86FVER)) { + d86f_log("86F: No longer supported development file version: %i.%02i\n", dev->version >> 8, dev->version & 0xff); + } else { + d86f_log("86F: Unrecognized file version: %i.%02i\n", dev->version >> 8, dev->version & 0xff); } + fclose(dev->f); + dev->f = NULL; + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); + return; + } else { + d86f_log("86F: Recognized file version: %i.%02i\n", dev->version >> 8, dev->version & 0xff); + } - fread(&(d86f[drive].version), 2, 1, d86f[drive].f); - - if (d86f[drive].version != D86FVER) - { - /* File is not of a recognized format version, abort. */ - if (d86f[drive].version == 0x0063) - { - d86f_log("86F: File has emulator-internal version 0.99, this version is not valid in a file\n"); - } - else if ((d86f[drive].version >= 0x0100) && (d86f[drive].version < D86FVER)) - { - d86f_log("86F: No longer supported development file version: %i.%02i\n", d86f[drive].version >> 8, d86f[drive].version & 0xFF); - } - else - { - d86f_log("86F: Unrecognized file version: %i.%02i\n", d86f[drive].version >> 8, d86f[drive].version & 0xFF); - } - fclose(d86f[drive].f); - d86f[drive].f = NULL; - ui_sb_update_icon_state(drive, 1); - return; - } - else - { - d86f_log("86F: Recognized file version: %i.%02i\n", d86f[drive].version >> 8, d86f[drive].version & 0xFF); - } - - fread(&(d86f[drive].disk_flags), 2, 1, d86f[drive].f); - - d86f[drive].is_compressed = (magic == 0x66623638) ? 1 : 0; - - if ((len < 51052) && !d86f[drive].is_compressed) - { - /* File too small, abort. */ - fclose(d86f[drive].f); - d86f[drive].f = NULL; - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; - } + fread(&(dev->disk_flags), 2, 1, dev->f); + dev->is_compressed = (magic == 0x66623638) ? 1 : 0; + if ((len < 51052) && !dev->is_compressed) { + /* File too small, abort. */ + fclose(dev->f); + dev->f = NULL; + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); + return; + } #ifdef DO_CRC64 - fseek(d86f[drive].f, 8, SEEK_SET); - fread(&read_crc64, 1, 8, d86f[drive].f); + fseek(dev->f, 8, SEEK_SET); + fread(&read_crc64, 1, 8, dev->f); - fseek(d86f[drive].f, 0, SEEK_SET); + fseek(dev->f, 0, SEEK_SET); - crc64 = 0xffffffffffffffff; + crc64 = 0xffffffffffffffff; - d86f[drive].filebuf = malloc(len); - fread(d86f[drive].filebuf, 1, len, d86f[drive].f); - *(uint64_t *) &(d86f[drive].filebuf[8]) = 0xffffffffffffffff; - crc64 = (uint64_t) crc64speed(0, d86f[drive].filebuf, len); - free(d86f[drive].filebuf); + dev->filebuf = malloc(len); + fread(dev->filebuf, 1, len, dev->f); + *(uint64_t *) &(dev->filebuf[8]) = 0xffffffffffffffff; + crc64 = (uint64_t) crc64speed(0, dev->filebuf, len); + free(dev->filebuf); - if (crc64 != read_crc64) - { - d86f_log("86F: CRC64 error\n"); - fclose(d86f[drive].f); - d86f[drive].f = NULL; - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; - } + if (crc64 != read_crc64) { + d86f_log("86F: CRC64 error\n"); + fclose(dev->f); + dev->f = NULL; + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); + return; + } #endif - if (d86f[drive].is_compressed) - { - memcpy(temp_file_name, drive ? nvr_path(L"TEMP$$$1.$$$") : nvr_path(L"TEMP$$$0.$$$"), 256); - memcpy(d86f[drive].original_file_name, fn, (wcslen(fn) << 1) + 2); + if (dev->is_compressed) { + memcpy(temp_file_name, drive ? nvr_path(L"TEMP$$$1.$$$") : nvr_path(L"TEMP$$$0.$$$"), 256); + memcpy(dev->original_file_name, fn, (wcslen(fn) << 1) + 2); - fclose(d86f[drive].f); - d86f[drive].f = NULL; + fclose(dev->f); + dev->f = NULL; - d86f[drive].f = plat_fopen(temp_file_name, L"wb"); - if (!d86f[drive].f) - { - d86f_log("86F: Unable to create temporary decompressed file\n"); - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; - } - - tf = plat_fopen(fn, L"rb"); - - for (i = 0; i < 8; i++) - { - fread(&temp, 1, 2, tf); - fwrite(&temp, 1, 2, d86f[drive].f); - } - - d86f[drive].filebuf = (uint8_t *) malloc(len); - d86f[drive].outbuf = (uint8_t *) malloc(67108864); - fread(d86f[drive].filebuf, 1, len, tf); - temp = lzf_decompress(d86f[drive].filebuf, len, d86f[drive].outbuf, 67108864); - if (temp) - { - fwrite(d86f[drive].outbuf, 1, temp, d86f[drive].f); - } - free(d86f[drive].outbuf); - free(d86f[drive].filebuf); - - fclose(tf); - fclose(d86f[drive].f); - d86f[drive].f = NULL; - - if (!temp) - { - d86f_log("86F: Error decompressing file\n"); - plat_remove(temp_file_name); - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; - } - - d86f[drive].f = plat_fopen(temp_file_name, L"rb+"); - } - - if (d86f[drive].disk_flags & 0x100) - { - /* Zoned disk. */ - d86f_log("86F: Disk is zoned (Apple or Sony)\n"); - fclose(d86f[drive].f); - d86f[drive].f = NULL; - if (d86f[drive].is_compressed) - { - plat_remove(temp_file_name); - } + dev->f = plat_fopen(temp_file_name, L"wb"); + if (! dev->f) { + d86f_log("86F: Unable to create temporary decompressed file\n"); memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); return; } - if (d86f[drive].disk_flags & 0x600) - { - /* Zone type is not 0 but the disk is fixed-RPM. */ - d86f_log("86F: Disk is fixed-RPM but zone type is not 0\n"); - fclose(d86f[drive].f); - d86f[drive].f = NULL; - if (d86f[drive].is_compressed) - { - plat_remove(temp_file_name); - } - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; + tf = plat_fopen(fn, L"rb"); + + for (i = 0; i < 8; i++) { + fread(&temp, 1, 2, tf); + fwrite(&temp, 1, 2, dev->f); } - if (!writeprot[drive]) - { - writeprot[drive] = (d86f[drive].disk_flags & 0x10) ? 1 : 0; - fwriteprot[drive] = writeprot[drive]; + dev->filebuf = (uint8_t *) malloc(len); + dev->outbuf = (uint8_t *) malloc(67108864); + fread(dev->filebuf, 1, len, tf); + temp = lzf_decompress(dev->filebuf, len, dev->outbuf, 67108864); + if (temp) { + fwrite(dev->outbuf, 1, temp, dev->f); } + free(dev->outbuf); + free(dev->filebuf); - if (writeprot[drive]) - { - fclose(d86f[drive].f); - d86f[drive].f = NULL; + fclose(tf); + fclose(dev->f); + dev->f = NULL; - if (d86f[drive].is_compressed) - { - d86f[drive].f = plat_fopen(temp_file_name, L"rb"); - } - else - { - d86f[drive].f = plat_fopen(fn, L"rb"); - } - } - - fseek(d86f[drive].f, 8, SEEK_SET); - - fread(d86f[drive].track_offset, 1, d86f_get_track_table_size(drive), d86f[drive].f); - - if (!(d86f[drive].track_offset[0])) - { - /* File has no track 0 side 0, abort. */ - d86f_log("86F: No Track 0 side 0\n"); - fclose(d86f[drive].f); - d86f[drive].f = NULL; - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; - } - - if ((d86f_get_sides(drive) == 2) && !(d86f[drive].track_offset[1])) - { - /* File is 2-sided but has no track 0 side 1, abort. */ - d86f_log("86F: No Track 0 side 1\n"); - fclose(d86f[drive].f); - d86f[drive].f = NULL; - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; - } - - /* Load track 0 flags as default. */ - fseek(d86f[drive].f, d86f[drive].track_offset[0], SEEK_SET); - fread(&(d86f[drive].side_flags[0]), 2, 1, d86f[drive].f); - if (d86f[drive].disk_flags & 0x80) - { - fread(&(d86f[drive].extra_bit_cells[0]), 4, 1, d86f[drive].f); - if (d86f[drive].extra_bit_cells[0] < -32768) d86f[drive].extra_bit_cells[0] = -32768; - if (d86f[drive].extra_bit_cells[0] > 32768) d86f[drive].extra_bit_cells[0] = 32768; - } - else - { - d86f[drive].extra_bit_cells[0] = 0; - } - - if (d86f_get_sides(drive) == 2) - { - fseek(d86f[drive].f, d86f[drive].track_offset[1], SEEK_SET); - fread(&(d86f[drive].side_flags[1]), 2, 1, d86f[drive].f); - if (d86f[drive].disk_flags & 0x80) - { - fread(&(d86f[drive].extra_bit_cells[1]), 4, 1, d86f[drive].f); - if (d86f[drive].extra_bit_cells[1] < -32768) d86f[drive].extra_bit_cells[1] = -32768; - if (d86f[drive].extra_bit_cells[1] > 32768) d86f[drive].extra_bit_cells[1] = 32768; - } - else - { - d86f[drive].extra_bit_cells[0] = 0; - } - } - else - { - switch ((d86f[drive].disk_flags >> 1) >> 3) - { - case 0: - default: - d86f[drive].side_flags[1] = 0x0A; - break; - case 1: - d86f[drive].side_flags[1] = 0x00; - break; - case 2: - case 3: - d86f[drive].side_flags[1] = 0x03; - break; - } - d86f[drive].extra_bit_cells[1] = 0; - } - - fseek(d86f[drive].f, 0, SEEK_END); - d86f[drive].file_size = ftell(d86f[drive].f); - - fseek(d86f[drive].f, 0, SEEK_SET); - - d86f_register_86f(drive); - - drives[drive].seek = d86f_seek; - d86f_common_handlers(drive); - drives[drive].format = d86f_format; - - d86f_log("86F: Disk is %scompressed and %s surface description data\n", d86f[drive].is_compressed ? "" : "not ", d86f_has_surface_desc(drive) ? "has" : "does not have"); -} - -void d86f_init() -{ - int i; - - memset(d86f, 0, sizeof(d86f)); - d86f_setupcrc(0x1021); - - for (i = 0; i < (FDD_NUM + 1); i++) - { - d86f[i].state = STATE_IDLE; - d86f_initialize_linked_lists(i); - } -} - -void d86f_set_fdc(void *fdc) -{ - d86f_fdc = (fdc_t *) fdc; -} - -void d86f_close(int drive) -{ - wchar_t temp_file_name[2048]; - - memcpy(temp_file_name, drive ? nvr_path(L"TEMP$$$1.$$$") : nvr_path(L"TEMP$$$0.$$$"), 26); - - if (d86f[drive].f) - { - fclose(d86f[drive].f); - d86f[drive].f = NULL; - } - if (d86f[drive].is_compressed) + if (! temp) { + d86f_log("86F: Error decompressing file\n"); plat_remove(temp_file_name); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); + return; + } + + dev->f = plat_fopen(temp_file_name, L"rb+"); + } + + if (dev->disk_flags & 0x100) { + /* Zoned disk. */ + d86f_log("86F: Disk is zoned (Apple or Sony)\n"); + fclose(dev->f); + dev->f = NULL; + if (dev->is_compressed) { + plat_remove(temp_file_name); + } + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); + return; + } + + if (dev->disk_flags & 0x600) { + /* Zone type is not 0 but the disk is fixed-RPM. */ + d86f_log("86F: Disk is fixed-RPM but zone type is not 0\n"); + fclose(dev->f); + dev->f = NULL; + if (dev->is_compressed) + plat_remove(temp_file_name); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); + return; + } + + if (!writeprot[drive]) { + writeprot[drive] = (dev->disk_flags & 0x10) ? 1 : 0; + fwriteprot[drive] = writeprot[drive]; + } + + if (writeprot[drive]) { + fclose(dev->f); + dev->f = NULL; + + if (dev->is_compressed) + dev->f = plat_fopen(temp_file_name, L"rb"); + else + dev->f = plat_fopen(fn, L"rb"); + } + + /* OK, set the drive data, other code needs it. */ + d86f[drive] = dev; + + fseek(dev->f, 8, SEEK_SET); + + fread(dev->track_offset, 1, d86f_get_track_table_size(drive), dev->f); + + if (! (dev->track_offset[0])) { + /* File has no track 0 side 0, abort. */ + d86f_log("86F: No Track 0 side 0\n"); + fclose(dev->f); + dev->f = NULL; + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); + d86f[drive] = NULL; + return; + } + + if ((d86f_get_sides(drive) == 2) && !(dev->track_offset[1])) { + /* File is 2-sided but has no track 0 side 1, abort. */ + d86f_log("86F: No Track 0 side 1\n"); + fclose(dev->f); + dev->f = NULL; + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); + d86f[drive] = NULL; + return; + } + + /* Load track 0 flags as default. */ + fseek(dev->f, dev->track_offset[0], SEEK_SET); + fread(&(dev->side_flags[0]), 2, 1, dev->f); + if (dev->disk_flags & 0x80) { + fread(&(dev->extra_bit_cells[0]), 4, 1, dev->f); + if (dev->extra_bit_cells[0] < -32768) dev->extra_bit_cells[0] = -32768; + if (dev->extra_bit_cells[0] > 32768) dev->extra_bit_cells[0] = 32768; + } else { + dev->extra_bit_cells[0] = 0; + } + + if (d86f_get_sides(drive) == 2) { + fseek(dev->f, dev->track_offset[1], SEEK_SET); + fread(&(dev->side_flags[1]), 2, 1, dev->f); + if (dev->disk_flags & 0x80) { + fread(&(dev->extra_bit_cells[1]), 4, 1, dev->f); + if (dev->extra_bit_cells[1] < -32768) dev->extra_bit_cells[1] = -32768; + if (dev->extra_bit_cells[1] > 32768) dev->extra_bit_cells[1] = 32768; + } else { + dev->extra_bit_cells[0] = 0; + } + } else { + switch ((dev->disk_flags >> 1) >> 3) { + case 0: + default: + dev->side_flags[1] = 0x0a; + break; + + case 1: + dev->side_flags[1] = 0x00; + break; + + case 2: + case 3: + dev->side_flags[1] = 0x03; + break; + } + + dev->extra_bit_cells[1] = 0; + } + + fseek(dev->f, 0, SEEK_END); + dev->file_size = ftell(dev->f); + + fseek(dev->f, 0, SEEK_SET); + + d86f_register_86f(drive); + + drives[drive].seek = d86f_seek; + d86f_common_handlers(drive); + drives[drive].format = d86f_format; + + d86f_log("86F: Disk is %scompressed and does%s have surface description data\n", + dev->is_compressed ? "" : "not ", + d86f_has_surface_desc(drive) ? "" : " not"); +} + + +void +d86f_init(void) +{ + int i; + + setup_crc(0x1021); + + for (i = 0; i < FDD_NUM; i++) + d86f[i] = NULL; +} + + +void +d86f_set_fdc(void *fdc) +{ + d86f_fdc = (fdc_t *) fdc; +} + + +void +d86f_close(int drive) +{ + wchar_t temp_file_name[2048]; + d86f_t *dev = d86f[drive]; + + /* Make sure the drive is alive. */ + if (dev == NULL) return; + + memcpy(temp_file_name, drive ? nvr_path(L"TEMP$$$1.$$$") : nvr_path(L"TEMP$$$0.$$$"), 26); + + if (dev->f) { + fclose(dev->f); + dev->f = NULL; + } + if (dev->is_compressed) + plat_remove(temp_file_name); +} + + +/* When an FDD is mounted, set up the D86F data structures. */ +void +d86f_setup(int drive) +{ + d86f_t *dev; + + /* Allocate a drive structure. */ + dev = (d86f_t *)malloc(sizeof(d86f_t)); + memset(dev, 0x00, sizeof(d86f_t)); + dev->state = STATE_IDLE; + + dev->last_side_sector[0] = NULL; + dev->last_side_sector[1] = NULL; + + /* Set the drive as active. */ + d86f[drive] = dev; +} + + +/* If an FDD is unmounted, unlink the D86F data structures. */ +void +d86f_destroy(int drive) +{ + d86f_t *dev = d86f[drive]; + + if (dev == NULL) return; + + d86f_destroy_linked_lists(drive, 0); + d86f_destroy_linked_lists(drive, 1); + + free(d86f[drive]); + d86f[drive] = NULL; } diff --git a/src/floppy/fdd_86f.h b/src/floppy/fdd_86f.h index f272ff59b..8242f5bb7 100644 --- a/src/floppy/fdd_86f.h +++ b/src/floppy/fdd_86f.h @@ -1,24 +1,46 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * - * Implementation of the 86F floppy image format (stores the - * data in the form of FM/MFM-encoded transitions) which also - * forms the core of the emulator's floppy disk emulation. + * Definitions for the 86F floppy image format. * - * Version: @(#)floppy_86f.h 1.0.5 2018/03/14 + * Version: @(#)floppy_86f.h 1.0.4 2018/03/17 * - * Author: Miran Grca, + * Authors: Fred N. van Kempen, + * Miran Grca, + * + * Copyright 2018 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ #ifndef EMU_FLOPPY_86F_H # define EMU_FLOPPY_86F_H +#define D86FVER 0x020B + + extern void d86f_init(void); extern void d86f_load(int drive, wchar_t *fn); extern void d86f_close(int drive); @@ -39,6 +61,10 @@ extern void d86f_prepare_track_layout(int drive, int side); extern void d86f_set_version(int drive, uint16_t version); extern uint16_t d86f_side_flags(int drive); extern uint16_t d86f_track_flags(int drive); +extern void d86f_initialize_last_sector_id(int drive, int c, int h, + int r, int n); +extern void d86f_initialize_linked_lists(int drive); +extern void d86f_destroy_linked_lists(int drive, int side); #define length_gap0 80 #define length_gap1 50 @@ -59,19 +85,5 @@ extern uint16_t d86f_track_flags(int drive); #define pre_data length_sync + length_am #define post_gap length_crc -#if 0 -extern int raw_tsize[2]; -extern int gap2_size[2]; -extern int gap3_size[2]; -extern int gap4_size[2]; -#endif - -#define D86FVER 0x020B - -extern void d86f_initialize_last_sector_id(int drive, int c, int h, int r, int n); - -extern void d86f_initialize_linked_lists(int drive); -extern void d86f_destroy_linked_lists(int drive, int side); - #endif /*EMU_FLOPPY_86F_H*/ diff --git a/src/floppy/fdd_common.c b/src/floppy/fdd_common.c index fcd04ab16..5638b0565 100644 --- a/src/floppy/fdd_common.c +++ b/src/floppy/fdd_common.c @@ -1,17 +1,36 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * Shared code for all the floppy modules. * - * Version: @(#)fdd_common.c 1.0.5 2018/01/16 + * Version: @(#)fdd_common.c 1.0.2 2018/03/16 * * Author: Fred N. van Kempen, + * * Copyright 2017,2018 Fred N. van Kempen. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ #include #include @@ -23,11 +42,11 @@ #include "fdd_common.h" -uint8_t fdd_holes[6] = { 0, 0, 0, 1, 1, 2 }; +const uint8_t fdd_holes[6] = { 0, 0, 0, 1, 1, 2 }; -uint8_t fdd_rates[6] = { 2, 2, 1, 4, 0, 3 }; +const uint8_t fdd_rates[6] = { 2, 2, 1, 4, 0, 3 }; -double fdd_bit_rates_300[6] = { +const double fdd_bit_rates_300[6] = { (250.0 * 300.0) / 360.0, 250.0, 300.0, @@ -46,7 +65,7 @@ double fdd_bit_rates_300[6] = { * Disks formatted at 300 kbps @ 300 RPM can be read with any 300 RPM * single-RPM drive by setting the rate to 300 kbps. */ -uint8_t fdd_max_sectors[8][6] = { +const uint8_t fdd_max_sectors[8][6] = { { 26, 31, 38, 53, 64, 118 }, /* 128 */ { 15, 19, 23, 32, 38, 73 }, /* 256 */ { 7, 10, 12, 17, 22, 41 }, /* 512 */ @@ -57,12 +76,12 @@ uint8_t fdd_max_sectors[8][6] = { { 0, 0, 0, 0, 0, 1 } /* 16384 */ }; -uint8_t fdd_dmf_r[21] = { +const uint8_t fdd_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 fdd_gap3_sizes[5][8][48] = { +static const uint8_t fdd_gap3_sizes[5][8][48] = { { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* [0][0] */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, @@ -346,7 +365,6 @@ static uint8_t fdd_gap3_sizes[5][8][48] = { }; - int fdd_get_gap3_size(int rate, int size, int sector) { diff --git a/src/floppy/fdd_common.h b/src/floppy/fdd_common.h index 77d9a4798..02ff78375 100644 --- a/src/floppy/fdd_common.h +++ b/src/floppy/fdd_common.h @@ -1,27 +1,46 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * Shared code for all the floppy modules. * - * Version: @(#)fdd_common.h 1.0.2 2018/01/16 + * Version: @(#)fdd_common.h 1.0.2 2018/03/16 * * Author: Fred N. van Kempen, + * * Copyright 2017,2018 Fred N. van Kempen. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ -#ifndef fdd_COMMON_H -# define fdd_COMMON_H +#ifndef FDD_COMMON_H +# define FDD_COMMON_H -extern uint8_t fdd_holes[6]; -extern uint8_t fdd_rates[6]; -extern double fdd_bit_rates_300[6]; -extern uint8_t fdd_max_sectors[8][6]; -extern uint8_t fdd_dmf_r[21]; +extern const uint8_t fdd_holes[6]; +extern const uint8_t fdd_rates[6]; +extern const double fdd_bit_rates_300[6]; +extern const uint8_t fdd_max_sectors[8][6]; +extern const uint8_t fdd_dmf_r[21]; extern int fdd_get_gap3_size(int rate, int size, int sector); @@ -31,4 +50,4 @@ extern int fdd_bps_valid(uint16_t bps); extern int fdd_interleave(int sector, int skew, int spt); -#endif /*fdd_COMMON_H*/ +#endif /*FDD_COMMON_H*/ diff --git a/src/floppy/fdd_fdi.c b/src/floppy/fdd_fdi.c index d8004fc51..b780fa233 100644 --- a/src/floppy/fdd_fdi.c +++ b/src/floppy/fdd_fdi.c @@ -1,25 +1,46 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * Implementation of the FDI floppy stream image format * interface to the FDI2RAW module. * - * Version: @(#)fdd_fdi.c 1.0.7 2018/01/16 + * Version: @(#)fdd_fdi.c 1.0.2 2018/03/17 * - * Authors: Sarah Walker, + * Authors: Fred N. van Kempen, * Miran Grca, + * Sarah Walker, * - * Copyright 2008-2018 Sarah Walker. + * Copyright 2018 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ #include #include #include +#include #include #include "../86box.h" #include "../plat.h" @@ -31,317 +52,355 @@ #include "fdi2raw.h" -static struct +typedef struct { + FILE *f; + FDI *h; + + int lasttrack; + int sides; + int track; + int tracklen[2][4]; + int trackindex[2][4]; + + uint8_t track_data[2][4][256*1024]; + uint8_t track_timing[2][4][256*1024]; +} fdi_t; + + +static fdi_t *fdi[FDD_NUM]; +static fdc_t *fdi_fdc; + + +static uint16_t +disk_flags(int drive) { - FILE *f; - FDI *h; - uint8_t track_data[2][4][256*1024]; - uint8_t track_timing[2][4][256*1024]; - - int sides; - int track; - int tracklen[2][4]; - int trackindex[2][4]; - - int lasttrack; -} fdi[FDD_NUM]; + fdi_t *dev = fdi[drive]; + uint16_t temp_disk_flags = 0x80; /* We ALWAYS claim to have extra bit cells, even if the actual amount is 0. */ -static fdc_t *fdi_fdc; + switch (fdi2raw_get_bit_rate(dev->h)) { + case 500: + temp_disk_flags |= 2; + break; -uint16_t fdi_disk_flags(int drive) -{ - uint16_t temp_disk_flags = 0x80; /* We ALWAYS claim to have extra bit cells, even if the actual amount is 0. */ + case 300: + case 250: + temp_disk_flags |= 0; + break; - switch (fdi2raw_get_bit_rate(fdi[drive].h)) - { - case 500: - temp_disk_flags |= 2; - break; - case 300: - case 250: - temp_disk_flags |= 0; - break; - case 1000: - temp_disk_flags |= 4; - break; - default: - temp_disk_flags |= 0; - } + case 1000: + temp_disk_flags |= 4; + break; - if (fdi[drive].sides == 2) - { - temp_disk_flags |= 8; - } + default: + temp_disk_flags |= 0; + } - /* Tell the 86F handler that will handle our data to handle it in reverse byte endianness. */ - temp_disk_flags |= 0x800; + if (dev->sides == 2) + temp_disk_flags |= 8; - return temp_disk_flags; + /* + * Tell the 86F handler that we 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) + +static uint16_t +side_flags(int drive) { - uint16_t temp_side_flags = 0; - switch (fdi2raw_get_bit_rate(fdi[drive].h)) - { - case 500: - temp_side_flags = 0; - break; - case 300: - temp_side_flags = 1; - break; - case 250: - temp_side_flags = 2; - break; - case 1000: - temp_side_flags = 3; - break; - default: - temp_side_flags = 2; - } - if (fdi2raw_get_rotation(fdi[drive].h) == 360) - { - temp_side_flags |= 0x20; - } + fdi_t *dev = fdi[drive]; + uint16_t temp_side_flags = 0; - /* 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; + switch (fdi2raw_get_bit_rate(dev->h)) { + case 500: + temp_side_flags = 0; + break; - return temp_side_flags; + case 300: + temp_side_flags = 1; + break; + + case 250: + temp_side_flags = 2; + break; + + case 1000: + temp_side_flags = 3; + break; + + default: + temp_side_flags = 2; + } + + if (fdi2raw_get_rotation(dev->h) == 360) + temp_side_flags |= 0x20; + + /* + * Set the encoding value to match that provided by the FDC. + * Then if it's wrong, it will sector not found anyway. + */ + temp_side_flags |= 0x08; + + return(temp_side_flags); } -int fdi_density() -{ - if (!fdc_is_mfm(fdi_fdc)) - { - return 0; - } - switch (fdc_get_bit_rate(fdi_fdc)) - { - case 0: - return 2; - case 1: - return 1; - case 2: - return 1; - case 3: - case 5: - return 3; - default: - return 1; - } +static int +fdi_density(void) +{ + if (! fdc_is_mfm(fdi_fdc)) return(0); + + switch (fdc_get_bit_rate(fdi_fdc)) { + case 0: + return(2); + + case 1: + return(1); + + case 2: + return(1); + + case 3: + case 5: + return(3); + + default: + break; + } + + return(1); } -int32_t fdi_extra_bit_cells(int drive, int side) + +static int32_t +extra_bit_cells(int drive, int side) { - int density = 0; + fdi_t *dev = fdi[drive]; + int density = 0; + int raw_size = 0; + int is_300_rpm = 0; - int raw_size = 0; + density = fdi_density(); - int is_300_rpm = 0; + is_300_rpm = (fdd_getrpm(drive) == 300); - density = fdi_density(); + switch (fdc_get_bit_rate(fdi_fdc)) { + case 0: + raw_size = is_300_rpm ? 200000 : 166666; + break; - is_300_rpm = (fdd_getrpm(drive) == 300); + case 1: + raw_size = is_300_rpm ? 120000 : 100000; + break; - switch (fdc_get_bit_rate(fdi_fdc)) - { - case 0: - raw_size = is_300_rpm ? 200000 : 166666; - break; - case 1: - raw_size = is_300_rpm ? 120000 : 100000; - break; - case 2: - raw_size = is_300_rpm ? 100000 : 83333; - case 3: - case 5: - raw_size = is_300_rpm ? 400000 : 333333; - break; - default: - raw_size = is_300_rpm ? 100000 : 83333; + case 2: + raw_size = is_300_rpm ? 100000 : 83333; + break; + + case 3: + case 5: + raw_size = is_300_rpm ? 400000 : 333333; + break; + + default: + raw_size = is_300_rpm ? 100000 : 83333; + } + + return((dev->tracklen[side][density] - raw_size)); +} + + +static void +read_revolution(int drive) +{ + fdi_t *dev = fdi[drive]; + int c, den, side; + int track = dev->track; + + if (track > dev->lasttrack) { + for (den = 0; den < 4; den++) { + memset(dev->track_data[0][den], 0, 106096); + memset(dev->track_data[1][den], 0, 106096); + dev->tracklen[0][den] = dev->tracklen[1][den] = 100000; + } + return; + } + + for (den = 0; den < 4; den++) { + for (side = 0; side < dev->sides; side++) { + c = fdi2raw_loadtrack(dev->h, + (uint16_t *)dev->track_data[side][den], + (uint16_t *)dev->track_timing[side][den], + (track * dev->sides) + side, + &dev->tracklen[side][den], + &dev->trackindex[side][den], NULL, den); + if (! c) + memset(dev->track_data[side][den], 0, dev->tracklen[side][den]); } - return (fdi[drive].tracklen[side][density] - raw_size); -} - -int fdi_hole(int drive) -{ - switch (fdi2raw_get_bit_rate(fdi[drive].h)) - { - case 1000: - return 2; - case 500: - return 1; - default: - return 0; + if (dev->sides == 1) { + memset(dev->track_data[1][den], 0, 106096); + dev->tracklen[1][den] = 100000; } + } } -void fdi_read_revolution(int drive) + +static uint32_t +index_hole_pos(int drive, int side) { - int density; - int track = fdi[drive].track; + fdi_t *dev = fdi[drive]; + int density; - int side = 0; + density = fdi_density(); - if (track > fdi[drive].lasttrack) - { - for (density = 0; density < 4; density++) - { - memset(fdi[drive].track_data[0][density], 0, 106096); - memset(fdi[drive].track_data[1][density], 0, 106096); - fdi[drive].tracklen[0][density] = fdi[drive].tracklen[1][density] = 100000; - } - return; - } - - for (density = 0; density < 4; density++) - { - for (side = 0; side < fdi[drive].sides; side++) - { - int c = fdi2raw_loadtrack(fdi[drive].h, (uint16_t *)fdi[drive].track_data[side][density], - (uint16_t *)fdi[drive].track_timing[side][density], - (track * fdi[drive].sides) + side, - &fdi[drive].tracklen[side][density], - &fdi[drive].trackindex[side][density], NULL, density); - if (!c) - memset(fdi[drive].track_data[side][density], 0, fdi[drive].tracklen[side][density]); - } - - if (fdi[drive].sides == 1) - { - memset(fdi[drive].track_data[1][density], 0, 106096); - fdi[drive].tracklen[1][density] = 100000; - } - } + return(dev->trackindex[side][density]); } -uint32_t fdi_index_hole_pos(int drive, int side) + +static uint32_t +get_raw_size(int drive, int side) { - int density; + fdi_t *dev = fdi[drive]; + int density; - density = fdi_density(); + density = fdi_density(); - return fdi[drive].trackindex[side][density]; + return(dev->tracklen[side][density]); } -uint32_t fdi_get_raw_size(int drive, int side) + +static uint16_t * +encoded_data(int drive, int side) { - int density; + fdi_t *dev = fdi[drive]; + int density = 0; - density = fdi_density(); + density = fdi_density(); - return fdi[drive].tracklen[side][density]; + return((uint16_t *)dev->track_data[side][density]); } -uint16_t* fdi_encoded_data(int drive, int side) + +void +fdi_seek(int drive, int track) { - int density = 0; + fdi_t *dev = fdi[drive]; - density = fdi_density(); + if (fdd_doublestep_40(drive)) { + if (fdi2raw_get_tpi(dev->h) < 2) + track /= 2; + } - return (uint16_t *)fdi[drive].track_data[side][density]; -} + d86f_set_cur_track(drive, track); -void d86f_register_fdi(int drive) -{ - d86f_handler[drive].disk_flags = fdi_disk_flags; - d86f_handler[drive].side_flags = fdi_side_flags; - d86f_handler[drive].writeback = null_writeback; - d86f_handler[drive].set_sector = null_set_sector; - d86f_handler[drive].write_data = null_write_data; - d86f_handler[drive].format_conditions = null_format_conditions; - d86f_handler[drive].extra_bit_cells = fdi_extra_bit_cells; - d86f_handler[drive].encoded_data = fdi_encoded_data; - d86f_handler[drive].read_revolution = fdi_read_revolution; - d86f_handler[drive].index_hole_pos = fdi_index_hole_pos; - d86f_handler[drive].get_raw_size = fdi_get_raw_size; - d86f_handler[drive].check_crc = 1; - d86f_set_version(drive, D86FVER); -} + if (dev->f == NULL) return; -void fdi_load(int drive, wchar_t *fn) -{ - char header[26]; - - writeprot[drive] = fwriteprot[drive] = 1; - fdi[drive].f = plat_fopen(fn, L"rb"); - if (!fdi[drive].f) - { - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; - } - - d86f_unregister(drive); - - fread(header, 1, 25, fdi[drive].f); - fseek(fdi[drive].f, 0, SEEK_SET); - header[25] = 0; - if (strcmp(header, "Formatted Disk Image file") != 0) - { - /* This is a Japanese FDI file. */ - pclog("fdi_load(): Japanese FDI file detected, redirecting to IMG loader\n"); - fclose(fdi[drive].f); - fdi[drive].f = NULL; - img_load(drive, fn); - return; - } - - fdi[drive].h = fdi2raw_header(fdi[drive].f); - fdi[drive].lasttrack = fdi2raw_get_last_track(fdi[drive].h); - fdi[drive].sides = fdi2raw_get_last_head(fdi[drive].h) + 1; - - d86f_register_fdi(drive); - - drives[drive].seek = fdi_seek; - d86f_common_handlers(drive); - - pclog("Loaded as FDI\n"); -} - -void fdi_close(int drive) -{ - d86f_unregister(drive); - drives[drive].seek = NULL; - if (fdi[drive].h) - fdi2raw_header_free(fdi[drive].h); - if (fdi[drive].f) - { - fclose(fdi[drive].f); - fdi[drive].f = NULL; - } -} - -void fdi_seek(int drive, int track) -{ - if (fdd_doublestep_40(drive)) - { - if (fdi2raw_get_tpi(fdi[drive].h) < 2) - { - track /= 2; - } - } - - d86f_set_cur_track(drive, track); - - if (!fdi[drive].f) - return; - if (track < 0) - track = 0; + if (track < 0) + track = 0; #if 0 - if (track > fdi[drive].lasttrack) - track = fdi[drive].lasttrack - 1; + if (track > dev->lasttrack) + track = dev->lasttrack - 1; #endif - fdi[drive].track = track; + dev->track = track; - fdi_read_revolution(drive); + read_revolution(drive); } -void fdi_set_fdc(void *fdc) + +void +fdi_load(int drive, wchar_t *fn) { - fdi_fdc = (fdc_t *) fdc; + char header[26]; + fdi_t *dev; + + writeprot[drive] = fwriteprot[drive] = 1; + + /* Allocate a drive block. */ + dev = (fdi_t *)malloc(sizeof(fdi_t)); + memset(dev, 0x00, sizeof(fdi_t)); + + dev->f = plat_fopen(fn, L"rb"); + if (dev == NULL) { + free(dev); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; + } + + d86f_unregister(drive); + + fread(header, 1, 25, dev->f); + fseek(dev->f, 0, SEEK_SET); + header[25] = 0; + if (strcmp(header, "Formatted Disk Image file") != 0) { + /* This is a Japanese FDI file. */ + pclog("fdi_load(): Japanese FDI file detected, redirecting to IMG loader\n"); + fclose(dev->f); + free(dev); + img_load(drive, fn); + return; + } + + /* Set up the drive unit. */ + fdi[drive] = dev; + + dev->h = fdi2raw_header(dev->f); + dev->lasttrack = fdi2raw_get_last_track(dev->h); + dev->sides = fdi2raw_get_last_head(dev->h) + 1; + + /* Attach this format to the D86F engine. */ + d86f_handler[drive].disk_flags = disk_flags; + d86f_handler[drive].side_flags = 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 = extra_bit_cells; + d86f_handler[drive].encoded_data = encoded_data; + d86f_handler[drive].read_revolution = read_revolution; + d86f_handler[drive].index_hole_pos = index_hole_pos; + d86f_handler[drive].get_raw_size = get_raw_size; + d86f_handler[drive].check_crc = 1; + d86f_set_version(drive, D86FVER); + + d86f_common_handlers(drive); + + drives[drive].seek = fdi_seek; + + pclog("Loaded as FDI\n"); +} + + +void +fdi_close(int drive) +{ + fdi_t *dev = fdi[drive]; + + if (dev == NULL) return; + + d86f_unregister(drive); + + drives[drive].seek = NULL; + + if (dev->h) + fdi2raw_header_free(dev->h); + + if (dev->f) + fclose(dev->f); + + /* Release the memory. */ + free(dev); + fdi[drive] = NULL; +} + + +void +fdi_set_fdc(void *fdc) +{ + fdi_fdc = (fdc_t *)fdc; } diff --git a/src/floppy/fdd_fdi.h b/src/floppy/fdd_fdi.h index f63f241e3..4808ecb03 100644 --- a/src/floppy/fdd_fdi.h +++ b/src/floppy/fdd_fdi.h @@ -1,38 +1,49 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * Implementation of the FDI floppy stream image format * interface to the FDI2RAW module. * - * Version: @(#)floppy_fdi.h 1.0.3 2017/12/14 + * Version: @(#)floppy_fdi.h 1.0.2 2018/03/17 * - * Authors: Sarah Walker, + * Authors: Fred N. van Kempen, * Miran Grca, + * Sarah Walker, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ #ifndef EMU_FLOPPY_FDI_H # define EMU_FLOPPY_FDI_H -extern void fdi_load(int drive, wchar_t *fn); -extern void fdi_close(int drive); -extern void fdi_seek(int drive, int track); -extern void fdi_readsector(int drive, int sector, int track, int side, int density, int sector_size); -extern void fdi_writesector(int drive, int sector, int track, int side, int density, int sector_size); -extern void fdi_comparesector(int drive, int sector, int track, int side, int density, int sector_size); -extern void fdi_readaddress(int drive, int sector, int side, int density); -extern void fdi_format(int drive, int sector, int side, int density, uint8_t fill); -extern int fdi_hole(int drive); -extern double fdi_byteperiod(int drive); -extern void fdi_stop(void); -extern void fdi_poll(void); +extern void fdi_seek(int drive, int track); +extern void fdi_load(int drive, wchar_t *fn); +extern void fdi_close(int drive); #endif /*EMU_FLOPPY_FDI_H*/ diff --git a/src/floppy/fdd_imd.c b/src/floppy/fdd_imd.c index 503521e1d..c78e85692 100644 --- a/src/floppy/fdd_imd.c +++ b/src/floppy/fdd_imd.c @@ -1,17 +1,38 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * Implementation of the IMD floppy image format. * - * Version: @(#)fdd_imd.c 1.0.8 2018/03/14 + * Version: @(#)fdd_imd.c 1.0.5 2018/03/17 * - * Author: Miran Grca, + * Authors: Fred N. van Kempen, + * Miran Grca, + * + * Copyright 2018 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ #include #include @@ -25,811 +46,785 @@ #include "fdc.h" -typedef struct -{ - uint8_t is_present; - uint32_t file_offs; - uint8_t params[5]; - uint32_t r_map_offs; - uint32_t c_map_offs; - uint32_t h_map_offs; - uint32_t n_map_offs; - uint32_t data_offs; - uint32_t sector_data_offs[255]; - uint32_t sector_data_size[255]; - uint32_t gap3_len; - uint16_t side_flags; +typedef struct { + uint8_t is_present; + uint32_t file_offs; + uint8_t params[5]; + uint32_t r_map_offs; + uint32_t c_map_offs; + uint32_t h_map_offs; + uint32_t n_map_offs; + uint32_t data_offs; + uint32_t sector_data_offs[255]; + uint32_t sector_data_size[255]; + uint32_t gap3_len; + uint16_t side_flags; } imd_track_t; -static struct -{ - FILE *f; - char *buffer; - uint32_t start_offs; - int track_count, sides; - int track; - uint16_t disk_flags; - int track_width; - imd_track_t tracks[256][2]; - uint16_t current_side_flags[2]; - uint8_t xdf_ordered_pos[256][2]; - uint8_t interleave_ordered_pos[256][2]; - char *current_data[2]; - uint8_t track_buffer[2][25000]; -} imd[FDD_NUM]; +typedef struct { + FILE *f; + char *buffer; + uint32_t start_offs; + int track_count, sides; + int track; + uint16_t disk_flags; + int track_width; + imd_track_t tracks[256][2]; + uint16_t current_side_flags[2]; + uint8_t xdf_ordered_pos[256][2]; + uint8_t interleave_ordered_pos[256][2]; + char *current_data[2]; + uint8_t track_buffer[2][25000]; +} imd_t; -static fdc_t *imd_fdc; -void imd_init() +static imd_t *imd[FDD_NUM]; +static fdc_t *imd_fdc; + + +static uint32_t +get_raw_tsize(int side_flags, int slower_rpm) { - memset(imd, 0, sizeof(imd)); + uint32_t size; + + switch(side_flags & 0x27) { + case 0x22: + size = slower_rpm ? 5314 : 5208; + break; + + default: + case 0x02: + case 0x21: + size = slower_rpm ? 6375 : 6250; + break; + + case 0x01: + size = slower_rpm ? 7650 : 7500; + break; + + case 0x20: + size = slower_rpm ? 10629 : 10416; + break; + + case 0x00: + size = slower_rpm ? 12750 : 12500; + break; + + case 0x23: + size = slower_rpm ? 21258 : 20833; + break; + + case 0x03: + size = slower_rpm ? 25500 : 25000; + break; + + case 0x25: + size = slower_rpm ? 42517 : 41666; + break; + + case 0x05: + size = slower_rpm ? 51000 : 50000; + break; + } + + return(size); } -void d86f_register_imd(int drive); -void imd_load(int drive, wchar_t *fn) +static int +track_is_xdf(int drive, int side, int track) { - uint32_t magic = 0; - uint32_t fsize = 0; - char *buffer; - char *buffer2; - int i = 0; - int track_spt = 0; - int sector_size = 0; - int track = 0; - int side = 0; - int extra = 0; - uint32_t last_offset = 0; - uint32_t data_size = 512; - uint32_t mfm = 0; - uint32_t pre_sector = 0; - uint32_t track_total = 0; - uint32_t raw_tsize = 0; - uint32_t minimum_gap3 = 0; - uint32_t minimum_gap4 = 0; + imd_t *dev = imd[drive]; + int i, effective_sectors, xdf_sectors; + int high_sectors, low_sectors; + int max_high_id, expected_high_count, expected_low_count; + uint8_t *r_map; + uint8_t *n_map; + char *data_base; + char *cur_data; - d86f_unregister(drive); + effective_sectors = xdf_sectors = high_sectors = low_sectors = 0; - writeprot[drive] = 0; - imd[drive].f = plat_fopen(fn, L"rb+"); - if (!imd[drive].f) - { - imd[drive].f = plat_fopen(fn, L"rb"); - if (!imd[drive].f) - { - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; + for (i = 0; i < 256; i++) + dev->xdf_ordered_pos[i][side] = 0; + + if (dev->tracks[track][side].params[2] & 0xC0) return(0); + + if ((dev->tracks[track][side].params[3] != 16) && + (dev->tracks[track][side].params[3] != 19)) return(0); + + r_map = (uint8_t *)(dev->buffer + dev->tracks[track][side].r_map_offs); + data_base = dev->buffer + dev->tracks[track][side].data_offs; + + if (! track) { + if (dev->tracks[track][side].params[4] != 2) return(0); + + if (! side) { + max_high_id = (dev->tracks[track][side].params[3] == 19) ? 0x8B : 0x88; + expected_high_count = (dev->tracks[track][side].params[3] == 19) ? 0x0B : 0x08; + expected_low_count = 8; + } else { + max_high_id = (dev->tracks[track][side].params[3] == 19) ? 0x93 : 0x90; + expected_high_count = (dev->tracks[track][side].params[3] == 19) ? 0x13 : 0x10; + expected_low_count = 0; + } + + for (i = 0; i < dev->tracks[track][side].params[3]; i++) { + if ((r_map[i] >= 0x81) && (r_map[i] <= max_high_id)) { + high_sectors++; + dev->xdf_ordered_pos[(int) r_map[i]][side] = i; } - writeprot[drive] = 1; - } - if (ui_writeprot[drive]) - { - writeprot[drive] = 1; - } - fwriteprot[drive] = writeprot[drive]; - - fseek(imd[drive].f, 0, SEEK_SET); - fread(&magic, 1, 4, imd[drive].f); - if (magic != 0x20444D49) - { - pclog("IMD: Not a valid ImageDisk image\n"); - fclose(imd[drive].f); - imd[drive].f = NULL; - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; - } - else - { - pclog("IMD: Valid ImageDisk image\n"); - } - - fseek(imd[drive].f, 0, SEEK_END); - fsize = ftell(imd[drive].f); - - fseek(imd[drive].f, 0, SEEK_SET); - imd[drive].buffer = malloc(fsize); - fread(imd[drive].buffer, 1, fsize, imd[drive].f); - buffer = imd[drive].buffer; - - buffer2 = strchr(buffer, 0x1A); - if (buffer2 == NULL) - { - pclog("IMD: No ASCII EOF character\n"); - fclose(imd[drive].f); - imd[drive].f = NULL; - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; - } - else - { - pclog("IMD: ASCII EOF character found at offset %08X\n", buffer2 - buffer); - } - - buffer2++; - if ((buffer2 - buffer) == fsize) - { - pclog("IMD: File ends after ASCII EOF character\n"); - fclose(imd[drive].f); - imd[drive].f = NULL; - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; - } - else - { - pclog("IMD: File continues after ASCII EOF character\n"); - } - - imd[drive].start_offs = (buffer2 - buffer); - imd[drive].disk_flags = 0x00; - imd[drive].track_count = 0; - imd[drive].sides = 1; - - while(1) - { - track = buffer2[1]; - side = buffer2[2]; - if (side & 1) imd[drive].sides = 2; - extra = side & 0xC0; - side &= 0x3F; - - imd[drive].tracks[track][side].side_flags = (buffer2[0] % 3); - if (!imd[drive].tracks[track][side].side_flags) imd[drive].disk_flags |= (0x02); - imd[drive].tracks[track][side].side_flags |= (!(buffer2[0] - imd[drive].tracks[track][side].side_flags) ? 0 : 8); - mfm = imd[drive].tracks[track][side].side_flags & 8; - track_total = mfm ? 146 : 73; - pre_sector = mfm ? 60 : 42; - - track_spt = buffer2[3]; - sector_size = buffer2[4]; - if ((track_spt == 15) && (sector_size == 2)) imd[drive].tracks[track][side].side_flags |= 0x20; - if ((track_spt == 16) && (sector_size == 2)) imd[drive].tracks[track][side].side_flags |= 0x20; - if ((track_spt == 17) && (sector_size == 2)) imd[drive].tracks[track][side].side_flags |= 0x20; - if ((track_spt == 8) && (sector_size == 3)) imd[drive].tracks[track][side].side_flags |= 0x20; - if ((imd[drive].tracks[track][side].side_flags & 7) == 1) imd[drive].tracks[track][side].side_flags |= 0x20; - imd[drive].tracks[track][side].is_present = 1; - imd[drive].tracks[track][side].file_offs = (buffer2 - buffer); - memcpy(imd[drive].tracks[track][side].params, buffer2, 5); - imd[drive].tracks[track][side].r_map_offs = imd[drive].tracks[track][side].file_offs + 5; - last_offset = imd[drive].tracks[track][side].r_map_offs + track_spt; - - if (extra & 0x80) - { - imd[drive].tracks[track][side].c_map_offs = last_offset; - last_offset += track_spt; + if ((r_map[i] >= 0x01) && (r_map[i] <= 0x08)) { + low_sectors++; + dev->xdf_ordered_pos[(int) r_map[i]][side] = i; } - - if (extra & 0x40) - { - imd[drive].tracks[track][side].h_map_offs = last_offset; - last_offset += track_spt; + if ((high_sectors == expected_high_count) && (low_sectors == expected_low_count)) { + dev->current_side_flags[side] = (dev->tracks[track][side].params[3] == 19) ? 0x08 : 0x28; + return((dev->tracks[track][side].params[3] == 19) ? 2 : 1); } + return(0); + } + } else { + if (dev->tracks[track][side].params[4] != 0xFF) return(0); - if (sector_size == 0xFF) - { - imd[drive].tracks[track][side].n_map_offs = last_offset; - buffer2 = buffer + last_offset; - last_offset += track_spt; + n_map = (uint8_t *) (dev->buffer + dev->tracks[track][side].n_map_offs); - imd[drive].tracks[track][side].data_offs = last_offset; + cur_data = data_base; + for (i = 0; i < dev->tracks[track][side].params[3]; i++) { + effective_sectors++; + if (!(r_map[i]) && !(n_map[i])) + effective_sectors--; - for (i = 0; i < track_spt; i++) - { - data_size = buffer2[i]; - data_size = 128 << data_size; - imd[drive].tracks[track][side].sector_data_offs[i] = last_offset; - imd[drive].tracks[track][side].sector_data_size[i] = 1; - if (buffer[imd[drive].tracks[track][side].sector_data_offs[i]] != 0) - { - imd[drive].tracks[track][side].sector_data_size[i] += (buffer[imd[drive].tracks[track][side].sector_data_offs[i]] & 1) ? data_size : 1; - } - last_offset += imd[drive].tracks[track][side].sector_data_size[i]; - if (!(buffer[imd[drive].tracks[track][side].sector_data_offs[i]] & 1)) - { - fwriteprot[drive] = writeprot[drive] = 1; - } - track_total += (pre_sector + data_size + 2); - } - } - else - { - imd[drive].tracks[track][side].data_offs = last_offset; - - for (i = 0; i < track_spt; i++) - { - data_size = sector_size; - data_size = 128 << data_size; - imd[drive].tracks[track][side].sector_data_offs[i] = last_offset; - imd[drive].tracks[track][side].sector_data_size[i] = 1; - if (buffer[imd[drive].tracks[track][side].sector_data_offs[i]] != 0) - { - imd[drive].tracks[track][side].sector_data_size[i] += (buffer[imd[drive].tracks[track][side].sector_data_offs[i]] & 1) ? data_size : 1; - } - last_offset += imd[drive].tracks[track][side].sector_data_size[i]; - if (!(buffer[imd[drive].tracks[track][side].sector_data_offs[i]] & 1)) - { - fwriteprot[drive] = writeprot[drive] = 1; - } - track_total += (pre_sector + data_size + 2); - } - } - buffer2 = buffer + last_offset; - - /* Leaving even GAP4: 80 : 40 */ - /* Leaving only GAP1: 96 : 47 */ - /* Not leaving even GAP1: 146 : 73 */ - raw_tsize = td0_get_raw_tsize(imd[drive].tracks[track][side].side_flags, 0); - minimum_gap3 = 12 * track_spt; - if ((raw_tsize - track_total + (mfm ? 146 : 73)) < (minimum_gap3 + minimum_gap4)) - { - /* If we can't fit the sectors with a reasonable minimum gap at perfect RPM, let's try 2% slower. */ - raw_tsize = td0_get_raw_tsize(imd[drive].tracks[track][side].side_flags, 1); - /* Set disk flags so that rotation speed is 2% slower. */ - imd[drive].disk_flags |= (3 << 5); - if ((raw_tsize - track_total + (mfm ? 146 : 73)) < (minimum_gap3 + minimum_gap4)) - { - /* If we can't fit the sectors with a reasonable minimum gap even at 2% slower RPM, abort. */ - pclog("IMD: Unable to fit the %i sectors in a track\n", track_spt); - fclose(imd[drive].f); - imd[drive].f = NULL; - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; - } - } - imd[drive].tracks[track][side].gap3_len = (raw_tsize - track_total - minimum_gap4 + (mfm ? 146 : 73)) / track_spt; - - imd[drive].track_count++; - - if (last_offset >= fsize) - { - break; + if (r_map[i] == (n_map[i] | 0x80)) { + xdf_sectors++; + dev->xdf_ordered_pos[(int) r_map[i]][side] = i; } + cur_data += (128 << ((uint32_t) n_map[i])); } - 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. */ + if ((effective_sectors == 3) && (xdf_sectors == 3)) { + dev->current_side_flags[side] = 0x28; + return(1); /* 5.25" 2HD XDF */ + } - d86f_register_imd(drive); + if ((effective_sectors == 4) && (xdf_sectors == 4)) { + dev->current_side_flags[side] = 0x08; + return(2); /* 3.5" 2HD XDF */ + } - drives[drive].seek = imd_seek; + return(0); + } - d86f_common_handlers(drive); + return(0); } -void imd_close(int drive) + +static int +track_is_interleave(int drive, int side, int track) { - int i = 0; - d86f_unregister(drive); - if (imd[drive].f) - { - free(imd[drive].buffer); - for (i = 0; i < 256; i++) - { - memset(&(imd[drive].tracks[i][0]), 0, sizeof(imd_track_t)); - memset(&(imd[drive].tracks[i][1]), 0, sizeof(imd_track_t)); - } - fclose(imd[drive].f); - imd[drive].f = NULL; + imd_t *dev = imd[drive]; + int i, effective_sectors; + char *r_map; + int track_spt; + + effective_sectors = 0; + + for (i = 0; i < 256; i++) + dev->interleave_ordered_pos[i][side] = 0; + + track_spt = dev->tracks[track][side].params[3]; + + r_map = dev->buffer + dev->tracks[track][side].r_map_offs; + + if (dev->tracks[track][side].params[2] & 0xC0) return(0); + + if (track_spt != 21) return(0); + + if (dev->tracks[track][side].params[4] != 2) return(0); + + for (i = 0; i < track_spt; i++) { + if ((r_map[i] >= 1) && (r_map[i] <= track_spt)) { + effective_sectors++; + dev->interleave_ordered_pos[(int) r_map[i]][side] = i; } + } + + if (effective_sectors == track_spt) return(1); + + return(0); } -int imd_track_is_xdf(int drive, int side, int track) + +static void +sector_to_buffer(int drive, int track, int side, uint8_t *buffer, int sector, int len) { - int i, effective_sectors, xdf_sectors; - int high_sectors, low_sectors; - int max_high_id, expected_high_count, expected_low_count; - uint8_t *r_map; - uint8_t *n_map; - char *data_base; - char *cur_data; + imd_t *dev = imd[drive]; + int type = dev->buffer[dev->tracks[track][side].sector_data_offs[sector]]; - effective_sectors = xdf_sectors = high_sectors = low_sectors = 0; - - for (i = 0; i < 256; i++) - { - imd[drive].xdf_ordered_pos[i][side] = 0; - } - - if (imd[drive].tracks[track][side].params[2] & 0xC0) - { - return 0; - } - if ((imd[drive].tracks[track][side].params[3] != 16) && (imd[drive].tracks[track][side].params[3] != 19)) - { - return 0; - } - r_map = (uint8_t *) (imd[drive].buffer + imd[drive].tracks[track][side].r_map_offs); - data_base = imd[drive].buffer + imd[drive].tracks[track][side].data_offs; - - if (!track) - { - if (imd[drive].tracks[track][side].params[4] != 2) - { - return 0; - } - if (!side) - { - max_high_id = (imd[drive].tracks[track][side].params[3] == 19) ? 0x8B : 0x88; - expected_high_count = (imd[drive].tracks[track][side].params[3] == 19) ? 0x0B : 0x08; - expected_low_count = 8; - } - else - { - max_high_id = (imd[drive].tracks[track][side].params[3] == 19) ? 0x93 : 0x90; - expected_high_count = (imd[drive].tracks[track][side].params[3] == 19) ? 0x13 : 0x10; - expected_low_count = 0; - } - for (i = 0; i < imd[drive].tracks[track][side].params[3]; i++) - { - if ((r_map[i] >= 0x81) && (r_map[i] <= max_high_id)) - { - high_sectors++; - imd[drive].xdf_ordered_pos[(int) r_map[i]][side] = i; - } - if ((r_map[i] >= 0x01) && (r_map[i] <= 0x08)) - { - low_sectors++; - imd[drive].xdf_ordered_pos[(int) r_map[i]][side] = i; - } - if ((high_sectors == expected_high_count) && (low_sectors == expected_low_count)) - { - imd[drive].current_side_flags[side] = (imd[drive].tracks[track][side].params[3] == 19) ? 0x08 : 0x28; - return (imd[drive].tracks[track][side].params[3] == 19) ? 2 : 1; - } - return 0; - } - } - else - { - if (imd[drive].tracks[track][side].params[4] != 0xFF) - { - return 0; - } - - n_map = (uint8_t *) (imd[drive].buffer + imd[drive].tracks[track][side].n_map_offs); - - cur_data = data_base; - for (i = 0; i < imd[drive].tracks[track][side].params[3]; i++) - { - effective_sectors++; - if (!(r_map[i]) && !(n_map[i])) - { - effective_sectors--; - } - if (r_map[i] == (n_map[i] | 0x80)) - { - xdf_sectors++; - imd[drive].xdf_ordered_pos[(int) r_map[i]][side] = i; - } - cur_data += (128 << ((uint32_t) n_map[i])); - } - if ((effective_sectors == 3) && (xdf_sectors == 3)) - { - imd[drive].current_side_flags[side] = 0x28; - return 1; /* 5.25" 2HD XDF */ - } - if ((effective_sectors == 4) && (xdf_sectors == 4)) - { - imd[drive].current_side_flags[side] = 0x08; - return 2; /* 3.5" 2HD XDF */ - } - return 0; - } - - return 0; + if (type == 0) + memset(buffer, 0x00, len); + else { + if (type & 1) + memcpy(buffer, &(dev->buffer[dev->tracks[track][side].sector_data_offs[sector] + 1]), len); + else + memset(buffer, dev->buffer[dev->tracks[track][side].sector_data_offs[sector] + 1], len); + } } -int imd_track_is_interleave(int drive, int side, int track) + +static void +imd_seek(int drive, int track) { - int i, effective_sectors; - char *r_map; - int track_spt; + uint32_t track_buf_pos[2] = { 0, 0 }; + uint8_t id[4] = { 0, 0, 0, 0 }; + uint8_t type, deleted, bad_crc; + imd_t *dev = imd[drive]; + int sector, current_pos; + int side, c = 0, h, n; + int ssize = 512; + int track_rate = 0; + int track_gap2 = 22; + int track_gap3 = 12; + int xdf_type = 0; + int interleave_type = 0; + int is_trackx = 0; + int xdf_spt = 0; + int xdf_sector = 0; + int ordered_pos = 0; + int real_sector = 0; + int actual_sector = 0; + char *c_map = NULL; + char *h_map = NULL; + char *r_map; + char *n_map = NULL; + uint8_t *data; - effective_sectors = 0; + if (dev->f == NULL) return; - for (i = 0; i < 256; i++) - { - imd[drive].interleave_ordered_pos[i][side] = 0; - } + if (!dev->track_width && fdd_doublestep_40(drive)) + track /= 2; - track_spt = imd[drive].tracks[track][side].params[3]; + d86f_set_cur_track(drive, track); - r_map = imd[drive].buffer + imd[drive].tracks[track][side].r_map_offs; + is_trackx = (track == 0) ? 0 : 1; - if (imd[drive].tracks[track][side].params[2] & 0xC0) - { - return 0; - } - if (track_spt != 21) - { - return 0; - } - if (imd[drive].tracks[track][side].params[4] != 2) - { - return 0; - } + dev->track = track; - for (i = 0; i < track_spt; i++) - { - if ((r_map[i] >= 1) && (r_map[i] <= track_spt)) - { - effective_sectors++; - imd[drive].interleave_ordered_pos[(int) r_map[i]][side] = i; - } - } + dev->current_side_flags[0] = dev->tracks[track][0].side_flags; + dev->current_side_flags[1] = dev->tracks[track][1].side_flags; - if (effective_sectors == track_spt) - { - return 1; - } - return 0; -} + d86f_reset_index_hole_pos(drive, 0); + d86f_reset_index_hole_pos(drive, 1); -void imd_sector_to_buffer(int drive, int track, int side, uint8_t *buffer, int sector, int len) -{ - int type = imd[drive].buffer[imd[drive].tracks[track][side].sector_data_offs[sector]]; - if (type == 0) - { - memset(buffer, 0, len); - } - else - { - if (type & 1) - { - memcpy(buffer, &(imd[drive].buffer[imd[drive].tracks[track][side].sector_data_offs[sector] + 1]), len); - } - else - { - memset(buffer, imd[drive].buffer[imd[drive].tracks[track][side].sector_data_offs[sector] + 1], len); - } - } -} + d86f_destroy_linked_lists(drive, 0); + d86f_destroy_linked_lists(drive, 1); -void imd_seek(int drive, int track) -{ - int side; - - uint8_t id[4] = { 0, 0, 0, 0 }; - uint8_t type, deleted, bad_crc; - - int sector, current_pos; - - int c = 0; - int h = 0; - int n = 0; - int ssize = 512; - - int track_rate = 0; - - int track_gap2 = 22; - int track_gap3 = 12; - - int xdf_type = 0; - int interleave_type = 0; - - int is_trackx = 0; - - int xdf_spt = 0; - int xdf_sector = 0; - - int ordered_pos = 0; - - int real_sector = 0; - int actual_sector = 0; - - char *c_map = NULL; - char *h_map = NULL; - char *r_map; - char *n_map = NULL; - uint8_t *data; - uint32_t track_buf_pos[2] = { 0, 0 }; - - if (!imd[drive].f) - return; - - if (!imd[drive].track_width && fdd_doublestep_40(drive)) - track /= 2; - - d86f_set_cur_track(drive, track); - - is_trackx = (track == 0) ? 0 : 1; - - imd[drive].track = track; - - imd[drive].current_side_flags[0] = imd[drive].tracks[track][0].side_flags; - imd[drive].current_side_flags[1] = imd[drive].tracks[track][1].side_flags; - - d86f_reset_index_hole_pos(drive, 0); - d86f_reset_index_hole_pos(drive, 1); - - d86f_destroy_linked_lists(drive, 0); - d86f_destroy_linked_lists(drive, 1); - - if (track > imd[drive].track_count) - { - d86f_zero_track(drive); - return; - } - - for (side = 0; side < imd[drive].sides; side++) - { - track_rate = imd[drive].current_side_flags[side] & 7; - if (!track_rate && (imd[drive].current_side_flags[side] & 0x20)) track_rate = 4; - if ((imd[drive].current_side_flags[side] & 0x27) == 0x21) track_rate = 2; - - r_map = imd[drive].buffer + imd[drive].tracks[track][side].r_map_offs; - h = imd[drive].tracks[track][side].params[2]; - if (h & 0x80) - { - c_map = imd[drive].buffer + imd[drive].tracks[track][side].c_map_offs; - } - else - { - c = imd[drive].tracks[track][side].params[1]; - } - if (h & 0x40) - { - h_map = imd[drive].buffer + imd[drive].tracks[track][side].h_map_offs; - } - n = imd[drive].tracks[track][side].params[4]; - if (n == 0xFF) - { - n_map = imd[drive].buffer + imd[drive].tracks[track][side].n_map_offs; - track_gap3 = gap3_sizes[track_rate][(int) n_map[0]][imd[drive].tracks[track][side].params[3]]; - } - else - { - track_gap3 = gap3_sizes[track_rate][n][imd[drive].tracks[track][side].params[3]]; - } - if (!track_gap3) - { - track_gap3 = imd[drive].tracks[track][side].gap3_len; - } - - xdf_type = imd_track_is_xdf(drive, side, track); - - interleave_type = imd_track_is_interleave(drive, side, track); - - current_pos = d86f_prepare_pretrack(drive, side, 0); - - if (!xdf_type) - { - for (sector = 0; sector < imd[drive].tracks[track][side].params[3]; sector++) - { - if (interleave_type == 0) - { - real_sector = r_map[sector]; - actual_sector = sector; - } - else - { - real_sector = dmf_r[sector]; - actual_sector = imd[drive].interleave_ordered_pos[real_sector][side]; - } - id[0] = (h & 0x80) ? c_map[actual_sector] : c; - id[1] = (h & 0x40) ? h_map[actual_sector] : (h & 1); - id[2] = real_sector; - id[3] = (n == 0xFF) ? n_map[actual_sector] : n; - ssize = 128 << ((uint32_t) id[3]); - data = imd[drive].track_buffer[side] + track_buf_pos[side]; - type = imd[drive].buffer[imd[drive].tracks[track][side].sector_data_offs[actual_sector]]; - type = (type >> 1) & 7; - deleted = bad_crc = 0; - if ((type == 2) || (type == 4)) deleted = 1; - if ((type == 3) || (type == 4)) bad_crc = 1; - - imd_sector_to_buffer(drive, track, side, data, actual_sector, ssize); - current_pos = d86f_prepare_sector(drive, side, current_pos, id, data, ssize, 22, track_gap3, deleted, bad_crc); - track_buf_pos[side] += ssize; - - if (sector == 0) - { - d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); - } - } - } - else - { - xdf_type--; - xdf_spt = xdf_physical_sectors[xdf_type][is_trackx]; - for (sector = 0; sector < xdf_spt; sector++) - { - xdf_sector = (side * xdf_spt) + sector; - id[0] = track; - id[1] = side; - id[2] = xdf_disk_layout[xdf_type][is_trackx][xdf_sector].id.r; - id[3] = is_trackx ? (id[2] & 7) : 2; - ssize = 128 << ((uint32_t) id[3]); - ordered_pos = imd[drive].xdf_ordered_pos[id[2]][side]; - - data = imd[drive].track_buffer[side] + track_buf_pos[side]; - type = imd[drive].buffer[imd[drive].tracks[track][side].sector_data_offs[ordered_pos]]; - type = (type >> 1) & 7; - deleted = bad_crc = 0; - if ((type == 2) || (type == 4)) deleted = 1; - if ((type == 3) || (type == 4)) bad_crc = 1; - imd_sector_to_buffer(drive, track, side, data, ordered_pos, ssize); - - if (is_trackx) - { - current_pos = d86f_prepare_sector(drive, side, xdf_trackx_spos[xdf_type][xdf_sector], id, data, ssize, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], deleted, bad_crc); - } - else - { - current_pos = d86f_prepare_sector(drive, side, current_pos, id, data, ssize, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], deleted, bad_crc); - } - - track_buf_pos[side] += ssize; - - if (sector == 0) - { - d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); - } - } - } - } -} - -uint16_t imd_disk_flags(int drive) -{ - return imd[drive].disk_flags; -} - -uint16_t imd_side_flags(int drive) -{ - int side = 0; - uint8_t sflags = 0; - side = fdd_get_head(drive); - sflags = imd[drive].current_side_flags[side]; - return sflags; -} - -void imd_set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n) -{ - int i = 0; - int track = imd[drive].track; - int sc = 0; - int sh = 0; - int sn = 0; - char *c_map = 0, *h_map = 0, *r_map = 0, *n_map = 0; - uint8_t id[4] = { 0, 0, 0, 0 }; - sc = imd[drive].tracks[track][side].params[1]; - sh = imd[drive].tracks[track][side].params[2]; - sn = imd[drive].tracks[track][side].params[4]; - if (sh & 0x80) - { - c_map = imd[drive].buffer + imd[drive].tracks[track][side].c_map_offs; - } - if (sh & 0x40) - { - h_map = imd[drive].buffer + imd[drive].tracks[track][side].h_map_offs; - } - r_map = imd[drive].buffer + imd[drive].tracks[track][side].r_map_offs; - if (sn == 0xFF) - { - n_map = imd[drive].buffer + imd[drive].tracks[track][side].n_map_offs; - } - if (c != imd[drive].track) return; - for (i = 0; i < imd[drive].tracks[track][side].params[3]; i++) - { - id[0] = (sh & 0x80) ? c_map[i] : sc; - id[1] = (sh & 0x40) ? h_map[i] : (sh & 1); - id[2] = r_map[i]; - id[3] = (sn == 0xFF) ? n_map[i] : sn; - if ((id[0] == c) && - (id[1] == h) && - (id[2] == r) && - (id[3] == n)) - { - imd[drive].current_data[side] = imd[drive].buffer + imd[drive].tracks[track][side].sector_data_offs[i]; - } - } + if (track > dev->track_count) { + d86f_zero_track(drive); return; -} + } -void imd_writeback(int drive) -{ - int side; - int track = imd[drive].track; + for (side = 0; side < dev->sides; side++) { + track_rate = dev->current_side_flags[side] & 7; + if (!track_rate && (dev->current_side_flags[side] & 0x20)) + track_rate = 4; + if ((dev->current_side_flags[side] & 0x27) == 0x21) + track_rate = 2; - int i = 0; + r_map = dev->buffer + dev->tracks[track][side].r_map_offs; + h = dev->tracks[track][side].params[2]; + if (h & 0x80) + c_map = dev->buffer + dev->tracks[track][side].c_map_offs; + else + c = dev->tracks[track][side].params[1]; - char *n_map = 0; + if (h & 0x40) + h_map = dev->buffer + dev->tracks[track][side].h_map_offs; - uint8_t h, n, spt; - uint32_t ssize; - - if (writeprot[drive]) - { - return; + n = dev->tracks[track][side].params[4]; + if (n == 0xFF) { + n_map = dev->buffer + dev->tracks[track][side].n_map_offs; + track_gap3 = gap3_sizes[track_rate][(int) n_map[0]][dev->tracks[track][side].params[3]]; + } else { + track_gap3 = gap3_sizes[track_rate][n][dev->tracks[track][side].params[3]]; } - for (side = 0; side < imd[drive].sides; side++) - { - if (imd[drive].tracks[track][side].is_present) - { - fseek(imd[drive].f, imd[drive].tracks[track][side].file_offs, SEEK_SET); - h = imd[drive].tracks[track][side].params[2]; - spt = imd[drive].tracks[track][side].params[3]; - n = imd[drive].tracks[track][side].params[4]; - fwrite(imd[drive].tracks[track][side].params, 1, 5, imd[drive].f); - if (h & 0x80) - { - fwrite(imd[drive].buffer + imd[drive].tracks[track][side].c_map_offs, 1, spt, imd[drive].f); - } - if (h & 0x40) - { - fwrite(imd[drive].buffer + imd[drive].tracks[track][side].h_map_offs, 1, spt, imd[drive].f); - } - if (n == 0xFF) - { - n_map = imd[drive].buffer + imd[drive].tracks[track][side].n_map_offs; - fwrite(n_map, 1, spt, imd[drive].f); - } - for (i = 0; i < spt; i++) - { - ssize = (n == 0xFF) ? n_map[i] : n; - ssize = 128 << ssize; - fwrite(imd[drive].buffer + imd[drive].tracks[track][side].sector_data_offs[i], 1, ssize, imd[drive].f); + if (! track_gap3) + track_gap3 = dev->tracks[track][side].gap3_len; + + xdf_type = track_is_xdf(drive, side, track); + + interleave_type = track_is_interleave(drive, side, track); + + current_pos = d86f_prepare_pretrack(drive, side, 0); + + if (! xdf_type) { + for (sector = 0; sector < dev->tracks[track][side].params[3]; sector++) { + if (interleave_type == 0) { + real_sector = r_map[sector]; + actual_sector = sector; + } else { + real_sector = dmf_r[sector]; + actual_sector = dev->interleave_ordered_pos[real_sector][side]; } + id[0] = (h & 0x80) ? c_map[actual_sector] : c; + id[1] = (h & 0x40) ? h_map[actual_sector] : (h & 1); + id[2] = real_sector; + id[3] = (n == 0xFF) ? n_map[actual_sector] : n; + ssize = 128 << ((uint32_t) id[3]); + data = dev->track_buffer[side] + track_buf_pos[side]; + type = dev->buffer[dev->tracks[track][side].sector_data_offs[actual_sector]]; + type = (type >> 1) & 7; + deleted = bad_crc = 0; + if ((type == 2) || (type == 4)) deleted = 1; + if ((type == 3) || (type == 4)) bad_crc = 1; + + sector_to_buffer(drive, track, side, data, actual_sector, ssize); + current_pos = d86f_prepare_sector(drive, side, current_pos, id, data, ssize, 22, track_gap3, deleted, bad_crc); + track_buf_pos[side] += ssize; + + if (sector == 0) + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + } + } else { + xdf_type--; + xdf_spt = xdf_physical_sectors[xdf_type][is_trackx]; + for (sector = 0; sector < xdf_spt; sector++) { + xdf_sector = (side * xdf_spt) + sector; + id[0] = track; + id[1] = side; + id[2] = xdf_disk_layout[xdf_type][is_trackx][xdf_sector].id.r; + id[3] = is_trackx ? (id[2] & 7) : 2; + ssize = 128 << ((uint32_t) id[3]); + ordered_pos = dev->xdf_ordered_pos[id[2]][side]; + + data = dev->track_buffer[side] + track_buf_pos[side]; + type = dev->buffer[dev->tracks[track][side].sector_data_offs[ordered_pos]]; + type = (type >> 1) & 7; + deleted = bad_crc = 0; + if ((type == 2) || (type == 4)) deleted = 1; + if ((type == 3) || (type == 4)) bad_crc = 1; + sector_to_buffer(drive, track, side, data, ordered_pos, ssize); + + if (is_trackx) + current_pos = d86f_prepare_sector(drive, side, xdf_trackx_spos[xdf_type][xdf_sector], id, data, ssize, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], deleted, bad_crc); + else + current_pos = d86f_prepare_sector(drive, side, current_pos, id, data, ssize, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], deleted, bad_crc); + + track_buf_pos[side] += ssize; + + if (sector == 0) + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); } } + } } -uint8_t imd_poll_read_data(int drive, int side, uint16_t pos) + +static uint16_t +disk_flags(int drive) { - int type = imd[drive].current_data[side][0]; - if (!(type & 1)) - { - return 0xf6; /* Should never happen. */ + imd_t *dev = imd[drive]; + + return(dev->disk_flags); +} + + +static uint16_t +side_flags(int drive) +{ + imd_t *dev = imd[drive]; + int side = 0; + uint16_t sflags = 0; + + side = fdd_get_head(drive); + sflags = dev->current_side_flags[side]; + + return(sflags); +} + + +static void +set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n) +{ + imd_t *dev = imd[drive]; + int track = dev->track; + int i, sc, sh, sn; + char *c_map = NULL, *h_map = NULL, *r_map = NULL, *n_map = NULL; + uint8_t id[4] = { 0, 0, 0, 0 }; + sc = dev->tracks[track][side].params[1]; + sh = dev->tracks[track][side].params[2]; + sn = dev->tracks[track][side].params[4]; + + if (sh & 0x80) + c_map = dev->buffer + dev->tracks[track][side].c_map_offs; + if (sh & 0x40) + h_map = dev->buffer + dev->tracks[track][side].h_map_offs; + r_map = dev->buffer + dev->tracks[track][side].r_map_offs; + + if (sn == 0xFF) + n_map = dev->buffer + dev->tracks[track][side].n_map_offs; + + if (c != dev->track) return; + + for (i = 0; i < dev->tracks[track][side].params[3]; i++) { + id[0] = (sh & 0x80) ? c_map[i] : sc; + id[1] = (sh & 0x40) ? h_map[i] : (sh & 1); + id[2] = r_map[i]; + id[3] = (sn == 0xFF) ? n_map[i] : sn; + if ((id[0] == c) && (id[1] == h) && (id[2] == r) && (id[3] == n)) { + dev->current_data[side] = dev->buffer + dev->tracks[track][side].sector_data_offs[i]; } - return imd[drive].current_data[side][pos + 1]; + } } -void imd_poll_write_data(int drive, int side, uint16_t pos, uint8_t data) + +static void +imd_writeback(int drive) { - int type = imd[drive].current_data[side][0]; - if (writeprot[drive]) - { + imd_t *dev = imd[drive]; + int side; + int track = dev->track; + int i = 0; + char *n_map = 0; + uint8_t h, n, spt; + uint32_t ssize; + + if (writeprot[drive]) return; + + for (side = 0; side < dev->sides; side++) { + if (dev->tracks[track][side].is_present) { + fseek(dev->f, dev->tracks[track][side].file_offs, SEEK_SET); + h = dev->tracks[track][side].params[2]; + spt = dev->tracks[track][side].params[3]; + n = dev->tracks[track][side].params[4]; + fwrite(dev->tracks[track][side].params, 1, 5, dev->f); + + if (h & 0x80) + fwrite(dev->buffer + dev->tracks[track][side].c_map_offs, 1, spt, dev->f); + + if (h & 0x40) + fwrite(dev->buffer + dev->tracks[track][side].h_map_offs, 1, spt, dev->f); + + if (n == 0xFF) { + n_map = dev->buffer + dev->tracks[track][side].n_map_offs; + fwrite(n_map, 1, spt, dev->f); + } + for (i = 0; i < spt; i++) { + ssize = (n == 0xFF) ? n_map[i] : n; + ssize = 128 << ssize; + fwrite(dev->buffer + dev->tracks[track][side].sector_data_offs[i], 1, ssize, dev->f); + } + } + } +} + + +static uint8_t +poll_read_data(int drive, int side, uint16_t pos) +{ + imd_t *dev = imd[drive]; + int type = dev->current_data[side][0]; + + if (! (type & 1)) return(0xf6); /* Should never happen. */ + + return(dev->current_data[side][pos + 1]); +} + + +static void +poll_write_data(int drive, int side, uint16_t pos, uint8_t data) +{ + imd_t *dev = imd[drive]; + int type = dev->current_data[side][0]; + + if (writeprot[drive]) return; + + if (! (type & 1)) return; /* Should never happen. */ + + dev->current_data[side][pos + 1] = data; +} + + +static int +format_conditions(int drive) +{ + imd_t *dev = imd[drive]; + int track = dev->track; + int side, temp; + + side = fdd_get_head(drive); + temp = (fdc_get_format_sectors(imd_fdc) == dev->tracks[track][side].params[3]); + temp = temp && (fdc_get_format_n(imd_fdc) == dev->tracks[track][side].params[4]); + + return(temp); +} + + +void +imd_init(void) +{ + memset(imd, 0x00, sizeof(imd)); +} + + +void +imd_load(int drive, wchar_t *fn) +{ + uint32_t magic = 0; + uint32_t fsize = 0; + char *buffer; + char *buffer2; + imd_t *dev; + int i = 0; + int track_spt = 0; + int sector_size = 0; + int track = 0; + int side = 0; + int extra = 0; + uint32_t last_offset = 0; + uint32_t data_size = 512; + uint32_t mfm = 0; + uint32_t pre_sector = 0; + uint32_t track_total = 0; + uint32_t raw_tsize = 0; + uint32_t minimum_gap3 = 0; + uint32_t minimum_gap4 = 0; + + d86f_unregister(drive); + + writeprot[drive] = 0; + + /* Allocate a drive block. */ + dev = (imd_t *)malloc(sizeof(imd_t)); + memset(dev, 0x00, sizeof(imd_t)); + + dev->f = plat_fopen(fn, L"rb+"); + if (dev->f == NULL) { + dev->f = plat_fopen(fn, L"rb"); + if (dev->f == NULL) { + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); return; } - if (!(type & 1)) - { - return; /* Should never happen. */ + writeprot[drive] = 1; + } + + if (ui_writeprot[drive]) + writeprot[drive] = 1; + fwriteprot[drive] = writeprot[drive]; + + fseek(dev->f, 0, SEEK_SET); + fread(&magic, 1, 4, dev->f); + if (magic != 0x20444D49) { + pclog("IMD: Not a valid ImageDisk image\n"); + fclose(dev->f); + free(dev);; + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; + } else { + pclog("IMD: Valid ImageDisk image\n"); + } + + fseek(dev->f, 0, SEEK_END); + fsize = ftell(dev->f); + fseek(dev->f, 0, SEEK_SET); + dev->buffer = malloc(fsize); + fread(dev->buffer, 1, fsize, dev->f); + buffer = dev->buffer; + + buffer2 = strchr(buffer, 0x1A); + if (buffer2 == NULL) { + pclog("IMD: No ASCII EOF character\n"); + fclose(dev->f); + free(dev); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; + } else { + pclog("IMD: ASCII EOF character found at offset %08X\n", buffer2 - buffer); + } + + buffer2++; + if ((buffer2 - buffer) == fsize) { + pclog("IMD: File ends after ASCII EOF character\n"); + fclose(dev->f); + free(dev); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; + } else { + pclog("IMD: File continues after ASCII EOF character\n"); + } + + dev->start_offs = (buffer2 - buffer); + dev->disk_flags = 0x00; + dev->track_count = 0; + dev->sides = 1; + + /* Set up the drive unit. */ + imd[drive] = dev; + + while(1) { + track = buffer2[1]; + side = buffer2[2]; + if (side & 1) + dev->sides = 2; + extra = side & 0xC0; + side &= 0x3F; + + dev->tracks[track][side].side_flags = (buffer2[0] % 3); + if (! dev->tracks[track][side].side_flags) + dev->disk_flags |= (0x02); + dev->tracks[track][side].side_flags |= (!(buffer2[0] - dev->tracks[track][side].side_flags) ? 0 : 8); + mfm = dev->tracks[track][side].side_flags & 8; + track_total = mfm ? 146 : 73; + pre_sector = mfm ? 60 : 42; + + track_spt = buffer2[3]; + sector_size = buffer2[4]; + if ((track_spt == 15) && (sector_size == 2)) + dev->tracks[track][side].side_flags |= 0x20; + if ((track_spt == 16) && (sector_size == 2)) + dev->tracks[track][side].side_flags |= 0x20; + if ((track_spt == 17) && (sector_size == 2)) + dev->tracks[track][side].side_flags |= 0x20; + if ((track_spt == 8) && (sector_size == 3)) + dev->tracks[track][side].side_flags |= 0x20; + if ((dev->tracks[track][side].side_flags & 7) == 1) + dev->tracks[track][side].side_flags |= 0x20; + dev->tracks[track][side].is_present = 1; + dev->tracks[track][side].file_offs = (buffer2 - buffer); + memcpy(dev->tracks[track][side].params, buffer2, 5); + dev->tracks[track][side].r_map_offs = dev->tracks[track][side].file_offs + 5; + last_offset = dev->tracks[track][side].r_map_offs + track_spt; + + if (extra & 0x80) { + dev->tracks[track][side].c_map_offs = last_offset; + last_offset += track_spt; } - imd[drive].current_data[side][pos + 1] = data; + + if (extra & 0x40) { + dev->tracks[track][side].h_map_offs = last_offset; + last_offset += track_spt; + } + + if (sector_size == 0xFF) { + dev->tracks[track][side].n_map_offs = last_offset; + buffer2 = buffer + last_offset; + last_offset += track_spt; + + dev->tracks[track][side].data_offs = last_offset; + + for (i = 0; i < track_spt; i++) { + data_size = buffer2[i]; + data_size = 128 << data_size; + dev->tracks[track][side].sector_data_offs[i] = last_offset; + dev->tracks[track][side].sector_data_size[i] = 1; + if (buffer[dev->tracks[track][side].sector_data_offs[i]] != 0) + dev->tracks[track][side].sector_data_size[i] += (buffer[dev->tracks[track][side].sector_data_offs[i]] & 1) ? data_size : 1; + last_offset += dev->tracks[track][side].sector_data_size[i]; + if (!(buffer[dev->tracks[track][side].sector_data_offs[i]] & 1)) + fwriteprot[drive] = writeprot[drive] = 1; + track_total += (pre_sector + data_size + 2); + } + } else { + dev->tracks[track][side].data_offs = last_offset; + + for (i = 0; i < track_spt; i++) { + data_size = sector_size; + data_size = 128 << data_size; + dev->tracks[track][side].sector_data_offs[i] = last_offset; + dev->tracks[track][side].sector_data_size[i] = 1; + if (buffer[dev->tracks[track][side].sector_data_offs[i]] != 0) + dev->tracks[track][side].sector_data_size[i] += (buffer[dev->tracks[track][side].sector_data_offs[i]] & 1) ? data_size : 1; + last_offset += dev->tracks[track][side].sector_data_size[i]; + if (!(buffer[dev->tracks[track][side].sector_data_offs[i]] & 1)) + fwriteprot[drive] = writeprot[drive] = 1; + track_total += (pre_sector + data_size + 2); + } + } + buffer2 = buffer + last_offset; + + /* Leaving even GAP4: 80 : 40 */ + /* Leaving only GAP1: 96 : 47 */ + /* Not leaving even GAP1: 146 : 73 */ + raw_tsize = get_raw_tsize(dev->tracks[track][side].side_flags, 0); + minimum_gap3 = 12 * track_spt; + if ((raw_tsize - track_total + (mfm ? 146 : 73)) < (minimum_gap3 + minimum_gap4)) { + /* If we can't fit the sectors with a reasonable minimum gap at perfect RPM, let's try 2% slower. */ + raw_tsize = get_raw_tsize(dev->tracks[track][side].side_flags, 1); + /* Set disk flags so that rotation speed is 2% slower. */ + dev->disk_flags |= (3 << 5); + if ((raw_tsize - track_total + (mfm ? 146 : 73)) < (minimum_gap3 + minimum_gap4)) { + /* If we can't fit the sectors with a reasonable minimum gap even at 2% slower RPM, abort. */ + pclog("IMD: Unable to fit the %i sectors in a track\n", track_spt); + fclose(dev->f); + free(dev); + imd[drive] = NULL; + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; + } + } + + dev->tracks[track][side].gap3_len = (raw_tsize - track_total - minimum_gap4 + (mfm ? 146 : 73)) / track_spt; + + dev->track_count++; + + if (last_offset >= fsize) break; + } + + /* If more than 43 tracks, then the tracks are thin (96 tpi). */ + dev->track_width = 0; + if (dev->track_count > 43) + dev->track_width = 1; + + /* If 2 sides, mark it as such. */ + if (dev->sides == 2) + dev->disk_flags |= 8; + + /* Attach this format to the D86F engine. */ + d86f_handler[drive].disk_flags = disk_flags; + d86f_handler[drive].side_flags = side_flags; + d86f_handler[drive].writeback = imd_writeback; + d86f_handler[drive].set_sector = set_sector; + d86f_handler[drive].read_data = poll_read_data; + d86f_handler[drive].write_data = poll_write_data; + d86f_handler[drive].format_conditions = format_conditions; + d86f_handler[drive].extra_bit_cells = null_extra_bit_cells; + d86f_handler[drive].encoded_data = common_encoded_data; + d86f_handler[drive].read_revolution = common_read_revolution; + d86f_handler[drive].index_hole_pos = null_index_hole_pos; + d86f_handler[drive].get_raw_size = common_get_raw_size; + d86f_handler[drive].check_crc = 1; + d86f_set_version(drive, 0x0063); + + drives[drive].seek = imd_seek; + + d86f_common_handlers(drive); } -int imd_format_conditions(int drive) + +void +imd_close(int drive) { - int track = imd[drive].track; - int side = 0; - int temp = 0; - side = fdd_get_head(drive); - temp = (fdc_get_format_sectors(imd_fdc) == imd[drive].tracks[track][side].params[3]); - temp = temp && (fdc_get_format_n(imd_fdc) == imd[drive].tracks[track][side].params[4]); - return temp; + imd_t *dev = imd[drive]; + + if (dev == NULL) return; + + d86f_unregister(drive); + + if (dev->f != NULL) { + free(dev->buffer); + + fclose(dev->f); + } + + /* Release the memory. */ + free(dev); + imd[drive] = NULL; } -void imd_set_fdc(void *fdc) -{ - imd_fdc = (fdc_t *) fdc; -} -void d86f_register_imd(int drive) +void +imd_set_fdc(void *fdc) { - d86f_handler[drive].disk_flags = imd_disk_flags; - d86f_handler[drive].side_flags = imd_side_flags; - d86f_handler[drive].writeback = imd_writeback; - d86f_handler[drive].set_sector = imd_set_sector; - d86f_handler[drive].read_data = imd_poll_read_data; - d86f_handler[drive].write_data = imd_poll_write_data; - d86f_handler[drive].format_conditions = imd_format_conditions; - d86f_handler[drive].extra_bit_cells = null_extra_bit_cells; - d86f_handler[drive].encoded_data = common_encoded_data; - d86f_handler[drive].read_revolution = common_read_revolution; - d86f_handler[drive].index_hole_pos = null_index_hole_pos; - d86f_handler[drive].get_raw_size = common_get_raw_size; - d86f_handler[drive].check_crc = 1; - d86f_set_version(drive, 0x0063); + imd_fdc = (fdc_t *) fdc; } diff --git a/src/floppy/fdd_imd.h b/src/floppy/fdd_imd.h index 7215639bd..4e16bd096 100644 --- a/src/floppy/fdd_imd.h +++ b/src/floppy/fdd_imd.h @@ -1,17 +1,38 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * - * Implementation of the IMD floppy image format. + * Definitions for the IMD floppy image format. * - * Version: @(#)floppy_imd.h 1.0.2 2017/09/03 + * Version: @(#)floppy_imd.h 1.0.2 2018/03/17 * - * Author: Miran Grca, - * Copyright 2016,2017 Miran Grca. + * Authors: Fred N. van Kempen, + * Miran Grca, + * + * Copyright 2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ #ifndef EMU_FLOPPY_IMD_H # define EMU_FLOPPY_IMD_H @@ -20,7 +41,6 @@ extern void imd_init(void); extern void imd_load(int drive, wchar_t *fn); extern void imd_close(int drive); -extern void imd_seek(int drive, int track); #endif /*EMU_FLOPPY_IMD_H*/ diff --git a/src/floppy/fdd_img.c b/src/floppy/fdd_img.c index daab0ad39..ce9dd4837 100644 --- a/src/floppy/fdd_img.c +++ b/src/floppy/fdd_img.c @@ -1,21 +1,45 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * Implementation of the raw sector-based floppy image format, * as well as the Japanese FDI, CopyQM, and FDF formats. * - * Version: @(#)fdd_img.c 1.0.9 2018/03/14 + * NOTE: This file is still a disaster, needs to be cleaned up and + * re-merged with the other files. Much of it is generic to + * all formats. * - * Authors: Sarah Walker, + * Version: @(#)fdd_img.c 1.0.5 2018/03/17 + * + * Authors: Fred N. van Kempen, * Miran Grca, + * Sarah Walker, * - * Copyright 2008-2018 Sarah Walker. + * Copyright 2018 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ #include #include @@ -30,42 +54,57 @@ #include "fdc.h" -static struct -{ - FILE *f; - uint8_t track_data[2][50000]; - int sectors, tracks, sides; - uint8_t sector_size; - int xdf_type; /* 0 = not XDF, 1-5 = one of the five XDF types */ - int dmf; - 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; - uint8_t *disk_data; - uint8_t is_cqm; - uint8_t disk_at_once; - uint8_t interleave; - uint8_t skew; -} img[FDD_NUM]; +typedef struct { + FILE *f; + uint8_t track_data[2][50000]; + int sectors, tracks, sides; + uint8_t sector_size; + int xdf_type; /* 0 = not XDF, 1-5 = one of the five XDF types */ + int dmf; + 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; + uint8_t *disk_data; + uint8_t is_cqm; + uint8_t disk_at_once; + uint8_t interleave; + uint8_t skew; +} img_t; -static fdc_t *img_fdc; -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_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 } }; +static img_t *img[FDD_NUM]; +static fdc_t *img_fdc; + +static double bit_rate_300; +static wchar_t *ext; +static uint8_t first_byte, + second_byte, + third_byte, + fourth_byte; +static uint8_t fdf_suppress_final_byte = 0; /* This is hard-coded to 0 - + * if you really need to read + * those NT 3.1 Beta floppy + * images, change this to 1 + * and recompile. + */ + + +const 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 const uint8_t xdf_logical_sectors[2][2] = { { 38, 6 }, { 46, 8 } }; +const uint8_t xdf_physical_sectors[2][2] = { { 16, 3 }, { 19, 4 } }; +const uint8_t xdf_gap3_sizes[2][2] = { { 60, 69 }, { 60, 50 } }; +const 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}, +const 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}, @@ -84,7 +123,7 @@ xdf_sector_t xdf_img_layout[2][2][46] = { { { {0x8100}, {0x8200}, {0x8300}, {0x8 }; /* 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}, +const 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} }, @@ -103,40 +142,40 @@ xdf_sector_t xdf_disk_layout[2][2][38] = { { { {0x0100}, {0x0200}, {0x8100}, {0x /* 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, 22, 41 }, /* 512 */ - { 3, 5, 6, 9, 11, 22 }, /* 1024 */ - { 2, 2, 3, 4, 5, 11 }, /* 2048 */ - { 1, 1, 1, 2, 2, 5 }, /* 4096 */ +static const uint8_t maximum_sectors[8][6] = { { 26, 31, 38, 53, 64, 118 }, /* 128 */ + { 15, 19, 23, 32, 38, 73 }, /* 256 */ + { 7, 10, 12, 17, 22, 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 */ +static const 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 */ +static const 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 const 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 const uint8_t rates[6] = { 2, 2, 1, 4, 0, 3 }; -static uint8_t holes[6] = { 0, 0, 0, 1, 1, 2 }; +static const uint8_t holes[6] = { 0, 0, 0, 1, 1, 2 }; -int gap3_sizes[5][8][48] = { { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [0][0] */ +const int gap3_sizes[5][8][48] = { { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [0][0] */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [0][1] */ @@ -257,911 +296,912 @@ int gap3_sizes[5][8][48] = { { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }; -void img_writeback(int drive); -static int sector_size_code(int sector_size) +/* Generic */ +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; - } + 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); + } } -void img_init() + +static int +bps_is_valid(uint16_t bps) { - memset(img, 0, sizeof(img)); + int i; + + for (i = 0; i <= 8; i++) { + if (bps == (128 << i)) return(1); + } + + return(0); } -void d86f_register_img(int drive); -int bps_is_valid(uint16_t bps) +static int +first_byte_is_valid(uint8_t first_byte) { - int i; - for (i = 0; i <= 8; i++) - { - if (bps == (128 << i)) - { - return 1; - } - } - return 0; + switch(first_byte) { + case 0x60: + case 0xE9: + case 0xEB: + return(1); + + default: + break; + } + + return(0); } -int first_byte_is_valid(uint8_t first_byte) -{ - switch(first_byte) - { - case 0x60: - case 0xE9: - case 0xEB: - return 1; - default: - return 0; - } -} - -double bit_rate_300; - -wchar_t *ext; - -uint8_t first_byte, second_byte, third_byte, fourth_byte; - -/* This is hard-coded to 0 - if you really need to read those NT 3.1 Beta floppy images, change this to 1 and recompile the emulator. */ -uint8_t fdf_suppress_final_byte = 0; - -void img_load(int drive, wchar_t *fn) -{ - int size; - uint16_t bpb_bps; - uint16_t bpb_total; - uint8_t bpb_mid; /* Media type ID. */ - uint8_t bpb_sectors; - uint8_t bpb_sides; - int temp_rate; - uint8_t fdi, cqm, fdf; - int i; - uint16_t comment_len = 0; - int16_t block_len = 0; - uint32_t cur_pos = 0; - uint8_t rep_byte = 0; - uint8_t run = 0; - uint8_t real_run = 0; - uint8_t *bpos; - uint16_t track_bytes = 0; - uint8_t *literal; - int guess = 0; - - ext = plat_get_extension(fn); - - d86f_unregister(drive); - - writeprot[drive] = 0; - img[drive].f = plat_fopen(fn, L"rb+"); - if (!img[drive].f) - { - img[drive].f = plat_fopen(fn, L"rb"); - if (!img[drive].f) - { - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; - } - writeprot[drive] = 1; - } - if (ui_writeprot[drive]) - { - writeprot[drive] = 1; - } - fwriteprot[drive] = writeprot[drive]; - - fdi = cqm = 0; - - img[drive].interleave = img[drive].skew = 0; - - if (! wcscasecmp(ext, L"FDI")) - { - /* 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); - - fseek(img[drive].f, img[drive].base, SEEK_SET); - first_byte = fgetc(img[drive].f); - - fdi = 1; - cqm = 0; - img[drive].disk_at_once = 0; - fdf = 0; - } - else - { - /* Read the first four bytes. */ - fseek(img[drive].f, 0x00, SEEK_SET); - first_byte = fgetc(img[drive].f); - fseek(img[drive].f, 0x01, SEEK_SET); - second_byte = fgetc(img[drive].f); - fseek(img[drive].f, 0x02, SEEK_SET); - third_byte = fgetc(img[drive].f); - fseek(img[drive].f, 0x03, SEEK_SET); - fourth_byte = fgetc(img[drive].f); - - if ((first_byte == 0x1A) && (second_byte == 'F') && (third_byte == 'D') && (fourth_byte == 'F')) - { - /* This is a FDF image. */ - pclog("img_load(): File is a FDF image...\n"); - fwriteprot[drive] = writeprot[drive] = 1; - fclose(img[drive].f); - img[drive].f = plat_fopen(fn, L"rb"); - - fdf = 1; - - cqm = 0; - img[drive].disk_at_once = 1; - - fseek(img[drive].f, 0x50, SEEK_SET); - fread(&img[drive].tracks, 1, 4, img[drive].f); - - /* Decode the entire file - pass 1, no write to buffer, determine length. */ - fseek(img[drive].f, 0x80, SEEK_SET); - size = 0; - track_bytes = 0; - bpos = img[drive].disk_data; - while(!feof(img[drive].f)) - { - if (!track_bytes) - { - /* Skip first 3 bytes - their meaning is unknown to us but could be a checksum. */ - first_byte = fgetc(img[drive].f); - fread(&track_bytes, 1, 2, img[drive].f); - pclog("Block header: %02X %04X ", first_byte, track_bytes); - /* Read the length of encoded data block. */ - fread(&track_bytes, 1, 2, img[drive].f); - pclog("%04X\n", track_bytes); - } - - if (feof(img[drive].f)) - { - break; - } - - if (first_byte == 0xFF) - { - break; - } - - if (first_byte) - { - run = fgetc(img[drive].f); - - /* I *HAVE* to read something because fseek tries to be smart and never hits EOF, causing an infinite loop. */ - track_bytes--; - - if (run & 0x80) - { - /* Repeat. */ - track_bytes--; - rep_byte = fgetc(img[drive].f); - } - else - { - /* Literal. */ - track_bytes -= (run & 0x7f); - literal = (uint8_t *) malloc(run & 0x7f); - fread(literal, 1, (run & 0x7f), img[drive].f); - free(literal); - } - size += (run & 0x7f); - if (!track_bytes) - { - size -= fdf_suppress_final_byte; - } - } - else - { - /* Literal block. */ - size += (track_bytes - fdf_suppress_final_byte); - literal = (uint8_t *) malloc(track_bytes); - fread(literal, 1, track_bytes, img[drive].f); - free(literal); - track_bytes = 0; - } - - if (feof(img[drive].f)) - { - break; - } - } - - /* Allocate the buffer. */ - img[drive].disk_data = (uint8_t *) malloc(size); - - /* Decode the entire file - pass 2, write to buffer. */ - fseek(img[drive].f, 0x80, SEEK_SET); - track_bytes = 0; - bpos = img[drive].disk_data; - while(!feof(img[drive].f)) - { - if (!track_bytes) - { - /* Skip first 3 bytes - their meaning is unknown to us but could be a checksum. */ - first_byte = fgetc(img[drive].f); - fread(&track_bytes, 1, 2, img[drive].f); - pclog("Block header: %02X %04X ", first_byte, track_bytes); - /* Read the length of encoded data block. */ - fread(&track_bytes, 1, 2, img[drive].f); - pclog("%04X\n", track_bytes); - } - - if (feof(img[drive].f)) - { - break; - } - - if (first_byte == 0xFF) - { - break; - } - - if (first_byte) - { - run = fgetc(img[drive].f); - real_run = (run & 0x7f); - - /* I *HAVE* to read something because fseek tries to be smart and never hits EOF, causing an infinite loop. */ - track_bytes--; - - if (run & 0x80) - { - /* Repeat. */ - track_bytes--; - if (!track_bytes) - { - real_run -= fdf_suppress_final_byte; - } - rep_byte = fgetc(img[drive].f); - if (real_run) - { - memset(bpos, rep_byte, real_run); - } - } - else - { - /* Literal. */ - track_bytes -= real_run; - literal = (uint8_t *) malloc(real_run); - fread(literal, 1, real_run, img[drive].f); - if (!track_bytes) - { - real_run -= fdf_suppress_final_byte; - } - if (run & 0x7f) - { - memcpy(bpos, literal, real_run); - } - free(literal); - } - bpos += real_run; - } - else - { - /* Literal block. */ - literal = (uint8_t *) malloc(track_bytes); - fread(literal, 1, track_bytes, img[drive].f); - memcpy(bpos, literal, track_bytes - fdf_suppress_final_byte); - free(literal); - bpos += (track_bytes - fdf_suppress_final_byte); - track_bytes = 0; - } - - if (feof(img[drive].f)) - { - break; - } - } - - first_byte = *img[drive].disk_data; - - bpb_bps = *(uint16_t *) (img[drive].disk_data + 0x0B); - bpb_total = *(uint16_t *) (img[drive].disk_data + 0x13); - bpb_mid = *(img[drive].disk_data + 0x15); - bpb_sectors = *(img[drive].disk_data + 0x18); - bpb_sides = *(img[drive].disk_data + 0x1A); - - /* Jump ahead to determine the image's geometry and finish the loading. */ - goto jump_if_fdf; - } - - if (((first_byte == 'C') && (second_byte == 'Q')) || ((first_byte == 'c') && (second_byte == 'q'))) - { - pclog("img_load(): File is a CopyQM image...\n"); - fwriteprot[drive] = writeprot[drive] = 1; - fclose(img[drive].f); - img[drive].f = plat_fopen(fn, L"rb"); - - fseek(img[drive].f, 0x03, SEEK_SET); - fread(&bpb_bps, 1, 2, img[drive].f); - /* fseek(img[drive].f, 0x0B, SEEK_SET); - fread(&bpb_total, 1, 2, img[drive].f); */ - fseek(img[drive].f, 0x10, SEEK_SET); - bpb_sectors = fgetc(img[drive].f); - fseek(img[drive].f, 0x12, SEEK_SET); - bpb_sides = fgetc(img[drive].f); - fseek(img[drive].f, 0x5B, SEEK_SET); - img[drive].tracks = fgetc(img[drive].f); - - bpb_total = ((uint16_t) bpb_sectors) * ((uint16_t) bpb_sides) * img[drive].tracks; - - fseek(img[drive].f, 0x74, SEEK_SET); - img[drive].interleave = fgetc(img[drive].f); - fseek(img[drive].f, 0x76, SEEK_SET); - img[drive].skew = fgetc(img[drive].f); - - img[drive].disk_data = (uint8_t *) malloc(((uint32_t) bpb_total) * ((uint32_t) bpb_bps)); - memset(img[drive].disk_data, 0xf6, ((uint32_t) bpb_total) * ((uint32_t) bpb_bps)); - - fseek(img[drive].f, 0x6F, SEEK_SET); - fread(&comment_len, 1, 2, img[drive].f); - - fseek(img[drive].f, -1, SEEK_END); - size = ftell(img[drive].f) + 1; - - fseek(img[drive].f, 133 + comment_len, SEEK_SET); - - cur_pos = 0; - - while(!feof(img[drive].f)) - { - fread(&block_len, 1, 2, img[drive].f); - - if (!feof(img[drive].f)) - { - if (block_len < 0) - { - rep_byte = fgetc(img[drive].f); - block_len = -block_len; - if ((cur_pos + block_len) > ((uint32_t) bpb_total) * ((uint32_t) bpb_bps)) - { - block_len = ((uint32_t) bpb_total) * ((uint32_t) bpb_bps) - cur_pos; - memset(img[drive].disk_data + cur_pos, rep_byte, block_len); - break; - } - else - { - memset(img[drive].disk_data + cur_pos, rep_byte, block_len); - cur_pos += block_len; - } - } - else if (block_len > 0) - { - if ((cur_pos + block_len) > ((uint32_t) bpb_total) * ((uint32_t) bpb_bps)) - { - block_len = ((uint32_t) bpb_total) * ((uint32_t) bpb_bps) - cur_pos; - fread(img[drive].disk_data + cur_pos, 1, block_len, img[drive].f); - break; - } - else - { - fread(img[drive].disk_data + cur_pos, 1, block_len, img[drive].f); - cur_pos += block_len; - } - } - } - } - pclog("Finished reading CopyQM image data\n"); - - cqm = 1; - img[drive].disk_at_once = 1; - fdf = 0; - first_byte = *img[drive].disk_data; - } - else - { - img[drive].disk_at_once = 0; - /* 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); - - cqm = 0; - } - - fseek(img[drive].f, -1, SEEK_END); - size = ftell(img[drive].f) + 1; - -jump_if_fdf: - img[drive].base = 0; - fdi = 0; - } - - img[drive].sides = 2; - img[drive].sector_size = 2; - - pclog("BPB reports %i sides and %i bytes per sector (%i sectors total)\n", bpb_sides, bpb_bps, bpb_total); - - guess = (bpb_sides < 1); - guess = guess || (bpb_sides > 2); - guess = guess || !bps_is_valid(bpb_bps); - guess = guess || !first_byte_is_valid(first_byte); - guess = guess || !fdd_get_check_bpb(drive); - guess = guess && !fdi; - guess = guess && !cqm; - - if (guess) - { - /* 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 <= (315*1024)) { img[drive].sectors = 9; img[drive].tracks = 70; img[drive].sides = 1; } - else if (size <= (320*1024)) { img[drive].sectors = 8; img[drive].tracks = 40; } - 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 <= 1474560) { 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 = 22; 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); - img[drive].f = NULL; - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; - } - - bpb_sides = img[drive].sides; - bpb_sectors = img[drive].sectors; - bpb_total = size >> (img[drive].sector_size + 7); - } - 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 - { - if (!cqm && !fdf) - { - /* 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 - { - if ((bit_rate_300 == 500.0) && (img[drive].sectors == 22) && (img[drive].sector_size == 2) && (img[drive].tracks >= 80) && (img[drive].tracks <= 82) && (img[drive].sides == 2)) - { - /* This is marked specially because of the track flag (a RPM slow down is needed). */ - img[drive].interleave = 2; - } - 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); - img[drive].f = NULL; - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - 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); - img[drive].f = NULL; - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - 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. */ - if (img[drive].interleave == 2) - { - img[drive].interleave = 1; - img[drive].disk_flags |= 0x60; - } - - 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. */ - - img[drive].is_cqm = cqm; - - 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; - } - if (img[drive].disk_data) - free(img[drive].disk_data); -} #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) + +static int +interleave(int sector, int skew, int track_spt) { - uint32_t skewed_i = 0; - uint32_t adjusted_r = 0; + uint32_t skewed_i; + uint32_t adjusted_r; + uint32_t add = (track_spt & 1); + uint32_t adjust = (track_spt >> 1); - 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); - skewed_i = (sector + skew) % track_spt; - adjusted_r = (skewed_i >> 1) + 1; - if (skewed_i & 1) - { - adjusted_r += (adjust + add); - } - - return adjusted_r; + return(adjusted_r); } -void img_seek(int drive, int track) + +static void +write_back(int drive) { - int side; - int current_xdft = img[drive].xdf_type - 1; + img_t *dev = img[drive]; + int ssize = 128 << ((int) dev->sector_size); + int side; - int read_bytes = 0; + if (dev->f == NULL) return; - 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); - uint32_t cur_pos = 0; - - if (!img[drive].f) - return; - - if (!img[drive].track_width && fdd_doublestep_40(drive)) - track /= 2; - - img[drive].track = track; - d86f_set_cur_track(drive, track); - - is_t0 = (track == 0) ? 1 : 0; - - if (!img[drive].disk_at_once) - { - 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++) - { - if (img[drive].disk_at_once) - { - cur_pos = (track * img[drive].sectors * ssize * img[drive].sides) + (side * img[drive].sectors * ssize); - memcpy(img[drive].track_data[side], img[drive].disk_data + cur_pos, img[drive].sectors * ssize); - } - else - { - read_bytes = fread(img[drive].track_data[side], 1, img[drive].sectors * ssize, img[drive].f); - if (read_bytes < (img[drive].sectors * ssize)) - { - memset(img[drive].track_data[side] + read_bytes, 0xf6, (img[drive].sectors * ssize) - read_bytes); - } - } - } - - d86f_reset_index_hole_pos(drive, 0); - d86f_reset_index_hole_pos(drive, 1); - - d86f_destroy_linked_lists(drive, 0); - d86f_destroy_linked_lists(drive, 1); - - if (track > img[drive].tracks) - { - d86f_zero_track(drive); - return; - } - - if (!img[drive].xdf_type || img[drive].is_cqm) - { - for (side = 0; side < img[drive].sides; side++) - { - current_pos = d86f_prepare_pretrack(drive, side, 0); - - for (sector = 0; sector < img[drive].sectors; sector++) - { - if (img[drive].is_cqm) - { - if (img[drive].interleave) - { - sr = interleave(sector, img[drive].skew, img[drive].sectors); - } - else - { - sr = sector + 1; - sr += img[drive].skew; - if (sr > img[drive].sectors) - { - sr -= img[drive].sectors; - } - } - } - else - { - if (img[drive].gap3_size < 68) - { - sr = interleave(sector, 1, img[drive].sectors); - } - 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; - 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); - - if (sector == 0) - { - d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); - } - } - } - } - 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; - } - - 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; - - 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]; - - id[0] = track; - id[1] = xdf_disk_sector.id.h; - id[2] = xdf_disk_sector.id.r; - - if (is_t0) - { - id[3] = 2; - 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; - 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); - } - - if (sector == 0) - { - d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); - } - } - } - } + if (dev->disk_at_once) return; + + fseek(dev->f, dev->base + (dev->track * dev->sectors * ssize * dev->sides), SEEK_SET); + for (side = 0; side < dev->sides; side++) + fwrite(dev->track_data[side], dev->sectors * ssize, 1, dev->f); } -void img_writeback(int drive) + +static uint16_t +disk_flags(int drive) { - int side; - int ssize = 128 << ((int) img[drive].sector_size); + img_t *dev = img[drive]; - if (!img[drive].f) - return; + return(dev->disk_flags); +} - if (img[drive].disk_at_once) - 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); + +static uint16_t +side_flags(int drive) +{ + img_t *dev = img[drive]; + + return(dev->track_flags); +} + + +static void +set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n) +{ + img_t *dev = img[drive]; + + dev->current_sector_pos_side = dev->sector_pos_side[h][r]; + dev->current_sector_pos = dev->sector_pos[h][r]; +} + + +static uint8_t +poll_read_data(int drive, int side, uint16_t pos) +{ + img_t *dev = img[drive]; + + return(dev->track_data[dev->current_sector_pos_side][dev->current_sector_pos + pos]); +} + + +static void +poll_write_data(int drive, int side, uint16_t pos, uint8_t data) +{ + img_t *dev = img[drive]; + + dev->track_data[dev->current_sector_pos_side][dev->current_sector_pos + pos] = data; +} + + +static int +format_conditions(int drive) +{ + img_t *dev = img[drive]; + int temp = (fdc_get_format_sectors(img_fdc) == dev->sectors); + + temp = temp && (fdc_get_format_n(img_fdc) == dev->sector_size); + temp = temp && (dev->xdf_type == 0); + + return(temp); +} + + +static void +img_seek(int drive, int track) +{ + img_t *dev = img[drive]; + int side; + int current_xdft = dev->xdf_type - 1; + int read_bytes = 0; + 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) dev->sector_size); + uint32_t cur_pos = 0; + + if (dev->f == NULL) return; + + if (!dev->track_width && fdd_doublestep_40(drive)) + track /= 2; + + dev->track = track; + d86f_set_cur_track(drive, track); + + is_t0 = (track == 0) ? 1 : 0; + + if (! dev->disk_at_once) + fseek(dev->f, dev->base + (track * dev->sectors * ssize * dev->sides), SEEK_SET); + + for (side = 0; side < dev->sides; side++) { + if (dev->disk_at_once) { + cur_pos = (track * dev->sectors * ssize * dev->sides) + (side * dev->sectors * ssize); + memcpy(dev->track_data[side], dev->disk_data + cur_pos, dev->sectors * ssize); + } else { + read_bytes = fread(dev->track_data[side], 1, dev->sectors * ssize, dev->f); + if (read_bytes < (dev->sectors * ssize)) + memset(dev->track_data[side] + read_bytes, 0xf6, (dev->sectors * ssize) - read_bytes); } -} + } -int img_xdf_type(int drive) -{ - return img[drive].xdf_type; -} + d86f_reset_index_hole_pos(drive, 0); + d86f_reset_index_hole_pos(drive, 1); -uint16_t img_disk_flags(int drive) -{ - return img[drive].disk_flags; -} + d86f_destroy_linked_lists(drive, 0); + d86f_destroy_linked_lists(drive, 1); -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]; + if (track > dev->tracks) { + d86f_zero_track(drive); return; + } + + if (!dev->xdf_type || dev->is_cqm) { + for (side = 0; side < dev->sides; side++) { + current_pos = d86f_prepare_pretrack(drive, side, 0); + + for (sector = 0; sector < dev->sectors; sector++) { + if (dev->is_cqm) { + if (dev->interleave) + sr = interleave(sector, dev->skew, dev->sectors); + else { + sr = sector + 1; + sr += dev->skew; + if (sr > dev->sectors) + sr -= dev->sectors; + } + } else { + if (dev->gap3_size < 68) + sr = interleave(sector, 1, dev->sectors); + else + sr = dev->dmf ? (dmf_r[sector]) : (sector + 1); + } + id[0] = track; + id[1] = side; + id[2] = sr; + id[3] = dev->sector_size; + dev->sector_pos_side[side][sr] = side; + dev->sector_pos[side][sr] = (sr - 1) * ssize; + current_pos = d86f_prepare_sector(drive, side, current_pos, id, &dev->track_data[side][(sr - 1) * ssize], ssize, dev->gap2_size, dev->gap3_size, 0, 0); + + if (sector == 0) + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + } + } + } else { + total = dev->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) { + dev->sector_pos_side[xdf_img_sector.id.h][xdf_img_sector.id.r] = sside; + dev->sector_pos[xdf_img_sector.id.h][xdf_img_sector.id.r] = 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 < dev->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; + buf_side = dev->sector_pos_side[xdf_disk_sector.id.h][xdf_disk_sector.id.r]; + buf_pos = dev->sector_pos[xdf_disk_sector.id.h][xdf_disk_sector.id.r]; + + id[0] = track; + id[1] = xdf_disk_sector.id.h; + id[2] = xdf_disk_sector.id.r; + + if (is_t0) { + id[3] = 2; + current_pos = d86f_prepare_sector(drive, side, current_pos, id, &dev->track_data[buf_side][buf_pos], ssize, dev->gap2_size, xdf_gap3_sizes[current_xdft][!is_t0], 0, 0); + } else { + id[3] = id[2] & 7; + ssize = (128 << id[3]); + current_pos = d86f_prepare_sector(drive, side, xdf_trackx_spos[current_xdft][array_sector], id, &dev->track_data[buf_side][buf_pos], ssize, dev->gap2_size, xdf_gap3_sizes[current_xdft][!is_t0], 0, 0); + } + + if (sector == 0) + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + } + } + } } -uint8_t img_poll_read_data(int drive, int side, uint16_t pos) + +void +img_init(void) { - return img[drive].track_data[img[drive].current_sector_pos_side][img[drive].current_sector_pos + pos]; + memset(img, 0x00, sizeof(img)); } -void img_poll_write_data(int drive, int side, uint16_t pos, uint8_t data) + +void +img_load(int drive, wchar_t *fn) { - img[drive].track_data[img[drive].current_sector_pos_side][img[drive].current_sector_pos + pos] = data; + uint16_t bpb_bps; + uint16_t bpb_total; + uint8_t bpb_mid; /* Media type ID. */ + uint8_t bpb_sectors; + uint8_t bpb_sides; + uint8_t fdi, cqm, fdf; + uint16_t comment_len = 0; + int16_t block_len = 0; + uint32_t cur_pos = 0; + uint8_t rep_byte = 0; + uint8_t run = 0; + uint8_t real_run = 0; + uint8_t *bpos; + uint16_t track_bytes = 0; + uint8_t *literal; + img_t *dev; + int temp_rate; + int guess = 0; + int size; + int i; + + ext = plat_get_extension(fn); + + d86f_unregister(drive); + + writeprot[drive] = 0; + + /* Allocate a drive block. */ + dev = (img_t *)malloc(sizeof(img_t)); + memset(dev, 0x00, sizeof(img_t)); + + dev->f = plat_fopen(fn, L"rb+"); + if (dev->f == NULL) { + dev->f = plat_fopen(fn, L"rb"); + if (dev->f == NULL) { + free(dev); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; + } + writeprot[drive] = 1; + } + + if (ui_writeprot[drive]) + writeprot[drive] = 1; + fwriteprot[drive] = writeprot[drive]; + + fdi = cqm = 0; + + dev->interleave = dev->skew = 0; + + if (! wcscasecmp(ext, L"FDI")) { + /* This is a Japanese FDI image, so let's read the header */ + pclog("img_load(): File is a Japanese FDI image...\n"); + fseek(dev->f, 0x10, SEEK_SET); + (void)fread(&bpb_bps, 1, 2, dev->f); + fseek(dev->f, 0x0C, SEEK_SET); + (void)fread(&size, 1, 4, dev->f); + bpb_total = size / bpb_bps; + fseek(dev->f, 0x08, SEEK_SET); + (void)fread(&(dev->base), 1, 4, dev->f); + fseek(dev->f, dev->base + 0x15, SEEK_SET); + bpb_mid = fgetc(dev->f); + if (bpb_mid < 0xF0) + bpb_mid = 0xF0; + fseek(dev->f, 0x14, SEEK_SET); + bpb_sectors = fgetc(dev->f); + fseek(dev->f, 0x18, SEEK_SET); + bpb_sides = fgetc(dev->f); + fseek(dev->f, dev->base, SEEK_SET); + first_byte = fgetc(dev->f); + + fdi = 1; + cqm = 0; + dev->disk_at_once = 0; + fdf = 0; + } else { + /* Read the first four bytes. */ + fseek(dev->f, 0x00, SEEK_SET); + first_byte = fgetc(dev->f); + fseek(dev->f, 0x01, SEEK_SET); + second_byte = fgetc(dev->f); + fseek(dev->f, 0x02, SEEK_SET); + third_byte = fgetc(dev->f); + fseek(dev->f, 0x03, SEEK_SET); + fourth_byte = fgetc(dev->f); + + if ((first_byte == 0x1A) && (second_byte == 'F') && + (third_byte == 'D') && (fourth_byte == 'F')) { + /* This is a FDF image. */ + pclog("img_load(): File is a FDF image...\n"); + fwriteprot[drive] = writeprot[drive] = 1; + fclose(dev->f); + dev->f = plat_fopen(fn, L"rb"); + + fdf = 1; + cqm = 0; + dev->disk_at_once = 1; + + fseek(dev->f, 0x50, SEEK_SET); + (void)fread(&dev->tracks, 1, 4, dev->f); + + /* Decode the entire file - pass 1, no write to buffer, determine length. */ + fseek(dev->f, 0x80, SEEK_SET); + size = 0; + track_bytes = 0; + bpos = dev->disk_data; + while (! feof(dev->f)) { + if (! track_bytes) { + /* Skip first 3 bytes - their meaning is unknown to us but could be a checksum. */ + first_byte = fgetc(dev->f); + fread(&track_bytes, 1, 2, dev->f); + pclog("Block header: %02X %04X ", first_byte, track_bytes); + /* Read the length of encoded data block. */ + fread(&track_bytes, 1, 2, dev->f); + pclog("%04X\n", track_bytes); + } + + if (feof(dev->f)) break; + + if (first_byte == 0xFF) break; + + if (first_byte) { + run = fgetc(dev->f); + + /* I *HAVE* to read something because fseek tries to be smart and never hits EOF, causing an infinite loop. */ + track_bytes--; + + if (run & 0x80) { + /* Repeat. */ + track_bytes--; + rep_byte = fgetc(dev->f); + } else { + /* Literal. */ + track_bytes -= (run & 0x7f); + literal = (uint8_t *)malloc(run & 0x7f); + fread(literal, 1, (run & 0x7f), dev->f); + free(literal); + } + size += (run & 0x7f); + if (!track_bytes) + size -= fdf_suppress_final_byte; + } else { + /* Literal block. */ + size += (track_bytes - fdf_suppress_final_byte); + literal = (uint8_t *)malloc(track_bytes); + fread(literal, 1, track_bytes, dev->f); + free(literal); + track_bytes = 0; + } + + if (feof(dev->f)) break; + } + + /* Allocate the buffer. */ + dev->disk_data = (uint8_t *)malloc(size); + + /* Decode the entire file - pass 2, write to buffer. */ + fseek(dev->f, 0x80, SEEK_SET); + track_bytes = 0; + bpos = dev->disk_data; + while(! feof(dev->f)) { + if (! track_bytes) { + /* Skip first 3 bytes - their meaning is unknown to us but could be a checksum. */ + first_byte = fgetc(dev->f); + fread(&track_bytes, 1, 2, dev->f); + pclog("Block header: %02X %04X ", first_byte, track_bytes); + /* Read the length of encoded data block. */ + fread(&track_bytes, 1, 2, dev->f); + pclog("%04X\n", track_bytes); + } + + if (feof(dev->f)) break; + + if (first_byte == 0xFF) break; + + if (first_byte) { + run = fgetc(dev->f); + real_run = (run & 0x7f); + + /* I *HAVE* to read something because fseek tries to be smart and never hits EOF, causing an infinite loop. */ + track_bytes--; + + if (run & 0x80) { + /* Repeat. */ + track_bytes--; + if (! track_bytes) + real_run -= fdf_suppress_final_byte; + rep_byte = fgetc(dev->f); + if (real_run) + memset(bpos, rep_byte, real_run); + } else { + /* Literal. */ + track_bytes -= real_run; + literal = (uint8_t *) malloc(real_run); + fread(literal, 1, real_run, dev->f); + if (! track_bytes) + real_run -= fdf_suppress_final_byte; + if (run & 0x7f) + memcpy(bpos, literal, real_run); + free(literal); + } + bpos += real_run; + } else { + /* Literal block. */ + literal = (uint8_t *) malloc(track_bytes); + fread(literal, 1, track_bytes, dev->f); + memcpy(bpos, literal, track_bytes - fdf_suppress_final_byte); + free(literal); + bpos += (track_bytes - fdf_suppress_final_byte); + track_bytes = 0; + } + + if (feof(dev->f)) break; + } + + first_byte = *dev->disk_data; + + bpb_bps = *(uint16_t *)(dev->disk_data + 0x0B); + bpb_total = *(uint16_t *)(dev->disk_data + 0x13); + bpb_mid = *(dev->disk_data + 0x15); + bpb_sectors = *(dev->disk_data + 0x18); + bpb_sides = *(dev->disk_data + 0x1A); + + /* Jump ahead to determine the image's geometry. */ + goto jump_if_fdf; + } + + if (((first_byte == 'C') && (second_byte == 'Q')) || + ((first_byte == 'c') && (second_byte == 'q'))) { + pclog("img_load(): File is a CopyQM image...\n"); + fwriteprot[drive] = writeprot[drive] = 1; + fclose(dev->f); + dev->f = plat_fopen(fn, L"rb"); + + fseek(dev->f, 0x03, SEEK_SET); + fread(&bpb_bps, 1, 2, dev->f); +#if 0 + fseek(dev->f, 0x0B, SEEK_SET); + fread(&bpb_total, 1, 2, dev->f); +#endif + fseek(dev->f, 0x10, SEEK_SET); + bpb_sectors = fgetc(dev->f); + fseek(dev->f, 0x12, SEEK_SET); + bpb_sides = fgetc(dev->f); + fseek(dev->f, 0x5B, SEEK_SET); + dev->tracks = fgetc(dev->f); + + bpb_total = ((uint16_t)bpb_sectors) * ((uint16_t) bpb_sides) * dev->tracks; + + fseek(dev->f, 0x74, SEEK_SET); + dev->interleave = fgetc(dev->f); + fseek(dev->f, 0x76, SEEK_SET); + dev->skew = fgetc(dev->f); + + dev->disk_data = (uint8_t *) malloc(((uint32_t) bpb_total) * ((uint32_t) bpb_bps)); + memset(dev->disk_data, 0xf6, ((uint32_t) bpb_total) * ((uint32_t) bpb_bps)); + + fseek(dev->f, 0x6F, SEEK_SET); + fread(&comment_len, 1, 2, dev->f); + + fseek(dev->f, -1, SEEK_END); + size = ftell(dev->f) + 1; + + fseek(dev->f, 133 + comment_len, SEEK_SET); + + cur_pos = 0; + + while(! feof(dev->f)) { + fread(&block_len, 1, 2, dev->f); + + if (! feof(dev->f)) { + if (block_len < 0) { + rep_byte = fgetc(dev->f); + block_len = -block_len; + if ((cur_pos + block_len) > ((uint32_t) bpb_total) * ((uint32_t) bpb_bps)) { + block_len = ((uint32_t) bpb_total) * ((uint32_t) bpb_bps) - cur_pos; + memset(dev->disk_data + cur_pos, rep_byte, block_len); + break; + } else { + memset(dev->disk_data + cur_pos, rep_byte, block_len); + cur_pos += block_len; + } + } else if (block_len > 0) { + if ((cur_pos + block_len) > ((uint32_t) bpb_total) * ((uint32_t) bpb_bps)) { + block_len = ((uint32_t) bpb_total) * ((uint32_t) bpb_bps) - cur_pos; + fread(dev->disk_data + cur_pos, 1, block_len, dev->f); + break; + } else { + fread(dev->disk_data + cur_pos, 1, block_len, dev->f); + cur_pos += block_len; + } + } + } + } + pclog("Finished reading CopyQM image data\n"); + + cqm = 1; + dev->disk_at_once = 1; + fdf = 0; + first_byte = *dev->disk_data; + } else { + dev->disk_at_once = 0; + /* Read the BPB */ + pclog("img_load(): File is a raw image...\n"); + fseek(dev->f, 0x0B, SEEK_SET); + fread(&bpb_bps, 1, 2, dev->f); + fseek(dev->f, 0x13, SEEK_SET); + fread(&bpb_total, 1, 2, dev->f); + fseek(dev->f, 0x15, SEEK_SET); + bpb_mid = fgetc(dev->f); + fseek(dev->f, 0x18, SEEK_SET); + bpb_sectors = fgetc(dev->f); + fseek(dev->f, 0x1A, SEEK_SET); + bpb_sides = fgetc(dev->f); + + cqm = 0; + } + + fseek(dev->f, -1, SEEK_END); + size = ftell(dev->f) + 1; + +jump_if_fdf: + dev->base = 0; + fdi = 0; + } + + dev->sides = 2; + dev->sector_size = 2; + + pclog("BPB reports %i sides and %i bytes per sector (%i sectors total)\n", + bpb_sides, bpb_bps, bpb_total); + + guess = (bpb_sides < 1); + guess = guess || (bpb_sides > 2); + guess = guess || !bps_is_valid(bpb_bps); + guess = guess || !first_byte_is_valid(first_byte); + guess = guess || !fdd_get_check_bpb(drive); + guess = guess && !fdi; + guess = guess && !cqm; + if (guess) { + /* + * 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)) { + dev->sectors = 8; + dev->tracks = 40; + dev->sides = 1; + } else if (size <= (180*1024)) { + dev->sectors = 9; + dev->tracks = 40; + dev->sides = 1; + } else if (size <= (315*1024)) { + dev->sectors = 9; + dev->tracks = 70; + dev->sides = 1; + } else if (size <= (320*1024)) { + dev->sectors = 8; + dev->tracks = 40; + } else if (size <= (320*1024)) { + dev->sectors = 8; + dev->tracks = 40; + } else if (size <= (360*1024)) { /*DD 360K*/ + dev->sectors = 9; + dev->tracks = 40; + } else if (size <= (400*1024)) { /*DEC RX50*/ + dev->sectors = 10; + dev->tracks = 80; + dev->sides = 1; + } else if (size <= (640*1024)) { /*DD 640K*/ + dev->sectors = 8; + dev->tracks = 80; + } else if (size <= (720*1024)) { /*DD 720K*/ + dev->sectors = 9; + dev->tracks = 80; + } else if (size <= (800*1024)) { /*DD*/ + dev->sectors = 10; + dev->tracks = 80; + } else if (size <= (880*1024)) { /*DD*/ + dev->sectors = 11; + dev->tracks = 80; + } else if (size <= (960*1024)) { /*DD*/ + dev->sectors = 12; + dev->tracks = 80; + } else if (size <= (1040*1024)) { /*DD*/ + dev->sectors = 13; + dev->tracks = 80; + } else if (size <= (1120*1024)) { /*DD*/ + dev->sectors = 14; + dev->tracks = 80; + } else if (size <= 1228800) { /*HD 1.2MB*/ + dev->sectors = 15; + dev->tracks = 80; + } else if (size <= 1261568) { /*HD 1.25MB Japanese*/ + dev->sectors = 8; + dev->tracks = 77; + dev->sector_size = 3; + } else if (size <= 1474560) { /*HD 1.44MB*/ + dev->sectors = 18; + dev->tracks = 80; + } else if (size <= 1556480) { /*HD*/ + dev->sectors = 19; + dev->tracks = 80; + } else if (size <= 1638400) { /*HD 1024 sector*/ + dev->sectors = 10; + dev->tracks = 80; + dev->sector_size = 3; + } else if (size <= 1720320) { /*DMF (Windows 95) */ + dev->sectors = 21; + dev->tracks = 80; + } else if (size <= 1741824) { + dev->sectors = 21; + dev->tracks = 81; + } else if (size <= 1763328) { + dev->sectors = 21; + dev->tracks = 82; + } else if (size <= 1802240) { /*HD 1024 sector*/ + dev->sectors = 22; + dev->tracks = 80; + dev->sector_size = 3; + } else if (size == 1884160) { /*XDF (OS/2 Warp)*/ + dev->sectors = 23; + dev->tracks = 80; + } else if (size <= 2949120) { /*ED*/ + dev->sectors = 36; + dev->tracks = 80; + } else if (size <= 3194880) { /*ED*/ + dev->sectors = 39; + dev->tracks = 80; + } else if (size <= 3276800) { /*ED*/ + dev->sectors = 40; + dev->tracks = 80; + } else if (size <= 3358720) { /*ED, maximum possible size*/ + dev->sectors = 41; + dev->tracks = 80; + } else if (size <= 3440640) { /*ED, maximum possible size*/ + dev->sectors = 42; + dev->tracks = 80; +#if 0 + } else if (size <= 3440640) { /*HD 1024 sector*/ + dev->sectors = 21; + dev->tracks = 80; + dev->sector_size = 3; +#endif + } else if (size <= 3604480) { /*HD 1024 sector*/ + dev->sectors = 22; + dev->tracks = 80; + dev->sector_size = 3; + } else if (size <= 3610624) { /*ED, maximum possible size*/ + dev->sectors = 41; + dev->tracks = 86; + } else if (size <= 3698688) { /*ED, maximum possible size*/ + dev->sectors = 42; + dev->tracks = 86; + } else { + pclog("Image is bigger than can fit on an ED floppy, ejecting...\n"); + fclose(dev->f); + free(dev); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; + } + + bpb_sides = dev->sides; + bpb_sectors = dev->sectors; + bpb_total = size >> (dev->sector_size + 7); + } 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(dev->f, 0x1C, SEEK_SET); + fread(&(dev->tracks), 1, 4, dev->f); + } else { + if (!cqm && !fdf) { + /* Number of tracks = number of total sectors divided by sides times sectors per track. */ + dev->tracks = ((uint32_t) bpb_total) / (((uint32_t) bpb_sides) * ((uint32_t) bpb_sectors)); + } + } + + /* The rest we just set directly from the BPB. */ + dev->sectors = bpb_sectors; + dev->sides = bpb_sides; + + /* The sector size. */ + dev->sector_size = sector_size_code(bpb_bps); + + temp_rate = 0xFF; + } + + for (i = 0; i < 6; i++) { + if ((dev->sectors <= maximum_sectors[dev->sector_size][i]) || (dev->sectors == xdf_sectors[dev->sector_size][i])) { + bit_rate_300 = bit_rates_300[i]; + temp_rate = rates[i]; + dev->disk_flags = holes[i] << 1; + dev->xdf_type = (dev->sectors == xdf_sectors[dev->sector_size][i]) ? xdf_types[dev->sector_size][i] : 0; + if ((bit_rate_300 == 500.0) && (dev->sectors == 21) && (dev->sector_size == 2) && (dev->tracks >= 80) && (dev->tracks <= 82) && (dev->sides == 2)) { + /* This is a DMF floppy, set the flag so we know to interleave the sectors. */ + dev->dmf = 1; + } else { + if ((bit_rate_300 == 500.0) && (dev->sectors == 22) && (dev->sector_size == 2) && (dev->tracks >= 80) && (dev->tracks <= 82) && (dev->sides == 2)) { + /* This is marked specially because of the track flag (a RPM slow down is needed). */ + dev->interleave = 2; + } + dev->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, dev->disk_flags >> 1, dev->dmf, dev->xdf_type); + break; + } + } + + if (temp_rate == 0xFF) { + pclog("Image is bigger than can fit on an ED floppy, ejecting...\n"); + fclose(dev->f); + free(dev); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; + } + + dev->gap2_size = (temp_rate == 3) ? 41 : 22; + if (dev->dmf) + dev->gap3_size = 8; + else + dev->gap3_size = gap3_sizes[temp_rate][dev->sector_size][dev->sectors]; + if (! dev->gap3_size) { + pclog("ERROR: Floppy image of unknown format was inserted into drive %c:!\n", drive + 0x41); + fclose(dev->f); + free(dev); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; + } + + dev->track_width = 0; + if (dev->tracks > 43) + dev->track_width = 1; /* If the image has more than 43 tracks, then the tracks are thin (96 tpi). */ + if (dev->sides == 2) + dev->disk_flags |= 8; /* If the has 2 sides, mark it as such. */ + if (dev->interleave == 2) { + dev->interleave = 1; + dev->disk_flags |= 0x60; + } + + dev->track_flags = 0x08; /* IMG files are always assumed to be MFM-encoded. */ + dev->track_flags |= temp_rate & 3; /* Data rate. */ + if (temp_rate & 4) + dev->track_flags |= 0x20; /* RPM. */ + + dev->is_cqm = cqm; + + pclog("Disk flags: %i, track flags: %i\n", + dev->disk_flags, dev->track_flags); + + /* Set up the drive unit. */ + img[drive] = dev; + + /* Attach this format to the D86F engine. */ + d86f_handler[drive].disk_flags = disk_flags; + d86f_handler[drive].side_flags = side_flags; + d86f_handler[drive].writeback = write_back; + d86f_handler[drive].set_sector = set_sector; + d86f_handler[drive].read_data = poll_read_data; + d86f_handler[drive].write_data = poll_write_data; + d86f_handler[drive].format_conditions = format_conditions; + d86f_handler[drive].extra_bit_cells = null_extra_bit_cells; + d86f_handler[drive].encoded_data = common_encoded_data; + d86f_handler[drive].read_revolution = common_read_revolution; + d86f_handler[drive].index_hole_pos = null_index_hole_pos; + d86f_handler[drive].get_raw_size = common_get_raw_size; + d86f_handler[drive].check_crc = 1; + d86f_set_version(drive, 0x0063); + + drives[drive].seek = img_seek; + + d86f_common_handlers(drive); } -int img_format_conditions(int drive) + +void +img_close(int drive) { - int temp = (fdc_get_format_sectors(img_fdc) == img[drive].sectors); - temp = temp && (fdc_get_format_n(img_fdc) == img[drive].sector_size); - temp = temp && (img[drive].xdf_type == 0); - return temp; + img_t *dev = img[drive]; + + if (dev == NULL) return; + + d86f_unregister(drive); + + if (dev->f != NULL) { + fclose(dev->f); + dev->f = NULL; + } + + if (dev->disk_data != NULL) + free(dev->disk_data); + + /* Release the memory. */ + free(dev); + img[drive] = NULL; } -void img_set_fdc(void *fdc) -{ - img_fdc = (fdc_t *) fdc; -} -void d86f_register_img(int drive) +void +img_set_fdc(void *fdc) { - 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].extra_bit_cells = null_extra_bit_cells; - d86f_handler[drive].encoded_data = common_encoded_data; - d86f_handler[drive].read_revolution = common_read_revolution; - d86f_handler[drive].index_hole_pos = null_index_hole_pos; - d86f_handler[drive].get_raw_size = common_get_raw_size; - d86f_handler[drive].check_crc = 1; - d86f_set_version(drive, 0x0063); + img_fdc = (fdc_t *) fdc; } diff --git a/src/floppy/fdd_img.h b/src/floppy/fdd_img.h index 81c2d8035..b5bddb4ad 100644 --- a/src/floppy/fdd_img.h +++ b/src/floppy/fdd_img.h @@ -1,29 +1,49 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * Implementation of the raw sector-based floppy image format, * as well as the Japanese FDI, CopyQM, and FDF formats. * - * Version: @(#)floppy_img.h 1.0.2 2017/09/03 + * Version: @(#)floppy_img.h 1.0.2 2018/03/17 * - * Authors: Sarah Walker, + * Authors: Fred N. van Kempen, * Miran Grca, - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Sarah Walker, + * + * Copyright 2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ #ifndef EMU_FLOPPY_IMG_H # define EMU_FLOPPY_IMG_H -extern void img_init(void); -extern void img_load(int drive, wchar_t *fn); -extern void img_close(int drive); -extern void img_seek(int drive, int track); +extern void img_init(void); +extern void img_load(int drive, wchar_t *fn); +extern void img_close(int drive); #endif /*EMU_FLOPPY_IMG_H*/ diff --git a/src/floppy/fdd_json.c b/src/floppy/fdd_json.c index 1daad4ee8..d3ae99ac9 100644 --- a/src/floppy/fdd_json.c +++ b/src/floppy/fdd_json.c @@ -1,18 +1,48 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * Implementation of the PCjs JSON floppy image format. * - * Version: @(#)fdd_json.c 1.0.11 2018/03/14 + * Version: @(#)fdd_json.c 1.0.4 2018/03/17 * * Author: Fred N. van Kempen, * * Copyright 2017,2018 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above 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. + * + * 3. Neither the name of the copyright holder 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 + * HOLDER 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 #include @@ -71,11 +101,11 @@ typedef struct { } json_t; -static json_t images[FDD_NUM]; +static json_t *images[FDD_NUM]; static void -handle(json_t *img, char *name, char *str) +handle(json_t *dev, char *name, char *str) { sector_t *sec = NULL; uint32_t l, pat; @@ -84,7 +114,7 @@ handle(json_t *img, char *name, char *str) int i, s; /* Point to the currently selected sector. */ - sec = &img->sects[img->track][img->side][img->dmf-1]; + sec = &dev->sects[dev->track][dev->side][dev->dmf-1]; /* If no name given, assume sector is done. */ if (name == NULL) { @@ -98,8 +128,8 @@ handle(json_t *img, char *name, char *str) sec->size = fdd_sector_size_code(sec->size); /* Set up the rest of the Sector ID. */ - sec->track = img->track; - sec->side = img->side; + sec->track = dev->track; + sec->side = dev->side; return; } @@ -159,13 +189,13 @@ unexpect(int c, int state, int level) static int -load_image(json_t *img) +load_image(json_t *dev) { char buff[4096], name[32]; int c, i, j, state, level; char *ptr; - if (img->f == NULL) { + if (dev->f == NULL) { pclog("JSON: no file loaded!\n"); return(0); } @@ -173,17 +203,17 @@ load_image(json_t *img) /* Initialize. */ for (i=0; isects[i][j], 0x00, sizeof(sector_t)); + memset(dev->sects[i][j], 0x00, sizeof(sector_t)); } - img->track = img->side = img->dmf = 0; /* "dmf" is "sector#" */ + dev->track = dev->side = dev->dmf = 0; /* "dmf" is "sector#" */ /* Now run the state machine. */ ptr = NULL; level = state = 0; while (state >= 0) { /* Get a character from the input. */ - c = fgetc(img->f); - if ((c == EOF) || ferror(img->f)) { + c = fgetc(dev->f); + if ((c == EOF) || ferror(dev->f)) { state = -1; break; } @@ -191,7 +221,7 @@ load_image(json_t *img) /* Process it. */ switch(state) { case 0: /* read level header */ - img->dmf = 1; + dev->dmf = 1; if (c != '[') { state = unexpect(c, state, level); } else { @@ -239,7 +269,7 @@ load_image(json_t *img) case ',': case '}': *ptr = '\0'; - handle(img, name, buff); + handle(dev, name, buff); if (c == '}') state = 7; /* done */ @@ -264,10 +294,10 @@ load_image(json_t *img) break; case 7: /* sector done */ - handle(img, NULL, NULL); + handle(dev, NULL, NULL); switch(c) { case ',': /* next sector */ - img->dmf++; + dev->dmf++; state = 1; break; @@ -297,14 +327,14 @@ load_image(json_t *img) default: state = unexpect(c, state, level); } - img->spt[img->track][img->side] = img->dmf; - img->side++; + dev->spt[dev->track][dev->side] = dev->dmf; + dev->side++; break; case 9: /* track done */ switch(c) { case ',': /* next track */ - img->side = 0; + dev->side = 0; state = 0; break; @@ -317,15 +347,15 @@ load_image(json_t *img) default: state = unexpect(c, state, level); } - img->track++; + dev->track++; break; } } /* Save derived values. */ - img->tracks = img->track; - img->sides = img->side; + dev->tracks = dev->track; + dev->sides = dev->side; return(1); } @@ -336,69 +366,71 @@ static void json_seek(int drive, int track) { uint8_t id[4] = { 0,0,0,0 }; - json_t *img = &images[drive]; + json_t *dev = images[drive]; int side, sector; int rate, gap2, gap3, pos; int ssize, rsec, asec; int interleave_type; - if (img->f == NULL) { + if (dev->f == NULL) { pclog("JSON: seek: no file loaded!\n"); return; } /* Allow for doublestepping tracks. */ - if (! img->track_width && fdd_doublestep_40(drive)) track /= 2; + if (! dev->track_width && fdd_doublestep_40(drive)) track /= 2; /* Set the new track. */ - img->track = track; + dev->track = track; d86f_set_cur_track(drive, track); /* Reset the 86F state machine. */ d86f_reset_index_hole_pos(drive, 0); - d86f_reset_index_hole_pos(drive, 1); d86f_destroy_linked_lists(drive, 0); + d86f_reset_index_hole_pos(drive, 1); d86f_destroy_linked_lists(drive, 1); interleave_type = 0; - if (track > img->tracks) { + if (track > dev->tracks) { d86f_zero_track(drive); return; } - for (side=0; sidesides; side++) { + for (side=0; sidesides; side++) { /* Get transfer rate for this side. */ - rate = img->track_flags & 0x07; - if (!rate && (img->track_flags & 0x20)) rate = 4; + rate = dev->track_flags & 0x07; + if (!rate && (dev->track_flags & 0x20)) rate = 4; /* Get correct GAP3 value for this side. */ gap3 = fdd_get_gap3_size(rate, - img->sects[track][side][0].size, - img->spt[track][side]); + dev->sects[track][side][0].size, + dev->spt[track][side]); /* Get correct GAP2 value for this side. */ - gap2 = ((img->track_flags & 0x07) >= 3) ? 41 : 22; + gap2 = ((dev->track_flags & 0x07) >= 3) ? 41 : 22; pos = d86f_prepare_pretrack(drive, side, 0); - for (sector=0; sectorspt[track][side]; sector++) { + for (sector=0; sectorspt[track][side]; sector++) { if (interleave_type == 0) { - rsec = img->sects[track][side][sector].sector; + rsec = dev->sects[track][side][sector].sector; asec = sector; } else { rsec = fdd_dmf_r[sector]; - asec = img->interleave_ordered[rsec][side]; + asec = dev->interleave_ordered[rsec][side]; } id[0] = track; id[1] = side; id[2] = rsec; - id[3] = img->sects[track][side][asec].size; - ssize = fdd_sector_code_size(img->sects[track][side][asec].size); + if (dev->sects[track][side][asec].size > 255) + perror("fdd_json.c: json_seek: sector size too big."); + id[3] = dev->sects[track][side][asec].size & 0xff; + ssize = fdd_sector_code_size(dev->sects[track][side][asec].size & 0xff); pos = d86f_prepare_sector( drive, side, pos, id, - img->sects[track][side][asec].data, + dev->sects[track][side][asec].data, ssize, gap2, gap3, 0, /*deleted flag*/ 0 /*bad_crc flag*/ @@ -414,38 +446,42 @@ json_seek(int drive, int track) static uint16_t disk_flags(int drive) { - return(images[drive].disk_flags); + json_t *dev = images[drive]; + + return(dev->disk_flags); } static uint16_t track_flags(int drive) { - return(images[drive].track_flags); + json_t *dev = images[drive]; + + return(dev->track_flags); } static void set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n) { - json_t *img = &images[drive]; + json_t *dev = images[drive]; int i; - img->sector[side] = 0; + dev->sector[side] = 0; /* Make sure we are on the desired track. */ - if (c != img->track) return; + if (c != dev->track) return; /* Set the desired side. */ - img->side = side; + dev->side = side; /* Now loop over all sector ID's on this side to find our sector. */ - for (i=0; ispt[c][side]; i++) { - if ((img->sects[img->track][side][i].track == c) && - (img->sects[img->track][side][i].side == h) && - (img->sects[img->track][side][i].sector == r) && - (img->sects[img->track][side][i].size == n)) { - img->sector[side] = i; + for (i=0; ispt[c][side]; i++) { + if ((dev->sects[dev->track][side][i].track == c) && + (dev->sects[dev->track][side][i].side == h) && + (dev->sects[dev->track][side][i].sector == r) && + (dev->sects[dev->track][side][i].size == n)) { + dev->sector[side] = i; } } } @@ -454,10 +490,10 @@ set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n) static uint8_t poll_read_data(int drive, int side, uint16_t pos) { - json_t *img = &images[drive]; - uint8_t sec = img->sector[side]; + json_t *dev = images[drive]; + uint8_t sec = dev->sector[side]; - return(img->sects[img->track][side][sec].data[pos]); + return(dev->sects[dev->track][side][sec].data[pos]); } @@ -471,21 +507,23 @@ json_init(void) void json_load(int drive, wchar_t *fn) { - json_t *img = &images[drive]; - sector_t *sec; double bit_rate; int temp_rate; + sector_t *sec; + json_t *dev; int i; /* Just in case- remove ourselves from 86F. */ d86f_unregister(drive); - /* Zap any old data. */ - memset(img, 0x00, sizeof(json_t)); + /* Allocate a drive block. */ + dev = (json_t *)malloc(sizeof(json_t)); + memset(dev, 0x00, sizeof(json_t)); /* Open the image file. */ - img->f = plat_fopen(fn, L"rb"); - if (img->f == NULL) { + dev->f = plat_fopen(fn, L"rb"); + if (dev->f == NULL) { + free(dev); memset(fn, 0x00, sizeof(wchar_t)); return; } @@ -493,66 +531,70 @@ json_load(int drive, wchar_t *fn) /* Our images are always RO. */ writeprot[drive] = 1; + /* Set up the drive unit. */ + images[drive] = dev; + /* Load all sectors from the image file. */ - if (! load_image(img)) { + if (! load_image(dev)) { pclog("JSON: failed to initialize\n"); - (void)fclose(img->f); - img->f = NULL; + (void)fclose(dev->f); + free(dev); + images[drive] = NULL; memset(fn, 0x00, sizeof(wchar_t)); return; } pclog("JSON(%d): %ls (%i tracks, %i sides, %i sectors)\n", - drive, fn, img->tracks, img->sides, img->spt[0][0]); + drive, fn, dev->tracks, dev->sides, dev->spt[0][0]); /* * If the image has more than 43 tracks, then * the tracks are thin (96 tpi). */ - img->track_width = (img->tracks > 43) ? 1 : 0; + dev->track_width = (dev->tracks > 43) ? 1 : 0; /* If the image has 2 sides, mark it as such. */ - img->disk_flags = 0x00; - if (img->sides == 2) - img->disk_flags |= 0x08; + dev->disk_flags = 0x00; + if (dev->sides == 2) + dev->disk_flags |= 0x08; /* JSON files are always assumed to be MFM-encoded. */ - img->track_flags = 0x08; + dev->track_flags = 0x08; - img->interleave = 0; + dev->interleave = 0; #if 0 - img->skew = 0; + dev->skew = 0; #endif temp_rate = 0xff; - sec = &img->sects[0][0][0]; + sec = &dev->sects[0][0][0]; for (i=0; i<6; i++) { - if (img->spt[0][0] > fdd_max_sectors[sec->size][i]) continue; + if (dev->spt[0][0] > fdd_max_sectors[sec->size][i]) continue; bit_rate = fdd_bit_rates_300[i]; temp_rate = fdd_rates[i]; - img->disk_flags |= (fdd_holes[i] << 1); + dev->disk_flags |= (fdd_holes[i] << 1); - if ((bit_rate == 500.0) && (img->spt[0][0] == 21) && - (sec->size == 2) && (img->tracks >= 80) && - (img->tracks <= 82) && (img->sides == 2)) { + if ((bit_rate == 500.0) && (dev->spt[0][0] == 21) && + (sec->size == 2) && (dev->tracks >= 80) && + (dev->tracks <= 82) && (dev->sides == 2)) { /* * This is a DMF floppy, set the flag so * we know to interleave the sectors. */ - img->dmf = 1; + dev->dmf = 1; } else { - if ((bit_rate == 500.0) && (img->spt[0][0] == 22) && - (sec->size == 2) && (img->tracks >= 80) && - (img->tracks <= 82) && (img->sides == 2)) { + if ((bit_rate == 500.0) && (dev->spt[0][0] == 22) && + (sec->size == 2) && (dev->tracks >= 80) && + (dev->tracks <= 82) && (dev->sides == 2)) { /* * This is marked specially because of the * track flag (a RPM slow down is needed). */ - img->interleave = 2; + dev->interleave = 2; } - img->dmf = 0; + dev->dmf = 0; } break; @@ -560,41 +602,44 @@ json_load(int drive, wchar_t *fn) if (temp_rate == 0xff) { pclog("JSON: invalid image (temp_rate=0xff)\n"); - (void)fclose(img->f); - img->f = NULL; + (void)fclose(dev->f); + dev->f = NULL; + free(dev); + images[drive] = NULL; memset(fn, 0x00, sizeof(wchar_t)); return; } - if (img->interleave == 2) { - img->interleave = 1; - img->disk_flags |= 0x60; + if (dev->interleave == 2) { + dev->interleave = 1; + dev->disk_flags |= 0x60; } - img->gap2_len = (temp_rate == 3) ? 41 : 22; - if (img->dmf) { - img->gap3_len = 8; - } else { - img->gap3_len = fdd_get_gap3_size(temp_rate,sec->size,img->spt[0][0]); - } + dev->gap2_len = (temp_rate == 3) ? 41 : 22; + if (dev->dmf) + dev->gap3_len = 8; + else + dev->gap3_len = fdd_get_gap3_size(temp_rate,sec->size,dev->spt[0][0]); - if (! img->gap3_len) { + if (! dev->gap3_len) { pclog("JSON: image of unknown format was inserted into drive %c:!\n", 'C'+drive); - (void)fclose(img->f); - img->f = NULL; + (void)fclose(dev->f); + dev->f = NULL; + free(dev); + images[drive] = NULL; memset(fn, 0x00, sizeof(wchar_t)); return; } - img->track_flags |= (temp_rate & 0x03); /* data rate */ + dev->track_flags |= (temp_rate & 0x03); /* data rate */ if (temp_rate & 0x04) - img->track_flags |= 0x20; /* RPM */ + dev->track_flags |= 0x20; /* RPM */ pclog(" disk_flags: 0x%02x, track_flags: 0x%02x, GAP3 length: %i\n", - img->disk_flags, img->track_flags, img->gap3_len); + dev->disk_flags, dev->track_flags, dev->gap3_len); pclog(" bit rate 300: %.2f, temporary rate: %i, hole: %i, DMF: %i\n", - bit_rate, temp_rate, (img->disk_flags >> 1), img->dmf); + bit_rate, temp_rate, (dev->disk_flags >> 1), dev->dmf); /* Set up handlers for 86F layer. */ d86f_handler[drive].disk_flags = disk_flags; @@ -622,26 +667,30 @@ json_load(int drive, wchar_t *fn) void json_close(int drive) { - json_t *img = &images[drive]; + json_t *dev = images[drive]; int t, h, s; + if (dev == NULL) return; + /* Unlink image from the system. */ d86f_unregister(drive); /* Release all the sector buffers. */ for (t=0; t<256; t++) { for (h=0; h<2; h++) { - memset(img->sects[t][h], 0x00, sizeof(sector_t)); + memset(dev->sects[t][h], 0x00, sizeof(sector_t)); for (s=0; s<256; s++) { - if (img->sects[t][h][s].data != NULL) - free(img->sects[t][h][s].data); - img->sects[t][h][s].data = NULL; + if (dev->sects[t][h][s].data != NULL) + free(dev->sects[t][h][s].data); + dev->sects[t][h][s].data = NULL; } } } - if (img->f != NULL) { - (void)fclose(img->f); - img->f = NULL; - } + if (dev->f != NULL) + (void)fclose(dev->f); + + /* Release the memory. */ + free(dev); + images[drive] = NULL; } diff --git a/src/floppy/fdd_json.h b/src/floppy/fdd_json.h index 82e2a6820..0df9dab7d 100644 --- a/src/floppy/fdd_json.h +++ b/src/floppy/fdd_json.h @@ -1,26 +1,56 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * - * Implementation of the PCjs JSON floppy image format. + * Definitions for the PCjs JSON floppy image format. * - * Version: @(#)floppy_json.h 1.0.1 2017/09/06 + * Version: @(#)floppy_json.h 1.0.2 2018/03/17 * * Author: Fred N. van Kempen, - * Copyright 2017 Fred N. van Kempen. + * + * Copyright 2017,2018 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above 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. + * + * 3. Neither the name of the copyright holder 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 + * HOLDER 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 EMU_FLOPPY_JSON_H # define EMU_FLOPPY_JSON_H -//extern void json_init(void); +extern void json_init(void); extern void json_load(int drive, wchar_t *fn); extern void json_close(int drive); -//extern void json_seek(int drive, int track); #endif /*EMU_FLOPPY_JSON_H*/ diff --git a/src/floppy/fdd_td0.c b/src/floppy/fdd_td0.c index c3056f705..b5558437f 100644 --- a/src/floppy/fdd_td0.c +++ b/src/floppy/fdd_td0.c @@ -1,41 +1,50 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * Implementation of the Teledisk floppy image format. * - * Version: @(#)fdd_td0.c 1.0.8 2018/03/14 + * Version: @(#)fdd_td0.c 1.0.4 2018/03/17 * - * Authors: Milodrag Milanovic, + * Authors: Fred N. van Kempen, + * Miran Grca, + * Milodrag Milanovic, * Haruhiko OKUMURA, * Haruyasu YOSHIZAKI, * Kenji RIKITAKE, - * Miran Grca, + * + * Based on Japanese version 29-NOV-1988 + * LZSS coded by Haruhiko OKUMURA + * Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI + * Edited and translated to English by Kenji RIKITAKE + * + * Copyright 2016-2018 Miran Grca. + * Copyright 2013-2018 Milodrag Milanovic. * Copyright 1988-2018 Haruhiko OKUMURA. * Copyright 1988-2018 Haruyasu YOSHIZAKI. * Copyright 1988-2018 Kenji RIKITAKE. - * Copyright 2013-2018 Milodrag Milanovic. - * Copyright 2016-2018 Miran Grca. - */ - -/* license:BSD-3-Clause - copyright-holders:Miodrag Milanovic, Miran Grca (translation to C and port to 86Box) */ -/********************************************************************* - - formats/td0_dsk.c - - TD0 disk images - -*********************************************************************/ -/* - * Based on Japanese version 29-NOV-1988 - * LZSS coded by Haruhiko OKUMURA - * Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI - * Edited and translated to English by Kenji RIKITAKE + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ #include #include @@ -49,1204 +58,1164 @@ #include "fdc.h" -#define BUFSZ 512 /* new input buffer */ +#define BUFSZ 512 /* new input buffer */ +#define TD0_MAX_BUFSZ (1024UL*1024UL*4UL) /* LZSS Parameters */ - -#define N 4096 /* Size of string buffer */ -#define F 60 /* Size of look-ahead buffer */ -#define THRESHOLD 2 -#define NIL N /* End of tree's node */ - +#define N 4096 /* Size of string buffer */ +#define F 60 /* Size of look-ahead buffer */ +#define THRESHOLD 2 +#define NIL N /* End of tree's node */ /* Huffman coding parameters */ - -#define N_CHAR (256 - THRESHOLD + F) - /* character code (= 0..N_CHAR-1) */ -#define T (N_CHAR * 2 - 1) /* Size of table */ -#define R (T - 1) /* root position */ -#define MAX_FREQ 0x8000 +#define N_CHAR (256-THRESHOLD+F) /* code (= 0..N_CHAR-1) */ +#define T (N_CHAR*2-1) /* Size of table */ +#define R (T-1) /* root position */ +#define MAX_FREQ 0x8000 /* update when cumulative frequency */ /* reaches to this value */ typedef struct { - uint16_t r, - bufcnt,bufndx,bufpos, /* string buffer */ - /* the following to allow block reads from input in next_word() */ - ibufcnt,ibufndx; /* input buffer counters */ - uint8_t inbuf[BUFSZ]; /* input buffer */ + uint16_t r, + bufcnt,bufndx,bufpos, /* string buffer */ + /* the following to allow block reads + from input in next_word() */ + ibufcnt,ibufndx; /* input buffer counters */ + uint8_t inbuf[BUFSZ]; /* input buffer */ } tdlzhuf; -typedef struct -{ - FILE *fdd_file; - uint64_t fdd_file_offset; +typedef struct { + FILE *fdd_file; + off_t fdd_file_offset; - tdlzhuf tdctl; - uint8_t text_buf[N + F - 1]; - uint16_t freq[T + 1]; /* cumulative freq table */ + tdlzhuf tdctl; + uint8_t text_buf[N + F - 1]; + uint16_t freq[T + 1]; /* cumulative freq table */ -/* - * pointing parent nodes. - * area [T..(T + N_CHAR - 1)] are pointers for leaves - */ - int16_t prnt[T + N_CHAR]; + /* + * pointing parent nodes. + * area [T..(T + N_CHAR - 1)] are pointers for leaves + */ + int16_t prnt[T + N_CHAR]; - /* pointing children nodes (son[], son[] + 1)*/ - int16_t son[T]; + /* pointing children nodes (son[], son[] + 1)*/ + int16_t son[T]; - uint16_t getbuf; - uint8_t getlen; + uint16_t getbuf; + uint8_t getlen; } td0dsk_t; -typedef struct -{ - uint8_t track; - uint8_t head; - uint8_t sector; - uint8_t size; - uint8_t deleted; - uint8_t bad_crc; - uint8_t *data; +typedef struct { + uint8_t track; + uint8_t head; + uint8_t sector; + uint8_t size; + uint8_t deleted; + uint8_t bad_crc; + uint8_t *data; } td0_sector_t; -typedef struct -{ - FILE *f; +typedef struct { + FILE *f; - int tracks; - int track_width; - int sides; - uint16_t disk_flags; - uint16_t default_track_flags; - uint16_t side_flags[256][2]; - uint8_t track_in_file[256][2]; - td0_sector_t sects[256][2][256]; - uint8_t track_spt[256][2]; - uint8_t gap3_len; - uint16_t current_side_flags[2]; - int track; - int current_sector_index[2]; - uint8_t calculated_gap3_lengths[256][2]; - uint8_t xdf_ordered_pos[256][2]; - uint8_t interleave_ordered_pos[256][2]; + int tracks; + int track_width; + int sides; + uint16_t disk_flags; + uint16_t default_track_flags; + uint16_t side_flags[256][2]; + uint8_t track_in_file[256][2]; + td0_sector_t sects[256][2][256]; + uint8_t track_spt[256][2]; + uint8_t gap3_len; + uint16_t current_side_flags[2]; + int track; + int current_sector_index[2]; + uint8_t calculated_gap3_lengths[256][2]; + uint8_t xdf_ordered_pos[256][2]; + uint8_t interleave_ordered_pos[256][2]; + + uint8_t *imagebuf; + uint8_t *processed_buf; } td0_t; -td0_t td0[FDD_NUM]; - - -void fdd_image_read(int drive, char *buffer, uint32_t offset, uint32_t len) -{ - fseek(td0[drive].f, offset, SEEK_SET); - fread(buffer, 1, len, td0[drive].f); -} - -int td0_dsk_identify(int drive) -{ - char header[2]; - - fdd_image_read(drive, header, 0, 2); - if (header[0]=='T' && header[1]=='D') { - return 1; - } else if (header[0]=='t' && header[1]=='d') { - return 1; - } else { - return 0; - } -} - -int td0_state_data_read(td0dsk_t *state, uint8_t *buf, uint16_t size) -{ - uint32_t image_size = 0; - fseek(state->fdd_file, 0, SEEK_END); - image_size = ftell(state->fdd_file); - if (size > image_size - state->fdd_file_offset) { - size = image_size - state->fdd_file_offset; - } - fseek(state->fdd_file, state->fdd_file_offset, SEEK_SET); - fread(buf, 1, size, state->fdd_file); - state->fdd_file_offset += size; - return size; -} - /* * Tables for encoding/decoding upper 6 bits of * sliding dictionary pointer */ - -/* decoder table */ static const uint8_t d_code[256] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, - 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, - 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, - 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, - 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, - 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, - 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, - 0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, - 0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F, - 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, - 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, - 0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B, - 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, + 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, + 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, + 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, + 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, + 0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, + 0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F, + 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, + 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, + 0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B, + 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, }; static const uint8_t d_len[256] = { - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, }; -int td0_state_next_word(td0dsk_t *state) + +static td0_t *td0[FDD_NUM]; + + +static void +fdd_image_read(int drive, char *buffer, uint32_t offset, uint32_t len) { - if(state->tdctl.ibufndx >= state->tdctl.ibufcnt) - { - state->tdctl.ibufndx = 0; - state->tdctl.ibufcnt = td0_state_data_read(state, state->tdctl.inbuf,BUFSZ); - if(state->tdctl.ibufcnt == 0) - return(-1); - } - while (state->getlen <= 8) { /* typically reads a word at a time */ - state->getbuf |= state->tdctl.inbuf[state->tdctl.ibufndx++] << (8 - state->getlen); - state->getlen += 8; - } - return(0); + td0_t *dev = td0[drive]; + + fseek(dev->f, offset, SEEK_SET); + fread(buffer, 1, len, dev->f); } -int td0_state_GetBit(td0dsk_t *state) /* get one bit */ +static int +dsk_identify(int drive) { - int16_t i; - if(td0_state_next_word(state) < 0) + char header[2]; + + fdd_image_read(drive, header, 0, 2); + if (header[0]=='T' && header[1]=='D') + return(1); + else if (header[0]=='t' && header[1]=='d') + return(1); + + return(0); +} + + +static int +state_data_read(td0dsk_t *state, uint8_t *buf, uint16_t size) +{ + uint32_t image_size = 0; + + fseek(state->fdd_file, 0, SEEK_END); + image_size = ftell(state->fdd_file); + if (size > image_size - state->fdd_file_offset) + size = (image_size - state->fdd_file_offset) & 0xffff; + fseek(state->fdd_file, state->fdd_file_offset, SEEK_SET); + fread(buf, 1, size, state->fdd_file); + state->fdd_file_offset += size; + + return(size); +} + + +static int +state_next_word(td0dsk_t *state) +{ + if (state->tdctl.ibufndx >= state->tdctl.ibufcnt) { + state->tdctl.ibufndx = 0; + state->tdctl.ibufcnt = state_data_read(state, state->tdctl.inbuf,BUFSZ); + if (state->tdctl.ibufcnt == 0) return(-1); - i = state->getbuf; - state->getbuf <<= 1; - state->getlen--; - if(i < 0) - return(1); - else - return(0); + } + + while (state->getlen <= 8) { /* typically reads a word at a time */ + state->getbuf |= state->tdctl.inbuf[state->tdctl.ibufndx++] << (8 - state->getlen); + state->getlen += 8; + } + + return(0); } -int td0_state_GetByte(td0dsk_t *state) /* get a byte */ + +/* get one bit */ +static int +state_GetBit(td0dsk_t *state) { - uint16_t i; - if(td0_state_next_word(state) != 0) - return(-1); - i = state->getbuf; - state->getbuf <<= 8; - state->getlen -= 8; - i = i >> 8; - return((int) i); + int16_t i; + + if (state_next_word(state) < 0) + return(-1); + + i = state->getbuf; + state->getbuf <<= 1; + state->getlen--; + if (i < 0) + return(1); + + return(0); } +/* get a byte */ +static int +state_GetByte(td0dsk_t *state) +{ + uint16_t i; + + if (state_next_word(state) != 0) + return(-1); + + i = state->getbuf; + state->getbuf <<= 8; + state->getlen -= 8; + i = i >> 8; + + return((int) i); +} + /* initialize freq tree */ - -void td0_state_StartHuff(td0dsk_t *state) +static void +state_StartHuff(td0dsk_t *state) { - int i, j; + int i, j; - for (i = 0; i < N_CHAR; i++) { - state->freq[i] = 1; - state->son[i] = i + T; - state->prnt[i + T] = i; - } - i = 0; j = N_CHAR; - while (j <= R) { - state->freq[j] = state->freq[i] + state->freq[i + 1]; - state->son[j] = i; - state->prnt[i] = state->prnt[i + 1] = j; - i += 2; j++; - } - state->freq[T] = 0xffff; - state->prnt[R] = 0; + for (i = 0; i < N_CHAR; i++) { + state->freq[i] = 1; + state->son[i] = i + T; + state->prnt[i + T] = i; + } + i = 0; j = N_CHAR; + while (j <= R) { + state->freq[j] = state->freq[i] + state->freq[i + 1]; + state->son[j] = i; + state->prnt[i] = state->prnt[i + 1] = j; + i += 2; j++; + } + state->freq[T] = 0xffff; + state->prnt[R] = 0; } /* reconstruct freq tree */ - -void td0_state_reconst(td0dsk_t *state) +static void +state_reconst(td0dsk_t *state) { - int16_t i, j, k; - uint16_t f, l; + int16_t i, j, k; + uint16_t f, l; - /* halven cumulative freq for leaf nodes */ - j = 0; - for (i = 0; i < T; i++) { - if (state->son[i] >= T) { - state->freq[j] = (state->freq[i] + 1) / 2; - state->son[j] = state->son[i]; - j++; - } + /* halven cumulative freq for leaf nodes */ + j = 0; + for (i = 0; i < T; i++) { + if (state->son[i] >= T) { + state->freq[j] = (state->freq[i] + 1) / 2; + state->son[j] = state->son[i]; + j++; } - /* make a tree : first, connect children nodes */ - for (i = 0, j = N_CHAR; j < T; i += 2, j++) { - k = i + 1; - f = state->freq[j] = state->freq[i] + state->freq[k]; - for (k = j - 1; f < state->freq[k]; k--) {}; - k++; - l = (j - k) * 2; + } - /* movmem() is Turbo-C dependent - rewritten to memmove() by Kenji */ + /* make a tree : first, connect children nodes */ + for (i = 0, j = N_CHAR; j < T; i += 2, j++) { + k = i + 1; + f = state->freq[j] = state->freq[i] + state->freq[k]; + for (k = j - 1; f < state->freq[k]; k--) {}; + k++; + l = (j - k) * 2; - /* movmem(&freq[k], &freq[k + 1], l); */ - (void)memmove(&state->freq[k + 1], &state->freq[k], l); - state->freq[k] = f; - /* movmem(&son[k], &son[k + 1], l); */ - (void)memmove(&state->son[k + 1], &state->son[k], l); - state->son[k] = i; - } - /* connect parent nodes */ - for (i = 0; i < T; i++) { - if ((k = state->son[i]) >= T) { - state->prnt[k] = i; - } else { - state->prnt[k] = state->prnt[k + 1] = i; - } - } + memcpy(&state->freq[k + 1], &state->freq[k], l); + state->freq[k] = f; + memcpy(&state->son[k + 1], &state->son[k], l); + state->son[k] = i; + } + + /* connect parent nodes */ + for (i = 0; i < T; i++) { + if ((k = state->son[i]) >= T) + state->prnt[k] = i; + else + state->prnt[k] = state->prnt[k + 1] = i; + } } /* update freq tree */ - -void td0_state_update(td0dsk_t *state, int c) +static void +state_update(td0dsk_t *state, int c) { - int i, j, k, l; + int i, j, k, l; - if (state->freq[R] == MAX_FREQ) { - td0_state_reconst(state); + if (state->freq[R] == MAX_FREQ) + state_reconst(state); + + c = state->prnt[c + T]; + + /* do it until reaching the root */ + do { + k = ++state->freq[c]; + + /* swap nodes to keep the tree freq-ordered */ + if (k > state->freq[l = c + 1]) { + while (k > state->freq[++l]) {}; + l--; + state->freq[c] = state->freq[l]; + state->freq[l] = k; + + i = state->son[c]; + state->prnt[i] = l; + if (i < T) state->prnt[i + 1] = l; + + j = state->son[l]; + state->son[l] = i; + + state->prnt[j] = c; + if (j < T) state->prnt[j + 1] = c; + state->son[c] = j; + + c = l; } - c = state->prnt[c + T]; - do { - k = ++state->freq[c]; - - /* swap nodes to keep the tree freq-ordered */ - if (k > state->freq[l = c + 1]) { - while (k > state->freq[++l]) {}; - l--; - state->freq[c] = state->freq[l]; - state->freq[l] = k; - - i = state->son[c]; - state->prnt[i] = l; - if (i < T) state->prnt[i + 1] = l; - - j = state->son[l]; - state->son[l] = i; - - state->prnt[j] = c; - if (j < T) state->prnt[j + 1] = c; - state->son[c] = j; - - c = l; - } - } while ((c = state->prnt[c]) != 0); /* do it until reaching the root */ + } while ((c = state->prnt[c]) != 0); } -int16_t td0_state_DecodeChar(td0dsk_t *state) +static int16_t +state_DecodeChar(td0dsk_t *state) { - int ret; - uint16_t c; + int ret; + uint16_t c; - c = state->son[R]; + c = state->son[R]; - /* - * start searching tree from the root to leaves. - * choose node #(son[]) if input bit == 0 - * else choose #(son[]+1) (input bit == 1) - */ - while (c < T) { - if((ret = td0_state_GetBit(state)) < 0) - return(-1); - c += (unsigned) ret; - c = state->son[c]; - } - c -= T; - td0_state_update(state, c); - return c; -} - -int16_t td0_state_DecodePosition(td0dsk_t *state) -{ - int16_t bit; - uint16_t i, j, c; - - /* decode upper 6 bits from given table */ - if((bit=td0_state_GetByte(state)) < 0) + /* + * start searching tree from the root to leaves. + * choose node #(son[]) if input bit == 0 + * else choose #(son[]+1) (input bit == 1) + */ + while (c < T) { + if ((ret = state_GetBit(state)) < 0) return(-1); - i = (uint16_t) bit; - c = (uint16_t)d_code[i] << 6; - j = d_len[i]; + c += (unsigned) ret; + c = state->son[c]; + } + c -= T; - /* input lower 6 bits directly */ - j -= 2; - while (j--) { - if((bit = td0_state_GetBit(state)) < 0) - return(-1); - i = (i << 1) + bit; - } - return(c | (i & 0x3f)); -} + state_update(state, c); -/* DeCompression - -split out initialization code to init_Decode() - -*/ - -void td0_state_init_Decode(td0dsk_t *state) -{ - int i; - state->getbuf = 0; - state->getlen = 0; - state->tdctl.ibufcnt= state->tdctl.ibufndx = 0; /* input buffer is empty */ - state->tdctl.bufcnt = 0; - td0_state_StartHuff(state); - for (i = 0; i < N - F; i++) - state->text_buf[i] = ' '; - state->tdctl.r = N - F; + return(c); } -int td0_state_Decode(td0dsk_t *state, uint8_t *buf, int len) /* Decoding/Uncompressing */ +static int16_t +state_DecodePosition(td0dsk_t *state) { - int16_t c,pos; - int count; /* was an unsigned long, seems unnecessary */ - for (count = 0; count < len; ) { - if(state->tdctl.bufcnt == 0) { - if((c = td0_state_DecodeChar(state)) < 0) - return(count); /* fatal error */ - if (c < 256) { - *(buf++) = c; - state->text_buf[state->tdctl.r++] = c; - state->tdctl.r &= (N - 1); - count++; - } - else { - if((pos = td0_state_DecodePosition(state)) < 0) - return(count); /* fatal error */ - state->tdctl.bufpos = (state->tdctl.r - pos - 1) & (N - 1); - state->tdctl.bufcnt = c - 255 + THRESHOLD; - state->tdctl.bufndx = 0; - } - } - else { /* still chars from last string */ - while( state->tdctl.bufndx < state->tdctl.bufcnt && count < len ) { - c = state->text_buf[(state->tdctl.bufpos + state->tdctl.bufndx) & (N - 1)]; - *(buf++) = c; - state->tdctl.bufndx++; - state->text_buf[state->tdctl.r++] = c; - state->tdctl.r &= (N - 1); - count++; - } - /* reset bufcnt after copy string from text_buf[] */ - if(state->tdctl.bufndx >= state->tdctl.bufcnt) - state->tdctl.bufndx = state->tdctl.bufcnt = 0; - } - } - return(count); /* count == len, success */ + int16_t bit; + uint16_t i, j, c; + + /* decode upper 6 bits from given table */ + if ((bit = state_GetByte(state)) < 0) + return(-1); + + i = (uint16_t) bit; + c = (uint16_t)d_code[i] << 6; + j = d_len[i]; + + /* input lower 6 bits directly */ + j -= 2; + while (j--) { + if ((bit = state_GetBit(state)) < 0) + return(-1); + i = (i << 1) + bit; + } + + return(c | (i & 0x3f)); } -/********************************************************************* - - formats/td0_dsk.h - - Teledisk disk images - -*********************************************************************/ - -int td0_initialize(int drive); - -void td0_seek(int drive, int track); - -void td0_init() +/* DeCompression - split out initialization code to init_Decode() */ +static void +state_init_Decode(td0dsk_t *state) { - memset(td0, 0, sizeof(td0)); + int i; + + state->getbuf = 0; + state->getlen = 0; + state->tdctl.ibufcnt= state->tdctl.ibufndx = 0; /* input buffer is empty */ + state->tdctl.bufcnt = 0; + + state_StartHuff(state); + for (i = 0; i < N - F; i++) + state->text_buf[i] = ' '; + + state->tdctl.r = N - F; } -void d86f_register_td0(int drive); -const int max_size = 4*1024*1024; /* 4MB ought to be large enough for any floppy */ -const int max_processed_size = 5*1024*1024; -uint8_t imagebuf[4*1024*1024]; -uint8_t processed_buf[5*1024*1024]; -uint8_t header[12]; - -void td0_load(int drive, wchar_t *fn) +/* Decoding/Uncompressing */ +static int +state_Decode(td0dsk_t *state, uint8_t *buf, int len) { - int ret = 0; + int16_t c, pos; + int count; /* was an unsigned long, seems unnecessary */ - d86f_unregister(drive); + for (count = 0; count < len; ) { + if (state->tdctl.bufcnt == 0) { + if ((c = state_DecodeChar(state)) < 0) + return(count); /* fatal error */ + if (c < 256) { + *(buf++) = c & 0xff; + state->text_buf[state->tdctl.r++] = c & 0xff; + state->tdctl.r &= (N - 1); + count++; + } else { + if ((pos = state_DecodePosition(state)) < 0) + return(count); /* fatal error */ + state->tdctl.bufpos = (state->tdctl.r - pos - 1) & (N - 1); + state->tdctl.bufcnt = c - 255 + THRESHOLD; + state->tdctl.bufndx = 0; + } + } else { + /* still chars from last string */ + while (state->tdctl.bufndx < state->tdctl.bufcnt && count < len) { + c = state->text_buf[(state->tdctl.bufpos + state->tdctl.bufndx) & (N - 1)]; + *(buf++) = c & 0xff; + state->tdctl.bufndx++; + state->text_buf[state->tdctl.r++] = c & 0xff; + state->tdctl.r &= (N - 1); + count++; + } - writeprot[drive] = 1; - td0[drive].f = plat_fopen(fn, L"rb"); - if (!td0[drive].f) - { - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; - } - fwriteprot[drive] = writeprot[drive]; - - ret = td0_dsk_identify(drive); - if (!ret) - { - pclog("TD0: Not a valid Teledisk image\n"); - fclose(td0[drive].f); - td0[drive].f = NULL; - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; - } - else - { - pclog("TD0: Valid Teledisk image\n"); + /* reset bufcnt after copy string from text_buf[] */ + if (state->tdctl.bufndx >= state->tdctl.bufcnt) + state->tdctl.bufndx = state->tdctl.bufcnt = 0; } + } - memset(imagebuf, 0, 4*1024*1024); - memset(processed_buf, 0, 4*1024*1024); - ret = td0_initialize(drive); - if (!ret) - { - pclog("TD0: Failed to initialize\n"); - fclose(td0[drive].f); - td0[drive].f = NULL; - memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); - return; - } - else - { - pclog("TD0: Initialized successfully\n"); - } - - d86f_register_td0(drive); - - drives[drive].seek = td0_seek; - - d86f_common_handlers(drive); + return(count); /* count == len, success */ } -void td0_close(int drive) -{ - int i = 0; - int j = 0; - int k = 0; - d86f_unregister(drive); - memset(imagebuf, 0, 4*1024*1024); - memset(processed_buf, 0, 4*1024*1024); - for (i = 0; i < 256; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 256; k++) - { - td0[drive].sects[i][j][k].data = NULL; +static uint32_t +get_raw_tsize(int side_flags, int slower_rpm) +{ + uint32_t size; + + switch(side_flags & 0x27) { + case 0x22: + size = slower_rpm ? 5314 : 5208; + break; + + default: + case 0x02: + case 0x21: + size = slower_rpm ? 6375 : 6250; + break; + + case 0x01: + size = slower_rpm ? 7650 : 7500; + break; + + case 0x20: + size = slower_rpm ? 10629 : 10416; + break; + + case 0x00: + size = slower_rpm ? 12750 : 12500; + break; + + case 0x23: + size = slower_rpm ? 21258 : 20833; + break; + + case 0x03: + size = slower_rpm ? 25500 : 25000; + break; + + case 0x25: + size = slower_rpm ? 42517 : 41666; + break; + + case 0x05: + size = slower_rpm ? 51000 : 50000; + break; + } + + return(size); +} + + +static int +td0_initialize(int drive) +{ + td0_t *dev = td0[drive]; + uint8_t header[12]; + int fm, head, track; + int track_count = 0; + int head_count = 0; + int track_spt; + int offset = 0; + int density = 0; + int temp_rate = 0; + uint32_t file_size; + uint16_t len, rep; + td0dsk_t disk_decode; + uint8_t *hs; + uint16_t size; + uint8_t *dbuf = dev->processed_buf; + uint32_t total_size = 0; + uint32_t pre_sector = 0; + uint32_t track_size = 0; + uint32_t raw_tsize = 0; + uint32_t minimum_gap3 = 0; + uint32_t minimum_gap4 = 0; + int i, j, k; + + if (dev->f == NULL) { + pclog("TD0: Attempted to initialize without loading a file first\n"); + return(0); + } + + fseek(dev->f, 0, SEEK_END); + file_size = ftell(dev->f); + + if (file_size < 12) { + pclog("TD0: File is too small to even contain the header\n"); + return(0); + } + + if (file_size > TD0_MAX_BUFSZ) { + pclog("TD0: File exceeds the maximum size\n"); + return(0); + } + + fseek(dev->f, 0, SEEK_SET); + fread(header, 1, 12, dev->f); + head_count = header[9]; + + if (header[0] == 't') { + pclog("TD0: File is compressed\n"); + disk_decode.fdd_file = dev->f; + state_init_Decode(&disk_decode); + disk_decode.fdd_file_offset = 12; + state_Decode(&disk_decode, dev->imagebuf, TD0_MAX_BUFSZ); + } else { + pclog("TD0: File is uncompressed\n"); + fseek(dev->f, 12, SEEK_SET); + fread(dev->imagebuf, 1, file_size - 12, dev->f); + } + + if (header[7] & 0x80) + offset = 10 + dev->imagebuf[2] + (dev->imagebuf[3] << 8); + + track_spt = dev->imagebuf[offset]; + if (track_spt == 255) { + /* Empty file? */ + pclog("TD0: File has no tracks\n"); + return(0); + } + + density = (header[5] >> 1) & 3; + + if (density == 3) { + pclog("TD0: Unknown density\n"); + return(0); + } + + /* + * We determine RPM from the drive type as well as we possibly can. + * This byte is actually the BIOS floppy drive type read by Teledisk + * from the CMOS. + */ + switch (header[6]) { + case 0: /* 5.25" 360k in 1.2M drive: 360 rpm + CMOS Drive type: None, value probably + reused by Teledisk */ + case 2: /* 5.25" 1.2M 360 rpm */ + case 5: /* 8"/5.25"/3.5" 1.25M 360 rpm */ + dev->default_track_flags = (density == 1) ? 0x20 : 0x21; + break; + + case 1: /* 5.25" 360k: 300 rpm */ + case 3: /* 3.5" 720k: 300 rpm */ + dev->default_track_flags = 0x02; + break; + + case 4: /* 3.5" 1.44M: 300 rpm */ + dev->default_track_flags = (density == 1) ? 0x00 : 0x02; + break; + + case 6: /* 3.5" 2.88M: 300 rpm */ + dev->default_track_flags = (density == 1) ? 0x00 : ((density == 2) ? 0x03 : 0x02); + break; + } + + dev->disk_flags = header[5] & 0x06; + + dev->track_width = (header[7] & 1) ^ 1; + + for (i = 0; i < 256; i++) { + memset(dev->side_flags[i], 0, 4); + memset(dev->track_in_file[i], 0, 2); + memset(dev->calculated_gap3_lengths[i], 0, 2); + for (j = 0; j < 2; j++) + memset(dev->sects[i][j], 0, sizeof(td0_sector_t)); + } + + while (track_spt != 255) { + track = dev->imagebuf[offset + 1]; + head = dev->imagebuf[offset + 2] & 1; + fm = (header[5] & 0x80) || (dev->imagebuf[offset + 2] & 0x80); /* ? */ + dev->side_flags[track][head] = dev->default_track_flags | (fm ? 0 : 8); + dev->track_in_file[track][head] = 1; + offset += 4; + track_size = fm ? 73 : 146; + pre_sector = fm ? 42 : 60; + + for (i = 0; i < track_spt; i++) { + hs = &dev->imagebuf[offset]; + offset += 6; + + dev->sects[track][head][i].track = hs[0]; + dev->sects[track][head][i].head = hs[1]; + dev->sects[track][head][i].sector = hs[2]; + dev->sects[track][head][i].size = hs[3]; + dev->sects[track][head][i].deleted = (hs[4] & 4) == 4; + dev->sects[track][head][i].bad_crc = (hs[4] & 2) == 2; + dev->sects[track][head][i].data = dbuf; + + size = 128 << hs[3]; + if ((total_size + size) >= TD0_MAX_BUFSZ) { + pclog("TD0: Processed buffer overflow\n"); + return(0); + } + + if (hs[4] & 0x30) { + memset(dbuf, 0, size); + } else { + offset += 3; + switch (hs[8]) { + default: + pclog("TD0: Image uses an unsupported sector data encoding\n"); + return(0); + + case 0: + memcpy(dbuf, &dev->imagebuf[offset], size); + offset += size; + break; + + case 1: + offset += 4; + k = (hs[9] + (hs[10] << 8)) * 2; + k = (k <= size) ? k : size; + for(j = 0; j < k; j += 2) { + dbuf[j] = hs[11]; + dbuf[j + 1] = hs[12]; + } + if (k < size) + memset(&(dbuf[k]), 0, size - k); + break; + + case 2: + k = 0; + while (k < size) { + len = dev->imagebuf[offset]; + rep = dev->imagebuf[offset + 1]; + offset += 2; + if (! len) { + memcpy(&(dbuf[k]), &dev->imagebuf[offset], rep); + offset += rep; + k += rep; + } else { + len = (1 << len); + rep = len * rep; + rep = ((rep + k) <= size) ? rep : (size - k); + for(j = 0; j < rep; j += len) + memcpy(&(dbuf[j + k]), &dev->imagebuf[offset], len); + k += rep; + offset += len; + } + } + break; } } + + dbuf += size; + total_size += size; + track_size += (pre_sector + size + 2); } - for (i = 0; i < 256; i++) - { - memset(td0[drive].side_flags[i], 0, 4); - memset(td0[drive].track_in_file[i], 0, 2); - memset(td0[drive].calculated_gap3_lengths[i], 0, 2); - for (j = 0; j < 2; j++) - { - memset(td0[drive].sects[i][j], 0, sizeof(td0_sector_t)); + track_count = track; + + if (track_spt != 255) { + dev->track_spt[track][head] = track_spt; + + if ((dev->track_spt[track][head] == 8) && (dev->sects[track][head][0].size == 3)) { + dev->side_flags[track][head] |= 0x20; } - } - if (td0[drive].f) - { - fclose(td0[drive].f); - td0[drive].f = NULL; - } -} - -uint32_t td0_get_raw_tsize(int side_flags, int slower_rpm) -{ - uint32_t size; - switch(side_flags & 0x27) - { - case 0x22: - size = slower_rpm ? 5314 : 5208; - break; - default: - case 0x02: - case 0x21: - size = slower_rpm ? 6375 : 6250; - break; - case 0x01: - size = slower_rpm ? 7650 : 7500; - break; - case 0x20: - size = slower_rpm ? 10629 : 10416; - break; - case 0x00: - size = slower_rpm ? 12750 : 12500; - break; - case 0x23: - size = slower_rpm ? 21258 : 20833; - break; - case 0x03: - size = slower_rpm ? 25500 : 25000; - break; - case 0x25: - size = slower_rpm ? 42517 : 41666; - break; - case 0x05: - size = slower_rpm ? 51000 : 50000; - break; - } - return size; -} - -int td0_initialize(int drive) -{ - int track; - int head; - int fm; - int track_count = 0; - int head_count = 0; - int track_spt; - int offset = 0; - int density = 0; - int i = 0; - int j = 0; - int k = 0; - int temp_rate = 0; - uint32_t file_size; - uint16_t len; - uint16_t rep; - td0dsk_t disk_decode; - uint8_t *hs; - uint16_t size; - uint8_t *dbuf = processed_buf; - uint32_t total_size = 0; - uint32_t pre_sector = 0; - uint32_t track_size = 0; - uint32_t raw_tsize = 0; - uint32_t minimum_gap3 = 0; - uint32_t minimum_gap4 = 0; - - if (!td0[drive].f) - { - pclog("TD0: Attempted to initialize without loading a file first\n"); - return 0; - } - - fseek(td0[drive].f, 0, SEEK_END); - file_size = ftell(td0[drive].f); - - if (file_size < 12) - { - pclog("TD0: File is too small to even contain the header\n"); - return 0; - } - - if (file_size > max_size) - { - pclog("TD0: File exceeds the maximum size\n"); - return 0; - } - - fseek(td0[drive].f, 0, SEEK_SET); - fread(header, 1, 12, td0[drive].f); - head_count = header[9]; - - if(header[0] == 't') - { - pclog("TD0: File is compressed\n"); - disk_decode.fdd_file = td0[drive].f; - td0_state_init_Decode(&disk_decode); - disk_decode.fdd_file_offset = 12; - td0_state_Decode(&disk_decode, imagebuf, max_size); - } - else - { - pclog("TD0: File is uncompressed\n"); - fseek(td0[drive].f, 12, SEEK_SET); - fread(imagebuf, 1, file_size - 12, td0[drive].f); - } - - if(header[7] & 0x80) - offset = 10 + imagebuf[2] + (imagebuf[3] << 8); - - track_spt = imagebuf[offset]; - if(track_spt == 255) /* Empty file? */ - { - pclog("TD0: File has no tracks\n"); - return 0; - } - - density = (header[5] >> 1) & 3; - - if (density == 3) - { - pclog("TD0: Unknown density\n"); - return 0; - } - - /* We determine RPM from the drive type as well as we possibly can. */ - /* This byte is actually the BIOS floppy drive type read by Teledisk from the CMOS. */ - switch(header[6]) - { - case 0: /* 5.25" 360k in 1.2M drive: 360 rpm - CMOS Drive type: None, value probably reused by Teledisk */ - case 2: /* 5.25" 1.2M 360 rpm */ - case 5: /* 8"/5.25"/3.5" 1.25M 360 rpm */ - td0[drive].default_track_flags = (density == 1) ? 0x20 : 0x21; - break; - case 1: /* 5.25" 360k: 300 rpm */ - case 3: /* 3.5" 720k: 300 rpm */ - td0[drive].default_track_flags = 0x02; - break; - case 4: /* 3.5" 1.44M: 300 rpm */ - td0[drive].default_track_flags = (density == 1) ? 0x00 : 0x02; - break; - case 6: /* 3.5" 2.88M: 300 rpm */ - td0[drive].default_track_flags = (density == 1) ? 0x00 : ((density == 2) ? 0x03 : 0x02); - break; - } - - td0[drive].disk_flags = header[5] & 0x06; - - td0[drive].track_width = (header[7] & 1) ^ 1; - - for (i = 0; i < 256; i++) - { - memset(td0[drive].side_flags[i], 0, 4); - memset(td0[drive].track_in_file[i], 0, 2); - memset(td0[drive].calculated_gap3_lengths[i], 0, 2); - for (j = 0; j < 2; j++) - { - memset(td0[drive].sects[i][j], 0, sizeof(td0_sector_t)); - } - } - - while(track_spt != 255) - { - track = imagebuf[offset + 1]; - head = imagebuf[offset + 2] & 1; - fm = (header[5] & 0x80) || (imagebuf[offset + 2] & 0x80); /* ? */ - td0[drive].side_flags[track][head] = td0[drive].default_track_flags | (fm ? 0 : 8); - td0[drive].track_in_file[track][head] = 1; - offset += 4; - track_size = fm ? 73 : 146; - pre_sector = fm ? 42 : 60; - - for(i = 0; i < track_spt; i++) - { - hs = &imagebuf[offset]; - offset += 6; - - td0[drive].sects[track][head][i].track = hs[0]; - td0[drive].sects[track][head][i].head = hs[1]; - td0[drive].sects[track][head][i].sector = hs[2]; - td0[drive].sects[track][head][i].size = hs[3]; - td0[drive].sects[track][head][i].deleted = (hs[4] & 4) == 4; - td0[drive].sects[track][head][i].bad_crc = (hs[4] & 2) == 2; - td0[drive].sects[track][head][i].data = dbuf; - - size = 128 << hs[3]; - if ((total_size + size) >= max_processed_size) - { - pclog("TD0: Processed buffer overflow\n"); - fclose(td0[drive].f); + raw_tsize = get_raw_tsize(dev->side_flags[track][head], 0); + minimum_gap3 = 12 * track_spt; + if ((raw_tsize - track_size + (fm ? 73 : 146)) < (minimum_gap3 + minimum_gap4)) { + /* If we can't fit the sectors with a reasonable minimum gap at perfect RPM, let's try 2% slower. */ + raw_tsize = get_raw_tsize(dev->side_flags[track][head], 1); + /* Set disk flags so that rotation speed is 2% slower. */ + dev->disk_flags |= (3 << 5); + if ((raw_tsize - track_size + (fm ? 73 : 146)) < (minimum_gap3 + minimum_gap4)) { + /* If we can't fit the sectors with a reasonable minimum gap even at 2% slower RPM, abort. */ + pclog("TD0: Unable to fit the %i sectors in a track\n", track_spt); return 0; } - - if(hs[4] & 0x30) - { - memset(dbuf, 0, size); - } - else - { - offset += 3; - switch(hs[8]) - { - default: - pclog("TD0: Image uses an unsupported sector data encoding\n"); - fclose(td0[drive].f); - return 0; - case 0: - memcpy(dbuf, &imagebuf[offset], size); - offset += size; - break; - case 1: - offset += 4; - k = (hs[9] + (hs[10] << 8)) * 2; - k = (k <= size) ? k : size; - for(j = 0; j < k; j += 2) - { - dbuf[j] = hs[11]; - dbuf[j + 1] = hs[12]; - } - if(k < size) - memset(&(dbuf[k]), 0, size - k); - break; - case 2: - k = 0; - while(k < size) - { - len = imagebuf[offset]; - rep = imagebuf[offset + 1]; - offset += 2; - if(!len) - { - memcpy(&(dbuf[k]), &imagebuf[offset], rep); - offset += rep; - k += rep; - } - else - { - len = (1 << len); - rep = len * rep; - rep = ((rep + k) <= size) ? rep : (size - k); - for(j = 0; j < rep; j += len) - memcpy(&(dbuf[j + k]), &imagebuf[offset], len); - k += rep; - offset += len; - } - } - break; - } - } - - dbuf += size; - total_size += size; - track_size += (pre_sector + size + 2); } + dev->calculated_gap3_lengths[track][head] = (raw_tsize - track_size - minimum_gap4 + (fm ? 73 : 146)) / track_spt; - track_count = track; - - if (track_spt != 255) - { - td0[drive].track_spt[track][head] = track_spt; - - if ((td0[drive].track_spt[track][head] == 8) && (td0[drive].sects[track][head][0].size == 3)) - { - td0[drive].side_flags[track][head] |= 0x20; - } - - raw_tsize = td0_get_raw_tsize(td0[drive].side_flags[track][head], 0); - minimum_gap3 = 12 * track_spt; - if ((raw_tsize - track_size + (fm ? 73 : 146)) < (minimum_gap3 + minimum_gap4)) - { - /* If we can't fit the sectors with a reasonable minimum gap at perfect RPM, let's try 2% slower. */ - raw_tsize = td0_get_raw_tsize(td0[drive].side_flags[track][head], 1); - /* Set disk flags so that rotation speed is 2% slower. */ - td0[drive].disk_flags |= (3 << 5); - if ((raw_tsize - track_size + (fm ? 73 : 146)) < (minimum_gap3 + minimum_gap4)) - { - /* If we can't fit the sectors with a reasonable minimum gap even at 2% slower RPM, abort. */ - pclog("TD0: Unable to fit the %i sectors in a track\n", track_spt); - return 0; - } - } - td0[drive].calculated_gap3_lengths[track][head] = (raw_tsize - track_size - minimum_gap4 + (fm ? 73 : 146)) / track_spt; - - track_spt = imagebuf[offset]; - } + track_spt = dev->imagebuf[offset]; } + } - if ((td0[drive].disk_flags & 0x60) == 0x60) - { - pclog("TD0: Disk will rotate 2% below perfect RPM\n"); - } + if ((dev->disk_flags & 0x60) == 0x60) + pclog("TD0: Disk will rotate 2% below perfect RPM\n"); - td0[drive].tracks = track_count + 1; + dev->tracks = track_count + 1; - temp_rate = td0[drive].default_track_flags & 7; - if ((td0[drive].default_track_flags & 0x27) == 0x20) temp_rate = 4; - td0[drive].gap3_len = gap3_sizes[temp_rate][td0[drive].sects[0][0][0].size][td0[drive].track_spt[0][0]]; - if (!td0[drive].gap3_len) - { - 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. */ - } + temp_rate = dev->default_track_flags & 7; + if ((dev->default_track_flags & 0x27) == 0x20) + temp_rate = 4; + dev->gap3_len = gap3_sizes[temp_rate][dev->sects[0][0][0].size][dev->track_spt[0][0]]; + if (! dev->gap3_len) + dev->gap3_len = dev->calculated_gap3_lengths[0][0]; /* If we can't determine the GAP3 length, assume the smallest one we possibly know of. */ - if(head_count == 2) - { - td0[drive].disk_flags |= 8; /* 2 sides */ - } + if (head_count == 2) + dev->disk_flags |= 8; /* 2 sides */ - if (td0[drive].tracks <= 43) - { - td0[drive].track_width &= ~1; - } + if (dev->tracks <= 43) + dev->track_width &= ~1; - td0[drive].sides = head_count; + dev->sides = head_count; - td0[drive].current_side_flags[0] = td0[drive].side_flags[0][0]; - td0[drive].current_side_flags[1] = td0[drive].side_flags[0][1]; + dev->current_side_flags[0] = dev->side_flags[0][0]; + dev->current_side_flags[1] = dev->side_flags[0][1]; - pclog("TD0: File loaded: %i tracks, %i sides, disk flags: %02X, side flags: %02X, %02X, GAP3 length: %02X\n", td0[drive].tracks, td0[drive].sides, td0[drive].disk_flags, td0[drive].current_side_flags[0], td0[drive].current_side_flags[1], td0[drive].gap3_len); + pclog("TD0: File loaded: %i tracks, %i sides, disk flags: %02X, side flags: %02X, %02X, GAP3 length: %02X\n", dev->tracks, dev->sides, dev->disk_flags, dev->current_side_flags[0], dev->current_side_flags[1], dev->gap3_len); - return 1; + return(1); } -int td0_track_is_xdf(int drive, int side, int track) + +static uint16_t +disk_flags(int drive) { - uint8_t id[4] = { 0, 0, 0, 0 }; - int i, effective_sectors, xdf_sectors; - int high_sectors, low_sectors; - int max_high_id, expected_high_count, expected_low_count; + td0_t *dev = td0[drive]; - effective_sectors = xdf_sectors = high_sectors = low_sectors = 0; - - memset(td0[drive].xdf_ordered_pos[side], 0, 256); - - if (!track) - { - if ((td0[drive].track_spt[track][side] == 16) || (td0[drive].track_spt[track][side] == 19)) - { - if (!side) - { - max_high_id = (td0[drive].track_spt[track][side] == 19) ? 0x8B : 0x88; - expected_high_count = (td0[drive].track_spt[track][side] == 19) ? 0x0B : 0x08; - expected_low_count = 8; - } - else - { - max_high_id = (td0[drive].track_spt[track][side] == 19) ? 0x93 : 0x90; - expected_high_count = (td0[drive].track_spt[track][side] == 19) ? 0x13 : 0x10; - expected_low_count = 0; - } - for (i = 0; i < td0[drive].track_spt[track][side]; i++) - { - id[0] = td0[drive].sects[track][side][i].track; - id[1] = td0[drive].sects[track][side][i].head; - id[2] = td0[drive].sects[track][side][i].sector; - id[3] = td0[drive].sects[track][side][i].size; - if (!(id[0]) && (id[1] == side) && (id[3] == 2)) - { - if ((id[2] >= 0x81) && (id[2] <= max_high_id)) - { - high_sectors++; - td0[drive].xdf_ordered_pos[id[2]][side] = i; - } - if ((id[2] >= 0x01) && (id[2] <= 0x08)) - { - low_sectors++; - td0[drive].xdf_ordered_pos[id[2]][side] = i; - } - } - } - if ((high_sectors == expected_high_count) && (low_sectors == expected_low_count)) - { - td0[drive].current_side_flags[side] = (td0[drive].track_spt[track][side] == 19) ? 0x08 : 0x28; - return (td0[drive].track_spt[track][side] == 19) ? 2 : 1; - } - return 0; - } - else - { - return 0; - } - } - else - { - for (i = 0; i < td0[drive].track_spt[track][side]; i++) - { - id[0] = td0[drive].sects[track][side][i].track; - id[1] = td0[drive].sects[track][side][i].head; - id[2] = td0[drive].sects[track][side][i].sector; - id[3] = td0[drive].sects[track][side][i].size; - effective_sectors++; - if ((id[0] == track) && (id[1] == side) && !(id[2]) && !(id[3])) - { - effective_sectors--; - } - if ((id[0] == track) && (id[1] == side) && (id[2] == (id[3] | 0x80))) - { - xdf_sectors++; - td0[drive].xdf_ordered_pos[id[2]][side] = i; - } - } - if ((effective_sectors == 3) && (xdf_sectors == 3)) - { - td0[drive].current_side_flags[side] = 0x28; - return 1; /* 5.25" 2HD XDF */ - } - if ((effective_sectors == 4) && (xdf_sectors == 4)) - { - td0[drive].current_side_flags[side] = 0x08; - return 2; /* 3.5" 2HD XDF */ - } - return 0; - } + return(dev->disk_flags); } -int td0_track_is_interleave(int drive, int side, int track) + +static uint16_t +side_flags(int drive) { - int i, effective_sectors; - int track_spt; + td0_t *dev = td0[drive]; + int side = 0; + uint16_t sflags = 0; - effective_sectors = 0; + side = fdd_get_head(drive); + sflags = dev->current_side_flags[side]; - for (i = 0; i < 256; i++) - { - td0[drive].interleave_ordered_pos[i][side] = 0; - } - - track_spt = td0[drive].track_spt[track][side]; - - if (track_spt != 21) - { - return 0; - } - - for (i = 0; i < track_spt; i++) - { - if ((td0[drive].sects[track][side][i].track == track) && (td0[drive].sects[track][side][i].head == side) && (td0[drive].sects[track][side][i].sector >= 1) && (td0[drive].sects[track][side][i].sector <= track_spt) && (td0[drive].sects[track][side][i].size == 2)) - { - effective_sectors++; - td0[drive].interleave_ordered_pos[td0[drive].sects[track][side][i].sector][side] = i; - } - } - - if (effective_sectors == track_spt) - { - return 1; - } - return 0; + return(sflags); } -void td0_seek(int drive, int track) + +static void +set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n) { - int side; + td0_t *dev = td0[drive]; + int i = 0; - uint8_t id[4] = { 0, 0, 0, 0 }; - - int sector, current_pos; - - int ssize = 512; - - int track_rate = 0; - - int track_gap2 = 22; - int track_gap3 = 12; - - int xdf_type = 0; - int interleave_type = 0; - - int is_trackx = 0; - - int xdf_spt = 0; - int xdf_sector = 0; - - int ordered_pos = 0; - - int real_sector = 0; - int actual_sector = 0; - - if (!td0[drive].f) - return; - - if (!td0[drive].track_width && fdd_doublestep_40(drive)) - track /= 2; - - d86f_set_cur_track(drive, track); - - is_trackx = (track == 0) ? 0 : 1; - - td0[drive].track = track; - - td0[drive].current_side_flags[0] = td0[drive].side_flags[track][0]; - td0[drive].current_side_flags[1] = td0[drive].side_flags[track][1]; - - d86f_reset_index_hole_pos(drive, 0); - d86f_reset_index_hole_pos(drive, 1); - - d86f_destroy_linked_lists(drive, 0); - d86f_destroy_linked_lists(drive, 1); - - if (track > td0[drive].tracks) - { - d86f_zero_track(drive); - return; + dev->current_sector_index[side] = 0; + if (c != dev->track) return; + for (i = 0; i < dev->track_spt[c][side]; i++) { + if ((dev->sects[c][side][i].track == c) && + (dev->sects[c][side][i].head == h) && + (dev->sects[c][side][i].sector == r) && + (dev->sects[c][side][i].size == n)) { + dev->current_sector_index[side] = i; } + } +} - for (side = 0; side < td0[drive].sides; side++) - { - track_rate = td0[drive].current_side_flags[side] & 7; - if (!track_rate && (td0[drive].current_side_flags[side] & 0x20)) track_rate = 4; - track_gap3 = gap3_sizes[track_rate][td0[drive].sects[track][side][0].size][td0[drive].track_spt[track][side]]; - if (!track_gap3) - { - track_gap3 = td0[drive].calculated_gap3_lengths[track][side]; + +static uint8_t +poll_read_data(int drive, int side, uint16_t pos) +{ + td0_t *dev = td0[drive]; + + return(dev->sects[dev->track][side][dev->current_sector_index[side]].data[pos]); +} + + +static int +track_is_xdf(int drive, int side, int track) +{ + td0_t *dev = td0[drive]; + uint8_t id[4] = { 0, 0, 0, 0 }; + int i, effective_sectors, xdf_sectors; + int high_sectors, low_sectors; + int max_high_id, expected_high_count, expected_low_count; + + effective_sectors = xdf_sectors = high_sectors = low_sectors = 0; + + memset(dev->xdf_ordered_pos[side], 0, 256); + + if (! track) { + if ((dev->track_spt[track][side] == 16) || (dev->track_spt[track][side] == 19)) { + if (! side) { + max_high_id = (dev->track_spt[track][side] == 19) ? 0x8B : 0x88; + expected_high_count = (dev->track_spt[track][side] == 19) ? 0x0B : 0x08; + expected_low_count = 8; + } else { + max_high_id = (dev->track_spt[track][side] == 19) ? 0x93 : 0x90; + expected_high_count = (dev->track_spt[track][side] == 19) ? 0x13 : 0x10; + expected_low_count = 0; } - track_gap2 = ((td0[drive].current_side_flags[side] & 7) >= 3) ? 41 : 22; - - xdf_type = td0_track_is_xdf(drive, side, track); - - interleave_type = td0_track_is_interleave(drive, side, track); - - current_pos = d86f_prepare_pretrack(drive, side, 0); - - if (!xdf_type) - { - for (sector = 0; sector < td0[drive].track_spt[track][side]; sector++) - { - if (interleave_type == 0) - { - real_sector = td0[drive].sects[track][side][sector].sector; - actual_sector = sector; + for (i = 0; i < dev->track_spt[track][side]; i++) { + id[0] = dev->sects[track][side][i].track; + id[1] = dev->sects[track][side][i].head; + id[2] = dev->sects[track][side][i].sector; + id[3] = dev->sects[track][side][i].size; + if (!(id[0]) && (id[1] == side) && (id[3] == 2)) { + if ((id[2] >= 0x81) && (id[2] <= max_high_id)) { + high_sectors++; + dev->xdf_ordered_pos[id[2]][side] = i; } - else - { - real_sector = dmf_r[sector]; - actual_sector = td0[drive].interleave_ordered_pos[real_sector][side]; - } - id[0] = td0[drive].sects[track][side][actual_sector].track; - id[1] = td0[drive].sects[track][side][actual_sector].head; - id[2] = real_sector; - id[3] = td0[drive].sects[track][side][actual_sector].size; - 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, track_gap2, track_gap3, td0[drive].sects[track][side][actual_sector].deleted, td0[drive].sects[track][side][actual_sector].bad_crc); - if (sector == 0) - { - d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + if ((id[2] >= 0x01) && (id[2] <= 0x08)) { + low_sectors++; + dev->xdf_ordered_pos[id[2]][side] = i; } } } - else - { - xdf_type--; - xdf_spt = xdf_physical_sectors[xdf_type][is_trackx]; - for (sector = 0; sector < xdf_spt; sector++) - { - xdf_sector = (side * xdf_spt) + sector; - id[0] = track; - id[1] = side; - id[2] = xdf_disk_layout[xdf_type][is_trackx][xdf_sector].id.r; - id[3] = is_trackx ? (id[2] & 7) : 2; - ssize = 128 << ((uint32_t) id[3]); - ordered_pos = td0[drive].xdf_ordered_pos[id[2]][side]; - 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, 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, 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); - } - if (sector == 0) - { - d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); - } - } + if ((high_sectors == expected_high_count) && (low_sectors == expected_low_count)) { + dev->current_side_flags[side] = (dev->track_spt[track][side] == 19) ? 0x08 : 0x28; + return((dev->track_spt[track][side] == 19) ? 2 : 1); } } -} - -uint16_t td0_disk_flags(int drive) -{ - return td0[drive].disk_flags; -} - -uint16_t td0_side_flags(int drive) -{ - int side = 0; - uint8_t sflags = 0; - side = fdd_get_head(drive); - sflags = td0[drive].current_side_flags[side]; - return sflags; -} - -void td0_set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n) -{ - int i = 0; - td0[drive].current_sector_index[side] = 0; - if (c != td0[drive].track) return; - for (i = 0; i < td0[drive].track_spt[c][side]; i++) - { - if ((td0[drive].sects[c][side][i].track == c) && - (td0[drive].sects[c][side][i].head == h) && - (td0[drive].sects[c][side][i].sector == r) && - (td0[drive].sects[c][side][i].size == n)) - { - td0[drive].current_sector_index[side] = i; + } else { + for (i = 0; i < dev->track_spt[track][side]; i++) { + id[0] = dev->sects[track][side][i].track; + id[1] = dev->sects[track][side][i].head; + id[2] = dev->sects[track][side][i].sector; + id[3] = dev->sects[track][side][i].size; + effective_sectors++; + if ((id[0] == track) && (id[1] == side) && !(id[2]) && !(id[3])) { + effective_sectors--; + } + if ((id[0] == track) && (id[1] == side) && (id[2] == (id[3] | 0x80))) { + xdf_sectors++; + dev->xdf_ordered_pos[id[2]][side] = i; } } + + if ((effective_sectors == 3) && (xdf_sectors == 3)) { + dev->current_side_flags[side] = 0x28; + return(1); /* 5.25" 2HD XDF */ + } + + if ((effective_sectors == 4) && (xdf_sectors == 4)) { + dev->current_side_flags[side] = 0x08; + return(2); /* 3.5" 2HD XDF */ + } + } + + return(0); +} + + +static int +track_is_interleave(int drive, int side, int track) +{ + td0_t *dev = td0[drive]; + int i, effective_sectors; + int track_spt; + + effective_sectors = 0; + + for (i = 0; i < 256; i++) + dev->interleave_ordered_pos[i][side] = 0; + + track_spt = dev->track_spt[track][side]; + + if (track_spt != 21) return(0); + + for (i = 0; i < track_spt; i++) { + if ((dev->sects[track][side][i].track == track) && (dev->sects[track][side][i].head == side) && (dev->sects[track][side][i].sector >= 1) && (dev->sects[track][side][i].sector <= track_spt) && (dev->sects[track][side][i].size == 2)) { + effective_sectors++; + dev->interleave_ordered_pos[dev->sects[track][side][i].sector][side] = i; + } + } + + if (effective_sectors == track_spt) return(1); + + return(0); +} + + +static void +td0_seek(int drive, int track) +{ + td0_t *dev = td0[drive]; + int side; + uint8_t id[4] = { 0, 0, 0, 0 }; + int sector, current_pos; + int ssize = 512; + int track_rate = 0; + int track_gap2 = 22; + int track_gap3 = 12; + int xdf_type = 0; + int interleave_type = 0; + int is_trackx = 0; + int xdf_spt = 0; + int xdf_sector = 0; + int ordered_pos = 0; + int real_sector = 0; + int actual_sector = 0; + + if (dev->f == NULL) return; + + if (!dev->track_width && fdd_doublestep_40(drive)) + track /= 2; + + d86f_set_cur_track(drive, track); + + is_trackx = (track == 0) ? 0 : 1; + dev->track = track; + + dev->current_side_flags[0] = dev->side_flags[track][0]; + dev->current_side_flags[1] = dev->side_flags[track][1]; + + d86f_reset_index_hole_pos(drive, 0); + d86f_reset_index_hole_pos(drive, 1); + + d86f_destroy_linked_lists(drive, 0); + d86f_destroy_linked_lists(drive, 1); + + if (track > dev->tracks) { + d86f_zero_track(drive); return; + } + + for (side = 0; side < dev->sides; side++) { + track_rate = dev->current_side_flags[side] & 7; + if (!track_rate && (dev->current_side_flags[side] & 0x20)) + track_rate = 4; + track_gap3 = gap3_sizes[track_rate][dev->sects[track][side][0].size][dev->track_spt[track][side]]; + if (! track_gap3) + track_gap3 = dev->calculated_gap3_lengths[track][side]; + + track_gap2 = ((dev->current_side_flags[side] & 7) >= 3) ? 41 : 22; + + xdf_type = track_is_xdf(drive, side, track); + + interleave_type = track_is_interleave(drive, side, track); + + current_pos = d86f_prepare_pretrack(drive, side, 0); + + if (! xdf_type) { + for (sector = 0; sector < dev->track_spt[track][side]; sector++) { + if (interleave_type == 0) { + real_sector = dev->sects[track][side][sector].sector; + actual_sector = sector; + } else { + real_sector = dmf_r[sector]; + actual_sector = dev->interleave_ordered_pos[real_sector][side]; + } + + id[0] = dev->sects[track][side][actual_sector].track; + id[1] = dev->sects[track][side][actual_sector].head; + id[2] = real_sector; + id[3] = dev->sects[track][side][actual_sector].size; + ssize = 128 << ((uint32_t) dev->sects[track][side][actual_sector].size); + current_pos = d86f_prepare_sector(drive, side, current_pos, id, dev->sects[track][side][actual_sector].data, ssize, track_gap2, track_gap3, dev->sects[track][side][actual_sector].deleted, dev->sects[track][side][actual_sector].bad_crc); + + if (sector == 0) + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + } + } else { + xdf_type--; + xdf_spt = xdf_physical_sectors[xdf_type][is_trackx]; + for (sector = 0; sector < xdf_spt; sector++) { + xdf_sector = (side * xdf_spt) + sector; + id[0] = track; + id[1] = side; + id[2] = xdf_disk_layout[xdf_type][is_trackx][xdf_sector].id.r; + id[3] = is_trackx ? (id[2] & 7) : 2; + ssize = 128 << ((uint32_t) id[3]); + ordered_pos = dev->xdf_ordered_pos[id[2]][side]; + if (is_trackx) { + current_pos = d86f_prepare_sector(drive, side, xdf_trackx_spos[xdf_type][xdf_sector], id, dev->sects[track][side][ordered_pos].data, ssize, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], dev->sects[track][side][ordered_pos].deleted, dev->sects[track][side][ordered_pos].bad_crc); + } else { + current_pos = d86f_prepare_sector(drive, side, current_pos, id, dev->sects[track][side][ordered_pos].data, ssize, track_gap2, xdf_gap3_sizes[xdf_type][is_trackx], dev->sects[track][side][ordered_pos].deleted, dev->sects[track][side][ordered_pos].bad_crc); + } + + if (sector == 0) + d86f_initialize_last_sector_id(drive, id[0], id[1], id[2], id[3]); + } + } + } } -uint8_t td0_poll_read_data(int drive, int side, uint16_t pos) + +void +td0_init(void) { - return td0[drive].sects[td0[drive].track][side][td0[drive].current_sector_index[side]].data[pos]; + memset(td0, 0x00, sizeof(td0)); } -void d86f_register_td0(int drive) + +void +td0_load(int drive, wchar_t *fn) { - 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_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; - d86f_set_version(drive, 0x0063); + td0_t *dev; + uint32_t i; + + d86f_unregister(drive); + + writeprot[drive] = 1; + + dev = (td0_t *)malloc(sizeof(td0_t)); + memset(dev, 0x00, sizeof(td0_t)); + td0[drive] = dev; + + dev->f = plat_fopen(fn, L"rb"); + if (dev->f == NULL) { + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; + } + + fwriteprot[drive] = writeprot[drive]; + + if (! dsk_identify(drive)) { + pclog("TD0: Not a valid Teledisk image\n"); + fclose(dev->f); + dev->f = NULL; + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; + } else { + pclog("TD0: Valid Teledisk image\n"); + } + + /* Allocate the processing buffers. */ + i = 1024UL * 1024UL * 4UL; + dev->imagebuf = (uint8_t *)malloc(i); + memset(dev->imagebuf, 0x00, i); + dev->processed_buf = (uint8_t *)malloc(i); + memset(dev->processed_buf, 0x00, i); + + if (! td0_initialize(drive)) { + pclog("TD0: Failed to initialize\n"); + fclose(dev->f); + free(dev->imagebuf); + free(dev->processed_buf); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; + } else { + pclog("TD0: Initialized successfully\n"); + } + + /* Attach this format to the D86F engine. */ + d86f_handler[drive].disk_flags = disk_flags; + d86f_handler[drive].side_flags = side_flags; + d86f_handler[drive].writeback = null_writeback; + d86f_handler[drive].set_sector = set_sector; + d86f_handler[drive].read_data = poll_read_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; + d86f_set_version(drive, 0x0063); + + drives[drive].seek = td0_seek; + + d86f_common_handlers(drive); +} + + +void +td0_close(int drive) +{ + td0_t *dev = td0[drive]; + int i, j, k; + + if (dev == NULL) return; + + d86f_unregister(drive); + + free(dev->imagebuf); + free(dev->processed_buf); + + for (i = 0; i < 256; i++) { + for (j = 0; j < 2; j++) { + for (k = 0; k < 256; k++) + dev->sects[i][j][k].data = NULL; + } + } + + for (i = 0; i < 256; i++) { + memset(dev->side_flags[i], 0, 4); + memset(dev->track_in_file[i], 0, 2); + memset(dev->calculated_gap3_lengths[i], 0, 2); + for (j = 0; j < 2; j++) + memset(dev->sects[i][j], 0, sizeof(td0_sector_t)); + } + + if (dev->f != NULL) + fclose(dev->f); + + /* Release resources. */ + free(dev); + td0[drive] = NULL; } diff --git a/src/floppy/fdd_td0.h b/src/floppy/fdd_td0.h index ad15d1bac..8c3593241 100644 --- a/src/floppy/fdd_td0.h +++ b/src/floppy/fdd_td0.h @@ -1,25 +1,38 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * - * Implementation of the Teledisk floppy image format. + * Definitions for the Teledisk floppy image format. * - * Version: @(#)floppy_td0.h 1.0.2 2017/09/03 + * Version: @(#)floppy_td0.h 1.0.2 2018/03/17 * - * Authors: Milodrag Milanovic, - * Haruhiko OKUMURA, - * Haruyasu YOSHIZAKI, - * Kenji RIKITAKE, + * Authors: Fred N. van Kempen, * Miran Grca, - * Copyright 1988-2017 Haruhiko OKUMURA. - * Copyright 1988-2017 Haruyasu YOSHIZAKI. - * Copyright 1988-2017 Kenji RIKITAKE. - * Copyright 2013-2017 Milodrag Milanovic. - * Copyright 2016,2017 Miran Grca. + * + * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ #ifndef EMU_FLOPPY_TD0_H # define EMU_FLOPPY_TD0_H @@ -28,7 +41,6 @@ extern void td0_init(void); extern void td0_load(int drive, wchar_t *fn); extern void td0_close(int drive); -extern void td0_seek(int drive, int track); #endif /*EMU_FLOPPY_TD0_H*/ diff --git a/src/floppy/fdi2raw.c b/src/floppy/fdi2raw.c index c7aefa431..0cb7ca4fd 100644 --- a/src/floppy/fdi2raw.c +++ b/src/floppy/fdi2raw.c @@ -1,22 +1,45 @@ -/* Copyright holders: Toni Wilen - see COPYING for more details -*/ /* - - FDI to raw bit stream converter - Copyright (c) 2001 by Toni Wilen - FDI 2.0 support - Copyright (c) 2003-2004 by Toni Wilen - and Vincent Joguin - - FDI format created by Vincent "ApH" Joguin - - Tiny changes - function type fixes, multiple drives, addition of - get_last_head and C++ callability - by Thomas Harte, 2001, - T.Harte@excite.co.uk - -*/ - + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * FDI to raw bit stream converter + * FDI format created by Vincent "ApH" Joguin + * Tiny changes - function type fixes, multiple drives, + * addition of get_last_head and C++ callability by Thomas + * Harte. + * + * Version: @(#)fdi2raw.c 1.0.2 2018/03/12 + * + * Authors: Toni Wilen, + * and Vincent Joguin, + * Thomas Harte, + * + * Copyright 2001-2004 Toni Wilen. + * Copyright 2001-2004 Vincent Joguin. + * Copyright 2001 Thomas Harte. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ #define STATIC_INLINE #include #include @@ -1857,7 +1880,7 @@ static int decode_lowlevel_track (FDI *fdi, int track, struct fdi_cache *cache) indexoffset = 0; p1 = idxp; for (i = 0; i < pulses; i++) { - if (p1[idx_off1] + p1[idx_off2] > maxidx) + if ((uint32_t)p1[idx_off1] + (uint32_t)p1[idx_off2] > maxidx) maxidx = p1[idx_off1] + p1[idx_off2]; p1 += idx_off3; } @@ -1893,7 +1916,7 @@ static int decode_lowlevel_track (FDI *fdi, int track, struct fdi_cache *cache) totalavg = 0; weakbits = 0; for (i = 0; i < pulses; i++) { - int sum = p1[idx_off1] + p1[idx_off2]; + uint32_t sum = p1[idx_off1] + p1[idx_off2]; if (sum >= maxidx) { totalavg += *p2; } else { diff --git a/src/floppy/fdi2raw.h b/src/floppy/fdi2raw.h index b8c3201e5..3c93ae2df 100644 --- a/src/floppy/fdi2raw.h +++ b/src/floppy/fdi2raw.h @@ -1,6 +1,41 @@ -/* Copyright holders: Toni Wilen - see COPYING for more details -*/ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the FDI floppy file format. + * + * Version: @(#)fdi2raw.h 1.0.1 2018/02/14 + * + * Authors: Toni Wilen, + * and Vincent Joguin, + * Thomas Harte, + * + * Copyright 2001-2004 Toni Wilen. + * Copyright 2001-2004 Vincent Joguin. + * Copyright 2001 Thomas Harte. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ #ifndef __FDI2RAW_H #define __FDI2RAW_H diff --git a/src/game/gameport.c b/src/game/gameport.c index c33f84cf8..c1f06ecb5 100644 --- a/src/game/gameport.c +++ b/src/game/gameport.c @@ -1,6 +1,39 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of a generic Game Port. + * + * Version: @(#)gameport.c 1.0.3 2018/03/15 + * + * Authors: Miran Grca, + * Sarah Walker, + * + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ #include #include #include @@ -17,261 +50,286 @@ #include "joystick_standard.h" #include "joystick_sw_pad.h" #include "joystick_tm_fcs.h" -#include "../plat_joystick.h" -int joystick_type; +typedef struct { + int64_t count; + int axis_nr; + struct _gameport_ *gameport; +} g_axis_t; +typedef struct _gameport_ { + uint8_t state; -joystick_if_t joystick_none = -{ - "No joystick", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - 0, - 0, - 0 -}; + g_axis_t axis[4]; -static joystick_if_t *joystick_list[] = -{ - &joystick_standard, - &joystick_standard_4button, - &joystick_standard_6button, - &joystick_standard_8button, - &joystick_ch_flightstick_pro, - &joystick_sw_pad, - &joystick_tm_fcs, - &joystick_none, - NULL -}; - -char *joystick_get_name(int64_t joystick) -{ - if (!joystick_list[joystick]) - return NULL; - return (char *) joystick_list[joystick]->name; -} - -int64_t joystick_get_max_joysticks(int64_t joystick) -{ - return joystick_list[joystick]->max_joysticks; -} - -int64_t joystick_get_axis_count(int64_t joystick) -{ - return joystick_list[joystick]->axis_count; -} - -int64_t joystick_get_button_count(int64_t joystick) -{ - return joystick_list[joystick]->button_count; -} - -int64_t joystick_get_pov_count(int64_t joystick) -{ - return joystick_list[joystick]->pov_count; -} - - char *joystick_get_axis_name(int64_t joystick, int64_t id) -{ - return (char *) joystick_list[joystick]->axis_names[id]; -} - -char *joystick_get_button_name(int64_t joystick, int64_t id) -{ - return (char *) joystick_list[joystick]->button_names[id]; -} - -char *joystick_get_pov_name(int64_t joystick, int64_t id) -{ - return (char *) joystick_list[joystick]->pov_names[id]; -} - -typedef struct gameport_axis_t -{ - int64_t count; - int64_t axis_nr; - struct gameport_t *gameport; -} gameport_axis_t; - -typedef struct gameport_t -{ - uint8_t state; - - gameport_axis_t axis[4]; - - joystick_if_t *joystick; - void *joystick_dat; + const joystick_if_t *joystick; + void *joystick_dat; } gameport_t; + +int joystick_type; + + +static const joystick_if_t joystick_none = { + "No joystick", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + 0, + 0, + 0 +}; + + +static const joystick_if_t *joystick_list[] = { + &joystick_standard, + &joystick_standard_4button, + &joystick_standard_6button, + &joystick_standard_8button, + &joystick_ch_flightstick_pro, + &joystick_sw_pad, + &joystick_tm_fcs, + &joystick_none, + NULL +}; static gameport_t *gameport_global = NULL; -static int64_t gameport_time(int64_t axis) -{ - if (axis == AXIS_NOT_PRESENT) - return 0; - axis += 32768; - axis = (axis * 100) / 65; /*Axis now in ohms*/ - axis = (axis * 11) / 1000; - return TIMER_USEC * (axis + 24); /*max = 11.115 ms*/ +char * +joystick_get_name(int js) +{ + if (! joystick_list[js]) + return(NULL); + return((char *)joystick_list[js]->name); } -void gameport_write(uint16_t addr, uint8_t val, void *p) + +int +joystick_get_max_joysticks(int js) { - gameport_t *gameport = (gameport_t *)p; - - timer_clock(); - gameport->state |= 0x0f; - pclog("gameport_write : joysticks_present=%i\n", joysticks_present); - - gameport->axis[0].count = gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 0)); - gameport->axis[1].count = gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 1)); - gameport->axis[2].count = gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 2)); - gameport->axis[3].count = gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 3)); - - gameport->joystick->write(gameport->joystick_dat); - - cycles -= ISA_CYCLES(8); + return(joystick_list[js]->max_joysticks); } -uint8_t gameport_read(uint16_t addr, void *p) + +int +joystick_get_axis_count(int js) { - gameport_t *gameport = (gameport_t *)p; - uint8_t ret; - - timer_clock(); - ret = gameport->state | gameport->joystick->read(gameport->joystick_dat); - - cycles -= ISA_CYCLES(8); - - return ret; + return(joystick_list[js]->axis_count); } -void gameport_timer_over(void *p) + +int +joystick_get_button_count(int js) { - gameport_axis_t *axis = (gameport_axis_t *)p; - gameport_t *gameport = axis->gameport; - - gameport->state &= ~(1 << axis->axis_nr); - axis->count = 0; - - if (axis == &gameport->axis[0]) - gameport->joystick->a0_over(gameport->joystick_dat); + return(joystick_list[js]->button_count); } -void *gameport_init_common(void) -{ - gameport_t *gameport = malloc(sizeof(gameport_t)); - - memset(gameport, 0, sizeof(gameport_t)); - - gameport->axis[0].gameport = gameport; - gameport->axis[1].gameport = gameport; - gameport->axis[2].gameport = gameport; - gameport->axis[3].gameport = gameport; - gameport->axis[0].axis_nr = 0; - gameport->axis[1].axis_nr = 1; - gameport->axis[2].axis_nr = 2; - gameport->axis[3].axis_nr = 3; - - timer_add(gameport_timer_over, &gameport->axis[0].count, &gameport->axis[0].count, &gameport->axis[0]); - timer_add(gameport_timer_over, &gameport->axis[1].count, &gameport->axis[1].count, &gameport->axis[1]); - timer_add(gameport_timer_over, &gameport->axis[2].count, &gameport->axis[2].count, &gameport->axis[2]); - timer_add(gameport_timer_over, &gameport->axis[3].count, &gameport->axis[3].count, &gameport->axis[3]); - - gameport->joystick = joystick_list[joystick_type]; - gameport->joystick_dat = gameport->joystick->init(); - - gameport_global = gameport; - - return gameport; +int +joystick_get_pov_count(int js) +{ + return(joystick_list[js]->pov_count); } -void gameport_update_joystick_type(void) + +char * +joystick_get_axis_name(int js, int id) { - gameport_t *gameport = gameport_global; - - if (gameport) - { - gameport->joystick->close(gameport->joystick_dat); - gameport->joystick = joystick_list[joystick_type]; - gameport->joystick_dat = gameport->joystick->init(); - } + return((char *)joystick_list[js]->axis_names[id]); } -void *gameport_init(device_t *info) + +char * +joystick_get_button_name(int js, int id) { - gameport_t *gameport = NULL; - - if (joystick_type == 7) - { - gameport = NULL; - return gameport; - } - - gameport = gameport_init_common(); - - io_sethandler(0x0200, 0x0008, gameport_read, NULL, NULL, gameport_write, NULL, NULL, gameport); - - return gameport; + return((char *)joystick_list[js]->button_names[id]); } -void *gameport_201_init(device_t *info) + +char * +joystick_get_pov_name(int js, int id) { - gameport_t *gameport; - - if (joystick_type == 7) - { - gameport = NULL; - return gameport; - } - - gameport = gameport_init_common(); - - io_sethandler(0x0201, 0x0001, gameport_read, NULL, NULL, gameport_write, NULL, NULL, gameport); - - return gameport; + return (char *)joystick_list[js]->pov_names[id]; } -void gameport_close(void *p) + +static int +gameport_time(int axis) { - gameport_t *gameport = (gameport_t *)p; + if (axis == AXIS_NOT_PRESENT) return(0); - if (!p) - { - return; - } - - gameport->joystick->close(gameport->joystick_dat); + axis += 32768; + axis = (axis * 100) / 65; /*Axis now in ohms*/ + axis = (axis * 11) / 1000; - gameport_global = NULL; - - free(gameport); + return(TIMER_USEC * (axis + 24)); /*max = 11.115 ms*/ } -device_t gameport_device = + +static void +gameport_write(uint16_t addr, uint8_t val, void *priv) { - "Game port", - 0, 0, - gameport_init, - gameport_close, - NULL, NULL, NULL, NULL, - NULL + gameport_t *p = (gameport_t *)priv; + + timer_clock(); + p->state |= 0x0f; + pclog("gameport_write : joysticks_present=%i\n", joysticks_present); + + p->axis[0].count = gameport_time(p->joystick->read_axis(p->joystick_dat, 0)); + p->axis[1].count = gameport_time(p->joystick->read_axis(p->joystick_dat, 1)); + p->axis[2].count = gameport_time(p->joystick->read_axis(p->joystick_dat, 2)); + p->axis[3].count = gameport_time(p->joystick->read_axis(p->joystick_dat, 3)); + + p->joystick->write(p->joystick_dat); + + cycles -= ISA_CYCLES(8); +} + + +static uint8_t +gameport_read(uint16_t addr, void *priv) +{ + gameport_t *p = (gameport_t *)p; + uint8_t ret; + + timer_clock(); + ret = p->state | p->joystick->read(p->joystick_dat); + + cycles -= ISA_CYCLES(8); + + return(ret); +} + + +static void +timer_over(void *priv) +{ + g_axis_t *axis = (g_axis_t *)priv; + gameport_t *p = axis->gameport; + + p->state &= ~(1 << axis->axis_nr); + axis->count = 0; + + if (axis == &p->axis[0]) + p->joystick->a0_over(p->joystick_dat); +} + + +static void * +init_common(void) +{ + gameport_t *p = malloc(sizeof(gameport_t)); + + memset(p, 0x00, sizeof(gameport_t)); + + p->axis[0].gameport = p; + p->axis[1].gameport = p; + p->axis[2].gameport = p; + p->axis[3].gameport = p; + + p->axis[0].axis_nr = 0; + p->axis[1].axis_nr = 1; + p->axis[2].axis_nr = 2; + p->axis[3].axis_nr = 3; + + timer_add(timer_over, &p->axis[0].count, &p->axis[0].count, &p->axis[0]); + timer_add(timer_over, &p->axis[1].count, &p->axis[1].count, &p->axis[1]); + timer_add(timer_over, &p->axis[2].count, &p->axis[2].count, &p->axis[2]); + timer_add(timer_over, &p->axis[3].count, &p->axis[3].count, &p->axis[3]); + + p->joystick = joystick_list[joystick_type]; + p->joystick_dat = p->joystick->init(); + + gameport_global = p; + + return(p); +} + + +void +gameport_update_joystick_type(void) +{ + gameport_t *p = gameport_global; + + if (p != NULL) { + p->joystick->close(p->joystick_dat); + p->joystick = joystick_list[joystick_type]; + p->joystick_dat = p->joystick->init(); + } +} + + +static void * +gameport_init(const device_t *info) +{ + gameport_t *p = NULL; + + if (joystick_type == 7) { + p = NULL; + return(p); + } + + p = init_common(); + + io_sethandler(0x0200, 8, + gameport_read,NULL,NULL, gameport_write,NULL,NULL, p); + + return(p); +} + + +static void * +gameport_201_init(const device_t *info) +{ + gameport_t *p; + + if (joystick_type == 7) { + p = NULL; + return(p); + } + + p = init_common(); + + io_sethandler(0x0201, 1, + gameport_read,NULL,NULL, gameport_write,NULL,NULL, p); + + return(p); +} + + +static void +gameport_close(void *priv) +{ + gameport_t *p = (gameport_t *)priv; + + if (p == NULL) return; + + p->joystick->close(p->joystick_dat); + + gameport_global = NULL; + + free(p); +} + + +const device_t gameport_device = { + "Game port", + 0, 0, + gameport_init, + gameport_close, + NULL, NULL, NULL, NULL, + NULL }; -device_t gameport_201_device = -{ - "Game port (port 201h only)", - 0, 0, - gameport_201_init, - gameport_close, - NULL, NULL, NULL, NULL, - NULL +const device_t gameport_201_device = { + "Game port (port 201h only)", + 0, 0, + gameport_201_init, + gameport_close, + NULL, NULL, NULL, NULL, + NULL }; diff --git a/src/game/gameport.h b/src/game/gameport.h index 81c95cc48..3db999646 100644 --- a/src/game/gameport.h +++ b/src/game/gameport.h @@ -1,49 +1,142 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the generic game port handlers. + * + * NOTE: This module needs a good cleanup someday. + * + * Version: @(#)gameport.h 1.0.3 2018/03/15 + * + * Authors: Miran Grca, + * Sarah Walker, + * + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2017 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ #ifndef EMU_GAMEPORT_H # define EMU_GAMEPORT_H -#define AXIS_NOT_PRESENT -99999 +#define MAX_PLAT_JOYSTICKS 8 +#define MAX_JOYSTICKS 4 + +#define POV_X 0x80000000 +#define POV_Y 0x40000000 + +#define AXIS_NOT_PRESENT -99999 + +#define JOYSTICK_PRESENT(n) (joystick_state[n].plat_joystick_nr != 0) -typedef struct -{ - const char *name; - void *(*init)(void); - void (*close)(void *p); - uint8_t (*read)(void *p); - void (*write)(void *p); - int (*read_axis)(void *p, int axis); - void (*a0_over)(void *p); - int axis_count, button_count, pov_count; - int max_joysticks; - const char *axis_names[8]; - const char *button_names[32]; - const char *pov_names[4]; +typedef struct { + char name[64]; + + int a[8]; + int b[32]; + int p[4]; + + struct { + char name[32]; + int id; + } axis[8]; + + struct { + char name[32]; + int id; + } button[32]; + + struct { + char name[32]; + int id; + } pov[4]; + + int nr_axes; + int nr_buttons; + int nr_povs; +} plat_joystick_t; + +typedef struct { + int axis[8]; + int button[32]; + int pov[4]; + + int plat_joystick_nr; + int axis_mapping[8]; + int button_mapping[32]; + int pov_mapping[4][2]; +} joystick_t; + +typedef struct { + const char *name; + + void *(*init)(void); + void (*close)(void *p); + uint8_t (*read)(void *p); + void (*write)(void *p); + int (*read_axis)(void *p, int axis); + void (*a0_over)(void *p); + + int axis_count, + button_count, + pov_count; + int max_joysticks; + const char *axis_names[8]; + const char *button_names[32]; + const char *pov_names[4]; } joystick_if_t; - #ifdef __cplusplus extern "C" { #endif -extern device_t gameport_device; -extern device_t gameport_201_device; +#ifdef EMU_DEVICE_H +extern const device_t gameport_device; +extern const device_t gameport_201_device; +#endif -extern int joystick_type; +extern plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; +extern joystick_t joystick_state[MAX_JOYSTICKS]; +extern int joysticks_present; + +extern int joystick_type; -extern char *joystick_get_name(int64_t joystick); -extern int64_t joystick_get_max_joysticks(int64_t joystick); -extern int64_t joystick_get_axis_count(int64_t joystick); -extern int64_t joystick_get_button_count(int64_t joystick); -extern int64_t joystick_get_pov_count(int64_t joystick); -extern char *joystick_get_axis_name(int64_t joystick, int64_t id); -extern char *joystick_get_button_name(int64_t joystick, int64_t id); -extern char *joystick_get_pov_name(int64_t joystick, int64_t id); +extern void joystick_init(void); +extern void joystick_close(void); +extern void joystick_process(void); + +extern char *joystick_get_name(int js); +extern int joystick_get_max_joysticks(int js); +extern int joystick_get_axis_count(int js); +extern int joystick_get_button_count(int js); +extern int joystick_get_pov_count(int js); +extern char *joystick_get_axis_name(int js, int id); +extern char *joystick_get_button_name(int js, int id); +extern char *joystick_get_pov_name(int js, int id); extern void gameport_update_joystick_type(void); diff --git a/src/game/joystick_ch_flightstick_pro.c b/src/game/joystick_ch_flightstick_pro.c index ae7539a01..062e753a6 100644 --- a/src/game/joystick_ch_flightstick_pro.c +++ b/src/game/joystick_ch_flightstick_pro.c @@ -1,3 +1,39 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of the Flight Stick Pro. + * + * Version: @(#)flightstick_pro.c 1.0.4 2018/03/15 + * + * Authors: Miran Grca, + * Sarah Walker, + * + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ #include #include #include @@ -6,12 +42,11 @@ #include "../86box.h" #include "../device.h" #include "../timer.h" -#include "../plat_joystick.h" #include "gameport.h" #include "joystick_standard.h" -static void *ch_flightstick_pro_init() +static void *ch_flightstick_pro_init(void) { return NULL; } @@ -78,7 +113,7 @@ static void ch_flightstick_pro_a0_over(void *p) { } -joystick_if_t joystick_ch_flightstick_pro = +const joystick_if_t joystick_ch_flightstick_pro = { "CH Flightstick Pro", ch_flightstick_pro_init, diff --git a/src/game/joystick_ch_flightstick_pro.h b/src/game/joystick_ch_flightstick_pro.h index 291cb0bfa..7cbb71767 100644 --- a/src/game/joystick_ch_flightstick_pro.h +++ b/src/game/joystick_ch_flightstick_pro.h @@ -1 +1,38 @@ -extern joystick_if_t joystick_ch_flightstick_pro; +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the Flight Stick Pro driver. + * + * Version: @(#)joystick_ch_flightstickpro.h 1.0.2 2018/03/15 + * + * Authors: Miran Grca, + * Sarah Walker, + * + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ + +extern const joystick_if_t joystick_ch_flightstick_pro; diff --git a/src/game/joystick_standard.c b/src/game/joystick_standard.c index 71be48d3b..f05634a9b 100644 --- a/src/game/joystick_standard.c +++ b/src/game/joystick_standard.c @@ -1,3 +1,39 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of a standard joystick. + * + * Version: @(#)joystick_standard.c 1.0.4 2018/03/15 + * + * Authors: Miran Grca, + * Sarah Walker, + * + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ #include #include #include @@ -6,12 +42,11 @@ #include "../86box.h" #include "../device.h" #include "../timer.h" -#include "../plat_joystick.h" #include "gameport.h" #include "joystick_standard.h" -static void *joystick_standard_init() +static void *joystick_standard_init(void) { return NULL; } @@ -160,7 +195,7 @@ static void joystick_standard_a0_over(void *p) { } -joystick_if_t joystick_standard = +const joystick_if_t joystick_standard = { "Standard 2-button joystick(s)", joystick_standard_init, @@ -176,7 +211,7 @@ joystick_if_t joystick_standard = {"X axis", "Y axis"}, {"Button 1", "Button 2"} }; -joystick_if_t joystick_standard_4button = +const joystick_if_t joystick_standard_4button = { "Standard 4-button joystick", joystick_standard_init, @@ -192,7 +227,7 @@ joystick_if_t joystick_standard_4button = {"X axis", "Y axis"}, {"Button 1", "Button 2", "Button 3", "Button 4"} }; -joystick_if_t joystick_standard_6button = +const joystick_if_t joystick_standard_6button = { "Standard 6-button joystick", joystick_standard_init, @@ -208,7 +243,7 @@ joystick_if_t joystick_standard_6button = {"X axis", "Y axis"}, {"Button 1", "Button 2", "Button 3", "Button 4", "Button 5", "Button 6"} }; -joystick_if_t joystick_standard_8button = +const joystick_if_t joystick_standard_8button = { "Standard 8-button joystick", joystick_standard_init, diff --git a/src/game/joystick_standard.h b/src/game/joystick_standard.h index 7150058a8..26b16998e 100644 --- a/src/game/joystick_standard.h +++ b/src/game/joystick_standard.h @@ -1,4 +1,41 @@ -extern joystick_if_t joystick_standard; -extern joystick_if_t joystick_standard_4button; -extern joystick_if_t joystick_standard_6button; -extern joystick_if_t joystick_standard_8button; +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the joystick driver. + * + * Version: @(#)joystick_standard.h 1.0.2 2018/03/15 + * + * Authors: Miran Grca, + * Sarah Walker, + * + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ + +extern const joystick_if_t joystick_standard; +extern const joystick_if_t joystick_standard_4button; +extern const joystick_if_t joystick_standard_6button; +extern const joystick_if_t joystick_standard_8button; diff --git a/src/game/joystick_sw_pad.c b/src/game/joystick_sw_pad.c index f0bb71e75..feec60593 100644 --- a/src/game/joystick_sw_pad.c +++ b/src/game/joystick_sw_pad.c @@ -1,24 +1,60 @@ -/*Sidewinder game pad notes : - - - Write to 0x201 starts packet transfer (5*N or 15*N bits) - - Currently alternates between Mode A and Mode B (is there any way of - actually controlling which is used?) - - Windows 9x drivers require Mode B when more than 1 pad connected - - Packet preceeded by high data (currently 50us), and followed by low - data (currently 160us) - timings are probably wrong, but good enough - for everything I've tried - - Analogue inputs are only used to time ID packet request. If A0 timing - out is followed after ~64us by another 0x201 write then an ID packet - is triggered - - Sidewinder game pad ID is 'H0003' - - ID is sent in Mode A (1 bit per clock), but data bit 2 must change - during ID packet transfer, or Windows 9x drivers won't use Mode B. I - don't know if it oscillates, mirrors the data transfer, or something - else - the drivers only check that it changes at least 10 times during - the transfer - - Some DOS stuff will write to 0x201 while a packet is being transferred. - This seems to be ignored. -*/ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of a Side Winder GamePad. + * + * Notes: - Write to 0x201 starts packet transfer (5*N or 15*N bits) + * - Currently alternates between Mode A and Mode B (is there + * any way of actually controlling which is used?) + * - Windows 9x drivers require Mode B when more than 1 pad + * connected + * - Packet preceeded by high data (currently 50us), and + * followed by low data (currently 160us) - timings are + * probably wrong, but good enoughfor everything I've tried + * - Analog inputs are only used to time ID packet request. + * If A0 timing out is followed after ~64us by another 0x201 + * write then an ID packet is triggered + * - Sidewinder game pad ID is 'H0003' + * - ID is sent in Mode A (1 bit per clock), but data bit 2 + * must change during ID packet transfer, or Windows 9x + * drivers won't use Mode B. I don't know if it oscillates, + * mirrors the data transfer, or something else - the drivers + * only check that it changes at least 10 times during the + * transfer + * - Some DOS stuff will write to 0x201 while a packet is + * being transferred. This seems to be ignored. + * + * Version: @(#)sw_pad.c 1.0.5 2018/03/15 + * + * Authors: Miran Grca, + * Sarah Walker, + * + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ #include #include #include @@ -27,7 +63,6 @@ #include "../86box.h" #include "../device.h" #include "../timer.h" -#include "../plat_joystick.h" #include "gameport.h" #include "joystick_sw_pad.h" @@ -90,7 +125,7 @@ static int sw_parity(uint16_t data) return bits_set & 1; } -static void *sw_init() +static void *sw_init(void) { sw_data *sw = (sw_data *)malloc(sizeof(sw_data)); memset(sw, 0, sizeof(sw_data)); @@ -139,7 +174,7 @@ static uint8_t sw_read(void *p) static void sw_write(void *p) { sw_data *sw = (sw_data *)p; - int time_since_last = sw->trigger_time / TIMER_USEC; + int64_t time_since_last = sw->trigger_time / TIMER_USEC; if (!JOYSTICK_PRESENT(0)) return; @@ -177,7 +212,7 @@ static void sw_write(void *p) for (c = 0; c < 4; c++) { - uint64_t data = 0x3fff; + uint16_t data = 0x3fff; int b; if (!JOYSTICK_PRESENT(c)) @@ -235,7 +270,7 @@ static void sw_a0_over(void *p) sw->trigger_time = TIMER_USEC * 10000; } -joystick_if_t joystick_sw_pad = +const joystick_if_t joystick_sw_pad = { "Microsoft SideWinder Pad", sw_init, diff --git a/src/game/joystick_sw_pad.h b/src/game/joystick_sw_pad.h index ba5ceb680..0cd4132a5 100644 --- a/src/game/joystick_sw_pad.h +++ b/src/game/joystick_sw_pad.h @@ -1 +1,38 @@ -extern joystick_if_t joystick_sw_pad; +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the Sidewinder Pro driver. + * + * Version: @(#)joystick_sw_pad.h 1.0.2 2018/03/15 + * + * Authors: Miran Grca, + * Sarah Walker, + * + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ + +extern const joystick_if_t joystick_sw_pad; diff --git a/src/game/joystick_tm_fcs.c b/src/game/joystick_tm_fcs.c index 892c0d546..69fa19d2b 100644 --- a/src/game/joystick_tm_fcs.c +++ b/src/game/joystick_tm_fcs.c @@ -1,3 +1,39 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of Thrust Master Flight Control System. + * + * Version: @(#)tm_fcs.c 1.0.3 2018/03/15 + * + * Authors: Miran Grca, + * Sarah Walker, + * + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ #include #include #include @@ -6,7 +42,6 @@ #include "../86box.h" #include "../device.h" #include "../timer.h" -#include "../plat_joystick.h" #include "gameport.h" #include "joystick_standard.h" @@ -77,7 +112,7 @@ static void tm_fcs_a0_over(void *p) { } -joystick_if_t joystick_tm_fcs = +const joystick_if_t joystick_tm_fcs = { "Thrustmaster Flight Control System", tm_fcs_init, diff --git a/src/game/joystick_tm_fcs.h b/src/game/joystick_tm_fcs.h index 9759cf897..7ada355ed 100644 --- a/src/game/joystick_tm_fcs.h +++ b/src/game/joystick_tm_fcs.h @@ -1 +1,38 @@ -extern joystick_if_t joystick_tm_fcs; +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the Flight Control System driver. + * + * Version: @(#)joystick_tm_fcs.h 1.0.2 2018/03/15 + * + * Authors: Miran Grca, + * Sarah Walker, + * + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ + +extern const joystick_if_t joystick_tm_fcs; diff --git a/src/intel_flash.c b/src/intel_flash.c index 3bcb24090..ccf141eff 100644 --- a/src/intel_flash.c +++ b/src/intel_flash.c @@ -6,9 +6,9 @@ * * This file is part of the 86Box distribution. * - * Implementation of the Intel 2 Mbit 8-bit flash devices. + * Implementation of the Intel 1 Mbit 8-bit flash devices. * - * Version: @(#)intel_flash.c 1.0.13 2018/02/09 + * Version: @(#)intel_flash.c 1.0.14 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -288,7 +288,7 @@ void intel_flash_close(void *p) } -device_t intel_flash_bxt_ami_device = +const device_t intel_flash_bxt_ami_device = { "Intel 28F001BXT Flash BIOS", 0, 0, @@ -298,7 +298,7 @@ device_t intel_flash_bxt_ami_device = NULL, NULL, NULL, NULL, NULL }; -device_t intel_flash_bxb_ami_device = +const device_t intel_flash_bxb_ami_device = { "Intel 28F001BXB Flash BIOS", 0, 0, @@ -308,7 +308,7 @@ device_t intel_flash_bxb_ami_device = NULL, NULL, NULL, NULL, NULL }; -device_t intel_flash_bxt_device = +const device_t intel_flash_bxt_device = { "Intel 28F001BXT Flash BIOS", 0, 0, @@ -318,7 +318,7 @@ device_t intel_flash_bxt_device = NULL, NULL, NULL, NULL, NULL }; -device_t intel_flash_bxb_device = +const device_t intel_flash_bxb_device = { "Intel 28F001BXB Flash BIOS", 0, 0, diff --git a/src/intel_flash.h b/src/intel_flash.h index d63b48c18..241a07c02 100644 --- a/src/intel_flash.h +++ b/src/intel_flash.h @@ -6,9 +6,9 @@ * * This file is part of the 86Box distribution. * - * Implementation of the Intel 2 Mbit 8-bit flash devices. + * Implementation of the Intel 1 Mbit 8-bit flash devices. * - * Version: @(#)intel_flash.h 1.0.0 2017/05/30 + * Version: @(#)intel_flash.h 1.0.1 2018/03/14 * * Author: Sarah Walker, * Miran Grca, @@ -16,7 +16,7 @@ * Copyright 2016-2017 Miran Grca. */ -extern device_t intel_flash_bxt_ami_device; -extern device_t intel_flash_bxb_ami_device; -extern device_t intel_flash_bxt_device; -extern device_t intel_flash_bxb_device; +extern const device_t intel_flash_bxt_ami_device; +extern const device_t intel_flash_bxb_ami_device; +extern const device_t intel_flash_bxt_device; +extern const device_t intel_flash_bxb_device; diff --git a/src/keyboard.h b/src/keyboard.h index aff83f49f..c9d5ebcd4 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -8,15 +8,15 @@ * * Definitions for the keyboard interface. * - * Version: @(#)keyboard.h 1.0.11 2018/02/10 + * Version: @(#)keyboard.h 1.0.12 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * * Copyright 2008-2018 Sarah Walker. - * Copyright 2016,2018 Miran Grca. - * Copyright 2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. */ #ifndef EMU_KEYBOARD_H # define EMU_KEYBOARD_H @@ -60,15 +60,15 @@ extern int mouse_queue_start, mouse_queue_end; extern int mouse_scan; #ifdef EMU_DEVICE_H -extern device_t keyboard_xt_device; -extern device_t keyboard_tandy_device; -extern device_t keyboard_at_device; -extern device_t keyboard_at_ami_device; -extern device_t keyboard_at_toshiba_device; -extern device_t keyboard_ps2_device; -extern device_t keyboard_ps2_ami_device; -extern device_t keyboard_ps2_mca_device; -extern device_t keyboard_ps2_quadtel_device; +extern const device_t keyboard_xt_device; +extern const device_t keyboard_tandy_device; +extern const device_t keyboard_at_device; +extern const device_t keyboard_at_ami_device; +extern const device_t keyboard_at_toshiba_device; +extern const device_t keyboard_ps2_device; +extern const device_t keyboard_ps2_ami_device; +extern const device_t keyboard_ps2_mca_device; +extern const device_t keyboard_ps2_quadtel_device; #endif extern void keyboard_init(void); diff --git a/src/keyboard_at.c b/src/keyboard_at.c index ea7357c28..09f255515 100644 --- a/src/keyboard_at.c +++ b/src/keyboard_at.c @@ -8,7 +8,7 @@ * * Intel 8042 (AT keyboard controller) emulation. * - * Version: @(#)keyboard_at.c 1.0.30 2018/03/13 + * Version: @(#)keyboard_at.c 1.0.31 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -1891,7 +1891,7 @@ kbd_reset(void *priv) static void * -kbd_init(device_t *info) +kbd_init(const device_t *info) { atkbd_t *kbd; @@ -1969,7 +1969,7 @@ kbd_close(void *priv) } -device_t keyboard_at_device = { +const device_t keyboard_at_device = { "PC/AT Keyboard", 0, KBC_TYPE_ISA | KBC_VEN_GENERIC, @@ -1979,7 +1979,7 @@ device_t keyboard_at_device = { NULL, NULL, NULL, NULL }; -device_t keyboard_at_ami_device = { +const device_t keyboard_at_ami_device = { "PC/AT Keyboard (AMI)", 0, KBC_TYPE_ISA | KBC_VEN_AMI, @@ -1989,7 +1989,7 @@ device_t keyboard_at_ami_device = { NULL, NULL, NULL, NULL }; -device_t keyboard_at_toshiba_device = { +const device_t keyboard_at_toshiba_device = { "PC/AT Keyboard (Toshiba)", 0, KBC_TYPE_ISA | KBC_VEN_TOSHIBA, @@ -1999,7 +1999,7 @@ device_t keyboard_at_toshiba_device = { NULL, NULL, NULL, NULL }; -device_t keyboard_ps2_device = { +const device_t keyboard_ps2_device = { "PS/2 Keyboard", 0, KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, @@ -2009,7 +2009,7 @@ device_t keyboard_ps2_device = { NULL, NULL, NULL, NULL }; -device_t keyboard_ps2_ami_device = { +const device_t keyboard_ps2_ami_device = { "PS/2 Keyboard (AMI)", 0, KBC_TYPE_PS2_1 | KBC_VEN_AMI, @@ -2019,7 +2019,7 @@ device_t keyboard_ps2_ami_device = { NULL, NULL, NULL, NULL }; -device_t keyboard_ps2_mca_device = { +const device_t keyboard_ps2_mca_device = { "PS/2 Keyboard", 0, KBC_TYPE_PS2_1 | KBC_VEN_IBM_MCA, @@ -2029,7 +2029,7 @@ device_t keyboard_ps2_mca_device = { NULL, NULL, NULL, NULL }; -device_t keyboard_ps2_quadtel_device = { +const device_t keyboard_ps2_quadtel_device = { "PS/2 Keyboard (Quadtel/MegaPC)", 0, KBC_TYPE_PS2_1 | KBC_VEN_QUADTEL, diff --git a/src/keyboard_xt.c b/src/keyboard_xt.c index 2b97cb564..28bd1b645 100644 --- a/src/keyboard_xt.c +++ b/src/keyboard_xt.c @@ -8,15 +8,15 @@ * * Implementation of the XT-style keyboard. * - * Version: @(#)keyboard_xt.c 1.0.9 2018/02/24 + * Version: @(#)keyboard_xt.c 1.0.10 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * * Copyright 2008-2018 Sarah Walker. - * Copyright 2016,2018 Miran Grca. - * Copyright 2018 Fred N. van kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van kempen. */ #include #include @@ -530,7 +530,7 @@ kbd_reset(void *priv) static void * -kbd_init(device_t *info) +kbd_init(const device_t *info) { xtkbd_t *kbd; @@ -574,7 +574,7 @@ kbd_close(void *priv) } -device_t keyboard_xt_device = { +const device_t keyboard_xt_device = { "PC/XT Keyboard", 0, 0, @@ -584,7 +584,7 @@ device_t keyboard_xt_device = { NULL, NULL, NULL, NULL }; -device_t keyboard_tandy_device = { +const device_t keyboard_tandy_device = { "Tandy 1000 Keyboard", 0, 1, diff --git a/src/lpt.c b/src/lpt.c index 56ec62299..4f692a37a 100644 --- a/src/lpt.c +++ b/src/lpt.c @@ -15,7 +15,7 @@ char lpt_device_names[3][16]; -static struct +static const struct { const char *name; const char *internal_name; diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index e8cc23add..108a7b638 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -32,7 +32,7 @@ * in alpha mode, but in highres ("ECD350") mode, it displays * some semi-random junk. Video-memory pointer maybe? * - * Version: @(#)m_amstrad.c 1.0.10 2018/02/02 + * Version: @(#)m_amstrad.c 1.0.11 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -557,7 +557,7 @@ vid_speed_change_1512(void *priv) } -static device_t vid_1512_device = { +static const device_t vid_1512_device = { "Amstrad PC1512 (video)", 0, 0, NULL, vid_close_1512, NULL, @@ -721,7 +721,7 @@ vid_speed_changed_1640(void *priv) } -static device_t vid_1640_device = { +static const device_t vid_1640_device = { "Amstrad PC1640 (video)", 0, 0, NULL, vid_close_1640, NULL, @@ -856,7 +856,7 @@ vid_speed_changed_200(void *priv) } -static device_t vid_200_device = { +static const device_t vid_200_device = { "Amstrad PC200 (video)", 0, 0, NULL, vid_close_200, NULL, @@ -1198,7 +1198,7 @@ ams_read(uint16_t port, void *priv) void -machine_amstrad_init(machine_t *model) +machine_amstrad_init(const machine_t *model) { amstrad_t *ams; diff --git a/src/machine/m_at.c b/src/machine/m_at.c index df8227881..edbec78a2 100644 --- a/src/machine/m_at.c +++ b/src/machine/m_at.c @@ -19,7 +19,7 @@ void -machine_at_common_init(machine_t *model) +machine_at_common_init(const machine_t *model) { machine_common_init(model); @@ -38,7 +38,7 @@ machine_at_common_init(machine_t *model) void -machine_at_init(machine_t *model) +machine_at_init(const machine_t *model) { machine_at_common_init(model); @@ -47,7 +47,7 @@ machine_at_init(machine_t *model) void -machine_at_ps2_init(machine_t *model) +machine_at_ps2_init(const machine_t *model) { machine_at_common_init(model); @@ -56,7 +56,7 @@ machine_at_ps2_init(machine_t *model) void -machine_at_common_ide_init(machine_t *model) +machine_at_common_ide_init(const machine_t *model) { machine_at_common_init(model); @@ -65,7 +65,7 @@ machine_at_common_ide_init(machine_t *model) void -machine_at_ide_init(machine_t *model) +machine_at_ide_init(const machine_t *model) { machine_at_init(model); @@ -74,7 +74,7 @@ machine_at_ide_init(machine_t *model) void -machine_at_ps2_ide_init(machine_t *model) +machine_at_ps2_ide_init(const machine_t *model) { machine_at_ps2_init(model); @@ -83,7 +83,7 @@ machine_at_ps2_ide_init(machine_t *model) void -machine_at_top_remap_init(machine_t *model) +machine_at_top_remap_init(const machine_t *model) { machine_at_init(model); @@ -92,7 +92,7 @@ machine_at_top_remap_init(machine_t *model) void -machine_at_ide_top_remap_init(machine_t *model) +machine_at_ide_top_remap_init(const machine_t *model) { machine_at_ide_init(model); @@ -101,7 +101,7 @@ machine_at_ide_top_remap_init(machine_t *model) void -machine_at_ibm_init(machine_t *model) +machine_at_ibm_init(const machine_t *model) { machine_at_top_remap_init(model); diff --git a/src/machine/m_at_430fx.c b/src/machine/m_at_430fx.c index 258a4ff7a..31c63d74a 100644 --- a/src/machine/m_at_430fx.c +++ b/src/machine/m_at_430fx.c @@ -8,7 +8,7 @@ * * Implementation of the Intel 430FX PCISet chip. * - * Version: @(#)m_at_430fx.c 1.0.13 2018/02/23 + * Version: @(#)m_at_430fx.c 1.0.14 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -207,7 +207,7 @@ static void i430fx_init(void) void -machine_at_p54tp4xe_init(machine_t *model) +machine_at_p54tp4xe_init(const machine_t *model) { machine_at_ps2_init(model); @@ -228,7 +228,7 @@ machine_at_p54tp4xe_init(machine_t *model) void -machine_at_endeavor_init(machine_t *model) +machine_at_endeavor_init(const machine_t *model) { machine_at_common_init(model); device_add(&keyboard_ps2_ami_device); @@ -253,7 +253,7 @@ machine_at_endeavor_init(machine_t *model) } -device_t * +const device_t * at_endeavor_get_device(void) { return &s3_phoenix_trio64_onboard_pci_device; @@ -261,7 +261,7 @@ at_endeavor_get_device(void) void -machine_at_zappa_init(machine_t *model) +machine_at_zappa_init(const machine_t *model) { machine_at_common_init(model); device_add(&keyboard_ps2_ami_device); @@ -282,7 +282,7 @@ machine_at_zappa_init(machine_t *model) void -machine_at_mb500n_init(machine_t *model) +machine_at_mb500n_init(const machine_t *model) { machine_at_ps2_init(model); @@ -302,7 +302,7 @@ machine_at_mb500n_init(machine_t *model) void -machine_at_president_init(machine_t *model) +machine_at_president_init(const machine_t *model) { machine_at_ps2_init(model); @@ -323,7 +323,7 @@ machine_at_president_init(machine_t *model) void -machine_at_thor_init(machine_t *model) +machine_at_thor_init(const machine_t *model) { machine_at_common_init(model); device_add(&keyboard_ps2_ami_device); diff --git a/src/machine/m_at_430hx.c b/src/machine/m_at_430hx.c index 5e734158f..74f735a28 100644 --- a/src/machine/m_at_430hx.c +++ b/src/machine/m_at_430hx.c @@ -8,7 +8,7 @@ * * Implementation of the Intel 430HX PCISet chip. * - * Version: @(#)m_at_430hx.c 1.0.11 2018/02/14 + * Version: @(#)m_at_430hx.c 1.0.11 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -216,7 +216,7 @@ acerm3a_in(uint16_t port, void *p) void -machine_at_acerm3a_init(machine_t *model) +machine_at_acerm3a_init(const machine_t *model) { machine_at_ps2_init(model); @@ -239,7 +239,7 @@ machine_at_acerm3a_init(machine_t *model) void -machine_at_acerv35n_init(machine_t *model) +machine_at_acerv35n_init(const machine_t *model) { machine_at_ps2_init(model); @@ -262,7 +262,7 @@ machine_at_acerv35n_init(machine_t *model) void -machine_at_ap53_init(machine_t *model) +machine_at_ap53_init(const machine_t *model) { machine_at_common_init(model); device_add(&keyboard_ps2_ami_device); @@ -286,7 +286,7 @@ machine_at_ap53_init(machine_t *model) void -machine_at_p55t2p4_init(machine_t *model) +machine_at_p55t2p4_init(const machine_t *model) { machine_at_ps2_init(model); @@ -307,7 +307,7 @@ machine_at_p55t2p4_init(machine_t *model) void -machine_at_p55t2s_init(machine_t *model) +machine_at_p55t2s_init(const machine_t *model) { machine_at_common_init(model); device_add(&keyboard_ps2_ami_device); diff --git a/src/machine/m_at_430lx_nx.c b/src/machine/m_at_430lx_nx.c index 865a85204..c2c80483e 100644 --- a/src/machine/m_at_430lx_nx.c +++ b/src/machine/m_at_430lx_nx.c @@ -8,13 +8,13 @@ * * Implementation of the Intel 430LX and 430NX PCISet chips. * - * Version: @(#)m_at_430lx_nx.c 1.0.10 2018/02/14 + * Version: @(#)m_at_430lx_nx.c 1.0.10 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, * * Copyright 2008-2018 Sarah Walker. - * Copyright 2016,2018 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -211,7 +211,7 @@ static void i430nx_init(void) static void -machine_at_premiere_common_init(machine_t *model) +machine_at_premiere_common_init(const machine_t *model) { machine_at_common_init(model); device_add(&keyboard_ps2_ami_device); @@ -233,7 +233,7 @@ machine_at_premiere_common_init(machine_t *model) void -machine_at_batman_init(machine_t *model) +machine_at_batman_init(const machine_t *model) { machine_at_premiere_common_init(model); @@ -242,7 +242,7 @@ machine_at_batman_init(machine_t *model) void -machine_at_plato_init(machine_t *model) +machine_at_plato_init(const machine_t *model) { machine_at_premiere_common_init(model); diff --git a/src/machine/m_at_430vx.c b/src/machine/m_at_430vx.c index 07d5ebf23..9165dd203 100644 --- a/src/machine/m_at_430vx.c +++ b/src/machine/m_at_430vx.c @@ -8,13 +8,13 @@ * * Implementation of the Intel 430VX PCISet chip. * - * Version: @(#)m_at_430vx.c 1.0.11 2018/02/14 + * Version: @(#)m_at_430vx.c 1.0.11 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, * * Copyright 2008-2018 Sarah Walker. - * Copyright 2016,2018 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -193,7 +193,7 @@ void i430vx_init(void) void -machine_at_p55tvp4_init(machine_t *model) +machine_at_p55tvp4_init(const machine_t *model) { machine_at_ps2_init(model); @@ -214,7 +214,7 @@ machine_at_p55tvp4_init(machine_t *model) void -machine_at_i430vx_init(machine_t *model) +machine_at_i430vx_init(const machine_t *model) { machine_at_ps2_init(model); @@ -235,7 +235,7 @@ machine_at_i430vx_init(machine_t *model) void -machine_at_p55va_init(machine_t *model) +machine_at_p55va_init(const machine_t *model) { machine_at_ps2_init(model); diff --git a/src/machine/m_at_440fx.c b/src/machine/m_at_440fx.c index 13747304f..6d3038048 100644 --- a/src/machine/m_at_440fx.c +++ b/src/machine/m_at_440fx.c @@ -8,13 +8,13 @@ * * Implementation of the Intel 440FX PCISet chip. * - * Version: @(#)m_at_440fx.c 1.0.10 2018/02/14 + * Version: @(#)m_at_440fx.c 1.0.11 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, * * Copyright 2008-2018 Sarah Walker. - * Copyright 2016,2018 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -195,7 +195,7 @@ static void i440fx_init(void) void -machine_at_i440fx_init(machine_t *model) +machine_at_i440fx_init(const machine_t *model) { machine_at_ps2_init(model); @@ -217,7 +217,7 @@ machine_at_i440fx_init(machine_t *model) void -machine_at_s1668_init(machine_t *model) +machine_at_s1668_init(const machine_t *model) { machine_at_common_init(model); device_add(&keyboard_ps2_ami_device); diff --git a/src/machine/m_at_4gpv31.c b/src/machine/m_at_4gpv31.c index c8d3d8215..b870131bf 100644 --- a/src/machine/m_at_4gpv31.c +++ b/src/machine/m_at_4gpv31.c @@ -11,7 +11,7 @@ * NOTE: The NEAT 82c206 code should be moved into a 82c206 module, * so it can be re-used by other boards. * - * Version: @(#)m_4gpv31.c 1.0.4 2018/01/16 + * Version: @(#)m_4gpv31.c 1.0.5 2018/03/18 * * Author: Fred N. van Kempen, * Copyright 2017,2018 Fred N. van Kempen. @@ -143,7 +143,7 @@ neat_init(void) void -machine_at_4gpv31_init(machine_t *model) +machine_at_4gpv31_init(const machine_t *model) { machine_at_common_ide_init(model); device_add(&keyboard_at_ami_device); diff --git a/src/machine/m_at_ali1429.c b/src/machine/m_at_ali1429.c index aadec2a14..a0dc3ddf0 100644 --- a/src/machine/m_at_ali1429.c +++ b/src/machine/m_at_ali1429.c @@ -98,7 +98,7 @@ static void ali1429_init(void) void -machine_at_ali1429_init(machine_t *model) +machine_at_ali1429_init(const machine_t *model) { ali1429_reset(); diff --git a/src/machine/m_at_commodore.c b/src/machine/m_at_commodore.c index ea5eb8fcc..e12e13970 100644 --- a/src/machine/m_at_commodore.c +++ b/src/machine/m_at_commodore.c @@ -46,7 +46,7 @@ static void cbm_io_init() void -machine_at_cmdpc_init(machine_t *model) +machine_at_cmdpc_init(const machine_t *model) { machine_at_ide_top_remap_init(model); device_add(&fdc_at_device); diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index 4c0705cc9..9497a8498 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -8,7 +8,7 @@ * * Emulation of various Compaq PC's. * - * Version: @(#)m_at_compaq.c 1.0.4 2018/02/14 + * Version: @(#)m_at_compaq.c 1.0.5 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -98,7 +98,7 @@ write_raml(uint32_t addr, uint32_t val, void *priv) void -machine_at_compaq_init(machine_t *model) +machine_at_compaq_init(const machine_t *model) { machine_at_top_remap_init(model); device_add(&fdc_at_device); diff --git a/src/machine/m_at_headland.c b/src/machine/m_at_headland.c index a8997e1a6..b8f707d4e 100644 --- a/src/machine/m_at_headland.c +++ b/src/machine/m_at_headland.c @@ -70,7 +70,7 @@ static void headland_init(void) void -machine_at_headland_init(machine_t *model) +machine_at_headland_init(const machine_t *model) { machine_at_common_ide_init(model); diff --git a/src/machine/m_at_neat.c b/src/machine/m_at_neat.c index 89baf7e17..2f789b3a1 100644 --- a/src/machine/m_at_neat.c +++ b/src/machine/m_at_neat.c @@ -88,7 +88,7 @@ static void neat_init(void) void -machine_at_neat_init(machine_t *model) +machine_at_neat_init(const machine_t *model) { machine_at_init(model); device_add(&fdc_at_device); @@ -98,7 +98,7 @@ machine_at_neat_init(machine_t *model) void -machine_at_neat_ami_init(machine_t *model) +machine_at_neat_ami_init(const machine_t *model) { machine_at_common_init(model); diff --git a/src/machine/m_at_opti495.c b/src/machine/m_at_opti495.c index 5db7ca55f..21f984827 100644 --- a/src/machine/m_at_opti495.c +++ b/src/machine/m_at_opti495.c @@ -323,7 +323,7 @@ static void opti495_init(void) void -machine_at_opti495_init(machine_t *model) +machine_at_opti495_init(const machine_t *model) { machine_at_common_ide_init(model); @@ -335,7 +335,7 @@ machine_at_opti495_init(machine_t *model) void -machine_at_opti495_ami_init(machine_t *model) +machine_at_opti495_ami_init(const machine_t *model) { machine_at_common_ide_init(model); diff --git a/src/machine/m_at_scat.c b/src/machine/m_at_scat.c index 37c4b2080..39ee46ea3 100644 --- a/src/machine/m_at_scat.c +++ b/src/machine/m_at_scat.c @@ -10,7 +10,7 @@ * * Re-worked version based on the 82C235 datasheet and errata. * - * Version: @(#)m_at_scat.c 1.0.10 2018/03/02 + * Version: @(#)m_at_scat.c 1.0.11 2018/03/18 * * Authors: Original by GreatPsycho for PCem. * Fred N. van Kempen, @@ -712,7 +712,7 @@ scatsx_init() void -machine_at_scat_init(machine_t *model) +machine_at_scat_init(const machine_t *model) { machine_at_init(model); device_add(&fdc_at_device); @@ -722,7 +722,7 @@ machine_at_scat_init(machine_t *model) void -machine_at_scatsx_init(machine_t *model) +machine_at_scatsx_init(const machine_t *model) { machine_at_init(model); device_add(&fdc_at_device); diff --git a/src/machine/m_at_sis_85c471.c b/src/machine/m_at_sis_85c471.c index c3f6b47fc..fc511d7c6 100644 --- a/src/machine/m_at_sis_85c471.c +++ b/src/machine/m_at_sis_85c471.c @@ -9,7 +9,7 @@ * SiS sis85c471 Super I/O Chip * Used by DTK PKM-0038S E-2 * - * Version: @(#)m_at_sis85c471.c 1.0.9 2018/01/16 + * Version: @(#)m_at_sis85c471.c 1.0.10 2018/03/18 * * Author: Miran Grca, * @@ -240,7 +240,7 @@ static void sis_85c471_init(void) void -machine_at_dtk486_init(machine_t *model) +machine_at_dtk486_init(const machine_t *model) { machine_at_ide_init(model); device_add(&fdc_at_device); diff --git a/src/machine/m_at_sis_85c496.c b/src/machine/m_at_sis_85c496.c index 8e0fe7064..1705425cb 100644 --- a/src/machine/m_at_sis_85c496.c +++ b/src/machine/m_at_sis_85c496.c @@ -162,7 +162,7 @@ static void sis_85c496_init(void) static void -machine_at_sis_85c496_common_init(machine_t *model) +machine_at_sis_85c496_common_init(const machine_t *model) { machine_at_ps2_init(model); device_add(&ide_pci_device); @@ -180,7 +180,7 @@ machine_at_sis_85c496_common_init(machine_t *model) void -machine_at_r418_init(machine_t *model) +machine_at_r418_init(const machine_t *model) { machine_at_sis_85c496_common_init(model); diff --git a/src/machine/m_at_sis_85c50x.c b/src/machine/m_at_sis_85c50x.c index e650e71dc..c5f18eeca 100644 --- a/src/machine/m_at_sis_85c50x.c +++ b/src/machine/m_at_sis_85c50x.c @@ -6,11 +6,11 @@ * * Emulation of the SiS 50x PCI chips. * - * Version: @(#)m_at_sis_85c50x.c 1.0.5 2017/11/04 + * Version: @(#)m_at_sis_85c50x.c 1.0.6 2018/03/18 * * Author: Miran Grca, * - * Copyright 2017 Miran Grca. + * Copyright 2015-2018 Miran Grca. */ #include #include diff --git a/src/machine/m_at_t3100e.c b/src/machine/m_at_t3100e.c index 9031d430d..799e4055c 100644 --- a/src/machine/m_at_t3100e.c +++ b/src/machine/m_at_t3100e.c @@ -117,7 +117,7 @@ * bit 2 set for single-pixel LCD font * bits 0,1 for display font * - * Version: @(#)m_at_t3100e.c 1.0.3 2018/03/05 + * Version: @(#)m_at_t3100e.c 1.0.4 2018/03/18 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -716,7 +716,7 @@ static void upper_write_raml(uint32_t addr, uint32_t val, void *priv) -void machine_at_t3100e_init(machine_t *model) +void machine_at_t3100e_init(const machine_t *model) { int pg; diff --git a/src/machine/m_at_t3100e.h b/src/machine/m_at_t3100e.h index 0de5cf62a..e92d23b73 100644 --- a/src/machine/m_at_t3100e.h +++ b/src/machine/m_at_t3100e.h @@ -8,7 +8,7 @@ * * Definitions for the Toshiba T3100e system. * - * Version: @(#)m_at_t3100e.h 1.0.2 2018/03/05 + * Version: @(#)m_at_t3100e.h 1.0.3 2018/03/18 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,7 +40,7 @@ # define MACHINE_T3100E_H -extern device_t t3100e_device; +extern const device_t t3100e_device; extern void t3100e_notify_set(uint8_t value); diff --git a/src/machine/m_at_t3100e_vid.c b/src/machine/m_at_t3100e_vid.c index 814d0dc3f..033520034 100644 --- a/src/machine/m_at_t3100e_vid.c +++ b/src/machine/m_at_t3100e_vid.c @@ -22,7 +22,7 @@ * 61 50 52 0F 19 06 19 19 02 0D 0B 0C MONO * 2D 28 22 0A 67 00 64 67 02 03 06 07 640x400 * - * Version: @(#)m_at_t3100e_vid.c 1.0.3 2018/03/07 + * Version: @(#)m_at_t3100e_vid.c 1.0.4 2018/03/18 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -703,7 +703,7 @@ void t3100e_recalcattrs(t3100e_t *t3100e) } -void *t3100e_init(device_t *info) +void *t3100e_init(const device_t *info) { t3100e_t *t3100e = malloc(sizeof(t3100e_t)); memset(t3100e, 0, sizeof(t3100e_t)); @@ -748,7 +748,7 @@ void t3100e_speed_changed(void *p) t3100e_recalctimings(t3100e); } -device_t t3100e_device = +const device_t t3100e_device = { "Toshiba T3100e", 0, diff --git a/src/machine/m_at_wd76c10.c b/src/machine/m_at_wd76c10.c index 1e1f3ac1f..f63cf2b8b 100644 --- a/src/machine/m_at_wd76c10.c +++ b/src/machine/m_at_wd76c10.c @@ -142,7 +142,7 @@ static void wd76c10_init(void) void -machine_at_wd76c10_init(machine_t *model) +machine_at_wd76c10_init(const machine_t *model) { machine_at_common_ide_init(model); diff --git a/src/machine/m_europc.c b/src/machine/m_europc.c index f2dae9a28..63d4b4b4d 100644 --- a/src/machine/m_europc.c +++ b/src/machine/m_europc.c @@ -68,7 +68,7 @@ * * WARNING THIS IS A WORK-IN-PROGRESS MODULE. USE AT OWN RISK. * - * Version: @(#)europc.c 1.0.2 2018/03/11 + * Version: @(#)europc.c 1.0.3 2018/03/18 * * Author: Fred N. van Kempen, * @@ -546,7 +546,7 @@ jim_read(uint16_t addr, void *priv) /* Initialize the mainboard 'device' of the machine. */ static void * -europc_boot(device_t *info) +europc_boot(const device_t *info) { europc_t *sys = &europc; uint8_t b; @@ -674,7 +674,7 @@ europc_close(void *priv) } -static device_config_t europc_config[] = { +static const device_config_t europc_config[] = { { "js9", "JS9 Jumper (JIM)", CONFIG_INT, "", 0, { @@ -695,7 +695,7 @@ static device_config_t europc_config[] = { }; -device_t europc_device = { +const device_t europc_device = { "EuroPC System Board", 0, 0, europc_boot, europc_close, NULL, @@ -713,7 +713,7 @@ device_t europc_device = { * user. */ void -machine_europc_init(machine_t *model) +machine_europc_init(const machine_t *model) { /* Clear the machine state. */ memset(&europc, 0x00, sizeof(europc_t)); diff --git a/src/machine/m_europc_hdc.c b/src/machine/m_europc_hdc.c index ef8b21514..315f0f85c 100644 --- a/src/machine/m_europc_hdc.c +++ b/src/machine/m_europc_hdc.c @@ -22,7 +22,7 @@ * * Based on the original "xebec.c" from Sarah Walker. * - * Version: @(#)m_europc_hdc.c 1.0.2 2018/03/11 + * Version: @(#)m_europc_hdc.c 1.0.3 2018/03/18 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -902,7 +902,7 @@ hd20_write(uint16_t port, uint8_t val, void *priv) static void * -hd20_init(device_t *info) +hd20_init(const device_t *info) { drive_t *drive; hd20_t *dev; @@ -978,7 +978,7 @@ hd20_available(void) } -device_t europc_hdc_device = { +const device_t europc_hdc_device = { "EuroPC HD20", 0, 0, hd20_init, hd20_close, NULL, diff --git a/src/machine/m_olivetti_m24.c b/src/machine/m_olivetti_m24.c index 9492af865..bf6c0ec6f 100644 --- a/src/machine/m_olivetti_m24.c +++ b/src/machine/m_olivetti_m24.c @@ -8,7 +8,7 @@ * * Emulation of the Olivetti M24. * - * Version: @(#)m_olivetti_m24.c 1.0.10 2018/01/29 + * Version: @(#)m_olivetti_m24.c 1.0.11 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -789,7 +789,7 @@ vid_close(void *priv) free(m24); } -device_t m24_device = { +const device_t m24_device = { "Olivetti M24", 0, 0, NULL, vid_close, NULL, @@ -801,7 +801,7 @@ device_t m24_device = { void -machine_olim24_init(machine_t *model) +machine_olim24_init(const machine_t *model) { olim24_t *m24; diff --git a/src/machine/m_pcjr.c b/src/machine/m_pcjr.c index 6f8f1ec4a..d2167ff70 100644 --- a/src/machine/m_pcjr.c +++ b/src/machine/m_pcjr.c @@ -8,7 +8,7 @@ * * Emulation of the IBM PCjr. * - * Version: @(#)m_pcjr.c 1.0.5 2018/02/09 + * Version: @(#)m_pcjr.c 1.0.6 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -693,7 +693,7 @@ speed_changed(void *priv) } -static device_config_t pcjr_config[] = { +static const device_config_t pcjr_config[] = { { "display_type", "Display type", CONFIG_SELECTION, "", PCJR_RGB, { @@ -714,7 +714,7 @@ static device_config_t pcjr_config[] = { }; -static device_t pcjr_device = { +static const device_t pcjr_device = { "IBM PCjr", 0, 0, NULL, NULL, NULL, @@ -726,7 +726,7 @@ static device_t pcjr_device = { }; -device_t * +const device_t * pcjr_get_device(void) { return &pcjr_device; @@ -734,7 +734,7 @@ pcjr_get_device(void) void -machine_pcjr_init(machine_t *model) +machine_pcjr_init(const machine_t *model) { int display_type; pcjr_t *pcjr; diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index 482fc2430..9be9cbd2c 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -28,7 +28,7 @@ * boot. Sometimes, they do, and then it shows an "Incorrect * DOS" error message?? --FvK * - * Version: @(#)m_ps1.c 1.0.6 2018/02/14 + * Version: @(#)m_ps1.c 1.0.7 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -236,7 +236,7 @@ snd_get_buffer(int32_t *buffer, int len, void *priv) static void * -snd_init(device_t *info) +snd_init(const device_t *info) { ps1snd_t *snd; @@ -265,7 +265,7 @@ snd_close(void *priv) } -static device_t snd_device = { +static const device_t snd_device = { "PS/1 Audio Card", 0, 0, snd_init, snd_close, NULL, @@ -535,7 +535,7 @@ ps1_setup(int model) static void -ps1_common_init(machine_t *model) +ps1_common_init(const machine_t *model) { machine_common_init(model); @@ -570,7 +570,7 @@ ps1_common_init(machine_t *model) void -machine_ps1_m2011_init(machine_t *model) +machine_ps1_m2011_init(const machine_t *model) { ps1_common_init(model); @@ -579,7 +579,7 @@ machine_ps1_m2011_init(machine_t *model) void -machine_ps1_m2121_init(machine_t *model) +machine_ps1_m2121_init(const machine_t *model) { ps1_common_init(model); @@ -588,7 +588,7 @@ machine_ps1_m2121_init(machine_t *model) void -machine_ps1_m2133_init(machine_t *model) +machine_ps1_m2133_init(const machine_t *model) { ps1_common_init(model); diff --git a/src/machine/m_ps2_isa.c b/src/machine/m_ps2_isa.c index 8f9c1906d..60300adf0 100644 --- a/src/machine/m_ps2_isa.c +++ b/src/machine/m_ps2_isa.c @@ -148,7 +148,7 @@ static void ps2board_init(void) void -machine_ps2_m30_286_init(machine_t *model) +machine_ps2_m30_286_init(const machine_t *model) { machine_common_init(model); device_add(&fdc_at_ps1_device); diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index f85a06c0b..5033945c2 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -1218,7 +1218,7 @@ static void ps2_mca_board_model_80_type2_init(int is486) static void -machine_ps2_common_init(machine_t *model) +machine_ps2_common_init(const machine_t *model) { machine_common_init(model); device_add(&fdc_at_device); @@ -1236,7 +1236,7 @@ machine_ps2_common_init(machine_t *model) void -machine_ps2_model_50_init(machine_t *model) +machine_ps2_model_50_init(const machine_t *model) { machine_ps2_common_init(model); @@ -1245,7 +1245,7 @@ machine_ps2_model_50_init(machine_t *model) void -machine_ps2_model_55sx_init(machine_t *model) +machine_ps2_model_55sx_init(const machine_t *model) { machine_ps2_common_init(model); @@ -1253,7 +1253,7 @@ machine_ps2_model_55sx_init(machine_t *model) } void -machine_ps2_model_70_type3_init(machine_t *model) +machine_ps2_model_70_type3_init(const machine_t *model) { machine_ps2_common_init(model); @@ -1261,7 +1261,7 @@ machine_ps2_model_70_type3_init(machine_t *model) } void -machine_ps2_model_70_type4_init(machine_t *model) +machine_ps2_model_70_type4_init(const machine_t *model) { machine_ps2_common_init(model); @@ -1269,7 +1269,7 @@ machine_ps2_model_70_type4_init(machine_t *model) } void -machine_ps2_model_80_init(machine_t *model) +machine_ps2_model_80_init(const machine_t *model) { machine_ps2_common_init(model); @@ -1279,7 +1279,7 @@ machine_ps2_model_80_init(machine_t *model) #ifdef WALTJE void -machine_ps2_model_80_486_init(machine_t *model) +machine_ps2_model_80_486_init(const machine_t *model) { machine_ps2_common_init(model); diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index 8d2a1b38e..a31fffde8 100644 --- a/src/machine/m_tandy.c +++ b/src/machine/m_tandy.c @@ -8,7 +8,7 @@ * * Emulation of Tandy models 1000, 1000HX and 1000SL2. * - * Version: @(#)m_tandy.c 1.0.3 2018/02/09 + * Version: @(#)m_tandy.c 1.0.4 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -1353,7 +1353,7 @@ vid_init(tandy_t *dev) } -static device_config_t vid_config[] = { +static const device_config_t vid_config[] = { { "display_type", "Display type", CONFIG_SELECTION, "", TANDY_RGB, { @@ -1374,7 +1374,7 @@ static device_config_t vid_config[] = { }; -static device_t vid_device = { +static const device_t vid_device = { "Tandy 1000", 0, 0, NULL, vid_close, NULL, @@ -1385,7 +1385,7 @@ static device_t vid_device = { vid_config }; -static device_t vid_device_hx = { +static const device_t vid_device_hx = { "Tandy 1000 HX", 0, 0, NULL, vid_close, NULL, @@ -1396,7 +1396,7 @@ static device_t vid_device_hx = { vid_config }; -static device_t vid_device_sl = { +static const device_t vid_device_sl = { "Tandy 1000SL2", 0, 1, NULL, vid_close, NULL, @@ -1408,14 +1408,14 @@ static device_t vid_device_sl = { }; -device_t * +const device_t * tandy1k_get_device(void) { return &vid_device; } -device_t * +const device_t * tandy1k_hx_get_device(void) { return &vid_device_hx; @@ -1501,7 +1501,7 @@ eep_write(uint16_t addr, uint8_t val, void *priv) static void * -eep_init(device_t *info) +eep_init(const device_t *info) { t1keep_t *eep; FILE *f = NULL; @@ -1548,7 +1548,7 @@ eep_close(void *priv) } -static device_t eep_device = { +static const device_t eep_device = { "Tandy 1000 EEPROM", 0, 0, eep_init, eep_close, NULL, @@ -1692,7 +1692,7 @@ init_rom(tandy_t *dev) void -machine_tandy1k_init(machine_t *model) +machine_tandy1k_init(const machine_t *model) { tandy_t *dev; diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index bb4ef2fb1..3878c98b1 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -15,7 +15,7 @@ void -machine_xt_init(machine_t *model) +machine_xt_init(const machine_t *model) { machine_common_init(model); diff --git a/src/machine/m_xt_compaq.c b/src/machine/m_xt_compaq.c index f070a05b3..751e45da8 100644 --- a/src/machine/m_xt_compaq.c +++ b/src/machine/m_xt_compaq.c @@ -8,7 +8,7 @@ * * Emulation of various Compaq XT-class PC's. * - * Version: @(#)m_xt_compaq.c 1.0.3 2018/02/24 + * Version: @(#)m_xt_compaq.c 1.0.4 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -37,7 +37,7 @@ void -machine_xt_compaq_init(machine_t *model) +machine_xt_compaq_init(const machine_t *model) { machine_common_init(model); diff --git a/src/machine/m_xt_laserxt.c b/src/machine/m_xt_laserxt.c index 61ae8d983..fe5d86606 100644 --- a/src/machine/m_xt_laserxt.c +++ b/src/machine/m_xt_laserxt.c @@ -132,7 +132,7 @@ static void laserxt_init(void) void -machine_xt_laserxt_init(machine_t *model) +machine_xt_laserxt_init(const machine_t *model) { machine_xt_init(model); diff --git a/src/machine/m_xt_t1000.c b/src/machine/m_xt_t1000.c index b1d5c2367..969329680 100644 --- a/src/machine/m_xt_t1000.c +++ b/src/machine/m_xt_t1000.c @@ -51,7 +51,7 @@ * NOTE: Still need to figure out a way to load/save ConfigSys and * HardRAM stuff. Needs to be linked in to the NVR code. * - * Version: @(#)m_xt_t1000.c 1.0.2 2018/03/11 + * Version: @(#)m_xt_t1000.c 1.0.3 2018/03/18 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -784,7 +784,7 @@ t1000_read_roml(uint32_t addr, void *priv) } -device_t * +const device_t * t1000_get_device(void) { return(&t1000_video_device); @@ -792,7 +792,7 @@ t1000_get_device(void) void -machine_xt_t1000_init(machine_t *model) +machine_xt_t1000_init(const machine_t *model) { FILE *f; int pg; @@ -862,7 +862,7 @@ machine_xt_t1000_init(machine_t *model) } -device_t * +const device_t * t1200_get_device(void) { return(&t1200_video_device); @@ -870,7 +870,7 @@ t1200_get_device(void) void -machine_xt_t1200_init(machine_t *model) +machine_xt_t1200_init(const machine_t *model) { int pg; diff --git a/src/machine/m_xt_t1000.h b/src/machine/m_xt_t1000.h index 545861eb5..e2a1ade1f 100644 --- a/src/machine/m_xt_t1000.h +++ b/src/machine/m_xt_t1000.h @@ -8,7 +8,7 @@ * * Definitions for the Toshiba T1000/T1200 machines. * - * Version: @(#)m_xt_t1000.h 1.0.2 2018/03/10 + * Version: @(#)m_xt_t1000.h 1.0.3 2018/03/18 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,8 +40,8 @@ # define MACHINE_T1000_H -extern device_t t1000_video_device; -extern device_t t1200_video_device; +extern const device_t t1000_video_device; +extern const device_t t1200_video_device; extern void t1000_video_options_set(uint8_t options); diff --git a/src/machine/m_xt_t1000_vid.c b/src/machine/m_xt_t1000_vid.c index e2058c94f..a1baa8f22 100644 --- a/src/machine/m_xt_t1000_vid.c +++ b/src/machine/m_xt_t1000_vid.c @@ -9,7 +9,7 @@ * Implementation of the Toshiba T1000 plasma display, which * has a fixed resolution of 640x200 pixels. * - * Version: @(#)m_xt_t1000_vid.c 1.0.4 2018/03/10 + * Version: @(#)m_xt_t1000_vid.c 1.0.5 2018/03/18 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -658,7 +658,7 @@ static void t1000_recalcattrs(t1000_t *t1000) } -static void *t1000_init(device_t *info) +static void *t1000_init(const device_t *info) { t1000_t *t1000 = malloc(sizeof(t1000_t)); memset(t1000, 0, sizeof(t1000_t)); @@ -704,7 +704,7 @@ static void t1000_speed_changed(void *p) t1000_recalctimings(t1000); } -static device_config_t t1000_config[] = +static const device_config_t t1000_config[] = { { .name = "display_language", @@ -729,7 +729,7 @@ static device_config_t t1000_config[] = }; -device_t t1000_video_device = { +const device_t t1000_video_device = { "Toshiba T1000 Video", 0, 0, t1000_init, t1000_close, NULL, @@ -741,7 +741,7 @@ device_t t1000_video_device = { }; -device_t t1200_video_device = { +const device_t t1200_video_device = { "Toshiba T1200 Video", 0, 0, t1000_init, t1000_close, NULL, diff --git a/src/machine/m_xt_xi8088.c b/src/machine/m_xt_xi8088.c index bf06bb572..f4137cfb0 100644 --- a/src/machine/m_xt_xi8088.c +++ b/src/machine/m_xt_xi8088.c @@ -76,7 +76,7 @@ static void *xi8088_init() return &xi8088; } -static device_config_t xi8088_config[] = +static const device_config_t xi8088_config[] = { { .name = "turbo_setting", @@ -101,7 +101,7 @@ static device_config_t xi8088_config[] = }; -device_t xi8088_device = +const device_t xi8088_device = { "Xi8088", 0, @@ -116,13 +116,13 @@ device_t xi8088_device = xi8088_config }; -device_t * +const device_t * xi8088_get_device(void) { return &xi8088_device; } -void machine_xt_xi8088_init(machine_t *model) +void machine_xt_xi8088_init(const machine_t *model) { /* TODO: set UMBs? See if PCem always sets when we have > 640KB ram and avoids conflicts when a peripheral uses the same memory space */ machine_common_init(model); diff --git a/src/machine/m_xt_xi8088.h b/src/machine/m_xt_xi8088.h index 1c33c6532..0270ed16d 100644 --- a/src/machine/m_xt_xi8088.h +++ b/src/machine/m_xt_xi8088.h @@ -1,6 +1,6 @@ #include "../device.h" -extern device_t xi8088_device; +extern const device_t xi8088_device; uint8_t xi8088_turbo_get(); void xi8088_turbo_set(uint8_t value); diff --git a/src/machine/machine.c b/src/machine/machine.c index a000a9fb5..4a17cc7ae 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -8,7 +8,7 @@ * * Handling of the emulated machines. * - * Version: @(#)machine.c 1.0.30 2018/03/15 + * Version: @(#)machine.c 1.0.31 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -65,7 +65,7 @@ machine_init(void) void -machine_common_init(machine_t *model) +machine_common_init(const machine_t *model) { /* System devices first. */ dma_init(); diff --git a/src/machine/machine.h b/src/machine/machine.h index 2cd9880f4..7822ffd2f 100644 --- a/src/machine/machine.h +++ b/src/machine/machine.h @@ -8,7 +8,7 @@ * * Handling of the emulated machines. * - * Version: @(#)machine.h 1.0.21 2018/03/02 + * Version: @(#)machine.h 1.0.22 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -58,9 +58,9 @@ typedef struct _machine_ { int min_ram, max_ram; int ram_granularity; int nvrmask; - void (*init)(struct _machine_ *); + void (*init)(const struct _machine_ *); #ifdef EMU_DEVICE_H - device_t *(*get_device)(void); + const device_t *(*get_device)(void); #else void *get_device; #endif @@ -69,7 +69,7 @@ typedef struct _machine_ { /* Global variables. */ -extern machine_t machines[]; +extern const machine_t machines[]; extern int machine; extern int romset; extern int AT, PCI; @@ -84,7 +84,7 @@ extern char *machine_get_internal_name(void); extern int machine_get_machine_from_internal_name(char *s); extern void machine_init(void); #ifdef EMU_DEVICE_H -extern device_t *machine_getdevice(int machine); +extern const device_t *machine_getdevice(int machine); #endif extern int machine_getromset_ex(int m); extern char *machine_get_internal_name_ex(int m); @@ -93,119 +93,119 @@ extern void machine_close(void); /* Initialization functions for boards and systems. */ -extern void machine_common_init(machine_t *); +extern void machine_common_init(const machine_t *); -extern void machine_at_common_init(machine_t *); -extern void machine_at_init(machine_t *); -extern void machine_at_ps2_init(machine_t *); -extern void machine_at_common_ide_init(machine_t *); -extern void machine_at_ide_init(machine_t *); -extern void machine_at_ps2_ide_init(machine_t *); -extern void machine_at_top_remap_init(machine_t *); -extern void machine_at_ide_top_remap_init(machine_t *); +extern void machine_at_common_init(const machine_t *); +extern void machine_at_init(const machine_t *); +extern void machine_at_ps2_init(const machine_t *); +extern void machine_at_common_ide_init(const machine_t *); +extern void machine_at_ide_init(const machine_t *); +extern void machine_at_ps2_ide_init(const machine_t *); +extern void machine_at_top_remap_init(const machine_t *); +extern void machine_at_ide_top_remap_init(const machine_t *); -extern void machine_at_ibm_init(machine_t *); +extern void machine_at_ibm_init(const machine_t *); -extern void machine_at_t3100e_init(machine_t *); +extern void machine_at_t3100e_init(const machine_t *); -extern void machine_at_p54tp4xe_init(machine_t *); -extern void machine_at_endeavor_init(machine_t *); -extern void machine_at_zappa_init(machine_t *); -extern void machine_at_mb500n_init(machine_t *); -extern void machine_at_president_init(machine_t *); -extern void machine_at_thor_init(machine_t *); +extern void machine_at_p54tp4xe_init(const machine_t *); +extern void machine_at_endeavor_init(const machine_t *); +extern void machine_at_zappa_init(const machine_t *); +extern void machine_at_mb500n_init(const machine_t *); +extern void machine_at_president_init(const machine_t *); +extern void machine_at_thor_init(const machine_t *); -extern void machine_at_acerm3a_init(machine_t *); -extern void machine_at_acerv35n_init(machine_t *); -extern void machine_at_ap53_init(machine_t *); -extern void machine_at_p55t2p4_init(machine_t *); -extern void machine_at_p55t2s_init(machine_t *); +extern void machine_at_acerm3a_init(const machine_t *); +extern void machine_at_acerv35n_init(const machine_t *); +extern void machine_at_ap53_init(const machine_t *); +extern void machine_at_p55t2p4_init(const machine_t *); +extern void machine_at_p55t2s_init(const machine_t *); -extern void machine_at_batman_init(machine_t *); -extern void machine_at_plato_init(machine_t *); +extern void machine_at_batman_init(const machine_t *); +extern void machine_at_plato_init(const machine_t *); -extern void machine_at_p55tvp4_init(machine_t *); -extern void machine_at_i430vx_init(machine_t *); -extern void machine_at_p55va_init(machine_t *); +extern void machine_at_p55tvp4_init(const machine_t *); +extern void machine_at_i430vx_init(const machine_t *); +extern void machine_at_p55va_init(const machine_t *); #if defined(DEV_BRANCH) && defined(USE_I686) -extern void machine_at_i440fx_init(machine_t *); -extern void machine_at_s1668_init(machine_t *); +extern void machine_at_i440fx_init(const machine_t *); +extern void machine_at_s1668_init(const machine_t *); #endif -extern void machine_at_ali1429_init(machine_t *); -extern void machine_at_cmdpc_init(machine_t *); +extern void machine_at_ali1429_init(const machine_t *); +extern void machine_at_cmdpc_init(const machine_t *); -extern void machine_at_headland_init(machine_t *); -extern void machine_at_neat_init(machine_t *); -extern void machine_at_neat_ami_init(machine_t *); -extern void machine_at_opti495_init(machine_t *); -extern void machine_at_opti495_ami_init(machine_t *); -extern void machine_at_scat_init(machine_t *); -extern void machine_at_scatsx_init(machine_t *); -extern void machine_at_compaq_init(machine_t *); +extern void machine_at_headland_init(const machine_t *); +extern void machine_at_neat_init(const machine_t *); +extern void machine_at_neat_ami_init(const machine_t *); +extern void machine_at_opti495_init(const machine_t *); +extern void machine_at_opti495_ami_init(const machine_t *); +extern void machine_at_scat_init(const machine_t *); +extern void machine_at_scatsx_init(const machine_t *); +extern void machine_at_compaq_init(const machine_t *); -extern void machine_at_dtk486_init(machine_t *); -extern void machine_at_r418_init(machine_t *); +extern void machine_at_dtk486_init(const machine_t *); +extern void machine_at_r418_init(const machine_t *); -extern void machine_at_wd76c10_init(machine_t *); +extern void machine_at_wd76c10_init(const machine_t *); #if defined(DEV_BRANCH) && defined(USE_GREENB) -extern void machine_at_4gpv31_init(machine_t *); +extern void machine_at_4gpv31_init(const machine_t *); #endif -extern void machine_pcjr_init(machine_t *); +extern void machine_pcjr_init(const machine_t *); -extern void machine_ps1_m2011_init(machine_t *); -extern void machine_ps1_m2121_init(machine_t *); -extern void machine_ps1_m2133_init(machine_t *); +extern void machine_ps1_m2011_init(const machine_t *); +extern void machine_ps1_m2121_init(const machine_t *); +extern void machine_ps1_m2133_init(const machine_t *); -extern void machine_ps2_m30_286_init(machine_t *); -extern void machine_ps2_model_50_init(machine_t *); -extern void machine_ps2_model_55sx_init(machine_t *); -extern void machine_ps2_model_70_type3_init(machine_t *); -extern void machine_ps2_model_70_type4_init(machine_t *); -extern void machine_ps2_model_80_init(machine_t *); +extern void machine_ps2_m30_286_init(const machine_t *); +extern void machine_ps2_model_50_init(const machine_t *); +extern void machine_ps2_model_55sx_init(const machine_t *); +extern void machine_ps2_model_70_type3_init(const machine_t *); +extern void machine_ps2_model_70_type4_init(const machine_t *); +extern void machine_ps2_model_80_init(const machine_t *); #ifdef WALTJE -extern void machine_ps2_model_80_486_init(machine_t *); +extern void machine_ps2_model_80_486_init(const machine_t *); #endif -extern void machine_amstrad_init(machine_t *); +extern void machine_amstrad_init(const machine_t *); -extern void machine_europc_init(machine_t *); +extern void machine_europc_init(const machine_t *); #ifdef EMU_DEVICE_H -extern device_t europc_device, +extern const device_t europc_device, europc_hdc_device; #endif -extern void machine_olim24_init(machine_t *); +extern void machine_olim24_init(const machine_t *); extern void machine_olim24_video_init(void); -extern void machine_tandy1k_init(machine_t *); +extern void machine_tandy1k_init(const machine_t *); extern int tandy1k_eeprom_read(void); -extern void machine_xt_init(machine_t *); -extern void machine_xt_compaq_init(machine_t *); +extern void machine_xt_init(const machine_t *); +extern void machine_xt_compaq_init(const machine_t *); #if defined(DEV_BRANCH) && defined(USE_LASERXT) -extern void machine_xt_laserxt_init(machine_t *); +extern void machine_xt_laserxt_init(const machine_t *); #endif -extern void machine_xt_t1000_init(machine_t *); -extern void machine_xt_t1200_init(machine_t *); +extern void machine_xt_t1000_init(const machine_t *); +extern void machine_xt_t1200_init(const machine_t *); -extern void machine_xt_xi8088_init(machine_t *); +extern void machine_xt_xi8088_init(const machine_t *); #ifdef EMU_DEVICE_H -extern device_t *xi8088_get_device(void); +extern const device_t *xi8088_get_device(void); -extern device_t *pcjr_get_device(void); +extern const device_t *pcjr_get_device(void); -extern device_t *tandy1k_get_device(void); -extern device_t *tandy1k_hx_get_device(void); +extern const device_t *tandy1k_get_device(void); +extern const device_t *tandy1k_hx_get_device(void); -extern device_t *t1000_get_device(void); -extern device_t *t1200_get_device(void); +extern const device_t *t1000_get_device(void); +extern const device_t *t1200_get_device(void); -extern device_t *at_endeavor_get_device(void); +extern const device_t *at_endeavor_get_device(void); #endif diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 8bb8d4982..8f02f57c8 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -11,7 +11,7 @@ * NOTES: OpenAT wip for 286-class machine with open BIOS. * PS2_M80-486 wip, pending receipt of TRM's for machine. * - * Version: @(#)machine_table.c 1.0.25 2018/03/13 + * Version: @(#)machine_table.c 1.0.26 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -34,7 +34,7 @@ #include "machine.h" -machine_t machines[] = { +const machine_t machines[] = { { "[8088] AMI XT clone", ROM_AMIXT, "amixt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL, NULL }, { "[8088] Compaq Portable", ROM_PORTABLE, "portable", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, machine_xt_compaq_init, NULL, NULL }, { "[8088] DTK XT clone", ROM_DTKXT, "dtk", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL, NULL }, @@ -223,7 +223,7 @@ machine_getname(void) } -device_t * +const device_t * machine_getdevice(int machine) { if (machines[machine].get_device) diff --git a/src/mouse.c b/src/mouse.c index 1c69a792c..0ee64943f 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -11,7 +11,7 @@ * TODO: Add the Genius bus- and serial mouse. * Remove the '3-button' flag from mouse types. * - * Version: @(#)mouse.c 1.0.22 2018/03/18 + * Version: @(#)mouse.c 1.0.23 2018/03/18 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -30,7 +30,7 @@ typedef struct { const char *internal_name; - device_t *device; + const device_t *device; } mouse_t; @@ -41,14 +41,14 @@ int mouse_x, mouse_buttons; -static device_t mouse_none_device = { +static const device_t mouse_none_device = { "None", 0, MOUSE_TYPE_NONE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -static device_t mouse_internal_device = { +static const device_t mouse_internal_device = { "Internal Mouse", 0, MOUSE_TYPE_INTERNAL, NULL, NULL, NULL, @@ -72,7 +72,7 @@ static mouse_t mouse_devices[] = { }; -static device_t *mouse_curr; +static const device_t *mouse_curr; static void *mouse_priv; static int mouse_nbut; static int (*mouse_dev_poll)(); @@ -211,7 +211,7 @@ mouse_has_config(int mouse) } -device_t * +const device_t * mouse_get_device(int mouse) { return(mouse_devices[mouse].device); diff --git a/src/mouse.h b/src/mouse.h index 84a6c5ec4..4d402fa0a 100644 --- a/src/mouse.h +++ b/src/mouse.h @@ -8,7 +8,7 @@ * * Definitions for the mouse driver. * - * Version: @(#)mouse.h 1.0.14 2018/01/29 + * Version: @(#)mouse.h 1.0.15 2018/03/18 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -44,17 +44,17 @@ extern int mouse_buttons; #ifdef EMU_DEVICE_H -extern device_t *mouse_get_device(int mouse); -extern void *mouse_ps2_init(device_t *); +extern const device_t *mouse_get_device(int mouse); +extern void *mouse_ps2_init(const device_t *); -extern device_t mouse_logibus_device; -extern device_t mouse_msinport_device; +extern const device_t mouse_logibus_device; +extern const device_t mouse_msinport_device; #if 0 -extern device_t mouse_genibus_device; +extern const device_t mouse_genibus_device; #endif -extern device_t mouse_mssystems_device; -extern device_t mouse_msserial_device; -extern device_t mouse_ps2_device; +extern const device_t mouse_mssystems_device; +extern const device_t mouse_msserial_device; +extern const device_t mouse_ps2_device; #endif extern void mouse_init(void); diff --git a/src/mouse_bus.c b/src/mouse_bus.c index 695f84f6a..ebd81a6df 100644 --- a/src/mouse_bus.c +++ b/src/mouse_bus.c @@ -49,7 +49,7 @@ * * Based on an early driver for MINIX 1.5. * - * Version: @(#)mouse_bus.c 1.0.31 2018/02/01 + * Version: @(#)mouse_bus.c 1.0.32 2018/03/18 * * Authors: Fred N. van Kempen, * @@ -669,7 +669,7 @@ bm_close(void *priv) /* Initialize the device for use by the user. */ static void * -bm_init(device_t *info) +bm_init(const device_t *info) { mouse_t *dev; int i; @@ -723,7 +723,7 @@ bm_init(device_t *info) } -static device_config_t bm_config[] = { +static const device_config_t bm_config[] = { { "irq", "IRQ", CONFIG_SELECTION, "", MOUSE_IRQ, { { @@ -762,7 +762,7 @@ static device_config_t bm_config[] = { }; -device_t mouse_logibus_device = { +const device_t mouse_logibus_device = { "Logitech Bus Mouse", DEVICE_ISA, MOUSE_TYPE_LOGIBUS, @@ -771,7 +771,7 @@ device_t mouse_logibus_device = { bm_config }; -device_t mouse_msinport_device = { +const device_t mouse_msinport_device = { "Microsoft Bus Mouse (InPort)", DEVICE_ISA, MOUSE_TYPE_INPORT, diff --git a/src/mouse_ps2.c b/src/mouse_ps2.c index e3743438d..3cf6ee27e 100644 --- a/src/mouse_ps2.c +++ b/src/mouse_ps2.c @@ -8,7 +8,7 @@ * * Implementation of PS/2 series Mouse devices. * - * Version: @(#)mouse_ps2.c 1.0.5 2017/12/14 + * Version: @(#)mouse_ps2.c 1.0.6 2018/03/18 * * Authors: Fred N. van Kempen, */ @@ -224,7 +224,7 @@ ps2_poll(int x, int y, int z, int b, void *priv) * We also get called from the various machines. */ void * -mouse_ps2_init(device_t *info) +mouse_ps2_init(const device_t *info) { mouse_t *dev; int i; @@ -264,7 +264,7 @@ ps2_close(void *priv) } -static device_config_t ps2_config[] = { +static const device_config_t ps2_config[] = { { "buttons", "Buttons", CONFIG_SELECTION, "", 2, { { @@ -287,7 +287,7 @@ static device_config_t ps2_config[] = { }; -device_t mouse_ps2_device = { +const device_t mouse_ps2_device = { "Standard PS/2 Mouse", 0, MOUSE_TYPE_PS2, diff --git a/src/mouse_serial.c b/src/mouse_serial.c index 22dc1973a..a0a487f9c 100644 --- a/src/mouse_serial.c +++ b/src/mouse_serial.c @@ -10,7 +10,7 @@ * * TODO: Add the Genius Serial Mouse. * - * Version: @(#)mouse_serial.c 1.0.20 2018/01/25 + * Version: @(#)mouse_serial.c 1.0.21 2018/03/18 * * Author: Fred N. van Kempen, */ @@ -196,7 +196,7 @@ sermouse_close(void *priv) /* Initialize the device for use by the user. */ static void * -sermouse_init(device_t *info) +sermouse_init(const device_t *info) { mouse_t *dev; int i; @@ -247,7 +247,7 @@ sermouse_init(device_t *info) } -static device_config_t sermouse_config[] = { +static const device_config_t sermouse_config[] = { { "port", "Serial Port", CONFIG_SELECTION, "", 0, { { @@ -283,7 +283,7 @@ static device_config_t sermouse_config[] = { }; -device_t mouse_mssystems_device = { +const device_t mouse_mssystems_device = { "Mouse Systems Serial Mouse", 0, MOUSE_TYPE_MSYSTEMS, @@ -292,7 +292,7 @@ device_t mouse_mssystems_device = { sermouse_config }; -device_t mouse_msserial_device = { +const device_t mouse_msserial_device = { "Microsoft/Logitech Serial Mouse", 0, 0, diff --git a/src/network/bswap.h b/src/network/bswap.h index 81275a6e6..75311d39b 100644 --- a/src/network/bswap.h +++ b/src/network/bswap.h @@ -1,6 +1,39 @@ -/* Copyright holders: neozeed - see COPYING for more details -*/ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Various definitions for portable byte-swapping. + * + * Version: @(#)bswap.h 1.0.2 2018/03/12 + * + * Authors: Fred N. van Kempen, + * neozeed, + * + * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 neozeed. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ #ifndef BSWAP_H #define BSWAP_H @@ -138,7 +171,7 @@ static __inline void cpu_to_le16wu(uint16_t *p, uint16_t v) { uint8_t *p1 = (uint8_t *)p; - p1[0] = v; + p1[0] = v & 0xff; p1[1] = v >> 8; } @@ -169,7 +202,7 @@ static __inline void cpu_to_be16wu(uint16_t *p, uint16_t v) uint8_t *p1 = (uint8_t *)p; p1[0] = v >> 8; - p1[1] = v; + p1[1] = v & 0xff; } static __inline void cpu_to_be32wu(uint32_t *p, uint32_t v) diff --git a/src/network/net_ne2000.c b/src/network/net_ne2000.c index 7c28acb23..97376fce7 100644 --- a/src/network/net_ne2000.c +++ b/src/network/net_ne2000.c @@ -1,10 +1,10 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * Implementation of the following network controllers: * - Novell NE1000 (ISA 8-bit); @@ -12,21 +12,36 @@ * - Realtek RTL8019AS (ISA 16-bit, PnP); * - Realtek RTL8029AS (PCI). * - * NOTE: The file will also implement an NE1000 for 8-bit ISA systems. - * - * Version: @(#)net_ne2000.c 1.0.30 2018/02/09 - * - * Authors: Fred N. van Kempen, - * Peter Grehan, - * Miran Grca, - * Sarah Walker, - * SA1988 + * Version: @(#)net_ne2000.c 1.0.3 2018/03/15 * * Based on @(#)ne2k.cc v1.56.2.1 2004/02/02 22:37:22 cbothamy * - * Portions Copyright (C) 2002 MandrakeSoft S.A. - * Portions Copyright (C) 2018 Sarah Walker. + * Authors: Fred N. van Kempen, + * TheCollector1995, + * Miran Grca, + * Peter Grehan, + * * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Portions Copyright (C) 2002 MandrakeSoft S.A. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ #include #include @@ -2362,7 +2377,7 @@ nic_rom_init(nic_t *dev, wchar_t *s) static void * -nic_init(device_t *info) +nic_init(const device_t *info) { uint32_t mac; wchar_t *rom; @@ -2370,9 +2385,9 @@ nic_init(device_t *info) #ifdef ENABLE_NIC_LOG int i; #endif - int c; - char *ansi_id = "REALTEK PLUG & PLAY ETHERNET CARD"; - uint64_t *eeprom_pnp_id; + int c; + char *ansi_id = "REALTEK PLUG & PLAY ETHERNET CARD"; + uint64_t *eeprom_pnp_id; /* Get the desired debug level. */ #ifdef ENABLE_NIC_LOG @@ -2388,6 +2403,8 @@ nic_init(device_t *info) switch(dev->board) { case NE2K_NE1000: dev->is_8bit = 1; + /*FALLTHROUGH*/ + case NE2K_NE2000: dev->maclocal[0] = 0x00; /* 00:00:D8 (Novell OID) */ dev->maclocal[1] = 0x00; @@ -2430,8 +2447,11 @@ nic_init(device_t *info) /* See if we have a local MAC address configured. */ mac = device_get_config_mac("mac", -1); - /* Make this device known to the I/O system. */ - if (dev->board < NE2K_RTL8019AS) /* PnP and PCI devices start with address spaces inactive. */ + /* + * Make this device known to the I/O system. + * PnP and PCI devices start with address spaces inactive. + */ + if (dev->board < NE2K_RTL8019AS) nic_ioset(dev, dev->base_address); /* Set up our BIOS ROM space, if any. */ @@ -2473,21 +2493,21 @@ nic_init(device_t *info) dev->pci_regs[0x02] = (PCI_DEVID&0xff); dev->pci_regs[0x03] = (PCI_DEVID>>8); - dev->pci_regs[0x04] = 0x03; /* IOEN */ + dev->pci_regs[0x04] = 0x03; /* IOEN */ dev->pci_regs[0x05] = 0x00; - dev->pci_regs[0x07] = 0x02; /* DST0, medium devsel */ + dev->pci_regs[0x07] = 0x02; /* DST0, medium devsel */ - dev->pci_regs[0x09] = 0x00; /* PIFR */ + dev->pci_regs[0x09] = 0x00; /* PIFR */ - dev->pci_regs[0x0B] = 0x02; /* BCR: Network Controller */ - dev->pci_regs[0x0A] = 0x00; /* SCR: Ethernet */ + dev->pci_regs[0x0B] = 0x02; /* BCR: Network Controller */ + dev->pci_regs[0x0A] = 0x00; /* SCR: Ethernet */ dev->pci_regs[0x2C] = (PCI_VENDID&0xff); dev->pci_regs[0x2D] = (PCI_VENDID>>8); dev->pci_regs[0x2E] = (PCI_DEVID&0xff); dev->pci_regs[0x2F] = (PCI_DEVID>>8); - dev->pci_regs[0x3D] = PCI_INTA; /* PCI_IPR */ + dev->pci_regs[0x3D] = PCI_INTA; /* PCI_IPR */ /* Enable our address space in PCI. */ dev->pci_bar[0].addr_regs[0] = 0x01; @@ -2503,8 +2523,9 @@ nic_init(device_t *info) mem_mapping_disable(&dev->bios_rom.mapping); - /* Insert this device onto the PCI bus, keep its slot number. */ - dev->card = pci_add_card(PCI_ADD_NORMAL, nic_pci_read, nic_pci_write, dev); + /* Add device to the PCI bus, keep its slot number. */ + dev->card = pci_add_card(PCI_ADD_NORMAL, + nic_pci_read, nic_pci_write, dev); } else { io_sethandler(0x0279, 1, NULL, NULL, NULL, @@ -2536,52 +2557,52 @@ nic_init(device_t *info) eeprom_pnp_id = (uint64_t *) &dev->eeprom[0x12]; *eeprom_pnp_id = dev->pnp_id; - /* TAG: Plug and Play Version Number */ - dev->eeprom[0x1B] = 0x0A; /* Item byte */ - dev->eeprom[0x1C] = 0x10; /* PnP version */ - dev->eeprom[0x1D] = 0x10; /* Vendor version */ + /* TAG: Plug and Play Version Number. */ + dev->eeprom[0x1B] = 0x0A; /* Item byte */ + dev->eeprom[0x1C] = 0x10; /* PnP version */ + dev->eeprom[0x1D] = 0x10; /* Vendor version */ - /* TAG: ANSI Identifier String */ - dev->eeprom[0x1E] = 0x82; /* Item byte */ - dev->eeprom[0x1F] = 0x22; /* Length bits 7-0 */ - dev->eeprom[0x20] = 0x00; /* Length bits 15-8 */ - memcpy(&dev->eeprom[0x21], ansi_id, 0x22); /* Identifier string */ + /* TAG: ANSI Identifier String. */ + dev->eeprom[0x1E] = 0x82; /* Item byte */ + dev->eeprom[0x1F] = 0x22; /* Length bits 7-0 */ + dev->eeprom[0x20] = 0x00; /* Length bits 15-8 */ + memcpy(&dev->eeprom[0x21], ansi_id, 0x22); - /* TAG: Logical Device ID */ - dev->eeprom[0x43] = 0x16; /* Item byte */ - dev->eeprom[0x44] = 0x4A; /* Logical device ID0 */ - dev->eeprom[0x45] = 0x8C; /* Logical device ID1 */ - dev->eeprom[0x46] = 0x80; /* Logical device ID2 */ - dev->eeprom[0x47] = 0x19; /* Logical device ID3 */ - dev->eeprom[0x48] = 0x02; /* Flag 0 (02 = BROM is disabled) */ - dev->eeprom[0x49] = 0x00; /* Flag 1 */ + /* TAG: Logical Device ID. */ + dev->eeprom[0x43] = 0x16; /* Item byte */ + dev->eeprom[0x44] = 0x4A; /* Logical device ID0 */ + dev->eeprom[0x45] = 0x8C; /* Logical device ID1 */ + dev->eeprom[0x46] = 0x80; /* Logical device ID2 */ + dev->eeprom[0x47] = 0x19; /* Logical device ID3 */ + dev->eeprom[0x48] = 0x02; /* Flag0 (02=BROM/disabled) */ + dev->eeprom[0x49] = 0x00; /* Flag 1 */ - /* TAG: Compatible Device ID (NE2000) */ - dev->eeprom[0x4A] = 0x1C; /* Item byte */ - dev->eeprom[0x4B] = 0x41; /* Compatible ID0 */ - dev->eeprom[0x4C] = 0xD0; /* Compatible ID1 */ - dev->eeprom[0x4D] = 0x80; /* Compatible ID2 */ - dev->eeprom[0x4E] = 0xD6; /* Compatible ID3 */ + /* TAG: Compatible Device ID (NE2000) */ + dev->eeprom[0x4A] = 0x1C; /* Item byte */ + dev->eeprom[0x4B] = 0x41; /* Compatible ID0 */ + dev->eeprom[0x4C] = 0xD0; /* Compatible ID1 */ + dev->eeprom[0x4D] = 0x80; /* Compatible ID2 */ + dev->eeprom[0x4E] = 0xD6; /* Compatible ID3 */ - /* TAG: I/O Format */ - dev->eeprom[0x4F] = 0x47; /* Item byte */ - dev->eeprom[0x50] = 0x00; /* I/O information */ - dev->eeprom[0x51] = 0x20; /* Min. I/O base bits 7-0 */ - dev->eeprom[0x52] = 0x02; /* Min. I/O base bits 15-8 */ - dev->eeprom[0x53] = 0x80; /* Max. I/O base bits 7-0 */ - dev->eeprom[0x54] = 0x03; /* Max. I/O base bits 15-8 */ - dev->eeprom[0x55] = 0x20; /* Base alignment */ - dev->eeprom[0x56] = 0x20; /* Range length */ + /* TAG: I/O Format */ + dev->eeprom[0x4F] = 0x47; /* Item byte */ + dev->eeprom[0x50] = 0x00; /* I/O information */ + dev->eeprom[0x51] = 0x20; /* Min. I/O base bits 7-0 */ + dev->eeprom[0x52] = 0x02; /* Min. I/O base bits 15-8 */ + dev->eeprom[0x53] = 0x80; /* Max. I/O base bits 7-0 */ + dev->eeprom[0x54] = 0x03; /* Max. I/O base bits 15-8 */ + dev->eeprom[0x55] = 0x20; /* Base alignment */ + dev->eeprom[0x56] = 0x20; /* Range length */ - /* TAG: IRQ Format */ - dev->eeprom[0x57] = 0x23; /* Item byte */ - dev->eeprom[0x58] = 0x38; /* IRQ mask bits 7-0 */ - dev->eeprom[0x59] = 0x9E; /* IRQ mask bits 15-8 */ - dev->eeprom[0x5A] = 0x01; /* IRQ information */ + /* TAG: IRQ Format. */ + dev->eeprom[0x57] = 0x23; /* Item byte */ + dev->eeprom[0x58] = 0x38; /* IRQ mask bits 7-0 */ + dev->eeprom[0x59] = 0x9E; /* IRQ mask bits 15-8 */ + dev->eeprom[0x5A] = 0x01; /* IRQ information */ - /* TAG: END Tag */ - dev->eeprom[0x5B] = 0x79; /* Item byte */ - for (c = 0x1B; c < 0x5C; c++) /* Checksum (2's complement) */ + /* TAG: END Tag */ + dev->eeprom[0x5B] = 0x79; /* Item byte */ + for (c = 0x1b; c < 0x5c; c++) /* Checksum (2's compl) */ dev->eeprom[0x5C] += dev->eeprom[c]; dev->eeprom[0x5C] = -dev->eeprom[0x5C]; @@ -2620,7 +2641,7 @@ nic_close(void *priv) } -static device_config_t ne1000_config[] = +static const device_config_t ne1000_config[] = { { "base", "Address", CONFIG_HEX16, "", 0x300, @@ -2679,7 +2700,7 @@ static device_config_t ne1000_config[] = } }; -static device_config_t ne2000_config[] = +static const device_config_t ne2000_config[] = { { "base", "Address", CONFIG_HEX16, "", 0x300, @@ -2764,7 +2785,7 @@ static device_config_t ne2000_config[] = } }; -static device_config_t rtl8019as_config[] = +static const device_config_t rtl8019as_config[] = { { "mac", "MAC Address", CONFIG_MAC, "", -1 @@ -2774,7 +2795,7 @@ static device_config_t rtl8019as_config[] = } }; -static device_config_t rtl8029as_config[] = +static const device_config_t rtl8029as_config[] = { { "bios", "Enable BIOS", CONFIG_BINARY, "", 0 @@ -2788,7 +2809,7 @@ static device_config_t rtl8029as_config[] = }; -device_t ne1000_device = { +const device_t ne1000_device = { "Novell NE1000", DEVICE_ISA, NE2K_NE1000, @@ -2797,7 +2818,7 @@ device_t ne1000_device = { ne1000_config }; -device_t ne2000_device = { +const device_t ne2000_device = { "Novell NE2000", DEVICE_ISA | DEVICE_AT, NE2K_NE2000, @@ -2806,7 +2827,7 @@ device_t ne2000_device = { ne2000_config }; -device_t rtl8019as_device = { +const device_t rtl8019as_device = { "Realtek RTL8019AS", DEVICE_ISA | DEVICE_AT, NE2K_RTL8019AS, @@ -2815,7 +2836,7 @@ device_t rtl8019as_device = { rtl8019as_config }; -device_t rtl8029as_device = { +const device_t rtl8029as_device = { "Realtek RTL8029AS", DEVICE_PCI, NE2K_RTL8029AS, diff --git a/src/network/net_ne2000.h b/src/network/net_ne2000.h index b623c10d9..0453a3ba5 100644 --- a/src/network/net_ne2000.h +++ b/src/network/net_ne2000.h @@ -1,34 +1,54 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * Definitions for the NE2000 ethernet controller. * - * Version: @(#)net_ne2000.h 1.0.5 2018/01/28 + * Version: @(#)net_ne2000.h 1.0.2 2018/03/15 * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, + * + * Copyright 2017,2018 Fred N. van Kempen. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. */ #ifndef NET_NE2000_H # define NET_NE2000_H enum { - NE2K_NONE = 0, - NE2K_NE1000, /* 8-bit ISA NE1000 */ - NE2K_NE2000, /* 16-bit ISA NE2000 */ - NE2K_RTL8019AS, /* 16-bit ISA PnP Realtek 8019AS */ - NE2K_RTL8029AS /* 32-bit PCI Realtek 8029AS */ + NE2K_NONE = 0, + NE2K_NE1000, /* 8-bit ISA NE1000 */ + NE2K_NE2000, /* 16-bit ISA NE2000 */ + NE2K_RTL8019AS, /* 16-bit ISA PnP Realtek 8019AS */ + NE2K_RTL8029AS /* 32-bit PCI Realtek 8029AS */ }; -extern device_t ne1000_device; -extern device_t ne2000_device; -extern device_t rtl8019as_device; -extern device_t rtl8029as_device; +extern const device_t ne1000_device; +extern const device_t ne2000_device; +extern const device_t rtl8019as_device; +extern const device_t rtl8029as_device; #endif /*NET_NE2000_H*/ diff --git a/src/network/net_pcap.c b/src/network/net_pcap.c index d78c716b2..a619868b6 100644 --- a/src/network/net_pcap.c +++ b/src/network/net_pcap.c @@ -1,25 +1,55 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * Handle WinPcap library processing. * - * Version: @(#)net_pcap.c 1.0.14 2018/03/18 + * Version: @(#)net_pcap.c 1.0.3 2018/03/15 * * Author: Fred N. van Kempen, * * Copyright 2017,2018 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above 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. + * + * 3. Neither the name of the copyright holder 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 + * HOLDER 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 #include #include #include #include -#include +#include #include "../86box.h" #include "../config.h" #include "../device.h" @@ -31,7 +61,7 @@ static volatile void *pcap_handle; /* handle to WinPcap DLL */ static volatile pcap_t *pcap; /* handle to WinPcap library */ static volatile thread_t *poll_tid; -static netcard_t *poll_card; /* netcard linked to us */ +static const netcard_t *poll_card; /* netcard linked to us */ static event_t *poll_state; @@ -204,9 +234,7 @@ net_pcap_init(void) pclog("PCAP: initializing, %s\n", errbuf); /* Get the value of our capture interface. */ - if ((network_pcap == NULL) || - (network_pcap[0] == '\0') || - !strcmp(network_pcap, "none")) { + if ((network_host[0] == '\0') || !strcmp(network_host, "none")) { pclog("PCAP: no interface configured!\n"); return(-1); } @@ -274,22 +302,22 @@ net_pcap_close(void) * tries to attach to the network module. */ int -net_pcap_reset(netcard_t *card, uint8_t *mac) +net_pcap_reset(const netcard_t *card, uint8_t *mac) { char errbuf[PCAP_ERRBUF_SIZE]; char filter_exp[255]; struct bpf_program fp; /* Open a PCAP live channel. */ - if ((pcap = f_pcap_open_live(network_pcap, /* interface name */ + if ((pcap = f_pcap_open_live(network_host, /* interface name */ 1518, /* max packet size */ 1, /* promiscuous mode? */ 10, /* timeout in msec */ errbuf)) == NULL) { /* error buffer */ - pclog(" Unable to open device: %s!\n", network_pcap); + pclog(" Unable to open device: %s!\n", network_host); return(-1); } - pclog("PCAP: interface: %s\n", network_pcap); + pclog("PCAP: interface: %s\n", network_host); /* Create a MAC address based packet filter. */ pclog("PCAP: installing filter for MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", diff --git a/src/network/net_slirp.c b/src/network/net_slirp.c index a1f336aa8..4fe2d4e98 100644 --- a/src/network/net_slirp.c +++ b/src/network/net_slirp.c @@ -1,18 +1,48 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * Handle SLiRP library processing. * - * Version: @(#)net_slirp.c 1.0.14 2018/03/18 + * Version: @(#)net_slirp.c 1.0.2 2018/03/15 * * Author: Fred N. van Kempen, * * Copyright 2017,2018 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above 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. + * + * 3. Neither the name of the copyright holder 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 + * HOLDER 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 #include @@ -30,7 +60,7 @@ static volatile queueADT slirpq; /* SLiRP library handle */ static volatile thread_t *poll_tid; -static netcard_t *poll_card; /* netcard attached to us */ +static const netcard_t *poll_card; /* netcard attached to us */ static event_t *poll_state; @@ -143,7 +173,7 @@ net_slirp_init(void) /* Initialize SLiRP for use. */ int -net_slirp_reset(netcard_t *card, uint8_t *mac) +net_slirp_reset(const netcard_t *card, uint8_t *mac) { /* Save the callback info. */ poll_card = card; diff --git a/src/network/network.c b/src/network/network.c index 930b9eea0..9a4bcd76a 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -1,10 +1,10 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * Implementation of the network module. * @@ -12,17 +12,50 @@ * it should be malloc'ed and then linked to the NETCARD def. * Will be done later. * - * Version: @(#)network.c 1.0.22 2018/03/18 + * Version: @(#)network.c 1.0.3 2018/03/15 * * Author: Fred N. van Kempen, * * Copyright 2017,2018 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above 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. + * + * 3. Neither the name of the copyright holder 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 + * HOLDER 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 #include #include #include #include +#ifdef WALTJE +# include +#endif #include "../86box.h" #include "../device.h" #include "../plat.h" @@ -32,18 +65,18 @@ static netcard_t net_cards[] = { - { "None", "none", NULL, - NULL, NULL }, + { "None", "none", NULL, + NULL }, { "[ISA] Novell NE1000", "ne1k", &ne1000_device, - NULL, NULL }, + NULL }, { "[ISA] Novell NE2000", "ne2k", &ne2000_device, - NULL, NULL }, + NULL }, { "[ISA] Realtek RTL8019AS", "ne2kpnp", &rtl8019as_device, - NULL, NULL }, + NULL }, { "[PCI] Realtek RTL8029AS", "ne2kpci", &rtl8029as_device, - NULL, NULL }, - { "", "", NULL, - NULL, NULL } + NULL }, + { "", "", NULL, + NULL } }; @@ -51,7 +84,7 @@ static netcard_t net_cards[] = { int network_type; int network_ndev; int network_card; -char network_pcap[512]; +char network_host[512]; netdev_t network_devs[32]; #ifdef ENABLE_NIC_LOG int nic_do_log = ENABLE_NIC_LOG; @@ -70,6 +103,87 @@ static struct { } poll_data; +#ifdef WALTJE +# define is_print(c) (isalnum((int)(c)) || ((c) == ' ')) + + +#if 0 +/* Dump a buffer in hex, standard output. */ +static void +hexdump(uint8_t *bufp, int len) +{ + char asci[20]; + uint8_t c; + int addr; + + addr = 0; + while (len-- > 0) { + c = bufp[addr]; + if ((addr % 16) == 0) { + printf("%06X %02X", addr, c); + } else { + printf(" %02X", c); + } + asci[(addr & 15)] = (char)((is_print(c) ? c : '.') & 0xff); + if ((++addr % 16) == 0) { + asci[16] = '\0'; + printf(" | %s |\n", asci); + } + } + + if (addr % 16) { + while (addr % 16) { + printf(" "); + asci[(addr & 15)] = ' '; + addr++; + } + asci[16] = '\0'; + printf(" | %s |\n", asci); + } +} +#endif + + +/* Dump a buffer in hex to output buffer. */ +static void +hexdump_p(char *ptr, uint8_t *bufp, int len) +{ + char asci[20]; + uint8_t c; + int addr; + + addr = 0; + while (len-- > 0) { + c = bufp[addr]; + if ((addr % 16) == 0) { + sprintf(ptr, "%06X %02X", addr, c); + } else { + sprintf(ptr, " %02X", c); + } + ptr += strlen(ptr); + asci[(addr & 15)] = (char)((is_print(c) ? c : '.') & 0xff); + if ((++addr % 16) == 0) { + asci[16] = '\0'; + sprintf(ptr, " | %s |\n", asci); + ptr += strlen(ptr); + } + } + + if (addr % 16) { + while (addr % 16) { + sprintf(ptr, " "); + ptr += strlen(ptr); + asci[(addr & 15)] = ' '; + addr++; + } + asci[16] = '\0'; + sprintf(ptr, " | %s |\n", asci); + ptr += strlen(ptr); + } +} +#endif + + void network_wait(uint8_t wait) { @@ -99,7 +213,7 @@ network_busy(uint8_t set) thread_set_event(poll_data.wake_poll_thread); } - + void network_end(void) { @@ -214,7 +328,13 @@ network_reset(void) { int i = -1; - pclog("NETWORK: reset (type=%d, card=%d)\n", network_type, network_card); +#ifdef ENABLE_NIC_LOG + pclog("NETWORK: reset (type=%d, card=%d) debug=%d\n", + network_type, network_card, nic_do_log); +#else + pclog("NETWORK: reset (type=%d, card=%d)\n", + network_type, network_card); +#endif ui_sb_update_icon(SB_NETWORK, 0); /* Just in case.. */ @@ -223,7 +343,7 @@ network_reset(void) /* If no active card, we're done. */ if ((network_type==NET_TYPE_NONE) || (network_card==0)) return; - network_mutex = thread_create_mutex(L"86Box.NetMutex"); + network_mutex = thread_create_mutex(L"VARCem.NetMutex"); /* Initialize the platform module. */ switch(network_type) { @@ -269,6 +389,14 @@ network_tx(uint8_t *bufp, int len) { ui_sb_update_icon(SB_NETWORK, 1); +#ifdef WALTJE +{ + char temp[4096]; + hexdump_p(temp, bufp, len); + pclog("NETWORK: >> len=%d\n%s\n", len, temp); +} +#endif + switch(network_type) { case NET_TYPE_PCAP: net_pcap_in(bufp, len); @@ -289,7 +417,7 @@ network_dev_to_id(char *devname) int i = 0; for (i=0; i + * + * Copyright 2017,2018 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above 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. + * + * 3. Neither the name of the copyright holder 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 + * HOLDER 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 EMU_NETWORK_H # define EMU_NETWORK_H @@ -24,11 +56,11 @@ /* Supported network cards. */ enum { - NONE = 0, - NE1000, - NE2000, - RTL8019AS, - RTL8029AS + NONE = 0, + NE1000, + NE2000, + RTL8019AS, + RTL8029AS }; @@ -36,18 +68,17 @@ typedef void (*NETRXCB)(void *, uint8_t *, int); typedef struct { - const char *name; - const char *internal_name; - device_t *device; - void *priv; - int (*poll)(void *); - NETRXCB rx; - uint8_t *mac; + const char *name; + const char *internal_name; + const device_t *device; + void *priv; + int (*poll)(void *); + NETRXCB rx; } netcard_t; typedef struct { - char device[128]; - char description[128]; + char device[128]; + char description[128]; } netdev_t; @@ -57,9 +88,6 @@ extern "C" { /* Global variables. */ extern int nic_do_log; /* config */ -extern int network_card; /* config */ -extern int network_type; /* config */ -extern char network_pcap[512]; /* config */ extern int network_ndev; extern netdev_t network_devs[32]; @@ -79,12 +107,12 @@ extern void network_tx(uint8_t *, int); extern int net_pcap_prepare(netdev_t *); extern int net_pcap_init(void); -extern int net_pcap_reset(netcard_t *, uint8_t *); +extern int net_pcap_reset(const netcard_t *, uint8_t *); extern void net_pcap_close(void); extern void net_pcap_in(uint8_t *, int); extern int net_slirp_init(void); -extern int net_slirp_reset(netcard_t *, uint8_t *); +extern int net_slirp_reset(const netcard_t *, uint8_t *); extern void net_slirp_close(void); extern void net_slirp_in(uint8_t *, int); @@ -94,7 +122,7 @@ extern char *network_card_getname(int); extern int network_card_has_config(int); extern char *network_card_get_internal_name(int); extern int network_card_get_from_internal_name(char *); -extern device_t *network_card_getdevice(int); +extern const device_t *network_card_getdevice(int); #ifdef __cplusplus } diff --git a/src/network/pcap_if.c b/src/network/pcap_if.c index 4d2c848ef..439dbfa94 100644 --- a/src/network/pcap_if.c +++ b/src/network/pcap_if.c @@ -1,20 +1,50 @@ /* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the 86Box distribution. + * This file is part of the VARCem Project. * * Simple program to show usage of (Win)Pcap. * * Based on the "libpcap" examples. * - * Version: @(#)pcap_if.c 1.0.7 2017/10/28 + * Version: @(#)pcap_if.c 1.0.10 2018/03/10 * * Author: Fred N. van Kempen, * - * Copyright 2017 Fred N. van Kempen. + * Copyright 2017,2018 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above 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. + * + * 3. Neither the name of the copyright holder 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 + * HOLDER 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 #include @@ -22,7 +52,7 @@ #include #include #include -#include +#include #include #include "../86box.h" #include "../plat.h" diff --git a/src/network/slirp/debug.c b/src/network/slirp/debug.c index 9e727732a..eef2c7de1 100644 --- a/src/network/slirp/debug.c +++ b/src/network/slirp/debug.c @@ -19,7 +19,9 @@ int dostats = 0; #endif int slirp_debug = 0; +#ifndef _MSC_VER extern char *strerror _P((int)); +#endif /* Carry over one item from main.c so that the tty's restored. * Only done when the tty being used is /dev/tty --RedWolf */ diff --git a/src/nvr_ps2.c b/src/nvr_ps2.c index ce1cdfe2a..ff887ca2c 100644 --- a/src/nvr_ps2.c +++ b/src/nvr_ps2.c @@ -8,7 +8,7 @@ * * Handling of the PS/2 series CMOS devices. * - * Version: @(#)nvr_ps2.c 1.0.4 2018/03/13 + * Version: @(#)nvr_ps2.c 1.0.5 2018/03/18 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -103,7 +103,7 @@ ps2_nvr_write(uint16_t port, uint8_t val, void *priv) static void * -ps2_nvr_init(device_t *info) +ps2_nvr_init(const device_t *info) { ps2_nvr_t *nvr; FILE *f = NULL; @@ -159,7 +159,7 @@ ps2_nvr_close(void *priv) } -device_t ps2_nvr_device = { +const device_t ps2_nvr_device = { "PS/2 Secondary NVRAM", 0, 0, ps2_nvr_init, ps2_nvr_close, NULL, diff --git a/src/nvr_ps2.h b/src/nvr_ps2.h index 802c27f4a..57293f212 100644 --- a/src/nvr_ps2.h +++ b/src/nvr_ps2.h @@ -8,7 +8,7 @@ * * Definitions for the PS/2 cmos/nvr device. * - * Version: @(#)nvr_ps2.h 1.0.1 2018/02/14 + * Version: @(#)nvr_ps2.h 1.0.2 2018/03/18 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -38,7 +38,7 @@ # define EMU_NVRPS2_H -extern device_t ps2_nvr_device; +extern const device_t ps2_nvr_device; #endif /*EMU_NVRPS2_H*/ diff --git a/src/pc.c b/src/pc.c index b19155990..fc4b205d9 100644 --- a/src/pc.c +++ b/src/pc.c @@ -8,7 +8,7 @@ * * Main emulator module where most things are controlled. * - * Version: @(#)pc.c 1.0.64 2018/03/15 + * Version: @(#)pc.c 1.0.65 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -75,7 +75,6 @@ #include "video/video.h" #include "ui.h" #include "plat.h" -#include "plat_joystick.h" #include "plat_midi.h" diff --git a/src/plat_joystick.h b/src/plat_joystick.h deleted file mode 100644 index d1287f769..000000000 --- a/src/plat_joystick.h +++ /dev/null @@ -1,65 +0,0 @@ -#define MAX_PLAT_JOYSTICKS 8 -#define MAX_JOYSTICKS 4 - -#define POV_X 0x80000000 -#define POV_Y 0x40000000 - - -typedef struct { - char name[64]; - - int a[8]; - int b[32]; - int p[4]; - - struct { - char name[32]; - int id; - } axis[8]; - - struct { - char name[32]; - int id; - } button[32]; - - struct { - char name[32]; - int id; - } pov[4]; - - int nr_axes; - int nr_buttons; - int nr_povs; -} plat_joystick_t; - -typedef struct { - int axis[8]; - int button[32]; - int pov[4]; - - int plat_joystick_nr; - int axis_mapping[8]; - int button_mapping[32]; - int pov_mapping[4][2]; -} joystick_t; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; -extern joystick_t joystick_state[MAX_JOYSTICKS]; -extern int joysticks_present; - - -#define JOYSTICK_PRESENT(n) (joystick_state[n].plat_joystick_nr != 0) - - -extern void joystick_init(void); -extern void joystick_close(void); -extern void joystick_process(void); - -#ifdef __cplusplus -} -#endif diff --git a/src/scsi/scsi.c b/src/scsi/scsi.c index fa4033ec5..e75993d82 100644 --- a/src/scsi/scsi.c +++ b/src/scsi/scsi.c @@ -8,7 +8,7 @@ * * Handling of the SCSI controllers. * - * Version: @(#)scsi.c 1.0.16 2018/03/06 + * Version: @(#)scsi.c 1.0.17 2018/03/18 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -56,10 +56,10 @@ static volatile mutex_t *scsiMutex; -typedef struct { - const char *name; - const char *internal_name; - device_t *device; +typedef const struct { + const char *name; + const char *internal_name; + const device_t *device; void (*reset)(void *p); } SCSI_CARD; @@ -102,7 +102,7 @@ char *scsi_card_getname(int card) } -device_t *scsi_card_getdevice(int card) +const device_t *scsi_card_getdevice(int card) { return(scsi_cards[card].device); } diff --git a/src/scsi/scsi.h b/src/scsi/scsi.h index 898596f68..0a8239cc6 100644 --- a/src/scsi/scsi.h +++ b/src/scsi/scsi.h @@ -8,7 +8,7 @@ * * SCSI controller handler header. * - * Version: @(#)scsi_h 1.0.13 2018/02/07 + * Version: @(#)scsi_h 1.0.14 2018/03/18 * * Authors: TheCollector1995, * Miran Grca, @@ -298,7 +298,7 @@ extern int scsi_card_current; extern int scsi_card_available(int card); extern char *scsi_card_getname(int card); #ifdef EMU_DEVICE_H -extern device_t *scsi_card_getdevice(int card); +extern const device_t *scsi_card_getdevice(int card); #endif extern int scsi_card_has_config(int card); extern char *scsi_card_get_internal_name(int card); diff --git a/src/scsi/scsi_aha154x.c b/src/scsi/scsi_aha154x.c index efc9a5fcb..efb34ebf8 100644 --- a/src/scsi/scsi_aha154x.c +++ b/src/scsi/scsi_aha154x.c @@ -10,7 +10,7 @@ * made by Adaptec, Inc. These controllers were designed for * the ISA bus. * - * Version: @(#)scsi_aha154x.c 1.0.39 2018/03/07 + * Version: @(#)scsi_aha154x.c 1.0.40 2018/03/18 * * Authors: Fred N. van Kempen, * Original Buslogic version by SA1988 and Miran Grca. @@ -733,7 +733,7 @@ aha_setnvr(x54x_t *dev) /* General initialization routine for all boards. */ static void * -aha_init(device_t *info) +aha_init(const device_t *info) { x54x_t *dev; @@ -878,7 +878,7 @@ aha_init(device_t *info) } -static device_config_t aha_154xb_config[] = { +static const device_config_t aha_154xb_config[] = { { "base", "Address", CONFIG_HEX16, "", 0x334, { @@ -1009,7 +1009,7 @@ static device_config_t aha_154xb_config[] = { }; -static device_config_t aha_154x_config[] = { +static const device_config_t aha_154x_config[] = { { "base", "Address", CONFIG_HEX16, "", 0x334, { @@ -1108,7 +1108,7 @@ static device_config_t aha_154x_config[] = { }; -device_t aha1540b_device = { +const device_t aha1540b_device = { "Adaptec AHA-1540B", DEVICE_ISA | DEVICE_AT, AHA_154xB, @@ -1117,7 +1117,7 @@ device_t aha1540b_device = { aha_154xb_config }; -device_t aha1542c_device = { +const device_t aha1542c_device = { "Adaptec AHA-1542C", DEVICE_ISA | DEVICE_AT, AHA_154xC, @@ -1126,7 +1126,7 @@ device_t aha1542c_device = { aha_154x_config }; -device_t aha1542cf_device = { +const device_t aha1542cf_device = { "Adaptec AHA-1542CF", DEVICE_ISA | DEVICE_AT, AHA_154xCF, @@ -1135,7 +1135,7 @@ device_t aha1542cf_device = { aha_154x_config }; -device_t aha1640_device = { +const device_t aha1640_device = { "Adaptec AHA-1640", DEVICE_MCA, AHA_1640, diff --git a/src/scsi/scsi_aha154x.h b/src/scsi/scsi_aha154x.h index 12c39b375..73eb10b89 100644 --- a/src/scsi/scsi_aha154x.h +++ b/src/scsi/scsi_aha154x.h @@ -2,10 +2,10 @@ # define SCSI_AHA154X_H -extern device_t aha1540b_device; -extern device_t aha1542c_device; -extern device_t aha1542cf_device; -extern device_t aha1640_device; +extern const device_t aha1540b_device; +extern const device_t aha1542c_device; +extern const device_t aha1542cf_device; +extern const device_t aha1640_device; extern void aha_device_reset(void *p); diff --git a/src/scsi/scsi_buslogic.c b/src/scsi/scsi_buslogic.c index cd95e823b..e796ec23e 100644 --- a/src/scsi/scsi_buslogic.c +++ b/src/scsi/scsi_buslogic.c @@ -11,7 +11,7 @@ * 1 - BT-545S ISA; * 2 - BT-958D PCI * - * Version: @(#)scsi_buslogic.c 1.0.35 2018/03/07 + * Version: @(#)scsi_buslogic.c 1.0.36 2018/03/18 * * Authors: TheCollector1995, * Miran Grca, @@ -1446,7 +1446,7 @@ BuslogicDeviceReset(void *p) static void * -buslogic_init(device_t *info) +buslogic_init(const device_t *info) { x54x_t *dev; wchar_t *bios_rom_name; @@ -1660,7 +1660,7 @@ buslogic_init(device_t *info) } -static device_config_t BT_ISA_Config[] = { +static const device_config_t BT_ISA_Config[] = { { "base", "Address", CONFIG_HEX16, "", 0x334, { @@ -1756,7 +1756,7 @@ static device_config_t BT_ISA_Config[] = { }; -static device_config_t BT958D_Config[] = { +static const device_config_t BT958D_Config[] = { { "bios", "Enable BIOS", CONFIG_BINARY, "", 0 }, @@ -1766,7 +1766,7 @@ static device_config_t BT958D_Config[] = { }; -device_t buslogic_device = { +const device_t buslogic_device = { "Buslogic BT-542BH ISA", DEVICE_ISA | DEVICE_AT, CHIP_BUSLOGIC_ISA_542, @@ -1775,7 +1775,7 @@ device_t buslogic_device = { BT_ISA_Config }; -device_t buslogic_545s_device = { +const device_t buslogic_545s_device = { "Buslogic BT-545S ISA", DEVICE_ISA | DEVICE_AT, CHIP_BUSLOGIC_ISA, @@ -1784,7 +1784,7 @@ device_t buslogic_545s_device = { BT_ISA_Config }; -device_t buslogic_640a_device = { +const device_t buslogic_640a_device = { "Buslogic BT-640A MCA", DEVICE_MCA, CHIP_BUSLOGIC_MCA, @@ -1793,7 +1793,7 @@ device_t buslogic_640a_device = { NULL }; -device_t buslogic_445s_device = { +const device_t buslogic_445s_device = { "Buslogic BT-445S ISA", DEVICE_VLB, CHIP_BUSLOGIC_VLB, @@ -1802,7 +1802,7 @@ device_t buslogic_445s_device = { BT_ISA_Config }; -device_t buslogic_pci_device = { +const device_t buslogic_pci_device = { "Buslogic BT-958D PCI", DEVICE_PCI, CHIP_BUSLOGIC_PCI, diff --git a/src/scsi/scsi_buslogic.h b/src/scsi/scsi_buslogic.h index 4383ad640..83ce417d9 100644 --- a/src/scsi/scsi_buslogic.h +++ b/src/scsi/scsi_buslogic.h @@ -7,24 +7,24 @@ * Emulation of BusLogic BT-542B ISA and BT-958D PCI SCSI * controllers. * - * Version: @(#)scsi_buslogic.h 1.0.2 2017/10/14 + * Version: @(#)scsi_buslogic.h 1.0.3 2018/03/18 * * Authors: TheCollector1995, * Miran Grca, * Fred N. van Kempen, - * Copyright 2016,2017 Miran Grca. - * Copyright 2017 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. */ #ifndef SCSI_BUSLOGIC_H # define SCSI_BUSLOGIC_H -extern device_t buslogic_device; -extern device_t buslogic_545s_device; -extern device_t buslogic_640a_device; -extern device_t buslogic_445s_device; -extern device_t buslogic_pci_device; +extern const device_t buslogic_device; +extern const device_t buslogic_545s_device; +extern const device_t buslogic_640a_device; +extern const device_t buslogic_445s_device; +extern const device_t buslogic_pci_device; extern void BuslogicDeviceReset(void *p); diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c index c5c374935..b4121ed36 100644 --- a/src/scsi/scsi_disk.c +++ b/src/scsi/scsi_disk.c @@ -6,7 +6,7 @@ * * Emulation of SCSI fixed and removable disks. * - * Version: @(#)scsi_disk.c 1.0.17 2018/03/07 + * Version: @(#)scsi_disk.c 1.0.18 2018/03/18 * * Author: Miran Grca, * @@ -78,7 +78,7 @@ uint8_t scsi_hard_disks[16][8] = { /* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ -uint8_t scsi_hd_command_flags[0x100] = { +const uint8_t scsi_hd_command_flags[0x100] = { IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ 0, diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index 97440394f..fd88997c4 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -9,7 +9,7 @@ * Implementation of the NCR 5380 series of SCSI Host Adapters * made by NCR. These controllers were designed for the ISA bus. * - * Version: @(#)scsi_ncr5380.c 1.0.11 2018/03/07 + * Version: @(#)scsi_ncr5380.c 1.0.12 2018/03/18 * * Authors: Sarah Walker, * TheCollector1995, @@ -825,7 +825,7 @@ scsiat_out(uint16_t port, uint8_t val, void *priv) static void * -ncr_init(device_t *info) +ncr_init(const device_t *info) { char temp[128]; ncr_t *scsi; @@ -948,7 +948,7 @@ scsiat_available(void) } -static device_config_t scsiat_config[] = { +static const device_config_t scsiat_config[] = { { "base", "Address", CONFIG_HEX16, "", 0x0310, { @@ -1045,7 +1045,7 @@ static device_config_t scsiat_config[] = { }; -device_t scsi_lcs6821n_device = +const device_t scsi_lcs6821n_device = { "Longshine LCS-6821N", DEVICE_ISA, @@ -1056,7 +1056,7 @@ device_t scsi_lcs6821n_device = NULL }; -device_t scsi_rt1000b_device = +const device_t scsi_rt1000b_device = { "Ranco RT1000B", DEVICE_ISA, @@ -1067,7 +1067,7 @@ device_t scsi_rt1000b_device = NULL }; -device_t scsi_t130b_device = +const device_t scsi_t130b_device = { "Trantor T130B", DEVICE_ISA, @@ -1078,7 +1078,7 @@ device_t scsi_t130b_device = NULL }; -device_t scsi_scsiat_device = +const device_t scsi_scsiat_device = { "Sumo SCSI-AT", DEVICE_ISA, diff --git a/src/scsi/scsi_ncr5380.h b/src/scsi/scsi_ncr5380.h index 6bafa8751..55b16f654 100644 --- a/src/scsi/scsi_ncr5380.h +++ b/src/scsi/scsi_ncr5380.h @@ -10,7 +10,7 @@ * made by NCR. These controllers were designed for * the ISA bus. * - * Version: @(#)scsi_ncr5380.c 1.0.1 2017/12/16 + * Version: @(#)scsi_ncr5380.c 1.0.2 2018/03/18 * * Authors: Sarah Walker, * TheCollector1995, @@ -18,16 +18,16 @@ * * Copyright 2017-2018 Sarah Walker. * Copyright 2017-2018 TheCollector1995. - * Copyright 2018 Fred N. van Kempen. + * Copyright 2017,2018 Fred N. van Kempen. */ #ifndef SCSI_NCR5380_H # define SCSI_NCR5380_H -extern device_t scsi_lcs6821n_device; -extern device_t scsi_rt1000b_device; -extern device_t scsi_t130b_device; -extern device_t scsi_scsiat_device; +extern const device_t scsi_lcs6821n_device; +extern const device_t scsi_rt1000b_device; +extern const device_t scsi_t130b_device; +extern const device_t scsi_scsiat_device; #endif /*SCSI_NCR5380_H*/ diff --git a/src/scsi/scsi_ncr53c810.c b/src/scsi/scsi_ncr53c810.c index 04b4e9e40..0dcb1fced 100644 --- a/src/scsi/scsi_ncr53c810.c +++ b/src/scsi/scsi_ncr53c810.c @@ -10,7 +10,7 @@ * NCR and later Symbios and LSI. This controller was designed * for the PCI bus. * - * Version: @(#)scsi_ncr53c810.c 1.0.9 2018/03/10 + * Version: @(#)scsi_ncr53c810.c 1.0.10 2018/03/18 * * Authors: Paul Brook (QEMU) * Artyom Tarasenko (QEMU) @@ -2134,7 +2134,7 @@ ncr53c810_pci_write(int func, int addr, uint8_t val, void *p) static void * -ncr53c810_init(device_t *info) +ncr53c810_init(const device_t *info) { ncr53c810_t *dev; @@ -2171,7 +2171,7 @@ ncr53c810_close(void *priv) } -device_t ncr53c810_pci_device = +const device_t ncr53c810_pci_device = { "NCR 53c810 (SCSI)", DEVICE_PCI, diff --git a/src/scsi/scsi_ncr53c810.h b/src/scsi/scsi_ncr53c810.h index 06286cda8..29666e935 100644 --- a/src/scsi/scsi_ncr53c810.h +++ b/src/scsi/scsi_ncr53c810.h @@ -10,22 +10,22 @@ * NCR and later Symbios and LSI. This controller was designed * for the PCI bus. * - * Version: @(#)scsi_ncr53c810.c 1.0.0 2017/12/10 + * Version: @(#)scsi_ncr53c810.c 1.0.1 2018/03/18 * * Authors: TheCollector1995, * Miran Grca, * Paul Brook (QEMU), * Artyom Tarasenko (QEMU), * - * Copyright 2006-2017 Paul Brook. - * Copyright 2009-2017 Artyom Tarasenko. - * Copyright 2017 Miran Grca. + * Copyright 2006-2018 Paul Brook. + * Copyright 2009-2018 Artyom Tarasenko. + * Copyright 2017,2018 Miran Grca. */ #ifndef SCSI_NCR5C3810_H # define SCSI_NCR53C810_H -extern device_t ncr53c810_pci_device; +extern const device_t ncr53c810_pci_device; #endif /*SCSI_NCR53C810_H*/ diff --git a/src/scsi/scsi_x54x.c b/src/scsi/scsi_x54x.c index 9ed018692..10f27249f 100644 --- a/src/scsi/scsi_x54x.c +++ b/src/scsi/scsi_x54x.c @@ -11,7 +11,7 @@ * series of SCSI Host Adapters made by Mylex. * These controllers were designed for various buses. * - * Version: @(#)scsi_x54x.c 1.0.19 2018/03/09 + * Version: @(#)scsi_x54x.c 1.0.20 2018/03/18 * * Authors: TheCollector1995, * Miran Grca, @@ -1891,7 +1891,7 @@ x54x_mem_disable(x54x_t *dev) /* General initialization routine for all boards. */ void * -x54x_init(device_t *info) +x54x_init(const device_t *info) { x54x_t *dev; diff --git a/src/scsi/scsi_x54x.h b/src/scsi/scsi_x54x.h index c9b0d190e..a35932169 100644 --- a/src/scsi/scsi_x54x.h +++ b/src/scsi/scsi_x54x.h @@ -11,7 +11,7 @@ * of SCSI Host Adapters made by Mylex. * These controllers were designed for various buses. * - * Version: @(#)scsi_x54x.h 1.0.5 2018/03/07 + * Version: @(#)scsi_x54x.h 1.0.6 2018/03/18 * * Authors: TheCollector1995, * Miran Grca, @@ -501,7 +501,7 @@ extern void x54x_mem_init(x54x_t *dev, uint32_t addr); extern void x54x_mem_enable(x54x_t *dev); extern void x54x_mem_set_addr(x54x_t *dev, uint32_t base); extern void x54x_mem_disable(x54x_t *dev); -extern void *x54x_init(device_t *info); +extern void *x54x_init(const device_t *info); extern void x54x_close(void *priv); extern void x54x_device_reset(void *priv); diff --git a/src/sound/midi.c b/src/sound/midi.c index bb0f5f5c7..d49eb6b29 100644 --- a/src/sound/midi.c +++ b/src/sound/midi.c @@ -25,10 +25,10 @@ typedef struct { const char *name; const char *internal_name; - device_t *device; + const device_t *device; } MIDI_DEVICE; -static MIDI_DEVICE devices[] = +static const MIDI_DEVICE devices[] = { {"None", "none", NULL}, #ifdef USE_FLUIDSYNTH @@ -57,7 +57,7 @@ char *midi_device_getname(int card) return (char *) devices[card].name; } -device_t *midi_device_getdevice(int card) +const device_t *midi_device_getdevice(int card) { return devices[card].device; } diff --git a/src/sound/midi.h b/src/sound/midi.h index 2b38c5a5f..6268a0e0c 100644 --- a/src/sound/midi.h +++ b/src/sound/midi.h @@ -8,7 +8,7 @@ extern int midi_device_current; int midi_device_available(int card); char *midi_device_getname(int card); #ifdef EMU_DEVICE_H -device_t *midi_device_getdevice(int card); +const device_t *midi_device_getdevice(int card); #endif int midi_device_has_config(int card); char *midi_device_get_internal_name(int card); diff --git a/src/sound/midi_fluidsynth.c b/src/sound/midi_fluidsynth.c index 71aebb31c..6fff49a1f 100644 --- a/src/sound/midi_fluidsynth.c +++ b/src/sound/midi_fluidsynth.c @@ -236,7 +236,7 @@ void fluidsynth_sysex(uint8_t* data, unsigned int len) f_fluid_synth_sysex(d->synth, (const char *) data, len, 0, 0, 0, 0); } -void* fluidsynth_init(device_t *info) +void* fluidsynth_init(const device_t *info) { fluidsynth_t* data = &fsdev; memset(data, 0, sizeof(fluidsynth_t)); @@ -390,7 +390,7 @@ void fluidsynth_close(void* p) /* pclog("fluidsynth closed\n"); */ } -static device_config_t fluidsynth_config[] = +static const device_config_t fluidsynth_config[] = { { .name = "sound_font", @@ -566,7 +566,7 @@ static device_config_t fluidsynth_config[] = } }; -device_t fluidsynth_device = +const device_t fluidsynth_device = { "FluidSynth", 0, diff --git a/src/sound/midi_fluidsynth.h b/src/sound/midi_fluidsynth.h index 1daeb29c0..518b1461d 100644 --- a/src/sound/midi_fluidsynth.h +++ b/src/sound/midi_fluidsynth.h @@ -1 +1 @@ -extern device_t fluidsynth_device; +extern const device_t fluidsynth_device; diff --git a/src/sound/midi_mt32.c b/src/sound/midi_mt32.c index a218df8bb..2687c5e10 100644 --- a/src/sound/midi_mt32.c +++ b/src/sound/midi_mt32.c @@ -222,12 +222,12 @@ void* mt32emu_init(wchar_t *control_rom, wchar_t *pcm_rom) return dev; } -void *mt32_init(device_t *info) +void *mt32_init(const device_t *info) { return mt32emu_init(L"roms/sound/mt32/mt32_control.rom", L"roms/sound/mt32/mt32_pcm.rom"); } -void *cm32l_init(device_t *info) +void *cm32l_init(const device_t *info) { return mt32emu_init(L"roms/sound/cm32l/cm32l_control.rom", L"roms/sound/cm32l/cm32l_pcm.rom"); } @@ -265,7 +265,7 @@ void mt32_close(void* p) /* pclog("mt32 closed\n"); */ } -static device_config_t mt32_config[] = +static const device_config_t mt32_config[] = { { .name = "output_gain", @@ -312,7 +312,7 @@ static device_config_t mt32_config[] = } }; -device_t mt32_device = +const device_t mt32_device = { "Roland MT-32 Emulation", 0, @@ -327,7 +327,7 @@ device_t mt32_device = mt32_config }; -device_t cm32l_device = +const device_t cm32l_device = { "Roland CM-32L Emulation", 0, diff --git a/src/sound/midi_mt32.h b/src/sound/midi_mt32.h index b881ea4cc..0aa012fa1 100644 --- a/src/sound/midi_mt32.h +++ b/src/sound/midi_mt32.h @@ -1,2 +1,2 @@ -extern device_t mt32_device; -extern device_t cm32l_device; +extern const device_t mt32_device; +extern const device_t cm32l_device; diff --git a/src/sound/midi_system.c b/src/sound/midi_system.c index 209889401..cbf1a469a 100644 --- a/src/sound/midi_system.c +++ b/src/sound/midi_system.c @@ -11,7 +11,7 @@ #include "midi_system.h" -void* system_midi_init(device_t *info) +void* system_midi_init(const device_t *info) { midi_device_t* dev = malloc(sizeof(midi_device_t)); memset(dev, 0, sizeof(midi_device_t)); @@ -39,7 +39,7 @@ int system_midi_available(void) return plat_midi_get_num_devs(); } -static device_config_t system_midi_config[] = +static const device_config_t system_midi_config[] = { { .name = "midi", @@ -52,7 +52,7 @@ static device_config_t system_midi_config[] = } }; -device_t system_midi_device = +const device_t system_midi_device = { SYSTEM_MIDI_NAME, 0, 0, diff --git a/src/sound/midi_system.h b/src/sound/midi_system.h index 7afbb4c45..b79bbf96f 100644 --- a/src/sound/midi_system.h +++ b/src/sound/midi_system.h @@ -1 +1 @@ -extern device_t system_midi_device; +extern const device_t system_midi_device; diff --git a/src/sound/snd_adlib.c b/src/sound/snd_adlib.c index 819fb12c0..cc9733bc5 100644 --- a/src/sound/snd_adlib.c +++ b/src/sound/snd_adlib.c @@ -63,7 +63,7 @@ void adlib_mca_write(int port, uint8_t val, void *p) adlib->pos_regs[port & 7] = val; } -void *adlib_init(device_t *info) +void *adlib_init(const device_t *info) { adlib_t *adlib = malloc(sizeof(adlib_t)); memset(adlib, 0, sizeof(adlib_t)); @@ -75,7 +75,7 @@ void *adlib_init(device_t *info) return adlib; } -void *adlib_mca_init(device_t *info) +void *adlib_mca_init(const device_t *info) { adlib_t *adlib = adlib_init(info); @@ -94,7 +94,7 @@ void adlib_close(void *p) free(adlib); } -device_t adlib_device = +const device_t adlib_device = { "AdLib", DEVICE_ISA, @@ -104,7 +104,7 @@ device_t adlib_device = NULL }; -device_t adlib_mca_device = +const device_t adlib_mca_device = { "AdLib (MCA)", DEVICE_MCA, diff --git a/src/sound/snd_adlib.h b/src/sound/snd_adlib.h index 1e2c363af..4a6a161ca 100644 --- a/src/sound/snd_adlib.h +++ b/src/sound/snd_adlib.h @@ -1,2 +1,2 @@ -extern device_t adlib_device; -extern device_t adlib_mca_device; +extern const device_t adlib_device; +extern const device_t adlib_mca_device; diff --git a/src/sound/snd_adlibgold.c b/src/sound/snd_adlibgold.c index 820dd020c..02e692491 100644 --- a/src/sound/snd_adlibgold.c +++ b/src/sound/snd_adlibgold.c @@ -754,7 +754,7 @@ static void adgold_get_buffer(int32_t *buffer, int len, void *p) } -void *adgold_init(device_t *info) +void *adgold_init(const device_t *info) { FILE *f; int c; @@ -827,7 +827,7 @@ void adgold_close(void *p) free(adgold); } -static device_config_t adgold_config[] = +static const device_config_t adgold_config[] = { { "surround", "Surround module", CONFIG_BINARY, "", 1 @@ -837,7 +837,7 @@ static device_config_t adgold_config[] = } }; -device_t adgold_device = +const device_t adgold_device = { "AdLib Gold", DEVICE_ISA, 0, diff --git a/src/sound/snd_adlibgold.h b/src/sound/snd_adlibgold.h index b952aaf03..daea1b490 100644 --- a/src/sound/snd_adlibgold.h +++ b/src/sound/snd_adlibgold.h @@ -1 +1 @@ -extern device_t adgold_device; +extern const device_t adgold_device; diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index 716327192..a7e0257a9 100644 --- a/src/sound/snd_audiopci.c +++ b/src/sound/snd_audiopci.c @@ -1300,7 +1300,7 @@ void es1371_add_status_info(char *s, int max_len, void *p) es1371_add_status_info_dac(es1371, s, max_len, 1); } -device_t es1371_device = +const device_t es1371_device = { "Ensoniq AudioPCI (ES1371)", DEVICE_PCI, diff --git a/src/sound/snd_audiopci.h b/src/sound/snd_audiopci.h index 5aff3d024..66600ed24 100644 --- a/src/sound/snd_audiopci.h +++ b/src/sound/snd_audiopci.h @@ -1 +1 @@ -extern device_t es1371_device; +extern const device_t es1371_device; diff --git a/src/sound/snd_cms.c b/src/sound/snd_cms.c index 69b0292a2..ce416650a 100644 --- a/src/sound/snd_cms.c +++ b/src/sound/snd_cms.c @@ -175,7 +175,7 @@ uint8_t cms_read(uint16_t addr, void *p) return 0xff; } -void *cms_init(device_t *info) +void *cms_init(const device_t *info) { cms_t *cms = malloc(sizeof(cms_t)); memset(cms, 0, sizeof(cms_t)); @@ -193,7 +193,7 @@ void cms_close(void *p) free(cms); } -device_t cms_device = +const device_t cms_device = { "Creative Music System / Game Blaster", 0, 0, diff --git a/src/sound/snd_cms.h b/src/sound/snd_cms.h index d5795cc0f..41b6d6059 100644 --- a/src/sound/snd_cms.h +++ b/src/sound/snd_cms.h @@ -1 +1 @@ -extern device_t cms_device; +extern const device_t cms_device; diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index e04b5b55b..d08b01da8 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -996,7 +996,7 @@ static void gus_get_buffer(int32_t *buffer, int len, void *p) } -void *gus_init(device_t *info) +void *gus_init(const device_t *info) { int c; double out = 1.0; @@ -1058,7 +1058,7 @@ void gus_speed_changed(void *p) gus->samp_latch = (int)(TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14])); } -device_t gus_device = +const device_t gus_device = { "Gravis UltraSound", 0, 0, diff --git a/src/sound/snd_gus.h b/src/sound/snd_gus.h index 6c124f9f8..89e8ea331 100644 --- a/src/sound/snd_gus.h +++ b/src/sound/snd_gus.h @@ -1 +1 @@ -extern device_t gus_device; +extern const device_t gus_device; diff --git a/src/sound/snd_mpu401.c b/src/sound/snd_mpu401.c index 9ae51c697..a885d72d3 100644 --- a/src/sound/snd_mpu401.c +++ b/src/sound/snd_mpu401.c @@ -8,16 +8,16 @@ * * Roland MPU-401 emulation. * - * Version: @(#)snd_mpu401.c 1.0.7 2017/11/23 + * Version: @(#)snd_mpu401.c 1.0.8 2018/03/18 * * Authors: Sarah Walker, * DOSBox Team, * Miran Grca, * TheCollector1995, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2008-2017 DOSBox Team. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2008-2018 DOSBox Team. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -895,7 +895,7 @@ mpu401_device_add(void) static void * -mpu401_standalone_init(device_t *info) +mpu401_standalone_init(const device_t *info) { mpu_t *mpu; @@ -918,7 +918,7 @@ mpu401_standalone_close(void *priv) } -static device_config_t mpu401_standalone_config[] = +static const device_config_t mpu401_standalone_config[] = { { "base", "MPU-401 Address", CONFIG_HEX16, "", 0x330, @@ -980,7 +980,7 @@ static device_config_t mpu401_standalone_config[] = }; -device_t mpu401_device = { +const device_t mpu401_device = { "MPU-401 (Standalone)", 0, 0, mpu401_standalone_init, mpu401_standalone_close, NULL, diff --git a/src/sound/snd_mpu401.h b/src/sound/snd_mpu401.h index 41c1e9240..0dda1b25a 100644 --- a/src/sound/snd_mpu401.h +++ b/src/sound/snd_mpu401.h @@ -8,16 +8,16 @@ * * Roland MPU-401 emulation. * - * Version: @(#)sound_mpu401.h 1.0.0 2017/05/30 + * Version: @(#)sound_mpu401.h 1.0.1 2018/03/18 * * Author: Sarah Walker, * DOSBox Team, * Miran Grca, * TheCollector1995, - * Copyright 2008-2017 Sarah Walker. - * Copyright 2008-2017 DOSBox Team. - * Copyright 2016-2017 Miran Grca. - * Copyright 2016-2017 TheCollector1995. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2008-2018 DOSBox Team. + * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2018 TheCollector1995. */ #define MPU401_VERSION 0x15 @@ -89,6 +89,6 @@ void mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode); extern int mpu401_standalone_enable; void mpu401_device_add(void); -device_t mpu401_device; +const device_t mpu401_device; void mpu401_uart_init(mpu_t *mpu, uint16_t addr); diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index bf900df50..5a0c4738d 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -722,7 +722,7 @@ void pas16_get_buffer(int32_t *buffer, int len, void *p) } -static void *pas16_init(device_t *info) +static void *pas16_init(const device_t *info) { pas16_t *pas16 = malloc(sizeof(pas16_t)); memset(pas16, 0, sizeof(pas16_t)); @@ -746,7 +746,7 @@ static void pas16_close(void *p) free(pas16); } -device_t pas16_device = +const device_t pas16_device = { "Pro Audio Spectrum 16", DEVICE_ISA | DEVICE_NOT_WORKING, diff --git a/src/sound/snd_pas16.h b/src/sound/snd_pas16.h index e3a134751..d7a208faa 100644 --- a/src/sound/snd_pas16.h +++ b/src/sound/snd_pas16.h @@ -1 +1 @@ -extern device_t pas16_device; +extern const device_t pas16_device; diff --git a/src/sound/snd_pssj.c b/src/sound/snd_pssj.c index 0dfcfd6cf..2e200c589 100644 --- a/src/sound/snd_pssj.c +++ b/src/sound/snd_pssj.c @@ -184,7 +184,7 @@ static void pssj_get_buffer(int32_t *buffer, int len, void *p) pssj->pos = 0; } -void *pssj_init(device_t *info) +void *pssj_init(const device_t *info) { pssj_t *pssj = malloc(sizeof(pssj_t)); memset(pssj, 0, sizeof(pssj_t)); @@ -205,7 +205,7 @@ void pssj_close(void *p) free(pssj); } -device_t pssj_device = +const device_t pssj_device = { "Tandy PSSJ", 0, 0, diff --git a/src/sound/snd_pssj.h b/src/sound/snd_pssj.h index 2255d48fb..71126f615 100644 --- a/src/sound/snd_pssj.h +++ b/src/sound/snd_pssj.h @@ -1 +1 @@ -extern device_t pssj_device; +extern const device_t pssj_device; diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 0f21b9464..c4c4ff255 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -8,7 +8,7 @@ * * Sound Blaster emulation. * - * Version: @(#)sound_sb.c 1.0.5 2018/02/15 + * Version: @(#)sound_sb.c 1.0.6 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -1339,7 +1339,7 @@ void sb_add_status_info(char *s, int max_len, void *p) sb_dsp_add_status_info(s, max_len, &sb->dsp); } -static device_config_t sb_config[] = +static const device_config_t sb_config[] = { { "base", "Address", CONFIG_HEX16, "", 0x220, @@ -1397,7 +1397,7 @@ static device_config_t sb_config[] = } }; -static device_config_t sb_mcv_config[] = +static const device_config_t sb_mcv_config[] = { { "irq", "IRQ", CONFIG_SELECTION, "", 7, @@ -1438,7 +1438,7 @@ static device_config_t sb_mcv_config[] = } }; -static device_config_t sb_pro_config[] = +static const device_config_t sb_pro_config[] = { { "base", "Address", CONFIG_HEX16, "", 0x220, @@ -1496,7 +1496,7 @@ static device_config_t sb_pro_config[] = } }; -static device_config_t sb_16_config[] = +static const device_config_t sb_16_config[] = { { "base", "Address", CONFIG_HEX16, "", 0x220, @@ -1634,7 +1634,7 @@ static device_config_t sb_16_config[] = } }; -static device_config_t sb_awe32_config[] = +static const device_config_t sb_awe32_config[] = { { "base", "Address", CONFIG_HEX16, "", 0x220, @@ -1815,7 +1815,7 @@ static device_config_t sb_awe32_config[] = } }; -device_t sb_1_device = +const device_t sb_1_device = { "Sound Blaster v1.0", DEVICE_ISA, @@ -1826,7 +1826,7 @@ device_t sb_1_device = sb_add_status_info, sb_config }; -device_t sb_15_device = +const device_t sb_15_device = { "Sound Blaster v1.5", DEVICE_ISA, @@ -1837,7 +1837,7 @@ device_t sb_15_device = sb_add_status_info, sb_config }; -device_t sb_mcv_device = +const device_t sb_mcv_device = { "Sound Blaster MCV", DEVICE_MCA, @@ -1848,7 +1848,7 @@ device_t sb_mcv_device = sb_add_status_info, sb_mcv_config }; -device_t sb_2_device = +const device_t sb_2_device = { "Sound Blaster v2.0", DEVICE_ISA, @@ -1859,7 +1859,7 @@ device_t sb_2_device = sb_add_status_info, sb_config }; -device_t sb_pro_v1_device = +const device_t sb_pro_v1_device = { "Sound Blaster Pro v1", DEVICE_ISA, @@ -1870,7 +1870,7 @@ device_t sb_pro_v1_device = sb_add_status_info, sb_pro_config }; -device_t sb_pro_v2_device = +const device_t sb_pro_v2_device = { "Sound Blaster Pro v2", DEVICE_ISA, @@ -1881,7 +1881,7 @@ device_t sb_pro_v2_device = sb_add_status_info, sb_pro_config }; -device_t sb_pro_mcv_device = +const device_t sb_pro_mcv_device = { "Sound Blaster Pro MCV", DEVICE_MCA, @@ -1892,7 +1892,7 @@ device_t sb_pro_mcv_device = sb_add_status_info, NULL }; -device_t sb_16_device = +const device_t sb_16_device = { "Sound Blaster 16", DEVICE_ISA, @@ -1903,7 +1903,7 @@ device_t sb_16_device = sb_add_status_info, sb_16_config }; -device_t sb_awe32_device = +const device_t sb_awe32_device = { "Sound Blaster AWE32", DEVICE_ISA, diff --git a/src/sound/snd_sb.h b/src/sound/snd_sb.h index a7197dfd2..feaec6c78 100644 --- a/src/sound/snd_sb.h +++ b/src/sound/snd_sb.h @@ -8,14 +8,14 @@ * * Sound Blaster emulation. * - * Version: @(#)sound_sb.h 1.0.2 2017/11/04 + * Version: @(#)sound_sb.h 1.0.3 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, * TheCollector1995, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #ifndef SOUND_SND_SB_H # define SOUND_SND_SB_H @@ -33,15 +33,15 @@ #define SND_PAS16 10 /* Pro Audio Spectrum 16 */ -extern device_t sb_1_device; -extern device_t sb_15_device; -extern device_t sb_mcv_device; -extern device_t sb_2_device; -extern device_t sb_pro_v1_device; -extern device_t sb_pro_v2_device; -extern device_t sb_pro_mcv_device; -extern device_t sb_16_device; -extern device_t sb_awe32_device; +extern const device_t sb_1_device; +extern const device_t sb_15_device; +extern const device_t sb_mcv_device; +extern const device_t sb_2_device; +extern const device_t sb_pro_v1_device; +extern const device_t sb_pro_v2_device; +extern const device_t sb_pro_mcv_device; +extern const device_t sb_16_device; +extern const device_t sb_awe32_device; #endif /*SOUND_SND_SB_H*/ diff --git a/src/sound/snd_sn76489.c b/src/sound/snd_sn76489.c index 0040f1769..c9dea8937 100644 --- a/src/sound/snd_sn76489.c +++ b/src/sound/snd_sn76489.c @@ -205,7 +205,7 @@ void sn76489_init(sn76489_t *sn76489, uint16_t base, uint16_t size, int type, in io_sethandler(base, size, NULL, NULL, NULL, sn76489_write, NULL, NULL, sn76489); } -void *sn76489_device_init(device_t *info) +void *sn76489_device_init(const device_t *info) { sn76489_t *sn76489 = malloc(sizeof(sn76489_t)); memset(sn76489, 0, sizeof(sn76489_t)); @@ -214,7 +214,7 @@ void *sn76489_device_init(device_t *info) return sn76489; } -void *ncr8496_device_init(device_t *info) +void *ncr8496_device_init(const device_t *info) { sn76489_t *sn76489 = malloc(sizeof(sn76489_t)); memset(sn76489, 0, sizeof(sn76489_t)); @@ -231,7 +231,7 @@ void sn76489_device_close(void *p) free(sn76489); } -device_t sn76489_device = +const device_t sn76489_device = { "TI SN74689 PSG", 0, @@ -241,7 +241,7 @@ device_t sn76489_device = NULL, NULL, NULL, NULL, NULL }; -device_t ncr8496_device = +const device_t ncr8496_device = { "NCR8496 PSG", 0, diff --git a/src/sound/snd_sn76489.h b/src/sound/snd_sn76489.h index 84c102821..01d19e0e5 100644 --- a/src/sound/snd_sn76489.h +++ b/src/sound/snd_sn76489.h @@ -5,8 +5,8 @@ enum PSSJ }; -extern device_t sn76489_device; -extern device_t ncr8496_device; +extern const device_t sn76489_device; +extern const device_t ncr8496_device; extern int sn76489_mute; diff --git a/src/sound/snd_ssi2001.c b/src/sound/snd_ssi2001.c index df2ff48da..5408a652d 100644 --- a/src/sound/snd_ssi2001.c +++ b/src/sound/snd_ssi2001.c @@ -57,7 +57,7 @@ static void ssi2001_write(uint16_t addr, uint8_t val, void *p) sid_write(addr, val, p); } -void *ssi2001_init(device_t *info) +void *ssi2001_init(const device_t *info) { ssi2001_t *ssi2001 = malloc(sizeof(ssi2001_t)); memset(ssi2001, 0, sizeof(ssi2001_t)); @@ -79,7 +79,7 @@ void ssi2001_close(void *p) free(ssi2001); } -device_t ssi2001_device = +const device_t ssi2001_device = { "Innovation SSI-2001", 0, 0, diff --git a/src/sound/snd_ssi2001.h b/src/sound/snd_ssi2001.h index 337c6260a..83af6838a 100644 --- a/src/sound/snd_ssi2001.h +++ b/src/sound/snd_ssi2001.h @@ -1 +1 @@ -extern device_t ssi2001_device; +extern const device_t ssi2001_device; diff --git a/src/sound/snd_wss.c b/src/sound/snd_wss.c index 5c97ebc35..8a6c82369 100644 --- a/src/sound/snd_wss.c +++ b/src/sound/snd_wss.c @@ -77,7 +77,7 @@ static void wss_get_buffer(int32_t *buffer, int len, void *p) wss->ad1848.pos = 0; } -void *wss_init(device_t *info) +void *wss_init(const device_t *info) { wss_t *wss = malloc(sizeof(wss_t)); @@ -112,7 +112,7 @@ void wss_speed_changed(void *p) ad1848_speed_changed(&wss->ad1848); } -device_t wss_device = +const device_t wss_device = { "Windows Sound System", DEVICE_ISA, 0, diff --git a/src/sound/snd_wss.h b/src/sound/snd_wss.h index bd387d6f3..0836e5808 100644 --- a/src/sound/snd_wss.h +++ b/src/sound/snd_wss.h @@ -1 +1 @@ -extern device_t wss_device; +extern const device_t wss_device; diff --git a/src/sound/sound.c b/src/sound/sound.c index de3bc47fd..66f8a0c87 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -8,7 +8,7 @@ * * Sound emulation core. * - * Version: @(#)sound.c 1.0.14 2018/02/18 + * Version: @(#)sound.c 1.0.15 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -45,7 +45,7 @@ typedef struct { const char *name; const char *internal_name; - device_t *device; + const device_t *device; } SOUND_CARD; typedef struct { @@ -77,7 +77,7 @@ static int cd_buf_update = CD_BUFLEN / SOUNDBUFLEN; static volatile int cdaudioon = 0; -static SOUND_CARD sound_cards[] = +static const SOUND_CARD sound_cards[] = { { "None", "none", NULL }, { "[ISA] Adlib", "adlib", &adlib_device }, @@ -115,7 +115,7 @@ char *sound_card_getname(int card) return (char *) sound_cards[card].name; } -device_t *sound_card_getdevice(int card) +const device_t *sound_card_getdevice(int card) { return sound_cards[card].device; } diff --git a/src/sound/sound.h b/src/sound/sound.h index 5f26736cc..05bfe4959 100644 --- a/src/sound/sound.h +++ b/src/sound/sound.h @@ -8,7 +8,7 @@ * * Sound emulation core. * - * Version: @(#)sound.h 1.0.5 2018/02/15 + * Version: @(#)sound.h 1.0.6 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -45,7 +45,7 @@ extern void sound_add_process_handler(void (*get_buffer)(int32_t *buffer, \ extern int sound_card_available(int card); extern char *sound_card_getname(int card); #ifdef EMU_DEVICE_H -extern device_t *sound_card_getdevice(int card); +extern const device_t *sound_card_getdevice(int card); #endif extern int sound_card_has_config(int card); extern char *sound_card_get_internal_name(int card); diff --git a/src/video/vid_ati18800.c b/src/video/vid_ati18800.c index 2081f0786..d31561816 100644 --- a/src/video/vid_ati18800.c +++ b/src/video/vid_ati18800.c @@ -8,7 +8,7 @@ * * ATI 18800 emulation (VGA Edge-16) * - * Version: @(#)vid_ati18800.c 1.0.7 2018/03/16 + * Version: @(#)vid_ati18800.c 1.0.8 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -215,7 +215,7 @@ static void ati18800_recalctimings(svga_t *svga) } } -static void *ati18800_init(device_t *info) +static void *ati18800_init(const device_t *info) { ati18800_t *ati18800 = malloc(sizeof(ati18800_t)); memset(ati18800, 0, sizeof(ati18800_t)); @@ -294,7 +294,7 @@ static void ati18800_add_status_info(char *s, int max_len, void *p) svga_add_status_info(s, max_len, &ati18800->svga); } -device_t ati18800_wonder_device = +const device_t ati18800_wonder_device = { "ATI-18800", DEVICE_ISA, ATI18800_WONDER, @@ -308,7 +308,7 @@ device_t ati18800_wonder_device = NULL }; -device_t ati18800_vga88_device = +const device_t ati18800_vga88_device = { "ATI-18800-1", DEVICE_ISA, ATI18800_VGA88, @@ -322,7 +322,7 @@ device_t ati18800_vga88_device = NULL }; -device_t ati18800_device = +const device_t ati18800_device = { "ATI-18800-5", DEVICE_ISA, ATI18800_EDGE16, diff --git a/src/video/vid_ati18800.h b/src/video/vid_ati18800.h index b0d4bb55a..b41facab3 100644 --- a/src/video/vid_ati18800.h +++ b/src/video/vid_ati18800.h @@ -1,6 +1,6 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ -extern device_t ati18800_wonder_device; -extern device_t ati18800_vga88_device; -extern device_t ati18800_device; +extern const device_t ati18800_wonder_device; +extern const device_t ati18800_vga88_device; +extern const device_t ati18800_device; diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index 0a1a0337d..1d20906b1 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -8,7 +8,7 @@ * * ATI 28800 emulation (VGA Charger and Korean VGA) * - * Version: @(#)vid_ati28800.c 1.0.12 2018/03/16 + * Version: @(#)vid_ati28800.c 1.0.13 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -387,7 +387,7 @@ void ati28800k_recalctimings(svga_t *svga) } void * -ati28800k_init(device_t *info) +ati28800k_init(const device_t *info) { ati28800_t *ati28800 = malloc(sizeof(ati28800_t)); memset(ati28800, 0, sizeof(ati28800_t)); @@ -422,7 +422,7 @@ ati28800k_init(device_t *info) } static void * -ati28800_init(device_t *info) +ati28800_init(const device_t *info) { ati28800_t *ati; ati = malloc(sizeof(ati28800_t)); @@ -555,7 +555,7 @@ static void ati28800_add_status_info(char *s, int max_len, void *priv) } -static device_config_t ati28800_config[] = +static const device_config_t ati28800_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 512, @@ -580,7 +580,7 @@ static device_config_t ati28800_config[] = }; #if defined(DEV_BRANCH) && defined(USE_XL24) -static device_config_t ati28800_wonderxl_config[] = +static const device_config_t ati28800_wonderxl_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 512, @@ -605,7 +605,7 @@ static device_config_t ati28800_wonderxl_config[] = }; #endif -device_t ati28800_device = +const device_t ati28800_device = { "ATI-28800", DEVICE_ISA, @@ -618,7 +618,7 @@ device_t ati28800_device = ati28800_config }; -device_t ati28800k_device = +const device_t ati28800k_device = { "ATI Korean VGA", DEVICE_ISA, @@ -631,7 +631,7 @@ device_t ati28800k_device = ati28800_config }; -device_t compaq_ati28800_device = +const device_t compaq_ati28800_device = { "Compaq ATI-28800", DEVICE_ISA, @@ -645,7 +645,7 @@ device_t compaq_ati28800_device = }; #if defined(DEV_BRANCH) && defined(USE_XL24) -device_t ati28800_wonderxl24_device = +const device_t ati28800_wonderxl24_device = { "ATI-28800 (VGA Wonder XL24)", DEVICE_ISA, diff --git a/src/video/vid_ati28800.h b/src/video/vid_ati28800.h index 70535331a..9db0fa7bc 100644 --- a/src/video/vid_ati28800.h +++ b/src/video/vid_ati28800.h @@ -1,9 +1,9 @@ /* Copyright holders: Sarah Walker, Tenshi see COPYING for more details */ -extern device_t ati28800_device; -extern device_t ati28800k_device; -extern device_t compaq_ati28800_device; +extern const device_t ati28800_device; +extern const device_t ati28800k_device; +extern const device_t compaq_ati28800_device; #if defined(DEV_BRANCH) && defined(USE_XL24) -extern device_t ati28800_wonderxl24_device; +extern const device_t ati28800_wonderxl24_device; #endif diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 3b349c635..b8f414ad3 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -8,7 +8,7 @@ * * ATi Mach64 graphics card emulation. * - * Version: @(#)vid_ati_mach64.c 1.0.16 2018/03/16 + * Version: @(#)vid_ati_mach64.c 1.0.17 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -3416,7 +3416,7 @@ void mach64_pci_write(int func, int addr, uint8_t val, void *p) } } -static void *mach64_common_init(device_t *info) +static void *mach64_common_init(const device_t *info) { mach64_t *mach64 = malloc(sizeof(mach64_t)); memset(mach64, 0, sizeof(mach64_t)); @@ -3462,7 +3462,7 @@ static void *mach64_common_init(device_t *info) return mach64; } -static void *mach64gx_init(device_t *info) +static void *mach64gx_init(const device_t *info) { mach64_t *mach64 = mach64_common_init(info); @@ -3487,7 +3487,7 @@ static void *mach64gx_init(device_t *info) return mach64; } -static void *mach64vt2_init(device_t *info) +static void *mach64vt2_init(const device_t *info) { mach64_t *mach64 = mach64_common_init(info); svga_t *svga = &mach64->svga; @@ -3600,7 +3600,7 @@ void mach64_add_status_info(char *s, int max_len, void *p) mach64->blitter_time = 0; } -static device_config_t mach64gx_config[] = +static const device_config_t mach64gx_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 4, @@ -3624,7 +3624,7 @@ static device_config_t mach64gx_config[] = } }; -static device_config_t mach64vt2_config[] = +static const device_config_t mach64vt2_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 4, @@ -3645,7 +3645,7 @@ static device_config_t mach64vt2_config[] = } }; -device_t mach64gx_isa_device = +const device_t mach64gx_isa_device = { "ATI Mach64GX ISA", DEVICE_AT | DEVICE_ISA, @@ -3658,7 +3658,7 @@ device_t mach64gx_isa_device = mach64gx_config }; -device_t mach64gx_vlb_device = +const device_t mach64gx_vlb_device = { "ATI Mach64GX VLB", DEVICE_VLB, @@ -3671,7 +3671,7 @@ device_t mach64gx_vlb_device = mach64gx_config }; -device_t mach64gx_pci_device = +const device_t mach64gx_pci_device = { "ATI Mach64GX PCI", DEVICE_PCI, @@ -3684,7 +3684,7 @@ device_t mach64gx_pci_device = mach64gx_config }; -device_t mach64vt2_device = +const device_t mach64vt2_device = { "ATI Mach64VT2", DEVICE_PCI, diff --git a/src/video/vid_ati_mach64.h b/src/video/vid_ati_mach64.h index 49dc5b9c8..c44444d7a 100644 --- a/src/video/vid_ati_mach64.h +++ b/src/video/vid_ati_mach64.h @@ -8,7 +8,7 @@ * * ATi Mach64 graphics card emulation. * - * Version: @(#)vid_ati_mach64.h 1.0.1 2018/01/21 + * Version: @(#)vid_ati_mach64.h 1.0.2 2018/03/18 * * Author: Sarah Walker, * Miran Grca, @@ -16,7 +16,7 @@ * Copyright 2016-2018 Miran Grca. */ -extern device_t mach64gx_isa_device; -extern device_t mach64gx_vlb_device; -extern device_t mach64gx_pci_device; -extern device_t mach64vt2_device; +extern const device_t mach64gx_isa_device; +extern const device_t mach64gx_vlb_device; +extern const device_t mach64gx_pci_device; +extern const device_t mach64vt2_device; diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index 79dc94dc9..4f94e7e20 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -8,7 +8,7 @@ * * Emulation of the old and new IBM CGA graphics cards. * - * Version: @(#)vid_cga.c 1.0.13 2018/01/25 + * Version: @(#)vid_cga.c 1.0.14 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -482,7 +482,7 @@ void cga_init(cga_t *cga) cga->composite = 0; } -void *cga_standalone_init(device_t *info) +void *cga_standalone_init(const device_t *info) { int display_type; cga_t *cga = malloc(sizeof(cga_t)); @@ -524,7 +524,7 @@ void cga_speed_changed(void *p) cga_recalctimings(cga); } -device_config_t cga_config[] = +const device_config_t cga_config[] = { { "display_type", "Display type", CONFIG_SELECTION, "", CGA_RGB, @@ -585,7 +585,7 @@ device_config_t cga_config[] = } }; -device_t cga_device = +const device_t cga_device = { "CGA", DEVICE_ISA, 0, diff --git a/src/video/vid_cga.h b/src/video/vid_cga.h index 93c8bac68..74aba09c2 100644 --- a/src/video/vid_cga.h +++ b/src/video/vid_cga.h @@ -8,12 +8,12 @@ * * Emulation of the old and new IBM CGA graphics cards. * - * Version: @(#)vid_cga.h 1.0.2 2017/12/31 + * Version: @(#)vid_cga.h 1.0.3 2018/03/18 * * Author: Sarah Walker, * Miran Grca, - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016-2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ typedef struct cga_t @@ -61,5 +61,5 @@ uint8_t cga_read(uint32_t addr, void *p); void cga_recalctimings(cga_t *cga); void cga_poll(void *p); -extern device_config_t cga_config[]; -extern device_t cga_device; +extern const device_config_t cga_config[]; +extern const device_t cga_device; diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index e58e11a23..de04c6fb2 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -9,7 +9,7 @@ * Emulation of select Cirrus Logic cards (CL-GD 5428, * CL-GD 5429, CL-GD 5430, CL-GD 5434 and CL-GD 5436 are supported). * - * Version: @(#)vid_cl_54xx.c 1.0.9 2018/03/02 + * Version: @(#)vid_cl_54xx.c 1.0.10 2018/03/18 * * Authors: Sarah Walker, * Barry Rodewald, @@ -2290,7 +2290,7 @@ cl_pci_write(int func, int addr, uint8_t val, void *p) static void -*gd54xx_init(device_t *info) +*gd54xx_init(const device_t *info) { gd54xx_t *gd54xx = malloc(sizeof(gd54xx_t)); svga_t *svga = &gd54xx->svga; @@ -2451,7 +2451,7 @@ gd54xx_add_status_info(char *s, int max_len, void *p) } -static device_config_t gd5428_config[] = +static const device_config_t gd5428_config[] = { { .name = "memory", @@ -2478,7 +2478,7 @@ static device_config_t gd5428_config[] = } }; -static device_config_t gd5434_config[] = +static const device_config_t gd5434_config[] = { { .name = "memory", @@ -2505,7 +2505,7 @@ static device_config_t gd5434_config[] = } }; -device_t gd5426_vlb_device = +const device_t gd5426_vlb_device = { "Cirrus Logic CL-GD 5426 (VLB)", DEVICE_VLB, @@ -2520,7 +2520,7 @@ device_t gd5426_vlb_device = gd5428_config }; -device_t gd5428_isa_device = +const device_t gd5428_isa_device = { "Cirrus Logic CL-GD 5428 (ISA)", DEVICE_AT | DEVICE_ISA, @@ -2535,7 +2535,7 @@ device_t gd5428_isa_device = gd5428_config }; -device_t gd5428_vlb_device = +const device_t gd5428_vlb_device = { "Cirrus Logic CL-GD 5428 (VLB)", DEVICE_VLB, @@ -2550,7 +2550,7 @@ device_t gd5428_vlb_device = gd5428_config }; -device_t gd5429_isa_device = +const device_t gd5429_isa_device = { "Cirrus Logic CL-GD 5429 (ISA)", DEVICE_AT | DEVICE_ISA, @@ -2565,7 +2565,7 @@ device_t gd5429_isa_device = gd5428_config }; -device_t gd5429_vlb_device = +const device_t gd5429_vlb_device = { "Cirrus Logic CL-GD 5429 (VLB)", DEVICE_VLB, @@ -2580,7 +2580,7 @@ device_t gd5429_vlb_device = gd5428_config }; -device_t gd5430_vlb_device = +const device_t gd5430_vlb_device = { "Cirrus Logic CL-GD 5430 (VLB)", DEVICE_VLB, @@ -2595,7 +2595,7 @@ device_t gd5430_vlb_device = gd5428_config }; -device_t gd5430_pci_device = +const device_t gd5430_pci_device = { "Cirrus Logic CL-GD 5430 (PCI)", DEVICE_PCI, @@ -2610,7 +2610,7 @@ device_t gd5430_pci_device = gd5428_config }; -device_t gd5434_isa_device = +const device_t gd5434_isa_device = { "Cirrus Logic CL-GD 5434 (ISA)", DEVICE_AT | DEVICE_ISA, @@ -2625,7 +2625,7 @@ device_t gd5434_isa_device = gd5434_config }; -device_t gd5434_vlb_device = +const device_t gd5434_vlb_device = { "Cirrus Logic CL-GD 5434 (VLB)", DEVICE_VLB, @@ -2640,7 +2640,7 @@ device_t gd5434_vlb_device = gd5434_config }; -device_t gd5434_pci_device = +const device_t gd5434_pci_device = { "Cirrus Logic CL-GD 5434 (PCI)", DEVICE_PCI, @@ -2655,7 +2655,7 @@ device_t gd5434_pci_device = gd5434_config }; -device_t gd5436_pci_device = +const device_t gd5436_pci_device = { "Cirrus Logic CL-GD 5436 (PCI)", DEVICE_PCI, diff --git a/src/video/vid_cl54xx.h b/src/video/vid_cl54xx.h index 472d8316b..af7707f0a 100644 --- a/src/video/vid_cl54xx.h +++ b/src/video/vid_cl54xx.h @@ -1,14 +1,14 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ -extern device_t gd5426_vlb_device; -extern device_t gd5428_isa_device; -extern device_t gd5428_vlb_device; -extern device_t gd5429_isa_device; -extern device_t gd5429_vlb_device; -extern device_t gd5430_vlb_device; -extern device_t gd5430_pci_device; -extern device_t gd5434_isa_device; -extern device_t gd5434_vlb_device; -extern device_t gd5434_pci_device; -extern device_t gd5436_pci_device; \ No newline at end of file +extern const device_t gd5426_vlb_device; +extern const device_t gd5428_isa_device; +extern const device_t gd5428_vlb_device; +extern const device_t gd5429_isa_device; +extern const device_t gd5429_vlb_device; +extern const device_t gd5430_vlb_device; +extern const device_t gd5430_pci_device; +extern const device_t gd5434_isa_device; +extern const device_t gd5434_vlb_device; +extern const device_t gd5434_pci_device; +extern const device_t gd5436_pci_device; \ No newline at end of file diff --git a/src/video/vid_colorplus.c b/src/video/vid_colorplus.c index 6af4e1b81..d03c7d94d 100644 --- a/src/video/vid_colorplus.c +++ b/src/video/vid_colorplus.c @@ -8,13 +8,13 @@ * * Plantronics ColorPlus emulation. * - * Version: @(#)vid_colorplus.c 1.0.7 2017/11/14 + * Version: @(#)vid_colorplus.c 1.0.8 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -385,7 +385,7 @@ void colorplus_init(colorplus_t *colorplus) cga_init(&colorplus->cga); } -void *colorplus_standalone_init(device_t *info) +void *colorplus_standalone_init(const device_t *info) { int display_type; @@ -426,7 +426,7 @@ void colorplus_speed_changed(void *p) cga_recalctimings(&colorplus->cga); } -static device_config_t colorplus_config[] = +static const device_config_t colorplus_config[] = { { "display_type", "Display type", CONFIG_SELECTION, "", CGA_RGB, @@ -464,7 +464,7 @@ static device_config_t colorplus_config[] = } }; -device_t colorplus_device = +const device_t colorplus_device = { "Colorplus", DEVICE_ISA, 0, diff --git a/src/video/vid_colorplus.h b/src/video/vid_colorplus.h index 3213b4edc..07a96ff4f 100644 --- a/src/video/vid_colorplus.h +++ b/src/video/vid_colorplus.h @@ -12,4 +12,4 @@ 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; +extern const device_t colorplus_device; diff --git a/src/video/vid_compaq_cga.c b/src/video/vid_compaq_cga.c index 17c0dbdef..10c518403 100644 --- a/src/video/vid_compaq_cga.c +++ b/src/video/vid_compaq_cga.c @@ -360,7 +360,7 @@ void compaq_cga_poll(void *p) } -void *compaq_cga_init(device_t *info) +void *compaq_cga_init(const device_t *info) { int display_type; int c; @@ -432,9 +432,9 @@ void compaq_cga_speed_changed(void *p) } } -extern device_config_t cga_config[]; +extern const device_config_t cga_config[]; -device_t compaq_cga_device = +const device_t compaq_cga_device = { "Compaq CGA", DEVICE_ISA, 0, @@ -448,7 +448,7 @@ device_t compaq_cga_device = cga_config }; -device_t compaq_cga_2_device = +const device_t compaq_cga_2_device = { "Compaq CGA 2", DEVICE_ISA, 1, diff --git a/src/video/vid_compaq_cga.h b/src/video/vid_compaq_cga.h index b00e048ca..e6c684d52 100644 --- a/src/video/vid_compaq_cga.h +++ b/src/video/vid_compaq_cga.h @@ -3,8 +3,8 @@ #ifdef EMU_DEVICE_H -extern device_t compaq_cga_device; -extern device_t compaq_cga_2_device; +extern const device_t compaq_cga_device; +extern const device_t compaq_cga_2_device; #endif diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index f990c17ce..2d73d46df 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -9,7 +9,7 @@ * Emulation of the EGA, Chips & Technologies SuperEGA, and * AX JEGA graphics cards. * - * Version: @(#)vid_ega.c 1.0.15 2018/02/01 + * Version: @(#)vid_ega.c 1.0.16 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -989,7 +989,7 @@ void ega_init(ega_t *ega, int monitor_type, int is_mono) } -static void *ega_standalone_init(device_t *info) +static void *ega_standalone_init(const device_t *info) { ega_t *ega = malloc(sizeof(ega_t)); int monitor_type; @@ -1134,7 +1134,7 @@ static void LoadFontxFile(wchar_t *fname) fclose(mfile); } -void *jega_standalone_init(device_t *info) +void *jega_standalone_init(const device_t *info) { ega_t *ega = (ega_t *)ega_standalone_init(info); @@ -1183,7 +1183,7 @@ static void ega_speed_changed(void *p) } -static device_config_t ega_config[] = +static const device_config_t ega_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 256, @@ -1244,7 +1244,7 @@ static device_config_t ega_config[] = }; -device_t ega_device = +const device_t ega_device = { "EGA", DEVICE_ISA, @@ -1257,7 +1257,7 @@ device_t ega_device = ega_config }; -device_t cpqega_device = +const device_t cpqega_device = { "Compaq EGA", DEVICE_ISA, @@ -1270,7 +1270,7 @@ device_t cpqega_device = ega_config }; -device_t sega_device = +const device_t sega_device = { "SuperEGA", DEVICE_ISA, @@ -1284,7 +1284,7 @@ device_t sega_device = }; #ifdef JEGA -device_t jega_device = +const device_t jega_device = { "AX JEGA", DEVICE_ISA, diff --git a/src/video/vid_ega.h b/src/video/vid_ega.h index 2d21418be..e5590d052 100644 --- a/src/video/vid_ega.h +++ b/src/video/vid_ega.h @@ -9,7 +9,7 @@ * Emulation of the EGA, Chips & Technologies SuperEGA, and * AX JEGA graphics cards. * - * Version: @(#)vid_ega.h 1.0.6 2018/01/25 + * Version: @(#)vid_ega.h 1.0.7 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -115,9 +115,9 @@ typedef struct ega_t { #ifdef EMU_DEVICE_H -extern device_t ega_device; -extern device_t cpqega_device; -extern device_t sega_device; +extern const device_t ega_device; +extern const device_t cpqega_device; +extern const device_t sega_device; #endif #ifdef JEGA extern uint8_t jfont_sbcs_19[SBCS19_LEN]; /* 256 * 19( * 8) */ diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index 6e76d2ecb..1dd4abb31 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -8,7 +8,7 @@ * * Emulation of the Tseng Labs ET4000. * - * Version: @(#)vid_et4000.c 1.0.4 2018/02/25 + * Version: @(#)vid_et4000.c 1.0.5 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -160,7 +160,7 @@ void et4000_recalctimings(svga_t *svga) } } -void *et4000_init(device_t *info) +void *et4000_init(const device_t *info) { et4000_t *et4000 = malloc(sizeof(et4000_t)); memset(et4000, 0, sizeof(et4000_t)); @@ -213,7 +213,7 @@ void et4000_add_status_info(char *s, int max_len, void *p) svga_add_status_info(s, max_len, &et4000->svga); } -device_t et4000_device = +const device_t et4000_device = { "Tseng Labs ET4000AX", DEVICE_ISA, 0, diff --git a/src/video/vid_et4000.h b/src/video/vid_et4000.h index 54daa1dd4..803f84729 100644 --- a/src/video/vid_et4000.h +++ b/src/video/vid_et4000.h @@ -1,4 +1,4 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ -extern device_t et4000_device; +extern const device_t et4000_device; diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index 3fe4c0399..19bb5c0a8 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -10,7 +10,7 @@ * * Known bugs: Accelerator doesn't work in planar modes * - * Version: @(#)vid_et4000w32.c 1.0.6 2018/02/11 + * Version: @(#)vid_et4000w32.c 1.0.7 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -1190,7 +1190,7 @@ void et4000w32p_pci_write(int func, int addr, uint8_t val, void *p) } } -void *et4000w32p_init(device_t *info) +void *et4000w32p_init(const device_t *info) { int vram_size; et4000w32p_t *et4000 = malloc(sizeof(et4000w32p_t)); @@ -1309,7 +1309,7 @@ void et4000w32p_add_status_info(char *s, int max_len, void *p) et4000->blitter_time = 0; } -static device_config_t et4000w32p_config[] = +static const device_config_t et4000w32p_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 2, @@ -1330,7 +1330,7 @@ static device_config_t et4000w32p_config[] = } }; -device_t et4000w32p_cardex_vlb_device = +const device_t et4000w32p_cardex_vlb_device = { "Tseng Labs ET4000/w32p VLB (Cardex)", DEVICE_VLB, ET4000W32_CARDEX, @@ -1342,7 +1342,7 @@ device_t et4000w32p_cardex_vlb_device = et4000w32p_config }; -device_t et4000w32p_cardex_pci_device = +const device_t et4000w32p_cardex_pci_device = { "Tseng Labs ET4000/w32p PCI (Cardex)", DEVICE_PCI, ET4000W32_CARDEX, @@ -1355,7 +1355,7 @@ device_t et4000w32p_cardex_pci_device = }; #if defined(DEV_BRANCH) && defined(USE_STEALTH32) -device_t et4000w32p_vlb_device = +const device_t et4000w32p_vlb_device = { "Tseng Labs ET4000/w32p VLB (Diamond)", DEVICE_VLB, ET4000W32_DIAMOND, @@ -1367,7 +1367,7 @@ device_t et4000w32p_vlb_device = et4000w32p_config }; -device_t et4000w32p_pci_device = +const device_t et4000w32p_pci_device = { "Tseng Labs ET4000/w32p PCI (Diamond)", DEVICE_PCI, ET4000W32_DIAMOND, diff --git a/src/video/vid_et4000w32.h b/src/video/vid_et4000w32.h index 7abe28038..80a14e5d4 100644 --- a/src/video/vid_et4000w32.h +++ b/src/video/vid_et4000w32.h @@ -1,7 +1,7 @@ #if defined(DEV_BRANCH) && defined(USE_STEALTH32) -extern device_t et4000w32p_vlb_device; -extern device_t et4000w32p_pci_device; +extern const device_t et4000w32p_vlb_device; +extern const device_t et4000w32p_pci_device; #endif -extern device_t et4000w32p_cardex_vlb_device; -extern device_t et4000w32p_cardex_pci_device; +extern const device_t et4000w32p_cardex_vlb_device; +extern const device_t et4000w32p_cardex_pci_device; diff --git a/src/video/vid_genius.c b/src/video/vid_genius.c index 3b5da4110..a205628ce 100644 --- a/src/video/vid_genius.c +++ b/src/video/vid_genius.c @@ -8,13 +8,13 @@ * * MDSI Genius VHR emulation. * - * Version: @(#)vid_genius.c 1.0.7 2017/11/04 + * Version: @(#)vid_genius.c 1.0.8 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -570,7 +570,7 @@ void genius_poll(void *p) } } -void *genius_init(device_t *info) +void *genius_init(const device_t *info) { int c; genius_t *genius = malloc(sizeof(genius_t)); @@ -638,7 +638,7 @@ void genius_speed_changed(void *p) genius_recalctimings(genius); } -device_t genius_device = +const device_t genius_device = { "Genius VHR", DEVICE_ISA, 0, diff --git a/src/video/vid_genius.h b/src/video/vid_genius.h index 77dce66f0..e1388ec5c 100644 --- a/src/video/vid_genius.h +++ b/src/video/vid_genius.h @@ -1 +1 @@ -extern device_t genius_device; +extern const device_t genius_device; diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index 188e4ea9e..d4ab49af4 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -8,13 +8,13 @@ * * Hercules emulation. * - * Version: @(#)vid_hercules.c 1.0.8 2017/11/14 + * Version: @(#)vid_hercules.c 1.0.9 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -331,7 +331,7 @@ void hercules_poll(void *p) } -void *hercules_init(device_t *info) +void *hercules_init(const device_t *info) { int c; hercules_t *hercules = malloc(sizeof(hercules_t)); @@ -391,7 +391,7 @@ void hercules_speed_changed(void *p) hercules_recalctimings(hercules); } -static device_config_t hercules_config[] = +static const device_config_t hercules_config[] = { { "rgb_type", "Display type", CONFIG_SELECTION, "", 0, @@ -419,7 +419,7 @@ static device_config_t hercules_config[] = }; -device_t hercules_device = +const device_t hercules_device = { "Hercules", DEVICE_ISA, 0, diff --git a/src/video/vid_hercules.h b/src/video/vid_hercules.h index 869ff317d..3c145e18f 100644 --- a/src/video/vid_hercules.h +++ b/src/video/vid_hercules.h @@ -1,4 +1,4 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ -extern device_t hercules_device; +extern const device_t hercules_device; diff --git a/src/video/vid_herculesplus.c b/src/video/vid_herculesplus.c index 282a1bb38..6a657bff7 100644 --- a/src/video/vid_herculesplus.c +++ b/src/video/vid_herculesplus.c @@ -8,13 +8,13 @@ * * Hercules InColor emulation. * - * Version: @(#)vid_herculesplus.c 1.0.6 2017/11/14 + * Version: @(#)vid_herculesplus.c 1.0.7 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -678,7 +678,7 @@ void herculesplus_poll(void *p) } } -void *herculesplus_init(device_t *info) +void *herculesplus_init(const device_t *info) { int c; herculesplus_t *herculesplus = malloc(sizeof(herculesplus_t)); @@ -729,7 +729,7 @@ void herculesplus_speed_changed(void *p) herculesplus_recalctimings(herculesplus); } -device_t herculesplus_device = +const device_t herculesplus_device = { "Hercules Plus", DEVICE_ISA, 0, diff --git a/src/video/vid_herculesplus.h b/src/video/vid_herculesplus.h index 377fd4ffd..72b47c35f 100644 --- a/src/video/vid_herculesplus.h +++ b/src/video/vid_herculesplus.h @@ -1,4 +1,4 @@ /* Copyright holders: John Elliott see COPYING for more details */ -extern device_t herculesplus_device; +extern const device_t herculesplus_device; diff --git a/src/video/vid_incolor.c b/src/video/vid_incolor.c index b3a81fca7..1a456f3b5 100644 --- a/src/video/vid_incolor.c +++ b/src/video/vid_incolor.c @@ -8,13 +8,13 @@ * * Hercules InColor emulation. * - * Version: @(#)vid_incolor.c 1.0.7 2017/11/14 + * Version: @(#)vid_incolor.c 1.0.8 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -1025,7 +1025,7 @@ void incolor_poll(void *p) } } -void *incolor_init(device_t *info) +void *incolor_init(const device_t *info) { int c; incolor_t *incolor = malloc(sizeof(incolor_t)); @@ -1073,7 +1073,7 @@ void incolor_speed_changed(void *p) incolor_recalctimings(incolor); } -device_t incolor_device = +const device_t incolor_device = { "Hercules InColor", DEVICE_ISA, 0, diff --git a/src/video/vid_incolor.h b/src/video/vid_incolor.h index 0e180ab82..d75a97186 100644 --- a/src/video/vid_incolor.h +++ b/src/video/vid_incolor.h @@ -1,4 +1,4 @@ /* Copyright holders: John Elliott see COPYING for more details */ -extern device_t incolor_device; +extern const device_t incolor_device; diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 655ac231c..9f792207a 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -8,13 +8,13 @@ * * MDA emulation. * - * Version: @(#)vid_mda.c 1.0.9 2017/11/14 + * Version: @(#)vid_mda.c 1.0.10 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -280,7 +280,7 @@ void mda_poll(void *p) } -void *mda_init(device_t *info) +void *mda_init(const device_t *info) { int c; mda_t *mda = malloc(sizeof(mda_t)); @@ -340,7 +340,7 @@ void mda_speed_changed(void *p) mda_recalctimings(mda); } -static device_config_t mda_config[] = +static const device_config_t mda_config[] = { { "rgb_type", "Display type", CONFIG_SELECTION, "", 0, @@ -368,7 +368,7 @@ static device_config_t mda_config[] = }; -device_t mda_device = +const device_t mda_device = { "MDA", DEVICE_ISA, 0, diff --git a/src/video/vid_mda.h b/src/video/vid_mda.h index f08e48d03..4e1e78e41 100644 --- a/src/video/vid_mda.h +++ b/src/video/vid_mda.h @@ -1,4 +1,4 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ -extern device_t mda_device; +extern const device_t mda_device; diff --git a/src/video/vid_nv_riva128.c b/src/video/vid_nv_riva128.c index 6014bc5f9..9abc94cc0 100644 --- a/src/video/vid_nv_riva128.c +++ b/src/video/vid_nv_riva128.c @@ -8,13 +8,13 @@ * * nVidia RIVA 128 emulation. * - * Version: @(#)vid_nv_riva128.c 1.0.4 2017/11/04 + * Version: @(#)vid_nv_riva128.c 1.0.5 2018/03/18 * * Author: Melissa Goad * Miran Grca, * - * Copyright 2017 Melissa Goad. - * Copyright 2017 Miran Grca. + * Copyright 2015-2018 Melissa Goad. + * Copyright 2015-2018 Miran Grca. */ #include #include @@ -2985,7 +2985,7 @@ void riva128_ptimer_tick(void *p) } -void *riva128_init(device_t *info) +void *riva128_init(const device_t *info) { riva128_t *riva128 = malloc(sizeof(riva128_t)); memset(riva128, 0, sizeof(riva128_t)); @@ -3160,7 +3160,7 @@ void riva128_add_status_info(char *s, int max_len, void *p) svga_add_status_info(s, max_len, &riva128->svga); } -device_config_t riva128_config[] = +const device_config_t riva128_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 4, @@ -3185,7 +3185,7 @@ device_config_t riva128_config[] = }; #if 0 -device_config_t riva128zx_config[] = +const device_config_t riva128zx_config[] = { { .name = "memory", @@ -3221,7 +3221,7 @@ device_config_t riva128zx_config[] = }; #endif -device_t riva128_device = +const device_t riva128_device = { "nVidia RIVA 128", DEVICE_PCI, @@ -3237,7 +3237,7 @@ device_t riva128_device = }; -void *rivatnt_init(device_t *info) +void *rivatnt_init(const device_t *info) { riva128_t *riva128 = malloc(sizeof(riva128_t)); memset(riva128, 0, sizeof(riva128_t)); @@ -3393,7 +3393,7 @@ void rivatnt_add_status_info(char *s, int max_len, void *p) svga_add_status_info(s, max_len, &riva128->svga); } -device_config_t rivatnt_config[] = +const device_config_t rivatnt_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 16, @@ -3417,7 +3417,7 @@ device_config_t rivatnt_config[] = } }; -device_t rivatnt_device = +const device_t rivatnt_device = { "nVidia RIVA TNT", DEVICE_PCI, @@ -3432,7 +3432,7 @@ device_t rivatnt_device = rivatnt_config }; -void *rivatnt2_init(device_t *info) +void *rivatnt2_init(const device_t *info) { riva128_t *riva128 = malloc(sizeof(riva128_t)); memset(riva128, 0, sizeof(riva128_t)); @@ -3601,7 +3601,7 @@ void rivatnt2_add_status_info(char *s, int max_len, void *p) svga_add_status_info(s, max_len, &riva128->svga); } -device_config_t rivatnt2_config[] = +const device_config_t rivatnt2_config[] = { { "model", "Card model", CONFIG_SELECTION, "", 0, @@ -3642,7 +3642,7 @@ device_config_t rivatnt2_config[] = } }; -device_t rivatnt2_device = +const device_t rivatnt2_device = { "nVidia RIVA TNT2", DEVICE_PCI, diff --git a/src/video/vid_nv_riva128.h b/src/video/vid_nv_riva128.h index 5f0f545e5..8c8e2cd6b 100644 --- a/src/video/vid_nv_riva128.h +++ b/src/video/vid_nv_riva128.h @@ -1,3 +1,3 @@ -extern device_t riva128_device; -extern device_t rivatnt_device; -extern device_t rivatnt2_device; +extern const device_t riva128_device; +extern const device_t rivatnt_device; +extern const device_t rivatnt2_device; diff --git a/src/video/vid_oak_oti.c b/src/video/vid_oak_oti.c index 027e93b95..15781aa32 100644 --- a/src/video/vid_oak_oti.c +++ b/src/video/vid_oak_oti.c @@ -8,7 +8,7 @@ * * Oak OTI037C/67/077 emulation. * - * Version: @(#)vid_oak_oti.c 1.0.8 2018/03/02 + * Version: @(#)vid_oak_oti.c 1.0.9 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -218,7 +218,7 @@ oti_recalctimings(svga_t *svga) static void * -oti_init(device_t *info) +oti_init(const device_t *info) { oti_t *oti = malloc(sizeof(oti_t)); wchar_t *romfn = NULL; @@ -309,7 +309,7 @@ oti067_077_available(void) } -static device_config_t oti067_config[] = +static const device_config_t oti067_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 512, @@ -331,7 +331,7 @@ static device_config_t oti067_config[] = }; -static device_config_t oti077_config[] = +static const device_config_t oti077_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 1024, @@ -355,7 +355,7 @@ static device_config_t oti077_config[] = } }; -device_t oti037c_device = +const device_t oti037c_device = { "Oak OTI-037C", DEVICE_ISA, @@ -368,7 +368,7 @@ device_t oti037c_device = oti067_config }; -device_t oti067_device = +const device_t oti067_device = { "Oak OTI-067", DEVICE_ISA, @@ -381,7 +381,7 @@ device_t oti067_device = oti067_config }; -device_t oti077_device = +const device_t oti077_device = { "Oak OTI-077", DEVICE_ISA, diff --git a/src/video/vid_oak_oti.h b/src/video/vid_oak_oti.h index 4652e4436..6a4d3cb1f 100644 --- a/src/video/vid_oak_oti.h +++ b/src/video/vid_oak_oti.h @@ -1,7 +1,7 @@ /* Copyright holders: Sarah Walker, Tenshi see COPYING for more details */ -extern device_t oti037c_device; -extern device_t oti067_device; -extern device_t oti067_acer386_device; -extern device_t oti077_device; +extern const device_t oti037c_device; +extern const device_t oti067_device; +extern const device_t oti067_acer386_device; +extern const device_t oti077_device; diff --git a/src/video/vid_paradise.c b/src/video/vid_paradise.c index dd96b1884..dda19b26d 100644 --- a/src/video/vid_paradise.c +++ b/src/video/vid_paradise.c @@ -10,7 +10,7 @@ * PC2086, PC3086 use PVGA1A * MegaPC uses W90C11A * - * Version: @(#)vid_paradise.c 1.0.5 2018/02/03 + * Version: @(#)vid_paradise.c 1.0.5 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -279,7 +279,7 @@ static uint16_t paradise_readw(uint32_t addr, void *p) return svga_readw_linear(addr, ¶dise->svga); } -void *paradise_pvga1a_init(device_t *info, uint32_t memsize) +void *paradise_pvga1a_init(const device_t *info, uint32_t memsize) { paradise_t *paradise = malloc(sizeof(paradise_t)); svga_t *svga = ¶dise->svga; @@ -312,7 +312,7 @@ void *paradise_pvga1a_init(device_t *info, uint32_t memsize) return paradise; } -void *paradise_wd90c11_init(device_t *info) +void *paradise_wd90c11_init(const device_t *info) { paradise_t *paradise = malloc(sizeof(paradise_t)); svga_t *svga = ¶dise->svga; @@ -347,7 +347,7 @@ void *paradise_wd90c11_init(device_t *info) return paradise; } -void *paradise_wd90c30_init(device_t *info, uint32_t memsize) +void *paradise_wd90c30_init(const device_t *info, uint32_t memsize) { paradise_t *paradise = malloc(sizeof(paradise_t)); svga_t *svga = ¶dise->svga; @@ -382,7 +382,7 @@ void *paradise_wd90c30_init(device_t *info, uint32_t memsize) return paradise; } -static void *paradise_pvga1a_pc2086_init(device_t *info) +static void *paradise_pvga1a_pc2086_init(const device_t *info) { paradise_t *paradise = paradise_pvga1a_init(info, 1 << 18); @@ -391,7 +391,7 @@ static void *paradise_pvga1a_pc2086_init(device_t *info) return paradise; } -static void *paradise_pvga1a_pc3086_init(device_t *info) +static void *paradise_pvga1a_pc3086_init(const device_t *info) { paradise_t *paradise = paradise_pvga1a_init(info, 1 << 18); @@ -401,7 +401,7 @@ static void *paradise_pvga1a_pc3086_init(device_t *info) return paradise; } -static void *paradise_pvga1a_standalone_init(device_t *info) +static void *paradise_pvga1a_standalone_init(const device_t *info) { paradise_t *paradise; uint32_t memory = 512; @@ -422,7 +422,7 @@ static int paradise_pvga1a_standalone_available(void) return rom_present(L"roms/video/pvga1a/BIOS.BIN"); } -static void *paradise_wd90c11_megapc_init(device_t *info) +static void *paradise_wd90c11_megapc_init(const device_t *info) { paradise_t *paradise = paradise_wd90c11_init(info); @@ -435,7 +435,7 @@ static void *paradise_wd90c11_megapc_init(device_t *info) return paradise; } -static void *paradise_wd90c11_standalone_init(device_t *info) +static void *paradise_wd90c11_standalone_init(const device_t *info) { paradise_t *paradise = paradise_wd90c11_init(info); @@ -450,7 +450,7 @@ static int paradise_wd90c11_standalone_available(void) return rom_present(L"roms/video/wd90c11/WD90C11.VBI"); } -static void *paradise_wd90c30_standalone_init(device_t *info) +static void *paradise_wd90c30_standalone_init(const device_t *info) { paradise_t *paradise; uint32_t memory = 512; @@ -502,7 +502,7 @@ void paradise_add_status_info(char *s, int max_len, void *p) } -device_t paradise_pvga1a_pc2086_device = +const device_t paradise_pvga1a_pc2086_device = { "Paradise PVGA1A (Amstrad PC2086)", 0, @@ -515,7 +515,7 @@ device_t paradise_pvga1a_pc2086_device = paradise_force_redraw, paradise_add_status_info }; -device_t paradise_pvga1a_pc3086_device = +const device_t paradise_pvga1a_pc3086_device = { "Paradise PVGA1A (Amstrad PC3086)", 0, @@ -529,7 +529,7 @@ device_t paradise_pvga1a_pc3086_device = paradise_add_status_info }; -static device_config_t paradise_pvga1a_config[] = +static const device_config_t paradise_pvga1a_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 512, @@ -553,7 +553,7 @@ static device_config_t paradise_pvga1a_config[] = } }; -device_t paradise_pvga1a_device = +const device_t paradise_pvga1a_device = { "Paradise PVGA1A", DEVICE_ISA, @@ -567,7 +567,7 @@ device_t paradise_pvga1a_device = paradise_add_status_info, paradise_pvga1a_config }; -device_t paradise_wd90c11_megapc_device = +const device_t paradise_wd90c11_megapc_device = { "Paradise WD90C11 (Amstrad MegaPC)", 0, @@ -580,7 +580,7 @@ device_t paradise_wd90c11_megapc_device = paradise_force_redraw, paradise_add_status_info }; -device_t paradise_wd90c11_device = +const device_t paradise_wd90c11_device = { "Paradise WD90C11-LR", DEVICE_ISA, @@ -594,7 +594,7 @@ device_t paradise_wd90c11_device = paradise_add_status_info }; -static device_config_t paradise_wd90c30_config[] = +static const device_config_t paradise_wd90c30_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 1024, @@ -615,7 +615,7 @@ static device_config_t paradise_wd90c30_config[] = } }; -device_t paradise_wd90c30_device = +const device_t paradise_wd90c30_device = { "Paradise WD90C30-LR", DEVICE_ISA, diff --git a/src/video/vid_paradise.h b/src/video/vid_paradise.h index 19c34b582..bdc4734aa 100644 --- a/src/video/vid_paradise.h +++ b/src/video/vid_paradise.h @@ -1,9 +1,9 @@ /* Copyright holders: Sarah Walker, Tenshi see COPYING for more details */ -extern device_t paradise_pvga1a_pc2086_device; -extern device_t paradise_pvga1a_pc3086_device; -extern device_t paradise_pvga1a_device; -extern device_t paradise_wd90c11_megapc_device; -extern device_t paradise_wd90c11_device; -extern device_t paradise_wd90c30_device; +extern const device_t paradise_pvga1a_pc2086_device; +extern const device_t paradise_pvga1a_pc3086_device; +extern const device_t paradise_pvga1a_device; +extern const device_t paradise_wd90c11_megapc_device; +extern const device_t paradise_wd90c11_device; +extern const device_t paradise_wd90c30_device; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 21034e812..22777421c 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -8,7 +8,7 @@ * * S3 emulation. * - * Version: @(#)vid_s3.c 1.0.6 2018/03/07 + * Version: @(#)vid_s3.c 1.0.7 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -2164,7 +2164,7 @@ static int vram_sizes[] = 3 /*8 MB*/ }; -static void *s3_init(device_t *info, wchar_t *bios_fn, int chip) +static void *s3_init(const device_t *info, wchar_t *bios_fn, int chip) { s3_t *s3 = malloc(sizeof(s3_t)); svga_t *svga = &s3->svga; @@ -2258,7 +2258,7 @@ static void *s3_init(device_t *info, wchar_t *bios_fn, int chip) return s3; } -void *s3_vision864_init(device_t *info, wchar_t *bios_fn) +void *s3_vision864_init(const device_t *info, wchar_t *bios_fn) { s3_t *s3 = s3_init(info, bios_fn, S3_VISION864); @@ -2273,13 +2273,13 @@ void *s3_vision864_init(device_t *info, wchar_t *bios_fn) } -static void *s3_bahamas64_init(device_t *info) +static void *s3_bahamas64_init(const device_t *info) { s3_t *s3 = s3_vision864_init(info, L"roms/video/s3/bahamas64.bin"); return s3; } -static void *s3_phoenix_vision864_init(device_t *info) +static void *s3_phoenix_vision864_init(const device_t *info) { s3_t *s3 = s3_vision864_init(info, L"roms/video/s3/86c864p.bin"); return s3; @@ -2295,7 +2295,7 @@ static int s3_phoenix_vision864_available(void) return rom_present(L"roms/video/s3/86c864p.bin"); } -static void *s3_phoenix_trio32_init(device_t *info) +static void *s3_phoenix_trio32_init(const device_t *info) { s3_t *s3 = s3_init(info, L"roms/video/s3/86c732p.bin", S3_TRIO32); @@ -2315,7 +2315,7 @@ static int s3_phoenix_trio32_available(void) return rom_present(L"roms/video/s3/86c732p.bin"); } -static void *s3_trio64_init(device_t *info, wchar_t *bios_fn) +static void *s3_trio64_init(const device_t *info, wchar_t *bios_fn) { s3_t *s3 = s3_init(info, bios_fn, S3_TRIO64); @@ -2329,13 +2329,13 @@ static void *s3_trio64_init(device_t *info, wchar_t *bios_fn) return s3; } -static void *s3_9fx_init(device_t *info) +static void *s3_9fx_init(const device_t *info) { s3_t *s3 = s3_trio64_init(info, L"roms/video/s3/s3_764.bin"); return s3; } -static void *s3_phoenix_trio64_init(device_t *info) +static void *s3_phoenix_trio64_init(const device_t *info) { s3_t *s3 = s3_trio64_init(info, L"roms/video/s3/86c764x1.bin"); if (device_get_config_int("memory") == 1) @@ -2343,7 +2343,7 @@ static void *s3_phoenix_trio64_init(device_t *info) return s3; } -static void *s3_phoenix_trio64_onboard_init(device_t *info) +static void *s3_phoenix_trio64_onboard_init(const device_t *info) { s3_t *s3 = s3_trio64_init(info, NULL); if (device_get_config_int("memory") == 1) @@ -2351,7 +2351,7 @@ static void *s3_phoenix_trio64_onboard_init(device_t *info) return s3; } -static void *s3_diamond_stealth64_init(device_t *info) +static void *s3_diamond_stealth64_init(const device_t *info) { s3_t *s3 = s3_trio64_init(info, L"roms/video/s3/stealt64.bin"); if (device_get_config_int("memory") == 1) @@ -2419,7 +2419,7 @@ static void s3_add_status_info(char *s, int max_len, void *p) s3->blitter_time = 0; } -static device_config_t s3_bahamas64_config[] = +static const device_config_t s3_bahamas64_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 4, @@ -2444,7 +2444,7 @@ static device_config_t s3_bahamas64_config[] = } }; -static device_config_t s3_9fx_config[] = +static const device_config_t s3_9fx_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 2, @@ -2480,7 +2480,7 @@ static device_config_t s3_9fx_config[] = } }; -static device_config_t s3_phoenix_trio32_config[] = +static const device_config_t s3_phoenix_trio32_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 2, @@ -2504,7 +2504,7 @@ static device_config_t s3_phoenix_trio32_config[] = } }; -static device_config_t s3_phoenix_trio64_onboard_config[] = +static const device_config_t s3_phoenix_trio64_onboard_config[] = { { "memory", "Video memory size", CONFIG_SELECTION, "", 4, @@ -2528,7 +2528,7 @@ static device_config_t s3_phoenix_trio64_onboard_config[] = } }; -static device_config_t s3_phoenix_trio64_config[] = +static const device_config_t s3_phoenix_trio64_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 4, @@ -2552,7 +2552,7 @@ static device_config_t s3_phoenix_trio64_config[] = } }; -device_t s3_bahamas64_vlb_device = +const device_t s3_bahamas64_vlb_device = { "Paradise Bahamas 64 (S3 Vision864) VLB", DEVICE_VLB, @@ -2567,7 +2567,7 @@ device_t s3_bahamas64_vlb_device = s3_bahamas64_config }; -device_t s3_bahamas64_pci_device = +const device_t s3_bahamas64_pci_device = { "Paradise Bahamas 64 (S3 Vision864) PCI", DEVICE_PCI, @@ -2582,7 +2582,7 @@ device_t s3_bahamas64_pci_device = s3_bahamas64_config }; -device_t s3_9fx_vlb_device = +const device_t s3_9fx_vlb_device = { "Number 9 9FX (S3 Trio64) VLB", DEVICE_VLB, @@ -2597,7 +2597,7 @@ device_t s3_9fx_vlb_device = s3_9fx_config }; -device_t s3_9fx_pci_device = +const device_t s3_9fx_pci_device = { "Number 9 9FX (S3 Trio64) PCI", DEVICE_PCI, @@ -2612,7 +2612,7 @@ device_t s3_9fx_pci_device = s3_9fx_config }; -device_t s3_phoenix_trio32_vlb_device = +const device_t s3_phoenix_trio32_vlb_device = { "Phoenix S3 Trio32 VLB", DEVICE_VLB, @@ -2627,7 +2627,7 @@ device_t s3_phoenix_trio32_vlb_device = s3_phoenix_trio32_config }; -device_t s3_phoenix_trio32_pci_device = +const device_t s3_phoenix_trio32_pci_device = { "Phoenix S3 Trio32 PCI", DEVICE_PCI, @@ -2642,7 +2642,7 @@ device_t s3_phoenix_trio32_pci_device = s3_phoenix_trio32_config }; -device_t s3_phoenix_trio64_vlb_device = +const device_t s3_phoenix_trio64_vlb_device = { "Phoenix S3 Trio64 VLB", DEVICE_VLB, @@ -2657,7 +2657,7 @@ device_t s3_phoenix_trio64_vlb_device = s3_phoenix_trio64_config }; -device_t s3_phoenix_trio64_onboard_pci_device = +const device_t s3_phoenix_trio64_onboard_pci_device = { "Phoenix S3 Trio64 On-Board PCI", DEVICE_PCI, @@ -2672,7 +2672,7 @@ device_t s3_phoenix_trio64_onboard_pci_device = s3_phoenix_trio64_onboard_config }; -device_t s3_phoenix_trio64_pci_device = +const device_t s3_phoenix_trio64_pci_device = { "Phoenix S3 Trio64 PCI", DEVICE_PCI, @@ -2687,7 +2687,7 @@ device_t s3_phoenix_trio64_pci_device = s3_phoenix_trio64_config }; -device_t s3_phoenix_vision864_vlb_device = +const device_t s3_phoenix_vision864_vlb_device = { "Phoenix S3 Vision864 VLB", DEVICE_VLB, @@ -2702,7 +2702,7 @@ device_t s3_phoenix_vision864_vlb_device = s3_bahamas64_config }; -device_t s3_phoenix_vision864_pci_device = +const device_t s3_phoenix_vision864_pci_device = { "Phoenix S3 Vision864 PCI", DEVICE_PCI, @@ -2717,7 +2717,7 @@ device_t s3_phoenix_vision864_pci_device = s3_bahamas64_config }; -device_t s3_diamond_stealth64_vlb_device = +const device_t s3_diamond_stealth64_vlb_device = { "S3 Trio64 (Diamond Stealth64 DRAM) VLB", DEVICE_PCI, @@ -2732,7 +2732,7 @@ device_t s3_diamond_stealth64_vlb_device = s3_phoenix_trio64_config }; -device_t s3_diamond_stealth64_pci_device = +const device_t s3_diamond_stealth64_pci_device = { "S3 Trio64 (Diamond Stealth64 DRAM) PCI", DEVICE_PCI, diff --git a/src/video/vid_s3.h b/src/video/vid_s3.h index 071cee218..04888acdb 100644 --- a/src/video/vid_s3.h +++ b/src/video/vid_s3.h @@ -9,7 +9,7 @@ * Emulation of the S3 Trio32, S3 Trio64, and S3 Vision864 * graphics cards. * - * Version: @(#)vid_s3.h 1.0.1 2018/02/09 + * Version: @(#)vid_s3.h 1.0.2 2018/03/18 * * Author: Sarah Walker, * Miran Grca, @@ -17,17 +17,17 @@ * Copyright 2016-2018 Miran Grca. */ -device_t s3_bahamas64_vlb_device; -device_t s3_bahamas64_pci_device; -device_t s3_9fx_vlb_device; -device_t s3_9fx_pci_device; -device_t s3_phoenix_trio32_vlb_device; -device_t s3_phoenix_trio32_pci_device; -device_t s3_phoenix_trio64_vlb_device; -device_t s3_phoenix_trio64_onboard_pci_device; -device_t s3_phoenix_trio64_pci_device; -device_t s3_phoenix_vision864_pci_device; -device_t s3_phoenix_vision864_vlb_device; -device_t s3_diamond_stealth64_pci_device; -device_t s3_diamond_stealth64_vlb_device; -/* device_t s3_miro_vision964_device; */ +const device_t s3_bahamas64_vlb_device; +const device_t s3_bahamas64_pci_device; +const device_t s3_9fx_vlb_device; +const device_t s3_9fx_pci_device; +const device_t s3_phoenix_trio32_vlb_device; +const device_t s3_phoenix_trio32_pci_device; +const device_t s3_phoenix_trio64_vlb_device; +const device_t s3_phoenix_trio64_onboard_pci_device; +const device_t s3_phoenix_trio64_pci_device; +const device_t s3_phoenix_vision864_pci_device; +const device_t s3_phoenix_vision864_vlb_device; +const device_t s3_diamond_stealth64_pci_device; +const device_t s3_diamond_stealth64_vlb_device; +/* const device_t s3_miro_vision964_device; */ diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index 41a1eebe3..5747d1119 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -8,13 +8,13 @@ * * S3 ViRGE emulation. * - * Version: @(#)vid_s3_virge.c 1.0.5 2017/12/28 + * Version: @(#)vid_s3_virge.c 1.0.6 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -3773,7 +3773,7 @@ static void s3_virge_pci_write(int func, int addr, uint8_t val, void *p) } } -static void *s3_virge_init(device_t *info) +static void *s3_virge_init(const device_t *info) { virge_t *virge = malloc(sizeof(virge_t)); memset(virge, 0, sizeof(virge_t)); @@ -3873,7 +3873,7 @@ static void *s3_virge_init(device_t *info) return virge; } -static void *s3_virge_988_init(device_t *info) +static void *s3_virge_988_init(const device_t *info) { virge_t *virge = malloc(sizeof(virge_t)); memset(virge, 0, sizeof(virge_t)); @@ -3972,7 +3972,7 @@ static void *s3_virge_988_init(device_t *info) return virge; } -static void *s3_virge_375_init(device_t *info, wchar_t *romfn) +static void *s3_virge_375_init(const device_t *info, wchar_t *romfn) { virge_t *virge = malloc(sizeof(virge_t)); memset(virge, 0, sizeof(virge_t)); @@ -4072,12 +4072,12 @@ static void *s3_virge_375_init(device_t *info, wchar_t *romfn) return virge; } -static void *s3_virge_375_1_init(device_t *info) +static void *s3_virge_375_1_init(const device_t *info) { return s3_virge_375_init(info, L"roms/video/s3virge/86c375_1.bin"); } -static void *s3_virge_375_4_init(device_t *info) +static void *s3_virge_375_4_init(const device_t *info) { return s3_virge_375_init(info, L"roms/video/s3virge/86c375_4.bin"); } @@ -4160,7 +4160,7 @@ static void s3_virge_add_status_info(char *s, int max_len, void *p) reg_writes = 0; } -static device_config_t s3_virge_config[] = +static const device_config_t s3_virge_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 4, @@ -4187,7 +4187,7 @@ static device_config_t s3_virge_config[] = } }; -device_t s3_virge_vlb_device = +const device_t s3_virge_vlb_device = { "Diamond Stealth 3D 2000 (S3 ViRGE) VLB", DEVICE_VLB, @@ -4202,7 +4202,7 @@ device_t s3_virge_vlb_device = s3_virge_config }; -device_t s3_virge_pci_device = +const device_t s3_virge_pci_device = { "Diamond Stealth 3D 2000 (S3 ViRGE) PCI", DEVICE_PCI, @@ -4217,7 +4217,7 @@ device_t s3_virge_pci_device = s3_virge_config }; -device_t s3_virge_988_vlb_device = +const device_t s3_virge_988_vlb_device = { "Diamond Stealth 3D 3000 (S3 ViRGE/VX) VLB", DEVICE_VLB, @@ -4232,7 +4232,7 @@ device_t s3_virge_988_vlb_device = s3_virge_config }; -device_t s3_virge_988_pci_device = +const device_t s3_virge_988_pci_device = { "Diamond Stealth 3D 3000 (S3 ViRGE/VX) PCI", DEVICE_PCI, @@ -4247,7 +4247,7 @@ device_t s3_virge_988_pci_device = s3_virge_config }; -device_t s3_virge_375_vlb_device = +const device_t s3_virge_375_vlb_device = { "S3 ViRGE/DX VLB", DEVICE_VLB, @@ -4262,7 +4262,7 @@ device_t s3_virge_375_vlb_device = s3_virge_config }; -device_t s3_virge_375_pci_device = +const device_t s3_virge_375_pci_device = { "S3 ViRGE/DX PCI", DEVICE_PCI, @@ -4277,7 +4277,7 @@ device_t s3_virge_375_pci_device = s3_virge_config }; -device_t s3_virge_375_4_vlb_device = +const device_t s3_virge_375_4_vlb_device = { "S3 ViRGE/DX (VBE 2.0) VLB", DEVICE_VLB, @@ -4292,7 +4292,7 @@ device_t s3_virge_375_4_vlb_device = s3_virge_config }; -device_t s3_virge_375_4_pci_device = +const device_t s3_virge_375_4_pci_device = { "S3 ViRGE/DX (VBE 2.0) PCI", DEVICE_PCI, diff --git a/src/video/vid_s3_virge.h b/src/video/vid_s3_virge.h index 85389eb40..2d340f649 100644 --- a/src/video/vid_s3_virge.h +++ b/src/video/vid_s3_virge.h @@ -1,11 +1,11 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ -extern device_t s3_virge_vlb_device; -extern device_t s3_virge_pci_device; -extern device_t s3_virge_988_vlb_device; -extern device_t s3_virge_988_pci_device; -extern device_t s3_virge_375_vlb_device; -extern device_t s3_virge_375_pci_device; -extern device_t s3_virge_375_4_vlb_device; -extern device_t s3_virge_375_4_pci_device; +extern const device_t s3_virge_vlb_device; +extern const device_t s3_virge_pci_device; +extern const device_t s3_virge_988_vlb_device; +extern const device_t s3_virge_988_pci_device; +extern const device_t s3_virge_375_vlb_device; +extern const device_t s3_virge_375_pci_device; +extern const device_t s3_virge_375_4_vlb_device; +extern const device_t s3_virge_375_4_pci_device; diff --git a/src/video/vid_t1000.c b/src/video/vid_t1000.c deleted file mode 100644 index a71e10b8e..000000000 --- a/src/video/vid_t1000.c +++ /dev/null @@ -1,721 +0,0 @@ -/* Emulate the Toshiba 1000 plasma display. This display has a fixed 640x200 - * resolution. */ -#include -#include -#include -#include -#include - -#include "../86box.h" -#include "../device.h" -#include "../io.h" -#include "../mem.h" -#include "../timer.h" -#include "../cpu/cpu.h" -#include "video.h" -#include "vid_cga.h" -#include "vid_t1000.h" - -#define T1000_XSIZE 640 -#define T1000_YSIZE 200 - -/* Mapping of attributes to colours */ -static uint32_t blue, grey; -static uint8_t boldcols[256]; /* Which attributes use the bold font */ -static uint32_t blinkcols[256][2]; -static uint32_t normcols[256][2]; -static uint8_t language; - -/* Video options set by the motherboard; they will be picked up by the card - * on the next poll. - * - * Bit 1: Danish - * Bit 0: Thin font - */ -static uint8_t st_video_options; -static uint8_t st_display_internal = -1; - -void t1000_video_options_set(uint8_t options) -{ - st_video_options = options & 1; - st_video_options |= language; -} - -void t1000_display_set(uint8_t internal) -{ - st_display_internal = internal; -} - -uint8_t t1000_display_get() -{ - return st_display_internal; -} - - -typedef struct t1000_t -{ - mem_mapping_t mapping; - - cga_t cga; /* The CGA is used for the external - * display; most of its registers are - * ignored by the plasma display. */ - - int font; /* Current font, 0-3 */ - int enabled; /* Hardware enabled, 0 or 1 */ - int internal; /* Using internal display? */ - uint8_t attrmap; /* Attribute mapping register */ - - int dispontime, dispofftime; - - int linepos, displine; - int vc; - int dispon; - int vsynctime; - uint8_t video_options; - - uint8_t *vram; -} t1000_t; - - -static void t1000_recalctimings(t1000_t *t1000); -static void t1000_write(uint32_t addr, uint8_t val, void *p); -static uint8_t t1000_read(uint32_t addr, void *p); -static void t1000_recalcattrs(t1000_t *t1000); - - -static void t1000_out(uint16_t addr, uint8_t val, void *p) -{ - t1000_t *t1000 = (t1000_t *)p; - switch (addr) - { - /* Emulated CRTC, register select */ - case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6: - cga_out(addr, val, &t1000->cga); - break; - - /* Emulated CRTC, value */ - case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: - /* Register 0x12 controls the attribute mappings for the - * LCD screen. */ - if (t1000->cga.crtcreg == 0x12) - { - t1000->attrmap = val; - t1000_recalcattrs(t1000); - return; - } - cga_out(addr, val, &t1000->cga); - - t1000_recalctimings(t1000); - return; - - /* CGA control register */ - case 0x3D8: - cga_out(addr, val, &t1000->cga); - return; - /* CGA colour register */ - case 0x3D9: - cga_out(addr, val, &t1000->cga); - return; - } -} - -static uint8_t t1000_in(uint16_t addr, void *p) -{ - t1000_t *t1000 = (t1000_t *)p; - uint8_t val; - - switch (addr) - { - case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: - if (t1000->cga.crtcreg == 0x12) - { - val = t1000->attrmap & 0x0F; - if (t1000->internal) val |= 0x20; /* LCD / CRT */ - return val; - } - } - - return cga_in(addr, &t1000->cga); -} - - - - -static void t1000_write(uint32_t addr, uint8_t val, void *p) -{ - t1000_t *t1000 = (t1000_t *)p; - egawrites++; - -// pclog("CGA_WRITE %04X %02X\n", addr, val); - t1000->vram[addr & 0x3fff] = val; - cycles -= 4; -} - -static uint8_t t1000_read(uint32_t addr, void *p) -{ - t1000_t *t1000 = (t1000_t *)p; - egareads++; - cycles -= 4; - -// pclog("CGA_READ %04X\n", addr); - return t1000->vram[addr & 0x3fff]; -} - - - -static void t1000_recalctimings(t1000_t *t1000) -{ - double disptime; - double _dispontime, _dispofftime; - - if (!t1000->internal) - { - cga_recalctimings(&t1000->cga); - return; - } - disptime = 651; - _dispontime = 640; - _dispofftime = disptime - _dispontime; - t1000->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - t1000->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); -} - -/* Draw a row of text in 80-column mode */ -static void t1000_text_row80(t1000_t *t1000) -{ - uint32_t cols[2]; - int x, c; - uint8_t chr, attr; - int drawcursor; - int cursorline; - int bold; - int blink; - uint16_t addr; - uint8_t sc; - uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff; - uint16_t ca = (t1000->cga.crtc[15] | (t1000->cga.crtc[14] << 8)) & 0x3fff; - - sc = (t1000->displine) & 7; - addr = ((ma & ~1) + (t1000->displine >> 3) * 80) * 2; - ma += (t1000->displine >> 3) * 80; - - if ((t1000->cga.crtc[10] & 0x60) == 0x20) - { - cursorline = 0; - } - else - { - cursorline = ((t1000->cga.crtc[10] & 0x0F) <= sc) && - ((t1000->cga.crtc[11] & 0x0F) >= sc); - } - for (x = 0; x < 80; x++) - { - chr = t1000->vram[(addr + 2 * x) & 0x3FFF]; - attr = t1000->vram[(addr + 2 * x + 1) & 0x3FFF]; - drawcursor = ((ma == ca) && cursorline && - (t1000->cga.cgamode & 8) && (t1000->cga.cgablink & 16)); - - blink = ((t1000->cga.cgablink & 16) && (t1000->cga.cgamode & 0x20) && - (attr & 0x80) && !drawcursor); - - if (t1000->video_options & 1) - bold = boldcols[attr] ? chr : chr + 256; - else - bold = boldcols[attr] ? chr + 256 : chr; - if (t1000->video_options & 2) - bold += 512; - - if (t1000->cga.cgamode & 0x20) /* Blink */ - { - cols[1] = blinkcols[attr][1]; - cols[0] = blinkcols[attr][0]; - if (blink) cols[1] = cols[0]; - } - else - { - cols[1] = normcols[attr][1]; - cols[0] = normcols[attr][0]; - } - if (drawcursor) - { - for (c = 0; c < 8; c++) - { - ((uint32_t *)buffer32->line[t1000->displine])[(x << 3) + c] = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (blue ^ grey); - } - } - else - { - for (c = 0; c < 8; c++) - ((uint32_t *)buffer32->line[t1000->displine])[(x << 3) + c] = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; - } - ++ma; - } -} - -/* Draw a row of text in 40-column mode */ -static void t1000_text_row40(t1000_t *t1000) -{ - uint32_t cols[2]; - int x, c; - uint8_t chr, attr; - int drawcursor; - int cursorline; - int bold; - int blink; - uint16_t addr; - uint8_t sc; - uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff; - uint16_t ca = (t1000->cga.crtc[15] | (t1000->cga.crtc[14] << 8)) & 0x3fff; - - sc = (t1000->displine) & 7; - addr = ((ma & ~1) + (t1000->displine >> 3) * 40) * 2; - ma += (t1000->displine >> 3) * 40; - - if ((t1000->cga.crtc[10] & 0x60) == 0x20) - { - cursorline = 0; - } - else - { - cursorline = ((t1000->cga.crtc[10] & 0x0F) <= sc) && - ((t1000->cga.crtc[11] & 0x0F) >= sc); - } - for (x = 0; x < 40; x++) - { - chr = t1000->vram[(addr + 2 * x) & 0x3FFF]; - attr = t1000->vram[(addr + 2 * x + 1) & 0x3FFF]; - drawcursor = ((ma == ca) && cursorline && - (t1000->cga.cgamode & 8) && (t1000->cga.cgablink & 16)); - - blink = ((t1000->cga.cgablink & 16) && (t1000->cga.cgamode & 0x20) && - (attr & 0x80) && !drawcursor); - - if (t1000->video_options & 1) - bold = boldcols[attr] ? chr : chr + 256; - else - bold = boldcols[attr] ? chr + 256 : chr; - if (t1000->video_options & 2) - bold += 512; - - if (t1000->cga.cgamode & 0x20) /* Blink */ - { - cols[1] = blinkcols[attr][1]; - cols[0] = blinkcols[attr][0]; - if (blink) cols[1] = cols[0]; - } - else - { - cols[1] = normcols[attr][1]; - cols[0] = normcols[attr][0]; - } - if (drawcursor) - { - for (c = 0; c < 8; c++) - { - ((uint32_t *)buffer32->line[t1000->displine])[(x << 4) + c*2] = - ((uint32_t *)buffer32->line[t1000->displine])[(x << 4) + c*2 + 1] = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (blue ^ grey); - } - } - else - { - for (c = 0; c < 8; c++) - { - ((uint32_t *)buffer32->line[t1000->displine])[(x << 4) + c*2] = - ((uint32_t *)buffer32->line[t1000->displine])[(x << 4) + c*2+1] = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - ++ma; - } -} - -/* Draw a line in CGA 640x200 mode */ -static void t1000_cgaline6(t1000_t *t1000) -{ - int x, c; - uint8_t dat; - uint32_t ink = 0; - uint16_t addr; - uint32_t fg = (t1000->cga.cgacol & 0x0F) ? blue : grey; - uint32_t bg = grey; - - uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff; - - addr = ((t1000->displine) & 1) * 0x2000 + - (t1000->displine >> 1) * 80 + - ((ma & ~1) << 1); - - for (x = 0; x < 80; x++) - { - dat = t1000->vram[addr & 0x3FFF]; - addr++; - - for (c = 0; c < 8; c++) - { - ink = (dat & 0x80) ? fg : bg; - if (!(t1000->cga.cgamode & 8)) - ink = grey; - ((uint32_t *)buffer32->line[t1000->displine])[x*8+c] = ink; - dat = dat << 1; - } - } -} - -/* Draw a line in CGA 320x200 mode. Here the CGA colours are converted to - * dither patterns: colour 1 to 25% grey, colour 2 to 50% grey */ -static void t1000_cgaline4(t1000_t *t1000) -{ - int x, c; - uint8_t dat, pattern; - uint32_t ink0 = 0, ink1 = 0; - uint16_t addr; - - uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff; - addr = ((t1000->displine) & 1) * 0x2000 + - (t1000->displine >> 1) * 80 + - ((ma & ~1) << 1); - - for (x = 0; x < 80; x++) - { - dat = t1000->vram[addr & 0x3FFF]; - addr++; - - for (c = 0; c < 4; c++) - { - pattern = (dat & 0xC0) >> 6; - if (!(t1000->cga.cgamode & 8)) pattern = 0; - - switch (pattern & 3) - { - case 0: ink0 = ink1 = grey; break; - case 1: if (t1000->displine & 1) - { - ink0 = grey; ink1 = grey; - } - else - { - ink0 = blue; ink1 = grey; - } - break; - case 2: if (t1000->displine & 1) - { - ink0 = grey; ink1 = blue; - } - else - { - ink0 = blue; ink1 = grey; - } - break; - case 3: ink0 = ink1 = blue; break; - - } - ((uint32_t *)buffer32->line[t1000->displine])[x*8+2*c] = ink0; - ((uint32_t *)buffer32->line[t1000->displine])[x*8+2*c+1] = ink1; - dat = dat << 2; - } - } -} - -static void t1000_poll(void *p) -{ - t1000_t *t1000 = (t1000_t *)p; - - if (t1000->video_options != st_video_options) - { - t1000->video_options = st_video_options; - - /* Set the font used for the external display */ - t1000->cga.fontbase = ((t1000->video_options & 3) * 256); - } - /* Switch between internal plasma and external CRT display. */ - if (st_display_internal != -1 && st_display_internal != t1000->internal) - { - t1000->internal = st_display_internal; - t1000_recalctimings(t1000); - } - if (!t1000->internal) - { - cga_poll(&t1000->cga); - return; - } - - if (!t1000->linepos) - { - t1000->cga.vidtime += t1000->dispofftime; - t1000->cga.cgastat |= 1; - t1000->linepos = 1; - if (t1000->dispon) - { - if (t1000->displine == 0) - { - video_wait_for_buffer(); - } - - /* Graphics */ - if (t1000->cga.cgamode & 0x02) - { - if (t1000->cga.cgamode & 0x10) - t1000_cgaline6(t1000); - else t1000_cgaline4(t1000); - } - else - if (t1000->cga.cgamode & 0x01) /* High-res text */ - { - t1000_text_row80(t1000); - } - else - { - t1000_text_row40(t1000); - } - } - t1000->displine++; - /* Hardcode a fixed refresh rate and VSYNC timing */ - if (t1000->displine == 200) /* Start of VSYNC */ - { - t1000->cga.cgastat |= 8; - t1000->dispon = 0; - } - if (t1000->displine == 216) /* End of VSYNC */ - { - t1000->displine = 0; - t1000->cga.cgastat &= ~8; - t1000->dispon = 1; - } - } - else - { - if (t1000->dispon) - { - t1000->cga.cgastat &= ~1; - } - t1000->cga.vidtime += t1000->dispontime; - t1000->linepos = 0; - - if (t1000->displine == 200) - { - /* Hardcode 640x200 window size */ - if (T1000_XSIZE != xsize || T1000_YSIZE != ysize) - { - xsize = T1000_XSIZE; - ysize = T1000_YSIZE; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, ysize); - } - video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize); - - frames++; - /* Fixed 640x200 resolution */ - video_res_x = T1000_XSIZE; - video_res_y = T1000_YSIZE; - - if (t1000->cga.cgamode & 0x02) - { - if (t1000->cga.cgamode & 0x10) - video_bpp = 1; - else video_bpp = 2; - - } - else video_bpp = 0; - t1000->cga.cgablink++; - } - } -} - -static void t1000_recalcattrs(t1000_t *t1000) -{ - int n; - - /* val behaves as follows: - * Bit 0: Attributes 01-06, 08-0E are inverse video - * Bit 1: Attributes 01-06, 08-0E are bold - * Bit 2: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF - * are inverse video - * Bit 3: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF - * are bold */ - - /* Set up colours */ - blue = makecol(0x2D, 0x39, 0x5A); - grey = makecol(0x85, 0xa0, 0xD6); - - /* Initialise the attribute mapping. Start by defaulting everything - * to grey on blue, and with bold set by bit 3 */ - for (n = 0; n < 256; n++) - { - boldcols[n] = (n & 8) != 0; - blinkcols[n][0] = normcols[n][0] = blue; - blinkcols[n][1] = normcols[n][1] = grey; - } - - /* Colours 0x11-0xFF are controlled by bits 2 and 3 of the - * passed value. Exclude x0 and x8, which are always grey on - * blue. */ - for (n = 0x11; n <= 0xFF; n++) - { - if ((n & 7) == 0) continue; - if (t1000->attrmap & 4) /* Inverse */ - { - blinkcols[n][0] = normcols[n][0] = blue; - blinkcols[n][1] = normcols[n][1] = grey; - } - else /* Normal */ - { - blinkcols[n][0] = normcols[n][0] = grey; - blinkcols[n][1] = normcols[n][1] = blue; - } - if (t1000->attrmap & 8) boldcols[n] = 1; /* Bold */ - } - /* Set up the 01-0E range, controlled by bits 0 and 1 of the - * passed value. When blinking is enabled this also affects 81-8E. */ - for (n = 0x01; n <= 0x0E; n++) - { - if (n == 7) continue; - if (t1000->attrmap & 1) - { - blinkcols[n][0] = normcols[n][0] = blue; - blinkcols[n][1] = normcols[n][1] = grey; - blinkcols[n+128][0] = blue; - blinkcols[n+128][1] = grey; - } - else - { - blinkcols[n][0] = normcols[n][0] = grey; - blinkcols[n][1] = normcols[n][1] = blue; - blinkcols[n+128][0] = grey; - blinkcols[n+128][1] = blue; - } - if (t1000->attrmap & 2) boldcols[n] = 1; - } - /* Colours 07 and 0F are always blue on grey. If blinking is - * enabled so are 87 and 8F. */ - for (n = 0x07; n <= 0x0F; n += 8) - { - blinkcols[n][0] = normcols[n][0] = grey; - blinkcols[n][1] = normcols[n][1] = blue; - blinkcols[n+128][0] = grey; - blinkcols[n+128][1] = blue; - } - /* When not blinking, colours 81-8F are always blue on grey. */ - for (n = 0x81; n <= 0x8F; n ++) - { - normcols[n][0] = grey; - normcols[n][1] = blue; - boldcols[n] = (n & 0x08) != 0; - } - - - /* Finally do the ones which are solid grey. These differ between - * the normal and blinking mappings */ - for (n = 0; n <= 0xFF; n += 0x11) - { - normcols[n][0] = normcols[n][1] = grey; - } - /* In the blinking range, 00 11 22 .. 77 and 80 91 A2 .. F7 are grey */ - for (n = 0; n <= 0x77; n += 0x11) - { - blinkcols[n][0] = blinkcols[n][1] = grey; - blinkcols[n+128][0] = blinkcols[n+128][1] = grey; - } -} - - -static void *t1000_init(device_t *info) -{ - t1000_t *t1000 = malloc(sizeof(t1000_t)); - memset(t1000, 0, sizeof(t1000_t)); - cga_init(&t1000->cga); - - t1000->internal = 1; - - /* 16k video RAM */ - t1000->vram = malloc(0x4000); - - timer_add(t1000_poll, &t1000->cga.vidtime, TIMER_ALWAYS_ENABLED, t1000); - - /* Occupy memory between 0xB8000 and 0xBFFFF */ - mem_mapping_add(&t1000->mapping, 0xb8000, 0x8000, t1000_read, NULL, NULL, t1000_write, NULL, NULL, NULL, 0, t1000); - /* Respond to CGA I/O ports */ - io_sethandler(0x03d0, 0x000c, t1000_in, NULL, NULL, t1000_out, NULL, NULL, t1000); - - /* Default attribute mapping is 4 */ - t1000->attrmap = 4; - t1000_recalcattrs(t1000); - - /* Start off in 80x25 text mode */ - t1000->cga.cgastat = 0xF4; - t1000->cga.vram = t1000->vram; - t1000->enabled = 1; - t1000->video_options = 0x01; - language = device_get_config_int("display_language") ? 2 : 0; - return t1000; -} - -static void t1000_close(void *p) -{ - t1000_t *t1000 = (t1000_t *)p; - - free(t1000->vram); - free(t1000); -} - -static void t1000_speed_changed(void *p) -{ - t1000_t *t1000 = (t1000_t *)p; - - t1000_recalctimings(t1000); -} - -static device_config_t t1000_config[] = -{ - { - .name = "display_language", - .description = "Language", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "USA", - .value = 0 - }, - { - .description = "Danish", - .value = 1 - } - }, - .default_int = 0 - }, - { - .type = -1 - } -}; - - -device_t t1000_device = -{ - "Toshiba T1000", - 0, - 0, - t1000_init, - t1000_close, - NULL, - NULL, - t1000_speed_changed, - NULL, - NULL, - t1000_config -}; - - -device_t t1200_device = -{ - "Toshiba T1200", - 0, - 0, - t1000_init, - t1000_close, - NULL, - NULL, - t1000_speed_changed, - NULL, - NULL, - t1000_config -}; diff --git a/src/video/vid_t1000.h b/src/video/vid_t1000.h deleted file mode 100644 index bfd292a5f..000000000 --- a/src/video/vid_t1000.h +++ /dev/null @@ -1,5 +0,0 @@ -extern device_t t1000_device; -extern device_t t1200_device; - -void t1000_video_options_set(uint8_t options); -void t1000_display_set(uint8_t internal); diff --git a/src/video/vid_t3100e.c b/src/video/vid_t3100e.c deleted file mode 100644 index e7ce5e45b..000000000 --- a/src/video/vid_t3100e.c +++ /dev/null @@ -1,726 +0,0 @@ -/* Emulate the Toshiba 3100e plasma display. This display has a fixed 640x400 - * resolution. */ -#include -#include -#include -#include -#include - -#include "../86box.h" -#include "../device.h" -#include "../io.h" -#include "../mem.h" -#include "../timer.h" -#include "../cpu/cpu.h" -#include "video.h" -#include "vid_cga.h" -#include "vid_t3100e.h" - -#define T3100E_XSIZE 640 -#define T3100E_YSIZE 400 - -/* T3100e CRTC regs (from the ROM): - * - * Selecting a character height of 3 seems to be sufficient to convert the - * 640x200 graphics mode to 640x400 (and, by analogy, 320x200 to 320x400). - * - * - * Horiz-----> Vert------> I ch - * 38 28 2D 0A 1F 06 19 1C 02 07 06 07 CO40 - * 71 50 5A 0A 1F 06 19 1C 02 07 06 07 CO80 - * 38 28 2D 0A 7F 06 64 70 02 01 06 07 Graphics - * 61 50 52 0F 19 06 19 19 02 0D 0B 0C MONO - * 2D 28 22 0A 67 00 64 67 02 03 06 07 640x400 - */ - -/* Mapping of attributes to colours */ -static uint32_t amber, black; -static uint8_t boldcols[256]; /* Which attributes use the bold font */ -static uint32_t blinkcols[256][2]; -static uint32_t normcols[256][2]; - -/* Video options set by the motherboard; they will be picked up by the card - * on the next poll. - * - * Bit 3: Disable built-in video (for add-on card) - * Bit 2: Thin font - * Bits 0,1: Font set (not currently implemented) - */ -static uint8_t st_video_options; -static uint8_t st_display_internal = -1; - -void t3100e_video_options_set(uint8_t options) -{ - st_video_options = options; -} - -void t3100e_display_set(uint8_t internal) -{ - st_display_internal = internal; -} - -uint8_t t3100e_display_get() -{ - return st_display_internal; -} - - -typedef struct t3100e_t -{ - mem_mapping_t mapping; - - cga_t cga; /* The CGA is used for the external - * display; most of its registers are - * ignored by the plasma display. */ - - int font; /* Current font, 0-3 */ - int enabled; /* Hardware enabled, 0 or 1 */ - int internal; /* Using internal display? */ - uint8_t attrmap; /* Attribute mapping register */ - - int dispontime, dispofftime; - - int linepos, displine; - int vc; - int dispon; - int vsynctime; - uint8_t video_options; - - uint8_t *vram; -} t3100e_t; - - -void t3100e_recalctimings(t3100e_t *t3100e); -void t3100e_write(uint32_t addr, uint8_t val, void *p); -uint8_t t3100e_read(uint32_t addr, void *p); -void t3100e_recalcattrs(t3100e_t *t3100e); - - -void t3100e_out(uint16_t addr, uint8_t val, void *p) -{ - t3100e_t *t3100e = (t3100e_t *)p; - switch (addr) - { - /* Emulated CRTC, register select */ - case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6: - cga_out(addr, val, &t3100e->cga); - break; - - /* Emulated CRTC, value */ - case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: - /* Register 0x12 controls the attribute mappings for the - * plasma screen. */ - if (t3100e->cga.crtcreg == 0x12) - { - t3100e->attrmap = val; - t3100e_recalcattrs(t3100e); - return; - } - cga_out(addr, val, &t3100e->cga); - - t3100e_recalctimings(t3100e); - return; - - /* CGA control register */ - case 0x3D8: - cga_out(addr, val, &t3100e->cga); - return; - /* CGA colour register */ - case 0x3D9: - cga_out(addr, val, &t3100e->cga); - return; - } -} - -uint8_t t3100e_in(uint16_t addr, void *p) -{ - t3100e_t *t3100e = (t3100e_t *)p; - uint8_t val; - - switch (addr) - { - case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: - if (t3100e->cga.crtcreg == 0x12) - { - val = t3100e->attrmap & 0x0F; - if (t3100e->internal) val |= 0x30; /* Plasma / CRT */ - return val; - } - } - - return cga_in(addr, &t3100e->cga); -} - - - - -void t3100e_write(uint32_t addr, uint8_t val, void *p) -{ - t3100e_t *t3100e = (t3100e_t *)p; - egawrites++; - -// pclog("CGA_WRITE %04X %02X\n", addr, val); - t3100e->vram[addr & 0x7fff] = val; - cycles -= 4; -} - - - -uint8_t t3100e_read(uint32_t addr, void *p) -{ - t3100e_t *t3100e = (t3100e_t *)p; - egareads++; - cycles -= 4; - -// pclog("CGA_READ %04X\n", addr); - return t3100e->vram[addr & 0x7fff]; -} - - - -void t3100e_recalctimings(t3100e_t *t3100e) -{ - double disptime; - double _dispontime, _dispofftime; - - if (!t3100e->internal) - { - cga_recalctimings(&t3100e->cga); - return; - } - disptime = 651; - _dispontime = 640; - _dispofftime = disptime - _dispontime; - t3100e->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - t3100e->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); -} - - -/* Draw a row of text in 80-column mode */ -void t3100e_text_row80(t3100e_t *t3100e) -{ - uint32_t cols[2]; - int x, c; - uint8_t chr, attr; - int drawcursor; - int cursorline; - int bold; - int blink; - uint16_t addr; - uint8_t sc; - uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; - uint16_t ca = (t3100e->cga.crtc[15] | (t3100e->cga.crtc[14] << 8)) & 0x7fff; - - sc = (t3100e->displine) & 15; - addr = ((ma & ~1) + (t3100e->displine >> 4) * 80) * 2; - ma += (t3100e->displine >> 4) * 80; - - if ((t3100e->cga.crtc[10] & 0x60) == 0x20) - { - cursorline = 0; - } - else - { - cursorline = ((t3100e->cga.crtc[10] & 0x0F)*2 <= sc) && - ((t3100e->cga.crtc[11] & 0x0F)*2 >= sc); - } - for (x = 0; x < 80; x++) - { - chr = t3100e->vram[(addr + 2 * x) & 0x7FFF]; - attr = t3100e->vram[(addr + 2 * x + 1) & 0x7FFF]; - drawcursor = ((ma == ca) && cursorline && - (t3100e->cga.cgamode & 8) && (t3100e->cga.cgablink & 16)); - - blink = ((t3100e->cga.cgablink & 16) && (t3100e->cga.cgamode & 0x20) && - (attr & 0x80) && !drawcursor); - - if (t3100e->video_options & 4) - bold = boldcols[attr] ? chr + 256 : chr; - else - bold = boldcols[attr] ? chr : chr + 256; - bold += 512 * (t3100e->video_options & 3); - - if (t3100e->cga.cgamode & 0x20) /* Blink */ - { - cols[1] = blinkcols[attr][1]; - cols[0] = blinkcols[attr][0]; - if (blink) cols[1] = cols[0]; - } - else - { - cols[1] = normcols[attr][1]; - cols[0] = normcols[attr][0]; - } - if (drawcursor) - { - for (c = 0; c < 8; c++) - { - ((uint32_t *)buffer32->line[t3100e->displine])[(x << 3) + c] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); - } - } - else - { - for (c = 0; c < 8; c++) - ((uint32_t *)buffer32->line[t3100e->displine])[(x << 3) + c] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; - } - ++ma; - } -} - -/* Draw a row of text in 40-column mode */ -void t3100e_text_row40(t3100e_t *t3100e) -{ - uint32_t cols[2]; - int x, c; - uint8_t chr, attr; - int drawcursor; - int cursorline; - int bold; - int blink; - uint16_t addr; - uint8_t sc; - uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; - uint16_t ca = (t3100e->cga.crtc[15] | (t3100e->cga.crtc[14] << 8)) & 0x7fff; - - sc = (t3100e->displine) & 15; - addr = ((ma & ~1) + (t3100e->displine >> 4) * 40) * 2; - ma += (t3100e->displine >> 4) * 40; - - if ((t3100e->cga.crtc[10] & 0x60) == 0x20) - { - cursorline = 0; - } - else - { - cursorline = ((t3100e->cga.crtc[10] & 0x0F)*2 <= sc) && - ((t3100e->cga.crtc[11] & 0x0F)*2 >= sc); - } - for (x = 0; x < 40; x++) - { - chr = t3100e->vram[(addr + 2 * x) & 0x7FFF]; - attr = t3100e->vram[(addr + 2 * x + 1) & 0x7FFF]; - drawcursor = ((ma == ca) && cursorline && - (t3100e->cga.cgamode & 8) && (t3100e->cga.cgablink & 16)); - - blink = ((t3100e->cga.cgablink & 16) && (t3100e->cga.cgamode & 0x20) && - (attr & 0x80) && !drawcursor); - - if (t3100e->video_options & 4) - bold = boldcols[attr] ? chr + 256 : chr; - else bold = boldcols[attr] ? chr : chr + 256; - bold += 512 * (t3100e->video_options & 3); - - if (t3100e->cga.cgamode & 0x20) /* Blink */ - { - cols[1] = blinkcols[attr][1]; - cols[0] = blinkcols[attr][0]; - if (blink) cols[1] = cols[0]; - } - else - { - cols[1] = normcols[attr][1]; - cols[0] = normcols[attr][0]; - } - if (drawcursor) - { - for (c = 0; c < 8; c++) - { - ((uint32_t *)buffer32->line[t3100e->displine])[(x << 4) + c*2] = - ((uint32_t *)buffer32->line[t3100e->displine])[(x << 4) + c*2 + 1] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); - } - } - else - { - for (c = 0; c < 8; c++) - { - ((uint32_t *)buffer32->line[t3100e->displine])[(x << 4) + c*2] = - ((uint32_t *)buffer32->line[t3100e->displine])[(x << 4) + c*2+1] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - ++ma; - } -} - - - - -/* Draw a line in CGA 640x200 or T3100e 640x400 mode */ -void t3100e_cgaline6(t3100e_t *t3100e) -{ - int x, c; - uint8_t dat; - uint32_t ink = 0; - uint16_t addr; - uint32_t fg = (t3100e->cga.cgacol & 0x0F) ? amber : black; - uint32_t bg = black; - - uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; - - if (t3100e->cga.crtc[9] == 3) /* 640*400 */ - { - addr = ((t3100e->displine) & 1) * 0x2000 + - ((t3100e->displine >> 1) & 1) * 0x4000 + - (t3100e->displine >> 2) * 80 + - ((ma & ~1) << 1); - } - else - { - addr = ((t3100e->displine >> 1) & 1) * 0x2000 + - (t3100e->displine >> 2) * 80 + - ((ma & ~1) << 1); - } - for (x = 0; x < 80; x++) - { - dat = t3100e->vram[addr & 0x7FFF]; - addr++; - - for (c = 0; c < 8; c++) - { - ink = (dat & 0x80) ? fg : bg; - if (!(t3100e->cga.cgamode & 8)) ink = black; - ((uint32_t *)buffer32->line[t3100e->displine])[x*8+c] = ink; - dat = dat << 1; - } - } -} - - -/* Draw a line in CGA 320x200 mode. Here the CGA colours are converted to - * dither patterns: colour 1 to 25% grey, colour 2 to 50% grey */ -void t3100e_cgaline4(t3100e_t *t3100e) -{ - int x, c; - uint8_t dat, pattern; - uint32_t ink0 = 0, ink1 = 0; - uint16_t addr; - - uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; - if (t3100e->cga.crtc[9] == 3) /* 320*400 undocumented */ - { - addr = ((t3100e->displine) & 1) * 0x2000 + - ((t3100e->displine >> 1) & 1) * 0x4000 + - (t3100e->displine >> 2) * 80 + - ((ma & ~1) << 1); - } - else /* 320*200 */ - { - addr = ((t3100e->displine >> 1) & 1) * 0x2000 + - (t3100e->displine >> 2) * 80 + - ((ma & ~1) << 1); - } - for (x = 0; x < 80; x++) - { - dat = t3100e->vram[addr & 0x7FFF]; - addr++; - - for (c = 0; c < 4; c++) - { - pattern = (dat & 0xC0) >> 6; - if (!(t3100e->cga.cgamode & 8)) pattern = 0; - - switch (pattern & 3) - { - case 0: ink0 = ink1 = black; break; - case 1: if (t3100e->displine & 1) - { - ink0 = black; ink1 = black; - } - else - { - ink0 = amber; ink1 = black; - } - break; - case 2: if (t3100e->displine & 1) - { - ink0 = black; ink1 = amber; - } - else - { - ink0 = amber; ink1 = black; - } - break; - case 3: ink0 = ink1 = amber; break; - - } - ((uint32_t *)buffer32->line[t3100e->displine])[x*8+2*c] = ink0; - ((uint32_t *)buffer32->line[t3100e->displine])[x*8+2*c+1] = ink1; - dat = dat << 2; - } - } -} - - - - - - -void t3100e_poll(void *p) -{ - t3100e_t *t3100e = (t3100e_t *)p; - - if (t3100e->video_options != st_video_options) - { - t3100e->video_options = st_video_options; - - if (t3100e->video_options & 8) /* Disable internal CGA */ - mem_mapping_disable(&t3100e->mapping); - else mem_mapping_enable(&t3100e->mapping); - - /* Set the font used for the external display */ - t3100e->cga.fontbase = (512 * (t3100e->video_options & 3)) - + ((t3100e->video_options & 4) ? 256 : 0); - - } - /* Switch between internal plasma and external CRT display. */ - if (st_display_internal != -1 && st_display_internal != t3100e->internal) - { - t3100e->internal = st_display_internal; - t3100e_recalctimings(t3100e); - } - if (!t3100e->internal) - { - cga_poll(&t3100e->cga); - return; - } - - - if (!t3100e->linepos) - { - t3100e->cga.vidtime += t3100e->dispofftime; - t3100e->cga.cgastat |= 1; - t3100e->linepos = 1; - if (t3100e->dispon) - { - if (t3100e->displine == 0) - { - video_wait_for_buffer(); - } - - /* Graphics */ - if (t3100e->cga.cgamode & 0x02) - { - if (t3100e->cga.cgamode & 0x10) - t3100e_cgaline6(t3100e); - else t3100e_cgaline4(t3100e); - } - else - if (t3100e->cga.cgamode & 0x01) /* High-res text */ - { - t3100e_text_row80(t3100e); - } - else - { - t3100e_text_row40(t3100e); - } - } - t3100e->displine++; - /* Hardcode a fixed refresh rate and VSYNC timing */ - if (t3100e->displine == 400) /* Start of VSYNC */ - { - t3100e->cga.cgastat |= 8; - t3100e->dispon = 0; - } - if (t3100e->displine == 416) /* End of VSYNC */ - { - t3100e->displine = 0; - t3100e->cga.cgastat &= ~8; - t3100e->dispon = 1; - } - } - else - { - if (t3100e->dispon) - { - t3100e->cga.cgastat &= ~1; - } - t3100e->cga.vidtime += t3100e->dispontime; - t3100e->linepos = 0; - - if (t3100e->displine == 400) - { -/* Hardcode 640x400 window size */ - if (T3100E_XSIZE != xsize || T3100E_YSIZE != ysize) - { - xsize = T3100E_XSIZE; - ysize = T3100E_YSIZE; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, ysize); - } - video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize); - - frames++; - /* Fixed 640x400 resolution */ - video_res_x = T3100E_XSIZE; - video_res_y = T3100E_YSIZE; - - if (t3100e->cga.cgamode & 0x02) - { - if (t3100e->cga.cgamode & 0x10) - video_bpp = 1; - else video_bpp = 2; - - } - else video_bpp = 0; - t3100e->cga.cgablink++; - } - } -} - - - -void t3100e_recalcattrs(t3100e_t *t3100e) -{ - int n; - - /* val behaves as follows: - * Bit 0: Attributes 01-06, 08-0E are inverse video - * Bit 1: Attributes 01-06, 08-0E are bold - * Bit 2: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF - * are inverse video - * Bit 3: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF - * are bold */ - - /* Set up colours */ - amber = makecol(0xf7, 0x7C, 0x34); - black = makecol(0x17, 0x0C, 0x00); - - /* Initialise the attribute mapping. Start by defaulting everything - * to black on amber, and with bold set by bit 3 */ - for (n = 0; n < 256; n++) - { - boldcols[n] = (n & 8) != 0; - blinkcols[n][0] = normcols[n][0] = amber; - blinkcols[n][1] = normcols[n][1] = black; - } - - /* Colours 0x11-0xFF are controlled by bits 2 and 3 of the - * passed value. Exclude x0 and x8, which are always black on - * amber. */ - for (n = 0x11; n <= 0xFF; n++) - { - if ((n & 7) == 0) continue; - if (t3100e->attrmap & 4) /* Inverse */ - { - blinkcols[n][0] = normcols[n][0] = amber; - blinkcols[n][1] = normcols[n][1] = black; - } - else /* Normal */ - { - blinkcols[n][0] = normcols[n][0] = black; - blinkcols[n][1] = normcols[n][1] = amber; - } - if (t3100e->attrmap & 8) boldcols[n] = 1; /* Bold */ - } - /* Set up the 01-0E range, controlled by bits 0 and 1 of the - * passed value. When blinking is enabled this also affects 81-8E. */ - for (n = 0x01; n <= 0x0E; n++) - { - if (n == 7) continue; - if (t3100e->attrmap & 1) - { - blinkcols[n][0] = normcols[n][0] = amber; - blinkcols[n][1] = normcols[n][1] = black; - blinkcols[n+128][0] = amber; - blinkcols[n+128][1] = black; - } - else - { - blinkcols[n][0] = normcols[n][0] = black; - blinkcols[n][1] = normcols[n][1] = amber; - blinkcols[n+128][0] = black; - blinkcols[n+128][1] = amber; - } - if (t3100e->attrmap & 2) boldcols[n] = 1; - } - /* Colours 07 and 0F are always amber on black. If blinking is - * enabled so are 87 and 8F. */ - for (n = 0x07; n <= 0x0F; n += 8) - { - blinkcols[n][0] = normcols[n][0] = black; - blinkcols[n][1] = normcols[n][1] = amber; - blinkcols[n+128][0] = black; - blinkcols[n+128][1] = amber; - } - /* When not blinking, colours 81-8F are always amber on black. */ - for (n = 0x81; n <= 0x8F; n ++) - { - normcols[n][0] = black; - normcols[n][1] = amber; - boldcols[n] = (n & 0x08) != 0; - } - - - /* Finally do the ones which are solid black. These differ between - * the normal and blinking mappings */ - for (n = 0; n <= 0xFF; n += 0x11) - { - normcols[n][0] = normcols[n][1] = black; - } - /* In the blinking range, 00 11 22 .. 77 and 80 91 A2 .. F7 are black */ - for (n = 0; n <= 0x77; n += 0x11) - { - blinkcols[n][0] = blinkcols[n][1] = black; - blinkcols[n+128][0] = blinkcols[n+128][1] = black; - } -} - - -void *t3100e_init(device_t *info) -{ - t3100e_t *t3100e = malloc(sizeof(t3100e_t)); - memset(t3100e, 0, sizeof(t3100e_t)); - cga_init(&t3100e->cga); - - t3100e->internal = 1; - - /* 32k video RAM */ - t3100e->vram = malloc(0x8000); - - timer_add(t3100e_poll, &t3100e->cga.vidtime, TIMER_ALWAYS_ENABLED, t3100e); - - /* Occupy memory between 0xB8000 and 0xBFFFF */ - mem_mapping_add(&t3100e->mapping, 0xb8000, 0x8000, t3100e_read, NULL, NULL, t3100e_write, NULL, NULL, NULL, 0, t3100e); - /* Respond to CGA I/O ports */ - io_sethandler(0x03d0, 0x000c, t3100e_in, NULL, NULL, t3100e_out, NULL, NULL, t3100e); - - /* Default attribute mapping is 4 */ - t3100e->attrmap = 4; - t3100e_recalcattrs(t3100e); - -/* Start off in 80x25 text mode */ - t3100e->cga.cgastat = 0xF4; - t3100e->cga.vram = t3100e->vram; - t3100e->enabled = 1; - t3100e->video_options = 0xFF; - return t3100e; -} - -void t3100e_close(void *p) -{ - t3100e_t *t3100e = (t3100e_t *)p; - - free(t3100e->vram); - free(t3100e); -} - -void t3100e_speed_changed(void *p) -{ - t3100e_t *t3100e = (t3100e_t *)p; - - t3100e_recalctimings(t3100e); -} - -device_t t3100e_device = -{ - "Toshiba T3100e", - 0, - 0, - t3100e_init, - t3100e_close, - NULL, - NULL, - t3100e_speed_changed, - NULL, - NULL -}; diff --git a/src/video/vid_t3100e.h b/src/video/vid_t3100e.h deleted file mode 100644 index ba0f4aa00..000000000 --- a/src/video/vid_t3100e.h +++ /dev/null @@ -1,4 +0,0 @@ -extern device_t t3100e_device; - -void t3100e_video_options_set(uint8_t options); -void t3100e_display_set(uint8_t internal); diff --git a/src/video/vid_table.c b/src/video/vid_table.c index d52c6d963..38337d5fe 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -76,14 +76,14 @@ enum { typedef struct { const char *name; const char *internal_name; - device_t *device; + const device_t *device; int legacy_id; int flags; video_timings_t timing; } VIDEO_CARD; -static VIDEO_CARD +static const VIDEO_CARD video_cards[] = { { "None", "none", NULL, GFX_NONE }, { "Internal", "internal", NULL, GFX_INTERNAL, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, @@ -222,7 +222,7 @@ video_card_getname(int card) } -device_t * +const device_t * video_card_getdevice(int card) { return(video_cards[card].device); diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index 9e5113c7b..bd1846c2c 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -47,7 +47,7 @@ * access size or host data has any affect, but the Windows 3.1 * driver always reads bytes and write words of 0xffff. * - * Version: @(#)vid_tgui9440.c 1.0.4 2018/02/12 + * Version: @(#)vid_tgui9440.c 1.0.5 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -771,7 +771,7 @@ void tgui_pci_write(int func, int addr, uint8_t val, void *p) } } -static void *tgui_init(device_t *info, wchar_t *bios_fn, int type) +static void *tgui_init(const device_t *info, wchar_t *bios_fn, int type) { tgui_t *tgui = malloc(sizeof(tgui_t)); memset(tgui, 0, sizeof(tgui_t)); @@ -809,12 +809,12 @@ static void *tgui_init(device_t *info, wchar_t *bios_fn, int type) return tgui; } -static void *tgui9400cxi_init(device_t *info) +static void *tgui9400cxi_init(const device_t *info) { return tgui_init(info, L"roms/video/tgui9440/9400CXI.vbi", TGUI_9400CXI); } -static void *tgui9440_init(device_t *info) +static void *tgui9440_init(const device_t *info) { return tgui_init(info, L"roms/video/tgui9440/9440.vbi", TGUI_9440); } @@ -1745,7 +1745,7 @@ void tgui_add_status_info(char *s, int max_len, void *p) tgui->blitter_time = 0; } -static device_config_t tgui9440_config[] = +static const device_config_t tgui9440_config[] = { { .name = "memory", @@ -1772,7 +1772,7 @@ static device_config_t tgui9440_config[] = } }; -device_t tgui9400cxi_device = +const device_t tgui9400cxi_device = { "Trident TGUI 9400CXi", DEVICE_VLB, @@ -1787,7 +1787,7 @@ device_t tgui9400cxi_device = tgui9440_config }; -device_t tgui9440_vlb_device = +const device_t tgui9440_vlb_device = { "Trident TGUI 9440 VLB", DEVICE_VLB, @@ -1802,7 +1802,7 @@ device_t tgui9440_vlb_device = tgui9440_config }; -device_t tgui9440_pci_device = +const device_t tgui9440_pci_device = { "Trident TGUI 9440 PCI", DEVICE_PCI, diff --git a/src/video/vid_tgui9440.h b/src/video/vid_tgui9440.h index bb5c1d439..24208e913 100644 --- a/src/video/vid_tgui9440.h +++ b/src/video/vid_tgui9440.h @@ -1,6 +1,6 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ -extern device_t tgui9400cxi_device; -extern device_t tgui9440_vlb_device; -extern device_t tgui9440_pci_device; +extern const device_t tgui9400cxi_device; +extern const device_t tgui9440_vlb_device; +extern const device_t tgui9440_pci_device; diff --git a/src/video/vid_ti_cf62011.c b/src/video/vid_ti_cf62011.c index 2dc036ce3..cbf3c48b7 100644 --- a/src/video/vid_ti_cf62011.c +++ b/src/video/vid_ti_cf62011.c @@ -42,7 +42,7 @@ * which are the same as the XGA. It supports up to 1MB of VRAM, * but we lock it down to 512K. The PS/1 2122 had 256K. * - * Version: @(#)vid_ti_cf62011.c 1.0.3 2018/01/21 + * Version: @(#)vid_ti_cf62011.c 1.0.4 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -239,7 +239,7 @@ vid_close(void *priv) static void * -vid_init(device_t *info) +vid_init(const device_t *info) { tivga_t *ti; @@ -271,7 +271,7 @@ vid_init(device_t *info) #if defined(DEV_BRANCH) && defined(USE_TI) -static device_config_t vid_config[] = +static const device_config_t vid_config[] = { { "vram_size", "Memory Size", CONFIG_SELECTION, "", 256, @@ -296,7 +296,7 @@ static device_config_t vid_config[] = }; -device_t ti_cf62011_device = { +const device_t ti_cf62011_device = { "TI CF62011 SVGA", 0, 0, @@ -310,7 +310,7 @@ device_t ti_cf62011_device = { #endif -device_t ibm_ps1_2121_device = { +const device_t ibm_ps1_2121_device = { "IBM PS/1 Model 2121 SVGA", 0, 512, diff --git a/src/video/vid_ti_cf62011.h b/src/video/vid_ti_cf62011.h index aa82bca5e..185f98511 100644 --- a/src/video/vid_ti_cf62011.h +++ b/src/video/vid_ti_cf62011.h @@ -1,4 +1,4 @@ #if defined(DEV_BRANCH) && defined(USE_TI) -extern device_t ti_cf62011_device; +extern const device_t ti_cf62011_device; #endif -extern device_t ibm_ps1_2121_device; +extern const device_t ibm_ps1_2121_device; diff --git a/src/video/vid_tvga.c b/src/video/vid_tvga.c index abc00de10..d5865e013 100644 --- a/src/video/vid_tvga.c +++ b/src/video/vid_tvga.c @@ -8,7 +8,7 @@ * * Trident TVGA (8900D) emulation. * - * Version: @(#)vid_tvga.c 1.0.4 2018/02/26 + * Version: @(#)vid_tvga.c 1.0.5 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -292,7 +292,7 @@ void tvga_recalctimings(svga_t *svga) } -static void *tvga8900d_init(device_t *info) +static void *tvga8900d_init(const device_t *info) { tvga_t *tvga = malloc(sizeof(tvga_t)); memset(tvga, 0, sizeof(tvga_t)); @@ -348,7 +348,7 @@ void tvga_add_status_info(char *s, int max_len, void *p) svga_add_status_info(s, max_len, &tvga->svga); } -static device_config_t tvga_config[] = +static const device_config_t tvga_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 1024, @@ -373,7 +373,7 @@ static device_config_t tvga_config[] = } }; -device_t tvga8900d_device = +const device_t tvga8900d_device = { "Trident TVGA 8900D", DEVICE_ISA, diff --git a/src/video/vid_tvga.h b/src/video/vid_tvga.h index 2851b9c59..43e1b778b 100644 --- a/src/video/vid_tvga.h +++ b/src/video/vid_tvga.h @@ -1,4 +1,4 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ -extern device_t tvga8900d_device; +extern const device_t tvga8900d_device; diff --git a/src/video/vid_vga.c b/src/video/vid_vga.c index 233ab0755..2311f5a00 100644 --- a/src/video/vid_vga.c +++ b/src/video/vid_vga.c @@ -8,7 +8,7 @@ * * IBM VGA emulation. * - * Version: @(#)vid_vga.c 1.0.3 2018/02/03 + * Version: @(#)vid_vga.c 1.0.4 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -97,7 +97,7 @@ uint8_t vga_in(uint16_t addr, void *p) } -static void *vga_init(device_t *info) +static void *vga_init(const device_t *info) { vga_t *vga = malloc(sizeof(vga_t)); memset(vga, 0, sizeof(vga_t)); @@ -120,7 +120,7 @@ static void *vga_init(device_t *info) #ifdef DEV_BRANCH -static void *trigem_unk_init(device_t *info) +static void *trigem_unk_init(const device_t *info) { vga_t *vga = malloc(sizeof(vga_t)); memset(vga, 0, sizeof(vga_t)); @@ -147,7 +147,7 @@ static void *trigem_unk_init(device_t *info) #endif /*PS/1 uses a standard VGA controller, but with no option ROM*/ -void *ps1vga_init(device_t *info) +void *ps1vga_init(const device_t *info) { vga_t *vga = malloc(sizeof(vga_t)); memset(vga, 0, sizeof(vga_t)); @@ -201,7 +201,7 @@ void vga_add_status_info(char *s, int max_len, void *p) svga_add_status_info(s, max_len, &vga->svga); } -device_t vga_device = +const device_t vga_device = { "VGA", DEVICE_ISA, @@ -215,7 +215,7 @@ device_t vga_device = vga_add_status_info }; #ifdef DEV_BRANCH -device_t trigem_unk_device = +const device_t trigem_unk_device = { "VGA", DEVICE_ISA, @@ -229,7 +229,7 @@ device_t trigem_unk_device = vga_add_status_info }; #endif -device_t ps1vga_device = +const device_t ps1vga_device = { "PS/1 VGA", 0, diff --git a/src/video/vid_vga.h b/src/video/vid_vga.h index 5ee66fc0b..44fa836fb 100644 --- a/src/video/vid_vga.h +++ b/src/video/vid_vga.h @@ -1,6 +1,8 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ -extern device_t vga_device; -extern device_t trigem_unk_device; -extern device_t ps1vga_device; +extern const device_t vga_device; +#ifdef DEV_BRANCH +extern const device_t trigem_unk_device; +#endif +extern const device_t ps1vga_device; diff --git a/src/video/vid_voodoo.c b/src/video/vid_voodoo.c index e3c170614..608708bd1 100644 --- a/src/video/vid_voodoo.c +++ b/src/video/vid_voodoo.c @@ -8,12 +8,12 @@ * * Emulation of the 3DFX Voodoo Graphics controller. * - * Version: @(#)vid_voodoo.c 1.0.11 2017/12/28 + * Version: @(#)vid_voodoo.c 1.0.12 2018/03/18 * * Authors: Sarah Walker, * leilei * - * Copyright 2008-2017 Sarah Walker. + * Copyright 2008-2018 Sarah Walker. */ #include #include @@ -7841,7 +7841,7 @@ void voodoo_close(void *p) free(voodoo_set); } -static device_config_t voodoo_config[] = +static const device_config_t voodoo_config[] = { { .name = "type", @@ -7958,7 +7958,7 @@ static device_config_t voodoo_config[] = } }; -device_t voodoo_device = +const device_t voodoo_device = { "3DFX Voodoo Graphics", DEVICE_PCI, diff --git a/src/video/vid_voodoo.h b/src/video/vid_voodoo.h index 047978327..9752899f7 100644 --- a/src/video/vid_voodoo.h +++ b/src/video/vid_voodoo.h @@ -1 +1 @@ -extern device_t voodoo_device; +extern const device_t voodoo_device; diff --git a/src/video/vid_wy700.c b/src/video/vid_wy700.c index e0cac8edc..0f93813e8 100644 --- a/src/video/vid_wy700.c +++ b/src/video/vid_wy700.c @@ -8,13 +8,13 @@ * * Wyse-700 emulation. * - * Version: @(#)vid_wy700.c 1.0.6 2017/11/04 + * Version: @(#)vid_wy700.c 1.0.7 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #include #include @@ -897,7 +897,7 @@ void wy700_poll(void *p) } -void *wy700_init(device_t *info) +void *wy700_init(const device_t *info) { int c; wy700_t *wy700 = malloc(sizeof(wy700_t)); @@ -1005,7 +1005,7 @@ void wy700_speed_changed(void *p) wy700_recalctimings(wy700); } -device_t wy700_device = +const device_t wy700_device = { "Wyse 700", DEVICE_ISA, 0, diff --git a/src/video/vid_wy700.h b/src/video/vid_wy700.h index 71d5063e4..0c8a986fe 100644 --- a/src/video/vid_wy700.h +++ b/src/video/vid_wy700.h @@ -1 +1 @@ -extern device_t wy700_device; +extern const device_t wy700_device; diff --git a/src/video/video.c b/src/video/video.c index 728b9799d..c41a52db9 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -40,7 +40,7 @@ * W = 3 bus clocks * L = 4 bus clocks * - * Version: @(#)video.c 1.0.19 2018/03/15 + * Version: @(#)video.c 1.0.20 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, diff --git a/src/video/video.h b/src/video/video.h index 1813e8115..313a06d9d 100644 --- a/src/video/video.h +++ b/src/video/video.h @@ -8,7 +8,7 @@ * * Definitions for the video controller module. * - * Version: @(#)video.h 1.0.23 2018/03/15 + * Version: @(#)video.h 1.0.24 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -214,7 +214,7 @@ extern void (*video_recalctimings)(void); extern int video_card_available(int card); extern char *video_card_getname(int card); #ifdef EMU_DEVICE_H -extern device_t *video_card_getdevice(int card); +extern const device_t *video_card_getdevice(int card); #endif extern int video_card_has_config(int card); extern video_timings_t *video_card_gettiming(int card); diff --git a/src/win/win.h b/src/win/win.h index 88a03887a..c909b0829 100644 --- a/src/win/win.h +++ b/src/win/win.h @@ -8,7 +8,7 @@ * * Platform support defintions for Win32. * - * Version: @(#)win.h 1.0.14 2018/01/21 + * Version: @(#)win.h 1.0.15 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -94,7 +94,7 @@ extern void win_mouse_close(void); extern intptr_t fdd_type_to_icon(int type); #ifdef EMU_DEVICE_H -extern uint8_t deviceconfig_open(HWND hwnd, device_t *device); +extern uint8_t deviceconfig_open(HWND hwnd, const device_t *device); #endif extern uint8_t joystickconfig_open(HWND hwnd, int joy_nr, int type); diff --git a/src/win/win_devconf.c b/src/win/win_devconf.c index 72c4f7f9a..d738ab39e 100644 --- a/src/win/win_devconf.c +++ b/src/win/win_devconf.c @@ -8,7 +8,7 @@ * * Windows device configuration dialog implementation. * - * Version: @(#)win_devconf.c 1.0.15 2018/02/25 + * Version: @(#)win_devconf.c 1.0.16 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, @@ -30,7 +30,7 @@ #include -static device_t *config_device; +static const device_t *config_device; static uint8_t deviceconfig_changed = 0; @@ -47,10 +47,10 @@ deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) int val_int; int id; int c; - int num; + int num; int changed; - int cid; - device_config_t *config; + int cid; + const device_config_t *config; char s[80]; wchar_t ws[512]; LPTSTR lptsTemp; @@ -66,7 +66,7 @@ deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) while (config->type != -1) { - device_config_selection_t *selection = config->selection; + const device_config_selection_t *selection = config->selection; h = GetDlgItem(hdlg, id); switch (config->type) @@ -183,7 +183,7 @@ deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) while (config->type != -1) { - device_config_selection_t *selection = config->selection; + const device_config_selection_t *selection = config->selection; h = GetDlgItem(hdlg, id); switch (config->type) @@ -295,7 +295,7 @@ deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) while (config->type != -1) { - device_config_selection_t *selection = config->selection; + const device_config_selection_t *selection = config->selection; h = GetDlgItem(hdlg, id); switch (config->type) @@ -375,7 +375,7 @@ deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) else { int id = IDC_CONFIG_BASE; - device_config_t *config = config_device->config; + const device_config_t *config = config_device->config; while (config->type != -1) { @@ -455,9 +455,9 @@ deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) return FALSE; } -uint8_t deviceconfig_open(HWND hwnd, device_t *device) +uint8_t deviceconfig_open(HWND hwnd, const device_t *device) { - device_config_t *config = device->config; + const device_config_t *config = device->config; uint16_t *data_block = malloc(16384); uint16_t *data; DLGTEMPLATE *dlg = (DLGTEMPLATE *)data_block; diff --git a/src/win/win_joystick.cpp b/src/win/win_joystick.cpp index 2f14c8169..1cf4e6d13 100644 --- a/src/win/win_joystick.cpp +++ b/src/win/win_joystick.cpp @@ -8,13 +8,13 @@ * * Joystick interface to host device. * - * Version: @(#)win_joystick.cpp 1.0.7 2017/12/15 + * Version: @(#)win_joystick.cpp 1.0.8 2018/03/18 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. */ #define DIRECTINPUT_VERSION 0x0800 #include @@ -25,7 +25,6 @@ #include "../device.h" #include "../plat.h" #include "../game/gameport.h" -#include "../plat_joystick.h" #include "win.h" diff --git a/src/win/win_jsconf.c b/src/win/win_jsconf.c index fe97c5b6c..39a02740b 100644 --- a/src/win/win_jsconf.c +++ b/src/win/win_jsconf.c @@ -12,7 +12,6 @@ #include "../device.h" #include "../game/gameport.h" #include "../plat.h" -#include "../plat_joystick.h" #include "win.h" diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 27359b286..ce9455061 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -8,7 +8,7 @@ * * Windows 86Box Settings dialog handler. * - * Version: @(#)win_settings.c 1.0.43 2018/03/10 + * Version: @(#)win_settings.c 1.0.44 2018/03/18 * * Author: Miran Grca, * @@ -173,7 +173,7 @@ static void win_settings_init(void) /* Network category */ temp_net_type = network_type; memset(temp_pcap_dev, 0, sizeof(temp_pcap_dev)); - strcpy(temp_pcap_dev, network_pcap); + strcpy(temp_pcap_dev, network_host); temp_net_card = network_card; /* Ports category */ @@ -289,7 +289,7 @@ static int win_settings_changed(void) /* Network category */ i = i || (network_type != temp_net_type); - i = i || strcmp(temp_pcap_dev, network_pcap); + i = i || strcmp(temp_pcap_dev, network_host); i = i || (network_card != temp_net_card); /* Ports category */ @@ -392,8 +392,8 @@ static void win_settings_save(void) /* Network category */ network_type = temp_net_type; - memset(network_pcap, '\0', sizeof(network_pcap)); - strcpy(network_pcap, temp_pcap_dev); + memset(network_host, '\0', sizeof(network_host)); + strcpy(network_host, temp_pcap_dev); network_card = temp_net_card; /* Ports category */ @@ -436,28 +436,7 @@ static void win_settings_save(void) /* Mark configuration as changed. */ config_changed = 1; -#if 1 pc_reset_hard_init(); -#else - mem_resize(); - rom_load_bios(romset); - - ui_sb_update_panes(); - - sound_realloc_buffers(); - - pc_reset_hard_init(); - - cpu_set(); - - cpu_update_waitstates(); - - config_save(); - - pc_speed_changed(); - - if (joystick_type != 7) gameport_update_joystick_type(); -#endif } @@ -980,7 +959,7 @@ win_settings_video_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) static int mouse_valid(int num, int m) { - device_t *dev; + const device_t *dev; if ((num == MOUSE_TYPE_INTERNAL) && !(machines[m].flags & MACHINE_MOUSE)) return(0); @@ -1184,7 +1163,7 @@ win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) int c = 0; int d = 0; LPTSTR lptsTemp; - device_t *sound_dev/*, *midi_dev*/; + const device_t *sound_dev; char *s; switch (message) @@ -1256,8 +1235,6 @@ win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) if (midi_device_available(c)) { - /* midi_dev = midi_device_getdevice(c); */ - if (c == 0) { SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_2152)); @@ -1606,7 +1583,7 @@ win_settings_peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPa int c = 0; int d = 0; LPTSTR lptsTemp; - device_t *scsi_dev; + const device_t *scsi_dev; switch (message) {