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