gbdk-2020 | GameBoy Development Kit |
| download: https://git.y1.nz/archives/gbdk.tar.gz | |
| README | Files | Log | Refs | LICENSE |
gbdk-support/makecom/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 "noi_file.h"
14 #include "bin_to_com.h"
15
16 // Example data to parse from a .noi file:
17 /*
18 DEF s__CODE 0x200
19 DEF l__BASE 0x2A3
20 DEF __shadow_OAM_OFF 0x455
21 DEF .mode 0x456
22 */
23
24 const char * known_section_names[] =
25 {"_CODE","_HOME","_BASE","_CODE_0","_INITIALIZER","_LIT","_GSINIT","_GSFINAL"};
26
27
28 list_type symbol_list;
29 uint32_t overlay_count_addr = SYM_VAL_UNSET;
30 uint32_t overlay_name_addr = SYM_VAL_UNSET;
31
32
33 // Initialize the symbol list
34 void noi_init(void) {
35
36 list_init(&symbol_list, sizeof(symbol_item));
37 }
38
39
40 // Free the symbol list
41 void noi_cleanup(void) {
42
43 list_cleanup(&symbol_list);
44 }
45
46
47 // Find a matching symbol, if none matches a new one is added and returned
48 static int symbollist_get_id_by_name(char * symbol_name) {
49
50 symbol_item * symbols = (symbol_item *)symbol_list.p_array;
51
52 // Check for matching symbol name
53 for(int c = 0;c < symbol_list.count; c++) {
54 // Return matching symbol index if present
55 if (strcmp(symbol_name, symbols[c].name) == 0) {
56 return c;
57 }
58 }
59
60 // no match was found, add symbol
61 symbol_item new_symbol = {.name = "", .addr_start = SYM_VAL_UNSET, .length = SYM_VAL_UNSET, .bank_num = 0x00, .src_rom_addr = SYM_VAL_UNSET};
62 snprintf(new_symbol.name, sizeof(new_symbol.name), "%s", symbol_name);
63 list_additem(&symbol_list, &new_symbol);
64
65 return (symbol_list.count - 1);
66 }
67
68
69 // Add the start address or length for a s_ or l_ symbol record
70 static void noi_symbollist_add(char rec_type, char * name, char * value) {
71
72 // Only add symbols if they're in the known section name list
73 for (int c = 0; c < ARRAY_LEN(known_section_names); c++) {
74
75 if ((strcmp(name, known_section_names[c]) == 0) ||
76 (strncmp(name, "_CODE_", (sizeof("_CODE_") - 1)) == 0)) {
77
78 symbol_item * symbols = (symbol_item *)symbol_list.p_array;
79
80 // Check to see if there is an existing record to update
81 // If one isn't found a new record will have been created automatically
82 int symbol_id = symbollist_get_id_by_name(name);
83 if (symbol_id != ERR_NO_SYMBOLS_LEFT) {
84
85 // Handle whether it's a start-of-address or a length record for the given symbol
86 if (rec_type == NOI_REC_START) {
87 symbols[symbol_id].addr_start = strtol(value, NULL, 16);
88 symbols[symbol_id].bank_num = BANK_GET_NUM(symbols[symbol_id].addr_start);
89 symbols[symbol_id].src_rom_addr = BANK_GET_ROM_ADDR(symbols[symbol_id].addr_start);
90 }
91 else if (rec_type == NOI_REC_LENGTH) {
92 symbols[symbol_id].length = strtol(value, NULL, 16);
93 }
94 }
95
96 return;
97 }
98 }
99 }
100
101
102 // Load symbols from a .noi file and create paired records for start & length entries
103 // Plus, look for and store for overlay symbol information
104 int noi_file_load_symbols(char * filename_in) {
105
106 char cols;
107 char * p_str;
108 char * p_words[MAX_SPLIT_WORDS];
109 char strline_in[MAX_STR_LEN] = "";
110 FILE * noi_file = fopen(filename_in, "r");
111 symbol_item symbol;
112 int symbol_id;
113
114 noi_init();
115
116 if (noi_file) {
117
118 // Read one line at a time into \0 terminated string
119 while ( fgets(strline_in, sizeof(strline_in), noi_file) != NULL) {
120
121 // Require minimum length to match
122 if (strlen(strline_in) >= NOI_REC_START_LEN) {
123
124 // Split string into words separated by spaces
125 cols = 0;
126 p_str = strtok(strline_in," ");
127 while (p_str != NULL)
128 {
129 p_words[cols++] = p_str;
130 // Only split on underscore for the second match
131 p_str = strtok(NULL, " ");
132 if (cols >= MAX_SPLIT_WORDS) break;
133 }
134
135 // [0] = "DEF"
136 // [1] = symbol name
137 // [2] = symbol value
138 if (cols >= NOI_REC_COUNT_MATCH) {
139
140 // If it matches either _s_egment or _l_ength records (first two chars)
141 // then add a record for it with the first two chars truncated
142 if ((strncmp(p_words[1], "l_", NOI_REC_S_L_CHK) == 0) ||
143 (strncmp(p_words[1], "s_", NOI_REC_S_L_CHK) == 0)) {
144 noi_symbollist_add(p_words[1][0], p_words[1] + NOI_REC_S_L_CHK, p_words[2]);
145 }
146 // Otherwise check for records of interest and store them
147 else if (strcmp(p_words[1], "___overlay_count") == 0) {
148 overlay_count_addr = strtol(p_words[2], NULL, 16);
149 }
150 else if (strcmp(p_words[1], "___overlay_name") == 0) {
151 overlay_name_addr = strtol(p_words[2], NULL, 16);
152 }
153 }
154 } // end: valid min chars to process line
155
156 } // end: while still lines to process
157
158 fclose(noi_file);
159
160 } // end: if valid file
161 else return (false);
162
163 return true;
164 }
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.