1 /*
2 Hatari tool: MSA and ST disk image creator and converter - hmsa.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
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <stdarg.h>
11 #include <string.h>
12
13 #include "hmsa.h"
14 #include "main.h" /* bool etc. */
15 #include "createBlankImage.h"
16 #include "file.h"
17 #include "msa.h"
18
19 /* prototypes for dummy log/alert functions below */
20 #include "dialog.h"
21 #include "log.h"
22
23 /**
24 * Print suitable output prefix based on log level
25 */
print_prefix(LOGTYPE nType)26 static void print_prefix(LOGTYPE nType)
27 {
28 const char *sType;
29 switch (nType) {
30 case LOG_FATAL:
31 case LOG_ERROR:
32 sType = "ERROR: ";
33 break;
34 case LOG_WARN:
35 sType = "WARNING: ";
36 break;
37 default:
38 return;
39 }
40 fputs(sType, stdout);
41 }
42
43 /* output newline if it's missing from text */
do_newline(const char * text)44 static void do_newline(const char *text)
45 {
46 if (text[strlen(text)-1] != '\n')
47 fputs("\n", stdout);
48 }
49
50 /**
51 * Output Hatari log string.
52 */
Log_Printf(LOGTYPE nType,const char * psFormat,...)53 extern void Log_Printf(LOGTYPE nType, const char *psFormat, ...)
54 {
55 va_list argptr;
56 print_prefix(nType);
57 va_start(argptr, psFormat);
58 vfprintf(stdout, psFormat, argptr);
59 va_end(argptr);
60 }
61
62 /**
63 * Output Hatari Alert dialog string.
64 */
Log_AlertDlg(LOGTYPE nType,const char * psFormat,...)65 extern void Log_AlertDlg(LOGTYPE nType, const char *psFormat, ...)
66 {
67 va_list argptr;
68 print_prefix(nType);
69 va_start(argptr, psFormat);
70 vfprintf(stdout, psFormat, argptr);
71 va_end(argptr);
72 do_newline(psFormat);
73 }
74
75 /**
76 * Output Hatari Query dialog string.
77 */
DlgAlert_Query(const char * text)78 int DlgAlert_Query(const char *text)
79 {
80 puts(text);
81 do_newline(text);
82 return TRUE;
83 }
84
85
86 /**
87 * ../src/file.c requires zip.c, which calls IPF_FileNameIsIPF
88 * We create an empty function to replace it, as we don't use IPF here
89 * and don't want to compile with all the IPF related files.
90 * We do it also for STX.
91 */
92 extern bool IPF_FileNameIsIPF(const char *pszFileName, bool bAllowGZ); /* function prototype */
IPF_FileNameIsIPF(const char * pszFileName,bool bAllowGZ)93 extern bool IPF_FileNameIsIPF(const char *pszFileName, bool bAllowGZ)
94 {
95 return FALSE;
96 }
97 extern bool STX_FileNameIsSTX(const char *pszFileName, bool bAllowGZ); /* function prototype */
STX_FileNameIsSTX(const char * pszFileName,bool bAllowGZ)98 extern bool STX_FileNameIsSTX(const char *pszFileName, bool bAllowGZ)
99 {
100 return FALSE;
101 }
102
103
104 /**
105 * Create MSA or ST image of requested size.
106 * return error string or NULL for success.
107 */
create_image(const char * filename,const char * sizeid)108 static const char* create_image(const char *filename, const char *sizeid)
109 {
110 int tracks, sectors, sides;
111 tracks = 80;
112
113 if (strcasecmp(sizeid, "ss") == 0) {
114 sides = 1;
115 sectors = 9;
116 } else if (strcasecmp(sizeid, "ds") == 0) {
117 sides = 2;
118 sectors = 9;
119 } else if (strcasecmp(sizeid, "hd") == 0) {
120 sides = 2;
121 sectors = 18;
122 } else if (strcasecmp(sizeid, "ed") == 0) {
123 sides = 2;
124 sectors = 36;
125 } else {
126 return "ERROR: given disk size isn't one of supported ones!\n";
127 }
128 if (CreateBlankImage_CreateFile(filename, tracks, sectors, sides)) {
129 return NULL;
130 }
131 return "ERROR: Disk creation failed.\n";
132 }
133
134 /**
135 * Print program usage
136 */
usage(const char * name)137 static void usage(const char *name)
138 {
139 printf("\n\
140 Hatari MSA (Magic Shadow Archiver) / ST disk image creator & converter v0.3.\n\
141 \n\
142 Usage: %s FILENAME [DISK SIZE]\n\
143 \n\
144 If you give only one parameter - the file name of an existing MSA\n\
145 or ST disk image, this image will be converted to the other disk image\n\
146 format under a suitable new file name. Disk image format is recognized\n\
147 based on the file name extension (.msa or .st).\n\
148 \n\
149 If the given file doesn't exist and you give also a disk size\n\
150 (SS, DS, HD, ED), an empty disk of the given size will be created.\n\
151 \n\
152 This software is distributed under the GNU General Public License, version 2\n\
153 or at your option any later version. Please read the file gpl.txt for details.\n\
154 \n",
155 name);
156 }
157
158 /**
159 * Command line argument parsing and new disk creation
160 */
main(int argc,char * argv[])161 int main(int argc, char *argv[])
162 {
163 bool isMsa;
164 int retval;
165 long disksize;
166 unsigned char *diskbuf;
167 const char *srcfile, *srcdot;
168 char *dstfile, *dstdot;
169 int ImageType;
170 int drive;
171
172 if(argc < 2 || argv[1][0] == '-') {
173 usage(argv[0]);
174 return 0;
175 }
176
177 srcfile = argv[1];
178 srcdot = strrchr(srcfile, '.');
179 if(srcdot == NULL) {
180 usage(argv[0]);
181 fprintf(stderr, "ERROR: extension missing for file name %s!\n", argv[1]);
182 return -1;
183 }
184
185 if (strcasecmp(srcdot, ".msa") == 0) {
186 isMsa = true;
187 } else if (strcasecmp(srcdot, ".st") == 0) {
188 isMsa = false;
189 } else {
190 usage(argv[0]);
191 fprintf(stderr, "ERROR: unrecognized file name extension %s (not .msa or .st)!\n", srcdot);
192 return -1;
193 }
194
195 if (!File_Exists(srcfile)) {
196 const char *errstr;
197 if (argc != 3) {
198 usage(argv[0]);
199 fprintf(stderr, "ERROR: disk size for the new disk image not given!\n");
200 return -1;
201 }
202 errstr = create_image(srcfile, argv[2]);
203 if (errstr) {
204 usage(argv[0]);
205 fputs(errstr, stderr);
206 return -1;
207 }
208 return 0;
209 }
210
211 dstfile = malloc(strlen(srcfile) + 6);
212 if (dstfile == NULL) {
213 fprintf(stderr, "ERROR: No memory for new disk name!\n");
214 return -1;
215 }
216
217 strcpy(dstfile, srcfile);
218 dstdot = strrchr(dstfile, '.');
219 if (isMsa) {
220 /* Convert MSA to ST disk image */
221 strcpy(dstdot, ".st");
222 } else {
223 /* Convert ST to MSA disk image */
224 strcpy(dstdot, ".msa");
225 }
226
227 if (File_Exists(dstfile)) {
228 fprintf(stderr, "ERROR: Destination disk image %s exists already!\n", dstfile);
229 free(dstfile);
230 return -1;
231 }
232
233 drive = 0; /* drive is not used for ST/MSA/DIM, set it to 0 */
234
235 if (isMsa) {
236 /* Read the source disk image */
237 diskbuf = MSA_ReadDisk(drive, srcfile, &disksize, &ImageType);
238 if (!diskbuf || disksize < 512*8) {
239 fprintf(stderr, "ERROR: could not read MSA disk %s!\n", srcfile);
240 retval = -1;
241 } else {
242 printf("Converting %s to %s (%li Bytes).\n", srcfile, dstfile, disksize);
243 retval = File_Save(dstfile, diskbuf, disksize, FALSE);
244 }
245 } else {
246 /* Just read disk image directly into buffer */
247 disksize = 0;
248 diskbuf = HFile_Read(srcfile, &disksize, NULL);
249 if (!diskbuf || disksize < 512*8) {
250 fprintf(stderr, "ERROR: could not read ST disk %s!\n", srcfile);
251 retval = -1;
252 } else {
253 printf("Converting %s to %s (%li Bytes).\n", srcfile, dstfile, disksize);
254 retval = MSA_WriteDisk(drive, dstfile, diskbuf, disksize);
255 }
256 }
257
258 if (diskbuf) {
259 free(diskbuf);
260 }
261 free(dstfile);
262
263 return retval;
264 }
265