|
|
1.1 root 1: /*
1.1.1.5 root 2: Hatari - floppy.c
1.1 root 3:
1.1.1.5 root 4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
6:
1.1.1.12! root 7: This is where we read/write sectors to/from the disk image buffers.
! 8: NOTE: these buffers are in memory so we only need to write routines for
! 9: the .ST format. When the buffer is to be saved (ie eject disk) we save
! 10: it back to the original file in the correct format (.ST or .MSA).
1.1.1.5 root 11:
12: There are some important notes about image accessing - as we use TOS and the
1.1.1.9 root 13: FDC to access the disk the boot-sector MUST be valid. Sometimes this is NOT
14: the case! In these situations we must guess at the disk format. Eg, some disk
1.1.1.5 root 15: images have a a boot sector which states single-sided, but the images have
16: been created as double-sided. As sides are interleaved we need to read the
17: image as if it was double-sided. Also note that 'NumBytesPerSector' is ALWAYS
18: 512 bytes, even if the boot-sector states otherwise.
1.1.1.4 root 19: Also note that old versions of the MAKEDISK utility do not set the correct
20: boot sector structure for a real ST (and also Hatari) to read it correctly.
21: (PaCifiST will, however, read/write to these images as it does not perform
22: FDC access as on a real ST)
1.1 root 23: */
1.1.1.12! root 24: const char Floppy_rcsid[] = "Hatari $Id: floppy.c,v 1.43 2008/11/28 17:54:14 thothy Exp $";
1.1.1.8 root 25:
26: #include <sys/stat.h>
1.1.1.12! root 27: #include <assert.h>
1.1.1.4 root 28: #include <SDL_endian.h>
29:
1.1 root 30: #include "main.h"
1.1.1.6 root 31: #include "configuration.h"
1.1.1.7 root 32: #include "dim.h"
1.1 root 33: #include "file.h"
34: #include "floppy.h"
1.1.1.9 root 35: #include "gemdos.h"
36: #include "hdc.h"
1.1.1.8 root 37: #include "log.h"
1.1 root 38: #include "memorySnapShot.h"
39: #include "msa.h"
40: #include "st.h"
1.1.1.6 root 41: #include "zip.h"
1.1 root 42:
1.1.1.10 root 43:
1.1.1.12! root 44: /* Emulation drive details, eg FileName, Inserted, Changed etc... */
! 45: EMULATION_DRIVE EmulationDrives[MAX_FLOPPYDRIVES];
! 46: /* Drive A is the default */
! 47: int nBootDrive = 0;
1.1 root 48:
1.1.1.9 root 49: /* Possible disk image file extensions to scan for */
1.1.1.10 root 50: static const char * const pszDiskImageNameExts[] =
1.1.1.5 root 51: {
1.1.1.10 root 52: ".msa",
53: ".st",
54: ".dim",
55: NULL
1.1 root 56: };
57:
58:
1.1.1.2 root 59: /*-----------------------------------------------------------------------*/
1.1.1.11 root 60: /**
61: * Initialize emulation floppy drives
62: */
1.1 root 63: void Floppy_Init(void)
64: {
1.1.1.10 root 65: int i;
1.1 root 66:
1.1.1.10 root 67: /* Clear drive structures */
1.1.1.12! root 68: for (i = 0; i < MAX_FLOPPYDRIVES; i++)
1.1.1.10 root 69: {
1.1.1.12! root 70: /* Clear structs and if floppies available, insert them */
1.1.1.10 root 71: memset(&EmulationDrives[i], 0, sizeof(EMULATION_DRIVE));
1.1.1.12! root 72: if (strlen(ConfigureParams.DiskImage.szDiskFileName[i]) > 0)
! 73: Floppy_InsertDiskIntoDrive(i);
1.1.1.10 root 74: }
1.1 root 75: }
76:
1.1.1.2 root 77:
78: /*-----------------------------------------------------------------------*/
1.1.1.11 root 79: /**
80: * UnInitialize drives
81: */
1.1 root 82: void Floppy_UnInit(void)
83: {
1.1.1.10 root 84: Floppy_EjectBothDrives();
1.1 root 85: }
86:
1.1.1.2 root 87:
88: /*-----------------------------------------------------------------------*/
1.1.1.11 root 89: /**
90: * Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
91: */
1.1.1.12! root 92: void Floppy_MemorySnapShot_Capture(bool bSave)
1.1 root 93: {
1.1.1.10 root 94: int i;
1.1 root 95:
1.1.1.10 root 96: /* If restoring then eject old drives first! */
97: if (!bSave)
98: Floppy_EjectBothDrives();
99:
100: /* Save/Restore details */
1.1.1.12! root 101: for (i = 0; i < MAX_FLOPPYDRIVES; i++)
1.1.1.10 root 102: {
103: MemorySnapShot_Store(&EmulationDrives[i].bDiskInserted, sizeof(EmulationDrives[i].bDiskInserted));
104: MemorySnapShot_Store(&EmulationDrives[i].nImageBytes, sizeof(EmulationDrives[i].nImageBytes));
105: if (!bSave && EmulationDrives[i].bDiskInserted)
106: {
107: EmulationDrives[i].pBuffer = malloc(EmulationDrives[i].nImageBytes);
108: if (!EmulationDrives[i].pBuffer)
109: perror("Floppy_MemorySnapShot_Capture");
110: }
111: if (EmulationDrives[i].pBuffer)
112: MemorySnapShot_Store(EmulationDrives[i].pBuffer, EmulationDrives[i].nImageBytes);
113: MemorySnapShot_Store(&EmulationDrives[i].bMediaChanged,sizeof(EmulationDrives[i].bMediaChanged));
114: MemorySnapShot_Store(&EmulationDrives[i].bContentsChanged,sizeof(EmulationDrives[i].bContentsChanged));
115: MemorySnapShot_Store(&EmulationDrives[i].bOKToSave,sizeof(EmulationDrives[i].bOKToSave));
116: }
1.1 root 117: }
118:
1.1.1.2 root 119:
120: /*-----------------------------------------------------------------------*/
1.1.1.11 root 121: /**
122: * Find which device to boot from (hard drive or floppy).
123: */
1.1 root 124: void Floppy_GetBootDrive(void)
125: {
1.1.1.10 root 126: /* Boot from hard drive if user wants this and HD emulation is turned on */
127: if ((ACSI_EMU_ON || GEMDOS_EMU_ON) && ConfigureParams.HardDisk.bBootFromHardDisk)
128: nBootDrive = 2; /* Drive C */
129: else
130: nBootDrive = 0; /* Drive A */
1.1 root 131: }
132:
1.1.1.2 root 133:
134: /*-----------------------------------------------------------------------*/
1.1.1.11 root 135: /**
136: * Test if disk image is write protected. Write protection can be configured
137: * in the GUI. When set to "automatic", we check the file permissions of the
138: * floppy disk image to decide.
139: */
1.1.1.12! root 140: bool Floppy_IsWriteProtected(int Drive)
1.1.1.8 root 141: {
1.1.1.10 root 142: if (ConfigureParams.DiskImage.nWriteProtection == WRITEPROT_OFF)
143: {
144: return FALSE;
145: }
146: else if (ConfigureParams.DiskImage.nWriteProtection == WRITEPROT_ON)
147: {
148: return TRUE;
149: }
150: else
151: {
152: struct stat FloppyStat;
153: /* Check whether disk is writable */
1.1.1.12! root 154: if (stat(ConfigureParams.DiskImage.szDiskFileName[Drive], &FloppyStat) == 0
! 155: && (FloppyStat.st_mode & S_IWUSR))
1.1.1.10 root 156: return FALSE;
157: else
158: return TRUE;
159: }
1.1.1.8 root 160: }
161:
162:
163: /*-----------------------------------------------------------------------*/
1.1.1.11 root 164: /**
165: * Test disk image for valid boot-sector.
166: * It has been noticed that some disks, eg blank images made by the MakeDisk
167: * utility or PaCifiST emulator fill in the boot-sector with incorrect information.
168: * Such images cannot be read correctly using a real ST, and also Hatari.
169: * To try and prevent data loss, we check for this error and flag the drive so
170: * the image will not be saved back to the file.
171: */
1.1.1.12! root 172: static bool Floppy_IsBootSectorOK(int Drive)
1.1 root 173: {
1.1.1.10 root 174: Uint8 *pDiskBuffer;
1.1 root 175:
1.1.1.10 root 176: /* Does our drive have a disk in? */
177: if (EmulationDrives[Drive].bDiskInserted)
178: {
179: pDiskBuffer = EmulationDrives[Drive].pBuffer;
180:
181: /* Check SPC (byte 13) for !=0 value. If is '0', invalid image and Hatari
182: * won't be-able to read (nor will a real ST)! */
183: if (pDiskBuffer[13] != 0)
184: {
185: return TRUE; /* Disk sector is OK! */
186: }
187: else
188: {
189: Log_AlertDlg(LOG_WARN, "Disk in drive %c: maybe suffers from the Pacifist/Makedisk bug.\n"
190: "If it does not work, please repair the disk first!\n", 'A' + Drive);
191: }
192: }
1.1 root 193:
1.1.1.10 root 194: return FALSE; /* Bad sector */
1.1 root 195: }
196:
1.1.1.2 root 197:
198: /*-----------------------------------------------------------------------*/
1.1.1.11 root 199: /**
200: * Try to create disk B filename, eg 'auto_100a' becomes 'auto_100b'
201: * Return new filename if think we should try, otherwise NULL
1.1.1.12! root 202: *
! 203: * TODO: doesn't work with images in ZIP archives
1.1.1.11 root 204: */
205: static char* Floppy_CreateDiskBFileName(const char *pSrcFileName)
1.1 root 206: {
1.1.1.10 root 207: char *szDir, *szName, *szExt;
1.1.1.12! root 208:
1.1.1.10 root 209: /* Allocate temporary memory for strings: */
210: szDir = malloc(3 * FILENAME_MAX);
211: if (!szDir)
212: {
213: perror("Floppy_CreateDiskBFileName");
214: return FALSE;
215: }
216: szName = szDir + FILENAME_MAX;
217: szExt = szName + FILENAME_MAX;
218:
219: /* So, first split name into parts */
1.1.1.11 root 220: File_SplitPath(pSrcFileName, szDir, szName, szExt);
1.1.1.10 root 221:
222: /* All OK? */
223: if (strlen(szName) > 0)
224: {
1.1.1.12! root 225: char *last = &(szName[strlen(szName)-1]);
! 226: /* Now, did filename end with an 'A' or 'a' */
! 227: if (*last == 'A' || *last == 'a')
1.1.1.10 root 228: {
1.1.1.11 root 229: char *szFull;
1.1.1.10 root 230: /* Change 'A' to a 'B' */
1.1.1.12! root 231: *last += 1;
1.1.1.10 root 232: /* And re-build name into destination */
1.1.1.11 root 233: szFull = File_MakePath(szDir, szName, szExt);
234: if (szFull)
235: {
236: /* Does file exist? */
237: if (File_Exists(szFull))
238: {
239: free(szDir);
240: return szFull;
241: }
242: free(szFull);
243: }
1.1.1.10 root 244: }
245: }
246: free(szDir);
1.1.1.11 root 247: return NULL;
1.1 root 248: }
249:
1.1.1.2 root 250:
251: /*-----------------------------------------------------------------------*/
1.1.1.11 root 252: /**
1.1.1.12! root 253: * Set floppy image to be ejected
! 254: */
! 255: const char* Floppy_SetDiskFileNameNone(int Drive)
! 256: {
! 257: assert(Drive >= 0 && Drive < MAX_FLOPPYDRIVES);
! 258: ConfigureParams.DiskImage.szDiskFileName[Drive][0] = '\0';
! 259: return ConfigureParams.DiskImage.szDiskFileName[Drive];
1.1.1.6 root 260: }
261:
1.1.1.12! root 262: /*-----------------------------------------------------------------------*/
! 263: /**
! 264: * Set given floppy drive image file name and handle
! 265: * different image extensions.
! 266: * Return corrected file name on success and NULL on failure.
1.1.1.11 root 267: */
1.1.1.12! root 268: const char* Floppy_SetDiskFileName(int Drive, const char *pszFileName, const char *pszZipPath)
1.1.1.6 root 269: {
1.1.1.11 root 270: char *filename;
1.1 root 271:
1.1.1.12! root 272: /* setting to empty or "none" ejects */
! 273: if (!*pszFileName || strcasecmp(pszFileName, "none") == 0)
! 274: {
! 275: return Floppy_SetDiskFileNameNone(Drive);
! 276: }
1.1.1.11 root 277: /* See if file exists, and if not, get/add correct extension */
1.1.1.12! root 278: if (!File_Exists(pszFileName))
1.1.1.11 root 279: filename = File_FindPossibleExtFileName(pszFileName, pszDiskImageNameExts);
280: else
281: filename = strdup(pszFileName);
1.1.1.12! root 282: if (!filename)
! 283: {
! 284: Log_AlertDlg(LOG_INFO, "Image '%s' not found", pszFileName);
! 285: return NULL;
! 286: }
! 287:
! 288: /* If we insert a disk into Drive A, should we try to put disk 2 into drive B? */
! 289: if (Drive == 0 && ConfigureParams.DiskImage.bAutoInsertDiskB)
! 290: {
! 291: /* Attempt to make up second filename, eg was 'auto_100a' to 'auto_100b' */
! 292: char *szDiskBFileName = Floppy_CreateDiskBFileName(filename);
! 293: if (szDiskBFileName)
! 294: {
! 295: /* recurse with Drive B */
! 296: Floppy_SetDiskFileName(1, szDiskBFileName, pszZipPath);
! 297: free(szDiskBFileName);
! 298: }
! 299: }
! 300:
! 301: /* do the changes */
! 302: assert(Drive >= 0 && Drive < MAX_FLOPPYDRIVES);
! 303: if (pszZipPath)
! 304: strcpy(ConfigureParams.DiskImage.szDiskZipPath[Drive], pszZipPath);
! 305: else
! 306: ConfigureParams.DiskImage.szDiskZipPath[Drive][0] = '\0';
! 307: strcpy(ConfigureParams.DiskImage.szDiskFileName[Drive], filename);
! 308: free(filename);
! 309: //File_MakeAbsoluteName(ConfigureParams.DiskImage.szDiskFileName[Drive]);
! 310: return ConfigureParams.DiskImage.szDiskFileName[Drive];
! 311: }
! 312:
! 313: /*-----------------------------------------------------------------------*/
! 314: /**
! 315: * Insert previously set disk file image into floppy drive.
! 316: * The WHOLE image is copied into Hatari drive buffers, and
! 317: * uncompressed if necessary.
! 318: * Return TRUE on success, false otherwise.
! 319: */
! 320: bool Floppy_InsertDiskIntoDrive(int Drive)
! 321: {
! 322: long nImageBytes = 0;
! 323: char *filename;
! 324:
! 325: /* Eject disk, if one is inserted (doesn't inform user) */
! 326: assert(Drive >= 0 && Drive < MAX_FLOPPYDRIVES);
! 327: Floppy_EjectDiskFromDrive(Drive);
! 328:
! 329: filename = ConfigureParams.DiskImage.szDiskFileName[Drive];
! 330: if (!filename[0])
! 331: {
! 332: return TRUE; /* only do eject */
! 333: }
! 334: if (!File_Exists(filename))
! 335: {
! 336: Log_AlertDlg(LOG_INFO, "Image '%s' not found", filename);
! 337: return FALSE;
! 338: }
! 339:
1.1.1.10 root 340: /* Check disk image type and read the file: */
1.1.1.11 root 341: if (MSA_FileNameIsMSA(filename, TRUE))
342: EmulationDrives[Drive].pBuffer = MSA_ReadDisk(filename, &nImageBytes);
343: else if (ST_FileNameIsST(filename, TRUE))
344: EmulationDrives[Drive].pBuffer = ST_ReadDisk(filename, &nImageBytes);
345: else if (DIM_FileNameIsDIM(filename, TRUE))
346: EmulationDrives[Drive].pBuffer = DIM_ReadDisk(filename, &nImageBytes);
347: else if (ZIP_FileNameIsZIP(filename))
1.1.1.12! root 348: {
! 349: const char *zippath = ConfigureParams.DiskImage.szDiskZipPath[Drive];
! 350: EmulationDrives[Drive].pBuffer = ZIP_ReadDisk(filename, zippath, &nImageBytes);
! 351: }
1.1.1.11 root 352:
353: if (EmulationDrives[Drive].pBuffer == NULL)
354: {
1.1.1.12! root 355: return FALSE;
1.1.1.11 root 356: }
1.1.1.12! root 357: /* Store image filename, size and set drive states */
1.1.1.11 root 358: EmulationDrives[Drive].nImageBytes = nImageBytes;
359: EmulationDrives[Drive].bDiskInserted = TRUE;
360: EmulationDrives[Drive].bContentsChanged = FALSE;
361: EmulationDrives[Drive].bMediaChanged = TRUE;
362: EmulationDrives[Drive].bOKToSave = Floppy_IsBootSectorOK(Drive);
1.1.1.12! root 363: Log_Printf(LOG_INFO, "Inserted disk '%s' to drive %c:.",
! 364: filename, 'A'+Drive);
! 365: return TRUE;
1.1 root 366: }
367:
1.1.1.2 root 368:
369: /*-----------------------------------------------------------------------*/
1.1.1.11 root 370: /**
371: * Eject disk from floppy drive, save contents back to PCs hard-drive if
372: * they have been changed.
1.1.1.12! root 373: * Return TRUE if there was something to eject.
1.1.1.11 root 374: */
1.1.1.12! root 375: bool Floppy_EjectDiskFromDrive(int Drive)
1.1 root 376: {
1.1.1.12! root 377: bool bEjected = FALSE;
! 378:
1.1.1.10 root 379: /* Does our drive have a disk in? */
380: if (EmulationDrives[Drive].bDiskInserted)
381: {
1.1.1.12! root 382: char *psFileName = ConfigureParams.DiskImage.szDiskFileName[Drive];
! 383:
1.1.1.10 root 384: /* OK, has contents changed? If so, need to save */
385: if (EmulationDrives[Drive].bContentsChanged)
386: {
387: /* Is OK to save image (if boot-sector is bad, don't allow a save) */
388: if (EmulationDrives[Drive].bOKToSave && !Floppy_IsWriteProtected(Drive))
389: {
390: /* Save as .MSA or .ST image? */
1.1.1.12! root 391: if (MSA_FileNameIsMSA(psFileName, TRUE))
! 392: MSA_WriteDisk(psFileName, EmulationDrives[Drive].pBuffer, EmulationDrives[Drive].nImageBytes);
! 393: else if (ST_FileNameIsST(psFileName, TRUE))
! 394: ST_WriteDisk(psFileName, EmulationDrives[Drive].pBuffer, EmulationDrives[Drive].nImageBytes);
! 395: else if (DIM_FileNameIsDIM(psFileName, TRUE))
! 396: DIM_WriteDisk(psFileName, EmulationDrives[Drive].pBuffer, EmulationDrives[Drive].nImageBytes);
! 397: else if (ZIP_FileNameIsZIP(psFileName))
! 398: ZIP_WriteDisk(psFileName, EmulationDrives[Drive].pBuffer, EmulationDrives[Drive].nImageBytes);
1.1.1.10 root 399: }
400: }
401:
402: /* Inform user that disk has been ejected! */
1.1.1.12! root 403: Log_Printf(LOG_INFO, "Floppy %c: has been removed from drive.",
! 404: 'A'+Drive);
! 405:
! 406: bEjected = TRUE;
1.1.1.10 root 407: }
408:
409: /* Drive is now empty */
410: if (EmulationDrives[Drive].pBuffer != NULL)
411: {
412: free(EmulationDrives[Drive].pBuffer);
413: EmulationDrives[Drive].pBuffer = NULL;
414: }
1.1.1.12! root 415:
1.1.1.10 root 416: EmulationDrives[Drive].nImageBytes = 0;
417: EmulationDrives[Drive].bDiskInserted = FALSE;
418: EmulationDrives[Drive].bContentsChanged = FALSE;
419: EmulationDrives[Drive].bOKToSave = FALSE;
1.1.1.12! root 420:
! 421: return bEjected;
1.1 root 422: }
423:
1.1.1.2 root 424:
425: /*-----------------------------------------------------------------------*/
1.1.1.11 root 426: /**
427: * Eject all disk image from floppy drives - call when quit.
1.1.1.12! root 428: * Return TRUE if there was something to eject.
1.1.1.11 root 429: */
1.1.1.12! root 430: bool Floppy_EjectBothDrives(void)
1.1 root 431: {
1.1.1.12! root 432: bool bEjectedA, bEjectedB;
! 433:
1.1.1.10 root 434: /* Eject disk images from drives 'A' and 'B' */
1.1.1.12! root 435: bEjectedA = Floppy_EjectDiskFromDrive(0);
! 436: bEjectedB = Floppy_EjectDiskFromDrive(1);
! 437:
! 438: return bEjectedA || bEjectedB;
1.1 root 439: }
440:
1.1.1.2 root 441:
442: /*-----------------------------------------------------------------------*/
1.1.1.11 root 443: /**
444: * Double-check information read from boot-sector as this is sometimes found to
445: * be incorrect. The .ST image file should be divisible by the sector size and
446: * sectors per track.
447: * NOTE - Pass information from boot-sector to this function (if we can't
448: * decide we leave it alone).
449: */
1.1.1.9 root 450: static void Floppy_DoubleCheckFormat(long nDiskSize, Uint16 *pnSides, Uint16 *pnSectorsPerTrack)
1.1 root 451: {
1.1.1.10 root 452: int nSectorsPerTrack;
453: long TotalSectors;
1.1 root 454:
1.1.1.10 root 455: /* Now guess at number of sides */
456: if (nDiskSize < (500*1024)) /* Is size is >500k assume 2 sides to disk! */
457: *pnSides = 1;
458: else
459: *pnSides = 2;
460:
461: /* And Sectors Per Track(always 512 bytes per sector) */
462: TotalSectors = nDiskSize/512; /* # Sectors on disk image */
463: /* Does this match up with what we've read from boot-sector? */
464: nSectorsPerTrack = *pnSectorsPerTrack;
465: if (nSectorsPerTrack==0) /* Check valid, default to 9 */
466: nSectorsPerTrack = 9;
467: if ((TotalSectors%nSectorsPerTrack)!=0)
468: {
469: /* No, we have an invalid boot-sector - re-calculate from disk size */
470: if ((TotalSectors%9)==0) /* Work in this order.... */
471: *pnSectorsPerTrack = 9;
472: else if ((TotalSectors%10)==0)
473: *pnSectorsPerTrack = 10;
474: else if ((TotalSectors%11)==0)
475: *pnSectorsPerTrack = 11;
476: else if ((TotalSectors%12)==0)
477: *pnSectorsPerTrack = 12;
478: }
479: /* else unknown, assume boot-sector is correct!!! */
1.1 root 480: }
481:
1.1.1.2 root 482:
483: /*-----------------------------------------------------------------------*/
1.1.1.11 root 484: /**
485: * Find details of disk image. We need to do this via a function as sometimes the boot-block
486: * is not actually correct with the image - some demos/game disks have incorrect bytes in the
487: * boot sector and this attempts to find the correct values.
488: */
1.1.1.9 root 489: void Floppy_FindDiskDetails(const Uint8 *pBuffer, int nImageBytes,
1.1.1.12! root 490: Uint16 *pnSectorsPerTrack, Uint16 *pnSides)
1.1 root 491: {
1.1.1.10 root 492: Uint16 nSectorsPerTrack, nSides, nSectors;
1.1 root 493:
1.1.1.10 root 494: /* First do check to find number of sectors and bytes per sector */
495: nSectorsPerTrack = SDL_SwapLE16(*(const Uint16 *)(pBuffer+24)); /* SPT */
496: nSides = SDL_SwapLE16(*(const Uint16 *)(pBuffer+26)); /* SIDE */
497: nSectors = pBuffer[19] | (pBuffer[20] << 8); /* total sectors */
498:
499: /* If the number of sectors announced is incorrect, the boot-sector may
500: * contain incorrect information, eg the 'Eat.st' demo, or wrongly imaged
501: * single/double sided floppies... */
502: if (nSectors != nImageBytes/512)
503: Floppy_DoubleCheckFormat(nImageBytes, &nSides, &nSectorsPerTrack);
504:
505: /* And set values */
506: if (pnSectorsPerTrack)
507: *pnSectorsPerTrack = nSectorsPerTrack;
508: if (pnSides)
509: *pnSides = nSides;
1.1 root 510: }
511:
1.1.1.2 root 512:
513: /*-----------------------------------------------------------------------*/
1.1.1.11 root 514: /**
515: * Read sectors from floppy disk image, return TRUE if all OK
516: * NOTE Pass -ve as Count to read whole track
517: */
1.1.1.12! root 518: bool Floppy_ReadSectors(int Drive, Uint8 *pBuffer, Uint16 Sector,
! 519: Uint16 Track, Uint16 Side, short Count,
1.1.1.9 root 520: int *pnSectorsPerTrack)
1.1 root 521: {
1.1.1.10 root 522: Uint8 *pDiskBuffer;
1.1.1.12! root 523: Uint16 nSectorsPerTrack, nSides, nBytesPerTrack;
1.1.1.10 root 524: long Offset;
525: int nImageTracks;
526:
527: /* Do we have a disk in our drive? */
528: if (EmulationDrives[Drive].bDiskInserted)
529: {
530: /* Looks good */
531: pDiskBuffer = EmulationDrives[Drive].pBuffer;
532:
533: /* Find #sides and #sectors per track */
534: Floppy_FindDiskDetails(EmulationDrives[Drive].pBuffer,EmulationDrives[Drive].nImageBytes,&nSectorsPerTrack,&nSides);
535: nImageTracks = ((EmulationDrives[Drive].nImageBytes / NUMBYTESPERSECTOR) / nSectorsPerTrack) / nSides;
536:
537: /* Need to read whole track? */
538: if (Count<0)
539: Count = nSectorsPerTrack;
540: /* Write back number of sector per track */
541: if (pnSectorsPerTrack)
542: *pnSectorsPerTrack = nSectorsPerTrack;
543:
544: /* Debug check as if we read over the end of a track we read into side 2! */
545: if (Count > nSectorsPerTrack)
546: {
547: Log_Printf(LOG_DEBUG, "Floppy_ReadSectors: reading over single track\n");
548: }
549:
550: /* Check that the side number (0 or 1) does not exceed the amount of sides (1 or 2).
551: * (E.g. some games like Drakkhen or Bolo can load additional data from the
552: * second disk side, but they also work with single side floppy drives) */
553: if (Side >= nSides)
554: {
555: Log_Printf(LOG_DEBUG, "Floppy_ReadSectors: Program tries to read from side %i "
556: "of a disk image with %i sides!\n", Side+1, nSides);
557: return FALSE;
558: }
559:
560: /* Check if track number is in range */
561: if (Track >= nImageTracks)
562: {
563: Log_Printf(LOG_DEBUG, "Floppy_ReadSectors: Program tries to read from track %i "
564: "of a disk image with only %i tracks!\n", Track, nImageTracks);
565: return FALSE;
566: }
567:
568: /* Check if sector number is in range */
569: if (Sector <= 0 || Sector > nSectorsPerTrack)
570: {
571: Log_Printf(LOG_DEBUG, "Floppy_ReadSectors: Program tries to read from sector %i "
572: "of a disk image with %i sectors per track!\n", Sector, nSectorsPerTrack);
573: return FALSE;
574: }
575:
576: /* Seek to sector */
577: nBytesPerTrack = NUMBYTESPERSECTOR*nSectorsPerTrack;
578: Offset = nBytesPerTrack*Side; /* First seek to side */
579: Offset += (nBytesPerTrack*nSides)*Track; /* Then seek to track */
580: Offset += (NUMBYTESPERSECTOR*(Sector-1)); /* And finally to sector */
1.1.1.6 root 581:
1.1.1.10 root 582: /* Read sectors (usually 512 bytes per sector) */
583: memcpy(pBuffer, pDiskBuffer+Offset, (int)Count*NUMBYTESPERSECTOR);
1.1 root 584:
1.1.1.10 root 585: return TRUE;
586: }
1.1 root 587:
1.1.1.10 root 588: return FALSE;
1.1 root 589: }
590:
1.1.1.2 root 591:
592: /*-----------------------------------------------------------------------*/
1.1.1.11 root 593: /**
594: * Write sectors from floppy disk image, return TRUE if all OK
595: * NOTE Pass -ve as Count to write whole track
596: */
1.1.1.12! root 597: bool Floppy_WriteSectors(int Drive, Uint8 *pBuffer, Uint16 Sector,
! 598: Uint16 Track, Uint16 Side, short Count,
1.1.1.9 root 599: int *pnSectorsPerTrack)
1.1 root 600: {
1.1.1.10 root 601: Uint8 *pDiskBuffer;
1.1.1.12! root 602: Uint16 nSectorsPerTrack, nSides, nBytesPerTrack;
1.1.1.10 root 603: long Offset;
604: int nImageTracks;
605:
606: /* Do we have a writable disk in our drive? */
607: if (EmulationDrives[Drive].bDiskInserted && !Floppy_IsWriteProtected(Drive))
608: {
609: /* Looks good */
610: pDiskBuffer = EmulationDrives[Drive].pBuffer;
611:
612: /* Find #sides and #sectors per track */
613: Floppy_FindDiskDetails(EmulationDrives[Drive].pBuffer,EmulationDrives[Drive].nImageBytes,&nSectorsPerTrack,&nSides);
614: nImageTracks = ((EmulationDrives[Drive].nImageBytes / NUMBYTESPERSECTOR) / nSectorsPerTrack) / nSides;
615:
616: /* Need to write whole track? */
617: if (Count<0)
618: Count = nSectorsPerTrack;
619: /* Write back number of sector per track */
620: if (pnSectorsPerTrack)
621: *pnSectorsPerTrack = nSectorsPerTrack;
622:
623: /* Debug check as if we write over the end of a track we write into side 2! */
624: if (Count > nSectorsPerTrack)
625: {
626: Log_Printf(LOG_DEBUG, "Floppy_WriteSectors: writing over single track\n");
627: }
628:
629: /* Check that the side number (0 or 1) does not exceed the amount of sides (1 or 2). */
630: if (Side >= nSides)
631: {
632: Log_Printf(LOG_DEBUG, "Floppy_WriteSectors: Program tries to write to side %i "
633: "of a disk image with %i sides!\n", Side+1, nSides);
634: return FALSE;
635: }
636:
637: /* Check if track number is in range */
638: if (Track >= nImageTracks)
639: {
640: Log_Printf(LOG_DEBUG, "Floppy_WriteSectors: Program tries to write to track %i "
641: "of a disk image with only %i tracks!\n", Track, nImageTracks);
642: return FALSE;
643: }
644:
645: /* Check if sector number is in range */
646: if (Sector <= 0 || Sector > nSectorsPerTrack)
647: {
648: Log_Printf(LOG_DEBUG, "Floppy_WriteSectors: Program tries to write to sector %i "
649: "of a disk image with %i sectors per track!\n", Sector, nSectorsPerTrack);
650: return FALSE;
651: }
652:
653: /* Seek to sector */
654: nBytesPerTrack = NUMBYTESPERSECTOR*nSectorsPerTrack;
655: Offset = nBytesPerTrack*Side; /* First seek to side */
656: Offset += (nBytesPerTrack*nSides)*Track; /* Then seek to track */
657: Offset += (NUMBYTESPERSECTOR*(Sector-1)); /* And finally to sector */
658:
659: /* Write sectors (usually 512 bytes per sector) */
660: memcpy(pDiskBuffer+Offset, pBuffer, (int)Count*NUMBYTESPERSECTOR);
661: /* And set 'changed' flag */
662: EmulationDrives[Drive].bContentsChanged = TRUE;
1.1 root 663:
1.1.1.10 root 664: return TRUE;
665: }
1.1 root 666:
1.1.1.10 root 667: return FALSE;
1.1 root 668: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.