diff blastem.c @ 1140:4490c9c12272

Detect system type from filename if header based methods fail. Allow overriding system type from command line.
author Michael Pavone <pavone@retrodev.com>
date Mon, 02 Jan 2017 21:46:26 -0800
parents 093c19f34dfd
children 21df13266e6a
line wrap: on
line diff
--- a/blastem.c	Mon Jan 02 16:33:03 2017 -0800
+++ b/blastem.c	Mon Jan 02 21:46:26 2017 -0800
@@ -49,7 +49,7 @@
 #define SMD_MAGIC3 0xBB
 #define SMD_BLOCK_SIZE 0x4000
 
-int load_smd_rom(long filesize, FILE * f, uint16_t **buffer)
+int load_smd_rom(long filesize, FILE * f, void **buffer)
 {
 	uint8_t block[SMD_BLOCK_SIZE];
 	filesize -= SMD_HEADER_SIZE;
@@ -67,7 +67,7 @@
 	return rom_size;
 }
 
-int load_rom(char * filename, uint16_t **dst, system_type *stype)
+uint32_t load_rom(char * filename, void **dst, system_type *stype)
 {
 	uint8_t header[10];
 	FILE * f = fopen(filename, "rb");
@@ -102,9 +102,6 @@
 		fatal_error("Error reading from %s\n", filename);
 	}
 	fclose(f);
-	if (stype) {
-		*stype = detect_system_type((uint8_t *)*dst, filesize);
-	}
 	return filesize;
 }
 
@@ -177,12 +174,11 @@
 	int debug = 0;
 	uint32_t opts = 0;
 	int loaded = 0;
-	system_type stype;
+	system_type stype = SYSTEM_UNKNOWN, force_stype = SYSTEM_UNKNOWN;
 	uint8_t force_region = 0;
 	char * romfname = NULL;
 	char * statefile = NULL;
-	int rom_size, lock_on_size;
-	uint16_t *cart = NULL, *lock_on = NULL;
+	system_media cart = {.chain = NULL}, lock_on;
 	debugger_type dtype = DEBUGGER_NATIVE;
 	uint8_t start_in_debugger = 0;
 	uint8_t fullscreen = FULLSCREEN_DEFAULT, use_gl = 1;
@@ -235,6 +231,21 @@
 					fatal_error("'%c' is not a valid region character for the -r option\n", argv[i][0]);
 				}
 				break;
