gbdk-2020 | GameBoy Development Kit |
| download: https://git.y1.nz/archives/gbdk.tar.gz | |
| README | Files | Log | Refs | LICENSE |
gbdk-support/bankpack/bankpack.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 2020
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 #include <time.h>
12
13 #include "obj_data.h"
14 #include "files.h"
15 #include "options.h"
16
17 static void display_help(void);
18 static int handle_args(int argc, char * argv[]);
19 static void init(void);
20 void cleanup(void);
21
22
23 static void display_help(void) {
24 fprintf(stdout,
25 "bankalloc [options] objfile1 objfile2 etc\n"
26 "Use: Read .o files and auto-assign areas with bank=255.\n"
27 " Typically called by Lcc compiler driver before linker.\n"
28 "\n"
29 "Options\n"
30 "-h : Show this help\n"
31 "-lkin=<file> : Load object files specified in linker file <file>\n"
32 "-lkout=<file> : Write list of object files out to linker file <file>\n"
33 "-yt<mbctype> : Set MBC type per ROM byte 149 in Decimal or Hex (0xNN)\n"
34 " ([see pandocs](https://gbdev.io/pandocs/The_Cartridge_Header.html#0147---cartridge-type))\n"
35 "-mbc=N : Similar to -yt, but sets MBC type directly to N instead\n"
36 " of by intepreting ROM byte 149\n"
37 " mbc1 will exclude banks {0x20,0x40,0x60} max=127, \n"
38 " mbc2 max=15, mbc3 max=127, mbc5 max=255 (not 511!) \n"
39 "-min=N : Min assigned ROM bank is N (default 1)\n"
40 "-max=N : Max assigned ROM bank is N, error if exceeded\n"
41 "-ext=<.ext> : Write files out with <.ext> instead of source extension\n"
42 "-path=<path> : Write files out to <path> (<path> *MUST* already exist)\n"
43 "-sym=<prefix> : Add symbols starting with <prefix> to match + update list\n"
44 " Default entry is \"___bank_\" (see below)\n"
45 "-cartsize : Print min required cart size as \"autocartsize:<NNN>\"\n"
46 "-plat=<plat> : Select platform specific behavior (default:gb) (gb,sms)\n"
47 "-random : Distribute banks randomly for testing (honors -min/-max)\n"
48 "-reserve=<b:n> : Reserve N bytes (hex) in bank B (decimal)\n"
49 " Ex: -reserve=105:30F reserves 0x30F bytes in bank 105\n"
50 "-banktype=<b:t>: Set bank B (decimal) to use type T (CODE or LIT). For sms/gg\n"
51 " Ex: -banktype=2:LIT sets bank 2 to type LIT\n"
52 "-v : Verbose output, show assignments\n"
53 "\n"
54 "Example: \"bankpack -ext=.rel -path=some/newpath/ file1.o file2.o\"\n"
55 "Unless -ext or -path specify otherwise, input files are overwritten.\n"
56 "\n"
57 "Default MBC type is not set. It *must* be specified by -mbc= or -yt!\n"
58 "\n"
59 "The following will have FF and 255 replaced with the assigned bank:\n"
60 "A _CODE_255 size <size> flags <flags> addr <address>\n"
61 "S b_<function name> Def0000FF\n"
62 "S ___bank_<const name> Def0000FF\n"
63 " (Above can be made by: const void __at(255) __bank_<const name>;\n"
64 );
65 }
66
67
68 static int handle_args(int argc, char * argv[]) {
69
70 int i;
71
72 if( argc < 2 ) {
73 display_help();
74 return false;
75 }
76
77 // Start at first optional argument, argc is zero based
78 for (i = 1; i <= (argc -1); i++ ) {
79
80 if (argv[i][0] == '-') {
81 if (strstr(argv[i], "-h") == argv[i]) {
82 display_help();
83 return false; // Don't parse input when -h is used
84 } else if (strstr(argv[i], "-min=") == argv[i]) {
85 if (!option_banks_set_min(atoi(argv[i] + 5))) {
86 printf("BankPack: ERROR: Invalid min bank: %s\n", argv[i] + 5);
87 return false;
88 }
89 } else if (strstr(argv[i], "-max=") == argv[i]) {
90 if (!option_banks_set_max(atoi(argv[i] + 5))) {
91 printf("BankPack: ERROR: Invalid max bank: %s\n", argv[i] + 5);
92 return false;
93 }
94 } else if (strstr(argv[i], "-ext=") == argv[i]) {
95 files_set_out_ext(argv[i] + 5);
96 } else if (strstr(argv[i], "-path=") == argv[i]) {
97 files_set_out_path(argv[i] + 6);
98 } else if (strstr(argv[i], "-mbc=") == argv[i]) {
99 option_set_mbc(atoi(argv[i] + 5));
100 } else if (strstr(argv[i], "-mapper=") == argv[i]) {
101 option_set_nes_mapper(atoi(argv[i] + 8));
102 } else if (strstr(argv[i], "-yt") == argv[i]) {
103 option_mbc_by_rom_byte_149(strtol(argv[i] + 3, NULL, 0));
104 } else if (strstr(argv[i], "-v") == argv[i]) {
105 option_set_verbose(true);
106 } else if (strstr(argv[i], "-sym=") == argv[i]) {
107 symbol_match_add(argv[i] + 5);
108 } else if (strstr(argv[i], "-cartsize") == argv[i]) {
109 option_set_cartsize(true);
110 } else if (strstr(argv[i], "-plat=") == argv[i]) {
111 option_set_platform(argv[i] + 6);
112 } else if (strstr(argv[i], "-random") == argv[i]) {
113 option_set_random_assign(true);
114 } else if (strstr(argv[i], "-lkin=") == argv[i]) {
115 files_read_linkerfile(argv[i] + strlen("-lkin="));
116 } else if (strstr(argv[i], "-lkout=") == argv[i]) {
117 files_set_linkerfile_outname(argv[i] + strlen("-lkout="));
118 } else if (strstr(argv[i], "-reserve=") == argv[i]) {
119 if (!option_bank_reserve_bytes(argv[i])) {
120 fprintf(stdout,"BankPack: ERROR! Malformed argument: %s\n\n", argv[i]);
121 display_help();
122 return false;
123 }
124 } else if (strstr(argv[i], "-banktype=") == argv[i]) {
125 if (!option_bank_set_type(argv[i])) {
126 fprintf(stdout,"BankPack: ERROR! Malformed argument: %s\n\n", argv[i]);
127 display_help();
128 return false;
129 }
130 } else {
131 printf("BankPack: Warning: Ignoring unknown option %s\n", argv[i]);
132 }
133 } else {
134 // Add to list of object files to process
135 files_add(argv[i]);
136 }
137 }
138
139 return true;
140 }
141
142
143 static int matches_extension(char * filename, char * extension) {
144 return (strcmp(filename + (strlen(filename) - strlen(extension)), extension) == 0);
145 }
146
147
148 static void init(void) {
149 srand( time(0) );
150 files_init();
151 obj_data_init();
152 }
153
154
155 void cleanup(void) {
156 files_cleanup();
157 obj_data_cleanup();
158 }
159
160
161 int main( int argc, char *argv[] ) {
162
163 // Exit with failure by default
164 int ret = EXIT_FAILURE;
165
166 // Register cleanup with exit handler
167 atexit(cleanup);
168
169 init();
170
171 if (handle_args(argc, argv)) {
172
173 // Require MBC for Game Boy
174 // SMS doesn't require an MBC setting
175 if ((option_get_platform() == PLATFORM_GB) && (option_get_mbc_type() == MBC_TYPE_NONE))
176 printf("BankPack: ERROR: auto-banking does not work with nonbanked ROMS (no MBC for Game Boy)\n");
177 else {
178 // Extract areas, sort and assign them to banks
179 // then rewrite object files as needed
180 files_extract();
181 files_rewrite();
182
183 if (option_get_verbose())
184 banks_show();
185 if (option_get_cartsize())
186 fprintf(stdout,"autocartsize:%d\n",option_banks_calc_cart_size());
187
188 cleanup();
189 ret = EXIT_SUCCESS;
190 }
191 }
192
193 return ret; // Exit with failure by default
194 }
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.