1 /*
2 Hatari - createBlankImage.c
3
4 This file is distributed under the GNU General Public License, version 2
5 or at your option any later version. Read the file gpl.txt for details.
6
7 Create blank .ST/.MSA disk images.
8 */
9 const char CreateBlankImage_fileid[] = "Hatari createBlankImage.c : " __DATE__ " " __TIME__;
10
11 #include "main.h"
12 #include "configuration.h"
13 #include "dim.h"
14 #include "file.h"
15 #include "floppy.h"
16 #include "log.h"
17 #include "msa.h"
18 #include "st.h"
19 #include "createBlankImage.h"
20
21 /*-----------------------------------------------------------------------*/
22 /*
23 40 track SS 40 track DS 80 track SS 80 track DS
24 0- 1 Branch instruction to boot program if executable
25 2- 7 'Loader'
26 8-10 24-bit serial number
27 11-12 BPS 512 512 512 512
28 13 SPC 1 2 2 2
29 14-15 RES 1 1 1 1
30 16 FAT 2 2 2 2
31 17-18 DIR 64 112 112 112
32 19-20 SEC 360 720 720 1440
33 21 MEDIA $FC $FD $F8 $F9 (isn't used by ST-BIOS)
34 22-23 SPF 2 2 5 5
35 24-25 SPT 9 9 9 9
36 26-27 SIDE 1 2 1 2
37 28-29 HID 0 0 0 0
38 510-511 CHECKSUM
39 */
40
41
42 /*-----------------------------------------------------------------------*/
43 /**
44 * Calculate the size of a disk in dialog.
45 */
CreateBlankImage_GetDiskImageCapacity(int nTracks,int nSectors,int nSides)46 static int CreateBlankImage_GetDiskImageCapacity(int nTracks, int nSectors, int nSides)
47 {
48 /* Find size of disk image */
49 return nTracks*nSectors*nSides*NUMBYTESPERSECTOR;
50 }
51
52
53 /*-----------------------------------------------------------------------*/
54 /**
55 * Write a short integer to addr using little endian byte order
56 * (needed for 16 bit values in the bootsector of the disk image).
57 */
WriteShortLE(void * addr,Uint16 val)58 static inline void WriteShortLE(void *addr, Uint16 val)
59 {
60 Uint8 *p = (Uint8 *)addr;
61
62 p[0] = (Uint8)val;
63 p[1] = (Uint8)(val >> 8);
64 }
65
66
67 /*-----------------------------------------------------------------------*/
68 /**
69 * Create .ST/.MSA disk image according to 'Tracks,Sector,Sides' and save
70 * it under given filename.
71 * Return true if saving succeeded, false otherwise.
72 */
CreateBlankImage_CreateFile(const char * pszFileName,int nTracks,int nSectors,int nSides)73 bool CreateBlankImage_CreateFile(const char *pszFileName, int nTracks, int nSectors, int nSides)
74 {
75 Uint8 *pDiskFile;
76 unsigned long nDiskSize;
77 unsigned short int SPC, nDir, MediaByte, SPF;
78 bool bRet = false;
79 int drive;
80
81 /* HD/ED disks are all double sided */
82 if (nSectors >= 18)
83 nSides = 2;
84
85 /* Calculate size of disk image */
86 nDiskSize = CreateBlankImage_GetDiskImageCapacity(nTracks, nSectors, nSides);
87
88 /* Allocate space for our 'file', and blank */
89 pDiskFile = malloc(nDiskSize);
90 if (pDiskFile == NULL)
91 {
92 perror("Error while creating blank disk image");
93 return false;
94 }
95 memset(pDiskFile, 0, nDiskSize); /* Clear buffer */
96
97 /* Fill in boot-sector */
98 pDiskFile[0] = 0xE9; /* Needed for MS-DOS compatibility */
99 memset(pDiskFile+2, 0x4e, 6); /* 2-7 'Loader' */
100
101 WriteShortLE(pDiskFile+8, rand()); /* 8-10 24-bit serial number */
102 pDiskFile[10] = rand();
103
104 WriteShortLE(pDiskFile+11, NUMBYTESPERSECTOR); /* 11-12 BPS */
105
106 if ((nTracks == 40) && (nSides == 1))
107 SPC = 1;
108 else
109 SPC = 2;
110 pDiskFile[13] = SPC; /* 13 SPC */
111
112 WriteShortLE(pDiskFile+14, 1); /* 14-15 RES */
113 pDiskFile[16] = 2; /* 16 FAT */
114
115 if (SPC==1)
116 nDir = 64;
117 else if (nSectors < 18)
118 nDir = 112;
119 else
120 nDir = 224;
121 WriteShortLE(pDiskFile+17, nDir); /* 17-18 DIR */
122
123 WriteShortLE(pDiskFile+19, nTracks*nSectors*nSides); /* 19-20 SEC */
124
125 if (nSectors >= 18)
126 MediaByte = 0xF0;
127 else
128 {
129 if (nTracks <= 42)
130 MediaByte = 0xFC;
131 else
132 MediaByte = 0xF8;
133 if (nSides == 2)
134 MediaByte |= 0x01;
135 }
136 pDiskFile[21] = MediaByte; /* 21 MEDIA */
137
138 if (nSectors >= 18)
139 SPF = 9;
140 else if (nTracks >= 80)
141 SPF = 5;
142 else
143 SPF = 2;
144 WriteShortLE(pDiskFile+22, SPF); /* 22-23 SPF */
145
146 WriteShortLE(pDiskFile+24, nSectors); /* 24-25 SPT */
147 WriteShortLE(pDiskFile+26, nSides); /* 26-27 SIDE */
148 WriteShortLE(pDiskFile+28, 0); /* 28-29 HID */
149
150 /* Set correct media bytes in the 1st FAT: */
151 pDiskFile[512] = MediaByte;
152 pDiskFile[513] = pDiskFile[514] = 0xFF;
153 /* Set correct media bytes in the 2nd FAT: */
154 pDiskFile[512 + SPF * 512] = MediaByte;
155 pDiskFile[513 + SPF * 512] = pDiskFile[514 + SPF * 512] = 0xFF;
156
157 /* Ask if OK to overwrite, if exists? */
158 if (File_QueryOverwrite(pszFileName))
159 {
160 drive = 0; /* drive is not used for ST/MSA/DIM, set it to 0 */
161 /* Save image to file */
162 if (MSA_FileNameIsMSA(pszFileName, true))
163 bRet = MSA_WriteDisk(drive, pszFileName, pDiskFile, nDiskSize);
164 else if (ST_FileNameIsST(pszFileName, true))
165 bRet = ST_WriteDisk(drive, pszFileName, pDiskFile, nDiskSize);
166 else if (DIM_FileNameIsDIM(pszFileName, true))
167 bRet = DIM_WriteDisk(drive, pszFileName, pDiskFile, nDiskSize);
168 else
169 Log_AlertDlg(LOG_ERROR, "Unknown floppy image filename extension!");
170
171 /* Did create successfully? */
172 if (bRet)
173 {
174 /* Say OK */
175 Log_AlertDlg(LOG_INFO, "Disk image '%s' created.", pszFileName);
176 }
177 else
178 {
179 /* Warn user we were unable to create image */
180 Log_AlertDlg(LOG_ERROR, "Unable to create disk image '%s'!", pszFileName);
181 }
182 }
183
184 /* Free image */
185 free(pDiskFile);
186 return bRet;
187 }
188