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
6 -/** @name makebin - turn a .ihx file into a binary image.
9 + makebin - turn a .ihx file into a binary image or GameBoy format binaryimage
11 + Copyright (c) 2000 Michael Hope
12 + Copyright (c) 2010 Borut Razem
13 + Copyright (c) 2012 Noel Lemouel
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.
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:
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.
39 -#if defined(__BORLANDC__) || defined(__MINGW32__) || defined(__CYGWIN__)
50 typedef unsigned char BYTE;
52 -#define FILL_BYTE 0xFF
53 +#define FILL_BYTE 0xff
55 -int getnibble(char **p)
57 +getnibble (FILE *fin)
59 - int ret = *((*p)++) - '0';
61 - ret -= 'A' - '9' - 1;
66 + if (feof (fin) || ferror (fin))
68 + fprintf (stderr, "error: unexpected end of file.\n");
75 + ret -= 'A' - '9' - 1;
83 + if (ret < 0 || ret > 0xf)
85 + fprintf (stderr, "error: character %02x.\n", ret);
91 -int getbyte(char **p)
93 +getbyte (FILE *fin, int *sum)
95 - return (getnibble(p) << 4) | getnibble(p);
96 + int b = (getnibble (fin) << 4) | getnibble (fin);
106 - "makebin: convert a Intel IHX file to binary.\n"
107 - "Usage: makebin [-p] [-s romsize] [-h]\n");
109 + "makebin: convert a Intel IHX file to binary or GameBoy format binary.\n"
110 + "Usage: makebin [options] [<in_file> [<out_file>]]\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"
121 + " <in_file> optional IHX input file, '-' means stdin. (default: stdin)\n"
122 + " <out_file> optional output file, '-' means stdout. (default: stdout)\n");
125 -void fixStdout(void)
126 +#define CART_NAME_LEN 16
130 - #if defined(__BORLANDC__) || defined(__MINGW32__) || defined(__CYGWIN__)
131 - setmode(fileno(stdout), O_BINARY);
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) */
140 +gb_postproc (BYTE * rom, int size, int *real_size, struct gb_opt_s *o)
143 + static const BYTE gb_logo[] =
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
153 + /* $0104-$0133: Nintendo logo
154 + * If missing, an actual Game Boy won't run the ROM.
157 + memcpy (&rom[0x104], gb_logo, sizeof (gb_logo));
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.
165 + /* capitalize cartridge name */
166 + for (i = 0; i < CART_NAME_LEN; ++i)
168 + rom[0x134 + i] = toupper (o->cart_name[i]);
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
188 + rom[0x147] = o->mbc_type;
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
203 + switch (o->nb_rom_banks)
242 + fprintf (stderr, "warning: unsupported number of ROM banks (%d)\n", o->nb_rom_banks);
250 + * 1 - 16kBit = 2kB = 1 bank
251 + * 2 - 64kBit = 8kB = 1 bank
252 + * 3 - 256kBit = 32kB = 4 banks
253 + * 4 - 1MBit =128kB =16 banks
255 + switch (o->nb_ram_banks)
274 + fprintf (stderr, "warning: unsupported number of RAM banks (%d)\n", o->nb_ram_banks);
279 + /* Update complement checksum */
281 + for (i = 0x134; i < 0x14d; ++i)
283 + rom[0x014d] = (unsigned char) (0xe7 - (chk & 0xff));
285 + /* Update checksum */
289 + for (i = 0; i < size; ++i)
291 + rom[0x14e] = (unsigned char) ((chk >> 8) & 0xff);
292 + rom[0x14f] = (unsigned char) (chk & 0xff);
294 + if (*real_size < 0x150)
295 + *real_size = 0x150;
299 +read_ihx (FILE *fin, BYTE *rom, int size, int *real_size)
307 + int checksum, sum = 0;
309 + if (getc (fin) != ':')
311 + fprintf (stderr, "error: invalid IHX line.\n");
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)
319 + fprintf (stderr, "error: unsupported record type: %02x.\n", record_type);
323 + if (addr + nbytes > size)
325 + fprintf (stderr, "error: size of the buffer is too small.\n");
332 + rom[addr++] = getbyte (fin, &sum);
335 + if (addr > *real_size)
338 + checksum = getbyte (fin, &sum);
339 + if (0 != (sum & 0xff))
341 + fprintf (stderr, "error: bad checksum: %02x.\n", checksum);
345 -int main(int argc, char **argv)
346 + while (isspace (sum = getc (fin))) /* skip all kind of speces */
350 + while (1 != record_type); /* EOF record */
356 +main (int argc, char **argv)
358 - int size = 32768, pack = 0, real_size = 0;
369 - if (**argv != '-') {
372 + int size = 32768, pack = 0, real_size = 0;
377 + struct gb_opt_s gb_opt = { "", 0, 2, 0 };
380 + setmode (fileno (stdout), O_BINARY);
383 + while (*++argv && '-' == argv[0][0] && '\0' != argv[0][1])
385 + switch (argv[0][1])
393 + size = atoi (*argv);
405 + /* generate GameBoy binary file */
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)
416 + switch (argv[0][2])
424 + gb_opt.nb_rom_banks = atoi (*argv);
433 + gb_opt.nb_ram_banks = atoi (*argv);
442 + gb_opt.mbc_type = atoi (*argv);
451 + strncpy (gb_opt.cart_name, *argv, CART_NAME_LEN);
464 - switch (argv[0][1]) {
475 + if ('-' != argv[0][0] || '\0' != argv[0][1])
477 + if (NULL == (fin = fopen (*argv, "r")))
479 + fprintf (stderr, "error: can't open %s: ", *argv);
485 - size = atoi(*argv);
502 + if (NULL != argv[0] && NULL != argv[1])
508 - rom = malloc(size);
510 - fprintf(stderr, "error: couldn't allocate room for the image.\n");
512 + if (gb && size != 32768)
514 + fprintf (stderr, "error: only length of 32768 bytes supported for GameBoy binary.\n");
517 - memset(rom, FILL_BYTE, size);
518 - while (fgets(line, 256, stdin) != NULL) {
522 - if (*line != ':') {
523 - fprintf(stderr, "error: invalid IHX line.\n");
527 - nbytes = getbyte(&p);
528 - addr = getbyte(&p)<<8 | getbyte(&p);
533 - rom[addr++] = getbyte(&p);
536 - if (addr > real_size)
539 + rom = malloc (size);
543 + fprintf (stderr, "error: couldn't allocate room for the image.\n");
546 + memset (rom, FILL_BYTE, size);
548 + ret = read_ihx (fin, rom, size, &real_size);
551 - fwrite(rom, 1, real_size, stdout);
553 - fwrite(rom, 1, size, stdout);
561 + gb_postproc (rom, size, &real_size, &gb_opt);
565 + if ('-' != argv[0][0] || '\0' != argv[0][1])
567 + if (NULL == (fout = fopen (*argv, "wb")))
569 + fprintf (stderr, "error: can't create %s: ", *argv);
576 + fwrite (rom, 1, (pack ? real_size : size), fout);