gbdk-2020 | GameBoy Development Kit |
| download: https://git.y1.nz/archives/gbdk.tar.gz | |
| README | Files | Log | Refs | LICENSE |
gbdk-support/bankpack/options.c
1 // This is free and unencumbered software released into the public domain.
2 // For more information, please refer to <https://unlicense.org>
3 // bbbbbr 2022
4
5 #include <stdio.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <stdbool.h>
10 #include <stdint.h>
11
12 #include "common.h"
13 #include "list.h"
14 #include "files.h"
15 #include "obj_data.h"
16 #include "options.h"
17
18 extern list_type banklist;
19 extern uint16_t bank_limit_rom_min;
20 extern uint16_t bank_limit_rom_max;
21 extern uint16_t bank_assigned_rom_max_alltypes;
22
23 bool option_verbose = false;
24 bool option_cartsize = false;
25 bool option_random_assign = false;
26 int option_mbc_type = MBC_TYPE_DEFAULT;
27 int option_platform = PLATFORM_DEFAULT;
28
29
30 void option_set_verbose(bool is_enabled) {
31 option_verbose = is_enabled;
32 }
33 bool option_get_verbose(void) {
34 return option_verbose;
35 }
36
37
38 void option_set_cartsize(bool is_enabled) {
39 option_cartsize = is_enabled;
40 }
41 bool option_get_cartsize(void) {
42 return option_cartsize;
43 }
44
45
46 void option_set_random_assign(bool is_enabled) {
47 option_random_assign = is_enabled;
48 }
49 bool option_get_random_assign(void) {
50 return option_random_assign;
51 }
52
53
54
55 // Format: -reserve=DECIMAL_BANKNUM:HEX_SIZE
56 // Reserve space in banks manually from command line arguments
57 // Should be called *after* obj_data_init() has initialized banks
58 int option_bank_reserve_bytes(char * arg_str) {
59
60 bank_item * banks = (bank_item *)banklist.p_array;
61
62 char cols;
63 char * p_str;
64 char * p_words[ARG_BANK_RESERVE_SIZE_MAX_SPLIT_WORDS];
65 char arg_str_copy[ARG_BANK_RESERVE_SIZE_MAX_LEN]; // copy arg since strtok modifies strings it operates on
66 snprintf(arg_str_copy, sizeof(arg_str_copy), "%s", arg_str);
67
68 // Split string into words using "-:=" as delimiters
69 cols = 0;
70 p_str = strtok(arg_str_copy,"-:=");
71 while (p_str != NULL)
72 {
73 p_words[cols++] = p_str;
74 p_str = strtok(NULL, "-:=");
75 if (cols >= ARG_BANK_RESERVE_SIZE_MAX_SPLIT_WORDS) break;
76 }
77
78 if (cols == ARG_BANK_RESERVE_SIZE_REC_COUNT_MATCH) {
79
80 uint32_t reserve_bank = strtol(p_words[1], NULL, 10); // [1] Decimal Bank Number
81 uint32_t reserve_size = strtol(p_words[2], NULL, 16); // [2] Hex Reserve Size
82
83 if ((reserve_bank < BANK_NUM_ROM_MIN) || (reserve_bank > BANK_NUM_ROM_MAX)) {
84 printf("BankPack: ERROR! Bank number %d for %s is invalid (min: %d, max: %d)\n", reserve_bank, arg_str, BANK_NUM_ROM_MIN, BANK_NUM_ROM_MAX);
85 exit(EXIT_FAILURE);
86 }
87
88 if (reserve_size > BANK_SIZE_ROM_MAX) {
89 printf("BankPack: ERROR! Size value %x for %s is too large (max:%x)\n", reserve_size, arg_str, BANK_SIZE_ROM_MAX);
90 exit(EXIT_FAILURE);
91 }
92
93 if (reserve_size > banks[reserve_bank].free) {
94 printf("BankPack: ERROR! Size of %x bytes for %s is larger than free space (%x bytes) in bank %d\n", reserve_size, arg_str, banks[reserve_bank].free, reserve_bank);
95 exit(EXIT_FAILURE);
96 }
97
98 // printf("Bankpack: Reserving %x bytes for bank %d (%s)\n", reserve_size, reserve_bank, arg_str);
99
100 // Params were valid, deduct the space from the bank
101 banks[reserve_bank].free -= reserve_size;
102 banks[reserve_bank].reserved += reserve_size;
103 return true;
104 } else
105 return false; // Signal failure
106
107 }
108
109
110 // Format: -banktype=DECIMAL_BANKNUM:BANK_TYPE_STRING
111 // Force a given bank to a specific type (mainly for SMS/GG with CODE and LIT types)
112 // Should be called *after* obj_data_init() has initialized banks
113 int option_bank_set_type(char * arg_str) {
114
115 bank_item * banks = (bank_item *)banklist.p_array;
116
117 char cols;
118 char * p_str;
119 char * p_words[ARG_BANK_SET_TYPE_MAX_SPLIT_WORDS];
120 char arg_str_copy[ARG_BANK_SET_TYPE_MAX_LEN]; // copy arg since strtok modifies strings it operates on
121 snprintf(arg_str_copy, sizeof(arg_str_copy), "%s", arg_str);
122
123 // Split string into words using "-:=" as delimiters
124 cols = 0;
125 p_str = strtok(arg_str_copy,"-:=");
126 while (p_str != NULL)
127 {
128 p_words[cols++] = p_str;
129 p_str = strtok(NULL, "-:=");
130 if (cols >= ARG_BANK_SET_TYPE_MAX_SPLIT_WORDS) break;
131 }
132
133 if (cols == ARG_BANK_SET_TYPE_REC_COUNT_MATCH) {
134
135 uint32_t bank_num = strtol(p_words[1], NULL, 10); // [1] Decimal Bank Number
136 uint32_t bank_type = BANK_TYPE_UNSET;
137
138 if (strncmp(p_words[2], "CODE", strlen("CODE") + 1) == 0) {
139 bank_type = BANK_TYPE_CODE;
140 } else if (strncmp(p_words[2], "LIT", strlen("LIT") + 1) == 0) {
141 bank_type = BANK_TYPE_LIT_EXCLUSIVE;
142 } else {
143 printf("BankPack: ERROR! Bank type %s for %s is invalid\n", p_words[2], arg_str);
144 exit(EXIT_FAILURE);
145 }
146
147 if ((bank_num < BANK_NUM_ROM_MIN) || (bank_num > BANK_NUM_ROM_MAX)) {
148 printf("BankPack: ERROR! Bank number %d for %s is invalid (min: %d, max: %d)\n", bank_num, arg_str, BANK_NUM_ROM_MIN, BANK_NUM_ROM_MAX);
149 exit(EXIT_FAILURE);
150 }
151
152 // Params were valid, set the bank type
153 banks[bank_num].type = bank_type;
154 return true;
155 } else
156 return false; // Signal failure
157 }
158
159
160 int option_get_platform(void) {
161 return option_platform;
162 }
163
164
165 void option_set_platform(char * platform_str) {
166
167 if (strcmp(platform_str, PLATFORM_STR_GB) == 0)
168 option_platform = PLATFORM_GB;
169 else if (strcmp(platform_str, PLATFORM_STR_AP) == 0)
170 option_platform = PLATFORM_GB; // Analogue Pocket uses GB platform
171 else if (strcmp(platform_str, PLATFORM_STR_DUCK) == 0)
172 option_platform = PLATFORM_GB; // Megaduck uses GB platform
173 else if (strcmp(platform_str, PLATFORM_STR_NES) == 0)
174 option_platform = PLATFORM_GB; // NES uses GB platform
175 else if (strcmp(platform_str, PLATFORM_STR_SMS) == 0)
176 option_platform = PLATFORM_SMS;
177 else if (strcmp(platform_str, PLATFORM_STR_GG) == 0)
178 option_platform = PLATFORM_SMS; // GG uses SMS platform
179 else if (strcmp(platform_str, PLATFORM_STR_MSXDOS) == 0)
180 option_platform = PLATFORM_SMS; // MSXDOS uses SMS platform
181 else
182 printf("BankPack: Warning: Invalid platform option %s\n", platform_str);
183 }
184
185
186
187 int option_get_mbc_type(void) {
188 return option_mbc_type;
189 }
190
191
192 // Set MBC type by interpreting from byte 149
193 //
194 // For lcc linker option: -Wl-ytN where N is one of the numbers below
195 //
196 // | Hex Code | MBC Type | SRAM | Battery | RTC | Extra Feature | Max ROM Size (1)|Max SRAM Size |
197 // | -------- | ------------- | ---- | ------- | --- | --------------- | --------------- |--------------- |
198 // | 0x00 | ROM ONLY | | | | | 32 K |0 |
199 // | 0x01 | MBC-1 (2) | | | | | 2 MB |0 |
200 // | 0x02 | MBC-1 (2) | SRAM | | | | 2 MB |32 K (5) |
201 // | 0x03 | MBC-1 (2) | SRAM | BATTERY | | | 2 MB |32 K (5) |
202 // | 0x05 | MBC-2 | | | | | 256 K |512 x 4 bits (6)|
203 // | 0x06 | MBC-2 | | BATTERY | | | 256 K |512 x 4 bits (6)|
204 // | 0x08 | ROM (3) | SRAM | | | | 32 K |8 K |
205 // | 0x09 | ROM (3) | SRAM | BATTERY | | | 32 K |8 K |
206 // | 0x0B | MMM01 | | | | | 8 MB / N | |
207 // | 0x0C | MMM01 | SRAM | | | | 8 MB / N |128K / N |
208 // | 0x0D | MMM01 | SRAM | BATTERY | | | 8 MB / N |128K / N |
209 // | 0x0F | MBC-3 | | BATTERY | RTC | | 2 MB | |
210 // | 0x10 | MBC-3 (4) | SRAM | BATTERY | RTC | | 2 MB |32 K |
211 // | 0x11 | MBC-3 | | | | | 2 MB | |
212 // | 0x12 | MBC-3 (4) | SRAM | | | | 2 MB |32 K |
213 // | 0x13 | MBC-3 (4) | SRAM | BATTERY | | | 2 MB |32 K |
214 // | 0x19 | MBC-5 | | | | | 8 MB | |
215 // | 0x1A | MBC-5 | SRAM | | | | 8 MB |128 K |
216 // | 0x1B | MBC-5 | SRAM | BATTERY | | | 8 MB |128 K |
217 // | 0x1C | MBC-5 | | | | RUMBLE | 8 MB | |
218 // | 0x1D | MBC-5 | SRAM | | | RUMBLE | 8 MB |128 K |
219 // | 0x1E | MBC-5 | SRAM | BATTERY | | RUMBLE | 8 MB |128 K |
220 // | 0x20 | MBC-6 | | | | | ~2MB | |
221 // | 0x22 | MBC-7 |EEPROM| | | ACCELEROMETER | 2MB |256 byte EEPROM |
222 // | 0xFC | POCKET CAMERA | | | | | 1MB |128KB RAM |
223 // | 0xFD | BANDAI TAMA5 | | | | | To Do |To Do |
224 // | 0xFE | HuC3 | | | RTC | | To Do |To Do |
225 // | 0xFF | HuC1 | SRAM | BATTERY | | IR | To Do |To Do |
226 void option_mbc_by_rom_byte_149(int mbc_type_rom_byte) {
227
228 switch (mbc_type_rom_byte) {
229 // NO MBC
230 case 0x00u: // 0-ROM ONLY
231 case 0x08u: // 2-ROM+MBC1+RAM
232 case 0x09u: // 8-ROM+RAM
233 case 0x0Bu: // B-ROM+MMM01
234 case 0x0Cu: // C-ROM+MMM01+SRAM
235 case 0x0Du: // D-ROM+MMM01+SRAM+BATT
236 option_set_mbc(MBC_TYPE_NONE);
237 break;
238
239 // MBC 1
240 case 0x01u: // 1-ROM+MBC1
241 case 0x02u: // 2-ROM+MBC1+RAM
242 case 0x03u: // 3-ROM+MBC1+RAM+BATT
243 option_set_mbc(MBC_TYPE_MBC1);
244 break;
245
246 // MBC 2
247 case 0x05u: // 5-ROM+MBC2
248 case 0x06u: // 6-ROM+MBC2+BATTERY
249 option_set_mbc(MBC_TYPE_MBC2);
250 break;
251
252 // MBC 3
253 case 0x0Fu: // F-ROM+MBC3+TIMER+BATT
254 case 0x10u: // 10-ROM+MBC3+TIMER+RAM+BATT
255 case 0x11u: // 11-ROM+MBC3
256 case 0x12u: // 12-ROM+MBC3+RAM
257 case 0x13u: // 13-ROM+MBC3+RAM+BATT
258 case 0xFCu: // FC-GAME BOY CAMERA
259 option_set_mbc(MBC_TYPE_MBC3);
260 break;
261
262 // MBC 5
263 case 0x19u: // 19-ROM+MBC5
264 case 0x1Au: // 1A-ROM+MBC5+RAM
265 case 0x1Bu: // 1B-ROM+MBC5+RAM+BATT
266 case 0x1Cu: // 1C-ROM+MBC5+RUMBLE
267 case 0x1Du: // 1D-ROM+MBC5+RUMBLE+SRAM
268 case 0x1Eu: // 1E-ROM+MBC5+RUMBLE+SRAM+BATT
269 option_set_mbc(MBC_TYPE_MBC5);
270 break;
271
272 // MBC 7
273 case 0x22u: // 22-MBC-7 +ACCELEROMETER +EEPROM : 2MB ROM, 256 byte EEPROM
274 option_set_mbc(MBC_TYPE_MBC7);
275 break;
276
277 default:
278 printf("BankPack: Warning: unrecognized MBC option -yt=%x\n", mbc_type_rom_byte);
279 break;
280 }
281 }
282
283
284 // Set MBC type directly
285 void option_set_mbc(int mbc_type) {
286
287 uint16_t mbc_bank_limit_rom_max;
288
289 switch (mbc_type) {
290 case MBC_TYPE_NONE:
291 option_mbc_type = MBC_TYPE_NONE;
292 break;
293 case MBC_TYPE_MBC1:
294 option_mbc_type = mbc_type;
295 mbc_bank_limit_rom_max = BANK_NUM_ROM_MAX_MBC1;
296 break;
297 case MBC_TYPE_MBC2:
298 option_mbc_type = mbc_type;
299 mbc_bank_limit_rom_max = BANK_NUM_ROM_MAX_MBC2;
300 break;
301 case MBC_TYPE_MBC3:
302 option_mbc_type = mbc_type;
303 mbc_bank_limit_rom_max = BANK_NUM_ROM_MAX_MBC3;
304 break;
305 case MBC_TYPE_MBC5:
306 option_mbc_type = mbc_type;
307 mbc_bank_limit_rom_max = BANK_NUM_ROM_MAX_MBC5;
308 break;
309 case MBC_TYPE_MBC7:
310 option_mbc_type = mbc_type;
311 mbc_bank_limit_rom_max = BANK_NUM_ROM_MAX_MBC7;
312 break;
313 default:
314 printf("BankPack: Warning: unrecognized MBC option -mbc%d!\n", mbc_type);
315 break;
316 }
317 if (mbc_bank_limit_rom_max < bank_limit_rom_max)
318 bank_limit_rom_max = mbc_bank_limit_rom_max;
319 }
320
321 // Set NES mapper type directly
322 void option_set_nes_mapper(int mapper_type) {
323
324 uint16_t mapper_bank_limit_rom_max;
325
326 switch (mapper_type) {
327 case NES_MAPPER_TYPE_NONE:
328 option_mbc_type = NES_MAPPER_TYPE_NONE;
329 break;
330 case NES_MAPPER_TYPE_UXROM:
331 option_mbc_type = mapper_type;
332 mapper_bank_limit_rom_max = BANK_NUM_ROM_MAX_UXROM;
333 break;
334 case NES_MAPPER_TYPE_MAPPER30:
335 option_mbc_type = mapper_type;
336 mapper_bank_limit_rom_max = BANK_NUM_ROM_MAX_MAPPER30;
337 break;
338 default:
339 printf("BankPack: Warning: unrecognized NES mapper option -mapper%d!\n", mapper_type);
340 break;
341 }
342 if (mapper_bank_limit_rom_max < bank_limit_rom_max)
343 bank_limit_rom_max = mapper_bank_limit_rom_max;
344 }
345
346 // From makebin
347 // Byte
348 // 0148 - ROM size -yt<N>
349 // 0 - 256Kbit = 32KByte = 2 banks
350 // 1 - 512Kbit = 64KByte = 4 banks
351 // 2 - 1Mbit = 128KByte = 8 banks
352 // 3 - 2Mbit = 256KByte = 16 banks
353 // 4 - 4Mbit = 512KByte = 32 banks
354 // 5 - 8Mbit = 1MByte = 64 banks
355 // 6 - 16Mbit = 2MByte = 128 banks
356 // 7 - 16Mbit = 2MByte = 256 banks
357 // 8 - 16Mbit = 2MByte = 512 banks
358 //
359 // Not supported by makebin:
360 // $52 - 9Mbit = 1.1MByte = 72 banks
361 // $53 - 10Mbit = 1.2MByte = 80 banks
362 // $54 - 12Mbit = 1.5MByte = 96 banks
363 uint32_t option_banks_calc_cart_size(void) {
364
365 uint32_t req_banks = 1;
366
367 if ((bank_assigned_rom_max_alltypes + 1) > BANK_ROM_CALC_MAX) {
368 printf("BankPack: Warning! Can't calc cart size, too many banks: %d (max %d)\n", (bank_assigned_rom_max_alltypes + 1), BANK_ROM_CALC_MAX);
369 return (0);
370 }
371
372 // Calculate nearest upper power of 2
373 while (req_banks < (bank_assigned_rom_max_alltypes + 1))
374 req_banks *= 2;
375
376 return (req_banks);
377 }
378
379
380 bool option_banks_set_min(uint16_t bank_num) {
381 if (bank_num < BANK_NUM_ROM_MIN)
382 return false;
383 else bank_limit_rom_min = bank_num;
384
385 return true;
386 }
387
388 bool option_banks_set_max(uint16_t bank_num) {
389 if (bank_num > BANK_NUM_ROM_MAX)
390 return false;
391 else bank_limit_rom_max = bank_num;
392
393 return true;
394 }
395
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.