3 Copyright (C) 1989-1995 Alan R. Baldwin
4 721 Berkeley St., Kent, Ohio 44240
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
31 /* Value used to fill the unused portions of the image */
32 /* FFh puts less stress on a EPROM/Flash */
33 #define FILLVALUE 0xFF
35 #define CARTSIZE ((unsigned long)nb_rom_banks*16UL*1024UL)
37 #define SEGSIZE (CARTSIZE/NBSEG)
39 #define ROMSIZE 0x8000UL
40 #define BANKSTART 0x4000UL
41 #define BANKSIZE 0x4000UL
43 unsigned char *cart[NBSEG];
49 char cart_name[16] = "";
51 patch* patches = NULL;
56 unsigned long pos, chk;
61 for(i = 0; i < NBSEG; i++) {
62 if((cart[i] = malloc(SEGSIZE)) == NULL) {
63 fprintf(stderr, "ERROR: can't allocate %dth segment of memory (%d bytes)\n", i, (int)SEGSIZE);
66 memset(cart[i], FILLVALUE, SEGSIZE);
73 pos = rtval[0] | (rtval[1]<<8);
75 pos = rtval[1] | (rtval[0]<<8);
77 /* Perform some validity checks */
79 fprintf(stderr, "ERROR: address overflow (addr %lx >= %lx)\n", pos, ROMSIZE);
82 if(current_rom_bank >= nb_rom_banks) {
83 fprintf(stderr, "ERROR: bank overflow (addr %x > %x)\n", current_rom_bank, nb_rom_banks);
86 if(current_rom_bank > 0 && pos < BANKSTART) {
87 fprintf(stderr, "ERROR: address underflow (addr %lx < %lx)\n", pos, BANKSTART);
90 if(nb_rom_banks == 2 && current_rom_bank > 0) {
91 fprintf(stderr, "ERROR: only 1 32kB segment with 2 bank\n");
94 if(current_rom_bank > 1)
95 pos += (current_rom_bank-1)*BANKSIZE;
96 for(i = 2; i < rtcnt; i++) {
99 if(cart[pos/SEGSIZE][pos%SEGSIZE] != FILLVALUE)
100 fprintf(stderr, "WARNING: possibly wrote twice at addr %lx (%02X->%02X)\n", pos, rtval[i], cart[pos/SEGSIZE][pos%SEGSIZE]);
101 cart[pos/SEGSIZE][pos%SEGSIZE] = rtval[i];
103 fprintf(stderr, "ERROR: cartridge size overflow (addr %lx >= %lx)\n", pos, CARTSIZE);
112 if(cart_name[0] == 0 && linkp->f_idp != NULL) {
113 for(i = strlen(linkp->f_idp);
114 i > 0 && (isalnum((unsigned char)linkp->f_idp[i-1]) || linkp->f_idp[i-1] == '.');
117 for(pos = 0; pos < 16 && linkp->f_idp[i] != '.'; pos++, i++)
118 cart_name[pos] = toupper((unsigned char)linkp->f_idp[i]);
122 for(pos = 0x0134, i = 0;
123 pos < 0x0144 && cart_name[i];
125 cart[pos/SEGSIZE][pos%SEGSIZE] = cart_name[i];
126 for(; pos < 0x0144; pos++)
127 cart[pos/SEGSIZE][pos%SEGSIZE] = 0;
128 cart[0x147/SEGSIZE][0x147%SEGSIZE] = mbc_type;
129 switch(nb_rom_banks) {
131 cart[0x148/SEGSIZE][0x148%SEGSIZE] = 0;
134 cart[0x148/SEGSIZE][0x148%SEGSIZE] = 1;
137 cart[0x148/SEGSIZE][0x148%SEGSIZE] = 2;
140 cart[0x148/SEGSIZE][0x148%SEGSIZE] = 3;
143 cart[0x148/SEGSIZE][0x148%SEGSIZE] = 4;
146 cart[0x148/SEGSIZE][0x148%SEGSIZE] = 5;
149 cart[0x148/SEGSIZE][0x148%SEGSIZE] = 6;
152 cart[0x148/SEGSIZE][0x148%SEGSIZE] = 7;
155 cart[0x148/SEGSIZE][0x148%SEGSIZE] = 8;
158 fprintf(stderr, "WARNING: unsupported number of ROM banks (%d)\n", nb_rom_banks);
159 cart[0x148/SEGSIZE][0x148%SEGSIZE] = 0;
162 switch(nb_ram_banks) {
164 cart[0x149/SEGSIZE][0x149%SEGSIZE] = 0;
167 cart[0x149/SEGSIZE][0x149%SEGSIZE] = 2;
170 cart[0x149/SEGSIZE][0x149%SEGSIZE] = 3;
173 cart[0x149/SEGSIZE][0x149%SEGSIZE] = 4;
176 fprintf(stderr, "WARNING: unsupported number of RAM banks (%d)\n", nb_ram_banks);
177 cart[0x149/SEGSIZE][0x149%SEGSIZE] = 0;
181 /* Patch before calculating the checksum */
183 for(p = patches; p; p = p->next)
184 cart[p->addr/SEGSIZE][p->addr%SEGSIZE] = p->value;
186 /* Update complement checksum */
188 for(pos = 0x0134; pos < 0x014D; pos++)
189 chk += cart[pos/SEGSIZE][pos%SEGSIZE];
190 cart[0x014D/SEGSIZE][0x014D%SEGSIZE] = (unsigned char)(0xE7 - (chk&0xFF));
191 /* Update checksum */
193 cart[0x014E/SEGSIZE][0x014E%SEGSIZE] = 0;
194 cart[0x014F/SEGSIZE][0x014F%SEGSIZE] = 0;
195 for(i = 0; i < NBSEG; i++)
196 for(pos = 0; pos < SEGSIZE; pos++)
198 cart[0x014E/SEGSIZE][0x014E%SEGSIZE] = (unsigned char)((chk>>8)&0xFF);
199 cart[0x014F/SEGSIZE][0x014F%SEGSIZE] = (unsigned char)(chk&0xFF);
201 for(i = 0; i < NBSEG; i++)
202 fwrite(cart[i], 1, SEGSIZE, ofp);