Annotation of hatari/src/floppy.c, revision 1.1.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.