+			case 'm':
+				i++;
+				if (i >= argc) {
+					fatal_error("-r must be followed by a machine type (sms, gen or jag)\n");
+				}
+				if (!strcmp("sms", argv[i])) {
+					stype = force_stype = SYSTEM_SMS;
+				} else if (!strcmp("gen", argv[i])) {
+					stype = force_stype = SYSTEM_GENESIS;
+				} else if (!strcmp("jag", argv[i])) {
+					stype = force_stype = SYSTEM_JAGUAR;
+				} else {
+					fatal_error("Unrecognized machine type %s\n", argv[i]);
+				}
+				break;
 			case 's':
 				i++;
 				if (i >= argc) {
@@ -253,10 +264,12 @@
 				if (i >= argc) {
 					fatal_error("-o must be followed by a lock on cartridge filename\n");
 				}
-				lock_on_size = load_rom(argv[i], &lock_on, NULL);
-				if (!lock_on_size) {
+				lock_on.size = load_rom(argv[i], &lock_on.buffer, NULL);
+				if (!lock_on.size) {
 					fatal_error("Failed to load lock on cartridge %s\n", argv[i]);
 				}
+				lock_on.extension = path_extension(argv[i]);
+				cart.chain = &lock_on;
 				break;
 			}
 			case 'h':
@@ -265,6 +278,10 @@
 					"Options:\n"
 					"	-h          Print this help text\n"
 					"	-r (J|U|E)  Force region to Japan, US or Europe respectively\n"
+					"   -m MACHINE  Force emulated machine type to MACHINE. Valid values are:\n"
+					"                   sms - Sega Master System/Mark III\n"
+					"                   gen - Sega Genesis/Megadrive\n"
+					"                   jag - Atari Jaguar\n"
 					"	-f          Toggles fullscreen mode\n"
 					"	-g          Disable OpenGL rendering\n"
 					"	-s FILE     Load a GST format savestate from FILE\n"
@@ -280,9 +297,10 @@
 				fatal_error("Unrecognized switch %s\n", argv[i]);
 			}
 		} else if (!loaded) {
-			if (!(rom_size = load_rom(argv[i], &cart, &stype))) {
+			if (!(cart.size = load_rom(argv[i], &cart.buffer, stype == SYSTEM_UNKNOWN ? &stype : NULL))) {
 				fatal_error("Failed to open %s for reading\n", argv[i]);
 			}
+			cart.extension = path_extension(argv[i]);
 			romfname = argv[i];
 			loaded = 1;
 		} else if (width < 0) {
@@ -299,21 +317,23 @@
 			romfname = "menu.bin";
 		}
 		if (is_absolute_path(romfname)) {
-			if (!(rom_size = load_rom(romfname, &cart, &stype))) {
+			if (!(cart.size = load_rom(romfname, &cart.buffer, &stype))) {
 				fatal_error("Failed to open UI ROM %s for reading", romfname);
 			}
 		} else {
-			long fsize;
-			cart = (uint16_t *)read_bundled_file(romfname, &fsize);
-			if (!cart) {
+			cart.buffer = (uint16_t *)read_bundled_file(romfname, &cart.size);
+			if (!cart.buffer) {
 				fatal_error("Failed to open UI ROM %s for reading", romfname);
 			}
-			stype = detect_system_type((uint8_t *)cart, fsize);
-			rom_size = nearest_pow2(fsize);
-			if (rom_size > fsize) {
-				cart = realloc(cart, rom_size);
+			uint32_t rom_size = nearest_pow2(cart.size);
+			if (rom_size > cart.size) {
+				cart.buffer = realloc(cart.buffer, rom_size);
+				cart.size = rom_size;
 			}
 		}
+		//force system detection, value on command line is only for games not the menu
+		stype = detect_system_type(&cart);
+		cart.extension = path_extension(romfname);
 
 		loaded = 1;
 	}
@@ -337,10 +357,16 @@
 		render_init(width, height, "BlastEm", fullscreen);
 	}
 
+	if (stype == SYSTEM_UNKNOWN) {
+		stype = detect_system_type(&cart);
+	}
+	if (stype == SYSTEM_UNKNOWN) {
+		fatal_error("Failed to detect system type for %s\n", romfname);
+	}
 	rom_info info;
-	current_system = alloc_config_system(stype, cart, rom_size, lock_on, lock_on_size, menu ? 0 : opts, force_region, &info);
+	current_system = alloc_config_system(stype, &cart, menu ? 0 : opts, force_region, &info);
 	if (!current_system) {
-		fatal_error("Failed to detect system type for %s\n", romfname);
+		fatal_error("Failed to configure emulated machine for %s\n", romfname);
 	}
 	setup_saves(romfname, &info, current_system);
 	update_title(info.name);
@@ -369,13 +395,21 @@
 				//start a new arena and save old one in suspended genesis context
 				current_system->arena = start_new_arena();
 			}
-			if (!(rom_size = load_rom(menu_context->next_rom, &cart, &stype))) {
+			if (!(cart.size = load_rom(menu_context->next_rom, &cart.buffer, &stype))) {
 				fatal_error("Failed to open %s for reading\n", menu_context->next_rom);
 			}
+			cart.extension = path_extension(menu_context->next_rom);
+			stype = force_stype;
+			if (stype == SYSTEM_UNKNOWN) {
+				stype = detect_system_type(&cart);
+			}
+			if (stype == SYSTEM_UNKNOWN) {
+				fatal_error("Failed to detect system type for %s\n", menu_context->next_rom);
+			}
 			//allocate new genesis context
-			game_context = alloc_config_system(stype, cart, rom_size, lock_on, lock_on_size, opts,force_region, &info);
+			game_context = alloc_config_system(stype, &cart, opts,force_region, &info);
 			if (!game_context) {
-				fatal_error("Failed to detect system type for %s\n", menu_context->next_rom);
+				fatal_error("Failed to configure emulated machine for %s\n", menu_context->next_rom);
 			}
 			menu_context->next_context = game_context;
 			game_context->next_context = menu_context;