git.y1.nz

gbdk-2020

GameBoy Development Kit
download: https://git.y1.nz/archives/gbdk.tar.gz
README | Files | Log | Refs | LICENSE

gbdk-support/romusage/src/map_file.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 
     12 #include "common.h"
     13 #include "logging.h"
     14 #include "banks.h"
     15 #include "map_file.h"
     16 
     17 // Example data to parse from a .map file (excluding unwanted lines):
     18 /*
     19 _CODE                  00000200    00006A62 =       27234. bytes (REL,CON)
     20 _CODE                  00000200    00006A62 =       27234. bytes (REL,CON)
     21 _HOME                  00006C62    000000ED =         237. bytes (REL,CON)
     22 _BASE                  00006D4F    000002A3 =         675. bytes (REL,CON)
     23 _GSINIT                00006FF2    000001F9 =         505. bytes (REL,CON)
     24 _GSINITTAIL            000071EB    00000001 =           1. bytes (REL,CON)
     25 _DATA                  0000C0A0    00001684 =        5764. bytes (REL,CON)
     26 _BSS                   0000D724    00000041 =          65. bytes (REL,CON)
     27 _HEAP                  0000D765    00000000 =           0. bytes (REL,CON)
     28 _HRAM10                00000000    00000001 =           1. bytes (ABS,CON)
     29 */
     30 
     31 #define MAX_SPLIT_WORDS 6
     32 #define RGBDS_BANK_SPLIT_WORDS 3
     33 #define RGBDS_SECT_NAME_SPLIT_WORDS 3
     34 #define RGBDS_SECT_INFO_SPLIT_WORDS 5
     35 #define GBDK_AREA_SPLIT_WORDS 6
     36 #define BANK_NUM_UNSET 0xFFFFFFFF
     37 
     38 
     39 
     40 static int str_split(char * str_check, char * p_words[], const char * split_criteria) {
     41 
     42     int cols;
     43     char * p_str;
     44 
     45     cols = 0;
     46     p_str = strtok (str_check,split_criteria);
     47     while (p_str != NULL)
     48     {
     49         p_words[cols++] = p_str;
     50         p_str = strtok(NULL, split_criteria);
     51         if (cols >= MAX_SPLIT_WORDS) break;
     52     }
     53 
     54     return (cols);
     55 }
     56 
     57 
     58 static void add_area_gbdk(char * p_words[]) {
     59 
     60     area_item area;
     61 
     62     if ((strtol(p_words[2], NULL, 16) > 0) &&  // Exclude empty areas
     63         !(strstr(p_words[0], "SFR")) &&        // Exclude SFR areas (not actually located at addresses in area listing)
     64         !(strstr(p_words[0], "HRAM"))          // Exclude HRAM area
     65         )
     66     {
     67         snprintf(area.name, sizeof(area.name), "%s", p_words[0]); // [0] Area Name
     68         area.start = strtol(p_words[1], NULL, 16);         // [1] Area Hex Address Start
     69         area.end   = area.start + strtol(p_words[2], NULL, 16) - 1; // Start + [3] Hex Size - 1 = Area End
     70         if (strstr(area.name,"HEADER"))
     71             area.exclusive = false; // HEADER areas almost always overlap, ignore them
     72         else
     73             area.exclusive = option_all_areas_exclusive; // Default is false
     74         banks_check(area);
     75     }
     76 }
     77 
     78 
     79 static void add_area_rgbds(char * p_words[], int current_bank, const char * str_area_name) {
     80 
     81     area_item area;
     82 
     83     snprintf(area.name, sizeof(area.name), "%s", str_area_name);        // Area Name
     84     area.start = strtol(p_words[1], NULL, 16) | (current_bank << 16);   // [1] Area Hex Address Start
     85     area.end   = strtol(p_words[2], NULL, 16) | (current_bank << 16);   // [2] Area Hex Address End
     86     area.exclusive = option_all_areas_exclusive; // Default is false
     87     banks_check(area);
     88 }
     89 
     90 
     91 static int get_bank_num_rgbds(char * p_words[]) {
     92 
     93     return strtol(p_words[2], NULL, 10);
     94 }
     95 
     96 
     97 int map_file_process_areas(char * filename_in) {
     98 
     99     uint32_t cur_bank_rgbds;
    100     char * p_words[MAX_SPLIT_WORDS];
    101     char strline_in[MAX_STR_LEN] = "";
    102     FILE * map_file = fopen(filename_in, "r");
    103 
    104     set_option_input_source(OPT_INPUT_SRC_MAP);
    105 
    106     cur_bank_rgbds = BANK_NUM_UNSET;
    107 
    108     if (map_file) {
    109 
    110         // Read one line at a time into \0 terminated string
    111         while ( fgets(strline_in, sizeof(strline_in), map_file) != NULL) {
    112 
    113             // RGBDS Bank Numbers: Bank lines precede Section lines, use them to set bank num
    114             if (strstr(strline_in, " bank #")) {
    115                 if (str_split(strline_in,p_words," #:\r\n") == RGBDS_BANK_SPLIT_WORDS)
    116                     cur_bank_rgbds = get_bank_num_rgbds(p_words);
    117             }
    118 
    119             // RGBDS Sections: Only parse lines that have Section (Area) summary info
    120             else if (strstr(strline_in, "  SECTION: ") || strstr(strline_in, "\tSECTION: ")) {
    121                 if (cur_bank_rgbds != BANK_NUM_UNSET) {
    122                     // Try to strip quote bracketed name out first
    123                     int name_split_count = str_split(strline_in, p_words,"\"");
    124                     if (name_split_count > 0) {
    125                         // Save section name from array before splitting again (if not blank)
    126                         const char * str_area_name = (name_split_count == RGBDS_SECT_NAME_SPLIT_WORDS) ? p_words[1] : "";
    127                         // Then split up the remaining section info from first string in split array
    128                         if (str_split(p_words[0], p_words," :$()[]\n\t\"") == RGBDS_SECT_INFO_SPLIT_WORDS)
    129                             add_area_rgbds(p_words, cur_bank_rgbds, str_area_name);
    130                     }
    131                 }
    132             }
    133 
    134             // Previous filtering now discontinued, areas with no leading "_" are allowed : GBDK Areas: Only parse lines that start with '_' character (Area summary lines)
    135             // else if (strline_in[0] == '_') {
    136             // }
    137             else if (str_split(strline_in, p_words, " =.") == GBDK_AREA_SPLIT_WORDS) {
    138                 // Require a secondary match on a known column value ("bytes") to filter matches better
    139                 if (strstr(p_words[4], "bytes")) {
    140                     add_area_gbdk(p_words);
    141                 }
    142             }
    143 
    144         } // end: while still lines to process
    145 
    146         fclose(map_file);
    147 
    148     } // end: if valid file
    149     else {
    150         log_error("Error: Failed to open input file %s\n", filename_in);
    151         return false;
    152     }
    153 
    154    return true;
    155 }
    156 

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.