File: dim.c

package info (click to toggle)
hatari 2.5.0%2Bdfsg-1
  • links: PTS
  • area: main
  • in suites: trixie
  • size: 12,744 kB
  • sloc: ansic: 164,630; cpp: 8,685; python: 6,251; objc: 1,899; asm: 1,742; sh: 1,668; javascript: 146; makefile: 86; xml: 32
file content (178 lines) | stat: -rw-r--r-- 4,877 bytes parent folder | download | duplicates (2)
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*/
}