|
|
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.7 ! root 24: char Floppy_rcsid[] = "Hatari $Id: floppy.c,v 1.19 2004/07/01 20:54:10 thothy Exp $";
1.1 root 25:
1.1.1.4 root 26: #include <SDL_endian.h>
27:
1.1 root 28: #include "main.h"
29: #include "debug.h"
1.1.1.6 root 30: #include "configuration.h"
1.1.1.7 ! root 31: #include "dim.h"
1.1 root 32: #include "errlog.h"
33: #include "file.h"
34: #include "floppy.h"
35: #include "memorySnapShot.h"
36: #include "misc.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.5 root 45: char *pszDiscImageNameExts[] =
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: /*
130: Test disc image for valid boot-sector
131:
1.1.1.5 root 132: It has been noticed that some discs, eg blank images made by the (current)
133: MakeDisk utility fill in the boot-sector with incorrect information. Such
134: images cannot be read correctly using a real ST, and also Hatari.
135: To try and prevent data loss, we check for this error and flag the drive so
136: the image will not be saved back to the file.
1.1 root 137: */
1.1.1.7 ! root 138: static BOOL Floppy_IsBootSectorOK(int Drive)
1.1 root 139: {
1.1.1.5 root 140: char szString[256];
1.1 root 141: unsigned char *pDiscBuffer;
142:
143: /* Does our drive have a disc in? */
1.1.1.5 root 144: if (EmulationDrives[Drive].bDiscInserted)
145: {
1.1 root 146: pDiscBuffer = EmulationDrives[Drive].pBuffer;
1.1.1.5 root 147:
148: /* Check SPC (byte 13) for !=0 value. If is '0', invalid image and Hatari
149: * won't be-able to read (nor will a real ST)! */
1.1 root 150: if (pDiscBuffer[13]!=0)
1.1.1.5 root 151: {
1.1 root 152: return(TRUE); /* Disc sector is OK! */
1.1.1.5 root 153: }
154: else
155: {
156: sprintf(szString, "Disc in drive %c seems to suffer from the Pacifist/Makedisk bug.\n"
157: "If it does not work, please repair the disk first!\n", 'A' + Drive);
158: Main_Message(szString, "Warning");
159: }
1.1 root 160: }
161:
162: return(FALSE); /* Bad sector */
163: }
164:
1.1.1.2 root 165:
166: /*-----------------------------------------------------------------------*/
1.1 root 167: /*
168: Try to create disc B filename, eg 'auto_100a' becomes 'auto_100b'
169: Return TRUE if think we should try!
170: */
1.1.1.7 ! root 171: static BOOL Floppy_CreateDiscBFileName(char *pSrcFileName, char *pDestFileName)
1.1 root 172: {
1.1.1.3 root 173: char szDir[256], szName[128], szExt[32];
1.1 root 174:
1.1.1.3 root 175: /* So, first split name into parts */
176: File_splitpath(pSrcFileName, szDir, szName, szExt);
177: /* All OK? */
1.1.1.5 root 178: if (strlen(szName)>0)
179: {
1.1.1.3 root 180: /* Now, did filename end with an 'A' or 'a'? */
1.1.1.5 root 181: if ( (szName[strlen(szName)-1]=='A') || (szName[strlen(szName)-1]=='a') )
182: {
1.1.1.3 root 183: /* Change 'A' to a 'B' */
184: szName[strlen(szName)-1] += 1;
185: /* And re-build name into destination */
186: File_makepath(pDestFileName,szDir,szName,szExt);
187: /* Does file exist? */
1.1 root 188: if (File_Exists(pDestFileName))
1.1.1.3 root 189: return(TRUE); /* Try this */
1.1 root 190: }
191: }
1.1.1.3 root 192:
1.1.1.2 root 193: return(FALSE); /* No, doesn't have disc B */
1.1 root 194: }
195:
1.1.1.2 root 196:
197: /*-----------------------------------------------------------------------*/
1.1 root 198: /*
199: Insert disc into floppy drive
200: The WHOLE image is copied into our drive buffers, and uncompressed if necessary
201: */
202: BOOL Floppy_InsertDiscIntoDrive(int Drive, char *pszFileName)
203: {
1.1.1.6 root 204: return(Floppy_ZipInsertDiscIntoDrive(Drive, pszFileName, NULL));
205: }
206:
207: BOOL Floppy_ZipInsertDiscIntoDrive(int Drive, char *pszFileName, char *pszZipPath)
208: {
1.1.1.7 ! root 209: long nImageBytes = 0;
1.1 root 210:
211: /* Eject disc, if one is inserted(don't inform user) */
212: Floppy_EjectDiscFromDrive(Drive,FALSE);
213:
214: /* See if file exists, and if not get correct extension */
1.1.1.3 root 215: if( !File_Exists(pszFileName) )
216: File_FindPossibleExtFileName(pszFileName,pszDiscImageNameExts);
1.1 root 217:
1.1.1.7 ! root 218: /* Check disc image type and read the file: */
! 219: if (MSA_FileNameIsMSA(pszFileName, TRUE))
! 220: EmulationDrives[Drive].pBuffer = MSA_ReadDisc(pszFileName, &nImageBytes);
! 221: else if (ST_FileNameIsST(pszFileName, TRUE))
! 222: EmulationDrives[Drive].pBuffer = ST_ReadDisc(pszFileName, &nImageBytes);
! 223: else if (DIM_FileNameIsDIM(pszFileName, TRUE))
! 224: EmulationDrives[Drive].pBuffer = DIM_ReadDisc(pszFileName, &nImageBytes);
! 225: else if (ZIP_FileNameIsZIP(pszFileName))
! 226: EmulationDrives[Drive].pBuffer = ZIP_ReadDisc(pszFileName, pszZipPath, &nImageBytes);
1.1.1.6 root 227:
1.1 root 228: /* Did load OK? */
1.1.1.7 ! root 229: if (EmulationDrives[Drive].pBuffer != NULL)
1.1.1.5 root 230: {
1.1 root 231: /* Store filename and size */
232: strcpy(EmulationDrives[Drive].szFileName,pszFileName);
233: EmulationDrives[Drive].nImageBytes = nImageBytes;
234: /* And set drive states */
235: EmulationDrives[Drive].bDiscInserted = TRUE;
236: EmulationDrives[Drive].bContentsChanged = FALSE;
237: EmulationDrives[Drive].bMediaChanged = TRUE;
238: EmulationDrives[Drive].bOKToSave = Floppy_IsBootSectorOK(Drive);
239: }
240:
241: /* If we insert a disc into Drive A, should be try to put disc 2 into drive B? */
1.1.1.5 root 242: if ( (Drive==0) && (ConfigureParams.DiscImage.bAutoInsertDiscB) )
243: {
1.1.1.7 ! root 244: char *szDiscBFileName = malloc(FILENAME_MAX);
1.1.1.3 root 245: /* Attempt to make up second filename, eg was 'auto_100a' to 'auto_100b' */
1.1.1.7 ! root 246: if (szDiscBFileName && Floppy_CreateDiscBFileName(pszFileName, szDiscBFileName))
1.1.1.5 root 247: {
1.1.1.3 root 248: /* Put image into Drive B, clear out if fails */
1.1 root 249: if (!Floppy_InsertDiscIntoDrive(1,szDiscBFileName))
250: strcpy(EmulationDrives[1].szFileName,"");
251: }
1.1.1.7 ! root 252: free(szDiscBFileName);
1.1 root 253: }
1.1.1.3 root 254:
1.1.1.6 root 255:
1.1 root 256: /* Return TRUE if loaded OK */
1.1.1.7 ! root 257: return (EmulationDrives[Drive].pBuffer != NULL);
1.1 root 258: }
259:
1.1.1.2 root 260:
261: /*-----------------------------------------------------------------------*/
1.1 root 262: /*
1.1.1.5 root 263: Eject disc from floppy drive, save contents back to PCs hard-drive if has changed
1.1 root 264: */
1.1.1.5 root 265: void Floppy_EjectDiscFromDrive(int Drive, BOOL bInformUser)
1.1 root 266: {
267: char szString[256];
268:
269: /* Does our drive have a disc in? */
1.1.1.5 root 270: if (EmulationDrives[Drive].bDiscInserted)
271: {
1.1 root 272: /* OK, has contents changed? If so, need to save */
1.1.1.5 root 273: if (EmulationDrives[Drive].bContentsChanged)
274: {
1.1 root 275: /* Is OK to save image(if boot-sector is bad, don't allow a save) */
1.1.1.5 root 276: if (EmulationDrives[Drive].bOKToSave)
277: {
1.1 root 278: /* Save as .MSA or .ST image? */
1.1.1.7 ! root 279: if (MSA_FileNameIsMSA(EmulationDrives[Drive].szFileName, TRUE))
! 280: MSA_WriteDisc(EmulationDrives[Drive].szFileName, EmulationDrives[Drive].pBuffer, EmulationDrives[Drive].nImageBytes);
! 281: else if (ST_FileNameIsST(EmulationDrives[Drive].szFileName, TRUE))
! 282: ST_WriteDisc(EmulationDrives[Drive].szFileName, EmulationDrives[Drive].pBuffer, EmulationDrives[Drive].nImageBytes);
! 283: else if (DIM_FileNameIsDIM(EmulationDrives[Drive].szFileName, TRUE))
! 284: DIM_WriteDisc(EmulationDrives[Drive].szFileName, EmulationDrives[Drive].pBuffer, EmulationDrives[Drive].nImageBytes);
! 285: else if (ZIP_FileNameIsZIP(EmulationDrives[Drive].szFileName))
! 286: ZIP_WriteDisc(EmulationDrives[Drive].szFileName, EmulationDrives[Drive].pBuffer, EmulationDrives[Drive].nImageBytes);
1.1 root 287: }
288: }
289:
290: /* Inform user that disc has been ejected! */
1.1.1.5 root 291: if (bInformUser)
292: {
1.1 root 293: sprintf(szString,"Disc has been removed from Drive '%c'.",'A'+Drive);
1.1.1.5 root 294: Main_Message(szString, PROG_NAME /*,MB_OK | MB_ICONINFORMATION*/);
1.1 root 295: }
296: }
297:
298: /* Drive is now empty */
1.1.1.7 ! root 299: if (EmulationDrives[Drive].pBuffer != NULL)
! 300: {
! 301: free(EmulationDrives[Drive].pBuffer);
! 302: EmulationDrives[Drive].pBuffer = NULL;
! 303: }
1.1 root 304: strcpy(EmulationDrives[Drive].szFileName,"");
305: EmulationDrives[Drive].nImageBytes = 0;
306: EmulationDrives[Drive].bDiscInserted = FALSE;
307: EmulationDrives[Drive].bContentsChanged = FALSE;
308: EmulationDrives[Drive].bOKToSave = FALSE;
309: }
310:
1.1.1.2 root 311:
312: /*-----------------------------------------------------------------------*/
1.1 root 313: /*
314: Eject all disc image from floppy drives - call when quit
315: */
316: void Floppy_EjectBothDrives(void)
317: {
318: /* Eject disc images from drives 'A' and 'B' */
319: Floppy_EjectDiscFromDrive(0,FALSE);
320: Floppy_EjectDiscFromDrive(1,FALSE);
321: }
322:
1.1.1.2 root 323:
324: /*-----------------------------------------------------------------------*/
1.1 root 325: /*
1.1.1.4 root 326: Double-check information read from boot-sector as this is sometimes found to
327: be incorrect. The .ST image file should be divisible by the sector size and
328: sectors per track.
329: NOTE - Pass information from boot-sector to this function (if we can't
330: decide we leave it alone).
1.1 root 331: */
1.1.1.4 root 332: static void Floppy_DoubleCheckFormat(long DiscSize, Uint16 *pnSides, Uint16 *pnSectorsPerTrack)
1.1 root 333: {
334: int nSectorsPerTrack;
335: long TotalSectors;
336:
337: /* Now guess at number of sides */
338: if (DiscSize<(500*1024)) /* Is size is >500k assume 2 sides to disc! */
339: *pnSides = 1;
340: else
341: *pnSides = 2;
342:
343: /* And Sectors Per Track(always 512 bytes per sector) */
344: TotalSectors = DiscSize/512; /* # Sectors on disc image */
1.1.1.2 root 345: /* Does this match up with what we've read from boot-sector? */
1.1 root 346: nSectorsPerTrack = *pnSectorsPerTrack;
347: if (nSectorsPerTrack==0) /* Check valid, default to 9 */
348: nSectorsPerTrack = 9;
1.1.1.4 root 349: if ((TotalSectors%nSectorsPerTrack)!=0)
350: {
1.1 root 351: /* No, we have an invalid boot-sector - re-calculate from disc size */
352: if ((TotalSectors%9)==0) /* Work in this order.... */
353: *pnSectorsPerTrack = 9;
354: else if ((TotalSectors%10)==0)
355: *pnSectorsPerTrack = 10;
356: else if ((TotalSectors%11)==0)
357: *pnSectorsPerTrack = 11;
358: else if ((TotalSectors%12)==0)
359: *pnSectorsPerTrack = 12;
360: }
361: /* else unknown, assume boot-sector is correct!!! */
362: }
363:
1.1.1.2 root 364:
365: /*-----------------------------------------------------------------------*/
1.1 root 366: /*
367: Find details of disc image. We need to do this via a function as sometimes the boot-block
368: is not actually correct with the image - some demos/game discs have incorrect bytes in the
369: boot sector and this attempts to find the correct values.
370: */
1.1.1.4 root 371: void Floppy_FindDiscDetails(unsigned char *pBuffer, int nImageBytes,
372: unsigned short int *pnSectorsPerTrack, unsigned short int *pnSides)
1.1 root 373: {
1.1.1.7 ! root 374: Uint8 *pDiscBuffer;
! 375: Uint16 nSectorsPerTrack, nSides, nSectors;
1.1 root 376:
377: pDiscBuffer = pBuffer;
1.1.1.7 ! root 378:
1.1 root 379: /* First do check to find number of sectors and bytes per sector */
1.1.1.4 root 380: nSectorsPerTrack = SDL_SwapLE16(*(Uint16 *)(pDiscBuffer+24)); /* SPT */
381: nSides = SDL_SwapLE16(*(Uint16 *)(pDiscBuffer+26)); /* SIDE */
1.1.1.7 ! root 382: nSectors = pDiscBuffer[19] | (pDiscBuffer[20] << 8); /* total sectors */
1.1.1.4 root 383:
1.1.1.7 ! root 384: /* If the number of sectors announced is incorrect, the boot-sector may
! 385: * contain incorrect information, eg the 'Eat.st' demo, or wrongly imaged
! 386: * single/double sided floppies... */
! 387: if (nSectors != nImageBytes/512)
1.1.1.6 root 388: Floppy_DoubleCheckFormat(nImageBytes, &nSides, &nSectorsPerTrack);
1.1 root 389:
390: /* And set values */
391: if (pnSectorsPerTrack)
392: *pnSectorsPerTrack = nSectorsPerTrack;
393: if (pnSides)
394: *pnSides = nSides;
395: }
396:
1.1.1.2 root 397:
398: /*-----------------------------------------------------------------------*/
1.1 root 399: /*
400: Read sectors from floppy disc image, return TRUE if all OK
401: NOTE Pass -ve as Count to read whole track
402: */
403: BOOL Floppy_ReadSectors(int Drive,char *pBuffer,unsigned short int Sector,unsigned short int Track,unsigned short int Side, short int Count, int *pnSectorsPerTrack)
404: {
405: unsigned char *pDiscBuffer;
406: unsigned short int nSectorsPerTrack,nSides,nBytesPerTrack;
407: long Offset;
1.1.1.7 ! root 408: int nImageTracks;
1.1.1.3 root 409:
1.1.1.2 root 410: /* Do we have a disc in our drive? */
1.1.1.5 root 411: if (EmulationDrives[Drive].bDiscInserted)
412: {
1.1.1.2 root 413: /* Looks good */
1.1 root 414: pDiscBuffer = EmulationDrives[Drive].pBuffer;
415:
1.1.1.2 root 416: /* Find #sides and #sectors per track */
1.1 root 417: Floppy_FindDiscDetails(EmulationDrives[Drive].pBuffer,EmulationDrives[Drive].nImageBytes,&nSectorsPerTrack,&nSides);
1.1.1.7 ! root 418: nImageTracks = ((EmulationDrives[Drive].nImageBytes / NUMBYTESPERSECTOR) / nSectorsPerTrack) / nSides;
1.1 root 419:
1.1.1.2 root 420: /* Need to read whole track? */
1.1 root 421: if (Count<0)
422: Count = nSectorsPerTrack;
1.1.1.2 root 423: /* Write back number of sector per track */
1.1 root 424: if (pnSectorsPerTrack)
425: *pnSectorsPerTrack = nSectorsPerTrack;
426:
1.1.1.2 root 427: /* Debug check as if we read over the end of a track we read into side 2! */
1.1.1.5 root 428: if (Count>nSectorsPerTrack)
429: {
1.1 root 430: ErrLog_File("ERROR Floppy_ReadSectors reading over single track\n");
431: }
432:
1.1.1.7 ! root 433: /* Check that the side number (0 or 1) does not exceed the amount of sides (1 or 2).
! 434: * (E.g. some games like Drakkhen or Bolo can load additional data from the
! 435: * second disc side, but they also work with single side floppy drives) */
! 436: if (Side >= nSides)
! 437: {
! 438: fprintf(stderr, "Warning: Program tries to read from side %i of a disk "
! 439: "image with %i sides!\n", Side+1, nSides);
! 440: return FALSE;
! 441: }
! 442:
! 443: /* Check if track number is in range */
! 444: if (Track >= nImageTracks)
! 445: {
! 446: fprintf(stderr, "Warning: Program tries to read from track %i of a disk "
! 447: "image with only %i tracks!\n", Track, nImageTracks);
! 448: return FALSE;
! 449: }
! 450:
1.1.1.2 root 451: /* Seek to sector */
1.1 root 452: nBytesPerTrack = NUMBYTESPERSECTOR*nSectorsPerTrack;
1.1.1.2 root 453: Offset = nBytesPerTrack*Side; /* First seek to side */
454: Offset += (nBytesPerTrack*nSides)*Track; /* Then seek to track */
455: Offset += (NUMBYTESPERSECTOR*(Sector-1)); /* And finally to sector */
1.1.1.6 root 456: if (Offset < 0)
457: {
458: fprintf(stderr,"Floppy_ReadSectors: Offset is negative (%li)!\n", Offset);
459: return FALSE;
460: }
461:
1.1.1.2 root 462: /* Read sectors (usually 512 bytes per sector) */
1.1 root 463: memcpy(pBuffer,pDiscBuffer+Offset,(int)Count*NUMBYTESPERSECTOR);
464:
465: return(TRUE);
466: }
467:
468: return(FALSE);
469: }
470:
1.1.1.2 root 471:
472: /*-----------------------------------------------------------------------*/
1.1 root 473: /*
474: Write sectors from floppy disc image, return TRUE if all OK
475: NOTE Pass -ve as Count to write whole track
476: */
477: BOOL Floppy_WriteSectors(int Drive,char *pBuffer,unsigned short int Sector,unsigned short int Track,unsigned short int Side, short int Count, int *pnSectorsPerTrack)
478: {
479: unsigned char *pDiscBuffer;
480: unsigned short int nSectorsPerTrack,nSides,nBytesPerTrack;
481: long Offset;
1.1.1.7 ! root 482: int nImageTracks;
1.1 root 483:
1.1.1.2 root 484: /* Do we have a disc in our drive? */
1.1.1.5 root 485: if (EmulationDrives[Drive].bDiscInserted)
486: {
1.1.1.2 root 487: /* Looks good */
1.1 root 488: pDiscBuffer = EmulationDrives[Drive].pBuffer;
489:
1.1.1.2 root 490: /* Find #sides and #sectors per track */
1.1 root 491: Floppy_FindDiscDetails(EmulationDrives[Drive].pBuffer,EmulationDrives[Drive].nImageBytes,&nSectorsPerTrack,&nSides);
1.1.1.7 ! root 492: nImageTracks = ((EmulationDrives[Drive].nImageBytes / NUMBYTESPERSECTOR) / nSectorsPerTrack) / nSides;
1.1 root 493:
1.1.1.2 root 494: /* Need to write whole track? */
1.1 root 495: if (Count<0)
496: Count = nSectorsPerTrack;
1.1.1.2 root 497: /* Write back number of sector per track */
1.1 root 498: if (pnSectorsPerTrack)
499: *pnSectorsPerTrack = nSectorsPerTrack;
500:
1.1.1.2 root 501: /* Debug check as if we write over the end of a track we write into side 2! */
1.1.1.5 root 502: if (Count>nSectorsPerTrack)
503: {
1.1 root 504: ErrLog_File("ERROR Floppy_WriteSectors reading over single track\n");
505: }
506:
1.1.1.7 ! root 507: /* Check that the side number (0 or 1) does not exceed the amount of sides (1 or 2). */
! 508: if (Side >= nSides)
! 509: {
! 510: fprintf(stderr, "Warning: Program tries to write to side %i of a disk "
! 511: "image with %i sides!\n", Side+1, nSides);
! 512: return FALSE;
! 513: }
! 514:
! 515: /* Check if track number is in range */
! 516: if (Track >= nImageTracks)
! 517: {
! 518: fprintf(stderr, "Warning: Program tries to write to track %i of a disk "
! 519: "image with only %i tracks!\n", Track, nImageTracks);
! 520: return FALSE;
! 521: }
! 522:
1.1.1.2 root 523: /* Seek to sector */
1.1 root 524: nBytesPerTrack = NUMBYTESPERSECTOR*nSectorsPerTrack;
1.1.1.2 root 525: Offset = nBytesPerTrack*Side; /* First seek to side */
526: Offset += (nBytesPerTrack*nSides)*Track; /* Then seek to track */
527: Offset += (NUMBYTESPERSECTOR*(Sector-1)); /* And finally to sector */
528: /* Write sectors (usually 512 bytes per sector) */
1.1 root 529: memcpy(pDiscBuffer+Offset,pBuffer,(int)Count*NUMBYTESPERSECTOR);
1.1.1.2 root 530: /* And set 'changed' flag */
1.1 root 531: EmulationDrives[Drive].bContentsChanged = TRUE;
532:
533: return(TRUE);
534: }
535:
536: return(FALSE);
537: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.