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

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.11! root       24: const char Floppy_rcsid[] = "Hatari $Id: floppy.c,v 1.35 2008/01/07 21:54:22 eerot 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.1.11! root       58: /**
        !            59:  * Initialize emulation floppy drives
        !            60:  */
1.1       root       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.1.11! root       75: /**
        !            76:  * UnInitialize drives
        !            77:  */
1.1       root       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.1.11! root       85: /**
        !            86:  * Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
        !            87:  */
1.1       root       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.1.11! root      118: /**
        !           119:  * Find which device to boot from (hard drive or floppy).
        !           120:  */
1.1       root      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.1.11! root      132: /**
        !           133:  * Test if disk image is write protected. Write protection can be configured
        !           134:  * in the GUI. When set to "automatic", we check the file permissions of the
        !           135:  * floppy disk image to decide.
        !           136:  */
1.1.1.8   root      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: /*-----------------------------------------------------------------------*/
1.1.1.11! root      160: /**
        !           161:  * Test disk image for valid boot-sector.
        !           162:  * It has been noticed that some disks, eg blank images made by the MakeDisk
        !           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.
        !           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.
        !           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.1.11! root      195: /**
        !           196:  * Try to create disk B filename, eg 'auto_100a' becomes 'auto_100b'
        !           197:  * Return new filename if think we should try, otherwise NULL
        !           198:  */
        !           199: static char* Floppy_CreateDiskBFileName(const char *pSrcFileName)
1.1       root      200: {
1.1.1.10  root      201:        char *szDir, *szName, *szExt;
1.1.1.11! root      202:        
1.1.1.10  root      203:        /* Allocate temporary memory for strings: */
                    204:        szDir = malloc(3 * FILENAME_MAX);
                    205:        if (!szDir)
                    206:        {
                    207:                perror("Floppy_CreateDiskBFileName");
                    208:                return FALSE;
                    209:        }
                    210:        szName = szDir + FILENAME_MAX;
                    211:        szExt = szName + FILENAME_MAX;
                    212: 
                    213:        /* So, first split name into parts */
1.1.1.11! root      214:        File_SplitPath(pSrcFileName, szDir, szName, szExt);
1.1.1.10  root      215: 
                    216:        /* All OK? */
                    217:        if (strlen(szName) > 0)
                    218:        {
                    219:                /* Now, did filename end with an 'A' or 'a'? */
                    220:                if ((szName[strlen(szName)-1]=='A') || (szName[strlen(szName)-1]=='a'))
                    221:                {
1.1.1.11! root      222:                        char *szFull;
1.1.1.10  root      223:                        /* Change 'A' to a 'B' */
                    224:                        szName[strlen(szName)-1] += 1;
                    225:                        /* And re-build name into destination */
1.1.1.11! root      226:                        szFull = File_MakePath(szDir, szName, szExt);
        !           227:                        if (szFull)
        !           228:                        {
        !           229:                                /* Does file exist? */
        !           230:                                if (File_Exists(szFull))
        !           231:                                {
        !           232:                                        free(szDir);
        !           233:                                        return szFull;
        !           234:                                }
        !           235:                                free(szFull);
        !           236:                        }
1.1.1.10  root      237:                }
                    238:        }
                    239:        free(szDir);
1.1.1.11! root      240:        return NULL;
1.1       root      241: }
                    242: 
1.1.1.2   root      243: 
                    244: /*-----------------------------------------------------------------------*/
1.1.1.11! root      245: /**
        !           246:  * Insert disk into floppy drive. Sets the disk image name
        !           247:  * back to given string with corrected extension. Maxlen is
        !           248:  * maximum string lenght.
        !           249:  * Returns TRUE of success and FALSE for failure.
        !           250:  * The WHOLE image is copied into our drive buffers,
        !           251:  * and uncompressed if necessary
        !           252:  */
        !           253: BOOL Floppy_InsertDiskIntoDrive(int Drive, char *pszFileName, int maxlen)
