]> git.sesse.net Git - pistorm/blobdiff - config_file/config_file.c
Add Meson build files.
[pistorm] / config_file / config_file.c
index 67a69a5761d780e84f8e31917ce31e324c262e55..f848ba51cd00bfa762ef7abaa59078aa7520cff6 100644 (file)
@@ -1,8 +1,12 @@
+// 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,8 @@ const char *map_type_names[MAPTYPE_NUM] = {
   "rom",
   "ram",
   "register",
+  "ram_noalloc",
+  "wtcram",
 };
 
 const char *config_item_names[CONFITEM_NUM] = {
@@ -34,6 +40,7 @@ const char *config_item_names[CONFITEM_NUM] = {
   "keyboard",
   "platform",
   "setvar",
+  "kbfile",
 };
 
 const char *mapcmd_names[MAPCMD_NUM] = {
@@ -45,6 +52,8 @@ const char *mapcmd_names[MAPCMD_NUM] = {
   "file",
   "ovl",
   "id",
+  "autodump_file",
+  "autodump_mem",
 };
 
 int get_config_item_type(char *cmd) {
@@ -60,12 +69,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;
 }
 
@@ -118,7 +127,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;
         }
       }
@@ -139,7 +148,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;
@@ -147,19 +156,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;
@@ -168,7 +194,7 @@ void get_next_string(char *str, char *str_out, int *strpos, char separator) {
   }
 }
 
-void add_mapping(struct emulator_config *cfg, unsigned int type, unsigned int addr, unsigned int size, int mirr_addr, char *filename, char *map_id) {
+void add_mapping(struct emulator_config *cfg, unsigned int type, unsigned int addr, unsigned int size, int mirr_addr, char *filename, char *map_id, unsigned int autodump) {
   unsigned int index = 0, file_size = 0;
   FILE *in = NULL;
 
@@ -178,7 +204,7 @@ 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;
   }
 
@@ -188,25 +214,60 @@ void add_mapping(struct emulator_config *cfg, unsigned int type, unsigned int ad
   cfg->map_high[index] = addr + size;
   cfg->map_mirror[index] = mirr_addr;
   if (strlen(map_id)) {
+    if (cfg->map_id[index]) {
+      free(cfg->map_id[index]);
+    }
     cfg->map_id[index] = (char *)malloc(strlen(map_id) + 1);
     strcpy(cfg->map_id[index], map_id);
   }
 
   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_WTC:
+      printf("[CFG] Allocating %d bytes for Write-Through Cached RAM mapping (%.1f MB)...\n", size, (float)size / 1024.0f / 1024.0f);
+      goto alloc_mapram;
+      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);
+alloc_mapram:
       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);
+      if (type == MAPTYPE_RAM_WTC) {
+        // This may look a bit weird, but it adds a read range for the WTC RAM. Writes still go through to the mapped read/write functions.
+        m68k_add_rom_range(cfg->map_offset[index], cfg->map_high[index], cfg->map_data[index]);
+      }
       break;
     case MAPTYPE_ROM:
       in = fopen(filename, "rb");
       if (!in) {
-        printf("Failed to open file %s for ROM mapping.\n", filename);
-        goto mapping_failed;
+        if (!autodump) {
+          printf("[CFG] Failed to open file %s for ROM mapping. Using onboard ROM instead, if available.\n", filename);
+          goto mapping_failed;
+        } else if (autodump == MAPCMD_AUTODUMP_FILE) {
+          printf("[CFG] Could not open file %s for ROM mapping. Autodump flag is set, dumping to file.\n", filename);
+          dump_range_to_file(cfg->map_offset[index], cfg->map_size[index], filename);
+          in = fopen(filename, "rb");
+          if (in == NULL) {
+            printf("[CFG] Could not open dumped file for reading. Using onboard ROM instead, if available.\n");
+            goto mapping_failed;
+          }
+        } else if (autodump == MAPCMD_AUTODUMP_MEM) {
+          printf("[CFG] Could not open file %s for ROM mapping. Autodump flag is set, dumping to memory.\n", filename);
+          cfg->map_data[index] = dump_range_to_memory(cfg->map_offset[index], cfg->map_size[index]);
+          cfg->rom_size[index] = cfg->map_size[index];
+          if (cfg->map_data[index] == NULL) {
+            printf("[CFG] Could not dump range to memory. Using onboard ROM instead, if available.\n");
+            goto mapping_failed;
+          }
+          goto skip_file_ops;
+        }
       }
       fseek(in, 0, SEEK_END);
       file_size = (int)ftell(in);
