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/noi_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 "list.h"
     15 #include "banks.h"
     16 #include "noi_file.h"
     17 
     18 
     19 list_type area_list;
     20 
     21 // Initialize the symbol list
     22 void noi_init(void) {
     23 
     24     list_init(&area_list, sizeof(area_item));
     25 }
     26 
     27 
     28 // Free the symbol list
     29 void noi_cleanup(void) {
     30 
     31     list_cleanup(&area_list);
     32 }
     33 
     34 // Example data to parse from a .map file (excluding unwanted lines):
     35 /*
     36 DEF l__BSS 0x41
     37 DEF l__HEADERe 0x75
     38 DEF l__HOME 0xED
     39 DEF l__GSINIT 0x1F9
     40 DEF s__CODE 0x200
     41 DEF l__BASE 0x2A3
     42 DEF l__DATA 0x1F20
     43 DEF l__CODE 0x6A62
     44 DEF s__HOME 0x6C62
     45 DEF s__BASE 0x6D4F
     46 */
     47 
     48 
     49 
     50 // Find a matching area, if none matches a new one is added and returned
     51 static int arealist_get_id_by_name(char * area_name) {
     52 
     53     area_item * areas = (area_item *)area_list.p_array;
     54     area_item new_area;
     55     int c;
     56 
     57     // Check for matching area name
     58     for(c=0;c < area_list.count; c++) {
     59         // Return matching area index if present
     60         if (strncmp(area_name, areas[c].name, AREA_MAX_STR) == 0) {
     61             return c;
     62         }
     63     }
     64 
     65     // no match was found, add area
     66     snprintf(new_area.name, sizeof(new_area.name), "%s", area_name);
     67     new_area.start  = AREA_VAL_UNSET;
     68     new_area.end    = AREA_VAL_UNSET;
     69     new_area.length = AREA_VAL_UNSET;
     70     if (strstr(area_name,"HEADER"))
     71         new_area.exclusive = false; // HEADER areas almost always overlap, ignore them
     72     else
     73         new_area.exclusive = option_all_areas_exclusive; // Default is false
     74     
     75     list_additem(&area_list, &new_area);
     76 
     77     return (area_list.count - 1);
     78 }
     79 
     80 
     81 // Process list of areas and add them to banks
     82 static void noi_arealist_add_all_to_banks() {
     83 
     84     area_item * areas = (area_item *)area_list.p_array;
     85     int c;
     86 
     87     // Only process completed areas (start and length both set)
     88     for(c=0;c < area_list.count; c++) {
     89 
     90         if ((areas[c].start != AREA_VAL_UNSET) &&
     91             (areas[c].length != AREA_VAL_UNSET)) {
     92             areas[c].end = areas[c].start + areas[c].length - 1;
     93             banks_check(areas[c]);
     94         }
     95     }
     96 }
     97 
     98 
     99 static void noi_arealist_add(char * rec_type, char * name, char * value) {
    100 
    101     area_item * areas = (area_item *)area_list.p_array;
    102 
    103     int area_id = arealist_get_id_by_name(name); // [2] Area Name1
    104     if (area_id != ERR_NO_AREAS_LEFT) {
    105 
    106         // Handle whether it's a start-of-address or a length record for the given area
    107         if (rec_type[0] == NOI_REC_START)
    108             areas[area_id].start = strtol(value, NULL, 16); // [2] Area Hex Address Start
    109         else if (rec_type[0] == NOI_REC_LENGTH) {
    110             // Don't add lengths of zero
    111             if (strtol(value, NULL, 16) > 0)
    112                 areas[area_id].length = strtol(value, NULL, 16); // [2] Area Hex Length
    113         }
    114     }
    115 
    116 }
    117 
    118 
    119 int noi_file_process_areas(char * filename_in) {
    120 
    121     int  cols;
    122     char * p_str;
    123     char * p_words[MAX_SPLIT_WORDS];
    124     char strline_in[MAX_STR_LEN] = "";
    125     FILE * noi_file = fopen(filename_in, "r");
    126     area_item area;
    127     int area_id;
    128 
    129     set_option_input_source(OPT_INPUT_SRC_NOI);
    130 
    131     if (noi_file) {
    132 
    133         // Read one line at a time into \0 terminated string
    134         while ( fgets(strline_in, sizeof(strline_in), noi_file) != NULL) {
    135 
    136             // Require minimum length to match
    137             if (strlen(strline_in) >= strlen("DEF l_")) {
    138 
    139                 // Match either _S_egment or _L_ength records
    140                 if ( (strncmp(strline_in, "DEF l_", strlen("DEF l_") ) == 0) ||
    141                      (strncmp(strline_in, "DEF s_", strlen("DEF s_") ) == 0)) {
    142 
    143                     // Split string into words separated by spaces
    144                     cols = 0;
    145                     p_str = strtok(strline_in," _");
    146                     while (p_str != NULL)
    147                     {
    148                         p_words[cols++] = p_str;
    149                         // Only split on underscore for the second match
    150                         if (cols == 1)
    151                             p_str = strtok(NULL, " _");
    152                         else
    153                             p_str = strtok(NULL, " ");
    154                         if (cols >= MAX_SPLIT_WORDS) break;
    155                     }
    156 
    157                     if (cols == NOI_REC_COUNT_MATCH) {
    158                         if ( !(strstr(p_words[2], "SFR")) &&        // Exclude SFR areas (not actually located at addresses in area listing)
    159                              !(strstr(p_words[2], "HRAM")) ) {      // Exclude HRAM area  // TODO: remove the HRAM discard? (now that there is an HRAM section)
    160 
    161                             noi_arealist_add(p_words[1], p_words[2], p_words[3]);
    162                         }
    163                     }
    164                 } // end: if valid start of line
    165             } // end: valid min chars to process line
    166 
    167         } // end: while still lines to process
    168 
    169         fclose(noi_file);
    170 
    171         // Process all the areas
    172         noi_arealist_add_all_to_banks();
    173 
    174     } // end: if valid file
    175     else {
    176         log_error("Error: Failed to open input file %s\n", filename_in);
    177         return false;
    178     }
    179 
    180    return true;
    181 }

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