PageRenderTime 95ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/disk.cpp

https://github.com/tonioni/WinUAE
C++ | 5979 lines | 5335 code | 459 blank | 185 comment | 1838 complexity | f4df4d55ceb951475eef724de372c779 MD5 | raw file
  1. /*
  2. * UAE - The Un*x Amiga Emulator
  3. *
  4. * Floppy disk emulation
  5. *
  6. * Copyright 1995 Hannu Rummukainen
  7. * Copyright 1995-2001 Bernd Schmidt
  8. * Copyright 2000-2021 Toni Wilen
  9. *
  10. * Original High Density Drive Handling by Dr. Adil Temel (C) 2001 [atemel1@hotmail.com]
  11. *
  12. * Small modifications to support abstracted Floppy Disk "Bridges" to hardware, Copyright 2021 Robert Smith, https://amiga.robsmithdev.co.uk
  13. *
  14. */
  15. #include "sysconfig.h"
  16. #include "sysdeps.h"
  17. int disk_debug_logging = 0;
  18. int disk_debug_mode = 0;
  19. int disk_debug_track = -1;
  20. #define REVOLUTION_DEBUG 0
  21. #define MFM_VALIDATOR 0
  22. #include "uae.h"
  23. #include "options.h"
  24. #include "memory.h"
  25. #include "events.h"
  26. #include "custom.h"
  27. #include "disk.h"
  28. #include "gui.h"
  29. #include "zfile.h"
  30. #include "newcpu.h"
  31. #include "osemu.h"
  32. #include "execlib.h"
  33. #include "savestate.h"
  34. #include "cia.h"
  35. #include "debug.h"
  36. #ifdef FDI2RAW
  37. #include "fdi2raw.h"
  38. #endif
  39. #include "catweasel.h"
  40. #include "driveclick.h"
  41. #ifdef CAPS
  42. #include "caps/caps_win32.h"
  43. #endif
  44. #ifdef SCP
  45. #include "scp.h"
  46. #endif
  47. #include "crc32.h"
  48. #include "inputrecord.h"
  49. #include "amax.h"
  50. #ifdef RETROPLATFORM
  51. #include "rp.h"
  52. #endif
  53. #include "fsdb.h"
  54. #include "statusline.h"
  55. #include "rommgr.h"
  56. #include "tinyxml2.h"
  57. #ifdef FLOPPYBRIDGE
  58. #include "floppybridge/floppybridge_abstract.h"
  59. #include "floppybridge/floppybridge_lib.h"
  60. #endif
  61. #undef CATWEASEL
  62. int floppy_writemode = 0;
  63. /* support HD floppies */
  64. #define FLOPPY_DRIVE_HD
  65. /* Writable track length with normal 2us bitcell/300RPM motor, 12688 PAL, 12784 NTSC */
  66. /* DMA clock / (7 clocks per bit * 5 revs per second * 8 bits per byte) */
  67. #define FLOPPY_WRITE_LEN_PAL 12668 // 3546895 / (7 * 5 * 8)
  68. #define FLOPPY_WRITE_LEN_NTSC 12784 // 3579545 / (7 * 5 * 8)
  69. #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)))
  70. #define FLOPPY_WRITE_MAXLEN 0x3800
  71. /* This works out to 350 PAL, 408 NTSC */
  72. #define FLOPPY_GAP_LEN (FLOPPY_WRITE_LEN - 11 * 544)
  73. /* 7 CCK per bit */
  74. #define NORMAL_FLOPPY_SPEED (7 * 256)
  75. /* max supported floppy drives, for small memory systems */
  76. #define MAX_FLOPPY_DRIVES 4
  77. #ifdef FLOPPY_DRIVE_HD
  78. #define DDHDMULT 2
  79. #else
  80. #define DDHDMULT 1
  81. #endif
  82. #define MAX_SECTORS (DDHDMULT * 11)
  83. #undef DEBUG_DRIVE_ID
  84. /* UAE-1ADF (ADF_EXT2)
  85. * W reserved
  86. * W number of tracks (default 2*80=160)
  87. *
  88. * W reserved
  89. * W type, 0=normal AmigaDOS track, 1 = raw MFM (upper byte = disk revolutions - 1)
  90. * L available space for track in bytes (must be even)
  91. * L track length in bits
  92. */
  93. static int side, direction, reserved_side;
  94. static uae_u8 selected = 15, disabled, reserved;
  95. static uae_u8 writebuffer[544 * MAX_SECTORS];
  96. static uae_u8 writesecheadbuffer[16 * MAX_SECTORS];
  97. #define DISK_INDEXSYNC 1
  98. #define DISK_WORDSYNC 2
  99. #define DISK_REVOLUTION 4 /* 8,16,32,64 */
  100. #define DSKREADY_UP_TIME 18
  101. #define DSKREADY_DOWN_TIME 24
  102. #define DSKDMA_OFF 0
  103. #define DSKDMA_INIT 1
  104. #define DSKDMA_READ 2
  105. #define DSKDMA_WRITE 3
  106. static int dskdmaen, dsklength, dsklength2, dsklen;
  107. static uae_u16 dskbytr_val;
  108. static uae_u32 dskpt;
  109. static bool fifo_filled;
  110. static uae_u16 fifo[3];
  111. static int fifo_inuse[3];
  112. static int dma_enable, bitoffset, syncoffset;
  113. static uae_u16 word, dsksync;
  114. static unsigned long dsksync_cycles;
  115. #define WORDSYNC_TIME 11
  116. /* Always carried through to the next line. */
  117. int disk_hpos;
  118. static int disk_jitter;
  119. static int indexdecay;
  120. static uae_u8 prev_data;
  121. static int prev_step;
  122. static bool initial_disk_statusline;
  123. static struct diskinfo disk_info_data = { 0 };
  124. static bool amax_enabled;
  125. typedef enum { TRACK_AMIGADOS, TRACK_RAW, TRACK_RAW1, TRACK_PCDOS, TRACK_DISKSPARE, TRACK_NONE } image_tracktype;
  126. typedef struct {
  127. uae_u16 len;
  128. int offs, extraoffs;
  129. int bitlen, track;
  130. uae_u16 sync;
  131. image_tracktype type;
  132. int revolutions;
  133. } trackid;
  134. #define MAX_TRACKS (2 * 83)
  135. /* We have three kinds of Amiga floppy drives
  136. * - internal A500/A2000 drive:
  137. * ID is always DRIVE_ID_NONE (S.T.A.G expects this)
  138. * - HD drive (A3000/A4000):
  139. * ID is DRIVE_ID_35DD if DD floppy is inserted or drive is empty
  140. * ID is DRIVE_ID_35HD if HD floppy is inserted
  141. * - regular external drive:
  142. * ID is always DRIVE_ID_35DD
  143. */
  144. #define DRIVE_ID_NONE 0x00000000
  145. #define DRIVE_ID_35DD 0xFFFFFFFF
  146. #define DRIVE_ID_35HD 0xAAAAAAAA
  147. #define DRIVE_ID_525SD 0x55555555 /* 40 track 5.25 drive , kickstart does not recognize this */
  148. 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;
  149. typedef struct {
  150. struct zfile *diskfile;
  151. struct zfile *writediskfile;
  152. struct zfile *pcdecodedfile;
  153. drive_filetype filetype;
  154. trackid trackdata[MAX_TRACKS];
  155. trackid writetrackdata[MAX_TRACKS];
  156. int buffered_cyl, buffered_side;
  157. int cyl;
  158. bool motoroff;
  159. int motordelay; /* dskrdy needs some clock cycles before it changes after switching off motor */
  160. bool state;
  161. int selected_delay;
  162. bool wrprot;
  163. bool forcedwrprot;
  164. uae_u16 bigmfmbuf[0x4000 * DDHDMULT];
  165. uae_u16 tracktiming[0x4000 * DDHDMULT];
  166. int multi_revolution;
  167. int revolution_check;
  168. int skipoffset;
  169. int mfmpos;
  170. int indexoffset;
  171. int tracklen;
  172. int revolutions;
  173. int prevtracklen;
  174. int trackspeed;
  175. int num_tracks, write_num_tracks, num_secs, num_heads;
  176. int hard_num_cyls;
  177. bool dskeject;
  178. bool dskchange;
  179. int dskchange_time;
  180. bool dskready;
  181. int dskready_up_time;
  182. int dskready_down_time;
  183. int writtento;
  184. int steplimit;
  185. frame_time_t steplimitcycle;
  186. int indexhack, indexhackmode;
  187. int ddhd; /* 1=DD 2=HD */
  188. int drive_id_scnt; /* drive id shift counter */
  189. int idbit;
  190. unsigned long drive_id; /* drive id to be reported */
  191. TCHAR newname[256]; /* storage space for new filename during eject delay */
  192. bool newnamewriteprotected;
  193. uae_u32 crc32;
  194. #ifdef FDI2RAW
  195. FDI *fdi;
  196. #endif
  197. int useturbo;
  198. int floppybitcounter; /* number of bits left */
  199. #ifdef CATWEASEL
  200. catweasel_drive *catweasel;
  201. #else
  202. int catweasel;
  203. int amax;
  204. int lastdataacesstrack;
  205. int lastrev;
  206. bool track_access_done;
  207. bool fourms;
  208. #endif
  209. #ifdef FLOPPYBRIDGE
  210. FloppyDiskBridge *bridge;
  211. bool writepending;
  212. #endif
  213. } drive;
  214. #define MIN_STEPLIMIT_CYCLE (CYCLE_UNIT * 140)
  215. static uae_u16 bigmfmbufw[0x4000 * DDHDMULT];
  216. static drive floppy[MAX_FLOPPY_DRIVES];
  217. static TCHAR dfxhistory[HISTORY_MAX][MAX_PREVIOUS_IMAGES][MAX_DPATH];
  218. static uae_u8 exeheader[]={0x00,0x00,0x03,0xf3,0x00,0x00,0x00,0x00};
  219. static uae_u8 bootblock_ofs[]={
  220. 0x44,0x4f,0x53,0x00,0xc0,0x20,0x0f,0x19,0x00,0x00,0x03,0x70,0x43,0xfa,0x00,0x18,
  221. 0x4e,0xae,0xff,0xa0,0x4a,0x80,0x67,0x0a,0x20,0x40,0x20,0x68,0x00,0x16,0x70,0x00,
  222. 0x4e,0x75,0x70,0xff,0x60,0xfa,0x64,0x6f,0x73,0x2e,0x6c,0x69,0x62,0x72,0x61,0x72,
  223. 0x79
  224. };
  225. static uae_u8 bootblock_ffs[]={
  226. 0x44, 0x4F, 0x53, 0x01, 0xE3, 0x3D, 0x0E, 0x72, 0x00, 0x00, 0x03, 0x70, 0x43, 0xFA, 0x00, 0x3E,
  227. 0x70, 0x25, 0x4E, 0xAE, 0xFD, 0xD8, 0x4A, 0x80, 0x67, 0x0C, 0x22, 0x40, 0x08, 0xE9, 0x00, 0x06,
  228. 0x00, 0x22, 0x4E, 0xAE, 0xFE, 0x62, 0x43, 0xFA, 0x00, 0x18, 0x4E, 0xAE, 0xFF, 0xA0, 0x4A, 0x80,
  229. 0x67, 0x0A, 0x20, 0x40, 0x20, 0x68, 0x00, 0x16, 0x70, 0x00, 0x4E, 0x75, 0x70, 0xFF, 0x4E, 0x75,
  230. 0x64, 0x6F, 0x73, 0x2E, 0x6C, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x00, 0x65, 0x78, 0x70, 0x61,
  231. 0x6E, 0x73, 0x69, 0x6F, 0x6E, 0x2E, 0x6C, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x00, 0x00, 0x00,
  232. };
  233. #define FS_OFS_DATABLOCKSIZE 488
  234. #define FS_FLOPPY_BLOCKSIZE 512
  235. #define FS_EXTENSION_BLOCKS 72
  236. #define FS_FLOPPY_TOTALBLOCKS 1760
  237. #define FS_FLOPPY_RESERVED 2
  238. static void writeimageblock (struct zfile *dst, uae_u8 *sector, int offset)
  239. {
  240. zfile_fseek (dst, offset, SEEK_SET);
  241. zfile_fwrite (sector, FS_FLOPPY_BLOCKSIZE, 1, dst);
  242. }
  243. static uae_u32 disk_checksum (uae_u8 *p, uae_u8 *c)
  244. {
  245. uae_u32 cs = 0;
  246. int i;
  247. for (i = 0; i < FS_FLOPPY_BLOCKSIZE; i+= 4)
  248. cs += (p[i] << 24) | (p[i+1] << 16) | (p[i+2] << 8) | (p[i+3] << 0);
  249. cs = (~cs) + 1;
  250. if (c) {
  251. c[0] = cs >> 24; c[1] = cs >> 16; c[2] = cs >> 8; c[3] = cs >> 0;
  252. }
  253. return cs;
  254. }
  255. static int dirhash (const uae_char *name)
  256. {
  257. unsigned long hash;
  258. int i;
  259. hash = strlen (name);
  260. for(i = 0; i < strlen (name); i++) {
  261. hash = hash * 13;
  262. hash = hash + toupper (name[i]);
  263. hash = hash & 0x7ff;
  264. }
  265. hash = hash % ((FS_FLOPPY_BLOCKSIZE / 4) - 56);
  266. return hash;
  267. }
  268. static void disk_date (uae_u8 *p)
  269. {
  270. static int pdays, pmins, pticks;
  271. int days, mins, ticks;
  272. struct timeval tv;
  273. struct mytimeval mtv;
  274. gettimeofday (&tv, NULL);
  275. tv.tv_sec -= _timezone;
  276. mtv.tv_sec = tv.tv_sec;
  277. mtv.tv_usec = tv.tv_usec;
  278. timeval_to_amiga (&mtv, &days, &mins, &ticks, 50);
  279. if (days == pdays && mins == pmins && ticks == pticks) {
  280. ticks++;
  281. if (ticks >= 50 * 60) {
  282. ticks = 0;
  283. mins++;
  284. if (mins >= 24 * 60)
  285. days++;
  286. }
  287. }
  288. pdays = days;
  289. pmins = mins;
  290. pticks = ticks;
  291. p[0] = days >> 24; p[1] = days >> 16; p[2] = days >> 8; p[3] = days >> 0;
  292. p[4] = mins >> 24; p[5] = mins >> 16; p[6] = mins >> 8; p[7] = mins >> 0;
  293. p[8] = ticks >> 24; p[9] = ticks >> 16; p[10] = ticks >> 8; p[11] = ticks >> 0;
  294. }
  295. static void createbootblock (uae_u8 *sector, int bootable, bool ffs)
  296. {
  297. memset (sector, 0, FS_FLOPPY_BLOCKSIZE);
  298. memcpy (sector, "DOS", 3);
  299. if (ffs) {
  300. sector[3] = 1;
  301. }
  302. if (bootable) {
  303. memcpy(sector + 8, bootblock_ofs + 8, sizeof(bootblock_ofs) - 8);
  304. uae_u32 crc = 0;
  305. for (int i = 0; i < FS_FLOPPY_BLOCKSIZE; i += 4) {
  306. uae_u32 v = (sector[i] << 24) | (sector[i + 1] << 16) | (sector[i + 2] << 8) | sector[i + 3];
  307. if (crc + v < crc) {
  308. crc++;
  309. }
  310. crc += v;
  311. }
  312. crc ^= 0xffffffff;
  313. sector[4] = crc >> 24;
  314. sector[5] = crc >> 16;
  315. sector[6] = crc >> 8;
  316. sector[7] = crc >> 0;
  317. }
  318. }
  319. static void createrootblock (uae_u8 *sector, const TCHAR *disk_name)
  320. {
  321. char *dn = ua (disk_name);
  322. if (strlen (dn) >= 30)
  323. dn[30] = 0;
  324. const char *dn2 = dn;
  325. if (dn2[0] == 0)
  326. dn2 = "empty";
  327. memset (sector, 0, FS_FLOPPY_BLOCKSIZE);
  328. sector[0+3] = 2;
  329. sector[12+3] = 0x48;
  330. sector[312] = sector[313] = sector[314] = sector[315] = (uae_u8)0xff;
  331. sector[316+2] = 881 >> 8; sector[316+3] = 881 & 255;
  332. sector[432] = (uae_u8)strlen (dn2);
  333. strcpy ((char*)sector + 433, dn2);
  334. sector[508 + 3] = 1;
  335. disk_date (sector + 420);
  336. memcpy (sector + 472, sector + 420, 3 * 4);
  337. memcpy (sector + 484, sector + 420, 3 * 4);
  338. xfree (dn);
  339. }
  340. static int getblock (uae_u8 *bitmap, int *prev)
  341. {
  342. int i = *prev;
  343. while (bitmap[i] != 0xff) {
  344. if (bitmap[i] == 0) {
  345. bitmap[i] = 1;
  346. *prev = i;
  347. return i;
  348. }
  349. i++;
  350. }
  351. i = 0;
  352. while (bitmap[i] != 0xff) {
  353. if (bitmap[i] == 0) {
  354. bitmap[i] = 1;
  355. *prev = i;
  356. return i;
  357. }
  358. i++;
  359. }
  360. return -1;
  361. }
  362. static void pl (uae_u8 *sector, int offset, uae_u32 v)
  363. {
  364. sector[offset + 0] = v >> 24;
  365. sector[offset + 1] = v >> 16;
  366. sector[offset + 2] = v >> 8;
  367. sector[offset + 3] = v >> 0;
  368. }
  369. static int createdirheaderblock (uae_u8 *sector, int parent, const char *filename, uae_u8 *bitmap, int *prevblock)
  370. {
  371. int block = getblock (bitmap, prevblock);
  372. memset (sector, 0, FS_FLOPPY_BLOCKSIZE);
  373. pl (sector, 0, 2);
  374. pl (sector, 4, block);
  375. disk_date (sector + 512 - 92);
  376. sector[512 - 80] = (uae_u8)strlen (filename);
  377. strcpy ((char*)sector + 512 - 79, filename);
  378. pl (sector, 512 - 12, parent);
  379. pl (sector, 512 - 4, 2);
  380. return block;
  381. }
  382. static int createfileheaderblock (struct zfile *z,uae_u8 *sector, int parent, const char *filename, struct zfile *src, uae_u8 *bitmap, bool ffs, int *prevblock)
  383. {
  384. uae_u8 sector2[FS_FLOPPY_BLOCKSIZE];
  385. uae_u8 sector3[FS_FLOPPY_BLOCKSIZE];
  386. int block = getblock (bitmap, prevblock);
  387. int datablock = getblock (bitmap, prevblock);
  388. int datasec = 1;
  389. int extensions;
  390. int extensionblock, extensioncounter, headerextension = 1;
  391. int size;
  392. int blocksize = ffs ? FS_FLOPPY_BLOCKSIZE : FS_OFS_DATABLOCKSIZE;
  393. zfile_fseek (src, 0, SEEK_END);
  394. size = (int)zfile_ftell (src);
  395. zfile_fseek (src, 0, SEEK_SET);
  396. extensions = (size + blocksize - 1) / blocksize;
  397. memset (sector, 0, FS_FLOPPY_BLOCKSIZE);
  398. pl (sector, 0, 2);
  399. pl (sector, 4, block);
  400. pl (sector, 8, extensions > FS_EXTENSION_BLOCKS ? FS_EXTENSION_BLOCKS : extensions);
  401. pl (sector, 16, datablock);
  402. pl (sector, FS_FLOPPY_BLOCKSIZE - 188, size);
  403. disk_date (sector + FS_FLOPPY_BLOCKSIZE - 92);
  404. sector[FS_FLOPPY_BLOCKSIZE - 80] = (uae_u8)strlen (filename);
  405. strcpy ((char*)sector + FS_FLOPPY_BLOCKSIZE - 79, filename);
  406. pl (sector, FS_FLOPPY_BLOCKSIZE - 12, parent);
  407. pl (sector, FS_FLOPPY_BLOCKSIZE - 4, -3);
  408. extensioncounter = 0;
  409. extensionblock = 0;
  410. while (size > 0) {
  411. int datablock2 = datablock;
  412. int extensionblock2 = extensionblock;
  413. if (extensioncounter == FS_EXTENSION_BLOCKS) {
  414. extensioncounter = 0;
  415. extensionblock = getblock (bitmap, prevblock);
  416. if (datasec > FS_EXTENSION_BLOCKS + 1) {
  417. pl (sector3, 8, FS_EXTENSION_BLOCKS);
  418. pl (sector3, FS_FLOPPY_BLOCKSIZE - 8, extensionblock);
  419. pl (sector3, 4, extensionblock2);
  420. disk_checksum(sector3, sector3 + 20);
  421. writeimageblock (z, sector3, extensionblock2 * FS_FLOPPY_BLOCKSIZE);
  422. } else {
  423. pl (sector, 512 - 8, extensionblock);
  424. }
  425. memset (sector3, 0, FS_FLOPPY_BLOCKSIZE);
  426. pl (sector3, 0, 16);
  427. pl (sector3, FS_FLOPPY_BLOCKSIZE - 12, block);
  428. pl (sector3, FS_FLOPPY_BLOCKSIZE - 4, -3);
  429. }
  430. memset (sector2, 0, FS_FLOPPY_BLOCKSIZE);
  431. if (!ffs) {
  432. pl(sector2, 0, 8);
  433. pl(sector2, 4, block);
  434. pl(sector2, 8, datasec);
  435. pl(sector2, 12, size > FS_OFS_DATABLOCKSIZE ? FS_OFS_DATABLOCKSIZE : size);
  436. zfile_fread(sector2 + 24, size > FS_OFS_DATABLOCKSIZE ? FS_OFS_DATABLOCKSIZE : size, 1, src);
  437. } else {
  438. zfile_fread(sector2, size > FS_FLOPPY_BLOCKSIZE ? FS_FLOPPY_BLOCKSIZE : size, 1, src);
  439. }
  440. datasec++;
  441. size -= blocksize;
  442. datablock = 0;
  443. if (size > 0) {
  444. datablock = getblock(bitmap, prevblock);
  445. }
  446. if (!ffs) {
  447. pl(sector2, 16, datablock);
  448. disk_checksum(sector2, sector2 + 20);
  449. }
  450. writeimageblock (z, sector2, datablock2 * FS_FLOPPY_BLOCKSIZE);
  451. if (datasec <= FS_EXTENSION_BLOCKS + 1)
  452. pl (sector, 512 - 204 - extensioncounter * 4, datablock2);
  453. else
  454. pl (sector3, 512 - 204 - extensioncounter * 4, datablock2);
  455. extensioncounter++;
  456. }
  457. if (datasec > FS_EXTENSION_BLOCKS) {
  458. pl (sector3, 8, extensioncounter);
  459. disk_checksum(sector3, sector3 + 20);
  460. writeimageblock (z, sector3, extensionblock * FS_FLOPPY_BLOCKSIZE);
  461. }
  462. disk_checksum(sector, sector + 20);
  463. writeimageblock (z, sector, block * FS_FLOPPY_BLOCKSIZE);
  464. return block;
  465. }
  466. static void createbitmapblock (uae_u8 *sector, uae_u8 *bitmap)
  467. {
  468. int i, j;
  469. memset (sector, 0, FS_FLOPPY_BLOCKSIZE);
  470. i = 0;
  471. for (;;) {
  472. uae_u32 mask = 0;
  473. for (j = 0; j < 32; j++) {
  474. if (bitmap[2 + i * 32 + j] == 0xff)
  475. break;
  476. if (!bitmap[2 + i * 32 + j])
  477. mask |= 1 << j;
  478. }
  479. sector[4 + i * 4 + 0] = mask >> 24;
  480. sector[4 + i * 4 + 1] = mask >> 16;
  481. sector[4 + i * 4 + 2] = mask >> 8;
  482. sector[4 + i * 4 + 3] = mask >> 0;
  483. if (bitmap[2 + i * 32 + j] == 0xff)
  484. break;
  485. i++;
  486. }
  487. disk_checksum(sector, sector + 0);
  488. }
  489. static int createimagefromexe(struct zfile *src, struct zfile *dst, int hd, bool ffs)
  490. {
  491. uae_u8 sector1[FS_FLOPPY_BLOCKSIZE], sector2[FS_FLOPPY_BLOCKSIZE];
  492. uae_u8 bitmap[FS_FLOPPY_TOTALBLOCKS * 2 + 8];
  493. int exesize;
  494. int blocksize = ffs ? FS_FLOPPY_BLOCKSIZE : FS_OFS_DATABLOCKSIZE;
  495. int blocks, extensionblocks;
  496. int totalblocks;
  497. int fblock1, dblock1;
  498. const char *fname1 = "runme.exe";
  499. const TCHAR *fname1b = _T("runme.adf");
  500. const char *fname2 = "startup-sequence";
  501. const char *dirname1 = "s";
  502. struct zfile *ss;
  503. int prevblock;
  504. memset (bitmap, 0, sizeof bitmap);
  505. zfile_fseek (src, 0, SEEK_END);
  506. exesize = (int)zfile_ftell (src);
  507. blocks = (exesize + blocksize - 1) / blocksize;
  508. extensionblocks = (blocks + FS_EXTENSION_BLOCKS - 1) / FS_EXTENSION_BLOCKS;
  509. /* bootblock=2, root=1, bitmap=1, startup-sequence=1+1, exefileheader=1 */
  510. totalblocks = 2 + 1 + 1 + 2 + 1 + blocks + extensionblocks;
  511. if (totalblocks > FS_FLOPPY_TOTALBLOCKS * hd)
  512. return 0;
  513. bitmap[880 * hd + 0] = 1;
  514. bitmap[880 * hd + 1] = 1;
  515. bitmap[0] = 1;
  516. bitmap[1] = 1;
  517. bitmap[1760 * hd] = -1;
  518. prevblock = 880 * hd;
  519. dblock1 = createdirheaderblock (sector2, 880 * hd, dirname1, bitmap, &prevblock);
  520. ss = zfile_fopen_empty (src, fname1b, strlen (fname1));
  521. zfile_fwrite (fname1, strlen(fname1), 1, ss);
  522. fblock1 = createfileheaderblock (dst, sector1, dblock1, fname2, ss, bitmap, ffs, &prevblock);
  523. zfile_fclose (ss);
  524. pl (sector2, 24 + dirhash (fname2) * 4, fblock1);
  525. disk_checksum(sector2, sector2 + 20);
  526. writeimageblock (dst, sector2, dblock1 * FS_FLOPPY_BLOCKSIZE);
  527. fblock1 = createfileheaderblock (dst, sector1, 880 * hd, fname1, src, bitmap, ffs, &prevblock);
  528. createrootblock (sector1, zfile_getfilename (src));
  529. pl (sector1, 24 + dirhash (fname1) * 4, fblock1);
  530. pl (sector1, 24 + dirhash (dirname1) * 4, dblock1);
  531. disk_checksum(sector1, sector1 + 20);
  532. writeimageblock (dst, sector1, 880 * hd * FS_FLOPPY_BLOCKSIZE);
  533. createbitmapblock (sector1, bitmap);
  534. writeimageblock (dst, sector1, (880 * hd + 1) * FS_FLOPPY_BLOCKSIZE);
  535. createbootblock (sector1, 1, ffs);
  536. writeimageblock (dst, sector1, 0 * FS_FLOPPY_BLOCKSIZE);
  537. return 1;
  538. }
  539. #ifdef FLOPPYBRIDGE
  540. static FloppyBridgeAPI *bridges[4];
  541. static int bridge_type[4];
  542. static const FloppyDiskBridge::BridgeDriver *bridge_driver[4];
  543. static FloppyBridgeAPI::BridgeInformation bridgeinfo;
  544. static int bridgeinfoloaded;
  545. static std::vector<FloppyBridgeAPI::DriverInformation> bridgedriverinfo;
  546. static void floppybridge_read_track(drive *drv);
  547. bool floppybridge_available;
  548. std::vector<FloppyBridgeAPI::FloppyBridgeProfileInformation> bridgeprofiles;
  549. static char *floppybridge_config = NULL;
  550. bool DISK_isfloppybridge(struct uae_prefs *p, int num)
  551. {
  552. return p->floppyslots[num].dfxtype == DRV_FB;
  553. }
  554. #endif
  555. static bool isfloppysound (drive *drv)
  556. {
  557. return drv->useturbo == 0;
  558. }
  559. static int get_floppy_speed (void)
  560. {
  561. int m = currprefs.floppy_speed;
  562. if (m <= 10)
  563. m = 100;
  564. m = NORMAL_FLOPPY_SPEED * 100 / m;
  565. return m;
  566. }
  567. static int get_floppy_speed_from_image(drive *drv)
  568. {
  569. int l, m;
  570. #ifdef FLOPPYBRIDGE
  571. if (drv->bridge) {
  572. drv->fourms = drv->bridge->getBitSpeed() == 4;
  573. m = NORMAL_FLOPPY_SPEED;
  574. if (drv->fourms) {
  575. m *= 2;
  576. }
  577. return m;
  578. }
  579. #endif
  580. m = get_floppy_speed();
  581. l = drv->tracklen;
  582. drv->fourms = false;
  583. if (!drv->tracktiming[0]) {
  584. m = m * l / (2 * 8 * FLOPPY_WRITE_LEN * drv->ddhd);
  585. }
  586. // 4us track?
  587. if (l < (FLOPPY_WRITE_LEN_PAL * 8) * 4 / 6) {
  588. m *= 2;
  589. drv->fourms = true;
  590. }
  591. if (m <= 0) {
  592. m = 1;
  593. }
  594. return m;
  595. }
  596. static const TCHAR *drive_id_name(drive *drv)
  597. {
  598. switch(drv->drive_id)
  599. {
  600. case DRIVE_ID_35HD : return _T("3.5HD");
  601. case DRIVE_ID_525SD: return _T("5.25SD");
  602. case DRIVE_ID_35DD : return _T("3.5DD");
  603. case DRIVE_ID_NONE : return _T("NONE");
  604. }
  605. return _T("UNKNOWN");
  606. }
  607. /* Simulate exact behaviour of an A3000T 3.5 HD disk drive.
  608. * The drive reports to be a 3.5 DD drive whenever there is no
  609. * disk or a 3.5 DD disk is inserted. Only 3.5 HD drive id is reported
  610. * when a real 3.5 HD disk is inserted. -Adil
  611. */
  612. static void drive_settype_id (drive *drv)
  613. {
  614. int drvnum = drv - &floppy[0];
  615. int t = currprefs.floppyslots[drvnum].dfxtype;
  616. #ifdef FLOPPYBRIDGE
  617. if (drv->bridge)
  618. {
  619. if (drv->bridge->isDiskInDrive()) {
  620. switch (drv->bridge->getDriveTypeID()) {
  621. case FloppyDiskBridge::DriveTypeID::dti35DD:
  622. drv->drive_id = DRIVE_ID_35DD;
  623. break;
  624. case FloppyDiskBridge::DriveTypeID::dti35HD:
  625. drv->drive_id = DRIVE_ID_35HD;
  626. break;
  627. case FloppyDiskBridge::DriveTypeID::dti5255SD:
  628. drv->drive_id = DRIVE_ID_525SD;
  629. break;
  630. }
  631. } else {
  632. drv->drive_id = DRIVE_ID_35DD;
  633. }
  634. drv->ddhd = drv->drive_id == DRIVE_ID_35HD ? 2 : 1;
  635. return;
  636. }
  637. #endif
  638. switch (t)
  639. {
  640. case DRV_35_HD:
  641. #ifdef FLOPPY_DRIVE_HD
  642. if (!drv->diskfile || drv->ddhd <= 1)
  643. drv->drive_id = DRIVE_ID_35DD;
  644. else
  645. drv->drive_id = DRIVE_ID_35HD;
  646. #else
  647. drv->drive_id = DRIVE_ID_35DD;
  648. #endif
  649. break;
  650. case DRV_35_DD_ESCOM:
  651. case DRV_35_DD:
  652. case DRV_525_DD:
  653. default:
  654. drv->drive_id = DRIVE_ID_35DD;
  655. break;
  656. case DRV_525_SD:
  657. drv->drive_id = DRIVE_ID_525SD;
  658. break;
  659. case DRV_NONE:
  660. case DRV_PC_525_ONLY_40:
  661. case DRV_PC_525_40_80:
  662. case DRV_PC_35_ONLY_80:
  663. drv->drive_id = DRIVE_ID_NONE;
  664. break;
  665. }
  666. #ifdef DEBUG_DRIVE_ID
  667. write_log (_T("drive_settype_id: DF%d: set to %s\n"), drv-floppy, drive_id_name(drv));
  668. #endif
  669. }
  670. static void drive_image_free (drive *drv)
  671. {
  672. switch (drv->filetype)
  673. {
  674. case ADF_IPF:
  675. #ifdef CAPS
  676. caps_unloadimage (drv - floppy);
  677. #endif
  678. break;
  679. case ADF_SCP:
  680. #ifdef SCP
  681. scp_close (drv - floppy);
  682. #endif
  683. break;
  684. case ADF_FDI:
  685. #ifdef FDI2RAW
  686. fdi2raw_header_free (drv->fdi);
  687. drv->fdi = 0;
  688. #endif
  689. break;
  690. }
  691. drv->filetype = ADF_NONE;
  692. zfile_fclose(drv->diskfile);
  693. drv->diskfile = NULL;
  694. zfile_fclose(drv->writediskfile);
  695. drv->writediskfile = NULL;
  696. zfile_fclose(drv->pcdecodedfile);
  697. drv->pcdecodedfile = NULL;
  698. }
  699. static int drive_insert (drive * drv, struct uae_prefs *p, int dnum, const TCHAR *fname, bool fake, bool writeprotected);
  700. static void reset_drive_gui (int num)
  701. {
  702. struct gui_info_drive *gid = &gui_data.drives[num];
  703. gid->drive_disabled = 0;
  704. gid->df[0] = 0;
  705. gid->crc32 = 0;
  706. if (currprefs.floppyslots[num].dfxtype < 0)
  707. gid->drive_disabled = 1;
  708. }
  709. static void setamax (void)
  710. {
  711. #ifdef AMAX
  712. amax_enabled = false;
  713. if (is_device_rom(&currprefs, ROMTYPE_AMAX, 0) > 0) {
  714. /* Put A-Max as last drive in drive chain */
  715. int j;
  716. amax_enabled = true;
  717. for (j = 0; j < MAX_FLOPPY_DRIVES; j++)
  718. if (floppy[j].amax)
  719. return;
  720. for (j = 0; j < MAX_FLOPPY_DRIVES; j++) {
  721. if ((1 << j) & disabled) {
  722. floppy[j].amax = 1;
  723. write_log (_T("AMAX: drive %d\n"), j);
  724. return;
  725. }
  726. }
  727. }
  728. #endif
  729. }
  730. static bool ispcbridgedrive(int num)
  731. {
  732. int type = currprefs.floppyslots[num].dfxtype;
  733. return type == DRV_PC_525_ONLY_40 || type == DRV_PC_35_ONLY_80 || type == DRV_PC_525_40_80;
  734. }
  735. static bool drive_writeprotected(drive *drv)
  736. {
  737. #ifdef FLOPPYBRIDGE
  738. if (drv->bridge) {
  739. bool v = drv->bridge->isWriteProtected();
  740. return v;
  741. }
  742. #endif
  743. #ifdef CATWEASEL
  744. if (drv->catweasel)
  745. return 1;
  746. #endif
  747. return currprefs.floppy_read_only || drv->wrprot || drv->forcedwrprot || drv->diskfile == NULL;
  748. }
  749. static void reset_drive (int num)
  750. {
  751. drive *drv = &floppy[num];
  752. drv->amax = 0;
  753. drive_image_free (drv);
  754. drv->motoroff = 1;
  755. drv->idbit = 0;
  756. drv->drive_id = 0;
  757. drv->drive_id_scnt = 0;
  758. drv->lastdataacesstrack = -1;
  759. disabled &= ~(1 << num);
  760. reserved &= ~(1 << num);
  761. if (currprefs.floppyslots[num].dfxtype < 0 || ispcbridgedrive(num))
  762. disabled |= 1 << num;
  763. if (ispcbridgedrive(num))
  764. reserved |= 1 << num;
  765. reset_drive_gui (num);
  766. /* most internal Amiga floppy drives won't enable
  767. * diskready until motor is running at full speed
  768. * and next indexsync has been passed
  769. */
  770. drv->indexhackmode = 0;
  771. if (num == 0 && currprefs.floppyslots[num].dfxtype == 0)
  772. drv->indexhackmode = 1;
  773. drv->dskchange_time = 0;
  774. drv->dskchange = false;
  775. drv->dskready_down_time = 0;
  776. drv->dskready_up_time = 0;
  777. drv->buffered_cyl = -1;
  778. drv->buffered_side = -1;
  779. gui_led (num + LED_DF0, 0, -1);
  780. drive_settype_id (drv);
  781. _tcscpy (currprefs.floppyslots[num].df, changed_prefs.floppyslots[num].df);
  782. drv->newname[0] = 0;
  783. drv->newnamewriteprotected = false;
  784. #ifdef FLOPPYBRIDGE
  785. if (drv->bridge) {
  786. drv->bridge->resetDrive(drv->cyl);
  787. drv->indexhackmode = 0;
  788. drv->num_tracks = drv->bridge->getMaxCylinder() * 2;
  789. drv->filetype = ADF_FLOPPYBRIDGE;
  790. drv->tracklen = drv->bridge->maxMFMBitPosition();
  791. drv->ddhd = drv->bridge->getDriveTypeID() == FloppyDiskBridge::DriveTypeID::dti35HD ? 2 : 1;
  792. }
  793. #endif
  794. if (!drive_insert (drv, &currprefs, num, currprefs.floppyslots[num].df, false, false))
  795. disk_eject (num);
  796. }
  797. /* code for track display */
  798. static void update_drive_gui (int num, bool force)
  799. {
  800. drive *drv = floppy + num;
  801. bool writ = dskdmaen == DSKDMA_WRITE && drv->state && !((selected | disabled) & (1 << num));
  802. struct gui_info_drive *gid = &gui_data.drives[num];
  803. if (!force && drv->state == gid->drive_motor
  804. && drv->cyl == gid->drive_track
  805. && side == gui_data.drive_side
  806. && drv->crc32 == gid->crc32
  807. && writ == gid->drive_writing
  808. && drive_writeprotected(drv) == gid->floppy_protected
  809. && !_tcscmp (gid->df, currprefs.floppyslots[num].df))
  810. return;
  811. _tcscpy (gid->df, currprefs.floppyslots[num].df);
  812. gid->crc32 = drv->crc32;
  813. gid->drive_motor = drv->state;
  814. gid->drive_track = drv->cyl;
  815. if (reserved & (1 << num))
  816. gui_data.drive_side = reserved_side;
  817. else
  818. gui_data.drive_side = side;
  819. gid->drive_writing = writ;
  820. gid->floppy_protected = drive_writeprotected(drv);
  821. gid->floppy_inserted = gid->df[0] || (drv->bridge && !drv->bridge->hasDiskChanged());
  822. gui_led (num + LED_DF0, (gid->drive_motor ? 1 : 0) | (gid->drive_writing ? 2 : 0), -1);
  823. }
  824. static void drive_fill_bigbuf (drive * drv,int);
  825. void DISK_get_path_text(struct uae_prefs *p, int n, TCHAR *text)
  826. {
  827. _tcscpy(text, p->floppyslots[n].df);
  828. #ifdef FLOPPYBRIDGE
  829. if (DISK_isfloppybridge(p, n) && floppybridge_available) {
  830. if (!bridgeinfoloaded) {
  831. FloppyBridgeAPI::getBridgeDriverInformation(false, bridgeinfo);
  832. bridgeinfoloaded = 1;
  833. }
  834. _tcscpy(text, bridgeinfo.about);
  835. floppybridge_init(p);
  836. if (bridge_driver[n]) {
  837. _tcscat(text, _T(", "));
  838. TCHAR *name = au(bridge_driver[n]->name);
  839. TCHAR *man = au(bridge_driver[n]->manufacturer);
  840. _tcscat(text, name);
  841. _tcscat(text, _T(", "));
  842. _tcscat(text, man);
  843. xfree(man);
  844. xfree(name);
  845. }
  846. }
  847. #endif
  848. }
  849. 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)
  850. {
  851. TCHAR outname[MAX_DPATH];
  852. if (zf)
  853. *zf = NULL;
  854. if (crc32)
  855. *crc32 = 0;
  856. if (wrprot)
  857. *wrprot = p->floppy_read_only ? 1 : 0;
  858. if (outfname)
  859. outfname[0] = 0;
  860. #ifdef FLOPPYBRIDGE
  861. if (DISK_isfloppybridge(p, num)) {
  862. return 1;
  863. }
  864. #endif
  865. cfgfile_resolve_path_out_load(fname_in, outname, MAX_DPATH, PATH_FLOPPY);
  866. if (outfname)
  867. _tcscpy(outfname, outname);
  868. if (leave_open || !zf) {
  869. struct zfile *f = zfile_fopen (outname, _T("r+b"), ZFD_NORMAL | ZFD_DISKHISTORY);
  870. if (!f) {
  871. if (wrprot)
  872. *wrprot = 1;
  873. f = zfile_fopen (outname, _T("rb"), ZFD_NORMAL | ZFD_DISKHISTORY);
  874. }
  875. if (f && crc32)
  876. *crc32 = zfile_crc32 (f);
  877. if (!zf)
  878. zfile_fclose (f);
  879. else
  880. *zf = f;
  881. return f ? 1 : 0;
  882. } else {
  883. if (zfile_exists (outname)) {
  884. if (wrprot && !p->floppy_read_only)
  885. *wrprot = 0;
  886. if (crc32) {
  887. struct zfile *f = zfile_fopen (outname, _T("rb"), ZFD_NORMAL | ZFD_DISKHISTORY);
  888. if (f)
  889. *crc32 = zfile_crc32 (f);
  890. zfile_fclose (f);
  891. }
  892. return 1;
  893. } else {
  894. if (wrprot)
  895. *wrprot = 1;
  896. return 0;
  897. }
  898. }
  899. }
  900. static void updatemfmpos (drive *drv)
  901. {
  902. if (drv->prevtracklen) {
  903. drv->mfmpos = drv->mfmpos * (drv->tracklen * 1000 / drv->prevtracklen) / 1000;
  904. if (drv->mfmpos >= drv->tracklen)
  905. drv->mfmpos = drv->tracklen - 1;
  906. }
  907. drv->mfmpos %= drv->tracklen;
  908. drv->prevtracklen = drv->tracklen;
  909. }
  910. static void track_reset (drive *drv)
  911. {
  912. drv->tracklen = FLOPPY_WRITE_LEN * drv->ddhd * 2 * 8;
  913. drv->revolutions = 1;
  914. drv->trackspeed = get_floppy_speed ();
  915. drv->buffered_side = -1;
  916. drv->skipoffset = -1;
  917. drv->tracktiming[0] = 0;
  918. memset (drv->bigmfmbuf, 0xaa, FLOPPY_WRITE_LEN * 2 * drv->ddhd);
  919. updatemfmpos (drv);
  920. }
  921. static int read_header_ext2 (struct zfile *diskfile, trackid *trackdata, int *num_tracks, int *ddhd)
  922. {
  923. uae_u8 buffer[2 + 2 + 4 + 4];
  924. trackid *tid;
  925. int offs;
  926. int i;
  927. zfile_fseek (diskfile, 0, SEEK_SET);
  928. zfile_fread (buffer, 1, 8, diskfile);
  929. if (strncmp ((char*)buffer, "UAE-1ADF", 8))
  930. return 0;
  931. zfile_fread (buffer, 1, 4, diskfile);
  932. *num_tracks = buffer[2] * 256 + buffer[3];
  933. offs = 8 + 2 + 2 + (*num_tracks) * (2 + 2 + 4 + 4);
  934. for (i = 0; i < (*num_tracks); i++) {
  935. tid = trackdata + i;
  936. zfile_fread (buffer, 2 + 2 + 4 + 4, 1, diskfile);
  937. tid->type = (image_tracktype)buffer[3];
  938. tid->revolutions = buffer[2] + 1;
  939. tid->len = buffer[5] * 65536 + buffer[6] * 256 + buffer[7];
  940. tid->bitlen = buffer[9] * 65536 + buffer[10] * 256 + buffer[11];
  941. tid->offs = offs;
  942. if (tid->len > 20000 && ddhd)
  943. *ddhd = 2;
  944. tid->track = i;
  945. offs += tid->len;
  946. }
  947. return 1;
  948. }
  949. static void saveimagecutpathpart(TCHAR *name)
  950. {
  951. int i;
  952. i = _tcslen (name) - 1;
  953. while (i > 0) {
  954. if (name[i] == '/' || name[i] == '\\') {
  955. name[i] = 0;
  956. break;
  957. }
  958. if (name[i] == '.') {
  959. name[i] = 0;
  960. break;
  961. }
  962. i--;
  963. }
  964. while (i > 0) {
  965. if (name[i] == '/' || name[i] == '\\') {
  966. name[i] = 0;
  967. break;
  968. }
  969. i--;
  970. }
  971. }
  972. static void saveimagecutfilepart(TCHAR *name)
  973. {
  974. TCHAR tmp[MAX_DPATH];
  975. int i;
  976. _tcscpy(tmp, name);
  977. i = _tcslen (tmp) - 1;
  978. while (i > 0) {
  979. if (tmp[i] == '/' || tmp[i] == '\\') {
  980. _tcscpy(name, tmp + i + 1);
  981. break;
  982. }
  983. if (tmp[i] == '.') {
  984. tmp[i] = 0;
  985. break;
  986. }
  987. i--;
  988. }
  989. while (i > 0) {
  990. if (tmp[i] == '/' || tmp[i] == '\\') {
  991. _tcscpy(name, tmp + i + 1);
  992. break;
  993. }
  994. i--;
  995. }
  996. }
  997. static void saveimageaddfilename(TCHAR *dst, const TCHAR *src, int type)
  998. {
  999. _tcscat(dst, src);
  1000. if (type)
  1001. _tcscat(dst, _T(".save_adf"));
  1002. else
  1003. _tcscat(dst, _T("_save.adf"));
  1004. }
  1005. static TCHAR *DISK_get_default_saveimagepath (const TCHAR *name)
  1006. {
  1007. TCHAR name1[MAX_DPATH];
  1008. TCHAR path[MAX_DPATH];
  1009. _tcscpy(name1, name);
  1010. saveimagecutfilepart(name1);
  1011. fetch_saveimagepath (path, sizeof path / sizeof (TCHAR), 1);
  1012. saveimageaddfilename(path, name1, 0);
  1013. return my_strdup(path);
  1014. }
  1015. // -2 = existing, if not, use 0.
  1016. // -1 = as configured
  1017. // 0 = saveimages-dir
  1018. // 1 = image dir
  1019. TCHAR *DISK_get_saveimagepath(const TCHAR *name, int type)
  1020. {
  1021. int typev = type;
  1022. for (int i = 0; i < 2; i++) {
  1023. if (typev == 1 || (typev == -1 && saveimageoriginalpath) || (typev == -2 && (saveimageoriginalpath || i == 1))) {
  1024. TCHAR si_name[MAX_DPATH], si_path[MAX_DPATH];
  1025. _tcscpy(si_name, name);
  1026. _tcscpy(si_path, name);
  1027. saveimagecutfilepart(si_name);
  1028. saveimagecutpathpart(si_path);
  1029. _tcscat(si_path, FSDB_DIR_SEPARATOR_S);
  1030. saveimageaddfilename(si_path, si_name, 1);
  1031. if (typev != -2 || (typev == -2 && zfile_exists(si_path)))
  1032. return my_strdup(si_path);
  1033. }
  1034. if (typev == 2 || (typev == -1 && !saveimageoriginalpath) || (typev == -2 && (!saveimageoriginalpath || i == 1))) {
  1035. TCHAR *p = DISK_get_default_saveimagepath(name);
  1036. if (typev != -2 || (typev == -2 && zfile_exists(p)))
  1037. return p;
  1038. xfree(p);
  1039. }
  1040. }
  1041. return DISK_get_saveimagepath(name, -1);
  1042. }
  1043. static struct zfile *getexistingwritefile(struct uae_prefs *p, const TCHAR *name, int num, bool *wrprot)
  1044. {
  1045. struct zfile *zf = NULL;
  1046. TCHAR *path;
  1047. TCHAR outname[MAX_DPATH];
  1048. path = DISK_get_saveimagepath(name, saveimageoriginalpath);
  1049. DISK_validate_filename(p, path, num, outname, 1, wrprot, NULL, &zf);
  1050. xfree(path);
  1051. if (zf)
  1052. return zf;
  1053. path = DISK_get_saveimagepath(name, !saveimageoriginalpath);
  1054. DISK_validate_filename(p, path, num, outname, 1, wrprot, NULL, &zf);
  1055. xfree(path);
  1056. return zf;
  1057. }
  1058. static int iswritefileempty(struct uae_prefs *p, int num, const TCHAR *name)
  1059. {
  1060. struct zfile *zf;
  1061. bool wrprot;
  1062. uae_char buffer[8];
  1063. trackid td[MAX_TRACKS];
  1064. int tracks, ddhd, i, ret;
  1065. zf = getexistingwritefile(p, name, num, &wrprot);
  1066. if (!zf)
  1067. return 1;
  1068. zfile_fread (buffer, sizeof (char), 8, zf);
  1069. if (strncmp((uae_char*)buffer, "UAE-1ADF", 8)) {
  1070. zfile_fclose(zf);
  1071. return 0;
  1072. }
  1073. ret = read_header_ext2 (zf, td, &tracks, &ddhd);
  1074. zfile_fclose (zf);
  1075. if (!ret)
  1076. return 1;
  1077. for (i = 0; i < tracks; i++) {
  1078. if (td[i].bitlen)
  1079. return 0;
  1080. }
  1081. return 1;
  1082. }
  1083. static int openwritefile (struct uae_prefs *p, drive *drv, int create)
  1084. {
  1085. bool wrprot = 0;
  1086. drv->writediskfile = getexistingwritefile(p, currprefs.floppyslots[drv - &floppy[0]].df, drv - &floppy[0], &wrprot);
  1087. if (drv->writediskfile) {
  1088. drv->wrprot = wrprot;
  1089. if (!read_header_ext2 (drv->writediskfile, drv->writetrackdata, &drv->write_num_tracks, 0)) {
  1090. zfile_fclose (drv->writediskfile);
  1091. drv->writediskfile = 0;
  1092. drv->wrprot = 1;
  1093. } else {
  1094. if (drv->write_num_tracks > drv->num_tracks)
  1095. drv->num_tracks = drv->write_num_tracks;
  1096. }
  1097. } else if (zfile_iscompressed (drv->diskfile)) {
  1098. drv->wrprot = 1;
  1099. }
  1100. return drv->writediskfile ? 1 : 0;
  1101. }
  1102. static bool diskfile_iswriteprotect (struct uae_prefs *p, const TCHAR *fname_in, int num, int *needwritefile, drive_type *drvtype)
  1103. {
  1104. struct zfile *zf1, *zf2;
  1105. bool wrprot1 = 0, wrprot2 = 1;
  1106. uae_char buffer[25];
  1107. TCHAR outname[MAX_DPATH];
  1108. *needwritefile = 0;
  1109. *drvtype = DRV_35_DD;
  1110. DISK_validate_filename (p, fname_in, num, outname, 1, &wrprot1, NULL, &zf1);
  1111. if (!zf1)
  1112. return 1;
  1113. if (zfile_iscompressed (zf1)) {
  1114. wrprot1 = 1;
  1115. *needwritefile = 1;
  1116. }
  1117. zf2 = getexistingwritefile(p, fname_in, num, &wrprot2);
  1118. zfile_fclose (zf2);
  1119. zfile_fread (buffer, sizeof (char), 25, zf1);
  1120. zfile_fclose (zf1);
  1121. if (strncmp ((uae_char*) buffer, "CAPS", 4) == 0) {
  1122. *needwritefile = 1;
  1123. return wrprot2;
  1124. }
  1125. if (strncmp ((uae_char*) buffer, "SCP", 3) == 0) {
  1126. *needwritefile = 1;
  1127. return wrprot2;
  1128. }
  1129. if (strncmp ((uae_char*) buffer, "Formatted Disk Image file", 25) == 0) {
  1130. *needwritefile = 1;
  1131. return wrprot2;
  1132. }
  1133. if (strncmp ((uae_char*) buffer, "UAE-1ADF", 8) == 0) {
  1134. if (wrprot1)
  1135. return wrprot2;
  1136. return wrprot1;
  1137. }
  1138. if (strncmp ((uae_char*) buffer, "UAE--ADF", 8) == 0) {
  1139. *needwritefile = 1;
  1140. return wrprot2;
  1141. }
  1142. if (memcmp (exeheader, buffer, sizeof exeheader) == 0)
  1143. return 0;
  1144. if (wrprot1)
  1145. return wrprot2;
  1146. return wrprot1;
  1147. }
  1148. static bool isrecognizedext(const TCHAR *name)
  1149. {
  1150. const TCHAR *ext = _tcsrchr(name, '.');
  1151. if (ext) {
  1152. ext++;
  1153. if (!_tcsicmp(ext, _T("adf")) || !_tcsicmp(ext, _T("adz")) || !_tcsicmp(ext, _T("st")) ||
  1154. !_tcsicmp(ext, _T("ima")) || !_tcsicmp(ext, _T("img")) || !_tcsicmp(ext, _T("dsk")))
  1155. return true;
  1156. }
  1157. return false;
  1158. }
  1159. static void update_disk_statusline(int num)
  1160. {
  1161. drive *drv = &floppy[num];
  1162. #ifdef FLOPPYBRIDGE
  1163. if (drv->bridge) {
  1164. const char *name = drv->bridge->getDriverInfo()->name;
  1165. TCHAR *n = au(name);
  1166. statusline_add_message(STATUSTYPE_FLOPPY, _T("DF%d: %s"), num, n);
  1167. xfree(n);
  1168. return;
  1169. }
  1170. #endif
  1171. if (!drv->diskfile)
  1172. return;
  1173. const TCHAR *fname = zfile_getoriginalname(drv->diskfile);
  1174. if (!fname)
  1175. fname = zfile_getname(drv->diskfile);
  1176. if (!fname)
  1177. fname = _T("?");
  1178. if (disk_info_data.diskname[0])
  1179. statusline_add_message(STATUSTYPE_FLOPPY, _T("DF%d: [%s] %s"), num, disk_info_data.diskname, my_getfilepart(fname));
  1180. else
  1181. statusline_add_message(STATUSTYPE_FLOPPY, _T("DF%d: %s"), num, my_getfilepart(fname));
  1182. }
  1183. static int drive_insert (drive *drv, struct uae_prefs *p, int dnum, const TCHAR *fname_in, bool fake, bool forcedwriteprotect)
  1184. {
  1185. uae_u8 buffer[2 + 2 + 4 + 4];
  1186. trackid *tid;
  1187. int num_tracks, size;
  1188. int canauto;
  1189. TCHAR outname[MAX_DPATH];
  1190. int dfxtype = p->floppyslots[dnum].dfxtype;
  1191. drive_image_free (drv);
  1192. if (!fake && !drv->bridge) {
  1193. DISK_examine_image(p, dnum, &disk_info_data, false, NULL);
  1194. }
  1195. DISK_validate_filename (p, fname_in, dnum, outname, 1, &drv->wrprot, &drv->crc32, &drv->diskfile);
  1196. drv->forcedwrprot = forcedwriteprotect;
  1197. if (drv->forcedwrprot)
  1198. drv->wrprot = true;
  1199. drv->ddhd = 1;
  1200. drv->num_heads = 2;
  1201. drv->num_secs = 0;
  1202. drv->hard_num_cyls = dfxtype == DRV_525_SD ? 40 : 80;
  1203. drv->tracktiming[0] = 0;
  1204. drv->useturbo = 0;
  1205. drv->indexoffset = 0;
  1206. if (!fake) {
  1207. drv->dskeject = false;
  1208. gui_disk_image_change (dnum, outname, drv->wrprot);
  1209. }
  1210. if (!drv->motoroff) {
  1211. drv->dskready_up_time = DSKREADY_UP_TIME * 312 + (uaerand() & 511);
  1212. drv->dskready_down_time = 0;
  1213. }
  1214. if (drv->diskfile == NULL && !drv->catweasel && !drv->bridge) {
  1215. track_reset (drv);
  1216. return 0;
  1217. }
  1218. if (!fake) {
  1219. inprec_recorddiskchange (dnum, fname_in, drv->wrprot);
  1220. if (currprefs.floppyslots[dnum].df != fname_in) {
  1221. _tcsncpy (currprefs.floppyslots[dnum].df, fname_in, 255);
  1222. currprefs.floppyslots[dnum].df[255] = 0;
  1223. }
  1224. currprefs.floppyslots[dnum].forcedwriteprotect = forcedwriteprotect;
  1225. _tcsncpy (changed_prefs.floppyslots[dnum].df, fname_in, 255);
  1226. changed_prefs.floppyslots[dnum].df[255] = 0;
  1227. changed_prefs.floppyslots[dnum].forcedwriteprotect = forcedwriteprotect;
  1228. _tcscpy (drv->newname, fname_in);
  1229. drv->newnamewriteprotected = forcedwriteprotect;
  1230. gui_filename (dnum, outname);
  1231. }
  1232. memset (buffer, 0, sizeof buffer);
  1233. size = 0;
  1234. if (drv->diskfile) {
  1235. zfile_fread (buffer, sizeof (char), 8, drv->diskfile);
  1236. zfile_fseek (drv->diskfile, 0, SEEK_END);
  1237. size = (int)zfile_ftell (drv->diskfile);
  1238. zfile_fseek (drv->diskfile, 0, SEEK_SET);
  1239. }
  1240. canauto = 0;
  1241. if (isrecognizedext (outname))
  1242. canauto = 1;
  1243. if (!canauto && drv->diskfile && isrecognizedext (zfile_getname (drv->diskfile)))
  1244. canauto = 1;
  1245. // if PC-only drive, make sure PC-like floppies are always detected
  1246. if (!canauto && ispcbridgedrive(dnum))
  1247. canauto = 1;
  1248. if (drv->catweasel) {
  1249. drv->wrprot = true;
  1250. drv->filetype = ADF_CATWEASEL;
  1251. drv->num_tracks = 80;
  1252. drv->ddhd = 1;
  1253. #ifdef FLOPPYBRIDGE
  1254. } else if (drv->bridge) {
  1255. drv->ddhd = (drv->bridge->getDriveTypeID() == FloppyDiskBridge::DriveTypeID::dti35HD) ? 2 : 1;
  1256. drv->num_heads = 2;
  1257. drv->num_secs = 0;
  1258. drv->hard_num_cyls = drv->bridge->getMaxCylinder();
  1259. drv->num_tracks = drv->bridge->getMaxCylinder() * 2;
  1260. drv->tracklen = drv->bridge->maxMFMBitPosition();
  1261. drv->tracktiming[0] = drv->bridge->getMFMSpeed(0);
  1262. drv->multi_revolution = 1;
  1263. drv->fourms = (drv->bridge->getBitSpeed() == 4);
  1264. drv->indexoffset = 0;
  1265. drv->prevtracklen = 0;
  1266. drv->forcedwrprot = false;
  1267. drv->wrprot = drv->bridge->isWriteProtected();
  1268. drv->filetype = ADF_FLOPPYBRIDGE;
  1269. drv->useturbo = 0;
  1270. drv->mfmpos = uaerand();
  1271. drv->mfmpos |= (uaerand() << 16);
  1272. drv->mfmpos %= drv->tracklen;
  1273. drv->prevtracklen = 0;
  1274. drive_settype_id(drv); /* Set DD or HD drive */
  1275. update_drive_gui(drv - floppy, false);
  1276. update_disk_statusline(drv - floppy);
  1277. drive_fill_bigbuf(drv, fake ? -1 : 1);
  1278. return 1;
  1279. #endif
  1280. #ifdef CAPS
  1281. } else if (strncmp ((char*)buffer, "CAPS", 4) == 0) {
  1282. drv->wrprot = true;
  1283. if (!caps_loadimage (drv->diskfile, drv - floppy, &num_tracks)) {
  1284. zfile_fclose (drv->diskfile);
  1285. drv->diskfile = 0;
  1286. return 0;
  1287. }
  1288. drv->num_tracks = num_tracks;
  1289. drv->filetype = ADF_IPF;
  1290. #endif
  1291. #ifdef SCP
  1292. } else if (strncmp ((char*)buffer, "SCP", 3) == 0) {
  1293. drv->wrprot = true;
  1294. if (!scp_open (drv->diskfile, drv - floppy, &num_tracks)) {
  1295. zfile_fclose (drv->diskfile);
  1296. drv->diskfile = 0;
  1297. return 0;
  1298. }
  1299. drv->num_tracks = num_tracks;
  1300. drv->filetype = ADF_SCP;
  1301. #endif
  1302. #ifdef FDI2RAW
  1303. } else if ((drv->fdi = fdi2raw_header (drv->diskfile))) {
  1304. drv->wrprot = true;
  1305. drv->num_tracks = fdi2raw_get_last_track (drv->fdi);
  1306. drv->num_secs = fdi2raw_get_num_sector (drv->fdi);
  1307. drv->filetype = ADF_FDI;
  1308. #endif
  1309. } else if (strncmp ((char*)buffer, "UAE-1ADF", 8) == 0) {
  1310. read_header_ext2 (drv->diskfile, drv->trackdata, &drv->num_tracks, &drv->ddhd);
  1311. drv->filetype = ADF_EXT2;
  1312. drv->num_secs = 11;
  1313. if (drv->ddhd > 1)
  1314. drv->num_secs = 22;
  1315. } else if (strncmp ((char*)buffer, "UAE--ADF", 8) == 0) {
  1316. int offs = 160 * 4 + 8;
  1317. drv->wrprot = true;
  1318. drv->filetype = ADF_EXT1;
  1319. drv->num_tracks = 160;
  1320. drv->num_secs = 11;
  1321. zfile_fseek (drv->diskfile, 8, SEEK_SET);
  1322. for (int i = 0; i < 160; i++) {
  1323. tid = &drv->trackdata[i];
  1324. zfile_fread (buffer, 4, 1, drv->diskfile);
  1325. tid->sync = buffer[0] * 256 + buffer[1];
  1326. tid->len = buffer[2] * 256 + buffer[3];
  1327. tid->offs = offs;
  1328. tid->revolutions = 1;
  1329. if (tid->sync == 0) {
  1330. tid->type = TRACK_AMIGADOS;
  1331. tid->bitlen = 0;
  1332. } else {
  1333. tid->type = TRACK_RAW1;
  1334. tid->bitlen = tid->len * 8;
  1335. }
  1336. offs += tid->len;
  1337. }
  1338. } else if (memcmp (exeheader, buffer, sizeof exeheader) == 0 && !canauto && size <= 512 * (1760 * 2 - 7)) {
  1339. bool ffs = false;
  1340. int hd = 1;
  1341. int freeblocks = 1760 - 7;
  1342. int blocks_ofs = (size + FS_OFS_DATABLOCKSIZE - 1) / FS_OFS_DATABLOCKSIZE;
  1343. int extensionblocks_ofs = (blocks_ofs + FS_EXTENSION_BLOCKS - 1) / FS_EXTENSION_BLOCKS;
  1344. int blocks_ffs = (size + FS_FLOPPY_BLOCKSIZE - 1) / FS_FLOPPY_BLOCKSIZE;
  1345. int extensionblocks_ffs = (blocks_ffs + FS_EXTENSION_BLOCKS - 1) / FS_EXTENSION_BLOCKS;
  1346. // select DD+FFS if file larger than DD+OFS
  1347. if (size > FS_OFS_DATABLOCKSIZE * (freeblocks - extensionblocks_ofs)) {
  1348. ffs = true;
  1349. // select HD+FFS if file larger than DD+FFS
  1350. if (size > FS_FLOPPY_BLOCKSIZE * (freeblocks - extensionblocks_ffs)) {
  1351. hd = 2;
  1352. }
  1353. }
  1354. if (dfxtype == DRV_35_DD) {
  1355. hd = 1;
  1356. }
  1357. if (size <= 512 * (1760 * hd - 7)) {
  1358. struct zfile *z = zfile_fopen_empty(NULL, _T(""), 512 * 1760 * hd);
  1359. createimagefromexe(drv->diskfile, z, hd, ffs);
  1360. drv->filetype = ADF_NORMAL;
  1361. zfile_fclose(drv->diskfile);
  1362. drv->diskfile = z;
  1363. drv->num_tracks = 160;
  1364. drv->num_secs = 11 * hd;
  1365. for (int i = 0; i < drv->num_tracks; i++) {
  1366. tid = &drv->trackdata[i];
  1367. tid->type = TRACK_AMIGADOS;
  1368. tid->len = 512 * drv->num_secs;
  1369. tid->bitlen = 0;
  1370. tid->offs = i * 512 * drv->num_secs;
  1371. tid->revolutions = 1;
  1372. }
  1373. drv->ddhd = hd;
  1374. drv->useturbo = 1;
  1375. }
  1376. } else if (canauto && (
  1377. // 320k double sided
  1378. size == 8 * 40 * 2 * 512 ||
  1379. // 320k single sided
  1380. size == 8 * 40 * 1 * 512 ||
  1381. // 360k double sided
  1382. size == 9 * 40 * 2 * 512 ||
  1383. // 360k single sided
  1384. size == 9 * 40 * 1 * 512 ||
  1385. // 1.2M double sided
  1386. size == 15 * 80 * 2 * 512 ||
  1387. // 720k/1440k double sided
  1388. 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 ||
  1389. 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 ||
  1390. 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 ||
  1391. // 720k/1440k single sided
  1392. size == 9 * 80 * 1 * 512 || size == 18 * 80 * 1 * 512 || size == 10 * 80 * 1 * 512 || size == 20 * 80 * 1 * 512 ||
  1393. size == 9 * 81 * 1 * 512 || size == 18 * 81 * 1 * 512 || size == 10 * 81 * 1 * 512 || size == 20 * 81 * 1 * 512 ||
  1394. size == 9 * 82 * 1 * 512 || size == 18 * 82 * 1 * 512 || size == 10 * 82 * 1 * 512 || size == 20 * 82 * 1 * 512)) {
  1395. /* PC formatted image */
  1396. int side, sd;
  1397. drv->num_secs = 9;
  1398. drv->ddhd = 1;
  1399. sd = 0;
  1400. bool can40 = dfxtype == DRV_525_DD || dfxtype == DRV_PC_525_ONLY_40 || dfxtype == DRV_PC_525_40_80;
  1401. bool can80 = dfxtype == DRV_35_HD || dfxtype == DRV_PC_35_ONLY_80 || dfxtype == DRV_PC_525_40_80;
  1402. bool drv525 = dfxtype == DRV_525_DD || dfxtype == DRV_PC_525_ONLY_40 || dfxtype == DRV_PC_525_40_80;
  1403. for (side = 2; side > 0; side--) {
  1404. if (drv->hard_num_cyls >= 80 && can80) {
  1405. if ( size == 9 * 80 * side * 512 || size == 9 * 81 * side * 512 || size == 9 * 82 * side * 512) {
  1406. drv->num_secs = 9;
  1407. drv->ddhd = 1;
  1408. break;
  1409. } else if (!drv525 && (size == 18 * 80 * side * 512 || size == 18 * 81 * side * 512 || size == 18 * 82 * side * 512)) {
  1410. drv->num_secs = 18;
  1411. drv->ddhd = 2;
  1412. break;
  1413. } else if (!drv525 && (size == 10 * 80 * side * 512 || size == 10 * 81 * side * 512 || size == 10 * 82 * side * 512)) {
  1414. drv->num_secs = 10;
  1415. drv->ddhd = 1;
  1416. break;
  1417. } else if (!drv525 && (size == 20 * 80 * side * 512 || size == 20 * 81 * side * 512 || size == 20 * 82 * side * 512)) {
  1418. drv->num_secs = 20;
  1419. drv->ddhd = 2;
  1420. break;
  1421. } else if (!drv525 && (size == 21 * 80 * side * 512 || size == 21 * 81 * side * 512 || size == 21 * 82 * side * 512)) {
  1422. drv->num_secs = 21;
  1423. drv->ddhd = 2;
  1424. break;
  1425. } else if (size == 15 * 80 * side * 512) {
  1426. drv->num_secs = 15;
  1427. drv->ddhd = 1;
  1428. break;
  1429. }
  1430. }
  1431. if (drv->hard_num_cyls == 40 || can40) {
  1432. if (size == 9 * 40 * side * 512) {
  1433. drv->num_secs = 9;
  1434. drv->ddhd = 1;
  1435. sd = 1;
  1436. break;
  1437. } else if (size == 8 * 40 * side * 512) {
  1438. drv->num_secs = 8;
  1439. drv->ddhd = 1;
  1440. sd = 1;
  1441. break;
  1442. }
  1443. }
  1444. }
  1445. drv->num_tracks = size / (drv->num_secs * 512);
  1446. // SD disk in 5.25 drive = duplicate each track
  1447. if (sd && dfxtype == DRV_525_DD) {
  1448. drv->num_tracks *= 2;
  1449. } else {
  1450. sd = 0;
  1451. }
  1452. drv->filetype = ADF_PCDOS;
  1453. tid = &drv->trackdata[0];
  1454. for (int i = 0; i < drv->num_tracks; i++) {
  1455. tid->type = TRACK_PCDOS;
  1456. tid->len = 512 * drv->num_secs;
  1457. tid->bitlen = 0;
  1458. tid->offs = (sd ? i / 2 : i) * 512 * drv->num_secs;
  1459. if (side == 1) {
  1460. tid++;
  1461. tid->type = TRACK_NONE;
  1462. tid->len = 512 * drv->num_secs;
  1463. }
  1464. tid->revolutions = 1;
  1465. tid++;
  1466. }
  1467. drv->num_heads = side;
  1468. if (side == 1)
  1469. drv->num_tracks *= 2;
  1470. } else if ((size == 262144 || size == 524288) && buffer[0] == 0x11 && (buffer[1] == 0x11 || buffer[1] == 0x14)) {
  1471. // 256k -> KICK disk, 512k -> SuperKickstart disk
  1472. drv->filetype = size == 262144 ? ADF_KICK : ADF_SKICK;
  1473. drv->num_tracks = 1760 / (drv->num_secs = 11);
  1474. for (int i = 0; i < drv->num_tracks; i++) {
  1475. tid = &drv->trackdata[i];
  1476. tid->type = TRACK_AMIGADOS;
  1477. tid->len = 512 * drv->num_secs;
  1478. tid->bitlen = 0;
  1479. tid->offs = i * 512 * drv->num_secs - (drv->filetype == ADF_KICK ? 512 : 262144 + 1024);
  1480. tid->track = i;
  1481. tid->revolutions = 1;
  1482. }
  1483. } else {
  1484. int ds;
  1485. ds = 0;
  1486. drv->filetype = ADF_NORMAL;
  1487. /* High-density, diskspare disk or sector headers included? */
  1488. drv->num_tracks = 0;
  1489. if (size > 160 * 11 * 512 + 511) { // larger than standard adf?
  1490. for (int i = 80; i <= 83; i++) {
  1491. if (size == i * 22 * 512 * 2) { // HD
  1492. drv->ddhd = 2;
  1493. drv->num_tracks = size / (512 * (drv->num_secs = 22));
  1494. break;
  1495. }
  1496. if (size == i * 11 * 512 * 2) { // >80 cyl DD
  1497. drv->num_tracks = size / (512 * (drv->num_secs = 11));
  1498. break;
  1499. }
  1500. if (size == i * 12 * 512 * 2) { // ds 12 sectors
  1501. drv->num_tracks = size / (512 * (drv->num_secs = 12));
  1502. ds = 1;
  1503. break;
  1504. }
  1505. if (size == i * 24 * 512 * 2) { // ds 24 sectors
  1506. drv->num_tracks = size / (512 * (drv->num_secs = 24));
  1507. drv->ddhd = 2;
  1508. ds = 1;
  1509. break;
  1510. }
  1511. if (size == i * 11 * (512 + 16) * 2) { // 80+ cyl DD + headers
  1512. drv->num_tracks = size / ((512 + 16) * (drv->num_secs = 11));
  1513. drv->filetype = ADF_NORMAL_HEADER;
  1514. break;
  1515. }
  1516. if (size == i * 22 * (512 + 16) * 2) { // 80+ cyl HD + headers
  1517. drv->num_tracks = size / ((512 + 16) * (drv->num_secs = 22));
  1518. drv->filetype = ADF_NORMAL_HEADER;
  1519. break;
  1520. }
  1521. }
  1522. if (drv->num_tracks == 0) {
  1523. drv->num_tracks = size / (512 * (drv->num_secs = 22));
  1524. drv->ddhd = 2;
  1525. }
  1526. } else {
  1527. drv->num_tracks = size / (512 * (drv->num_secs = 11));
  1528. }
  1529. if (!ds && drv->num_tracks > MAX_TRACKS)
  1530. write_log (_T("Your diskfile is too big, %d bytes!\n"), size);
  1531. for (int i = 0; i < drv->num_tracks; i++) {
  1532. tid = &drv->trackdata[i];
  1533. tid->type = ds ? TRACK_DISKSPARE : TRACK_AMIGADOS;
  1534. tid->len = 512 * drv->num_secs;
  1535. tid->bitlen = 0;
  1536. tid->offs = i * 512 * drv->num_secs;
  1537. tid->revolutions = 1;
  1538. if (drv->filetype == ADF_NORMAL_HEADER) {
  1539. tid->extraoffs = drv->num_tracks * 512 * drv->num_secs + i * 16 * drv->num_secs;
  1540. } else {
  1541. tid->extraoffs = -1;
  1542. }
  1543. }
  1544. }
  1545. openwritefile (p, drv, 0);
  1546. drive_settype_id (drv); /* Set DD or HD drive */
  1547. drive_fill_bigbuf (drv, 1);
  1548. drv->mfmpos = uaerand ();
  1549. drv->mfmpos |= (uaerand () << 16);
  1550. drv->mfmpos %= drv->tracklen;
  1551. drv->prevtracklen = 0;
  1552. if (!fake) {
  1553. #ifdef DRIVESOUND
  1554. if (isfloppysound (drv))
  1555. driveclick_insert (drv - floppy, 0);
  1556. #endif
  1557. update_drive_gui (drv - floppy, false);
  1558. update_disk_statusline(drv - floppy);
  1559. }
  1560. return 1;
  1561. }
  1562. static void rand_shifter (drive *drv)
  1563. {
  1564. if (selected & (1 << (drv - floppy)))
  1565. return;
  1566. int r = ((uaerand() >> 4) & 7) + 1;
  1567. while (r-- > 0) {
  1568. word <<= 1;
  1569. word |= (uaerand() & 0x1000) ? 1 : 0;
  1570. bitoffset++;
  1571. bitoffset &= 15;
  1572. }
  1573. }
  1574. static void set_steplimit (drive *drv)
  1575. {
  1576. // emulate step limit only if cycle-exact or approximate CPU speed
  1577. if (currprefs.m68k_speed != 0)
  1578. return;
  1579. drv->steplimit = 4;
  1580. drv->steplimitcycle = get_cycles ();
  1581. }
  1582. static bool drive_empty (drive * drv)
  1583. {
  1584. #ifdef FLOPPYBRIDGE
  1585. if (drv->bridge) {
  1586. bool v = drv->bridge->isDiskInDrive();
  1587. return v == false;
  1588. }
  1589. #endif
  1590. #ifdef CATWEASEL
  1591. if (drv->catweasel)
  1592. return catweasel_disk_changed (drv->catweasel) == 0;
  1593. #endif
  1594. return drv->diskfile == 0 && drv->dskchange_time >= 0;
  1595. }
  1596. static void drive_step (drive *drv, int step_direction)
  1597. {
  1598. #ifdef CATWEASEL
  1599. if (drv->catweasel) {
  1600. int dir = direction ? -1 : 1;
  1601. catweasel_step (drv->catweasel, dir);
  1602. drv->cyl += dir;
  1603. if (drv->cyl < 0)
  1604. drv->cyl = 0;
  1605. write_log (_T("%d -> %d\n"), dir, drv->cyl);
  1606. return;
  1607. }
  1608. #endif
  1609. if (!drive_empty (drv))
  1610. drv->dskchange = 0;
  1611. #ifdef FLOPPYBRIDGE
  1612. if (drv->bridge) {
  1613. int dir = step_direction ? -1 : 1;
  1614. drv->cyl += dir;
  1615. if (drv->cyl < 0) {
  1616. drv->cyl = 0;
  1617. drv->bridge->handleNoClickStep(side);
  1618. } else {
  1619. if (drv->cyl >= drv->bridge->getMaxCylinder()) {
  1620. drv->cyl = drv->bridge->getMaxCylinder() - 1;
  1621. }
  1622. drv->bridge->gotoCylinder(drv->cyl, side);
  1623. }
  1624. return;
  1625. }
  1626. #endif
  1627. if (drv->steplimit && get_cycles() - drv->steplimitcycle < MIN_STEPLIMIT_CYCLE) {
  1628. write_log (_T(" step ignored drive %ld, %lu\n"),
  1629. drv - floppy, (get_cycles() - drv->steplimitcycle) / CYCLE_UNIT);
  1630. return;
  1631. }
  1632. /* A1200's floppy drive needs at least 30 raster lines between steps
  1633. * but we'll use very small value for better compatibility with faster CPU emulation
  1634. * (stupid trackloaders with CPU delay loops)
  1635. */
  1636. set_steplimit (drv);
  1637. if (step_direction) {
  1638. if (drv->cyl) {
  1639. drv->cyl--;
  1640. #ifdef DRIVESOUND
  1641. if (isfloppysound (drv))
  1642. driveclick_click (drv - floppy, drv->cyl);
  1643. #endif
  1644. }
  1645. /* else
  1646. write_log (_T("program tried to step beyond track zero\n"));
  1647. "no-click" programs does that
  1648. */
  1649. } else {
  1650. int maxtrack = drv->hard_num_cyls;
  1651. if (drv->cyl < maxtrack + 3) {
  1652. drv->cyl++;
  1653. #ifdef CATWEASEL
  1654. if (drv->catweasel)
  1655. catweasel_step (drv->catweasel, 1);
  1656. #endif
  1657. }
  1658. if (drv->cyl >= maxtrack)
  1659. write_log (_T("program tried to step over track %d PC %08x\n"), maxtrack, M68K_GETPC);
  1660. #ifdef DRIVESOUND
  1661. if (isfloppysound (drv))
  1662. driveclick_click (drv - floppy, drv->cyl);
  1663. #endif
  1664. }
  1665. rand_shifter (drv);
  1666. if (disk_debug_logging > 2)
  1667. write_log (_T(" ->step %d"), drv->cyl);
  1668. }
  1669. static bool drive_track0 (drive * drv)
  1670. {
  1671. #ifdef FLOPPYBRIDGE
  1672. if (drv->bridge) {
  1673. bool v = drv->bridge->isAtCylinder0();
  1674. return v;
  1675. }
  1676. #endif
  1677. #ifdef CATWEASEL
  1678. if (drv->catweasel)
  1679. return catweasel_track0 (drv->catweasel);
  1680. #endif
  1681. return drv->cyl == 0;
  1682. }
  1683. static bool drive_diskchange(drive *drv)
  1684. {
  1685. #ifdef FLOPPYBRIDGE
  1686. if (drv->bridge) {
  1687. bool v = drv->bridge->hasDiskChanged();
  1688. return v;
  1689. }
  1690. #endif
  1691. return drv->dskchange;
  1692. }
  1693. static bool drive_diskready(drive *drv)
  1694. {
  1695. #ifdef FLOPPYBRIDGE
  1696. if (drv->bridge) {
  1697. bool v = drv->bridge->isReady();
  1698. return v;
  1699. }
  1700. #endif
  1701. return drv->dskready;
  1702. }
  1703. static bool drive_at_index(drive *drv, int mfmBitPosition)
  1704. {
  1705. #ifdef FLOPPYBRIDGE
  1706. if (drv->bridge) {
  1707. bool v = drv->bridge->isMFMPositionAtIndex(mfmBitPosition);
  1708. return v;
  1709. }
  1710. #endif
  1711. return mfmBitPosition == drv->indexoffset;
  1712. }
  1713. static bool drive_running (drive * drv)
  1714. {
  1715. #ifdef FLOPPYBRIDGE
  1716. if (drv->bridge) {
  1717. bool v = drv->bridge->isMotorRunning();
  1718. return v;
  1719. }
  1720. #endif
  1721. return !drv->motoroff;
  1722. }
  1723. static void motordelay_func (uae_u32 v)
  1724. {
  1725. floppy[v].motordelay = 0;
  1726. }
  1727. static void drive_motor (drive * drv, bool off)
  1728. {
  1729. if (drv->motoroff && !off) {
  1730. drv->dskready_up_time = DSKREADY_UP_TIME * 312 + (uaerand() & 511);
  1731. rand_shifter (drv);
  1732. #ifdef DRIVESOUND
  1733. if (isfloppysound (drv))
  1734. driveclick_motor (drv - floppy, drv->dskready_down_time == 0 ? 2 : 1);
  1735. #endif
  1736. if (disk_debug_logging > 2)
  1737. write_log (_T(" ->motor on"));
  1738. }
  1739. if (!drv->motoroff && off) {
  1740. drv->drive_id_scnt = 0; /* Reset id shift reg counter */
  1741. #ifdef FLOPPYBRIDGE
  1742. if (drv->bridge) {
  1743. drive_settype_id(drv); // allow for dynamic DD/HD switching
  1744. }
  1745. #endif
  1746. drv->dskready_down_time = DSKREADY_DOWN_TIME * 312 + (uaerand() & 511);
  1747. #ifdef DRIVESOUND
  1748. driveclick_motor (drv - floppy, 0);
  1749. #endif
  1750. #ifdef DEBUG_DRIVE_ID
  1751. write_log (_T("drive_motor: Selected DF%d: reset id shift reg.\n"),drv-floppy);
  1752. #endif
  1753. if (disk_debug_logging > 2)
  1754. write_log (_T(" ->motor off"));
  1755. if (currprefs.cpu_model <= 68010 && currprefs.m68k_speed == 0) {
  1756. drv->motordelay = 1;
  1757. event2_newevent2 (30, drv - floppy, motordelay_func);
  1758. }
  1759. }
  1760. drv->motoroff = off;
  1761. if (drv->motoroff) {
  1762. drv->dskready = 0;
  1763. drv->dskready_up_time = 0;
  1764. } else {
  1765. drv->dskready_down_time = 0;
  1766. }
  1767. #ifdef FLOPPYBRIDGE
  1768. if (drv->bridge) {
  1769. drv->bridge->setMotorStatus(side, !drv->motoroff);
  1770. }
  1771. #endif
  1772. #ifdef CATWEASEL
  1773. if (drv->catweasel)
  1774. catweasel_set_motor (drv->catweasel, !drv->motoroff);
  1775. #endif
  1776. }
  1777. static void read_floppy_data(struct zfile *diskfile, int type, trackid *tid, int sector, uae_u8 *dst, uae_u8 *secheaddst, int len)
  1778. {
  1779. if (len <= 0)
  1780. return;
  1781. if (secheaddst) {
  1782. memset(secheaddst, 0, 16);
  1783. }
  1784. if (tid->track == 0) {
  1785. if (type == ADF_KICK) {
  1786. memset (dst, 0, len > 512 ? 512 : len);
  1787. if (sector == 0) {
  1788. memcpy (dst, "KICK", 4);
  1789. len -= 512;
  1790. }
  1791. } else if (type == ADF_SKICK) {
  1792. memset (dst, 0, len > 512 ? 512 : len);
  1793. if (sector == 0) {
  1794. memcpy (dst, "KICKSUP0", 8);
  1795. len -= 1024;
  1796. } else if (sector == 1) {
  1797. len -= 512;
  1798. }
  1799. }
  1800. }
  1801. if (tid->offs < 0 || sector < 0)
  1802. return;
  1803. if (type == ADF_NORMAL_HEADER && tid->extraoffs > 0) {
  1804. zfile_fseek(diskfile, tid->extraoffs + sector * 16, SEEK_SET);
  1805. zfile_fread(secheaddst, 1, 16, diskfile);
  1806. }
  1807. zfile_fseek(diskfile, tid->offs + sector * 512, SEEK_SET);
  1808. zfile_fread(dst, 1, len, diskfile);
  1809. }
  1810. /* Megalomania does not like zero MFM words... */
  1811. static void mfmcode (uae_u16 * mfm, int words)
  1812. {
  1813. uae_u32 lastword = 0;
  1814. while (words--) {
  1815. uae_u32 v = (*mfm) & 0x55555555;
  1816. uae_u32 lv = (lastword << 16) | v;
  1817. uae_u32 nlv = 0x55555555 & ~lv;
  1818. uae_u32 mfmbits = (nlv << 1) & (nlv >> 1);
  1819. *mfm++ = v | mfmbits;
  1820. lastword = v;
  1821. }
  1822. }
  1823. static const uae_u8 mfmencodetable[16] = {
  1824. 0x2a, 0x29, 0x24, 0x25, 0x12, 0x11, 0x14, 0x15,
  1825. 0x4a, 0x49, 0x44, 0x45, 0x52, 0x51, 0x54, 0x55
  1826. };
  1827. static uae_u16 dos_encode_byte (uae_u8 byte)
  1828. {
  1829. uae_u8 b2, b1;
  1830. uae_u16 word;
  1831. b1 = byte;
  1832. b2 = b1 >> 4;
  1833. b1 &= 15;
  1834. word = mfmencodetable[b2] <<8 | mfmencodetable[b1];
  1835. return (word | ((word & (256 | 64)) ? 0 : 128));
  1836. }
  1837. static uae_u16 *mfmcoder (uae_u8 *src, uae_u16 *dest, int len)
  1838. {
  1839. int i;
  1840. for (i = 0; i < len; i++) {
  1841. *dest = dos_encode_byte (*src++);
  1842. *dest |= ((dest[-1] & 1)||(*dest & 0x4000)) ? 0: 0x8000;
  1843. dest++;
  1844. }
  1845. return dest;
  1846. }
  1847. static void decode_pcdos (drive *drv)
  1848. {
  1849. int i, len;
  1850. int tr = drv->cyl * 2 + side;
  1851. uae_u16 *dstmfmbuf, *mfm2;
  1852. uae_u8 secbuf[1000];
  1853. uae_u16 crc16;
  1854. trackid *ti = drv->trackdata + tr;
  1855. int tracklen = 12500;
  1856. mfm2 = drv->bigmfmbuf;
  1857. *mfm2++ = 0x9254;
  1858. memset (secbuf, 0x4e, 40);
  1859. memset (secbuf + 40, 0x00, 12);
  1860. secbuf[52] = 0xc2;
  1861. secbuf[53] = 0xc2;
  1862. secbuf[54] = 0xc2;
  1863. secbuf[55] = 0xfc;
  1864. memset (secbuf + 56, 0x4e, 40);
  1865. dstmfmbuf = mfmcoder (secbuf, mfm2, 96);
  1866. mfm2[52] = 0x5224;
  1867. mfm2[53] = 0x5224;
  1868. mfm2[54] = 0x5224;
  1869. for (i = 0; i < drv->num_secs; i++) {
  1870. mfm2 = dstmfmbuf;
  1871. memset (secbuf, 0x00, 12);
  1872. secbuf[12] = 0xa1;
  1873. secbuf[13] = 0xa1;
  1874. secbuf[14] = 0xa1;
  1875. secbuf[15] = 0xfe;
  1876. secbuf[16] = drv->cyl;
  1877. secbuf[17] = side;
  1878. secbuf[18] = 1 + i;
  1879. secbuf[19] = 2; // 128 << 2 = 512
  1880. crc16 = get_crc16(secbuf + 12, 3 + 1 + 4);
  1881. secbuf[20] = crc16 >> 8;
  1882. secbuf[21] = crc16 & 0xff;
  1883. memset(secbuf + 22, 0x4e, 22);
  1884. memset(secbuf + 44, 0x00, 12);
  1885. secbuf[56] = 0xa1;
  1886. secbuf[57] = 0xa1;
  1887. secbuf[58] = 0xa1;
  1888. secbuf[59] = 0xfb;
  1889. read_floppy_data (drv->diskfile, drv->filetype, ti, i, &secbuf[60], NULL, 512);
  1890. crc16 = get_crc16 (secbuf + 56, 3 + 1 + 512);
  1891. secbuf[60 + 512] = crc16 >> 8;
  1892. secbuf[61 + 512] = crc16 & 0xff;
  1893. len = (tracklen / 2 - 96) / drv->num_secs - 574 / drv->ddhd;
  1894. if (len > 0)
  1895. memset(secbuf + 512 + 62, 0x4e, len);
  1896. dstmfmbuf = mfmcoder (secbuf, mfm2, 60 + 512 + 2 + 76 / drv->ddhd);
  1897. mfm2[12] = 0x4489;
  1898. mfm2[13] = 0x4489;
  1899. mfm2[14] = 0x4489;
  1900. mfm2[56] = 0x4489;
  1901. mfm2[57] = 0x4489;
  1902. mfm2[58] = 0x4489;
  1903. }
  1904. while (dstmfmbuf - drv->bigmfmbuf < tracklen / 2)
  1905. *dstmfmbuf++ = 0x9254;
  1906. drv->skipoffset = 0;
  1907. drv->tracklen = (dstmfmbuf - drv->bigmfmbuf) * 16;
  1908. if (disk_debug_logging > 0)
  1909. write_log (_T("pcdos read track %d\n"), tr);
  1910. }
  1911. static void decode_amigados (drive *drv)
  1912. {
  1913. /* Normal AmigaDOS format track */
  1914. int tr = drv->cyl * 2 + side;
  1915. int sec;
  1916. int dstmfmoffset = 0;
  1917. uae_u16 *dstmfmbuf = drv->bigmfmbuf;
  1918. int len = drv->num_secs * 544 + FLOPPY_GAP_LEN;
  1919. int prevbit;
  1920. trackid *ti = drv->trackdata + tr;
  1921. memset (dstmfmbuf, 0xaa, len * 2);
  1922. dstmfmoffset += FLOPPY_GAP_LEN;
  1923. drv->skipoffset = (FLOPPY_GAP_LEN * 8) / 3 * 2;
  1924. drv->tracklen = len * 2 * 8;
  1925. prevbit = 0;
  1926. for (sec = 0; sec < drv->num_secs; sec++) {
  1927. uae_u8 secbuf[544];
  1928. uae_u8 secheadbuf[16];
  1929. uae_u16 mfmbuf[544 + 1];
  1930. int i;
  1931. uae_u32 deven, dodd;
  1932. uae_u32 hck = 0, dck = 0;
  1933. secbuf[0] = secbuf[1] = 0x00;
  1934. secbuf[2] = secbuf[3] = 0xa1;
  1935. secbuf[4] = 0xff;
  1936. secbuf[5] = tr;
  1937. secbuf[6] = sec;
  1938. secbuf[7] = drv->num_secs - sec;
  1939. for (i = 8; i < 24; i++)
  1940. secbuf[i] = 0;
  1941. read_floppy_data (drv->diskfile, drv->filetype, ti, sec, &secbuf[32], secheadbuf, 512);
  1942. mfmbuf[0] = prevbit ? 0x2aaa : 0xaaaa;
  1943. mfmbuf[1] = 0xaaaa;
  1944. mfmbuf[2] = mfmbuf[3] = 0x4489;
  1945. deven = ((secbuf[4] << 24) | (secbuf[5] << 16)
  1946. | (secbuf[6] << 8) | (secbuf[7]));
  1947. dodd = deven >> 1;
  1948. deven &= 0x55555555;
  1949. dodd &= 0x55555555;
  1950. mfmbuf[4] = dodd >> 16;
  1951. mfmbuf[5] = dodd;
  1952. mfmbuf[6] = deven >> 16;
  1953. mfmbuf[7] = deven;
  1954. for (i = 0; i < 16; i += 4) {
  1955. deven = ((secheadbuf[i] << 24) | (secheadbuf[i + 1] << 16)
  1956. | (secheadbuf[i + 2] << 8) | (secheadbuf[i + 3]));
  1957. dodd = deven >> 1;
  1958. deven &= 0x55555555;
  1959. dodd &= 0x55555555;
  1960. mfmbuf[(i >> 1) + 8] = dodd >> 16;
  1961. mfmbuf[(i >> 1) + 9] = dodd;
  1962. mfmbuf[(i >> 1) + 8 + 8] = deven >> 16;
  1963. mfmbuf[(i >> 1) + 8 + 9] = deven;
  1964. }
  1965. for (i = 4; i < 24; i += 2) {
  1966. hck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1];
  1967. }
  1968. deven = dodd = hck;
  1969. dodd >>= 1;
  1970. mfmbuf[24] = dodd >> 16;
  1971. mfmbuf[25] = dodd;
  1972. mfmbuf[26] = deven >> 16;
  1973. mfmbuf[27] = deven;
  1974. for (i = 0; i < 512; i += 4) {
  1975. deven = ((secbuf[i + 32] << 24) | (secbuf[i + 33] << 16)
  1976. | (secbuf[i + 34] << 8) | (secbuf[i + 35]));
  1977. dodd = deven >> 1;
  1978. deven &= 0x55555555;
  1979. dodd &= 0x55555555;
  1980. mfmbuf[(i >> 1) + 32] = dodd >> 16;
  1981. mfmbuf[(i >> 1) + 33] = dodd;
  1982. mfmbuf[(i >> 1) + 256 + 32] = deven >> 16;
  1983. mfmbuf[(i >> 1) + 256 + 33] = deven;
  1984. }
  1985. for (i = 32; i < 544; i += 2) {
  1986. dck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1];
  1987. }
  1988. deven = dodd = dck;
  1989. dodd >>= 1;
  1990. mfmbuf[28] = dodd >> 16;
  1991. mfmbuf[29] = dodd;
  1992. mfmbuf[30] = deven >> 16;
  1993. mfmbuf[31] = deven;
  1994. mfmbuf[544] = 0;
  1995. mfmcode (mfmbuf + 4, 544 - 4 + 1);
  1996. for (i = 0; i < 544; i++) {
  1997. dstmfmbuf[dstmfmoffset % len] = mfmbuf[i];
  1998. dstmfmoffset++;
  1999. }
  2000. prevbit = mfmbuf[i - 1] & 1;
  2001. // so that final word has correct MFM encoding
  2002. dstmfmbuf[dstmfmoffset % len] = mfmbuf[i];
  2003. }
  2004. if (disk_debug_logging > 0)
  2005. write_log (_T("amigados read track %d\n"), tr);
  2006. }
  2007. /*
  2008. * diskspare format
  2009. *
  2010. * 0 <4489> <4489> 0 track sector crchi, crclo, data[512] (520 bytes per sector)
  2011. *
  2012. * 0xAAAA 0x4489 0x4489 0x2AAA oddhi, oddlo, evenhi, evenlo, ...
  2013. *
  2014. * NOTE: data is MFM encoded using same method as ADOS header, not like ADOS data!
  2015. *
  2016. */
  2017. static void decode_diskspare (drive *drv)
  2018. {
  2019. int tr = drv->cyl * 2 + side;
  2020. int sec;
  2021. int dstmfmoffset = 0;
  2022. int size = 512 + 8;
  2023. uae_u16 *dstmfmbuf = drv->bigmfmbuf;
  2024. int len = drv->num_secs * size + FLOPPY_GAP_LEN;
  2025. trackid *ti = drv->trackdata + tr;
  2026. memset (dstmfmbuf, 0xaa, len * 2);
  2027. dstmfmoffset += FLOPPY_GAP_LEN;
  2028. drv->skipoffset = (FLOPPY_GAP_LEN * 8) / 3 * 2;
  2029. drv->tracklen = len * 2 * 8;
  2030. for (sec = 0; sec < drv->num_secs; sec++) {
  2031. uae_u8 secbuf[512 + 8];
  2032. uae_u16 mfmbuf[512 + 8];
  2033. int i;
  2034. uae_u32 deven, dodd;
  2035. uae_u16 chk;
  2036. secbuf[0] = tr;
  2037. secbuf[1] = sec;
  2038. secbuf[2] = 0;
  2039. secbuf[3] = 0;
  2040. read_floppy_data (drv->diskfile, drv->filetype, ti, sec, &secbuf[4], NULL, 512);
  2041. mfmbuf[0] = 0xaaaa;
  2042. mfmbuf[1] = 0x4489;
  2043. mfmbuf[2] = 0x4489;
  2044. mfmbuf[3] = 0x2aaa;
  2045. for (i = 0; i < 512; i += 4) {
  2046. deven = ((secbuf[i + 4] << 24) | (secbuf[i + 5] << 16)
  2047. | (secbuf[i + 6] << 8) | (secbuf[i + 7]));
  2048. dodd = deven >> 1;
  2049. deven &= 0x55555555;
  2050. dodd &= 0x55555555;
  2051. mfmbuf[i + 8 + 0] = dodd >> 16;
  2052. mfmbuf[i + 8 + 1] = dodd;
  2053. mfmbuf[i + 8 + 2] = deven >> 16;
  2054. mfmbuf[i + 8 + 3] = deven;
  2055. }
  2056. mfmcode (mfmbuf + 8, 512);
  2057. i = 8;
  2058. chk = mfmbuf[i++] & 0x7fff;
  2059. while (i < 512 + 8)
  2060. chk ^= mfmbuf[i++];
  2061. secbuf[2] = chk >> 8;
  2062. secbuf[3] = (uae_u8)chk;
  2063. deven = ((secbuf[0] << 24) | (secbuf[1] << 16)
  2064. | (secbuf[2] << 8) | (secbuf[3]));
  2065. dodd = deven >> 1;
  2066. deven &= 0x55555555;
  2067. dodd &= 0x55555555;
  2068. mfmbuf[4] = dodd >> 16;
  2069. mfmbuf[5] = dodd;
  2070. mfmbuf[6] = deven >> 16;
  2071. mfmbuf[7] = deven;
  2072. mfmcode (mfmbuf + 4, 4);
  2073. for (i = 0; i < 512 + 8; i++) {
  2074. dstmfmbuf[dstmfmoffset % len] = mfmbuf[i];
  2075. dstmfmoffset++;
  2076. }
  2077. }
  2078. if (disk_debug_logging > 0)
  2079. write_log (_T("diskspare read track %d\n"), tr);
  2080. }
  2081. static void drive_fill_bigbuf (drive * drv, int force)
  2082. {
  2083. int tr = drv->cyl * 2 + side;
  2084. trackid *ti = drv->trackdata + tr;
  2085. bool retrytrack;
  2086. int rev = -1;
  2087. if ((!drv->diskfile && !drv->catweasel && !drv->bridge) || tr >= drv->num_tracks) {
  2088. track_reset (drv);
  2089. return;
  2090. }
  2091. if (!force && drv->catweasel) {
  2092. drv->buffered_cyl = -1;
  2093. return;
  2094. }
  2095. if (!force && drv->buffered_cyl == drv->cyl && drv->buffered_side == side)
  2096. return;
  2097. drv->indexoffset = 0;
  2098. drv->multi_revolution = 0;
  2099. drv->tracktiming[0] = 0;
  2100. drv->skipoffset = -1;
  2101. drv->revolutions = 1;
  2102. retrytrack = drv->lastdataacesstrack == drv->cyl * 2 + side;
  2103. if (!dskdmaen && !retrytrack)
  2104. drv->track_access_done = false;
  2105. //write_log (_T("%d:%d %d\n"), drv->cyl, side, retrytrack);
  2106. if (drv->writediskfile && drv->writetrackdata[tr].bitlen > 0) {
  2107. int i;
  2108. trackid *wti = &drv->writetrackdata[tr];
  2109. drv->tracklen = wti->bitlen;
  2110. drv->revolutions = wti->revolutions;
  2111. read_floppy_data(drv->writediskfile, drv->filetype, wti, 0, (uae_u8 *)drv->bigmfmbuf, NULL, (wti->bitlen + 7) / 8);
  2112. for (i = 0; i < (drv->tracklen + 15) / 16; i++) {
  2113. uae_u16 *mfm = drv->bigmfmbuf + i;
  2114. uae_u8 *data = (uae_u8 *)mfm;
  2115. *mfm = 256 * *data + *(data + 1);
  2116. }
  2117. if (disk_debug_logging > 0)
  2118. write_log(_T("track %d, length %d read from \"saveimage\"\n"), tr, drv->tracklen);
  2119. #ifdef FLOPPYBRIDGE
  2120. } else if (drv->filetype == ADF_FLOPPYBRIDGE) {
  2121. if (drv->bridge) {
  2122. drv->multi_revolution = 1;
  2123. drv->skipoffset = -1;
  2124. drv->bridge->setSurface(side); // force the correct disk side to be selected
  2125. drv->tracklen = drv->bridge->maxMFMBitPosition();
  2126. drv->tracktiming[0] = drv->bridge->getMFMSpeed(drv->mfmpos % drv->tracklen);
  2127. if (force < 0) {
  2128. floppybridge_read_track(drv);
  2129. }
  2130. }
  2131. #endif
  2132. } else if (drv->filetype == ADF_CATWEASEL) {
  2133. #ifdef CATWEASEL
  2134. drv->tracklen = 0;
  2135. if (!catweasel_disk_changed (drv->catweasel)) {
  2136. drv->tracklen = catweasel_fillmfm (drv->catweasel, drv->bigmfmbuf, side, drv->ddhd, 0);
  2137. }
  2138. drv->buffered_cyl = -1;
  2139. if (!drv->tracklen) {
  2140. track_reset (drv);
  2141. return;
  2142. }
  2143. #endif
  2144. } else if (drv->filetype == ADF_IPF) {
  2145. #ifdef CAPS
  2146. caps_loadtrack (drv->bigmfmbuf, drv->tracktiming, drv - floppy, tr, &drv->tracklen, &drv->multi_revolution, &drv->skipoffset, &drv->lastrev, retrytrack);
  2147. #endif
  2148. } else if (drv->filetype == ADF_SCP) {
  2149. #ifdef SCP
  2150. scp_loadtrack (drv->bigmfmbuf, drv->tracktiming, drv - floppy, tr, &drv->tracklen, &drv->multi_revolution, &drv->skipoffset, &drv->lastrev, retrytrack);
  2151. #endif
  2152. } else if (drv->filetype == ADF_FDI) {
  2153. #ifdef FDI2RAW
  2154. fdi2raw_loadtrack (drv->fdi, drv->bigmfmbuf, drv->tracktiming, tr, &drv->tracklen, &drv->indexoffset, &drv->multi_revolution, 1);
  2155. #endif
  2156. } else if (ti->type == TRACK_PCDOS) {
  2157. decode_pcdos (drv);
  2158. } else if (ti->type == TRACK_AMIGADOS) {
  2159. decode_amigados (drv);
  2160. } else if (ti->type == TRACK_DISKSPARE) {
  2161. decode_diskspare (drv);
  2162. } else if (ti->type == TRACK_NONE) {
  2163. ;
  2164. } else {
  2165. int i;
  2166. int base_offset = ti->type == TRACK_RAW ? 0 : 1;
  2167. drv->tracklen = ti->bitlen + 16 * base_offset;
  2168. drv->bigmfmbuf[0] = ti->sync;
  2169. read_floppy_data (drv->diskfile, drv->filetype, ti, 0, (uae_u8*)(drv->bigmfmbuf + base_offset), NULL, (ti->bitlen + 7) / 8);
  2170. for (i = base_offset; i < (drv->tracklen + 15) / 16; i++) {
  2171. uae_u16 *mfm = drv->bigmfmbuf + i;
  2172. uae_u8 *data = (uae_u8 *) mfm;
  2173. *mfm = 256 * *data + *(data + 1);
  2174. }
  2175. if (disk_debug_logging > 2)
  2176. write_log (_T("rawtrack %d image offset=%x\n"), tr, ti->offs);
  2177. }
  2178. drv->buffered_side = side;
  2179. drv->buffered_cyl = drv->cyl;
  2180. if (drv->tracklen == 0) {
  2181. drv->tracklen = FLOPPY_WRITE_LEN * drv->ddhd * 2 * 8;
  2182. memset (drv->bigmfmbuf, 0, FLOPPY_WRITE_LEN * 2 * drv->ddhd);
  2183. }
  2184. drv->trackspeed = get_floppy_speed_from_image(drv);
  2185. updatemfmpos (drv);
  2186. }
  2187. /* Update ADF_EXT2 track header */
  2188. static void diskfile_update (struct zfile *diskfile, trackid *ti, int len, image_tracktype type)
  2189. {
  2190. uae_u8 buf[2 + 2 + 4 + 4], *zerobuf;
  2191. ti->revolutions = 1;
  2192. ti->bitlen = len;
  2193. zfile_fseek (diskfile, 8 + 4 + (2 + 2 + 4 + 4) * ti->track, SEEK_SET);
  2194. memset (buf, 0, sizeof buf);
  2195. ti->type = type;
  2196. buf[2] = 0;
  2197. buf[3] = ti->type;
  2198. do_put_mem_long ((uae_u32 *) (buf + 4), ti->len);
  2199. do_put_mem_long ((uae_u32 *) (buf + 8), ti->bitlen);
  2200. zfile_fwrite (buf, sizeof buf, 1, diskfile);
  2201. if (ti->len > (len + 7) / 8) {
  2202. zerobuf = xmalloc (uae_u8, ti->len);
  2203. memset (zerobuf, 0, ti->len);
  2204. zfile_fseek (diskfile, ti->offs, SEEK_SET);
  2205. zfile_fwrite (zerobuf, 1, ti->len, diskfile);
  2206. free (zerobuf);
  2207. }
  2208. if (disk_debug_logging > 0)
  2209. write_log (_T("track %d, raw track length %d written (total size %d)\n"), ti->track, (ti->bitlen + 7) / 8, ti->len);
  2210. }
  2211. #define MFMMASK 0x55555555
  2212. static uae_u16 getmfmword (uae_u16 *mbuf, int shift)
  2213. {
  2214. return (mbuf[0] << shift) | (mbuf[1] >> (16 - shift));
  2215. }
  2216. static uae_u32 getmfmlong (uae_u16 *mbuf, int shift)
  2217. {
  2218. return ((getmfmword (mbuf, shift) << 16) | getmfmword (mbuf + 1, shift)) & MFMMASK;
  2219. }
  2220. #if MFM_VALIDATOR
  2221. static void check_valid_mfm (uae_u16 *mbuf, int words, int sector)
  2222. {
  2223. int prevbit = 0;
  2224. for (int i = 0; i < words * 8; i++) {
  2225. int wordoffset = i / 8;
  2226. uae_u16 w = mbuf[wordoffset];
  2227. uae_u16 wp = mbuf[wordoffset - 1];
  2228. int bitoffset = (7 - (i & 7)) * 2;
  2229. int clockbit = w & (1 << (bitoffset + 1));
  2230. int databit = w & (1 << (bitoffset + 0));
  2231. if ((clockbit && databit) || (clockbit && !databit && prevbit) || (!clockbit && !databit && !prevbit)) {
  2232. write_log (_T("illegal mfm sector %d data %04x %04x, bit %d:%d\n"), sector, wp, w, wordoffset, bitoffset);
  2233. }
  2234. prevbit = databit;
  2235. }
  2236. }
  2237. #endif
  2238. static int decode_buffer(drive *drv, uae_u16 *mbuf, int cyl, int drvsec, int ddhd, int filetype, int *drvsecp, int *sectable, int checkmode)
  2239. {
  2240. int i, secwritten = 0;
  2241. int fwlen = FLOPPY_WRITE_LEN * ddhd;
  2242. int length = 2 * fwlen;
  2243. uae_u32 odd, even, chksum, id, dlong;
  2244. uae_u8 *secdata;
  2245. uae_u8 secbuf[544];
  2246. uae_u16 *mend = mbuf + length, *mstart;
  2247. uae_u32 sechead[4];
  2248. int shift = 0;
  2249. bool issechead;
  2250. memset (sectable, 0, MAX_SECTORS * sizeof (int));
  2251. mstart = mbuf;
  2252. if (!drv->bridge) {
  2253. memcpy(mbuf + fwlen, mbuf, fwlen * sizeof(uae_u16));
  2254. }
  2255. mend -= (4 + 16 + 8 + 512);
  2256. while (secwritten < drvsec) {
  2257. int trackoffs;
  2258. while (getmfmword (mbuf, shift) != 0x4489) {
  2259. if (mbuf >= mend)
  2260. return 1;
  2261. shift++;
  2262. if (shift == 16) {
  2263. shift = 0;
  2264. mbuf++;
  2265. }
  2266. }
  2267. while (getmfmword (mbuf, shift) == 0x4489) {
  2268. if (mbuf >= mend)
  2269. return 1;
  2270. mbuf++;
  2271. }
  2272. odd = getmfmlong (mbuf, shift);
  2273. even = getmfmlong (mbuf + 2, shift);
  2274. mbuf += 4;
  2275. id = (odd << 1) | even;
  2276. trackoffs = (id & 0xff00) >> 8;
  2277. if (trackoffs + 1 > drvsec) {
  2278. write_log (_T("Disk decode: track %d, weird sector number %d (%08x, %ld)\n"), cyl * 2 + side, trackoffs, id, mbuf - mstart);
  2279. if (filetype == ADF_EXT2)
  2280. return 2;
  2281. continue;
  2282. }
  2283. #if MFM_VALIDATOR
  2284. check_valid_mfm (mbuf - 4, 544 - 4 + 1, trackoffs);
  2285. #endif
  2286. issechead = false;
  2287. chksum = odd ^ even;
  2288. for (i = 0; i < 4; i++) {
  2289. odd = getmfmlong (mbuf, shift);
  2290. even = getmfmlong (mbuf + 8, shift);
  2291. mbuf += 2;
  2292. dlong = (odd << 1) | even;
  2293. if (dlong && !checkmode) {
  2294. issechead = true;
  2295. }
  2296. sechead[i] = dlong;
  2297. chksum ^= odd ^ even;
  2298. }
  2299. if (issechead) {
  2300. if (filetype != ADF_NORMAL_HEADER) {
  2301. write_log(_T("Disk decode: track %d, sector %d header: %08X %08X %08X %08X\n"),
  2302. cyl * 2 + side, trackoffs, sechead[0], sechead[1], sechead[2], sechead[3]);
  2303. if (filetype == ADF_EXT2)
  2304. return 6;
  2305. }
  2306. }
  2307. mbuf += 8;
  2308. odd = getmfmlong (mbuf, shift);
  2309. even = getmfmlong (mbuf + 2, shift);
  2310. mbuf += 4;
  2311. if (((odd << 1) | even) != chksum) {
  2312. write_log (_T("Disk decode: track %d, checksum error on sector %d header\n"), cyl * 2 + side, trackoffs);
  2313. if (filetype == ADF_EXT2)
  2314. return 3;
  2315. continue;
  2316. }
  2317. if (((id & 0x00ff0000) >> 16) != cyl * 2 + side) {
  2318. write_log (_T("Disk decode: mismatched track (%d <> %d) on sector %d header (%08X)\n"), (id & 0x00ff0000) >> 16, cyl * 2 + side, trackoffs, id);
  2319. if (filetype == ADF_EXT2)
  2320. return 3;
  2321. continue;
  2322. }
  2323. odd = getmfmlong (mbuf, shift);
  2324. even = getmfmlong (mbuf + 2, shift);
  2325. mbuf += 4;
  2326. chksum = (odd << 1) | even;
  2327. secdata = secbuf + 32;
  2328. for (i = 0; i < 128; i++) {
  2329. odd = getmfmlong (mbuf, shift);
  2330. even = getmfmlong (mbuf + 256, shift);
  2331. mbuf += 2;
  2332. dlong = (odd << 1) | even;
  2333. *secdata++ = dlong >> 24;
  2334. *secdata++ = dlong >> 16;
  2335. *secdata++ = dlong >> 8;
  2336. *secdata++ = dlong;
  2337. chksum ^= odd ^ even;
  2338. }
  2339. if (chksum) {
  2340. write_log (_T("Disk decode: track %d, sector %d, data checksum error\n"), cyl * 2 + side, trackoffs);
  2341. if (filetype == ADF_EXT2)
  2342. return 4;
  2343. continue;
  2344. }
  2345. mbuf += 256;
  2346. //write_log (_T("Sector %d ok\n"), trackoffs);
  2347. sectable[trackoffs] = 1;
  2348. secwritten++;
  2349. memcpy (writebuffer + trackoffs * 512, secbuf + 32, 512);
  2350. uae_u8 *secheadbuf = writesecheadbuffer + trackoffs * 16;
  2351. for (i = 0; i < 4; i++) {
  2352. *secheadbuf++ = sechead[i] >> 24;
  2353. *secheadbuf++ = sechead[i] >> 16;
  2354. *secheadbuf++ = sechead[i] >> 8;
  2355. *secheadbuf++ = sechead[i] >> 0;
  2356. }
  2357. }
  2358. if (filetype == ADF_EXT2 && (secwritten == 0 || secwritten < 0))
  2359. return 5;
  2360. if (secwritten == 0)
  2361. write_log (_T("Disk decode: track %d, unsupported format\n"), cyl * 2 + side);
  2362. if (secwritten < 0)
  2363. write_log (_T("Disk decode: track %d, sector labels ignored\n"), cyl * 2 + side);
  2364. *drvsecp = drvsec;
  2365. return 0;
  2366. }
  2367. static uae_u8 mfmdecode (uae_u16 **mfmp, int shift)
  2368. {
  2369. uae_u16 mfm = getmfmword (*mfmp, shift);
  2370. uae_u8 out = 0;
  2371. int i;
  2372. (*mfmp)++;
  2373. mfm &= 0x5555;
  2374. for (i = 0; i < 8; i++) {
  2375. out >>= 1;
  2376. if (mfm & 1)
  2377. out |= 0x80;
  2378. mfm >>= 2;
  2379. }
  2380. return out;
  2381. }
  2382. static int drive_write_pcdos (drive *drv, struct zfile *zf, bool count)
  2383. {
  2384. int i;
  2385. int drvsec = drv->num_secs;
  2386. int fwlen = FLOPPY_WRITE_LEN * drv->ddhd;
  2387. int length = 2 * fwlen;
  2388. uae_u16 *mbuf = drv->bigmfmbuf;
  2389. uae_u16 *mend = mbuf + length;
  2390. int secwritten = 0, seccnt = 0;
  2391. int shift = 0, sector = -1;
  2392. int sectable[24];
  2393. uae_u8 secbuf[3 + 1 + 512];
  2394. uae_u8 mark;
  2395. uae_u16 crc;
  2396. memset (sectable, 0, sizeof sectable);
  2397. memcpy (mbuf + fwlen, mbuf, fwlen * sizeof (uae_u16));
  2398. mend -= 518;
  2399. secbuf[0] = secbuf[1] = secbuf[2] = 0xa1;
  2400. secbuf[3] = 0xfb;
  2401. while (seccnt < drvsec) {
  2402. int mfmcount;
  2403. mfmcount = 0;
  2404. while (getmfmword (mbuf, shift) != 0x4489) {
  2405. mfmcount++;
  2406. if (mbuf >= mend)
  2407. return -1;
  2408. shift++;
  2409. if (shift == 16) {
  2410. shift = 0;
  2411. mbuf++;
  2412. }
  2413. if (sector >= 0 && mfmcount / 16 >= 43)
  2414. sector = -1;
  2415. }
  2416. mfmcount = 0;
  2417. while (getmfmword (mbuf, shift) == 0x4489) {
  2418. mfmcount++;
  2419. if (mbuf >= mend)
  2420. return -1;
  2421. mbuf++;
  2422. }
  2423. if (mfmcount < 3) // ignore if less than 3 sync markers
  2424. continue;
  2425. mark = mfmdecode(&mbuf, shift);
  2426. if (mark == 0xfe) {
  2427. uae_u8 tmp[8];
  2428. uae_u8 cyl, head, size;
  2429. cyl = mfmdecode (&mbuf, shift);
  2430. head = mfmdecode (&mbuf, shift);
  2431. sector = mfmdecode (&mbuf, shift);
  2432. size = mfmdecode (&mbuf, shift);
  2433. crc = (mfmdecode (&mbuf, shift) << 8) | mfmdecode (&mbuf, shift);
  2434. tmp[0] = 0xa1; tmp[1] = 0xa1; tmp[2] = 0xa1; tmp[3] = mark;
  2435. tmp[4] = cyl; tmp[5] = head; tmp[6] = sector; tmp[7] = size;
  2436. // skip 28 bytes
  2437. for (i = 0; i < 28; i++)
  2438. mfmdecode (&mbuf, shift);
  2439. if (get_crc16 (tmp, 8) != crc || cyl != drv->cyl || head != side || size != 2 || sector < 1 || sector > drv->num_secs || sector >= sizeof sectable) {
  2440. write_log (_T("PCDOS: track %d, corrupted sector header\n"), drv->cyl * 2 + side);
  2441. return -1;
  2442. }
  2443. sector--;
  2444. continue;
  2445. }
  2446. if (mark != 0xfb && mark != 0xfa) {
  2447. write_log (_T("PCDOS: track %d: unknown address mark %02X\n"), drv->cyl * 2 + side, mark);
  2448. continue;
  2449. }
  2450. if (sector < 0)
  2451. continue;
  2452. for (i = 0; i < 512; i++)
  2453. secbuf[i + 4] = mfmdecode (&mbuf, shift);
  2454. crc = (mfmdecode (&mbuf, shift) << 8) | mfmdecode (&mbuf, shift);
  2455. if (get_crc16 (secbuf, 3 + 1 + 512) != crc) {
  2456. write_log (_T("PCDOS: track %d, sector %d data checksum error\n"),
  2457. drv->cyl * 2 + side, sector + 1);
  2458. continue;
  2459. }
  2460. seccnt++;
  2461. if (count && sectable[sector])
  2462. break;
  2463. if (!sectable[sector]) {
  2464. secwritten++;
  2465. sectable[sector] = 1;
  2466. zfile_fseek (zf, drv->trackdata[drv->cyl * 2 + side].offs + sector * 512, SEEK_SET);
  2467. zfile_fwrite (secbuf + 4, sizeof (uae_u8), 512, zf);
  2468. //write_log (_T("PCDOS: track %d sector %d written\n"), drv->cyl * 2 + side, sector + 1);
  2469. }
  2470. sector = -1;
  2471. }
  2472. if (!count && secwritten != drv->num_secs)
  2473. write_log (_T("PCDOS: track %d, %d corrupted sectors ignored\n"),
  2474. drv->cyl * 2 + side, drv->num_secs - secwritten);
  2475. return secwritten;
  2476. }
  2477. static int drive_write_adf_amigados (drive *drv)
  2478. {
  2479. int drvsec;
  2480. int sectable[MAX_SECTORS];
  2481. if (decode_buffer (drv, drv->bigmfmbuf, drv->cyl, drv->num_secs, drv->ddhd, drv->filetype, &drvsec, sectable, 0))
  2482. return 2;
  2483. if (!drvsec)
  2484. return 2;
  2485. if (drv->filetype == ADF_EXT2) {
  2486. diskfile_update(drv->diskfile, &drv->trackdata[drv->cyl * 2 + side], drvsec * 512 * 8, TRACK_AMIGADOS);
  2487. }
  2488. trackid *tid = &drv->trackdata[drv->cyl * 2 + side];
  2489. if (drv->filetype == ADF_NORMAL_HEADER && tid->extraoffs > 0) {
  2490. zfile_fseek(drv->diskfile, tid->extraoffs, SEEK_SET);
  2491. zfile_fwrite(writesecheadbuffer, sizeof(uae_u8), drvsec * 16, drv->diskfile);
  2492. }
  2493. zfile_fseek (drv->diskfile, tid->offs, SEEK_SET);
  2494. zfile_fwrite (writebuffer, sizeof (uae_u8), drvsec * 512, drv->diskfile);
  2495. return 0;
  2496. }
  2497. /* write raw track to disk file */
  2498. static int drive_write_ext2 (uae_u16 *bigmfmbuf, struct zfile *diskfile, trackid *ti, int tracklen)
  2499. {
  2500. int len, i, offset;
  2501. offset = 0;
  2502. len = (tracklen + 7) / 8;
  2503. if (len > ti->len) {
  2504. write_log (_T("disk raw write: image file's track %d is too small (%d < %d)!\n"), ti->track, ti->len, len);
  2505. offset = (len - ti->len) / 2;
  2506. len = ti->len;
  2507. }
  2508. diskfile_update (diskfile, ti, tracklen, TRACK_RAW);
  2509. for (i = 0; i < ti->len / 2; i++) {
  2510. uae_u16 *mfm = bigmfmbuf + i + offset;
  2511. uae_u16 *mfmw = bigmfmbufw + i + offset;
  2512. uae_u8 *data = (uae_u8 *) mfm;
  2513. *mfmw = 256 * *data + *(data + 1);
  2514. }
  2515. zfile_fseek (diskfile, ti->offs, SEEK_SET);
  2516. zfile_fwrite (bigmfmbufw, 1, len, diskfile);
  2517. return 1;
  2518. }
  2519. static void drive_write_data (drive * drv);
  2520. static bool convert_adf_to_ext2 (drive *drv, int mode)
  2521. {
  2522. TCHAR name[MAX_DPATH];
  2523. bool hd = drv->ddhd == 2;
  2524. struct zfile *f;
  2525. if (drv->filetype != ADF_NORMAL)
  2526. return false;
  2527. _tcscpy (name, currprefs.floppyslots[drv - floppy].df);
  2528. if (!name[0])
  2529. return false;
  2530. if (mode == 1) {
  2531. TCHAR *p = _tcsrchr (name, '.');
  2532. if (!p)
  2533. p = name + _tcslen (name);
  2534. _tcscpy (p, _T(".extended.adf"));
  2535. if (!disk_creatediskfile (&currprefs, name, 1, hd ? DRV_35_HD : DRV_35_DD, -1, NULL, false, false, drv->diskfile))
  2536. return false;
  2537. } else if (mode == 2) {
  2538. struct zfile *tmp = zfile_fopen_load_zfile (drv->diskfile);
  2539. if (!tmp)
  2540. return false;
  2541. zfile_fclose (drv->diskfile);
  2542. drv->diskfile = NULL;
  2543. if (!disk_creatediskfile (&currprefs, name, 1, hd ? DRV_35_HD : DRV_35_DD, -1, NULL, false, false, tmp)) {
  2544. zfile_fclose (tmp);
  2545. return false;
  2546. }
  2547. zfile_fclose(tmp);
  2548. } else {
  2549. return false;
  2550. }
  2551. f = zfile_fopen (name, _T("r+b"));
  2552. if (!f)
  2553. return false;
  2554. _tcscpy (currprefs.floppyslots[drv - floppy].df, name);
  2555. _tcscpy (changed_prefs.floppyslots[drv - floppy].df, name);
  2556. zfile_fclose (drv->diskfile);
  2557. drv->diskfile = f;
  2558. drv->filetype = ADF_EXT2;
  2559. read_header_ext2 (drv->diskfile, drv->trackdata, &drv->num_tracks, &drv->ddhd);
  2560. drive_write_data (drv);
  2561. #ifdef RETROPLATFORM
  2562. rp_disk_image_change (drv - &floppy[0], name, false);
  2563. #endif
  2564. drive_fill_bigbuf (drv, 1);
  2565. return true;
  2566. }
  2567. static void drive_write_data (drive * drv)
  2568. {
  2569. int ret = -1;
  2570. int tr = drv->cyl * 2 + side;
  2571. if (drive_writeprotected (drv) || drv->trackdata[tr].type == TRACK_NONE) {
  2572. /* read original track back because we didn't really write anything */
  2573. drv->buffered_side = 2;
  2574. return;
  2575. }
  2576. if (drv->writediskfile) {
  2577. drive_write_ext2 (drv->bigmfmbuf, drv->writediskfile, &drv->writetrackdata[tr],
  2578. floppy_writemode > 0 ? dsklength2 * 8 : drv->tracklen);
  2579. }
  2580. switch (drv->filetype) {
  2581. case ADF_NORMAL:
  2582. case ADF_NORMAL_HEADER:
  2583. if (drv->ddhd > 1 && currprefs.floppyslots[drv - &floppy[0]].dfxtype != DRV_35_HD) {
  2584. // HD image in DD drive: ignore writing.
  2585. drv->buffered_side = 2;
  2586. } else {
  2587. if (drive_write_adf_amigados (drv)) {
  2588. if (currprefs.floppy_auto_ext2) {
  2589. convert_adf_to_ext2 (drv, currprefs.floppy_auto_ext2);
  2590. } else {
  2591. static int warned;
  2592. if (!warned)
  2593. notify_user (NUMSG_NEEDEXT2);
  2594. warned = 1;
  2595. }
  2596. }
  2597. }
  2598. return;
  2599. case ADF_EXT1:
  2600. break;
  2601. case ADF_EXT2:
  2602. if (!floppy_writemode)
  2603. ret = drive_write_adf_amigados (drv);
  2604. if (ret) {
  2605. write_log (_T("not an amigados track %d (error %d), writing as raw track\n"), drv->cyl * 2 + side, ret);
  2606. drive_write_ext2 (drv->bigmfmbuf, drv->diskfile, &drv->trackdata[drv->cyl * 2 + side],
  2607. floppy_writemode > 0 ? dsklength2 * 8 : drv->tracklen);
  2608. }
  2609. return;
  2610. case ADF_IPF:
  2611. break;
  2612. case ADF_SCP:
  2613. break;
  2614. case ADF_PCDOS:
  2615. ret = drive_write_pcdos (drv, drv->diskfile, 0);
  2616. if (ret < 0)
  2617. write_log (_T("not a PC formatted track %d (error %d)\n"), drv->cyl * 2 + side, ret);
  2618. break;
  2619. #ifdef FLOPPYBRIDGE
  2620. case ADF_FLOPPYBRIDGE:
  2621. if (drv->bridge) {
  2622. // Request to commit the buffer we have collected to disk - this should hardly ever be triggered
  2623. drv->tracklen = drv->bridge->commitWriteBuffer(side, drv->cyl);
  2624. drv->writepending = true;
  2625. }
  2626. break;
  2627. #endif
  2628. }
  2629. drv->tracktiming[0] = 0;
  2630. }
  2631. static void drive_eject (drive * drv)
  2632. {
  2633. #ifdef DRIVESOUND
  2634. if (isfloppysound (drv))
  2635. driveclick_insert (drv - floppy, 1);
  2636. #endif
  2637. if (drv->diskfile || drv->filetype >= 0)
  2638. statusline_add_message(STATUSTYPE_FLOPPY, _T("DF%d: -"), drv - floppy);
  2639. drive_image_free (drv);
  2640. drv->dskeject = false;
  2641. drv->dskchange = true;
  2642. drv->ddhd = 1;
  2643. drv->dskchange_time = 0;
  2644. drv->dskready = 0;
  2645. drv->dskready_up_time = 0;
  2646. drv->dskready_down_time = 0;
  2647. drv->forcedwrprot = false;
  2648. drv->crc32 = 0;
  2649. drive_settype_id (drv); /* Back to 35 DD */
  2650. if (disk_debug_logging > 0)
  2651. write_log (_T("eject drive %ld\n"), drv - &floppy[0]);
  2652. gui_disk_image_change(drv - floppy, NULL, drv->wrprot);
  2653. inprec_recorddiskchange (drv - floppy, NULL, false);
  2654. }
  2655. static void floppy_get_bootblock (uae_u8 *dst, bool ffs, bool bootable)
  2656. {
  2657. strcpy ((char*)dst, "DOS");
  2658. dst[3] = ffs ? 1 : 0;
  2659. if (bootable)
  2660. memcpy (dst, ffs ? bootblock_ffs : bootblock_ofs, ffs ? sizeof bootblock_ffs : sizeof bootblock_ofs);
  2661. }
  2662. static void floppy_get_rootblock (uae_u8 *dst, int block, const TCHAR *disk_name, bool hd)
  2663. {
  2664. dst[0+3] = 2; // primary type
  2665. dst[12+3] = 0x48; // size of hash table
  2666. dst[312] = dst[313] = dst[314] = dst[315] = (uae_u8)0xff; // bitmap valid
  2667. dst[316+2] = (block + 1) >> 8; dst[316+3] = (block + 1) & 255; // bitmap pointer
  2668. char *s = ua ((disk_name && _tcslen (disk_name) > 0) ? disk_name : _T("empty"));
  2669. dst[432] = (uae_u8)strlen (s); // name length
  2670. strcpy ((char*)dst + 433, s); // name
  2671. xfree (s);
  2672. dst[508 + 3] = 1; // secondary type
  2673. disk_date (dst + 420); // root modification date
  2674. disk_date(dst + 484); // creation date
  2675. disk_checksum (dst, dst + 20);
  2676. /* bitmap block */
  2677. memset (dst + 512 + 4, 0xff, 2 * block / 8);
  2678. if (!hd)
  2679. dst[512 + 0x72] = 0x3f;
  2680. else
  2681. dst[512 + 0xdc] = 0x3f;
  2682. disk_checksum (dst + 512, dst + 512);
  2683. }
  2684. /* type: 0=regular, 1=ext2adf, 2=regular+headers */
  2685. bool disk_creatediskfile (struct uae_prefs *p, const TCHAR *name, int type, drive_type adftype, int hd, const TCHAR *disk_name, bool ffs, bool bootable, struct zfile *copyfrom)
  2686. {
  2687. int size = 32768;
  2688. struct zfile *f;
  2689. int i, l, file_size, data_size, tracks, track_len, sectors;
  2690. uae_u8 *chunk = NULL;
  2691. int ddhd = 1;
  2692. bool ok = false;
  2693. uae_u64 pos;
  2694. if (type == 1)
  2695. tracks = 2 * 83;
  2696. else
  2697. tracks = 2 * 80;
  2698. file_size = 880 * 2 * 512;
  2699. data_size = file_size;
  2700. if (type == 2)
  2701. file_size = 880 * 2 * (512 + 16);
  2702. sectors = 11;
  2703. if (adftype == DRV_PC_525_ONLY_40 || adftype == DRV_PC_35_ONLY_80 || adftype == DRV_PC_525_40_80) {
  2704. file_size = 720 * 1024;
  2705. sectors = 9;
  2706. }
  2707. // largest needed
  2708. track_len = FLOPPY_WRITE_LEN_NTSC;
  2709. if (p->floppy_write_length > track_len && p->floppy_write_length < 2 * FLOPPY_WRITE_LEN_NTSC)
  2710. track_len = p->floppy_write_length;
  2711. if (adftype == DRV_35_HD || hd > 0) {
  2712. file_size *= 2;
  2713. track_len *= 2;
  2714. data_size *= 2;
  2715. ddhd = 2;
  2716. if (adftype == DRV_PC_525_40_80) {
  2717. file_size = 15 * 512 * 80 * 2;
  2718. }
  2719. } else if (adftype == DRV_PC_525_ONLY_40) {
  2720. file_size /= 2;
  2721. tracks /= 2;
  2722. data_size /= 2;
  2723. }
  2724. if (copyfrom) {
  2725. pos = zfile_ftell (copyfrom);
  2726. zfile_fseek (copyfrom, 0, SEEK_SET);
  2727. }
  2728. f = zfile_fopen (name, _T("wb"), 0);
  2729. chunk = xmalloc (uae_u8, size);
  2730. if (f && chunk) {
  2731. int cylsize = sectors * 2 * 512;
  2732. memset (chunk, 0, size);
  2733. if (type == 0 || type == 2) {
  2734. int dataoffset = 0;
  2735. if (type == 2) {
  2736. cylsize = sectors * 2 * (512 + 16);
  2737. dataoffset += 16;
  2738. }
  2739. for (i = 0; i < file_size; i += cylsize) {
  2740. memset(chunk, 0, cylsize);
  2741. if (adftype == DRV_35_DD || adftype == DRV_35_HD) {
  2742. if (i == 0) {
  2743. /* boot block */
  2744. floppy_get_bootblock (chunk + dataoffset, ffs, bootable);
  2745. } else if (i == file_size / 2) {
  2746. /* root block */
  2747. floppy_get_rootblock (chunk + dataoffset, data_size / 1024, disk_name, ddhd > 1);
  2748. }
  2749. }
  2750. zfile_fwrite (chunk, cylsize, 1, f);
  2751. }
  2752. ok = true;
  2753. } else {
  2754. uae_u8 root[4];
  2755. uae_u8 rawtrack[3 * 4], dostrack[3 * 4];
  2756. l = track_len;
  2757. zfile_fwrite ("UAE-1ADF", 8, 1, f);
  2758. root[0] = 0; root[1] = 0; /* flags (reserved) */
  2759. root[2] = 0; root[3] = tracks; /* number of tracks */
  2760. zfile_fwrite (root, 4, 1, f);
  2761. rawtrack[0] = 0; rawtrack[1] = 0; /* flags (reserved) */
  2762. rawtrack[2] = 0; rawtrack[3] = 1; /* track type */
  2763. rawtrack[4] = 0; rawtrack[5] = 0; rawtrack[6]=(uae_u8)(l >> 8); rawtrack[7] = (uae_u8)l;
  2764. rawtrack[8] = 0; rawtrack[9] = 0; rawtrack[10] = 0; rawtrack[11] = 0;
  2765. memcpy (dostrack, rawtrack, sizeof rawtrack);
  2766. dostrack[3] = 0;
  2767. dostrack[9] = (l * 8) >> 16; dostrack[10] = (l * 8) >> 8; dostrack[11] = (l * 8) >> 0;
  2768. bool dodos = ffs || bootable || (disk_name && _tcslen (disk_name) > 0);
  2769. for (i = 0; i < tracks; i++) {
  2770. uae_u8 tmp[3 * 4];
  2771. memcpy (tmp, rawtrack, sizeof rawtrack);
  2772. if (dodos || copyfrom)
  2773. memcpy (tmp, dostrack, sizeof dostrack);
  2774. zfile_fwrite (tmp, sizeof tmp, 1, f);
  2775. }
  2776. for (i = 0; i < tracks; i++) {
  2777. memset (chunk, 0, size);
  2778. if (copyfrom) {
  2779. zfile_fread (chunk, 11 * ddhd, 512, copyfrom);
  2780. } else {
  2781. if (dodos) {
  2782. if (i == 0)
  2783. floppy_get_bootblock (chunk, ffs, bootable);
  2784. else if (i == 80)
  2785. floppy_get_rootblock (chunk, 80 * 11 * ddhd, disk_name, adftype == DRV_35_HD);
  2786. }
  2787. }
  2788. zfile_fwrite (chunk, l, 1, f);
  2789. }
  2790. ok = true;
  2791. }
  2792. }
  2793. xfree (chunk);
  2794. zfile_fclose (f);
  2795. if (copyfrom)
  2796. zfile_fseek (copyfrom, pos, SEEK_SET);
  2797. return ok;
  2798. }
  2799. int disk_getwriteprotect (struct uae_prefs *p, const TCHAR *name, int num)
  2800. {
  2801. int needwritefile;
  2802. drive_type drvtype;
  2803. return diskfile_iswriteprotect (p, name, num, &needwritefile, &drvtype);
  2804. }
  2805. static void diskfile_readonly (const TCHAR *name, bool readonly)
  2806. {
  2807. struct mystat st;
  2808. int mode, oldmode;
  2809. if (!my_stat (name, &st)) {
  2810. write_log (_T("failed to access '%s'\n"), name);
  2811. return;
  2812. }
  2813. write_log(_T("'%s': old mode = %x\n"), name, st.mode);
  2814. oldmode = mode = st.mode;
  2815. mode &= ~FILEFLAG_WRITE;
  2816. if (!readonly)
  2817. mode |= FILEFLAG_WRITE;
  2818. if (mode != oldmode) {
  2819. if (!my_chmod (name, mode))
  2820. write_log(_T("chmod failed!\n"));
  2821. }
  2822. write_log(_T("'%s': new mode = %x\n"), name, mode);
  2823. }
  2824. static void setdskchangetime (drive *drv, int dsktime)
  2825. {
  2826. int i;
  2827. /* prevent multiple disk insertions at the same time */
  2828. if (drv->dskchange_time > 0)
  2829. return;
  2830. for (i = 0; i < MAX_FLOPPY_DRIVES; i++) {
  2831. if (&floppy[i] != drv && floppy[i].dskchange_time > 0 && floppy[i].dskchange_time + 1 >= dsktime) {
  2832. dsktime = floppy[i].dskchange_time + 1;
  2833. }
  2834. }
  2835. drv->dskchange_time = dsktime;
  2836. if (disk_debug_logging > 0)
  2837. write_log (_T("delayed insert enable %d\n"), dsktime);
  2838. }
  2839. void DISK_reinsert (int num)
  2840. {
  2841. drive_eject (&floppy[num]);
  2842. setdskchangetime (&floppy[num], 2 * 50 * 312);
  2843. }
  2844. int disk_setwriteprotect (struct uae_prefs *p, int num, const TCHAR *fname_in, bool writeprotected)
  2845. {
  2846. int needwritefile, oldprotect;
  2847. struct zfile *zf1, *zf2;
  2848. bool wrprot1, wrprot2;
  2849. int i;
  2850. TCHAR *name2;
  2851. drive_type drvtype;
  2852. TCHAR outfname[MAX_DPATH];
  2853. write_log(_T("disk_setwriteprotect %d '%s' %d\n"), num, fname_in, writeprotected);
  2854. oldprotect = diskfile_iswriteprotect (p, fname_in, num, &needwritefile, &drvtype);
  2855. DISK_validate_filename (p, fname_in, num, outfname, 1, &wrprot1, NULL, &zf1);
  2856. if (!zf1)
  2857. return 0;
  2858. write_log(_T("old = %d writeprot = %d master = %d\n"), oldprotect, wrprot1, p->floppy_read_only);
  2859. if (wrprot1 && p->floppy_read_only) {
  2860. zfile_fclose(zf1);
  2861. return 0;
  2862. }
  2863. if (zfile_iscompressed (zf1))
  2864. wrprot1 = 1;
  2865. zfile_fclose (zf1);
  2866. zf2 = getexistingwritefile(p, fname_in, num, &wrprot2);
  2867. name2 = DISK_get_saveimagepath(fname_in, -2);
  2868. if (needwritefile && zf2 == NULL)
  2869. disk_creatediskfile (p, name2, 1, drvtype, -1, NULL, false, false, NULL);
  2870. zfile_fclose (zf2);
  2871. if (writeprotected && iswritefileempty(p, num, fname_in)) {
  2872. for (i = 0; i < MAX_FLOPPY_DRIVES; i++) {
  2873. if (!_tcscmp (fname_in, floppy[i].newname))
  2874. drive_eject (&floppy[i]);
  2875. }
  2876. _wunlink (name2);
  2877. }
  2878. if (!needwritefile)
  2879. diskfile_readonly (outfname, writeprotected);
  2880. diskfile_readonly (name2, writeprotected);
  2881. floppy[num].forcedwrprot = false;
  2882. floppy[num].newnamewriteprotected = false;
  2883. return 1;
  2884. }
  2885. void disk_eject (int num)
  2886. {
  2887. set_config_changed ();
  2888. gui_filename (num, _T(""));
  2889. drive_eject (floppy + num);
  2890. *currprefs.floppyslots[num].df = *changed_prefs.floppyslots[num].df = 0;
  2891. floppy[num].newname[0] = 0;
  2892. update_drive_gui (num, true);
  2893. }
  2894. int DISK_history_add (const TCHAR *name, int idx, int type, int donotcheck)
  2895. {
  2896. int i;
  2897. if (idx >= MAX_PREVIOUS_IMAGES)
  2898. return 0;
  2899. if (name == NULL) {
  2900. if (idx < 0)
  2901. return 0;
  2902. dfxhistory[type][idx][0] = 0;
  2903. return 1;
  2904. }
  2905. if (name[0] == 0)
  2906. return 0;
  2907. #if 0
  2908. if (!donotcheck) {
  2909. if (!zfile_exists (name)) {
  2910. for (i = 0; i < MAX_PREVIOUS_IMAGES; i++) {
  2911. if (!_tcsicmp (dfxhistory[type][i], name)) {
  2912. while (i < MAX_PREVIOUS_IMAGES - 1) {
  2913. _tcscpy (dfxhistory[type][i], dfxhistory[type][i + 1]);
  2914. i++;
  2915. }
  2916. dfxhistory[type][MAX_PREVIOUS_IMAGES - 1][0] = 0;
  2917. break;
  2918. }
  2919. }
  2920. return 0;
  2921. }
  2922. }
  2923. #endif
  2924. if (idx >= 0) {
  2925. if (idx >= MAX_PREVIOUS_IMAGES)
  2926. return 0;
  2927. dfxhistory[type][idx][0] = 0;
  2928. for (i = 0; i < MAX_PREVIOUS_IMAGES; i++) {
  2929. if (!_tcsicmp (dfxhistory[type][i], name))
  2930. return 0;
  2931. }
  2932. _tcscpy (dfxhistory[type][idx], name);
  2933. return 1;
  2934. }
  2935. for (i = 0; i < MAX_PREVIOUS_IMAGES; i++) {
  2936. if (!_tcscmp (dfxhistory[type][i], name)) {
  2937. while (i < MAX_PREVIOUS_IMAGES - 1) {
  2938. _tcscpy (dfxhistory[type][i], dfxhistory[type][i + 1]);
  2939. i++;
  2940. }
  2941. dfxhistory[type][MAX_PREVIOUS_IMAGES - 1][0] = 0;
  2942. break;
  2943. }
  2944. }
  2945. for (i = MAX_PREVIOUS_IMAGES - 2; i >= 0; i--)
  2946. _tcscpy (dfxhistory[type][i + 1], dfxhistory[type][i]);
  2947. _tcscpy (dfxhistory[type][0], name);
  2948. return 1;
  2949. }
  2950. TCHAR *DISK_history_get (int idx, int type)
  2951. {
  2952. if (idx >= MAX_PREVIOUS_IMAGES)
  2953. return NULL;
  2954. return dfxhistory[type][idx];
  2955. }
  2956. static void disk_insert_2 (int num, const TCHAR *name, bool forced, bool forcedwriteprotect)
  2957. {
  2958. drive *drv = floppy + num;
  2959. if (forced) {
  2960. drive_insert (drv, &currprefs, num, name, false, forcedwriteprotect);
  2961. return;
  2962. }
  2963. if (!_tcscmp (currprefs.floppyslots[num].df, name))
  2964. return;
  2965. drv->dskeject = false;
  2966. _tcscpy(drv->newname, name);
  2967. drv->newnamewriteprotected = forcedwriteprotect;
  2968. _tcscpy (currprefs.floppyslots[num].df, name);
  2969. currprefs.floppyslots[num].forcedwriteprotect = forcedwriteprotect;
  2970. DISK_history_add (name, -1, HISTORY_FLOPPY, 0);
  2971. if (name[0] == 0) {
  2972. disk_eject (num);
  2973. } else if (!drive_empty(drv) || drv->dskchange_time > 0) {
  2974. // delay eject so that it is always called when emulation is active
  2975. drv->dskeject = true;
  2976. } else {
  2977. setdskchangetime (drv, 1 * 312);
  2978. }
  2979. }
  2980. void disk_insert (int num, const TCHAR *name, bool forcedwriteprotect)
  2981. {
  2982. set_config_changed ();
  2983. target_addtorecent (name, 0);
  2984. disk_insert_2 (num, name, 0, forcedwriteprotect);
  2985. }
  2986. void disk_insert (int num, const TCHAR *name)
  2987. {
  2988. set_config_changed ();
  2989. target_addtorecent (name, 0);
  2990. disk_insert_2 (num, name, 0, false);
  2991. }
  2992. void disk_insert_force (int num, const TCHAR *name, bool forcedwriteprotect)
  2993. {
  2994. disk_insert_2 (num, name, 1, forcedwriteprotect);
  2995. }
  2996. static void DISK_check_change (void)
  2997. {
  2998. if (currprefs.floppy_speed != changed_prefs.floppy_speed)
  2999. currprefs.floppy_speed = changed_prefs.floppy_speed;
  3000. if (currprefs.floppy_read_only != changed_prefs.floppy_read_only)
  3001. currprefs.floppy_read_only = changed_prefs.floppy_read_only;
  3002. for (int i = 0; i < MAX_FLOPPY_DRIVES; i++) {
  3003. drive *drv = floppy + i;
  3004. if (drv->dskeject) {
  3005. drive_eject(drv);
  3006. /* set dskchange_time, disk_insert() will be
  3007. * called from DISK_check_change() after 2 second delay
  3008. * this makes sure that all programs detect disk change correctly
  3009. */
  3010. setdskchangetime(drv, 2 * 50 * 312);
  3011. }
  3012. if (currprefs.floppyslots[i].dfxtype != changed_prefs.floppyslots[i].dfxtype) {
  3013. currprefs.floppyslots[i].dfxtype = changed_prefs.floppyslots[i].dfxtype;
  3014. reset_drive (i);
  3015. #ifdef RETROPLATFORM
  3016. rp_floppy_device_enable (i, currprefs.floppyslots[i].dfxtype >= 0);
  3017. #endif
  3018. }
  3019. }
  3020. if (config_changed) {
  3021. for (int i = 0; i < MAX_SPARE_DRIVES; i++) {
  3022. _tcscpy(currprefs.dfxlist[i], changed_prefs.dfxlist[i]);
  3023. }
  3024. }
  3025. }
  3026. void DISK_vsync (void)
  3027. {
  3028. DISK_check_change ();
  3029. for (int i = 0; i < MAX_FLOPPY_DRIVES; i++) {
  3030. drive *drv = floppy + i;
  3031. if (drv->selected_delay > 0) {
  3032. drv->selected_delay--;
  3033. }
  3034. if (drv->dskchange_time == 0 && _tcscmp (currprefs.floppyslots[i].df, changed_prefs.floppyslots[i].df))
  3035. disk_insert (i, changed_prefs.floppyslots[i].df, changed_prefs.floppyslots[i].forcedwriteprotect);
  3036. }
  3037. }
  3038. int disk_empty (int num)
  3039. {
  3040. return drive_empty (floppy + num);
  3041. }
  3042. static TCHAR *tobin (uae_u8 v)
  3043. {
  3044. static TCHAR buf[9];
  3045. for (int i = 7; i >= 0; i--)
  3046. buf[7 - i] = v & (1 << i) ? '1' : '0';
  3047. return buf;
  3048. }
  3049. static void fetch_DISK_select(uae_u8 data)
  3050. {
  3051. if (currprefs.cs_compatible == CP_VELVET) {
  3052. selected = (data >> 3) & 3;
  3053. } else {
  3054. selected = (data >> 3) & 15;
  3055. }
  3056. side = 1 - ((data >> 2) & 1);
  3057. direction = (data >> 1) & 1;
  3058. }
  3059. void DISK_select_set (uae_u8 data)
  3060. {
  3061. prev_data = data;
  3062. prev_step = data & 1;
  3063. fetch_DISK_select (data);
  3064. }
  3065. void DISK_select (uae_u8 data)
  3066. {
  3067. bool velvet = currprefs.cs_compatible == CP_VELVET;
  3068. int step_pulse, prev_selected, dr;
  3069. prev_selected = selected;
  3070. fetch_DISK_select (data);
  3071. step_pulse = data & 1;
  3072. if (disk_debug_logging > 2) {
  3073. if (velvet) {
  3074. write_log (_T("%08X %02X->%02X %s drvmask=%x"), M68K_GETPC, prev_data, data, tobin(data), selected ^ 3);
  3075. } else {
  3076. write_log (_T("%08X %02X->%02X %s drvmask=%x"), M68K_GETPC, prev_data, data, tobin(data), selected ^ 15);
  3077. }
  3078. }
  3079. #ifdef AMAX
  3080. if (amax_enabled) {
  3081. for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
  3082. drive *drv = floppy + dr;
  3083. if (drv->amax)
  3084. amax_disk_select (data, prev_data, dr);
  3085. }
  3086. }
  3087. #endif
  3088. if (!velvet) {
  3089. if ((prev_data & 0x80) != (data & 0x80)) {
  3090. for (dr = 0; dr < 4; dr++) {
  3091. if (floppy[dr].indexhackmode > 1 && !((selected | disabled) & (1 << dr))) {
  3092. floppy[dr].indexhack = 1;
  3093. if (disk_debug_logging > 2)
  3094. write_log (_T(" indexhack!"));
  3095. }
  3096. }
  3097. }
  3098. }
  3099. if (disk_debug_logging > 2) {
  3100. if (velvet) {
  3101. write_log (_T(" %d%d"), (selected & 1) ? 0 : 1, (selected & 2) ? 0 : 1);
  3102. if ((prev_data & 0x08) != (data & 0x08))
  3103. write_log (_T(" dsksel0>%d"), (data & 0x08) ? 0 : 1);
  3104. if ((prev_data & 0x10) != (data & 0x10))
  3105. write_log (_T(" dsksel1>%d"), (data & 0x10) ? 0 : 1);
  3106. if ((prev_data & 0x20) != (data & 0x20))
  3107. write_log (_T(" dskmotor0>%d"), (data & 0x20) ? 0 : 1);
  3108. if ((prev_data & 0x40) != (data & 0x40))
  3109. write_log (_T(" dskmotor1>%d"), (data & 0x40) ? 0 : 1);
  3110. if ((prev_data & 0x02) != (data & 0x02))
  3111. write_log (_T(" direct>%d"), (data & 0x02) ? 1 : 0);
  3112. if ((prev_data & 0x04) != (data & 0x04))
  3113. write_log (_T(" side>%d"), (data & 0x04) ? 1 : 0);
  3114. } else {
  3115. write_log (_T(" %d%d%d%d"), (selected & 1) ? 0 : 1, (selected & 2) ? 0 : 1, (selected & 4) ? 0 : 1, (selected & 8) ? 0 : 1);
  3116. for (int i = 0; i < 4; i++) {
  3117. int im = 1 << i;
  3118. if ((selected & im) && !(prev_selected & im))
  3119. write_log(_T(" sel%d>0"), i);
  3120. if (!(selected & im) && (prev_selected & im))
  3121. write_log(_T(" sel%d>1"), i);
  3122. }
  3123. if ((prev_data & 0x80) != (data & 0x80))
  3124. write_log (_T(" dskmotor>%d"), (data & 0x80) ? 1 : 0);
  3125. if ((prev_data & 0x02) != (data & 0x02))
  3126. write_log (_T(" direct>%d"), (data & 0x02) ? 1 : 0);
  3127. if ((prev_data & 0x04) != (data & 0x04))
  3128. write_log (_T(" side>%d"), (data & 0x04) ? 1 : 0);
  3129. }
  3130. }
  3131. // step goes high and drive was selected when step pulse changes: step
  3132. if (prev_step != step_pulse) {
  3133. if (disk_debug_logging > 2)
  3134. write_log (_T(" dskstep %d "), step_pulse);
  3135. prev_step = step_pulse;
  3136. if (prev_step && !savestate_state) {
  3137. for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
  3138. if (!((prev_selected | disabled) & (1 << dr))) {
  3139. drive_step (floppy + dr, direction);
  3140. if (floppy[dr].indexhackmode > 1 && (data & 0x80))
  3141. floppy[dr].indexhack = 1;
  3142. }
  3143. }
  3144. }
  3145. }
  3146. if (!savestate_state) {
  3147. if (velvet) {
  3148. for (dr = 0; dr < 2; dr++) {
  3149. drive *drv = floppy + dr;
  3150. int motormask = 0x20 << dr;
  3151. int selectmask = 0x08 << dr;
  3152. if (!(selected & (1 << dr)) && !(disabled & (1 << dr))) {
  3153. if (!(prev_data & motormask) && (data & motormask)) {
  3154. drive_motor(drv, 1);
  3155. } else if ((prev_data & motormask) && !(data & motormask)) {
  3156. drive_motor(drv, 0);
  3157. }
  3158. }
  3159. }
  3160. } else {
  3161. for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
  3162. drive *drv = floppy + dr;
  3163. /* motor on/off workings tested with small assembler code on real Amiga 1200. */
  3164. /* motor/id flipflop is set only when drive select goes from high to low */
  3165. if (!((selected | disabled) & (1 << dr)) && (prev_selected & (1 << dr)) ) {
  3166. drv->drive_id_scnt++;
  3167. drv->drive_id_scnt &= 31;
  3168. #ifdef FLOPPYBRIDGE
  3169. if (drv->bridge) {
  3170. drive_settype_id(drv); // allow for dynamic DD/HD switching
  3171. }
  3172. #endif
  3173. drv->idbit = (drv->drive_id & (1L << (31 - drv->drive_id_scnt))) ? 1 : 0;
  3174. if (!(disabled & (1 << dr))) {
  3175. if ((prev_data & 0x80) == 0 || (data & 0x80) == 0) {
  3176. /* motor off: if motor bit = 0 in prevdata or data -> turn motor on */
  3177. drive_motor (drv, 0);
  3178. } else if (prev_data & 0x80) {
  3179. /* motor on: if motor bit = 1 in prevdata only (motor flag state in data has no effect)
  3180. -> turn motor off */
  3181. drive_motor (drv, 1);
  3182. }
  3183. }
  3184. if (!currprefs.cs_df0idhw && dr == 0)
  3185. drv->idbit = 0;
  3186. #ifdef DEBUG_DRIVE_ID
  3187. write_log (_T("DISK_status: sel %d id %s (%08X) [0x%08x, bit #%02d: %d]\n"),
  3188. dr, drive_id_name(drv), drv->drive_id, drv->drive_id << drv->drive_id_scnt, 31 - drv->drive_id_scnt, drv->idbit);
  3189. #endif
  3190. }
  3191. }
  3192. }
  3193. }
  3194. for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
  3195. // selected
  3196. if (!(selected & (1 << dr)) && floppy[dr].selected_delay < 0) {
  3197. floppy[dr].selected_delay = 2;
  3198. }
  3199. // not selected
  3200. if ((selected & (1 << dr))) {
  3201. floppy[dr].selected_delay = -1;
  3202. }
  3203. // external drives usually (always?) light activity led when selected. Internal only when motor is running.
  3204. bool selected_led = !(selected & (1 << dr)) && floppy[dr].selected_delay == 0 && dr > 0;
  3205. floppy[dr].state = selected_led || !floppy[dr].motoroff;
  3206. update_drive_gui (dr, false);
  3207. }
  3208. prev_data = data;
  3209. if (disk_debug_logging > 2)
  3210. write_log (_T("\n"));
  3211. }
  3212. uae_u8 DISK_status_ciab(uae_u8 st)
  3213. {
  3214. if (currprefs.cs_compatible == CP_VELVET) {
  3215. st |= 0x80;
  3216. for (int dr = 0; dr < 2; dr++) {
  3217. drive *drv = floppy + dr;
  3218. if (!(((selected >> 3) | disabled) & (1 << dr))) {
  3219. if (drive_writeprotected (drv))
  3220. st &= ~0x80;
  3221. }
  3222. }
  3223. if (disk_debug_logging > 2) {
  3224. write_log(_T("DISK_STATUS_CIAB %08x %02x\n"), M68K_GETPC, st);
  3225. }
  3226. }
  3227. return st;
  3228. }
  3229. uae_u8 DISK_status_ciaa(void)
  3230. {
  3231. uae_u8 st = 0x3c;
  3232. if (currprefs.cs_compatible == CP_VELVET) {
  3233. for (int dr = 0; dr < 2; dr++) {
  3234. drive *drv = floppy + dr;
  3235. if (!(((selected >> 3) | disabled) & (1 << dr))) {
  3236. if (drive_diskchange(drv))
  3237. st &= ~0x20;
  3238. if (drive_track0 (drv))
  3239. st &= ~0x10;
  3240. }
  3241. }
  3242. if (disk_debug_logging > 2) {
  3243. write_log(_T("DISK_STATUS_CIAA %08x %02x\n"), M68K_GETPC, st);
  3244. }
  3245. return st;
  3246. }
  3247. for (int dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
  3248. drive *drv = floppy + dr;
  3249. if (drv->amax) {
  3250. if (amax_active())
  3251. st = amax_disk_status (st);
  3252. } else if (!((selected | disabled) & (1 << dr))) {
  3253. if (drive_running (drv)) {
  3254. if (drv->catweasel) {
  3255. #ifdef CATWEASEL
  3256. if (catweasel_diskready (drv->catweasel))
  3257. st &= ~0x20;
  3258. #endif
  3259. } else {
  3260. if (drive_diskready(drv) && !drv->indexhack && currprefs.floppyslots[dr].dfxtype != DRV_35_DD_ESCOM)
  3261. st &= ~0x20;
  3262. }
  3263. } else {
  3264. if (currprefs.cs_df0idhw || dr > 0) {
  3265. /* report drive ID */
  3266. if (drv->idbit && currprefs.floppyslots[dr].dfxtype != DRV_35_DD_ESCOM)
  3267. st &= ~0x20;
  3268. } else {
  3269. /* non-ID internal drive: mirror real dskready */
  3270. if (drive_diskready(drv))
  3271. st &= ~0x20;
  3272. }
  3273. /* dskrdy needs some cycles after switching the motor off.. (Pro Tennis Tour) */
  3274. if (!currprefs.cs_df0idhw && dr == 0 && drv->motordelay)
  3275. st &= ~0x20;
  3276. }
  3277. if (drive_track0 (drv))
  3278. st &= ~0x10;
  3279. if (drive_writeprotected (drv))
  3280. st &= ~8;
  3281. if (drv->catweasel) {
  3282. #ifdef CATWEASEL
  3283. if (catweasel_disk_changed (drv->catweasel))
  3284. st &= ~4;
  3285. #endif
  3286. } else if (drive_diskchange(drv) && currprefs.floppyslots[dr].dfxtype != DRV_525_SD) {
  3287. st &= ~4;
  3288. }
  3289. } else if (!((selected | disabled) & (1 << dr))) {
  3290. if (drv->idbit)
  3291. st &= ~0x20;
  3292. }
  3293. }
  3294. return st;
  3295. }
  3296. static bool unformatted (drive *drv)
  3297. {
  3298. #ifdef FLOPPYBRIDGE
  3299. if (drv->bridge) {
  3300. bool v = drv->bridge->isDiskInDrive();
  3301. return v == false;
  3302. }
  3303. #endif
  3304. int tr = drv->cyl * 2 + side;
  3305. if (tr >= drv->num_tracks)
  3306. return true;
  3307. if (drv->filetype == ADF_EXT2 && drv->trackdata[tr].bitlen == 0 && drv->trackdata[tr].type != TRACK_AMIGADOS)
  3308. return true;
  3309. if (drv->trackdata[tr].type == TRACK_NONE)
  3310. return true;
  3311. return false;
  3312. }
  3313. static int nextbit(drive *drv)
  3314. {
  3315. return drv && !drv->fourms && !(adkcon & 0x0100) ? 2 : 1;
  3316. }
  3317. /* get one bit from bit stream */
  3318. static uae_u32 getonebit(drive *drv, uae_u16 *mfmbuf, int mfmpos, int *inc)
  3319. {
  3320. uae_u16 *buf;
  3321. if (inc)
  3322. *inc = 1;
  3323. #ifdef FLOPPYBRIDGE
  3324. if (drv && drv->bridge) {
  3325. drv->tracklen = drv->bridge->maxMFMBitPosition(); // this shouldnt happen
  3326. return drv->bridge->getMFMBit(mfmpos) ? 1 : 0;
  3327. }
  3328. #endif
  3329. if (inc && nextbit(drv) == 2) {
  3330. // 2us -> 4us
  3331. int b1 = getonebit(NULL, mfmbuf, mfmpos, NULL);
  3332. int b2 = getonebit(NULL, mfmbuf, (mfmpos + 1) % drv->tracklen, NULL);
  3333. if (!b1 && b2) {
  3334. *inc = 3;
  3335. return 1;
  3336. }
  3337. if (b1 && !b2) {
  3338. *inc = 2;
  3339. return 1;
  3340. }
  3341. if (b1 && b2) {
  3342. *inc = 3;
  3343. return 1;
  3344. }
  3345. *inc = 2;
  3346. return 0;
  3347. }
  3348. buf = &mfmbuf[mfmpos >> 4];
  3349. return (buf[0] & (1 << (15 - (mfmpos & 15)))) ? 1 : 0;
  3350. }
  3351. void dumpdisk (const TCHAR *name)
  3352. {
  3353. int i, j, k;
  3354. uae_u16 w;
  3355. for (i = 0; i < MAX_FLOPPY_DRIVES; i++) {
  3356. drive *drv = &floppy[i];
  3357. if (!(disabled & (1 << i))) {
  3358. console_out_f (_T("%s: drive %d motor %s cylinder %2d sel %s %s mfmpos %d/%d\n"),
  3359. name, i, drv->motoroff ? _T("off") : _T(" on"), drv->cyl, (selected & (1 << i)) ? _T("no") : _T("yes"),
  3360. drive_writeprotected (drv) ? _T("ro") : _T("rw"), drv->mfmpos, drv->tracklen);
  3361. if (drv->motoroff == 0) {
  3362. w = 0;
  3363. for (j = -4; j < 13; j++) {
  3364. for (k = 0; k < 16; k++) {
  3365. int pos = drv->mfmpos + j * 16 + k;
  3366. if (pos < 0)
  3367. pos += drv->tracklen;
  3368. w <<= 1;
  3369. w |= getonebit(NULL, drv->bigmfmbuf, pos, NULL);
  3370. }
  3371. console_out_f(_T("%04X%c"), w, j == -1 ? '|' : ' ');
  3372. }
  3373. console_out (_T("\n"));
  3374. }
  3375. }
  3376. }
  3377. console_out_f (_T("side %d dma %d off %d word %04X pt %08X len %04X bytr %04X adk %04X sync %04X\n"),
  3378. side, dskdmaen, bitoffset, word, dskpt, dsklen, dskbytr_val, adkcon, dsksync);
  3379. }
  3380. static void disk_dmafinished (void)
  3381. {
  3382. INTREQ (0x8000 | 0x0002);
  3383. if (floppy_writemode > 0)
  3384. floppy_writemode = 0;
  3385. dskdmaen = DSKDMA_OFF;
  3386. dsklength = 0;
  3387. dsklen = 0;
  3388. if (disk_debug_logging > 0) {
  3389. int dr;
  3390. write_log (_T("disk dma finished %08X MFMpos="), dskpt);
  3391. for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++)
  3392. write_log (_T("%d%s"), floppy[dr].mfmpos, dr < MAX_FLOPPY_DRIVES - 1 ? _T(",") : _T(""));
  3393. write_log (_T("\n"));
  3394. }
  3395. }
  3396. static void fetchnextrevolution (drive *drv)
  3397. {
  3398. if (drv->revolution_check)
  3399. return;
  3400. drv->trackspeed = get_floppy_speed_from_image(drv);
  3401. #if REVOLUTION_DEBUG
  3402. if (1 || drv->mfmpos != 0) {
  3403. write_log (_T("REVOLUTION: DMA=%d %d %d/%d %d %d\n"), dskdmaen, drv->trackspeed, drv->mfmpos, drv->tracklen, drv->indexoffset, drv->floppybitcounter);
  3404. }
  3405. #endif
  3406. drv->revolution_check = 2;
  3407. if (!drv->multi_revolution)
  3408. return;
  3409. switch (drv->filetype)
  3410. {
  3411. case ADF_IPF:
  3412. #ifdef CAPS
  3413. caps_loadrevolution (drv->bigmfmbuf, drv->tracktiming, drv - floppy, drv->cyl * 2 + side, &drv->tracklen, &drv->lastrev, drv->track_access_done);
  3414. #endif
  3415. break;
  3416. case ADF_SCP:
  3417. #ifdef SCP
  3418. scp_loadrevolution (drv->bigmfmbuf, drv - floppy, drv->tracktiming, &drv->tracklen);
  3419. #endif
  3420. break;
  3421. case ADF_FDI:
  3422. #ifdef FDI2RAW
  3423. fdi2raw_loadrevolution(drv->fdi, drv->bigmfmbuf, drv->tracktiming, drv->cyl * 2 + side, &drv->tracklen, 1);
  3424. #endif
  3425. break;
  3426. #ifdef FLOPPYBRIDGE
  3427. case ADF_FLOPPYBRIDGE:
  3428. drv->bridge->mfmSwitchBuffer(side);
  3429. drv->trackspeed = get_floppy_speed_from_image(drv);
  3430. break;
  3431. #endif
  3432. }
  3433. }
  3434. static void do_disk_index (void)
  3435. {
  3436. #if REVOLUTION_DEBUG
  3437. write_log(_T("INDEX %d\n"), indexdecay);
  3438. #endif
  3439. if (!indexdecay) {
  3440. indexdecay = 2;
  3441. cia_diskindex ();
  3442. }
  3443. }
  3444. void DISK_handler (uae_u32 data)
  3445. {
  3446. int flag = data & 255;
  3447. int disk_sync_cycle = data >> 8;
  3448. int hpos = current_hpos ();
  3449. event2_remevent (ev2_disk);
  3450. DISK_update (disk_sync_cycle);
  3451. if (!dskdmaen) {
  3452. if (flag & (DISK_REVOLUTION << 0))
  3453. fetchnextrevolution (&floppy[0]);
  3454. if (flag & (DISK_REVOLUTION << 1))
  3455. fetchnextrevolution (&floppy[1]);
  3456. if (flag & (DISK_REVOLUTION << 2))
  3457. fetchnextrevolution (&floppy[2]);
  3458. if (flag & (DISK_REVOLUTION << 3))
  3459. fetchnextrevolution (&floppy[3]);
  3460. }
  3461. if (flag & DISK_WORDSYNC)
  3462. INTREQ (0x8000 | 0x1000);
  3463. if (flag & DISK_INDEXSYNC)
  3464. do_disk_index ();
  3465. }
  3466. static void disk_doupdate_write(int floppybits, int trackspeed)
  3467. {
  3468. int dr;
  3469. int drives[4];
  3470. for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
  3471. drive *drv2 = &floppy[dr];
  3472. drives[dr] = 0;
  3473. if (drv2->motoroff)
  3474. continue;
  3475. if ((selected | disabled) & (1 << dr))
  3476. continue;
  3477. drives[dr] = 1;
  3478. }
  3479. while (floppybits >= trackspeed) {
  3480. for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
  3481. if (drives[dr]) {
  3482. drive *drv2 = &floppy[dr];
  3483. drv2->mfmpos++;
  3484. drv2->mfmpos %= drv2->tracklen;
  3485. if (drive_at_index(drv2, drv2->mfmpos)) {
  3486. do_disk_index();
  3487. }
  3488. }
  3489. }
  3490. if (dmaen(DMA_DISK) && dmaen(DMA_MASTER) && dskdmaen == DSKDMA_WRITE && dsklength > 0 && fifo_filled) {
  3491. bitoffset++;
  3492. bitoffset &= 15;
  3493. if (!bitoffset) {
  3494. // fast disk modes, fill the fifo instantly
  3495. if (currprefs.floppy_speed > 100 && !fifo_inuse[0] && !fifo_inuse[1] && !fifo_inuse[2]) {
  3496. while (!fifo_inuse[2]) {
  3497. uae_u16 w = chipmem_wget_indirect (dskpt);
  3498. DSKDAT (w);
  3499. dskpt += 2;
  3500. }
  3501. }
  3502. if (disk_fifostatus () >= 0) {
  3503. #ifdef FLOPPYBRIDGE
  3504. bool wasBridge = false;
  3505. #endif
  3506. uae_u16 w = DSKDATR ();
  3507. for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
  3508. drive *drv2 = &floppy[dr];
  3509. if (drives[dr]) {
  3510. drv2->bigmfmbuf[drv2->mfmpos >> 4] = w;
  3511. drv2->bigmfmbuf[(drv2->mfmpos >> 4) + 1] = 0x5555;
  3512. drv2->writtento = 1;
  3513. #ifdef FLOPPYBRIDGE
  3514. if (drv2->bridge) {
  3515. wasBridge = true;
  3516. drv2->bridge->writeShortToBuffer(side, drv2->cyl, w, drv2->mfmpos);
  3517. }
  3518. #endif
  3519. }
  3520. #ifdef AMAX
  3521. if (amax_enabled)
  3522. amax_diskwrite (w);
  3523. #endif
  3524. }
  3525. dsklength--;
  3526. if (dsklength <= 0) {
  3527. // delay write DMA finished state until bridge has all pending data written
  3528. if (!wasBridge) {
  3529. disk_dmafinished();
  3530. }
  3531. for (int dr = 0; dr < MAX_FLOPPY_DRIVES ; dr++) {
  3532. drive *drv = &floppy[dr];
  3533. drv->writtento = 0;
  3534. if (drv->motoroff)
  3535. continue;
  3536. if ((selected | disabled) & (1 << dr))
  3537. continue;
  3538. drive_write_data(drv);
  3539. }
  3540. }
  3541. }
  3542. }
  3543. }
  3544. floppybits -= trackspeed;
  3545. }
  3546. }
  3547. static void update_jitter (void)
  3548. {
  3549. if (currprefs.floppy_random_bits_max > 0 && currprefs.floppy_random_bits_max >= currprefs.floppy_random_bits_min)
  3550. disk_jitter = ((uaerand () >> 4) % (currprefs.floppy_random_bits_max - currprefs.floppy_random_bits_min + 1)) + currprefs.floppy_random_bits_min;
  3551. else
  3552. disk_jitter = 0;
  3553. }
  3554. static void updatetrackspeed (drive *drv, int mfmpos)
  3555. {
  3556. if (dskdmaen < DSKDMA_WRITE) {
  3557. #ifdef FLOPPYBRIDGE
  3558. if (drv->bridge) {
  3559. drv->trackspeed = NORMAL_FLOPPY_SPEED * drv->bridge->getMFMSpeed(mfmpos) / 1000;
  3560. return;
  3561. }
  3562. #endif
  3563. int t = drv->tracktiming[mfmpos / 8];
  3564. int ts = get_floppy_speed_from_image(drv) * t / 1000;
  3565. if (ts < 700 || ts > 3000) {
  3566. static int warned;
  3567. warned++;
  3568. if (warned < 50)
  3569. write_log (_T("corrupted trackspeed value %d %d (%d/%d)\n"), t, ts, mfmpos, drv->tracklen);
  3570. } else {
  3571. drv->trackspeed = ts;
  3572. }
  3573. }
  3574. }
  3575. static void disk_doupdate_predict (int startcycle)
  3576. {
  3577. int finaleventcycle = maxhpos << 8;
  3578. int finaleventflag = 0;
  3579. bool noselected = true;
  3580. for (int dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
  3581. drive *drv = &floppy[dr];
  3582. if (drv->motoroff)
  3583. continue;
  3584. if (!drv->trackspeed)
  3585. continue;
  3586. if ((selected | disabled) & (1 << dr))
  3587. continue;
  3588. bool isempty = drive_empty(drv);
  3589. bool isunformatted = unformatted(drv);
  3590. int mfmpos = drv->mfmpos;
  3591. if (drv->tracktiming[0])
  3592. updatetrackspeed (drv, mfmpos);
  3593. int diskevent_flag = 0;
  3594. uae_u32 tword = word;
  3595. noselected = false;
  3596. int countcycle = startcycle;
  3597. while (countcycle < (maxhpos << 8)) {
  3598. int inc = nextbit(drv);
  3599. if (drv->tracktiming[0])
  3600. updatetrackspeed (drv, mfmpos);
  3601. countcycle += drv->trackspeed;
  3602. if (dskdmaen != DSKDMA_WRITE || (dskdmaen == DSKDMA_WRITE && !dma_enable)) {
  3603. tword <<= 1;
  3604. if (!isempty) {
  3605. if (isunformatted)
  3606. tword |= (uaerand () & 0x1000) ? 1 : 0;
  3607. else
  3608. tword |= getonebit(drv, drv->bigmfmbuf, mfmpos, &inc);
  3609. }
  3610. if (dskdmaen != DSKDMA_READ && (tword & 0xffff) == dsksync && dsksync != 0)
  3611. diskevent_flag |= DISK_WORDSYNC;
  3612. }
  3613. mfmpos += inc;
  3614. mfmpos %= drv->tracklen;
  3615. if (!dskdmaen) {
  3616. if (mfmpos == 0)
  3617. diskevent_flag |= DISK_REVOLUTION << (drv - floppy);
  3618. if (drive_at_index(drv, mfmpos))
  3619. diskevent_flag |= DISK_INDEXSYNC;
  3620. }
  3621. if (dskdmaen != DSKDMA_WRITE && mfmpos == drv->skipoffset) {
  3622. int skipcnt = disk_jitter;
  3623. while (skipcnt-- > 0) {
  3624. mfmpos++;
  3625. mfmpos %= drv->tracklen;
  3626. if (!dskdmaen) {
  3627. if (mfmpos == 0)
  3628. diskevent_flag |= DISK_REVOLUTION << (drv - floppy);
  3629. if (drive_at_index(drv, mfmpos))
  3630. diskevent_flag |= DISK_INDEXSYNC;
  3631. }
  3632. }
  3633. }
  3634. if (diskevent_flag)
  3635. break;
  3636. }
  3637. if (drv->tracktiming[0])
  3638. updatetrackspeed (drv, drv->mfmpos);
  3639. if (diskevent_flag && countcycle < finaleventcycle) {
  3640. finaleventcycle = countcycle;
  3641. finaleventflag = diskevent_flag;
  3642. }
  3643. }
  3644. if (finaleventflag && (finaleventcycle >> 8) < maxhpos) {
  3645. event2_newevent (ev2_disk, (finaleventcycle - startcycle) >> 8, ((finaleventcycle >> 8) << 8) | finaleventflag);
  3646. }
  3647. }
  3648. int disk_fifostatus (void)
  3649. {
  3650. if (fifo_inuse[0] && fifo_inuse[1] && fifo_inuse[2])
  3651. return 1;
  3652. if (!fifo_inuse[0] && !fifo_inuse[1] && !fifo_inuse[2])
  3653. return -1;
  3654. return 0;
  3655. }
  3656. static int doreaddma (void)
  3657. {
  3658. if (dmaen(DMA_DISK) && dmaen(DMA_MASTER) && bitoffset == 15 && dma_enable && dskdmaen == DSKDMA_READ && dsklength >= 0) {
  3659. if (dsklength > 0) {
  3660. // DSKLEN == 1: finish without DMA transfer.
  3661. if (dsklength == 1 && dsklength2 == 1) {
  3662. disk_dmafinished ();
  3663. return 0;
  3664. }
  3665. // fast disk modes, just flush the fifo
  3666. if (currprefs.floppy_speed > 100 && fifo_inuse[0] && fifo_inuse[1] && fifo_inuse[2]) {
  3667. while (fifo_inuse[0]) {
  3668. uae_u16 w = DSKDATR ();
  3669. chipmem_wput_indirect (dskpt, w);
  3670. dskpt += 2;
  3671. }
  3672. }
  3673. if (disk_fifostatus () > 0) {
  3674. return -1;
  3675. } else {
  3676. DSKDAT (word);
  3677. dsklength--;
  3678. #if 0
  3679. if (dsklength < 1 && (adkcon & 0x200))
  3680. activate_debugger();
  3681. #endif
  3682. }
  3683. }
  3684. return 1;
  3685. }
  3686. return 0;
  3687. }
  3688. static void wordsync_detected(bool startup)
  3689. {
  3690. dsksync_cycles = get_cycles() + WORDSYNC_TIME * CYCLE_UNIT;
  3691. if (dskdmaen != DSKDMA_OFF) {
  3692. if (disk_debug_logging && dma_enable == 0) {
  3693. int pos = -1;
  3694. for (int i = 0; i < MAX_FLOPPY_DRIVES; i++) {
  3695. drive *drv = &floppy[i];
  3696. if (!(disabled & (1 << i)) && !drv->motoroff) {
  3697. pos = drv->mfmpos;
  3698. break;
  3699. }
  3700. }
  3701. write_log(_T("Sync match %04x mfmpos %d enable %d wordsync %d\n"), dsksync, pos, dma_enable, (adkcon & 0x0400) != 0);
  3702. if (disk_debug_logging > 1)
  3703. dumpdisk(_T("SYNC"));
  3704. }
  3705. if (!startup)
  3706. dma_enable = 1;
  3707. INTREQ(0x8000 | 0x1000);
  3708. }
  3709. if (adkcon & 0x0400) { // WORDSYNC
  3710. bitoffset = 15;
  3711. }
  3712. }
  3713. static void disk_doupdate_read_reallynothing(int floppybits, bool state)
  3714. {
  3715. // Only because there is at least one demo that checks wrong bit
  3716. // and hangs unless DSKSYNC bit it set with zero DSKSYNC value...
  3717. if (INTREQR() & 0x1000)
  3718. return;
  3719. while (floppybits >= get_floppy_speed()) {
  3720. bool skipbit = false;
  3721. word <<= 1;
  3722. word |= (state ? 1 : 0);
  3723. // MSBSYNC
  3724. if (adkcon & 0x200) {
  3725. if ((word & 0x0001) == 0 && bitoffset == 0) {
  3726. word = 0;
  3727. skipbit = true;
  3728. }
  3729. if ((word & 0x0001) == 0 && bitoffset == 8) {
  3730. word >>= 1;
  3731. skipbit = true;
  3732. }
  3733. }
  3734. if (!skipbit && (bitoffset & 7) == 7) {
  3735. dskbytr_val = word & 0xff;
  3736. dskbytr_val |= 0x8000;
  3737. }
  3738. if (!(adkcon & 0x200) && word == dsksync) {
  3739. INTREQ(0x8000 | 0x1000);
  3740. }
  3741. bitoffset++;
  3742. bitoffset &= 15;
  3743. floppybits -= get_floppy_speed();
  3744. }
  3745. }
  3746. static void disk_doupdate_read_nothing(int floppybits)
  3747. {
  3748. while (floppybits >= get_floppy_speed()) {
  3749. bool skipbit = false;
  3750. word <<= 1;
  3751. word |= (uaerand() & 0x1000) ? 1 : 0;
  3752. doreaddma();
  3753. // MSBSYNC
  3754. if (adkcon & 0x200) {
  3755. if ((word & 0x0001) == 0 && bitoffset == 0) {
  3756. word = 0;
  3757. skipbit = true;
  3758. }
  3759. if ((word & 0x0001) == 0 && bitoffset == 8) {
  3760. word >>= 1;
  3761. skipbit = true;
  3762. }
  3763. }
  3764. if (!skipbit && (bitoffset & 7) == 7) {
  3765. dskbytr_val = word & 0xff;
  3766. dskbytr_val |= 0x8000;
  3767. }
  3768. if (!(adkcon & 0x200) && word == dsksync) {
  3769. wordsync_detected(false);
  3770. }
  3771. bitoffset++;
  3772. bitoffset &= 15;
  3773. floppybits -= get_floppy_speed();
  3774. }
  3775. }
  3776. static void disk_doupdate_read (drive * drv, int floppybits)
  3777. {
  3778. /*
  3779. uae_u16 *mfmbuf = drv->bigmfmbuf;
  3780. dsksync = 0x4444;
  3781. adkcon |= 0x400;
  3782. drv->mfmpos = 0;
  3783. memset (mfmbuf, 0, 1000);
  3784. cycles = 0x1000000;
  3785. // 4444 4444 4444 aaaa aaaaa 4444 4444 4444
  3786. // 4444 aaaa aaaa 4444
  3787. mfmbuf[0] = 0x4444;
  3788. mfmbuf[1] = 0x4444;
  3789. mfmbuf[2] = 0x4444;
  3790. mfmbuf[3] = 0xaaaa;
  3791. mfmbuf[4] = 0xaaaa;
  3792. mfmbuf[5] = 0x4444;
  3793. mfmbuf[6] = 0x4444;
  3794. mfmbuf[7] = 0x4444;
  3795. */
  3796. bool isempty = drive_empty(drv);
  3797. bool isunformatted = unformatted(drv);
  3798. while (floppybits >= drv->trackspeed) {
  3799. bool skipbit = false;
  3800. int inc = nextbit(drv);
  3801. if (drv->tracktiming[0])
  3802. updatetrackspeed (drv, drv->mfmpos);
  3803. word <<= 1;
  3804. if (!isempty) {
  3805. if (isunformatted)
  3806. word |= (uaerand () & 0x1000) ? 1 : 0;
  3807. else
  3808. word |= getonebit(drv, drv->bigmfmbuf, drv->mfmpos, &inc);
  3809. }
  3810. //write_log (_T("%08X bo=%d so=%d mfmpos=%d dma=%d\n"), (word & 0xffffff), bitoffset, syncoffset, drv->mfmpos, dma_enable);
  3811. if (doreaddma () < 0) {
  3812. word >>= 1;
  3813. return;
  3814. }
  3815. drv->mfmpos += inc;
  3816. drv->mfmpos %= drv->tracklen;
  3817. if (drive_at_index(drv, drv->mfmpos)) {
  3818. if (disk_debug_logging > 2 && drv->indexhack)
  3819. write_log (_T("indexhack cleared\n"));
  3820. drv->indexhack = 0;
  3821. do_disk_index ();
  3822. }
  3823. if (drv->mfmpos == 0) {
  3824. fetchnextrevolution (drv);
  3825. if (drv->tracktiming[0])
  3826. updatetrackspeed (drv, drv->mfmpos);
  3827. }
  3828. if (drv->mfmpos == drv->skipoffset) {
  3829. int skipcnt = disk_jitter;
  3830. while (skipcnt-- > 0) {
  3831. drv->mfmpos += nextbit(drv);
  3832. drv->mfmpos %= drv->tracklen;
  3833. if (drive_at_index(drv, drv->mfmpos)) {
  3834. if (disk_debug_logging > 2 && drv->indexhack)
  3835. write_log (_T("indexhack cleared\n"));
  3836. drv->indexhack = 0;
  3837. do_disk_index ();
  3838. }
  3839. if (drv->mfmpos == 0) {
  3840. fetchnextrevolution (drv);
  3841. if (drv->tracktiming[0])
  3842. updatetrackspeed (drv, drv->mfmpos);
  3843. }
  3844. }
  3845. }
  3846. // MSBSYNC
  3847. if (adkcon & 0x200) {
  3848. if ((word & 0x0001) == 0 && bitoffset == 0) {
  3849. word = 0;
  3850. skipbit = true;
  3851. }
  3852. if ((word & 0x0001) == 0 && bitoffset == 8) {
  3853. word >>= 1;
  3854. skipbit = true;
  3855. }
  3856. }
  3857. if (!skipbit && (bitoffset & 7) == 7) {
  3858. dskbytr_val = word & 0xff;
  3859. dskbytr_val |= 0x8000;
  3860. }
  3861. // WORDSYNC
  3862. if (!(adkcon & 0x200) && word == dsksync) {
  3863. wordsync_detected(false);
  3864. }
  3865. if (!skipbit) {
  3866. bitoffset++;
  3867. bitoffset &= 15;
  3868. }
  3869. floppybits -= drv->trackspeed;
  3870. }
  3871. }
  3872. static void disk_dma_debugmsg (void)
  3873. {
  3874. write_log (_T("LEN=%04X (%d) SYNC=%04X PT=%08X ADKCON=%04X INTREQ=%04X PC=%08X\n"),
  3875. dsklength, dsklength, (adkcon & 0x400) ? dsksync : 0xffff, dskpt, adkcon, intreq, M68K_GETPC);
  3876. }
  3877. /* this is very unoptimized. DSKBYTR is used very rarely, so it should not matter. */
  3878. uae_u16 DSKBYTR (int hpos)
  3879. {
  3880. uae_u16 v;
  3881. DISK_update (hpos);
  3882. v = dskbytr_val;
  3883. dskbytr_val &= ~0x8000;
  3884. if (word == dsksync && cycles_in_range (dsksync_cycles)) {
  3885. v |= 0x1000;
  3886. if (disk_debug_logging > 1) {
  3887. dumpdisk(_T("DSKBYTR SYNC"));
  3888. }
  3889. }
  3890. if (dskdmaen != DSKDMA_OFF && dmaen(DMA_DISK) && dmaen(DMA_MASTER))
  3891. v |= 0x4000;
  3892. if (dsklen & 0x4000)
  3893. v |= 0x2000;
  3894. if (disk_debug_logging > 2)
  3895. write_log (_T("DSKBYTR=%04X hpos=%d\n"), v, hpos);
  3896. for (int dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
  3897. drive *drv = &floppy[dr];
  3898. if (drv->motoroff)
  3899. continue;
  3900. if (!((selected | disabled) & (1 << dr))) {
  3901. drv->lastdataacesstrack = drv->cyl * 2 + side;
  3902. #if REVOLUTION_DEBUG
  3903. if (!drv->track_access_done)
  3904. write_log(_T("DSKBYTR\n"));
  3905. #endif
  3906. drv->track_access_done = true;
  3907. if (disk_debug_mode & DISK_DEBUG_PIO) {
  3908. if (disk_debug_track < 0 || disk_debug_track == 2 * drv->cyl + side) {
  3909. disk_dma_debugmsg ();
  3910. write_log (_T("DSKBYTR=%04X\n"), v);
  3911. activate_debugger ();
  3912. break;
  3913. }
  3914. }
  3915. }
  3916. }
  3917. return v;
  3918. }
  3919. static void DISK_start (void)
  3920. {
  3921. int dr;
  3922. if (disk_debug_logging > 1) {
  3923. dumpdisk(_T("DSKLEN"));
  3924. }
  3925. for (int i = 0; i < 3; i++)
  3926. fifo_inuse[i] = false;
  3927. fifo_filled = 0;
  3928. for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
  3929. drive *drv = &floppy[dr];
  3930. if (!((selected | disabled) & (1 << dr))) {
  3931. int tr = drv->cyl * 2 + side;
  3932. trackid *ti = drv->trackdata + tr;
  3933. if (drv->dskchange_time == -1) {
  3934. drv->dskchange_time = -2;
  3935. write_log(_T("Accessing state restored non-existing disk '%s'!\n"), drv->newname);
  3936. if (gui_ask_disk(dr, drv->newname)) {
  3937. if (drive_insert(drv, &currprefs, dr, drv->newname, false, false)) {
  3938. write_log(_T("Replacement disk '%s' inserted.\n"), drv->newname);
  3939. drv->dskready_up_time = 0;
  3940. drv->dskchange_time = 0;
  3941. }
  3942. }
  3943. }
  3944. if (dskdmaen == DSKDMA_WRITE) {
  3945. word = 0;
  3946. drv->tracklen = floppy_writemode > 0 ? FLOPPY_WRITE_MAXLEN : FLOPPY_WRITE_LEN * drv->ddhd * 8 * 2;
  3947. drv->trackspeed = get_floppy_speed ();
  3948. drv->skipoffset = -1;
  3949. updatemfmpos (drv);
  3950. }
  3951. /* Ugh. A nasty hack. Assume ADF_EXT1 tracks are always read
  3952. from the start. */
  3953. if (ti->type == TRACK_RAW1) {
  3954. drv->mfmpos = 0;
  3955. bitoffset = 0;
  3956. word = 0;
  3957. }
  3958. #ifdef CATWEASEL
  3959. if (drv->catweasel) {
  3960. word = 0;
  3961. drive_fill_bigbuf (drv, 1);
  3962. }
  3963. #endif
  3964. #ifdef FLOPPYBRIDGE
  3965. if (drv->bridge && dskdmaen != DSKDMA_WRITE) {
  3966. word = 0;
  3967. drive_fill_bigbuf(drv, 1);
  3968. }
  3969. #endif
  3970. }
  3971. drv->floppybitcounter = 0;
  3972. }
  3973. dma_enable = (adkcon & 0x400) ? 0 : 1;
  3974. if (word == dsksync)
  3975. wordsync_detected(true);
  3976. }
  3977. static int linecounter;
  3978. void DISK_hsync (void)
  3979. {
  3980. int dr;
  3981. for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
  3982. drive *drv = &floppy[dr];
  3983. if (drv->steplimit)
  3984. drv->steplimit--;
  3985. if (drv->revolution_check)
  3986. drv->revolution_check--;
  3987. if (drv->dskready_down_time > 0)
  3988. drv->dskready_down_time--;
  3989. /* emulate drive motor turn on time */
  3990. if (drv->dskready_up_time > 0 && !drive_empty (drv)) {
  3991. drv->dskready_up_time--;
  3992. if (drv->dskready_up_time == 0 && !drv->motoroff)
  3993. drv->dskready = true;
  3994. }
  3995. /* delay until new disk image is inserted */
  3996. if (drv->dskchange_time > 0) {
  3997. drv->dskchange_time--;
  3998. if (drv->dskchange_time == 0) {
  3999. drive_insert (drv, &currprefs, dr, drv->newname, false, drv->newnamewriteprotected);
  4000. if (disk_debug_logging > 0)
  4001. write_log (_T("delayed insert, drive %d, image '%s'\n"), dr, drv->newname);
  4002. update_drive_gui (dr, false);
  4003. }
  4004. }
  4005. #ifdef FLOPPYBRIDGE
  4006. if (drv->bridge && drv->writepending) {
  4007. // With bridge we wait for the disk to commit the data before fireing the DMA
  4008. if (drv->bridge->isWriteComplete()) {
  4009. disk_dmafinished();
  4010. drv->writepending = false;
  4011. }
  4012. }
  4013. #endif
  4014. }
  4015. if (indexdecay)
  4016. indexdecay--;
  4017. if (linecounter) {
  4018. linecounter--;
  4019. if (! linecounter)
  4020. disk_dmafinished ();
  4021. return;
  4022. }
  4023. DISK_update (maxhpos);
  4024. // show insert disk in df0: when booting
  4025. if (initial_disk_statusline) {
  4026. initial_disk_statusline = false;
  4027. update_disk_statusline(0);
  4028. }
  4029. }
  4030. void DISK_update (int tohpos)
  4031. {
  4032. int dr;
  4033. int cycles;
  4034. if (disk_hpos < 0) {
  4035. disk_hpos = - disk_hpos;
  4036. return;
  4037. }
  4038. cycles = (tohpos << 8) - disk_hpos;
  4039. #if 0
  4040. if (tohpos == 228)
  4041. write_log (_T("x"));
  4042. if (tohpos != maxhpos || cycles / 256 != maxhpos)
  4043. write_log (_T("%d %d %d\n"), tohpos, cycles / 256, disk_hpos / 256);
  4044. #endif
  4045. if (cycles <= 0)
  4046. return;
  4047. disk_hpos += cycles;
  4048. if (disk_hpos >= (maxhpos << 8))
  4049. disk_hpos %= 1 << 8;
  4050. for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
  4051. drive *drv = &floppy[dr];
  4052. if (drv->motoroff || !drv->tracklen || !drv->trackspeed) {
  4053. continue;
  4054. }
  4055. drv->floppybitcounter += cycles;
  4056. if ((selected | disabled) & (1 << dr)) {
  4057. drv->mfmpos += drv->floppybitcounter / drv->trackspeed;
  4058. drv->mfmpos %= drv->tracklen;
  4059. drv->floppybitcounter %= drv->trackspeed;
  4060. continue;
  4061. }
  4062. if (drv->diskfile) {
  4063. drive_fill_bigbuf(drv, 0);
  4064. }
  4065. #ifdef FLOPPYBRIDGE
  4066. if (drv->bridge) {
  4067. drive_fill_bigbuf(drv, 0);
  4068. }
  4069. #endif
  4070. drv->mfmpos %= drv->tracklen;
  4071. }
  4072. int didaccess = 0;
  4073. bool done_jitter = false;
  4074. for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
  4075. drive *drv = &floppy[dr];
  4076. if (drv->motoroff || !drv->trackspeed)
  4077. continue;
  4078. if ((selected | disabled) & (1 << dr))
  4079. continue;
  4080. if (!done_jitter) {
  4081. update_jitter();
  4082. done_jitter = true;
  4083. }
  4084. /* write dma and wordsync enabled: read until wordsync match found */
  4085. if (dskdmaen == DSKDMA_WRITE && dma_enable) {
  4086. disk_doupdate_write(drv->floppybitcounter, drv->trackspeed);
  4087. } else {
  4088. disk_doupdate_read(drv, drv->floppybitcounter);
  4089. }
  4090. drv->floppybitcounter %= drv->trackspeed;
  4091. didaccess = 1;
  4092. }
  4093. /* no floppy selected but dma active */
  4094. if (!didaccess) {
  4095. if (dskdmaen == DSKDMA_READ) {
  4096. disk_doupdate_read_nothing(cycles);
  4097. } else if (dskdmaen == DSKDMA_WRITE) {
  4098. disk_doupdate_write(cycles, get_floppy_speed());
  4099. } else {
  4100. //disk_doupdate_read_reallynothing(cycles, true);
  4101. }
  4102. }
  4103. /* instantly finish dma if dsklen==0 and wordsync detected */
  4104. if (dskdmaen != DSKDMA_OFF && dma_enable && dsklength2 == 0 && dsklength == 0)
  4105. disk_dmafinished ();
  4106. if (!done_jitter) {
  4107. update_jitter();
  4108. done_jitter = true;
  4109. }
  4110. disk_doupdate_predict (disk_hpos);
  4111. }
  4112. void DSKLEN (uae_u16 v, int hpos)
  4113. {
  4114. int dr;
  4115. int prevlen = dsklen;
  4116. int prevdatalen = dsklength;
  4117. int noselected = 0;
  4118. int motormask;
  4119. DISK_update (hpos);
  4120. dsklen = v;
  4121. dsklength2 = dsklength = dsklen & 0x3fff;
  4122. if ((v & 0x8000) && (prevlen & 0x8000)) {
  4123. if (dskdmaen == DSKDMA_READ && !(v & 0x4000)) {
  4124. // update only currently active DMA length, don't change DMA state
  4125. write_log(_T("warning: Disk read DMA length rewrite %d -> %d. (%04x) PC=%08x\n"), prevlen & 0x3fff, v & 0x3fff, v, M68K_GETPC);
  4126. return;
  4127. }
  4128. dskdmaen = DSKDMA_READ;
  4129. DISK_start ();
  4130. }
  4131. if (!(v & 0x8000)) {
  4132. if (dskdmaen != DSKDMA_OFF) {
  4133. /* Megalomania and Knightmare does this */
  4134. if (disk_debug_logging > 0 && dskdmaen == DSKDMA_READ)
  4135. write_log (_T("warning: Disk read DMA aborted, %d words left PC=%x\n"), prevdatalen, M68K_GETPC);
  4136. if (dskdmaen == DSKDMA_WRITE) {
  4137. write_log (_T("warning: Disk write DMA aborted, %d words left PC=%x\n"), prevdatalen, M68K_GETPC);
  4138. // did program write something that needs to be stored to file?
  4139. for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
  4140. drive *drv2 = &floppy[dr];
  4141. if (!drv2->writtento)
  4142. continue;
  4143. drive_write_data (drv2);
  4144. }
  4145. }
  4146. dskdmaen = DSKDMA_OFF;
  4147. }
  4148. }
  4149. if (dskdmaen == DSKDMA_OFF)
  4150. return;
  4151. if (dsklength == 0 && dma_enable) {
  4152. disk_dmafinished ();
  4153. return;
  4154. }
  4155. if ((v & 0x4000) && (prevlen & 0x4000)) {
  4156. if (dsklength == 0)
  4157. return;
  4158. if (dsklength == 1) {
  4159. disk_dmafinished ();
  4160. return;
  4161. }
  4162. if (dskdmaen == DSKDMA_WRITE) {
  4163. write_log(_T("warning: Disk write DMA length rewrite %d -> %d\n"), prevlen & 0x3fff, v & 0x3fff);
  4164. return;
  4165. }
  4166. dskdmaen = DSKDMA_WRITE;
  4167. DISK_start ();
  4168. }
  4169. for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
  4170. drive *drv = &floppy[dr];
  4171. if (drv->motoroff)
  4172. continue;
  4173. if (selected & (1 << dr))
  4174. continue;
  4175. if (dskdmaen == DSKDMA_READ) {
  4176. drv->lastdataacesstrack = drv->cyl * 2 + side;
  4177. drv->track_access_done = true;
  4178. #if REVOLUTION_DEBUG
  4179. write_log(_T("DMA\n"));
  4180. #endif
  4181. }
  4182. }
  4183. if (((disk_debug_mode & DISK_DEBUG_DMA_READ) && dskdmaen == DSKDMA_READ) ||
  4184. ((disk_debug_mode & DISK_DEBUG_DMA_WRITE) && dskdmaen == DSKDMA_WRITE))
  4185. {
  4186. for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
  4187. drive *drv = &floppy[dr];
  4188. if (drv->motoroff)
  4189. continue;
  4190. if (!(selected & (1 << dr))) {
  4191. if (disk_debug_track < 0 || disk_debug_track == 2 * drv->cyl + side) {
  4192. disk_dma_debugmsg ();
  4193. activate_debugger ();
  4194. break;
  4195. }
  4196. }
  4197. }
  4198. }
  4199. motormask = 0;
  4200. for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
  4201. drive *drv = &floppy[dr];
  4202. drv->writtento = 0;
  4203. if (drv->motoroff)
  4204. continue;
  4205. motormask |= 1 << dr;
  4206. if ((selected & (1 << dr)) == 0)
  4207. break;
  4208. }
  4209. if (dr == 4) {
  4210. if (!amax_enabled) {
  4211. write_log (_T("disk %s DMA started, drvmask=%x motormask=%x PC=%08x\n"),
  4212. dskdmaen == DSKDMA_WRITE ? _T("write") : _T("read"), selected ^ 15, motormask, M68K_GETPC);
  4213. }
  4214. noselected = 1;
  4215. } else {
  4216. if (disk_debug_logging > 0) {
  4217. write_log (_T("disk %s DMA started, drvmask=%x track %d mfmpos %d dmaen=%d PC=%08X\n"),
  4218. dskdmaen == DSKDMA_WRITE ? _T("write") : _T("read"), selected ^ 15,
  4219. floppy[dr].cyl * 2 + side, floppy[dr].mfmpos, dma_enable, M68K_GETPC);
  4220. disk_dma_debugmsg ();
  4221. }
  4222. }
  4223. for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++)
  4224. update_drive_gui (dr, false);
  4225. /* Try to make floppy access from Kickstart faster. */
  4226. if (dskdmaen != DSKDMA_READ && dskdmaen != DSKDMA_WRITE)
  4227. return;
  4228. for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
  4229. drive *drv = &floppy[dr];
  4230. if (selected & (1 << dr))
  4231. continue;
  4232. #ifdef FLOPPYBRIDGE
  4233. if (drv->bridge) {
  4234. if (dskdmaen == DSKDMA_WRITE) {
  4235. // In write mode we allow a special version of 'turbo' to happen. We only complete the DMA response when we have actually written to disk
  4236. if (drv->bridge->canTurboWrite()) continue;
  4237. }
  4238. break;
  4239. }
  4240. #endif
  4241. if (drv->filetype != ADF_NORMAL && drv->filetype != ADF_KICK && drv->filetype != ADF_SKICK && drv->filetype != ADF_NORMAL_HEADER)
  4242. break;
  4243. }
  4244. if (dr < MAX_FLOPPY_DRIVES) /* no turbo mode if any selected drive has non-standard ADF */
  4245. return;
  4246. {
  4247. int done = 0;
  4248. for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
  4249. drive *drv = &floppy[dr];
  4250. bool floppysupported = (drv->ddhd < 2) || (drv->ddhd > 1 && currprefs.floppyslots[dr].dfxtype == DRV_35_HD) || (drv->bridge);
  4251. int pos, i;
  4252. if (drv->motoroff)
  4253. continue;
  4254. if (!drv->useturbo && currprefs.floppy_speed > 0 && !drv->bridge)
  4255. continue;
  4256. if (selected & (1 << dr))
  4257. continue;
  4258. pos = drv->mfmpos & ~15;
  4259. drive_fill_bigbuf (drv, 0);
  4260. if (dskdmaen == DSKDMA_READ) { /* TURBO read */
  4261. if ((adkcon & 0x400) && floppysupported) {
  4262. for (i = 0; i < drv->tracklen; i += 16) {
  4263. pos += 16;
  4264. pos %= drv->tracklen;
  4265. if (drv->bigmfmbuf[pos >> 4] == dsksync) {
  4266. /* must skip first disk sync marker */
  4267. pos += 16;
  4268. pos %= drv->tracklen;
  4269. break;
  4270. }
  4271. }
  4272. if (i >= drv->tracklen)
  4273. return;
  4274. }
  4275. // read nothing if not supported and MFMSYNC is on.
  4276. if ((floppysupported) || (!floppysupported && !(adkcon & 0x400))) {
  4277. while (dsklength-- > 0) {
  4278. chipmem_wput_indirect (dskpt, floppysupported ? drv->bigmfmbuf[pos >> 4] : uaerand());
  4279. dskpt += 2;
  4280. pos += 16;
  4281. pos %= drv->tracklen;
  4282. }
  4283. } else {
  4284. pos += uaerand();
  4285. pos %= drv->tracklen;
  4286. }
  4287. drv->mfmpos = pos;
  4288. if (floppysupported)
  4289. INTREQ (0x8000 | 0x1000);
  4290. done = 2;
  4291. } else if (dskdmaen == DSKDMA_WRITE) { /* TURBO write */
  4292. #ifdef FLOPPYBRIDGE
  4293. if (drv->bridge) {
  4294. if (!drv->bridge->isWritePending()) {
  4295. for (i = 0; i < dsklength; i++) {
  4296. uae_u16 w = chipmem_wget_indirect(dskpt + i * 2);
  4297. drv->bigmfmbuf[pos >> 4] = w;
  4298. drv->bridge->writeShortToBuffer(side, drv->cyl, w, drv->mfmpos);
  4299. pos += 16;
  4300. pos %= drv->tracklen;
  4301. }
  4302. drv->mfmpos = pos;
  4303. if (drv->bridge->isReadyToWrite()) {
  4304. drv->bridge->commitWriteBuffer(side, drv->cyl);
  4305. }
  4306. } else
  4307. if (drv->bridge->isWriteComplete()) {
  4308. done = 2;
  4309. drv->writepending = false;
  4310. }
  4311. } else
  4312. #endif
  4313. if (floppysupported) {
  4314. for (i = 0; i < dsklength; i++) {
  4315. uae_u16 w = chipmem_wget_indirect (dskpt + i * 2);
  4316. drv->bigmfmbuf[pos >> 4] = w;
  4317. #ifdef AMAX
  4318. if (amax_enabled)
  4319. amax_diskwrite (w);
  4320. #endif
  4321. pos += 16;
  4322. pos %= drv->tracklen;
  4323. }
  4324. drv->mfmpos = pos;
  4325. drive_write_data (drv);
  4326. done = 2;
  4327. } else {
  4328. pos += uaerand();
  4329. pos %= drv->tracklen;
  4330. drv->mfmpos = pos;
  4331. done = 2;
  4332. }
  4333. }
  4334. }
  4335. if (!done && noselected && amax_enabled) {
  4336. int bits = -1;
  4337. while (dsklength-- > 0) {
  4338. if (dskdmaen == DSKDMA_WRITE) {
  4339. uae_u16 w = chipmem_wget_indirect(dskpt);
  4340. #ifdef AMAX
  4341. amax_diskwrite(w);
  4342. if (w) {
  4343. for (int i = 0; i < 16; i++) {
  4344. if (w & (1 << i))
  4345. bits++;
  4346. }
  4347. }
  4348. #endif
  4349. } else {
  4350. chipmem_wput_indirect(dskpt, 0);
  4351. }
  4352. dskpt += 2;
  4353. }
  4354. if (bits == 0) {
  4355. // AMAX speedup hack
  4356. done = 1;
  4357. } else {
  4358. INTREQ(0x8000 | 0x1000);
  4359. done = 2;
  4360. }
  4361. }
  4362. if (done) {
  4363. linecounter = done;
  4364. dskdmaen = DSKDMA_OFF;
  4365. return;
  4366. }
  4367. }
  4368. }
  4369. void DISK_update_adkcon (int hpos, uae_u16 v)
  4370. {
  4371. uae_u16 vold = adkcon;
  4372. uae_u16 vnew = adkcon;
  4373. if (v & 0x8000)
  4374. vnew |= v & 0x7FFF;
  4375. else
  4376. vnew &= ~v;
  4377. if ((vnew & 0x400) && !(vold & 0x400))
  4378. bitoffset = 0;
  4379. }
  4380. void DSKSYNC (int hpos, uae_u16 v)
  4381. {
  4382. if (v == dsksync)
  4383. return;
  4384. DISK_update (hpos);
  4385. dsksync = v;
  4386. }
  4387. STATIC_INLINE bool iswrite (void)
  4388. {
  4389. return dskdmaen == DSKDMA_WRITE;
  4390. }
  4391. void DSKDAT (uae_u16 v)
  4392. {
  4393. if (fifo_inuse[2]) {
  4394. write_log (_T("DSKDAT: FIFO overflow!\n"));
  4395. return;
  4396. }
  4397. fifo_inuse[2] = fifo_inuse[1];
  4398. fifo[2] = fifo[1];
  4399. fifo_inuse[1] = fifo_inuse[0];
  4400. fifo[1] = fifo[0];
  4401. fifo_inuse[0] = iswrite () ? 2 : 1;
  4402. fifo[0] = v;
  4403. fifo_filled = 1;
  4404. }
  4405. uae_u16 DSKDATR (void)
  4406. {
  4407. int i;
  4408. uae_u16 v = 0;
  4409. for (i = 2; i >= 0; i--) {
  4410. if (fifo_inuse[i]) {
  4411. fifo_inuse[i] = 0;
  4412. v = fifo[i];
  4413. break;
  4414. }
  4415. }
  4416. if (i < 0) {
  4417. write_log (_T("DSKDATR: FIFO underflow!\n"));
  4418. } else if (dskdmaen > 0 && dskdmaen < 3 && dsklength <= 0 && disk_fifostatus () < 0) {
  4419. disk_dmafinished ();
  4420. }
  4421. return v;
  4422. }
  4423. uae_u16 disk_dmal (void)
  4424. {
  4425. uae_u16 dmal = 0;
  4426. if (dskdmaen) {
  4427. if (dskdmaen == 3) {
  4428. dmal = (1 + 2) * (fifo_inuse[0] ? 1 : 0) + (4 + 8) * (fifo_inuse[1] ? 1 : 0) + (16 + 32) * (fifo_inuse[2] ? 1 : 0);
  4429. dmal ^= 63;
  4430. if (dsklength == 2)
  4431. dmal &= ~(16 + 32);
  4432. if (dsklength == 1)
  4433. dmal &= ~(16 + 32 + 4 + 8);
  4434. } else {
  4435. dmal = 16 * (fifo_inuse[0] ? 1 : 0) + 4 * (fifo_inuse[1] ? 1 : 0) + 1 * (fifo_inuse[2] ? 1 : 0);
  4436. }
  4437. }
  4438. return dmal;
  4439. }
  4440. uaecptr disk_getpt (void)
  4441. {
  4442. uaecptr pt = dskpt;
  4443. dskpt += 2;
  4444. return pt;
  4445. }
  4446. void DSKPTH (uae_u16 v)
  4447. {
  4448. dskpt = (dskpt & 0xffff) | ((uae_u32) v << 16);
  4449. }
  4450. void DSKPTL (uae_u16 v)
  4451. {
  4452. dskpt = (dskpt & ~0xffff) | (v);
  4453. }
  4454. void DISK_free (void)
  4455. {
  4456. for (int dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
  4457. drive *drv = &floppy[dr];
  4458. drive_image_free (drv);
  4459. }
  4460. }
  4461. static void floppybridge_read_track(drive *drv)
  4462. {
  4463. int timeout;
  4464. FloppyDiskBridge *b = drv->bridge;
  4465. if (!b) {
  4466. return;
  4467. }
  4468. for (;;) {
  4469. if (!b->isDiskInDrive()) {
  4470. break;
  4471. }
  4472. b->setMotorStatus(false, true);
  4473. b->gotoCylinder(drv->cyl, false);
  4474. timeout = 5000 / 10;
  4475. while (b->getCurrentCylinderNumber() != drv->cyl) {
  4476. if (timeout-- < 0) {
  4477. break;
  4478. }
  4479. sleep_millis(10);
  4480. }
  4481. while (!b->isReady() && b->isDiskInDrive()) {
  4482. if (timeout-- < 0) {
  4483. break;
  4484. }
  4485. sleep_millis(10);
  4486. }
  4487. if (!b->isDiskInDrive() || timeout < 0) {
  4488. break;
  4489. }
  4490. int totalbits = FLOPPY_WRITE_MAXLEN * 8 * drv->ddhd;
  4491. int pos = 0, bitcnt = 0;
  4492. uae_u16 *p = drv->bigmfmbuf;
  4493. uae_u16 w = 0;
  4494. timeout = 5000 / 10;
  4495. drv->tracklen = totalbits;
  4496. while (totalbits > 0 && timeout > 0) {
  4497. while (b->isMFMDataAvailable() && totalbits > 0) {
  4498. uae_u8 bit = b->getMFMBit(pos);
  4499. int max = b->maxMFMBitPosition();
  4500. pos++;
  4501. if (pos >= max) {
  4502. pos = 0;
  4503. }
  4504. w <<= 1;
  4505. w |= bit;
  4506. bitcnt++;
  4507. if ((bitcnt & 15) == 0) {
  4508. *p++ = w;
  4509. }
  4510. totalbits--;
  4511. }
  4512. sleep_millis(10);
  4513. timeout--;
  4514. }
  4515. break;
  4516. }
  4517. b->gotoCylinder(0, false);
  4518. b->setMotorStatus(false, side);
  4519. }
  4520. static void floppybridge_update_config(void)
  4521. {
  4522. if (floppybridge_available && floppybridge_config) {
  4523. FloppyBridgeAPI::importProfilesFromString(floppybridge_config);
  4524. xfree(floppybridge_config);
  4525. floppybridge_config = NULL;
  4526. }
  4527. }
  4528. void floppybridge_set_config(const char *c)
  4529. {
  4530. xfree(floppybridge_config);
  4531. floppybridge_config = strdup(c);
  4532. floppybridge_update_config();
  4533. }
  4534. void floppybridge_reload_profiles(void)
  4535. {
  4536. if (floppybridge_available) {
  4537. floppybridge_update_config();
  4538. bridgeprofiles.clear();
  4539. FloppyBridgeAPI::getAllProfiles(bridgeprofiles);
  4540. }
  4541. }
  4542. static void floppybridge_init3(void)
  4543. {
  4544. static bool checked;
  4545. if (checked) {
  4546. return;
  4547. }
  4548. checked = true;
  4549. if (FloppyBridgeAPI::isAvailable()) {
  4550. floppybridge_available = true;
  4551. FloppyBridgeAPI::getDriverList(bridgedriverinfo);
  4552. floppybridge_reload_profiles();
  4553. }
  4554. }
  4555. bool floppybridge_has(void)
  4556. {
  4557. floppybridge_init3();
  4558. return floppybridge_available;
  4559. }
  4560. static void floppybridge_init2(struct uae_prefs *p)
  4561. {
  4562. floppybridge_init3();
  4563. bool needbridge = false;
  4564. for (int i = 0; i < MAX_FLOPPY_DRIVES; i++) {
  4565. int type = p->floppyslots[i].dfxtype;
  4566. if (type >= DRV_FB) {
  4567. needbridge = true;
  4568. }
  4569. }
  4570. if (!needbridge) {
  4571. for (int dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
  4572. floppy[dr].bridge = NULL;
  4573. if (bridges[dr]) {
  4574. delete bridges[dr];
  4575. bridges[dr] = NULL;
  4576. }
  4577. }
  4578. return;
  4579. }
  4580. for (int dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
  4581. int type = p->floppyslots[dr].dfxtype;
  4582. if (type == DRV_FB) {
  4583. if (floppy[dr].bridge == NULL || type != bridge_type[dr]) {
  4584. if (bridges[dr]) {
  4585. bridges[dr]->shutdown();
  4586. delete bridges[dr];
  4587. bridges[dr] = NULL;
  4588. }
  4589. floppy[dr].bridge = NULL;
  4590. bridge_driver[dr] = NULL;
  4591. bridge_type[dr] = type;
  4592. FloppyBridgeAPI *bridge = NULL;
  4593. int id = _tstol(p->floppyslots[dr].dfxsubtypeid);
  4594. const TCHAR *name = _tcschr(p->floppyslots[dr].dfxsubtypeid, ':');
  4595. if (name) {
  4596. name++;
  4597. for (int i = 0; i < bridgeprofiles.size(); i++) {
  4598. FloppyBridgeAPI::FloppyBridgeProfileInformation fbpi = bridgeprofiles.at(i);
  4599. if (fbpi.profileID == id && !_tcscmp(fbpi.name, name)) {
  4600. bridge = FloppyBridgeAPI::createDriverFromProfileID(id);
  4601. break;
  4602. }
  4603. }
  4604. if (!bridge) {
  4605. for (int i = 0; i < bridgeprofiles.size(); i++) {
  4606. FloppyBridgeAPI::FloppyBridgeProfileInformation fbpi = bridgeprofiles.at(i);
  4607. if (!_tcscmp(fbpi.name, name)) {
  4608. bridge = FloppyBridgeAPI::createDriverFromProfileID(fbpi.profileID);
  4609. break;
  4610. }
  4611. }
  4612. }
  4613. }
  4614. if (!bridge) {
  4615. bridge = FloppyBridgeAPI::createDriverFromProfileID(id);
  4616. }
  4617. if (bridge) {
  4618. if (!bridge->initialise()) {
  4619. const char *errorMessage = bridge->getLastErrorMessage();
  4620. const char *name = bridge->getDriverInfo()->name;
  4621. TCHAR *terrorMessage = au(errorMessage);
  4622. TCHAR *tname = au(name);
  4623. TCHAR formattedMessage[512];
  4624. _stprintf(formattedMessage, _T("Floppy Disk Bridge Error\n\nUnable to replace DF%i: using %s\n\n%s.\n\nDrive DF%i: will be disabled and ignored."), dr, tname, terrorMessage, dr);
  4625. gui_message(formattedMessage);
  4626. xfree(tname);
  4627. xfree(terrorMessage);
  4628. } else {
  4629. bridge_driver[dr] = bridge->getDriverInfo();
  4630. }
  4631. }
  4632. bridges[dr] = bridge;
  4633. floppy[dr].bridge = bridge;
  4634. }
  4635. } else {
  4636. if (bridges[dr]) {
  4637. bridges[dr]->shutdown();
  4638. delete bridges[dr];
  4639. bridges[dr] = NULL;
  4640. }
  4641. floppy[dr].bridge = NULL;
  4642. bridge_driver[dr] = NULL;
  4643. }
  4644. }
  4645. }
  4646. void floppybridge_init(struct uae_prefs *p)
  4647. {
  4648. floppybridge_init2(p);
  4649. floppybridge_reload_profiles();
  4650. }
  4651. void floppybridge_modified(int num)
  4652. {
  4653. if (num < 0) {
  4654. for (int i = 0; i < MAX_FLOPPY_DRIVES; i++) {
  4655. bridge_type[i] = -1;
  4656. }
  4657. } else {
  4658. bridge_type[num] = -1;
  4659. }
  4660. }
  4661. void DISK_init (void)
  4662. {
  4663. for (int dr = MAX_FLOPPY_DRIVES - 1; dr >= 0; dr--) {
  4664. drive *drv = &floppy[dr];
  4665. /* reset all drive types to 3.5 DD */
  4666. drive_settype_id (drv);
  4667. if (!drive_insert (drv, &currprefs, dr, currprefs.floppyslots[dr].df, false, currprefs.floppyslots[dr].forcedwriteprotect))
  4668. disk_eject (dr);
  4669. }
  4670. floppybridge_init2(&currprefs);
  4671. if (disk_empty (0))
  4672. write_log (_T("No disk in drive 0.\n"));
  4673. amax_init ();
  4674. }
  4675. void DISK_reset (void)
  4676. {
  4677. if (savestate_state)
  4678. return;
  4679. //floppy[0].catweasel = &cwc.drives[0];
  4680. disk_hpos = 0;
  4681. dskdmaen = 0;
  4682. disabled = 0;
  4683. memset(&disk_info_data, 0, sizeof disk_info_data);
  4684. for (int dr = MAX_FLOPPY_DRIVES - 1; dr >= 0; dr--) {
  4685. reset_drive (dr);
  4686. }
  4687. initial_disk_statusline = true;
  4688. setamax ();
  4689. }
  4690. static void load_track (int num, int cyl, int side, int *sectable)
  4691. {
  4692. int oldcyl, oldside, drvsec;
  4693. drive *drv = &floppy[num];
  4694. oldcyl = drv->cyl;
  4695. oldside = side;
  4696. drv->cyl = cyl;
  4697. side = 0;
  4698. drv->buffered_cyl = -1;
  4699. drive_fill_bigbuf (drv, -1);
  4700. decode_buffer (drv, drv->bigmfmbuf, drv->cyl, 11, drv->ddhd, drv->filetype, &drvsec, sectable, 1);
  4701. drv->cyl = oldcyl;
  4702. side = oldside;
  4703. drv->buffered_cyl = -1;
  4704. }
  4705. using namespace tinyxml2;
  4706. static bool abr_loaded;
  4707. static tinyxml2::XMLDocument abr_xml[2];
  4708. static const TCHAR* abr_files[] = { _T("brainfile.xml"), _T("catlist.xml"), NULL };
  4709. static void abrcheck(struct diskinfo *di)
  4710. {
  4711. TCHAR path[MAX_DPATH];
  4712. if (!abr_loaded) {
  4713. bool error = false;
  4714. for (int i = 0; abr_files[i] && !error; i++) {
  4715. get_plugin_path(path, sizeof(path) / sizeof(TCHAR), _T("abr"));
  4716. _tcscat(path, abr_files[i]);
  4717. FILE *f = _tfopen(path, _T("rb"));
  4718. if (f) {
  4719. tinyxml2::XMLError err = abr_xml[i].LoadFile(f);
  4720. if (err != XML_SUCCESS) {
  4721. write_log(_T("failed to parse '%s': %d\n"), path, err);
  4722. error = true;
  4723. }
  4724. fclose(f);
  4725. } else {
  4726. error = true;
  4727. }
  4728. }
  4729. if (!error) {
  4730. abr_loaded = true;
  4731. }
  4732. }
  4733. if (!abr_loaded)
  4734. return;
  4735. tinyxml2::XMLElement *detectedelementcrc32 = NULL;
  4736. tinyxml2::XMLElement *detectedelementrecog = NULL;
  4737. tinyxml2::XMLElement *e = abr_xml[0].FirstChildElement("Bootblocks");
  4738. if (e) {
  4739. e = e->FirstChildElement("Bootblock");
  4740. if (e) {
  4741. do {
  4742. tinyxml2::XMLElement *ercrc = e->FirstChildElement("CRC");
  4743. if (ercrc) {
  4744. const char *n_crc32 = ercrc->GetText();
  4745. if (strlen(n_crc32) == 8) {
  4746. char *endptr;
  4747. uae_u32 crc32 = strtol(n_crc32, &endptr, 16);
  4748. if (di->bootblockcrc32 == crc32) {
  4749. detectedelementcrc32 = e;
  4750. }
  4751. }
  4752. }
  4753. tinyxml2::XMLElement *er = e->FirstChildElement("Recog");
  4754. if (er) {
  4755. const char *tr = er->GetText();
  4756. bool detected = false;
  4757. while (tr) {
  4758. int offset = atoi(tr);
  4759. if (offset < 0 || offset > 1023)
  4760. break;
  4761. tr = strchr(tr, ',');
  4762. if (!tr || !tr[1])
  4763. break;
  4764. tr++;
  4765. int val = atoi(tr);
  4766. if (val < 0 || val > 255)
  4767. break;
  4768. if (di->bootblock[offset] != val)
  4769. break;
  4770. tr = strchr(tr, ',');
  4771. if (!tr) {
  4772. detected = true;
  4773. } else {
  4774. tr++;
  4775. }
  4776. }
  4777. if (detected) {
  4778. detectedelementrecog = e;
  4779. }
  4780. }
  4781. e = e->NextSiblingElement();
  4782. } while (e && !detectedelementcrc32);
  4783. if (detectedelementcrc32 != NULL || detectedelementrecog != NULL) {
  4784. if (detectedelementcrc32) {
  4785. e = detectedelementcrc32;
  4786. } else {
  4787. e = detectedelementrecog;
  4788. }
  4789. tinyxml2::XMLElement *e_name = e->FirstChildElement("Name");
  4790. if (e_name) {
  4791. const char *n_name = e_name->GetText();
  4792. if (n_name) {
  4793. TCHAR *s = au(n_name);
  4794. _tcscpy(di->bootblockinfo, s);
  4795. xfree(s);
  4796. }
  4797. }
  4798. tinyxml2::XMLElement *e_class = e->FirstChildElement("Class");
  4799. if (e_class) {
  4800. const char *t_class = e_class->GetText();
  4801. if (t_class) {
  4802. tinyxml2::XMLElement *ecats = abr_xml[1].FirstChildElement("Categories");
  4803. if (ecats) {
  4804. tinyxml2::XMLElement *ecat = ecats->FirstChildElement("Category");
  4805. if (ecat) {
  4806. do {
  4807. tinyxml2::XMLElement *ecatr = ecat->FirstChildElement("abbrev");
  4808. if (ecatr) {
  4809. const char *catabbr = ecatr->GetText();
  4810. if (!strcmp(catabbr, t_class)) {
  4811. tinyxml2::XMLElement *ecatn = ecat->FirstChildElement("Name");
  4812. if (ecatn) {
  4813. const char *n_catname = ecatn->GetText();
  4814. if (n_catname) {
  4815. TCHAR *s = au(n_catname);
  4816. _tcscpy(di->bootblockclass, s);
  4817. xfree(s);
  4818. break;
  4819. }
  4820. }
  4821. }
  4822. }
  4823. ecat = ecat->NextSiblingElement();
  4824. } while (ecat);
  4825. }
  4826. }
  4827. return;
  4828. }
  4829. }
  4830. }
  4831. }
  4832. }
  4833. }
  4834. static void get_floppybridgeinfo(struct uae_prefs *prefs, TCHAR *infotext, int num)
  4835. {
  4836. if (!infotext) {
  4837. return;
  4838. }
  4839. floppybridge_init(prefs);
  4840. if (bridgeinfoloaded <= 1) {
  4841. FloppyBridgeAPI::getBridgeDriverInformation(true, bridgeinfo);
  4842. bridgeinfoloaded = 2;
  4843. }
  4844. TCHAR *p = infotext;
  4845. _tcscat(p, bridgeinfo.about);
  4846. p += _tcslen(p);
  4847. if (bridgeinfo.isUpdateAvailable) {
  4848. _stprintf(p, _T(" v%u.%u (v%u.%u) "), bridgeinfo.majorVersion, bridgeinfo.minorVersion, bridgeinfo.updateMajorVersion, bridgeinfo.updateMinorVersion);
  4849. } else {
  4850. _stprintf(p, _T(" v%u.%u "), bridgeinfo.majorVersion, bridgeinfo.minorVersion);
  4851. }
  4852. p += _tcslen(p);
  4853. _stprintf(p, _T("(%s)"), bridgeinfo.url);
  4854. _tcscat(p, _T("\r\n\r\n"));
  4855. p += _tcslen(p);
  4856. if (bridge_driver[num]) {
  4857. const FloppyDiskBridge::BridgeDriver *bd = bridge_driver[num];
  4858. TCHAR *name = au(bd->name);
  4859. TCHAR *man = au(bd->manufacturer);
  4860. TCHAR *url = au(bd->url);
  4861. _stprintf(p, _T("%s, %s (%s)\r\n"), name, man, url);
  4862. xfree(url);
  4863. xfree(man);
  4864. xfree(name);
  4865. p += _tcslen(p);
  4866. }
  4867. }
  4868. int DISK_examine_image(struct uae_prefs *p, int num, struct diskinfo *di, bool deepcheck, TCHAR *infotext)
  4869. {
  4870. int drvsec;
  4871. int ret, i;
  4872. drive *drv = &floppy[num];
  4873. uae_u32 dos, crc, crc2;
  4874. int wasdelayed = drv->dskchange_time;
  4875. int sectable[MAX_SECTORS];
  4876. int oldcyl, oldside;
  4877. uae_u32 v = 0;
  4878. bool fb = DISK_isfloppybridge(p, num);
  4879. if (infotext) {
  4880. infotext[0] = 0;
  4881. }
  4882. ret = 0;
  4883. memset (di, 0, sizeof (struct diskinfo));
  4884. if (fb) {
  4885. get_floppybridgeinfo(p, infotext, num);
  4886. }
  4887. di->unreadable = true;
  4888. oldcyl = drv->cyl;
  4889. oldside = side;
  4890. if (!drive_insert (drv, p, num, p->floppyslots[num].df, true, true) || (!drv->diskfile && !drv->bridge)) {
  4891. drv->cyl = oldcyl;
  4892. side = oldside;
  4893. return 1;
  4894. }
  4895. if (drv->diskfile) {
  4896. di->imagecrc32 = zfile_crc32(drv->diskfile);
  4897. di->image_crc_value = true;
  4898. }
  4899. di->unreadable = false;
  4900. decode_buffer(drv, drv->bigmfmbuf, drv->cyl, 11, drv->ddhd, drv->filetype, &drvsec, sectable, 1);
  4901. di->hd = drv->ddhd == 2;
  4902. drv->cyl = oldcyl;
  4903. side = oldside;
  4904. if (sectable[0] == 0 || sectable[1] == 0) {
  4905. ret = 2;
  4906. di->unreadable = true;
  4907. goto end2;
  4908. }
  4909. crc = crc2 = 0;
  4910. for (i = 0; i < 1024; i += 4) {
  4911. di->bootblock[i + 0] = writebuffer[i + 0];
  4912. di->bootblock[i + 1] = writebuffer[i + 1];
  4913. di->bootblock[i + 2] = writebuffer[i + 2];
  4914. di->bootblock[i + 3] = writebuffer[i + 3];
  4915. uae_u32 v = (writebuffer[i] << 24) | (writebuffer[i + 1] << 16) | (writebuffer[i + 2] << 8) | writebuffer[i + 3];
  4916. if (i == 0)
  4917. dos = v;
  4918. if (i == 4) {
  4919. crc2 = v;
  4920. v = 0;
  4921. }
  4922. if (crc + v < crc)
  4923. crc++;
  4924. crc += v;
  4925. }
  4926. di->bootblockcrc32 = get_crc32(di->bootblock, 1024);
  4927. if (deepcheck) {
  4928. abrcheck(di);
  4929. }
  4930. if (dos == 0x4b49434b) { /* KICK */
  4931. ret = 10;
  4932. goto end;
  4933. }
  4934. crc ^= 0xffffffff;
  4935. if (crc != crc2) {
  4936. ret = 3;
  4937. goto end;
  4938. }
  4939. di->bb_crc_valid = true;
  4940. writebuffer[4] = writebuffer[5] = writebuffer[6] = writebuffer[7] = 0;
  4941. if (get_crc32 (writebuffer, 0x31) == 0xae5e282c) {
  4942. di->bootblocktype = 1;
  4943. }
  4944. if (dos == 0x444f5300)
  4945. ret = 10;
  4946. else if (dos == 0x444f5301 || dos == 0x444f5302 || dos == 0x444f5303)
  4947. ret = 11;
  4948. else if (dos == 0x444f5304 || dos == 0x444f5305 || dos == 0x444f5306 || dos == 0x444f5307)
  4949. ret = 12;
  4950. else
  4951. ret = 4;
  4952. v = get_crc32 (writebuffer + 8, 0x5c - 8);
  4953. if (ret >= 10 && v == 0xe158ca4b) {
  4954. di->bootblocktype = 2;
  4955. }
  4956. end:
  4957. if (!fb || (fb && infotext)) {
  4958. load_track(num, 40, 0, sectable);
  4959. if (sectable[0]) {
  4960. if (!disk_checksum(writebuffer, NULL) &&
  4961. writebuffer[0] == 0 && writebuffer[1] == 0 && writebuffer[2] == 0 && writebuffer[3] == 2 &&
  4962. writebuffer[508] == 0 && writebuffer[509] == 0 && writebuffer[510] == 0 && writebuffer[511] == 1) {
  4963. writebuffer[512 - 20 * 4 + 1 + writebuffer[512 - 20 * 4]] = 0;
  4964. TCHAR *n = au((const char *)(writebuffer + 512 - 20 * 4 + 1));
  4965. if (_tcslen(n) >= sizeof(di->diskname))
  4966. n[sizeof(di->diskname) - 1] = 0;
  4967. _tcscpy(di->diskname, n);
  4968. xfree(n);
  4969. }
  4970. }
  4971. }
  4972. end2:
  4973. load_track(num, oldcyl, oldside, sectable);
  4974. drive_image_free (drv);
  4975. if (wasdelayed > 1) {
  4976. drive_eject (drv);
  4977. currprefs.floppyslots[num].df[0] = 0;
  4978. drv->dskchange_time = wasdelayed;
  4979. disk_insert (num, drv->newname);
  4980. }
  4981. return ret;
  4982. }
  4983. /* Disk save/restore code */
  4984. #if defined SAVESTATE || defined DEBUGGER
  4985. void DISK_save_custom (uae_u32 *pdskpt, uae_u16 *pdsklength, uae_u16 *pdsksync, uae_u16 *pdskbytr)
  4986. {
  4987. if (pdskpt)
  4988. *pdskpt = dskpt;
  4989. if (pdsklength)
  4990. *pdsklength = dsklen;
  4991. if (pdsksync)
  4992. *pdsksync = dsksync;
  4993. if (pdskbytr)
  4994. *pdskbytr = dskbytr_val;
  4995. }
  4996. #endif /* SAVESTATE || DEBUGGER */
  4997. static uae_u32 getadfcrc (drive *drv)
  4998. {
  4999. uae_u8 *b;
  5000. uae_u32 crc32;
  5001. int size;
  5002. if (!drv->diskfile)
  5003. return 0;
  5004. zfile_fseek (drv->diskfile, 0, SEEK_END);
  5005. size = (int)zfile_ftell (drv->diskfile);
  5006. b = xmalloc (uae_u8, size);
  5007. if (!b)
  5008. return 0;
  5009. zfile_fseek (drv->diskfile, 0, SEEK_SET);
  5010. zfile_fread (b, 1, size, drv->diskfile);
  5011. crc32 = get_crc32 (b, size);
  5012. free (b);
  5013. return crc32;
  5014. }
  5015. #ifdef SAVESTATE
  5016. void DISK_restore_custom (uae_u32 pdskpt, uae_u16 pdsklength, uae_u16 pdskbytr)
  5017. {
  5018. dskpt = pdskpt;
  5019. dsklen = pdsklength;
  5020. dskbytr_val = pdskbytr;
  5021. }
  5022. void restore_disk_finish (void)
  5023. {
  5024. int cnt = 0;
  5025. for (int i = 0; i < MAX_FLOPPY_DRIVES; i++) {
  5026. if (currprefs.floppyslots[i].dfxtype >= 0) {
  5027. update_drive_gui (i, true);
  5028. cnt++;
  5029. }
  5030. }
  5031. currprefs.nr_floppies = changed_prefs.nr_floppies = cnt;
  5032. DISK_check_change ();
  5033. setamax ();
  5034. #if 0
  5035. if (dskdmaen)
  5036. dumpdisk ();
  5037. #endif
  5038. }
  5039. uae_u8 *restore_disk (int num,uae_u8 *src)
  5040. {
  5041. drive *drv;
  5042. int state, dfxtype;
  5043. TCHAR old[MAX_DPATH];
  5044. TCHAR *s;
  5045. int newis;
  5046. drv = &floppy[num];
  5047. disabled &= ~(1 << num);
  5048. drv->drive_id = restore_u32 ();
  5049. drv->motoroff = 1;
  5050. drv->idbit = 0;
  5051. state = restore_u8 ();
  5052. if (state & 2) {
  5053. disabled |= 1 << num;
  5054. if (changed_prefs.nr_floppies > num)
  5055. changed_prefs.nr_floppies = num;
  5056. changed_prefs.floppyslots[num].dfxtype = -1;
  5057. } else {
  5058. drv->motoroff = (state & 1) ? 0 : 1;
  5059. drv->idbit = (state & 4) ? 1 : 0;
  5060. switch (drv->drive_id)
  5061. {
  5062. case DRIVE_ID_35HD:
  5063. dfxtype = DRV_35_HD;
  5064. break;
  5065. case DRIVE_ID_525SD:
  5066. dfxtype = DRV_525_SD;
  5067. break;
  5068. default:
  5069. dfxtype = DRV_35_DD;
  5070. break;
  5071. }
  5072. currprefs.floppyslots[num].dfxtype = changed_prefs.floppyslots[num].dfxtype = dfxtype;
  5073. }
  5074. drv->dskchange = (state & 8) != 0;
  5075. side = (state & 16) ? 1 : 0;
  5076. drv->indexhackmode = 0;
  5077. if (num == 0 && currprefs.floppyslots[num].dfxtype == 0)
  5078. drv->indexhackmode = 1;
  5079. drv->buffered_cyl = -1;
  5080. drv->buffered_side = -1;
  5081. drv->cyl = restore_u8 ();
  5082. drv->dskready = restore_u8 () != 0;
  5083. drv->drive_id_scnt = restore_u8 ();
  5084. int mfmpos = restore_u32 ();
  5085. drv->dskchange_time = 0;
  5086. restore_u32 ();
  5087. s = restore_path (SAVESTATE_PATH_FLOPPY);
  5088. int dskready_up_time = restore_u16 ();
  5089. int dskready_down_time = restore_u16 ();
  5090. if (restore_u32() & 1) {
  5091. xfree(s);
  5092. s = restore_path_full();
  5093. }
  5094. if (s && s[0])
  5095. write_log(_T("-> '%s'\n"), s);
  5096. _tcscpy(old, currprefs.floppyslots[num].df);
  5097. _tcsncpy(changed_prefs.floppyslots[num].df, s, MAX_DPATH);
  5098. xfree(s);
  5099. newis = changed_prefs.floppyslots[num].df[0] ? 1 : 0;
  5100. if (!(disabled & (1 << num))) {
  5101. if (!newis && old[0]) {
  5102. *currprefs.floppyslots[num].df = *changed_prefs.floppyslots[num].df = 0;
  5103. drv->dskchange = false;
  5104. } else if (newis) {
  5105. drive_insert (floppy + num, &currprefs, num, changed_prefs.floppyslots[num].df, false, false);
  5106. if (drive_empty (floppy + num)) {
  5107. if (newis && zfile_exists(old)) {
  5108. _tcscpy (changed_prefs.floppyslots[num].df, old);
  5109. drive_insert (floppy + num, &currprefs, num, changed_prefs.floppyslots[num].df, false, false);
  5110. if (drive_empty (floppy + num))
  5111. drv->dskchange = true;
  5112. } else {
  5113. drv->dskchange_time = -1;
  5114. _tcscpy(drv->newname, changed_prefs.floppyslots[num].df);
  5115. _tcscpy(currprefs.floppyslots[num].df, drv->newname);
  5116. write_log(_T("Disk image not found, faking inserted disk.\n"));
  5117. }
  5118. }
  5119. }
  5120. }
  5121. drv->mfmpos = mfmpos;
  5122. drv->prevtracklen = drv->tracklen;
  5123. drv->dskready_up_time = dskready_up_time;
  5124. drv->dskready_down_time = dskready_down_time;
  5125. reset_drive_gui (num);
  5126. return src;
  5127. }
  5128. uae_u8 *restore_disk2 (int num,uae_u8 *src)
  5129. {
  5130. drive *drv = &floppy[num];
  5131. uae_u32 m = restore_u32 ();
  5132. if (m) {
  5133. drv->floppybitcounter = restore_u16 ();
  5134. drv->tracklen = restore_u32 ();
  5135. drv->trackspeed = restore_u16 ();
  5136. drv->skipoffset = restore_u32 ();
  5137. drv->indexoffset = restore_u32 ();
  5138. drv->buffered_cyl = drv->cyl;
  5139. drv->buffered_side = side;
  5140. for (int j = 0; j < (drv->tracklen + 15) / 16; j++) {
  5141. drv->bigmfmbuf[j] = restore_u16 ();
  5142. if (m & 2)
  5143. drv->tracktiming[j] = restore_u16 ();
  5144. }
  5145. drv->revolutions = restore_u16 ();
  5146. }
  5147. return src;
  5148. }
  5149. uae_u8 *save_disk (int num, int *len, uae_u8 *dstptr, bool usepath)
  5150. {
  5151. uae_u8 *dstbak,*dst;
  5152. drive *drv = &floppy[num];
  5153. if (dstptr)
  5154. dstbak = dst = dstptr;
  5155. else
  5156. dstbak = dst = xmalloc (uae_u8, 2 + 1 + 1 + 1 + 1 + 4 + 4 + MAX_DPATH + 2 + 2 + 4 + 2 * MAX_DPATH);
  5157. save_u32 (drv->drive_id); /* drive type ID */
  5158. save_u8 ((drv->motoroff ? 0 : 1) | ((disabled & (1 << num)) ? 2 : 0) | (drv->idbit ? 4 : 0) | (drive_diskchange(drv) ? 8 : 0) | (side ? 16 : 0) | (drv->wrprot ? 32 : 0));
  5159. save_u8 (drv->cyl); /* cylinder */
  5160. save_u8 (drive_diskready(drv)); /* dskready */
  5161. save_u8 (drv->drive_id_scnt); /* id mode position */
  5162. save_u32 (drv->mfmpos); /* disk position */
  5163. save_u32 (getadfcrc (drv)); /* CRC of disk image */
  5164. save_path (usepath ? currprefs.floppyslots[num].df : _T(""), SAVESTATE_PATH_FLOPPY);/* image name */
  5165. save_u16 (drv->dskready_up_time);
  5166. save_u16 (drv->dskready_down_time);
  5167. if (usepath) {
  5168. save_u32(1);
  5169. save_path_full(currprefs.floppyslots[num].df, SAVESTATE_PATH_FLOPPY);
  5170. }
  5171. *len = dst - dstbak;
  5172. return dstbak;
  5173. }
  5174. uae_u8 *save_disk2 (int num, int *len, uae_u8 *dstptr)
  5175. {
  5176. uae_u8 *dstbak,*dst;
  5177. drive *drv = &floppy[num];
  5178. int m = 0;
  5179. int size = 0;
  5180. if (drv->motoroff == 0 && drv->buffered_side >= 0 && drv->tracklen > 0) {
  5181. m = 1;
  5182. size += ((drv->tracklen + 15) * 2) / 8;
  5183. if (drv->tracktiming[0]) {
  5184. m |= 2;
  5185. size *= 2;
  5186. }
  5187. }
  5188. if (!m)
  5189. return NULL;
  5190. if (dstptr)
  5191. dstbak = dst = dstptr;
  5192. else
  5193. dstbak = dst = xmalloc (uae_u8, 2 + 4 + 2 + 4 + 4 + size + 2);
  5194. save_u32 (m);
  5195. save_u16 (drv->floppybitcounter);
  5196. save_u32 (drv->tracklen);
  5197. save_u16 (drv->trackspeed);
  5198. save_u32 (drv->skipoffset);
  5199. save_u32 (drv->indexoffset);
  5200. for (int j = 0; j < (drv->tracklen + 15) / 16; j++) {
  5201. save_u16(drv->bigmfmbuf[j]);
  5202. if (drv->tracktiming[0])
  5203. save_u16(drv->tracktiming[j]);
  5204. }
  5205. save_u16 (drv->revolutions);
  5206. *len = dst - dstbak;
  5207. return dstbak;
  5208. }
  5209. /* internal floppy controller variables */
  5210. uae_u8 *restore_floppy (uae_u8 *src)
  5211. {
  5212. word = restore_u16 ();
  5213. bitoffset = restore_u8 ();
  5214. dma_enable = restore_u8 ();
  5215. disk_hpos = restore_u8 () & 0xff;
  5216. dskdmaen = restore_u8 ();
  5217. for (int i = 0; i < 3; i++) {
  5218. fifo[i] = restore_u16 ();
  5219. fifo_inuse[i] = restore_u8 ();
  5220. if (dskdmaen == 0)
  5221. fifo_inuse[i] = false;
  5222. }
  5223. fifo_filled = fifo_inuse[0] || fifo_inuse[1] || fifo_inuse[2];
  5224. dsklength = restore_u16 ();
  5225. return src;
  5226. }
  5227. uae_u8 *save_floppy (int *len, uae_u8 *dstptr)
  5228. {
  5229. uae_u8 *dstbak, *dst;
  5230. if (dstptr)
  5231. dstbak = dst = dstptr;
  5232. else
  5233. dstbak = dst = xmalloc (uae_u8, 100);
  5234. save_u16 (word); /* shift register */
  5235. save_u8 (bitoffset); /* dma bit offset */
  5236. save_u8 (dma_enable); /* disk sync found */
  5237. save_u8 (disk_hpos & 0xff); /* next bit read position */
  5238. save_u8 (dskdmaen); /* dma status */
  5239. for (int i = 0; i < 3; i++) {
  5240. save_u16 (fifo[i]);
  5241. save_u8 (fifo_inuse[i]);
  5242. }
  5243. save_u16 (dsklength);
  5244. *len = dst - dstbak;
  5245. return dstbak;
  5246. }
  5247. #endif /* SAVESTATE */
  5248. #define MAX_DISKENTRIES 4
  5249. int disk_prevnext_name (TCHAR *imgp, int dir)
  5250. {
  5251. TCHAR img[MAX_DPATH], *ext, *p, *p2, *ps, *dst[MAX_DISKENTRIES];
  5252. int num = -1;
  5253. int cnt, i;
  5254. TCHAR imgl[MAX_DPATH];
  5255. int ret, gotone, wrapped;
  5256. TCHAR *old;
  5257. old = my_strdup (imgp);
  5258. struct zfile *zf = zfile_fopen (imgp, _T("rb"), ZFD_NORMAL);
  5259. if (zf) {
  5260. _tcscpy (img, zfile_getname (zf));
  5261. zfile_fclose (zf);
  5262. zf = zfile_fopen (img, _T("rb"), ZFD_NORMAL);
  5263. if (!zf) // oops, no directory support in this archive type
  5264. _tcscpy (img, imgp);
  5265. zfile_fclose (zf);
  5266. } else {
  5267. _tcscpy (img, imgp);
  5268. }
  5269. wrapped = 0;
  5270. retry:
  5271. _tcscpy (imgl, img);
  5272. to_lower (imgl, sizeof imgl / sizeof (TCHAR));
  5273. gotone = 0;
  5274. ret = 0;
  5275. ps = imgl;
  5276. cnt = 0;
  5277. dst[cnt] = NULL;
  5278. for (;;) {
  5279. // disk x of y
  5280. p = _tcsstr (ps, _T("(disk "));
  5281. if (p && _istdigit (p[6])) {
  5282. p2 = p - imgl + img;
  5283. num = _tstoi (p + 6);
  5284. dst[cnt++] = p2 + 6;
  5285. if (cnt >= MAX_DISKENTRIES - 1)
  5286. break;
  5287. gotone = 1;
  5288. ps = p + 6;
  5289. continue;
  5290. }
  5291. if (gotone)
  5292. break;
  5293. p = _tcsstr (ps, _T("disk"));
  5294. if (p && _istdigit (p[4])) {
  5295. p2 = p - imgl + img;
  5296. num = _tstoi (p + 4);
  5297. dst[cnt++] = p2 + 4;
  5298. if (cnt >= MAX_DISKENTRIES - 1)
  5299. break;
  5300. gotone = 1;
  5301. ps = p + 4;
  5302. continue;
  5303. }
  5304. if (gotone)
  5305. break;
  5306. ext = _tcsrchr (ps, '.');
  5307. if (!ext || ext - ps < 4)
  5308. break;
  5309. TCHAR *ext2 = ext - imgl + img;
  5310. // name_<non numeric character>x.ext
  5311. if (ext[-3] == '_' && !_istdigit (ext[-2]) && _istdigit (ext[-1])) {
  5312. num = _tstoi (ext - 1);
  5313. dst[cnt++] = ext2 - 1;
  5314. // name_x.ext, name-x.ext, name x.ext
  5315. } else if ((ext[-2] == '_' || ext[-2] == '-' || ext[-2] == ' ') && _istdigit (ext[-1])) {
  5316. num = _tstoi (ext - 1);
  5317. dst[cnt++] = ext2 - 1;
  5318. // name_a.ext, name-a.ext, name a .ext
  5319. } else if ((ext[-2] == '_' || ext[-2] == '-' || ext[-2] == ' ') && ext[-1] >= 'a' && ext[-1] <= 'z') {
  5320. num = ext[-1] - 'a' + 1;
  5321. dst[cnt++] = ext2 - 1;
  5322. // nameA.ext
  5323. } else if (ext2[-2] >= 'a' && ext2[-2] <= 'z' && ext2[-1] >= 'A' && ext2[-1] <= 'Z') {
  5324. num = ext[-1] - 'a' + 1;
  5325. dst[cnt++] = ext2 - 1;
  5326. // namex.ext
  5327. } else if (!_istdigit (ext2[-2]) && _istdigit (ext[-1])) {
  5328. num = ext[-1] - '0';
  5329. dst[cnt++] = ext2 - 1;
  5330. }
  5331. break;
  5332. }
  5333. dst[cnt] = NULL;
  5334. if (num <= 0 || num >= 19)
  5335. goto end;
  5336. num += dir;
  5337. if (num > 9)
  5338. goto end;
  5339. if (num == 9)
  5340. num = 1;
  5341. else if (num == 0)
  5342. num = 9;
  5343. for (i = 0; i < cnt; i++) {
  5344. if (!_istdigit (dst[i][0])) {
  5345. int capital = dst[i][0] >= 'A' && dst[i][0] <= 'Z';
  5346. dst[i][0] = (num - 1) + (capital ? 'A' : 'a');
  5347. } else {
  5348. dst[i][0] = num + '0';
  5349. }
  5350. }
  5351. if (zfile_exists (img)) {
  5352. ret = 1;
  5353. goto end;
  5354. }
  5355. if (gotone) { // was (disk x but no match, perhaps there are extra tags..
  5356. TCHAR *old2 = my_strdup (img);
  5357. for (;;) {
  5358. ext = _tcsrchr (img, '.');
  5359. if (!ext)
  5360. break;
  5361. if (ext == img)
  5362. break;
  5363. if (ext[-1] != ']')
  5364. break;
  5365. TCHAR *t = _tcsrchr (img, '[');
  5366. if (!t)
  5367. break;
  5368. t[0] = 0;
  5369. if (zfile_exists (img)) {
  5370. ret = 1;
  5371. goto end;
  5372. }
  5373. }
  5374. _tcscpy (img, old2);
  5375. xfree (old2);
  5376. }
  5377. if (!wrapped) {
  5378. for (i = 0; i < cnt; i++) {
  5379. if (!_istdigit (dst[i][0]))
  5380. dst[i][0] = dst[i][0] >= 'A' && dst[i][0] <= 'Z' ? 'A' : 'a';
  5381. else
  5382. dst[i][0] = '1';
  5383. if (dir < 0)
  5384. dst[i][0] += 8;
  5385. }
  5386. wrapped++;
  5387. }
  5388. if (zfile_exists (img)) {
  5389. ret = -1;
  5390. goto end;
  5391. }
  5392. if (dir < 0 && wrapped < 2)
  5393. goto retry;
  5394. _tcscpy (img, old);
  5395. end:
  5396. _tcscpy (imgp, img);
  5397. xfree (old);
  5398. return ret;
  5399. }
  5400. int disk_prevnext (int drive, int dir)
  5401. {
  5402. TCHAR img[MAX_DPATH];
  5403. _tcscpy (img, currprefs.floppyslots[drive].df);
  5404. if (!img[0])
  5405. return 0;
  5406. disk_prevnext_name (img, dir);
  5407. _tcscpy (changed_prefs.floppyslots[drive].df, img);
  5408. return 1;
  5409. }
  5410. static int getdebug(void)
  5411. {
  5412. return floppy[0].mfmpos;
  5413. }
  5414. static int get_reserved_id(int num)
  5415. {
  5416. for (int i = 0; i < MAX_FLOPPY_DRIVES; i++) {
  5417. if (reserved & (1 << i)) {
  5418. if (num > 0) {
  5419. num--;
  5420. continue;
  5421. }
  5422. return i;
  5423. }
  5424. }
  5425. return -1;
  5426. }
  5427. void disk_reserved_setinfo(int num, int cyl, int head, int motor)
  5428. {
  5429. int i = get_reserved_id(num);
  5430. if (i >= 0) {
  5431. drive *drv = &floppy[i];
  5432. reserved_side = head;
  5433. drv->cyl = cyl;
  5434. drv->state = motor != 0;
  5435. update_drive_gui(i, false);
  5436. }
  5437. }
  5438. bool disk_reserved_getinfo(int num, struct floppy_reserved *fr)
  5439. {
  5440. int idx = get_reserved_id(num);
  5441. if (idx >= 0) {
  5442. drive *drv = &floppy[idx];
  5443. fr->num = idx;
  5444. fr->img = drv->diskfile;
  5445. fr->wrprot = drv->wrprot;
  5446. if (drv->diskfile && !drv->pcdecodedfile && (drv->filetype == ADF_EXT2 || drv->filetype == ADF_FDI || drv->filetype == ADF_IPF || drv->filetype == ADF_SCP)) {
  5447. int cyl = drv->cyl;
  5448. int side2 = side;
  5449. struct zfile *z = zfile_fopen_empty(NULL, zfile_getfilename(drv->diskfile));
  5450. if (z) {
  5451. bool ok = false;
  5452. drv->num_secs = 21; // max possible
  5453. drive_fill_bigbuf(drv, true);
  5454. int secs = drive_write_pcdos(drv, z, 1);
  5455. if (secs >= 8) {
  5456. ok = true;
  5457. drv->num_secs = secs;
  5458. for (int i = 0; i < drv->num_tracks; i++) {
  5459. drv->cyl = i / 2;
  5460. side = i & 1;
  5461. drive_fill_bigbuf(drv, true);
  5462. drive_write_pcdos(drv, z, 0);
  5463. }
  5464. }
  5465. drv->cyl = cyl;
  5466. side = side2;
  5467. if (ok) {
  5468. write_log(_T("Created internal PC disk image cyl=%d secs=%d size=%d\n"), drv->num_tracks / 2, drv->num_secs, zfile_size(z));
  5469. drv->pcdecodedfile = z;
  5470. } else {
  5471. write_log(_T("Failed to create internal PC disk image\n"));
  5472. zfile_fclose(z);
  5473. }
  5474. }
  5475. }
  5476. if (drv->pcdecodedfile) {
  5477. fr->img = drv->pcdecodedfile;
  5478. }
  5479. fr->cyl = drv->cyl;
  5480. fr->cyls = drv->num_tracks / 2;
  5481. fr->drive_cyls = currprefs.floppyslots[idx].dfxtype == DRV_PC_525_ONLY_40 ? 40 : 80;
  5482. fr->secs = drv->num_secs;
  5483. fr->heads = drv->num_heads;
  5484. fr->disk_changed = drive_diskchange(drv) || fr->img == NULL;
  5485. if (currprefs.floppyslots[idx].dfxtype == DRV_PC_35_ONLY_80) {
  5486. if (drv->num_secs > 14)
  5487. fr->rate = FLOPPY_RATE_500K; // 1.2M/1.4M
  5488. else
  5489. fr->rate = FLOPPY_RATE_250K; // 720K
  5490. } else if (currprefs.floppyslots[idx].dfxtype == DRV_PC_525_40_80) {
  5491. if (fr->cyls < 80) {
  5492. if (drv->num_secs < 9)
  5493. fr->rate = FLOPPY_RATE_250K; // 320k in 80 track drive
  5494. else
  5495. fr->rate = FLOPPY_RATE_300K; // 360k in 80 track drive
  5496. } else {
  5497. if (drv->num_secs > 14)
  5498. fr->rate = FLOPPY_RATE_500K; // 1.2M/1.4M
  5499. else
  5500. fr->rate = FLOPPY_RATE_300K; // 720K
  5501. }
  5502. } else {
  5503. if (drv->num_secs < 9)
  5504. fr->rate = FLOPPY_RATE_300K;// 320k in 40 track drive
  5505. else
  5506. fr->rate = FLOPPY_RATE_250K;// 360k in 40 track drive
  5507. // yes, above values are swapped compared to 1.2M drive case
  5508. }
  5509. return true;
  5510. }
  5511. return false;
  5512. }
  5513. void disk_reserved_reset_disk_change(int num)
  5514. {
  5515. int i = get_reserved_id(num);
  5516. if (i >= 0) {
  5517. drive *drv = &floppy[i];
  5518. drv->dskchange = false;
  5519. }
  5520. }