static void LoadCPalette(const char *syspalname, uint8 **ptr, uint32 num_entries) { std::string colormap_fn = MDFN_MakeFName(MDFNMKF_PALETTE, 0, syspalname).c_str(); MDFN_printf(_("Loading custom palette from \"%s\"...\n"), colormap_fn.c_str()); MDFN_indent(1); try { FileStream fp(colormap_fn.c_str(), FileStream::MODE_READ); *ptr = new uint8[num_entries * 3]; fp.read(*ptr, num_entries * 3); } catch(MDFN_Error &e) { MDFN_printf(_("Error: %s\n"), e.what()); MDFN_indent(-1); if(e.GetErrno() != ENOENT) throw; return; } catch(std::exception &e) { MDFN_printf(_("Error: %s\n"), e.what()); MDFN_indent(-1); throw; } MDFN_indent(-1); }
static bool cdif_open_sub(const char *device_name) { MDFN_printf(_("Loading %s...\n\n"), device_name ? device_name : _("PHYSICAL CDROM DISC")); MDFN_indent(1); if(!(p_cdrfile = cdrfile_open(device_name))) { MDFN_indent(-1); return(0); } CD_Info.NumTracks = cdrfile_get_num_tracks(p_cdrfile); if(CD_Info.NumTracks < 1 || CD_Info.NumTracks > 100) { MDFN_indent(-1); return(0); } CD_Info.FirstTrack = cdrfile_get_first_track_num(p_cdrfile); for(track_t track = CD_Info.FirstTrack; track < CD_Info.FirstTrack + CD_Info.NumTracks; track++) { CD_Info.Tracks[track].LSN = cdrfile_get_track_lsn(p_cdrfile, track); CD_Info.Tracks[track].Format = cdrfile_get_track_format(p_cdrfile, track); MDFN_printf(_("Track %2d, LSN: %6d %s\n"), track, CD_Info.Tracks[track].LSN, track_format2str[CD_Info.Tracks[track].Format]); } MDFN_indent(-1); return(1); }
// Return FALSE on fatal error(IPS file found but couldn't be applied), // or TRUE on success(IPS patching succeeded, or IPS file not found). static bool LoadIPS(MDFNFILE &GameFile, const char *path) { FILE *IPSFile; MDFN_printf(_("Applying IPS file \"%s\"...\n"), path); IPSFile = fopen(path, "rb"); if(!IPSFile) { ErrnoHolder ene(errno); MDFN_indent(1); MDFN_printf(_("Failed: %s\n"), ene.StrError()); MDFN_indent(-1); if(ene.Errno() == ENOENT) return(1); else { MDFN_PrintError(_("Error opening IPS file: %s\n"), ene.StrError()); return(0); } } if(!GameFile.ApplyIPS(IPSFile)) { fclose(IPSFile); return(0); } fclose(IPSFile); return(1); }
bool MDFNI_StartAVRecord(const char *path, double SoundRate) { try { QTRecord::VideoSpec spec; memset(&spec, 0, sizeof(spec)); spec.SoundRate = SoundRate; spec.SoundChan = MDFNGameInfo->soundchan; spec.VideoWidth = MDFNGameInfo->lcm_width; spec.VideoHeight = MDFNGameInfo->lcm_height; spec.VideoCodec = MDFN_GetSettingI("qtrecord.vcodec"); spec.MasterClock = MDFNGameInfo->MasterClock; if(spec.VideoWidth < MDFN_GetSettingUI("qtrecord.w_double_threshold")) spec.VideoWidth *= 2; if(spec.VideoHeight < MDFN_GetSettingUI("qtrecord.h_double_threshold")) spec.VideoHeight *= 2; spec.AspectXAdjust = ((double)MDFNGameInfo->nominal_width * 2) / spec.VideoWidth; spec.AspectYAdjust = ((double)MDFNGameInfo->nominal_height * 2) / spec.VideoHeight; MDFN_printf("\n"); MDFN_printf(_("Starting QuickTime recording to file \"%s\":\n"), path); MDFN_indent(1); MDFN_printf(_("Video width: %u\n"), spec.VideoWidth); MDFN_printf(_("Video height: %u\n"), spec.VideoHeight); MDFN_printf(_("Video codec: %s\n"), MDFN_GetSettingS("qtrecord.vcodec").c_str()); if(spec.SoundRate && spec.SoundChan) { MDFN_printf(_("Sound rate: %u\n"), std::min<uint32>(spec.SoundRate, 64000)); MDFN_printf(_("Sound channels: %u\n"), spec.SoundChan); } else MDFN_printf(_("Sound: Disabled\n")); MDFN_indent(-1); MDFN_printf("\n"); qtrecorder = new QTRecord(path, spec); } catch(std::exception &e) { MDFND_PrintError(e.what()); return(false); } return(true); }
static bool LoadCPalette(const char *syspalname, uint8 **ptr, uint32 num_entries) { std::string colormap_fn = MDFN_MakeFName(MDFNMKF_PALETTE, 0, syspalname).c_str(); MDFN_printf(_("Loading custom palette from \"%s\"...\n"), colormap_fn.c_str()); MDFN_indent(1); *ptr = NULL; try { FileStream fp(colormap_fn.c_str(), FileStream::MODE_READ); if(!(*ptr = (uint8 *)MDFN_malloc(num_entries * 3, _("custom color map")))) { MDFN_indent(-1); return(false); } fp.read(*ptr, num_entries * 3); } catch(MDFN_Error &e) { if(*ptr) { MDFN_free(*ptr); *ptr = NULL; } MDFN_printf(_("Error: %s\n"), e.what()); MDFN_indent(-1); return(e.GetErrno() == ENOENT); // Return fatal error if it's an error other than the file not being found. } catch(std::exception &e) { if(*ptr) { MDFN_free(*ptr); *ptr = NULL; } MDFN_printf(_("Error: %s\n"), e.what()); MDFN_indent(-1); return(false); } MDFN_indent(-1); return(true); }
static void LoadCommonPost(const md_game_info &ginfo) { MDFN_printf(_("ROM: %dKiB\n"), (ginfo.rom_size + 1023) / 1024); MDFN_printf(_("ROM CRC32: 0x%08x\n"), ginfo.crc32); MDFN_printf(_("ROM MD5: 0x%s\n"), md5_context::asciistr(ginfo.md5, 0).c_str()); MDFN_printf(_("Header MD5: 0x%s\n"), md5_context::asciistr(ginfo.info_header_md5, 0).c_str()); MDFN_printf(_("Product Code: %s\n"), ginfo.product_code); MDFN_printf(_("Domestic name: %s\n"), ginfo.domestic_name); // TODO: Character set conversion(shift_jis -> utf-8) MDFN_printf(_("Overseas name: %s\n"), ginfo.overseas_name); MDFN_printf(_("Copyright: %s\n"), ginfo.copyright); if(ginfo.checksum == ginfo.checksum_real) MDFN_printf(_("Checksum: 0x%04x\n"), ginfo.checksum); else MDFN_printf(_("Checksum: 0x%04x\n Warning: calculated checksum(0x%04x) does not match\n"), ginfo.checksum, ginfo.checksum_real); MDFN_printf(_("Supported I/O devices:\n")); MDFN_indent(1); for(unsigned int iot = 0; iot < sizeof(IO_types) / sizeof(IO_type_t); iot++) { if(ginfo.io_support & (1 << IO_types[iot].id)) MDFN_printf(_("%s\n"), _(IO_types[iot].name)); } MDFN_indent(-1); MDFNMP_Init(8192, (1 << 24) / 8192); MDFNMP_AddRAM(65536, 0x7 << 21, work_ram); MDFNGameInfo->GameSetMD5Valid = FALSE; MDSound_Init(); MDFN_printf(_("Supported regions:\n")); MDFN_indent(1); if(ginfo.region_support & REGIONMASK_JAPAN_NTSC) MDFN_printf(_("Japan/Domestic NTSC\n")); if(ginfo.region_support & REGIONMASK_JAPAN_PAL) MDFN_printf(_("Japan/Domestic PAL\n")); if(ginfo.region_support & REGIONMASK_OVERSEAS_NTSC) MDFN_printf(_("Overseas NTSC\n")); if(ginfo.region_support & REGIONMASK_OVERSEAS_PAL) MDFN_printf(_("Overseas PAL\n")); MDFN_indent(-1); { const int region_setting = MDFN_GetSettingI("md.region"); const int reported_region_setting = MDFN_GetSettingI("md.reported_region"); // Default, in case the game doesn't support any regions! bool game_overseas = TRUE; bool game_pal = FALSE; bool overseas; bool pal; bool overseas_reported; bool pal_reported; // Preference order, TODO: Make it configurable if(ginfo.region_support & REGIONMASK_OVERSEAS_NTSC) { game_overseas = TRUE; game_pal = FALSE; } else if(ginfo.region_support & REGIONMASK_JAPAN_NTSC) { game_overseas = FALSE; game_pal = FALSE; } else if(ginfo.region_support & REGIONMASK_OVERSEAS_PAL) { game_overseas = TRUE; game_pal = TRUE; } else if(ginfo.region_support & REGIONMASK_JAPAN_PAL) // WTF? { game_overseas = FALSE; game_pal = TRUE; } if(region_setting == REGION_GAME) { overseas = game_overseas; pal = game_pal; } else { decode_region_setting(region_setting, overseas, pal); } if(reported_region_setting == REGION_GAME) { overseas_reported = game_overseas; pal_reported = game_pal; } else if(reported_region_setting == REGION_SAME) { overseas_reported = overseas; pal_reported = pal; } else { decode_region_setting(reported_region_setting, overseas_reported, pal_reported); } MDFN_printf("\n"); MDFN_printf(_("Active Region: %s %s\n"), overseas ? _("Overseas") : _("Domestic"), pal ? _("PAL") : _("NTSC")); MDFN_printf(_("Active Region Reported: %s %s\n"), overseas_reported ? _("Overseas") : _("Domestic"), pal_reported ? _("PAL") : _("NTSC")); system_init(overseas, pal, overseas_reported, pal_reported); if(pal) MDFNGameInfo->nominal_height = 240; else MDFNGameInfo->nominal_height = 224; MDFNGameInfo->MasterClock = MDFN_MASTERCLOCK_FIXED(pal ? CLOCK_PAL : CLOCK_NTSC); if(pal) MDFNGameInfo->fps = (int64)CLOCK_PAL * 65536 * 256 / (313 * 3420); else MDFNGameInfo->fps = (int64)CLOCK_NTSC * 65536 * 256 / (262 * 3420); //printf("%f\n", (double)MDFNGameInfo->fps / 65536 / 256); } if(MDFN_GetSettingB("md.correct_aspect")) { MDFNGameInfo->nominal_width = 292; MDFNGameInfo->lcm_width = 1280; } else { MDFNGameInfo->nominal_width = 320; MDFNGameInfo->lcm_width = 320; } MDFNGameInfo->lcm_height = MDFNGameInfo->nominal_height * 2; MDFNGameInfo->LayerNames = "BG0\0BG1\0OBJ\0"; // // { unsigned mtt = MDFN_GetSettingUI("md.input.multitap"); if(MDFN_GetSettingB("md.input.auto")) { for(auto const& e : InputDB) { if(e.crc32 == ginfo.crc32 && (!e.prod_code || !strcmp(e.prod_code, ginfo.product_code))) { MDFNGameInfo->DesiredInput.resize(8); for(unsigned n = e.max_players; n < 8; n++) // Particularly for Gauntlet 4. MDFNGameInfo->DesiredInput[n] = "none"; mtt = e.tap; break; } } } for(const auto* mte = MultiTap_List; mte->string; mte++) { if((unsigned)mte->number == mtt) { MDFN_printf(_("Active Multitap(s): %s\n"), mte->description); break; } } MDINPUT_SetMultitap(mtt); } // // system_reset(true); }
bool Sound_Init(MDFNGI *gi) { SexyAL_DriverInfo CurDriver; NeedReInit = false; SoundRate = 0; memset(&format, 0, sizeof(format)); memset(&buffering, 0, sizeof(buffering)); Interface = new SexyAL(); format.sampformat = SEXYAL_FMT_PCMS16; assert(gi->soundchan); format.channels = gi->soundchan; format.revbyteorder = 0; format.noninterleaved = false; format.rate = gi->soundrate ? gi->soundrate : MDFN_GetSettingUI("sound.rate"); buffering.ms = MDFN_GetSettingUI("sound.buffer_time"); if(!buffering.ms) { buffering.overhead_kludge = true; buffering.ms = 7 + floor(0.5 + 1.5 * 1000.0 / gi->fps * (256 * 65536)); } else buffering.overhead_kludge = false; buffering.period_us = MDFN_GetSettingUI("sound.period_time"); std::string zedevice = MDFN_GetSettingS("sound.device"); std::string zedriver = MDFN_GetSettingS("sound.driver"); MDFNI_printf(_("\nInitializing sound...\n")); MDFN_indent(1); if(!Interface->FindDriver(&CurDriver, zedriver.c_str())) { std::vector<SexyAL_DriverInfo> DriverTypes = Interface->GetDriverList(); MDFN_printf(_("\nUnknown sound driver \"%s\". Compiled-in sound drivers:\n"), zedriver.c_str()); MDFN_indent(2); for(unsigned x = 0; x < DriverTypes.size(); x++) { MDFN_printf("%s\n", DriverTypes[x].short_name); } MDFN_indent(-2); MDFN_printf("\n"); delete Interface; Interface = NULL; MDFN_indent(-1); return(FALSE); } if(!strcasecmp(zedevice.c_str(), "default")) MDFNI_printf(_("Using \"%s\" audio driver with SexyAL's default device selection."), CurDriver.name); else MDFNI_printf(_("Using \"%s\" audio driver with device \"%s\":"), CurDriver.name, zedevice.c_str()); MDFN_indent(1); //RunSexyALTest(Interface, &buffering, zedevice.c_str(), CurDriver.type); //exit(1); if(!(Output=Interface->Open(zedevice.c_str(), &format, &buffering, CurDriver.type))) { MDFND_PrintError(_("Error opening a sound device.")); delete Interface; Interface = NULL; MDFN_indent(-2); return(FALSE); } if(format.rate < 22050 || format.rate > 192000) { MDFND_PrintError(_("Set rate is out of range [22050-192000]")); Sound_Kill(); MDFN_indent(-2); return(FALSE); } MDFNI_printf(_("\nBits: %u%s\nRate: %u\nChannels: %u%s\nByte order: CPU %s\nBuffer size: %u sample frames(%f ms)\n"), (format.sampformat>>4)*8, (format.sampformat == SEXYAL_FMT_PCMFLOAT) ? _(" (floating-point)") : "",format.rate,format.channels,format.noninterleaved ? _(" (non-interleaved) ") : "", format.revbyteorder?"Reversed":"Native", buffering.buffer_size, (double)buffering.buffer_size * 1000 / format.rate); MDFNI_printf(_("Latency: %u sample frames(%f ms)\n"), buffering.latency, (double)buffering.latency * 1000 / format.rate); if(buffering.period_size) { //int64_t pt_test_result = ((int64_t)buffering.period_size * (1000 * 1000) / format.rate); int64_t bt_test_result = ((int64_t)(buffering.bt_gran ? buffering.bt_gran : buffering.period_size) * (1000 * 1000) / format.rate); MDFNI_printf(_("Period size: %u sample frames(%f ms)\n"), buffering.period_size, (double)buffering.period_size * 1000 / format.rate); if(bt_test_result > 5333) { MDFN_indent(1); if(!buffering.bt_gran) MDFN_printf(_("Warning: Period time is too large(it should be <= ~5.333ms). Video will appear very jerky.\n")); else MDFN_printf(_("Warning: Buffer update timing granularity is too large(%f; it should be <= ~5.333ms). Video will appear very jerky.\n"), (double)buffering.bt_gran * 1000 / format.rate); MDFN_indent(-1); } } format.sampformat = SEXYAL_FMT_PCMS16; format.channels = gi->soundchan?gi->soundchan:1; format.revbyteorder = 0; format.noninterleaved = false; //format.rate=gi->soundrate?gi->soundrate:soundrate; Output->SetConvert(Output, &format); EmuModBufferSize = (500 * format.rate + 999) / 1000; EmuModBuffer = (int16 *)calloc(sizeof(int16) * format.channels, EmuModBufferSize); SoundRate = format.rate; MDFN_indent(-2); return(1); }
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_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); }
static int ReadThreadStart(void *arg) { char *device_name = (char *)arg; bool Running = TRUE; MDFN_printf(_("Loading %s...\n\n"), device_name ? device_name : _("PHYSICAL CDROM DISC")); MDFN_indent(1); if(!(p_cdrfile = cdrfile_open(device_name))) { MDFN_indent(-1); EmuThreadQueue->Write(CDIF_Message(CDIF_MSG_INIT_DONE, FALSE, 0, 0, 0, NULL)); return(0); } if(!cdrfile_read_toc(p_cdrfile, &toc)) { puts("Error reading TOC"); MDFN_indent(-1); EmuThreadQueue->Write(CDIF_Message(CDIF_MSG_INIT_DONE, FALSE, 0, 0, 0, NULL)); return(0); } if(toc.first_track < 1 || toc.last_track > 99 || toc.first_track > toc.last_track) { puts("First/Last track numbers bad"); MDFN_indent(-1); EmuThreadQueue->Write(CDIF_Message(CDIF_MSG_INIT_DONE, FALSE, 0, 0, 0, NULL)); return(0); } 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); EmuThreadQueue->Write(CDIF_Message(CDIF_MSG_INIT_DONE, TRUE, 0, 0, 0, NULL)); while(Running) { CDIF_Message msg; // Only do a blocking-wait for a message if we don't have any sectors to read-ahead. // MDFN_DispMessage("%d %d %d\n", last_read_lba, ra_lba, ra_count); if(ReadThreadQueue->Read(&msg, ra_count ? FALSE : TRUE)) { switch(msg.message) { case CDIF_MSG_DIEDIEDIE: Running = FALSE; break; case CDIF_MSG_READ_SECTOR: { static const int max_ra = 16; static const int initial_ra = 1; static const int speedmult_ra = 2; uint32 new_lba = msg.args[0]; assert((unsigned int)max_ra < (SBSize / 4)); if(new_lba == (last_read_lba + 1)) { int how_far_ahead = ra_lba - new_lba; assert(how_far_ahead >= 0); if(how_far_ahead <= max_ra) ra_count = std::min(speedmult_ra, 1 + max_ra - how_far_ahead); else ra_count++; } else { ra_lba = new_lba; ra_count = initial_ra; } last_read_lba = new_lba; } break; } } // Don't read >= the "end" of the disc, silly snake. Slither. if(ra_count && ra_lba == toc.tracks[100].lba) { ra_count = 0; //printf("Ephemeral scarabs: %d!\n", ra_lba); } if(ra_count) { uint8 tmpbuf[2352 + 96]; if(!cdrfile_read_raw_sector(p_cdrfile, tmpbuf, ra_lba)) { printf("Sector %d read error! Abandon ship!", ra_lba); memset(tmpbuf, 0, sizeof(tmpbuf)); } MDFND_LockMutex(SBMutex); SectorBuffers[SBWritePos].lba = ra_lba; memcpy(SectorBuffers[SBWritePos].data, tmpbuf, 2352 + 96); SectorBuffers[SBWritePos].valid = TRUE; SBWritePos = (SBWritePos + 1) % SBSize; MDFND_UnlockMutex(SBMutex); ra_lba++; ra_count--; } } if(p_cdrfile) { cdrfile_destroy(p_cdrfile); p_cdrfile = NULL; } return(1); }
MDFNGI *MDFNI_LoadGame(const char *force_module, const char *name) { MDFNFILE GameFile; std::vector<FileExtensionSpecStruct> valid_iae; MDFNGameInfo = MDFNGI_CORE; 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(); 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]; #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); }
void NSFLoad(Stream *fp, NESGameType *gt) { try { char magic[5]; int x; NSFInfo = new NSFINFO(); fp->rewind(); fp->read(magic, 5); if(!memcmp(magic, "NESM\x1a", 5)) { fp->rewind(); LoadNSF(fp); } else if(!memcmp(magic, "NSFE", 4)) { fp->rewind(); LoadNSFE(NSFInfo, fp, 0); } if(NSFInfo->LoadAddr < 0x6000) throw MDFN_Error(0, _("Load address is invalid!")); if(NSFInfo->TotalSongs < 1) throw MDFN_Error(0, _("Total number of songs is less than 1!")); BSon = 0; for(x=0;x<8;x++) BSon |= NSFInfo->BankSwitch[x]; MDFNGameInfo->GameType = GMT_PLAYER; if(NSFInfo->GameName.size()) MDFNGameInfo->name = NSFInfo->GameName; for(x=0;;x++) { if(NSFROM[x]==0x20) { NSFROM[x+1]=NSFInfo->InitAddr&0xFF; NSFROM[x+2]=NSFInfo->InitAddr>>8; NSFROM[x+8]=NSFInfo->PlayAddr&0xFF; NSFROM[x+9]=NSFInfo->PlayAddr>>8; break; } } if(NSFInfo->VideoSystem == 0) MDFNGameInfo->VideoSystem = VIDSYS_NTSC; else if(NSFInfo->VideoSystem == 1) MDFNGameInfo->VideoSystem = VIDSYS_PAL; MDFN_printf(_("NSF Loaded. File information:\n\n")); MDFN_indent(1); if(NSFInfo->GameName.size()) MDFN_printf(_("Game/Album Name:\t%s\n"), NSFInfo->GameName.c_str()); if(NSFInfo->Artist.size()) MDFN_printf(_("Music Artist:\t%s\n"), NSFInfo->Artist.c_str()); if(NSFInfo->Copyright.size()) MDFN_printf(_("Copyright:\t\t%s\n"), NSFInfo->Copyright.c_str()); if(NSFInfo->Ripper.size()) MDFN_printf(_("Ripper:\t\t%s\n"), NSFInfo->Ripper.c_str()); if(NSFInfo->SoundChip) { static const char *tab[6]={"Konami VRCVI","Konami VRCVII","Nintendo FDS","Nintendo MMC5","Namco 106","Sunsoft FME-07"}; for(x=0;x<6;x++) if(NSFInfo->SoundChip&(1<<x)) { MDFN_printf(_("Expansion hardware: %s\n"), tab[x]); //NSFInfo->SoundChip=1<<x; /* Prevent confusing weirdness if more than one bit is set. */ //break; } } if(BSon) MDFN_printf(_("Bank-switched\n")); MDFN_printf(_("Load address: $%04x\nInit address: $%04x\nPlay address: $%04x\n"),NSFInfo->LoadAddr,NSFInfo->InitAddr,NSFInfo->PlayAddr); MDFN_printf("%s\n",(NSFInfo->VideoSystem&1)?"PAL":"NTSC"); MDFN_printf(_("Starting song: %d / %d\n\n"),NSFInfo->StartingSong + 1,NSFInfo->TotalSongs); if(NSFInfo->SoundChip&4) ExWRAM = new uint8[32768+8192]; else ExWRAM = new uint8[8192]; MDFN_indent(-1); gt->Power = NSF_Power; gt->Reset = NSF_Reset; gt->SaveNV = NULL; gt->Kill = NSF_Kill; gt->StateAction = NSF_StateAction; Player_Init(NSFInfo->TotalSongs, NSFInfo->GameName, NSFInfo->Artist, NSFInfo->Copyright, NSFInfo->SongNames); MDFNGameInfo->DesiredInput.push_back("gamepad"); MDFNGameInfo->DesiredInput.push_back("none"); MDFNGameInfo->DesiredInput.push_back("none"); MDFNGameInfo->DesiredInput.push_back("none"); MDFNGameInfo->DesiredInput.push_back("none"); }
CDRFile *cdrfile_open(const char *path) { CDRFile *ret = (CDRFile *)calloc(1, sizeof(CDRFile)); struct stat stat_buf; if(path == NULL || stat(path, &stat_buf) || !S_ISREG(stat_buf.st_mode)) { CdIo *p_cdio; char **devices; char **parseit; cdio_init(); GetFileBase("cdrom"); devices = cdio_get_devices(DRIVER_DEVICE); parseit = devices; if(parseit) { MDFN_printf(_("Connected physical devices:\n")); MDFN_indent(1); while(*parseit) { MDFN_printf("%s\n", *parseit); parseit++; } MDFN_indent(-1); } if(!parseit || parseit == devices) { MDFN_PrintError(_("No CDROM drives detected(or no disc present).")); if(devices) cdio_free_device_list(devices); free(ret); return(NULL); } if(devices) cdio_free_device_list(devices); p_cdio = cdio_open_cd(path); //, DRIVER_UNKNOWN); //NULL, DRIVER_UNKNOWN); if(!p_cdio) { free(ret); return(NULL); } ret->p_cdio = p_cdio; ret->FirstTrack = cdio_get_first_track_num(ret->p_cdio); ret->NumTracks = cdio_get_num_tracks(ret->p_cdio); ret->total_sectors = cdio_stat_size(ret->p_cdio); if(ret->FirstTrack > 99) { MDFN_PrintError(_("Invalid first track: %d\n"), ret->FirstTrack); free(ret); cdio_destroy(p_cdio); return(NULL); } if(ret->NumTracks > 100) { MDFN_PrintError(_("Invalid track count: %d\n"), ret->NumTracks); free(ret); cdio_destroy(p_cdio); return(NULL); } for(track_t track = ret->FirstTrack; track < (ret->FirstTrack + ret->NumTracks); track++) { memset(&ret->Tracks[track], 0, sizeof(CDRFILE_TRACK_INFO)); ret->Tracks[track].sectors = cdio_get_track_sec_count(ret->p_cdio, track); ret->Tracks[track].LSN = cdio_get_track_lsn(ret->p_cdio, track); ret->Tracks[track].Format = cdio_get_track_format(ret->p_cdio, track); } return(ret); } FILE *fp = fopen(path, "rb"); bool IsTOC = FALSE; // Assign opposite maximum values so our tests will work! int FirstTrack = 99; int LastTrack = 0; if(!fp) { MDFN_PrintError(_("Error opening CUE sheet/TOC \"%s\": %m\n"), path, errno); free(ret); return(NULL); } GetFileBase(path); char linebuf[512]; int32 active_track = -1; int32 AutoTrackInc = 1; // For TOC CDRFILE_TRACK_INFO TmpTrack; memset(&TmpTrack, 0, sizeof(TmpTrack)); while(fgets(linebuf, 512, fp) > 0) { char cmdbuf[512], raw_args[512], args[4][512]; int argcount = 0; raw_args[0] = 0; cmdbuf[0] = 0; args[0][0] = args[1][0] = args[2][0] = args[3][0] = 0; if(!strncasecmp(linebuf, "CD_ROM", 6) || !strncasecmp(linebuf, "CD_DA", 5) || !strncasecmp(linebuf, "CD_ROM_XA", 9)) { IsTOC = TRUE; puts("TOC file detected."); } if(IsTOC) { char *ss_loc = strstr(linebuf, "//"); if(ss_loc) { ss_loc[0] = '\n'; // For consistency! ss_loc[1] = 0; } } trio_sscanf(linebuf, "%s %[^\r\n]", cmdbuf, raw_args); if(!strcasecmp(cmdbuf, "CD_ROM") || !strcasecmp(cmdbuf, "CD_DA")) IsTOC = TRUE; UnQuotify(UnQuotify(UnQuotify(UnQuotify(raw_args, args[0]), args[1]), args[2]), args[3]); if(args[0][0]) { argcount++; if(args[1][0]) { argcount++; if(args[2][0]) { argcount++; if(args[3][0]) { argcount++; } } } } if(IsTOC) { if(!strcasecmp(cmdbuf, "TRACK")) { if(active_track >= 0) { memcpy(&ret->Tracks[active_track], &TmpTrack, sizeof(TmpTrack)); memset(&TmpTrack, 0, sizeof(TmpTrack)); active_track = -1; } if(AutoTrackInc > 99) { MDFN_printf(_("Invalid track number: %d\n"), AutoTrackInc); free(ret); return(NULL); } active_track = AutoTrackInc++; if(active_track < FirstTrack) FirstTrack = active_track; if(active_track > LastTrack) LastTrack = active_track; if(!strcasecmp(args[0], "AUDIO")) { TmpTrack.Format = TRACK_FORMAT_AUDIO; TmpTrack.RawAudioMSBFirst = TRUE; // Silly cdrdao... } else if(!strcasecmp(args[0], "MODE1")) { TmpTrack.Format = TRACK_FORMAT_DATA; TmpTrack.IsData2352 = 0; } else if(!strcasecmp(args[0], "MODE1_RAW")) { TmpTrack.Format = TRACK_FORMAT_DATA; TmpTrack.IsData2352 = 1; } if(!strcasecmp(args[1], "RW")) { TmpTrack.SubchannelMode = CDRF_SUBM_RW; MDFN_printf(_("\"RW\" format subchannel data not supported, only \"RW_RAW\" is!\n")); free(ret); return(0); } else if(!strcasecmp(args[1], "RW_RAW")) TmpTrack.SubchannelMode = CDRF_SUBM_RW_RAW; } // end to TRACK else if(!strcasecmp(cmdbuf, "SILENCE")) { } else if(!strcasecmp(cmdbuf, "ZERO")) { } else if(!strcasecmp(cmdbuf, "FILE") || !strcasecmp(cmdbuf, "AUDIOFILE")) { const char *binoffset = NULL; const char *msfoffset = NULL; const char *length = NULL; if(args[1][0] == '#') { binoffset = args[1] + 1; msfoffset = args[2]; length = args[3]; } else { msfoffset = args[1]; length = args[2]; } //printf("%s, %s, %s, %s\n", args[0], binoffset, msfoffset, length); if(!ParseTOCFileLineInfo(&TmpTrack, active_track, args[0], binoffset, msfoffset, length)) { free(ret); return(0); } } else if(!strcasecmp(cmdbuf, "DATAFILE")) { const char *binoffset = NULL; const char *length = NULL; if(args[1][0] == '#') { binoffset = args[1] + 1; length = args[2]; } else length = args[1]; if(!ParseTOCFileLineInfo(&TmpTrack, active_track, args[0], binoffset, NULL, length)) { free(ret); return(0); } } else if(!strcasecmp(cmdbuf, "INDEX")) { } else if(!strcasecmp(cmdbuf, "PREGAP")) { if(active_track < 0) { MDFN_printf(_("Command %s is outside of a TRACK definition!\n"), cmdbuf); free(ret); return(NULL); } int m,s,f; trio_sscanf(args[0], "%d:%d:%d", &m, &s, &f); TmpTrack.pregap = (m * 60 + s) * 75 + f; } // end to PREGAP else if(!strcasecmp(cmdbuf, "START")) { if(active_track < 0) { MDFN_printf(_("Command %s is outside of a TRACK definition!\n"), cmdbuf); free(ret); return(NULL); } int m,s,f; trio_sscanf(args[0], "%d:%d:%d", &m, &s, &f); TmpTrack.pregap = (m * 60 + s) * 75 + f; } } /*********** END TOC HANDLING ************/ else // now for CUE sheet handling { if(!strcasecmp(cmdbuf, "FILE")) { if(active_track >= 0) { memcpy(&ret->Tracks[active_track], &TmpTrack, sizeof(TmpTrack)); memset(&TmpTrack, 0, sizeof(TmpTrack)); active_track = -1; } std::string efn = MDFN_MakeFName(MDFNMKF_AUX, 0, args[0]); if(NULL == (TmpTrack.fp = fopen(efn.c_str(), "rb"))) { MDFN_printf(_("Could not open referenced file \"%s\": %m\n"), efn.c_str(), errno); free(ret); return(0); } TmpTrack.FirstFileInstance = 1; if(!strcasecmp(args[1], "BINARY")) { //TmpTrack.Format = TRACK_FORMAT_DATA; //struct stat stat_buf; //fstat(fileno(TmpTrack.fp), &stat_buf); //TmpTrack.sectors = stat_buf.st_size; // / 2048; } else if(!strcasecmp(args[1], "OGG") || !strcasecmp(args[1], "VORBIS") || !strcasecmp(args[1], "WAVE") || !strcasecmp(args[1], "WAV") || !strcasecmp(args[1], "PCM") || !strcasecmp(args[1], "MPC") || !strcasecmp(args[1], "MP+")) { TmpTrack.ovfile = (OggVorbis_File *) calloc(1, sizeof(OggVorbis_File)); if((TmpTrack.sf = sf_open_fd(fileno(TmpTrack.fp), SFM_READ, &TmpTrack.sfinfo, 0))) { free(TmpTrack.ovfile); TmpTrack.ovfile = NULL; } else if(!lseek(fileno(TmpTrack.fp), 0, SEEK_SET) && !ov_open(TmpTrack.fp, TmpTrack.ovfile, NULL, 0)) { //TmpTrack.Format = TRACK_FORMAT_AUDIO; //TmpTrack.sectors = ov_pcm_total(&TmpTrack.ovfile, -1) / 588; } else { free(TmpTrack.ovfile); TmpTrack.ovfile = NULL; fseek(TmpTrack.fp, 0, SEEK_SET); TmpTrack.MPCReaderFile = (mpc_reader_file *)calloc(1, sizeof(mpc_reader_file)); TmpTrack.MPCStreamInfo = (mpc_streaminfo *)calloc(1, sizeof(mpc_streaminfo)); TmpTrack.MPCDecoder = (mpc_decoder *)calloc(1, sizeof(mpc_decoder)); TmpTrack.MPCBuffer = (MPC_SAMPLE_FORMAT *)calloc(MPC_DECODER_BUFFER_LENGTH, sizeof(MPC_SAMPLE_FORMAT)); mpc_streaminfo_init(TmpTrack.MPCStreamInfo); mpc_reader_setup_file_reader(TmpTrack.MPCReaderFile, TmpTrack.fp); if(mpc_streaminfo_read(TmpTrack.MPCStreamInfo, &TmpTrack.MPCReaderFile->reader) != ERROR_CODE_OK) { MDFN_printf(_("Unsupported audio track file format: %s\n"), args[0]); free(TmpTrack.MPCReaderFile); free(TmpTrack.MPCStreamInfo); free(TmpTrack.MPCDecoder); free(TmpTrack.MPCBuffer); free(ret); return(0); } mpc_decoder_setup(TmpTrack.MPCDecoder, &TmpTrack.MPCReaderFile->reader); if(!mpc_decoder_initialize(TmpTrack.MPCDecoder, TmpTrack.MPCStreamInfo)) { MDFN_printf(_("Error initializing MusePack decoder: %s!\n"), args[0]); free(TmpTrack.MPCReaderFile); free(TmpTrack.MPCStreamInfo); free(TmpTrack.MPCDecoder); free(TmpTrack.MPCBuffer); free(ret); return(0); } } } else { MDFN_printf(_("Unsupported track format: %s\n"), args[1]); free(ret); return(0); } } else if(!strcasecmp(cmdbuf, "TRACK")) { if(active_track >= 0) { memcpy(&ret->Tracks[active_track], &TmpTrack, sizeof(TmpTrack)); TmpTrack.FirstFileInstance = 0; TmpTrack.pregap = 0; } active_track = atoi(args[0]); if(active_track < FirstTrack) FirstTrack = active_track; if(active_track > LastTrack) LastTrack = active_track; if(!strcasecmp(args[1], "AUDIO")) TmpTrack.Format = TRACK_FORMAT_AUDIO; else if(!strcasecmp(args[1], "MODE1/2048")) { TmpTrack.Format = TRACK_FORMAT_DATA; TmpTrack.IsData2352 = 0; } else if(!strcasecmp(args[1], "MODE1/2352")) { TmpTrack.Format = TRACK_FORMAT_DATA; TmpTrack.IsData2352 = 1; } TmpTrack.sectors = GetSectorCount(&TmpTrack); if(active_track < 0 || active_track > 99) { MDFN_printf(_("Invalid track number: %d\n"), active_track); return(0); } } else if(!strcasecmp(cmdbuf, "INDEX")) { if(active_track >= 0 && (!strcasecmp(args[0], "01") || !strcasecmp(args[0], "1"))) { int m,s,f; trio_sscanf(args[1], "%d:%d:%d", &m, &s, &f); TmpTrack.index = (m * 60 + s) * 75 + f; } } else if(!strcasecmp(cmdbuf, "PREGAP")) { if(active_track >= 0) { int m,s,f; trio_sscanf(args[0], "%d:%d:%d", &m, &s, &f); TmpTrack.pregap = (m * 60 + s) * 75 + f; } } } // end of CUE sheet handling } // end of fgets() loop if(ferror(fp)) { if(IsTOC) MDFN_printf(_("Error reading TOC file: %m\n"), errno); else MDFN_printf(_("Error reading CUE sheet: %m\n"), errno); return(0); } if(active_track >= 0) memcpy(&ret->Tracks[active_track], &TmpTrack, sizeof(TmpTrack)); if(FirstTrack > LastTrack) { MDFN_printf(_("No tracks found!\n")); return(0); } ret->FirstTrack = FirstTrack; ret->NumTracks = 1 + LastTrack - FirstTrack; lsn_t RunningLSN = 0; lsn_t LastIndex = 0; long FileOffset = 0; for(int x = ret->FirstTrack; x < (ret->FirstTrack + ret->NumTracks); x++) { if(IsTOC) { RunningLSN += ret->Tracks[x].pregap; ret->Tracks[x].LSN = RunningLSN; RunningLSN += ret->Tracks[x].sectors; } else // else handle CUE sheet... { if(ret->Tracks[x].FirstFileInstance) { LastIndex = 0; FileOffset = 0; } RunningLSN += ret->Tracks[x].pregap; ret->Tracks[x].LSN = RunningLSN; // Make sure this is set before the call to GetSectorCount() for the last track sector count fix. ret->Tracks[x].FileOffset = FileOffset; if((x + 1) >= (ret->FirstTrack + ret->NumTracks)) { if(!(ret->Tracks[x].FirstFileInstance)) { // This will fix the last sector count for CUE+BIN ret->Tracks[x].sectors = GetSectorCount(&ret->Tracks[x]); } } else if(ret->Tracks[x+1].FirstFileInstance) { //RunningLSN += ret->Tracks[x].sectors; } else { // Fix the sector count if we're CUE+BIN ret->Tracks[x].sectors = ret->Tracks[x + 1].index - ret->Tracks[x].index; } //printf("Poo: %d %d\n", x, ret->Tracks[x].sectors); RunningLSN += ret->Tracks[x].sectors; //printf("%d, %ld %d %d %d %d\n", x, FileOffset, ret->Tracks[x].index, ret->Tracks[x].pregap, ret->Tracks[x].sectors, ret->Tracks[x].LSN); if(ret->Tracks[x].Format == TRACK_FORMAT_AUDIO || TmpTrack.IsData2352) FileOffset += ret->Tracks[x].sectors * 2352; else FileOffset += ret->Tracks[x].sectors * 2048; } // end to cue sheet handling } // end to track loop LEC_Eval = MDFN_GetSettingB("cdrom.lec_eval"); if(LEC_Eval) { Init_LEC_Correct(); } MDFN_printf(_("Raw rip data correction using L-EC: %s\n\n"), LEC_Eval ? _("Enabled") : _("Disabled")); ret->total_sectors = RunningLSN; // Running LBA? Running LSN? arghafsdf...LSNBAN!#!$ -_- return(ret); }
bool MDFNFILE::ApplyIPS(FILE *ips) { uint8 header[5]; uint32 count = 0; //MDFN_printf(_("Applying IPS file \"%s\"...\n"), path); MDFN_indent(1); if(::fread(header, 1, 5, ips) != 5) { ErrnoHolder ene(errno); MDFN_PrintError(_("Error reading IPS file header: %s"), ene.StrError()); MDFN_indent(-1); return(0); } if(memcmp(header, "PATCH", 5)) { MDFN_PrintError(_("IPS file header is invalid.")); MDFN_indent(-1); return(0); } #ifdef HAVE_MMAP // If the file is mmap()'d, move it to malloc()'d RAM if(is_mmap) { void *tmp_ptr = MDFN_malloc(f_size, _("file read buffer")); if(!tmp_ptr) { //Close(); //fclose(ipsfile); return(0); } memcpy(tmp_ptr, f_data, f_size); munmap(f_data, f_size); is_mmap = FALSE; f_data = (uint8 *)tmp_ptr; } #endif while(::fread(header, 1, 3, ips) == 3) { uint32 offset = (header[0] << 16) | (header[1] << 8) | header[2]; uint8 patch_size_raw[2]; uint32 patch_size; bool rle = false; if(!memcmp(header, "EOF", 3)) { MDFN_printf(_("IPS EOF: Did %d patches\n\n"), count); MDFN_indent(-1); return(1); } if(::fread(patch_size_raw, 1, 2, ips) != 2) { ErrnoHolder ene(errno); MDFN_PrintError(_("Error reading IPS patch length: %s"), ene.StrError()); return(0); } patch_size = MDFN_de16msb(patch_size_raw); if(!patch_size) /* RLE */ { if(::fread(patch_size_raw, 1, 2, ips) != 2) { ErrnoHolder ene(errno); MDFN_PrintError(_("Error reading IPS RLE patch length: %s"), ene.StrError()); return(0); } patch_size = MDFN_de16msb(patch_size_raw); // Is this right? if(!patch_size) patch_size = 65536; rle = true; //MDFN_printf(" Offset: %8d Size: %5d RLE\n",offset, patch_size); } if((offset + patch_size) > f_size) { uint8 *tmp; //printf("%d\n", offset + patch_size, f_size); if((offset + patch_size) > MaxROMImageSize) { MDFN_PrintError(_("ROM image will be too large after IPS patch; maximum size allowed is %llu bytes."), (unsigned long long)MaxROMImageSize); return(0); } if(!(tmp = (uint8 *)MDFN_realloc(f_data, offset + patch_size, _("file read buffer")))) return(0); // Zero newly-allocated memory memset(tmp + f_size, 0, (offset + patch_size) - f_size); f_size = offset + patch_size; f_data = tmp; } if(rle) { const int b = ::fgetc(ips); uint8 *start = f_data + offset; if(EOF == b) { ErrnoHolder ene(errno); MDFN_PrintError(_("Error reading IPS RLE patch byte: %s"), ene.StrError()); return(0); } while(patch_size--) { *start=b; start++; } } else /* Normal patch */ { //MDFN_printf(" Offset: %8d Size: %5d\n", offset, patch_size); if(::fread(f_data + offset, 1, patch_size, ips) != patch_size) { ErrnoHolder ene(errno); MDFN_PrintError(_("Error reading IPS patch: %s"), ene.StrError()); return(0); } } count++; } ErrnoHolder ene(errno); //MDFN_printf(_("Warning: IPS ended without an EOF chunk.\n")); //MDFN_printf(_("IPS EOF: Did %d patches\n\n"), count); MDFN_indent(-1); MDFN_PrintError(_("Error reading IPS patch header: %s"), ene.StrError()); return(0); //return(1); }
/* Rectangle, left, right(not inclusive), top, bottom(not inclusive). */ OpenGL_Blitter::OpenGL_Blitter(int scanlines, ShaderType pixshader, const int screen_w, const int screen_h, int *rs, int *gs, int *bs, int *as) : gl_screen_w(screen_w), gl_screen_h(screen_h) { try { const char *extensions; const char *vendor; const char *renderer; const char *version; uint32 version_h; MaxTextureSize = 0; SupportNPOT = false; SupportARBSync = false; PixelFormat = 0; PixelType = 0; for(unsigned i = 0; i < 4; i++) textures[i] = 0; rgb_mask = 0; using_scanlines = 0; last_w = 0; last_h = 0; OSDLastWidth = 0; OSDLastHeight = 0; shader = NULL; DummyBlack = NULL; DummyBlackSize = 0; #define LFG(x) if(!(p_##x = (x##_Func) SDL_GL_GetProcAddress(#x))) { throw MDFN_Error(0, _("Error getting proc address for: %s\n"), #x); } #define LFGN(x) p_##x = (x##_Func) SDL_GL_GetProcAddress(#x) LFG(glGetError); LFG(glBindTexture); LFGN(glColorTableEXT); LFG(glTexImage2D); LFG(glBegin); LFG(glVertex2f); LFG(glTexCoord2f); LFG(glEnd); LFG(glEnable); LFG(glBlendFunc); LFG(glGetString); LFG(glViewport); LFG(glGenTextures); LFG(glDeleteTextures); LFG(glTexParameteri); LFG(glClearColor); LFG(glLoadIdentity); LFG(glClear); LFG(glMatrixMode); LFG(glDisable); LFG(glPixelStorei); LFG(glTexSubImage2D); LFG(glFinish); LFG(glOrtho); LFG(glPixelTransferf); LFG(glColorMask); LFG(glTexEnvf); LFG(glGetIntegerv); LFG(glTexGend); LFG(glRasterPos2i); LFG(glDrawPixels); LFG(glPixelZoom); LFG(glAccum); LFG(glClearAccum); LFG(glGetTexLevelParameteriv); LFG(glPushMatrix); LFG(glPopMatrix); LFG(glRotated); LFG(glScalef); LFG(glReadPixels); vendor = (const char *)p_glGetString(GL_VENDOR); renderer = (const char *)p_glGetString(GL_RENDERER); version = (const char *)p_glGetString(GL_VERSION); { int major = 0, minor = 0; trio_sscanf(version, "%d.%d", &major, &minor); if(minor < 0) minor = 0; if(minor > 255) minor = 255; version_h = (major << 8) | minor; //printf("%08x\n", version_h); } MDFN_printf(_("OpenGL Implementation: %s %s %s\n"), vendor, renderer, version); extensions = (const char*)p_glGetString(GL_EXTENSIONS); MDFN_printf(_("Checking extensions:\n")); MDFN_indent(1); SupportNPOT = FALSE; SupportARBSync = false; if(CheckExtension(extensions, "GL_ARB_texture_non_power_of_two")) { MDFN_printf(_("GL_ARB_texture_non_power_of_two found.\n")); SupportNPOT = TRUE; } if(CheckExtension(extensions, "GL_ARB_sync")) { MDFN_printf(_("GL_ARB_sync found.\n")); LFG(glFenceSync); LFG(glIsSync); LFG(glDeleteSync); LFG(glClientWaitSync); LFG(glWaitSync); LFG(glGetInteger64v); LFG(glGetSynciv); SupportARBSync = true; } MDFN_indent(-1); // x,y specify LOWER left corner of the viewport. p_glViewport(0, 0, gl_screen_w, gl_screen_h); p_glGenTextures(4, &textures[0]); p_glGenTextures(1, &rgb_mask); using_scanlines = 0; shader = NULL; if(pixshader != SHADER_NONE) { LFG(glCreateShaderObjectARB); LFG(glShaderSourceARB); LFG(glCompileShaderARB); LFG(glCreateProgramObjectARB); LFG(glAttachObjectARB); LFG(glLinkProgramARB); LFG(glUseProgramObjectARB); LFG(glUniform1fARB); LFG(glUniform2fARB); LFG(glUniform3fARB); LFG(glUniform1iARB); LFG(glUniform2iARB); LFG(glUniform3iARB); LFG(glUniformMatrix2fvARB); LFG(glActiveTextureARB); LFG(glGetInfoLogARB); LFG(glGetUniformLocationARB); LFG(glDeleteObjectARB); LFG(glDetachObjectARB); LFG(glGetObjectParameterivARB); shader = new OpenGL_Blitter_Shader(this, pixshader); SupportNPOT = 0; // Our pixel shaders don't work right with NPOT textures(for them to do so would probably necessitate rewriting them to use texelFetch) p_glActiveTextureARB(GL_TEXTURE0_ARB); } // printf here because pixel shader code will set SupportNPOT to 0 if(SupportNPOT) MDFN_printf(_("Using non-power-of-2 sized textures.\n")); else MDFN_printf(_("Using power-of-2 sized textures.\n")); if(scanlines) { int slcount; using_scanlines = scanlines; p_glBindTexture(GL_TEXTURE_2D, textures[1]); p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); uint8 *buf=(uint8*)malloc(64 * (256 * 2) * 4); slcount = 0; for(int y=0;y<(256 * 2);y++) { for(int x=0;x<64;x++) { int sl_alpha; if(slcount) sl_alpha = 0xFF - (0xFF * abs(scanlines) / 100); else sl_alpha = 0xFF; buf[y*64*4+x*4]=0; buf[y*64*4+x*4+1]=0; buf[y*64*4+x*4+2]=0; buf[y*64*4+x*4+3] = sl_alpha; //buf[y*256+x]=(y&1)?0x00:0xFF; } slcount ^= 1; } p_glPixelStorei(GL_UNPACK_ROW_LENGTH, 64); p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 64, 256 * 2, 0, GL_RGBA,GL_UNSIGNED_BYTE,buf); free(buf); } p_glBindTexture(GL_TEXTURE_2D, textures[3]); p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP); p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP); p_glBindTexture(GL_TEXTURE_2D, textures[0]); p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); //p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 0x812F); //p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 0x812F); p_glBindTexture(GL_TEXTURE_2D, textures[2]); p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP); p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP); p_glEnable(GL_TEXTURE_2D); p_glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Background color to black. p_glMatrixMode(GL_MODELVIEW); p_glLoadIdentity(); p_glFinish(); p_glDisable(GL_TEXTURE_1D); p_glDisable(GL_FOG); p_glDisable(GL_LIGHTING); p_glDisable(GL_LOGIC_OP); p_glDisable(GL_DITHER); p_glDisable(GL_COLOR_MATERIAL); p_glDisable(GL_NORMALIZE); p_glDisable(GL_SCISSOR_TEST); p_glDisable(GL_STENCIL_TEST); p_glDisable(GL_ALPHA_TEST); p_glDisable(GL_DEPTH_TEST); p_glPixelTransferf(GL_RED_BIAS, 0); p_glPixelTransferf(GL_GREEN_BIAS, 0); p_glPixelTransferf(GL_BLUE_BIAS, 0); p_glPixelTransferf(GL_ALPHA_BIAS, 0); p_glPixelTransferf(GL_RED_SCALE, 1); p_glPixelTransferf(GL_GREEN_SCALE, 1); p_glPixelTransferf(GL_BLUE_SCALE, 1); p_glPixelTransferf(GL_ALPHA_SCALE, 1); p_glPixelTransferf(GL_MAP_COLOR, GL_FALSE); p_glOrtho(0, gl_screen_w, gl_screen_h, 0, -1.0, 1.0); last_w = 0; last_h = 0; OSDLastWidth = OSDLastHeight = 0; MDFN_printf(_("Checking maximum texture size...\n")); MDFN_indent(1); p_glBindTexture(GL_TEXTURE_2D, textures[0]); // Assume maximum texture width is the same as maximum texture height to greatly simplify things MaxTextureSize = 32768; while(MaxTextureSize) { GLint width_test = 0; p_glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, MaxTextureSize, MaxTextureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); p_glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width_test); if((unsigned int)width_test == MaxTextureSize) break; MaxTextureSize >>= 1; } MDFN_printf(_("Apparently it is at least: %d x %d\n"), MaxTextureSize, MaxTextureSize); if(MaxTextureSize < 256) { MDFN_printf(_("Warning: Maximum texture size is reported as being less than 256, but we can't handle that.\n")); MaxTextureSize = 256; } DummyBlack = NULL; DummyBlackSize = 0; MDFN_indent(-1); if(!CheckAlternateFormat(version_h)) { #ifdef LSB_FIRST *rs = 0; *gs = 8; *bs = 16; *as = 24; #else *rs = 24; *gs = 16; *bs = 8; *as = 0; #endif PixelFormat = GL_RGBA; PixelType = GL_UNSIGNED_BYTE; MDFN_printf(_("Using GL_RGBA, GL_UNSIGNED_BYTE for texture source data.\n")); } else { *as = 24; *rs = 16; *gs = 8; *bs = 0; PixelFormat = GL_BGRA; PixelType = GL_UNSIGNED_INT_8_8_8_8_REV; MDFN_printf(_("Using GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV for texture source data.\n")); } } catch(...) { Cleanup(); throw; } }
bool InitSound(MDFNGI *gi) { SoundRate = 0; memset(&format,0,sizeof(format)); memset(&buffering,0,sizeof(buffering)); Interface = (SexyAL *)SexyAL_Init(0); DriverTypes = Interface->EnumerateTypes(Interface); format.sampformat = SEXYAL_FMT_PCMS16; assert(gi->soundchan); format.channels = gi->soundchan; format.revbyteorder = 0; format.rate = gi->soundrate ? gi->soundrate : MDFN_GetSettingUI("sound.rate"); buffering.ms = MDFN_GetSettingUI("sound.buffer_time"); buffering.period_us = MDFN_GetSettingUI("sound.period_time"); std::string zedevice = MDFN_GetSettingS("sound.device"); std::string zedriver = MDFN_GetSettingS("sound.driver"); CurDriverIndex = -1; if(!strcasecmp(zedriver.c_str(), "default")) CurDriverIndex = 0; else { for(int x = 0; DriverTypes[x].short_name; x++) { if(!strcasecmp(zedriver.c_str(), DriverTypes[x].short_name)) { CurDriverIndex = x; break; } } } MDFNI_printf(_("\nInitializing sound...\n")); MDFN_indent(1); if(CurDriverIndex == -1) { MDFN_printf(_("\nUnknown sound driver \"%s\". Supported sound drivers:\n"), zedriver.c_str()); MDFN_indent(2); for(int x = 0; DriverTypes[x].short_name; x++) { MDFN_printf("%s\n", DriverTypes[x].short_name); } MDFN_indent(-2); MDFN_printf("\n"); Interface->Destroy(Interface); Interface = NULL; MDFN_indent(-1); return(FALSE); } MDFNI_printf(_("Using \"%s\" audio driver with device \"%s\":"),DriverTypes[CurDriverIndex].name, zedevice.c_str()); MDFN_indent(1); //RunSexyALTest(Interface, &buffering, zedevice.c_str(), DriverTypes[CurDriverIndex].type); //exit(1); if(!(Output=Interface->Open(Interface, zedevice.c_str(), &format, &buffering, DriverTypes[CurDriverIndex].type))) { MDFND_PrintError(_("Error opening a sound device.")); Interface->Destroy(Interface); Interface=0; MDFN_indent(-2); return(FALSE); } if(format.rate<8192 || format.rate > 48000) { MDFND_PrintError(_("Set rate is out of range [8192-48000]")); KillSound(); MDFN_indent(-2); return(FALSE); } MDFNI_printf(_("\nBits: %u\nRate: %u\nChannels: %u\nByte order: CPU %s\nBuffer size: %u sample frames(%f ms)\n"), (format.sampformat>>4)*8,format.rate,format.channels,format.revbyteorder?"Reversed":"Native", buffering.buffer_size, (double)buffering.buffer_size * 1000 / format.rate); MDFNI_printf(_("Latency: %u sample frames(%f ms)\n"), buffering.latency, (double)buffering.latency * 1000 / format.rate); if(buffering.period_size) { int64_t pt_test_result = ((int64_t)buffering.period_size * (1000 * 1000) / format.rate); MDFNI_printf(_("Period size: %u sample frames(%f ms)\n"), buffering.period_size, (double)buffering.period_size * 1000 / format.rate); if(pt_test_result > 5333) { MDFN_indent(1); MDFN_printf(_("Warning: Period time is too large(it should be <= ~5.333ms). Video will appear very jerky.\n")); MDFN_indent(-1); } } format.sampformat=SEXYAL_FMT_PCMS16; format.channels=gi->soundchan?gi->soundchan:1; format.revbyteorder=0; //format.rate=gi->soundrate?gi->soundrate:soundrate; Output->SetConvert(Output, &format); EmuModBufferSize = (500 * format.rate + 999) / 1000; EmuModBuffer = (int16 *)calloc(sizeof(int16) * format.channels, EmuModBufferSize); SoundRate = format.rate; MDFN_indent(-2); return(1); }