void PSFTags::AddTag(char *tag_line) { char *eq; // Transform 0x01-0x1F -> 0x20 for(unsigned int i = 0; i < strlen(tag_line); i++) if((unsigned char)tag_line[i] < 0x20) tag_line[i] = 0x20; eq = strchr(tag_line, '='); if(eq) { *eq = 0; MDFN_trim(tag_line); MDFN_trim(eq + 1); for(unsigned int i = 0; i < strlen(tag_line); i++) tag_line[i] = tolower(tag_line[i]); if(TagExists(tag_line)) tags[tag_line] = tags[std::string(tag_line)] + std::string(1, '\n') + std::string(eq + 1); else tags[tag_line] = std::string(eq + 1); } }
static void LoadNSF(Stream *fp) { NSF_HEADER NSFHeader; fp->read(&NSFHeader, 0x80); // NULL-terminate strings just in case. NSFHeader.GameName[31] = NSFHeader.Artist[31] = NSFHeader.Copyright[31] = 0; MDFN_zapctrlchars((char*)NSFHeader.GameName); MDFN_zapctrlchars((char*)NSFHeader.Artist); MDFN_zapctrlchars((char*)NSFHeader.Copyright); MDFN_trim((char*)NSFHeader.GameName); MDFN_trim((char*)NSFHeader.Artist); MDFN_trim((char*)NSFHeader.Copyright); NSFInfo->GameName = std::string((const char *)NSFHeader.GameName); NSFInfo->Artist = std::string((const char *)NSFHeader.Artist); NSFInfo->Copyright = std::string((const char *)NSFHeader.Copyright); NSFInfo->LoadAddr = NSFHeader.LoadAddressLow | (NSFHeader.LoadAddressHigh << 8); NSFInfo->InitAddr = NSFHeader.InitAddressLow | (NSFHeader.InitAddressHigh << 8); NSFInfo->PlayAddr = NSFHeader.PlayAddressLow | (NSFHeader.PlayAddressHigh << 8); uint64 tmp_size = fp->size() - 0x80; if(tmp_size > 16 * 1024 * 1024) throw MDFN_Error(0, _("NSF is too large.")); NSFInfo->NSFSize = tmp_size; NSFInfo->NSFMaxBank = ((NSFInfo->NSFSize+(NSFInfo->LoadAddr&0xfff)+4095)/4096); NSFInfo->NSFMaxBank = round_up_pow2(NSFInfo->NSFMaxBank); NSFInfo->NSFDATA = new uint8[NSFInfo->NSFMaxBank * 4096]; memset(NSFInfo->NSFDATA, 0x00, NSFInfo->NSFMaxBank*4096); fp->read(NSFInfo->NSFDATA+(NSFInfo->LoadAddr&0xfff), NSFInfo->NSFSize); NSFInfo->NSFMaxBank--; NSFInfo->VideoSystem = NSFHeader.VideoSystem; NSFInfo->SoundChip = NSFHeader.SoundChip; NSFInfo->TotalSongs = NSFHeader.TotalSongs; if(NSFHeader.StartingSong == 0) NSFHeader.StartingSong = 1; NSFInfo->StartingSong = NSFHeader.StartingSong - 1; memcpy(NSFInfo->BankSwitch, NSFHeader.BankSwitch, 8); }
int LoadNSF(MDFNFILE *fp) { NSF_HEADER NSFHeader; fp->rewind(); fp->fread(&NSFHeader, 1, 0x80); // NULL-terminate strings just in case. NSFHeader.GameName[31] = NSFHeader.Artist[31] = NSFHeader.Copyright[31] = 0; NSFInfo->GameName = (UTF8*)MDFN_RemoveControlChars(strdup((char *)NSFHeader.GameName)); NSFInfo->Artist = (UTF8 *)MDFN_RemoveControlChars(strdup((char *)NSFHeader.Artist)); NSFInfo->Copyright = (UTF8 *)MDFN_RemoveControlChars(strdup((char *)NSFHeader.Copyright)); MDFN_trim((char*)NSFInfo->GameName); MDFN_trim((char*)NSFInfo->Artist); MDFN_trim((char*)NSFInfo->Copyright); NSFInfo->LoadAddr = NSFHeader.LoadAddressLow | (NSFHeader.LoadAddressHigh << 8); NSFInfo->InitAddr = NSFHeader.InitAddressLow | (NSFHeader.InitAddressHigh << 8); NSFInfo->PlayAddr = NSFHeader.PlayAddressLow | (NSFHeader.PlayAddressHigh << 8); NSFInfo->NSFSize = fp->Size() - 0x80; NSFInfo->NSFMaxBank = ((NSFInfo->NSFSize+(NSFInfo->LoadAddr&0xfff)+4095)/4096); NSFInfo->NSFMaxBank = round_up_pow2(NSFInfo->NSFMaxBank); if(!(NSFInfo->NSFDATA=(uint8 *)MDFN_malloc(NSFInfo->NSFMaxBank*4096, _("NSF data")))) return 0; fp->fseek(0x80, SEEK_SET); memset(NSFInfo->NSFDATA, 0x00, NSFInfo->NSFMaxBank*4096); fp->fread(NSFInfo->NSFDATA+(NSFInfo->LoadAddr&0xfff), 1, NSFInfo->NSFSize); NSFInfo->NSFMaxBank--; NSFInfo->VideoSystem = NSFHeader.VideoSystem; NSFInfo->SoundChip = NSFHeader.SoundChip; NSFInfo->TotalSongs = NSFHeader.TotalSongs; if(NSFHeader.StartingSong == 0) NSFHeader.StartingSong = 1; NSFInfo->StartingSong = NSFHeader.StartingSong - 1; memcpy(NSFInfo->BankSwitch, NSFHeader.BankSwitch, 8); return(1); }
static void MakeGIName(MDFNGI* gi, const char* path) { char* ns = NULL; char* tmp; if((ns = strdup(GetFNComponent(path)))) { unsigned nslen = strlen(ns); for(unsigned x = 0; x < nslen; x++) { if(ns[x] == '_') ns[x] = ' '; else if(ns[x] < 0x20) ns[x] = ' '; } if((tmp = strrchr(ns, '.'))) *tmp = 0; MDFN_trim(ns); gi->name = (UTF8*)ns; } }
static std::string GrabString(Stream* fp, size_t len) { std::string ret; size_t null_pos; ret.resize(len); fp->read(&ret[0], len); null_pos = ret.find('\0'); // ANDDYYYYYYYYY if(null_pos != std::string::npos) ret.resize(null_pos); MDFN_zapctrlchars(&ret); MDFN_trim(&ret); return ret; }
void MD_ReadSegaHeader(const uint8 *header, md_game_info *ginfo) { ginfo->rom_size = 0; //fp->size; memcpy(ginfo->copyright, header + 0x10, 16); ginfo->copyright[16] = 0; MDFN_RemoveControlChars(ginfo->copyright); // FIXME: SJIS to UTF8 conversion. memcpy(ginfo->domestic_name, header + 0x20, 0x30); ginfo->domestic_name[0x30] = 0; MDFN_RemoveControlChars(ginfo->domestic_name); memcpy(ginfo->overseas_name, header + 0x50, 0x30); ginfo->overseas_name[0x30] = 0; MDFN_RemoveControlChars(ginfo->overseas_name); memcpy(ginfo->product_code, header + 0x82, 0x0C); ginfo->product_code[0xC] = 0; MDFN_RemoveControlChars(ginfo->product_code); MDFN_trim(ginfo->product_code); ginfo->checksum = (header[0x8E] << 8) | (header[0x8F] << 0); for(int i = 0; i < 16; i++) { for(unsigned int iot = 0; iot < sizeof(IO_types) / sizeof(IO_type_t); iot++) { if(IO_types[iot].code_char == header[0x90 + i]) { ginfo->io_support |= 1 << IO_types[iot].id; break; } } } ginfo->region_support = get_region_numeric(header[0xF0]); }
static void GetString(char *s, int max) { CHEAT_gets(s, max); MDFN_trim(s); }
static void ValidateSetting(const char *value, const MDFNSetting *setting) { MDFNSettingType base_type = setting->type; if(base_type == MDFNST_UINT) { unsigned long long ullvalue; if(!TranslateSettingValueUI(value, ullvalue)) { throw MDFN_Error(0, _("Setting \"%s\", value \"%s\", is not set to a valid unsigned integer."), setting->name, value); } if(setting->minimum) { unsigned long long minimum; TranslateSettingValueUI(setting->minimum, minimum); if(ullvalue < minimum) { throw MDFN_Error(0, _("Setting \"%s\" is set too small(\"%s\"); the minimum acceptable value is \"%s\"."), setting->name, value, setting->minimum); } } if(setting->maximum) { unsigned long long maximum; TranslateSettingValueUI(setting->maximum, maximum); if(ullvalue > maximum) { throw MDFN_Error(0, _("Setting \"%s\" is set too large(\"%s\"); the maximum acceptable value is \"%s\"."), setting->name, value, setting->maximum); } } } else if(base_type == MDFNST_INT) { long long llvalue; if(!TranslateSettingValueI(value, llvalue)) { throw MDFN_Error(0, _("Setting \"%s\", value \"%s\", is not set to a valid signed integer."), setting->name, value); } if(setting->minimum) { long long minimum; TranslateSettingValueI(setting->minimum, minimum); if(llvalue < minimum) { throw MDFN_Error(0, _("Setting \"%s\" is set too small(\"%s\"); the minimum acceptable value is \"%s\"."), setting->name, value, setting->minimum); } } if(setting->maximum) { long long maximum; TranslateSettingValueI(setting->maximum, maximum); if(llvalue > maximum) { throw MDFN_Error(0, _("Setting \"%s\" is set too large(\"%s\"); the maximum acceptable value is \"%s\"."), setting->name, value, setting->maximum); } } } else if(base_type == MDFNST_FLOAT) { double dvalue; if(!MR_StringToDouble(value, &dvalue)) { throw MDFN_Error(0, _("Setting \"%s\", value \"%s\", is not set to a floating-point(real) number."), setting->name, value); } if(std::isnan(dvalue)) throw MDFN_Error(0, _("Setting \"%s\", value \"%s\", is NaN!"), setting->name, value); if(setting->minimum) { double minimum; if(MDFN_UNLIKELY(!MR_StringToDouble(setting->minimum, &minimum))) throw MDFN_Error(0, _("Minimum value, \"%f\", for setting \"%s\" is not set to a floating-point(real) number."), minimum, setting->name); if(MDFN_UNLIKELY(dvalue < minimum)) throw MDFN_Error(0, _("Setting \"%s\" is set too small(\"%s\"); the minimum acceptable value is \"%s\"."), setting->name, value, setting->minimum); } if(setting->maximum) { double maximum; if(MDFN_UNLIKELY(!MR_StringToDouble(setting->maximum, &maximum))) throw MDFN_Error(0, _("Maximum value, \"%f\", for setting \"%s\" is not set to a floating-point(real) number."), maximum, setting->name); if(MDFN_UNLIKELY(dvalue > maximum)) throw MDFN_Error(0, _("Setting \"%s\" is set too large(\"%s\"); the maximum acceptable value is \"%s\"."), setting->name, value, setting->maximum); } } else if(base_type == MDFNST_BOOL) { if(strlen(value) != 1 || (value[0] != '0' && value[0] != '1')) { throw MDFN_Error(0, _("Setting \"%s\", value \"%s\", is not a valid boolean value."), setting->name, value); } } else if(base_type == MDFNST_ENUM) { const MDFNSetting_EnumList *enum_list = setting->enum_list; bool found = false; std::string valid_string_list; assert(enum_list); while(enum_list->string) { if(!MDFN_strazicmp(value, enum_list->string)) { found = true; break; } if(enum_list->description) // Don't list out undocumented and deprecated values. valid_string_list = valid_string_list + (enum_list == setting->enum_list ? "" : " ") + std::string(enum_list->string); enum_list++; } if(!found) { throw MDFN_Error(0, _("Setting \"%s\", value \"%s\", is not a recognized string. Recognized strings: %s"), setting->name, value, valid_string_list.c_str()); } } else if(base_type == MDFNST_MULTI_ENUM) { std::vector<std::string> mel = MDFN_strsplit(value); assert(setting->enum_list); for(auto& mee : mel) { bool found = false; const MDFNSetting_EnumList* enum_list = setting->enum_list; MDFN_trim(&mee); while(enum_list->string) { if(!MDFN_strazicmp(mee.c_str(), enum_list->string)) { found = true; break; } enum_list++; } if(!found) { std::string valid_string_list; enum_list = setting->enum_list; while(enum_list->string) { if(enum_list->description) // Don't list out undocumented and deprecated values. valid_string_list = valid_string_list + (enum_list == setting->enum_list ? "" : " ") + std::string(enum_list->string); enum_list++; } throw MDFN_Error(0, _("Setting \"%s\", value \"%s\" component \"%s\", is not a recognized string. Recognized strings: %s"), setting->name, value, mee.c_str(), valid_string_list.c_str()); } } } if(setting->validate_func && !setting->validate_func(setting->name, value)) { if(base_type == MDFNST_STRING) throw MDFN_Error(0, _("Setting \"%s\" is not set to a valid string: \"%s\""), setting->name, value); else throw MDFN_Error(0, _("Setting \"%s\" is not set to a valid unsigned integer: \"%s\""), setting->name, value); } }
void CDAccess_CCD::Load(const char *path, bool image_memcache) { FileStream cf(path, FileStream::MODE_READ); std::map<std::string, CCD_Section> Sections; std::string linebuf; std::string cur_section_name; std::string dir_path, file_base, file_ext; char img_extsd[4] = { 'i', 'm', 'g', 0 }; char sub_extsd[4] = { 's', 'u', 'b', 0 }; MDFN_GetFilePathComponents(path, &dir_path, &file_base, &file_ext); if(file_ext.length() == 4 && file_ext[0] == '.') { signed char extupt[3] = { -1, -1, -1 }; for(int i = 1; i < 4; i++) { if(file_ext[i] >= 'A' && file_ext[i] <= 'Z') extupt[i - 1] = 'A' - 'a'; else if(file_ext[i] >= 'a' && file_ext[i] <= 'z') extupt[i - 1] = 0; } signed char av = -1; for(int i = 0; i < 3; i++) { if(extupt[i] != -1) av = extupt[i]; else extupt[i] = av; } if(av == -1) av = 0; for(int i = 0; i < 3; i++) { if(extupt[i] == -1) extupt[i] = av; } for(int i = 0; i < 3; i++) { img_extsd[i] += extupt[i]; sub_extsd[i] += extupt[i]; } } //printf("%s %d %d %d\n", file_ext.c_str(), extupt[0], extupt[1], extupt[2]); linebuf.reserve(256); while(cf.get_line(linebuf) >= 0) { MDFN_trim(linebuf); if(linebuf.length() == 0) // Skip blank lines. continue; if(linebuf[0] == '[') { if(linebuf.length() < 3 || linebuf[linebuf.length() - 1] != ']') throw MDFN_Error(0, _("Malformed section specifier: %s"), linebuf.c_str()); cur_section_name = linebuf.substr(1, linebuf.length() - 2); MDFN_strtoupper(cur_section_name); } else { const size_t feqpos = linebuf.find('='); const size_t leqpos = linebuf.rfind('='); std::string k, v; if(feqpos == std::string::npos || feqpos != leqpos) throw MDFN_Error(0, _("Malformed value pair specifier: %s"), linebuf.c_str()); k = linebuf.substr(0, feqpos); v = linebuf.substr(feqpos + 1); MDFN_trim(k); MDFN_trim(v); MDFN_strtoupper(k); Sections[cur_section_name][k] = v; } } { CCD_Section& ds = Sections["DISC"]; unsigned toc_entries = CCD_ReadInt<unsigned>(ds, "TOCENTRIES"); unsigned num_sessions = CCD_ReadInt<unsigned>(ds, "SESSIONS"); bool data_tracks_scrambled = CCD_ReadInt<unsigned>(ds, "DATATRACKSSCRAMBLED"); if(num_sessions != 1) throw MDFN_Error(0, _("Unsupported number of sessions: %u"), num_sessions); if(data_tracks_scrambled) throw MDFN_Error(0, _("Scrambled CCD data tracks currently not supported.")); //printf("MOO: %d\n", toc_entries); for(unsigned te = 0; te < toc_entries; te++) { char tmpbuf[64]; snprintf(tmpbuf, sizeof(tmpbuf), "ENTRY %u", te); CCD_Section& ts = Sections[std::string(tmpbuf)]; unsigned session = CCD_ReadInt<unsigned>(ts, "SESSION"); uint8 point = CCD_ReadInt<uint8>(ts, "POINT"); uint8 adr = CCD_ReadInt<uint8>(ts, "ADR"); uint8 control = CCD_ReadInt<uint8>(ts, "CONTROL"); uint8 pmin = CCD_ReadInt<uint8>(ts, "PMIN"); uint8 psec = CCD_ReadInt<uint8>(ts, "PSEC"); uint8 pframe = CCD_ReadInt<uint8>(ts, "PFRAME"); signed plba = CCD_ReadInt<signed>(ts, "PLBA"); if(session != 1) throw MDFN_Error(0, "Unsupported TOC entry Session value: %u", session); // Reference: ECMA-394, page 5-14 switch(point) { default: throw MDFN_Error(0, "Unsupported TOC entry Point value: %u", point); break; case 0xA0: tocd.first_track = pmin; tocd.disc_type = psec; break; case 0xA1: tocd.last_track = pmin; break; case 0xA2: tocd.tracks[100].adr = adr; tocd.tracks[100].control = control; tocd.tracks[100].lba = plba; break; case 99: case 98: case 97: case 96: case 95: case 94: case 93: case 92: case 91: case 90: case 89: case 88: case 87: case 86: case 85: case 84: case 83: case 82: case 81: case 80: case 79: case 78: case 77: case 76: case 75: case 74: case 73: case 72: case 71: case 70: case 69: case 68: case 67: case 66: case 65: case 64: case 63: case 62: case 61: case 60: case 59: case 58: case 57: case 56: case 55: case 54: case 53: case 52: case 51: case 50: case 49: case 48: case 47: case 46: case 45: case 44: case 43: case 42: case 41: case 40: case 39: case 38: case 37: case 36: case 35: case 34: case 33: case 32: case 31: case 30: case 29: case 28: case 27: case 26: case 25: case 24: case 23: case 22: case 21: case 20: case 19: case 18: case 17: case 16: case 15: case 14: case 13: case 12: case 11: case 10: case 9: case 8: case 7: case 6: case 5: case 4: case 3: case 2: case 1: tocd.tracks[point].adr = adr; tocd.tracks[point].control = control; tocd.tracks[point].lba = plba; break; } } } // Convenience leadout track duplication. if(tocd.last_track < 99) tocd.tracks[tocd.last_track + 1] = tocd.tracks[100]; // // Open image stream. { std::string image_path = MDFN_EvalFIP(dir_path, file_base + std::string(".") + std::string(img_extsd), true); if(image_memcache) { img_stream = new MemoryStream(new FileStream(image_path.c_str(), FileStream::MODE_READ)); } else { img_stream = new FileStream(image_path.c_str(), FileStream::MODE_READ); } int64 ss = img_stream->size(); if(ss % 2352) throw MDFN_Error(0, _("CCD image size is not evenly divisible by 2352.")); img_numsectors = ss / 2352; } // // Open subchannel stream { std::string sub_path = MDFN_EvalFIP(dir_path, file_base + std::string(".") + std::string(sub_extsd), true); if(image_memcache) sub_stream = new MemoryStream(new FileStream(sub_path.c_str(), FileStream::MODE_READ)); else sub_stream = new FileStream(sub_path.c_str(), FileStream::MODE_READ); if(sub_stream->size() != (int64)img_numsectors * 96) throw MDFN_Error(0, _("CCD SUB file size mismatch.")); } CheckSubQSanity(); }