MDFNGI *MDFNI_LoadCD(const char *force_module, const char *devicename, const bool is_device) { uint8 LayoutMD5[16]; MDFNI_CloseGame(); LastSoundMultiplier = 1; if(is_device) { if(devicename) MDFN_printf(_("Loading from CD drive device %s...\n\n"), devicename); else MDFN_printf(_("Load from default CD drive device...\n\n")); } else { assert(devicename != NULL); MDFN_printf(_("Loading %s...\n\n"), devicename); } try { const bool image_memcache = MDFN_GetSettingB("cd.image_memcache"); if(is_device) { CDInterfaces.push_back(CDIF_Open(devicename, true, image_memcache)); GetFileBase("cdrom"); } else { 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, image_memcache)); } } else { CDInterfaces.push_back(CDIF_Open(devicename, false, image_memcache)); } GetFileBase(devicename); } } catch(std::exception &e) { MDFN_PrintError(_("Error opening CD: %s"), e.what()); 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); MDFN_printf(_("Disc Type: 0x%02x\n"), toc.disc_type); 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 %s\n"), toc.tracks[100].lba, (toc.tracks[100].control & 0x4) ? "DATA" : "AUDIO"); if((toc.tracks[toc.last_track].control & 0x4) != (toc.tracks[100].control & 0x4)) MDFN_printf(_("WARNING: DATA/AUDIO TYPE MISMATCH BETWEEN LAST TRACK AND LEADOUT AREA.")); 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); std::string modoverride_settings_file_path = MDFN_GetBaseDirectory() + std::string(PSS) + std::string(MDFNGameInfo->shortname) + std::string(".cfg"); if(!MDFN_LoadSettings(modoverride_settings_file_path.c_str(), true)) { for(unsigned i = 0; i < CDInterfaces.size(); i++) delete CDInterfaces[i]; CDInterfaces.clear(); MDFNGameInfo = NULL; return(0); } if(!(MDFNGameInfo->LoadCD(&CDInterfaces))) { for(unsigned i = 0; i < CDInterfaces.size(); i++) delete CDInterfaces[i]; CDInterfaces.clear(); MDFNGameInfo = NULL; return(0); } if(!MDFNGameInfo->name && !is_device) MakeGIName(MDFNGameInfo, devicename); 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); }