]> git.sesse.net Git - pistorm/blobdiff - config_file/config_file.c
Merge pull request #29 from LinuxJedi/byte-swap
[pistorm] / config_file / config_file.c
index 31e06b41e50c733e62aa2efeb5c8e8445c68bd32..0b5d86a215eed8ddc536d08f49109c559f35cb37 100644 (file)
@@ -1,8 +1,12 @@
-#include "config_file.h"
+// SPDX-License-Identifier: MIT
+
+#include "platforms/platforms.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
+#include "rominfo.h"
+
 #define M68K_CPU_TYPES M68K_CPU_TYPE_SCC68070
 
 const char *cpu_types[M68K_CPU_TYPES] = {
@@ -23,6 +27,7 @@ const char *map_type_names[MAPTYPE_NUM] = {
   "rom",
   "ram",
   "register",
+  "ram (no alloc)",
 };
 
 const char *config_item_names[CONFITEM_NUM] = {
@@ -32,6 +37,9 @@ const char *config_item_names[CONFITEM_NUM] = {
   "loopcycles",
   "mouse",
   "keyboard",
+  "platform",
+  "setvar",
+  "kbfile",
 };
 
 const char *mapcmd_names[MAPCMD_NUM] = {
@@ -58,12 +66,12 @@ int get_config_item_type(char *cmd) {
 unsigned int get_m68k_cpu_type(char *name) {
   for (int i = 0; i < M68K_CPU_TYPES; i++) {
     if (strcmp(name, cpu_types[i]) == 0) {
-      printf("Set CPU type to %s.\n", cpu_types[i]);
+      printf("[CFG] Set CPU type to %s.\n", cpu_types[i]);
       return i + 1;
     }
   }
 
-  printf ("Invalid CPU type %s specified, defaulting to 68000.\n", name);
+  printf("[CFG] Invalid CPU type %s specified, defaulting to 68000.\n", name);
   return M68K_CPU_TYPE_68000;
 }
 
@@ -116,7 +124,7 @@ unsigned int get_int(char *str) {
           case 'M': ret_int = ret_int * SIZE_MEGA; break;
           case 'G': ret_int = ret_int * SIZE_GIGA; break;
           default:
-            printf("Unknown character %c in hex value.\n", str[i]);
+            printf("[CFG] Unknown character %c in hex value.\n", str[i]);
             break;
         }
       }
@@ -137,7 +145,7 @@ unsigned int get_int(char *str) {
 }
 
 void get_next_string(char *str, char *str_out, int *strpos, char separator) {
-  int str_pos = 0, out_pos = 0;
+  int str_pos = 0, out_pos = 0, startquote = 0, endstring = 0;
 
   if (!str_out)
     return;
@@ -145,19 +153,36 @@ void get_next_string(char *str, char *str_out, int *strpos, char separator) {
   if (strpos)
     str_pos = *strpos;
 
-  while (str[str_pos] == ' ' && str[str_pos] == '\t' && str_pos < (int)strlen(str)) {
+  while ((str[str_pos] == ' ' || str[str_pos] == '\t') && str_pos < (int)strlen(str)) {
     str_pos++;
   }
 
+  if (str[str_pos] == '\"') {
+    str_pos++;
+    startquote = 1;
+  }
+
+
   for (int i = str_pos; i < (int)strlen(str); i++) {
     str_out[out_pos] = str[i];
-    if ((separator == ' ' && (str[i] == ' ' || str[i] == '\t')) || str[i] == separator) {
+
+    if (startquote) {
+      if (str[i] == '\"')
+        endstring = 1;
+    } else {
+      if ((separator == ' ' && (str[i] == ' ' || str[i] == '\t')) || str[i] == separator) {
+        endstring = 1;
+      }
+    }
+
+    if (endstring) {
       str_out[out_pos] = '\0';
       if (strpos) {
         *strpos = i + 1;
       }
       break;
     }
+
     out_pos++;
     if (i + 1 == (int)strlen(str) && strpos) {
       *strpos = i + 1;
@@ -176,13 +201,14 @@ void add_mapping(struct emulator_config *cfg, unsigned int type, unsigned int ad
     index++;
   }
   if (index == MAX_NUM_MAPPED_ITEMS) {
-    printf("Unable to map item, only %d items can be mapped with current binary.\n", MAX_NUM_MAPPED_ITEMS);
+    printf("[CFG] Unable to map item, only %d items can be mapped with current binary.\n", MAX_NUM_MAPPED_ITEMS);
     return;
   }
 
   cfg->map_type[index] = type;
   cfg->map_offset[index] = addr;
   cfg->map_size[index] = size;
+  cfg->map_high[index] = addr + size;
   cfg->map_mirror[index] = mirr_addr;
   if (strlen(map_id)) {
     cfg->map_id[index] = (char *)malloc(strlen(map_id) + 1);
@@ -190,11 +216,15 @@ void add_mapping(struct emulator_config *cfg, unsigned int type, unsigned int ad
   }
 
   switch(type) {
+    case MAPTYPE_RAM_NOALLOC:
+      printf("[CFG] Adding %d byte (%d MB) RAM mapping %s...\n", size, size / 1024 / 1024, map_id);
+      cfg->map_data[index] = (unsigned char *)filename;
+      break;
     case MAPTYPE_RAM:
-      printf("Allocating %d bytes for RAM mapping (%d MB)...\n", size, size / 1024 / 1024);
+      printf("[CFG] Allocating %d bytes for RAM mapping (%d MB)...\n", size, size / 1024 / 1024);
       cfg->map_data[index] = (unsigned char *)malloc(size);
       if (!cfg->map_data[index]) {
-        printf("ERROR: Unable to allocate memory for mapped RAM!\n");
+        printf("[CFG] ERROR: Unable to allocate memory for mapped RAM!\n");
         goto mapping_failed;
       }
       memset(cfg->map_data[index], 0x00, size);
@@ -202,32 +232,35 @@ void add_mapping(struct emulator_config *cfg, unsigned int type, unsigned int ad
     case MAPTYPE_ROM:
       in = fopen(filename, "rb");
       if (!in) {
-        printf("Failed to open file %s for ROM mapping.\n", filename);
+        printf("[CFG] Failed to open file %s for ROM mapping. Using onboard ROM instead, if available.\n", filename);
         goto mapping_failed;
       }
       fseek(in, 0, SEEK_END);
       file_size = (int)ftell(in);
       if (size == 0) {
         cfg->map_size[index] = file_size;
+        cfg->map_high[index] = addr + cfg->map_size[index];
       }
       fseek(in, 0, SEEK_SET);
       cfg->map_data[index] = (unsigned char *)calloc(1, cfg->map_size[index]);
       cfg->rom_size[index] = (cfg->map_size[index] <= file_size) ? cfg->map_size[index] : file_size;
       if (!cfg->map_data[index]) {
-        printf("ERROR: Unable to allocate memory for mapped ROM!\n");
+        printf("[CFG] ERROR: Unable to allocate memory for mapped ROM!\n");
         goto mapping_failed;
       }
       memset(cfg->map_data[index], 0x00, cfg->map_size[index]);
       fread(cfg->map_data[index], cfg->rom_size[index], 1, in);
       fclose(in);
+      displayRomInfo(cfg->map_data[index], cfg->rom_size[index]);
+      if (cfg->map_size[index] == cfg->rom_size[index])
+        m68k_add_rom_range(cfg->map_offset[index], cfg->map_high[index], cfg->map_data[index]);
       break;
     case MAPTYPE_REGISTER:
     default:
       break;
-      break;
   }
 
-  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]);
+  printf("[CFG] [MAP %d] Added %s mapping for range %.8lX-%.8lX ID: %s\n", index, map_type_names[type], cfg->map_offset[index], cfg->map_high[index] - 1, cfg->map_id[index] ? cfg->map_id[index] : "None");
 
   return;
 
@@ -237,10 +270,45 @@ void add_mapping(struct emulator_config *cfg, unsigned int type, unsigned int ad
     fclose(in);
 }
 
+void free_config_file(struct emulator_config *cfg) {
+  if (!cfg) {
+    printf("[CFG] Tried to free NULL config, aborting.\n");
+  }
+
+  if (cfg->platform) {
+    cfg->platform->shutdown(cfg);
+    free(cfg->platform);
+    cfg->platform = NULL;
+  }
+
+  for (int i = 0; i < MAX_NUM_MAPPED_ITEMS; i++) {
+    if (cfg->map_data[i]) {
+      free(cfg->map_data[i]);
+      cfg->map_data[i] = NULL;
+    }
+    if (cfg->map_id[i]) {
+      free(cfg->map_id[i]);
+      cfg->map_id[i] = NULL;
+    }
+  }
+  if (cfg->mouse_file) {
+    free(cfg->mouse_file);
+    cfg->mouse_file = NULL;
+  }
+  if (cfg->keyboard_file) {
+    free(cfg->keyboard_file);
+    cfg->keyboard_file = NULL;
+  }
+
+  m68k_clear_ranges();
+
+  printf("[CFG] Config file freed. Maybe.\n");
+}
+
 struct emulator_config *load_config_file(char *filename) {
   FILE *in = fopen(filename, "rb");
   if (in == NULL) {
-    printf("Failed to open config file %s for reading.\n", filename);
+    printf("[CFG] Failed to open config file %s for reading.\n", filename);
     return NULL;
   }
 
@@ -251,12 +319,12 @@ struct emulator_config *load_config_file(char *filename) {
 
   parse_line = (char *)calloc(1, 512);
   if (!parse_line) {
-    printf("Failed to allocate memory for config file line buffer.\n");
+    printf("[CFG] Failed to allocate memory for config file line buffer.\n");
     return NULL;
   }
   cfg = (struct emulator_config *)calloc(1, sizeof(struct emulator_config));
   if (!cfg) {
-    printf("Failed to allocate memory for temporary emulator config.\n");
+    printf("[CFG] Failed to allocate memory for temporary emulator config.\n");
     goto load_failed;
   }
 
@@ -272,7 +340,7 @@ struct emulator_config *load_config_file(char *filename) {
       goto skip_line;
 
     trim_whitespace(parse_line);
-    
+
     get_next_string(parse_line, cur_cmd, &str_pos, ' ');
 
     switch (get_config_item_type(cur_cmd)) {
@@ -281,7 +349,7 @@ struct emulator_config *load_config_file(char *filename) {
         break;
       case CONFITEM_MAP: {
         unsigned int maptype = 0, mapsize = 0, mapaddr = 0;
-        int mirraddr = -1;
+        unsigned int mirraddr = ((unsigned int)-1);
         char mapfile[128], mapid[128];
         memset(mapfile, 0x00, 128);
         memset(mapid, 0x00, 128);
@@ -326,7 +394,7 @@ struct emulator_config *load_config_file(char *filename) {
               mirraddr = get_int(cur_cmd);
               break;
             default:
-              printf("Unknown/unhandled map argument %s on line %d.\n", cur_cmd, cur_line);
+              printf("[CFG] Unknown/unhandled map argument %s on line %d.\n", cur_cmd, cur_line);
               break;
           }
         }
@@ -336,7 +404,7 @@ struct emulator_config *load_config_file(char *filename) {
       }
       case CONFITEM_LOOPCYCLES:
         cfg->loop_cycles = get_int(parse_line + str_pos);
-        printf("Set CPU loop cycles to %d.\n", cfg->loop_cycles);
+        printf("[CFG] Set CPU loop cycles to %d.\n", cfg->loop_cycles);
         break;
       case CONFITEM_MOUSE:
         get_next_string(parse_line, cur_cmd, &str_pos, ' ');
@@ -344,21 +412,66 @@ struct emulator_config *load_config_file(char *filename) {
         strcpy(cfg->mouse_file, cur_cmd);
         get_next_string(parse_line, cur_cmd, &str_pos, ' ');
         cfg->mouse_toggle_key = cur_cmd[0];
+        get_next_string(parse_line, cur_cmd, &str_pos, ' ');
+        cfg->mouse_autoconnect = (strcmp(cur_cmd, "autoconnect") == 0) ? 1 : 0;
         cfg->mouse_enabled = 1;
-        printf("Enabled mouse event forwarding from file %s, toggle key %c.\n", cfg->mouse_file, cfg->mouse_toggle_key);
+        printf("[CFG] Enabled mouse event forwarding from file %s, toggle key %c.\n", cfg->mouse_file, cfg->mouse_toggle_key);
         break;
       case CONFITEM_KEYBOARD:
         get_next_string(parse_line, cur_cmd, &str_pos, ' ');
         cfg->keyboard_toggle_key = cur_cmd[0];
-        printf("Enabled keyboard event forwarding, toggle key %c.\n", cfg->keyboard_toggle_key);
+        get_next_string(parse_line, cur_cmd, &str_pos, ' ');
+        cfg->keyboard_grab = (strcmp(cur_cmd, "grab") == 0) ? 1 : 0;
+        get_next_string(parse_line, cur_cmd, &str_pos, ' ');
+        cfg->keyboard_autoconnect = (strcmp(cur_cmd, "autoconnect") == 0) ? 1 : 0;
+        printf("[CFG] Enabled keyboard event forwarding, toggle key %c", cfg->keyboard_toggle_key);
+        if (cfg->keyboard_grab)
+          printf(", locking from host when connected");
+        if (cfg->keyboard_autoconnect)
+          printf(", connected to guest at startup");
+        printf(".\n");
+        break;
+      case CONFITEM_KBFILE:
+        get_next_string(parse_line, cur_cmd, &str_pos, ' ');
+        cfg->keyboard_file = (char *)calloc(1, strlen(cur_cmd) + 1);
+        strcpy(cfg->keyboard_file, cur_cmd);
+        printf("[CFG] Set keyboard event source file to %s.\n", cfg->keyboard_file);
         break;
+      case CONFITEM_PLATFORM: {
+        char platform_name[128], platform_sub[128];
+        memset(platform_name, 0x00, 128);
+        memset(platform_sub, 0x00, 128);
+        get_next_string(parse_line, platform_name, &str_pos, ' ');
+        printf("[CFG] Setting platform to %s", platform_name);
+        get_next_string(parse_line, platform_sub, &str_pos, ' ');
+        if (strlen(platform_sub))
+          printf(" (sub: %s)", platform_sub);
+        printf("\n");
+        cfg->platform = make_platform_config(platform_name, platform_sub);
+        break;
+      }
+      case CONFITEM_SETVAR: {
+        if (!cfg->platform) {
+          printf("[CFG] Warning: setvar used in config file with no platform specified.\n");
+          break;
+        }
+
+        char var_name[128], var_value[128];
+        memset(var_name, 0x00, 128);
+        memset(var_value, 0x00, 128);
+        get_next_string(parse_line, var_name, &str_pos, ' ');
+        get_next_string(parse_line, var_value, &str_pos, ' ');
+        cfg->platform->setvar(cfg, var_name, var_value);
+
+        break;
+      }
       case CONFITEM_NONE:
       default:
-        printf("Unknown config item %s on line %d.\n", cur_cmd, cur_line);
+        printf("[CFG] Unknown config item %s on line %d.\n", cur_cmd, cur_line);
         break;
     }
-    
-    skip_line:;
+
+  skip_line:
     cur_line++;
   }
   goto load_successful;
@@ -379,3 +492,28 @@ struct emulator_config *load_config_file(char *filename) {
 
   return cfg;
 }
+
+int get_named_mapped_item(struct emulator_config *cfg, char *name) {
+  if (strlen(name) == 0)
+    return -1;
+
+  for (int i = 0; i < MAX_NUM_MAPPED_ITEMS; i++) {
+    if (cfg->map_type[i] == MAPTYPE_NONE || !cfg->map_id[i])
+      continue;
+    if (strcmp(name, cfg->map_id[i]) == 0)
+      return i;
+  }
+
+  return -1;
+}
+
+int get_mapped_item_by_address(struct emulator_config *cfg, uint32_t address) {
+  for (int i = 0; i < MAX_NUM_MAPPED_ITEMS; i++) {
+    if (cfg->map_type[i] == MAPTYPE_NONE || !cfg->map_data[i])
+      continue;
+    if (address >= cfg->map_offset[i] && address < cfg->map_high[i])
+      return i;
+  }
+
+  return -1;
+}