HatariWii/src/dim.c

177 lines
4.8 KiB
C

/*
Hatari - dim.c
This file is distributed under the GNU General Public License, version 2
or at your option any later version. Read the file gpl.txt for details.
DIM disk image support.
*/
const char DIM_fileid[] = "Hatari dim.c : " __DATE__ " " __TIME__;
#include <zlib.h>
#include "main.h"
#include "file.h"
#include "floppy.h"
#include "dim.h"
#undef SAVE_TO_DIM_IMAGES
/*
.DIM FILE FORMAT
--===============-------------------------------------------------------------
The file format of normal .DIM image files are quite the same as the .ST image
files (see st.c) - the .DIM image files just have an additional header of
32 bytes. However, there are also "compressed" images which only contain the
used sectors of the disk. It is necessary to parse the FAT to "uncompress"
these images.
The header contains following information:
Offset Size Description
------ -------- -----------
0x0000 Word ID Header (0x4242('BB'))
0x0002 Byte 1 = disk configuration has been detected automatically
0 = the user specified the disk configuration
0x0003 Byte Image contains all sectors (0) or only used sectors (1)
0x0006 Byte Sides (0 or 1; add 1 to this to get correct number of sides)
0x0008 Byte Sectors per track
0x000A Byte Starting Track (0 based)
0x000C Byte Ending Track (0 based)
0x000D Byte Double-Density(0) or High-Density (1)
0x000E 18 Bytes A copy of the Bios Parameter Block (BPB) of this disk.
*/
/*-----------------------------------------------------------------------*/
/**
* Does filename end with a .DIM extension? If so, return TRUE
*/
bool DIM_FileNameIsDIM(const char *pszFileName, bool bAllowGZ)
{
return(File_DoesFileExtensionMatch(pszFileName,".dim")
|| (bAllowGZ && File_DoesFileExtensionMatch(pszFileName,".dim.gz")));
}
/*-----------------------------------------------------------------------*/
/**
* Load .DIM file into memory, set number of bytes loaded and return a pointer
* to the buffer.
*/
Uint8 *DIM_ReadDisk(int Drive, const char *pszFileName, long *pImageSize, int *pImageType)
{
Uint8 *pDimFile;
Uint8 *pDiskBuffer = NULL;
/* Load file into buffer */
pDimFile = File_Read(pszFileName, pImageSize, NULL);
if (pDimFile)
{
/* Check header for valid image: */
if (pDimFile[0x00] != 0x42 || pDimFile[0x01] != 0x42 ||
pDimFile[0x03] != 0 || pDimFile[0x0A] != 0)
{
fprintf(stderr, "This is not a valid DIM image!\n");
*pImageSize = 0;
free(pDimFile);
return NULL;
}
/* Simply use disk contents without the DIM header: */
*pImageSize -= 32;
pDiskBuffer = malloc(*pImageSize);
if (pDiskBuffer)
memcpy(pDiskBuffer, pDimFile+32, *pImageSize);
else
perror("DIM_ReadDisk");
/* Free DIM file we loaded */
free(pDimFile);
}
if (pDiskBuffer == NULL)
{
*pImageSize = 0;
return NULL;
}
*pImageType = FLOPPY_IMAGE_TYPE_DIM;
return pDiskBuffer;
}
/*-----------------------------------------------------------------------*/
/**
* 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*/
}