1 /*
2 * cartconv - Cartridge Conversion utility.
3 *
4 * Written by
5 * Marco van den heuvel <blackystardust68@yahoo.com>
6 * groepaz <groepaz@gmx.net>
7 *
8 * This file is part of VICE, the Versatile Commodore Emulator.
9 * See README for copyright notice.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 * 02111-1307 USA.
25 *
26 */
27
28 #include "vice.h"
29
30 #include <assert.h>
31 #include <ctype.h>
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <string.h>
35
36 #ifdef HAVE_STRINGS_H
37 #include <strings.h>
38 #endif
39
40 #ifdef HAVE_UNISTD_H
41 #include <unistd.h>
42 #endif
43
44 #if defined(WATCOM_COMPILE) && defined(HAVE_IO_H)
45 #include <io.h>
46 #endif
47
48
49 #include "version.h"
50
51 #ifdef USE_SVN_REVISION
52 # include "svnversion.h"
53 #endif
54
55 #include "cartridge.h"
56
57 static FILE *infile, *outfile;
58 static int load_address = 0;
59 static int loadfile_offset = 0;
60 static unsigned int loadfile_size = 0;
61 static char *output_filename = NULL;
62 static char *input_filename[33];
63 static char *cart_name = NULL;
64 static signed char cart_type = -1;
65 static char convert_to_bin = 0;
66 static char convert_to_prg = 0;
67 static char convert_to_ultimax = 0;
68 static unsigned char input_filenames = 0;
69 static char loadfile_is_crt = 0;
70 static char loadfile_is_ultimax = 0;
71 static int loadfile_cart_type = 0;
72 static unsigned char filebuffer[(1024 * 1024) + 2];
73 static unsigned char headerbuffer[0x40];
74 static unsigned char extra_buffer_32kb[0x8000];
75 static unsigned char chipbuffer[16];
76 static int repair_mode = 0;
77 static int input_padding = 0;
78 static int quiet_mode = 0;
79 static int omit_empty_banks = 1;
80
81 static int load_input_file(char *filename);
82
83 typedef struct cart_s {
84 unsigned char exrom;
85 unsigned char game;
86 unsigned int sizes;
87 unsigned int bank_size;
88 unsigned int load_address;
89 unsigned char banks; /* 0 means the amount of banks need to be taken from the load-size and bank-size */
90 unsigned int data_type;
91 char *name;
92 char *opt;
93 void (*save)(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char gameline, unsigned char exromline);
94 } cart_t;
95
96 typedef struct sorted_cart_s {
97 char *opt;
98 char *name;
99 int crt_id;
100 int insertion;
101 } sorted_cart_t;
102
103 /* some prototypes to save routines */
104 static void save_regular_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char game, unsigned char exrom);
105 static void save_fcplus_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char game, unsigned char exrom);
106 static void save_2_blocks_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char game, unsigned char exrom);
107 static void save_generic_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char p5, unsigned char p6);
108 static void save_easyflash_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char game, unsigned char exrom);
109 static void save_ocean_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char game, unsigned char exrom);
110 static void save_funplay_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char game, unsigned char exrom);
111 static void save_zaxxon_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char game, unsigned char exrom);
112 static void save_stardos_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char game, unsigned char exrom);
113 static void save_delaep64_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char game, unsigned char exrom);
114 static void save_delaep256_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char game, unsigned char exrom);
115 static void save_delaep7x8_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char game, unsigned char exrom);
116 static void save_rexep256_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char game, unsigned char exrom);
117 static void save_easycalc_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char game, unsigned char exrom);
118
119 /* this table must be in correct order so it can be indexed by CRT ID */
120 /*
121 exrom, game, sizes, bank size, load addr, num banks, data type, name, option, saver
122
123 num banks == 0 - take number of banks from input file size
124 */
125 static const cart_t cart_info[] = {
126 /* {0, 1, CARTRIDGE_SIZE_8KB, 0x2000, 0x8000, 1, 0, "Generic 8kb", NULL, NULL}, */ /* 8k game config */
127 /* {0, 0, CARTRIDGE_SIZE_12KB, 0x3000, 0x8000, 1, 0, "Generic 12kb", NULL, NULL}, */ /* 16k game config */
128 /* {0, 0, CARTRIDGE_SIZE_16KB, 0x4000, 0x8000, 1, 0, "Generic 16kb", NULL, NULL}, */ /* 16k game config */
129 /* {1, 0, CARTRIDGE_SIZE_4KB | CARTRIDGE_SIZE_16KB, 0, 0, 1, 0, "Ultimax", NULL, NULL}, */ /* ultimax config */
130
131 /* FIXME: initial exrom/game values are often wrong in this table
132 * don't forget to also update vice.texi accordingly */
133
134 {0, 1, CARTRIDGE_SIZE_4KB | CARTRIDGE_SIZE_8KB | CARTRIDGE_SIZE_12KB | CARTRIDGE_SIZE_16KB, 0, 0, 0, 0, "Generic Cartridge", NULL, save_generic_crt},
135 {0, 1, CARTRIDGE_SIZE_32KB, 0x2000, 0x8000, 4, 0, CARTRIDGE_NAME_ACTION_REPLAY, "ar5", save_regular_crt}, /* this is NOT AR1, but 4.2,5,6 etc */
136 {0, 0, CARTRIDGE_SIZE_16KB, 0x2000, 0, 2, 0, CARTRIDGE_NAME_KCS_POWER, "kcs", save_2_blocks_crt},
137 {0, 0, CARTRIDGE_SIZE_64KB | CARTRIDGE_SIZE_256KB, 0x4000, 0x8000, 0, 0, CARTRIDGE_NAME_FINAL_III, "fc3", save_regular_crt},
138 {0, 0, CARTRIDGE_SIZE_16KB, 0x2000, 0, 2, 0, CARTRIDGE_NAME_SIMONS_BASIC, "simon", save_2_blocks_crt},
139 {0, 0, CARTRIDGE_SIZE_32KB | CARTRIDGE_SIZE_128KB | CARTRIDGE_SIZE_256KB | CARTRIDGE_SIZE_512KB, 0x2000, 0, 0, 0, CARTRIDGE_NAME_OCEAN, "ocean", save_ocean_crt},
140 {1, 0, CARTRIDGE_SIZE_8KB, 0x2000, 0x8000, 1, 2, CARTRIDGE_NAME_EXPERT, "expert", NULL},
141 {0, 1, CARTRIDGE_SIZE_128KB, 0x2000, 0x8000, 16, 0, CARTRIDGE_NAME_FUNPLAY, "fp", save_funplay_crt},
142 {0, 0, CARTRIDGE_SIZE_64KB, 0x4000, 0x8000, 4, 0, CARTRIDGE_NAME_SUPER_GAMES, "sg", save_regular_crt},
143 {0, 1, CARTRIDGE_SIZE_32KB, 0x2000, 0x8000, 4, 0, CARTRIDGE_NAME_ATOMIC_POWER, "ap", save_regular_crt},
144 {0, 1, CARTRIDGE_SIZE_8KB, 0x2000, 0x8000, 1, 0, CARTRIDGE_NAME_EPYX_FASTLOAD, "epyx", save_regular_crt},
145 {0, 0, CARTRIDGE_SIZE_16KB, 0x4000, 0x8000, 1, 0, CARTRIDGE_NAME_WESTERMANN, "wl", save_regular_crt},
146 {0, 1, CARTRIDGE_SIZE_8KB, 0x2000, 0x8000, 1, 0, CARTRIDGE_NAME_REX, "ru", save_regular_crt},
147 {0, 0, CARTRIDGE_SIZE_16KB, 0x4000, 0x8000, 1, 0, CARTRIDGE_NAME_FINAL_I, "fc1", save_regular_crt},
148 {1, 0, CARTRIDGE_SIZE_64KB | CARTRIDGE_SIZE_96KB | CARTRIDGE_SIZE_128KB, 0x2000, 0xe000, 0, 0, CARTRIDGE_NAME_MAGIC_FORMEL, "mf", save_regular_crt}, /* FIXME: 64k (v1), 96k (v2) and 128k (full) bins exist */
149 {0, 1, CARTRIDGE_SIZE_512KB, 0x2000, 0x8000, 64, 0, CARTRIDGE_NAME_GS, "gs", save_regular_crt},
150 {0, 0, CARTRIDGE_SIZE_16KB, 0x4000, 0x8000, 1, 0, CARTRIDGE_NAME_WARPSPEED, "ws", save_regular_crt},
151 {0, 1, CARTRIDGE_SIZE_128KB, 0x2000, 0x8000, 16, 0, CARTRIDGE_NAME_DINAMIC, "din", save_regular_crt},
152 {0, 0, CARTRIDGE_SIZE_20KB, 0, 0, 3, 0, CARTRIDGE_NAME_ZAXXON, "zaxxon", save_zaxxon_crt},
153 {0, 1, CARTRIDGE_SIZE_32KB | CARTRIDGE_SIZE_64KB | CARTRIDGE_SIZE_128KB | CARTRIDGE_SIZE_256KB | CARTRIDGE_SIZE_512KB | CARTRIDGE_SIZE_1024KB, 0x2000, 0x8000, 0, 0, CARTRIDGE_NAME_MAGIC_DESK, "md", save_regular_crt},
154 {0, 0, CARTRIDGE_SIZE_64KB, 0x4000, 0x8000, 4, 0, CARTRIDGE_NAME_SUPER_SNAPSHOT_V5, "ss5", save_regular_crt},
155 {0, 0, CARTRIDGE_SIZE_64KB | CARTRIDGE_SIZE_128KB, 0x4000, 0x8000, 0, 0, CARTRIDGE_NAME_COMAL80, "comal", save_regular_crt},
156 {1, 0, CARTRIDGE_SIZE_16KB, 0x2000, 0x8000, 2, 0, CARTRIDGE_NAME_STRUCTURED_BASIC, "sb", save_regular_crt},
157 {0, 0, CARTRIDGE_SIZE_16KB | CARTRIDGE_SIZE_32KB, 0x4000, 0x8000, 0, 0, CARTRIDGE_NAME_ROSS, "ross", save_regular_crt},
158 {0, 1, CARTRIDGE_SIZE_8KB, 0, 0x8000, 0, 0, CARTRIDGE_NAME_DELA_EP64, "dep64", save_delaep64_crt},
159 {0, 1, CARTRIDGE_SIZE_8KB, 0x2000, 0x8000, 0, 0, CARTRIDGE_NAME_DELA_EP7x8, "dep7x8", save_delaep7x8_crt},
160 {0, 1, CARTRIDGE_SIZE_8KB, 0x2000, 0x8000, 0, 0, CARTRIDGE_NAME_DELA_EP256, "dep256", save_delaep256_crt},
161 {0, 1, CARTRIDGE_SIZE_8KB, 0, 0x8000, 0, 0, CARTRIDGE_NAME_REX_EP256, "rep256", save_rexep256_crt},
162 {0, 1, CARTRIDGE_SIZE_8KB, 0x2000, 0x8000, 1, 0, CARTRIDGE_NAME_MIKRO_ASSEMBLER, "mikro", save_regular_crt},
163 {1, 0, CARTRIDGE_SIZE_24KB | CARTRIDGE_SIZE_32KB, 0x8000, 0x0000, 1, 0, CARTRIDGE_NAME_FINAL_PLUS, "fcp", save_fcplus_crt},
164 {0, 1, CARTRIDGE_SIZE_32KB, 0x2000, 0x8000, 4, 0, CARTRIDGE_NAME_ACTION_REPLAY4, "ar4", save_regular_crt},
165 {1, 0, CARTRIDGE_SIZE_16KB, 0x2000, 0, 4, 0, CARTRIDGE_NAME_STARDOS, "star", save_stardos_crt},
166 {1, 0, CARTRIDGE_SIZE_1024KB, 0x2000, 0, 128, 0, CARTRIDGE_NAME_EASYFLASH, "easy", save_easyflash_crt},
167 {0, 0, 0, 0, 0, 0, 0, CARTRIDGE_NAME_EASYFLASH_XBANK, NULL, NULL}, /* TODO ?? */
168 {1, 1, CARTRIDGE_SIZE_8KB, 0x2000, 0x8000, 1, 0, CARTRIDGE_NAME_CAPTURE, "cap", save_regular_crt},
169 {0, 1, CARTRIDGE_SIZE_16KB, 0x2000, 0x8000, 2, 0, CARTRIDGE_NAME_ACTION_REPLAY3, "ar3", save_regular_crt},
170 {0, 1, CARTRIDGE_SIZE_32KB | CARTRIDGE_SIZE_64KB | CARTRIDGE_SIZE_128KB, 0x2000, 0x8000, 0, 0, CARTRIDGE_NAME_RETRO_REPLAY, "rr", save_regular_crt},
171 {0, 1, CARTRIDGE_SIZE_8KB, 0x2000, 0x8000, 1, 0, CARTRIDGE_NAME_MMC64, "mmc64", save_regular_crt},
172 {0, 0, CARTRIDGE_SIZE_64KB | CARTRIDGE_SIZE_512KB, 0x2000, 0x8000, 0, 0, CARTRIDGE_NAME_MMC_REPLAY, "mmcr", save_regular_crt},
173 {0, 1, CARTRIDGE_SIZE_64KB | CARTRIDGE_SIZE_128KB | CARTRIDGE_SIZE_512KB, 0x4000, 0x8000, 0, 2, CARTRIDGE_NAME_IDE64, "ide64", save_regular_crt},
174 {0, 0, CARTRIDGE_SIZE_32KB, 0x4000, 0x8000, 2, 0, CARTRIDGE_NAME_SUPER_SNAPSHOT, "ss4", save_regular_crt},
175 {0, 1, CARTRIDGE_SIZE_4KB, 0x1000, 0x8000, 1, 0, CARTRIDGE_NAME_IEEE488, "ieee", save_regular_crt},
176 {1, 0, CARTRIDGE_SIZE_8KB, 0x2000, 0xe000, 1, 0, CARTRIDGE_NAME_GAME_KILLER, "gk", save_regular_crt},
177 {0, 1, CARTRIDGE_SIZE_256KB, 0x2000, 0x8000, 32, 0, CARTRIDGE_NAME_P64, "p64", save_regular_crt},
178 {1, 0, CARTRIDGE_SIZE_8KB, 0x2000, 0xe000, 1, 0, CARTRIDGE_NAME_EXOS, "exos", save_regular_crt},
179 {0, 1, CARTRIDGE_SIZE_8KB, 0x2000, 0x8000, 1, 0, CARTRIDGE_NAME_FREEZE_FRAME, "ff", save_regular_crt},
180 {0, 1, CARTRIDGE_SIZE_16KB | CARTRIDGE_SIZE_32KB, 0x4000, 0x8000, 0, 0, CARTRIDGE_NAME_FREEZE_MACHINE, "fm", save_regular_crt},
181 {0, 0, CARTRIDGE_SIZE_4KB, 0x1000, 0xe000, 1, 0, CARTRIDGE_NAME_SNAPSHOT64, "s64", save_regular_crt},
182 {0, 1, CARTRIDGE_SIZE_16KB, 0x2000, 0x8000, 2, 0, CARTRIDGE_NAME_SUPER_EXPLODE_V5, "se5", save_regular_crt},
183 {1, 0, CARTRIDGE_SIZE_16KB, 0x4000, 0x8000, 1, 0, CARTRIDGE_NAME_MAGIC_VOICE, "mv", save_regular_crt},
184 {0, 1, CARTRIDGE_SIZE_16KB, 0x2000, 0x8000, 2, 0, CARTRIDGE_NAME_ACTION_REPLAY2, "ar2", save_regular_crt},
185 {0, 1, CARTRIDGE_SIZE_4KB | CARTRIDGE_SIZE_8KB, 0x2000, 0x8000, 0, 0, CARTRIDGE_NAME_MACH5, "mach5", save_regular_crt},
186 {0, 1, CARTRIDGE_SIZE_8KB, 0x2000, 0x8000, 1, 0, CARTRIDGE_NAME_DIASHOW_MAKER, "dsm", save_regular_crt},
187 {0, 0, CARTRIDGE_SIZE_64KB, 0x4000, 0x8000, 4, 0, CARTRIDGE_NAME_PAGEFOX, "pf", save_regular_crt},
188 {0, 0, CARTRIDGE_SIZE_24KB, 0x2000, 0x8000, 3, 0, CARTRIDGE_NAME_KINGSOFT, "ks", save_regular_crt},
189 {0, 1, CARTRIDGE_SIZE_128KB, 0x2000, 0x8000, 16, 0, CARTRIDGE_NAME_SILVERROCK_128, "silver", save_regular_crt},
190 {1, 0, CARTRIDGE_SIZE_32KB, 0x2000, 0xe000, 4, 0, CARTRIDGE_NAME_FORMEL64, "f64", save_regular_crt},
191 {0, 1, CARTRIDGE_SIZE_64KB, 0x2000, 0x8000, 8, 0, CARTRIDGE_NAME_RGCD, "rgcd", save_regular_crt},
192 {0, 1, CARTRIDGE_SIZE_8KB, 0x2000, 0x8000, 1, 0, CARTRIDGE_NAME_RRNETMK3, "rrnet", save_regular_crt},
193 {0, 0, CARTRIDGE_SIZE_24KB, 0, 0, 3, 0, CARTRIDGE_NAME_EASYCALC, "ecr", save_easycalc_crt},
194 {0, 1, CARTRIDGE_SIZE_512KB, 0x2000, 0x8000, 64, 0, CARTRIDGE_NAME_GMOD2, "gmod2", save_regular_crt},
195 {0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL}
196 };
197
198 #ifndef HAVE_MEMMOVE
199 #define memmove(x, y, z) bcopy(y, x, z)
200 #endif
201
202 #ifndef HAVE_STRDUP
strdup(const char * string)203 char *strdup(const char *string)
204 {
205 char *new;
206
207 new = malloc(strlen(string) + 1);
208 if (new != NULL) {
209 strcpy(new, string);
210 }
211 return new;
212 }
213 #endif
214
215 #if !defined(HAVE_STRNCASECMP)
216 static const unsigned char charmap[] = {
217 '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
218 '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
219 '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
220 '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
221 '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
222 '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
223 '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
224 '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
225 '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
226 '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
227 '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
228 '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
229 '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
230 '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
231 '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
232 '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
233 '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
234 '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
235 '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
236 '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
237 '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
238 '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
239 '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
240 '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
241 '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
242 '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
243 '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
244 '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
245 '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
246 '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
247 '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
248 '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
249 };
250
strncasecmp(const char * s1,const char * s2,size_t n)251 int strncasecmp(const char *s1, const char *s2, size_t n)
252 {
253 unsigned char u1, u2;
254
255 for (; n != 0; --n) {
256 u1 = (unsigned char)*s1++;
257 u2 = (unsigned char)*s2++;
258 if (charmap[u1] != charmap[u2]) {
259 return charmap[u1] - charmap[u2];
260 }
261
262 if (u1 == '\0') {
263 return 0;
264 }
265 }
266 return 0;
267 }
268 #endif
269
cleanup(void)270 static void cleanup(void)
271 {
272 int i;
273
274 if (output_filename != NULL) {
275 free(output_filename);
276 }
277 if (cart_name != NULL) {
278 free(cart_name);
279 }
280 for (i = 0; i < 33; i++) {
281 if (input_filename[i] != NULL) {
282 free(input_filename[i]);
283 }
284 }
285 }
286
count_valid_option_elements(void)287 static unsigned int count_valid_option_elements(void)
288 {
289 unsigned int i = 1;
290 unsigned int amount = 0;
291
292 while (cart_info[i].name) {
293 if (cart_info[i].opt) {
294 amount++;
295 }
296 i++;
297 }
298 return amount;
299 }
300
compare_elements(const void * op1,const void * op2)301 static int compare_elements(const void *op1, const void *op2)
302 {
303 const sorted_cart_t *p1 = (const sorted_cart_t *)op1;
304 const sorted_cart_t *p2 = (const sorted_cart_t *)op2;
305
306 return strcmp(p1->opt, p2->opt);
307 }
308
usage_types(void)309 static void usage_types(void)
310 {
311 unsigned int i = 1;
312 int n = 0;
313 unsigned int amount;
314 sorted_cart_t *sorted_option_elements;
315
316 cleanup();
317 printf("supported cart types:\n\n");
318
319 printf("bin Binary .bin file (Default crt->bin)\n");
320 printf("prg Binary C64 .prg file with load-address\n\n");
321 printf("normal Generic 8kb/12kb/16kb .crt file (Default bin->crt)\n");
322 printf("ulti Ultimax mode 4kb/8kb/16kb .crt file\n\n");
323
324 /* get the amount of valid options, excluding crt id 0 */
325 amount = count_valid_option_elements();
326
327 sorted_option_elements = malloc(amount * sizeof(sorted_cart_t));
328
329 /* fill in the array with the information needed */
330 while (cart_info[i].name) {
331 if (cart_info[i].opt) {
332 sorted_option_elements[n].opt = cart_info[i].opt;
333 sorted_option_elements[n].name = cart_info[i].name;
334 sorted_option_elements[n].crt_id = (int)i;
335 switch (i) {
336 case CARTRIDGE_DELA_EP7x8:
337 case CARTRIDGE_DELA_EP64:
338 case CARTRIDGE_REX_EP256:
339 case CARTRIDGE_DELA_EP256:
340 sorted_option_elements[n].insertion = 1;
341 break;
342 default:
343 sorted_option_elements[n].insertion = 0;
344 break;
345 }
346 n++;
347 }
348 i++;
349 }
350
351 qsort(sorted_option_elements, amount, sizeof(sorted_cart_t), compare_elements);
352
353 /* output the sorted list */
354 for (i = 0; i < amount; i++) {
355 n = sorted_option_elements[i].insertion;
356 printf("%-8s %s .crt file%s\n", sorted_option_elements[i].opt, sorted_option_elements[i].name, n ? ", extra files can be inserted" : "");
357 }
358 free(sorted_option_elements);
359 exit(1);
360 }
361
usage(void)362 static void usage(void)
363 {
364 cleanup();
365 printf("convert: cartconv [-r] [-q] [-t cart type] -i \"input name\" -o \"output name\" [-n \"cart name\"] [-l load address]\n");
366 printf("print info: cartconv [-r] -f \"input name\"\n\n");
367 printf("-f <name> print info on file\n");
368 printf("-r repair mode (accept broken input files)\n");
369 printf("-p accept non padded binaries as input\n");
370 printf("-b output all banks (do not optimize the .crt file)\n");
371 printf("-t <type> output cart type\n");
372 printf("-i <name> input filename\n");
373 printf("-o <name> output filename\n");
374 printf("-n <name> crt cart name\n");
375 printf("-l <addr> load address\n");
376 printf("-q quiet\n");
377 printf("--types show the supported cart types\n");
378 printf("--version print cartconv version\n");
379 exit(1);
380 }
381
382
383 /** \brief Dump cartconv version string on stdout
384 *
385 * Dumps the SVN revision as well, if compiled from SVN
386 */
dump_version(void)387 static void dump_version(void)
388 {
389 #ifdef USE_SVN_REVISION
390 printf("cartconv (VICE %s SVN r%d)\n", VERSION, VICE_SVN_REV_NUMBER);
391 #else
392 printf("cartconv (VICE %s)\n", VERSION);
393 #endif
394 }
395
396
printbanks(char * name)397 static void printbanks(char *name)
398 {
399 FILE *f;
400 unsigned char b[0x10];
401 long len, filelen;
402 long pos;
403 unsigned int type, bank, start, size;
404 char *typestr[4] = { "ROM", "RAM", "FLASH", "UNK" };
405 unsigned int numbanks;
406 unsigned long tsize;
407
408 f = fopen(name, "rb");
409 fseek(f, 0, SEEK_END);
410 filelen = ftell(f);
411
412 tsize = 0; numbanks = 0;
413 if (f) {
414 fseek(f, 0x40, SEEK_SET); /* skip crt header */
415 pos = 0x40;
416 printf("\noffset sig type bank start size chunklen\n");
417 while (!feof(f)) {
418 fseek(f, pos, SEEK_SET);
419 /* get chip header */
420 if (fread(b, 1, 0x10, f) < 0x10) {
421 break;
422 }
423 len = (b[7] + (b[6] * 0x100) + (b[5] * 0x10000) + (b[4] * 0x1000000));
424 type = (unsigned int)((b[8] * 0x100) + b[9]);
425 bank = (unsigned int)((b[10] * 0x100) + b[11]);
426 start = (unsigned int)((b[12] * 0x100) + b[13]);
427 size = (unsigned int)((b[14] * 0x100) + b[15]);
428 if (type > 2) {
429 type = 3; /* invalid */
430 }
431 printf("$%06lx %-1c%-1c%-1c%-1c %-5s #%03d $%04x $%04x $%04lx\n", pos, b[0], b[1], b[2], b[3], typestr[type], bank, start, size, len);
432 if ((size + 0x10) > len) {
433 printf(" Error: data size exceeds chunk length\n");
434 }
435 if (len > (filelen - pos)) {
436 printf(" Error: data size exceeds end of file\n");
437 break;
438 }
439 pos += len;
440 numbanks++;
441 tsize += size;
442 }
443 fclose(f);
444 printf("\ntotal banks: %d size: $%06lx\n", numbanks, tsize);
445 }
446 }
447
printinfo(char * name)448 static void printinfo(char *name)
449 {
450 int crtid;
451 char *idname, *modename;
452 char cartname[0x20 + 1];
453 char *exrom_warning = NULL;
454 char *game_warning = NULL;
455
456 if (load_input_file(name) < 0) {
457 printf("Error: this file seems broken.\n\n");
458 }
459 crtid = headerbuffer[0x17] + (headerbuffer[0x16] << 8);
460 if (headerbuffer[0x17] & 0x80) {
461 /* handle our negative test IDs */
462 crtid -= 0x10000;
463 }
464 if ((crtid >= 0) && (crtid <= CARTRIDGE_LAST)) {
465 idname = cart_info[crtid].name;
466 } else {
467 idname = "unknown";
468 }
469 if ((headerbuffer[0x18] == 1) && (headerbuffer[0x19] == 0)) {
470 modename = "ultimax";
471 } else if ((headerbuffer[0x18] == 0) && (headerbuffer[0x19] == 0)) {
472 modename = "16k Game";
473 } else if ((headerbuffer[0x18] == 0) && (headerbuffer[0x19] == 1)) {
474 modename = "8k Game";
475 } else {
476 modename = "?";
477 }
478 if (crtid && headerbuffer[0x18] != cart_info[crtid].exrom) {
479 exrom_warning = "Warning: exrom in crt image set incorrectly.\n";
480 }
481 if (crtid && headerbuffer[0x19] != cart_info[crtid].game) {
482 game_warning = "Warning: game in crt image set incorrectly.\n";
483 }
484 memcpy(cartname, &headerbuffer[0x20], 0x20); cartname[0x20] = 0;
485 printf("CRT Version: %d.%d\n", headerbuffer[0x14], headerbuffer[0x15]);
486 printf("Name: %s\n", cartname);
487 printf("Hardware ID: %d (%s)\n", crtid, idname);
488 printf("Mode: exrom: %d game: %d (%s)\n", headerbuffer[0x18], headerbuffer[0x19], modename);
489 if (exrom_warning) {
490 printf("%s", exrom_warning);
491 }
492 if (game_warning) {
493 printf("%s", game_warning);
494 }
495 printbanks(name);
496 exit (0);
497 }
498
checkarg(char * arg)499 static void checkarg(char *arg)
500 {
501 if (arg == NULL) {
502 usage();
503 }
504 }
505
checkflag(char * flg,char * arg)506 static int checkflag(char *flg, char *arg)
507 {
508 int i;
509
510 switch (tolower((int)(flg[1]))) {
511 case 'f':
512 printinfo(arg);
513 return 2;
514 case 'r':
515 repair_mode = 1;
516 return 1;
517 case 'b':
518 omit_empty_banks = 0;
519 return 1;
520 case 'q':
521 quiet_mode = 1;
522 return 1;
523 case 'p':
524 input_padding = 1;
525 return 1;
526 case 'o':
527 checkarg(arg);
528 if (output_filename == NULL) {
529 output_filename = strdup(arg);
530 } else {
531 usage();
532 }
533 return 2;
534 case 'n':
535 checkarg(arg);
536 if (cart_name == NULL) {
537 cart_name = strdup(arg);
538 } else {
539 usage();
540 }
541 return 2;
542 case 'l':
543 checkarg(arg);
544 if (load_address == 0) {
545 load_address = atoi(arg);
546 } else {
547 usage();
548 }
549 return 2;
550 case 't':
551 checkarg(arg);
552 if (cart_type != -1 || convert_to_bin != 0 || convert_to_prg != 0 || convert_to_ultimax != 0) {
553 usage();
554 } else {
555 for (i = 0; cart_info[i].name != NULL; i++) {
556 if (cart_info[i].opt != NULL) {
557 if (!strcasecmp(cart_info[i].opt, arg)) {
558 cart_type = (signed char)i;
559 break;
560 }
561 }
562 }
563 if (cart_type == -1) {
564 if (!strcmp(arg, "bin")) {
565 convert_to_bin = 1;
566 } else if (!strcmp(arg, "normal")) {
567 cart_type = CARTRIDGE_CRT;
568 } else if (!strcmp(arg, "prg")) {
569 convert_to_prg = 1;
570 } else if (!strcmp(arg, "ulti")) {
571 cart_type = CARTRIDGE_CRT;
572 convert_to_ultimax = 1;
573 } else {
574 usage();
575 }
576 }
577 }
578 return 2;
579 case 'i':
580 checkarg(arg);
581 if (input_filenames == 33) {
582 usage();
583 }
584 input_filename[input_filenames] = strdup(arg);
585 input_filenames++;
586 return 2;
587 default:
588 usage();
589 break;
590 }
591 return 1;
592 }
593
too_many_inputs(void)594 static void too_many_inputs(void)
595 {
596 fprintf(stderr, "Error: too many input files\n");
597 cleanup();
598 exit(1);
599 }
600
601
602 /* this loads the easyflash cart and puts it as the interleaved way into
603 the buffer for easy binary saving */
load_easyflash_crt(void)604 static int load_easyflash_crt(void)
605 {
606 unsigned int load_position;
607
608 memset(filebuffer, 0xff, 0x100000);
609 while (1) {
610 if (fread(chipbuffer, 1, 16, infile) != 16) {
611 if (loadfile_size == 0) {
612 return -1;
613 } else {
614 return 0;
615 }
616 }
617 loadfile_size = 0x100000;
618 if (chipbuffer[0] != 'C' || chipbuffer[1] != 'H' || chipbuffer[2] != 'I' || chipbuffer[3] != 'P') {
619 return -1;
620 }
621 if (load_address == 0) {
622 load_address = (chipbuffer[0xc] << 8) + chipbuffer[0xd];
623 }
624 load_position = (unsigned int)((chipbuffer[0xb] * 0x4000) + ((chipbuffer[0xc] == 0x80) ? 0 : 0x2000));
625 if (fread(filebuffer + load_position, 1, 0x2000, infile) != 0x2000) {
626 return -1;
627 }
628 }
629 }
630
load_all_banks(void)631 static int load_all_banks(void)
632 {
633 unsigned int length, datasize, loadsize, pad;
634
635 if (loadfile_cart_type == CARTRIDGE_EASYFLASH) {
636 return load_easyflash_crt();
637 }
638
639 while (1) {
640 /* get CHIP header */
641 if (fread(chipbuffer, 1, 16, infile) != 16) {
642 if (loadfile_size == 0) {
643 fprintf(stderr, "Error: could not read data from file.\n");
644 return -1;
645 } else {
646 return 0;
647 }
648 }
649 if (chipbuffer[0] != 'C' || chipbuffer[1] != 'H' || chipbuffer[2] != 'I' || chipbuffer[3] != 'P') {
650 fprintf(stderr, "Error: CHIP tag not found.\n");
651 return -1;
652 }
653 /* set load address to the load address of first CHIP in the file. this is not quite
654 correct, but works ok for the few cases when it matters */
655 if (load_address == 0) {
656 load_address = (chipbuffer[0xc] << 8) + chipbuffer[0xd];
657 }
658 length = (unsigned int)((chipbuffer[4] << 24) + (chipbuffer[5] << 16) + (chipbuffer[6] << 8) + chipbuffer[7]);
659 datasize = (unsigned int)((chipbuffer[14] * 0x100) + chipbuffer[15]);
660 loadsize = datasize;
661 if ((datasize + 0x10) > length) {
662 if (repair_mode) {
663 fprintf(stderr, "Warning: data size exceeds chunk length. (data:%04x chunk:%04x)\n", datasize, length);
664 loadsize = length - 0x10;
665 } else {
666 fprintf(stderr, "Error: data size exceeds chunk length. (data:%04x chunk:%04x) (use -r to force)\n", datasize, length);
667 return -1;
668 }
669 }
670 /* load data */
671 if (fread(filebuffer + loadfile_size, 1, loadsize, infile) != loadsize) {
672 if (repair_mode) {
673 fprintf(stderr, "Warning: unexpected end of file.\n");
674 loadfile_size += datasize;
675 break;
676 }
677 fprintf(stderr, "Error: could not read data from file. (use -r to force)\n");
678 return -1;
679 }
680 /* if the chunk is larger than the contained data+chip header, skip the rest */
681 pad = length - (datasize + 0x10);
682 if (pad > 0) {
683 fprintf(stderr, "Warning: chunk length exceeds data size (data:%04x chunk:%04x), skipping %04x bytes.\n", datasize, length, pad);
684 fseek(infile, pad, SEEK_CUR);
685 }
686 loadfile_size += datasize;
687 }
688 return 0;
689 }
690
save_binary_output_file(void)691 static int save_binary_output_file(void)
692 {
693 unsigned char address_buffer[2];
694
695 outfile = fopen(output_filename, "wb");
696 if (outfile == NULL) {
697 fprintf(stderr, "Error: Can't open output file %s\n", output_filename);
698 return -1;
699 }
700 if (convert_to_prg == 1) {
701 address_buffer[0] = (unsigned char)(load_address & 0xff);
702 address_buffer[1] = (unsigned char)(load_address >> 8);
703 if (fwrite(address_buffer, 1, 2, outfile) != 2) {
704 fprintf(stderr, "Error: Can't write to file %s\n", output_filename);
705 fclose(outfile);
706 return -1;
707 }
708 }
709 if (fwrite(filebuffer, 1, loadfile_size, outfile) != loadfile_size) {
710 fprintf(stderr, "Error: Can't write to file %s\n", output_filename);
711 fclose(outfile);
712 return -1;
713 }
714 fclose(outfile);
715 if (!quiet_mode) {
716 printf("Input file : %s\n", input_filename[0]);
717 printf("Output file : %s\n", output_filename);
718 printf("Conversion from %s .crt to binary format successful.\n", cart_info[loadfile_cart_type].name);
719 }
720 return 0;
721 }
722
write_crt_header(unsigned char gameline,unsigned char exromline)723 static int write_crt_header(unsigned char gameline, unsigned char exromline)
724 {
725 unsigned char crt_header[0x40] = "C64 CARTRIDGE ";
726 int endofname = 0;
727 int i;
728
729 crt_header[0x10] = 0;
730 crt_header[0x11] = 0;
731 crt_header[0x12] = 0;
732 crt_header[0x13] = 0x40;
733
734 crt_header[0x14] = 1;
735 crt_header[0x15] = 0;
736
737 crt_header[0x16] = 0;
738 crt_header[0x17] = (unsigned char)cart_type;
739
740 crt_header[0x18] = exromline;
741 crt_header[0x19] = gameline;
742
743 crt_header[0x1a] = 0;
744 crt_header[0x1b] = 0;
745 crt_header[0x1c] = 0;
746 crt_header[0x1d] = 0;
747 crt_header[0x1e] = 0;
748 crt_header[0x1f] = 0;
749
750 if (cart_name == NULL) {
751 cart_name = strdup("VICE CART");
752 }
753
754 for (i = 0; i < 32; i++) {
755 if (endofname == 1) {
756 crt_header[0x20 + i] = 0;
757 } else {
758 if (cart_name[i] == 0) {
759 endofname = 1;
760 } else {
761 crt_header[0x20 + i] = (unsigned char)toupper((int)cart_name[i]);
762 }
763 }
764 }
765
766 outfile = fopen(output_filename, "wb");
767 if (outfile == NULL) {
768 fprintf(stderr, "Error: Can't open output file %s\n", output_filename);
769 return -1;
770 }
771 if (fwrite(crt_header, 1, 0x40, outfile) != 0x40) {
772 fprintf(stderr, "Error: Can't write crt header to file %s\n", output_filename);
773 fclose(outfile);
774 unlink(output_filename);
775 return -1;
776 }
777 return 0;
778 }
779
write_chip_package(unsigned int length,unsigned int bankint,unsigned int address,unsigned char type)780 static int write_chip_package(unsigned int length, unsigned int bankint, unsigned int address, unsigned char type)
781 {
782 unsigned char chip_header[0x10] = "CHIP";
783 unsigned char bank = (unsigned char)bankint;
784
785 /* make sure the above conversion did not remove significant bits */
786 assert(bankint == bank);
787
788 chip_header[4] = 0;
789 chip_header[5] = 0;
790 chip_header[6] = (unsigned char)((length + 0x10) >> 8);
791 chip_header[7] = (unsigned char)((length + 0x10) & 0xff);
792
793 chip_header[8] = 0;
794 chip_header[9] = type;
795
796 chip_header[0xa] = 0;
797 chip_header[0xb] = bank;
798
799 chip_header[0xc] = (unsigned char)(address >> 8);
800 chip_header[0xd] = (unsigned char)(address & 0xff);
801
802 chip_header[0xe] = (unsigned char)(length >> 8);
803 chip_header[0xf] = (unsigned char)(length & 0xff);
804 if (fwrite(chip_header, 1, 0x10, outfile) != 0x10) {
805 fprintf(stderr, "Error: Can't write chip header to file %s\n", output_filename);
806 fclose(outfile);
807 unlink(output_filename);
808 return -1;
809 }
810 if (fwrite(filebuffer + loadfile_offset, 1, length, outfile) != length) {
811 fprintf(stderr, "Error: Can't write data to file %s\n", output_filename);
812 fclose(outfile);
813 unlink(output_filename);
814 return -1;
815 }
816 loadfile_offset += (int)length;
817 return 0;
818 }
819
bin2crt_ok(void)820 static void bin2crt_ok(void)
821 {
822 if (!quiet_mode) {
823 printf("Input file : %s\n", input_filename[0]);
824 printf("Output file : %s\n", output_filename);
825 printf("Conversion from binary format to %s .crt successful.\n", cart_info[(unsigned char)cart_type].name);
826 }
827 }
828
save_regular_crt(unsigned int length,unsigned int banks,unsigned int address,unsigned int type,unsigned char game,unsigned char exrom)829 static void save_regular_crt(unsigned int length, unsigned int banks, unsigned int address, unsigned int type, unsigned char game, unsigned char exrom)
830 {
831 unsigned int i;
832 unsigned int real_banks = banks;
833
834 /* printf("save_regular_crt length: %d banks:%d address: %d\n", length, banks, address); */
835
836 if (write_crt_header(game, exrom) < 0) {
837 cleanup();
838 exit(1);
839 }
840
841 if (real_banks == 0) {
842 /* handle the case when a chip of half the regular size
843 is used on an otherwise identical hardware (eg 4k
844 chip on a 8k cart)
845 */
846 if (loadfile_size == (length / 2)) {
847 length /= 2;
848 }
849 real_banks = loadfile_size / length;
850 }
851
852 for (i = 0; i < real_banks; i++) {
853 if (write_chip_package(length, i, address, (unsigned char)type) < 0) {
854 cleanup();
855 exit(1);
856 }
857 }
858 fclose(outfile);
859 bin2crt_ok();
860 cleanup();
861 exit(0);
862 }
863
save_fcplus_crt(unsigned int length,unsigned int banks,unsigned int address,unsigned int type,unsigned char game,unsigned char exrom)864 static void save_fcplus_crt(unsigned int length, unsigned int banks, unsigned int address, unsigned int type, unsigned char game, unsigned char exrom)
865 {
866 unsigned int i;
867 unsigned int real_banks = banks;
868
869 /* printf("save_fcplus_crt length: %d banks:%d address: %d\n", length, banks, address); */
870
871 if (write_crt_header(game, exrom) < 0) {
872 cleanup();
873 exit(1);
874 }
875
876 if (real_banks == 0) {
877 real_banks = loadfile_size / length;
878 }
879
880 if (loadfile_size != 0x8000) {
881 memmove(filebuffer + 0x2000, filebuffer, 0x6000);
882 memset(filebuffer, 0xff, 0x2000);
883 }
884
885 for (i = 0; i < real_banks; i++) {
886 if (write_chip_package(length, i, address, (unsigned char)type) < 0) {
887 cleanup();
888 exit(1);
889 }
890 }
891
892 fclose(outfile);
893 bin2crt_ok();
894 cleanup();
895 exit(0);
896 }
897
save_2_blocks_crt(unsigned int l1,unsigned int l2,unsigned int a1,unsigned int a2,unsigned char game,unsigned char exrom)898 static void save_2_blocks_crt(unsigned int l1, unsigned int l2, unsigned int a1, unsigned int a2, unsigned char game, unsigned char exrom)
899 {
900 if (write_crt_header(game, exrom) < 0) {
901 cleanup();
902 exit(1);
903 }
904
905 if (write_chip_package(0x2000, 0, 0x8000, 0) < 0) {
906 cleanup();
907 exit(1);
908 }
909
910 if (write_chip_package(0x2000, 0, (a2 == 0xe000) ? 0xe000 : 0xa000, 0) < 0) {
911 cleanup();
912 exit(1);
913 }
914
915 fclose(outfile);
916 bin2crt_ok();
917 cleanup();
918 exit(0);
919 }
920
check_empty_easyflash(void)921 static int check_empty_easyflash(void)
922 {
923 int i;
924
925 for (i = 0; i < 0x2000; i++) {
926 if (filebuffer[loadfile_offset + i] != 0xff) {
927 return 0;
928 }
929 }
930 return 1;
931 }
932
save_easyflash_crt(unsigned int p1,unsigned int p2,unsigned int p3,unsigned int p4,unsigned char p5,unsigned char p6)933 static void save_easyflash_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char p5, unsigned char p6)
934 {
935 unsigned int i, j;
936
937 if (write_crt_header(0, 0) < 0) {
938 cleanup();
939 exit(1);
940 }
941
942 for (i = 0; i < 64; i++) {
943 for (j = 0; j < 2; j++) {
944 if ((omit_empty_banks == 1) && (check_empty_easyflash() == 1)) {
945 loadfile_offset += 0x2000;
946 } else {
947 if (write_chip_package(0x2000, i, (j == 0) ? 0x8000 : 0xa000, 2) < 0) {
948 cleanup();
949 exit(1);
950 }
951 }
952 }
953 }
954
955 fclose(outfile);
956 bin2crt_ok();
957 cleanup();
958 exit(0);
959 }
960
save_ocean_crt(unsigned int p1,unsigned int p2,unsigned int p3,unsigned int p4,unsigned char p5,unsigned char p6)961 static void save_ocean_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char p5, unsigned char p6)
962 {
963 unsigned int i;
964
965 if (loadfile_size != CARTRIDGE_SIZE_256KB) {
966 save_regular_crt(0x2000, 0, 0x8000, 0, 0, 0);
967 } else {
968 if (write_crt_header(1, 0) < 0) {
969 cleanup();
970 exit(1);
971 }
972
973 for (i = 0; i < 16; i++) {
974 if (write_chip_package(0x2000, i, 0x8000, 0) < 0) {
975 cleanup();
976 exit(1);
977 }
978 }
979
980 for (i = 0; i < 16; i++) {
981 if (write_chip_package(0x2000, i + 16, 0xa000, 0) < 0) {
982 cleanup();
983 exit(1);
984 }
985 }
986
987 fclose(outfile);
988 bin2crt_ok();
989 cleanup();
990 exit(0);
991 }
992 }
993
save_funplay_crt(unsigned int p1,unsigned int p2,unsigned int p3,unsigned int p4,unsigned char p5,unsigned char p6)994 static void save_funplay_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char p5, unsigned char p6)
995 {
996 unsigned int i = 0;
997
998 if (write_crt_header(1, 0) < 0) {
999 cleanup();
1000 exit(1);
1001 }
1002
1003 while (i != 0x41) {
1004 if (write_chip_package(0x2000, i, 0x8000, 0) < 0) {
1005 cleanup();
1006 exit(1);
1007 }
1008 i += 8;
1009 if (i == 0x40) {
1010 i = 1;
1011 }
1012 }
1013
1014 fclose(outfile);
1015 bin2crt_ok();
1016 cleanup();
1017 exit(0);
1018 }
1019
save_easycalc_crt(unsigned int p1,unsigned int p2,unsigned int p3,unsigned int p4,unsigned char p5,unsigned char p6)1020 static void save_easycalc_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char p5, unsigned char p6)
1021 {
1022 if (write_crt_header(1, 1) < 0) {
1023 cleanup();
1024 exit(1);
1025 }
1026
1027 if (write_chip_package(0x2000, 0, 0x8000, 0) < 0) {
1028 cleanup();
1029 exit(1);
1030 }
1031
1032 if (write_chip_package(0x2000, 0, 0xa000, 0) < 0) {
1033 cleanup();
1034 exit(1);
1035 }
1036
1037 if (write_chip_package(0x2000, 1, 0xa000, 0) < 0) {
1038 cleanup();
1039 exit(1);
1040 }
1041
1042 fclose(outfile);
1043 bin2crt_ok();
1044 cleanup();
1045 exit(0);
1046 }
1047
save_zaxxon_crt(unsigned int p1,unsigned int p2,unsigned int p3,unsigned int p4,unsigned char p5,unsigned char p6)1048 static void save_zaxxon_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char p5, unsigned char p6)
1049 {
1050 if (write_crt_header(0, 0) < 0) {
1051 cleanup();
1052 exit(1);
1053 }
1054
1055 if (write_chip_package(0x1000, 0, 0x8000, 0) < 0) {
1056 cleanup();
1057 exit(1);
1058 }
1059
1060 if (write_chip_package(0x2000, 0, 0xa000, 0) < 0) {
1061 cleanup();
1062 exit(1);
1063 }
1064
1065 if (write_chip_package(0x2000, 1, 0xa000, 0) < 0) {
1066 cleanup();
1067 exit(1);
1068 }
1069
1070 fclose(outfile);
1071 bin2crt_ok();
1072 cleanup();
1073 exit(0);
1074 }
1075
save_stardos_crt(unsigned int p1,unsigned int p2,unsigned int p3,unsigned int p4,unsigned char p5,unsigned char p6)1076 static void save_stardos_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char p5, unsigned char p6)
1077 {
1078 if (write_crt_header(1, 0) < 0) {
1079 cleanup();
1080 exit(1);
1081 }
1082
1083 if (write_chip_package(0x2000, 0, 0x8000, 0) < 0) {
1084 cleanup();
1085 exit(1);
1086 }
1087
1088 if (write_chip_package(0x2000, 0, 0xe000, 0) < 0) {
1089 cleanup();
1090 exit(1);
1091 }
1092
1093 fclose(outfile);
1094 bin2crt_ok();
1095 cleanup();
1096 exit(0);
1097 }
1098
load_input_file(char * filename)1099 static int load_input_file(char *filename)
1100 {
1101 loadfile_offset = 0;
1102 infile = fopen(filename, "rb");
1103 if (infile == NULL) {
1104 fprintf(stderr, "Error: Can't open %s\n", filename);
1105 return -1;
1106 }
1107 if (fread(filebuffer, 1, 16, infile) != 16) {
1108 fprintf(stderr, "Error: Can't read %s\n", filename);
1109 fclose(infile);
1110 return -1;
1111 }
1112 if (!strncmp("C64 CARTRIDGE ", (char *)filebuffer, 16)) {
1113 loadfile_is_crt = 1;
1114 if (fread(headerbuffer + 0x10, 1, 0x30, infile) != 0x30) {
1115 fprintf(stderr, "Error: Can't read the full header of %s\n", filename);
1116 fclose(infile);
1117 return -1;
1118 }
1119 if (headerbuffer[0x10] != 0 || headerbuffer[0x11] != 0 || headerbuffer[0x12] != 0 || headerbuffer[0x13] != 0x40) {
1120 fprintf(stderr, "Error: Illegal header size in %s\n", filename);
1121 if (!repair_mode) {
1122 fclose(infile);
1123 return -1;
1124 }
1125 }
1126 if (headerbuffer[0x18] == 1 && headerbuffer[0x19] == 0) {
1127 loadfile_is_ultimax = 1;
1128 } else {
1129 loadfile_is_ultimax = 0;
1130 }
1131
1132 loadfile_cart_type = headerbuffer[0x17] + (headerbuffer[0x16] << 8);
1133 if (headerbuffer[0x17] & 0x80) {
1134 /* handle our negative test IDs */
1135 loadfile_cart_type -= 0x10000;
1136 }
1137 if (!((loadfile_cart_type >= 0) && (loadfile_cart_type <= CARTRIDGE_LAST))) {
1138 fprintf(stderr, "Error: Unknown CRT ID: %d\n", loadfile_cart_type);
1139 fclose(infile);
1140 return -1;
1141 }
1142
1143 loadfile_size = 0;
1144 if (load_all_banks() < 0) {
1145 if (repair_mode) {
1146 fprintf(stderr, "Warning: Can't load all banks of %s\n", filename);
1147 fclose(infile);
1148 return 0;
1149 } else {
1150 fprintf(stderr, "Error: Can't load all banks of %s (use -r to force)\n", filename);
1151 fclose(infile);
1152 return -1;
1153 }
1154 } else {
1155 fclose(infile);
1156 return 0;
1157 }
1158 } else {
1159 loadfile_is_crt = 0;
1160 loadfile_size = (unsigned int)fread(filebuffer + 0x10, 1, 0x100000 - 14, infile) + 0x10;
1161 switch (loadfile_size) {
1162 case CARTRIDGE_SIZE_4KB:
1163 case CARTRIDGE_SIZE_8KB:
1164 case CARTRIDGE_SIZE_12KB:
1165 case CARTRIDGE_SIZE_16KB:
1166 case CARTRIDGE_SIZE_20KB:
1167 case CARTRIDGE_SIZE_24KB:
1168 case CARTRIDGE_SIZE_32KB:
1169 case CARTRIDGE_SIZE_64KB:
1170 case CARTRIDGE_SIZE_96KB:
1171 case CARTRIDGE_SIZE_128KB:
1172 case CARTRIDGE_SIZE_256KB:
1173 case CARTRIDGE_SIZE_512KB:
1174 case CARTRIDGE_SIZE_1024KB:
1175 loadfile_offset = 0;
1176 fclose(infile);
1177 return 0;
1178 break;
1179 case CARTRIDGE_SIZE_4KB + 2:
1180 case CARTRIDGE_SIZE_8KB + 2:
1181 case CARTRIDGE_SIZE_12KB + 2:
1182 case CARTRIDGE_SIZE_16KB + 2:
1183 case CARTRIDGE_SIZE_20KB + 2:
1184 case CARTRIDGE_SIZE_24KB + 2:
1185 case CARTRIDGE_SIZE_32KB + 2:
1186 case CARTRIDGE_SIZE_64KB + 2:
1187 case CARTRIDGE_SIZE_96KB + 2:
1188 case CARTRIDGE_SIZE_128KB + 2:
1189 case CARTRIDGE_SIZE_256KB + 2:
1190 case CARTRIDGE_SIZE_512KB + 2:
1191 case CARTRIDGE_SIZE_1024KB + 2:
1192 loadfile_size -= 2;
1193 loadfile_offset = 2;
1194 fclose(infile);
1195 return 0;
1196 break;
1197 case CARTRIDGE_SIZE_32KB + 4:
1198 loadfile_size -= 4;
1199 loadfile_offset = 4;
1200 fclose(infile);
1201 return 0;
1202 break;
1203 default:
1204 fclose(infile);
1205 if (input_padding) {
1206 return 0;
1207 }
1208 fprintf(stderr, "Error: Illegal file size of %s\n", filename);
1209 return -1;
1210 break;
1211 }
1212 }
1213 }
1214
close_output_cleanup(void)1215 static void close_output_cleanup(void)
1216 {
1217 fclose(outfile);
1218 unlink(output_filename);
1219 cleanup();
1220 exit(1);
1221 }
1222
save_delaep64_crt(unsigned int p1,unsigned int p2,unsigned int p3,unsigned int p4,unsigned char p5,unsigned char p6)1223 static void save_delaep64_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char p5, unsigned char p6)
1224 {
1225 unsigned int i;
1226
1227 if (loadfile_size != CARTRIDGE_SIZE_8KB) {
1228 fprintf(stderr, "Error: wrong size of Dela EP64 base file %s (%d)\n", input_filename[0], loadfile_size);
1229 cleanup();
1230 exit(1);
1231 }
1232
1233 if (write_crt_header(1, 0) < 0) {
1234 cleanup();
1235 exit(1);
1236 }
1237
1238 /* write base file */
1239 if (write_chip_package(0x2000, 0, 0x8000, 0) < 0) {
1240 cleanup();
1241 exit(1);
1242 }
1243
1244 if (input_filenames > 1) {
1245 /* write user eproms */
1246 for (i = 0; i < input_filenames; i++) {
1247 if (load_input_file(input_filename[i]) < 0) {
1248 close_output_cleanup();
1249 }
1250 if (loadfile_is_crt == 1) {
1251 fprintf(stderr, "Error: to be inserted file can only be a binary for Dela EP64\n");
1252 close_output_cleanup();
1253 }
1254 if (loadfile_size != CARTRIDGE_SIZE_32KB) {
1255 fprintf(stderr, "Error: to be inserted file can only be 32KB in size for Dela EP64\n");
1256 close_output_cleanup();
1257 }
1258 if (write_chip_package(0x8000, i + 1, 0x8000, 0) < 0) {
1259 close_output_cleanup();
1260 }
1261 }
1262 }
1263
1264 fclose(outfile);
1265 bin2crt_ok();
1266 cleanup();
1267 exit(0);
1268 }
1269
save_delaep256_crt(unsigned int p1,unsigned int p2,unsigned int p3,unsigned int p4,unsigned char p5,unsigned char p6)1270 static void save_delaep256_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char p5, unsigned char p6)
1271 {
1272 unsigned int i, j;
1273 unsigned int insert_size = 0;
1274
1275 if (loadfile_size != CARTRIDGE_SIZE_8KB) {
1276 fprintf(stderr, "Error: wrong size of Dela EP256 base file %s (%d)\n", input_filename[0], loadfile_size);
1277 cleanup();
1278 exit(1);
1279 }
1280
1281 if (input_filenames == 1) {
1282 fprintf(stderr, "Error: no files to insert into Dela EP256 .crt\n");
1283 cleanup();
1284 exit(1);
1285 }
1286
1287 if (write_crt_header(1, 0) < 0) {
1288 cleanup();
1289 exit(1);
1290 }
1291
1292 if (write_chip_package(0x2000, 0, 0x8000, 0) < 0) {
1293 cleanup();
1294 exit(1);
1295 }
1296
1297 for (i = 0; i < (unsigned int)input_filenames - 1; i++) {
1298 if (load_input_file(input_filename[i + 1]) < 0) {
1299 close_output_cleanup();
1300 }
1301
1302 if (loadfile_size != CARTRIDGE_SIZE_32KB && loadfile_size != CARTRIDGE_SIZE_8KB) {
1303 fprintf(stderr, "Error: only 32KB binary files or 8KB bin/crt files can be inserted in Dela EP256\n");
1304 close_output_cleanup();
1305 }
1306
1307 if (insert_size == 0) {
1308 insert_size = loadfile_size;
1309 }
1310
1311 if (insert_size == CARTRIDGE_SIZE_32KB && input_filenames > 8) {
1312 fprintf(stderr, "Error: a maximum of 8 32KB images can be inserted\n");
1313 close_output_cleanup();
1314 }
1315
1316 if (insert_size != loadfile_size) {
1317 fprintf(stderr, "Error: only one type of insertion is allowed at this time for Dela EP256\n");
1318 close_output_cleanup();
1319 }
1320
1321 if (loadfile_is_crt == 1 && (loadfile_size != CARTRIDGE_SIZE_8KB || load_address != 0x8000 || loadfile_is_ultimax == 1)) {
1322 fprintf(stderr, "Error: you can only insert generic 8KB .crt files for Dela EP256\n");
1323 close_output_cleanup();
1324 }
1325
1326 if (insert_size == CARTRIDGE_SIZE_32KB) {
1327 for (j = 0; j < 4; j++) {
1328 if (write_chip_package(0x2000, (i * 4) + j + 1, 0x8000, 0) < 0) {
1329 close_output_cleanup();
1330 }
1331 }
1332 if (!quiet_mode) {
1333 printf("inserted %s in banks %d-%d of the Dela EP256 .crt\n", input_filename[i + 1], (i * 4) + 1, (i * 4) + 4);
1334 }
1335 } else {
1336 if (write_chip_package(0x2000, i + 1, 0x8000, 0) < 0) {
1337 close_output_cleanup();
1338 }
1339 if (!quiet_mode) {
1340 printf("inserted %s in bank %d of the Dela EP256 .crt\n", input_filename[i + 1], i + 1);
1341 }
1342 }
1343 }
1344
1345 fclose(outfile);
1346 bin2crt_ok();
1347 cleanup();
1348 exit(0);
1349 }
1350
save_delaep7x8_crt(unsigned int p1,unsigned int p2,unsigned int p3,unsigned int p4,unsigned char p5,unsigned char p6)1351 static void save_delaep7x8_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char p5, unsigned char p6)
1352 {
1353 int inserted_size = 0;
1354 int name_counter = 1;
1355 unsigned int chip_counter = 1;
1356
1357 if (loadfile_size != CARTRIDGE_SIZE_8KB) {
1358 fprintf(stderr, "Error: wrong size of Dela EP7x8 base file %s (%d)\n", input_filename[0], loadfile_size);
1359 cleanup();
1360 exit(1);
1361 }
1362
1363 if (input_filenames == 1) {
1364 fprintf(stderr, "Error: no files to insert into Dela EP7x8 .crt\n");
1365 cleanup();
1366 exit(1);
1367 }
1368
1369 if (write_crt_header(1, 0) < 0) {
1370 cleanup();
1371 exit(1);
1372 }
1373
1374 if (write_chip_package(0x2000, 0, 0x8000, 0) < 0) {
1375 cleanup();
1376 exit(1);
1377 }
1378
1379 while (name_counter != input_filenames) {
1380 if (load_input_file(input_filename[name_counter]) < 0) {
1381 close_output_cleanup();
1382 }
1383
1384 if (loadfile_size == CARTRIDGE_SIZE_32KB) {
1385 if (loadfile_is_crt == 1) {
1386 fprintf(stderr, "Error: (%s) only binary 32KB images can be inserted into a Dela EP7x8 .crt\n",
1387 input_filename[name_counter]);
1388 close_output_cleanup();
1389 } else {
1390 if (inserted_size != 0) {
1391 fprintf(stderr, "Error: (%s) only the first inserted image can be a 32KB image for Dela EP7x8\n",
1392 input_filename[name_counter]);
1393 close_output_cleanup();
1394 } else {
1395 if (write_chip_package(0x2000, chip_counter, 0x8000, 0) < 0) {
1396 close_output_cleanup();
1397 }
1398 if (write_chip_package(0x2000, chip_counter + 1, 0x8000, 0) < 0) {
1399 close_output_cleanup();
1400 }
1401 if (write_chip_package(0x2000, chip_counter + 2, 0x8000, 0) < 0) {
1402 close_output_cleanup();
1403 }
1404 if (write_chip_package(0x2000, chip_counter + 3, 0x8000, 0) < 0) {
1405 close_output_cleanup();
1406 }
1407 if (!quiet_mode) {
1408 printf("inserted %s in banks %d-%d of the Dela EP7x8 .crt\n",
1409 input_filename[name_counter], chip_counter, chip_counter + 3);
1410 }
1411 chip_counter += 4;
1412 inserted_size += 0x8000;
1413 }
1414 }
1415 }
1416
1417 if (loadfile_size == CARTRIDGE_SIZE_16KB) {
1418 if (loadfile_is_crt == 1 && (loadfile_cart_type != 0 || loadfile_is_ultimax == 1)) {
1419 fprintf(stderr, "Error: (%s) only generic 16KB .crt images can be inserted into a Dela EP7x8 .crt\n",
1420 input_filename[name_counter]);
1421 close_output_cleanup();
1422 } else {
1423 if (inserted_size >= 0xc000) {
1424 fprintf(stderr, "Error: (%s) no room to insert a 16KB binary file into the Dela EP7x8 .crt\n",
1425 input_filename[name_counter]);
1426 close_output_cleanup();
1427 } else {
1428 if (write_chip_package(0x2000, chip_counter, 0x8000, 0) < 0) {
1429 close_output_cleanup();
1430 }
1431 if (write_chip_package(0x2000, chip_counter + 1, 0x8000, 0) < 0) {
1432 close_output_cleanup();
1433 }
1434 if (!quiet_mode) {
1435 printf("inserted %s in banks %d and %d of the Dela EP7x8 .crt\n",
1436 input_filename[name_counter], chip_counter, chip_counter + 1);
1437 }
1438 chip_counter += 2;
1439 inserted_size += 0x4000;
1440 }
1441 }
1442 }
1443
1444 if (loadfile_size == CARTRIDGE_SIZE_8KB) {
1445 if (loadfile_is_crt == 1 && (loadfile_cart_type != 0 || loadfile_is_ultimax == 1)) {
1446 fprintf(stderr, "Error: (%s) only generic 8KB .crt images can be inserted into a Dela EP7x8 .crt\n",
1447 input_filename[name_counter]);
1448 close_output_cleanup();
1449 } else {
1450 if (inserted_size >= 0xe000) {
1451 fprintf(stderr, "Error: (%s) no room to insert a 8KB binary file into the Dela EP7x8 .crt\n",
1452 input_filename[name_counter]);
1453 close_output_cleanup();
1454 } else {
1455 if (write_chip_package(0x2000, chip_counter, 0x8000, 0) < 0) {
1456 close_output_cleanup();
1457 }
1458 if (!quiet_mode) {
1459 printf("inserted %s in bank %d of the Dela EP7x8 .crt\n", input_filename[name_counter], chip_counter);
1460 }
1461 chip_counter++;
1462 inserted_size += 0x2000;
1463 }
1464 }
1465 }
1466
1467 name_counter++;
1468 }
1469
1470 fclose(outfile);
1471 bin2crt_ok();
1472 cleanup();
1473 exit(0);
1474 }
1475
save_rexep256_crt(unsigned int p1,unsigned int p2,unsigned int p3,unsigned int p4,unsigned char p5,unsigned char p6)1476 static void save_rexep256_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char p5, unsigned char p6)
1477 {
1478 int eprom_size_for_8kb = 0;
1479 int images_of_8kb_started = 0;
1480 int name_counter = 1;
1481 unsigned int chip_counter = 1;
1482 int subchip_counter = 1;
1483
1484 if (loadfile_size != CARTRIDGE_SIZE_8KB) {
1485 fprintf(stderr, "Error: wrong size of Rex EP256 base file %s (%d)\n", input_filename[0], loadfile_size);
1486 cleanup();
1487 exit(1);
1488 }
1489
1490 if (input_filenames == 1) {
1491 fprintf(stderr, "Error: no files to insert into Rex EP256 .crt\n");
1492 cleanup();
1493 exit(1);
1494 }
1495
1496 if (write_crt_header(1, 0) < 0) {
1497 cleanup();
1498 exit(1);
1499 }
1500
1501 if (write_chip_package(0x2000, 0, 0x8000, 0) < 0) {
1502 cleanup();
1503 exit(1);
1504 }
1505
1506 while (name_counter != input_filenames) {
1507 if (load_input_file(input_filename[name_counter]) < 0) {
1508 close_output_cleanup();
1509 }
1510
1511 if (chip_counter > 8) {
1512 fprintf(stderr, "Error: no more room for %s in the Rex EP256 .crt\n", input_filename[name_counter]);
1513 }
1514
1515 if (loadfile_size == CARTRIDGE_SIZE_32KB) {
1516 if (loadfile_is_crt == 1) {
1517 fprintf(stderr, "Error: (%s) only binary 32KB images can be inserted into a Rex EP256 .crt\n",
1518 input_filename[name_counter]);
1519 close_output_cleanup();
1520 } else {
1521 if (images_of_8kb_started != 0) {
1522 fprintf(stderr, "Error: (%s) only the first inserted images can be a 32KB image for Rex EP256\n",
1523 input_filename[name_counter]);
1524 close_output_cleanup();
1525 } else {
1526 if (write_chip_package(0x8000, chip_counter, 0x8000, 0) < 0) {
1527 close_output_cleanup();
1528 }
1529 if (!quiet_mode) {
1530 printf("inserted %s in bank %d as a 32KB eprom of the Rex EP256 .crt\n",
1531 input_filename[name_counter], chip_counter);
1532 }
1533 chip_counter++;
1534 }
1535 }
1536 }
1537
1538 if (loadfile_size == CARTRIDGE_SIZE_8KB) {
1539 if (loadfile_is_crt == 1 && (loadfile_cart_type != 0 || loadfile_is_ultimax == 1)) {
1540 fprintf(stderr, "Error: (%s) only generic 8KB .crt images can be inserted into a Rex EP256 .crt\n",
1541 input_filename[name_counter]);
1542 close_output_cleanup();
1543 } else {
1544 if (images_of_8kb_started == 0) {
1545 images_of_8kb_started = 1;
1546 if ((9 - chip_counter) * 4 < (unsigned int)(input_filenames - name_counter)) {
1547 fprintf(stderr, "Error: no room for the amount of input files given\n");
1548 close_output_cleanup();
1549 }
1550 eprom_size_for_8kb = 1;
1551 if ((9 - chip_counter) * 2 < (unsigned int)(input_filenames - name_counter)) {
1552 eprom_size_for_8kb = 4;
1553 }
1554 if (9 - chip_counter < (unsigned int)(input_filenames - name_counter)) {
1555 eprom_size_for_8kb = 2;
1556 }
1557 }
1558
1559 if (eprom_size_for_8kb == 1) {
1560 if (write_chip_package(0x2000, chip_counter, 0x8000, 0) < 0) {
1561 close_output_cleanup();
1562 if (!quiet_mode) {
1563 printf("inserted %s as an 8KB eprom in bank %d of the Rex EP256 .crt\n",
1564 input_filename[name_counter], chip_counter);
1565 }
1566 chip_counter++;
1567 }
1568
1569 if (eprom_size_for_8kb == 4 && (subchip_counter == 4 || name_counter == input_filenames - 1)) {
1570 memcpy(extra_buffer_32kb + ((subchip_counter - 1) * 0x2000), filebuffer + loadfile_offset, 0x2000);
1571 memcpy(filebuffer, extra_buffer_32kb, 0x8000);
1572 loadfile_offset = 0;
1573 if (write_chip_package(0x8000, chip_counter, 0x8000, 0) < 0) {
1574 close_output_cleanup();
1575 }
1576 if (!quiet_mode) {
1577 if (subchip_counter == 1) {
1578 printf("inserted %s as a 32KB eprom in bank %d of the Rex EP256 .crt\n",
1579 input_filename[name_counter], chip_counter);
1580 } else {
1581 printf(" and %s as a 32KB eprom in bank %d of the Rex EP256 .crt\n",
1582 input_filename[name_counter], chip_counter);
1583 }
1584 }
1585 chip_counter++;
1586 subchip_counter = 1;
1587 }
1588
1589 if (eprom_size_for_8kb == 4 && (subchip_counter == 3 || subchip_counter == 2) &&
1590 name_counter != input_filenames) {
1591 memcpy(extra_buffer_32kb + ((subchip_counter - 1) * 0x2000), filebuffer + loadfile_offset, 0x2000);
1592 if (!quiet_mode) {
1593 printf(", %s", input_filename[name_counter]);
1594 }
1595 subchip_counter++;
1596 }
1597
1598 if (eprom_size_for_8kb == 2) {
1599 if (subchip_counter == 2 || name_counter == input_filenames - 1) {
1600 memcpy(extra_buffer_32kb + ((subchip_counter - 1) * 0x2000),
1601 filebuffer + loadfile_offset, 0x2000);
1602 memcpy(filebuffer, extra_buffer_32kb, 0x4000);
1603 loadfile_offset = 0;
1604 if (write_chip_package(0x4000, chip_counter, 0x8000, 0) < 0) {
1605 close_output_cleanup();
1606 }
1607 if (!quiet_mode) {
1608 if (subchip_counter == 1) {
1609 printf("inserted %s as a 16KB eprom in bank %d of the Rex EP256 .crt\n",
1610 input_filename[name_counter], chip_counter);
1611 } else {
1612 printf(" and %s as a 16KB eprom in bank %d of the Rex EP256 .crt\n",
1613 input_filename[name_counter], chip_counter);
1614 }
1615 }
1616 chip_counter++;
1617 subchip_counter = 1;
1618 } else {
1619 memcpy(extra_buffer_32kb, filebuffer + loadfile_offset, 0x2000);
1620 if (!quiet_mode) {
1621 printf("inserted %s", input_filename[name_counter]);
1622 }
1623 subchip_counter++;
1624 }
1625 }
1626
1627 if (eprom_size_for_8kb == 4 && subchip_counter == 1 && name_counter != input_filenames) {
1628 memcpy(extra_buffer_32kb, filebuffer + loadfile_offset, 0x2000);
1629 if (!quiet_mode) {
1630 printf("inserted %s", input_filename[name_counter]);
1631 }
1632 subchip_counter++;
1633 }
1634 }
1635 }
1636 }
1637 name_counter++;
1638 }
1639
1640 fclose(outfile);
1641 bin2crt_ok();
1642 cleanup();
1643 exit(0);
1644 }
1645
save_generic_crt(unsigned int p1,unsigned int p2,unsigned int p3,unsigned int p4,unsigned char p5,unsigned char p6)1646 static void save_generic_crt(unsigned int p1, unsigned int p2, unsigned int p3, unsigned int p4, unsigned char p5, unsigned char p6)
1647 {
1648 /* printf("save_generic_crt ultimax: %d size: %08x\n", convert_to_ultimax, loadfile_size); */
1649 if (convert_to_ultimax == 1) {
1650 switch (loadfile_size) {
1651 case CARTRIDGE_SIZE_4KB:
1652 save_regular_crt(0x1000, 1, 0xf000, 0, 0, 1);
1653 break;
1654 case CARTRIDGE_SIZE_8KB:
1655 save_regular_crt(0x2000, 1, 0xe000, 0, 0, 1);
1656 break;
1657 case CARTRIDGE_SIZE_16KB:
1658 save_2_blocks_crt(0x2000, 0x2000, 0x8000, 0xe000, 0, 1);
1659 break;
1660 default:
1661 break;
1662 }
1663 } else {
1664 switch (loadfile_size) {
1665 case CARTRIDGE_SIZE_4KB:
1666 save_regular_crt(0x1000, 0, 0x8000, 0, 1, 0);
1667 break;
1668 case CARTRIDGE_SIZE_8KB:
1669 save_regular_crt(0x2000, 0, 0x8000, 0, 1, 0);
1670 break;
1671 case CARTRIDGE_SIZE_12KB:
1672 save_regular_crt(0x3000, 1, 0x8000, 0, 0, 0);
1673 break;
1674 case CARTRIDGE_SIZE_16KB:
1675 save_regular_crt(0x4000, 1, 0x8000, 0, 0, 0);
1676 break;
1677 default:
1678 break;
1679 }
1680 }
1681 }
1682
main(int argc,char * argv[])1683 int main(int argc, char *argv[])
1684 {
1685 int i;
1686 int arg_counter = 1;
1687 char *flag, *argument;
1688
1689 if (argc > 1) {
1690 if(strcmp(argv[1], "--types") == 0) {
1691 usage_types();
1692 return EXIT_SUCCESS;
1693 } else if (strcmp(argv[1], "--version") == 0) {
1694 dump_version();
1695 return EXIT_SUCCESS;
1696 }
1697 }
1698
1699 if (argc < 3) {
1700 usage();
1701 return EXIT_FAILURE;
1702 }
1703
1704 for (i = 0; i < 33; i++) {
1705 input_filename[i] = NULL;
1706 }
1707
1708 while (arg_counter < argc) {
1709 flag = argv[arg_counter];
1710 argument = (arg_counter + 1 < argc) ? argv[arg_counter + 1] : NULL;
1711 if (flag[0] != '-') {
1712 usage();
1713 } else {
1714 arg_counter += checkflag(flag, argument);
1715 }
1716 }
1717
1718 if (output_filename == NULL) {
1719 fprintf(stderr, "Error: no output filename\n");
1720 cleanup();
1721 exit(1);
1722 }
1723 if (input_filenames == 0) {
1724 fprintf(stderr, "Error: no input filename\n");
1725 cleanup();
1726 exit(1);
1727 }
1728 if (!strcmp(output_filename, input_filename[0])) {
1729 fprintf(stderr, "Error: output filename = input filename\n");
1730 cleanup();
1731 exit(1);
1732 }
1733 if (load_input_file(input_filename[0]) < 0) {
1734 cleanup();
1735 exit(1);
1736 }
1737 if (input_filenames > 1 && cart_type != CARTRIDGE_DELA_EP64 && cart_type != CARTRIDGE_DELA_EP256 &&
1738 cart_type != CARTRIDGE_DELA_EP7x8 && cart_type != CARTRIDGE_REX_EP256 && loadfile_cart_type != CARTRIDGE_DELA_EP64 &&
1739 loadfile_cart_type != CARTRIDGE_DELA_EP256 && loadfile_cart_type != CARTRIDGE_DELA_EP7x8 &&
1740 loadfile_cart_type != CARTRIDGE_REX_EP256) {
1741 too_many_inputs();
1742 }
1743 if ((cart_type == CARTRIDGE_DELA_EP64 || loadfile_cart_type == CARTRIDGE_DELA_EP64) && input_filenames > 3) {
1744 too_many_inputs();
1745 }
1746 if ((cart_type == CARTRIDGE_DELA_EP7x8 || loadfile_cart_type == CARTRIDGE_DELA_EP7x8) && input_filenames > 8) {
1747 too_many_inputs();
1748 }
1749 if (loadfile_is_crt == 1) {
1750 if (cart_type == CARTRIDGE_DELA_EP64 || cart_type == CARTRIDGE_DELA_EP256 || cart_type == CARTRIDGE_DELA_EP7x8 ||
1751 cart_type == CARTRIDGE_REX_EP256) {
1752 cart_info[(unsigned char)cart_type].save(0, 0, 0, 0, 0, 0);
1753 } else {
1754 if (cart_type == -1) {
1755 if (save_binary_output_file() < 0) {
1756 cleanup();
1757 exit(1);
1758 }
1759 } else {
1760 fprintf(stderr, "Error: File is already .crt format\n");
1761 cleanup();
1762 exit(1);
1763 }
1764 }
1765 } else {
1766 if (cart_type == -1) {
1767 fprintf(stderr, "Error: File is already in binary format\n");
1768 cleanup();
1769 exit(1);
1770 }
1771 /* FIXME: the sizes are used in a bitfield, and also by their absolute values. this
1772 check is doomed to fail because of that :)
1773 */
1774 if (input_padding) {
1775 while ((loadfile_size & cart_info[(unsigned char)cart_type].sizes) != loadfile_size) {
1776 loadfile_size++;
1777 }
1778 } else {
1779 if ((loadfile_size & cart_info[(unsigned char)cart_type].sizes) != loadfile_size) {
1780 fprintf(stderr, "Error: Input file size (%d) doesn't match %s requirements\n",
1781 loadfile_size, cart_info[(unsigned char)cart_type].name);
1782 cleanup();
1783 exit(1);
1784 }
1785 }
1786 if (cart_info[(unsigned char)cart_type].save != NULL) {
1787 cart_info[(unsigned char)cart_type].save(cart_info[(unsigned char)cart_type].bank_size,
1788 cart_info[(unsigned char)cart_type].banks,
1789 cart_info[(unsigned char)cart_type].load_address,
1790 cart_info[(unsigned char)cart_type].data_type,
1791 cart_info[(unsigned char)cart_type].game,
1792 cart_info[(unsigned char)cart_type].exrom);
1793 }
1794 }
1795 return 0;
1796 }
1797