1 #include "config_file.h"
6 #define M68K_CPU_TYPES M68K_CPU_TYPE_SCC68070
8 const char *cpu_types[M68K_CPU_TYPES] = {
21 const char *map_type_names[MAPTYPE_NUM] = {
28 const char *config_item_names[CONFITEM_NUM] = {
37 const char *mapcmd_names[MAPCMD_NUM] = {
48 int get_config_item_type(char *cmd) {
49 for (int i = 0; i < CONFITEM_NUM; i++) {
50 if (strcmp(cmd, config_item_names[i]) == 0) {
58 unsigned int get_m68k_cpu_type(char *name) {
59 for (int i = 0; i < M68K_CPU_TYPES; i++) {
60 if (strcmp(name, cpu_types[i]) == 0) {
61 printf("Set CPU type to %s.\n", cpu_types[i]);
66 printf ("Invalid CPU type %s specified, defaulting to 68000.\n", name);
67 return M68K_CPU_TYPE_68000;
70 unsigned int get_map_cmd(char *name) {
71 for (int i = 1; i < MAPCMD_NUM; i++) {
72 if (strcmp(name, mapcmd_names[i]) == 0) {
77 return MAPCMD_UNKNOWN;
80 unsigned int get_map_type(char *name) {
81 for (int i = 1; i < MAPTYPE_NUM; i++) {
82 if (strcmp(name, map_type_names[i]) == 0) {
90 void trim_whitespace(char *str) {
91 while (strlen(str) != 0 && (str[strlen(str) - 1] == ' ' || str[strlen(str) - 1] == '\t' || str[strlen(str) - 1] == 0x0A || str[strlen(str) - 1] == 0x0D)) {
92 str[strlen(str) - 1] = '\0';
96 unsigned int get_int(char *str) {
102 if (strlen(str) > 2 && str[0] == '0' && str[1] == 'x') {
103 for (int i = 2; i < (int)strlen(str); i++) {
104 if (str[i] >= '0' && str[i] <= '9') {
105 ret_int = (str[i] - '0') | (ret_int << 4);
109 case 'A': ret_int = 0xA | (ret_int << 4); break;
110 case 'B': ret_int = 0xB | (ret_int << 4); break;
111 case 'C': ret_int = 0xC | (ret_int << 4); break;
112 case 'D': ret_int = 0xD | (ret_int << 4); break;
113 case 'E': ret_int = 0xE | (ret_int << 4); break;
114 case 'F': ret_int = 0xF | (ret_int << 4); break;
115 case 'K': ret_int = ret_int * SIZE_KILO; break;
116 case 'M': ret_int = ret_int * SIZE_MEGA; break;
117 case 'G': ret_int = ret_int * SIZE_GIGA; break;
119 printf("Unknown character %c in hex value.\n", str[i]);
128 if (str[strlen(str) - 1] == 'K')
129 ret_int = ret_int * SIZE_KILO;
130 else if (str[strlen(str) - 1] == 'M')
131 ret_int = ret_int * SIZE_MEGA;
132 else if (str[strlen(str) - 1] == 'G')
133 ret_int = ret_int * SIZE_GIGA;
139 void get_next_string(char *str, char *str_out, int *strpos, char separator) {
140 int str_pos = 0, out_pos = 0;
148 while (str[str_pos] == ' ' && str[str_pos] == '\t' && str_pos < (int)strlen(str)) {
152 for (int i = str_pos; i < (int)strlen(str); i++) {
153 str_out[out_pos] = str[i];
154 if ((separator == ' ' && (str[i] == ' ' || str[i] == '\t')) || str[i] == separator) {
155 str_out[out_pos] = '\0';
162 if (i + 1 == (int)strlen(str) && strpos) {
164 str_out[out_pos] = '\0';
169 void add_mapping(struct emulator_config *cfg, unsigned int type, unsigned int addr, unsigned int size, int mirr_addr, char *filename, char *map_id) {
170 unsigned int index = 0, file_size = 0;
173 while (index < MAX_NUM_MAPPED_ITEMS) {
174 if (cfg->map_type[index] == MAPTYPE_NONE)
178 if (index == MAX_NUM_MAPPED_ITEMS) {
179 printf("Unable to map item, only %d items can be mapped with current binary.\n", MAX_NUM_MAPPED_ITEMS);
183 cfg->map_type[index] = type;
184 cfg->map_offset[index] = addr;
185 cfg->map_size[index] = size;
186 cfg->map_mirror[index] = mirr_addr;
187 if (strlen(map_id)) {
188 cfg->map_id[index] = (char *)malloc(strlen(map_id) + 1);
189 strcpy(cfg->map_id[index], map_id);
194 printf("Allocating %d bytes for RAM mapping (%d MB)...\n", size, size / 1024 / 1024);
195 cfg->map_data[index] = (unsigned char *)malloc(size);
196 if (!cfg->map_data[index]) {
197 printf("ERROR: Unable to allocate memory for mapped RAM!\n");
200 memset(cfg->map_data[index], 0x00, size);
203 in = fopen(filename, "rb");
205 printf("Failed to open file %s for ROM mapping.\n", filename);
208 fseek(in, 0, SEEK_END);
209 file_size = (int)ftell(in);
211 cfg->map_size[index] = file_size;
213 fseek(in, 0, SEEK_SET);
214 cfg->map_data[index] = (unsigned char *)calloc(1, cfg->map_size[index]);
215 cfg->rom_size[index] = (cfg->map_size[index] <= file_size) ? cfg->map_size[index] : file_size;
216 if (!cfg->map_data[index]) {
217 printf("ERROR: Unable to allocate memory for mapped ROM!\n");
220 memset(cfg->map_data[index], 0x00, cfg->map_size[index]);
221 fread(cfg->map_data[index], cfg->rom_size[index], 1, in);
224 case MAPTYPE_REGISTER:
230 printf("[MAP %d] Added %s mapping for range %.8lX-%.8lX (%lX)\n", index, map_type_names[type], cfg->map_offset[index], cfg->map_offset[index] + cfg->map_size[index] - 1, (uint64_t)cfg->map_data[index]);
235 cfg->map_type[index] = MAPTYPE_NONE;
240 struct emulator_config *load_config_file(char *filename) {
241 FILE *in = fopen(filename, "rb");
243 printf("Failed to open config file %s for reading.\n", filename);
247 char *parse_line = NULL;
249 struct emulator_config *cfg = NULL;
252 parse_line = (char *)calloc(1, 512);
254 printf("Failed to allocate memory for config file line buffer.\n");
257 cfg = (struct emulator_config *)calloc(1, sizeof(struct emulator_config));
259 printf("Failed to allocate memory for temporary emulator config.\n");
263 memset(cfg, 0x00, sizeof(struct emulator_config));
264 cfg->cpu_type = M68K_CPU_TYPE_68000;
268 memset(parse_line, 0x00, 512);
269 fgets(parse_line, 512, in);
271 if (strlen(parse_line) <= 2 || parse_line[0] == '#' || parse_line[0] == '/')
274 trim_whitespace(parse_line);
276 get_next_string(parse_line, cur_cmd, &str_pos, ' ');
278 switch (get_config_item_type(cur_cmd)) {
279 case CONFITEM_CPUTYPE:
280 cfg->cpu_type = get_m68k_cpu_type(parse_line + str_pos);
283 unsigned int maptype = 0, mapsize = 0, mapaddr = 0;
285 char mapfile[128], mapid[128];
286 memset(mapfile, 0x00, 128);
287 memset(mapid, 0x00, 128);
289 while (str_pos < (int)strlen(parse_line)) {
290 get_next_string(parse_line, cur_cmd, &str_pos, '=');
291 switch(get_map_cmd(cur_cmd)) {
293 get_next_string(parse_line, cur_cmd, &str_pos, ' ');
294 maptype = get_map_type(cur_cmd);
295 //printf("Type! %s\n", map_type_names[maptype]);
298 get_next_string(parse_line, cur_cmd, &str_pos, ' ');
299 mapaddr = get_int(cur_cmd);
300 //printf("Address! %.8X\n", mapaddr);
303 get_next_string(parse_line, cur_cmd, &str_pos, ' ');
304 mapsize = get_int(cur_cmd);
305 //printf("Size! %.8X\n", mapsize);
308 get_next_string(parse_line, cur_cmd, &str_pos, '-');
309 mapaddr = get_int(cur_cmd);
310 get_next_string(parse_line, cur_cmd, &str_pos, ' ');
311 mapsize = get_int(cur_cmd) - 1 - mapaddr;
312 //printf("Range! %d-%d\n", mapaddr, mapaddr + mapsize);
314 case MAPCMD_FILENAME:
315 get_next_string(parse_line, cur_cmd, &str_pos, ' ');
316 strcpy(mapfile, cur_cmd);
317 //printf("File! %s\n", mapfile);
320 get_next_string(parse_line, cur_cmd, &str_pos, ' ');
321 strcpy(mapid, cur_cmd);
322 //printf("File! %s\n", mapfile);
324 case MAPCMD_OVL_REMAP:
325 get_next_string(parse_line, cur_cmd, &str_pos, ' ');
326 mirraddr = get_int(cur_cmd);
329 printf("Unknown/unhandled map argument %s on line %d.\n", cur_cmd, cur_line);
333 add_mapping(cfg, maptype, mapaddr, mapsize, mirraddr, mapfile, mapid);
337 case CONFITEM_LOOPCYCLES:
338 cfg->loop_cycles = get_int(parse_line + str_pos);
339 printf("Set CPU loop cycles to %d.\n", cfg->loop_cycles);
342 get_next_string(parse_line, cur_cmd, &str_pos, ' ');
343 cfg->mouse_file = (char *)calloc(1, strlen(cur_cmd) + 1);
344 strcpy(cfg->mouse_file, cur_cmd);
345 get_next_string(parse_line, cur_cmd, &str_pos, ' ');
346 cfg->mouse_toggle_key = cur_cmd[0];
347 cfg->mouse_enabled = 1;
348 printf("Enabled mouse event forwarding from file %s, toggle key %c.\n", cfg->mouse_file, cfg->mouse_toggle_key);
350 case CONFITEM_KEYBOARD:
351 get_next_string(parse_line, cur_cmd, &str_pos, ' ');
352 cfg->keyboard_toggle_key = cur_cmd[0];
353 printf("Enabled keyboard event forwarding, toggle key %c.\n", cfg->keyboard_toggle_key);
357 printf("Unknown config item %s on line %d.\n", cur_cmd, cur_line);
364 goto load_successful;
368 for (int i = 0; i < MAX_NUM_MAPPED_ITEMS; i++) {
369 if (cfg->map_data[i])
370 free(cfg->map_data[i]);
371 cfg->map_data[i] = NULL;