comparison 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
comparison
equal deleted inserted replaced
1139:160e3f597cec 1140:4490c9c12272
47 #define SMD_MAGIC1 0x03 47 #define SMD_MAGIC1 0x03
48 #define SMD_MAGIC2 0xAA 48 #define SMD_MAGIC2 0xAA
49 #define SMD_MAGIC3 0xBB 49 #define SMD_MAGIC3 0xBB
50 #define SMD_BLOCK_SIZE 0x4000 50 #define SMD_BLOCK_SIZE 0x4000
51 51
52 int load_smd_rom(long filesize, FILE * f, uint16_t **buffer) 52 int load_smd_rom(long filesize, FILE * f, void **buffer)
53 { 53 {
54 uint8_t block[SMD_BLOCK_SIZE]; 54 uint8_t block[SMD_BLOCK_SIZE];
55 filesize -= SMD_HEADER_SIZE; 55 filesize -= SMD_HEADER_SIZE;
56 fseek(f, SMD_HEADER_SIZE, SEEK_SET); 56 fseek(f, SMD_HEADER_SIZE, SEEK_SET);
57 57
65 filesize -= SMD_BLOCK_SIZE; 65 filesize -= SMD_BLOCK_SIZE;
66 } 66 }
67 return rom_size; 67 return rom_size;
68 } 68 }
69 69
70 int load_rom(char * filename, uint16_t **dst, system_type *stype) 70 uint32_t load_rom(char * filename, void **dst, system_type *stype)
71 { 71 {
72 uint8_t header[10]; 72 uint8_t header[10];
73 FILE * f = fopen(filename, "rb"); 73 FILE * f = fopen(filename, "rb");
74 if (!f) { 74 if (!f) {
75 return 0; 75 return 0;
100 *dst = malloc(nearest_pow2(filesize)); 100 *dst = malloc(nearest_pow2(filesize));
101 if (filesize != fread(*dst, 1, filesize, f)) { 101 if (filesize != fread(*dst, 1, filesize, f)) {
102 fatal_error("Error reading from %s\n", filename); 102 fatal_error("Error reading from %s\n", filename);
103 } 103 }
104 fclose(f); 104 fclose(f);
105 if (stype) {
106 *stype = detect_system_type((uint8_t *)*dst, filesize);
107 }
108 return filesize; 105 return filesize;
109 } 106 }
110 107
111 108
112 109
175 int width = -1; 172 int width = -1;
176 int height = -1; 173 int height = -1;
177 int debug = 0; 174 int debug = 0;
178 uint32_t opts = 0; 175 uint32_t opts = 0;
179 int loaded = 0; 176 int loaded = 0;
180 system_type stype; 177 system_type stype = SYSTEM_UNKNOWN, force_stype = SYSTEM_UNKNOWN;
181 uint8_t force_region = 0; 178 uint8_t force_region = 0;
182 char * romfname = NULL; 179 char * romfname = NULL;
183 char * statefile = NULL; 180 char * statefile = NULL;
184 int rom_size, lock_on_size; 181 system_media cart = {.chain = NULL}, lock_on;
185 uint16_t *cart = NULL, *lock_on = NULL;
186 debugger_type dtype = DEBUGGER_NATIVE; 182 debugger_type dtype = DEBUGGER_NATIVE;
187 uint8_t start_in_debugger = 0; 183 uint8_t start_in_debugger = 0;
188 uint8_t fullscreen = FULLSCREEN_DEFAULT, use_gl = 1; 184 uint8_t fullscreen = FULLSCREEN_DEFAULT, use_gl = 1;
189 uint8_t debug_target = 0; 185 uint8_t debug_target = 0;
190 for (int i = 1; i < argc; i++) { 186 for (int i = 1; i < argc; i++) {
233 force_region = translate_region_char(toupper(argv[i][0])); 229 force_region = translate_region_char(toupper(argv[i][0]));
234 if (!force_region) { 230 if (!force_region) {
235 fatal_error("'%c' is not a valid region character for the -r option\n", argv[i][0]); 231 fatal_error("'%c' is not a valid region character for the -r option\n", argv[i][0]);
236 } 232 }
237 break; 233 break;
234 case 'm':
235 i++;
236 if (i >= argc) {
237 fatal_error("-r must be followed by a machine type (sms, gen or jag)\n");
238 }
239 if (!strcmp("sms", argv[i])) {
240 stype = force_stype = SYSTEM_SMS;
241 } else if (!strcmp("gen", argv[i])) {
242 stype = force_stype = SYSTEM_GENESIS;
243 } else if (!strcmp("jag", argv[i])) {
244 stype = force_stype = SYSTEM_JAGUAR;
245 } else {
246 fatal_error("Unrecognized machine type %s\n", argv[i]);
247 }
248 break;
238 case 's': 249 case 's':
239 i++; 250 i++;
240 if (i >= argc) { 251 if (i >= argc) {
241 fatal_error("-s must be followed by a savestate filename\n"); 252 fatal_error("-s must be followed by a savestate filename\n");
242 } 253 }
251 case 'o': { 262 case 'o': {
252 i++; 263 i++;
253 if (i >= argc) { 264 if (i >= argc) {
254 fatal_error("-o must be followed by a lock on cartridge filename\n"); 265 fatal_error("-o must be followed by a lock on cartridge filename\n");
255 } 266 }
256 lock_on_size = load_rom(argv[i], &lock_on, NULL); 267 lock_on.size = load_rom(argv[i], &lock_on.buffer, NULL);
257 if (!lock_on_size) { 268 if (!lock_on.size) {
258 fatal_error("Failed to load lock on cartridge %s\n", argv[i]); 269 fatal_error("Failed to load lock on cartridge %s\n", argv[i]);
259 } 270 }
271 lock_on.extension = path_extension(argv[i]);
272 cart.chain = &lock_on;
260 break; 273 break;
261 } 274 }
262 case 'h': 275 case 'h':
263 info_message( 276 info_message(
264 "Usage: blastem [OPTIONS] ROMFILE [WIDTH] [HEIGHT]\n" 277 "Usage: blastem [OPTIONS] ROMFILE [WIDTH] [HEIGHT]\n"
265 "Options:\n" 278 "Options:\n"
266 " -h Print this help text\n" 279 " -h Print this help text\n"
267 " -r (J|U|E) Force region to Japan, US or Europe respectively\n" 280 " -r (J|U|E) Force region to Japan, US or Europe respectively\n"
281 " -m MACHINE Force emulated machine type to MACHINE. Valid values are:\n"
282 " sms - Sega Master System/Mark III\n"
283 " gen - Sega Genesis/Megadrive\n"
284 " jag - Atari Jaguar\n"
268 " -f Toggles fullscreen mode\n" 285 " -f Toggles fullscreen mode\n"
269 " -g Disable OpenGL rendering\n" 286 " -g Disable OpenGL rendering\n"
270 " -s FILE Load a GST format savestate from FILE\n" 287 " -s FILE Load a GST format savestate from FILE\n"
271 " -o FILE Load FILE as a lock-on cartridge\n" 288 " -o FILE Load FILE as a lock-on cartridge\n"
272 " -d Enter debugger on startup\n" 289 " -d Enter debugger on startup\n"
278 return 0; 295 return 0;
279 default: 296 default:
280 fatal_error("Unrecognized switch %s\n", argv[i]); 297 fatal_error("Unrecognized switch %s\n", argv[i]);
281 } 298 }
282 } else if (!loaded) { 299 } else if (!loaded) {
283 if (!(rom_size = load_rom(argv[i], &cart, &stype))) { 300 if (!(cart.size = load_rom(argv[i], &cart.buffer, stype == SYSTEM_UNKNOWN ? &stype : NULL))) {
284 fatal_error("Failed to open %s for reading\n", argv[i]); 301 fatal_error("Failed to open %s for reading\n", argv[i]);
285 } 302 }
303 cart.extension = path_extension(argv[i]);
286 romfname = argv[i]; 304 romfname = argv[i];
287 loaded = 1; 305 loaded = 1;
288 } else if (width < 0) { 306 } else if (width < 0) {
289 width = atoi(argv[i]); 307 width = atoi(argv[i]);
290 } else if (height < 0) { 308 } else if (height < 0) {
297 romfname = tern_find_path(config, "ui\0rom\0").ptrval; 315 romfname = tern_find_path(config, "ui\0rom\0").ptrval;
298 if (!romfname) { 316 if (!romfname) {
299 romfname = "menu.bin"; 317 romfname = "menu.bin";
300 } 318 }
301 if (is_absolute_path(romfname)) { 319 if (is_absolute_path(romfname)) {
302 if (!(rom_size = load_rom(romfname, &cart, &stype))) { 320 if (!(cart.size = load_rom(romfname, &cart.buffer, &stype))) {
303 fatal_error("Failed to open UI ROM %s for reading", romfname); 321 fatal_error("Failed to open UI ROM %s for reading", romfname);
304 } 322 }
305 } else { 323 } else {
306 long fsize; 324 cart.buffer = (uint16_t *)read_bundled_file(romfname, &cart.size);
307 cart = (uint16_t *)read_bundled_file(romfname, &fsize); 325 if (!cart.buffer) {
308 if (!cart) {
309 fatal_error("Failed to open UI ROM %s for reading", romfname); 326 fatal_error("Failed to open UI ROM %s for reading", romfname);
310 } 327 }
311 stype = detect_system_type((uint8_t *)cart, fsize); 328 uint32_t rom_size = nearest_pow2(cart.size);
312 rom_size = nearest_pow2(fsize); 329 if (rom_size > cart.size) {
313 if (rom_size > fsize) { 330 cart.buffer = realloc(cart.buffer, rom_size);
314 cart = realloc(cart, rom_size); 331 cart.size = rom_size;
315 } 332 }
316 } 333 }
334 //force system detection, value on command line is only for games not the menu
335 stype = detect_system_type(&cart);
336 cart.extension = path_extension(romfname);
317 337
318 loaded = 1; 338 loaded = 1;
319 } 339 }
320 340
321 int def_width = 0; 341 int def_width = 0;
335 } 355 }
336 if (!headless) { 356 if (!headless) {
337 render_init(width, height, "BlastEm", fullscreen); 357 render_init(width, height, "BlastEm", fullscreen);
338 } 358 }
339 359
360 if (stype == SYSTEM_UNKNOWN) {
361 stype = detect_system_type(&cart);
362 }
363 if (stype == SYSTEM_UNKNOWN) {
364 fatal_error("Failed to detect system type for %s\n", romfname);
365 }
340 rom_info info; 366 rom_info info;
341 current_system = alloc_config_system(stype, cart, rom_size, lock_on, lock_on_size, menu ? 0 : opts, force_region, &info); 367 current_system = alloc_config_system(stype, &cart, menu ? 0 : opts, force_region, &info);
342 if (!current_system) { 368 if (!current_system) {
343 fatal_error("Failed to detect system type for %s\n", romfname); 369 fatal_error("Failed to configure emulated machine for %s\n", romfname);
344 } 370 }
345 setup_saves(romfname, &info, current_system); 371 setup_saves(romfname, &info, current_system);
346 update_title(info.name); 372 update_title(info.name);
347 if (menu) { 373 if (menu) {
348 menu_context = current_system; 374 menu_context = current_system;
367 game_context->free_context(game_context); 393 game_context->free_context(game_context);
368 } else { 394 } else {
369 //start a new arena and save old one in suspended genesis context 395 //start a new arena and save old one in suspended genesis context
370 current_system->arena = start_new_arena(); 396 current_system->arena = start_new_arena();
371 } 397 }
372 if (!(rom_size = load_rom(menu_context->next_rom, &cart, &stype))) { 398 if (!(cart.size = load_rom(menu_context->next_rom, &cart.buffer, &stype))) {
373 fatal_error("Failed to open %s for reading\n", menu_context->next_rom); 399 fatal_error("Failed to open %s for reading\n", menu_context->next_rom);
374 } 400 }
401 cart.extension = path_extension(menu_context->next_rom);
402 stype = force_stype;
403 if (stype == SYSTEM_UNKNOWN) {
404 stype = detect_system_type(&cart);
405 }
406 if (stype == SYSTEM_UNKNOWN) {
407 fatal_error("Failed to detect system type for %s\n", menu_context->next_rom);
408 }
375 //allocate new genesis context 409 //allocate new genesis context
376 game_context = alloc_config_system(stype, cart, rom_size, lock_on, lock_on_size, opts,force_region, &info); 410 game_context = alloc_config_system(stype, &cart, opts,force_region, &info);
377 if (!game_context) { 411 if (!game_context) {
378 fatal_error("Failed to detect system type for %s\n", menu_context->next_rom); 412 fatal_error("Failed to configure emulated machine for %s\n", menu_context->next_rom);
379 } 413 }
380 menu_context->next_context = game_context; 414 menu_context->next_context = game_context;
381 game_context->next_context = menu_context; 415 game_context->next_context = menu_context;
382 setup_saves(menu_context->next_rom, &info, game_context); 416 setup_saves(menu_context->next_rom, &info, game_context);
383 update_title(info.name); 417 update_title(info.name);