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

1.1     ! root        1: /*
        !             2:   Hatari
        !             3: 
        !             4:   This where we read/write sectors to/from the disc image buffers. NOTE these buffers are in
        !             5:   memory so we only need to write routines for the .ST format. When the buffer is to be
        !             6:   saved(ie eject disc) we save it back to the original file in the correct format(.ST or .MSA)
        !             7: 
        !             8:   There are some important notes about image accessing - as we use TOS and the FDC to access
        !             9:   the disc the boot-sector MUST be valid. Sometimes this is NOT the case! In these
        !            10:   situations we must guess at the disc format. Eg, some disc images have a a boot sector which
        !            11:   states single-sided, but the images have been created as double-sided. As sides are interleaved
        !            12:   we need to read the image as if it was double-sided. Also note that 'NumBytesPerSector' is
        !            13:   ALWAYS 512 bytes, even if the boot-sector states otherwise.
        !            14:   Also note that the (current)MAKEDISK utility does not set the correct boot sector structure
        !            15:   for a real ST(and also Hatari) to read it correctly. (PaCifiST will, however, read/write to
        !            16:   these images as it does not perform FDC access as on a real ST)
        !            17: */
        !            18: 
        !            19: #include "main.h"
        !            20: #include "debug.h"
        !            21: #include "dialog.h"
        !            22: #include "errlog.h"
        !            23: #include "file.h"
        !            24: #include "floppy.h"
        !            25: #include "memAlloc.h"
        !            26: #include "memorySnapShot.h"
        !            27: #include "misc.h"
        !            28: #include "msa.h"
        !            29: #include "st.h"
        !            30: #include "statusBar.h"
        !            31: #include "view.h"
        !            32: 
        !            33: 
        !            34: EMULATION_DRIVE EmulationDrives[NUM_EMULATION_DRIVES];  /* Emulation drive details, eg FileName, Inserted, Changed etc... */
        !            35: int nBootDrive=0;               /* Drive A, default */
        !            36: 
        !            37: /* Possible disc image file extensions to scan for */
        !            38: char *pszDiscImageNameExts[] = {
        !            39:   ".msa",
        !            40:   ".st",
        !            41:   NULL
        !            42: };
        !            43: 
        !            44: 
        !            45: //-----------------------------------------------------------------------
        !            46: /*
        !            47:   Initialize emulation floppy drives
        !            48: */
        !            49: void Floppy_Init(void)
        !            50: {
        !            51:   int i;
        !            52: 
        !            53:   /* Clear drive structures */
        !            54:   for(i=0; i<NUM_EMULATION_DRIVES; i++) {
        !            55:     /* Clear */
        !            56:     Memory_Clear(&EmulationDrives[i],sizeof(EMULATION_DRIVE));
        !            57:     /* And allocate buffer */
        !            58:     EmulationDrives[i].pBuffer = (unsigned char *)Memory_Alloc(DRIVE_BUFFER_BYTES);
        !            59:   }
        !            60: }
        !            61: 
        !            62: //-----------------------------------------------------------------------
        !            63: /*
        !            64:   UnInitialize drives
        !            65: */
        !            66: void Floppy_UnInit(void)
        !            67: {
        !            68:   int i;
        !            69: 
        !            70:   // Free buffers used for emulation drives
        !            71:   for(i=0; i<NUM_EMULATION_DRIVES; i++) {
        !            72:     Memory_Free(EmulationDrives[i].pBuffer);
        !            73:   }
        !            74: }
        !            75: 
        !            76: //-----------------------------------------------------------------------
        !            77: /*
        !            78:   Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
        !            79: */
        !            80: void Floppy_MemorySnapShot_Capture(BOOL bSave)
        !            81: {
        !            82:   int i;
        !            83: 
        !            84:   // Save/Restore details
        !            85:   for(i=0; i<NUM_EMULATION_DRIVES; i++) {
        !            86:     MemorySnapShot_Store(EmulationDrives[i].pBuffer,DRIVE_BUFFER_BYTES);
        !            87:     MemorySnapShot_Store(EmulationDrives[i].szFileName,sizeof(EmulationDrives[i].szFileName));
        !            88:     MemorySnapShot_Store(&EmulationDrives[i].nImageBytes,sizeof(EmulationDrives[i].nImageBytes));
        !            89:     MemorySnapShot_Store(&EmulationDrives[i].bDiscInserted,sizeof(EmulationDrives[i].bDiscInserted));
        !            90:     MemorySnapShot_Store(&EmulationDrives[i].bMediaChanged,sizeof(EmulationDrives[i].bMediaChanged));
        !            91:     MemorySnapShot_Store(&EmulationDrives[i].bContentsChanged,sizeof(EmulationDrives[i].bContentsChanged));
        !            92:     MemorySnapShot_Store(&EmulationDrives[i].bOKToSave,sizeof(EmulationDrives[i].bOKToSave));
        !            93:   }
        !            94: }
        !            95: 
        !            96: //-----------------------------------------------------------------------
        !            97: /*
        !            98:   Find which device to boot from
        !            99: */
        !           100: void Floppy_GetBootDrive(void)
        !           101: {
        !           102: /* FIXME */
        !           103: /*
        !           104:   // If we've inserted a disc or not enabled boot from hard-drive, boot from the floppy drive
        !           105:   if ( (!ConfigureParams.HardDisc.bBootFromHardDisc) || (EmulationDrives[0].bDiscInserted) )
        !           106:     nBootDrive = 0;  //Drive A
        !           107:   else
        !           108:     nBootDrive = 2;  //Drive C
        !           109: */
        !           110: }
        !           111: 
        !           112: //-----------------------------------------------------------------------
        !           113: /*
        !           114:   Test disc image for valid boot-sector
        !           115: 
        !           116:   It has been noticed that some discs, eg blank images made by the (current)MakeDisk utility
        !           117:   fill in the boot-sector with incorrect information. Such images cannot be read correctly using
        !           118:   a real ST, and also Hatari. To try and prevent data loss, we check for this error and flag
        !           119:   the drive so the image will not be saved back to the file.
        !           120: */
        !           121: BOOL Floppy_IsBootSectorOK(int Drive)
        !           122: {
        !           123:   unsigned char *pDiscBuffer;
        !           124: 
        !           125:   /* Does our drive have a disc in? */
        !           126:   if (EmulationDrives[Drive].bDiscInserted) {
        !           127:     pDiscBuffer = EmulationDrives[Drive].pBuffer;
        !           128:     /* Check SPC(byte 13) for !=0 value. If is '0', invalid image and Hatari won't be-able to read(nor will a real ST)! */
        !           129:     if (pDiscBuffer[13]!=0)
        !           130:       return(TRUE);     /* Disc sector is OK! */
        !           131:   }
        !           132: 
        !           133:   return(FALSE);        /* Bad sector */
        !           134: }
        !           135: 
        !           136: //-----------------------------------------------------------------------
        !           137: /*
        !           138:   Try to create disc B filename, eg 'auto_100a' becomes 'auto_100b'
        !           139:   Return TRUE if think we should try!
        !           140: */
        !           141: BOOL Floppy_CreateDiscBFileName(char *pSrcFileName, char *pDestFileName)
        !           142: {
        !           143: /* FIXME */
        !           144: /*
        !           145:   char szDrive[_MAX_DRIVE],szDir[_MAX_DIR],szName[_MAX_FNAME],szExt[_MAX_EXT];
        !           146: 
        !           147:   // So, first split name into parts
        !           148:   _splitpath(pSrcFileName,szDrive,szDir,szName,szExt);
        !           149:   // All OK?
        !           150:   if (strlen(szName)>0) {
        !           151:     // Now, did filename end with an 'A' or 'a'?
        !           152:     if ( (szName[strlen(szName)-1]=='A') || (szName[strlen(szName)-1]=='a') ) {
        !           153:       // Change 'A' to a 'B'
        !           154:       szName[strlen(szName)-1] = 'b';
        !           155:       // And re-build name into destination
        !           156:       _makepath(pDestFileName,szDrive,szDir,szName,szExt);
        !           157:       // Does file exist?
        !           158:       if (File_Exists(pDestFileName))
        !           159:         return(TRUE);  // Try this
        !           160:     }
        !           161:   }
        !           162: */
        !           163:   return(FALSE);  // No, doesn't have disc B
        !           164: }
        !           165: 
        !           166: //-----------------------------------------------------------------------
        !           167: /*
        !           168:   Insert disc into floppy drive
        !           169:   The WHOLE image is copied into our drive buffers, and uncompressed if necessary
        !           170: */
        !           171: BOOL Floppy_InsertDiscIntoDrive(int Drive, char *pszFileName)
        !           172: {
        !           173:   char szDiscBFileName[MAX_FILENAME_LENGTH];
        !           174:   int nImageBytes=0;
        !           175: 
        !           176:   /* Eject disc, if one is inserted(don't inform user) */
        !           177:   Floppy_EjectDiscFromDrive(Drive,FALSE);
        !           178: 
        !           179:   /* See if file exists, and if not get correct extension */
        !           180:   File_FindPossibleExtFileName(pszFileName,pszDiscImageNameExts);
        !           181: 
        !           182:   /* Is .MSA or .ST image? */
        !           183:   if (File_FileNameIsMSA(pszFileName))
        !           184:     nImageBytes = MSA_ReadDisc(pszFileName,EmulationDrives[Drive].pBuffer);
        !           185:   else if (File_FileNameIsST(pszFileName))
        !           186:     nImageBytes = ST_ReadDisc(pszFileName,EmulationDrives[Drive].pBuffer);
        !           187:   /* Did load OK? */
        !           188:   if (nImageBytes!=0) {
        !           189:     /* Store filename and size */
        !           190:     strcpy(EmulationDrives[Drive].szFileName,pszFileName);
        !           191:     EmulationDrives[Drive].nImageBytes = nImageBytes;
        !           192:     /* And set drive states */
        !           193:     EmulationDrives[Drive].bDiscInserted = TRUE;
        !           194:     EmulationDrives[Drive].bContentsChanged = FALSE;
        !           195:     EmulationDrives[Drive].bMediaChanged = TRUE;
        !           196:     EmulationDrives[Drive].bOKToSave = Floppy_IsBootSectorOK(Drive);
        !           197:   }
        !           198: 
        !           199:   /* If we insert a disc into Drive A, should be try to put disc 2 into drive B? */
        !           200: /* FIXME */
        !           201: /*
        !           202:   if ( (Drive==0) && (ConfigureParams.DiscImage.bAutoInsertDiscB) ) {
        !           203:     strcpy(EmulationDrives[1].szFileName,"");
        !           204:     // Attempt to make up second filename, eg was 'auto_100a' to 'auto_100b'
        !           205:     if (Floppy_CreateDiscBFileName(pszFileName,szDiscBFileName)) {
        !           206:       // Put image into Drive B, clear out if fails
        !           207:       if (!Floppy_InsertDiscIntoDrive(1,szDiscBFileName))
        !           208:         strcpy(EmulationDrives[1].szFileName,"");
        !           209:     }
        !           210:   }
        !           211: */
        !           212:   /* Return TRUE if loaded OK */
        !           213:   if (nImageBytes)
        !           214:     return(TRUE);
        !           215:   else
        !           216:     return(FALSE);
        !           217: }
        !           218: 
        !           219: //-----------------------------------------------------------------------
        !           220: /*
        !           221:   Eject disc from floppy drive, save contents back to PCs hard-drive is has changed
        !           222: */
        !           223: void Floppy_EjectDiscFromDrive(int Drive,BOOL bInformUser)
        !           224: {
        !           225:   char szString[256];
        !           226: 
        !           227:   /* Does our drive have a disc in? */
        !           228:   if (EmulationDrives[Drive].bDiscInserted) {
        !           229:     /* OK, has contents changed? If so, need to save */
        !           230:     if (EmulationDrives[Drive].bContentsChanged) {
        !           231:       /* Is OK to save image(if boot-sector is bad, don't allow a save) */
        !           232:       if (EmulationDrives[Drive].bOKToSave) {
        !           233:         /* Save as .MSA or .ST image? */
        !           234:         if (File_FileNameIsMSA(EmulationDrives[Drive].szFileName))
        !           235:           MSA_WriteDisc(EmulationDrives[Drive].szFileName,EmulationDrives[Drive].pBuffer,EmulationDrives[Drive].nImageBytes);
        !           236:         else if (File_FileNameIsST(EmulationDrives[Drive].szFileName))
        !           237:           ST_WriteDisc(EmulationDrives[Drive].szFileName,EmulationDrives[Drive].pBuffer,EmulationDrives[Drive].nImageBytes);
        !           238:       }
        !           239:     }
        !           240: 
        !           241:     /* Inform user that disc has been ejected! */
        !           242:     if (bInformUser) {
        !           243:       sprintf(szString,"Disc has been removed from Drive '%c'.",'A'+Drive);
        !           244: /* FIXME */ //    MessageBox(hWnd,szString,PROG_NAME,MB_OK | MB_ICONINFORMATION);
        !           245:     }
        !           246:   }
        !           247: 
        !           248:   /* Drive is now empty */
        !           249:   strcpy(EmulationDrives[Drive].szFileName,"");
        !           250:   EmulationDrives[Drive].nImageBytes = 0;
        !           251:   EmulationDrives[Drive].bDiscInserted = FALSE;
        !           252:   EmulationDrives[Drive].bContentsChanged = FALSE;
        !           253:   EmulationDrives[Drive].bOKToSave = FALSE;
        !           254: }
        !           255: 
        !           256: //-----------------------------------------------------------------------
        !           257: /*
        !           258:   Eject all disc image from floppy drives - call when quit
        !           259: */
        !           260: void Floppy_EjectBothDrives(void)
        !           261: {
        !           262:   /* Eject disc images from drives 'A' and 'B' */
        !           263:   Floppy_EjectDiscFromDrive(0,FALSE);
        !           264:   Floppy_EjectDiscFromDrive(1,FALSE);
        !           265: }
        !           266: 
        !           267: //-----------------------------------------------------------------------
        !           268: /*
        !           269:   Double-check information read from boot-sector as this is sometimes found to be incorrect
        !           270:   The .ST image file should be divisible by the sector size & sectors per track
        !           271:   NOTE - Pass information from boot-sector to this function(if we can't decide we leave it alone)
        !           272: */
        !           273: void Floppy_DoubleCheckFormat(long DiscSize,unsigned short int *pnSides,unsigned short int *pnSectorsPerTrack)
        !           274: {
        !           275:   int nSectorsPerTrack;
        !           276:   long TotalSectors;
        !           277: 
        !           278:   /* Now guess at number of sides */
        !           279:   if (DiscSize<(500*1024))                      /* Is size is >500k assume 2 sides to disc! */
        !           280:     *pnSides = 1;
        !           281:   else
        !           282:     *pnSides = 2;
        !           283: 
        !           284:   /* And Sectors Per Track(always 512 bytes per sector) */
        !           285:   TotalSectors = DiscSize/512;                  /* # Sectors on disc image */
        !           286:   // Does this match up with what we've read from boot-sector?
        !           287:   nSectorsPerTrack = *pnSectorsPerTrack;
        !           288:   if (nSectorsPerTrack==0)                      /* Check valid, default to 9 */
        !           289:     nSectorsPerTrack = 9;
        !           290:   if ((TotalSectors%nSectorsPerTrack)!=0) {
        !           291:     /* No, we have an invalid boot-sector - re-calculate from disc size */
        !           292:     if ((TotalSectors%9)==0)                    /* Work in this order.... */
        !           293:       *pnSectorsPerTrack = 9;
        !           294:     else if ((TotalSectors%10)==0)
        !           295:       *pnSectorsPerTrack = 10;
        !           296:     else if ((TotalSectors%11)==0)
        !           297:       *pnSectorsPerTrack = 11;
        !           298:     else if ((TotalSectors%12)==0)
        !           299:       *pnSectorsPerTrack = 12;
        !           300:   }
        !           301:   /* else unknown, assume boot-sector is correct!!! */
        !           302: }
        !           303: 
        !           304: //-----------------------------------------------------------------------
        !           305: /*
        !           306:   Find details of disc image. We need to do this via a function as sometimes the boot-block
        !           307:   is not actually correct with the image - some demos/game discs have incorrect bytes in the
        !           308:   boot sector and this attempts to find the correct values.
        !           309: */
        !           310: void Floppy_FindDiscDetails(unsigned char *pBuffer,int nImageBytes,unsigned short int *pnSectorsPerTrack,unsigned short int *pnSides)
        !           311: {
        !           312:   unsigned char *pDiscBuffer;
        !           313:   unsigned short int nSectorsPerTrack=9,nSides=2;
        !           314: 
        !           315:   pDiscBuffer = pBuffer;
        !           316:   /* First do check to find number of sectors and bytes per sector */
        !           317:   nSectorsPerTrack = *(unsigned short int *)(pDiscBuffer+24);         /* SPT */
        !           318:   nSides = *(unsigned short int *)(pDiscBuffer+26);                   /* SIDE */
        !           319:   /* Now double-check info as boot-sector may contain incorrect information, eg 'Eat.st' demo, or single/double sides */
        !           320:   Floppy_DoubleCheckFormat(nImageBytes,&nSides,&nSectorsPerTrack);
        !           321: 
        !           322:   /* And set values */
        !           323:   if (pnSectorsPerTrack)
        !           324:     *pnSectorsPerTrack = nSectorsPerTrack;
        !           325:   if (pnSides)
        !           326:     *pnSides = nSides;
        !           327: }
        !           328: 
        !           329: //-----------------------------------------------------------------------
        !           330: /*
        !           331:   Read sectors from floppy disc image, return TRUE if all OK
        !           332:   NOTE Pass -ve as Count to read whole track
        !           333: */
        !           334: BOOL Floppy_ReadSectors(int Drive,char *pBuffer,unsigned short int Sector,unsigned short int Track,unsigned short int Side, short int Count, int *pnSectorsPerTrack)
        !           335: {
        !           336:   unsigned char *pDiscBuffer;
        !           337:   unsigned short int nSectorsPerTrack,nSides,nBytesPerTrack;
        !           338:   long Offset;
        !           339: 
        !           340:   // Do we have a disc in our drive?
        !           341:   if (EmulationDrives[Drive].bDiscInserted) {
        !           342:     // Looks good
        !           343:     StatusBar_SetIcon(STATUS_ICON_FLOPPY,ICONSTATE_UPDATE);
        !           344:     pDiscBuffer = EmulationDrives[Drive].pBuffer;
        !           345: 
        !           346:     // Find #sides and #sectors per track
        !           347:     Floppy_FindDiscDetails(EmulationDrives[Drive].pBuffer,EmulationDrives[Drive].nImageBytes,&nSectorsPerTrack,&nSides);
        !           348: 
        !           349:     // Need to read whole track?
        !           350:     if (Count<0)
        !           351:       Count = nSectorsPerTrack;
        !           352:     // Write back number of sector per track
        !           353:     if (pnSectorsPerTrack)
        !           354:       *pnSectorsPerTrack = nSectorsPerTrack;
        !           355: 
        !           356:     // Debug check as if we read over the end of a track we read into side 2!
        !           357:     if (Count>nSectorsPerTrack) {
        !           358:       ErrLog_File("ERROR Floppy_ReadSectors reading over single track\n");
        !           359:     }
        !           360: 
        !           361:     // Seek to sector
        !           362:     nBytesPerTrack = NUMBYTESPERSECTOR*nSectorsPerTrack;
        !           363:     Offset = nBytesPerTrack*Side;                 // First seek to side
        !           364:     Offset += (nBytesPerTrack*nSides)*Track;      // Then seek to track
        !           365:     Offset += (NUMBYTESPERSECTOR*(Sector-1));     // And finally to sector
        !           366:     // Read sectors (usually 512 bytes per sector)
        !           367:     memcpy(pBuffer,pDiscBuffer+Offset,(int)Count*NUMBYTESPERSECTOR);
        !           368: 
        !           369:     return(TRUE);
        !           370:   }
        !           371: 
        !           372:   return(FALSE);
        !           373: }
        !           374: 
        !           375: //-----------------------------------------------------------------------
        !           376: /*
        !           377:   Write sectors from floppy disc image, return TRUE if all OK
        !           378:   NOTE Pass -ve as Count to write whole track
        !           379: */
        !           380: BOOL Floppy_WriteSectors(int Drive,char *pBuffer,unsigned short int Sector,unsigned short int Track,unsigned short int Side, short int Count, int *pnSectorsPerTrack)
        !           381: {
        !           382:   unsigned char *pDiscBuffer;
        !           383:   unsigned short int nSectorsPerTrack,nSides,nBytesPerTrack;
        !           384:   long Offset;
        !           385: 
        !           386:   // Do we have a disc in our drive?
        !           387:   if (EmulationDrives[Drive].bDiscInserted) {
        !           388:     // Looks good
        !           389:     StatusBar_SetIcon(STATUS_ICON_FLOPPY,ICONSTATE_UPDATE);
        !           390:     pDiscBuffer = EmulationDrives[Drive].pBuffer;
        !           391: 
        !           392:     // Find #sides and #sectors per track
        !           393:     Floppy_FindDiscDetails(EmulationDrives[Drive].pBuffer,EmulationDrives[Drive].nImageBytes,&nSectorsPerTrack,&nSides);
        !           394: 
        !           395:     // Need to write whole track?
        !           396:     if (Count<0)
        !           397:       Count = nSectorsPerTrack;
        !           398:     // Write back number of sector per track
        !           399:     if (pnSectorsPerTrack)
        !           400:       *pnSectorsPerTrack = nSectorsPerTrack;
        !           401: 
        !           402:     // Debug check as if we write over the end of a track we write into side 2!
        !           403:     if (Count>nSectorsPerTrack) {
        !           404:       ErrLog_File("ERROR Floppy_WriteSectors reading over single track\n");
        !           405:     }
        !           406: 
        !           407:     // Seek to sector
        !           408:     nBytesPerTrack = NUMBYTESPERSECTOR*nSectorsPerTrack;
        !           409:     Offset = nBytesPerTrack*Side;          // First seek to side
        !           410:     Offset += (nBytesPerTrack*nSides)*Track;    // Then seek to track
        !           411:     Offset += (NUMBYTESPERSECTOR*(Sector-1));    // And finally to sector
        !           412:     // Write sectors (usually 512 bytes per sector)
        !           413:     memcpy(pDiscBuffer+Offset,pBuffer,(int)Count*NUMBYTESPERSECTOR);
        !           414:     // And set 'changed' flag
        !           415:     EmulationDrives[Drive].bContentsChanged = TRUE;
        !           416: 
        !           417:     return(TRUE);
        !           418:   }
        !           419: 
        !           420:   return(FALSE);
        !           421: }

unix.superglobalmegacorp.com

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