MDFNGI *MDFNI_LoadGame(const char *force_module, const char *name) { MDFNFILE GameFile; struct stat stat_buf; std::vector<FileExtensionSpecStruct> valid_iae; if(strlen(name) > 4 && (!strcasecmp(name + strlen(name) - 4, ".cue") || !strcasecmp(name + strlen(name) - 4, ".toc") || !strcasecmp(name + strlen(name) - 4, ".m3u"))) { return(MDFNI_LoadCD(force_module, name)); } if(!stat(name, &stat_buf) && !S_ISREG(stat_buf.st_mode)) { return(MDFNI_LoadCD(force_module, name)); } MDFNI_CloseGame(); LastSoundMultiplier = 1; MDFNGameInfo = NULL; MDFN_printf(_("Loading %s...\n"),name); MDFN_indent(1); GetFileBase(name); // Construct a NULL-delimited list of known file extensions for MDFN_fopen() for(unsigned int i = 0; i < MDFNSystems.size(); i++) { const FileExtensionSpecStruct *curexts = MDFNSystems[i]->FileExtensions; // If we're forcing a module, only look for extensions corresponding to that module if(force_module && strcmp(MDFNSystems[i]->shortname, force_module)) continue; if(curexts) while(curexts->extension && curexts->description) { valid_iae.push_back(*curexts); curexts++; } } { FileExtensionSpecStruct tmpext = { NULL, NULL }; valid_iae.push_back(tmpext); } if(!GameFile.Open(name, &valid_iae[0], _("game"))) { MDFNGameInfo = NULL; return 0; } if(!LoadIPS(GameFile, MDFN_MakeFName(MDFNMKF_IPS, 0, 0).c_str())) { MDFNGameInfo = NULL; GameFile.Close(); return(0); } MDFNGameInfo = NULL; for(std::list<MDFNGI *>::iterator it = MDFNSystemsPrio.begin(); it != MDFNSystemsPrio.end(); it++) //_unsigned int x = 0; x < MDFNSystems.size(); x++) { char tmpstr[256]; trio_snprintf(tmpstr, 256, "%s.enable", (*it)->shortname); if(force_module) { if(!strcmp(force_module, (*it)->shortname)) { if(!(*it)->Load) { GameFile.Close(); if((*it)->LoadCD) MDFN_PrintError(_("Specified system only supports CD(physical, or image files, such as *.cue and *.toc) loading.")); else MDFN_PrintError(_("Specified system does not support normal file loading.")); MDFN_indent(-1); MDFNGameInfo = NULL; return 0; } MDFNGameInfo = *it; break; } } else { // Is module enabled? if(!MDFN_GetSettingB(tmpstr)) continue; if(!(*it)->Load || !(*it)->TestMagic) continue; if((*it)->TestMagic(name, &GameFile)) { MDFNGameInfo = *it; break; } } } if(!MDFNGameInfo) { GameFile.Close(); if(force_module) MDFN_PrintError(_("Unrecognized system \"%s\"!"), force_module); else MDFN_PrintError(_("Unrecognized file format. Sorry.")); MDFN_indent(-1); MDFNGameInfo = NULL; return 0; } MDFN_printf(_("Using module: %s(%s)\n\n"), MDFNGameInfo->shortname, MDFNGameInfo->fullname); MDFN_indent(1); assert(MDFNGameInfo->soundchan != 0); MDFNGameInfo->soundrate = 0; MDFNGameInfo->name = NULL; MDFNGameInfo->rotated = 0; if(MDFNGameInfo->Load(name, &GameFile) <= 0) { GameFile.Close(); MDFN_indent(-2); MDFNGameInfo = NULL; return(0); } if(MDFNGameInfo->GameType != GMT_PLAYER) { MDFN_LoadGameCheats(NULL); MDFNMP_InstallReadPatches(); } MDFNI_SetLayerEnableMask(~0ULL); #ifdef WANT_DEBUGGER MDFNDBG_PostGameLoad(); #endif MDFNSS_CheckStates(); MDFNMOV_CheckMovies(); MDFN_ResetMessages(); // Save state, status messages, etc. MDFN_indent(-2); if(!MDFNGameInfo->name) { unsigned int x; char *tmp; MDFNGameInfo->name = (UTF8 *)strdup(GetFNComponent(name)); for(x=0; x<strlen((char *)MDFNGameInfo->name); x++) { if(MDFNGameInfo->name[x] == '_') MDFNGameInfo->name[x] = ' '; } if((tmp = strrchr((char *)MDFNGameInfo->name, '.'))) *tmp = 0; } PrevInterlaced = false; deint.ClearState(); TBlur_Init(); MDFN_StateEvilBegin(); last_sound_rate = -1; memset(&last_pixel_format, 0, sizeof(MDFN_PixelFormat)); return(MDFNGameInfo); }
MDFNGI *MDFNI_LoadGame(const char *force_module, const char *name) { MDFNFILE GameFile; std::vector<FileExtensionSpecStruct> valid_iae; MDFNGameInfo = MDFNGI_CORE; #ifdef NEED_CD if(strlen(name) > 4 && (!strcasecmp(name + strlen(name) - 4, ".cue") || !strcasecmp(name + strlen(name) - 4, ".toc") || !strcasecmp(name + strlen(name) - 4, ".m3u"))) return(MDFNI_LoadCD(force_module, name)); #endif MDFN_printf(_("Loading %s...\n"),name); MDFN_indent(1); // Construct a NULL-delimited list of known file extensions for MDFN_fopen() const FileExtensionSpecStruct *curexts = MDFNGameInfo->FileExtensions; while(curexts->extension && curexts->description) { valid_iae.push_back(*curexts); curexts++; } if(!GameFile.Open(name, &valid_iae[0], _("game"))) { MDFNGameInfo = NULL; return 0; } MDFN_printf(_("Using module: %s(%s)\n\n"), MDFNGameInfo->shortname, MDFNGameInfo->fullname); MDFN_indent(1); // // Load per-game settings // // Maybe we should make a "pgcfg" subdir, and automatically load all files in it? // End load per-game settings // if(MDFNGameInfo->Load(name, &GameFile) <= 0) { GameFile.Close(); MDFN_indent(-2); MDFNGameInfo = NULL; return(0); } // MDFN_LoadGameCheats(NULL); MDFNMP_InstallReadPatches(); #ifdef WANT_DEBUGGER MDFNDBG_PostGameLoad(); #endif MDFN_ResetMessages(); // Save state, status messages, etc. MDFN_indent(-2); if(!MDFNGameInfo->name) { unsigned int x; char *tmp; MDFNGameInfo->name = (UTF8 *)strdup(GetFNComponent(name)); for(x=0;x<strlen((char *)MDFNGameInfo->name);x++) { if(MDFNGameInfo->name[x] == '_') MDFNGameInfo->name[x] = ' '; } if((tmp = strrchr((char *)MDFNGameInfo->name, '.'))) *tmp = 0; } return(MDFNGameInfo); }
MDFNGI *MDFNI_LoadCD(const char *force_module, const char *devicename) { uint8 LayoutMD5[16]; MDFNI_CloseGame(); LastSoundMultiplier = 1; MDFN_printf(_("Loading %s...\n\n"), devicename ? devicename : _("PHYSICAL CD")); try { if(devicename && strlen(devicename) > 4 && !strcasecmp(devicename + strlen(devicename) - 4, ".m3u")) { std::vector<std::string> file_list; ReadM3U(file_list, devicename); for(unsigned i = 0; i < file_list.size(); i++) { CDInterfaces.push_back(new CDIF(file_list[i].c_str())); } GetFileBase(devicename); } else { CDInterfaces.push_back(new CDIF(devicename)); if(CDInterfaces[0]->IsPhysical()) { GetFileBase("cdrom"); } else GetFileBase(devicename); } } catch(std::exception &e) { MDFND_PrintError(e.what()); MDFN_PrintError(_("Error opening CD.")); return(0); } // // Print out a track list for all discs. // MDFN_indent(1); for(unsigned i = 0; i < CDInterfaces.size(); i++) { CDUtility::TOC toc; CDInterfaces[i]->ReadTOC(&toc); MDFN_printf(_("CD %d Layout:\n"), i + 1); MDFN_indent(1); for(int32 track = toc.first_track; track <= toc.last_track; track++) { MDFN_printf(_("Track %2d, LBA: %6d %s\n"), track, toc.tracks[track].lba, (toc.tracks[track].control & 0x4) ? "DATA" : "AUDIO"); } MDFN_printf("Leadout: %6d\n", toc.tracks[100].lba); MDFN_indent(-1); MDFN_printf("\n"); } MDFN_indent(-1); // // // Calculate layout MD5. The system emulation LoadCD() code is free to ignore this value and calculate // its own, or to use it to look up a game in its database. { md5_context layout_md5; layout_md5.starts(); for(unsigned i = 0; i < CDInterfaces.size(); i++) { CD_TOC toc; CDInterfaces[i]->ReadTOC(&toc); layout_md5.update_u32_as_lsb(toc.first_track); layout_md5.update_u32_as_lsb(toc.last_track); layout_md5.update_u32_as_lsb(toc.tracks[100].lba); for(uint32 track = toc.first_track; track <= toc.last_track; track++) { layout_md5.update_u32_as_lsb(toc.tracks[track].lba); layout_md5.update_u32_as_lsb(toc.tracks[track].control & 0x4); } } layout_md5.finish(LayoutMD5); } MDFNGameInfo = NULL; for(std::list<MDFNGI *>::iterator it = MDFNSystemsPrio.begin(); it != MDFNSystemsPrio.end(); it++) //_unsigned int x = 0; x < MDFNSystems.size(); x++) { char tmpstr[256]; trio_snprintf(tmpstr, 256, "%s.enable", (*it)->shortname); if(force_module) { if(!strcmp(force_module, (*it)->shortname)) { MDFNGameInfo = *it; break; } } else { // Is module enabled? if(!MDFN_GetSettingB(tmpstr)) continue; if(!(*it)->LoadCD || !(*it)->TestMagicCD) continue; if((*it)->TestMagicCD(&CDInterfaces)) { MDFNGameInfo = *it; break; } } } if(!MDFNGameInfo) { if(force_module) { MDFN_PrintError(_("Unrecognized system \"%s\"!"), force_module); return(0); } // This code path should never be taken, thanks to "cdplay" MDFN_PrintError(_("Could not find a system that supports this CD.")); return(0); } // This if statement will be true if force_module references a system without CDROM support. if(!MDFNGameInfo->LoadCD) { MDFN_PrintError(_("Specified system \"%s\" doesn't support CDs!"), force_module); return(0); } MDFN_printf(_("Using module: %s(%s)\n\n"), MDFNGameInfo->shortname, MDFNGameInfo->fullname); // TODO: include module name in hash memcpy(MDFNGameInfo->MD5, LayoutMD5, 16); if(!(MDFNGameInfo->LoadCD(&CDInterfaces))) { for(unsigned i = 0; i < CDInterfaces.size(); i++) delete CDInterfaces[i]; CDInterfaces.clear(); MDFNGameInfo = NULL; return(0); } MDFNI_SetLayerEnableMask(~0ULL); #ifdef WANT_DEBUGGER MDFNDBG_PostGameLoad(); #endif MDFNSS_CheckStates(); MDFNMOV_CheckMovies(); MDFN_ResetMessages(); // Save state, status messages, etc. TBlur_Init(); MDFN_StateEvilBegin(); if(MDFNGameInfo->GameType != GMT_PLAYER) { MDFN_LoadGameCheats(NULL); MDFNMP_InstallReadPatches(); } last_sound_rate = -1; memset(&last_pixel_format, 0, sizeof(MDFN_PixelFormat)); return(MDFNGameInfo); }
MDFNGI *MDFNI_LoadCD(const char *force_module, const char *devicename) { uint8 LayoutMD5[16]; #ifdef NEED_CD static std::vector<CDIF *> CDInterfaces; // FIXME: Cleanup on error out. #endif MDFN_printf(_("Loading %s...\n\n"), devicename ? devicename : _("PHYSICAL CD")); try { if(devicename && strlen(devicename) > 4 && !strcasecmp(devicename + strlen(devicename) - 4, ".m3u")) { std::vector<std::string> file_list; ReadM3U(file_list, devicename); for(unsigned i = 0; i < file_list.size(); i++) { CDInterfaces.push_back(CDIF_Open(file_list[i].c_str(), false /* cdimage_memcache */)); } } else { CDInterfaces.push_back(CDIF_Open(devicename, false /* cdimage_memcache */)); } } catch(std::exception &e) { MDFND_PrintError(e.what()); MDFN_PrintError(_("Error opening CD.")); return(0); } // // Print out a track list for all discs. // MDFN_indent(1); for(unsigned i = 0; i < CDInterfaces.size(); i++) { CDUtility::TOC toc; CDInterfaces[i]->ReadTOC(&toc); MDFN_printf(_("CD %d Layout:\n"), i + 1); MDFN_indent(1); for(int32 track = toc.first_track; track <= toc.last_track; track++) { MDFN_printf(_("Track %2d, LBA: %6d %s\n"), track, toc.tracks[track].lba, (toc.tracks[track].control & 0x4) ? "DATA" : "AUDIO"); } MDFN_printf("Leadout: %6d\n", toc.tracks[100].lba); MDFN_indent(-1); MDFN_printf("\n"); } MDFN_indent(-1); // Calculate layout MD5. The system emulation LoadCD() code is free to ignore this value and calculate // its own, or to use it to look up a game in its database. { md5_context layout_md5; layout_md5.starts(); for(unsigned i = 0; i < CDInterfaces.size(); i++) { CD_TOC toc; CDInterfaces[i]->ReadTOC(&toc); layout_md5.update_u32_as_lsb(toc.first_track); layout_md5.update_u32_as_lsb(toc.last_track); layout_md5.update_u32_as_lsb(toc.tracks[100].lba); for(uint32 track = toc.first_track; track <= toc.last_track; track++) { layout_md5.update_u32_as_lsb(toc.tracks[track].lba); layout_md5.update_u32_as_lsb(toc.tracks[track].control & 0x4); } } layout_md5.finish(LayoutMD5); } // This if statement will be true if force_module references a system without CDROM support. if(!MDFNGameInfo->LoadCD) { MDFN_PrintError(_("Specified system \"%s\" doesn't support CDs!"), force_module); return(0); } MDFN_printf(_("Using module: %s(%s)\n\n"), MDFNGameInfo->shortname, MDFNGameInfo->fullname); // TODO: include module name in hash memcpy(MDFNGameInfo->MD5, LayoutMD5, 16); if(!(MDFNGameInfo->LoadCD(&CDInterfaces))) { for(unsigned i = 0; i < CDInterfaces.size(); i++) delete CDInterfaces[i]; CDInterfaces.clear(); MDFNGameInfo = NULL; return(0); } //MDFNI_SetLayerEnableMask(~0ULL); #ifdef WANT_DEBUGGER MDFNDBG_PostGameLoad(); #endif MDFN_ResetMessages(); // Save state, status messages, etc. // MDFN_LoadGameCheats(NULL); MDFNMP_InstallReadPatches(); return(MDFNGameInfo); }