/** * Write sectors from floppy disk image, return TRUE if all OK * NOTE Pass -ve as Count to write whole track */ bool Floppy_WriteSectors(int Drive, Uint8 *pBuffer, Uint16 Sector, Uint16 Track, Uint16 Side, short Count, int *pnSectorsPerTrack, int *pSectorSize) { Uint8 *pDiskBuffer; Uint16 nSectorsPerTrack, nSides, nBytesPerTrack; long Offset; int nImageTracks; /* Do we have a writable disk in our drive? */ if (EmulationDrives[Drive].bDiskInserted && !Floppy_IsWriteProtected(Drive)) { /* Looks good */ pDiskBuffer = EmulationDrives[Drive].pBuffer; /* Find #sides and #sectors per track */ Floppy_FindDiskDetails(EmulationDrives[Drive].pBuffer,EmulationDrives[Drive].nImageBytes,&nSectorsPerTrack,&nSides); nImageTracks = ((EmulationDrives[Drive].nImageBytes / NUMBYTESPERSECTOR) / nSectorsPerTrack) / nSides; /* Need to write whole track? */ if (Count<0) Count = nSectorsPerTrack; /* Write back number of sector per track */ if (pnSectorsPerTrack) *pnSectorsPerTrack = nSectorsPerTrack; if (pSectorSize) *pSectorSize = NUMBYTESPERSECTOR; /* Size is 512 bytes for ST/MSA */ /* Debug check as if we write over the end of a track we write into side 2! */ if (Count > nSectorsPerTrack) { Log_Printf(LOG_DEBUG, "Floppy_WriteSectors: writing over single track\n"); } /* Check that the side number (0 or 1) does not exceed the amount of sides (1 or 2). */ if (Side >= nSides) { Log_Printf(LOG_DEBUG, "Floppy_WriteSectors: Program tries to write to side %i " "of a disk image with %i sides!\n", Side+1, nSides); return false; } /* Check if track number is in range */ if (Track >= nImageTracks) { Log_Printf(LOG_DEBUG, "Floppy_WriteSectors: Program tries to write to track %i " "of a disk image with only %i tracks!\n", Track, nImageTracks); return false; } /* Check if sector number is in range */ if (Sector <= 0 || Sector > nSectorsPerTrack) { Log_Printf(LOG_DEBUG, "Floppy_WriteSectors: Program tries to write to sector %i " "of a disk image with %i sectors per track!\n", Sector, nSectorsPerTrack); return false; } /* Seek to sector */ nBytesPerTrack = NUMBYTESPERSECTOR*nSectorsPerTrack; Offset = nBytesPerTrack*Side; /* First seek to side */ Offset += (nBytesPerTrack*nSides)*Track; /* Then seek to track */ Offset += (NUMBYTESPERSECTOR*(Sector-1)); /* And finally to sector */ /* Write sectors (usually 512 bytes per sector) */ memcpy(pDiskBuffer+Offset, pBuffer, (int)Count*NUMBYTESPERSECTOR); /* And set 'changed' flag */ EmulationDrives[Drive].bContentsChanged = true; return true; } return false; }
/** * Save compressed .MSA file from memory buffer. Returns true is all OK */ bool MSA_WriteDisk(const char *pszFileName, Uint8 *pBuffer, int ImageSize) { #ifdef SAVE_TO_MSA_IMAGES MSAHEADERSTRUCT *pMSAHeader; unsigned short int *pMSADataLength; Uint8 *pMSAImageBuffer, *pMSABuffer, *pImageBuffer; Uint16 nSectorsPerTrack, nSides, nCompressedBytes, nBytesPerTrack; bool nRet; int nTracks,nBytesToGo,nBytesRun; int Track,Side; /* Allocate workspace for compressed image */ pMSAImageBuffer = (Uint8 *)malloc(MSA_WORKSPACE_SIZE); if (!pMSAImageBuffer) { perror("MSA_WriteDisk"); return false; } /* Store header */ pMSAHeader = (MSAHEADERSTRUCT *)pMSAImageBuffer; pMSAHeader->ID = SDL_SwapBE16(0x0E0F); Floppy_FindDiskDetails(pBuffer,ImageSize, &nSectorsPerTrack, &nSides); pMSAHeader->SectorsPerTrack = SDL_SwapBE16(nSectorsPerTrack); pMSAHeader->Sides = SDL_SwapBE16(nSides-1); pMSAHeader->StartingTrack = SDL_SwapBE16(0); nTracks = ((ImageSize / NUMBYTESPERSECTOR) / nSectorsPerTrack) / nSides; pMSAHeader->EndingTrack = SDL_SwapBE16(nTracks-1); /* Compress image */ pMSABuffer = pMSAImageBuffer + sizeof(MSAHEADERSTRUCT); for (Track = 0; Track < nTracks; Track++) { for (Side = 0; Side < nSides; Side++) { /* Get track data pointer */ nBytesPerTrack = NUMBYTESPERSECTOR*nSectorsPerTrack; pImageBuffer = pBuffer + (nBytesPerTrack*Side) + ((nBytesPerTrack*nSides)*Track); /* Skip data length (fill in later) */ pMSADataLength = (Uint16 *)pMSABuffer; pMSABuffer += sizeof(Uint16); /* Compress track */ nBytesToGo = nBytesPerTrack; nCompressedBytes = 0; while (nBytesToGo > 0) { nBytesRun = MSA_FindRunOfBytes(pImageBuffer,nBytesToGo); if (nBytesRun == 0) { /* Just copy byte */ *pMSABuffer++ = *pImageBuffer++; nCompressedBytes++; nBytesRun = 1; } else { /* Store run! */ *pMSABuffer++ = 0xE5; /* Marker */ *pMSABuffer++ = *pImageBuffer; /* Byte, and follow with 16-bit length */ do_put_mem_word(pMSABuffer, nBytesRun); pMSABuffer += sizeof(Uint16); pImageBuffer += nBytesRun; nCompressedBytes += 4; } nBytesToGo -= nBytesRun; } /* Is compressed track smaller than the original? */ if (nCompressedBytes < nBytesPerTrack) { /* Yes, store size */ do_put_mem_word(pMSADataLength, nCompressedBytes); } else { /* No, just store uncompressed track */ do_put_mem_word(pMSADataLength, nBytesPerTrack); pMSABuffer = ((Uint8 *)pMSADataLength) + 2; pImageBuffer = pBuffer + (nBytesPerTrack*Side) + ((nBytesPerTrack*nSides)*Track); memcpy(pMSABuffer,pImageBuffer, nBytesPerTrack); pMSABuffer += nBytesPerTrack; } } } /* And save to file! */ nRet = File_Save(pszFileName,pMSAImageBuffer, pMSABuffer-pMSAImageBuffer, false); /* Free workspace */ free(pMSAImageBuffer); return nRet; #else /*SAVE_TO_MSA_IMAGES*/ /* Oops, cannot save */ return false; #endif /*SAVE_TO_MSA_IMAGES*/ }
/** * Read sectors from floppy disk image, return TRUE if all OK * NOTE Pass -ve as Count to read whole track */ bool Floppy_ReadSectors(int Drive, Uint8 **pBuffer, Uint16 Sector, Uint16 Track, Uint16 Side, short Count, int *pnSectorsPerTrack, int *pSectorSize) { Uint8 *pDiskBuffer; Uint16 nSectorsPerTrack, nSides, nBytesPerTrack; long Offset; int nImageTracks; /* Do we have a disk in our drive? */ if (EmulationDrives[Drive].bDiskInserted) { /* Looks good */ pDiskBuffer = EmulationDrives[Drive].pBuffer; /* Find #sides and #sectors per track */ Floppy_FindDiskDetails(EmulationDrives[Drive].pBuffer,EmulationDrives[Drive].nImageBytes,&nSectorsPerTrack,&nSides); nImageTracks = ((EmulationDrives[Drive].nImageBytes / NUMBYTESPERSECTOR) / nSectorsPerTrack) / nSides; /* Need to read whole track? */ if (Count<0) Count = nSectorsPerTrack; /* Write back number of sector per track */ if (pnSectorsPerTrack) *pnSectorsPerTrack = nSectorsPerTrack; if (pSectorSize) *pSectorSize = NUMBYTESPERSECTOR; /* Size is 512 bytes for ST/MSA */ /* Debug check as if we read over the end of a track we read into side 2! */ if (Count > nSectorsPerTrack) { Log_Printf(LOG_DEBUG, "Floppy_ReadSectors: reading over single track\n"); } /* Check that the side number (0 or 1) does not exceed the amount of sides (1 or 2). * (E.g. some games like Drakkhen or Bolo can load additional data from the * second disk side, but they also work with single side floppy drives) */ if (Side >= nSides) { Log_Printf(LOG_DEBUG, "Floppy_ReadSectors: Program tries to read from side %i " "of a disk image with %i sides!\n", Side+1, nSides); return false; } /* Check if track number is in range */ if (Track >= nImageTracks) { Log_Printf(LOG_DEBUG, "Floppy_ReadSectors: Program tries to read from track %i " "of a disk image with only %i tracks!\n", Track, nImageTracks); return false; } /* Check if sector number is in range */ if (Sector <= 0 || Sector > nSectorsPerTrack) { Log_Printf(LOG_DEBUG, "Floppy_ReadSectors: Program tries to read from sector %i " "of a disk image with %i sectors per track!\n", Sector, nSectorsPerTrack); return false; } /* Seek to sector */ nBytesPerTrack = NUMBYTESPERSECTOR*nSectorsPerTrack; Offset = nBytesPerTrack*Side; /* First seek to side */ Offset += (nBytesPerTrack*nSides)*Track; /* Then seek to track */ Offset += (NUMBYTESPERSECTOR*(Sector-1)); /* And finally to sector */ /* Return a pointer to the sectors data (usually 512 bytes per sector) */ *pBuffer = pDiskBuffer+Offset; return true; } return false; }
/** * Save .DIM file from memory buffer. Returns TRUE is all OK */ bool DIM_WriteDisk(int Drive, const char *pszFileName, Uint8 *pBuffer, int ImageSize) { #ifdef SAVE_TO_DIM_IMAGES unsigned short int nSectorsPerTrack, nSides; Uint8 *pDimFile; int nTracks; bool bRet; #if HAVE_LIBZ gzFile hGzFile; #else FILE *fhdl; #endif /* Allocate memory for the whole DIM image: */ pDimFile = malloc(ImageSize + 32); if (!pDimFile) { perror("DIM_WriteDisk"); return false; } memset(pDimFile, 0, 32); /* Try to load the old header data to preserve the header fields that are unknown yet: */ #if HAVE_LIBZ hGzFile = gzopen(pszFileName, "rb"); if (hGzFile != NULL) { gzread(hGzFile, pDimFile, 32); gzclose(hGzFile); } #else fhdl = fopen(pszFileName, "rb"); if (fhndl != NULL) { fread(pDimFile, 32, 1, fhndl); fclose(fhndl); } #endif /* Now fill in the new header information: */ Floppy_FindDiskDetails(pBuffer, ImageSize, &nSectorsPerTrack, &nSides); nTracks = ((ImageSize / NUMBYTESPERSECTOR) / nSectorsPerTrack) / nSides; pDimFile[0x00] = pDimFile[0x01] = 0x42; /* ID */ pDimFile[0x03] = 0; /* Image contains all sectors */ pDimFile[0x06] = nSides - 1; /* Sides */ pDimFile[0x08] = nSectorsPerTrack; /* Sectors per track */ pDimFile[0x0A] = 0; /* Starting track */ pDimFile[0x0C] = nTracks - 1; /* Ending track */ pDimFile[0x0D] = (ImageSize > 1024*1024); /* DD / HD flag */ /* Now copy the disk data: */ memcpy(pDimFile + 32, pBuffer, ImageSize); /* And finally save it: */ bRet = File_Save(pszFileName, pDimFile, ImageSize + 32, false); free(pDimFile); return bRet; #else /*SAVE_TO_ST_IMAGES*/ /* Oops, cannot save */ return false; #endif /*SAVE_TO_ST_IMAGES*/ }