update makebin to fix mayhem report
[debian/cc1111] / debian / patches / updated_makebin
1 diff --git a/support/makebin/makebin.c b/support/makebin/makebin.c
2 index 83d4ec6..d8028d3 100644
3 --- a/support/makebin/makebin.c
4 +++ b/support/makebin/makebin.c
5 @@ -1,121 +1,491 @@
6 -/** @name makebin - turn a .ihx file into a binary image.
7 - */
8 +/*
9 +  makebin - turn a .ihx file into a binary image or GameBoy format binaryimage
10 +
11 +  Copyright (c) 2000 Michael Hope
12 +  Copyright (c) 2010 Borut Razem
13 +  Copyright (c) 2012 Noel Lemouel
14 +
15 +  This software is provided 'as-is', without any express or implied
16 +  warranty.  In no event will the authors be held liable for any damages
17 +  arising from the use of this software.
18 +
19 +  Permission is granted to anyone to use this software for any purpose,
20 +  including commercial applications, and to alter it and redistribute it
21 +  freely, subject to the following restrictions:
22 +
23 +  1. The origin of this software must not be misrepresented; you must not
24 +     claim that you wrote the original software. If you use this software
25 +     in a product, an acknowledgment in the product documentation would be
26 +     appreciated but is not required.
27 +  2. Altered source versions must be plainly marked as such, and must not be
28 +     misrepresented as being the original software.
29 +  3. This notice may not be removed or altered from any source distribution.
30 +*/
31 +
32 +
33  #include <stdio.h>
34 -#include <unistd.h>
35  #include <stdlib.h>
36  #include <string.h>
37 +#include <ctype.h>
38  
39 -#if defined(__BORLANDC__) || defined(__MINGW32__) || defined(__CYGWIN__)
40 -  #include <fcntl.h>
41 -  #include <io.h>
42 +#if defined(_WIN32)
43 +#include <fcntl.h>
44 +#include <io.h>
45 +#else
46 +#include <unistd.h>
47  #endif
48  
49  
50  typedef unsigned char BYTE;
51  
52 -#define FILL_BYTE 0xFF
53 +#define FILL_BYTE 0xff
54  
55 -int getnibble(char **p)
56 +int
57 +getnibble (FILE *fin)
58  {
59 -  int ret = *((*p)++) - '0';
60 -  if (ret > 9) {
61 -    ret -= 'A' - '9' - 1;
62 -  }
63 +  int ret;
64 +  int c = getc (fin);
65 +
66 +  if (feof (fin) || ferror (fin))
67 +    {
68 +      fprintf (stderr, "error: unexpected end of file.\n");
69 +      exit (6);
70 +    }
71 +
72 +  ret = c - '0';
73 +  if (ret > 9)
74 +    {
75 +      ret -= 'A' - '9' - 1;
76 +    }
77 +
78 +  if (ret > 0xf)
79 +    {
80 +       ret -= 'a' - 'A';
81 +    }
82 +
83 +  if (ret < 0 || ret > 0xf)
84 +    {
85 +      fprintf (stderr, "error: character %02x.\n", ret);
86 +      exit (7);
87 +    }
88    return ret;
89  }
90  
91 -int getbyte(char **p)
92 +int
93 +getbyte (FILE *fin, int *sum)
94  {
95 -  return (getnibble(p) << 4) | getnibble(p);
96 +  int b = (getnibble (fin) << 4) | getnibble (fin);
97 +  *sum += b;
98 +  return b;
99  }
100  
101 -void usage(void)
102 +void
103 +usage (void)
104  {
105 -  fprintf(stderr, 
106 -          "makebin: convert a Intel IHX file to binary.\n"
107 -          "Usage: makebin [-p] [-s romsize] [-h]\n");
108 +  fprintf (stderr,
109 +           "makebin: convert a Intel IHX file to binary or GameBoy format binary.\n"
110 +           "Usage: makebin [options] [<in_file> [<out_file>]]\n"
111 +           "Options:\n"
112 +           "  -p             pack mode: the binary file size will be truncated to the last occupied byte\n"
113 +           "  -s romsize     size of the binary file (default: 32768)\n"
114 +           "  -Z             genarate GameBoy format binary file\n"
115 +           "GameBoy format options (applicable only with -Z option):\n"
116 +           "  -yo n          number of rom banks (default: 2)\n"
117 +           "  -ya n          number of ram banks (default: 0)\n"
118 +           "  -yt n          MBC type (default: no MBC)\n"
119 +           "  -yn name       cartridge name (default: none)\n"
120 +           "Arguments:\n"
121 +           "  <in_file>      optional IHX input file, '-' means stdin. (default: stdin)\n"
122 +           "  <out_file>     optional output file, '-' means stdout. (default: stdout)\n");
123  }
124  
125 -void fixStdout(void)
126 +#define CART_NAME_LEN 16
127 +
128 +struct gb_opt_s
129  {
130 -  #if defined(__BORLANDC__) || defined(__MINGW32__) || defined(__CYGWIN__)
131 -    setmode(fileno(stdout), O_BINARY);
132 -  #endif
133 +  char cart_name[CART_NAME_LEN];  /* cartridge name buffer */
134 +  BYTE mbc_type;                  /* MBC type (default: no MBC) */
135 +  short nb_rom_banks;             /* Number of rom banks (default: 2) */
136 +  BYTE nb_ram_banks;              /* Number of ram banks (default: 0) */
137 +};
138 +
139 +void
140 +gb_postproc (BYTE * rom, int size, int *real_size, struct gb_opt_s *o)
141 +{
142 +  int i, chk;
143 +  static const BYTE gb_logo[] =
144 +    {
145 +      0xce, 0xed, 0x66, 0x66, 0xcc, 0x0d, 0x00, 0x0b,
146 +      0x03, 0x73, 0x00, 0x83, 0x00, 0x0c, 0x00, 0x0d,
147 +      0x00, 0x08, 0x11, 0x1f, 0x88, 0x89, 0x00, 0x0e,
148 +      0xdc, 0xcc, 0x6e, 0xe6, 0xdd, 0xdd, 0xd9, 0x99,
149 +      0xbb, 0xbb, 0x67, 0x63, 0x6e, 0x0e, 0xec, 0xcc,
150 +      0xdd, 0xdc, 0x99, 0x9f, 0xbb, 0xb9, 0x33, 0x3e
151 +    };
152 +
153 +  /* $0104-$0133: Nintendo logo
154 +   * If missing, an actual Game Boy won't run the ROM.
155 +   */
156 +
157 +  memcpy (&rom[0x104], gb_logo, sizeof (gb_logo));
158 +
159 +  /*
160 +   * 0134-0142: Title of the game in UPPER CASE ASCII. If it
161 +   * is less than 16 characters then the
162 +   * remaining bytes are filled with 00's.
163 +   */
164 +
165 +  /* capitalize cartridge name */
166 +  for (i = 0; i < CART_NAME_LEN; ++i)
167 +    {
168 +      rom[0x134 + i] = toupper (o->cart_name[i]);
169 +    }
170 +
171 +  /*
172 +   * 0147: Cartridge type:
173 +   * 0-ROM ONLY            12-ROM+MBC3+RAM
174 +   * 1-ROM+MBC1            13-ROM+MBC3+RAM+BATT
175 +   * 2-ROM+MBC1+RAM        19-ROM+MBC5
176 +   * 3-ROM+MBC1+RAM+BATT   1A-ROM+MBC5+RAM
177 +   * 5-ROM+MBC2            1B-ROM+MBC5+RAM+BATT
178 +   * 6-ROM+MBC2+BATTERY    1C-ROM+MBC5+RUMBLE
179 +   * 8-ROM+RAM             1D-ROM+MBC5+RUMBLE+SRAM
180 +   * 9-ROM+RAM+BATTERY     1E-ROM+MBC5+RUMBLE+SRAM+BATT
181 +   * B-ROM+MMM01           1F-Pocket Camera
182 +   * C-ROM+MMM01+SRAM      FD-Bandai TAMA5
183 +   * D-ROM+MMM01+SRAM+BATT FE - Hudson HuC-3
184 +   * F-ROM+MBC3+TIMER+BATT FF - Hudson HuC-1
185 +   * 10-ROM+MBC3+TIMER+RAM+BATT
186 +   * 11-ROM+MBC3
187 +   */
188 +  rom[0x147] = o->mbc_type;
189 +
190 +  /*
191 +   * 0148 ROM size:
192 +   * 0 - 256Kbit = 32KByte = 2 banks
193 +   * 1 - 512Kbit = 64KByte = 4 banks
194 +   * 2 - 1Mbit = 128KByte = 8 banks
195 +   * 3 - 2Mbit = 256KByte = 16 banks
196 +   * 4 - 4Mbit = 512KByte = 32 banks
197 +   * 5 - 8Mbit = 1MByte = 64 banks
198 +   * 6 - 16Mbit = 2MByte = 128 banks
199 +   * $52 - 9Mbit = 1.1MByte = 72 banks
200 +   * $53 - 10Mbit = 1.2MByte = 80 banks
201 +   * $54 - 12Mbit = 1.5MByte = 96 banks
202 +   */
203 +  switch (o->nb_rom_banks)
204 +    {
205 +    case 2:
206 +      rom[0x148] = 0;
207 +      break;
208 +
209 +    case 4:
210 +      rom[0x148] = 1;
211 +      break;
212 +
213 +    case 8:
214 +      rom[0x148] = 2;
215 +      break;
216 +
217 +    case 16:
218 +      rom[0x148] = 3;
219 +      break;
220 +
221 +    case 32:
222 +      rom[0x148] = 4;
223 +      break;
224 +
225 +    case 64:
226 +      rom[0x148] = 5;
227 +      break;
228 +
229 +    case 128:
230 +      rom[0x148] = 6;
231 +      break;
232 +
233 +    case 256:
234 +      rom[0x148] = 7;
235 +      break;
236 +
237 +    case 512:
238 +      rom[0x148] = 8;
239 +      break;
240 +
241 +    default:
242 +      fprintf (stderr, "warning: unsupported number of ROM banks (%d)\n", o->nb_rom_banks);
243 +      rom[0x148] = 0;
244 +      break;
245 +    }
246 +
247 +  /*
248 +   * 0149 RAM size:
249 +   * 0 - None
250 +   * 1 - 16kBit = 2kB = 1 bank
251 +   * 2 - 64kBit = 8kB = 1 bank
252 +   * 3 - 256kBit = 32kB = 4 banks
253 +   * 4 - 1MBit =128kB =16 banks
254 +   */
255 +  switch (o->nb_ram_banks)
256 +    {
257 +    case 0:
258 +      rom[0x149] = 0;
259 +      break;
260 +
261 +    case 1:
262 +      rom[0x149] = 2;
263 +      break;
264 +
265 +    case 4:
266 +      rom[0x149] = 3;
267 +      break;
268 +
269 +    case 16:
270 +      rom[0x149] = 4;
271 +      break;
272 +
273 +    default:
274 +      fprintf (stderr, "warning: unsupported number of RAM banks (%d)\n", o->nb_ram_banks);
275 +      rom[0x149] = 0;
276 +      break;
277 +    }
278 +
279 +  /* Update complement checksum */
280 +  chk = 0;
281 +  for (i = 0x134; i < 0x14d; ++i)
282 +    chk += rom[i];
283 +  rom[0x014d] = (unsigned char) (0xe7 - (chk & 0xff));
284 +
285 +  /* Update checksum */
286 +  chk = 0;
287 +  rom[0x14e] = 0;
288 +  rom[0x14f] = 0;
289 +  for (i = 0; i < size; ++i)
290 +    chk += rom[i];
291 +  rom[0x14e] = (unsigned char) ((chk >> 8) & 0xff);
292 +  rom[0x14f] = (unsigned char) (chk & 0xff);
293 +
294 +  if (*real_size < 0x150)
295 +    *real_size = 0x150;
296  }
297  
298 +int
299 +read_ihx (FILE *fin, BYTE *rom, int size, int *real_size)
300 +{
301 +  int record_type;
302 +
303 +  do
304 +    {
305 +      int nbytes;
306 +      int addr;
307 +      int checksum, sum = 0;
308 +
309 +      if (getc (fin) != ':')
310 +        {
311 +          fprintf (stderr, "error: invalid IHX line.\n");
312 +          return 0;
313 +        }
314 +      nbytes = getbyte (fin, &sum);
315 +      addr = getbyte (fin, &sum) << 8 | getbyte (fin, &sum);
316 +      record_type = getbyte (fin, &sum);
317 +      if (record_type > 1)
318 +        {
319 +          fprintf (stderr, "error: unsupported record type: %02x.\n", record_type);
320 +          return 0;
321 +        }
322 +
323 +      if (addr + nbytes > size)
324 +        {
325 +          fprintf (stderr, "error: size of the buffer is too small.\n");
326 +          return 0;
327 +        }
328 +
329 +      while (nbytes--)
330 +        {
331 +          if (addr < size)
332 +            rom[addr++] = getbyte (fin, &sum);
333 +        }
334 +
335 +      if (addr > *real_size)
336 +        *real_size = addr;
337 +
338 +      checksum = getbyte (fin, &sum);
339 +      if (0 != (sum & 0xff))
340 +        {
341 +          fprintf (stderr, "error: bad checksum: %02x.\n", checksum);
342 +          return 0;
343 +        }
344  
345 -int main(int argc, char **argv)
346 +      while (isspace (sum = getc (fin)))  /* skip all kind of speces */
347 +        ;
348 +      ungetc (sum, fin);
349 +    }
350 +  while (1 != record_type); /* EOF record */
351 +
352 +  return 1;
353 +}
354 +
355 +int
356 +main (int argc, char **argv)
357  {
358 -    int size = 32768, pack = 0, real_size = 0;
359 -    BYTE *rom;
360 -    char line[256];
361 -    char *p;
362 -
363 -    argc--;
364 -    argv++;
365 -
366 -    fixStdout();
367 -    
368 -    while (argc--) {
369 -        if (**argv != '-') {
370 -            usage();
371 -            return -1;
372 +  int size = 32768, pack = 0, real_size = 0;
373 +  BYTE *rom;
374 +  FILE *fin, *fout;
375 +  int ret;
376 +  int gb = 0;
377 +  struct gb_opt_s gb_opt = { "", 0, 2, 0 };
378 +
379 +#if defined(_WIN32)
380 +  setmode (fileno (stdout), O_BINARY);
381 +#endif
382 +
383 +  while (*++argv && '-' == argv[0][0] && '\0' != argv[0][1])
384 +    {
385 +      switch (argv[0][1])
386 +        {
387 +        case 's':
388 +          if (!*++argv)
389 +            {
390 +              usage ();
391 +              return 1;
392 +            }
393 +          size = atoi (*argv);
394 +          break;
395 +
396 +        case 'h':
397 +          usage ();
398 +          return 0;
399 +
400 +        case 'p':
401 +          pack = 1;
402 +          break;
403 +
404 +        case 'Z':
405 +          /* generate GameBoy binary file */
406 +          gb = 1;
407 +          break;
408 +
409 +        case 'y':
410 +          /* GameBoy options:
411 +           * -yo  Number of rom banks (default: 2)
412 +           * -ya  Number of ram banks (default: 0)
413 +           * -yt  MBC type (default: no MBC)
414 +           * -yn  Name of program (default: name of output file)
415 +           */
416 +          switch (argv[0][2])
417 +            {
418 +            case 'o':
419 +              if (!*++argv)
420 +                {
421 +                  usage ();
422 +                  return 1;
423 +                }
424 +              gb_opt.nb_rom_banks = atoi (*argv);
425 +              break;
426 +
427 +            case 'a':
428 +              if (!++argv)
429 +                {
430 +                  usage ();
431 +                  return 1;
432 +                }
433 +              gb_opt.nb_ram_banks = atoi (*argv);
434 +              break;
435 +
436 +            case 't':
437 +              if (!*++argv)
438 +                {
439 +                  usage ();
440 +                  return 1;
441 +                }
442 +              gb_opt.mbc_type = atoi (*argv);
443 +              break;
444 +
445 +            case 'n':
446 +              if (!*++argv)
447 +                {
448 +                  usage ();
449 +                  return 1;
450 +                }
451 +              strncpy (gb_opt.cart_name, *argv, CART_NAME_LEN);
452 +              break;
453 +
454 +            default:
455 +              usage ();
456 +              return 1;
457 +            }
458 +          break;
459 +
460 +        default:
461 +          usage ();
462 +          return 1;
463          }
464 -        switch (argv[0][1]) {
465 -       case 's':
466 -            if (argc < 1) {
467 -                usage();
468 -                return -1;
469 +    }
470 +
471 +  fin = stdin;
472 +  fout = stdout;
473 +  if (*argv)
474 +    {
475 +      if ('-' != argv[0][0] || '\0' != argv[0][1])
476 +        {
477 +          if (NULL == (fin = fopen (*argv, "r")))
478 +            {
479 +              fprintf (stderr, "error: can't open %s: ", *argv);
480 +              perror(NULL);
481 +              return 1;
482              }
483 -            argc--;
484 -            argv++;
485 -           size = atoi(*argv);
486 -           break;
487 -       case 'h':
488 -            usage();
489 -           return 0;
490 -       case 'p':
491 -           pack = 1;
492 -           break;
493 -       default:
494 -            usage();
495 -            return -1;
496 -       }
497 -        argv++;
498 +        }
499 +      ++argv;
500 +    }
501 +
502 +  if (NULL != argv[0] && NULL != argv[1])
503 +    {
504 +      usage ();
505 +      return 1;
506      }
507  
508 -    rom = malloc(size);
509 -    if (rom == NULL) {
510 -       fprintf(stderr, "error: couldn't allocate room for the image.\n");
511 -       return -1;
512 +  if (gb && size != 32768)
513 +    {
514 +      fprintf (stderr, "error: only length of 32768 bytes supported for GameBoy binary.\n");
515 +      return 1;
516      }
517 -    memset(rom, FILL_BYTE, size);
518 -    while (fgets(line, 256, stdin) != NULL) {
519 -       int nbytes;
520 -       int addr;
521 -
522 -       if (*line != ':') {
523 -           fprintf(stderr, "error: invalid IHX line.\n");
524 -           return -2;
525 -       }
526 -       p = line+1;
527 -       nbytes = getbyte(&p);
528 -       addr = getbyte(&p)<<8 | getbyte(&p);
529 -       getbyte(&p);
530 -
531 -       while (nbytes--) {
532 -           if (addr < size)
533 -               rom[addr++] = getbyte(&p);
534 -       }
535 -
536 -       if (addr > real_size)
537 -           real_size = addr;
538 +
539 +  rom = malloc (size);
540 +  if (rom == NULL)
541 +    {
542 +      fclose (fin);
543 +      fprintf (stderr, "error: couldn't allocate room for the image.\n");
544 +      return 1;
545      }
546 +  memset (rom, FILL_BYTE, size);
547 +
548 +  ret = read_ihx (fin, rom, size, &real_size);
549  
550 -    if (pack)
551 -        fwrite(rom, 1, real_size, stdout);
552 -    else
553 -        fwrite(rom, 1, size, stdout);
554 -    
555 -    return 0;
556 +  fclose (fin);
557 +
558 +  if (ret)
559 +    {
560 +      if (gb)
561 +        gb_postproc (rom, size, &real_size, &gb_opt);
562 +
563 +      if (*argv)
564 +        {
565 +          if ('-' != argv[0][0] || '\0' != argv[0][1])
566 +            {
567 +              if (NULL == (fout = fopen (*argv, "wb")))
568 +                {
569 +                  fprintf (stderr, "error: can't create %s: ", *argv);
570 +                  perror(NULL);
571 +                  return 1;
572 +                }
573 +            }
574 +        }
575 +
576 +      fwrite (rom, 1, (pack ? real_size : size), fout);
577 +
578 +      fclose (fout);
579 +
580 +      return 0;
581 +    }
582 +  else
583 +    return 1;
584  }