1.1       root      254: {
1.1.1.11! root      255:        char *path;
        !           256:        path = Floppy_ZipInsertDiskIntoDrive(Drive, pszFileName, NULL);
        !           257:        if (path)
        !           258:        {
        !           259:                strncpy(pszFileName, path, maxlen);
        !           260:                pszFileName[maxlen-1] = '\0';
        !           261:                free(path);
        !           262:                return TRUE;
        !           263:        }
        !           264:        return FALSE;
1.1.1.6   root      265: }
                    266: 
1.1.1.11! root      267: /* Read image into buffers, handles different image extensions,
        !           268:  * return corrected file name on success and NULL on failure.
        !           269:  */
        !           270: char* Floppy_ZipInsertDiskIntoDrive(int Drive, const char *pszFileName, const char *pszZipPath)
1.1.1.6   root      271: {
1.1.1.10  root      272:        long nImageBytes = 0;
1.1.1.11! root      273:        char *filename;
1.1       root      274: 
1.1.1.11! root      275:        /* Eject disk, if one is inserted (doesn't inform user) */
1.1.1.10  root      276:        Floppy_EjectDiskFromDrive(Drive,FALSE);
1.1       root      277: 
1.1.1.11! root      278:        /* See if file exists, and if not, get/add correct extension */
1.1.1.10  root      279:        if ( !File_Exists(pszFileName) )
1.1.1.11! root      280:                filename = File_FindPossibleExtFileName(pszFileName, pszDiskImageNameExts);
        !           281:        else
        !           282:                filename = strdup(pszFileName);
        !           283:        
1.1.1.10  root      284:        /* Check disk image type and read the file: */
1.1.1.11! root      285:        if (MSA_FileNameIsMSA(filename, TRUE))
        !           286:                EmulationDrives[Drive].pBuffer = MSA_ReadDisk(filename, &nImageBytes);
        !           287:        else if (ST_FileNameIsST(filename, TRUE))
        !           288:                EmulationDrives[Drive].pBuffer = ST_ReadDisk(filename, &nImageBytes);
        !           289:        else if (DIM_FileNameIsDIM(filename, TRUE))
        !           290:                EmulationDrives[Drive].pBuffer = DIM_ReadDisk(filename, &nImageBytes);
        !           291:        else if (ZIP_FileNameIsZIP(filename))
        !           292:                EmulationDrives[Drive].pBuffer = ZIP_ReadDisk(filename, pszZipPath, &nImageBytes);
        !           293: 
        !           294:        if (EmulationDrives[Drive].pBuffer == NULL)
        !           295:        {
        !           296:                free(filename);
        !           297:                return NULL;
        !           298:        }
        !           299:        /* Store filename and size */
        !           300:        strcpy(EmulationDrives[Drive].szFileName, filename);
        !           301:        EmulationDrives[Drive].nImageBytes = nImageBytes;
        !           302:        /* And set drive states */
        !           303:        EmulationDrives[Drive].bDiskInserted = TRUE;
        !           304:        EmulationDrives[Drive].bContentsChanged = FALSE;
        !           305:        EmulationDrives[Drive].bMediaChanged = TRUE;
        !           306:        EmulationDrives[Drive].bOKToSave = Floppy_IsBootSectorOK(Drive);
1.1.1.10  root      307: 
1.1.1.11! root      308:        /* If we insert a disk into Drive A, should we try to put disk 2 into drive B? */
1.1.1.10  root      309:        if (Drive == 0 && ConfigureParams.DiskImage.bAutoInsertDiskB)
                    310:        {
1.1.1.11! root      311:                char *szTmp;
1.1.1.10  root      312:                /* Attempt to make up second filename, eg was 'auto_100a' to 'auto_100b' */
1.1.1.11! root      313:                char *szDiskBFileName =  Floppy_CreateDiskBFileName(filename);
        !           314:                if (szDiskBFileName)
1.1.1.10  root      315:                {
1.1.1.11! root      316:                        /* recurse with Drive B */
        !           317:                        szTmp = Floppy_ZipInsertDiskIntoDrive(1, szDiskBFileName, NULL);
        !           318:                        if (szTmp)
        !           319:                                free(szTmp);
        !           320:                        free(szDiskBFileName);
1.1.1.10  root      321:                }
                    322:        }
1.1.1.11! root      323:        return filename;
1.1       root      324: }
                    325: 
1.1.1.2   root      326: 
                    327: /*-----------------------------------------------------------------------*/
