1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
|
/*
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";
#include "main.h"
#if HAVE_ZLIB_H
#include <zlib.h>
#endif
#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_t *DIM_ReadDisk(int Drive, const char *pszFileName, long *pImageSize, int *pImageType)
{
uint8_t *pDimFile;
uint8_t *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_t *pBuffer, int ImageSize)
{
#ifdef SAVE_TO_DIM_IMAGES
unsigned short int nSectorsPerTrack, nSides;
uint8_t *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*/
}
|