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