1.1.1.11! root      328: /**
        !           329:  * Eject disk from floppy drive, save contents back to PCs hard-drive if
        !           330:  * they have been changed.
        !           331:  */
1.1.1.9   root      332: void Floppy_EjectDiskFromDrive(int Drive, BOOL bInformUser)
1.1       root      333: {
1.1.1.10  root      334:        /* Does our drive have a disk in? */
                    335:        if (EmulationDrives[Drive].bDiskInserted)
                    336:        {
                    337:                /* OK, has contents changed? If so, need to save */
                    338:                if (EmulationDrives[Drive].bContentsChanged)
                    339:                {
                    340:                        /* Is OK to save image (if boot-sector is bad, don't allow a save) */
                    341:                        if (EmulationDrives[Drive].bOKToSave && !Floppy_IsWriteProtected(Drive))
                    342:                        {
                    343:                                /* Save as .MSA or .ST image? */
                    344:                                if (MSA_FileNameIsMSA(EmulationDrives[Drive].szFileName, TRUE))
                    345:                                        MSA_WriteDisk(EmulationDrives[Drive].szFileName, EmulationDrives[Drive].pBuffer, EmulationDrives[Drive].nImageBytes);
                    346:                                else if (ST_FileNameIsST(EmulationDrives[Drive].szFileName, TRUE))
                    347:                                        ST_WriteDisk(EmulationDrives[Drive].szFileName, EmulationDrives[Drive].pBuffer, EmulationDrives[Drive].nImageBytes);
                    348:                                else if (DIM_FileNameIsDIM(EmulationDrives[Drive].szFileName, TRUE))
                    349:                                        DIM_WriteDisk(EmulationDrives[Drive].szFileName, EmulationDrives[Drive].pBuffer, EmulationDrives[Drive].nImageBytes);
                    350:                                else if (ZIP_FileNameIsZIP(EmulationDrives[Drive].szFileName))
                    351:                                        ZIP_WriteDisk(EmulationDrives[Drive].szFileName, EmulationDrives[Drive].pBuffer, EmulationDrives[Drive].nImageBytes);
                    352:                        }
                    353:                }
                    354: 
                    355:                /* Inform user that disk has been ejected! */
                    356:                if (bInformUser)
                    357:                {
                    358:                        Log_AlertDlg(LOG_INFO, "Disk has been removed from drive '%c:'.", 'A'+Drive);
                    359:                }
                    360:        }
                    361: 
                    362:        /* Drive is now empty */
                    363:        if (EmulationDrives[Drive].pBuffer != NULL)
                    364:        {
                    365:                free(EmulationDrives[Drive].pBuffer);
                    366:                EmulationDrives[Drive].pBuffer = NULL;
                    367:        }
                    368:        strcpy(EmulationDrives[Drive].szFileName,"");
                    369:        EmulationDrives[Drive].nImageBytes = 0;
                    370:        EmulationDrives[Drive].bDiskInserted = FALSE;
                    371:        EmulationDrives[Drive].bContentsChanged = FALSE;
                    372:        EmulationDrives[Drive].bOKToSave = FALSE;
1.1       root      373: }
                    374: 
1.1.1.2   root      375: 
                    376: /*-----------------------------------------------------------------------*/
1.1.1.11! root      377: /**
        !           378:  * Eject all disk image from floppy drives - call when quit.
        !           379:  */
1.1       root      380: void Floppy_EjectBothDrives(void)
                    381: {
1.1.1.10  root      382:        /* Eject disk images from drives 'A' and 'B' */
                    383:        Floppy_EjectDiskFromDrive(0, FALSE);
                    384:        Floppy_EjectDiskFromDrive(1, FALSE);
1.1       root      385: }
                    386: 
1.1.1.2   root      387: 
                    388: /*-----------------------------------------------------------------------*/
1.1.1.11! root      389: /**
        !           390:  * Double-check information read from boot-sector as this is sometimes found to
        !           391:  * be incorrect. The .ST image file should be divisible by the sector size and
        !           392:  * sectors per track.
        !           393:  * NOTE - Pass information from boot-sector to this function (if we can't
        !           394:  * decide we leave it alone).
        !           395:  */
