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