|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.