@@ -218,22 +279,24 @@ void add_mapping(struct emulator_config *cfg, unsigned int type, unsigned int ad
       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);
+      if (in)
+        fclose(in);
+skip_file_ops:
+      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 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");
-  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]);
+  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;
 
@@ -243,10 +306,48 @@ 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]) {
+      if (cfg->map_type[i] != MAPTYPE_RAM_NOALLOC) {
+        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;
   }
 
@@ -257,12 +358,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;
   }
 
@@ -286,8 +387,8 @@ struct emulator_config *load_config_file(char *filename) {
         cfg->cpu_type = get_m68k_cpu_type(parse_line + str_pos);
         break;
       case CONFITEM_MAP: {
-        unsigned int maptype = 0, mapsize = 0, mapaddr = 0;
-        int mirraddr = -1;
+        unsigned int maptype = 0, mapsize = 0, mapaddr = 0, autodump = 0;
+        unsigned int mirraddr = ((unsigned int)-1);
         char mapfile[128], mapid[128];
         memset(mapfile, 0x00, 128);
         memset(mapid, 0x00, 128);
@@ -331,18 +432,22 @@ struct emulator_config *load_config_file(char *filename) {
               get_next_string(parse_line, cur_cmd, &str_pos, ' ');
               mirraddr = get_int(cur_cmd);
               break;
+            case MAPCMD_AUTODUMP_FILE:
+            case MAPCMD_AUTODUMP_MEM:
+              autodump = get_map_cmd(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;
           }
         }
-        add_mapping(cfg, maptype, mapaddr, mapsize, mirraddr, mapfile, mapid);
+        add_mapping(cfg, maptype, mapaddr, mapsize, mirraddr, mapfile, mapid, autodump);
 
         break;
       }
       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, ' ');
@@ -350,20 +455,37 @@ 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("Setting platform to %s", platform_name);
+        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);
@@ -373,7 +495,7 @@ struct emulator_config *load_config_file(char *filename) {
       }
       case CONFITEM_SETVAR: {
         if (!cfg->platform) {
-          printf("Warning: esetvar used in config file with no platform specified.\n");
+          printf("[CFG] Warning: setvar used in config file with no platform specified.\n");
           break;
         }
 
@@ -388,11 +510,11 @@ struct emulator_config *load_config_file(char *filename) {
       }
       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;
@@ -432,9 +554,24 @@ 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;
+    else if (address >= cfg->map_offset[i] && address < cfg->map_high[i]) {
+      if (cfg->map_type[i] == MAPTYPE_RAM || cfg->map_type[i] == MAPTYPE_RAM_NOALLOC || cfg->map_type[i] == MAPTYPE_ROM)
+        return i;
+    }
   }
 
   return -1;
 }
+
+uint8_t *get_mapped_data_pointer_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;
+    else if (address >= cfg->map_offset[i] && address < cfg->map_high[i]) {
+      if (cfg->map_type[i] == MAPTYPE_RAM || cfg->map_type[i] == MAPTYPE_RAM_NOALLOC || cfg->map_type[i] == MAPTYPE_ROM)
+        return cfg->map_data[i] + (address - cfg->map_offset[i]);
+    }
+  }
+
+  return NULL;
+}