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.