-#include "../platforms/platforms.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] = {
"rom",
"ram",
"register",
+ "ram (no alloc)",
};
const char *config_item_names[CONFITEM_NUM] = {
"keyboard",
"platform",
"setvar",
+ "kbfile",
};
const char *mapcmd_names[MAPCMD_NUM] = {
"file",
"ovl",
"id",
+ "autodump_file",
+ "autodump_mem",
};
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;
}
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;
}
}
}
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;
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;
}
}
-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;
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);
}
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);
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);
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);
+ 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_offset[index] + cfg->map_size[index] - 1, cfg->map_id[index] ? cfg->map_id[index] : "None");
+ 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;
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;
}
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;
}
goto skip_line;
trim_whitespace(parse_line);
-
+
get_next_string(parse_line, cur_cmd, &str_pos, ' ');
switch (get_config_item_type(cur_cmd)) {
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);
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, ' ');
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);
}
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;
}
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(var_name, var_value);
+ 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;
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;
+ 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;
+}