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