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

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: }

unix.superglobalmegacorp.com

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