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.