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

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

unix.superglobalmegacorp.com

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