cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

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}