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