|
|
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.11! root 24: const char Floppy_rcsid[] = "Hatari $Id: floppy.c,v 1.35 2008/01/07 21:54:22 eerot 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.1.11! root 58: /**
! 59: * Initialize emulation floppy drives
! 60: */
1.1 root 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.1.11! root 75: /**
! 76: * UnInitialize drives
! 77: */
1.1 root 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.1.11! root 85: /**
! 86: * Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
! 87: */
1.1 root 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.1.11! root 118: /**
! 119: * Find which device to boot from (hard drive or floppy).
! 120: */
1.1 root 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.1.11! root 132: /**
! 133: * Test if disk image is write protected. Write protection can be configured
! 134: * in the GUI. When set to "automatic", we check the file permissions of the
! 135: * floppy disk image to decide.
! 136: */
1.1.1.8 root 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: /*-----------------------------------------------------------------------*/
1.1.1.11! root 160: /**
! 161: * Test disk image for valid boot-sector.
! 162: * It has been noticed that some disks, eg blank images made by the MakeDisk
! 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.
! 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.
! 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.1.11! root 195: /**
! 196: * Try to create disk B filename, eg 'auto_100a' becomes 'auto_100b'
! 197: * Return new filename if think we should try, otherwise NULL
! 198: */
! 199: static char* Floppy_CreateDiskBFileName(const char *pSrcFileName)
1.1 root 200: {
1.1.1.10 root 201: char *szDir, *szName, *szExt;
1.1.1.11! root 202:
1.1.1.10 root 203: /* Allocate temporary memory for strings: */
204: szDir = malloc(3 * FILENAME_MAX);
205: if (!szDir)
206: {
207: perror("Floppy_CreateDiskBFileName");
208: return FALSE;
209: }
210: szName = szDir + FILENAME_MAX;
211: szExt = szName + FILENAME_MAX;
212:
213: /* So, first split name into parts */
1.1.1.11! root 214: File_SplitPath(pSrcFileName, szDir, szName, szExt);
1.1.1.10 root 215:
216: /* All OK? */
217: if (strlen(szName) > 0)
218: {
219: /* Now, did filename end with an 'A' or 'a'? */
220: if ((szName[strlen(szName)-1]=='A') || (szName[strlen(szName)-1]=='a'))
221: {
1.1.1.11! root 222: char *szFull;
1.1.1.10 root 223: /* Change 'A' to a 'B' */
224: szName[strlen(szName)-1] += 1;
225: /* And re-build name into destination */
1.1.1.11! root 226: szFull = File_MakePath(szDir, szName, szExt);
! 227: if (szFull)
! 228: {
! 229: /* Does file exist? */
! 230: if (File_Exists(szFull))
! 231: {
! 232: free(szDir);
! 233: return szFull;
! 234: }
! 235: free(szFull);
! 236: }
1.1.1.10 root 237: }
238: }
239: free(szDir);
1.1.1.11! root 240: return NULL;
1.1 root 241: }
242:
1.1.1.2 root 243:
244: /*-----------------------------------------------------------------------*/
1.1.1.11! root 245: /**
! 246: * Insert disk into floppy drive. Sets the disk image name
! 247: * back to given string with corrected extension. Maxlen is
! 248: * maximum string lenght.
! 249: * Returns TRUE of success and FALSE for failure.
! 250: * The WHOLE image is copied into our drive buffers,
! 251: * and uncompressed if necessary
! 252: */
! 253: BOOL Floppy_InsertDiskIntoDrive(int Drive, char *pszFileName, int maxlen)
1.1 root 254: {
1.1.1.11! root 255: char *path;
! 256: path = Floppy_ZipInsertDiskIntoDrive(Drive, pszFileName, NULL);
! 257: if (path)
! 258: {
! 259: strncpy(pszFileName, path, maxlen);
! 260: pszFileName[maxlen-1] = '\0';
! 261: free(path);
! 262: return TRUE;
! 263: }
! 264: return FALSE;
1.1.1.6 root 265: }
266:
1.1.1.11! root 267: /* Read image into buffers, handles different image extensions,
! 268: * return corrected file name on success and NULL on failure.
! 269: */
! 270: char* Floppy_ZipInsertDiskIntoDrive(int Drive, const char *pszFileName, const char *pszZipPath)
1.1.1.6 root 271: {
1.1.1.10 root 272: long nImageBytes = 0;
1.1.1.11! root 273: char *filename;
1.1 root 274:
1.1.1.11! root 275: /* Eject disk, if one is inserted (doesn't inform user) */
1.1.1.10 root 276: Floppy_EjectDiskFromDrive(Drive,FALSE);
1.1 root 277:
1.1.1.11! root 278: /* See if file exists, and if not, get/add correct extension */
1.1.1.10 root 279: if ( !File_Exists(pszFileName) )
1.1.1.11! root 280: filename = File_FindPossibleExtFileName(pszFileName, pszDiskImageNameExts);
! 281: else
! 282: filename = strdup(pszFileName);
! 283:
1.1.1.10 root 284: /* Check disk image type and read the file: */
1.1.1.11! root 285: if (MSA_FileNameIsMSA(filename, TRUE))
! 286: EmulationDrives[Drive].pBuffer = MSA_ReadDisk(filename, &nImageBytes);
! 287: else if (ST_FileNameIsST(filename, TRUE))
! 288: EmulationDrives[Drive].pBuffer = ST_ReadDisk(filename, &nImageBytes);
! 289: else if (DIM_FileNameIsDIM(filename, TRUE))
! 290: EmulationDrives[Drive].pBuffer = DIM_ReadDisk(filename, &nImageBytes);
! 291: else if (ZIP_FileNameIsZIP(filename))
! 292: EmulationDrives[Drive].pBuffer = ZIP_ReadDisk(filename, pszZipPath, &nImageBytes);
! 293:
! 294: if (EmulationDrives[Drive].pBuffer == NULL)
! 295: {
! 296: free(filename);
! 297: return NULL;
! 298: }
! 299: /* Store filename and size */
! 300: strcpy(EmulationDrives[Drive].szFileName, filename);
! 301: EmulationDrives[Drive].nImageBytes = nImageBytes;
! 302: /* And set drive states */
! 303: EmulationDrives[Drive].bDiskInserted = TRUE;
! 304: EmulationDrives[Drive].bContentsChanged = FALSE;
! 305: EmulationDrives[Drive].bMediaChanged = TRUE;
! 306: EmulationDrives[Drive].bOKToSave = Floppy_IsBootSectorOK(Drive);
1.1.1.10 root 307:
1.1.1.11! root 308: /* If we insert a disk into Drive A, should we try to put disk 2 into drive B? */
1.1.1.10 root 309: if (Drive == 0 && ConfigureParams.DiskImage.bAutoInsertDiskB)
310: {
1.1.1.11! root 311: char *szTmp;
1.1.1.10 root 312: /* Attempt to make up second filename, eg was 'auto_100a' to 'auto_100b' */
1.1.1.11! root 313: char *szDiskBFileName = Floppy_CreateDiskBFileName(filename);
! 314: if (szDiskBFileName)
1.1.1.10 root 315: {
1.1.1.11! root 316: /* recurse with Drive B */
! 317: szTmp = Floppy_ZipInsertDiskIntoDrive(1, szDiskBFileName, NULL);
! 318: if (szTmp)
! 319: free(szTmp);
! 320: free(szDiskBFileName);
1.1.1.10 root 321: }
322: }
1.1.1.11! root 323: return filename;
1.1 root 324: }
325:
1.1.1.2 root 326:
327: /*-----------------------------------------------------------------------*/
1.1.1.11! root 328: /**
! 329: * Eject disk from floppy drive, save contents back to PCs hard-drive if
! 330: * they have been changed.
! 331: */
1.1.1.9 root 332: void Floppy_EjectDiskFromDrive(int Drive, BOOL bInformUser)
1.1 root 333: {
1.1.1.10 root 334: /* Does our drive have a disk in? */
335: if (EmulationDrives[Drive].bDiskInserted)
336: {
337: /* OK, has contents changed? If so, need to save */
338: if (EmulationDrives[Drive].bContentsChanged)
339: {
340: /* Is OK to save image (if boot-sector is bad, don't allow a save) */
341: if (EmulationDrives[Drive].bOKToSave && !Floppy_IsWriteProtected(Drive))
342: {
343: /* Save as .MSA or .ST image? */
344: if (MSA_FileNameIsMSA(EmulationDrives[Drive].szFileName, TRUE))
345: MSA_WriteDisk(EmulationDrives[Drive].szFileName, EmulationDrives[Drive].pBuffer, EmulationDrives[Drive].nImageBytes);
346: else if (ST_FileNameIsST(EmulationDrives[Drive].szFileName, TRUE))
347: ST_WriteDisk(EmulationDrives[Drive].szFileName, EmulationDrives[Drive].pBuffer, EmulationDrives[Drive].nImageBytes);
348: else if (DIM_FileNameIsDIM(EmulationDrives[Drive].szFileName, TRUE))
349: DIM_WriteDisk(EmulationDrives[Drive].szFileName, EmulationDrives[Drive].pBuffer, EmulationDrives[Drive].nImageBytes);
350: else if (ZIP_FileNameIsZIP(EmulationDrives[Drive].szFileName))
351: ZIP_WriteDisk(EmulationDrives[Drive].szFileName, EmulationDrives[Drive].pBuffer, EmulationDrives[Drive].nImageBytes);
352: }
353: }
354:
355: /* Inform user that disk has been ejected! */
356: if (bInformUser)
357: {
358: Log_AlertDlg(LOG_INFO, "Disk has been removed from drive '%c:'.", 'A'+Drive);
359: }
360: }
361:
362: /* Drive is now empty */
363: if (EmulationDrives[Drive].pBuffer != NULL)
364: {
365: free(EmulationDrives[Drive].pBuffer);
366: EmulationDrives[Drive].pBuffer = NULL;
367: }
368: strcpy(EmulationDrives[Drive].szFileName,"");
369: EmulationDrives[Drive].nImageBytes = 0;
370: EmulationDrives[Drive].bDiskInserted = FALSE;
371: EmulationDrives[Drive].bContentsChanged = FALSE;
372: EmulationDrives[Drive].bOKToSave = FALSE;
1.1 root 373: }
374:
1.1.1.2 root 375:
376: /*-----------------------------------------------------------------------*/
1.1.1.11! root 377: /**
! 378: * Eject all disk image from floppy drives - call when quit.
! 379: */
1.1 root 380: void Floppy_EjectBothDrives(void)
381: {
1.1.1.10 root 382: /* Eject disk images from drives 'A' and 'B' */
383: Floppy_EjectDiskFromDrive(0, FALSE);
384: Floppy_EjectDiskFromDrive(1, FALSE);
1.1 root 385: }
386:
1.1.1.2 root 387:
388: /*-----------------------------------------------------------------------*/
1.1.1.11! root 389: /**
! 390: * Double-check information read from boot-sector as this is sometimes found to
! 391: * be incorrect. The .ST image file should be divisible by the sector size and
! 392: * sectors per track.
! 393: * NOTE - Pass information from boot-sector to this function (if we can't
! 394: * decide we leave it alone).
! 395: */
1.1.1.9 root 396: static void Floppy_DoubleCheckFormat(long nDiskSize, Uint16 *pnSides, Uint16 *pnSectorsPerTrack)
1.1 root 397: {
1.1.1.10 root 398: int nSectorsPerTrack;
399: long TotalSectors;
1.1 root 400:
1.1.1.10 root 401: /* Now guess at number of sides */
402: if (nDiskSize < (500*1024)) /* Is size is >500k assume 2 sides to disk! */
403: *pnSides = 1;
404: else
405: *pnSides = 2;
406:
407: /* And Sectors Per Track(always 512 bytes per sector) */
408: TotalSectors = nDiskSize/512; /* # Sectors on disk image */
409: /* Does this match up with what we've read from boot-sector? */
410: nSectorsPerTrack = *pnSectorsPerTrack;
411: if (nSectorsPerTrack==0) /* Check valid, default to 9 */
412: nSectorsPerTrack = 9;
413: if ((TotalSectors%nSectorsPerTrack)!=0)
414: {
415: /* No, we have an invalid boot-sector - re-calculate from disk size */
416: if ((TotalSectors%9)==0) /* Work in this order.... */
417: *pnSectorsPerTrack = 9;
418: else if ((TotalSectors%10)==0)
419: *pnSectorsPerTrack = 10;
420: else if ((TotalSectors%11)==0)
421: *pnSectorsPerTrack = 11;
422: else if ((TotalSectors%12)==0)
423: *pnSectorsPerTrack = 12;
424: }
425: /* else unknown, assume boot-sector is correct!!! */
1.1 root 426: }
427:
1.1.1.2 root 428:
429: /*-----------------------------------------------------------------------*/
1.1.1.11! root 430: /**
! 431: * Find details of disk image. We need to do this via a function as sometimes the boot-block
! 432: * is not actually correct with the image - some demos/game disks have incorrect bytes in the
! 433: * boot sector and this attempts to find the correct values.
! 434: */
1.1.1.9 root 435: void Floppy_FindDiskDetails(const Uint8 *pBuffer, int nImageBytes,
436: unsigned short *pnSectorsPerTrack, unsigned short *pnSides)
1.1 root 437: {
1.1.1.10 root 438: Uint16 nSectorsPerTrack, nSides, nSectors;
1.1 root 439:
1.1.1.10 root 440: /* First do check to find number of sectors and bytes per sector */
441: nSectorsPerTrack = SDL_SwapLE16(*(const Uint16 *)(pBuffer+24)); /* SPT */
442: nSides = SDL_SwapLE16(*(const Uint16 *)(pBuffer+26)); /* SIDE */
443: nSectors = pBuffer[19] | (pBuffer[20] << 8); /* total sectors */
444:
445: /* If the number of sectors announced is incorrect, the boot-sector may
446: * contain incorrect information, eg the 'Eat.st' demo, or wrongly imaged
447: * single/double sided floppies... */
448: if (nSectors != nImageBytes/512)
449: Floppy_DoubleCheckFormat(nImageBytes, &nSides, &nSectorsPerTrack);
450:
451: /* And set values */
452: if (pnSectorsPerTrack)
453: *pnSectorsPerTrack = nSectorsPerTrack;
454: if (pnSides)
455: *pnSides = nSides;
1.1 root 456: }
457:
1.1.1.2 root 458:
459: /*-----------------------------------------------------------------------*/
1.1.1.11! root 460: /**
! 461: * Read sectors from floppy disk image, return TRUE if all OK
! 462: * NOTE Pass -ve as Count to read whole track
! 463: */
1.1.1.9 root 464: BOOL Floppy_ReadSectors(int Drive, Uint8 *pBuffer, unsigned short Sector,
465: unsigned short Track, unsigned short Side, short Count,
466: int *pnSectorsPerTrack)
1.1 root 467: {
1.1.1.10 root 468: Uint8 *pDiskBuffer;
469: unsigned short int nSectorsPerTrack,nSides,nBytesPerTrack;
470: long Offset;
471: int nImageTracks;
472:
473: /* Do we have a disk in our drive? */
474: if (EmulationDrives[Drive].bDiskInserted)
475: {
476: /* Looks good */
477: pDiskBuffer = EmulationDrives[Drive].pBuffer;
478:
479: /* Find #sides and #sectors per track */
480: Floppy_FindDiskDetails(EmulationDrives[Drive].pBuffer,EmulationDrives[Drive].nImageBytes,&nSectorsPerTrack,&nSides);
481: nImageTracks = ((EmulationDrives[Drive].nImageBytes / NUMBYTESPERSECTOR) / nSectorsPerTrack) / nSides;
482:
483: /* Need to read whole track? */
484: if (Count<0)
485: Count = nSectorsPerTrack;
486: /* Write back number of sector per track */
487: if (pnSectorsPerTrack)
488: *pnSectorsPerTrack = nSectorsPerTrack;
489:
490: /* Debug check as if we read over the end of a track we read into side 2! */
491: if (Count > nSectorsPerTrack)
492: {
493: Log_Printf(LOG_DEBUG, "Floppy_ReadSectors: reading over single track\n");
494: }
495:
496: /* Check that the side number (0 or 1) does not exceed the amount of sides (1 or 2).
497: * (E.g. some games like Drakkhen or Bolo can load additional data from the
498: * second disk side, but they also work with single side floppy drives) */
499: if (Side >= nSides)
500: {
501: Log_Printf(LOG_DEBUG, "Floppy_ReadSectors: Program tries to read from side %i "
502: "of a disk image with %i sides!\n", Side+1, nSides);
503: return FALSE;
504: }
505:
506: /* Check if track number is in range */
507: if (Track >= nImageTracks)
508: {
509: Log_Printf(LOG_DEBUG, "Floppy_ReadSectors: Program tries to read from track %i "
510: "of a disk image with only %i tracks!\n", Track, nImageTracks);
511: return FALSE;
512: }
513:
514: /* Check if sector number is in range */
515: if (Sector <= 0 || Sector > nSectorsPerTrack)
516: {
517: Log_Printf(LOG_DEBUG, "Floppy_ReadSectors: Program tries to read from sector %i "
518: "of a disk image with %i sectors per track!\n", Sector, nSectorsPerTrack);
519: return FALSE;
520: }
521:
522: /* Seek to sector */
523: nBytesPerTrack = NUMBYTESPERSECTOR*nSectorsPerTrack;
524: Offset = nBytesPerTrack*Side; /* First seek to side */
525: Offset += (nBytesPerTrack*nSides)*Track; /* Then seek to track */
526: Offset += (NUMBYTESPERSECTOR*(Sector-1)); /* And finally to sector */
1.1.1.6 root 527:
1.1.1.10 root 528: /* Read sectors (usually 512 bytes per sector) */
529: memcpy(pBuffer, pDiskBuffer+Offset, (int)Count*NUMBYTESPERSECTOR);
1.1 root 530:
1.1.1.10 root 531: return TRUE;
532: }
1.1 root 533:
1.1.1.10 root 534: return FALSE;
1.1 root 535: }
536:
1.1.1.2 root 537:
538: /*-----------------------------------------------------------------------*/
1.1.1.11! root 539: /**
! 540: * Write sectors from floppy disk image, return TRUE if all OK
! 541: * NOTE Pass -ve as Count to write whole track
! 542: */
1.1.1.9 root 543: BOOL Floppy_WriteSectors(int Drive, Uint8 *pBuffer, unsigned short Sector,
544: unsigned short Track, unsigned short Side, short Count,
545: int *pnSectorsPerTrack)
1.1 root 546: {
1.1.1.10 root 547: Uint8 *pDiskBuffer;
548: unsigned short int nSectorsPerTrack,nSides,nBytesPerTrack;
549: long Offset;
550: int nImageTracks;
551:
552: /* Do we have a writable disk in our drive? */
553: if (EmulationDrives[Drive].bDiskInserted && !Floppy_IsWriteProtected(Drive))
554: {
555: /* Looks good */
556: pDiskBuffer = EmulationDrives[Drive].pBuffer;
557:
558: /* Find #sides and #sectors per track */
559: Floppy_FindDiskDetails(EmulationDrives[Drive].pBuffer,EmulationDrives[Drive].nImageBytes,&nSectorsPerTrack,&nSides);
560: nImageTracks = ((EmulationDrives[Drive].nImageBytes / NUMBYTESPERSECTOR) / nSectorsPerTrack) / nSides;
561:
562: /* Need to write whole track? */
563: if (Count<0)
564: Count = nSectorsPerTrack;
565: /* Write back number of sector per track */
566: if (pnSectorsPerTrack)
567: *pnSectorsPerTrack = nSectorsPerTrack;
568:
569: /* Debug check as if we write over the end of a track we write into side 2! */
570: if (Count > nSectorsPerTrack)
571: {
572: Log_Printf(LOG_DEBUG, "Floppy_WriteSectors: writing over single track\n");
573: }
574:
575: /* Check that the side number (0 or 1) does not exceed the amount of sides (1 or 2). */
576: if (Side >= nSides)
577: {
578: Log_Printf(LOG_DEBUG, "Floppy_WriteSectors: Program tries to write to side %i "
579: "of a disk image with %i sides!\n", Side+1, nSides);
580: return FALSE;
581: }
582:
583: /* Check if track number is in range */
584: if (Track >= nImageTracks)
585: {
586: Log_Printf(LOG_DEBUG, "Floppy_WriteSectors: Program tries to write to track %i "
587: "of a disk image with only %i tracks!\n", Track, nImageTracks);
588: return FALSE;
589: }
590:
591: /* Check if sector number is in range */
592: if (Sector <= 0 || Sector > nSectorsPerTrack)
593: {
594: Log_Printf(LOG_DEBUG, "Floppy_WriteSectors: Program tries to write to sector %i "
595: "of a disk image with %i sectors per track!\n", Sector, nSectorsPerTrack);
596: return FALSE;
597: }
598:
599: /* Seek to sector */
600: nBytesPerTrack = NUMBYTESPERSECTOR*nSectorsPerTrack;
601: Offset = nBytesPerTrack*Side; /* First seek to side */
602: Offset += (nBytesPerTrack*nSides)*Track; /* Then seek to track */
603: Offset += (NUMBYTESPERSECTOR*(Sector-1)); /* And finally to sector */
604:
605: /* Write sectors (usually 512 bytes per sector) */
606: memcpy(pDiskBuffer+Offset, pBuffer, (int)Count*NUMBYTESPERSECTOR);
607: /* And set 'changed' flag */
608: EmulationDrives[Drive].bContentsChanged = TRUE;
1.1 root 609:
1.1.1.10 root 610: return TRUE;
611: }
1.1 root 612:
1.1.1.10 root 613: return FALSE;
1.1 root 614: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.