/disk.cpp
C++ | 5979 lines | 5335 code | 459 blank | 185 comment | 1838 complexity | f4df4d55ceb951475eef724de372c779 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /*
- * UAE - The Un*x Amiga Emulator
- *
- * Floppy disk emulation
- *
- * Copyright 1995 Hannu Rummukainen
- * Copyright 1995-2001 Bernd Schmidt
- * Copyright 2000-2021 Toni Wilen
- *
- * Original High Density Drive Handling by Dr. Adil Temel (C) 2001 [atemel1@hotmail.com]
- *
- * Small modifications to support abstracted Floppy Disk "Bridges" to hardware, Copyright 2021 Robert Smith, https://amiga.robsmithdev.co.uk
- *
- */
- #include "sysconfig.h"
- #include "sysdeps.h"
- int disk_debug_logging = 0;
- int disk_debug_mode = 0;
- int disk_debug_track = -1;
- #define REVOLUTION_DEBUG 0
- #define MFM_VALIDATOR 0
- #include "uae.h"
- #include "options.h"
- #include "memory.h"
- #include "events.h"
- #include "custom.h"
- #include "disk.h"
- #include "gui.h"
- #include "zfile.h"
- #include "newcpu.h"
- #include "osemu.h"
- #include "execlib.h"
- #include "savestate.h"
- #include "cia.h"
- #include "debug.h"
- #ifdef FDI2RAW
- #include "fdi2raw.h"
- #endif
- #include "catweasel.h"
- #include "driveclick.h"
- #ifdef CAPS
- #include "caps/caps_win32.h"
- #endif
- #ifdef SCP
- #include "scp.h"
- #endif
- #include "crc32.h"
- #include "inputrecord.h"
- #include "amax.h"
- #ifdef RETROPLATFORM
- #include "rp.h"
- #endif
- #include "fsdb.h"
- #include "statusline.h"
- #include "rommgr.h"
- #include "tinyxml2.h"
- #ifdef FLOPPYBRIDGE
- #include "floppybridge/floppybridge_abstract.h"
- #include "floppybridge/floppybridge_lib.h"
- #endif
- #undef CATWEASEL
- int floppy_writemode = 0;
- /* support HD floppies */
- #define FLOPPY_DRIVE_HD
- /* Writable track length with normal 2us bitcell/300RPM motor, 12688 PAL, 12784 NTSC */
- /* DMA clock / (7 clocks per bit * 5 revs per second * 8 bits per byte) */
- #define FLOPPY_WRITE_LEN_PAL 12668 // 3546895 / (7 * 5 * 8)
- #define FLOPPY_WRITE_LEN_NTSC 12784 // 3579545 / (7 * 5 * 8)
- #define FLOPPY_WRITE_LEN (currprefs.floppy_write_length > 256 ? currprefs.floppy_write_length / 2 : (currprefs.ntscmode ? (FLOPPY_WRITE_LEN_NTSC / 2) : (FLOPPY_WRITE_LEN_PAL / 2)))
- #define FLOPPY_WRITE_MAXLEN 0x3800
- /* This works out to 350 PAL, 408 NTSC */
- #define FLOPPY_GAP_LEN (FLOPPY_WRITE_LEN - 11 * 544)
- /* 7 CCK per bit */
- #define NORMAL_FLOPPY_SPEED (7 * 256)
- /* max supported floppy drives, for small memory systems */
- #define MAX_FLOPPY_DRIVES 4
- #ifdef FLOPPY_DRIVE_HD
- #define DDHDMULT 2
- #else
- #define DDHDMULT 1
- #endif
- #define MAX_SECTORS (DDHDMULT * 11)
- #undef DEBUG_DRIVE_ID
- /* UAE-1ADF (ADF_EXT2)
- * W reserved
- * W number of tracks (default 2*80=160)
- *
- * W reserved
- * W type, 0=normal AmigaDOS track, 1 = raw MFM (upper byte = disk revolutions - 1)
- * L available space for track in bytes (must be even)
- * L track length in bits
- */
- static int side, direction, reserved_side;
- static uae_u8 selected = 15, disabled, reserved;
- static uae_u8 writebuffer[544 * MAX_SECTORS];
- static uae_u8 writesecheadbuffer[16 * MAX_SECTORS];
- #define DISK_INDEXSYNC 1
- #define DISK_WORDSYNC 2
- #define DISK_REVOLUTION 4 /* 8,16,32,64 */
- #define DSKREADY_UP_TIME 18
- #define DSKREADY_DOWN_TIME 24
- #define DSKDMA_OFF 0
- #define DSKDMA_INIT 1
- #define DSKDMA_READ 2
- #define DSKDMA_WRITE 3
- static int dskdmaen, dsklength, dsklength2, dsklen;
- static uae_u16 dskbytr_val;
- static uae_u32 dskpt;
- static bool fifo_filled;
- static uae_u16 fifo[3];
- static int fifo_inuse[3];
- static int dma_enable, bitoffset, syncoffset;
- static uae_u16 word, dsksync;
- static unsigned long dsksync_cycles;
- #define WORDSYNC_TIME 11
- /* Always carried through to the next line. */
- int disk_hpos;
- static int disk_jitter;
- static int indexdecay;
- static uae_u8 prev_data;
- static int prev_step;
- static bool initial_disk_statusline;
- static struct diskinfo disk_info_data = { 0 };
- static bool amax_enabled;
- typedef enum { TRACK_AMIGADOS, TRACK_RAW, TRACK_RAW1, TRACK_PCDOS, TRACK_DISKSPARE, TRACK_NONE } image_tracktype;
- typedef struct {
- uae_u16 len;
- int offs, extraoffs;
- int bitlen, track;
- uae_u16 sync;
- image_tracktype type;
- int revolutions;
- } trackid;
- #define MAX_TRACKS (2 * 83)
- /* We have three kinds of Amiga floppy drives
- * - internal A500/A2000 drive:
- * ID is always DRIVE_ID_NONE (S.T.A.G expects this)
- * - HD drive (A3000/A4000):
- * ID is DRIVE_ID_35DD if DD floppy is inserted or drive is empty
- * ID is DRIVE_ID_35HD if HD floppy is inserted
- * - regular external drive:
- * ID is always DRIVE_ID_35DD
- */
- #define DRIVE_ID_NONE 0x00000000
- #define DRIVE_ID_35DD 0xFFFFFFFF
- #define DRIVE_ID_35HD 0xAAAAAAAA
- #define DRIVE_ID_525SD 0x55555555 /* 40 track 5.25 drive , kickstart does not recognize this */
- typedef enum { ADF_NONE = -1, ADF_NORMAL, ADF_EXT1, ADF_EXT2, ADF_FDI, ADF_IPF, ADF_SCP, ADF_CATWEASEL, ADF_PCDOS, ADF_KICK, ADF_SKICK, ADF_NORMAL_HEADER, ADF_FLOPPYBRIDGE } drive_filetype;
- typedef struct {
- struct zfile *diskfile;
- struct zfile *writediskfile;
- struct zfile *pcdecodedfile;
- drive_filetype filetype;
- trackid trackdata[MAX_TRACKS];
- trackid writetrackdata[MAX_TRACKS];
- int buffered_cyl, buffered_side;
- int cyl;
- bool motoroff;
- int motordelay; /* dskrdy needs some clock cycles before it changes after switching off motor */
- bool state;
- int selected_delay;
- bool wrprot;
- bool forcedwrprot;
- uae_u16 bigmfmbuf[0x4000 * DDHDMULT];
- uae_u16 tracktiming[0x4000 * DDHDMULT];
- int multi_revolution;
- int revolution_check;
- int skipoffset;
- int mfmpos;
- int indexoffset;
- int tracklen;
- int revolutions;
- int prevtracklen;
- int trackspeed;
- int num_tracks, write_num_tracks, num_secs, num_heads;
- int hard_num_cyls;
- bool dskeject;
- bool dskchange;
- int dskchange_time;
- bool dskready;
- int dskready_up_time;
- int dskready_down_time;
- int writtento;
- int steplimit;
- frame_time_t steplimitcycle;
- int indexhack, indexhackmode;
- int ddhd; /* 1=DD 2=HD */
- int drive_id_scnt; /* drive id shift counter */
- int idbit;
- unsigned long drive_id; /* drive id to be reported */
- TCHAR newname[256]; /* storage space for new filename during eject delay */
- bool newnamewriteprotected;
- uae_u32 crc32;
- #ifdef FDI2RAW
- FDI *fdi;
- #endif
- int useturbo;
- int floppybitcounter; /* number of bits left */
- #ifdef CATWEASEL
- catweasel_drive *catweasel;
- #else
- int catweasel;
- int amax;
- int lastdataacesstrack;
- int lastrev;
- bool track_access_done;
- bool fourms;
- #endif
- #ifdef FLOPPYBRIDGE
- FloppyDiskBridge *bridge;
- bool writepending;
- #endif
- } drive;
- #define MIN_STEPLIMIT_CYCLE (CYCLE_UNIT * 140)
- static uae_u16 bigmfmbufw[0x4000 * DDHDMULT];
- static drive floppy[MAX_FLOPPY_DRIVES];
- static TCHAR dfxhistory[HISTORY_MAX][MAX_PREVIOUS_IMAGES][MAX_DPATH];
- static uae_u8 exeheader[]={0x00,0x00,0x03,0xf3,0x00,0x00,0x00,0x00};
- static uae_u8 bootblock_ofs[]={
- 0x44,0x4f,0x53,0x00,0xc0,0x20,0x0f,0x19,0x00,0x00,0x03,0x70,0x43,0xfa,0x00,0x18,
- 0x4e,0xae,0xff,0xa0,0x4a,0x80,0x67,0x0a,0x20,0x40,0x20,0x68,0x00,0x16,0x70,0x00,
- 0x4e,0x75,0x70,0xff,0x60,0xfa,0x64,0x6f,0x73,0x2e,0x6c,0x69,0x62,0x72,0x61,0x72,
- 0x79
- };
- static uae_u8 bootblock_ffs[]={
- 0x44, 0x4F, 0x53, 0x01, 0xE3, 0x3D, 0x0E, 0x72, 0x00, 0x00, 0x03, 0x70, 0x43, 0xFA, 0x00, 0x3E,
- 0x70, 0x25, 0x4E, 0xAE, 0xFD, 0xD8, 0x4A, 0x80, 0x67, 0x0C, 0x22, 0x40, 0x08, 0xE9, 0x00, 0x06,
- 0x00, 0x22, 0x4E, 0xAE, 0xFE, 0x62, 0x43, 0xFA, 0x00, 0x18, 0x4E, 0xAE, 0xFF, 0xA0, 0x4A, 0x80,
- 0x67, 0x0A, 0x20, 0x40, 0x20, 0x68, 0x00, 0x16, 0x70, 0x00, 0x4E, 0x75, 0x70, 0xFF, 0x4E, 0x75,
- 0x64, 0x6F, 0x73, 0x2E, 0x6C, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x00, 0x65, 0x78, 0x70, 0x61,
- 0x6E, 0x73, 0x69, 0x6F, 0x6E, 0x2E, 0x6C, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x00, 0x00, 0x00,
- };
- #define FS_OFS_DATABLOCKSIZE 488
- #define FS_FLOPPY_BLOCKSIZE 512
- #define FS_EXTENSION_BLOCKS 72
- #define FS_FLOPPY_TOTALBLOCKS 1760
- #define FS_FLOPPY_RESERVED 2
- static void writeimageblock (struct zfile *dst, uae_u8 *sector, int offset)
- {
- zfile_fseek (dst, offset, SEEK_SET);
- zfile_fwrite (sector, FS_FLOPPY_BLOCKSIZE, 1, dst);
- }
- static uae_u32 disk_checksum (uae_u8 *p, uae_u8 *c)
- {
- uae_u32 cs = 0;
- int i;
- for (i = 0; i < FS_FLOPPY_BLOCKSIZE; i+= 4)
- cs += (p[i] << 24) | (p[i+1] << 16) | (p[i+2] << 8) | (p[i+3] << 0);
- cs = (~cs) + 1;
- if (c) {
- c[0] = cs >> 24; c[1] = cs >> 16; c[2] = cs >> 8; c[3] = cs >> 0;
- }
- return cs;
- }
- static int dirhash (const uae_char *name)
- {
- unsigned long hash;
- int i;
- hash = strlen (name);
- for(i = 0; i < strlen (name); i++) {
- hash = hash * 13;
- hash = hash + toupper (name[i]);
- hash = hash & 0x7ff;
- }
- hash = hash % ((FS_FLOPPY_BLOCKSIZE / 4) - 56);
- return hash;
- }
- static void disk_date (uae_u8 *p)
- {
- static int pdays, pmins, pticks;
- int days, mins, ticks;
- struct timeval tv;
- struct mytimeval mtv;
- gettimeofday (&tv, NULL);
- tv.tv_sec -= _timezone;
- mtv.tv_sec = tv.tv_sec;
- mtv.tv_usec = tv.tv_usec;
- timeval_to_amiga (&mtv, &days, &mins, &ticks, 50);
- if (days == pdays && mins == pmins && ticks == pticks) {
- ticks++;
- if (ticks >= 50 * 60) {
- ticks = 0;
- mins++;
- if (mins >= 24 * 60)
- days++;
- }
- }
- pdays = days;
- pmins = mins;
- pticks = ticks;
- p[0] = days >> 24; p[1] = days >> 16; p[2] = days >> 8; p[3] = days >> 0;
- p[4] = mins >> 24; p[5] = mins >> 16; p[6] = mins >> 8; p[7] = mins >> 0;
- p[8] = ticks >> 24; p[9] = ticks >> 16; p[10] = ticks >> 8; p[11] = ticks >> 0;
- }
- static void createbootblock (uae_u8 *sector, int bootable, bool ffs)
- {
- memset (sector, 0, FS_FLOPPY_BLOCKSIZE);
- memcpy (sector, "DOS", 3);
- if (ffs) {
- sector[3] = 1;
- }
- if (bootable) {
- memcpy(sector + 8, bootblock_ofs + 8, sizeof(bootblock_ofs) - 8);
- uae_u32 crc = 0;
- for (int i = 0; i < FS_FLOPPY_BLOCKSIZE; i += 4) {
- uae_u32 v = (sector[i] << 24) | (sector[i + 1] << 16) | (sector[i + 2] << 8) | sector[i + 3];
- if (crc + v < crc) {
- crc++;
- }
- crc += v;
- }
- crc ^= 0xffffffff;
- sector[4] = crc >> 24;
- sector[5] = crc >> 16;
- sector[6] = crc >> 8;
- sector[7] = crc >> 0;
- }
- }
- static void createrootblock (uae_u8 *sector, const TCHAR *disk_name)
- {
- char *dn = ua (disk_name);
- if (strlen (dn) >= 30)
- dn[30] = 0;
- const char *dn2 = dn;
- if (dn2[0] == 0)
- dn2 = "empty";
- memset (sector, 0, FS_FLOPPY_BLOCKSIZE);
- sector[0+3] = 2;
- sector[12+3] = 0x48;
- sector[312] = sector[313] = sector[314] = sector[315] = (uae_u8)0xff;
- sector[316+2] = 881 >> 8; sector[316+3] = 881 & 255;
- sector[432] = (uae_u8)strlen (dn2);
- strcpy ((char*)sector + 433, dn2);
- sector[508 + 3] = 1;
- disk_date (sector + 420);
- memcpy (sector + 472, sector + 420, 3 * 4);
- memcpy (sector + 484, sector + 420, 3 * 4);
- xfree (dn);
- }
- static int getblock (uae_u8 *bitmap, int *prev)
- {
- int i = *prev;
- while (bitmap[i] != 0xff) {
- if (bitmap[i] == 0) {
- bitmap[i] = 1;
- *prev = i;
- return i;
- }
- i++;
- }
- i = 0;
- while (bitmap[i] != 0xff) {
- if (bitmap[i] == 0) {
- bitmap[i] = 1;
- *prev = i;
- return i;
- }
- i++;
- }
- return -1;
- }
- static void pl (uae_u8 *sector, int offset, uae_u32 v)
- {
- sector[offset + 0] = v >> 24;
- sector[offset + 1] = v >> 16;
- sector[offset + 2] = v >> 8;
- sector[offset + 3] = v >> 0;
- }
- static int createdirheaderblock (uae_u8 *sector, int parent, const char *filename, uae_u8 *bitmap, int *prevblock)
- {
- int block = getblock (bitmap, prevblock);
- memset (sector, 0, FS_FLOPPY_BLOCKSIZE);
- pl (sector, 0, 2);
- pl (sector, 4, block);
- disk_date (sector + 512 - 92);
- sector[512 - 80] = (uae_u8)strlen (filename);
- strcpy ((char*)sector + 512 - 79, filename);
- pl (sector, 512 - 12, parent);
- pl (sector, 512 - 4, 2);
- return block;
- }
- static int createfileheaderblock (struct zfile *z,uae_u8 *sector, int parent, const char *filename, struct zfile *src, uae_u8 *bitmap, bool ffs, int *prevblock)
- {
- uae_u8 sector2[FS_FLOPPY_BLOCKSIZE];
- uae_u8 sector3[FS_FLOPPY_BLOCKSIZE];
- int block = getblock (bitmap, prevblock);
- int datablock = getblock (bitmap, prevblock);
- int datasec = 1;
- int extensions;
- int extensionblock, extensioncounter, headerextension = 1;
- int size;
- int blocksize = ffs ? FS_FLOPPY_BLOCKSIZE : FS_OFS_DATABLOCKSIZE;
- zfile_fseek (src, 0, SEEK_END);
- size = (int)zfile_ftell (src);
- zfile_fseek (src, 0, SEEK_SET);
- extensions = (size + blocksize - 1) / blocksize;
- memset (sector, 0, FS_FLOPPY_BLOCKSIZE);
- pl (sector, 0, 2);
- pl (sector, 4, block);
- pl (sector, 8, extensions > FS_EXTENSION_BLOCKS ? FS_EXTENSION_BLOCKS : extensions);
- pl (sector, 16, datablock);
- pl (sector, FS_FLOPPY_BLOCKSIZE - 188, size);
- disk_date (sector + FS_FLOPPY_BLOCKSIZE - 92);
- sector[FS_FLOPPY_BLOCKSIZE - 80] = (uae_u8)strlen (filename);
- strcpy ((char*)sector + FS_FLOPPY_BLOCKSIZE - 79, filename);
- pl (sector, FS_FLOPPY_BLOCKSIZE - 12, parent);
- pl (sector, FS_FLOPPY_BLOCKSIZE - 4, -3);
- extensioncounter = 0;
- extensionblock = 0;
- while (size > 0) {
- int datablock2 = datablock;
- int extensionblock2 = extensionblock;
- if (extensioncounter == FS_EXTENSION_BLOCKS) {
- extensioncounter = 0;
- extensionblock = getblock (bitmap, prevblock);
- if (datasec > FS_EXTENSION_BLOCKS + 1) {
- pl (sector3, 8, FS_EXTENSION_BLOCKS);
- pl (sector3, FS_FLOPPY_BLOCKSIZE - 8, extensionblock);
- pl (sector3, 4, extensionblock2);
- disk_checksum(sector3, sector3 + 20);
- writeimageblock (z, sector3, extensionblock2 * FS_FLOPPY_BLOCKSIZE);
- } else {
- pl (sector, 512 - 8, extensionblock);
- }
- memset (sector3, 0, FS_FLOPPY_BLOCKSIZE);
- pl (sector3, 0, 16);
- pl (sector3, FS_FLOPPY_BLOCKSIZE - 12, block);
- pl (sector3, FS_FLOPPY_BLOCKSIZE - 4, -3);
- }
- memset (sector2, 0, FS_FLOPPY_BLOCKSIZE);
- if (!ffs) {
- pl(sector2, 0, 8);
- pl(sector2, 4, block);
- pl(sector2, 8, datasec);
- pl(sector2, 12, size > FS_OFS_DATABLOCKSIZE ? FS_OFS_DATABLOCKSIZE : size);
- zfile_fread(sector2 + 24, size > FS_OFS_DATABLOCKSIZE ? FS_OFS_DATABLOCKSIZE : size, 1, src);
- } else {
- zfile_fread(sector2, size > FS_FLOPPY_BLOCKSIZE ? FS_FLOPPY_BLOCKSIZE : size, 1, src);
- }
- datasec++;
- size -= blocksize;
- datablock = 0;
- if (size > 0) {
- datablock = getblock(bitmap, prevblock);
- }
- if (!ffs) {
- pl(sector2, 16, datablock);
- disk_checksum(sector2, sector2 + 20);
- }
- writeimageblock (z, sector2, datablock2 * FS_FLOPPY_BLOCKSIZE);
- if (datasec <= FS_EXTENSION_BLOCKS + 1)
- pl (sector, 512 - 204 - extensioncounter * 4, datablock2);
- else
- pl (sector3, 512 - 204 - extensioncounter * 4, datablock2);
- extensioncounter++;
- }
- if (datasec > FS_EXTENSION_BLOCKS) {
- pl (sector3, 8, extensioncounter);
- disk_checksum(sector3, sector3 + 20);
- writeimageblock (z, sector3, extensionblock * FS_FLOPPY_BLOCKSIZE);
- }
- disk_checksum(sector, sector + 20);
- writeimageblock (z, sector, block * FS_FLOPPY_BLOCKSIZE);
- return block;
- }
- static void createbitmapblock (uae_u8 *sector, uae_u8 *bitmap)
- {
- int i, j;
- memset (sector, 0, FS_FLOPPY_BLOCKSIZE);
- i = 0;
- for (;;) {
- uae_u32 mask = 0;
- for (j = 0; j < 32; j++) {
- if (bitmap[2 + i * 32 + j] == 0xff)
- break;
- if (!bitmap[2 + i * 32 + j])
- mask |= 1 << j;
- }
- sector[4 + i * 4 + 0] = mask >> 24;
- sector[4 + i * 4 + 1] = mask >> 16;
- sector[4 + i * 4 + 2] = mask >> 8;
- sector[4 + i * 4 + 3] = mask >> 0;
- if (bitmap[2 + i * 32 + j] == 0xff)
- break;
- i++;
- }
- disk_checksum(sector, sector + 0);
- }
- static int createimagefromexe(struct zfile *src, struct zfile *dst, int hd, bool ffs)
- {
- uae_u8 sector1[FS_FLOPPY_BLOCKSIZE], sector2[FS_FLOPPY_BLOCKSIZE];
- uae_u8 bitmap[FS_FLOPPY_TOTALBLOCKS * 2 + 8];
- int exesize;
- int blocksize = ffs ? FS_FLOPPY_BLOCKSIZE : FS_OFS_DATABLOCKSIZE;
- int blocks, extensionblocks;
- int totalblocks;
- int fblock1, dblock1;
- const char *fname1 = "runme.exe";
- const TCHAR *fname1b = _T("runme.adf");
- const char *fname2 = "startup-sequence";
- const char *dirname1 = "s";
- struct zfile *ss;
- int prevblock;
- memset (bitmap, 0, sizeof bitmap);
- zfile_fseek (src, 0, SEEK_END);
- exesize = (int)zfile_ftell (src);
- blocks = (exesize + blocksize - 1) / blocksize;
- extensionblocks = (blocks + FS_EXTENSION_BLOCKS - 1) / FS_EXTENSION_BLOCKS;
- /* bootblock=2, root=1, bitmap=1, startup-sequence=1+1, exefileheader=1 */
- totalblocks = 2 + 1 + 1 + 2 + 1 + blocks + extensionblocks;
- if (totalblocks > FS_FLOPPY_TOTALBLOCKS * hd)
- return 0;
- bitmap[880 * hd + 0] = 1;
- bitmap[880 * hd + 1] = 1;
- bitmap[0] = 1;
- bitmap[1] = 1;
- bitmap[1760 * hd] = -1;
- prevblock = 880 * hd;
- dblock1 = createdirheaderblock (sector2, 880 * hd, dirname1, bitmap, &prevblock);
- ss = zfile_fopen_empty (src, fname1b, strlen (fname1));
- zfile_fwrite (fname1, strlen(fname1), 1, ss);
- fblock1 = createfileheaderblock (dst, sector1, dblock1, fname2, ss, bitmap, ffs, &prevblock);
- zfile_fclose (ss);
- pl (sector2, 24 + dirhash (fname2) * 4, fblock1);
- disk_checksum(sector2, sector2 + 20);
- writeimageblock (dst, sector2, dblock1 * FS_FLOPPY_BLOCKSIZE);
- fblock1 = createfileheaderblock (dst, sector1, 880 * hd, fname1, src, bitmap, ffs, &prevblock);
- createrootblock (sector1, zfile_getfilename (src));
- pl (sector1, 24 + dirhash (fname1) * 4, fblock1);
- pl (sector1, 24 + dirhash (dirname1) * 4, dblock1);
- disk_checksum(sector1, sector1 + 20);
- writeimageblock (dst, sector1, 880 * hd * FS_FLOPPY_BLOCKSIZE);
- createbitmapblock (sector1, bitmap);
- writeimageblock (dst, sector1, (880 * hd + 1) * FS_FLOPPY_BLOCKSIZE);
- createbootblock (sector1, 1, ffs);
- writeimageblock (dst, sector1, 0 * FS_FLOPPY_BLOCKSIZE);
- return 1;
- }
- #ifdef FLOPPYBRIDGE
- static FloppyBridgeAPI *bridges[4];
- static int bridge_type[4];
- static const FloppyDiskBridge::BridgeDriver *bridge_driver[4];
- static FloppyBridgeAPI::BridgeInformation bridgeinfo;
- static int bridgeinfoloaded;
- static std::vector<FloppyBridgeAPI::DriverInformation> bridgedriverinfo;
- static void floppybridge_read_track(drive *drv);
- bool floppybridge_available;
- std::vector<FloppyBridgeAPI::FloppyBridgeProfileInformation> bridgeprofiles;
- static char *floppybridge_config = NULL;
- bool DISK_isfloppybridge(struct uae_prefs *p, int num)
- {
- return p->floppyslots[num].dfxtype == DRV_FB;
- }
- #endif
- static bool isfloppysound (drive *drv)
- {
- return drv->useturbo == 0;
- }
- static int get_floppy_speed (void)
- {
- int m = currprefs.floppy_speed;
- if (m <= 10)
- m = 100;
- m = NORMAL_FLOPPY_SPEED * 100 / m;
- return m;
- }
- static int get_floppy_speed_from_image(drive *drv)
- {
- int l, m;
-
- #ifdef FLOPPYBRIDGE
- if (drv->bridge) {
- drv->fourms = drv->bridge->getBitSpeed() == 4;
- m = NORMAL_FLOPPY_SPEED;
- if (drv->fourms) {
- m *= 2;
- }
- return m;
- }
- #endif
- m = get_floppy_speed();
- l = drv->tracklen;
- drv->fourms = false;
- if (!drv->tracktiming[0]) {
- m = m * l / (2 * 8 * FLOPPY_WRITE_LEN * drv->ddhd);
- }
- // 4us track?
- if (l < (FLOPPY_WRITE_LEN_PAL * 8) * 4 / 6) {
- m *= 2;
- drv->fourms = true;
- }
- if (m <= 0) {
- m = 1;
- }
- return m;
- }
- static const TCHAR *drive_id_name(drive *drv)
- {
- switch(drv->drive_id)
- {
- case DRIVE_ID_35HD : return _T("3.5HD");
- case DRIVE_ID_525SD: return _T("5.25SD");
- case DRIVE_ID_35DD : return _T("3.5DD");
- case DRIVE_ID_NONE : return _T("NONE");
- }
- return _T("UNKNOWN");
- }
- /* Simulate exact behaviour of an A3000T 3.5 HD disk drive.
- * The drive reports to be a 3.5 DD drive whenever there is no
- * disk or a 3.5 DD disk is inserted. Only 3.5 HD drive id is reported
- * when a real 3.5 HD disk is inserted. -Adil
- */
- static void drive_settype_id (drive *drv)
- {
- int drvnum = drv - &floppy[0];
- int t = currprefs.floppyslots[drvnum].dfxtype;
- #ifdef FLOPPYBRIDGE
- if (drv->bridge)
- {
- if (drv->bridge->isDiskInDrive()) {
- switch (drv->bridge->getDriveTypeID()) {
- case FloppyDiskBridge::DriveTypeID::dti35DD:
- drv->drive_id = DRIVE_ID_35DD;
- break;
- case FloppyDiskBridge::DriveTypeID::dti35HD:
- drv->drive_id = DRIVE_ID_35HD;
- break;
- case FloppyDiskBridge::DriveTypeID::dti5255SD:
- drv->drive_id = DRIVE_ID_525SD;
- break;
- }
- } else {
- drv->drive_id = DRIVE_ID_35DD;
- }
- drv->ddhd = drv->drive_id == DRIVE_ID_35HD ? 2 : 1;
- return;
- }
- #endif
- switch (t)
- {
- case DRV_35_HD:
- #ifdef FLOPPY_DRIVE_HD
- if (!drv->diskfile || drv->ddhd <= 1)
- drv->drive_id = DRIVE_ID_35DD;
- else
- drv->drive_id = DRIVE_ID_35HD;
- #else
- drv->drive_id = DRIVE_ID_35DD;
- #endif
- break;
- case DRV_35_DD_ESCOM:
- case DRV_35_DD:
- case DRV_525_DD:
- default:
- drv->drive_id = DRIVE_ID_35DD;
- break;
- case DRV_525_SD:
- drv->drive_id = DRIVE_ID_525SD;
- break;
- case DRV_NONE:
- case DRV_PC_525_ONLY_40:
- case DRV_PC_525_40_80:
- case DRV_PC_35_ONLY_80:
- drv->drive_id = DRIVE_ID_NONE;
- break;
- }
- #ifdef DEBUG_DRIVE_ID
- write_log (_T("drive_settype_id: DF%d: set to %s\n"), drv-floppy, drive_id_name(drv));
- #endif
- }
- static void drive_image_free (drive *drv)
- {
- switch (drv->filetype)
- {
- case ADF_IPF:
- #ifdef CAPS
- caps_unloadimage (drv - floppy);
- #endif
- break;
- case ADF_SCP:
- #ifdef SCP
- scp_close (drv - floppy);
- #endif
- break;
- case ADF_FDI:
- #ifdef FDI2RAW
- fdi2raw_header_free (drv->fdi);
- drv->fdi = 0;
- #endif
- break;
- }
- drv->filetype = ADF_NONE;
- zfile_fclose(drv->diskfile);
- drv->diskfile = NULL;
- zfile_fclose(drv->writediskfile);
- drv->writediskfile = NULL;
- zfile_fclose(drv->pcdecodedfile);
- drv->pcdecodedfile = NULL;
- }
- static int drive_insert (drive * drv, struct uae_prefs *p, int dnum, const TCHAR *fname, bool fake, bool writeprotected);
- static void reset_drive_gui (int num)
- {
- struct gui_info_drive *gid = &gui_data.drives[num];
- gid->drive_disabled = 0;
- gid->df[0] = 0;
- gid->crc32 = 0;
- if (currprefs.floppyslots[num].dfxtype < 0)
- gid->drive_disabled = 1;
- }
- static void setamax (void)
- {
- #ifdef AMAX
- amax_enabled = false;
- if (is_device_rom(&currprefs, ROMTYPE_AMAX, 0) > 0) {
- /* Put A-Max as last drive in drive chain */
- int j;
- amax_enabled = true;
- for (j = 0; j < MAX_FLOPPY_DRIVES; j++)
- if (floppy[j].amax)
- return;
- for (j = 0; j < MAX_FLOPPY_DRIVES; j++) {
- if ((1 << j) & disabled) {
- floppy[j].amax = 1;
- write_log (_T("AMAX: drive %d\n"), j);
- return;
- }
- }
- }
- #endif
- }
- static bool ispcbridgedrive(int num)
- {
- int type = currprefs.floppyslots[num].dfxtype;
- return type == DRV_PC_525_ONLY_40 || type == DRV_PC_35_ONLY_80 || type == DRV_PC_525_40_80;
- }
- static bool drive_writeprotected(drive *drv)
- {
- #ifdef FLOPPYBRIDGE
- if (drv->bridge) {
- bool v = drv->bridge->isWriteProtected();
- return v;
- }
- #endif
- #ifdef CATWEASEL
- if (drv->catweasel)
- return 1;
- #endif
- return currprefs.floppy_read_only || drv->wrprot || drv->forcedwrprot || drv->diskfile == NULL;
- }
- static void reset_drive (int num)
- {
- drive *drv = &floppy[num];
- drv->amax = 0;
- drive_image_free (drv);
- drv->motoroff = 1;
- drv->idbit = 0;
- drv->drive_id = 0;
- drv->drive_id_scnt = 0;
- drv->lastdataacesstrack = -1;
- disabled &= ~(1 << num);
- reserved &= ~(1 << num);
- if (currprefs.floppyslots[num].dfxtype < 0 || ispcbridgedrive(num))
- disabled |= 1 << num;
- if (ispcbridgedrive(num))
- reserved |= 1 << num;
- reset_drive_gui (num);
- /* most internal Amiga floppy drives won't enable
- * diskready until motor is running at full speed
- * and next indexsync has been passed
- */
- drv->indexhackmode = 0;
- if (num == 0 && currprefs.floppyslots[num].dfxtype == 0)
- drv->indexhackmode = 1;
- drv->dskchange_time = 0;
- drv->dskchange = false;
- drv->dskready_down_time = 0;
- drv->dskready_up_time = 0;
- drv->buffered_cyl = -1;
- drv->buffered_side = -1;
- gui_led (num + LED_DF0, 0, -1);
- drive_settype_id (drv);
- _tcscpy (currprefs.floppyslots[num].df, changed_prefs.floppyslots[num].df);
- drv->newname[0] = 0;
- drv->newnamewriteprotected = false;
- #ifdef FLOPPYBRIDGE
- if (drv->bridge) {
- drv->bridge->resetDrive(drv->cyl);
- drv->indexhackmode = 0;
- drv->num_tracks = drv->bridge->getMaxCylinder() * 2;
- drv->filetype = ADF_FLOPPYBRIDGE;
- drv->tracklen = drv->bridge->maxMFMBitPosition();
- drv->ddhd = drv->bridge->getDriveTypeID() == FloppyDiskBridge::DriveTypeID::dti35HD ? 2 : 1;
- }
- #endif
- if (!drive_insert (drv, &currprefs, num, currprefs.floppyslots[num].df, false, false))
- disk_eject (num);
- }
- /* code for track display */
- static void update_drive_gui (int num, bool force)
- {
- drive *drv = floppy + num;
- bool writ = dskdmaen == DSKDMA_WRITE && drv->state && !((selected | disabled) & (1 << num));
- struct gui_info_drive *gid = &gui_data.drives[num];
- if (!force && drv->state == gid->drive_motor
- && drv->cyl == gid->drive_track
- && side == gui_data.drive_side
- && drv->crc32 == gid->crc32
- && writ == gid->drive_writing
- && drive_writeprotected(drv) == gid->floppy_protected
- && !_tcscmp (gid->df, currprefs.floppyslots[num].df))
- return;
- _tcscpy (gid->df, currprefs.floppyslots[num].df);
- gid->crc32 = drv->crc32;
- gid->drive_motor = drv->state;
- gid->drive_track = drv->cyl;
- if (reserved & (1 << num))
- gui_data.drive_side = reserved_side;
- else
- gui_data.drive_side = side;
- gid->drive_writing = writ;
- gid->floppy_protected = drive_writeprotected(drv);
- gid->floppy_inserted = gid->df[0] || (drv->bridge && !drv->bridge->hasDiskChanged());
- gui_led (num + LED_DF0, (gid->drive_motor ? 1 : 0) | (gid->drive_writing ? 2 : 0), -1);
- }
- static void drive_fill_bigbuf (drive * drv,int);
- void DISK_get_path_text(struct uae_prefs *p, int n, TCHAR *text)
- {
- _tcscpy(text, p->floppyslots[n].df);
- #ifdef FLOPPYBRIDGE
- if (DISK_isfloppybridge(p, n) && floppybridge_available) {
- if (!bridgeinfoloaded) {
- FloppyBridgeAPI::getBridgeDriverInformation(false, bridgeinfo);
- bridgeinfoloaded = 1;
- }
- _tcscpy(text, bridgeinfo.about);
- floppybridge_init(p);
- if (bridge_driver[n]) {
- _tcscat(text, _T(", "));
- TCHAR *name = au(bridge_driver[n]->name);
- TCHAR *man = au(bridge_driver[n]->manufacturer);
- _tcscat(text, name);
- _tcscat(text, _T(", "));
- _tcscat(text, man);
- xfree(man);
- xfree(name);
- }
- }
- #endif
- }
- int DISK_validate_filename (struct uae_prefs *p, const TCHAR *fname_in, int num, TCHAR *outfname, int leave_open, bool *wrprot, uae_u32 *crc32, struct zfile **zf)
- {
- TCHAR outname[MAX_DPATH];
- if (zf)
- *zf = NULL;
- if (crc32)
- *crc32 = 0;
- if (wrprot)
- *wrprot = p->floppy_read_only ? 1 : 0;
- if (outfname)
- outfname[0] = 0;
- #ifdef FLOPPYBRIDGE
- if (DISK_isfloppybridge(p, num)) {
- return 1;
- }
- #endif
- cfgfile_resolve_path_out_load(fname_in, outname, MAX_DPATH, PATH_FLOPPY);
- if (outfname)
- _tcscpy(outfname, outname);
- if (leave_open || !zf) {
- struct zfile *f = zfile_fopen (outname, _T("r+b"), ZFD_NORMAL | ZFD_DISKHISTORY);
- if (!f) {
- if (wrprot)
- *wrprot = 1;
- f = zfile_fopen (outname, _T("rb"), ZFD_NORMAL | ZFD_DISKHISTORY);
- }
- if (f && crc32)
- *crc32 = zfile_crc32 (f);
- if (!zf)
- zfile_fclose (f);
- else
- *zf = f;
- return f ? 1 : 0;
- } else {
- if (zfile_exists (outname)) {
- if (wrprot && !p->floppy_read_only)
- *wrprot = 0;
- if (crc32) {
- struct zfile *f = zfile_fopen (outname, _T("rb"), ZFD_NORMAL | ZFD_DISKHISTORY);
- if (f)
- *crc32 = zfile_crc32 (f);
- zfile_fclose (f);
- }
- return 1;
- } else {
- if (wrprot)
- *wrprot = 1;
- return 0;
- }
- }
- }
- static void updatemfmpos (drive *drv)
- {
- if (drv->prevtracklen) {
- drv->mfmpos = drv->mfmpos * (drv->tracklen * 1000 / drv->prevtracklen) / 1000;
- if (drv->mfmpos >= drv->tracklen)
- drv->mfmpos = drv->tracklen - 1;
- }
- drv->mfmpos %= drv->tracklen;
- drv->prevtracklen = drv->tracklen;
- }
- static void track_reset (drive *drv)
- {
- drv->tracklen = FLOPPY_WRITE_LEN * drv->ddhd * 2 * 8;
- drv->revolutions = 1;
- drv->trackspeed = get_floppy_speed ();
- drv->buffered_side = -1;
- drv->skipoffset = -1;
- drv->tracktiming[0] = 0;
- memset (drv->bigmfmbuf, 0xaa, FLOPPY_WRITE_LEN * 2 * drv->ddhd);
- updatemfmpos (drv);
- }
- static int read_header_ext2 (struct zfile *diskfile, trackid *trackdata, int *num_tracks, int *ddhd)
- {
- uae_u8 buffer[2 + 2 + 4 + 4];
- trackid *tid;
- int offs;
- int i;
- zfile_fseek (diskfile, 0, SEEK_SET);
- zfile_fread (buffer, 1, 8, diskfile);
- if (strncmp ((char*)buffer, "UAE-1ADF", 8))
- return 0;
- zfile_fread (buffer, 1, 4, diskfile);
- *num_tracks = buffer[2] * 256 + buffer[3];
- offs = 8 + 2 + 2 + (*num_tracks) * (2 + 2 + 4 + 4);
- for (i = 0; i < (*num_tracks); i++) {
- tid = trackdata + i;
- zfile_fread (buffer, 2 + 2 + 4 + 4, 1, diskfile);
- tid->type = (image_tracktype)buffer[3];
- tid->revolutions = buffer[2] + 1;
- tid->len = buffer[5] * 65536 + buffer[6] * 256 + buffer[7];
- tid->bitlen = buffer[9] * 65536 + buffer[10] * 256 + buffer[11];
- tid->offs = offs;
- if (tid->len > 20000 && ddhd)
- *ddhd = 2;
- tid->track = i;
- offs += tid->len;
- }
- return 1;
- }
- static void saveimagecutpathpart(TCHAR *name)
- {
- int i;
- i = _tcslen (name) - 1;
- while (i > 0) {
- if (name[i] == '/' || name[i] == '\\') {
- name[i] = 0;
- break;
- }
- if (name[i] == '.') {
- name[i] = 0;
- break;
- }
- i--;
- }
- while (i > 0) {
- if (name[i] == '/' || name[i] == '\\') {
- name[i] = 0;
- break;
- }
- i--;
- }
- }
- static void saveimagecutfilepart(TCHAR *name)
- {
- TCHAR tmp[MAX_DPATH];
- int i;
- _tcscpy(tmp, name);
- i = _tcslen (tmp) - 1;
- while (i > 0) {
- if (tmp[i] == '/' || tmp[i] == '\\') {
- _tcscpy(name, tmp + i + 1);
- break;
- }
- if (tmp[i] == '.') {
- tmp[i] = 0;
- break;
- }
- i--;
- }
- while (i > 0) {
- if (tmp[i] == '/' || tmp[i] == '\\') {
- _tcscpy(name, tmp + i + 1);
- break;
- }
- i--;
- }
- }
- static void saveimageaddfilename(TCHAR *dst, const TCHAR *src, int type)
- {
- _tcscat(dst, src);
- if (type)
- _tcscat(dst, _T(".save_adf"));
- else
- _tcscat(dst, _T("_save.adf"));
- }
- static TCHAR *DISK_get_default_saveimagepath (const TCHAR *name)
- {
- TCHAR name1[MAX_DPATH];
- TCHAR path[MAX_DPATH];
- _tcscpy(name1, name);
- saveimagecutfilepart(name1);
- fetch_saveimagepath (path, sizeof path / sizeof (TCHAR), 1);
- saveimageaddfilename(path, name1, 0);
- return my_strdup(path);
- }
- // -2 = existing, if not, use 0.
- // -1 = as configured
- // 0 = saveimages-dir
- // 1 = image dir
- TCHAR *DISK_get_saveimagepath(const TCHAR *name, int type)
- {
- int typev = type;
- for (int i = 0; i < 2; i++) {
- if (typev == 1 || (typev == -1 && saveimageoriginalpath) || (typev == -2 && (saveimageoriginalpath || i == 1))) {
- TCHAR si_name[MAX_DPATH], si_path[MAX_DPATH];
- _tcscpy(si_name, name);
- _tcscpy(si_path, name);
- saveimagecutfilepart(si_name);
- saveimagecutpathpart(si_path);
- _tcscat(si_path, FSDB_DIR_SEPARATOR_S);
- saveimageaddfilename(si_path, si_name, 1);
- if (typev != -2 || (typev == -2 && zfile_exists(si_path)))
- return my_strdup(si_path);
- }
- if (typev == 2 || (typev == -1 && !saveimageoriginalpath) || (typev == -2 && (!saveimageoriginalpath || i == 1))) {
- TCHAR *p = DISK_get_default_saveimagepath(name);
- if (typev != -2 || (typev == -2 && zfile_exists(p)))
- return p;
- xfree(p);
- }
- }
- return DISK_get_saveimagepath(name, -1);
- }
- static struct zfile *getexistingwritefile(struct uae_prefs *p, const TCHAR *name, int num, bool *wrprot)
- {
- struct zfile *zf = NULL;
- TCHAR *path;
- TCHAR outname[MAX_DPATH];
- path = DISK_get_saveimagepath(name, saveimageoriginalpath);
- DISK_validate_filename(p, path, num, outname, 1, wrprot, NULL, &zf);
- xfree(path);
- if (zf)
- return zf;
- path = DISK_get_saveimagepath(name, !saveimageoriginalpath);
- DISK_validate_filename(p, path, num, outname, 1, wrprot, NULL, &zf);
- xfree(path);
- return zf;
- }
- static int iswritefileempty(struct uae_prefs *p, int num, const TCHAR *name)
- {
- struct zfile *zf;
- bool wrprot;
- uae_char buffer[8];
- trackid td[MAX_TRACKS];
- int tracks, ddhd, i, ret;
- zf = getexistingwritefile(p, name, num, &wrprot);
- if (!zf)
- return 1;
- zfile_fread (buffer, sizeof (char), 8, zf);
- if (strncmp((uae_char*)buffer, "UAE-1ADF", 8)) {
- zfile_fclose(zf);
- return 0;
- }
- ret = read_header_ext2 (zf, td, &tracks, &ddhd);
- zfile_fclose (zf);
- if (!ret)
- return 1;
- for (i = 0; i < tracks; i++) {
- if (td[i].bitlen)
- return 0;
- }
- return 1;
- }
- static int openwritefile (struct uae_prefs *p, drive *drv, int create)
- {
- bool wrprot = 0;
- drv->writediskfile = getexistingwritefile(p, currprefs.floppyslots[drv - &floppy[0]].df, drv - &floppy[0], &wrprot);
- if (drv->writediskfile) {
- drv->wrprot = wrprot;
- if (!read_header_ext2 (drv->writediskfile, drv->writetrackdata, &drv->write_num_tracks, 0)) {
- zfile_fclose (drv->writediskfile);
- drv->writediskfile = 0;
- drv->wrprot = 1;
- } else {
- if (drv->write_num_tracks > drv->num_tracks)
- drv->num_tracks = drv->write_num_tracks;
- }
- } else if (zfile_iscompressed (drv->diskfile)) {
- drv->wrprot = 1;
- }
- return drv->writediskfile ? 1 : 0;
- }
- static bool diskfile_iswriteprotect (struct uae_prefs *p, const TCHAR *fname_in, int num, int *needwritefile, drive_type *drvtype)
- {
- struct zfile *zf1, *zf2;
- bool wrprot1 = 0, wrprot2 = 1;
- uae_char buffer[25];
- TCHAR outname[MAX_DPATH];
- *needwritefile = 0;
- *drvtype = DRV_35_DD;
- DISK_validate_filename (p, fname_in, num, outname, 1, &wrprot1, NULL, &zf1);
- if (!zf1)
- return 1;
- if (zfile_iscompressed (zf1)) {
- wrprot1 = 1;
- *needwritefile = 1;
- }
- zf2 = getexistingwritefile(p, fname_in, num, &wrprot2);
- zfile_fclose (zf2);
- zfile_fread (buffer, sizeof (char), 25, zf1);
- zfile_fclose (zf1);
- if (strncmp ((uae_char*) buffer, "CAPS", 4) == 0) {
- *needwritefile = 1;
- return wrprot2;
- }
- if (strncmp ((uae_char*) buffer, "SCP", 3) == 0) {
- *needwritefile = 1;
- return wrprot2;
- }
- if (strncmp ((uae_char*) buffer, "Formatted Disk Image file", 25) == 0) {
- *needwritefile = 1;
- return wrprot2;
- }
- if (strncmp ((uae_char*) buffer, "UAE-1ADF", 8) == 0) {
- if (wrprot1)
- return wrprot2;
- return wrprot1;
- }
- if (strncmp ((uae_char*) buffer, "UAE--ADF", 8) == 0) {
- *needwritefile = 1;
- return wrprot2;
- }
- if (memcmp (exeheader, buffer, sizeof exeheader) == 0)
- return 0;
- if (wrprot1)
- return wrprot2;
- return wrprot1;
- }
- static bool isrecognizedext(const TCHAR *name)
- {
- const TCHAR *ext = _tcsrchr(name, '.');
- if (ext) {
- ext++;
- if (!_tcsicmp(ext, _T("adf")) || !_tcsicmp(ext, _T("adz")) || !_tcsicmp(ext, _T("st")) ||
- !_tcsicmp(ext, _T("ima")) || !_tcsicmp(ext, _T("img")) || !_tcsicmp(ext, _T("dsk")))
- return true;
- }
- return false;
- }
- static void update_disk_statusline(int num)
- {
- drive *drv = &floppy[num];
- #ifdef FLOPPYBRIDGE
- if (drv->bridge) {
- const char *name = drv->bridge->getDriverInfo()->name;
- TCHAR *n = au(name);
- statusline_add_message(STATUSTYPE_FLOPPY, _T("DF%d: %s"), num, n);
- xfree(n);
- return;
- }
- #endif
- if (!drv->diskfile)
- return;
- const TCHAR *fname = zfile_getoriginalname(drv->diskfile);
- if (!fname)
- fname = zfile_getname(drv->diskfile);
- if (!fname)
- fname = _T("?");
- if (disk_info_data.diskname[0])
- statusline_add_message(STATUSTYPE_FLOPPY, _T("DF%d: [%s] %s"), num, disk_info_data.diskname, my_getfilepart(fname));
- else
- statusline_add_message(STATUSTYPE_FLOPPY, _T("DF%d: %s"), num, my_getfilepart(fname));
- }
- static int drive_insert (drive *drv, struct uae_prefs *p, int dnum, const TCHAR *fname_in, bool fake, bool forcedwriteprotect)
- {
- uae_u8 buffer[2 + 2 + 4 + 4];
- trackid *tid;
- int num_tracks, size;
- int canauto;
- TCHAR outname[MAX_DPATH];
- int dfxtype = p->floppyslots[dnum].dfxtype;
- drive_image_free (drv);
- if (!fake && !drv->bridge) {
- DISK_examine_image(p, dnum, &disk_info_data, false, NULL);
- }
- DISK_validate_filename (p, fname_in, dnum, outname, 1, &drv->wrprot, &drv->crc32, &drv->diskfile);
- drv->forcedwrprot = forcedwriteprotect;
- if (drv->forcedwrprot)
- drv->wrprot = true;
- drv->ddhd = 1;
- drv->num_heads = 2;
- drv->num_secs = 0;
- drv->hard_num_cyls = dfxtype == DRV_525_SD ? 40 : 80;
- drv->tracktiming[0] = 0;
- drv->useturbo = 0;
- drv->indexoffset = 0;
- if (!fake) {
- drv->dskeject = false;
- gui_disk_image_change (dnum, outname, drv->wrprot);
- }
- if (!drv->motoroff) {
- drv->dskready_up_time = DSKREADY_UP_TIME * 312 + (uaerand() & 511);
- drv->dskready_down_time = 0;
- }
- if (drv->diskfile == NULL && !drv->catweasel && !drv->bridge) {
- track_reset (drv);
- return 0;
- }
- if (!fake) {
- inprec_recorddiskchange (dnum, fname_in, drv->wrprot);
- if (currprefs.floppyslots[dnum].df != fname_in) {
- _tcsncpy (currprefs.floppyslots[dnum].df, fname_in, 255);
- currprefs.floppyslots[dnum].df[255] = 0;
- }
- currprefs.floppyslots[dnum].forcedwriteprotect = forcedwriteprotect;
- _tcsncpy (changed_prefs.floppyslots[dnum].df, fname_in, 255);
- changed_prefs.floppyslots[dnum].df[255] = 0;
- changed_prefs.floppyslots[dnum].forcedwriteprotect = forcedwriteprotect;
- _tcscpy (drv->newname, fname_in);
- drv->newnamewriteprotected = forcedwriteprotect;
- gui_filename (dnum, outname);
- }
- memset (buffer, 0, sizeof buffer);
- size = 0;
- if (drv->diskfile) {
- zfile_fread (buffer, sizeof (char), 8, drv->diskfile);
- zfile_fseek (drv->diskfile, 0, SEEK_END);
- size = (int)zfile_ftell (drv->diskfile);
- zfile_fseek (drv->diskfile, 0, SEEK_SET);
- }
- canauto = 0;
- if (isrecognizedext (outname))
- canauto = 1;
- if (!canauto && drv->diskfile && isrecognizedext (zfile_getname (drv->diskfile)))
- canauto = 1;
- // if PC-only drive, make sure PC-like floppies are always detected
- if (!canauto && ispcbridgedrive(dnum))
- canauto = 1;
- if (drv->catweasel) {
- drv->wrprot = true;
- drv->filetype = ADF_CATWEASEL;
- drv->num_tracks = 80;
- drv->ddhd = 1;
- #ifdef FLOPPYBRIDGE
- } else if (drv->bridge) {
- drv->ddhd = (drv->bridge->getDriveTypeID() == FloppyDiskBridge::DriveTypeID::dti35HD) ? 2 : 1;
- drv->num_heads = 2;
- drv->num_secs = 0;
- drv->hard_num_cyls = drv->bridge->getMaxCylinder();
- drv->num_tracks = drv->bridge->getMaxCylinder() * 2;
- drv->tracklen = drv->bridge->maxMFMBitPosition();
- drv->tracktiming[0] = drv->bridge->getMFMSpeed(0);
- drv->multi_revolution = 1;
- drv->fourms = (drv->bridge->getBitSpeed() == 4);
- drv->indexoffset = 0;
- drv->prevtracklen = 0;
- drv->forcedwrprot = false;
- drv->wrprot = drv->bridge->isWriteProtected();
- drv->filetype = ADF_FLOPPYBRIDGE;
- drv->useturbo = 0;
- drv->mfmpos = uaerand();
- drv->mfmpos |= (uaerand() << 16);
- drv->mfmpos %= drv->tracklen;
- drv->prevtracklen = 0;
- drive_settype_id(drv); /* Set DD or HD drive */
- update_drive_gui(drv - floppy, false);
- update_disk_statusline(drv - floppy);
- drive_fill_bigbuf(drv, fake ? -1 : 1);
- return 1;
- #endif
- #ifdef CAPS
- } else if (strncmp ((char*)buffer, "CAPS", 4) == 0) {
- drv->wrprot = true;
- if (!caps_loadimage (drv->diskfile, drv - floppy, &num_tracks)) {
- zfile_fclose (drv->diskfile);
- drv->diskfile = 0;
- return 0;
- }
- drv->num_tracks = num_tracks;
- drv->filetype = ADF_IPF;
- #endif
- #ifdef SCP
- } else if (strncmp ((char*)buffer, "SCP", 3) == 0) {
- drv->wrprot = true;
- if (!scp_open (drv->diskfile, drv - floppy, &num_tracks)) {
- zfile_fclose (drv->diskfile);
- drv->diskfile = 0;
- return 0;
- }
- drv->num_tracks = num_tracks;
- drv->filetype = ADF_SCP;
- #endif
- #ifdef FDI2RAW
- } else if ((drv->fdi = fdi2raw_header (drv->diskfile))) {
- drv->wrprot = true;
- drv->num_tracks = fdi2raw_get_last_track (drv->fdi);
- drv->num_secs = fdi2raw_get_num_sector (drv->fdi);
- drv->filetype = ADF_FDI;
- #endif
- } else if (strncmp ((char*)buffer, "UAE-1ADF", 8) == 0) {
- read_header_ext2 (drv->diskfile, drv->trackdata, &drv->num_tracks, &drv->ddhd);
- drv->filetype = ADF_EXT2;
- drv->num_secs = 11;
- if (drv->ddhd > 1)
- drv->num_secs = 22;
- } else if (strncmp ((char*)buffer, "UAE--ADF", 8) == 0) {
- int offs = 160 * 4 + 8;
- drv->wrprot = true;
- drv->filetype = ADF_EXT1;
- drv->num_tracks = 160;
- drv->num_secs = 11;
- zfile_fseek (drv->diskfile, 8, SEEK_SET);
- for (int i = 0; i < 160; i++) {
- tid = &drv->trackdata[i];
- zfile_fread (buffer, 4, 1, drv->diskfile);
- tid->sync = buffer[0] * 256 + buffer[1];
- tid->len = buffer[2] * 256 + buffer[3];
- tid->offs = offs;
- tid->revolutions = 1;
- if (tid->sync == 0) {
- tid->type = TRACK_AMIGADOS;
- tid->bitlen = 0;
- } else {
- tid->type = TRACK_RAW1;
- tid->bitlen = tid->len * 8;
- }
- offs += tid->len;
- }
- } else if (memcmp (exeheader, buffer, sizeof exeheader) == 0 && !canauto && size <= 512 * (1760 * 2 - 7)) {
- bool ffs = false;
- int hd = 1;
- int freeblocks = 1760 - 7;
- int blocks_ofs = (size + FS_OFS_DATABLOCKSIZE - 1) / FS_OFS_DATABLOCKSIZE;
- int extensionblocks_ofs = (blocks_ofs + FS_EXTENSION_BLOCKS - 1) / FS_EXTENSION_BLOCKS;
- int blocks_ffs = (size + FS_FLOPPY_BLOCKSIZE - 1) / FS_FLOPPY_BLOCKSIZE;
- int extensionblocks_ffs = (blocks_ffs + FS_EXTENSION_BLOCKS - 1) / FS_EXTENSION_BLOCKS;
- // select DD+FFS if file larger than DD+OFS
- if (size > FS_OFS_DATABLOCKSIZE * (freeblocks - extensionblocks_ofs)) {
- ffs = true;
- // select HD+FFS if file larger than DD+FFS
- if (size > FS_FLOPPY_BLOCKSIZE * (freeblocks - extensionblocks_ffs)) {
- hd = 2;
- }
- }
- if (dfxtype == DRV_35_DD) {
- hd = 1;
- }
- if (size <= 512 * (1760 * hd - 7)) {
- struct zfile *z = zfile_fopen_empty(NULL, _T(""), 512 * 1760 * hd);
- createimagefromexe(drv->diskfile, z, hd, ffs);
- drv->filetype = ADF_NORMAL;
- zfile_fclose(drv->diskfile);
- drv->diskfile = z;
- drv->num_tracks = 160;
- drv->num_secs = 11 * hd;
- for (int i = 0; i < drv->num_tracks; i++) {
- tid = &drv->trackdata[i];
- tid->type = TRACK_AMIGADOS;
- tid->len = 512 * drv->num_secs;
- tid->bitlen = 0;
- tid->offs = i * 512 * drv->num_secs;
- tid->revolutions = 1;
- }
- drv->ddhd = hd;
- drv->useturbo = 1;
- }
- } else if (canauto && (
- // 320k double sided
- size == 8 * 40 * 2 * 512 ||
- // 320k single sided
- size == 8 * 40 * 1 * 512 ||
- // 360k double sided
- size == 9 * 40 * 2 * 512 ||
- // 360k single sided
- size == 9 * 40 * 1 * 512 ||
- // 1.2M double sided
- size == 15 * 80 * 2 * 512 ||
- // 720k/1440k double sided
- size == 9 * 80 * 2 * 512 || size == 18 * 80 * 2 * 512 || size == 10 * 80 * 2 * 512 || size == 20 * 80 * 2 * 512 || size == 21 * 80 * 2 * 512 ||
- size == 9 * 81 * 2 * 512 || size == 18 * 81 * 2 * 512 || size == 10 * 81 * 2 * 512 || size == 20 * 81 * 2 * 512 || size == 21 * 81 * 2 * 512 ||
- size == 9 * 82 * 2 * 512 || size == 18 * 82 * 2 * 512 || size == 10 * 82 * 2 * 512 || size == 20 * 82 * 2 * 512 || size == 21 * 82 * 2 * 512 ||
- // 720k/1440k single sided
- size == 9 * 80 * 1 * 512 || size == 18 * 80 * 1 * 512 || size == 10 * 80 * 1 * 512 || size == 20 * 80 * 1 * 512 ||
- size == 9 * 81 * 1 * 512 || size == 18 * 81 * 1 * 512 || size == 10 * 81 * 1 * 512 || size == 20 * 81 * 1 * 512 ||
- size == 9 * 82 * 1 * 512 || size == 18 * 82 * 1 * 512 || size == 10 * 82 * 1 * 512 || size == 20 * 82 * 1 * 512)) {
- /* PC formatted image */
- int side, sd;
- drv->num_secs = 9;
- drv->ddhd = 1;
- sd = 0;
- bool can40 = dfxtype == DRV_525_DD || dfxtype == DRV_PC_525_ONLY_40 || dfxtype == DRV_PC_525_40_80;
- bool can80 = dfxtype == DRV_35_HD || dfxtype == DRV_PC_35_ONLY_80 || dfxtype == DRV_PC_525_40_80;
- bool drv525 = dfxtype == DRV_525_DD || dfxtype == DRV_PC_525_ONLY_40 || dfxtype == DRV_PC_525_40_80;
-
- for (side = 2; side > 0; side--) {
- if (drv->hard_num_cyls >= 80 && can80) {
- if ( size == 9 * 80 * side * 512 || size == 9 * 81 * side * 512 || size == 9 * 82 * side * 512) {
- drv->num_secs = 9;
- drv->ddhd = 1;
- break;
- } else if (!drv525 && (size == 18 * 80 * side * 512 || size == 18 * 81 * side * 512 || size == 18 * 82 * side * 512)) {
- drv->num_secs = 18;
- drv->ddhd = 2;
- break;
- } else if (!drv525 && (size == 10 * 80 * side * 512 || size == 10 * 81 * side * 512 || size == 10 * 82 * side * 512)) {
- drv->num_secs = 10;
- drv->ddhd = 1;
- break;
- } else if (!drv525 && (size == 20 * 80 * side * 512 || size == 20 * 81 * side * 512 || size == 20 * 82 * side * 512)) {
- drv->num_secs = 20;
- drv->ddhd = 2;
- break;
- } else if (!drv525 && (size == 21 * 80 * side * 512 || size == 21 * 81 * side * 512 || size == 21 * 82 * side * 512)) {
- drv->num_secs = 21;
- drv->ddhd = 2;
- break;
- } else if (size == 15 * 80 * side * 512) {
- drv->num_secs = 15;
- drv->ddhd = 1;
- break;
- }
- }
- if (drv->hard_num_cyls == 40 || can40) {
- if (size == 9 * 40 * side * 512) {
- drv->num_secs = 9;
- drv->ddhd = 1;
- sd = 1;
- break;
- } else if (size == 8 * 40 * side * 512) {
- drv->num_secs = 8;
- drv->ddhd = 1;
- sd = 1;
- break;
- }
- }
- }
- drv->num_tracks = size / (drv->num_secs * 512);
- // SD disk in 5.25 drive = duplicate each track
- if (sd && dfxtype == DRV_525_DD) {
- drv->num_tracks *= 2;
- } else {
- sd = 0;
- }
- drv->filetype = ADF_PCDOS;
- tid = &drv->trackdata[0];
- for (int i = 0; i < drv->num_tracks; i++) {
- tid->type = TRACK_PCDOS;
- tid->len = 512 * drv->num_secs;
- tid->bitlen = 0;
- tid->offs = (sd ? i / 2 : i) * 512 * drv->num_secs;
- if (side == 1) {
- tid++;
- tid->type = TRACK_NONE;
- tid->len = 512 * drv->num_secs;
- }
- tid->revolutions = 1;
- tid++;
- }
- drv->num_heads = side;
- if (side == 1)
- drv->num_tracks *= 2;
- } else if ((size == 262144 || size == 524288) && buffer[0] == 0x11 && (buffer[1] == 0x11 || buffer[1] == 0x14)) {
- // 256k -> KICK disk, 512k -> SuperKickstart disk
- drv->filetype = size == 262144 ? ADF_KICK : ADF_SKICK;
- drv->num_tracks = 1760 / (drv->num_secs = 11);
- for (int i = 0; i < drv->num_tracks; i++) {
- tid = &drv->trackdata[i];
- tid->type = TRACK_AMIGADOS;
- tid->len = 512 * drv->num_secs;
- tid->bitlen = 0;
- tid->offs = i * 512 * drv->num_secs - (drv->filetype == ADF_KICK ? 512 : 262144 + 1024);
- tid->track = i;
- tid->revolutions = 1;
- }
- } else {
- int ds;
- ds = 0;
- drv->filetype = ADF_NORMAL;
- /* High-density, diskspare disk or sector headers included? */
- drv->num_tracks = 0;
- if (size > 160 * 11 * 512 + 511) { // larger than standard adf?
- for (int i = 80; i <= 83; i++) {
- if (size == i * 22 * 512 * 2) { // HD
- drv->ddhd = 2;
- drv->num_tracks = size / (512 * (drv->num_secs = 22));
- break;
- }
- if (size == i * 11 * 512 * 2) { // >80 cyl DD
- drv->num_tracks = size / (512 * (drv->num_secs = 11));
- break;
- }
- if (size == i * 12 * 512 * 2) { // ds 12 sectors
- drv->num_tracks = size / (512 * (drv->num_secs = 12));
- ds = 1;
- break;
- }
- if (size == i * 24 * 512 * 2) { // ds 24 sectors
- drv->num_tracks = size / (512 * (drv->num_secs = 24));
- drv->ddhd = 2;
- ds = 1;
- break;
- }
- if (size == i * 11 * (512 + 16) * 2) { // 80+ cyl DD + headers
- drv->num_tracks = size / ((512 + 16) * (drv->num_secs = 11));
- drv->filetype = ADF_NORMAL_HEADER;
- break;
- }
- if (size == i * 22 * (512 + 16) * 2) { // 80+ cyl HD + headers
- drv->num_tracks = size / ((512 + 16) * (drv->num_secs = 22));
- drv->filetype = ADF_NORMAL_HEADER;
- break;
- }
- }
- if (drv->num_tracks == 0) {
- drv->num_tracks = size / (512 * (drv->num_secs = 22));
- drv->ddhd = 2;
- }
- } else {
- drv->num_tracks = size / (512 * (drv->num_secs = 11));
- }
- if (!ds && drv->num_tracks > MAX_TRACKS)
- write_log (_T("Your diskfile is too big, %d bytes!\n"), size);
- for (int i = 0; i < drv->num_tracks; i++) {
- tid = &drv->trackdata[i];
- tid->type = ds ? TRACK_DISKSPARE : TRACK_AMIGADOS;
- tid->len = 512 * drv->num_secs;
- tid->bitlen = 0;
- tid->offs = i * 512 * drv->num_secs;
- tid->revolutions = 1;
- if (drv->filetype == ADF_NORMAL_HEADER) {
- tid->extraoffs = drv->num_tracks * 512 * drv->num_secs + i * 16 * drv->num_secs;
- } else {
- tid->extraoffs = -1;
- }
- }
- }
- openwritefile (p, drv, 0);
- drive_settype_id (drv); /* Set DD or HD drive */
- drive_fill_bigbuf (drv, 1);
- drv->mfmpos = uaerand ();
- drv->mfmpos |= (uaerand () << 16);
- drv->mfmpos %= drv->tracklen;
- drv->prevtracklen = 0;
- if (!fake) {
- #ifdef DRIVESOUND
- if (isfloppysound (drv))
- driveclick_insert (drv - floppy, 0);
- #endif
- update_drive_gui (drv - floppy, false);
- update_disk_statusline(drv - floppy);
- }
- return 1;
- }
- static void rand_shifter (drive *drv)
- {
- if (selected & (1 << (drv - floppy)))
- return;
- int r = ((uaerand() >> 4) & 7) + 1;
- while (r-- > 0) {
- word <<= 1;
- word |= (uaerand() & 0x1000) ? 1 : 0;
- bitoffset++;
- bitoffset &= 15;
- }
- }
- static void set_steplimit (drive *drv)
- {
- // emulate step limit only if cycle-exact or approximate CPU speed
- if (currprefs.m68k_speed != 0)
- return;
- drv->steplimit = 4;
- drv->steplimitcycle = get_cycles ();
- }
- static bool drive_empty (drive * drv)
- {
- #ifdef FLOPPYBRIDGE
- if (drv->bridge) {
- bool v = drv->bridge->isDiskInDrive();
- return v == false;
- }
- #endif
- #ifdef CATWEASEL
- if (drv->catweasel)
- return catweasel_disk_changed (drv->catweasel) == 0;
- #endif
- return drv->diskfile == 0 && drv->dskchange_time >= 0;
- }
- static void drive_step (drive *drv, int step_direction)
- {
- #ifdef CATWEASEL
- if (drv->catweasel) {
- int dir = direction ? -1 : 1;
- catweasel_step (drv->catweasel, dir);
- drv->cyl += dir;
- if (drv->cyl < 0)
- drv->cyl = 0;
- write_log (_T("%d -> %d\n"), dir, drv->cyl);
- return;
- }
- #endif
- if (!drive_empty (drv))
- drv->dskchange = 0;
- #ifdef FLOPPYBRIDGE
- if (drv->bridge) {
- int dir = step_direction ? -1 : 1;
- drv->cyl += dir;
- if (drv->cyl < 0) {
- drv->cyl = 0;
- drv->bridge->handleNoClickStep(side);
- } else {
- if (drv->cyl >= drv->bridge->getMaxCylinder()) {
- drv->cyl = drv->bridge->getMaxCylinder() - 1;
- }
- drv->bridge->gotoCylinder(drv->cyl, side);
- }
- return;
- }
- #endif
- if (drv->steplimit && get_cycles() - drv->steplimitcycle < MIN_STEPLIMIT_CYCLE) {
- write_log (_T(" step ignored drive %ld, %lu\n"),
- drv - floppy, (get_cycles() - drv->steplimitcycle) / CYCLE_UNIT);
- return;
- }
- /* A1200's floppy drive needs at least 30 raster lines between steps
- * but we'll use very small value for better compatibility with faster CPU emulation
- * (stupid trackloaders with CPU delay loops)
- */
- set_steplimit (drv);
- if (step_direction) {
- if (drv->cyl) {
- drv->cyl--;
- #ifdef DRIVESOUND
- if (isfloppysound (drv))
- driveclick_click (drv - floppy, drv->cyl);
- #endif
- }
- /* else
- write_log (_T("program tried to step beyond track zero\n"));
- "no-click" programs does that
- */
- } else {
- int maxtrack = drv->hard_num_cyls;
- if (drv->cyl < maxtrack + 3) {
- drv->cyl++;
- #ifdef CATWEASEL
- if (drv->catweasel)
- catweasel_step (drv->catweasel, 1);
- #endif
- }
- if (drv->cyl >= maxtrack)
- write_log (_T("program tried to step over track %d PC %08x\n"), maxtrack, M68K_GETPC);
- #ifdef DRIVESOUND
- if (isfloppysound (drv))
- driveclick_click (drv - floppy, drv->cyl);
- #endif
- }
- rand_shifter (drv);
- if (disk_debug_logging > 2)
- write_log (_T(" ->step %d"), drv->cyl);
- }
- static bool drive_track0 (drive * drv)
- {
- #ifdef FLOPPYBRIDG…
Large files files are truncated, but you can click here to view the full file