1.1.1.9   root      396: static void Floppy_DoubleCheckFormat(long nDiskSize, Uint16 *pnSides, Uint16 *pnSectorsPerTrack)
1.1       root      397: {
1.1.1.10  root      398:        int nSectorsPerTrack;
                    399:        long TotalSectors;
1.1       root      400: 
1.1.1.10  root      401:        /* Now guess at number of sides */
                    402:        if (nDiskSize < (500*1024))                    /* Is size is >500k assume 2 sides to disk! */
                    403:                *pnSides = 1;
                    404:        else
                    405:                *pnSides = 2;
                    406: 
                    407:        /* And Sectors Per Track(always 512 bytes per sector) */
                    408:        TotalSectors = nDiskSize/512;                 /* # Sectors on disk image */
                    409:        /* Does this match up with what we've read from boot-sector? */
                    410:        nSectorsPerTrack = *pnSectorsPerTrack;
                    411:        if (nSectorsPerTrack==0)                      /* Check valid, default to 9 */
                    412:                nSectorsPerTrack = 9;
                    413:        if ((TotalSectors%nSectorsPerTrack)!=0)
                    414:        {
                    415:                /* No, we have an invalid boot-sector - re-calculate from disk size */
                    416:                if ((TotalSectors%9)==0)                    /* Work in this order.... */
                    417:                        *pnSectorsPerTrack = 9;
                    418:                else if ((TotalSectors%10)==0)
                    419:                        *pnSectorsPerTrack = 10;
                    420:                else if ((TotalSectors%11)==0)
                    421:                        *pnSectorsPerTrack = 11;
                    422:                else if ((TotalSectors%12)==0)
                    423:                        *pnSectorsPerTrack = 12;
                    424:        }
                    425:        /* else unknown, assume boot-sector is correct!!! */
1.1       root      426: }
                    427: 
1.1.1.2   root      428: 
                    429: /*-----------------------------------------------------------------------*/
1.1.1.11! root      430: /**
        !           431:  * Find details of disk image. We need to do this via a function as sometimes the boot-block
        !           432:  * is not actually correct with the image - some demos/game disks have incorrect bytes in the
        !           433:  * boot sector and this attempts to find the correct values.
        !           434:  */
1.1.1.9   root      435: void Floppy_FindDiskDetails(const Uint8 *pBuffer, int nImageBytes,
                    436:                             unsigned short *pnSectorsPerTrack, unsigned short *pnSides)
1.1       root      437: {
1.1.1.10  root      438:        Uint16 nSectorsPerTrack, nSides, nSectors;
1.1       root      439: 
1.1.1.10  root      440:        /* First do check to find number of sectors and bytes per sector */
                    441:        nSectorsPerTrack = SDL_SwapLE16(*(const Uint16 *)(pBuffer+24));   /* SPT */
                    442:        nSides = SDL_SwapLE16(*(const Uint16 *)(pBuffer+26));             /* SIDE */
                    443:        nSectors = pBuffer[19] | (pBuffer[20] << 8);                      /* total sectors */
                    444: 
                    445:        /* If the number of sectors announced is incorrect, the boot-sector may
                    446:         * contain incorrect information, eg the 'Eat.st' demo, or wrongly imaged
                    447:         * single/double sided floppies... */
                    448:        if (nSectors != nImageBytes/512)
                    449:                Floppy_DoubleCheckFormat(nImageBytes, &nSides, &nSectorsPerTrack);
                    450: 
                    451:        /* And set values */
                    452:        if (pnSectorsPerTrack)
                    453:                *pnSectorsPerTrack = nSectorsPerTrack;
                    454:        if (pnSides)
                    455:                *pnSides = nSides;
1.1       root      456: }
                    457: 
1.1.1.2   root      458: 
                    459: /*-----------------------------------------------------------------------*/
1.1.1.11! root      460: /**
        !           461:  * Read sectors from floppy disk image, return TRUE if all OK
        !           462:  * NOTE Pass -ve as Count to read whole track
        !           463:  */
1.1.1.9   root      464: BOOL Floppy_ReadSectors(int Drive, Uint8 *pBuffer, unsigned short Sector,
                    465:                         unsigned short Track, unsigned short Side, short Count,
                    466:                         int *pnSectorsPerTrack)
