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(CDIF_Open(file_list[i].c_str(), MDFN_GetSettingB("cd.image_memcache"))); } GetFileBase(devicename); } else { CDInterfaces.push_back(CDIF_Open(devicename, MDFN_GetSettingB("cd.image_memcache"))); 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_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; // // Load per-game settings // // Maybe we should make a "pgcfg" subdir, and automatically load all files in it? #if 0 { char hash_string[n + 1]; const char *section_names[3] = { MDFNGameInfo->shortname, hash_string, NULL }; //asdfasdfMDFN_LoadSettings(std::string(basedir) + std::string(PSS) + std::string("pergame.cfg"); } #endif // End load per-game settings // 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); }
int HuCLoadCD(const char *bios_path) { static const FileExtensionSpecStruct KnownBIOSExtensions[] = { { ".pce", gettext_noop("PC Engine ROM Image") }, { ".bin", gettext_noop("PC Engine ROM Image") }, { ".bios", gettext_noop("BIOS Image") }, { NULL, NULL } }; MDFNFILE fp; if(!fp.Open(bios_path, KnownBIOSExtensions, "CD BIOS")) return(0); memset(ROMSpace, 0xFF, 262144); memcpy(ROMSpace, fp.f_data + (fp.f_size & 512), ((fp.f_size & ~512) > 262144) ? 262144 : (fp.f_size &~ 512) ); fp.Close(); PCE_IsCD = 1; PCE_InitCD(); md5_context md5; md5.starts(); MDFN_printf(_("Arcade Card Emulation: %s\n"), PCE_ACEnabled ? _("Enabled") : _("Disabled")); for(int x = 0; x < 0x40; x++) { HuCPUFastMap[x] = ROMSpace; PCERead[x] = HuCRead; } for(int x = 0x68; x < 0x88; x++) { HuCPUFastMap[x] = ROMSpace; PCERead[x] = HuCRead; PCEWrite[x] = HuCRAMWrite; } PCEWrite[0x80] = HuCRAMWriteCDSpecial; // Hyper Dyne Special hack MDFNMP_AddRAM(262144, 0x68 * 8192, ROMSpace + 0x68 * 8192); if(PCE_ACEnabled) { try { arcade_card = new ArcadeCard(); } catch(std::exception &e) { MDFN_PrintError(_("Error creating %s object: %s"), "ArcadeCard", e.what()); return(0); } for(int x = 0x40; x < 0x44; x++) { HuCPUFastMap[x] = NULL; PCERead[x] = ACPhysRead; PCEWrite[x] = ACPhysWrite; } } FILE *srp; memset(SaveRAM, 0x00, 2048); memcpy(SaveRAM, BRAM_Init_String, 8); // So users don't have to manually intialize the file cabinet // in the CD BIOS screen. if((srp = fopen(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), "rb"))) { fread(SaveRAM, 2048, 1, srp); fclose(srp); } PCEWrite[0xF7] = SaveRAMWrite; PCERead[0xF7] = SaveRAMRead; MDFNMP_AddRAM(2048, 0xF7 * 8192, SaveRAM); return(1); }