Annotation of hatari/src/floppy.c, revision 1.1.1.9

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.