1.1       root      467: {
1.1.1.10  root      468:        Uint8 *pDiskBuffer;
                    469:        unsigned short int nSectorsPerTrack,nSides,nBytesPerTrack;
                    470:        long Offset;
                    471:        int nImageTracks;
                    472: 
                    473:        /* Do we have a disk in our drive? */
                    474:        if (EmulationDrives[Drive].bDiskInserted)
                    475:        {
                    476:                /* Looks good */
                    477:                pDiskBuffer = EmulationDrives[Drive].pBuffer;
                    478: 
                    479:                /* Find #sides and #sectors per track */
                    480:                Floppy_FindDiskDetails(EmulationDrives[Drive].pBuffer,EmulationDrives[Drive].nImageBytes,&nSectorsPerTrack,&nSides);
                    481:                nImageTracks = ((EmulationDrives[Drive].nImageBytes / NUMBYTESPERSECTOR) / nSectorsPerTrack) / nSides;
                    482: 
                    483:                /* Need to read whole track? */
                    484:                if (Count<0)
                    485:                        Count = nSectorsPerTrack;
                    486:                /* Write back number of sector per track */
                    487:                if (pnSectorsPerTrack)
                    488:                        *pnSectorsPerTrack = nSectorsPerTrack;
                    489: 
                    490:                /* Debug check as if we read over the end of a track we read into side 2! */
                    491:                if (Count > nSectorsPerTrack)
                    492:                {
                    493:                        Log_Printf(LOG_DEBUG, "Floppy_ReadSectors: reading over single track\n");
                    494:                }
                    495: 
                    496:                /* Check that the side number (0 or 1) does not exceed the amount of sides (1 or 2).
                    497:                 * (E.g. some games like Drakkhen or Bolo can load additional data from the
                    498:                 * second disk side, but they also work with single side floppy drives) */
                    499:                if (Side >= nSides)
                    500:                {
                    501:                        Log_Printf(LOG_DEBUG, "Floppy_ReadSectors: Program tries to read from side %i "
                    502:                                   "of a disk image with %i sides!\n", Side+1, nSides);
                    503:                        return FALSE;
                    504:                }
                    505: 
                    506:                /* Check if track number is in range */
                    507:                if (Track >= nImageTracks)
                    508:                {
                    509:                        Log_Printf(LOG_DEBUG, "Floppy_ReadSectors: Program tries to read from track %i "
                    510:                                   "of a disk image with only %i tracks!\n", Track, nImageTracks);
                    511:                        return FALSE;
                    512:                }
                    513: 
                    514:                /* Check if sector number is in range */
                    515:                if (Sector <= 0 || Sector > nSectorsPerTrack)
                    516:                {
                    517:                        Log_Printf(LOG_DEBUG, "Floppy_ReadSectors: Program tries to read from sector %i "
                    518:                                   "of a disk image with %i sectors per track!\n", Sector, nSectorsPerTrack);
                    519:                        return FALSE;
                    520:                }
                    521: 
                    522:                /* Seek to sector */
                    523:                nBytesPerTrack = NUMBYTESPERSECTOR*nSectorsPerTrack;
                    524:                Offset = nBytesPerTrack*Side;                 /* First seek to side */
                    525:                Offset += (nBytesPerTrack*nSides)*Track;      /* Then seek to track */
                    526:                Offset += (NUMBYTESPERSECTOR*(Sector-1));     /* And finally to sector */
1.1.1.6   root      527: 
1.1.1.10  root      528:                /* Read sectors (usually 512 bytes per sector) */
                    529:                memcpy(pBuffer, pDiskBuffer+Offset, (int)Count*NUMBYTESPERSECTOR);
1.1       root      530: 
1.1.1.10  root      531:                return TRUE;
                    532:        }
1.1       root      533: 
1.1.1.10  root      534:        return FALSE;
1.1       root      535: }
                    536: 
1.1.1.2   root      537: 
                    538: /*-----------------------------------------------------------------------*/
1.1.1.11! root      539: /**
        !           540:  * Write sectors from floppy disk image, return TRUE if all OK
        !           541:  * NOTE Pass -ve as Count to write whole track
        !           542:  */
1.1.1.9   root      543: BOOL Floppy_WriteSectors(int Drive, Uint8 *pBuffer, unsigned short Sector,
                    544:                          unsigned short Track, unsigned short Side, short Count,
                    545:                          int *pnSectorsPerTrack)
1.1       root      546: {
1.1.1.10  root      547:        Uint8 *pDiskBuffer;
                    548:        unsigned short int nSectorsPerTrack,nSides,nBytesPerTrack;
                    549:        long Offset;
                    550:        int nImageTracks;
                    551: 
                    552:        /* Do we have a writable disk in our drive? */
                    553:        if (EmulationDrives[Drive].bDiskInserted && !Floppy_IsWriteProtected(Drive))
                    554:        {
                    555:                /* Looks good */
                    556:                pDiskBuffer = EmulationDrives[Drive].pBuffer;
                    557: 
                    558:                /* Find #sides and #sectors per track */
                    559:                Floppy_FindDiskDetails(EmulationDrives[Drive].pBuffer,EmulationDrives[Drive].nImageBytes,&nSectorsPerTrack,&nSides);
                    560:                nImageTracks = ((EmulationDrives[Drive].nImageBytes / NUMBYTESPERSECTOR) / nSectorsPerTrack) / nSides;
                    561: 
                    562:                /* Need to write whole track? */
                    563:                if (Count<0)
                    564:                        Count = nSectorsPerTrack;
                    565:                /* Write back number of sector per track */
                    566:                if (pnSectorsPerTrack)
                    567:                        *pnSectorsPerTrack = nSectorsPerTrack;
                    568: 
                    569:                /* Debug check as if we write over the end of a track we write into side 2! */
                    570:                if (Count > nSectorsPerTrack)
                    571:                {
                    572:                        Log_Printf(LOG_DEBUG, "Floppy_WriteSectors: writing over single track\n");
                    573:                }
                    574: 
                    575:                /* Check that the side number (0 or 1) does not exceed the amount of sides (1 or 2). */
                    576:                if (Side >= nSides)
                    577:                {
                    578:                        Log_Printf(LOG_DEBUG, "Floppy_WriteSectors: Program tries to write to side %i "
                    579:                                   "of a disk image with %i sides!\n", Side+1, nSides);
                    580:                        return FALSE;
                    581:                }
                    582: 
                    583:                /* Check if track number is in range */
                    584:                if (Track >= nImageTracks)
                    585:                {
                    586:                        Log_Printf(LOG_DEBUG, "Floppy_WriteSectors: Program tries to write to track %i "
                    587:                                   "of a disk image with only %i tracks!\n", Track, nImageTracks);
                    588:                        return FALSE;
                    589:                }
                    590: 
                    591:                /* Check if sector number is in range */
                    592:                if (Sector <= 0 || Sector > nSectorsPerTrack)
                    593:                {
                    594:                        Log_Printf(LOG_DEBUG, "Floppy_WriteSectors: Program tries to write to sector %i "
                    595:                                   "of a disk image with %i sectors per track!\n", Sector, nSectorsPerTrack);
                    596:                        return FALSE;
                    597:                }
                    598: 
                    599:                /* Seek to sector */
                    600:                nBytesPerTrack = NUMBYTESPERSECTOR*nSectorsPerTrack;
                    601:                Offset = nBytesPerTrack*Side;               /* First seek to side */
                    602:                Offset += (nBytesPerTrack*nSides)*Track;    /* Then seek to track */
                    603:                Offset += (NUMBYTESPERSECTOR*(Sector-1));   /* And finally to sector */
                    604: 
                    605:                /* Write sectors (usually 512 bytes per sector) */
                    606:                memcpy(pDiskBuffer+Offset, pBuffer, (int)Count*NUMBYTESPERSECTOR);
                    607:                /* And set 'changed' flag */
                    608:                EmulationDrives[Drive].bContentsChanged = TRUE;
1.1       root      609: 
1.1.1.10  root      610:                return TRUE;
                    611:        }
1.1       root      612: 
1.1.1.10  root      613:        return FALSE;
1.1       root      614: }

unix.superglobalmegacorp.com

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